diff --git a/library/src/calculator_functions.cpp b/library/src/calculator_functions.cpp index a0c31ff..b9bfe59 100644 --- a/library/src/calculator_functions.cpp +++ b/library/src/calculator_functions.cpp @@ -181,6 +181,13 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg, int durationMinutes = Utilities::getMaximalParkingTime(cfg, paymentMethodId); int durationMinutesBrutto = 0; +#ifdef _DEBUG_ +#undef _DEBUG_ +#endif + +//#define _DEBUG_ 1 +#define _DEBUG_ 0 + QDateTime current = start; int days = 7; @@ -229,139 +236,340 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg, 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(); + QVector weekDayWorkTimeRanges; + + using WTIterator = std::multimap::const_iterator; + std::pair p = cfg->WeekDaysWorktime.equal_range(weekdayId); + + for (WTIterator itr = p.first; itr != p.second; ++itr) { + weekDayWorkTimeRanges.append(itr->second); // working with vector is easier + } + + int weekDayWorkTimeIndex = 0; + bool moveToNextTimeRange = false; + + // time ranges for Neuhauser-Kirchdorf (743): 30, 5, 5, ... 5 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); + while (timeRangeIt != cfg->TimeRange.cend()) { // ; ++timeRangeIt) { - for (WTIterator itr = p.first; itr != p.second; ++itr) { - ++range; + if (weekDayWorkTimeIndex >= weekDayWorkTimeRanges.size()) { - QTime const &from = Utilities::WeekDaysWorkTimeFrom(itr); - QTime const &to = Utilities::WeekDaysWorkTimeUntil(itr); +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex + << "weekDayWorkTimeRanges.size()" << weekDayWorkTimeRanges.size() + << "price" << price; +#endif + end_datetime = current; + return end_datetime.toString(Qt::ISODate).toStdString(); + } - Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES"); + QTime const &from = QTime::fromString(weekDayWorkTimeRanges[weekDayWorkTimeIndex].pwd_time_from.c_str(), Qt::ISODate); + QTime const &to = QTime::fromString(weekDayWorkTimeRanges[weekDayWorkTimeIndex].pwd_time_to.c_str(), Qt::ISODate); - 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 _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "current" << current.toString(Qt::ISODate) + << "from" << from.toString(Qt::ISODate) + << "to" << to.toString(Qt::ISODate); +#endif - if (range == 1) { - start_datetime = current; - } - } - } + Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES"); - while (timeRangeIt != cfg->TimeRange.cend()) { - ATBTimeRange timeRange = timeRangeIt->second; + if (current.time() >= to) { + ++weekDayWorkTimeIndex; - timeRange.computeQTimes(current.time()); +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "try to use next available work-time with" + << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex + << "price" << price; +#endif + // time range is not affected + continue; + } 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; - int duration = timeRange.time_range_to_in_minutes_from_start - - timeRange.time_range_from_in_minutes_from_start; +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "lastCurrent" << lastCurrent.toString(Qt::ISODate) + << "current" << current.toString(Qt::ISODate) + << "minutesMoved" << minutesMoved + << "durationMinutesBrutto" << durationMinutesBrutto; +#endif - 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; + if (weekDayWorkTimeIndex == 0) { + start_datetime = current; } } } + 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 _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "current" << current.toString(Qt::ISODate) + << "duration" << duration + << "minsUsed" << minsUsed + << "minsToCarryOver" << minsToCarryOver + << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex + << "price" << price; +#endif + + if (minsToCarryOver > 0) { // the price for this time range + // has been is paid already + Q_ASSERT_X(weekDayWorkTimeIndex > 0, __func__, "WRONG-WORK-TIME"); + + current = current.addSecs(minsToCarryOver*60); + + durationMinutes -= minsToCarryOver; + durationMinutesNetto += minsToCarryOver; + durationMinutesBrutto += minsToCarryOver; + + minsToCarryOver = 0; + +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "current" << current.toString(Qt::ISODate) + << "duration" << duration + << "durationMinutes" << durationMinutes + << "durationMinutesNetto" << durationMinutesNetto + << "durationMinutesBrutto" << durationMinutesBrutto + << "price" << price; +#endif + if (price >= cost) { + end_datetime = current; + +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "end_datetime" << end_datetime.toString(Qt::ISODate) + << "price" << price; +#endif + return end_datetime.toString(Qt::ISODate).toStdString(); + } + } + + if (current.addSecs(duration * 60).time() <= to) { + +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "current" << current.toString(Qt::ISODate) + << "current.addSecs(" << duration * 60 << ")" << current.addSecs(duration*60).time().toString(Qt::ISODate) + << "duration" << duration + << "to" << to.toString(Qt::ISODate) + << "minsUsed" << minsUsed + << "minsToCarryOver" << minsToCarryOver + << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex + << "durationMinutes" << durationMinutes; +#endif + + moveToNextTimeRange = false; + 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; +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "end_datetime" << end_datetime.toString(Qt::ISODate) + << "price" << price; +#endif + return end_datetime.toString(Qt::ISODate).toStdString(); + } + + // price has been updated; use next time range + moveToNextTimeRange = true; + break; + } + } + +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "current" << current.toString(Qt::ISODate) + << "duration" << duration + << "to" << to.toString(Qt::ISODate) + << "price" << price + << "minsToCarryOver" << minsToCarryOver + << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex + << "durationMinutes" << durationMinutes + << "durationMinutesNetto" << durationMinutesNetto + << "durationMinutesBrutto" << durationMinutesBrutto; +#endif + + if (price >= cost) { + end_datetime = current; + +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "end_datetime" << end_datetime.toString(Qt::ISODate) + << "price" << price; +#endif + + return end_datetime.toString(Qt::ISODate).toStdString(); + } + + if (moveToNextTimeRange) { + if (++timeRangeIt != cfg->TimeRange.cend()) { + continue; + } + } + + // havin a new time range means that we always have a new + // work-time-range + // ++timeRangeIt; + + } else { // current.addSecs(duration * 60).time() > to + +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "current" << current.toString(Qt::ISODate) + << "current.addSecs(" << duration * 60 << ")" << current.addSecs(duration*60).time().toString(Qt::ISODate) + << "duration" << duration + << ", to:" << to.toString(Qt::ISODate); +#endif + + lastCurrent = current; + current.setTime(to); + minsUsed = lastCurrent.secsTo(current) / 60; + +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "lastCurrent" << lastCurrent.toString(Qt::ISODate) + << "current" << current.toString(Qt::ISODate) + << "duration" << duration + << "to" << to.toString(Qt::ISODate) + << "minsUsed" << minsUsed + << "minsToCarryOver" << minsToCarryOver + << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex + << "durationMinutes" << durationMinutes; +#endif + + // mod duration: possibly discard some minutes in + // the next time-range + if (duration >= minsUsed) { + minsToCarryOver = duration - minsUsed; + } + + durationMinutes -= minsUsed; + durationMinutesNetto += minsUsed; + durationMinutesBrutto += minsUsed; + +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "lastCurrent" << lastCurrent.toString(Qt::ISODate) + << "current" << current.toString(Qt::ISODate) + << "duration" << duration + << "to" << to.toString(Qt::ISODate) + << "minsUsed" << minsUsed + << "minsToCarryOver" << minsToCarryOver + << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex + << "durationMinutes" << durationMinutes + << "price" << price; +#endif + + moveToNextTimeRange = false; + + 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; + +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "end_datetime" << end_datetime.toString(Qt::ISODate) + << "price" << price; +#endif + + // return end_datetime.toString(Qt::ISODate).toStdString(); + } + + // price has been updated; use next time range + moveToNextTimeRange = true; + break; + } + } + } + +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "current" << current.toString(Qt::ISODate) + << "duration" << duration + << "minsUsed" << minsUsed + << "durationMinutes" << durationMinutes + << "moveToNextTimeRange" << moveToNextTimeRange + << "price" << price; +#endif + + if (moveToNextTimeRange) { + if (++timeRangeIt != cfg->TimeRange.cend()) { + continue; + } + + // no valid time range left + end_datetime = current; + +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "end_datetime" << end_datetime.toString(Qt::ISODate) + << "price" << price; +#endif + + return end_datetime.toString(Qt::ISODate).toStdString(); + } + } + end_datetime = start.addSecs(durationMinutesBrutto * 60); + +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "start" << start.toString(Qt::ISODate) + << "end_datetime" << end_datetime.toString(Qt::ISODate) + << "final price" << std::max(price, minParkingPrice); +#endif + return end_datetime.toString(Qt::ISODate).toStdString(); - } + } // while (timeRangeIt != cfg->TimeRange.cend()) { } +#if _DEBUG_==1 + qCritical() << "(" << __func__ << ":" << __LINE__ << ")" + << "INVALID END TIME"; +#endif end_datetime = QDateTime(); return end_datetime.toString(Qt::ISODate).toStdString(); } @@ -373,6 +581,7 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg, // TODO: im fehlerfall return t.getValidUntil().toString(Qt::ISODate).toStdString(); } +#undef _DEBUG_ /////////////////////////////////////// @@ -522,6 +731,9 @@ double Calculator::GetCostFromDuration(Configuration* cfg, int weekdayIdLast = -1; int durationMinutesBrutto = 0; +#ifdef _DEBUG_ +#undef _DEBUG_ +#endif //#define _DEBUG_ 1 #define _DEBUG_ 0 diff --git a/main/main.cpp b/main/main.cpp index 808ad62..65bec25 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -269,17 +269,20 @@ int main() { QList::const_iterator step; for (step = steps.cbegin(); step != steps.cend(); ++step) { qCritical() << QString("*** NEXT STEP: %1 ***").arg(*step); - for (int offset = 7*60; offset < 18*60; ++offset) { + //for (int offset = 691; offset < 692; ++offset) { + for (int offset = 480; offset < 1080; ++offset) { //for (int offset = 7*60; offset < (18*60)-90; ++offset) { //for (int offset = (18*60)-90; offset < 18*60; ++offset) { //for (int offset = 1046; offset < 1047; ++offset) { QDateTime start = s.addSecs(offset * 60); QDateTime const firstStart = start; - //if (*step != 35) continue; + if (*step != 30) continue; + + double cost = 0; if (compute_price_for_parking_ticket(&cfg, start, *step, end, &price)) { - double cost = price.netto; + cost = price.netto; qCritical() << "****" << offset << *step << "****"; qCritical() << " firstStart :" << firstStart.toString(Qt::ISODate); @@ -424,6 +427,12 @@ int main() { return -1; } + if (compute_duration_for_parking_ticket(&cfg, start, cost, end)) { // return value + qCritical() << "XXXX start" << start.toString(Qt::ISODate) + << "offset" << offset + << "cost" << cost + << "end" << end.toString(Qt::ISODate); + } } } }