236 lines
5.5 KiB
C++
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();
|
|
}
|
|
}
|