Compare commits

...

16 Commits

Author SHA1 Message Date
d07fdd8540 GetPriceForTimeStep(): use parameter paymentOptionIndex. 2024-04-19 13:33:54 +02:00
1fab458de3 Implement isParkingAllowedForWeekDay(), isParkingAllowedForSpecialDay()
and isParkingAllowed() (4 parameters) using the 2 functions.
2024-04-19 13:32:24 +02:00
1ac2ca91c5 GetCostFromDuration(): use new parameter paymentOptionIndex. 2024-04-19 13:31:01 +02:00
1852f552a3 compute_price_for_parking_ticket(): compute paymentOptionIndex.
(a tariff-file can conatin more than one payment options).
2024-04-19 13:28:35 +02:00
e2c02420f0 Add parsing for new values in helper-structures.
NOTE: unfortunately switched to Unix-File-Format.
2024-04-19 13:26:33 +02:00
1240abbbec Add test cases BAD_NEUENAHR_AHRWEILER, zone2. 2024-04-19 13:24:10 +02:00
e20eb93abf Implement SpecialDaysWorkTimeFrom() and SpecialDaysWorkTimeUntil().
Extend getBusinessHours() to include new enum-values.
Implement isDayIncluded() as switch-case on dayOfWeek.
Implement dumpBusinessHours().
2024-04-19 13:21:38 +02:00
b0e7bd91b4 Add ariff_global_defines.h. 2024-04-19 13:20:44 +02:00
0cd4424434 Add utilities
isDayIncluded(), SpecialDaysWorkTimeFrom() and specialDaysWorkTimeUntil().
2024-04-19 13:19:26 +02:00
1991853b66 Add new enum-values for business_hours. Keep the old ones for
backward-compatibility.
2024-04-19 13:18:02 +02:00
b31fcc5f4f Minor: add explicit default constructor. 2024-04-19 13:17:00 +02:00
dbe649d0e4 Add member variables
pop_carry_over_start_time_range
pop_carry_over_end_time_range:

If carry-over has been set, then provide the limits
for the carry-over: at the end of day1 (start) and
at the beginning of the next day (end).
2024-04-19 13:12:46 +02:00
dfd74a455a Add getPaymentOptionIndexIfSpecialDay().
Add isSpecialDay(), isSpecialDay((), specialDayId(),
specialDay(), isSpecialDay(), specialDayId(), specialDay(),
isDayIncluded(), isDayIncludedAsSpecialDay() and isDayIncludedAsSpecialDay().
2024-04-19 13:09:53 +02:00
10828e0708 Add private mathods isParkingAllowedForWeekDay() and isParkingAllowedForSpecialDay().
Overload isParkingAllowed().
GetCostFromDuration(): add default parameter "int paymentOptionIndex=0"
2024-04-19 13:06:37 +02:00
2dbcc7018c start header for global defines 2024-04-19 13:04:36 +02:00
18ed85430d Minor: first commit 2024-04-18 08:52:15 +02:00
13 changed files with 1356 additions and 827 deletions

View File

@ -17,6 +17,16 @@ class Calculator {
mutable QVector<QList<int>> m_timeSteps; mutable QVector<QList<int>> m_timeSteps;
mutable QList<int> m_priceSteps; mutable QList<int> m_priceSteps;
CalcState isParkingAllowedForWeekDay(Configuration const *cfg,
QDateTime const &start,
int netto_parking_time,
int paymentOptionIndex);
CalcState isParkingAllowedForSpecialDay(Configuration const *cfg,
QDateTime const &start,
int netto_parking_time,
int paymentOptionIndex);
protected: protected:
explicit Calculator() = default; explicit Calculator() = default;
@ -44,7 +54,13 @@ public:
void ResetPriceSteps() { m_priceSteps.clear(); } void ResetPriceSteps() { m_priceSteps.clear(); }
QList<int> priceSteps() const { return m_priceSteps; } QList<int> priceSteps() const { return m_priceSteps; }
CalcState isParkingAllowed(Configuration const *cfg, QDateTime const &start); CalcState isParkingAllowed(Configuration const *cfg,
QDateTime const &start);
CalcState isParkingAllowed(Configuration const *cfg,
QDateTime const &start,
int netto_parking_time,
int paymentOptionIndex);
/// <summary> /// <summary>
/// Gets duration in seconds from cost /// Gets duration in seconds from cost
@ -96,8 +112,8 @@ public:
// testing public: // testing public:
// Introduced for PaymentMethod::Steps (e.g. Schoenau) // Introduced for PaymentMethod::Steps (e.g. Schoenau)
// For tariff of following structure: only steps, no special days, nonstop. // For tariff of following structure: only steps, no special days, nonstop.
uint32_t GetCostFromDuration(Configuration *cfg, QDateTime const &start, quint64 durationMinutes) const; uint32_t GetCostFromDuration(Configuration *cfg, QDateTime const &start, quint64 durationMinutes, int paymentOptionIndex=0) const;
uint32_t GetCostFromDuration(Configuration *cfg, QDateTime const &start, QDateTime const &end) const; uint32_t GetCostFromDuration(Configuration *cfg, QDateTime const &start, QDateTime const &end, int paymentOptionIndex=0) const;
private: private:
Ticket private_GetCostFromDuration(Configuration const* cfg, Ticket private_GetCostFromDuration(Configuration const* cfg,
@ -113,7 +129,7 @@ private:
int durationMinutes); int durationMinutes);
// //
uint32_t GetPriceForTimeStep(Configuration *cfg, int timeStep) const; uint32_t GetPriceForTimeStep(Configuration *cfg, int timeStep, int paymentOptionIndex=0) const;
uint32_t GetPriceForStep(Configuration *cfg, int step) const { uint32_t GetPriceForStep(Configuration *cfg, int step) const {
return GetPriceForTimeStep(cfg, step); return GetPriceForTimeStep(cfg, step);
} }

View File

@ -36,6 +36,9 @@ class Calculator;
class Configuration class Configuration
{ {
public: public:
using SpecialDaysType = std::multimap<int, ATBSpecialDays>;
using SpecialDaysWorktimeType = std::multimap<int, ATBSpecialDaysWorktime>;
ATBProject project; ATBProject project;
ATBCurrency Currency; ATBCurrency Currency;
ATBDuration duration; ATBDuration duration;
@ -43,8 +46,8 @@ public:
multimap<int, ATBDuration> Duration; multimap<int, ATBDuration> Duration;
multimap<int, ATBPaymentMethod> PaymentMethod; multimap<int, ATBPaymentMethod> PaymentMethod;
multimap<int, ATBPaymentRate> PaymentRate; multimap<int, ATBPaymentRate> PaymentRate;
multimap<int, ATBSpecialDaysWorktime> SpecialDaysWorktime; SpecialDaysWorktimeType SpecialDaysWorktime;
multimap<int, ATBSpecialDays> SpecialDays; SpecialDaysType SpecialDays;
multimap<int, ATBWeekDays> WeekDays; multimap<int, ATBWeekDays> WeekDays;
multimap<int, ATBPeriodYear> YearPeriod; multimap<int, ATBPeriodYear> YearPeriod;
multimap<int, ATBWeekDaysWorktime> WeekDaysWorktime; multimap<int, ATBWeekDaysWorktime> WeekDaysWorktime;
@ -67,8 +70,14 @@ public:
ATBPaymentOption const &getPaymentOptions(int paymentOptionsIndex=0) 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; int getPaymentOptionIndex(QDateTime const &dt) const;
bool isHoliday(QDateTime const &dt) const; int getPaymentOptionIndexIfSpecialDay(QDateTime const &dt) const;
bool isSpecialDay(QDateTime const &dt) const;
int specialDayId(QDateTime const &dt) const;
ATBSpecialDays specialDay(QDateTime const &dt) const;
bool isDayIncluded(uint64_t businessHours, QDateTime const &dt) const;
bool isDayIncludedAsSpecialDay(uint64_t businessHours, QDateTime const &dt) const;
bool isDayIncludedAsSpecialDay(uint64_t businessHours, int specialDayId) 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

@ -23,6 +23,8 @@ public:
pop_max_price = 0; pop_max_price = 0;
pop_carry_over = -1; pop_carry_over = -1;
pop_carry_over_time_range_id = -1; pop_carry_over_time_range_id = -1;
pop_carry_over_start_time_range = -1;
pop_carry_over_end_time_range = -1;
pop_daily_card_price = -1; pop_daily_card_price = -1;
pop_business_hours = -1; pop_business_hours = -1;
pop_time_step_config = -1; pop_time_step_config = -1;
@ -40,6 +42,8 @@ public:
double pop_max_price; double pop_max_price;
int pop_carry_over; int pop_carry_over;
int pop_carry_over_time_range_id; int pop_carry_over_time_range_id;
int pop_carry_over_start_time_range;
int pop_carry_over_end_time_range;
int pop_daily_card_price; int pop_daily_card_price;
uint64_t pop_business_hours; uint64_t pop_business_hours;
int pop_time_step_config; int pop_time_step_config;

View File

@ -4,10 +4,12 @@
class ATBSpecialDays class ATBSpecialDays
{ {
public: public:
explicit ATBSpecialDays() = default;
int ped_id; int ped_id;
std::string ped_label; std::string ped_label;
std::string ped_date_start; std::string ped_date_start;
std::string ped_date_end; std::string ped_date_end;
int ped_period_special_day_id; int ped_period_special_day_id;
int ped_payment_option_id;
int ped_year; int ped_year;
}; };

View File

@ -6,20 +6,23 @@
/// </summary> /// </summary>
/// ///
#define _MON_ (1ULL << 8) #include <Qt>
#define _TUE_ (1ULL << 9)
#define _WED_ (1ULL << 10) #define _NO_RESTRICTION_24_7_ (uint64_t)(0ULL)
#define _THU_ (1ULL << 11) #define _MON_ (uint64_t)(1ULL << 8)
#define _FRI_ (1ULL << 12) #define _TUE_ (uint64_t)(1ULL << 9)
#define _SAT_ (1ULL << 13) #define _WED_ (uint64_t)(1ULL << 10)
#define _SUN_ (1ULL << 14) #define _THU_ (uint64_t)(1ULL << 11)
#define _FRI_ (uint64_t)(1ULL << 12)
#define _SAT_ (uint64_t)(1ULL << 13)
#define _SUN_ (uint64_t)(1ULL << 14)
#define _WEEK_DAYS_ ((_MON_|_TUE_|_WED_|_THU_|_FRI_)) #define _WEEK_DAYS_ ((_MON_|_TUE_|_WED_|_THU_|_FRI_))
#define _WORKING_DAYS_ ((_MON_|_TUE_|_WED_|_THU_|_FRI_|_SAT_)) #define _WORKING_DAYS_ ((_MON_|_TUE_|_WED_|_THU_|_FRI_|_SAT_))
#define _ALL_DAYS_ ((_MON_|_TUE_|_WED_|_THU_|_FRI_|_SAT_|_SUN_)) #define _ALL_DAYS_ ((_MON_|_TUE_|_WED_|_THU_|_FRI_|_SAT_|_SUN_))
#define _OFFICIAL_HOLIDAY_ (1ULL << 15) #define _OFFICIAL_HOLIDAY_ (uint64_t)(1ULL << 15)
#define _ONLY_WEEKEND ((_SAT_|_SUN_)) #define _ONLY_WEEKEND_ ((_SAT_|_SUN_))
#define _ONLY_OPEN_FOR_BUSINESS_DAYS (1ULL << 16) /* verkaufsoffen */ #define _ONLY_OPEN_FOR_BUSINESS_DAYS_ (uint64_t)(1ULL << 16) /* verkaufsoffen */
#define _NOT_DEFINED (~0ULL) #define _NOT_DEFINED_ (uint64_t)(~0ULL)
enum BusinessHours : std::uint64_t enum BusinessHours : std::uint64_t
{ {
@ -37,7 +40,7 @@ enum BusinessHours : std::uint64_t
NoBusinessHoursDefined = 255, NoBusinessHoursDefined = 255,
// new 12.04.2024 // new 12.04.2024
NO_RESTRICTION_24_7 = 0, NO_RESTRICTION_24_7 = _NO_RESTRICTION_24_7_,
MON = _MON_, MON = _MON_,
TUE = _TUE_, TUE = _TUE_,
WED = _WED_, WED = _WED_,
@ -49,11 +52,26 @@ enum BusinessHours : std::uint64_t
WORKING_DAYS = _WORKING_DAYS_, WORKING_DAYS = _WORKING_DAYS_,
ALL_DAYS = _ALL_DAYS_, ALL_DAYS = _ALL_DAYS_,
OFFICIAL_HOLIDAY = _OFFICIAL_HOLIDAY_, OFFICIAL_HOLIDAY = _OFFICIAL_HOLIDAY_,
ONLY_WEEKEND = _ONLY_WEEKEND, ONLY_WEEKEND = _ONLY_WEEKEND_,
ONLY_OPEN_FOR_BUSINESS_DAYS = _ONLY_OPEN_FOR_BUSINESS_DAYS, ONLY_OPEN_FOR_BUSINESS_DAYS = _ONLY_OPEN_FOR_BUSINESS_DAYS_,
NOT_DEFINED = _NOT_DEFINED NOT_DEFINED = _NOT_DEFINED_
}; };
#if 0
static bool business(uint64_t businessHours, QDateTime &const dt) {
switch (dayOfWeek) {
case Qt::Monday:
(businessHours & _MON_) == _MON_;
case Qt::Tuesday:
case Qt::Wednesday:
case Qt::Thursday:
case Qt::Saturday:
case Qt::Sunday:
}
}
#endif
struct BusinessHours_struct { struct BusinessHours_struct {
BusinessHours bh; BusinessHours bh;
}; };

View File

@ -0,0 +1,6 @@
#ifndef TARIFF_GLOBAL_DEFINES_H_INCLUDED
#define TARIFF_GLOBAL_DEFINES_H_INCLUDED
#define DBG_HEADER "(" << __func__ << ":" << __LINE__ << ")"
#endif // TARIFF_GLOBAL_DEFINES_H_INCLUDED

View File

@ -15,6 +15,9 @@
using namespace std; using namespace std;
namespace Utilities { namespace Utilities {
bool isDayIncluded(uint64_t businessHours, QDateTime const &dt);
/// <summary> /// <summary>
/// Get day of week from current date (Zeller's Algorithm), starting day is Sunday /// Get day of week from current date (Zeller's Algorithm), starting day is Sunday
/// </summary> /// </summary>
@ -76,7 +79,9 @@ namespace Utilities {
double CalculatePricePerUnit(double pra_price, double durationUnit = -1); double CalculatePricePerUnit(double pra_price, double durationUnit = -1);
QTime SpecialDaysWorkTimeFrom(Configuration const *cfg, int specialDayId); QTime SpecialDaysWorkTimeFrom(Configuration const *cfg, int specialDayId);
QTime SpecialDaysWorkTimeFrom(Configuration::SpecialDaysWorktimeType::const_iterator it);
QTime SpecialDaysWorkTimeUntil(Configuration const *cfg, int specialDayId); QTime SpecialDaysWorkTimeUntil(Configuration const *cfg, int specialDayId);
QTime SpecialDaysWorkTimeUntil(Configuration::SpecialDaysWorktimeType::const_iterator it);
QTime WeekDaysWorkTimeFrom(std::multimap<int, ATBWeekDaysWorktime>::const_iterator itr); QTime WeekDaysWorkTimeFrom(std::multimap<int, ATBWeekDaysWorktime>::const_iterator itr);
QTime WeekDaysWorkTimeUntil(std::multimap<int, ATBWeekDaysWorktime>::const_iterator itr); QTime WeekDaysWorkTimeUntil(std::multimap<int, ATBWeekDaysWorktime>::const_iterator itr);
int WeekDayId(std::multimap<int, ATBWeekDaysWorktime>::const_iterator itr); int WeekDayId(std::multimap<int, ATBWeekDaysWorktime>::const_iterator itr);
@ -94,4 +99,5 @@ namespace Utilities {
BusinessHours getBusinessHours(Configuration const *cfg, PaymentMethod methodId); BusinessHours getBusinessHours(Configuration const *cfg, PaymentMethod methodId);
uint32_t computeWeekDaysPrice(Configuration const *cfg, PaymentMethod id); uint32_t computeWeekDaysPrice(Configuration const *cfg, PaymentMethod id);
double computeWeekDaysDurationUnit(Configuration const *cfg, PaymentMethod id); double computeWeekDaysDurationUnit(Configuration const *cfg, PaymentMethod id);
QStringList dumpBusinessHours(uint64_t businessHours);
} }

View File

@ -79,7 +79,8 @@ HEADERS += \
include/mobilisis/tariff_timebase.h \ include/mobilisis/tariff_timebase.h \
include/mobilisis/tariff_timestep_config.h \ include/mobilisis/tariff_timestep_config.h \
include/mobilisis/tariff_product.h \ include/mobilisis/tariff_product.h \
include/mobilisis/tariff_permit_type.h include/mobilisis/tariff_permit_type.h \
include/mobilisis/tariff_global_defines.h
OTHER_FILES += src/main.cpp \ OTHER_FILES += src/main.cpp \
../tariffs/tariff_korneuburg.json \ ../tariffs/tariff_korneuburg.json \

View File

@ -445,8 +445,11 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
bool prepaid) bool prepaid)
{ {
CalcState calcState; CalcState calcState;
double minMin = tariff->getPaymentOptions().pop_min_time;
double maxMin = tariff->getPaymentOptions().pop_max_time; int paymentOptionIndex = tariff->getPaymentOptionIndex(start_parking_time);
double minMin = tariff->getPaymentOptions(paymentOptionIndex).pop_min_time;
double maxMin = tariff->getPaymentOptions(paymentOptionIndex).pop_max_time;
// DEBUG // DEBUG
qCritical() << "compute_price_for_parking_ticket() " << endl qCritical() << "compute_price_for_parking_ticket() " << endl
@ -477,11 +480,13 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
double cost = -1; double cost = -1;
if (start_parking_time.isValid()) { if (start_parking_time.isValid()) {
if (tariff->getPaymentOptions().pop_payment_method_id == PaymentMethod::Steps) { if (tariff->getPaymentOptions().pop_payment_method_id == PaymentMethod::Steps) {
calcState = Calculator::GetInstance().isParkingAllowed(tariff, start_parking_time); // 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) { if (calcState.getStatus() == CalcState::State::OUTSIDE_ALLOWED_PARKING_TIME) {
return calcState; return calcState;
} }
cost = Calculator::GetInstance().GetCostFromDuration(tariff, start_parking_time, netto_parking_time); cost = Calculator::GetInstance().GetCostFromDuration(tariff, start_parking_time, netto_parking_time, paymentOptionIndex);
} else { } else {
cost = Calculator::GetInstance().GetCostFromDuration( cost = Calculator::GetInstance().GetCostFromDuration(
tariff, tariff,
@ -491,7 +496,7 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
netto_parking_time, // minutes, netto netto_parking_time, // minutes, netto
false, prepaid); false, prepaid);
} }
double minCost = tariff->getPaymentOptions().pop_min_price; double minCost = tariff->getPaymentOptions(paymentOptionIndex).pop_min_price;
if (cost < minCost) { if (cost < minCost) {
calcState.setDesc(QString("minCost=%1, cost=%2").arg(minCost, cost)); calcState.setDesc(QString("minCost=%1, cost=%2").arg(minCost, cost));
return calcState.set(CalcState::State::BELOW_MIN_PARKING_PRICE); return calcState.set(CalcState::State::BELOW_MIN_PARKING_PRICE);

View File

@ -4,6 +4,7 @@
#include "tariff_log.h" #include "tariff_log.h"
#include "tariff_time_range.h" #include "tariff_time_range.h"
#include "ticket.h" #include "ticket.h"
#include "tariff_global_defines.h"
#include <sstream> #include <sstream>
#include <algorithm> #include <algorithm>
@ -590,30 +591,283 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
uint32_t Calculator::GetCostFromDuration(Configuration *cfg, uint32_t Calculator::GetCostFromDuration(Configuration *cfg,
QDateTime const &start, QDateTime const &start,
quint64 timeStepInMinutes) const { quint64 timeStepInMinutes,
int paymentOptionIndex) const {
// for instance, a tariff as used in Schoenau, Koenigssee: only steps, no // for instance, a tariff as used in Schoenau, Koenigssee: only steps, no
// special days, nonstop. // special days, nonstop.
static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg); static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg);
if (paymentMethodId == PaymentMethod::Steps) { if (paymentMethodId == PaymentMethod::Steps) {
QDateTime const end = start.addSecs(timeStepInMinutes*60); QDateTime const end = start.addSecs(timeStepInMinutes*60);
return GetCostFromDuration(cfg, start, end); return GetCostFromDuration(cfg, start, end, paymentOptionIndex);
} }
return 0; return 0;
} }
uint32_t Calculator::GetCostFromDuration(Configuration * cfg, uint32_t Calculator::GetCostFromDuration(Configuration * cfg,
QDateTime const &start, QDateTime const &start,
QDateTime const &end) const { QDateTime const &end,
int paymentOptionIndex) const {
static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg); static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg);
if (paymentMethodId == PaymentMethod::Steps) { if (paymentMethodId == PaymentMethod::Steps) {
int const timeStepInMinutes = start.secsTo(end) / 60; int const timeStepInMinutes = start.secsTo(end) / 60;
return GetPriceForTimeStep(cfg, timeStepInMinutes); return GetPriceForTimeStep(cfg, timeStepInMinutes, paymentOptionIndex);
} }
return 0; return 0;
} }
CalcState Calculator::isParkingAllowedForWeekDay(Configuration const *cfg,
QDateTime const &start,
int netto_parking_time,
int paymentOptionIndex) {
CalcState Calculator::isParkingAllowed(Configuration const *cfg, QDateTime const &start) { qCritical() << DBG_HEADER << "start" << start.toString(Qt::ISODate)
<< "paymentOptionIndex" << paymentOptionIndex;
QString errorStr = "UNKNOWN ERROR";
PaymentMethod const paymentMethodId = Utilities::getPaymentMethodId(cfg);
if (paymentMethodId == PaymentMethod::Steps) {
uint64_t const businessHours = cfg->getPaymentOptions(paymentOptionIndex).pop_business_hours;
if (cfg->isDayIncluded(businessHours, start)) {
if (businessHours == BusinessHours::NO_RESTRICTION_24_7) {
return CalcState(CalcState::State::SUCCESS, "PARKING_ALLOWED",
QTime(0, 0, 0), QTime(23, 59, 59));
}
int const weekdayId = start.date().dayOfWeek();
if (cfg->WeekDaysWorktime.count(weekdayId) > 0) {
using WTIterator = std::multimap<int, ATBWeekDaysWorktime>::const_iterator;
std::pair<WTIterator, WTIterator> p = cfg->WeekDaysWorktime.equal_range(weekdayId);
for (WTIterator itr = p.first; itr != p.second; ++itr) {
QTime const &from = Utilities::WeekDaysWorkTimeFrom(itr);
QTime const &until = Utilities::WeekDaysWorkTimeUntil(itr);
qCritical() << DBG_HEADER
<< "CHECK IF PARKING IS ALLOWED IN TIME-RANGE ("
<< from.toString(Qt::ISODate) << "->" << until.toString(Qt::ISODate) << ") ...";
QTime const &startTime = start.time();
if (startTime >= from && startTime <= until) {
QTime const endTime = start.addSecs(netto_parking_time*60).time();
if (endTime <= until) {
return CalcState(CalcState::State::SUCCESS, "PARKING_ALLOWED", from, until);
} else {
errorStr = QString("%1 startTime not in range (%2 not in [%3, %4))")
.arg(__LINE__)
.arg(startTime.toString(Qt::ISODate))
.arg(from.toString(Qt::ISODate))
.arg(endTime.toString(Qt::ISODate));
}
} else {
errorStr = QString("%1 startTime not in range (%2 not in [%3, %4))")
.arg(__LINE__)
.arg(startTime.toString(Qt::ISODate))
.arg(from.toString(Qt::ISODate))
.arg(until.toString(Qt::ISODate));
}
int const pop_carry_over = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over;
if (pop_carry_over == 1) {
qCritical() << DBG_HEADER
<< "NO. CHECK IF PARKING IS ALLOWED WITH CARRY-OVER ...";
int const pop_carry_over_start_time_range = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over_start_time_range;
int const pop_carry_over_end_time_range = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over_end_time_range;
if (cfg->TimeRange.count(pop_carry_over_start_time_range) == 1 &&
cfg->TimeRange.count(pop_carry_over_end_time_range) == 1) {
ATBTimeRange s = cfg->TimeRange.find(pop_carry_over_start_time_range)->second;
ATBTimeRange e = cfg->TimeRange.find(pop_carry_over_end_time_range)->second;
if (startTime >= s.getTimeFrom() && startTime <= s.getTimeUntil()) {
QDateTime sd = start;
sd.setTime(s.getTimeUntil());
QDateTime ed = start.addDays(1);
ed.setTime(e.getTimeFrom());
int const jumpSecs = sd.secsTo(ed);
QDateTime const end = start.addSecs(netto_parking_time*60 + jumpSecs);
if (end.time() <= e.getTimeUntil()) {
qCritical() << DBG_HEADER
<< "PARKING IS ALLOWED WITH CARRY-OVER ("
<< start.toString(Qt::ISODate) << "->" << ed.toString(Qt::ISODate) << ")";
return CalcState(CalcState::State::SUCCESS, "PARKING_ALLOWED",
startTime, end.time());
} else {
errorStr = QString("endTime %1 exceeds [%2, %3))")
.arg(end.toString(Qt::ISODate))
.arg(sd.toString(Qt::ISODate))
.arg(ed.toString(Qt::ISODate));
}
} else {
errorStr = QString("startTime %1 exceeds [%2, %3))")
.arg(startTime.toString(Qt::ISODate))
.arg(s.getTimeFrom().toString(Qt::ISODate))
.arg(s.getTimeUntil().toString(Qt::ISODate));
}
} else {
errorStr = "no carry-over limits configured";
}
} else {
errorStr = "no carry-over configured";
}
}
} else {
errorStr = QString("no weekday configured for day-id %1").arg(weekdayId);
}
} else {
errorStr = QString("start %1 not contained in business hours %2")
.arg(start.toString(Qt::ISODate))
.arg(businessHours);
}
}
return CalcState(CalcState::State::OUTSIDE_ALLOWED_PARKING_TIME, errorStr,
QTime(), QTime());
}
CalcState Calculator::isParkingAllowedForSpecialDay(Configuration const *cfg,
QDateTime const &start,
int netto_parking_time,
int paymentOptionIndex) {
QString errorStr = "UNKNOWN ERROR";
qCritical() << DBG_HEADER << "start" << start.toString(Qt::ISODate)
<< "paymentOptionIndex" << paymentOptionIndex;
PaymentMethod const paymentMethodId = Utilities::getPaymentMethodId(cfg);
if (paymentMethodId == PaymentMethod::Steps) {
//uint64_t const businessHours = cfg->getPaymentOptions(paymentOptionIndex).pop_business_hours;
int const specialDayId = cfg->specialDayId(start);
if ((specialDayId > 0) && (cfg->SpecialDaysWorktime.count(specialDayId) > 0)) {
using SDIterator = Configuration::SpecialDaysWorktimeType::const_iterator;
std::pair<SDIterator, SDIterator> p = cfg->SpecialDaysWorktime.equal_range(specialDayId);
for (SDIterator it = p.first; it != p.second; ++it) {
QTime const &from = Utilities::SpecialDaysWorkTimeFrom(it);
QTime const &until = Utilities::SpecialDaysWorkTimeUntil(it);
qCritical() << DBG_HEADER
<< "CHECK IF PARKING IS ALLOWED IN TIME-RANGE ("
<< from.toString(Qt::ISODate) << "->" << until.toString(Qt::ISODate) << ") ...";
QTime const &startTime = start.time();
if (startTime >= from && startTime <= until) {
QTime const endTime = start.addSecs(netto_parking_time*60).time();
if (endTime <= until) {
return CalcState(CalcState::State::SUCCESS, "PARKING_ALLOWED", from, until);
} else {
errorStr = QString("%1 startTime not in range (%2 not in [%3, %4))")
.arg(__LINE__)
.arg(startTime.toString(Qt::ISODate))
.arg(from.toString(Qt::ISODate))
.arg(endTime.toString(Qt::ISODate));
}
} else {
errorStr = QString("%1 startTime not in range (%2 not in [%3, %4))")
.arg(__LINE__)
.arg(startTime.toString(Qt::ISODate))
.arg(from.toString(Qt::ISODate))
.arg(until.toString(Qt::ISODate));
}
int const pop_carry_over = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over;
if (pop_carry_over == 1) {
qCritical() << DBG_HEADER << "NO. CHECK IF PARKING IS ALLOWED WITH CARRY-OVER ...";
int const pop_carry_over_start_time_range = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over_start_time_range;
int const pop_carry_over_end_time_range = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over_end_time_range;
if (cfg->TimeRange.count(pop_carry_over_start_time_range) == 1 &&
cfg->TimeRange.count(pop_carry_over_end_time_range) == 1) {
ATBTimeRange s = cfg->TimeRange.find(pop_carry_over_start_time_range)->second;
ATBTimeRange e = cfg->TimeRange.find(pop_carry_over_end_time_range)->second;
if (startTime >= s.getTimeFrom() && startTime <= s.getTimeUntil()) {
QDateTime sd = start;
sd.setTime(s.getTimeUntil());
QDateTime ed = start.addDays(1);
ed.setTime(e.getTimeFrom());
int const jumpSecs = sd.secsTo(ed);
QDateTime const end = start.addSecs(netto_parking_time*60 + jumpSecs);
if (end.time() <= e.getTimeUntil()) {
ed.setTime(e.getTimeUntil()); // for printing
qCritical() << DBG_HEADER
<< "PARKING IS ALLOWED WITH CARRY-OVER ("
<< start.toString(Qt::ISODate) << "->" << ed.toString(Qt::ISODate) << ")";
return CalcState(CalcState::State::SUCCESS, "PARKING_ALLOWED",
startTime, end.time());
} else {
ed.setTime(e.getTimeUntil()); // for printing
errorStr = QString("endTime %1 exceeds [%2, %3))")
.arg(end.toString(Qt::ISODate))
.arg(sd.toString(Qt::ISODate))
.arg(ed.toString(Qt::ISODate));
}
} else {
errorStr = QString("startTime %1 exceeds [%2, %3))")
.arg(startTime.toString(Qt::ISODate))
.arg(s.getTimeFrom().toString(Qt::ISODate))
.arg(s.getTimeUntil().toString(Qt::ISODate));
}
} else {
errorStr = "no carry-over limits configured";
}
} else {
errorStr = "no carry-over configured";
}
}
}
}
return CalcState(CalcState::State::OUTSIDE_ALLOWED_PARKING_TIME, errorStr,
QTime(), QTime());
}
CalcState Calculator::isParkingAllowed(Configuration const *cfg,
QDateTime const &start,
int netto_parking_time,
int paymentOptionIndex) {
qCritical() << DBG_HEADER << "CHECK IF PARKING IS ALLOWED AT"
<< start.toString(Qt::ISODate) << "...";
CalcState cs;
if ((cs = isParkingAllowedForWeekDay(cfg, start, netto_parking_time, paymentOptionIndex))) {
return cs;
}
qCritical() << DBG_HEADER << QString(cs);
if ((cs = isParkingAllowedForSpecialDay(cfg, start, netto_parking_time, paymentOptionIndex))) {
return cs;
}
qCritical() << DBG_HEADER << QString(cs);
return CalcState(CalcState::State::OUTSIDE_ALLOWED_PARKING_TIME, "UNKNOWN ERROR",
QTime(), QTime());
}
CalcState Calculator::isParkingAllowed(Configuration const *cfg,
QDateTime const &start) {
static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg); static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg);
if (paymentMethodId == PaymentMethod::Steps) { if (paymentMethodId == PaymentMethod::Steps) {
@ -1686,9 +1940,9 @@ QList<int> Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex)
return m_timeSteps[paymentOptionIndex]; return m_timeSteps[paymentOptionIndex];
} }
uint32_t Calculator::GetPriceForTimeStep(Configuration *cfg, int timeStep) const { uint32_t Calculator::GetPriceForTimeStep(Configuration *cfg, int timeStep, int paymentOptionIndex) const {
int const pop_id = cfg->getPaymentOptions().pop_id; int const pop_id = cfg->getPaymentOptions(paymentOptionIndex).pop_id;
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)
{ {

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
#include "utilities.h" #include "utilities.h"
#include "tariff_log.h" #include "tariff_log.h"
#include "tariff_business_hours.h"
#include <QDebug> #include <QDebug>
#include <algorithm> #include <algorithm>
@ -333,6 +334,14 @@ QTime Utilities::SpecialDaysWorkTimeFrom(Configuration const *cfg, int specialDa
return QTime::fromString(cfg->SpecialDaysWorktime.find(specialDayId)->second.pedwt_time_from.c_str(), Qt::ISODate); return QTime::fromString(cfg->SpecialDaysWorktime.find(specialDayId)->second.pedwt_time_from.c_str(), Qt::ISODate);
} }
QTime Utilities::SpecialDaysWorkTimeFrom(Configuration::SpecialDaysWorktimeType::const_iterator it) {
return QTime::fromString(it->second.pedwt_time_from.c_str(), Qt::ISODate);
}
QTime Utilities::SpecialDaysWorkTimeUntil(Configuration::SpecialDaysWorktimeType::const_iterator it) {
return QTime::fromString(it->second.pedwt_time_to.c_str(), Qt::ISODate);
}
QTime Utilities::SpecialDaysWorkTimeUntil(Configuration const *cfg, int specialDayId) { QTime Utilities::SpecialDaysWorkTimeUntil(Configuration const *cfg, int specialDayId) {
return QTime::fromString(cfg->SpecialDaysWorktime.find(specialDayId)->second.pedwt_time_to.c_str(), Qt::ISODate); return QTime::fromString(cfg->SpecialDaysWorktime.find(specialDayId)->second.pedwt_time_to.c_str(), Qt::ISODate);
} }
@ -420,10 +429,10 @@ uint32_t Utilities::getFirstDurationStep(Configuration const *cfg, PaymentMethod
} }
BusinessHours Utilities::getBusinessHours(Configuration const *cfg, PaymentMethod methodId) { BusinessHours Utilities::getBusinessHours(Configuration const *cfg, PaymentMethod methodId) {
int businessHours = cfg->PaymentOption.find(methodId)->second.pop_business_hours; uint64_t businessHours = cfg->PaymentOption.find(methodId)->second.pop_business_hours;
switch (businessHours) { switch (businessHours) {
case NoRestriction_24_7: return BusinessHours::NoRestriction_24_7; //case NoRestriction_24_7: return BusinessHours::NoRestriction_24_7;
case OnlyWorkingDays: return BusinessHours::OnlyWorkingDays; case OnlyWorkingDays: return BusinessHours::OnlyWorkingDays;
case OnlyWeekDays: return BusinessHours::OnlyWeekDays; case OnlyWeekDays: return BusinessHours::OnlyWeekDays;
case OnlyWeekEnd: return BusinessHours::OnlyWeekEnd; case OnlyWeekEnd: return BusinessHours::OnlyWeekEnd;
@ -433,6 +442,21 @@ BusinessHours Utilities::getBusinessHours(Configuration const *cfg, PaymentMetho
case SpecialAndSchoolHolidays: return BusinessHours::SpecialAndSchoolHolidays; case SpecialAndSchoolHolidays: return BusinessHours::SpecialAndSchoolHolidays;
case OnlyOpenForBusinessDays: return BusinessHours::OnlyOpenForBusinessDays; case OnlyOpenForBusinessDays: return BusinessHours::OnlyOpenForBusinessDays;
case AllDaysWithRestrictedHours: return BusinessHours::AllDaysWithRestrictedHours; case AllDaysWithRestrictedHours: return BusinessHours::AllDaysWithRestrictedHours;
case _NO_RESTRICTION_24_7_: return BusinessHours::NO_RESTRICTION_24_7;
case _MON_: return BusinessHours::MON;
case _TUE_: return BusinessHours::TUE;
case _WED_: return BusinessHours::WED;
case _THU_: return BusinessHours::THU;
case _FRI_: return BusinessHours::FRI;
case _SAT_: return BusinessHours::SAT;
case _SUN_: return BusinessHours::SUN;
case _WEEK_DAYS_: return BusinessHours::WEEK_DAYS;
case _WORKING_DAYS_: return BusinessHours::WORKING_DAYS;
case _ALL_DAYS_: return BusinessHours::ALL_DAYS;
case _OFFICIAL_HOLIDAY_: return BusinessHours::OFFICIAL_HOLIDAY;
case _ONLY_WEEKEND_: return BusinessHours::ONLY_WEEKEND;
case _ONLY_OPEN_FOR_BUSINESS_DAYS_: return BusinessHours::ONLY_OPEN_FOR_BUSINESS_DAYS;
case _NOT_DEFINED_: return BusinessHours::NOT_DEFINED;
} }
return BusinessHours::NoBusinessHoursDefined; return BusinessHours::NoBusinessHoursDefined;
} }
@ -447,3 +471,82 @@ double Utilities::computeWeekDaysDurationUnit(Configuration const *cfg, PaymentM
int durationId = cfg->PaymentRate.find(pop_id)->second.pra_payment_unit_id; int durationId = cfg->PaymentRate.find(pop_id)->second.pra_payment_unit_id;
return (double)(cfg->Duration.find(durationId)->second.pun_duration); return (double)(cfg->Duration.find(durationId)->second.pun_duration);
} }
bool Utilities::isDayIncluded(uint64_t businessHours, QDateTime const &dt) {
int dayOfWeek = dt.date().dayOfWeek();
switch (dayOfWeek) {
case Qt::Monday:
return ((businessHours & BusinessHours::MON) == BusinessHours::MON);
case Qt::Tuesday:
return ((businessHours & BusinessHours::TUE) == BusinessHours::TUE);
case Qt::Wednesday:
return ((businessHours & BusinessHours::WED) == BusinessHours::WED);
case Qt::Thursday:
return ((businessHours & BusinessHours::THU) == BusinessHours::THU);
case Qt::Friday:
return ((businessHours & BusinessHours::FRI) == BusinessHours::FRI);
case Qt::Saturday:
return ((businessHours & BusinessHours::SAT) == BusinessHours::SAT);
case Qt::Sunday:
return ((businessHours & BusinessHours::SUN) == BusinessHours::SUN);
default:;
}
return false;
}
QStringList Utilities::dumpBusinessHours(uint64_t businessHours) {
QStringList s;
if ((businessHours & BusinessHours::MON) == BusinessHours::MON) {
if ((businessHours & BusinessHours::OFFICIAL_HOLIDAY) == BusinessHours::OFFICIAL_HOLIDAY) {
s << "MON (Holiday)";
} else {
s << "MON";
}
}
if ((businessHours & BusinessHours::TUE) == BusinessHours::TUE) {
if ((businessHours & BusinessHours::OFFICIAL_HOLIDAY) == BusinessHours::OFFICIAL_HOLIDAY) {
s << "TUE (Holiday)";
} else {
s << "TUE";
}
}
if ((businessHours & BusinessHours::WED) == BusinessHours::WED) {
if ((businessHours & BusinessHours::OFFICIAL_HOLIDAY) == BusinessHours::OFFICIAL_HOLIDAY) {
s << "WED (Holiday)";
} else {
s << "WED";
}
}
if ((businessHours & BusinessHours::THU) == BusinessHours::THU) {
if ((businessHours & BusinessHours::OFFICIAL_HOLIDAY) == BusinessHours::OFFICIAL_HOLIDAY) {
s << "THU (Holiday)";
} else {
s << "THU";
}
}
if ((businessHours & BusinessHours::FRI) == BusinessHours::FRI) {
if ((businessHours & BusinessHours::OFFICIAL_HOLIDAY) == BusinessHours::OFFICIAL_HOLIDAY) {
s << "FRI (Holiday)";
} else {
s << "FRI";
}
}
if ((businessHours & BusinessHours::SAT) == BusinessHours::SAT) {
if ((businessHours & BusinessHours::OFFICIAL_HOLIDAY) == BusinessHours::OFFICIAL_HOLIDAY) {
s << "SAT (Holiday)";
} else {
s << "SAT";
}
}
if ((businessHours & BusinessHours::SUN) == BusinessHours::SUN) {
if ((businessHours & BusinessHours::OFFICIAL_HOLIDAY) == BusinessHours::OFFICIAL_HOLIDAY) {
s << "SUN (Holiday)";
} else {
s << "SUN";
}
}
return s;
}

View File

@ -41,9 +41,9 @@ extern "C" char* strptime(const char* s,
#define NEUHAUSER_NORDISCHES_AUSBILDUNGSZENTRUM (0) #define NEUHAUSER_NORDISCHES_AUSBILDUNGSZENTRUM (0)
#define NEUHAUSER_BILEXA_GALTUER (0) #define NEUHAUSER_BILEXA_GALTUER (0)
#define NEUHAUSER_KIRCHDORF (0) #define NEUHAUSER_KIRCHDORF (0)
#define BAD_NEUENAHR_AHRWEILER (0) #define BAD_NEUENAHR_AHRWEILER (1)
#define NEUHAUSER_CHRISTOPH_REISEN (0) #define NEUHAUSER_CHRISTOPH_REISEN (0)
#define NEUHAUSER_PERNEGG_AN_DER_MUR (1) #define NEUHAUSER_PERNEGG_AN_DER_MUR (0)
int main() { int main() {
#if NEUHAUSER_PERNEGG_AN_DER_MUR==1 #if NEUHAUSER_PERNEGG_AN_DER_MUR==1
@ -408,29 +408,59 @@ int main() {
} }
#endif #endif
bool fail;
QDateTime start;
QDateTime start(QDate(2024, 4, 14), QTime()); for (int i=0; i < 4; ++i) {
QDateTime end; switch (i) {
struct price_t price; case 0:
start = QDateTime(QDate(2024, 5, 1), QTime(16, 0, 0)); // holiday
fail = false;
break;
case 1:
start = QDateTime(QDate(2024, 4, 21), QTime(16, 0, 0)); // sunday
fail = false;
break;
case 2:
start = QDateTime(QDate(2024, 4, 22), QTime(8, 0, 0)); // monday
fail = false;
break;
case 3:
start = QDateTime(QDate(2024, 4, 22), QTime(17, 30, 0)); // monday
fail = true;
break;
default:;
}
//start = QDateTime::currentDateTime(); QDateTime end;
struct price_t price;
int paymentOptionIndex = cfg.getCurrentPaymentOptionIndex(start); //start = QDateTime::currentDateTime();
if (paymentOptionIndex != -1) { QList<int> timeSteps;
qCritical() << "paymentOptionIndex" << paymentOptionIndex;
QList<int> const timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg, paymentOptionIndex);
qCritical() << "TimeSteps" << timeSteps;
// QDateTime start = s.addSecs(offset * 60); int paymentOptionIndex = cfg.getPaymentOptionIndex(start);
if (paymentOptionIndex != -1) {
qCritical() << "paymentOptionIndex" << paymentOptionIndex;
timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg, paymentOptionIndex);
qCritical() << "TimeSteps" << timeSteps;
QList<int>::const_iterator step; QList<int>::const_iterator step;
for (step = timeSteps.cbegin(); step != timeSteps.cend(); ++step) { for (step = timeSteps.cbegin(); step != timeSteps.cend(); ++step) {
double cost = 0; double cost = 0;
CalcState cs;
//if (compute_price_for_parking_ticket(&cfg, start, *step, end, &price)) { if ((cs = compute_price_for_parking_ticket(&cfg, start, *step, end, &price))) {
// cost = price.netto; cost = price.netto;
//} qCritical() << "step" << *step << ": cost" << cost;
} else {
if (fail == false) {
qCritical() << "<<<ERROR>>> cs =" << QString(cs);
}
}
}
} else {
qCritical() << "ERROR paymentOptionIndex =" << paymentOptionIndex;
} }
} }
} }