Compare commits

...

10 Commits

Author SHA1 Message Date
b0c4ad0e2e getCurrentPaymentOptionIndex(): start implementation.
getPaymentOptions(): use new parameter paymentOptionIndex.
2024-04-12 14:31:02 +02:00
7e3347b043 GetTimeSteps(): use new parameter paymentOptionIndex 2024-04-12 14:30:04 +02:00
4e7fa83507 get_minimal_parkingtime()
get_maximal_parkingtime()
get_minimal_parkingprice()
get_maximal_parkingprice():
use new parameter paymentOptionIndex.
2024-04-12 14:27:08 +02:00
ac76f194e1 Added new constants 2024-04-12 14:26:03 +02:00
fe485b7b39 pop_business_hours as uint64_t. 2024-04-12 14:24:32 +02:00
e210224340 getPaymentOptions(): added default-parameter 'paymentOptionsIndex'
Added getCurrentPaymentOptionIndex() and isHoliday().
2024-04-12 14:22:20 +02:00
afa62183fd ResetTimeSteps(), GetTimeSteps(), GetSteps():
add parameter paymentOptionIndex (default=0)
2024-04-12 14:20:05 +02:00
f241a87dc1 get_minimal_parking_price()
get_maximal_parking_price()
get_maximal_parking_time()
get_minimal_parking_time():
	adden perameter paymentOptionIndex
2024-04-12 14:17:43 +02:00
9b1cc49d34 Minor: remove some debug output 2024-04-12 14:16:18 +02:00
449e618417 Add test-cases 2024-04-12 14:14:40 +02:00
10 changed files with 345 additions and 252 deletions

View File

@ -196,11 +196,25 @@ int CALCULATE_LIBRARY_API get_zone_nr(int zone = -1);
int CALCULATE_LIBRARY_API compute_next_timestep(parking_tariff_t *tariff, int currentTimeMinutes, int UpDown); int CALCULATE_LIBRARY_API compute_next_timestep(parking_tariff_t *tariff, int currentTimeMinutes, int UpDown);
QList<int> CALCULATE_LIBRARY_API get_time_steps(Configuration *cfg); QList<int> CALCULATE_LIBRARY_API get_time_steps(Configuration *cfg);
int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration *cfg, PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING);
int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration *cfg, PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING); int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration *cfg,
int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg, PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING); PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
int CALCULATE_LIBRARY_API get_maximal_parkingprice(Configuration *cfg, PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING); int paymentOptionIndex=0);
int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg, PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING);
int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration *cfg,
PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
int paymentOptionIndex=0);
int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg,
PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
int paymentOptionIndex=0);
int CALCULATE_LIBRARY_API get_maximal_parkingprice(Configuration *cfg,
PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
int paymentOptionIndex=0);
int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg,
PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING);
CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( // deprecated CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( // deprecated
parking_tariff_t *tariff, parking_tariff_t *tariff,

View File

@ -14,7 +14,7 @@
using namespace std; using namespace std;
class Calculator { class Calculator {
mutable QList<int> m_timeSteps; mutable QVector<QList<int>> m_timeSteps;
mutable QList<int> m_priceSteps; mutable QList<int> m_priceSteps;
protected: protected:
@ -29,8 +29,17 @@ public:
return c; return c;
} }
void ResetTimeSteps() { m_timeSteps.clear(); } void ResetTimeSteps(int paymentOptionIndex) {
QList<int> timeSteps() const { return m_timeSteps; } if (m_timeSteps.size() > 0) {
m_timeSteps[paymentOptionIndex].clear();
}
}
QList<int> timeSteps(int paymentOptionIndex=0) const {
if (m_timeSteps.size() > 0) {
return m_timeSteps[paymentOptionIndex];
}
return QList<int>();
}
void ResetPriceSteps() { m_priceSteps.clear(); } void ResetPriceSteps() { m_priceSteps.clear(); }
QList<int> priceSteps() const { return m_priceSteps; } QList<int> priceSteps() const { return m_priceSteps; }
@ -66,8 +75,8 @@ public:
// helper function to find time steps for a tariff with PaymentMethod::Steps // helper function to find time steps for a tariff with PaymentMethod::Steps
// (e.g. Schoenau/Koenigsee) // (e.g. Schoenau/Koenigsee)
// //
QList<int> GetTimeSteps(Configuration *cfg) const; QList<int> GetTimeSteps(Configuration *cfg, int paymentOptionIndex=0) const;
QList<int> GetSteps(Configuration *cfg) const { return GetTimeSteps(cfg); } QList<int> GetSteps(Configuration *cfg, int paymentOptionIndex=0) const { return GetTimeSteps(cfg, paymentOptionIndex); }
QList<int> GetPriceSteps(Configuration *cfg) const; QList<int> GetPriceSteps(Configuration *cfg) const;

View File

@ -63,10 +63,12 @@ public:
/// <returns>Returns operation status bool (OK | FAIL) </returns> /// <returns>Returns operation status bool (OK | FAIL) </returns>
bool ParseJson(Configuration* cfg, const char* json); bool ParseJson(Configuration* cfg, const char* json);
ATBPaymentOption &getPaymentOptions(); ATBPaymentOption &getPaymentOptions(int paymentOptionsIndex=0);
ATBPaymentOption const &getPaymentOptions() const; ATBPaymentOption const &getPaymentOptions(int paymentOptionsIndex=0) const;
QVector<ATBPaymentOption> &getAllPaymentOptions(); QVector<ATBPaymentOption> &getAllPaymentOptions();
QVector<ATBPaymentOption> const &getAllPaymentOptions() const; QVector<ATBPaymentOption> const &getAllPaymentOptions() const;
int getCurrentPaymentOptionIndex(QDateTime const &dt) const;
bool isHoliday(QDateTime const &dt) const;
std::optional<QVector<ATBPaymentRate>> getPaymentRateForAllKeys() const; std::optional<QVector<ATBPaymentRate>> getPaymentRateForAllKeys() const;
std::optional<QVector<ATBPaymentRate>> getPaymentRateForKey(int key) const; std::optional<QVector<ATBPaymentRate>> getPaymentRateForKey(int key) const;
std::optional<QVector<ATBDailyTicket>> getDailyTicketsForAllKeys() const; std::optional<QVector<ATBDailyTicket>> getDailyTicketsForAllKeys() const;

View File

@ -1,5 +1,9 @@
#pragma once #ifndef PAYMENT_OPT_H_INCLUDED
#define PAYMENT_OPT_H_INCLUDED
#include <string> #include <string>
#include <cinttypes>
class ATBPaymentOption class ATBPaymentOption
{ {
@ -37,6 +41,8 @@ public:
int pop_carry_over; int pop_carry_over;
int pop_carry_over_time_range_id; int pop_carry_over_time_range_id;
int pop_daily_card_price; int pop_daily_card_price;
int pop_business_hours; uint64_t pop_business_hours;
int pop_time_step_config; int pop_time_step_config;
}; };
#endif // PAYMENT_OPT_H_INCLUDED

View File

@ -4,19 +4,58 @@
/// <summary> /// <summary>
/// Business hours (byte represents payment option id) /// Business hours (byte represents payment option id)
/// </summary> /// </summary>
enum BusinessHours ///
#define _MON_ (1ULL << 8)
#define _TUE_ (1ULL << 9)
#define _WED_ (1ULL << 10)
#define _THU_ (1ULL << 11)
#define _FRI_ (1ULL << 12)
#define _SAT_ (1ULL << 13)
#define _SUN_ (1ULL << 14)
#define _WEEK_DAYS_ ((_MON_|_TUE_|_WED_|_THU_|_FRI_))
#define _WORKING_DAYS_ ((_MON_|_TUE_|_WED_|_THU_|_FRI_|_SAT_))
#define _ALL_DAYS_ ((_MON_|_TUE_|_WED_|_THU_|_FRI_|_SAT_|_SUN_))
#define _OFFICIAL_HOLIDAY_ (1ULL << 15)
#define _ONLY_WEEKEND ((_SAT_|_SUN_))
#define _ONLY_OPEN_FOR_BUSINESS_DAYS (1ULL << 16) /* verkaufsoffen */
#define _NOT_DEFINED (~0ULL)
enum BusinessHours : std::uint64_t
{ {
NoRestriction_24_7 = 0, NoRestriction_24_7 = 0,
OnlyWorkingDays = 1, // [Monday-Friday] OnlyWorkingDays = 1, // [Monday-Friday]
OnlyWeekDays = 2, // [Monday-Saturday] OnlyWeekDays = 2, // [Monday-Saturday]
OnlyWeekEnd = 4, // [Saturday+Sunday] OnlyWeekEnd = 4, // [Saturday+Sunday]
OnlyOfficialHolidays = 8, OnlyOfficialHolidays = 8,
OnlySundaysAndHolidays = 12, // [Sun+Holiday]
OnlySpecialDays = 16, OnlySpecialDays = 16,
OnlySchoolHolidays = 32, OnlySchoolHolidays = 32,
SpecialAndSchoolHolidays = 48, SpecialAndSchoolHolidays = 48,
OnlyOpenForBusinessDays = 64, // verkaufsoffen OnlyOpenForBusinessDays = 64, // verkaufsoffen
AllDaysWithRestrictedHours = 128, // every day, restricted to some time range AllDaysWithRestrictedHours = 128, // every day, restricted to some time range
NoBusinessHoursDefined = 255 NoBusinessHoursDefined = 255,
// new 12.04.2024
NO_RESTRICTION_24_7 = 0,
MON = _MON_,
TUE = _TUE_,
WED = _WED_,
THU = _THU_,
FRI = _FRI_,
SAT = _SAT_,
SUN = _SUN_,
WEEK_DAYS = _WEEK_DAYS_,
WORKING_DAYS = _WORKING_DAYS_,
ALL_DAYS = _ALL_DAYS_,
OFFICIAL_HOLIDAY = _OFFICIAL_HOLIDAY_,
ONLY_WEEKEND = _ONLY_WEEKEND,
ONLY_OPEN_FOR_BUSINESS_DAYS = _ONLY_OPEN_FOR_BUSINESS_DAYS,
NOT_DEFINED = _NOT_DEFINED
};
struct BusinessHours_struct {
BusinessHours bh;
}; };
#endif // TARIFF_BUSINESS_HOURS_H_INCLUDED #endif // TARIFF_BUSINESS_HOURS_H_INCLUDED

View File

@ -14,12 +14,14 @@ QList<int> CALCULATE_LIBRARY_API get_time_steps(Configuration *cfg) {
return Calculator::GetInstance().GetTimeSteps(cfg); return Calculator::GetInstance().GetTimeSteps(cfg);
} }
int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration *cfg, PERMIT_TYPE permitType) { int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration *cfg,
PERMIT_TYPE permitType,
int paymentOptionIndex) {
int minTime = 0; int minTime = 0;
switch(permitType) { switch(permitType) {
case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281) case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281)
minTime = cfg->getPaymentOptions().pop_min_time; minTime = cfg->getPaymentOptions(paymentOptionIndex).pop_min_time;
} break; } break;
case PERMIT_TYPE::DAY_TICKET_ADULT: { case PERMIT_TYPE::DAY_TICKET_ADULT: {
} break; } break;
@ -30,20 +32,22 @@ int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration *cfg, PERMIT_TYP
default: default:
// for each new sell-procedure, recomute the timesteps. implicitly, set // for each new sell-procedure, recomute the timesteps. implicitly, set
// the minimal parking time. // the minimal parking time.
Calculator::GetInstance().ResetTimeSteps(); Calculator::GetInstance().ResetTimeSteps(paymentOptionIndex);
Calculator::GetInstance().GetTimeSteps(cfg); Calculator::GetInstance().GetTimeSteps(cfg, paymentOptionIndex);
minTime = qRound(cfg->getPaymentOptions().pop_min_time); minTime = qRound(cfg->getPaymentOptions(paymentOptionIndex).pop_min_time);
} }
return minTime; return minTime;
} }
int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration *cfg, PERMIT_TYPE permitType) { int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration *cfg,
PERMIT_TYPE permitType,
int paymentOptionIndex) {
int maxTime = 0; int maxTime = 0;
switch(permitType) { switch(permitType) {
case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281) case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281)
maxTime = cfg->getPaymentOptions().pop_max_time; maxTime = cfg->getPaymentOptions(paymentOptionIndex).pop_max_time;
} break; } break;
case PERMIT_TYPE::DAY_TICKET_ADULT: { case PERMIT_TYPE::DAY_TICKET_ADULT: {
} break; } break;
@ -57,12 +61,14 @@ int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration *cfg, PERMIT_TYP
return maxTime; return maxTime;
} }
int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg, PERMIT_TYPE permitType) { int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg,
PERMIT_TYPE permitType,
int paymentOptionIndex) {
int minPrice = -1; int minPrice = -1;
switch(permitType) { switch(permitType) {
case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281) case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281)
minPrice = cfg->getPaymentOptions().pop_min_price; minPrice = cfg->getPaymentOptions(paymentOptionIndex).pop_min_price;
} break; } break;
case PERMIT_TYPE::DAY_TICKET_ADULT: { case PERMIT_TYPE::DAY_TICKET_ADULT: {
} break; } break;
@ -119,7 +125,9 @@ int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg, PERMIT
return 0; return 0;
} }
int CALCULATE_LIBRARY_API get_maximal_parkingprice(Configuration *cfg, PERMIT_TYPE permitType) { int CALCULATE_LIBRARY_API get_maximal_parkingprice(Configuration *cfg,
PERMIT_TYPE permitType,
int paymentOptionIndex) {
int maxPrice = -1; int maxPrice = -1;
static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg); static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg);
@ -128,8 +136,8 @@ int CALCULATE_LIBRARY_API get_maximal_parkingprice(Configuration *cfg, PERMIT_TY
if (paymentMethodId == PaymentMethod::Progressive || paymentMethodId == PaymentMethod::Steps) { if (paymentMethodId == PaymentMethod::Progressive || paymentMethodId == PaymentMethod::Steps) {
maxPrice = Utilities::getMaximalParkingPrice(cfg, paymentMethodId); maxPrice = Utilities::getMaximalParkingPrice(cfg, paymentMethodId);
} else { // PaymentMethod::Linear -> e.g. szeged } else { // PaymentMethod::Linear -> e.g. szeged
int const key = cfg->getPaymentOptions().pop_id; int const key = cfg->getPaymentOptions(paymentOptionIndex).pop_id;
int const maxTime = cfg->getPaymentOptions().pop_max_time; // maxTime is given in minutes int const maxTime = cfg->getPaymentOptions(paymentOptionIndex).pop_max_time; // maxTime is given in minutes
std::optional<QVector<ATBPaymentRate>> const &pv = cfg->getPaymentRateForKey(key); std::optional<QVector<ATBPaymentRate>> const &pv = cfg->getPaymentRateForKey(key);
if (pv) { if (pv) {
QVector<ATBPaymentRate> const &paymentRate = pv.value(); QVector<ATBPaymentRate> const &paymentRate = pv.value();

View File

@ -1569,24 +1569,26 @@ QList<int> Calculator::GetPriceSteps(Configuration * /*cfg*/) const {
return QList<int>(); return QList<int>();
} }
QList<int> Calculator::GetTimeSteps(Configuration *cfg) const { QList<int> Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex) const {
if (m_timeSteps.size() > 0) { qCritical() << "(" << __func__ << ":" << __LINE__ << ")" << "paymentOptionIndex:" << paymentOptionIndex;
if (m_timeSteps.size() > paymentOptionIndex) {
//qCritical() << __PRETTY_FUNCTION__ << "timeSteps:" << m_timeSteps; //qCritical() << __PRETTY_FUNCTION__ << "timeSteps:" << m_timeSteps;
return m_timeSteps; return m_timeSteps[paymentOptionIndex];
} }
QDateTime start = QDateTime::currentDateTime(); QDateTime start = QDateTime::currentDateTime();
start.setTime(QTime(start.time().hour(), start.time().minute(), 0)); start.setTime(QTime(start.time().hour(), start.time().minute(), 0));
int const pop_id = cfg->getPaymentOptions().pop_id; int const pop_id = cfg->getPaymentOptions(paymentOptionIndex).pop_id;
int const pop_carry_over = cfg->getPaymentOptions().pop_carry_over; int const pop_carry_over = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over;
int const pop_time_step_config = cfg->getPaymentOptions().pop_time_step_config; int const pop_time_step_config = cfg->getPaymentOptions(paymentOptionIndex).pop_time_step_config;
static PaymentMethod const paymentMethodId = Utilities::getPaymentMethodId(cfg); static PaymentMethod const paymentMethodId = Utilities::getPaymentMethodId(cfg);
qCritical() << __func__ << ":" << __LINE__ << " start parking time:" << start.toString(Qt::ISODate); qCritical() << "(" << __func__ << ":" << __LINE__ << ") start parking time:" << start.toString(Qt::ISODate);
qCritical() << __func__ << ":" << __LINE__ << " payment option id:" << pop_id; qCritical() << "(" << __func__ << ":" << __LINE__ << ") payment option id:" << pop_id;
qCritical() << __func__ << ":" << __LINE__ << "payment option carry over:" << pop_carry_over; qCritical() << "(" << __func__ << ":" << __LINE__ << ") payment option carry over:" << pop_carry_over;
if (pop_time_step_config == (int)ATBTimeStepConfig::TimeStepConfig::DYNAMIC) { if (pop_time_step_config == (int)ATBTimeStepConfig::TimeStepConfig::DYNAMIC) {
//qCritical() << __PRETTY_FUNCTION__ << "payment option time step config:" << "TimeStepConfig::DYNAMIC"; //qCritical() << __PRETTY_FUNCTION__ << "payment option time step config:" << "TimeStepConfig::DYNAMIC";
@ -1595,13 +1597,13 @@ QList<int> Calculator::GetTimeSteps(Configuration *cfg) const {
std::size_t const s = cfg->TimeRange.size(); std::size_t const s = cfg->TimeRange.size();
for (std::size_t id = 1; id <= s; ++id) { for (std::size_t id = 1; id <= s; ++id) {
int const step = Utilities::getTimeRangeStep(cfg, id, paymentMethodId); int const step = Utilities::getTimeRangeStep(cfg, id, paymentMethodId);
m_timeSteps.append(step); m_timeSteps[paymentOptionIndex].append(step);
} }
} else { } else {
uint16_t timeStepCompensation = 0; uint16_t timeStepCompensation = 0;
if (pop_carry_over) { if (pop_carry_over) {
int const pop_carry_over_time_range_id = cfg->getPaymentOptions().pop_carry_over_time_range_id; int const pop_carry_over_time_range_id = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over_time_range_id;
QTime const carryOverTimeRangeFrom = cfg->TimeRange.find(pop_carry_over_time_range_id)->second.time_range_from; 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; QTime const carryOverTimeRangeTo = cfg->TimeRange.find(pop_carry_over_time_range_id)->second.time_range_to;
@ -1625,19 +1627,19 @@ QList<int> Calculator::GetTimeSteps(Configuration *cfg) const {
.arg(timeStep).arg(duration.pun_duration_max); .arg(timeStep).arg(duration.pun_duration_max);
break; break;
} }
qCritical() << __PRETTY_FUNCTION__ << "configured minimal parking time:" << cfg->getPaymentOptions().pop_min_time; qCritical() << "(" << __func__ << ":" << __LINE__ << ") configured minimal parking time:" << cfg->getPaymentOptions(paymentOptionIndex).pop_min_time;
// set dynamic minimal parking time // set dynamic minimal parking time
cfg->getPaymentOptions().pop_min_time = timeStep; cfg->getPaymentOptions().pop_min_time = timeStep;
qCritical() << __PRETTY_FUNCTION__ << " computed minimal parking time:" << cfg->getPaymentOptions().pop_min_time; qCritical() << "(" << __func__ << ":" << __LINE__ << ") computed minimal parking time:" << cfg->getPaymentOptions(paymentOptionIndex).pop_min_time;
duration.pun_duration = timeStep; duration.pun_duration = timeStep;
timeStepCompensation = duration.pun_duration_max - duration.pun_duration; timeStepCompensation = duration.pun_duration_max - duration.pun_duration;
m_timeSteps << duration.pun_duration; m_timeSteps[paymentOptionIndex] << duration.pun_duration;
} else { } else {
duration.pun_duration = duration.pun_duration_max - timeStepCompensation; duration.pun_duration = duration.pun_duration_max - timeStepCompensation;
m_timeSteps << duration.pun_duration;; m_timeSteps[paymentOptionIndex] << duration.pun_duration;;
} }
cfg->Duration.erase(search); cfg->Duration.erase(search);
@ -1658,19 +1660,26 @@ QList<int> Calculator::GetTimeSteps(Configuration *cfg) const {
} }
} }
} else { } else {
qCritical() << __PRETTY_FUNCTION__ << "payment option time step config:" << "TimeStepConfig::STATIC"; qCritical() << "(" << __func__ << ":" << __LINE__ << ") payment option time step config:" << "TimeStepConfig::STATIC";
for (auto[itr, rangeEnd] = cfg->PaymentRate.equal_range(pop_id); itr != rangeEnd; ++itr) for (auto[itr, rangeEnd] = cfg->PaymentRate.equal_range(pop_id); itr != rangeEnd; ++itr)
{ {
int const durationId = itr->second.pra_payment_unit_id; int const durationId = itr->second.pra_payment_unit_id;
int const durationUnit = cfg->Duration.find(durationId)->second.pun_duration; int const durationUnit = cfg->Duration.find(durationId)->second.pun_duration;
m_timeSteps << durationUnit; int size = m_timeSteps.size();
while (size <= paymentOptionIndex) {
m_timeSteps.push_back(QList<int>());
size = m_timeSteps.size();
}
m_timeSteps[paymentOptionIndex] << durationUnit;
} }
} }
qCritical() << __PRETTY_FUNCTION__ << "NEW timeSteps:" << m_timeSteps; qCritical() << "(" << __func__ << ":" << __LINE__ << ")" << "NEW timeSteps:" << m_timeSteps;
return m_timeSteps; return m_timeSteps[paymentOptionIndex];
} }
uint32_t Calculator::GetPriceForTimeStep(Configuration *cfg, int timeStep) const { uint32_t Calculator::GetPriceForTimeStep(Configuration *cfg, int timeStep) const {

View File

@ -3,6 +3,7 @@
#include "time_range_header.h" #include "time_range_header.h"
#include "tariff_timestep_config.h" #include "tariff_timestep_config.h"
#include "tariff_permit_type.h" #include "tariff_permit_type.h"
#include "tariff_business_hours.h"
#include <QString> #include <QString>
#include <QDebug> #include <QDebug>
@ -542,15 +543,76 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
} }
} }
int Configuration::getCurrentPaymentOptionIndex(QDateTime const &dt) const {
int const numOptions = getAllPaymentOptions().size();
ATBPaymentOption const &Configuration::getPaymentOptions() const { for (int opt=0; opt < numOptions; ++opt) {
Q_ASSERT(!this->currentPaymentOptions.isEmpty()); uint64_t const pop_business_hours = getPaymentOptions(opt).pop_business_hours;
return this->currentPaymentOptions.at(0); uint64_t p = 0;
switch (dt.date().dayOfWeek()) {
case (int)Qt::Monday: {
p = BusinessHours::MON;
if ((pop_business_hours & p) == p) {
return opt;
}
} break;
case (int)Qt::Tuesday: {
p = BusinessHours::TUE;
if ((pop_business_hours & p) == p) {
return opt;
}
} break;
case (int)Qt::Wednesday: {
p = BusinessHours::WED;
if ((pop_business_hours & p) == p) {
return opt;
}
} break;
case (int)Qt::Thursday: {
p = BusinessHours::THU;
if ((pop_business_hours & p) == p) {
return opt;
}
} break;
case (int)Qt::Friday: {
p = BusinessHours::FRI;
if ((pop_business_hours & p) == p) {
return opt;
}
} break;
case (int)Qt::Saturday: {
p = BusinessHours::SAT;
if ((pop_business_hours & p) == p) {
return opt;
}
} break;
case (int)Qt::Sunday: {
p = BusinessHours::SUN;
if (isHoliday(dt)) {
p |= BusinessHours::OFFICIAL_HOLIDAY;
}
if ((pop_business_hours & p) == p) {
return opt;
}
} break;
}
}
return -1;
} }
ATBPaymentOption &Configuration::getPaymentOptions() { bool Configuration::isHoliday(QDateTime const &dt) const {
return false;
}
ATBPaymentOption const &Configuration::getPaymentOptions(int paymentOptionsIndex) const {
Q_ASSERT(!this->currentPaymentOptions.isEmpty()); Q_ASSERT(!this->currentPaymentOptions.isEmpty());
return this->currentPaymentOptions[0]; return this->currentPaymentOptions.at(paymentOptionsIndex);
}
ATBPaymentOption &Configuration::getPaymentOptions(int paymentOptionsIndex) {
Q_ASSERT(!this->currentPaymentOptions.isEmpty());
return this->currentPaymentOptions[paymentOptionsIndex];
} }
QVector<ATBPaymentOption> const &Configuration::getAllPaymentOptions() const { QVector<ATBPaymentOption> const &Configuration::getAllPaymentOptions() const {

View File

@ -260,7 +260,7 @@ bool Utilities::CheckSpecialDay(Configuration* cfg, const char* currentDateTimeS
//cout << "CheckSpecialDay() => Month is in range between start and end" << endl; //cout << "CheckSpecialDay() => Month is in range between start and end" << endl;
if ((current_tm.tm_mday >= start_tm.tm_mday) && (current_tm.tm_mday <= end_tm.tm_mday)) if ((current_tm.tm_mday >= start_tm.tm_mday) && (current_tm.tm_mday <= end_tm.tm_mday))
{ {
LOG_DEBUG("CheckSpecialDay() => SPECIAL DAY"); //LOG_DEBUG("CheckSpecialDay() => SPECIAL DAY");
*specialDayId = spec_days_itr->second.ped_id; *specialDayId = spec_days_itr->second.ped_id;
*specialDayPrice = cfg->SpecialDaysWorktime.find(*specialDayId)->second.pedwt_price; *specialDayPrice = cfg->SpecialDaysWorktime.find(*specialDayId)->second.pedwt_price;
return true; return true;
@ -275,7 +275,7 @@ bool Utilities::CheckSpecialDay(Configuration* cfg, const char* currentDateTimeS
//cout << "CheckSpecialDay() => Month is in range between start and end" << endl; //cout << "CheckSpecialDay() => Month is in range between start and end" << endl;
if ((current_tm.tm_mday >= start_tm.tm_mday) && (current_tm.tm_mday <= end_tm.tm_mday)) if ((current_tm.tm_mday >= start_tm.tm_mday) && (current_tm.tm_mday <= end_tm.tm_mday))
{ {
LOG_DEBUG("CheckSpecialDay() => SPECIAL DAY"); //LOG_DEBUG("CheckSpecialDay() => SPECIAL DAY");
*specialDayId = spec_days_itr->second.ped_id; *specialDayId = spec_days_itr->second.ped_id;
*specialDayPrice = cfg->SpecialDaysWorktime.find(*specialDayId)->second.pedwt_price; *specialDayPrice = cfg->SpecialDaysWorktime.find(*specialDayId)->second.pedwt_price;
return true; return true;
@ -317,7 +317,7 @@ bool Utilities::CheckSpecialDay(Configuration const *cfg,
continue; continue;
} }
} }
qDebug() << "CheckSpecialDay() => SPECIAL DAY"; //qDebug() << "CheckSpecialDay() => SPECIAL DAY";
*specialDayId = spec_days_itr->second.ped_id; *specialDayId = spec_days_itr->second.ped_id;
*specialDayPrice = cfg->SpecialDaysWorktime.find(*specialDayId)->second.pedwt_price; *specialDayPrice = cfg->SpecialDaysWorktime.find(*specialDayId)->second.pedwt_price;
return true; return true;

View File

@ -43,122 +43,6 @@ extern "C" char* strptime(const char* s,
#define NEUHAUSER_KIRCHDORF (0) #define NEUHAUSER_KIRCHDORF (0)
#define BAD_NEUENAHR_AHRWEILER (1) #define BAD_NEUENAHR_AHRWEILER (1)
#if NEUHAUSER_KIRCHDORF==1
static bool test_neuhauser_kirchdorf(int step, double cost) {
switch (step) {
case 30:
if (cost != 30) {
qCritical() << "ERROR COMPUTING COST"
<< "HAVE" << cost
<< "SHOULD" << 30;
return false;
}
break;
case 35:
if (cost != 40) {
qCritical() << "ERROR COMPUTING COST"
<< "HAVE" << cost
<< "SHOULD" << 40;
return false;
}
break;
case 40:
if (cost != 50) {
qCritical() << "ERROR COMPUTING COST"
<< "HAVE" << cost
<< "SHOULD" << 50;
return false;
}
break;
case 45:
if (cost != 60) {
qCritical() << "ERROR COMPUTING COST"
<< "HAVE" << cost
<< "SHOULD" << 60;
return false;
}
break;
case 50:
if (cost != 70) {
qCritical() << "ERROR COMPUTING COST"
<< "HAVE" << cost
<< "SHOULD" << 70;
return false;
}
break;
case 55:
if (cost != 80) {
qCritical() << "ERROR COMPUTING COST"
<< "HAVE" << cost
<< "SHOULD" << 80;
return false;
}
break;
case 60:
if (cost != 90) {
qCritical() << "ERROR COMPUTING COST"
<< "HAVE" << cost
<< "SHOULD" << 90;
return false;
}
break;
case 65:
if (cost != 100) {
qCritical() << "ERROR COMPUTING COST"
<< "HAVE" << cost
<< "SHOULD" << 100;
return false;
}
break;
case 70:
if (cost != 110) {
qCritical() << "ERROR COMPUTING COST"
<< "HAVE" << cost
<< "SHOULD" << 110;
return false;
}
break;
case 75:
if (cost != 120) {
qCritical() << "ERROR COMPUTING COST"
<< "HAVE" << cost
<< "SHOULD" << 120;
return false;
}
break;
case 80:
if (cost != 130) {
qCritical() << "ERROR COMPUTING COST"
<< "HAVE" << cost
<< "SHOULD" << 130;
return false;
}
break;
case 85:
if (cost != 140) {
qCritical() << "ERROR COMPUTING COST"
<< "HAVE" << cost
<< "SHOULD" << 140;
return false;
}
break;
case 90:
if (cost != 150) {
qCritical() << "ERROR COMPUTING COST"
<< "HAVE" << cost
<< "SHOULD" << 150;
return false;
}
break;
default:
break;
}
return true;
}
#endif
int main() { int main() {
#if BAD_NEUENAHR_AHRWEILER==1 #if BAD_NEUENAHR_AHRWEILER==1
std::ifstream input; std::ifstream input;
@ -167,8 +51,10 @@ int main() {
int pop_min_price; int pop_min_price;
int pop_max_price; int pop_max_price;
int pop_daily_card_price; int pop_daily_card_price;
int pop_carry_over;
int pop_carry_over_time_range_id;
for (int zone=1; zone < 2; ++zone) { for (int zone=2; zone < 3; ++zone) {
//for (int t=6; t < 7; t+=20) { //for (int t=6; t < 7; t+=20) {
switch (zone) { switch (zone) {
case 1: { case 1: {
@ -214,91 +100,151 @@ int main() {
if (isParsed) { if (isParsed) {
// test library functions // test library functions
pop_min_time = get_minimal_parkingtime(&cfg); if (zone == 1) {
pop_max_time = get_maximal_parkingtime(&cfg); pop_min_time = get_minimal_parkingtime(&cfg);
pop_min_price = get_minimal_parkingprice(&cfg); pop_max_time = get_maximal_parkingtime(&cfg);
pop_max_price = get_maximal_parkingprice(&cfg); pop_min_price = get_minimal_parkingprice(&cfg);
pop_daily_card_price = cfg.getPaymentOptions().pop_daily_card_price; pop_max_price = get_maximal_parkingprice(&cfg);
pop_daily_card_price = cfg.getPaymentOptions().pop_daily_card_price;
qCritical() << " pop_min_time: " << pop_min_time; qCritical() << " pop_min_time: " << pop_min_time;
qCritical() << " pop_max_time: " << pop_max_time; qCritical() << " pop_max_time: " << pop_max_time;
qCritical() << " pop_min_price: " << pop_min_price; qCritical() << " pop_min_price: " << pop_min_price;
qCritical() << " pop_max_price: " << pop_max_price; qCritical() << " pop_max_price: " << pop_max_price;
qCritical() << "pop_daily_card_price: " << pop_daily_card_price; qCritical() << "pop_daily_card_price: " << pop_daily_card_price;
static QList<int> const stepsConfigured static QList<int> const stepsConfigured
= QList(std::initializer_list<int>{ = QList(std::initializer_list<int>{
20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 1440}); 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 1440});
//static QList<double> const cost //static QList<double> const cost
// = QList(std::initializer_list<double>{ // = QList(std::initializer_list<double>{
// 0, 40, 80, 120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 500}); // 0, 40, 80, 120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 500});
static QList<int> const timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg); static QList<int> const timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg);
qCritical() << "TimeSteps" << timeSteps; qCritical() << "TimeSteps" << timeSteps;
if (stepsConfigured != timeSteps) { if (stepsConfigured != timeSteps) {
qCritical() << "TIME-STEPS SHOULD BE" << stepsConfigured; qCritical() << "TIME-STEPS SHOULD BE" << stepsConfigured;
return -1; return -1;
} }
QDateTime start = QDateTime::currentDateTime(); QDateTime start = QDateTime::currentDateTime();
struct price_t costs; struct price_t costs;
double price1 = 0; double price1 = 0;
double price2 = 0; double price2 = 0;
for (int m=0; m < 1440; ++m) { for (int m=0; m < 1440; ++m) {
start.setTime(QTime(0, 0, 0)); start.setTime(QTime(0, 0, 0));
start = start.addSecs(m*60); start = start.addSecs(m*60);
qCritical() << "START" << start.toString(Qt::ISODate); qCritical() << "START" << start.toString(Qt::ISODate);
//int Down = 0; //int Down = 0;
//int Up = 1; //int Up = 1;
// for (int i = 0, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) { // for (int i = 0, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) {
// int nextTimeStep = compute_next_timestep(&cfg, timeSteps.at(i), Up); // int nextTimeStep = compute_next_timestep(&cfg, timeSteps.at(i), Up);
// qCritical() << "nextTimeStep" << nextTimeStep; // qCritical() << "nextTimeStep" << nextTimeStep;
// //
// int prevTimeStep = compute_next_timestep(&cfg, timeSteps.at(i), Down); // int prevTimeStep = compute_next_timestep(&cfg, timeSteps.at(i), Down);
// qCritical() << "prevTimeStep" << prevTimeStep; // qCritical() << "prevTimeStep" << prevTimeStep;
//} //}
CalcState cs; CalcState cs;
for (int i = 0, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) { for (int i = 0, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) {
QDateTime end = start.addSecs(timeSteps.at(i)*60); 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);
if (cs.getStatus() != CalcState::State::SUCCESS) { if (cs.getStatus() != CalcState::State::SUCCESS) {
if (start.time().hour() >= 8 && start.time().hour() < 18) { if (start.time().hour() >= 8 && start.time().hour() < 18) {
qCritical() << "ERROR CALC-STATE-1=" << QString(cs); qCritical() << "ERROR CALC-STATE-1=" << QString(cs);
exit(-1); exit(-1);
} else { } else {
if (cs.getStatus() == CalcState::State::OUTSIDE_ALLOWED_PARKING_TIME) { if (cs.getStatus() == CalcState::State::OUTSIDE_ALLOWED_PARKING_TIME) {
qCritical() << "CALC-STATE=" << QString(cs); qCritical() << "CALC-STATE=" << QString(cs);
continue; continue;
}
qCritical() << "ERROR CALC-STATE-2=" << QString(cs);
exit(-1);
} }
qCritical() << "ERROR CALC-STATE-2=" << QString(cs); }
price1 = costs.netto;
price2 = Calculator::GetInstance().GetCostFromDuration(&cfg, start, timeSteps.at(i));
if (price1 != price2) {
qCritical() << "ERROR DIFFERENT PRICES" << price1 << price2;
exit(-1); exit(-1);
} }
}
price1 = costs.netto;
price2 = Calculator::GetInstance().GetCostFromDuration(&cfg, start, timeSteps.at(i));
if (price1 != price2) { qCritical() << "compute_price_for_parking_ticket()/GetCostFromDuration() TIME: "
qCritical() << "ERROR DIFFERENT PRICES" << price1 << price2; << timeSteps.at(i) << "PRICE=" << price1;
exit(-1);
//std::string duration = Calculator::GetInstance().GetDurationFromCost(&cfg, 4,
// start.toString(Qt::ISODate).toStdString().c_str(),
// cost[i], false, true);
//qCritical() << "duration" << duration.c_str();
}
}
} // zone == 1
if (zone == 2) {
int const numOptions = cfg.getAllPaymentOptions().size();
#if 0
for (int payOpt=0; payOpt < numOptions; ++payOpt) {
pop_min_time = get_minimal_parkingtime(&cfg, PERMIT_TYPE::SHORT_TERM_PARKING, payOpt);
pop_max_time = get_maximal_parkingtime(&cfg, PERMIT_TYPE::SHORT_TERM_PARKING, payOpt);
pop_min_price = get_minimal_parkingprice(&cfg, PERMIT_TYPE::SHORT_TERM_PARKING, payOpt);
pop_max_price = get_maximal_parkingprice(&cfg, PERMIT_TYPE::SHORT_TERM_PARKING, payOpt);
pop_daily_card_price = cfg.getPaymentOptions(payOpt).pop_daily_card_price;
pop_carry_over = cfg.getPaymentOptions(payOpt).pop_carry_over;
pop_carry_over_time_range_id = cfg.getPaymentOptions(payOpt).pop_carry_over_time_range_id;
qCritical() << QString(" pop_min_time[%1]: %2").arg(payOpt).arg(pop_min_time);
qCritical() << QString(" pop_max_time[%1]: %2").arg(payOpt).arg(pop_max_time);
qCritical() << QString(" pop_min_price[%1]: %2").arg(payOpt).arg(pop_min_price);
qCritical() << QString(" pop_max_price[%1]: %2").arg(payOpt).arg(pop_max_price);
qCritical() << QString(" pop_daily_card_price[%1]: %2").arg(payOpt).arg(pop_daily_card_price);
qCritical() << QString(" pop_carry_over[%1]: %2").arg(payOpt).arg(pop_carry_over);
qCritical() << QString("pop_carry_over_time_range_id[%1]: %2").arg(payOpt).arg(pop_carry_over_time_range_id);
if (pop_carry_over_time_range_id != -1) {
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() << QString(" timeRangeFrom[%1]: %2").arg(payOpt).arg(carryOverTimeRangeFrom.toString(Qt::ISODate));
qCritical() << QString(" timeRangeTo[%1]: %2").arg(payOpt).arg(carryOverTimeRangeTo.toString(Qt::ISODate));
} }
qCritical() << "compute_price_for_parking_ticket()/GetCostFromDuration() TIME: " }
<< timeSteps.at(i) << "PRICE=" << price1; #endif
QDateTime start(QDate(2024, 4, 14), QTime());
QDateTime end;
struct price_t price;
//std::string duration = Calculator::GetInstance().GetDurationFromCost(&cfg, 4, //start = QDateTime::currentDateTime();
// start.toString(Qt::ISODate).toStdString().c_str(),
// cost[i], false, true); int paymentOptionIndex = cfg.getCurrentPaymentOptionIndex(start);
//qCritical() << "duration" << duration.c_str(); if (paymentOptionIndex != -1) {
qCritical() << "paymentOptionIndex" << paymentOptionIndex;
QList<int> const timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg, paymentOptionIndex);
qCritical() << "TimeSteps" << timeSteps;
// QDateTime start = s.addSecs(offset * 60);
QList<int>::const_iterator step;
for (step = timeSteps.cbegin(); step != timeSteps.cend(); ++step) {
double cost = 0;
//if (compute_price_for_parking_ticket(&cfg, start, *step, end, &price)) {
// cost = price.netto;
//}
}
} }
} }
} }
@ -306,8 +252,8 @@ int main() {
#endif #endif
#if SCHOENAU_KOENIGSEE==1 #if SCHOENAU_KOENIGSEE==1
QString f("/opt/ptu5/opt/customer_332/etc/psa_tariff/tariff01.json"); //QString f("/opt/ptu5/opt/customer_332/etc/psa_tariff/tariff01.json");
//QString f("/opt/ptu5/opt/customer_332/etc/psa_tariff/tariff02.json"); QString f("/opt/ptu5/opt/customer_332/etc/psa_tariff/tariff02.json");
std::ifstream input(f.toUtf8().constData()); std::ifstream input(f.toUtf8().constData());
@ -329,24 +275,22 @@ int main() {
QDateTime start = QDateTime::currentDateTime(); QDateTime start = QDateTime::currentDateTime();
// zone 1 // zone 1
//int timeSteps[9] = {60, 180, 1440, 2880, 4320, 5670, 7200, 8640, 10080}; //int timeSteps[] = {60, 180, 1440, 2880, 4320, 5670, 7200, 8640, 10080, 11520, 12960, 14400};
// zone 2
//int timeSteps[3] = {60, 180, 1440};
static QList<int> const timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg); static QList<int> const timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg);
qCritical() << "TimeSteps" << timeSteps; qCritical() << "TimeSteps" << timeSteps;
// for (int i = 0 ; i < timeSteps.size(); ++i) { for (int i = 0 ; i < timeSteps.size(); ++i) {
// QDateTime end = start.addSecs(timeSteps.at(i)*60); QDateTime end = start.addSecs(timeSteps.at(i)*60);
//
// double price = Calculator::GetInstance().GetCostFromDuration( double price = Calculator::GetInstance().GetCostFromDuration(
// &cfg, &cfg,
// start, start,
// timeSteps.at(i)); timeSteps.at(i));
// qDebug() << "GetCostFromDuration() time: " << timeSteps.at(i) << "price=" << price; qDebug() << "GetCostFromDuration() time: " << timeSteps.at(i)
//} << "(" << timeSteps.at(i)/60 << "h)"
<< "price=" << price;
}
} }
#endif #endif