Skip to content

Commit

Permalink
[Ŧ¢Þ] server - show record
Browse files Browse the repository at this point in the history
  • Loading branch information
pereira0x committed Dec 15, 2023
1 parent d9002fc commit c8b2f29
Show file tree
Hide file tree
Showing 10 changed files with 295 additions and 35 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ CXXFLAGS += $(INCLUDES)
LDFLAGS += $(INCLUDES)


#LDFLAGS = -fsanitize=address -lasan
LDFLAGS = -fsanitize=address -lasan

CXXFLAGS += -fdiagnostics-color=always
CXXFLAGS += -Wall
Expand All @@ -48,6 +48,7 @@ CXXFLAGS += -Wswitch-enum
CXXFLAGS += -Wundef
CXXFLAGS += -Wunreachable-code
CXXFLAGS += -Wunused
CXXFLAGS += -g3
LDFLAGS += -pthread


Expand Down
26 changes: 6 additions & 20 deletions src/client/commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -607,18 +607,12 @@ void ShowRecordCommand::handleCommand(std::string args, UserState &state) {

const int columnWidth = 30;

std::tm *tm_info = std::localtime(&showRecordResponse.startDate);

// Format the date and time
char start_date[20];
std::strftime(start_date, sizeof(start_date), "%Y-%m-%d %H:%M:%S", tm_info);

std::cout << "Show record successful!" << std::endl;
std::cout << "Host ID: " << showRecordResponse.hostUID << "\t\t"
<< "Auction Name: " << showRecordResponse.auctionName << "\t"
<< "Asset Filename: " << showRecordResponse.assetFilename << "\t"
<< "Start Value: " << showRecordResponse.startValue << "\t"
<< "Start Date: " << start_date << "\t\t"
<< "Start Date: " << showRecordResponse.startDate << "\t\t"
<< "Active Time: " << showRecordResponse.timeActive << std::endl;

// Print the top border
Expand All @@ -645,30 +639,22 @@ void ShowRecordCommand::handleCommand(std::string args, UserState &state) {
// Accessing elements of the tuple
std::string bidder_UID = std::get<0>(bid);
uint32_t bid_value = std::get<1>(bid);
time_t bid_date_time = std::get<2>(bid);
std::string bid_date_time = std::get<2>(bid);
uint32_t bid_sec_time = std::get<3>(bid);

// Convert time_t to a struct tm for extracting date and time components
std::tm *bid_date_time_tm_info = std::localtime(&bid_date_time);

// Format the date and time
char date[20];
std::strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S",
bid_date_time_tm_info);

std::cout << "|" << std::setw(columnWidth - 1) << std::left << bidder_UID
<< "|" << std::setw(columnWidth - 1) << std::left << bid_value
<< "|" << std::setw(columnWidth - 1) << std::left << date << "|"
<< std::setw(columnWidth - 1) << std::left << bid_sec_time
<< "|" << std::endl;
<< "|" << std::setw(columnWidth - 1) << std::left
<< bid_date_time << "|" << std::setw(columnWidth - 1)
<< std::left << bid_sec_time << "|" << std::endl;

// Print the border between rows
std::cout << std::setw(columnWidth) << std::setfill('-') << "+"
<< std::setw(columnWidth) << "+" << std::setw(columnWidth)
<< "+" << std::setw(columnWidth) << "+" << std::setfill(' ')
<< "+" << std::endl;
}
if (showRecordResponse.end.first != 0) {
if (showRecordResponse.end.first != "") {
std::cout << "End Date: " << showRecordResponse.end.first << "\t\t"
<< "Time passed: " << showRecordResponse.end.second << "\t"
<< std::endl;
Expand Down
73 changes: 73 additions & 0 deletions src/server/handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,79 @@ void handleShowRecord(AuctionServerState &state, std::stringstream &buf,
(void)state;
(void)buf;
(void)addressFrom;

ShowRecordRequest request;
ShowRecordResponse response;

try {
request.deserialize(buf);
state.cdebug << "[ShowRecord] User "
<< " requested to show record of auction " << request.auctionID
<< std::endl;

std::tuple<
std::string, std::string, std::string, uint32_t, std::string, uint32_t,
std::vector<std::tuple<std::string, uint32_t, std::string, uint32_t>>,
std::pair<std::string, uint32_t>>
auctionRecords =
state.auctionManager.getAuctionRecord(request.auctionID);
response.hostUID = std::get<0>(auctionRecords);
response.auctionName = std::get<1>(auctionRecords);
response.assetFilename = std::get<2>(auctionRecords);
response.startValue = std::get<3>(auctionRecords);
response.startDate = std::get<4>(auctionRecords);
response.timeActive = std::get<5>(auctionRecords);
response.bids = std::get<6>(auctionRecords);
for (auto bid : response.bids) {
state.cdebug << "[ShowRecord] Bidsasdasd: " << std::get<0>(bid) << " "
<< std::get<1>(bid) << " " << std::get<2>(bid) << " "
<< std::get<3>(bid) << std::endl;
}

if (std::get<7>(auctionRecords).first != "") {
response.end = std::get<7>(auctionRecords);
}
response.status = ShowRecordResponse::OK;
state.cdebug << "[ShowRecord] Record of auction " << request.auctionID
<< " shown successfully" << std::endl;
state.cdebug << "[ShowRecord] Host UID: " << response.hostUID << std::endl;
state.cdebug << "[ShowRecord] Auction name: " << response.auctionName
<< std::endl;
state.cdebug << "[ShowRecord] Asset filename: " << response.assetFilename
<< std::endl;
state.cdebug << "[ShowRecord] Start value: " << response.startValue

<< std::endl;
state.cdebug << "[ShowRecord] Start date: " << response.startDate
<< std::endl;
state.cdebug << "[ShowRecord] Time active: " << response.timeActive
<< std::endl;
for (auto bid : response.bids) {
state.cdebug << "[ShowRecord] Bid: " << std::get<0>(bid) << " "
<< std::get<1>(bid) << " " << std::get<2>(bid) << " "
<< std::get<3>(bid) << std::endl;
}

state.cdebug << "[ShowRecord] End: " << response.end.first << " "
<< response.end.second << std::endl;
state.cdebug << "[ShowRecord] Record shown successfully" << std::endl;

} catch (AuctionNotFoundException &e) {
state.cdebug << "[ShowRecord] Auction " << request.auctionID << " not found"
<< std::endl;
response.status = ShowRecordResponse::NOK;
} catch (InvalidPacketException &e) {
state.cdebug << "[ShowRecord] Invalid packet received" << std::endl;
response.status = ShowRecordResponse::ERR;
} catch (std::exception &e) {
std::cerr << "[ShowRecord] There was an unhandled exception that "
"prevented the user from showing the record"
<< e.what() << std::endl;
return;
}

send_packet(response, addressFrom.socket,
(struct sockaddr *)&addressFrom.addr, addressFrom.size);
}

void handleOpenAuction(AuctionServerState &state, int fd) {
Expand Down
128 changes: 126 additions & 2 deletions src/server/server_auction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,17 @@ void AuctionManager::bidOnAuction(std::string userID, std::string password,
std::string bidPath =
auctionBidsPath + "/" + std::to_string(bidValue) + ".txt";
create_new_file(bidPath);
std::string bid_datetime = getCurrentTimeFormated();
std::string bidDateTime = getCurrentTimeFormated();
std::string bidTimeSeconds = std::to_string(std::time(nullptr));

std::string auctionInfo = getAuctionInfo(auctionID);
std::string startTimeSeconds = auctionInfo.substr(
auctionInfo.find_last_of(" ") + 1, auctionInfo.length());

write_to_file(bidPath,
userID + " " + std::to_string(bidValue) + " " + bid_datetime);
userID + " " + std::to_string(bidValue) + " " + bidDateTime +
" " +
getTimeDifferenceStr(startTimeSeconds, bidTimeSeconds));

return;
} catch (std::exception &e) {
Expand Down Expand Up @@ -427,3 +435,119 @@ AuctionManager::getAuctionAsset(std::string auctionID) {
throw;
}
}

std::tuple<
std::string, std::string, std::string, uint32_t, std::string, uint32_t,
std::vector<std::tuple<std::string, uint32_t, std::string, uint32_t>>,
std::pair<std::string, uint32_t>>
AuctionManager::getAuctionRecord(std::string auctionID) {
try {
if (validateAuctionID(auctionID) == INVALID) {
throw InvalidPacketException();
}

std::string auctionPath = AUCTIONDIR;
auctionPath += "/" + auctionID;
if (directory_exists(auctionPath) == INVALID) {
throw AuctionNotFoundException();
}

std::string auctionOwner;
std::string auctionName;
std::string assetFilename;
uint32_t startValue;
std::string start_datetime;
uint32_t timeActive;

std::string bidder;
uint32_t bidValue;
std::string bid_datetime;
uint32_t bid_sec_time;
std::tuple<std::string, uint32_t, std::string, uint32_t> bids;

std::string end_datetime;
uint32_t end_sec_time;
std::pair<std::string, uint32_t> auctionEndInfoPair;

std::string auctionInfo = getAuctionInfo(auctionID);
std::string word;

// constructing stream from the string
std::stringstream start(auctionInfo);

// declaring vector to store the string after split
std::vector<std::string> words;
while (getline(start, word, ' ')) {
words.push_back(word);
}

auctionOwner = words[0];
auctionName = words[1];
assetFilename = words[2];
startValue = (uint32_t)std::stoi(words[3]);
start_datetime = words[5] + " " + words[6];
timeActive = (uint32_t)std::stoi(words[4]);

std::string auctionBidsPath = auctionPath + "/BIDS";
std::vector<std::tuple<std::string, uint32_t, std::string, uint32_t>>
auctionBids;
// UID bid_value bid_datetime bid_sec_time
for (const auto &entry :
std::filesystem::directory_iterator(auctionBidsPath)) {
if (entry.is_regular_file() && entry.path().extension() == ".txt") {
std::string bidFile = entry.path();
std::string bidInfo;
read_from_file(bidFile, bidInfo);
// split on spaces
std::stringstream bid(bidInfo);
std::vector<std::string> bidWords;
while (getline(bid, word, ' ')) {
bidWords.push_back(word);
}

bidder = bidWords[0];
bidValue = (uint32_t)std::stoi(bidWords[1]);
bid_datetime = bidWords[2] + " " + bidWords[3];
bid_sec_time = (uint32_t)std::stoi(bidWords[4]);
bids = std::make_tuple(bidder, bidValue, bid_datetime, bid_sec_time);
auctionBids.push_back(bids);
}
}

// end_datetime end_sec_time
std::pair<std::string, uint32_t> auctionEnd;
std::string auctionEndPath = auctionPath + "/END_" + auctionID + ".txt";
if (file_exists(auctionEndPath) != INVALID) {
std::string auctionEndInfo;
read_from_file(auctionEndPath, auctionEndInfo);
std::stringstream auctionEnd_(auctionEndInfo);
std::vector<std::string> auctionEndWords;
while (getline(auctionEnd_, word, ' ')) {
auctionEndWords.push_back(word);
}
end_datetime = auctionEndWords[0] + " " + auctionEndWords[1];
end_sec_time = (uint32_t)std::stoi(auctionEndWords[1]);

auctionEndInfoPair = std::make_pair(end_datetime, end_sec_time);
}

// sort auctionsBids by bidValue
std::sort(
auctionBids.begin(), auctionBids.end(),
[](const std::tuple<std::string, uint32_t, std::string, uint32_t> &a,
const std::tuple<std::string, uint32_t, std::string, uint32_t> &b) {
return std::get<1>(a) > std::get<1>(b);
});

if (auctionBids.size() > 50) {
auctionBids.erase(auctionBids.begin() + 50, auctionBids.end());
}

return std::make_tuple(auctionOwner, auctionName, assetFilename, startValue,
start_datetime, timeActive, auctionBids,
auctionEndInfoPair);

} catch (std::exception &e) {
throw;
}
}
7 changes: 7 additions & 0 deletions src/server/server_auction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "../utils/utils.hpp"
#include "server_user.hpp"

#include <algorithm>
#include <filesystem>
#include <iostream>
#include <random>
Expand Down Expand Up @@ -48,6 +49,12 @@ class AuctionManager {
std::tuple<std::string, uint32_t, std::string>
getAuctionAsset(std::string auctionID);

std::tuple<
std::string, std::string, std::string, uint32_t, std::string, uint32_t,
std::vector<std::tuple<std::string, uint32_t, std::string, uint32_t>>,
std::pair<std::string, uint32_t>>
getAuctionRecord(std::string auctionID);

// constructor
AuctionManager() = default;
// destructor
Expand Down
11 changes: 4 additions & 7 deletions src/utils/protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,11 @@ uint32_t UdpPacket::readInt(std::stringstream &buffer) {
return (uint32_t)i;
}

time_t UdpPacket::readTime(std::stringstream &buffer) {
std::string UdpPacket::readTime(std::stringstream &buffer) {
auto date = readString(buffer, 10);
readSpace(buffer);
auto time = readString(buffer, 8);
struct tm tm;
memset(&tm, 0, sizeof(struct tm));
strptime((date + " " + time).c_str(), "%Y-%m-%d %H:%M:%S", &tm);
return mktime(&tm);
return date + " " + time;
}

std::stringstream LoginRequest::serialize() {
Expand Down Expand Up @@ -478,7 +475,7 @@ std::stringstream ShowRecordResponse::serialize() {
buffer << " B " << std::get<0>(bid) << " " << std::get<1>(bid) << " "
<< std::get<2>(bid) << " " << std::get<3>(bid);
}
if (end.first != 0) {
if (end.first != "") {
buffer << " E " << end.first << " " << end.second;
}
} else if (status == NOK) {
Expand Down Expand Up @@ -531,7 +528,7 @@ void ShowRecordResponse::deserialize(std::stringstream &buffer) {
readSpace(buffer);
auto bid_sec_time = readInt(buffer);
bids.push_back(
std::make_tuple(user_id, bid_value, bid_date, bid_sec_time));
std::make_tuple(bidder_id, bid_value, bid_date, bid_sec_time));
} else if (b_or_e == 'E') {
readSpace(buffer);
auto end_date_time = readTime(buffer);
Expand Down
8 changes: 4 additions & 4 deletions src/utils/protocol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ class UdpPacket {
* @param buffer The buffer to read from.
* @return The time that was read.
*/
time_t readTime(std::stringstream &buffer);
std::string readTime(std::stringstream &buffer);

public:
/**
Expand Down Expand Up @@ -475,10 +475,10 @@ class ShowRecordResponse : public UdpPacket {
std::string auctionName;
std::string assetFilename;
uint32_t startValue;
time_t startDate;
std::string startDate;
uint32_t timeActive;
std::vector<std::tuple<std::string, uint32_t, time_t, uint32_t>> bids;
std::pair<time_t, uint32_t> end;
std::vector<std::tuple<std::string, uint32_t, std::string, uint32_t>> bids;
std::pair<std::string, uint32_t> end;

std::stringstream serialize();
void deserialize(std::stringstream &buffer);
Expand Down
14 changes: 13 additions & 1 deletion src/utils/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ std::string getCurrentTimeFormated() {
// Convert the time point to a time_t object
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);

// Convert the time_t object to a tm struct
// Convert the time_t object to a time_t struct
std::tm *timeInfo = std::localtime(&currentTime);

// Format the date and time
Expand Down Expand Up @@ -354,3 +354,15 @@ std::string getFirstWord(std::string path) {
}
return firstWord;
}

std::string getTimeDifferenceStr(std::string startTime, std::string endTime) {
try {
int start = std::stoi(startTime);
int end = std::stoi(endTime);
int diff = end - start;
std::string diffStr = std::to_string(diff);
return diffStr;
} catch (...) {
throw std::exception();
}
}
Loading

0 comments on commit c8b2f29

Please sign in to comment.