cpp/CPP09/ex00/BitcoinExchange.cpp
2024-12-04 17:29:31 +01:00

236 lines
5.5 KiB
C++

#include "BitcoinExchange.hpp"
void isDate(std::string date);
BitcoinExchange::BitcoinExchange() {
std::ifstream data("data.csv");
if (data.is_open()) {
std::string s;
int i = 0;
while (std::getline(data, s)) {
if (i == 0 && s != "date,exchange_rate") {
std::cout << "Error: Data need to start with \"date,exchange_rate\"" << std::endl;
throw std::exception();
}
else if (i > 0) {
try {
std::string date = s.substr(0, s.find(","));
if (date.size() < 10 || date.size() > 10) {
std::cout << "Error: date invalid";
throw std::exception();
}
else
isDate(date);
char *endPrice;
double price = std::strtof(s.substr(s.find(",") + 1 , s.size()).c_str(), &endPrice);
if (price < 0) {
std::cout << "Error: price negatif";
throw std::exception();
}
else
if (i != 0 && *endPrice == '\0')
mapBitcoin.insert(std::make_pair(date, price));
}
catch (std::exception &e) {
std::cout << " in data" << std::endl;
throw std::exception();
}
}
i++;
}
data.close();
if (mapBitcoin.size() == 0) {
std::cout << "Data file empty." << std::endl;
throw std::exception();
}
}
else {
std::cout << "Error data file." << std::endl;
throw std::exception();
}
}
BitcoinExchange::~BitcoinExchange() {
}
BitcoinExchange::BitcoinExchange(const BitcoinExchange &bit) {
*this = bit;
}
BitcoinExchange &BitcoinExchange::operator=(const BitcoinExchange &bit) {
if (this != &bit) {
this->mapBitcoin = bit.mapBitcoin;
}
return *this;
}
// if the month finish by 31 return true else return false
bool finishMonth(int month) {
if (month == 1 || month == 3 || month == 5 || month == 7
|| month == 8 || month == 10 || month == 12)
return true;
return false;
}
bool isLeapYear(int year) {
return (((year % 4 == 0 && year % 100 != 0) || year % 400 == 0));
}
void isDate(std::string date) {
int year = std::atoi(date.substr(0, 4).c_str());
int month = std::atoi(date.substr(5, 7).c_str());
int day = std::atoi(date.substr(8, 10).c_str());
bool leapYear = isLeapYear(year);
if (month < 1 || month > 12) {
std::cout << "Error: Bad Month";
throw std::exception();
}
if ( (day < 1) ||
(month == 2 && ((day > 28 && !leapYear) || (day > 29 && leapYear))) ||
(finishMonth(month) && day > 31) ||
(!finishMonth(month) && day > 30)
) {
std::cout << "Error: Bad Day";
throw std::exception();
}
if (year < 2009 || (year == 2009 && month == 1 && day < 2)) {
std::cout << "Error: Too old date";
throw std::exception();
}
}
double getValue(std::string value) {
char* endPtr;
double newValue = std::strtod(value.c_str(), &endPtr);
if (*endPtr != '\0') {
std::cout << "Error: Bad value";
throw std::exception();
}
if (newValue > 1000) {
std::cout << "Error: Too High";
throw std::exception();
}
if (newValue < 0) {
std::cout << "Error: Negatif Number";
throw std::exception();
}
return newValue;
}
void verification(std::string s) {
int nbr = 0;
for (size_t i = 0; i < s.size() && nbr <= 1; i++)
if (s[i] == '|')
nbr++;
if (nbr > 1) {
std::cout << "Error: There are too many '|' in the line";
throw std::exception();
}
else if (nbr == 0) {
std::cout << "Error: There aren't '|' in the line";
throw std::exception();
}
if (s.substr(0, s.find(" ")).size() != 10) {
std::cout << "Error: Bad date";
throw std::exception();
}
if (s.substr(s.find("|") + 1, s.size()).size() <= 0) {
std::cout << "Error: Bad value";
throw std::exception();
}
}
// True if d1 is older or equal than d2
bool olderDate(std::string d1, std::string d2) {
int year1 = std::atoi(d1.substr(0, 4).c_str());
int month1 = std::atoi(d1.substr(5, 7).c_str());
int day1 = std::atoi(d1.substr(8, 10).c_str());
int year2 = std::atoi(d2.substr(0, 4).c_str());
int month2 = std::atoi(d2.substr(5, 7).c_str());
int day2 = std::atoi(d2.substr(8, 10).c_str());
if (year1 == year2) {
if (month1 == month2) {
if (day1 == day2) {
return true;
}
else
return (day1 < day2);
}
else
return (month1 < month2);
}
else
return (year1 < year2);
}
void BitcoinExchange::printBitcoinValue(std::string date, double value) {
std::map<std::string, double>::iterator it;
std::string dateMap;
double valueMap;
double lastValueMap = 0;
for (it = mapBitcoin.begin(); it != mapBitcoin.end(); ++it) {
dateMap = it->first;
valueMap = it->second;
if (dateMap == date)
break;
else if (olderDate(date, dateMap)) {
valueMap = lastValueMap;
break;
}
lastValueMap = valueMap;
}
std::cout << date << " => " << value << " = " << value * valueMap << std::endl;
}
void BitcoinExchange::read(const std::string &file) {
std::ifstream input(file.c_str());
int i = 0;
if (input.is_open()) {
std::string s;
while (std::getline(input, s)) {
if (i == 0)
{
if (s == "date | value")
std::cout << "date | value" << std::endl;
else {
std::cout << "Error: File need to start with \"date | value\"" << std::endl;
return ;
}
}
else {
try {
verification(s);
std::string date = s.substr(0, s.find("|") - 1);
isDate(s.substr(0, s.find("|") - 1));
double value = getValue(s.substr(s.find("|") + 1, s.size()));
printBitcoinValue(date, value);
}
catch (std::exception &e) {
std::cout << " << Your input: " << s << std::endl;
}
}
i++;
}
if (i == 0)
std::cout << "Error: Empty file" << std::endl;
}
else {
std::cout << "Error input file." << std::endl;
throw std::exception();
}
}