From 49298a182166b91aac2042b8a26833c7c88fe35b Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Wed, 5 Jun 2024 17:00:27 +0200 Subject: [PATCH] Extend Calculator::GetDurationFromCost() (needed for Neuhauser/Stockerau/748). --- library/src/calculator_functions.cpp | 199 ++++++++++++++++++++++++++- 1 file changed, 198 insertions(+), 1 deletion(-) diff --git a/library/src/calculator_functions.cpp b/library/src/calculator_functions.cpp index 5173f32..0190a24 100644 --- a/library/src/calculator_functions.cpp +++ b/library/src/calculator_functions.cpp @@ -144,7 +144,204 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg, } } - qCritical() << __func__ << ":" << __LINE__ << "NOT YET IMPLEMENTED"; + // TODO: man braucht den richtigen Index + int paymentOptionIndex = 0; + int const pop_id = cfg->getPaymentOptions(paymentOptionIndex).pop_id; + int const pop_max_price = cfg->getPaymentOptions(paymentOptionIndex).pop_max_price; + int const pop_min_price = cfg->getPaymentOptions(paymentOptionIndex).pop_min_price; + + if (cost > pop_max_price) { + qCritical() << DBG_HEADER << "MAX-PARKING-PRICE" << pop_max_price << ", COST" << cost; + return CalcState::OVERPAID.toStdString(); + } + + if (cost < pop_min_price) { + qCritical() << DBG_HEADER << "MIN-PARKING-PRICE" << pop_min_price << ", COST" << cost; + return CalcState::BELOW_MIN_PARKING_PRICE.toStdString(); + } + + // int const pop_pre_paid = 1; + + if (prepaid) { + // no limits on pre-pay-option, i.e. pre-pay-ranges are exactly + // the complements of operational-ranges + + // find out if we are in a pre-pay-range. + // in this case, adapt inputDate accordingly. + + qCritical() << DBG_HEADER << "PRE-PAID-OPTION: ADAPT-INPUT-DATE" << inputDate.toString(Qt::ISODate); + + QTime currentTime = inputDate.time(); + int pwd_period_day_in_week_id = inputDate.date().dayOfWeek(); + + bool useWeekDaysWorkTimeOfOtherDay = true; + + for (auto[iter, rEnd] = cfg->WeekDaysWorktime.equal_range(pwd_period_day_in_week_id); iter != rEnd; ++iter) { + 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); + + if (inputDate.time() < pwd_time_from) { + inputDate.setTime(pwd_time_from); + useWeekDaysWorkTimeOfOtherDay = false; + break; + } + if (currentTime <= pwd_time_to) { + useWeekDaysWorkTimeOfOtherDay = false; + break; + } + } + + if (useWeekDaysWorkTimeOfOtherDay) {// for the current day, we are above + // the latest worktime-range -> find the next valid range + + QTime pwd_time_from_next_valid_range(0, 0, 0); + int pwd_period_next_day_in_week_id = pwd_period_day_in_week_id; + for (int days = 1; days < 8; ++days) { + pwd_period_next_day_in_week_id += 1; + if (pwd_period_next_day_in_week_id > (int)Qt::Sunday) { + pwd_period_next_day_in_week_id = Qt::Monday; + } + + if (cfg->WeekDaysWorktime.count(pwd_period_next_day_in_week_id) > 0) { + for (auto[iter, rEnd] = cfg->WeekDaysWorktime.equal_range(pwd_period_next_day_in_week_id); iter != rEnd; ++iter) { + QTime pwd_time_from = QTime::fromString(QString::fromStdString(iter->second.pwd_time_from), Qt::ISODate); + if (pwd_time_from_next_valid_range < pwd_time_from) { + pwd_time_from_next_valid_range = pwd_time_from; + break; + } + } + inputDate = inputDate.addDays(days); + inputDate.setTime(pwd_time_from_next_valid_range); + break; + } + } + } + } + + qCritical() << DBG_HEADER << "(ADAPTED) INPUT-DATE" << inputDate.toString(Qt::ISODate); + + // inputDate is now located in a valid operational-working-range + // find this working-time-range + int pwd_period_day_in_week_id = inputDate.date().dayOfWeek(); + if (cfg->WeekDaysWorktime.count(pwd_period_day_in_week_id) == 0) { + qCritical() << DBG_HEADER + << "ERROR" << inputDate.toString(Qt::ISODate) + << "NOT IN VALID WORKING TIME-RANGE"; + return ""; + } + + QTime current_working_time_from; + QTime current_working_time_to; + + for (auto[iter, rEnd] = cfg->WeekDaysWorktime.equal_range(pwd_period_day_in_week_id); iter != rEnd; ++iter) { + 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); + if (pwd_time_from <= inputDate.time() && inputDate.time() <= pwd_time_to) { + current_working_time_from = pwd_time_from; + current_working_time_to = pwd_time_to; + } + } + + if (current_working_time_from.isNull() || current_working_time_to.isNull()) { + // can never happen + qCritical() << DBG_HEADER + << "ERROR" << inputDate.toString(Qt::ISODate) + << "NOT IN VALID WORKING TIME-RANGE"; + return ""; + } + + qCritical() << DBG_HEADER << "CURRENT WORKING-TIME-FROM" << current_working_time_from.toString(Qt::ISODate); + qCritical() << DBG_HEADER << " CURRENT WORKING-TIME-TO" << current_working_time_to.toString(Qt::ISODate); + + for (auto[itr, rangeEnd] = cfg->PaymentRate.equal_range(pop_id); itr != rangeEnd; ++itr) { + int const pra_price = itr->second.pra_price; + if ((double)pra_price == cost) { + int const durationId = itr->second.pra_payment_unit_id; + auto search = cfg->Duration.find(durationId); + if (search != cfg->Duration.end()) { + // found now the duration in minutes + // check if we are still inside the working-time-range + ATBDuration duration = search->second; + + int durationInSecs = duration.pun_duration * 60; + + QDateTime current_working_date_time_to = inputDate; + current_working_date_time_to.setTime(current_working_time_to); + + qCritical() << DBG_HEADER << "DURATION IN MINUTES" << duration.pun_duration; + qCritical() << DBG_HEADER << "DURATION IN SECONDS" << duration.pun_duration * 60; + qCritical() << DBG_HEADER << "CURRENT-WORKING-DATE-TIME-TO" + << current_working_date_time_to.toString(Qt::ISODate); + qCritical() << DBG_HEADER << "NEW INPUT DATE" << inputDate.addSecs(durationInSecs).toString(Qt::ISODate); + + if (inputDate.addSecs(durationInSecs) > current_working_date_time_to) { + + qCritical() << DBG_HEADER; + + QTime next_working_time_from; + if (cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over != 0) { + qCritical() << DBG_HEADER << "CARRY-OVER SET"; + // check for next working-time-range on same day + int day_in_week_id = inputDate.date().dayOfWeek(); + for (auto[iter, rEnd] = cfg->WeekDaysWorktime.equal_range(day_in_week_id); iter != rEnd; ++iter) { + QTime pwd_time_from = QTime::fromString(QString::fromStdString(iter->second.pwd_time_from), Qt::ISODate); + if (pwd_time_from > current_working_time_to) { + next_working_time_from = pwd_time_from; + qCritical() << DBG_HEADER << "NEXT-WORKING-TIME-FROM" + << next_working_time_from.toString(Qt::ISODate); + break; + } + } + // check for next working-time-range on following day(s) + if (next_working_time_from.isNull()) { + next_working_time_from = QTime(0, 0, 0); + for (int days = 1; days < 8; ++days) { + day_in_week_id += 1; + if (day_in_week_id > (int)Qt::Sunday) { + day_in_week_id = Qt::Monday; + } + if (cfg->WeekDaysWorktime.count(day_in_week_id) > 0) { + for (auto[iter, rEnd] = cfg->WeekDaysWorktime.equal_range(day_in_week_id); iter != rEnd; ++iter) { + 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; + break; + } + } + + } + QDateTime upper = inputDate.addDays(days); + upper.setTime(next_working_time_from); + + QDateTime lower = inputDate; + lower.setTime(current_working_time_to); + + inputDate = inputDate.addSecs(lower.secsTo(upper) + durationInSecs); + qCritical() << DBG_HEADER << "TICKET-END" << inputDate.toString(Qt::ISODate); + } + } else { // next working-time is on same day + QDateTime upper = inputDate; + upper.setTime(next_working_time_from); + + QDateTime lower = inputDate; + lower.setTime(current_working_time_to); + + inputDate = inputDate.addSecs(lower.secsTo(upper) + durationInSecs); + qCritical() << DBG_HEADER << "TICKET-END" << inputDate.toString(Qt::ISODate); + } + } + } else { + inputDate = inputDate.addSecs(duration.pun_duration * 60); + qCritical() << DBG_HEADER << "INPUT-DATE" << inputDate.toString(Qt::ISODate); + } + + QString const &s = inputDate.toString(Qt::ISODate); + qCritical() << DBG_HEADER << "TICKET-END" << s; + return s.toStdString(); + } + } + } + return ""; } }