diff --git a/library/include/mobilisis/calculate_price.h b/library/include/mobilisis/calculate_price.h index 2fa53a2..fabd009 100644 --- a/library/include/mobilisis/calculate_price.h +++ b/library/include/mobilisis/calculate_price.h @@ -132,6 +132,11 @@ CalcState CALCULATE_LIBRARY_API compute_duration_for_parking_ticket( QDateTime const &start_parking_time, double cost, QDateTime &ticketEndTime); + +CalcState CALCULATE_LIBRARY_API compute_duration_for_daily_ticket( + parking_tariff_t *tariff, + QString const &start_parking_time, + uint8_t paymentMethod); //#ifdef __cplusplus //} // extern "C" //#endif diff --git a/library/include/mobilisis/calculator_functions.h b/library/include/mobilisis/calculator_functions.h index 52c0688..33c0514 100644 --- a/library/include/mobilisis/calculator_functions.h +++ b/library/include/mobilisis/calculator_functions.h @@ -1,7 +1,7 @@ #pragma once #include #include "configuration.h" - +#include using namespace std; class Calculator @@ -26,4 +26,7 @@ public: /// Duration of parking in minutes /// Returns cost (data type: double) double GetCostFromDuration(Configuration* cfg, uint8_t vehicle_type, char const* start_datetime, double durationMin, bool nextDay = false, bool prepaid = false); -}; \ No newline at end of file + + // Daily ticket + QString GetDailyTicketDuration(Configuration* cfg, QString start_datetime, uint8_t payment_option, bool carry_over); +}; diff --git a/library/include/mobilisis/configuration.h b/library/include/mobilisis/configuration.h index 32f5d39..62caafb 100644 --- a/library/include/mobilisis/configuration.h +++ b/library/include/mobilisis/configuration.h @@ -55,4 +55,4 @@ private: /// /// MemberType IdentifyJsonMember(const char* member_name); -}; \ No newline at end of file +}; diff --git a/library/include/mobilisis/payment_opt.h b/library/include/mobilisis/payment_opt.h index e8ddb16..0655755 100644 --- a/library/include/mobilisis/payment_opt.h +++ b/library/include/mobilisis/payment_opt.h @@ -14,4 +14,5 @@ public: double pop_max_time; double pop_min_price; int pop_carry_over; -}; \ No newline at end of file + int pop_daily_card_price; +}; diff --git a/library/include/mobilisis/utilities.h b/library/include/mobilisis/utilities.h index d13be82..74dad3f 100644 --- a/library/include/mobilisis/utilities.h +++ b/library/include/mobilisis/utilities.h @@ -69,4 +69,5 @@ public: /// /// static double CalculatePricePerUnit(double pra_price); + }; diff --git a/library/library.pro b/library/library.pro index 9cd9740..dcea08e 100644 --- a/library/library.pro +++ b/library/library.pro @@ -1,6 +1,6 @@ TEMPLATE = lib TARGET = mobilisis_calc -# CONFIG += staticlib +#CONFIG += staticlib QMAKE_CXXFLAGS += -std=c++17 -g -O0 diff --git a/library/src/calculate_price.cpp b/library/src/calculate_price.cpp index e2cde89..66103fd 100644 --- a/library/src/calculate_price.cpp +++ b/library/src/calculate_price.cpp @@ -14,7 +14,7 @@ int CALCULATE_LIBRARY_API get_zone_nr(int zone) { if(zone > -1) return zone; else - { + { QFile zone("/etc/zone_nr"); if (zone.exists()) { QFileInfo finfo(zone); @@ -26,7 +26,7 @@ int CALCULATE_LIBRARY_API get_zone_nr(int zone) } } return -1; - } + } } CalcState CALCULATE_LIBRARY_API init_tariff(parking_tariff_t **tariff, char const *config_file) { @@ -65,7 +65,7 @@ CalcState CALCULATE_LIBRARY_API init_tariff(parking_tariff_t **tariff, char cons QFile fname(confFile); if (fname.exists() && - fname.open(QIODevice::ReadOnly | QIODevice::Text)) { + fname.open(QIODevice::ReadOnly | QIODevice::Text)) { // DEBUG qCritical() << " ... confFile is open"; @@ -93,10 +93,10 @@ void CALCULATE_LIBRARY_API free_tariff(parking_tariff_t *tariff) { } CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( - parking_tariff_t *tariff, - time_t start_parking_time, // in minutes - time_t end_parking_time, // in minutes - struct price_t *price) { + parking_tariff_t *tariff, + time_t start_parking_time, // in minutes + time_t end_parking_time, // in minutes + struct price_t *price) { CalcState calcState; double minMin = tariff->PaymentOption.find(PaymentOption::Option1)->second.pop_min_time; double maxMin = tariff->PaymentOption.find(PaymentOption::Option1)->second.pop_max_time; @@ -109,7 +109,7 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( int const duration = end_parking_time - start_parking_time; if (duration < 0) { calcState.setDesc(QString("end=%1, start=%2") - .arg(end_parking_time, start_parking_time)); + .arg(end_parking_time, start_parking_time)); return calcState.set(CalcState::State::NEGATIVE_PARING_TIME); } if (duration > maxMin) { @@ -132,9 +132,9 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( if (start.isValid()) { QString cs = start.toString(Qt::ISODate); double cost = calculator.GetCostFromDuration( - tariff, PaymentOption::Option1, - cs.toLocal8Bit().constData(), - duration, false, true); + tariff, PaymentOption::Option1, + cs.toLocal8Bit().constData(), + duration, false, true); double minCost = tariff->PaymentOption.find(PaymentOption::Option1)->second.pop_min_price; if (cost < minCost) { calcState.setDesc(QString("minCost=%1, cost=%2").arg(minCost).arg(cost)); @@ -150,10 +150,10 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( } CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( - parking_tariff_t *tariff, - QDateTime const &start_parking_time, - QDateTime const &end_parking_time, - struct price_t *price) { + parking_tariff_t *tariff, + QDateTime const &start_parking_time, + QDateTime const &end_parking_time, + struct price_t *price) { CalcState calcState; double minMin = tariff->PaymentOption.find(PaymentOption::Option1)->second.pop_min_time; double maxMin = tariff->PaymentOption.find(PaymentOption::Option1)->second.pop_max_time; @@ -171,8 +171,8 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( if (duration < 0) { calcState.setDesc(QString("end=%1, start=%2") - .arg(end_parking_time.toString(Qt::ISODate), - start_parking_time.toString(Qt::ISODate))); + .arg(end_parking_time.toString(Qt::ISODate), + start_parking_time.toString(Qt::ISODate))); return calcState.set(CalcState::State::NEGATIVE_PARING_TIME); } if (duration > maxMin) { @@ -191,9 +191,9 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( if (start_parking_time.isValid()) { QString cs = start_parking_time.toString(Qt::ISODate); double cost = calculator.GetCostFromDuration( - tariff, PaymentOption::Option1, - cs.toLocal8Bit().constData(), - duration, false, true); + tariff, PaymentOption::Option1, + cs.toLocal8Bit().constData(), + duration, false, true); double minCost = tariff->PaymentOption.find(PaymentOption::Option1)->second.pop_min_price; if (cost < minCost) { calcState.setDesc(QString("minCost=%1, cost=%2").arg(minCost, cost)); @@ -213,10 +213,10 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( } CalcState CALCULATE_LIBRARY_API compute_duration_for_parking_ticket( - parking_tariff_t *tariff, - time_t start_parking_time, - double price, - QString &duration) { + parking_tariff_t *tariff, + time_t start_parking_time, + double price, + QString &duration) { CalcState calcState; QDate const d(1970, 1, 1); QTime const t(0, 0, 0); @@ -246,17 +246,17 @@ CalcState CALCULATE_LIBRARY_API compute_duration_for_parking_ticket( } CalcState CALCULATE_LIBRARY_API compute_duration_for_parking_ticket( - parking_tariff_t *tariff, - QDateTime const &start_parking_time, - double price, - QDateTime &ticketEndTime) { + parking_tariff_t *tariff, + QDateTime const &start_parking_time, + double price, + QDateTime &ticketEndTime) { CalcState calcState; if (start_parking_time.isValid()) { QString cs = start_parking_time.toString(Qt::ISODate); QString endTime = calculator.GetDurationFromCost( - tariff, PaymentOption::Option1, - cs.toLocal8Bit().constData(), - price, false, true).c_str(); + tariff, PaymentOption::Option1, + cs.toLocal8Bit().constData(), + price, false, true).c_str(); ticketEndTime = QDateTime::fromString(endTime,Qt::ISODate); // DEBUG @@ -274,3 +274,13 @@ CalcState CALCULATE_LIBRARY_API compute_duration_for_parking_ticket( return calcState.set(CalcState::State::SUCCESS); } + +CalcState CALCULATE_LIBRARY_API compute_duration_for_daily_ticket(parking_tariff_t *tariff, QString const &start_parking_time,uint8_t paymentMethod) +{ + CalcState calcState; + QString result = calculator.GetDailyTicketDuration(tariff, start_parking_time, PaymentOption::Option1,false); + qDebug() << "DailyTicket() => " + result; + + return calcState.set(CalcState::State::SUCCESS); +} + diff --git a/library/src/calculator_functions.cpp b/library/src/calculator_functions.cpp index b503f5f..af86222 100644 --- a/library/src/calculator_functions.cpp +++ b/library/src/calculator_functions.cpp @@ -19,6 +19,92 @@ inline struct tm* localtime_r(const time_t *clock, struct tm* result){ } #endif +QString Calculator::GetDailyTicketDuration(Configuration* cfg, QString start_datetime, uint8_t payment_option, bool carry_over) +{ + if(start_datetime.isNull() || start_datetime.isEmpty()) return NULL; + + double day_price = 0.0f; + int current_special_day_id = -1; + bool is_special_day = Utilities::CheckSpecialDay(cfg, start_datetime.toStdString().c_str(), ¤t_special_day_id, &day_price); + + QDateTime inputDateTime = QDateTime::fromString(start_datetime, Qt::ISODate); + QTime worktime_from; + QTime worktime_to; + + int daily_card_price = cfg->PaymentOption.find(payment_option)->second.pop_daily_card_price; + if(daily_card_price <= 0) return "Daily ticket price zero or less"; + + if(is_special_day) + { + worktime_from = QTime::fromString(cfg->SpecialDaysWorktime.find(current_special_day_id)->second.pedwt_time_from.c_str(), Qt::ISODate); + worktime_to = QTime::fromString(cfg->SpecialDaysWorktime.find(current_special_day_id)->second.pedwt_time_to.c_str(),Qt::ISODate); + + if(inputDateTime.time() < worktime_from) inputDateTime.setTime(worktime_from); + if(carry_over) inputDateTime.setTime(worktime_from); + + if(inputDateTime.time() >= worktime_to) + { + // Go to next day if outside worktime + inputDateTime = inputDateTime.addSecs(86400); + return GetDailyTicketDuration(cfg,inputDateTime.toString(Qt::ISODate), payment_option,true); + } + + if(day_price <=0) + { + // Go to next day if special day price is 0 + inputDateTime = inputDateTime.addSecs(86400); + return GetDailyTicketDuration(cfg,inputDateTime.toString(Qt::ISODate), payment_option,true); + } + + int diff = abs(inputDateTime.time().secsTo(worktime_to)); + inputDateTime = inputDateTime.addSecs(diff); + + //qDebug() << "Ticket is valid until: " << inputDateTime.toString(Qt::ISODate) << "price = " << daily_card_price << ", duration = " << diff / 60; + return inputDateTime.toString(Qt::ISODate) + ", price = " + to_string(daily_card_price).c_str() + ", duration = " + to_string((diff/60)).c_str(); + } + else + { + // Get day of week + int weekdayId = 0; + weekdayId = Utilities::ZellersAlgorithm(inputDateTime.date().day(),inputDateTime.date().month(),inputDateTime.date().year()); + + // If no working day found, skip it (recursively call method again) + size_t found = 0; + found = cfg->WeekDaysWorktime.count(weekdayId); + + // When no workday found, go to next available day + if(found <=0) + { + inputDateTime = inputDateTime.addSecs(86400); + return GetDailyTicketDuration(cfg,inputDateTime.toString(Qt::ISODate), payment_option,true); + } + else + { + worktime_from = QTime::fromString(cfg->WeekDaysWorktime.find(weekdayId)->second.pwd_time_from.c_str(),Qt::ISODate); + worktime_to = QTime::fromString(cfg->WeekDaysWorktime.find(weekdayId)->second.pwd_time_to.c_str(),Qt::ISODate); + if(inputDateTime.time() < worktime_from) + inputDateTime.setTime(worktime_from); + + if(carry_over) + inputDateTime.setTime(worktime_from); + + if(inputDateTime.time() >= worktime_to) + { + // Go to next day if outside worktime + inputDateTime = inputDateTime.addSecs(86400); + return GetDailyTicketDuration(cfg,inputDateTime.toString(Qt::ISODate), payment_option,true); + } + + int diff = abs(inputDateTime.time().secsTo(worktime_to)); + inputDateTime = inputDateTime.addSecs(diff); + + //qDebug() << "Ticket is valid until: " << inputDateTime.toString(Qt::ISODate) << "price = " << daily_card_price << ", duration = " << diff / 60; + return inputDateTime.toString(Qt::ISODate) + ", price = " + to_string(daily_card_price).c_str() + ", duration = " + to_string((diff/60)).c_str(); + } + } + + return NULL; +} /// std::string Calculator::GetDurationFromCost(Configuration* cfg, uint8_t payment_option, diff --git a/library/src/configuration.cpp b/library/src/configuration.cpp index 5a37085..70e61c7 100644 --- a/library/src/configuration.cpp +++ b/library/src/configuration.cpp @@ -154,6 +154,7 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json) else if (strcmp(inner_obj_name, "pop_max_time") == 0) PaymentOption.pop_max_time = k->value.GetDouble(); else if (strcmp(inner_obj_name, "pop_min_price") == 0) PaymentOption.pop_min_price = k->value.GetDouble(); else if (strcmp(inner_obj_name, "pop_carry_over") == 0) PaymentOption.pop_carry_over = k->value.GetInt(); + else if (strcmp(inner_obj_name, "pop_daily_card_price") == 0) PaymentOption.pop_daily_card_price = k->value.GetInt(); break; case MemberType::DurationType: if (strcmp(inner_obj_name, "pun_id") == 0) Duration.pun_id = k->value.GetInt(); diff --git a/main/main.cpp b/main/main.cpp index c87fb95..f294005 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1,10 +1,9 @@ -#include - - #ifdef WIN32 #include #include #include +#include + extern "C" char* strptime(const char* s, const char* f, @@ -27,30 +26,35 @@ extern "C" char* strptime(const char* s, #include #include - int main() { parking_tariff_t *tariff = 0; - if (init_tariff(&tariff, "C:\\Users\\MROD\\Documents\\QtCreator\\build-MOBILISIS-Calculator-Desktop_Qt_5_12_12_MSVC2017_32bit-Debug\\main\\etc\\psa_tariff\\zone1.json")) { + if (init_tariff(&tariff, "C:\\Users\\MROD\\Documents\\QtCreator\\build-MOBILISIS-Calculator-Desktop_Qt_5_12_12_MSVC2017_32bit-Debug\\main\\etc\\psa_tariff\\zone1.json")) + { struct price_t price; memset(&price, 0x00, sizeof(price)); - QDateTime start = QDateTime::fromString("2023-05-12T15:00:38",Qt::ISODate); //QDateTime::currentDateTime(); + QDateTime start = QDateTime::fromString("2023-05-11T07:50:00",Qt::ISODate); //QDateTime::currentDateTime(); time_t start_parking_time = start.toSecsSinceEpoch() / 60; - time_t end_parking_time = start_parking_time + 15; + time_t end_parking_time = start_parking_time + 1230; if (compute_price_for_parking_ticket(tariff, start_parking_time, end_parking_time, - &price)) { + &price)) + { qDebug() << "GetCostFromDuration() => price=" << price.netto; } QString duration; - if(compute_duration_for_parking_ticket(tariff,start_parking_time,37.5,duration)) + if(compute_duration_for_parking_ticket(tariff,start_parking_time,3090,duration)) { qDebug() << "GetDurationFromCost() => duration=" << duration; } + // Daily ticket + compute_duration_for_daily_ticket(tariff,start.toString(Qt::ISODate),3); + + //Configuration* cfg, QString start_datetime, uint8_t payment_option, bool carry_over // // tests // struct tm now; // memset(&now, 0, sizeof(now));