save current state

This commit is contained in:
Gerhard Hoffmann 2024-09-13 10:42:45 +02:00
parent f53e9ceaae
commit 7c0514e241
5 changed files with 159 additions and 72 deletions

View File

@ -3,6 +3,7 @@
#include <iostream>
#include <optional>
#include <utility>
#include "configuration.h"
#include "calculate_price.h"
@ -70,7 +71,8 @@ public:
/// <param name="start_datetime">Date/time of payment to be conducted in ISO8601 format (e.g. 2022-12-25T08:00:00Z)</param>
/// <param name="price"></param>
/// <returns>Returns duration in seconds (data type: double)</returns>
std::string GetDurationFromCost(Configuration* cfg, uint8_t vehicle_type, char const* start_datetime, double price,
std::pair<std::string, QDateTime>
GetDurationFromCost(Configuration* cfg, uint8_t vehicle_type, char const* start_datetime, double price,
PermitType permitType, bool nextDay = false, bool prepaid = false);
/// <summary>

View File

@ -8,5 +8,9 @@ public:
int pedwt_period_exc_day_id;
std::string pedwt_time_from;
std::string pedwt_time_to;
double pedwt_price;
};
double pedwt_price;
int pedwt_paid; // 00: not paid (i.e. free)
// 01: not paid in winter term, piad in summer term
// 10: paid in winter term, not paid in summer term
// 11: paid in winter and in summer term
};

View File

@ -808,22 +808,48 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
int pop_prepaid_option_id = tariff->getPaymentOptions(paymentOptionIndex).pop_prepaid_option_id;
std::optional<ATBPeriodYear> yperiod = Utilities::GetYearPeriodActive(tariff, start_parking_time);
int period_id = -1;
if (yperiod.has_value()) {
ATBPeriodYear const &period = yperiod.value();
period_id = period.pye_id;
pop_carry_over_option_id = period.pye_id;
pop_prepaid_option_id = period.pye_id;
qCritical() << __func__ << ":" << __LINE__ << "re-computed carry-over-id" << pop_carry_over_option_id;
qCritical() << __func__ << ":" << __LINE__ << " re-computed prepaid-id" << pop_prepaid_option_id;
}
QTime carryOverStart = tariff->TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].static_start;
int carryOverDuration = tariff->TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].duration;
QDateTime effectiveStartTime(start_parking_time);
qCritical() << __func__ << ":" << __LINE__ << " carryOverStart" << carryOverStart.toString(Qt::ISODate);
qCritical() << __func__ << ":" << __LINE__ << "carryOverDuration" << carryOverDuration;
// handle special days
int const specialDayId = tariff->specialDayId(start_parking_time);
if (specialDayId > 0) { // found special day
for (auto[itr, rangeEnd] = tariff->SpecialDaysWorktime.equal_range(specialDayId); itr != rangeEnd; ++itr) {
ATBSpecialDaysWorktime const &wt = itr->second;
switch(period_id) {
case 1: // summer term
if ((wt.pedwt_paid & 1) == 0) {
// does not have to be paid, move to next midnight
// better: start of next day (falls kein vorkauf besteht)
effectiveStartTime = effectiveStartTime.addDays(1);
effectiveStartTime.setTime(QTime(0, 0, 0));
}
break;
case 2: // winter term
if ((wt.pedwt_paid & 2) == 0) {
// does not have to be paid, move to next midnight
// better: start of next day (falls kein vorkauf besteht)
effectiveStartTime = effectiveStartTime.addDays(1);
effectiveStartTime.setTime(QTime(0, 0, 0));
}
break;
default:;
}
}
}
// handle prepaid option
QDateTime effectiveStartTime(start_parking_time);
int const prepaid_option_id = tariff->getPaymentOptions(paymentOptionIndex).pop_prepaid_option_id;
std::optional<ATBPrepaid> prepaidOption = tariff->getPrepaidType(prepaid_option_id);
if (prepaidOption.has_value()) {
@ -846,37 +872,52 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
qCritical() << __func__ << ":" << __LINE__ << "effectiveStartTime:" << effectiveStartTime.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);
}
int const carryOver = tariff->getPaymentOptions(paymentOptionIndex).pop_carry_over;
qCritical() << __func__ << ":" << __LINE__ << "end-parking-time:" << end_parking_time.toString(Qt::ISODate);
qCritical() << __func__ << ":" << __LINE__ << " carryOver flag" << carryOver;
weekDay = end_parking_time.date().dayOfWeek();
if (carryOver == 1) {
QTime carryOverStart = tariff->TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].static_start;
int carryOverDuration = tariff->TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].duration;
// musste man in einer schleife machen
carryOverStart = tariff->TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].static_start;
carryOverDuration = tariff->TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].duration;
if (end_parking_time.time() > carryOverStart) {
end_parking_time = end_parking_time.addSecs(carryOverDuration * 60);
} else
if (end_parking_time.time() == carryOverStart) {
qCritical() << __func__ << ":" << __LINE__ << "end-parking-time:" << end_parking_time.toString(Qt::ISODate);
qCritical() << __func__ << ":" << __LINE__ << " carryOverStart" << carryOverStart.toString(Qt::ISODate);
ATBPaymentOption const &po = tariff->getPaymentOptions(paymentOptionIndex);
if (po.pop_apply_carry_over_to_ticket_endtime) {
end_parking_time = end_parking_time.addSecs(carryOverDuration * 60);
qCritical() << __func__ << ":" << __LINE__ << "end-parking-time:" << end_parking_time.toString(Qt::ISODate);
qCritical() << __func__ << ":" << __LINE__ << "carryOverDuration" << carryOverDuration;
// 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);
}
qCritical() << __func__ << ":" << __LINE__ << "end-parking-time:" << end_parking_time.toString(Qt::ISODate);
weekDay = end_parking_time.date().dayOfWeek();
// musste man in einer schleife machen
carryOverStart = tariff->TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].static_start;
carryOverDuration = tariff->TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].duration;
if (end_parking_time.time() > carryOverStart) {
end_parking_time = end_parking_time.addSecs(carryOverDuration * 60);
} else
if (end_parking_time.time() == carryOverStart) {
qCritical() << __func__ << ":" << __LINE__ << "end-parking-time:" << end_parking_time.toString(Qt::ISODate);
qCritical() << __func__ << ":" << __LINE__ << " carryOverStart" << carryOverStart.toString(Qt::ISODate);
ATBPaymentOption const &po = tariff->getPaymentOptions(paymentOptionIndex);
if (po.pop_apply_carry_over_to_ticket_endtime) {
end_parking_time = end_parking_time.addSecs(carryOverDuration * 60);
qCritical() << __func__ << ":" << __LINE__ << "end-parking-time:" << end_parking_time.toString(Qt::ISODate);
}
}
} else {
qCritical() << __func__ << ":" << __LINE__ << "NO carryOver configured";
end_parking_time = effectiveStartTime.addSecs(netto_parking_time*60);
}
end_parking_time.setTime(QTime(end_parking_time.time().hour(),
@ -970,10 +1011,14 @@ CalcState CALCULATE_LIBRARY_API compute_duration_for_parking_ticket(
qCritical() << " start (cs): " << cs;
qCritical() << " price: " << price;
duration = Calculator::GetInstance().GetDurationFromCost(tariff,
tariff->getPaymentOptions(paymentOptionIndex).pop_payment_method_id,
cs.toLocal8Bit().constData(),
price, permitType, nextDay, prepaid).c_str();
std::pair<std::string, QDateTime> p_duration
= Calculator::GetInstance().GetDurationFromCost(tariff,
tariff->getPaymentOptions(paymentOptionIndex).pop_payment_method_id,
cs.toLocal8Bit().constData(),
price, permitType, nextDay, prepaid);
duration = p_duration.first.c_str();
QDateTime d = QDateTime::fromString(duration, Qt::ISODate);
if (!d.isValid()) {
calcState.setDesc(QString("ticketEndTime=%1").arg(duration));
@ -1044,11 +1089,16 @@ CalcState CALCULATE_LIBRARY_API compute_duration_for_parking_ticket(
}
QString cs = start_parking_time.toString(Qt::ISODate);
QString endTime = Calculator::GetInstance().GetDurationFromCost(
std::pair<std::string, QDateTime> p_endTime
= Calculator::GetInstance().GetDurationFromCost(
tariff,
tariff->getPaymentOptions().pop_payment_method_id,
cs.toLocal8Bit().constData(),
price, permitType, nextDay, prepaid).c_str();
price, permitType, nextDay, prepaid);
QString endTime = p_endTime.first.c_str();
ticketEndTime = p_endTime.second;
if (endTime == CalcState::SUCCESS) {
calcState.setDesc(QString("SUCCESS"));

View File

@ -118,13 +118,14 @@ QDateTime Calculator::GetDailyTicketDuration(Configuration* cfg, const QDateTime
return QDateTime();
}
/// <inheritdoc/>
std::string Calculator::GetDurationFromCost(Configuration* cfg,
uint8_t payment_option,
char const *startDatetimePassed, // given in local time
double cost,
PermitType /*permitType*/,
bool nextDay,
bool prepaid)
std::pair<std::string, QDateTime>
Calculator::GetDurationFromCost(Configuration* cfg,
uint8_t payment_option,
char const *startDatetimePassed, // given in local time
double cost,
PermitType /*permitType*/,
bool nextDay,
bool prepaid)
{
Q_UNUSED(payment_option);
Q_UNUSED(nextDay);
@ -134,6 +135,8 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
inputDate.setTime(QTime(inputDate.time().hour(), inputDate.time().minute(), 0));
static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg);
bool overPaid = false;
int paymentOptionIndex = getPaymentOptionIndex(*cfg, inputDate);
if (paymentOptionIndex == -1) {
paymentOptionIndex = cfg->getPaymentOptionIndex(QDateTime::fromString(startDatetimePassed, Qt::ISODate));
@ -162,7 +165,7 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
// minimal price is set by GetTimeSteps()
qCritical() << DBG_HEADER << " provided price (cost):" << cost;
qCritical() << DBG_HEADER << "configured minimal price:" << cfg->getPaymentOptions(paymentOptionIndex).pop_min_price;
return CalcState::BELOW_MIN_PARKING_PRICE.toStdString();
return std::make_pair(CalcState::BELOW_MIN_PARKING_PRICE.toStdString(), QDateTime());
}
if (prepaid == false) {
@ -225,9 +228,9 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
qCritical() << DBG_HEADER << " minimal parking time (minutes):" << cfg->getPaymentOptions(paymentOptionIndex).pop_min_time;
if (duration_previous < cfg->getPaymentOptions(paymentOptionIndex).pop_min_time) {
return CalcState::BELOW_MIN_PARKING_TIME.toStdString(); // minimal parking time is set by GetTimeSteps()
return std::make_pair(CalcState::BELOW_MIN_PARKING_TIME.toStdString(), d); // minimal parking time is set by GetTimeSteps()
}
return d.toString(Qt::ISODate).toStdString();
return std::make_pair(d.toString(Qt::ISODate).toStdString(), d);
}
}
@ -240,7 +243,7 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
qCritical() << DBG_HEADER << " provided price (cost):" << cost;
qCritical() << DBG_HEADER << " duration for price:" << durationStr;
return durationStr.toStdString();
return std::make_pair(durationStr.toStdString(), d);
}
}
}
@ -254,14 +257,14 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
// use tariff with structure as for instance Schoenau, Koenigsee:
// without given YearPeriod, SpecialDays and SpecialDaysWorktime
inputDate = inputDate.addSecs(GetDurationForPrice(cfg, cost) * 60);
return inputDate.toString(Qt::ISODate).toStdString();
return std::make_pair(inputDate.toString(Qt::ISODate).toStdString(), inputDate);
} else {
if (Utilities::IsYearPeriodActive(cfg, inputDate)) {
if (!prepaid) {
CalcState cs = isParkingAllowed(cfg, inputDate);
if (cs) {
inputDate.setTime(cs.getAllowedTimeRange().getTimeUntil());
return inputDate.toString(Qt::ISODate).toStdString();
return std::make_pair(inputDate.toString(Qt::ISODate).toStdString(), inputDate);
}
}
@ -273,15 +276,16 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
if (cost > pop_max_price) {
qCritical() << DBG_HEADER << "MAX-PARKING-PRICE" << pop_max_price << ", COST" << cost;
if (pop_allow_overpay == false) {
return CalcState::OVERPAID.toStdString();
return std::make_pair(CalcState::OVERPAID.toStdString(), QDateTime());
}
cost = pop_max_price;
overPaid = true;
// 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();
return std::make_pair(CalcState::BELOW_MIN_PARKING_PRICE.toStdString(), QDateTime());
}
// int const pop_pre_paid = 1;
@ -366,7 +370,7 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
qCritical() << DBG_HEADER
<< "ERROR" << inputDate.toString(Qt::ISODate)
<< "NOT IN VALID WORKING TIME-RANGE";
return "";
return std::make_pair("", QDateTime());
}
//qCritical() << __func__ << __LINE__;
@ -391,7 +395,7 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
qCritical() << DBG_HEADER
<< "ERROR" << inputDate.toString(Qt::ISODate)
<< "NOT IN VALID WORKING TIME-RANGE";
return "";
return std::make_pair("", QDateTime());
}
#if DEBUG_GET_DURATION_FROM_COST==1
@ -440,7 +444,10 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
QDateTime d(QDateTime::fromString(s, Qt::ISODate));
d = d.addSecs(duration_previous * 60);
//qCritical() << DBG_HEADER << "XXXXXXXXXXXXXXXXXXXXX" << d;
return d.toString(Qt::ISODate).toStdString();
if (overPaid) {
return std::make_pair(CalcState::OVERPAID.toStdString(), d);
}
return std::make_pair(d.toString(Qt::ISODate).toStdString(), d);
}
} else {
durationInSecs = cfg->Duration.find(durationId)->second.pun_duration * 60;
@ -551,7 +558,10 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
qCritical() << DBG_HEADER << "TICKET-END" << s;
#endif
return s.toStdString();
if (overPaid) {
return std::make_pair(CalcState::OVERPAID.toStdString(), inputDate);
}
return std::make_pair(s.toStdString(), inputDate);
} // if ((double)price == cost) {
else {
//qCritical() << DBG_HEADER;
@ -561,7 +571,7 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
}
}
return "";
return std::make_pair("", QDateTime());
}
}
} else
@ -578,7 +588,7 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
if (cost < minParkingPrice) {
qCritical() << QString("ERROR: COST < MIN_PARKING_PRICE (%1 < %2)").arg(cost).arg(minParkingPrice);
return QDateTime().toString(Qt::ISODate).toStdString();
return std::make_pair(QDateTime().toString(Qt::ISODate).toStdString(), QDateTime());
}
if (cost > maxParkingPrice) {
@ -617,7 +627,7 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
weekdayId = current.date().dayOfWeek();
if (weekdayId == weekdayIdLast) {
qCritical() << "ERROR: NO VALID WORKDAY-TIMES DEFINED";
return QDateTime().toString(Qt::ISODate).toStdString();
return std::make_pair(QDateTime().toString(Qt::ISODate).toStdString(), QDateTime());
}
}
@ -635,7 +645,10 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
if (current.time() >= to) {
if (carryOverNotSet) {
return end_datetime.toString(Qt::ISODate).toStdString();
if (overPaid) {
return std::make_pair(CalcState::OVERPAID.toStdString(), end_datetime);
}
return std::make_pair(end_datetime.toString(Qt::ISODate).toStdString(), end_datetime);
} else {
QDateTime const dt = start;
start = start.addDays(1);
@ -682,7 +695,10 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
<< "price" << price;
#endif
end_datetime = current;
return end_datetime.toString(Qt::ISODate).toStdString();
if (overPaid) {
return std::make_pair(CalcState::OVERPAID.toStdString(), end_datetime);
}
return std::make_pair(end_datetime.toString(Qt::ISODate).toStdString(), end_datetime);
}
QTime const &from = QTime::fromString(weekDayWorkTimeRanges[weekDayWorkTimeIndex].pwd_time_from.c_str(), Qt::ISODate);
@ -777,7 +793,10 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
<< "end_datetime" << end_datetime.toString(Qt::ISODate)
<< "price" << price;
#endif
return end_datetime.toString(Qt::ISODate).toStdString();
if (overPaid) {
return std::make_pair(CalcState::OVERPAID.toStdString(), end_datetime);
}
return std::make_pair(end_datetime.toString(Qt::ISODate).toStdString(), end_datetime);
}
}
@ -818,7 +837,10 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
<< "end_datetime" << end_datetime.toString(Qt::ISODate)
<< "price" << price;
#endif
return end_datetime.toString(Qt::ISODate).toStdString();
if (overPaid) {
return std::make_pair(CalcState::OVERPAID.toStdString(), end_datetime);
}
return std::make_pair(end_datetime.toString(Qt::ISODate).toStdString(), end_datetime);
}
// price has been updated; use next time range
@ -849,7 +871,10 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
<< "price" << price;
#endif
return end_datetime.toString(Qt::ISODate).toStdString();
if (overPaid) {
return std::make_pair(CalcState::OVERPAID.toStdString(), end_datetime);
}
return std::make_pair(end_datetime.toString(Qt::ISODate).toStdString(), end_datetime);
}
if (moveToNextTimeRange) {
@ -965,8 +990,10 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
<< "end_datetime" << end_datetime.toString(Qt::ISODate)
<< "price" << price;
#endif
return end_datetime.toString(Qt::ISODate).toStdString();
if (overPaid) {
return std::make_pair(CalcState::OVERPAID.toStdString(), end_datetime);
}
return std::make_pair(end_datetime.toString(Qt::ISODate).toStdString(), end_datetime);
}
}
@ -979,7 +1006,10 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
<< "final price" << std::max(price, minParkingPrice);
#endif
return end_datetime.toString(Qt::ISODate).toStdString();
if (overPaid) {
return std::make_pair(CalcState::OVERPAID.toStdString(), end_datetime);
}
return std::make_pair(end_datetime.toString(Qt::ISODate).toStdString(), end_datetime);
} // while (timeRangeIt != cfg->TimeRange.cend()) {
}
@ -988,7 +1018,7 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
<< "INVALID END TIME";
#endif
end_datetime = QDateTime();
return end_datetime.toString(Qt::ISODate).toStdString();
return std::make_pair(end_datetime.toString(Qt::ISODate).toStdString(), end_datetime);
}
Ticket t = private_GetDurationFromCost(cfg, inputDate, cost, prepaid);
@ -996,7 +1026,7 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
// qCritical().noquote() << t;
// TODO: im fehlerfall
return t.getValidUntil().toString(Qt::ISODate).toStdString();
return std::make_pair(t.getValidUntil().toString(Qt::ISODate).toStdString(), t.getValidUntil());
}
#undef _DEBUG_

View File

@ -1110,6 +1110,7 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
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();
else if (strcmp(inner_obj_name, "pedwt_paid") == 0) SpecialDaysWorktime.pedwt_paid = k->value.GetInt();
break;
/*case MemberType::WeekDaysType:
if (strcmp(inner_obj_name, "pdiw_id") == 0) WeekDays.pdiw_id = k->value.GetInt();