From 260973cd094c731dba4f5be149edc691e5cf28fb Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Thu, 1 Aug 2024 15:44:06 +0200 Subject: [PATCH 1/8] Added pop_plus_steps/pop_minus_steps to control step sizes --- library/include/mobilisis/payment_opt.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/include/mobilisis/payment_opt.h b/library/include/mobilisis/payment_opt.h index 6bb51c0..ec16849 100644 --- a/library/include/mobilisis/payment_opt.h +++ b/library/include/mobilisis/payment_opt.h @@ -38,8 +38,10 @@ public: pop_daily_card_price = -1; pop_business_hours = -1; pop_time_step_config = -1; - pop_use_only_upto_datetime = ""; - pop_use_only_for_duration = 0; + pop_use_only_upto_datetime = ""; // deprecated + pop_use_only_for_duration = 0; // deprecated + pop_plus_steps = 1; // +: jump steps forward + pop_minus_steps = 1; // -: jump steps backward } int pop_id; @@ -69,6 +71,8 @@ public: int pop_time_step_config; bool pop_accumulate_prices; bool pop_accumulate_durations; + int pop_plus_steps; + int pop_minus_steps; struct ATBMaxDateTime { int direction; From 89b05ffadc1606a2afb16470e0644c72a4107595 Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Thu, 1 Aug 2024 15:45:50 +0200 Subject: [PATCH 2/8] Added GetYearPeriodActive() to get active year period. --- library/include/mobilisis/utilities.h | 2 ++ library/src/utilities.cpp | 37 +++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/library/include/mobilisis/utilities.h b/library/include/mobilisis/utilities.h index cf1b756..9c9a46a 100644 --- a/library/include/mobilisis/utilities.h +++ b/library/include/mobilisis/utilities.h @@ -3,6 +3,7 @@ #include #include #include +#include #include "day_of_week.h" #include "configuration.h" @@ -62,6 +63,7 @@ namespace Utilities { /// bool IsYearPeriodActive(Configuration* cfg, struct tm* currentDateTime); bool IsYearPeriodActive(Configuration const *cfg, QDateTime const ¤tDateTime); + std::optional GetYearPeriodActive(Configuration const *cfg, QDateTime const ¤tDateTime); /// /// Check permissions diff --git a/library/src/utilities.cpp b/library/src/utilities.cpp index ff47fc5..85f43fb 100644 --- a/library/src/utilities.cpp +++ b/library/src/utilities.cpp @@ -215,6 +215,43 @@ bool Utilities::IsYearPeriodActive(Configuration const *cfg, QDateTime const &dt return true; } +std::optional +Utilities::GetYearPeriodActive(Configuration const *cfg, QDateTime const ¤tDateTime) { + + ATBPeriodYear period; + std::optional value; + + for (multimap::const_iterator it = cfg->YearPeriod.cbegin(); + it != cfg->YearPeriod.cend(); + ++it) { + QDate const s(currentDateTime.date().year(), it->second.pye_start_month, it->second.pye_start_day); + QDate const e(currentDateTime.date().year(), it->second.pye_end_month, it->second.pye_end_day); + + QDateTime start(currentDateTime); + QDateTime end(currentDateTime); + + start.setDate(s); + end.setDate(e); + + if (start.date().dayOfYear() < end.date().dayOfYear()) { + // start and end in the same year + if (currentDateTime.date().dayOfYear() >= start.date().dayOfYear() && + currentDateTime.date().dayOfYear() <= end.date().dayOfYear()) { + value = value.value_or(it->second); + break; + } + } else { + if (currentDateTime.date().dayOfYear() >= start.date().dayOfYear() || + currentDateTime.date().dayOfYear() <= end.date().dayOfYear()) { + value = value.value_or(it->second); + break; + } + } + } + + return value; +} + /// bool Utilities::CheckSpecialDay(Configuration* cfg, const char* currentDateTimeStr, int* specialDayId, double* specialDayPrice) { From f0677374eca7dd248df3231c0183a0e159bcac33 Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Thu, 1 Aug 2024 15:46:49 +0200 Subject: [PATCH 3/8] Parsing of pop_plus_steps/pop_minus_steps --- library/src/configuration.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/library/src/configuration.cpp b/library/src/configuration.cpp index 8e19ea0..c481ad2 100644 --- a/library/src/configuration.cpp +++ b/library/src/configuration.cpp @@ -598,6 +598,14 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json) if (k->value.IsInt()) { this->currentPaymentOptions.last().pop_use_only_for_duration = k->value.GetInt(); } + } else if (strcmp(inner_obj_name, "pop_plus_steps") == 0) { + if (k->value.IsInt()) { + this->currentPaymentOptions.last().pop_plus_steps = k->value.GetInt(); + } + } else if (strcmp(inner_obj_name, "pop_minus_steps") == 0) { + if (k->value.IsInt()) { + this->currentPaymentOptions.last().pop_minus_steps = k->value.GetInt(); + } } else if (strcmp(inner_obj_name, "pop_payment_method_id") == 0) { this->currentPaymentOptions.last().pop_payment_method_id = k->value.GetInt(); } else if (strcmp(inner_obj_name, "pop_day_end_time") == 0) { @@ -999,6 +1007,9 @@ int Configuration::getPaymentOptionIndex(QDateTime const &dt) const { for (int opt=0; opt < numOptions; ++opt) { uint64_t const pop_business_hours = getPaymentOptions(opt).pop_business_hours; + if (pop_business_hours == 0) { // 0 == 24/7 + return opt; + } uint64_t p = 0; int const dayOfWeek = dt.date().dayOfWeek(); From cde490bab2d0c051228c6f20559e6181e90ab7e5 Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Thu, 1 Aug 2024 16:00:10 +0200 Subject: [PATCH 4/8] compute_next_time_step(): Added handling with pop_plus_steps/pop_minus_steps: '+' usually takes more than one time step. '-' is usually 1. Changed behaviour when current time is not found in the list of time steps: Search for the entry with the smallest distance to 'current time'. If the distance is smaller than 3 minutes, then use 'current time' as new entry in the list of time steps. --- library/src/calculate_price.cpp | 94 +++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 23 deletions(-) diff --git a/library/src/calculate_price.cpp b/library/src/calculate_price.cpp index ca0ec84..7d76560 100644 --- a/library/src/calculate_price.cpp +++ b/library/src/calculate_price.cpp @@ -3,6 +3,8 @@ #include "calculator_functions.h" #include "payment_option.h" #include "utilities.h" +#include "tariff_global_defines.h" +#include "period_year.h" #include #include @@ -462,8 +464,8 @@ int CALCULATE_LIBRARY_API compute_next_timestep(parking_tariff_t *tariff, int cu int UpDown, PermitType const &permitType) { - qCritical() << " compute_next_timestep() currentTimeMinutes: " << currentTimeMinutes; - qCritical() << " compute_next_timestep() up/down (1=up, 0=down): " << UpDown; + qCritical() << __LINE__ << "compute_next_timestep() currentTimeMinutes: " << currentTimeMinutes; + qCritical() << __LINE__ << "compute_next_timestep() up/down (1=up, 0=down): " << UpDown; // FIXME //std::optional paymentOption = tariff->getPaymentOptionForKey(permitType.get()); @@ -473,7 +475,12 @@ int CALCULATE_LIBRARY_API compute_next_timestep(parking_tariff_t *tariff, int cu //} int const paymentOptionIndex = tariff->getPaymentOptionIndex(permitType); - qCritical() << " compute_next_timestep() payment option index: " << paymentOptionIndex; + int const &pop_plus_steps = tariff->getPaymentOptions(paymentOptionIndex).pop_plus_steps; + int const &pop_minus_steps = tariff->getPaymentOptions(paymentOptionIndex).pop_minus_steps; + + qCritical() << __LINE__ << "compute_next_timestep() payment option index: " << paymentOptionIndex; + qCritical() << __LINE__ << "compute_next_timestep() plus steps: " << pop_plus_steps; + qCritical() << __LINE__ << "compute_next_timestep() minus steps: " << pop_minus_steps; Configuration const *cfg = tariff; @@ -481,19 +488,19 @@ int CALCULATE_LIBRARY_API compute_next_timestep(parking_tariff_t *tariff, int cu PaymentMethod const paymentMethodId = Utilities::getPaymentMethodId(cfg); switch (paymentMethodId) { case PaymentMethod::Progressive: - qCritical() << __LINE__ << " compute_next_timestep() paymentMethodId: Progressive"; + qCritical() << __LINE__ << "compute_next_timestep() paymentMethodId: Progressive"; break; case PaymentMethod::Degressive: - qCritical() << __LINE__ << " compute_next_timestep() paymentMethodId: Degressive"; + qCritical() << __LINE__ << "compute_next_timestep() paymentMethodId: Degressive"; break; case PaymentMethod::Linear: - qCritical() << __LINE__ << " compute_next_timestep() paymentMethodId: Linear"; + qCritical() << __LINE__ << "compute_next_timestep() paymentMethodId: Linear"; break; case PaymentMethod::Steps: - qCritical() << __LINE__ << " compute_next_timestep() paymentMethodId: Steps"; + qCritical() << __LINE__ << "compute_next_timestep() paymentMethodId: Steps"; break; case PaymentMethod::Undefined: - qCritical() << __LINE__ << " compute_next_timestep() paymentMethodId: Undefined"; + qCritical() << __LINE__ << "compute_next_timestep() paymentMethodId: Undefined"; break; } @@ -502,9 +509,8 @@ int CALCULATE_LIBRARY_API compute_next_timestep(parking_tariff_t *tariff, int cu if ((paymentMethodId == PaymentMethod::Steps) || // progressive tariff: e.g. Neuhauser, Kirchdorf (743) (paymentMethodId == PaymentMethod::Progressive)) + // (paymentMethodId == PaymentMethod::Degressive)) degressive tariff: e.g. Fuchs Technik (500) { - // int paymentOptionIndex = 1; - QList &stepList = Calculator::GetInstance().GetTimeSteps(tariff, paymentOptionIndex); int const size = stepList.size(); if (size == 0) { @@ -512,52 +518,94 @@ int CALCULATE_LIBRARY_API compute_next_timestep(parking_tariff_t *tariff, int cu return currentTimeMinutes; } - qCritical() << " compute_next_timestep() first time step:" << stepList[0]; - qCritical() << " compute_next_timestep() timeSteps:" << stepList; - qCritical() << " compute_next_timestep() currentTimeInMinutes:" << currentTimeMinutes; + qCritical() << __LINE__ << "compute_next_timestep() first time step:" << stepList[0]; + qCritical() << __LINE__ << "compute_next_timestep() timeSteps:" << stepList; + qCritical() << __LINE__ << "compute_next_timestep() currentTimeInMinutes:" << currentTimeMinutes; // consider time shift: the step-list might have been computed at a // slightly different time point + + int currentStepIndex = stepList.indexOf(currentTimeMinutes); + if (currentStepIndex == -1) { + unsigned minimalDistance = ~0; + int j = -1; + for (int i = 0; i < stepList.size(); ++i) { + unsigned distance = std::abs(stepList[i] - currentTimeMinutes); + if (distance < minimalDistance) { + minimalDistance = distance; + j = i; + } + } + // max. tolerance set to 3 minutes + unsigned const tolerance = std::min(minimalDistance, (unsigned)(3)); + if (j != -1) { + stepList[j] = currentTimeMinutes; + } + } + +#if 0 int maxStep = -1; if (size >= 2) { maxStep = stepList[1] - stepList[0]; } - int tolerance = (maxStep == -1) ? 5 : std::min(maxStep, 5); + // max. tolerance set to 5 minutes + int const tolerance = (maxStep == -1) ? 5 : std::min(maxStep, 5); for (int i=0; i < stepList.size(); ++i) { if (std::abs(stepList[i] - currentTimeMinutes) <= tolerance) { qCritical().noquote() - << QString(" compute_next_timestep() correction stepList[%1]=%2 -> %3:") + << __LINE__ << QString("compute_next_timestep() correction stepList[%1]=%2 -> %3:") .arg(i).arg(stepList[0]).arg(currentTimeMinutes); stepList[i] = currentTimeMinutes; - qCritical() << " compute_next_timestep() NEW timeSteps:" << stepList; + qCritical() << __LINE__ << "compute_next_timestep() NEW timeSteps:" << stepList; } } int currentStepIndex = stepList.indexOf(currentTimeMinutes); +#endif + + currentStepIndex = stepList.indexOf(currentTimeMinutes); + qCritical() << __LINE__ << "compute_next_timestep() currentStepIndex (" << currentStepIndex << ")"; if (currentStepIndex == -1) { - qCritical() << "compute_next_timestep() *NO STEP* for currentTimeMinutes (" << currentTimeMinutes << ")"; + qCritical() << __LINE__ << "compute_next_timestep() *NO STEP* for currentTimeMinutes (" << currentTimeMinutes << ")"; return currentTimeMinutes; } if (UpDown == 1) { // UP if (stepList[currentStepIndex] == stepList.last()) { - qCritical() << "compute_next_timestep() *NO NEXT STEP* for currentTimeMinutes (" << currentTimeMinutes << ")"; + qCritical() << __LINE__ << "compute_next_timestep() *NO NEXT STEP* for currentTimeMinutes (" << currentTimeMinutes << ")"; return currentTimeMinutes; } else { - qCritical() << " compute_next_timestep() return next time step:" << stepList[currentStepIndex + 1]; - return stepList[currentStepIndex + 1]; + int const rest = currentStepIndex % pop_plus_steps; + + if (rest) { + currentStepIndex -= rest; + } + + qCritical() << __LINE__ << "compute_next_timestep() currentStepIndex (" << currentStepIndex << ")"; + + int const nextStepIndex = currentStepIndex + pop_plus_steps; + + qCritical() << __LINE__ << "compute_next_timestep() next step index:" << nextStepIndex; + if (nextStepIndex >= 0 && nextStepIndex < stepList.size()) { + qCritical() << __LINE__ << "compute_next_timestep() return next time step:" << stepList[nextStepIndex]; + return stepList[nextStepIndex]; + } } } if (UpDown == 0) { // DOWN if (stepList[currentStepIndex] == stepList.first()) { - qCritical() << "compute_next_timestep() *NO PREVIOUS STEP* for currentTimeMinutes (" << currentTimeMinutes << ")"; + qCritical() << __LINE__ << "compute_next_timestep() *NO PREVIOUS STEP* for currentTimeMinutes (" << currentTimeMinutes << ")"; return currentTimeMinutes; } else { - qCritical() << " compute_next_timestep() return next time step:" << stepList[currentStepIndex - 1]; - return stepList[currentStepIndex - 1]; + int const nextStepIndex = currentStepIndex - pop_minus_steps; + qCritical() << __LINE__ << "compute_next_timestep() next step index:" << nextStepIndex; + if (nextStepIndex >= 0 && nextStepIndex < stepList.size()) { + qCritical() << __LINE__ << "compute_next_timestep() return next time step:" << stepList[nextStepIndex]; + return stepList[nextStepIndex]; + } } } } else From 9cb7d4aea6eeb21e1e79aff5a79184f337270c59 Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Thu, 1 Aug 2024 16:04:57 +0200 Subject: [PATCH 5/8] compute_price_for_parking_ticket(): Added handling for prepaid and carry-over. --- library/src/calculate_price.cpp | 90 ++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 40 deletions(-) diff --git a/library/src/calculate_price.cpp b/library/src/calculate_price.cpp index 7d76560..6aca26e 100644 --- a/library/src/calculate_price.cpp +++ b/library/src/calculate_price.cpp @@ -708,7 +708,7 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( parking_tariff_t *tariff, - QDateTime &start_parking_time, + QDateTime &start_parking_time_, int netto_parking_time, QDateTime &end_parking_time, struct price_t *price, @@ -717,6 +717,8 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( { CalcState calcState; + QDateTime start_parking_time(start_parking_time_); + int paymentOptionIndex = tariff->getPaymentOptionIndex(permitType); double minMin = tariff->getPaymentOptions(paymentOptionIndex).pop_min_time; @@ -730,9 +732,9 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( << " start + netto: " << start_parking_time.addSecs(netto_parking_time * 60) << endl << " minMin: " << minMin << endl << " maxMin: " << maxMin + << " prepaid: " << prepaid << " permitType: " << permitType.toString(); - if (netto_parking_time < 0) { calcState.setDesc(QString("end=%1, start=%2") .arg(end_parking_time.toString(Qt::ISODate), @@ -753,59 +755,65 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( double cost = -1; if (start_parking_time.isValid()) { - - // qCritical() << __func__ << __LINE__; - if (tariff->getPaymentOptions(paymentOptionIndex).pop_payment_method_id == PaymentMethod::Steps || tariff->getPaymentOptions(paymentOptionIndex).pop_payment_method_id == PaymentMethod::Degressive) { - // qCritical() << __func__ << __LINE__; // hier muesste man unterscheiden: uebertrag oder nicht? calcState = Calculator::GetInstance().isParkingAllowed(tariff, start_parking_time, netto_parking_time, paymentOptionIndex); if (calcState.getStatus() == CalcState::State::OUTSIDE_ALLOWED_PARKING_TIME) { - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << calcState.toString(); - // qCritical() << __func__ << __LINE__; + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << calcState.toString(); return calcState; } - // qCritical() << __func__ << __LINE__; - QList lll = Calculator::GetInstance().GetTimeSteps(tariff); + QList tlist = Calculator::GetInstance().GetTimeSteps(tariff); + Q_UNUSED(tlist); - // netto_parking_time = compute_next_timestep(tariff, netto_parking_time, 1, permitType); - - qCritical() << "LINE" << __LINE__ << "netto" << netto_parking_time << lll; - - // qCritical() << __func__ << __LINE__; cost = Calculator::GetInstance().GetCostFromDuration(tariff, start_parking_time, netto_parking_time, paymentOptionIndex); int weekDay = start_parking_time.date().dayOfWeek(); - int const pop_carry_over_option_id = tariff->getPaymentOptions(paymentOptionIndex).pop_carry_over_option_id; + int pop_carry_over_option_id = tariff->getPaymentOptions(paymentOptionIndex).pop_carry_over_option_id; + + std::optional yperiod = Utilities::GetYearPeriodActive(tariff, start_parking_time); + if (yperiod.has_value()) { + ATBPeriodYear const &period = yperiod.value(); + pop_carry_over_option_id = period.pye_id; + } + qCritical() << __func__ << __LINE__ << "carryOver-id" << pop_carry_over_option_id; + QTime const carryOverStart = tariff->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; int const carryOverDuration = tariff->TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].duration; - qCritical() << "LINE" << __LINE__ << "carryStart" << carryOverStart.toString(Qt::ISODate); - qCritical() << "LINE" << __LINE__ << "carryDur" << carryOverDuration; - qCritical() << "LINE" << __LINE__ << "start" << start_parking_time.toString(Qt::ISODate); + qCritical() << __func__ << __LINE__ << "carryOverStart" << carryOverStart.toString(Qt::ISODate); + qCritical() << __func__ << __LINE__ << "carryOverDuration" << carryOverDuration; - if (start_parking_time.time() > carryOverStart) { - //int const backTime = carryOverStart.secsTo(start_parking_time.time()) / 60; - //qCritical() << "LINE" << __LINE__ << "backTime" << backTime; - //qCritical() << "LINE" << __LINE__ << "backTime + dur" << backTime + carryOverDuration; - start_parking_time.setTime(carryOverStart); - start_parking_time = start_parking_time.addSecs(carryOverDuration * 60); + // handle prepaid option + QDateTime effectiveStartTime(start_parking_time); + int const prepaid_option_id = tariff->getPaymentOptions(paymentOptionIndex).pop_prepaid_option_id; + std::optional prepaidOption = tariff->getPrepaidType(prepaid_option_id); + if (prepaidOption.has_value()) { + ATBPrepaid const &p = prepaidOption.value(); + if (start_parking_time.time() < p.static_end) { // static_end: e.g. 08:00:00 + effectiveStartTime.setTime(p.static_end); + } else + if (start_parking_time.time() > p.static_start) { // static_start: e.g. 22:00:00 + effectiveStartTime.setTime(p.static_start); + } } - end_parking_time = start_parking_time.addSecs(netto_parking_time*60); - - qCritical() << "LINE" << __LINE__ << "netto" << netto_parking_time; - qCritical() << "LINE" << __LINE__ << "start" << start_parking_time.toString(Qt::ISODate); - qCritical() << "(" << __func__ << ":" << __LINE__ << ")" - << "end_parking_time" << end_parking_time.toString(Qt::ISODate); + // handle carry over + int minutesUntilCarryOver = effectiveStartTime.time().secsTo(carryOverStart) / 60; + if (netto_parking_time > minutesUntilCarryOver) { + int const rest = netto_parking_time - minutesUntilCarryOver; + QDateTime s(effectiveStartTime); + s = s.addSecs(minutesUntilCarryOver * 60); + s = s.addSecs(carryOverDuration * 60); + end_parking_time = s.addSecs(rest * 60); + } else { + end_parking_time = effectiveStartTime.addSecs(netto_parking_time*60); + } } else { - // qCritical() << __func__ << __LINE__; cost = Calculator::GetInstance().GetCostFromDuration( tariff, tariff->getPaymentOptions().pop_payment_method_id, @@ -822,8 +830,8 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( } // DEBUG - qCritical() << __LINE__ << " end_parking_time: " << end_parking_time; - qCritical() << __LINE__ << " -> calculated cost (netto): " << cost; + //qCritical() << __LINE__ << " end_parking_time: " << end_parking_time; + //qCritical() << __LINE__ << " -> calculated cost (netto): " << cost; price->brutto = price->vat = price->vat_percentage = 0; price->units = cost; @@ -899,10 +907,12 @@ CalcState CALCULATE_LIBRARY_API compute_duration_for_parking_ticket( bool const nextDay = false; // DEBUG - qCritical() << "compute_duration_for_parking_ticket(2): "; - qCritical() << " payment option index: " << paymentOptionIndex; - qCritical() << " prepaid: " << prepaid; - qCritical() << " price: " << price; + if (DBG_LEVEL >= DBG_DEBUG) { + qCritical() << "compute_duration_for_parking_ticket(2): "; + qCritical() << " payment option index: " << paymentOptionIndex; + qCritical() << " prepaid: " << prepaid; + qCritical() << " price: " << price; + } if (start_parking_time.isValid()) { QString cs = start_parking_time.toString(Qt::ISODate); From 138221759b50f443307e8a9132a306438576ab24 Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Thu, 1 Aug 2024 16:43:19 +0200 Subject: [PATCH 6/8] GetDurationFromCost(): Minor: removed some debug ouput --- library/src/calculator_functions.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/library/src/calculator_functions.cpp b/library/src/calculator_functions.cpp index 6444af0..59474fa 100644 --- a/library/src/calculator_functions.cpp +++ b/library/src/calculator_functions.cpp @@ -135,14 +135,20 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg, static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg); int const paymentOptionIndex = cfg->getPaymentOptionIndex(permitType.get()); - qCritical() << DBG_HEADER << " start:" << inputDate.toString(Qt::ISODate); - qCritical() << DBG_HEADER << " option index:" << paymentOptionIndex; - qCritical() << DBG_HEADER << "paymentMethodId:" << static_cast(paymentMethodId); - qCritical() << DBG_HEADER << " prepaid:" << prepaid; - qCritical() << DBG_HEADER << " cost (price):" << cost; + if (DBG_LEVEL >= DBG_DEBUG) { + qCritical() << DBG_HEADER << " start:" << inputDate.toString(Qt::ISODate); + qCritical() << DBG_HEADER << " option index:" << paymentOptionIndex; + qCritical() << DBG_HEADER << "paymentMethodId:" << static_cast(paymentMethodId); + qCritical() << DBG_HEADER << " prepaid:" << prepaid; + qCritical() << DBG_HEADER << " cost (price):" << cost; + } QList tsteps = Calculator::GetInstance().GetTimeSteps(cfg, paymentOptionIndex, inputDate); - qCritical() << DBG_HEADER << " time steps:" << tsteps; + if (DBG_LEVEL >= DBG_DEBUG) { + qCritical() << DBG_HEADER << " time steps:" << tsteps; + } else { + Q_UNUSED(tsteps); + } if (paymentMethodId == PaymentMethod::Degressive) { @@ -287,6 +293,9 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg, QTime pwd_time_from = QTime::fromString(QString::fromStdString(iter->second.pwd_time_from), Qt::ISODate); QTime pwd_time_to = QTime::fromString(QString::fromStdString(iter->second.pwd_time_to), Qt::ISODate); + //qCritical() << DBG_HEADER << "from" << pwd_time_from.toString(Qt::ISODate); + //qCritical() << DBG_HEADER << " to" << pwd_time_to.toString(Qt::ISODate); + if (inputDate.time() < pwd_time_from) { inputDate.setTime(pwd_time_from); useWeekDaysWorkTimeOfOtherDay = false; @@ -465,6 +474,7 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg, QTime pwd_time_from = QTime::fromString(QString::fromStdString(iter->second.pwd_time_from), Qt::ISODate); if (next_working_time_from < pwd_time_from) { next_working_time_from = pwd_time_from; + qCritical() << DBG_HEADER << "next working time from" << next_working_time_from.toString(Qt::ISODate); break; } } From 4bce854d77d452d83adc99058c5c68c375ef5f9b Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Thu, 1 Aug 2024 16:44:06 +0200 Subject: [PATCH 7/8] GetDurationFromCost(): Set durationInSecs in case 'pop_accumulate_prices' is not configured in tariff file. --- library/src/calculator_functions.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/src/calculator_functions.cpp b/library/src/calculator_functions.cpp index 59474fa..36085d9 100644 --- a/library/src/calculator_functions.cpp +++ b/library/src/calculator_functions.cpp @@ -427,6 +427,10 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg, //qCritical() << DBG_HEADER << "XXXXXXXXXXXXXXXXXXXXX" << d; return d.toString(Qt::ISODate).toStdString(); } + } else { + durationInSecs = cfg->Duration.find(durationId)->second.pun_duration * 60; + //qCritical() << DBG_HEADER << "DURATION-SECS" << durationInSecs; + //qCritical() << DBG_HEADER << "DURATION-MINS" << durationInSecs / 60; } if ((double)price == cost) { From 24d9d4a0ff25408dcd16ce88abb73f22bb79a22c Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Thu, 1 Aug 2024 16:46:09 +0200 Subject: [PATCH 8/8] test case for kleipeda and fuchs --- main/main.cpp | 155 ++++++++++++++------------------------------------ 1 file changed, 43 insertions(+), 112 deletions(-) diff --git a/main/main.cpp b/main/main.cpp index 387c983..b557d6d 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -47,11 +47,11 @@ extern "C" char* strptime(const char* s, #define NEUHAUSER_CHRISTOPH_REISEN (0) #define NEUHAUSER_PERNEGG_AN_DER_MUR (0) #define NEUHAUSER_STOCKERAU (0) -#define KLEIPEDA_LITAUEN (0) +#define KLEIPEDA_LITAUEN (1) #define SEXTEN (0) #define SCHNALS_LEITER_KIRCHL (0) #define SCHNALS_STAUMAUER (SCHNALS_LEITER_KIRCHL) -#define VALSER_ALM (1) +#define VALSER_ALM (0) #if NEUHAUSER_KIRCHDORF==1 static bool test_neuhauser_kirchdorf(int step, double cost) { @@ -354,7 +354,7 @@ int main() { QList timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg); qCritical() << "TimeSteps" << timeSteps; - return 0; + // return 0; CalcState cs; double cost; @@ -363,7 +363,7 @@ int main() { // for (int day = Qt::Monday; day <= Qt::Sunday; ++day) { for (int day = Qt::Monday; day <= Qt::Monday; ++day) { - QDateTime s(QDate(2024, 5, 19 + day), QTime()); // 20: (whit) monday,..., 26: sunday + QDateTime s(QDate(2024, 7, 29 + day), QTime()); // 20: (whit) monday,..., 26: sunday QDateTime end; switch (day) { @@ -401,9 +401,11 @@ int main() { bool prepaid = true); */ - for (int minutes = 0; minutes < 1440; ++minutes) { - QDateTime start = s.addSecs(minutes * 60); - QDateTime effectiveStart = start; + //for (int minutes = 0; minutes < 1440; ++minutes) { + for (int minutes = 540; minutes <= 540; ++minutes) { + // QDateTime start = s.addSecs(minutes * 60); + QDateTime start(QDateTime::currentDateTime()); + QDateTime effectiveStart(QDateTime::currentDateTime()); if (start.time() < QTime(8, 0, 0)) { effectiveStart.setTime(QTime(8, 0, 0)); @@ -415,55 +417,18 @@ int main() { effectiveStart.setTime(QTime(8, 0, 0)); // next day } - for (int i = 0; i <= 2100; i += 10) { + for (int i = 30; i <= 30; i += 10) { //for (int i = 2100; i <= 2100; i += 10) { cost = i; - if ((cs = compute_duration_for_parking_ticket(&cfg, start, cost, end))) { // return value - durationInMinutes = pop_min_time; - if (i > 0) { - durationInMinutes += (i/10) * 4; - } - offsetInMinutes = 0; - - if (effectiveStart.time() >= QTime(8, 0, 0) && effectiveStart.time() <= QTime(22, 0, 0)) { - if (effectiveStart.time().secsTo(QTime(22, 0, 0)) < (durationInMinutes * 60)) { - offsetInMinutes = 600; // 22:00 -> 8:00 - } - } - - if (i == 0) { - i += 20; - } - - if ((durationInMinutes + offsetInMinutes) == (effectiveStart.secsTo(end) / 60)) { - - if (day == Qt::Monday && minutes >= 480 && minutes <= 1320) { - qCritical() << "| start ............................" << start.toString(Qt::ISODate); - qCritical() << "| cost ............................." << cost; - qCritical() << "| durationInMinutes ................" << durationInMinutes - << "(" << (durationInMinutes - 60) << "+ 60 )"; - qCritical() << "| offsetInMinutes .................." << offsetInMinutes; - qCritical() << "| end .............................." << end.toString(Qt::ISODate) << endl; - } - - continue; - } + if ((cs = compute_duration_for_parking_ticket(&cfg, start, cost, end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)))) { // return value + qCritical() << "start" << start.toString(Qt::ISODate) << "< cost" << cost + << "> end" << end.toString(Qt::ISODate); } if (!cs) { qCritical() << "ERROR CalcState" << cs.toString() << endl; - } else { - qCritical() << cs.toString(); } - qCritical() << __LINE__ << "start ............................" << start.toString(Qt::ISODate); - qCritical() << __LINE__ << "effectiveStart ..................." << effectiveStart.toString(Qt::ISODate); - qCritical() << __LINE__ << "cost ............................." << cost; - qCritical() << __LINE__ << "durationInMinutes ................" << durationInMinutes; - qCritical() << __LINE__ << "offsetInMinutes .................." << offsetInMinutes; - qCritical() << __LINE__ << "effectiveStart.secsTo(end) / 60 .." << effectiveStart.secsTo(end) / 60; - qCritical() << __LINE__ << "end .............................." << end.toString(Qt::ISODate) << endl; - exit(-1); } } } @@ -552,7 +517,7 @@ int main() { */ //for (int minutes = 0; minutes < 1440; ++minutes) { - for (int minutes = 0; minutes < 1440; minutes += 1) { + for (int minutes = 480; minutes <= 480; minutes += 1) { QDateTime start = s.addSecs(minutes * 60); // qCritical() << "start" << start.toString(Qt::ISODate); @@ -569,66 +534,32 @@ int main() { effectiveStart.setTime(QTime(8, 0, 0)); // next day } +/* for (int i = 10; i <= 400; i += 10) { - //for (int i = 2100; i <= 2100; i += 10) { cost = i; - if ((cs = compute_duration_for_parking_ticket(&cfg, start, cost, end))) { // return value - - + if ((cs = compute_duration_for_parking_ticket(&cfg, start, cost, end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)))) { // return value qCritical() << "start" << start.toString(Qt::ISODate) << "< cost" << cost << "> end" << end.toString(Qt::ISODate); - - durationInMinutes = pop_min_time; - if (i > 0) { - durationInMinutes += (i/10) * 4; - } - offsetInMinutes = 0; - - if (effectiveStart.time() >= QTime(8, 0, 0) && effectiveStart.time() <= QTime(19, 0, 0)) { - if (effectiveStart.time().secsTo(QTime(19, 0, 0)) < (durationInMinutes * 60)) { - offsetInMinutes = 780; // 19:00 -> 8:00 - } - } - - if (i == 0) { - i += 20; - } - -#if 0 - if ((durationInMinutes + offsetInMinutes) == (effectiveStart.secsTo(end) / 60)) { - - if (day == Qt::Monday && minutes >= 480 && minutes <= 1140) { - qCritical() << "| start ............................" << start.toString(Qt::ISODate); - qCritical() << "| cost ............................." << cost; - qCritical() << "| durationInMinutes ................" << durationInMinutes - << "(" << (durationInMinutes - 60) << "+ 60 )"; - qCritical() << "| offsetInMinutes .................." << offsetInMinutes; - qCritical() << "| end .............................." << end.toString(Qt::ISODate) << endl; - } - - continue; - } -#endif } if (!cs) { qCritical() << "ERROR CalcState" << cs.toString() << endl; - } else { -// qCritical() << cs.toString(); } + } +*/ + int netto_parking_time = 60; + struct price_t price; -#if 0 - qCritical() << __LINE__ << "start ............................" << start.toString(Qt::ISODate); - qCritical() << __LINE__ << "effectiveStart ..................." << effectiveStart.toString(Qt::ISODate); - qCritical() << __LINE__ << "cost ............................." << cost; - qCritical() << __LINE__ << "durationInMinutes ................" << durationInMinutes; - qCritical() << __LINE__ << "offsetInMinutes .................." << offsetInMinutes; - qCritical() << __LINE__ << "effectiveStart.secsTo(end) / 60 .." << effectiveStart.secsTo(end) / 60; - qCritical() << __LINE__ << "end .............................." << end.toString(Qt::ISODate) << endl; - exit(-1); -#endif + qCritical() << "start" << start.toString(Qt::ISODate); + QDateTime const s = start; + + if ((cs = compute_price_for_parking_ticket(&cfg, start, netto_parking_time, end, &price, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)))) { + qCritical() << "start" << s.toString(Qt::ISODate) + << "netto_parking_time" << netto_parking_time + << "< price" << price.netto + << "> end" << end.toString(Qt::ISODate); } } } @@ -737,7 +668,7 @@ int main() { effectiveStart.setTime(QTime(7, 0, 0)); // next day } -#if 1 +#if 0 PermitType permitType(PERMIT_TYPE::SHORT_TERM_PARKING); for (int i = 200; i <= 200; i += 10) { cost = i; @@ -760,7 +691,7 @@ int main() { //for (int i = 2100; i <= 2100; i += 10) { cost = i; - if ((cs = compute_duration_for_parking_ticket(&cfg, start, cost, end))) { // return value + if ((cs = compute_duration_for_parking_ticket(&cfg, start, cost, end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING_PKW)))) { // return value } if (!cs) { @@ -898,7 +829,7 @@ int main() { //qCritical() << calcState.toString(); calcState = compute_duration_for_parking_ticket(&cfg, s, - (double)9000, end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING_BUS)); + (double)50, end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING_BUS)); qCritical() << end.toString(Qt::ISODate); qCritical() << calcState.toString(); } @@ -988,7 +919,7 @@ int main() { s.setTime(QTime(12, 0, 0)); int minimal_parking_price = get_minimal_parkingprice(&cfg, - PermitType(PERMIT_TYPE::SHORT_TERM_PARKING_PKW), + PermitType(PERMIT_TYPE::SHORT_TERM_PARKING), paymentOptionIndex, s); qCritical() << "minimal parking price" << minimal_parking_price; @@ -996,14 +927,14 @@ int main() { for (int i = 0; i < 8; ++i) { calcState = compute_duration_for_parking_ticket(&cfg, s, (double)minimal_parking_price + i*800, - end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING_PKW)); + end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)); qCritical() << "RUN" << i << end.toString(Qt::ISODate) << calcState.toString(); } s.setTime(QTime(15, 0, 0)); minimal_parking_price = get_minimal_parkingprice(&cfg, - PermitType(PERMIT_TYPE::SHORT_TERM_PARKING_PKW), + PermitType(PERMIT_TYPE::SHORT_TERM_PARKING), paymentOptionIndex, s); qCritical() << "minimal parking price" << minimal_parking_price; @@ -1011,7 +942,7 @@ int main() { for (int i = 0; i < 8; ++i) { calcState = compute_duration_for_parking_ticket(&cfg, s, (double)minimal_parking_price + i*800, - end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING_PKW)); + end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)); qCritical() << "RUN" << i << end.toString(Qt::ISODate) << calcState.toString(); } } @@ -1532,7 +1463,7 @@ int main() { for (int i = 0, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) { QDateTime end = start.addSecs(timeSteps.at(i)*60); - cs = compute_price_for_parking_ticket(&cfg, start, timeSteps.at(i), end, &costs); + cs = compute_price_for_parking_ticket(&cfg, start, timeSteps.at(i), end, &costs, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)); if (cs.getStatus() != CalcState::State::SUCCESS) { if (start.time().hour() >= 8 && start.time().hour() < 18) { qCritical() << "ERROR CALC-STATE-1=" << QString(cs); @@ -1555,7 +1486,7 @@ int main() { } qCritical() << "compute_price_for_parking_ticket()/GetCostFromDuration() TIME: " - << timeSteps.at(i) << "PRICE=" << price1; + << timeSteps.at(i) << "PRICE=" << price1 << "end=" << end.toString(Qt::ISODate); //std::string duration = Calculator::GetInstance().GetDurationFromCost(&cfg, 4, @@ -1639,7 +1570,7 @@ int main() { double cost = 0; CalcState cs; - if ((cs = compute_price_for_parking_ticket(&cfg, start, *step, end, &price))) { + if ((cs = compute_price_for_parking_ticket(&cfg, start, *step, end, &price, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)))) { cost = price.netto; qCritical() << "step" << *step << ": cost" << cost; } else { @@ -1723,7 +1654,7 @@ int main() { double cost = 0; CalcState cs; - if ((cs = compute_price_for_parking_ticket(&cfg, start, *step, end, &price))) { + if ((cs = compute_price_for_parking_ticket(&cfg, start, *step, end, &price, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)))) { cost = price.netto; qCritical() << "step" << *step << ": cost" << cost; } else { @@ -1808,7 +1739,7 @@ int main() { double cost = 0; CalcState cs; - if ((cs = compute_price_for_parking_ticket(&cfg, start, *step, end, &price))) { + if ((cs = compute_price_for_parking_ticket(&cfg, start, *step, end, &price, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)))) { cost = price.netto; qCritical() << "step" << *step << ": cost" << cost; } else { @@ -1866,7 +1797,7 @@ int main() { double cost = 0; CalcState cs; - if ((cs = compute_price_for_parking_ticket(&cfg, start, *step, end, &price))) { + if ((cs = compute_price_for_parking_ticket(&cfg, start, *step, end, &price, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)))) { cost = price.netto; qCritical() << "step" << *step << ": cost" << cost; } else { @@ -1969,7 +1900,7 @@ int main() { CalcState cs; for (int i = 13, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) { QDateTime end = start.addSecs(timeSteps.at(i)*60); - cs = compute_price_for_parking_ticket(&cfg, start, timeSteps.at(i), end, &costs); + cs = compute_price_for_parking_ticket(&cfg, start, timeSteps.at(i), end, &costs, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)); qCritical() << endl; } @@ -1994,7 +1925,7 @@ int main() { for (int i = 0, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) { QDateTime end = start.addSecs(timeSteps.at(i)*60); - cs = compute_price_for_parking_ticket(&cfg, start, timeSteps.at(i), end, &costs); + cs = compute_price_for_parking_ticket(&cfg, start, timeSteps.at(i), end, &costs, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)); if (cs.getStatus() != CalcState::State::SUCCESS) { if (start.time().hour() >= 8 && start.time().hour() < 18) { qCritical() << "ERROR CALC-STATE-1=" << QString(cs);