From 35033066374e8e0948cb87de6a74f1c84e505119 Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Sun, 21 Jul 2024 20:58:12 +0200 Subject: [PATCH] save experimental --- library/include/mobilisis/configuration.h | 31 +- library/include/mobilisis/payment_opt.h | 2 + library/include/mobilisis/tariff_carryover.h | 8 +- .../include/mobilisis/tariff_global_defines.h | 14 + .../include/mobilisis/tariff_interpolation.h | 16 +- library/library.pro | 6 +- library/src/calculator_functions.cpp | 76 +- .../src/calculator_functions.cpp.kirchdorf | 658 +++++++++++------- library/src/configuration.cpp | 492 ++++++++----- library/src/tariff_global_defines.cpp | 5 + main/main.cpp | 14 +- main/main.pro | 4 +- 12 files changed, 849 insertions(+), 477 deletions(-) create mode 100644 library/src/tariff_global_defines.cpp diff --git a/library/include/mobilisis/configuration.h b/library/include/mobilisis/configuration.h index 51be47e..820c149 100644 --- a/library/include/mobilisis/configuration.h +++ b/library/include/mobilisis/configuration.h @@ -50,26 +50,26 @@ public: ATBProject project; ATBCurrency Currency; - ATBDuration duration; + ATBDuration duration; multimap Duration; multimap PaymentMethod; multimap PaymentRate; - SpecialDaysWorktimeType SpecialDaysWorktime; - SpecialDaysType SpecialDays; + SpecialDaysWorktimeType SpecialDaysWorktime; + SpecialDaysType SpecialDays; multimap WeekDays; multimap YearPeriod; multimap WeekDaysWorktime; - ATBPaymentOptionType PaymentOption; - multimap DailyTicket; - TimeRangeType TimeRange; - multimap TimeStepConfig; - multimap TimeBase; - multimap Customer; - TariffProductType TariffProduct; - TariffInterpolationType TariffInterpolations; - TariffPrepaidType TariffPrepaidOptions; - TariffCarryOverType TariffCarryOverOptions; + ATBPaymentOptionType PaymentOption; + multimap DailyTicket; + TimeRangeType TimeRange; + multimap TimeStepConfig; + multimap TimeBase; + multimap Customer; + TariffProductType TariffProduct; + TariffInterpolationType TariffInterpolations; + TariffPrepaidType TariffPrepaidOptions; + TariffCarryOverType TariffCarryOverOptions; /// /// Parse JSON string @@ -95,6 +95,7 @@ public: std::optional> getDailyTicketsForAllKeys() const; std::optional> getDailyTicketsForKey(int key) const; std::optional getInterpolationType(int type) const; + std::optional getInterpolationEnd(QDateTime const &start, int paymentOptionIndex) const; std::optional getPrepaidType(int type) const; std::optional> getTariffProductForAllKeys() const; std::optional> getTariffProductForProductId(int id) const; @@ -103,7 +104,7 @@ public: std::optional getCustomerForType(ATBCustomer::CustomerType customerType); std::optional getWeekDayWorkTime(QTime const &time, Qt::DayOfWeek dayOfWeek); - std::optional adaptStart(QDateTime const &start, int prepaid_option_id); + std::optional prepaidStart(QDateTime const &start, int prepaid_option_id); private: /// @@ -113,5 +114,5 @@ private: /// MemberType IdentifyJsonMember(const char* member_name); - QVector currentPaymentOptions; + QVector currentPaymentOptions; }; diff --git a/library/include/mobilisis/payment_opt.h b/library/include/mobilisis/payment_opt.h index 9e57191..8c40dc1 100644 --- a/library/include/mobilisis/payment_opt.h +++ b/library/include/mobilisis/payment_opt.h @@ -26,6 +26,7 @@ public: pop_carry_over = -1; pop_carry_over_option_id = -1; pop_prepaid_option_id = -1; + pop_truncate_last_interpolation_step = false; pop_carry_over_target = false; pop_carry_over_time_range_id = -1; pop_carry_over_start_time_range = -1; @@ -47,6 +48,7 @@ public: double pop_max_price; int pop_carry_over; int pop_carry_over_option_id; + bool pop_truncate_last_interpolation_step; int pop_prepaid_option_id; bool pop_carry_over_target; int pop_carry_over_time_range_id; diff --git a/library/include/mobilisis/tariff_carryover.h b/library/include/mobilisis/tariff_carryover.h index 2a68dd3..08ffb89 100644 --- a/library/include/mobilisis/tariff_carryover.h +++ b/library/include/mobilisis/tariff_carryover.h @@ -10,11 +10,11 @@ struct ATBCarryOver { bool never; QTime static_start; QTime static_end; + int duration; } carryover[8]; int id; - friend QDebug operator<<(QDebug debug, ATBCarryOver const &co) { QDebugStateSaver saver(debug); @@ -24,24 +24,28 @@ struct ATBCarryOver { << " day: " << co.carryover[(int)Qt::Monday].day << "\n" << " static_start: " << co.carryover[(int)Qt::Monday].static_start.toString(Qt::ISODate) << "\n" << " static_end: " << co.carryover[(int)Qt::Monday].static_end.toString(Qt::ISODate) << "\n" + << " duration: " << co.carryover[(int)Qt::Monday].duration << "\n" << " anytime: " << co.carryover[(int)Qt::Monday].seemless << "\n" << " never: " << co.carryover[(int)Qt::Monday].never << "\n" << " **** Tuesday **** \n" << " day: " << co.carryover[(int)Qt::Tuesday].day << "\n" << " static_start: " << co.carryover[(int)Qt::Tuesday].static_start.toString(Qt::ISODate) << "\n" << " static_end: " << co.carryover[(int)Qt::Tuesday].static_end.toString(Qt::ISODate) << "\n" + << " duration: " << co.carryover[(int)Qt::Monday].duration << "\n" << " anytime: " << co.carryover[(int)Qt::Tuesday].seemless << "\n" << " never: " << co.carryover[(int)Qt::Tuesday].never << "\n" << " **** Wednesday **** \n" << " day: " << co.carryover[(int)Qt::Wednesday].day << "\n" << " static_start: " << co.carryover[(int)Qt::Wednesday].static_start.toString(Qt::ISODate) << "\n" << " static_end: " << co.carryover[(int)Qt::Wednesday].static_end.toString(Qt::ISODate) << "\n" + << " duration: " << co.carryover[(int)Qt::Monday].duration << "\n" << " anytime: " << co.carryover[(int)Qt::Wednesday].seemless << "\n" << " never: " << co.carryover[(int)Qt::Wednesday].never << "\n" << " **** Thursday **** \n" << " day: " << co.carryover[(int)Qt::Thursday].day << "\n" << " static_start: " << co.carryover[(int)Qt::Thursday].static_start.toString(Qt::ISODate) << "\n" << " static_end: " << co.carryover[(int)Qt::Thursday].static_end.toString(Qt::ISODate) << "\n" + << " duration: " << co.carryover[(int)Qt::Monday].duration << "\n" << " anytime: " << co.carryover[(int)Qt::Thursday].seemless << "\n" << " never: " << co.carryover[(int)Qt::Thursday].never << "\n" << " **** Friday **** \n" @@ -54,12 +58,14 @@ struct ATBCarryOver { << " day: " << co.carryover[(int)Qt::Saturday].day << "\n" << " static_start: " << co.carryover[(int)Qt::Saturday].static_start.toString(Qt::ISODate) << "\n" << " static_end: " << co.carryover[(int)Qt::Saturday].static_end.toString(Qt::ISODate) << "\n" + << " duration: " << co.carryover[(int)Qt::Monday].duration << "\n" << " anytime: " << co.carryover[(int)Qt::Saturday].seemless << "\n" << " never: " << co.carryover[(int)Qt::Saturday].never << "\n" << " **** Sunday **** \n" << " day: " << co.carryover[(int)Qt::Sunday].day << "\n" << " static_start: " << co.carryover[(int)Qt::Sunday].static_start.toString(Qt::ISODate) << "\n" << " static_end: " << co.carryover[(int)Qt::Sunday].static_end.toString(Qt::ISODate) << "\n" + << " duration: " << co.carryover[(int)Qt::Monday].duration << "\n" << " anytime: " << co.carryover[(int)Qt::Sunday].seemless << "\n" << " never: " << co.carryover[(int)Qt::Sunday].never << "\n"; diff --git a/library/include/mobilisis/tariff_global_defines.h b/library/include/mobilisis/tariff_global_defines.h index dbb7145..cdc3509 100644 --- a/library/include/mobilisis/tariff_global_defines.h +++ b/library/include/mobilisis/tariff_global_defines.h @@ -3,4 +3,18 @@ #define DBG_HEADER "(" << __func__ << ":" << __LINE__ << ")" +#define DBG_EMERGENCY (0) // System is unusable +#define DBG_ALERT (1) // Action must be taken immediately +#define DBG_CRITICAL (2) // Critical conditions +#define DBG_ERROR (3) // Error conditions +#define DBG_WARNING (4) // Warning conditions +#define DBG_NOTICE (5) // Normal but significant conditions + // Conditions that are not error conditions, but that may require special handling +#define DBG_INFORMATION (6) // Informational messages + // Confirmation that the program is working as expected +#define DBG_DEBUG (7) // Debug-level messages + // Messages that contain information normally of use only when debugging a program + +extern int DBG_LEVEL; + #endif // TARIFF_GLOBAL_DEFINES_H_INCLUDED diff --git a/library/include/mobilisis/tariff_interpolation.h b/library/include/mobilisis/tariff_interpolation.h index 492dd4e..76968de 100644 --- a/library/include/mobilisis/tariff_interpolation.h +++ b/library/include/mobilisis/tariff_interpolation.h @@ -12,7 +12,7 @@ struct ATBInterpolation { STATIC_TIMEPOINT_AND_DURATION = 3, DYNAMIC_TIMEPOINT_AND_STATIC_DURATION = 4, DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_DURATION = 5, - DYNAMIC_ABSTRACT_TIMEPOINT_AND_PRICE = 6, + DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_PRICE = 6, DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_END_TIME = 7 }; @@ -28,8 +28,8 @@ struct ATBInterpolation { return QString("%1: DYNAMIC_TIMEPOINT_AND_STATIC_DURATION").arg(i); case (int)(DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_DURATION): return QString("%1: DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_DURATION").arg(i); - case (int)(DYNAMIC_ABSTRACT_TIMEPOINT_AND_PRICE): - return QString("%1: DYNAMIC_ABSTRACT_TIMEPOINT_AND_PRICE").arg(i); + case (int)(DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_PRICE): + return QString("%1: DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_PRICE").arg(i); case (int)(DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_END_TIME): return QString("%1: DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_END_TIME").arg(i); default:; @@ -49,7 +49,9 @@ struct ATBInterpolation { , dynamic_start_str(QString()) , dynamic_end_str(QString()) , dynamic_duration(0) - , dynamic_until_price(0) { + , dynamic_until_price(0) + , seemless(false) + , never(false) { } int id; @@ -64,6 +66,8 @@ struct ATBInterpolation { QString dynamic_end_str; int dynamic_duration; int dynamic_until_price; + bool seemless; + bool never; friend QDebug operator<<(QDebug debug, ATBInterpolation const &i) { QDebugStateSaver saver(debug); @@ -80,7 +84,9 @@ struct ATBInterpolation { << " dynamic_start_str: " << i.dynamic_start_str << "\n" << " dynamic_end_str: " << i.dynamic_end_str << "\n" << " dynamic_duration: " << i.dynamic_duration << "\n" - << "dynamic_until_price: " << i.dynamic_until_price << "\n"; + << "dynamic_until_price: " << i.dynamic_until_price << "\n" + << " seemless: " << i.seemless << "\n" + << " never: " << i.never << "\n"; return debug; } diff --git a/library/library.pro b/library/library.pro index a978c03..4779cb3 100644 --- a/library/library.pro +++ b/library/library.pro @@ -34,7 +34,8 @@ SOURCES += \ src/configuration.cpp \ src/tariff_log.cpp \ src/calculate_price.cpp \ - src/ticket.cpp + src/ticket.cpp \ + src/tariff_global_defines.cpp HEADERS += \ include/mobilisis/calculator_functions.h \ @@ -87,7 +88,8 @@ HEADERS += \ include/mobilisis/tariff_global_defines.h \ include/mobilisis/tariff_interpolation.h \ include/mobilisis/tariff_prepaid.h \ - include/mobilisis/tariff_carryover.h + include/mobilisis/tariff_carryover.h \ + include/mobilisis/tariff_global_defines.h OTHER_FILES += src/main.cpp \ ../tariffs/tariff_korneuburg.json \ diff --git a/library/src/calculator_functions.cpp b/library/src/calculator_functions.cpp index bcc2f74..dbe8447 100644 --- a/library/src/calculator_functions.cpp +++ b/library/src/calculator_functions.cpp @@ -107,7 +107,7 @@ QDateTime Calculator::GetDailyTicketDuration(Configuration* cfg, const QDateTime 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; + //qDebug() << "Ticket is valid until: " << inputDateTime.toString(Qt::ISODate) << "price = " << daily_card_price << ", duration = " << diff / 60; return inputDateTime; } } @@ -2106,7 +2106,8 @@ QList &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex) } QDateTime start = QDateTime::currentDateTime(); - start.setTime(QTime(start.time().hour(), start.time().minute(), 0)); + //start.setTime(QTime(start.time().hour(), start.time().minute(), 0)); + start.setTime(QTime(7, start.time().minute(), 0)); int const pop_id = cfg->getPaymentOptions(paymentOptionIndex).pop_id; int const pop_carry_over = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over; @@ -2136,10 +2137,22 @@ QList &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex) if (pop_carry_over) { int const pop_carry_over_time_range_id = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over_time_range_id; + int const pop_carry_over_option_id = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over_option_id; QTime const carryOverTimeRangeFrom = cfg->TimeRange.find(pop_carry_over_time_range_id)->second.time_range_from; QTime const carryOverTimeRangeTo = cfg->TimeRange.find(pop_carry_over_time_range_id)->second.time_range_to; qCritical() << "(" << __func__ << ":" << __LINE__ << ") carry over time range id:" << pop_carry_over_time_range_id; + qCritical() << "(" << __func__ << ":" << __LINE__ << ") carry over option id:" << pop_carry_over_time_range_id; + qCritical() << "(" << __func__ << ":" << __LINE__ << ") carry over time from:" << carryOverTimeRangeFrom.toString(Qt::ISODate); + qCritical() << "(" << __func__ << ":" << __LINE__ << ") carry over time to:" << carryOverTimeRangeTo.toString(Qt::ISODate); + + int weekDay = start.date().dayOfWeek(); + QTime const carryOverStart = cfg->TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].static_start; + QTime const carryOverEnd = cfg->TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].static_end; + + qCritical() << "(" << __func__ << ":" << __LINE__ << ") carry over start:" << carryOverStart.toString(Qt::ISODate); + qCritical() << "(" << __func__ << ":" << __LINE__ << ") carry over end:" << carryOverEnd.toString(Qt::ISODate); + // TODO: reparieren if (carryOverTimeRangeFrom.secsTo(carryOverTimeRangeTo) <= 60) { // carry over time point, usually 00:00:00 if (carryOverTimeRangeFrom == QTime(0, 0, 0)) { @@ -2189,14 +2202,26 @@ QList &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex) m_timeSteps[paymentOptionIndex].clear(); - std::optional adaptedStart = cfg->adaptStart(start, pop_prepaid_option_id); - if (adaptedStart) { - start = adaptedStart.value(); + std::optional prepaidStart = cfg->prepaidStart(start, pop_prepaid_option_id); + // TODO: zusaetzlicher faktor falls vorkauf-option zieht + if (prepaidStart) { + start = prepaidStart.value(); + qCritical() << "(" << __func__ << ":" << __LINE__ << ") prepaid adapted start:" << start.toString(Qt::ISODate); } else { - // TODO + qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO"; + } + + QDateTime interpolationEnd; + std::optional interpolationEndDate = cfg->getInterpolationEnd(start, paymentOptionIndex); + if (interpolationEndDate) { + interpolationEnd = interpolationEndDate.value(); + qCritical() << "(" << __func__ << ":" << __LINE__ << ") interpolation end:" << interpolationEnd.toString(Qt::ISODate); + } else { + qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO"; } int const start_time = start.time().hour() * 60 + start.time().minute(); + QDateTime nextTimeStep = start; for (auto[itr, rangeEnd] = cfg->PaymentRate.equal_range(pop_id); itr != rangeEnd; ++itr) { int const durationId = itr->second.pra_payment_unit_id; @@ -2219,9 +2244,11 @@ QList &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex) if (ipolCheck) { ATBInterpolation interpolation = ipolCheck.value(); - if (duration.pun_interpolation_id == (int)ATBInterpolation::DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_END_TIME) { + if (duration.pun_interpolation_id == (int)ATBInterpolation::DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_PRICE) { + + interpolation.dynamic_start = start.time(); + interpolation.dynamic_start.setHMS(start.time().hour(), start.time().minute(), 0); - //qCritical() << "(" << __func__ << ":" << __LINE__ << ") pun_id:" << duration.pun_id; int const end_time = interpolation.dynamic_end.hour() * 60 + interpolation.dynamic_end.minute(); //qCritical() << "(" << __func__ << ":" << __LINE__ << ") pun_duration:" << duration.pun_duration; @@ -2234,9 +2261,12 @@ QList &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex) int pop_min_time = cfg->getPaymentOptions(paymentOptionIndex).pop_min_time; - int nextTimeStep = start_time + duration.pun_duration; - int rest = end_time - nextTimeStep; - if (nextTimeStep <= end_time) { + nextTimeStep = nextTimeStep.addSecs(duration.pun_duration * 60); + + // int nextTimeStep = start_time + duration.pun_duration; + //int rest = end_time - nextTimeStep; + int rest = nextTimeStep.secsTo(interpolationEnd); + if (nextTimeStep <= interpolationEnd) { if (durationId == 1) { @@ -2247,17 +2277,17 @@ QList &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex) qCritical() << "(" << __func__ << ":" << __LINE__ << ") interpolation dynamic end:" << interpolation.dynamic_end.toString(Qt::ISODate); #endif - int const timeStep = nextTimeStep; + int const timeStep = start.secsTo(nextTimeStep) / 60; qCritical() << "(" << __func__ << ":" << __LINE__ << ") time step:" << timeStep; - if (timeStep < duration.pun_duration_min || timeStep > duration.pun_duration_max) { - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << QString("ERROR timeStep (%1) < durationMin (%2) || timeStep (%3)) > durationMax (%4)") - .arg(timeStep).arg(duration.pun_duration_min) - .arg(timeStep).arg(duration.pun_duration_max); - break; - } + //if (timeStep < duration.pun_duration_min || timeStep > duration.pun_duration_max) { + // qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + // << QString("ERROR timeStep (%1) < durationMin (%2) || timeStep (%3)) > durationMax (%4)") + // .arg(timeStep).arg(duration.pun_duration_min) + // .arg(timeStep).arg(duration.pun_duration_max); + // break; + //} qCritical() << "(" << __func__ << ":" << __LINE__ << ") configured minimal parking time:" << cfg->getPaymentOptions(paymentOptionIndex).pop_min_time; @@ -2267,7 +2297,7 @@ QList &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex) qCritical() << "(" << __func__ << ":" << __LINE__ << ") computed minimal parking time:" << cfg->getPaymentOptions(paymentOptionIndex).pop_min_time; duration.pun_duration = timeStep; - timeStepCompensation = end_time - start_time; + timeStepCompensation = start.secsTo(interpolationEnd) / 60; if (duration.pun_duration > 0) { m_timeSteps[paymentOptionIndex] << duration.pun_duration; @@ -2280,7 +2310,9 @@ QList &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex) qCritical() << "(" << __func__ << ":" << __LINE__ << ") time step compensation:" << timeStepCompensation; #endif } else { - duration.pun_duration = nextTimeStep; + // duration.pun_duration = nextTimeStep; + + // HIER WEITER #if DEBUG_GET_TIME_STEPS==1 QTime nextTime(0, 0, 0); @@ -2338,9 +2370,11 @@ QList &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex) } } else { // if (carryOverTimeRangeFrom == carryOverTimeRangeTo) { // TODO + qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO"; } } else { // if (pop_carry_over) { // TODO + qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO"; } } } else { diff --git a/library/src/calculator_functions.cpp.kirchdorf b/library/src/calculator_functions.cpp.kirchdorf index 8353516..8a0e2ed 100644 --- a/library/src/calculator_functions.cpp.kirchdorf +++ b/library/src/calculator_functions.cpp.kirchdorf @@ -115,8 +115,8 @@ QDateTime Calculator::GetDailyTicketDuration(Configuration* cfg, const QDateTime /// std::string Calculator::GetDurationFromCost(Configuration* cfg, uint8_t payment_option, - char const* start_datetime, // given in local time - double price, + char const *startDatetimePassed, // given in local time + double cost, bool nextDay, bool prepaid) { @@ -124,14 +124,14 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg, Q_UNUSED(nextDay); // Get input date - QDateTime inputDate = QDateTime::fromString(start_datetime,Qt::ISODate); + QDateTime inputDate = QDateTime::fromString(startDatetimePassed,Qt::ISODate); static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg); if (paymentMethodId == PaymentMethod::Steps) { if (tariffIs24_7(cfg)) { // use tariff with structure as for instance Schoenau, Koenigsee: // without given YearPeriod, SpecialDays and SpecialDaysWorktime - inputDate = inputDate.addSecs(GetDurationForPrice(cfg, price) * 60); + inputDate = inputDate.addSecs(GetDurationForPrice(cfg, cost) * 60); return inputDate.toString(Qt::ISODate).toStdString(); } else { if (Utilities::IsYearPeriodActive(cfg, inputDate)) { @@ -147,9 +147,226 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg, return ""; } } + } else + if (paymentMethodId == PaymentMethod::Progressive) { + // started with Neuhauser, Kirchdorf: merge into main algo. later + // for now try out some ideas + + // started with Neuhauser, Kirchdorf: merge into main algo. later + // for now try out some ideas + + static const bool carryOverNotSet = Utilities::isCarryOverNotSet(cfg, paymentMethodId); + static const uint minParkingPrice = Utilities::getMinimalParkingPrice(cfg, paymentMethodId); + static const uint maxParkingPrice = Utilities::getMaximalParkingPrice(cfg, paymentMethodId); + + if (cost < minParkingPrice) { + qCritical() << QString("ERROR: COST < MIN_PARKING_PRICE (%1 < %2)").arg(cost).arg(minParkingPrice); + return QDateTime().toString(Qt::ISODate).toStdString(); + } + + if (cost > maxParkingPrice) { + qCritical() << QString("WARN: COST > MAX_PARKING_PRICE (%1 > %2)").arg(cost).arg(maxParkingPrice); + cost = maxParkingPrice; + } + + Q_ASSERT_X(carryOverNotSet, __func__, "CARRYOVER SET (FOR KIRCHDORF)"); + Q_ASSERT_X(prepaid, __func__, "PREPAID NOT SET (FOR KIRCHDORF)"); + + QDateTime start_datetime = QDateTime::fromString(QString(startDatetimePassed), Qt::ISODate); + QDateTime start = start_datetime; + QDateTime end_datetime = QDateTime(); + + int weekdayId = -1; + int weekdayIdLast = -1; + int durationMinutes = Utilities::getMaximalParkingTime(cfg, paymentMethodId); + int durationMinutesBrutto = 0; + + QDateTime current = start; + + int days = 7; + while (--days > 0) { + weekdayId = current.date().dayOfWeek(); + weekdayIdLast = weekdayId; // TODO: some end condition in json-file + + while (cfg->WeekDaysWorktime.count(weekdayId) == 0) { + current = current.addDays(1); + weekdayId = current.date().dayOfWeek(); + if (weekdayId == weekdayIdLast) { + qCritical() << "ERROR: NO VALID WORKDAY-TIMES DEFINED"; + return QDateTime().toString(Qt::ISODate).toStdString(); + } + } + + using WTIterator = std::multimap::const_iterator; + std::pair p = cfg->WeekDaysWorktime.equal_range(weekdayId); + + QTime to = QTime(0, 0, 0); + for (WTIterator itr = p.first; itr != p.second; ++itr) { + QTime const &t = Utilities::WeekDaysWorkTimeUntil(itr); + + if (to < t) { + to = t; + } + } + + if (current.time() >= to) { + if (carryOverNotSet) { + return end_datetime.toString(Qt::ISODate).toStdString(); + } else { + QDateTime const dt = start; + start = start.addDays(1); + start.setTime(QTime(0, 0, 0)); + + durationMinutesBrutto += dt.secsTo(start) / 60; + current = start; + } + } else { + break; + } + } + + int durationMinutesNetto = 0; + uint price = 0; + + if (carryOverNotSet) { + int range = 0; + int minsToCarryOver = 0; // from one work-time to the other on the same day + int minsUsed = 0; + QDateTime lastCurrent = QDateTime(); + + auto timeRangeIt = cfg->TimeRange.cbegin(); + for (; timeRangeIt != cfg->TimeRange.cend(); ++timeRangeIt) { + using WTIterator = std::multimap::const_iterator; + std::pair p = cfg->WeekDaysWorktime.equal_range(weekdayId); + + for (WTIterator itr = p.first; itr != p.second; ++itr) { + ++range; + + QTime const &from = Utilities::WeekDaysWorkTimeFrom(itr); + QTime const &to = Utilities::WeekDaysWorkTimeUntil(itr); + + Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES"); + + if (current.time() >= to) { + continue; // try to use next available work-time + } else + if (current.time() <= from) { + if (prepaid) { + lastCurrent = current; + current.setTime(from); // move current forward (range==1), + // as prepaid is set + uint const minutesMoved = lastCurrent.secsTo(current) / 60; + durationMinutesBrutto += minutesMoved; + + if (range == 1) { + start_datetime = current; + } + } + } + + while (timeRangeIt != cfg->TimeRange.cend()) { + ATBTimeRange timeRange = timeRangeIt->second; + + timeRange.computeQTimes(current.time()); + + int duration = timeRange.time_range_to_in_minutes_from_start - + timeRange.time_range_from_in_minutes_from_start; + + if (minsUsed > 0) { + duration -= minsUsed; + minsUsed = 0; + } + + if (current.addSecs(duration * 60).time() <= to) { + if (minsToCarryOver > 0) { // the price for this time range + // has been is paid already + durationMinutes -= duration; + durationMinutesNetto += duration; + durationMinutesBrutto += duration; + current = current.addSecs(duration*60); + minsToCarryOver = 0; + } else { + for(const auto &x: cfg->PaymentRate) { + ATBPaymentRate const rate = x.second; + if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) { + price += (uint)rate.pra_price; + + if (price >= maxParkingPrice) { + price = maxParkingPrice; + } + + durationMinutes -= duration; + durationMinutesNetto += duration; + durationMinutesBrutto += duration; + + current = current.addSecs(duration * 60); + + if (price >= cost) { + end_datetime = current; + return end_datetime.toString(Qt::ISODate).toStdString(); + } + + break; + } + } + } + + if (durationMinutes <= 0) { + end_datetime = current; + return end_datetime.toString(Qt::ISODate).toStdString(); + } + + ++timeRangeIt; + + } else { + + lastCurrent = current; + current.setTime(to); + minsUsed = lastCurrent.secsTo(current) / 60; + + // mod duration: possibly discard some minutes in + // the next time-range + if (durationMinutes >= minsUsed) { + minsToCarryOver = durationMinutes - minsUsed; + } + + durationMinutes -= minsUsed; + durationMinutesNetto += minsUsed; + durationMinutesBrutto += minsUsed; + + if (minsUsed > 0) { + for(const auto &x: cfg->PaymentRate) { + ATBPaymentRate const rate = x.second; + if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) { + price += (uint)rate.pra_price; + + if (price >= maxParkingPrice) { + price = maxParkingPrice; + } + + if (price >= cost) { + end_datetime = current; + // return end_datetime.toString(Qt::ISODate).toStdString(); + } + break; + } + } + } + break; + } + } + } + + end_datetime = start.addSecs(durationMinutesBrutto * 60); + return end_datetime.toString(Qt::ISODate).toStdString(); + } + } + + end_datetime = QDateTime(); + return end_datetime.toString(Qt::ISODate).toStdString(); } - Ticket t = private_GetDurationFromCost(cfg, inputDate, price, prepaid); + Ticket t = private_GetDurationFromCost(cfg, inputDate, cost, prepaid); // qCritical().noquote() << t; @@ -279,9 +496,11 @@ double Calculator::GetCostFromDuration(Configuration* cfg, end_datetime.setTime(cs.getAllowedTimeRange().getTimeUntil()); return cost; } + } else { + // it might be that in such a case even prepaid ("vorkauf") + // is not allowed at any moment } - - qCritical() << __PRETTY_FUNCTION__ << "NOT YET IMPLEMENTED"; + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" << "NOT YET IMPLEMENTED"; end_datetime = QDateTime(); return 0; } @@ -299,34 +518,18 @@ double Calculator::GetCostFromDuration(Configuration* cfg, QDateTime start = start_datetime; -#define DEBUG 0 -#if DEBUG==1 - qCritical() << "start" << start.toString(Qt::ISODate) << durationMinutes; -#endif int weekdayId = -1; int weekdayIdLast = -1; - int timeRanges = 0; int durationMinutesBrutto = 0; QDateTime current = start; - //if ((durationMinutes % 5) != 0) { - // qCritical() << "ERROR DURATION (" << durationMinutes - // << ") NOT A MULTIPLE Of 5"; - //} - int days = 7; while (--days > 0) { - -#if DEBUG==1 - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "start" << start.toString(Qt::ISODate) - << "current" << current.toString(Qt::ISODate); -#endif weekdayId = current.date().dayOfWeek(); weekdayIdLast = weekdayId; // TODO: some end condition in json-file - while ((timeRanges = cfg->WeekDaysWorktime.count(weekdayId)) == 0) { + while (cfg->WeekDaysWorktime.count(weekdayId) == 0) { current = current.addDays(1); weekdayId = current.date().dayOfWeek(); if (weekdayId == weekdayIdLast) { @@ -335,11 +538,6 @@ double Calculator::GetCostFromDuration(Configuration* cfg, } } -#if DEBUG==1 - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "current" << current.toString(Qt::ISODate); -#endif - using WTIterator = std::multimap::const_iterator; std::pair p = cfg->WeekDaysWorktime.equal_range(weekdayId); @@ -347,235 +545,169 @@ double Calculator::GetCostFromDuration(Configuration* cfg, for (WTIterator itr = p.first; itr != p.second; ++itr) { QTime const &t = Utilities::WeekDaysWorkTimeUntil(itr); -#if DEBUG==1 - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "current" << current.time().toString(Qt::ISODate) - << "t" << t.toString(Qt::ISODate) - << "to" << to.toString(Qt::ISODate); -#endif - if (to < t) { to = t; } } - if (current.time() >= to) { - QDateTime const dt = start; - start = start.addDays(1); - start.setTime(QTime(0, 0, 0)); + if (carryOverNotSet) { + end_datetime = start; + return 0; + } else { + QDateTime const dt = start; + start = start.addDays(1); + start.setTime(QTime(0, 0, 0)); - durationMinutesBrutto += dt.secsTo(start) / 60; - current = start; + durationMinutesBrutto += dt.secsTo(start) / 60; + current = start; + } } else { - -#if DEBUG==1 - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "current" << current.toString(Qt::ISODate) - << "durationMinutesBrutto" << durationMinutesBrutto; -#endif - break; } } -#if DEBUG==1 - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "timeRanges" << timeRanges << weekdayId - << "durationMinutesBrutto" << durationMinutesBrutto - << "start" << start.toString(Qt::ISODate) - << "current" << current.toString(Qt::ISODate); -#endif - int durationMinutesNetto = 0; uint price = 0; if (carryOverNotSet) { int range = 0; int minsToCarryOver = 0; // from one work-time to the other on the same day + int minsUsed = 0; QDateTime lastCurrent = QDateTime(); - auto timeRangeIt = cfg->TimeRange.cbegin(); - for (; timeRangeIt != cfg->TimeRange.cend(); ++timeRangeIt) { - using WTIterator = std::multimap::const_iterator; - std::pair p = cfg->WeekDaysWorktime.equal_range(weekdayId); + using WTIterator = std::multimap::const_iterator; + std::pair p = cfg->WeekDaysWorktime.equal_range(weekdayId); - for (WTIterator itr = p.first; itr != p.second; ++itr) { - ++range; + for (WTIterator itr = p.first; itr != p.second; ++itr) { + ++range; - QTime const &from = Utilities::WeekDaysWorkTimeFrom(itr); - QTime const &to = Utilities::WeekDaysWorkTimeUntil(itr); + QTime const &from = Utilities::WeekDaysWorkTimeFrom(itr); + QTime const &to = Utilities::WeekDaysWorkTimeUntil(itr); - Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES"); + Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES"); + if (current.time() >= to) { + continue; // try to use next available work-time + } else + if (current.time() <= from) { + if (prepaid) { + lastCurrent = current; + current.setTime(from); // move current forward (range==1), + // as prepaid is set + uint const minutesMoved = lastCurrent.secsTo(current) / 60; + durationMinutesBrutto += minutesMoved; - if (current.time() >= to) { -#if DEBUG==1 - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "current" << current.toString(Qt::ISODate) - << "from" << from.toString(Qt::ISODate) - << "to" << to.toString(Qt::ISODate); -#endif - continue; // try to use next available work-time - } else - if (current.time() <= from) { - if (prepaid) { - lastCurrent = current; - current.setTime(from); // move current forward (range==1), - // as prepaid is set - uint const minutesMoved = lastCurrent.secsTo(current) / 60; -#if DEBUG==1 - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "current" << current.toString(Qt::ISODate) - << "lastCurrent" << lastCurrent.toString(Qt::ISODate) - << "minutesMoved" << minutesMoved - << "durationMinutes" << durationMinutes; -#endif - durationMinutesBrutto += minutesMoved; - - if (range == 1) { - start_datetime = current; - } + if (range == 1) { + start_datetime = current; } } + } -#if DEBUG==1 - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "from" << from.toString(Qt::ISODate) - << "to" << to.toString(Qt::ISODate) + for (auto timeRangeIt = cfg->TimeRange.cbegin(); timeRangeIt != cfg->TimeRange.cend(); ++timeRangeIt) { + + ATBTimeRange timeRange = timeRangeIt->second; + + timeRange.computeQTimes(current.time()); + + int duration = timeRange.time_range_to_in_minutes_from_start - + timeRange.time_range_from_in_minutes_from_start; + + qCritical() << __func__ << ":" << __LINE__ << "current" << current.toString(Qt::ISODate) - << "durationMinutes" << durationMinutes; -#endif + << "duration" << duration + << "minsUsed" << minsUsed + << "minsToCarryOver" << minsToCarryOver; - while (timeRangeIt != cfg->TimeRange.cend()) { - ATBTimeRange timeRange = timeRangeIt->second; - timeRange.computeQTimes(current.time()); + //if (minsUsed > 0) { + // duration -= minsUsed; + // minsUsed = 0; + //} - int duration = timeRange.time_range_to_in_minutes_from_start - - timeRange.time_range_from_in_minutes_from_start; - -#if DEBUG==1 - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "duration" << duration << timeRange.time_range_id - << "current" << current.toString(Qt::ISODate) - << "minsToCarryOver" << minsToCarryOver - << "durationMinutes" << durationMinutes; -#endif - - if (current.addSecs(duration * 60).time() <= to) { - - for(const auto &x: cfg->PaymentRate) { - ATBPaymentRate const rate = x.second; - if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) { - if (minsToCarryOver > 0) { - durationMinutes -= minsToCarryOver; - durationMinutesNetto += minsToCarryOver; - durationMinutesBrutto += minsToCarryOver; - current = current.addSecs(minsToCarryOver*60); - minsToCarryOver = 0; -#if DEBUG==1 - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "durationMinutes" << durationMinutes - << "durationMinutesNetto" << durationMinutesNetto - << "durationMinutesBrutto" << durationMinutesBrutto - << "current" << current.toString(Qt::ISODate); -#endif - } else { + if (current.addSecs(duration * 60).time() <= to) { + if (minsToCarryOver > 0) { // the price for this time range + // has been is paid already + if (minsUsed == 0) { + for(const auto &x: cfg->PaymentRate) { + ATBPaymentRate const rate = x.second; + if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) { price += (uint)rate.pra_price; durationMinutes -= duration; durationMinutesNetto += duration; durationMinutesBrutto += duration; -#if DEBUG==1 - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "duration" << duration - << "durationMinutes" << durationMinutes - << "durationMinutesNetto" << durationMinutesNetto - << "durationMinutesBrutto" << durationMinutesBrutto; -#endif - current = current.addSecs(duration * 60); -#if DEBUG==1 - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "current" << current.toString(Qt::ISODate) - << "price" << price; -#endif - } + if (durationMinutes <= 0) { + end_datetime = current; + return price; + } - break; - } - } - - if (durationMinutes <= 0) { - end_datetime = current; -#if DEBUG==1 - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "duration" << durationMinutesNetto << ", price" << price - << current.toString(Qt::ISODate) - << end_datetime.toString(Qt::ISODate); -#endif - return price; - } - - ++timeRangeIt; - - } else { - - lastCurrent = current; - current.setTime(to); - int const minsLeft = lastCurrent.secsTo(current) / 60; - - // mod duration: possibly discard some minutes in - // the next time-range - minsToCarryOver = (durationMinutes - minsLeft) % duration; - - durationMinutes -= minsLeft; - durationMinutesNetto += minsLeft; - durationMinutesBrutto += minsLeft; - -#if DEBUG==1 - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "lastCurrent" << lastCurrent.toString(Qt::ISODate) - << "current" << current.toString(Qt::ISODate) - << "minsLeft" << minsLeft; - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "duration" << duration - << "durationMinutes" << durationMinutes - << "durationMinutesNetto" << durationMinutesNetto - << "durationMinutesBrutto" << durationMinutesBrutto - << "minsToCarryOver" << minsToCarryOver; -#endif - - if (minsLeft > 0) { - for(const auto &x: cfg->PaymentRate) { - ATBPaymentRate const rate = x.second; - if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) { - price += (uint)rate.pra_price; -#if DEBUG==1 - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "price" << price; -#endif break; } } + } else { + durationMinutes -= duration; + durationMinutesNetto += duration; + durationMinutesBrutto += duration; + current = current.addSecs(duration*60); + minsToCarryOver = 0; } + } else { + for(const auto &x: cfg->PaymentRate) { + ATBPaymentRate const rate = x.second; + if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) { + price += (uint)rate.pra_price; - break; + durationMinutes -= duration; + durationMinutesNetto += duration; + durationMinutesBrutto += duration; + + current = current.addSecs(duration * 60); + break; + } + } } + + if (durationMinutes <= 0) { + end_datetime = current; + return price; + } + + //++timeRangeIt; + + } else { + + lastCurrent = current; + current.setTime(to); + minsUsed = lastCurrent.secsTo(current) / 60; + + // mod duration: possibly discard some minutes in + // the next time-range + if (durationMinutes >= minsUsed) { + minsToCarryOver = durationMinutes - minsUsed; + } + + durationMinutes -= minsUsed; + durationMinutesNetto += minsUsed; + durationMinutesBrutto += minsUsed; + + if (minsUsed > 0) { + for(const auto &x: cfg->PaymentRate) { + ATBPaymentRate const rate = x.second; + if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) { + price += (uint)rate.pra_price; + break; + } + } + } + // break; } - } + } // for (WTIterator itr = p.first; itr != p.second; ++itr) { end_datetime = start.addSecs(durationMinutesBrutto * 60); -#if DEBUG==1 - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "duration" << durationMinutesNetto - << ", price" << std::max(price, minParkingPrice) - << start.toString(Qt::ISODate) - << end_datetime.toString(Qt::ISODate); -#endif return std::max(price, minParkingPrice); } } @@ -1072,6 +1204,8 @@ QList Calculator::GetTimeSteps(Configuration *cfg) const { int const pop_carry_over = cfg->getPaymentOptions().pop_carry_over; int const pop_time_step_config = cfg->getPaymentOptions().pop_time_step_config; + static PaymentMethod const paymentMethodId = Utilities::getPaymentMethodId(cfg); + qCritical() << __func__ << ":" << __LINE__ << " start parking time:" << start.toString(Qt::ISODate); qCritical() << __func__ << ":" << __LINE__ << " payment option id:" << pop_id; qCritical() << __func__ << ":" << __LINE__ << "payment option carry over:" << pop_carry_over; @@ -1079,63 +1213,71 @@ QList Calculator::GetTimeSteps(Configuration *cfg) const { if (pop_time_step_config == (int)ATBTimeStepConfig::TimeStepConfig::DYNAMIC) { //qCritical() << __PRETTY_FUNCTION__ << "payment option time step config:" << "TimeStepConfig::DYNAMIC"; - uint16_t timeStepCompensation = 0; + if (paymentMethodId == PaymentMethod::Progressive) { // e.g. neuhauser kirchdorf (743) + std::size_t const s = cfg->TimeRange.size(); + for (std::size_t id = 1; id <= s; ++id) { + int const step = Utilities::getTimeRangeStep(cfg, id, paymentMethodId); + m_timeSteps.append(step); + } + } else { + uint16_t timeStepCompensation = 0; - if (pop_carry_over) { - int const pop_carry_over_time_range_id = cfg->getPaymentOptions().pop_carry_over_time_range_id; - QTime const carryOverTimeRangeFrom = cfg->TimeRange.find(pop_carry_over_time_range_id)->second.time_range_from; - QTime const carryOverTimeRangeTo = cfg->TimeRange.find(pop_carry_over_time_range_id)->second.time_range_to; + if (pop_carry_over) { + int const pop_carry_over_time_range_id = cfg->getPaymentOptions().pop_carry_over_time_range_id; + QTime const carryOverTimeRangeFrom = cfg->TimeRange.find(pop_carry_over_time_range_id)->second.time_range_from; + QTime const carryOverTimeRangeTo = cfg->TimeRange.find(pop_carry_over_time_range_id)->second.time_range_to; - if (carryOverTimeRangeFrom.secsTo(carryOverTimeRangeTo) <= 60) { // carry over time point, usually 00:00:00 - if (carryOverTimeRangeFrom == QTime(0, 0, 0)) { - for (auto[itr, rangeEnd] = cfg->PaymentRate.equal_range(pop_id); itr != rangeEnd; ++itr) { - int const durationId = itr->second.pra_payment_unit_id; - auto search = cfg->Duration.find(durationId); - if (search != cfg->Duration.end()) { - ATBDuration duration = search->second; - if (durationId == 1) { - QDateTime carryOver = start; - carryOver = carryOver.addDays(1); - carryOver.setTime(QTime(0, 0, 0)); + if (carryOverTimeRangeFrom.secsTo(carryOverTimeRangeTo) <= 60) { // carry over time point, usually 00:00:00 + if (carryOverTimeRangeFrom == QTime(0, 0, 0)) { + for (auto[itr, rangeEnd] = cfg->PaymentRate.equal_range(pop_id); itr != rangeEnd; ++itr) { + int const durationId = itr->second.pra_payment_unit_id; + auto search = cfg->Duration.find(durationId); + if (search != cfg->Duration.end()) { + ATBDuration duration = search->second; + if (durationId == 1) { + QDateTime carryOver = start; + carryOver = carryOver.addDays(1); + carryOver.setTime(QTime(0, 0, 0)); - int const timeStep = std::ceil(start.secsTo(carryOver) / 60.0); - if (timeStep < duration.pun_duration_min || timeStep > duration.pun_duration_max) { - qCritical() - << QString("ERROR timeStep (%1) < durationMin (%2) || timeStep (%3)) > durationMax (%4)") - .arg(timeStep).arg(duration.pun_duration_min) - .arg(timeStep).arg(duration.pun_duration_max); - break; + int const timeStep = std::ceil(start.secsTo(carryOver) / 60.0); + if (timeStep < duration.pun_duration_min || timeStep > duration.pun_duration_max) { + qCritical() + << QString("ERROR timeStep (%1) < durationMin (%2) || timeStep (%3)) > durationMax (%4)") + .arg(timeStep).arg(duration.pun_duration_min) + .arg(timeStep).arg(duration.pun_duration_max); + break; + } + qCritical() << __PRETTY_FUNCTION__ << "configured minimal parking time:" << cfg->getPaymentOptions().pop_min_time; + + // set dynamic minimal parking time + cfg->getPaymentOptions().pop_min_time = timeStep; + + qCritical() << __PRETTY_FUNCTION__ << " computed minimal parking time:" << cfg->getPaymentOptions().pop_min_time; + + duration.pun_duration = timeStep; + timeStepCompensation = duration.pun_duration_max - duration.pun_duration; + m_timeSteps << duration.pun_duration; + } else { + duration.pun_duration = duration.pun_duration_max - timeStepCompensation; + m_timeSteps << duration.pun_duration;; } - qCritical() << __PRETTY_FUNCTION__ << "configured minimal parking time:" << cfg->getPaymentOptions().pop_min_time; - // set dynamic minimal parking time - cfg->getPaymentOptions().pop_min_time = timeStep; + cfg->Duration.erase(search); + cfg->Duration.insert(pair(duration.pun_id, duration)); - qCritical() << __PRETTY_FUNCTION__ << " computed minimal parking time:" << cfg->getPaymentOptions().pop_min_time; - - duration.pun_duration = timeStep; - timeStepCompensation = duration.pun_duration_max - duration.pun_duration; - m_timeSteps << duration.pun_duration; - } else { - duration.pun_duration = duration.pun_duration_max - timeStepCompensation; - m_timeSteps << duration.pun_duration;; + } else { // if (search != cfg->Duration.end()) { + // TODO } - - cfg->Duration.erase(search); - cfg->Duration.insert(pair(duration.pun_id, duration)); - - } else { // if (search != cfg->Duration.end()) { - // TODO } + } else { // if (carryOverTimeRangeFrom == QTime(0, 0, 0)) { + // TODO } - } else { // if (carryOverTimeRangeFrom == QTime(0, 0, 0)) { + } else { // if (carryOverTimeRangeFrom == carryOverTimeRangeTo) { // TODO } - } else { // if (carryOverTimeRangeFrom == carryOverTimeRangeTo) { + } else { // if (pop_carry_over) { // TODO } - } else { // if (pop_carry_over) { - // TODO } } else { qCritical() << __PRETTY_FUNCTION__ << "payment option time step config:" << "TimeStepConfig::STATIC"; @@ -1308,6 +1450,18 @@ Calculator::GetDailyTicketPrice(Configuration* cfg, case PERMIT_TYPE::INVALID: break; } + } else { + // for projects which have not defined a daily ticket in their + // tariff-files (e.g. szeged) + price.netto = cfg->getPaymentOptions().pop_daily_card_price; + + qCritical() << "( GetDailyTicketPrice():" << __LINE__ << ")"; + qCritical() << " start:" << startDatetime.toString(Qt::ISODate); + qCritical() << " workTime from:" << QTime::fromString(QString(wt.pwd_time_from.c_str()), Qt::ISODate); + qCritical() << " workTime to:" << QTime::fromString(QString(wt.pwd_time_to.c_str()), Qt::ISODate); + qCritical() << "daily_ticket_card_price:" << price.netto; + + value = value.value_or(price); } } diff --git a/library/src/configuration.cpp b/library/src/configuration.cpp index fc42b5d..dfacdab 100644 --- a/library/src/configuration.cpp +++ b/library/src/configuration.cpp @@ -7,6 +7,7 @@ #include "tariff_business_hours.h" #include "tariff_global_defines.h" #include "tariff_carryover.h" +#include "tariff_global_defines.h" #include #include @@ -15,16 +16,16 @@ /// MemberType Configuration::IdentifyJsonMember(const char* member_name) { - if (strcmp(member_name, "Currency") == 0) return MemberType::CurrencyType; - if (strcmp(member_name, "PaymentMethod") == 0) return MemberType::PaymentMethodType; - if (strcmp(member_name, "PaymentRate") == 0) return MemberType::PaymentRateType; - if (strcmp(member_name, "PaymentOption") == 0) return MemberType::PaymentOptionType; - if (strcmp(member_name, "Duration") == 0) return MemberType::DurationType; - //if (strcmp(member_name, "WeekDays") == 0) return MemberType::WeekDaysType; - if (strcmp(member_name, "WeekDaysWorktime") == 0) return MemberType::WeekDaysWorkTimeType; - if (strcmp(member_name, "SpecialDaysWorktime") == 0) return MemberType::SpecialDaysWorktimeType; - if (strcmp(member_name, "SpecialDays") == 0) return MemberType::SpecialDaysType; - if (strcmp(member_name, "PeriodYear") == 0) return MemberType::PeriodYearType; + if (strcmp(member_name, "Currency") == 0) return MemberType::CurrencyType; + if (strcmp(member_name, "PaymentMethod") == 0) return MemberType::PaymentMethodType; + if (strcmp(member_name, "PaymentRate") == 0) return MemberType::PaymentRateType; + if (strcmp(member_name, "PaymentOption") == 0) return MemberType::PaymentOptionType; + if (strcmp(member_name, "Duration") == 0) return MemberType::DurationType; + //if (strcmp(member_name, "WeekDays") == 0) return MemberType::WeekDaysType; + if (strcmp(member_name, "WeekDaysWorktime") == 0) return MemberType::WeekDaysWorkTimeType; + if (strcmp(member_name, "SpecialDaysWorktime") == 0) return MemberType::SpecialDaysWorktimeType; + if (strcmp(member_name, "SpecialDays") == 0) return MemberType::SpecialDaysType; + if (strcmp(member_name, "PeriodYear") == 0) return MemberType::PeriodYearType; if (strcmp(member_name, "DailyTicket") == 0) return MemberType::DailyTicketType; if (strcmp(member_name, "TimeBase") == 0) return MemberType::TimeBaseType; if (strcmp(member_name, "Customer") == 0) return MemberType::CustomerType; @@ -42,36 +43,36 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json) { try { - if (cfg == nullptr) - { - printf("TariffConfiguration pointer not set\n"); - return false; - } - if (json == NULL) - { - printf("%s", "Input JSON string is NULL\n"); - return false; - } + if (cfg == nullptr) + { + printf("TariffConfiguration pointer not set\n"); + return false; + } + if (json == NULL) + { + printf("%s", "Input JSON string is NULL\n"); + return false; + } - // Parse JSON to document - Document document; - document.Parse(json); + // Parse JSON to document + Document document; + document.Parse(json); - // Return if parse error has been found - ParseErrorCode err = document.GetParseError(); - if (err != 0) - { - printf("%s %d (%s)\n", "Unable to parse JSON, error code:", err, GetParseError_En(err)); - return false; - } + // Return if parse error has been found + ParseErrorCode err = document.GetParseError(); + if (err != 0) + { + printf("%s %d (%s)\n", "Unable to parse JSON, error code:", err, GetParseError_En(err)); + return false; + } - // Validate JSON, check if it's a JSON object - qCritical() << "JSON parsing has been successful"; + // Validate JSON, check if it's a JSON object + qCritical() << "JSON parsing has been successful"; if (!document.IsObject()) { printf("%s", "Error: not a (valid) JSON object\n"); return false; } - qCritical() << "Valid JSON object identified"; + qCritical() << "Valid JSON object identified"; // Validate JSON, check configuration members if (!document.HasMember("Currency") @@ -80,36 +81,36 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json) || !document.HasMember("PaymentRate") || !document.HasMember("Duration") //|| !document.HasMember("WeekDays") - //|| !document.HasMember("SpecialDaysWorktime") - //|| !document.HasMember("SpecialDays") - ) + //|| !document.HasMember("SpecialDaysWorktime") + //|| !document.HasMember("SpecialDays") + ) { printf("%s", "Error: not a valid configuration JSON\n"); return false; } - qCritical() << "Valid JSON configuration identified"; + qCritical() << "Valid JSON configuration identified"; - ATBCurrency Currency; - ATBDuration Duration; - ATBPaymentMethod PaymentMethod; - ATBPaymentRate PaymentRate; - ATBSpecialDaysWorktime SpecialDaysWorktime; - ATBSpecialDays SpecialDays; - ATBWeekDays WeekDays; - ATBWeekDaysWorktime WeekDaysWorktime; - ATBPeriodYear YearPeriod; - ATBDailyTicket DailyTicket; - ATBTimeBase TimeBase; - ATBCustomer Customer; - ATBTimeRange TimeRange; - ATBTimeStepConfig TimeStepConfig; - ATBTariffProduct TariffProduct; - ATBInterpolation TariffInterpolation; - ATBPrepaid TariffPrepaidOption; - ATBCarryOver TariffCarryOver; + ATBCurrency Currency; + ATBDuration Duration; + ATBPaymentMethod PaymentMethod; + ATBPaymentRate PaymentRate; + ATBSpecialDaysWorktime SpecialDaysWorktime; + ATBSpecialDays SpecialDays; + ATBWeekDays WeekDays; + ATBWeekDaysWorktime WeekDaysWorktime; + ATBPeriodYear YearPeriod; + ATBDailyTicket DailyTicket; + ATBTimeBase TimeBase; + ATBCustomer Customer; + ATBTimeRange TimeRange; + ATBTimeStepConfig TimeStepConfig; + ATBTariffProduct TariffProduct; + ATBInterpolation TariffInterpolation; + ATBPrepaid TariffPrepaidOption; + ATBCarryOver TariffCarryOver; - MemberType mb_type = MemberType::UnknownType; - this->currentPaymentOptions.clear(); + MemberType mb_type = MemberType::UnknownType; + this->currentPaymentOptions.clear(); // Get all JSON object members // This code should run only once (to load JSON variables into memory) @@ -142,35 +143,34 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json) qCritical() << " -" << mb_name; - // Get array for each JSON object member - auto mb_array = document[mb_name].GetArray(); - if (mb_array.Size() <= 0) break; + // Get array for each JSON object member + auto mb_array = document[mb_name].GetArray(); + if (mb_array.Size() <= 0) break; //Iterate over provided array - for (rapidjson::SizeType j = 0; j < mb_array.Size(); j++) - { - // Get all inner objects, don't print name if NULL - auto inner_obj = mb_array[j].GetObject(); - if (inner_obj.MemberCount() <= 0) break; + for (rapidjson::SizeType j = 0; j < mb_array.Size(); j++) { + // Get all inner objects, don't print name if NULL + auto inner_obj = mb_array[j].GetObject(); + if (inner_obj.MemberCount() <= 0) break; - // Iterate over inner object JSON members - for (auto k = inner_obj.MemberBegin(); k != inner_obj.MemberEnd(); k++) - { - // Get inner object JSON member, don't print name if NULL - const char* inner_obj_name = k->name.GetString(); - if (inner_obj_name == NULL) - { - printf("Inner object name is NULL\n"); - continue; - } + // Iterate over inner object JSON members + for (auto k = inner_obj.MemberBegin(); k != inner_obj.MemberEnd(); k++) + { + // Get inner object JSON member, don't print name if NULL + const char* inner_obj_name = k->name.GetString(); + if (inner_obj_name == NULL) + { + printf("Inner object name is NULL\n"); + continue; + } - // Identify member type - mb_type = IdentifyJsonMember(mb_name); + // Identify member type + mb_type = IdentifyJsonMember(mb_name); - switch (mb_type) - { - case MemberType::UnknownType: - break; + switch (mb_type) + { + case MemberType::UnknownType: + break; case MemberType::CarryOverType: { if (QString(inner_obj_name) == QString("carry_over_id")) { if (k->value.IsInt()) { @@ -196,6 +196,11 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json) TariffCarryOver.carryover[day].day = day; } } else + if (member == "carry_over_duration") { + if (w->value.IsInt()) { + TariffCarryOver.carryover[day].duration = w->value.GetInt(); + } + } else if (member == "carry_over_seemless") { if (w->value.IsBool()) { bool b = w->value.GetBool(); @@ -330,6 +335,18 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json) int const x = k->value.GetInt(); TariffInterpolation.dynamic_until_price = x; } + } else + if (QString(inner_obj_name) == QString("interpol_seemless")) { + if (k->value.IsBool()) { + bool const x = k->value.GetBool(); + TariffInterpolation.seemless = x; + } + } + if (QString(inner_obj_name) == QString("interpol_never")) { + if (k->value.IsBool()) { + bool const x = k->value.GetBool(); + TariffInterpolation.never = x; + } } } break; case MemberType::ProductType: { @@ -543,22 +560,22 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json) } break; case MemberType::CurrencyType: - if (strcmp(inner_obj_name, "pcu_id") == 0) Currency.pcu_id = k->value.GetInt(); - else if (strcmp(inner_obj_name, "pcu_sign") == 0) Currency.pcu_sign = k->value.GetString(); - else if (strcmp(inner_obj_name, "pcu_major") == 0) Currency.pcu_major = k->value.GetString(); - else if (strcmp(inner_obj_name, "pcu_minor") == 0) Currency.pcu_minor = k->value.GetString(); - else if (strcmp(inner_obj_name, "pcu_active") == 0) Currency.pcu_active = k->value.GetBool(); - break; - case MemberType::PaymentMethodType: - if (strcmp(inner_obj_name, "pme_id") == 0) PaymentMethod.pme_id = k->value.GetInt(); - else if (strcmp(inner_obj_name, "pme_label") == 0) PaymentMethod.pme_label = k->value.GetString(); - break; - case MemberType::PaymentRateType: - if (strcmp(inner_obj_name, "pra_payment_option_id") == 0) PaymentRate.pra_payment_option_id = k->value.GetInt(); - else if (strcmp(inner_obj_name, "pra_payment_unit_id") == 0) PaymentRate.pra_payment_unit_id = k->value.GetInt(); - else if (strcmp(inner_obj_name, "pra_price") == 0) PaymentRate.pra_price = k->value.GetDouble(); - break; - case MemberType::PaymentOptionType: + if (strcmp(inner_obj_name, "pcu_id") == 0) Currency.pcu_id = k->value.GetInt(); + else if (strcmp(inner_obj_name, "pcu_sign") == 0) Currency.pcu_sign = k->value.GetString(); + else if (strcmp(inner_obj_name, "pcu_major") == 0) Currency.pcu_major = k->value.GetString(); + else if (strcmp(inner_obj_name, "pcu_minor") == 0) Currency.pcu_minor = k->value.GetString(); + else if (strcmp(inner_obj_name, "pcu_active") == 0) Currency.pcu_active = k->value.GetBool(); + break; + case MemberType::PaymentMethodType: + if (strcmp(inner_obj_name, "pme_id") == 0) PaymentMethod.pme_id = k->value.GetInt(); + else if (strcmp(inner_obj_name, "pme_label") == 0) PaymentMethod.pme_label = k->value.GetString(); + break; + case MemberType::PaymentRateType: + if (strcmp(inner_obj_name, "pra_payment_option_id") == 0) PaymentRate.pra_payment_option_id = k->value.GetInt(); + else if (strcmp(inner_obj_name, "pra_payment_unit_id") == 0) PaymentRate.pra_payment_unit_id = k->value.GetInt(); + else if (strcmp(inner_obj_name, "pra_price") == 0) PaymentRate.pra_price = k->value.GetDouble(); + break; + case MemberType::PaymentOptionType: if (strcmp(inner_obj_name, "pop_id") == 0) { this->currentPaymentOptions.append(ATBPaymentOption()); this->currentPaymentOptions.last().reset(); @@ -583,6 +600,8 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json) this->currentPaymentOptions.last().pop_min_price = k->value.GetDouble(); } else if (strcmp(inner_obj_name, "pop_prepaid_option_id") == 0) { this->currentPaymentOptions.last().pop_prepaid_option_id = k->value.GetInt(); + } else if (strcmp(inner_obj_name, "pop_truncate_last_interpolation_step") == 0) { + this->currentPaymentOptions.last().pop_truncate_last_interpolation_step = k->value.GetBool(); } else if (strcmp(inner_obj_name, "pop_carry_over_option_id") == 0) { this->currentPaymentOptions.last().pop_carry_over_option_id = k->value.GetInt(); } else if (strcmp(inner_obj_name, "pop_carry_over") == 0) { @@ -665,93 +684,92 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json) } } break; - case MemberType::DurationType: - if (strcmp(inner_obj_name, "pun_id") == 0) Duration.pun_id = k->value.GetInt(); - else if (strcmp(inner_obj_name, "pun_label") == 0) Duration.pun_label = k->value.GetString(); - else if (strcmp(inner_obj_name, "pun_duration") == 0) Duration.pun_duration = k->value.GetDouble(); + case MemberType::DurationType: + if (strcmp(inner_obj_name, "pun_id") == 0) Duration.pun_id = k->value.GetInt(); + else if (strcmp(inner_obj_name, "pun_label") == 0) Duration.pun_label = k->value.GetString(); + else if (strcmp(inner_obj_name, "pun_duration") == 0) Duration.pun_duration = k->value.GetDouble(); else if (strcmp(inner_obj_name, "pun_duration_min") == 0) Duration.pun_duration_min = k->value.GetInt(); else if (strcmp(inner_obj_name, "pun_duration_max") == 0) Duration.pun_duration_max = k->value.GetInt(); else if (strcmp(inner_obj_name, "pun_interpolation_id") == 0) Duration.pun_interpolation_id = k->value.GetInt(); break; - case MemberType::SpecialDaysWorktimeType: - if (strcmp(inner_obj_name, "pedwt_id") == 0) SpecialDaysWorktime.pedwt_id = k->value.GetInt(); - else if (strcmp(inner_obj_name, "pedwt_period_exc_day_id") == 0) SpecialDaysWorktime.pedwt_period_exc_day_id = k->value.GetInt(); - else if (strcmp(inner_obj_name, "pedwt_time_from") == 0) SpecialDaysWorktime.pedwt_time_from = k->value.GetString(); - else if (strcmp(inner_obj_name, "pedwt_time_to") == 0) SpecialDaysWorktime.pedwt_time_to = k->value.GetString(); - else if (strcmp(inner_obj_name, "pedwt_price") == 0) SpecialDaysWorktime.pedwt_price = k->value.GetDouble(); - break; - /*case MemberType::WeekDaysType: - if (strcmp(inner_obj_name, "pdiw_id") == 0) WeekDays.pdiw_id = k->value.GetInt(); - else if (strcmp(inner_obj_name, "pdiw_label") == 0) WeekDays.pdiw_label = k->value.GetString(); - else if (strcmp(inner_obj_name, "pdiw_index") == 0) WeekDays.pdiw_index = k->value.GetInt(); - break;*/ - case MemberType::WeekDaysWorkTimeType: - if (strcmp(inner_obj_name, "pwd_id") == 0) WeekDaysWorktime.pwd_id = k->value.GetInt(); - else if (strcmp(inner_obj_name, "pwd_period_week_day_id") == 0) WeekDaysWorktime.pwd_period_week_day_id = k->value.GetInt(); - else if (strcmp(inner_obj_name, "pwd_period_day_in_week_id") == 0) WeekDaysWorktime.pwd_period_day_in_week_id = k->value.GetInt(); - else if (strcmp(inner_obj_name, "pwd_time_from") == 0) WeekDaysWorktime.pwd_time_from = k->value.GetString(); + case MemberType::SpecialDaysWorktimeType: + if (strcmp(inner_obj_name, "pedwt_id") == 0) SpecialDaysWorktime.pedwt_id = k->value.GetInt(); + else if (strcmp(inner_obj_name, "pedwt_period_exc_day_id") == 0) SpecialDaysWorktime.pedwt_period_exc_day_id = k->value.GetInt(); + else if (strcmp(inner_obj_name, "pedwt_time_from") == 0) SpecialDaysWorktime.pedwt_time_from = k->value.GetString(); + else if (strcmp(inner_obj_name, "pedwt_time_to") == 0) SpecialDaysWorktime.pedwt_time_to = k->value.GetString(); + else if (strcmp(inner_obj_name, "pedwt_price") == 0) SpecialDaysWorktime.pedwt_price = k->value.GetDouble(); + break; + /*case MemberType::WeekDaysType: + if (strcmp(inner_obj_name, "pdiw_id") == 0) WeekDays.pdiw_id = k->value.GetInt(); + else if (strcmp(inner_obj_name, "pdiw_label") == 0) WeekDays.pdiw_label = k->value.GetString(); + else if (strcmp(inner_obj_name, "pdiw_index") == 0) WeekDays.pdiw_index = k->value.GetInt(); + break;*/ + case MemberType::WeekDaysWorkTimeType: + if (strcmp(inner_obj_name, "pwd_id") == 0) WeekDaysWorktime.pwd_id = k->value.GetInt(); + else if (strcmp(inner_obj_name, "pwd_period_week_day_id") == 0) WeekDaysWorktime.pwd_period_week_day_id = k->value.GetInt(); + else if (strcmp(inner_obj_name, "pwd_period_day_in_week_id") == 0) WeekDaysWorktime.pwd_period_day_in_week_id = k->value.GetInt(); + else if (strcmp(inner_obj_name, "pwd_time_from") == 0) WeekDaysWorktime.pwd_time_from = k->value.GetString(); else if (strcmp(inner_obj_name, "pwd_time_to") == 0) WeekDaysWorktime.pwd_time_to = k->value.GetString(); break; - case MemberType::SpecialDaysType: - if (strcmp(inner_obj_name, "ped_id") == 0) SpecialDays.ped_id = k->value.GetInt(); - else if (strcmp(inner_obj_name, "ped_label") == 0) SpecialDays.ped_label = k->value.GetString(); - else if (strcmp(inner_obj_name, "ped_date_start") == 0) SpecialDays.ped_date_start = k->value.GetString(); - else if (strcmp(inner_obj_name, "ped_date_end") == 0) SpecialDays.ped_date_end = k->value.GetString(); - else if (strcmp(inner_obj_name, "ped_period_special_day_id") == 0) SpecialDays.ped_period_special_day_id = k->value.GetInt(); + case MemberType::SpecialDaysType: + if (strcmp(inner_obj_name, "ped_id") == 0) SpecialDays.ped_id = k->value.GetInt(); + else if (strcmp(inner_obj_name, "ped_label") == 0) SpecialDays.ped_label = k->value.GetString(); + else if (strcmp(inner_obj_name, "ped_date_start") == 0) SpecialDays.ped_date_start = k->value.GetString(); + else if (strcmp(inner_obj_name, "ped_date_end") == 0) SpecialDays.ped_date_end = k->value.GetString(); + else if (strcmp(inner_obj_name, "ped_period_special_day_id") == 0) SpecialDays.ped_period_special_day_id = k->value.GetInt(); else if (strcmp(inner_obj_name, "ped_payment_option_id") == 0) SpecialDays.ped_payment_option_id = k->value.GetInt(); else if (strcmp(inner_obj_name, "ped_year") == 0) SpecialDays.ped_year = k->value.GetInt(); - break; - case MemberType::PeriodYearType: - if (strcmp(inner_obj_name, "pye_id") == 0) YearPeriod.pye_id = k->value.GetInt(); - else if (strcmp(inner_obj_name, "pye_label") == 0) YearPeriod.pye_label = k->value.GetString(); - else if (strcmp(inner_obj_name, "pye_start_month") == 0) YearPeriod.pye_start_month = k->value.GetInt(); - else if (strcmp(inner_obj_name, "pye_start_day") == 0) YearPeriod.pye_start_day = k->value.GetInt(); - else if (strcmp(inner_obj_name, "pye_end_month") == 0) YearPeriod.pye_end_month = k->value.GetInt(); - else if (strcmp(inner_obj_name, "pye_end_day") == 0) YearPeriod.pye_end_day = k->value.GetInt(); - break; - default: - break; - } + break; + case MemberType::PeriodYearType: + if (strcmp(inner_obj_name, "pye_id") == 0) YearPeriod.pye_id = k->value.GetInt(); + else if (strcmp(inner_obj_name, "pye_label") == 0) YearPeriod.pye_label = k->value.GetString(); + else if (strcmp(inner_obj_name, "pye_start_month") == 0) YearPeriod.pye_start_month = k->value.GetInt(); + else if (strcmp(inner_obj_name, "pye_start_day") == 0) YearPeriod.pye_start_day = k->value.GetInt(); + else if (strcmp(inner_obj_name, "pye_end_month") == 0) YearPeriod.pye_end_month = k->value.GetInt(); + else if (strcmp(inner_obj_name, "pye_end_day") == 0) YearPeriod.pye_end_day = k->value.GetInt(); + break; + default: + break; + } //#pragma endregion - } + } // Push to specific list depending on member type - switch (mb_type) - { - case MemberType::UnknownType: - break; + switch (mb_type) { + case MemberType::UnknownType: + break; case MemberType::PaymentMethodType: - cfg->PaymentMethod.insert(pair(PaymentMethod.pme_id, PaymentMethod)); - break; + cfg->PaymentMethod.insert(pair(PaymentMethod.pme_id, PaymentMethod)); + break; case MemberType::PaymentRateType: - // qCritical() << "PaymentRate" << PaymentRate; + // qCritical() << "PaymentRate" << PaymentRate.pra_price << PaymentRate.pra_payment_option_id; cfg->PaymentRate.insert(pair(PaymentRate.pra_payment_option_id, PaymentRate)); - break; + break; case MemberType::PaymentOptionType: { if (!this->currentPaymentOptions.isEmpty()) { ATBPaymentOption const &PaymentOption = this->currentPaymentOptions.last(); cfg->PaymentOption.insert(pair(PaymentOption.pop_payment_method_id, PaymentOption)); } } break; - case MemberType::DurationType: + case MemberType::DurationType: cfg->Duration.insert(pair(Duration.pun_id, Duration)); // qCritical() << Duration; break; - case MemberType::SpecialDaysWorktimeType: - cfg->SpecialDaysWorktime.insert(pair(SpecialDaysWorktime.pedwt_period_exc_day_id, SpecialDaysWorktime)); - break; + case MemberType::SpecialDaysWorktimeType: + cfg->SpecialDaysWorktime.insert(pair(SpecialDaysWorktime.pedwt_period_exc_day_id, SpecialDaysWorktime)); + break; //case MemberType::WeekDaysType: // cfg->WeekDays.insert(pair(WeekDays.pdiw_index, WeekDays)); // break; - case MemberType::WeekDaysWorkTimeType: - cfg->WeekDaysWorktime.insert(pair(WeekDaysWorktime.pwd_period_day_in_week_id, WeekDaysWorktime)); - break; - case MemberType::SpecialDaysType: - cfg->SpecialDays.insert(pair(SpecialDays.ped_id, SpecialDays)); - break; - case MemberType::PeriodYearType: - cfg->YearPeriod.insert(pair(YearPeriod.pye_id, YearPeriod)); - break; + case MemberType::WeekDaysWorkTimeType: + cfg->WeekDaysWorktime.insert(pair(WeekDaysWorktime.pwd_period_day_in_week_id, WeekDaysWorktime)); + break; + case MemberType::SpecialDaysType: + cfg->SpecialDays.insert(pair(SpecialDays.ped_id, SpecialDays)); + break; + case MemberType::PeriodYearType: + cfg->YearPeriod.insert(pair(YearPeriod.pye_id, YearPeriod)); + break; case MemberType::DailyTicketType: cfg->DailyTicket.insert(pair(DailyTicket.daily_ticket_id, DailyTicket)); qCritical() << DailyTicket; @@ -790,18 +808,136 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json) qCritical() << TariffCarryOver; break; default: - break; - } - } + break; } - return true; - } - catch (...) { - printf("%s\n", "General exception has occurred while parsing JSON\n"); - return false; + } } + return true; + } + catch (...) { + printf("%s\n", "General exception has occurred while parsing JSON\n"); + return false; + } } +std::optional Configuration::getInterpolationEnd(QDateTime const &start, int paymentOptionIndex) const { + int const pop_id = getPaymentOptions(paymentOptionIndex).pop_id; + int const pop_carry_over_option_id = getPaymentOptions(paymentOptionIndex).pop_carry_over_option_id; + int const pop_truncate_last_interpolation_step = getPaymentOptions(paymentOptionIndex).pop_truncate_last_interpolation_step; + int const weekDay = start.date().dayOfWeek(); + //QTime const &carryOverStart = TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].static_start; + //QTime const &carryOverEnd = TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].static_end; + //bool const carry_over_seemless = TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].seemless; + //bool const carry_over_never = TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].never; + int const carryOverDuration = TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].duration; + + std::optional value = std::nullopt; + + QDateTime interpolationEndTime = start; + + int price = 0; + + for (auto[itr, rangeEnd] = PaymentRate.equal_range(pop_id); itr != rangeEnd; ++itr) { + int const durationId = itr->second.pra_payment_unit_id; + // int const price = itr->second.pra_price; + + auto search = Duration.find(durationId); + if (search != Duration.end()) { + ATBDuration duration = search->second; + + if (duration.pun_interpolation_id == -1) { + // should never happen -> misconfigured tariff-file + qCritical() << "(" << __func__ << ":" << __LINE__ << ") ERROR pun_interpolation not set!"; + qCritical() << "(" << __func__ << ":" << __LINE__ << ") See for instance customer_505/6"; + break; + } + + std::optional ipolCheck = getInterpolationType(duration.pun_interpolation_id); + if (ipolCheck) { + ATBInterpolation interpolation = ipolCheck.value(); + switch (duration.pun_interpolation_id) { + case static_cast(ATBInterpolation::NO_INTERPOLATION): + //qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO"; + break; + case static_cast(ATBInterpolation::STATIC_WALLCLOCK_TIME_VALUES): + //qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO"; + break; + case static_cast(ATBInterpolation::STATIC_TIMEPOINT_AND_DURATION): + //qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO"; + break; + case static_cast(ATBInterpolation::DYNAMIC_TIMEPOINT_AND_STATIC_DURATION): + //qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO"; + break; + case static_cast(ATBInterpolation::DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_DURATION): + //qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO"; + break; + case static_cast(ATBInterpolation::DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_PRICE): { + interpolation.dynamic_start = start.time(); + interpolation.dynamic_start.setHMS(start.time().hour(), start.time().minute(), 0); + + //qCritical() << "(" << __func__ << ":" << __LINE__ << ") interpol start:" << interpolation.dynamic_start.toString(Qt::ISODate); + //qCritical() << "(" << __func__ << ":" << __LINE__ << ") computed interpol end so far:" << interpolationEndTime.toString(Qt::ISODate); + + if (interpolation.seemless) { + qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO"; + } else + if (interpolation.never) { + qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO"; + } else { + QDateTime const &s = interpolationEndTime.addSecs(duration.pun_duration * 60); + int const minutesToStaticEnd = s.time().secsTo(interpolation.static_end) / 60; + + //qCritical() << "(" << __func__ << ":" << __LINE__ << ") computed interpol end so far:" << s.toString(Qt::ISODate); + //qCritical() << "(" << __func__ << ":" << __LINE__ << ") interpol static end:" << interpolation.static_end.toString(Qt::ISODate); + //qCritical() << "(" << __func__ << ":" << __LINE__ << ") minutes to static end:" << minutesToStaticEnd; + //qCritical() << "(" << __func__ << ":" << __LINE__ << ") pun-id:" << duration.pun_id; + + int p = 0; + for (auto[it, rangeEnd] = this->PaymentRate.equal_range(pop_id); it != rangeEnd; ++it) { + if (it->second.pra_payment_unit_id == duration.pun_id) { + if (minutesToStaticEnd >= 0) { + // the end of the interpolation for this day must be before a possible carry over interval + p = it->second.pra_price; + //qCritical() << "(" << __func__ << ":" << __LINE__ << ") next price:" << p; + price += p; + interpolationEndTime = s; + } else { + if (pop_truncate_last_interpolation_step == false) { + p = it->second.pra_price; + //qCritical() << "(" << __func__ << ":" << __LINE__ << ") next price:" << p; + price += p; + interpolationEndTime = s; + interpolationEndTime = interpolationEndTime.addSecs(carryOverDuration * 60); + } else { + qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO"; + } + } + } + } + + //qCritical() << "(" << __func__ << ":" << __LINE__ << ") price:" << price; + + if (price >= interpolation.dynamic_until_price) { + qCritical() << "(" << __func__ << ":" << __LINE__ << ") price:" << price; + qCritical() << "(" << __func__ << ":" << __LINE__ << ") computed interpol endr:" << interpolationEndTime.toString(Qt::ISODate); + value = value.value_or(interpolationEndTime); + break; + } + } + } + break; + case static_cast(ATBInterpolation::DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_END_TIME): + break; + default:; + } + } + } + } + + return value; +} + + int Configuration::getPaymentOptionIndexIfSpecialDay(QDateTime const &dt) const { if (isSpecialDay(dt)) { int const numOptions = getAllPaymentOptions().size(); @@ -1043,23 +1179,27 @@ std::optional Configuration::getPrepaidType(int key) const { return value; } -std::optional Configuration::adaptStart(QDateTime const &start, int prepaid_option_id) { +std::optional Configuration::prepaidStart(QDateTime const &start, int prepaid_option_id) { std::optional value; QDateTime s = start; + qCritical() << "(" << __func__ << ":" << __LINE__ << ") prepaid option id:" << prepaid_option_id; + std::optional prepaid_option = getPrepaidType(prepaid_option_id); if (prepaid_option.has_value()) { ATBPrepaid prepaid = prepaid_option.value(); - if (prepaid.anytime == true) { - int const weekdayId = s.date().dayOfWeek(); - QTime worktime_from = QTime::fromString(WeekDaysWorktime.find(weekdayId)->second.pwd_time_from.c_str(), Qt::ISODate); - QTime worktime_to = QTime::fromString(WeekDaysWorktime.find(weekdayId)->second.pwd_time_to.c_str(), Qt::ISODate); - if (s.time() < worktime_from) { - s.setTime(worktime_from); + + if (prepaid.anytime == false && prepaid.never == false) { + // start: 22:00, end: 08:00 + QTime prepaidStart = TariffPrepaidOptions.find(prepaid_option_id)->second.static_start; + QTime prepaidEnd = TariffPrepaidOptions.find(prepaid_option_id)->second.static_end; + + if (s.time() >= prepaidStart) { + s = s.addDays(1); + s.setTime(prepaidEnd); } else - if (worktime_to < s.time()) { - s = start.addDays(1); - s.setTime(worktime_from); + if (s.time() < prepaidEnd) { + s.setTime(prepaidEnd); } s.setTime(QTime(s.time().hour(), s.time().minute(), 0)); value = value.value_or(s); diff --git a/library/src/tariff_global_defines.cpp b/library/src/tariff_global_defines.cpp new file mode 100644 index 0000000..162c745 --- /dev/null +++ b/library/src/tariff_global_defines.cpp @@ -0,0 +1,5 @@ +#include "tariff_global_defines.h" + +int DBG_LEVEL = DBG_NOTICE; +// int DBG_LEVEL = DBG_INFORMATION; +// int DBG_LEVEL = DBG_DEBUG; diff --git a/main/main.cpp b/main/main.cpp index f5e52b8..d98d4d3 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -643,7 +643,7 @@ int main() { int pop_max_price; int pop_daily_card_price; - input.open("/opt/ptu5/opt/customer_505/etc/psa_tariff/tariff01.json"); + input.open("/home/linux/customer_505/etc/psa_tariff/tariff01.json"); //input.open("/opt/ptu5/opt/customer_506/etc/psa_tariff/tariff01.json"); std::stringstream sstr; @@ -667,6 +667,14 @@ int main() { qCritical() << " pop_min_price: " << pop_min_price; qCritical() << " pop_max_price: " << pop_max_price; + //QDateTime s = QDateTime::currentDateTime(); + //s.setTime(QTime(13, 30, 0)); + //std::optional e = cfg.getInterpolationEnd(s, 0); + //if (e) { + // qCritical() << " endtime: " << e.value().toString(Qt::ISODate); + //} + //return 0; + QList timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg); qCritical() << "TimeSteps" << timeSteps; @@ -707,7 +715,7 @@ int main() { } //for (int minutes = 0; minutes < 1440; ++minutes) { - for (int minutes = 420; minutes < 420; minutes += 1) { + for (int minutes = 480; minutes < 480; minutes += 1) { QDateTime start = s.addSecs(minutes * 60); // qCritical() << "start" << start.toString(Qt::ISODate); @@ -726,7 +734,7 @@ int main() { effectiveStart.setTime(QTime(8, 0, 0)); // next day } - for (int i = 10; i <= 400; i += 10) { + for (int i = 10; i <= 10; i += 10) { //for (int i = 2100; i <= 2100; i += 10) { cost = i; diff --git a/main/main.pro b/main/main.pro index 19f74e6..e75a7f5 100644 --- a/main/main.pro +++ b/main/main.pro @@ -29,8 +29,8 @@ SOURCES += main.cpp # HEADERS += -# OTHER_FILES += \ - +OTHER_FILES += \ + /home/linux/customer_505/etc/psa_tariff/tariff01.json