Compare commits

...

36 Commits

Author SHA1 Message Date
b70094abb5 Extend compute_product_price() for use of PERMIT_TYPE::DAY_TICKET.
First time used for Neuhauder-Pernegg-an-der-Mur.
2024-04-16 12:10:34 +02:00
aa15d1c126 Add default-parameters to compute_product_price():
start [in]: currentDateTime(): start date-time for daily-ticket-price computation.
startProduct, endProduct: real start- and end-date/time for daily-ticket.
Used first time for Neuhauser-Pernegg-an-der-Mur (747).
2024-04-16 12:07:18 +02:00
cd159f2bbd Add case for BusinessHours::NoRestriction_24_7: used for Neuhauder-Christoph-Reisen 2024-04-16 12:05:55 +02:00
475487c2ce Minor: add utility getProductPrice() 2024-04-16 12:03:42 +02:00
8ff5b8e2b5 Added test-cases for Neuhauser-Christoph-Reisen (746) and Neuhauser-Pernegg-an-der-Mur (747) 2024-04-16 12:01:36 +02:00
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
aba38d2614 compute_price_for_parking_ticket(): add handling for PaymentMethod::Steps. 2024-04-08 13:58:24 +02:00
57d6b85f52 get_maximal_parking_price(): add handling for PaymentMethod::Steps. 2024-04-08 13:57:40 +02:00
4f9c0422fc Start test case for Bad Neuenahr 2024-04-08 13:53:29 +02:00
a5b95d71b8 CalcState: Add setStatus()/getStatus() 2024-04-08 13:52:53 +02:00
fcbc8dcdc3 Merge branch 'neuhauser-kirchdorf' of https://git.mimbach49.de/GerhardHoffmann/MOBILISIS-Calculator into neuhauser-kirchdorf 2024-03-07 08:19:26 +01:00
ed99bae725 Use Calculator::getInstance() 2024-03-07 08:18:40 +01:00
627d14204d Use paymentRate.last() instead of aymentRate.at(0) so we can enter new entries
in tariff-files to provide the prices for an hour.
2024-03-07 08:17:32 +01:00
d8a4c4eaa7 Merge branch 'neuhauser-kirchdorf' of git.mimbach49.de:GerhardHoffmann/MOBILISIS-Calculator into neuhauser-kirchdorf 2024-02-29 09:30:22 +01:00
4f45db4fde revised tests for Neuhauser/Linsinger Maschinenbau (744) 2024-02-28 12:06:43 +01:00
a744a1ebb3 compute_product_price(): add handling for FOOD_STAMP 2024-02-28 12:06:02 +01:00
df16bd7f9c GetDailyTicketPrice(): add case for FOOD_STAMP (not implemented) 2024-02-28 12:05:14 +01:00
b751ba339e Add permit type FOOD_STAMP 2024-02-28 12:03:13 +01:00
588a88455b CalcState: add toString() method 2024-02-28 11:31:28 +01:00
92bfdced6a Merge branch 'neuhauser-kirchdorf' of git.mimbach49.de:GerhardHoffmann/MOBILISIS-Calculator into neuhauser-kirchdorf 2024-02-28 10:04:09 +01:00
8bbec596c9 Check for 08:00 <= currentTime <= 20:00 removed:
assumption is prepaid.
2024-02-28 09:58:00 +01:00
87b14ee3f8 Added check for NEUHAUSER_NORDISCHES_AUSBILDUNGSZENTRUM:
08:00 <= currentTime <= 20:00.
2024-02-28 09:26:51 +01:00
3ad2c77467 Adapted tests for NEUHAUSER_NORDISCHES_AUSBILDUNGSZENTRUM 2024-02-28 09:26:05 +01:00
493d94aaa1 Add re-check 2024-02-27 17:30:15 +01:00
7831329b11 kirchdorf: getDurationFromCost(): to be tested 2024-02-27 17:11:00 +01:00
abbbd06f93 GetCostFromDuration(): re-implement cpmputation for paymentMethod==progressive
(e.g. neuhauser/kirchdorf (743))
2024-02-27 12:25:13 +01:00
ac6e45a913 test cases for neuhauser-kirchdorf 2024-02-27 12:23:52 +01:00
12 changed files with 1527 additions and 525 deletions

View File

@@ -84,6 +84,51 @@ struct CALCULATE_LIBRARY_API CalcState {
return (m_status == State::SUCCESS); return (m_status == State::SUCCESS);
} }
QString toString() {
QString s;
switch (m_status) {
case State::SUCCESS:
s = "SUCCESS";
break;
case State::ERROR_PARSING_ZONE_NR:
s = "ERROR_PARSING_ZONE_NR";
break;
case State::ERROR_LOADING_TARIFF:
s = "ERROR_LOADING_TARIFF";
break;
case State::ERROR_PARSING_TARIFF:
s = "ERROR_PARSING_TARIFF";
break;
case State::NEGATIVE_PARING_TIME:
s = "NEGATIVE_PARKING_TIME";
break;
case State::ABOVE_MAX_PARKING_TIME:
s = "ABOVE_MAX_PARKING_TIME";
break;
case State::WRONG_PARAM_VALUES:
s = "WRONG_PARAM_VALUES";
break;
case State::BELOW_MIN_PARKING_TIME:
s = "BELOW_MIN_PARKING_TIME";
break;
case State::BELOW_MIN_PARKING_PRICE:
s = "BELOW_MIN_PARKING_PRICE";
break;
case State::OVERPAID:
s = "OVERPAID";
break;
case State::INVALID_START_DATE:
s = "INVALID_START_DATE";
break;
case State::WRONG_ISO_TIME_FORMAT:
s = "WRONG_ISO_TIME_FORMAT";
break;
case State::OUTSIDE_ALLOWED_PARKING_TIME:
s = "OUTSIDE_ALLOWED_PARKING_TIME";
}
return s + ":" + m_desc;
}
explicit operator QString () const noexcept { explicit operator QString () const noexcept {
QString s; QString s;
switch (m_status) { switch (m_status) {
@@ -130,6 +175,8 @@ struct CALCULATE_LIBRARY_API CalcState {
} }
CalcState &set(State s) { m_status = s; return *this; } CalcState &set(State s) { m_status = s; return *this; }
CalcState &setStatus(State s) { return set(s); }
State getStatus() const { return m_status; }
CalcState &setDesc(QString s) { m_desc = s; return *this; } CalcState &setDesc(QString s) { m_desc = s; return *this; }
void setAllowedTimeRange(QTime const &from, QTime const &until) { void setAllowedTimeRange(QTime const &from, QTime const &until) {
@@ -149,11 +196,28 @@ 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,
QDateTime const &start = QDateTime::currentDateTime(),
QDateTime *productStart = nullptr,
QDateTime *productEnd = nullptr);
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

@@ -11,6 +11,7 @@ enum class PERMIT_TYPE : quint8 {
DAY_TICKET_ADULT, DAY_TICKET_ADULT,
DAY_TICKET_TEEN, DAY_TICKET_TEEN,
DAY_TICKET_CHILD, DAY_TICKET_CHILD,
FOOD_STAMP,
INVALID INVALID
}; };
@@ -41,6 +42,9 @@ struct PermitType {
case 6: case 6:
m_permitType = PERMIT_TYPE::DAY_TICKET_CHILD; m_permitType = PERMIT_TYPE::DAY_TICKET_CHILD;
break; break;
case 7:
m_permitType = PERMIT_TYPE::FOOD_STAMP;
break;
default: default:
m_permitType = PERMIT_TYPE::INVALID; m_permitType = PERMIT_TYPE::INVALID;
} }
@@ -52,7 +56,7 @@ struct PermitType {
operator PERMIT_TYPE() const { return m_permitType; } operator PERMIT_TYPE() const { return m_permitType; }
operator int() const { operator int () const {
switch(m_permitType) { switch(m_permitType) {
case PERMIT_TYPE::SHORT_TERM_PARKING: case PERMIT_TYPE::SHORT_TERM_PARKING:
return 0; return 0;
@@ -68,6 +72,8 @@ struct PermitType {
return 5; return 5;
case PERMIT_TYPE::DAY_TICKET_TEEN: case PERMIT_TYPE::DAY_TICKET_TEEN:
return 6; return 6;
case PERMIT_TYPE::FOOD_STAMP:
return 7;
default: default:
break; break;
} }
@@ -75,7 +81,7 @@ struct PermitType {
} }
operator QString() const { operator QString () {
switch(m_permitType) { switch(m_permitType) {
case PERMIT_TYPE::DAY_TICKET: case PERMIT_TYPE::DAY_TICKET:
return QString("DAY_TICKET"); return QString("DAY_TICKET");
@@ -91,6 +97,32 @@ struct PermitType {
return QString("SZEGED_START"); return QString("SZEGED_START");
case PERMIT_TYPE::SZEGED_STOP: case PERMIT_TYPE::SZEGED_STOP:
return QString("SZEGED_STOP"); return QString("SZEGED_STOP");
case PERMIT_TYPE::FOOD_STAMP:
return QString("FOOD_STAMP");
default:
break;
}
return QString("INVALID");
}
operator QString () const {
switch(m_permitType) {
case PERMIT_TYPE::DAY_TICKET:
return QString("DAY_TICKET");
case PERMIT_TYPE::DAY_TICKET_ADULT:
return QString("DAY_TICKET_ADULT");
case PERMIT_TYPE::DAY_TICKET_CHILD:
return QString("DAY_TICKET_CHILD");
case PERMIT_TYPE::DAY_TICKET_TEEN:
return QString("DAY_TICKET_TEEN");
case PERMIT_TYPE::SHORT_TERM_PARKING:
return QString("SHORT_TERM_PARKING");
case PERMIT_TYPE::SZEGED_START:
return QString("SZEGED_START");
case PERMIT_TYPE::SZEGED_STOP:
return QString("SZEGED_STOP");
case PERMIT_TYPE::FOOD_STAMP:
return QString("FOOD_STAMP");
default: default:
break; break;
} }

View File

@@ -45,6 +45,8 @@ struct ATBTariffProduct {
return false; return false;
} }
uint32_t getProductPrice() const { return m_tariff_product_price; }
friend QDebug operator<<(QDebug debug, ATBTariffProduct const &product) { friend QDebug operator<<(QDebug debug, ATBTariffProduct const &product) {
QDebugStateSaver saver(debug); QDebugStateSaver saver(debug);

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;
@@ -76,7 +82,11 @@ int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg, PERMIT_TY
return minPrice; return minPrice;
} }
int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg, PERMIT_TYPE permitType) { int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg,
PERMIT_TYPE permitType,
QDateTime const &start,
QDateTime *productStart,
QDateTime *productEnd) {
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)
@@ -85,6 +95,8 @@ int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg, PERMIT
// [[fallthrough]]; // [[fallthrough]];
case PERMIT_TYPE::DAY_TICKET_TEEN: case PERMIT_TYPE::DAY_TICKET_TEEN:
// [[fallthrough]]; // [[fallthrough]];
case PERMIT_TYPE::FOOD_STAMP:
// [[fallthrough]];
case PERMIT_TYPE::DAY_TICKET_ADULT: { case PERMIT_TYPE::DAY_TICKET_ADULT: {
std::optional<QVector<ATBTariffProduct>> products = cfg->getTariffProductForProductId(permitType); std::optional<QVector<ATBTariffProduct>> products = cfg->getTariffProductForProductId(permitType);
if (products) { if (products) {
@@ -92,7 +104,56 @@ int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg, PERMIT
if (product.size() > 0) { if (product.size() > 0) {
ATBTariffProduct const &p = product[0]; ATBTariffProduct const &p = product[0];
return p.m_tariff_product_price; return p.m_tariff_product_price;
#if 0
// in case we do not have prepaid-option
QTime const &currentTime = QDateTime::currentDateTime().time();
if (p.m_tariff_product_start <= currentTime && currentTime <= p.m_tariff_product_end) {
return p.m_tariff_product_price;
} else {
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "ERROR currentTime"
<< currentTime.toString(Qt::ISODate)
<< "INVALID ("
<< p.m_tariff_product_start.toString(Qt::ISODate)
<< p.m_tariff_product_end.toString(Qt::ISODate) << ")";
} }
#endif
}
}
} break;
case PERMIT_TYPE::INVALID:
// [[fallthrough]];
case PERMIT_TYPE::DAY_TICKET: {
std::optional<QVector<ATBTariffProduct>> products = cfg->getTariffProductForProductId(permitType);
if (products) {
QVector<ATBTariffProduct> product = products.value();
int product_price = 0;
if (productStart && productEnd) {
*productStart = start;
*productEnd = start;
if (product.size() > 0) {
productStart->setTime(product[0].getTimeStart());
productEnd->setTime(product[0].getTimeEnd());
}
}
for (QVector<ATBTariffProduct>::size_type i=0; i<product.size(); ++i) {
ATBTariffProduct const &p = product[i];
QTime const &startTime = p.getTimeStart();
QTime const &endTime = p.getTimeEnd();
if (start.time() >= startTime && start.time() < endTime) {
product_price = p.getProductPrice();
if (productStart && productEnd) {
productStart->setTime(startTime);
productEnd->setTime(endTime);
}
}
}
return product_price;
} }
} break; } break;
default: default:
@@ -102,22 +163,24 @@ 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);
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)
if (paymentMethodId == PaymentMethod::Progressive) { 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();
if (paymentRate.size() > 0) { if (paymentRate.size() > 0) {
int const price = paymentRate.at(0).pra_price; // price is given per hour int const price = paymentRate.last().pra_price; // price is given per hour
maxPrice = qRound((maxTime * price) / 60.0f); maxPrice = qRound((maxTime * price) / 60.0f);
} }
} }
@@ -411,14 +474,23 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
return calcState.set(CalcState::State::SUCCESS); return calcState.set(CalcState::State::SUCCESS);
} }
double cost = -1;
if (start_parking_time.isValid()) { if (start_parking_time.isValid()) {
double cost = Calculator::GetInstance().GetCostFromDuration( if (tariff->getPaymentOptions().pop_payment_method_id == PaymentMethod::Steps) {
calcState = Calculator::GetInstance().isParkingAllowed(tariff, start_parking_time);
if (calcState.getStatus() == CalcState::State::OUTSIDE_ALLOWED_PARKING_TIME) {
return calcState;
}
cost = Calculator::GetInstance().GetCostFromDuration(tariff, start_parking_time, netto_parking_time);
} else {
cost = Calculator::GetInstance().GetCostFromDuration(
tariff, tariff,
tariff->getPaymentOptions().pop_payment_method_id, tariff->getPaymentOptions().pop_payment_method_id,
start_parking_time, // starting time start_parking_time, // starting time
end_parking_time, // return value: end time end_parking_time, // return value: end time
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().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));
@@ -428,8 +500,10 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
// DEBUG // DEBUG
qCritical() << " -> calculated cost (price->netto) = " << cost; qCritical() << " -> calculated cost (price->netto) = " << cost;
price->brutto = price->vat = price->vat_percentage = 0;
price->units = cost; price->units = cost;
price->netto = cost; price->netto = cost;
} else { } else {
return calcState.set(CalcState::State::INVALID_START_DATE); return calcState.set(CalcState::State::INVALID_START_DATE);
} }

View File

@@ -181,6 +181,13 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
int durationMinutes = Utilities::getMaximalParkingTime(cfg, paymentMethodId); int durationMinutes = Utilities::getMaximalParkingTime(cfg, paymentMethodId);
int durationMinutesBrutto = 0; int durationMinutesBrutto = 0;
#ifdef _DEBUG_
#undef _DEBUG_
#endif
//#define _DEBUG_ 1
#define _DEBUG_ 0
QDateTime current = start; QDateTime current = start;
int days = 7; int days = 7;
@@ -229,26 +236,61 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
uint price = 0; uint price = 0;
if (carryOverNotSet) { if (carryOverNotSet) {
int range = 0;
int minsToCarryOver = 0; // from one work-time to the other on the same day int minsToCarryOver = 0; // from one work-time to the other on the same day
int minsUsed = 0; int minsUsed = 0;
QDateTime lastCurrent = QDateTime(); QDateTime lastCurrent = QDateTime();
auto timeRangeIt = cfg->TimeRange.cbegin(); QVector<ATBWeekDaysWorktime> weekDayWorkTimeRanges;
for (; timeRangeIt != cfg->TimeRange.cend(); ++timeRangeIt) {
using WTIterator = std::multimap<int, ATBWeekDaysWorktime>::const_iterator; using WTIterator = std::multimap<int, ATBWeekDaysWorktime>::const_iterator;
std::pair<WTIterator, WTIterator> p = cfg->WeekDaysWorktime.equal_range(weekdayId); std::pair<WTIterator, WTIterator> p = cfg->WeekDaysWorktime.equal_range(weekdayId);
for (WTIterator itr = p.first; itr != p.second; ++itr) { for (WTIterator itr = p.first; itr != p.second; ++itr) {
++range; weekDayWorkTimeRanges.append(itr->second); // working with vector is easier
}
QTime const &from = Utilities::WeekDaysWorkTimeFrom(itr); int weekDayWorkTimeIndex = 0;
QTime const &to = Utilities::WeekDaysWorkTimeUntil(itr); bool moveToNextTimeRange = false;
// time ranges for Neuhauser-Kirchdorf (743): 30, 5, 5, ... 5
auto timeRangeIt = cfg->TimeRange.cbegin();
while (timeRangeIt != cfg->TimeRange.cend()) { // ; ++timeRangeIt) {
if (weekDayWorkTimeIndex >= weekDayWorkTimeRanges.size()) {
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
<< "weekDayWorkTimeRanges.size()" << weekDayWorkTimeRanges.size()
<< "price" << price;
#endif
end_datetime = current;
return end_datetime.toString(Qt::ISODate).toStdString();
}
QTime const &from = QTime::fromString(weekDayWorkTimeRanges[weekDayWorkTimeIndex].pwd_time_from.c_str(), Qt::ISODate);
QTime const &to = QTime::fromString(weekDayWorkTimeRanges[weekDayWorkTimeIndex].pwd_time_to.c_str(), Qt::ISODate);
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "current" << current.toString(Qt::ISODate)
<< "from" << from.toString(Qt::ISODate)
<< "to" << to.toString(Qt::ISODate);
#endif
Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES"); Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES");
if (current.time() >= to) { if (current.time() >= to) {
continue; // try to use next available work-time ++weekDayWorkTimeIndex;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "try to use next available work-time with"
<< "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
<< "price" << price;
#endif
// time range is not affected
continue;
} else } else
if (current.time() <= from) { if (current.time() <= from) {
if (prepaid) { if (prepaid) {
@@ -258,13 +300,20 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
uint const minutesMoved = lastCurrent.secsTo(current) / 60; uint const minutesMoved = lastCurrent.secsTo(current) / 60;
durationMinutesBrutto += minutesMoved; durationMinutesBrutto += minutesMoved;
if (range == 1) { #if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "lastCurrent" << lastCurrent.toString(Qt::ISODate)
<< "current" << current.toString(Qt::ISODate)
<< "minutesMoved" << minutesMoved
<< "durationMinutesBrutto" << durationMinutesBrutto;
#endif
if (weekDayWorkTimeIndex == 0) {
start_datetime = current; start_datetime = current;
} }
} }
} }
while (timeRangeIt != cfg->TimeRange.cend()) {
ATBTimeRange timeRange = timeRangeIt->second; ATBTimeRange timeRange = timeRangeIt->second;
timeRange.computeQTimes(current.time()); timeRange.computeQTimes(current.time());
@@ -272,20 +321,64 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
int duration = timeRange.time_range_to_in_minutes_from_start - int duration = timeRange.time_range_to_in_minutes_from_start -
timeRange.time_range_from_in_minutes_from_start; timeRange.time_range_from_in_minutes_from_start;
if (minsUsed > 0) { #if _DEBUG_==1
duration -= minsUsed; qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
minsUsed = 0; << "current" << current.toString(Qt::ISODate)
<< "duration" << duration
<< "minsUsed" << minsUsed
<< "minsToCarryOver" << minsToCarryOver
<< "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
<< "price" << price;
#endif
if (minsToCarryOver > 0) { // the price for this time range
// has been is paid already
Q_ASSERT_X(weekDayWorkTimeIndex > 0, __func__, "WRONG-WORK-TIME");
current = current.addSecs(minsToCarryOver*60);
durationMinutes -= minsToCarryOver;
durationMinutesNetto += minsToCarryOver;
durationMinutesBrutto += minsToCarryOver;
minsToCarryOver = 0;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "current" << current.toString(Qt::ISODate)
<< "duration" << duration
<< "durationMinutes" << durationMinutes
<< "durationMinutesNetto" << durationMinutesNetto
<< "durationMinutesBrutto" << durationMinutesBrutto
<< "price" << price;
#endif
if (price >= cost) {
end_datetime = current;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "end_datetime" << end_datetime.toString(Qt::ISODate)
<< "price" << price;
#endif
return end_datetime.toString(Qt::ISODate).toStdString();
}
} }
if (current.addSecs(duration * 60).time() <= to) { if (current.addSecs(duration * 60).time() <= to) {
if (minsToCarryOver > 0) { // the price for this time range
// has been is paid already #if _DEBUG_==1
durationMinutes -= duration; qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
durationMinutesNetto += duration; << "current" << current.toString(Qt::ISODate)
durationMinutesBrutto += duration; << "current.addSecs(" << duration * 60 << ")" << current.addSecs(duration*60).time().toString(Qt::ISODate)
current = current.addSecs(duration*60); << "duration" << duration
minsToCarryOver = 0; << "to" << to.toString(Qt::ISODate)
} else { << "minsUsed" << minsUsed
<< "minsToCarryOver" << minsToCarryOver
<< "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
<< "durationMinutes" << durationMinutes;
#endif
moveToNextTimeRange = false;
for(const auto &x: cfg->PaymentRate) { for(const auto &x: cfg->PaymentRate) {
ATBPaymentRate const rate = x.second; ATBPaymentRate const rate = x.second;
if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) { if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) {
@@ -303,37 +396,106 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
if (price >= cost) { if (price >= cost) {
end_datetime = current; end_datetime = current;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "end_datetime" << end_datetime.toString(Qt::ISODate)
<< "price" << price;
#endif
return end_datetime.toString(Qt::ISODate).toStdString(); return end_datetime.toString(Qt::ISODate).toStdString();
} }
// price has been updated; use next time range
moveToNextTimeRange = true;
break; break;
} }
} }
}
if (durationMinutes <= 0) { #if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "current" << current.toString(Qt::ISODate)
<< "duration" << duration
<< "to" << to.toString(Qt::ISODate)
<< "price" << price
<< "minsToCarryOver" << minsToCarryOver
<< "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
<< "durationMinutes" << durationMinutes
<< "durationMinutesNetto" << durationMinutesNetto
<< "durationMinutesBrutto" << durationMinutesBrutto;
#endif
if (price >= cost) {
end_datetime = current; end_datetime = current;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "end_datetime" << end_datetime.toString(Qt::ISODate)
<< "price" << price;
#endif
return end_datetime.toString(Qt::ISODate).toStdString(); return end_datetime.toString(Qt::ISODate).toStdString();
} }
++timeRangeIt; if (moveToNextTimeRange) {
if (++timeRangeIt != cfg->TimeRange.cend()) {
continue;
}
}
} else { // havin a new time range means that we always have a new
// work-time-range
// ++timeRangeIt;
} else { // current.addSecs(duration * 60).time() > to
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "current" << current.toString(Qt::ISODate)
<< "current.addSecs(" << duration * 60 << ")" << current.addSecs(duration*60).time().toString(Qt::ISODate)
<< "duration" << duration
<< ", to:" << to.toString(Qt::ISODate);
#endif
lastCurrent = current; lastCurrent = current;
current.setTime(to); current.setTime(to);
minsUsed = lastCurrent.secsTo(current) / 60; minsUsed = lastCurrent.secsTo(current) / 60;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "lastCurrent" << lastCurrent.toString(Qt::ISODate)
<< "current" << current.toString(Qt::ISODate)
<< "duration" << duration
<< "to" << to.toString(Qt::ISODate)
<< "minsUsed" << minsUsed
<< "minsToCarryOver" << minsToCarryOver
<< "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
<< "durationMinutes" << durationMinutes;
#endif
// mod duration: possibly discard some minutes in // mod duration: possibly discard some minutes in
// the next time-range // the next time-range
if (durationMinutes >= minsUsed) { if (duration >= minsUsed) {
minsToCarryOver = durationMinutes - minsUsed; minsToCarryOver = duration - minsUsed;
} }
durationMinutes -= minsUsed; durationMinutes -= minsUsed;
durationMinutesNetto += minsUsed; durationMinutesNetto += minsUsed;
durationMinutesBrutto += minsUsed; durationMinutesBrutto += minsUsed;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "lastCurrent" << lastCurrent.toString(Qt::ISODate)
<< "current" << current.toString(Qt::ISODate)
<< "duration" << duration
<< "to" << to.toString(Qt::ISODate)
<< "minsUsed" << minsUsed
<< "minsToCarryOver" << minsToCarryOver
<< "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
<< "durationMinutes" << durationMinutes
<< "price" << price;
#endif
moveToNextTimeRange = false;
if (minsUsed > 0) { if (minsUsed > 0) {
for(const auto &x: cfg->PaymentRate) { for(const auto &x: cfg->PaymentRate) {
ATBPaymentRate const rate = x.second; ATBPaymentRate const rate = x.second;
@@ -346,22 +508,68 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
if (price >= cost) { if (price >= cost) {
end_datetime = current; end_datetime = current;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "end_datetime" << end_datetime.toString(Qt::ISODate)
<< "price" << price;
#endif
// return end_datetime.toString(Qt::ISODate).toStdString(); // return end_datetime.toString(Qt::ISODate).toStdString();
} }
break;
} // price has been updated; use next time range
} moveToNextTimeRange = true;
}
break; break;
} }
} }
} }
end_datetime = start.addSecs(durationMinutesBrutto * 60); #if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "current" << current.toString(Qt::ISODate)
<< "duration" << duration
<< "minsUsed" << minsUsed
<< "durationMinutes" << durationMinutes
<< "moveToNextTimeRange" << moveToNextTimeRange
<< "price" << price;
#endif
if (moveToNextTimeRange) {
if (++timeRangeIt != cfg->TimeRange.cend()) {
continue;
}
// no valid time range left
end_datetime = current;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "end_datetime" << end_datetime.toString(Qt::ISODate)
<< "price" << price;
#endif
return end_datetime.toString(Qt::ISODate).toStdString(); return end_datetime.toString(Qt::ISODate).toStdString();
} }
} }
end_datetime = start.addSecs(durationMinutesBrutto * 60);
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "start" << start.toString(Qt::ISODate)
<< "end_datetime" << end_datetime.toString(Qt::ISODate)
<< "final price" << std::max(price, minParkingPrice);
#endif
return end_datetime.toString(Qt::ISODate).toStdString();
} // while (timeRangeIt != cfg->TimeRange.cend()) {
}
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "INVALID END TIME";
#endif
end_datetime = QDateTime(); end_datetime = QDateTime();
return end_datetime.toString(Qt::ISODate).toStdString(); return end_datetime.toString(Qt::ISODate).toStdString();
} }
@@ -373,6 +581,7 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
// TODO: im fehlerfall // TODO: im fehlerfall
return t.getValidUntil().toString(Qt::ISODate).toStdString(); return t.getValidUntil().toString(Qt::ISODate).toStdString();
} }
#undef _DEBUG_
/////////////////////////////////////// ///////////////////////////////////////
@@ -410,6 +619,10 @@ CalcState Calculator::isParkingAllowed(Configuration const *cfg, QDateTime const
if (paymentMethodId == PaymentMethod::Steps) { if (paymentMethodId == PaymentMethod::Steps) {
int const weekdayId = start.date().dayOfWeek(); int const weekdayId = start.date().dayOfWeek();
BusinessHours businessHours = Utilities::getBusinessHours(cfg, paymentMethodId); BusinessHours businessHours = Utilities::getBusinessHours(cfg, paymentMethodId);
if (businessHours == BusinessHours::NoRestriction_24_7) {
return CalcState(CalcState::State::SUCCESS, "PARKING_ALLOWED",
QTime(0, 0, 0), QTime(23, 59, 59));
} else
if (businessHours == BusinessHours::OnlyWeekDays) { if (businessHours == BusinessHours::OnlyWeekDays) {
if (weekdayId != (int)Qt::Saturday && weekdayId != (int)Qt::Sunday) { // e.g. Neuhauser, Linsinger Maschinenbau (741) if (weekdayId != (int)Qt::Saturday && weekdayId != (int)Qt::Sunday) { // e.g. Neuhauser, Linsinger Maschinenbau (741)
if (cfg->WeekDaysWorktime.count(weekdayId) > 0) { if (cfg->WeekDaysWorktime.count(weekdayId) > 0) {
@@ -522,6 +735,13 @@ double Calculator::GetCostFromDuration(Configuration* cfg,
int weekdayIdLast = -1; int weekdayIdLast = -1;
int durationMinutesBrutto = 0; int durationMinutesBrutto = 0;
#ifdef _DEBUG_
#undef _DEBUG_
#endif
//#define _DEBUG_ 1
#define _DEBUG_ 0
QDateTime current = start; QDateTime current = start;
int days = 7; int days = 7;
@@ -571,26 +791,60 @@ double Calculator::GetCostFromDuration(Configuration* cfg,
uint price = 0; uint price = 0;
if (carryOverNotSet) { if (carryOverNotSet) {
int range = 0;
int minsToCarryOver = 0; // from one work-time to the other on the same day int minsToCarryOver = 0; // from one work-time to the other on the same day
int minsUsed = 0; int minsUsed = 0;
QDateTime lastCurrent = QDateTime(); QDateTime lastCurrent = QDateTime();
auto timeRangeIt = cfg->TimeRange.cbegin(); QVector<ATBWeekDaysWorktime> weekDayWorkTimeRanges;
for (; timeRangeIt != cfg->TimeRange.cend(); ++timeRangeIt) {
using WTIterator = std::multimap<int, ATBWeekDaysWorktime>::const_iterator; using WTIterator = std::multimap<int, ATBWeekDaysWorktime>::const_iterator;
std::pair<WTIterator, WTIterator> p = cfg->WeekDaysWorktime.equal_range(weekdayId); std::pair<WTIterator, WTIterator> p = cfg->WeekDaysWorktime.equal_range(weekdayId);
for (WTIterator itr = p.first; itr != p.second; ++itr) { for (WTIterator itr = p.first; itr != p.second; ++itr) {
++range; weekDayWorkTimeRanges.append(itr->second); // working with vector is easier
}
QTime const &from = Utilities::WeekDaysWorkTimeFrom(itr); int weekDayWorkTimeIndex = 0;
QTime const &to = Utilities::WeekDaysWorkTimeUntil(itr); bool moveToNextTimeRange = false;
// time ranges for Neuhauser-Kirchdorf (743): 30, 5, 5, ... 5
auto timeRangeIt = cfg->TimeRange.cbegin();
while (timeRangeIt != cfg->TimeRange.cend()) { // ; ++timeRangeIt) {
if (weekDayWorkTimeIndex >= weekDayWorkTimeRanges.size()) {
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
<< "weekDayWorkTimeRanges.size()" << weekDayWorkTimeRanges.size();
#endif
end_datetime = current;
return price;
}
QTime const &from = QTime::fromString(weekDayWorkTimeRanges[weekDayWorkTimeIndex].pwd_time_from.c_str(), Qt::ISODate);
QTime const &to = QTime::fromString(weekDayWorkTimeRanges[weekDayWorkTimeIndex].pwd_time_to.c_str(), Qt::ISODate);
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "current" << current.toString(Qt::ISODate)
<< "from" << from.toString(Qt::ISODate)
<< "to" << to.toString(Qt::ISODate);
#endif
Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES"); Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES");
if (current.time() >= to) { if (current.time() >= to) {
continue; // try to use next available work-time ++weekDayWorkTimeIndex;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "try to use next available work-time with"
<< "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
<< "price" << price;
#endif
// time range is not affected
continue;
} else } else
if (current.time() <= from) { if (current.time() <= from) {
if (prepaid) { if (prepaid) {
@@ -600,13 +854,20 @@ double Calculator::GetCostFromDuration(Configuration* cfg,
uint const minutesMoved = lastCurrent.secsTo(current) / 60; uint const minutesMoved = lastCurrent.secsTo(current) / 60;
durationMinutesBrutto += minutesMoved; durationMinutesBrutto += minutesMoved;
if (range == 1) { #if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "lastCurrent" << lastCurrent.toString(Qt::ISODate)
<< "current" << current.toString(Qt::ISODate)
<< "minutesMoved" << minutesMoved
<< "durationMinutesBrutto" << durationMinutesBrutto;
#endif
if (weekDayWorkTimeIndex == 0) {
start_datetime = current; start_datetime = current;
} }
} }
} }
while (timeRangeIt != cfg->TimeRange.cend()) {
ATBTimeRange timeRange = timeRangeIt->second; ATBTimeRange timeRange = timeRangeIt->second;
timeRange.computeQTimes(current.time()); timeRange.computeQTimes(current.time());
@@ -614,49 +875,64 @@ double Calculator::GetCostFromDuration(Configuration* cfg,
int duration = timeRange.time_range_to_in_minutes_from_start - int duration = timeRange.time_range_to_in_minutes_from_start -
timeRange.time_range_from_in_minutes_from_start; timeRange.time_range_from_in_minutes_from_start;
qCritical() << __func__ << ":" << __LINE__ #if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "current" << current.toString(Qt::ISODate) << "current" << current.toString(Qt::ISODate)
<< "duration" << duration << "duration" << duration
<< "minsUsed" << minsUsed << "minsUsed" << minsUsed
<< "minsToCarryOver" << minsToCarryOver; << "minsToCarryOver" << minsToCarryOver
<< "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
<< "price" << price;
#endif
//if (minsUsed > 0) {
// duration -= minsUsed;
// minsUsed = 0;
//}
if (current.addSecs(duration * 60).time() <= to) {
if (minsToCarryOver > 0) { // the price for this time range if (minsToCarryOver > 0) { // the price for this time range
// has been is paid already // has been is paid already
if (minsUsed == 0) { Q_ASSERT_X(weekDayWorkTimeIndex > 0, __func__, "WRONG-WORK-TIME");
for(const auto &x: cfg->PaymentRate) {
ATBPaymentRate const rate = x.second;
if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) {
price += (uint)rate.pra_price;
durationMinutes -= duration; current = current.addSecs(minsToCarryOver*60);
durationMinutesNetto += duration;
durationMinutesBrutto += duration;
current = current.addSecs(duration * 60); durationMinutes -= minsToCarryOver;
durationMinutesNetto += minsToCarryOver;
durationMinutesBrutto += minsToCarryOver;
if (durationMinutes <= 0) {
end_datetime = current;
return price;
}
break;
}
}
} else {
durationMinutes -= duration;
durationMinutesNetto += duration;
durationMinutesBrutto += duration;
current = current.addSecs(duration*60);
minsToCarryOver = 0; minsToCarryOver = 0;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "current" << current.toString(Qt::ISODate)
<< "duration" << duration
<< "durationMinutes" << durationMinutes
<< "durationMinutesNetto" << durationMinutesNetto
<< "durationMinutesBrutto" << durationMinutesBrutto;
#endif
if (durationMinutes <= 0) {
end_datetime = current;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "end_datetime" << end_datetime.toString(Qt::ISODate)
<< "price" << price;
#endif
return price;
} }
} else { }
if (current.addSecs(duration * 60).time() <= to) {
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "current" << current.toString(Qt::ISODate)
<< "current.addSecs(" << duration * 60 << ")" << current.addSecs(duration*60).time().toString(Qt::ISODate)
<< "duration" << duration
<< "to" << to.toString(Qt::ISODate)
<< "minsUsed" << minsUsed
<< "minsToCarryOver" << minsToCarryOver
<< "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
<< "durationMinutes" << durationMinutes;
#endif
moveToNextTimeRange = false;
for(const auto &x: cfg->PaymentRate) { for(const auto &x: cfg->PaymentRate) {
ATBPaymentRate const rate = x.second; ATBPaymentRate const rate = x.second;
if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) { if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) {
@@ -667,53 +943,157 @@ double Calculator::GetCostFromDuration(Configuration* cfg,
durationMinutesBrutto += duration; durationMinutesBrutto += duration;
current = current.addSecs(duration * 60); current = current.addSecs(duration * 60);
// price has been updated; use next time range
moveToNextTimeRange = true;
break; break;
} }
} }
}
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "current" << current.toString(Qt::ISODate)
<< "duration" << duration
<< "to" << to.toString(Qt::ISODate)
<< "price" << price
<< "minsToCarryOver" << minsToCarryOver
<< "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
<< "durationMinutes" << durationMinutes
<< "durationMinutesNetto" << durationMinutesNetto
<< "durationMinutesBrutto" << durationMinutesBrutto;
#endif
if (durationMinutes <= 0) { if (durationMinutes <= 0) {
end_datetime = current; end_datetime = current;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "end_datetime" << end_datetime.toString(Qt::ISODate)
<< "price" << price;
#endif
return price; return price;
} }
++timeRangeIt; if (moveToNextTimeRange) {
if (++timeRangeIt != cfg->TimeRange.cend()) {
continue;
}
}
} else { // havin a new time range means that we always have a new
// work-time-range
// ++timeRangeIt;
} else { // current.addSecs(duration * 60).time() > to
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "current" << current.toString(Qt::ISODate)
<< "current.addSecs(" << duration * 60 << ")" << current.addSecs(duration*60).time().toString(Qt::ISODate)
<< "duration" << duration
<< ", to:" << to.toString(Qt::ISODate);
#endif
lastCurrent = current; lastCurrent = current;
current.setTime(to); current.setTime(to);
minsUsed = lastCurrent.secsTo(current) / 60; minsUsed = lastCurrent.secsTo(current) / 60;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "lastCurrent" << lastCurrent.toString(Qt::ISODate)
<< "current" << current.toString(Qt::ISODate)
<< "duration" << duration
<< "to" << to.toString(Qt::ISODate)
<< "minsUsed" << minsUsed
<< "minsToCarryOver" << minsToCarryOver
<< "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
<< "durationMinutes" << durationMinutes;
#endif
// mod duration: possibly discard some minutes in // mod duration: possibly discard some minutes in
// the next time-range // the next time-range
if (durationMinutes >= minsUsed) { if (duration >= minsUsed) {
minsToCarryOver = durationMinutes - minsUsed; minsToCarryOver = duration - minsUsed;
} }
durationMinutes -= minsUsed; durationMinutes -= minsUsed;
durationMinutesNetto += minsUsed; durationMinutesNetto += minsUsed;
durationMinutesBrutto += minsUsed; durationMinutesBrutto += minsUsed;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "lastCurrent" << lastCurrent.toString(Qt::ISODate)
<< "current" << current.toString(Qt::ISODate)
<< "duration" << duration
<< "to" << to.toString(Qt::ISODate)
<< "minsUsed" << minsUsed
<< "minsToCarryOver" << minsToCarryOver
<< "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
<< "durationMinutes" << durationMinutes
<< "price" << price;
#endif
moveToNextTimeRange = false;
if (minsUsed > 0) { if (minsUsed > 0) {
for(const auto &x: cfg->PaymentRate) { for(const auto &x: cfg->PaymentRate) {
ATBPaymentRate const rate = x.second; ATBPaymentRate const rate = x.second;
if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) { if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) {
price += (uint)rate.pra_price; price += (uint)rate.pra_price;
// price has been updated; use next time range
moveToNextTimeRange = true;
break; break;
} }
} }
} }
break;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "current" << current.toString(Qt::ISODate)
<< "duration" << duration
<< "minsUsed" << minsUsed
<< "durationMinutes" << durationMinutes
<< "moveToNextTimeRange" << moveToNextTimeRange
<< "price" << price;
#endif
if (moveToNextTimeRange) {
if (++timeRangeIt != cfg->TimeRange.cend()) {
continue;
} }
// no valid time range left
end_datetime = current;
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "end_datetime" << end_datetime.toString(Qt::ISODate)
<< "price" << price;
#endif
return price;
} }
} }
end_datetime = start.addSecs(durationMinutesBrutto * 60); end_datetime = start.addSecs(durationMinutesBrutto * 60);
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "start" << start.toString(Qt::ISODate)
<< "end_datetime" << end_datetime.toString(Qt::ISODate)
<< "final price" << std::max(price, minParkingPrice);
#endif
return std::max(price, minParkingPrice); return std::max(price, minParkingPrice);
} } // while (timeRangeIt != cfg->TimeRange.cend()) {
} }
#if _DEBUG_==1
qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "INVALID END TIME";
#endif
end_datetime = QDateTime(); end_datetime = QDateTime();
return 0; return 0;
} }
@@ -1193,24 +1573,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";
@@ -1219,13 +1601,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;
@@ -1249,19 +1631,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);
@@ -1282,19 +1664,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 {
@@ -1360,6 +1749,9 @@ Calculator::GetDailyTicketPrice(Configuration* cfg,
if (dailyTickets) { if (dailyTickets) {
QVector<ATBDailyTicket> const tickets = dailyTickets.value(); QVector<ATBDailyTicket> const tickets = dailyTickets.value();
switch (permitType) { switch (permitType) {
case PERMIT_TYPE::FOOD_STAMP: {
// TODO
} break;
case PERMIT_TYPE::DAY_TICKET_ADULT: { case PERMIT_TYPE::DAY_TICKET_ADULT: {
std::optional<ATBCustomer> c = cfg->getCustomerForType(ATBCustomer::CustomerType::ADULT); std::optional<ATBCustomer> c = cfg->getCustomerForType(ATBCustomer::CustomerType::ADULT);
if (c) { if (c) {

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

@@ -34,134 +34,413 @@ extern "C" char* strptime(const char* s,
#include "calculator_functions.h" #include "calculator_functions.h"
#include "calculate_price.h" #include "calculate_price.h"
#define SZEGED (1) #define SZEGED (0)
#define SCHOENAU_KOENIGSEE (0) #define SCHOENAU_KOENIGSEE (0)
#define NEUHAUSER_KORNEUBURG (0) #define NEUHAUSER_KORNEUBURG (0)
#define NEUHAUSER_LINSINGER_MASCHINENBAU (0) #define NEUHAUSER_LINSINGER_MASCHINENBAU (0)
#define NEUHAUSER_NORDISCHES_AUSBILDUNGSZENTRUM (0) #define NEUHAUSER_NORDISCHES_AUSBILDUNGSZENTRUM (0)
#define NEUHAUSER_BILEXA_GALTUER (0) #define NEUHAUSER_BILEXA_GALTUER (0)
#define NEUHAUSER_KIRCHDORF (1) #define NEUHAUSER_KIRCHDORF (0)
#define BAD_NEUENAHR_AHRWEILER (0)
#if NEUHAUSER_KIRCHDORF==1 #define NEUHAUSER_CHRISTOPH_REISEN (0)
static bool test_neuhauser_kirchdorf(int step, double cost) { #define NEUHAUSER_PERNEGG_AN_DER_MUR (1)
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 NEUHAUSER_PERNEGG_AN_DER_MUR==1
std::ifstream input;
int pop_min_time;
int pop_max_time;
int pop_min_price;
int pop_max_price;
int pop_daily_card_price;
input.open("/opt/ptu5/opt/customer_747/etc/psa_tariff/tariff01.json");
std::stringstream sstr;
while(input >> sstr.rdbuf());
std::string json(sstr.str());
Configuration cfg;
bool isParsed = cfg.ParseJson(&cfg, json.c_str());
cout << endl;
if (isParsed) {
pop_min_time = get_minimal_parkingtime(&cfg);
pop_max_time = get_maximal_parkingtime(&cfg);
pop_min_price = get_minimal_parkingprice(&cfg);
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_max_time: " << pop_max_time;
qCritical() << " pop_min_price: " << pop_min_price;
qCritical() << " pop_max_price: " << pop_max_price;
qCritical() << "pop_daily_card_price: " << pop_daily_card_price;
int price;
QDateTime productStart;
QDateTime productEnd;
QDateTime start = QDateTime::currentDateTime();
start.setTime(QTime(0, 0, 0));
price = compute_product_price(&cfg, PERMIT_TYPE::DAY_TICKET, start);
qCritical() << QString("price (%1) :").arg(start.time().toString(Qt::ISODate)) << price;
start.setTime(QTime(6, 0, 0));
productStart = productEnd = QDateTime();
price = compute_product_price(&cfg, PERMIT_TYPE::DAY_TICKET, start, &productStart, &productEnd);
qCritical() << QString("price (%1-%2) :")
.arg(productStart.time().toString(Qt::ISODate))
.arg(productEnd.time().toString(Qt::ISODate))
<< price;
start.setTime(QTime(15, 0, 0));
productStart = productEnd = QDateTime();
price = compute_product_price(&cfg, PERMIT_TYPE::DAY_TICKET, start, &productStart, &productEnd);
qCritical() << QString("price (%1-%2) :")
.arg(productStart.time().toString(Qt::ISODate))
.arg(productEnd.time().toString(Qt::ISODate))
<< price;
start.setTime(QTime(16, 0, 0));
productStart = productEnd = QDateTime();
price = compute_product_price(&cfg, PERMIT_TYPE::DAY_TICKET, start, &productStart, &productEnd);
qCritical() << QString("price (%1-%2) :")
.arg(productStart.time().toString(Qt::ISODate))
.arg(productEnd.time().toString(Qt::ISODate))
<< price;
start.setTime(QTime(17, 0, 0));
productStart = productEnd = QDateTime();
price = compute_product_price(&cfg, PERMIT_TYPE::INVALID, start, &productStart, &productEnd);
qCritical() << QString("price (%1-%2) :")
.arg(productStart.time().toString(Qt::ISODate))
.arg(productEnd.time().toString(Qt::ISODate))
<< price;
}
#endif
#if NEUHAUSER_CHRISTOPH_REISEN==1
std::ifstream input;
int pop_min_time;
int pop_max_time;
int pop_min_price;
int pop_max_price;
int pop_daily_card_price;
input.open("/opt/ptu5/opt/customer_746/etc/psa_tariff/tariff01.json");
std::stringstream sstr;
while(input >> sstr.rdbuf());
std::string json(sstr.str());
Configuration cfg;
bool isParsed = cfg.ParseJson(&cfg, json.c_str());
cout << endl;
if (isParsed) {
pop_min_time = get_minimal_parkingtime(&cfg);
pop_max_time = get_maximal_parkingtime(&cfg);
pop_min_price = get_minimal_parkingprice(&cfg);
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_max_time: " << pop_max_time;
qCritical() << " pop_min_price: " << pop_min_price;
qCritical() << " pop_max_price: " << pop_max_price;
qCritical() << "pop_daily_card_price: " << pop_daily_card_price;
static QList<int> stepsConfigured
= QList(std::initializer_list<int>{
360, 420, 1440, 2880, 4320, 5400, 7440});
QList<int> timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg);
qCritical() << "TimeSteps" << timeSteps;
if (stepsConfigured != timeSteps) {
qCritical() << "TIME-STEPS SHOULD BE" << stepsConfigured;
return -1;
}
stepsConfigured.push_front(360); // for test run
stepsConfigured.push_back(7440);
#if 0
static const int Down = 0;
static const int Up = 1;
for (int i = 0, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) {
int nextTimeStep = compute_next_timestep(&cfg, timeSteps.at(i), Up);
if (nextTimeStep != stepsConfigured.at(i+2)) {
qCritical() << "(" << __func__ << ":" << __LINE__ << ") ERROR"
<< nextTimeStep << stepsConfigured.at(i+2);
return -1;
}
qCritical() << "curTimeStep" << timeSteps.at(i) << ", nextTimeStep" << nextTimeStep;
int prevTimeStep = compute_next_timestep(&cfg, timeSteps.at(i), Down);
if (prevTimeStep != stepsConfigured.at(i)) {
qCritical() << "(" << __func__ << ":" << __LINE__ << ") ERROR"
<< prevTimeStep << stepsConfigured.at(i);
return -1;
}
qCritical() << "curTimeStep" << timeSteps.at(i) << ", prevTimeStep" << prevTimeStep;
}
#endif
QDateTime start = QDateTime::currentDateTime();
//start.setTime(QTime(0, 0, 0));
struct price_t costs;
double const cost[] = {600, 700, 800, 1600, 2400, 3000, 3600};
double price1 = 0;
double price2 = 0;
CalcState cs;
for (int i = 0, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) {
QDateTime end = start.addSecs(timeSteps.at(i)*60);
cs = compute_price_for_parking_ticket(&cfg, start, timeSteps.at(i), end, &costs);
if (cs.getStatus() != CalcState::State::SUCCESS) {
qCritical() << "ERROR STATUS" << costs.netto;
exit(-1);
}
price1 = costs.netto;
price2 = Calculator::GetInstance().GetCostFromDuration(&cfg, start, timeSteps.at(i));
if (price1 != price2) {
qCritical() << "ERROR DIFFERENT PRICES" << price1 << price2;
exit(-1);
}
qCritical() << "compute_price_for_parking_ticket()/GetCostFromDuration() TIME: "
<< timeSteps.at(i) << "PRICE=" << price1;
std::string duration = Calculator::GetInstance().GetDurationFromCost(&cfg, 4,
start.toString(Qt::ISODate).toStdString().c_str(),
cost[i], false, true);
QDateTime d(QDateTime::fromString(QString(duration.c_str()), Qt::ISODate));
qCritical() << "start" << start.toString(Qt::ISODate)
<< "cost[" << i << "]" << cost[i] << "duration" << d.toString(Qt::ISODate) << (start.secsTo(d) + 59) / 60;
}
}
#endif
#if BAD_NEUENAHR_AHRWEILER==1
std::ifstream input;
int pop_min_time;
int pop_max_time;
int pop_min_price;
int pop_max_price;
int pop_daily_card_price;
int pop_carry_over;
int pop_carry_over_time_range_id;
for (int zone=2; zone < 3; ++zone) {
//for (int t=6; t < 7; t+=20) {
switch (zone) {
case 1: {
input.open("/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff01.json");
//pop_max_time = 6*60;
} break;
case 2: {
input.open("/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff02.json");
//pop_max_time = 5*60;
} break;
case 3: {
input.open("/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff03.json");
//pop_max_time = 6*60;
} break;
case 4: {
input.open("/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff04.json");
//pop_max_time = 4*60;
} break;
case 5: {
input.open("/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff05.json");
//pop_max_time = 6*60;
} break;
case 6: {
input.open("/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff06.json");
//pop_max_time = 4*60;
} break;
case 7: {
input.open("/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff07.json");
//pop_max_time = 4*60;
} break;
default:
continue;
}
std::stringstream sstr;
while(input >> sstr.rdbuf());
std::string json(sstr.str());
Configuration cfg;
bool isParsed = cfg.ParseJson(&cfg, json.c_str());
cout << endl;
if (isParsed) {
// test library functions
if (zone == 1) {
pop_min_time = get_minimal_parkingtime(&cfg);
pop_max_time = get_maximal_parkingtime(&cfg);
pop_min_price = get_minimal_parkingprice(&cfg);
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_max_time: " << pop_max_time;
qCritical() << " pop_min_price: " << pop_min_price;
qCritical() << " pop_max_price: " << pop_max_price;
qCritical() << "pop_daily_card_price: " << pop_daily_card_price;
static QList<int> const stepsConfigured
= QList(std::initializer_list<int>{
20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 1440});
//static QList<double> const cost
// = QList(std::initializer_list<double>{
// 0, 40, 80, 120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 500});
static QList<int> const timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg);
qCritical() << "TimeSteps" << timeSteps;
if (stepsConfigured != timeSteps) {
qCritical() << "TIME-STEPS SHOULD BE" << stepsConfigured;
return -1;
}
QDateTime start = QDateTime::currentDateTime();
struct price_t costs;
double price1 = 0;
double price2 = 0;
for (int m=0; m < 1440; ++m) {
start.setTime(QTime(0, 0, 0));
start = start.addSecs(m*60);
qCritical() << "START" << start.toString(Qt::ISODate);
//int Down = 0;
//int Up = 1;
// for (int i = 0, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) {
// int nextTimeStep = compute_next_timestep(&cfg, timeSteps.at(i), Up);
// qCritical() << "nextTimeStep" << nextTimeStep;
//
// int prevTimeStep = compute_next_timestep(&cfg, timeSteps.at(i), Down);
// qCritical() << "prevTimeStep" << prevTimeStep;
//}
CalcState cs;
for (int i = 0, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) {
QDateTime end = start.addSecs(timeSteps.at(i)*60);
cs = compute_price_for_parking_ticket(&cfg, start, timeSteps.at(i), end, &costs);
if (cs.getStatus() != CalcState::State::SUCCESS) {
if (start.time().hour() >= 8 && start.time().hour() < 18) {
qCritical() << "ERROR CALC-STATE-1=" << QString(cs);
exit(-1);
} else {
if (cs.getStatus() == CalcState::State::OUTSIDE_ALLOWED_PARKING_TIME) {
qCritical() << "CALC-STATE=" << QString(cs);
continue;
}
qCritical() << "ERROR CALC-STATE-2=" << QString(cs);
exit(-1);
}
}
price1 = costs.netto;
price2 = Calculator::GetInstance().GetCostFromDuration(&cfg, start, timeSteps.at(i));
if (price1 != price2) {
qCritical() << "ERROR DIFFERENT PRICES" << price1 << price2;
exit(-1);
}
qCritical() << "compute_price_for_parking_ticket()/GetCostFromDuration() TIME: "
<< timeSteps.at(i) << "PRICE=" << price1;
//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));
}
}
#endif
QDateTime start(QDate(2024, 4, 14), QTime());
QDateTime end;
struct price_t price;
//start = QDateTime::currentDateTime();
int paymentOptionIndex = cfg.getCurrentPaymentOptionIndex(start);
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;
//}
}
}
}
}
}
#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());
@@ -183,24 +462,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
@@ -269,13 +546,20 @@ int main() {
QList<int>::const_iterator step; QList<int>::const_iterator step;
for (step = steps.cbegin(); step != steps.cend(); ++step) { for (step = steps.cbegin(); step != steps.cend(); ++step) {
qCritical() << QString("*** NEXT STEP: %1 ***").arg(*step); qCritical() << QString("*** NEXT STEP: %1 ***").arg(*step);
//for (int offset = 7*60; offset < 18*60; ++offset) { //for (int offset = 691; offset < 692; ++offset) {
for (int offset = 690; offset < 691; ++offset) { for (int offset = 480; offset < 1080; ++offset) {
//for (int offset = 7*60; offset < (18*60)-90; ++offset) {
//for (int offset = (18*60)-90; offset < 18*60; ++offset) {
//for (int offset = 1046; offset < 1047; ++offset) {
QDateTime start = s.addSecs(offset * 60); QDateTime start = s.addSecs(offset * 60);
QDateTime const firstStart = start; QDateTime const firstStart = start;
//if (*step != 30) continue;
double cost = 0;
if (compute_price_for_parking_ticket(&cfg, start, *step, end, &price)) { if (compute_price_for_parking_ticket(&cfg, start, *step, end, &price)) {
double cost = price.netto; cost = price.netto;
qCritical() << "****" << offset << *step << "****"; qCritical() << "****" << offset << *step << "****";
qCritical() << " firstStart :" << firstStart.toString(Qt::ISODate); qCritical() << " firstStart :" << firstStart.toString(Qt::ISODate);
@@ -284,66 +568,132 @@ int main() {
qCritical() << " cost :" << cost; qCritical() << " cost :" << cost;
if (offset < 8*60) { // [7:00 - 8:00[ if (offset < 8*60) { // [7:00 - 8:00[
if (!test_neuhauser_kirchdorf(*step, cost)) { double new_cost = cost;
if (offset > (18*60)-(*step)) {
new_cost += ((*step-30)/5)*10;
qCritical() << __LINE__ << "new_cost" << new_cost << "(cost" << cost << ")";
}
if (!test_neuhauser_kirchdorf(*step, new_cost)) {
qCritical() << "ERROR AT OFFSET" << offset; qCritical() << "ERROR AT OFFSET" << offset;
return -1; //return -1;
} }
} else } else
if (offset < 9*60) { // [8:00 - 9:00[ if (offset < 9*60) { // [8:00 - 9:00[
if (!test_neuhauser_kirchdorf(*step, cost)) { double new_cost = cost;
if (offset > (18*60)-(*step)) {
new_cost += ((*step-30)/5)*10;
qCritical() << __LINE__ << "new_cost" << new_cost << "(cost" << cost << ")";
}
if (!test_neuhauser_kirchdorf(*step, new_cost)) {
qCritical() << "ERROR AT OFFSET" << offset; qCritical() << "ERROR AT OFFSET" << offset;
return -1; //return -1;
} }
} else } else
if (offset < 10*60) { if (offset < 10*60) {
if (!test_neuhauser_kirchdorf(*step, cost)) { double new_cost = cost;
if (offset > (18*60)-(*step)) {
new_cost += ((*step-30)/5)*10;
qCritical() << __LINE__ << "new_cost" << new_cost << "(cost" << cost << ")";
}
if (!test_neuhauser_kirchdorf(*step, new_cost)) {
qCritical() << "ERROR AT OFFSET" << offset; qCritical() << "ERROR AT OFFSET" << offset;
return -1; //return -1;
} }
} else } else
if (offset < 11*60) { if (offset < 11*60) {
if (!test_neuhauser_kirchdorf(*step, cost)) { double new_cost = cost;
if (offset > (18*60)-(*step)) {
new_cost += ((*step-30)/5)*10;
qCritical() << __LINE__ << "new_cost" << new_cost << "(cost" << cost << ")";
}
if (!test_neuhauser_kirchdorf(*step, new_cost)) {
qCritical() << "ERROR AT OFFSET" << offset; qCritical() << "ERROR AT OFFSET" << offset;
return -1; //return -1;
} }
} else } else
if (offset < 12*60) { if (offset < 12*60) {
if (!test_neuhauser_kirchdorf(*step, cost)) { double new_cost = cost;
if (offset > (18*60)-(*step)) {
new_cost += ((*step-30)/5)*10;
qCritical() << __LINE__ << "new_cost" << new_cost << "(cost" << cost << ")";
}
if (!test_neuhauser_kirchdorf(*step, new_cost)) {
qCritical() << "ERROR AT OFFSET" << offset; qCritical() << "ERROR AT OFFSET" << offset;
return -1; //return -1;
} }
} else } else
if (offset < 13*60) { if (offset < 13*60) {
if (!test_neuhauser_kirchdorf(*step, cost)) { double new_cost = cost;
if (offset > (18*60)-(*step)) {
new_cost += ((*step-30)/5)*10;
qCritical() << __LINE__ << "new_cost" << new_cost << "(cost" << cost << ")";
}
if (!test_neuhauser_kirchdorf(*step, new_cost)) {
qCritical() << "ERROR AT OFFSET" << offset; qCritical() << "ERROR AT OFFSET" << offset;
return -1; //return -1;
} }
} else } else
if (offset < 14*60) { if (offset < 14*60) {
if (!test_neuhauser_kirchdorf(*step, cost)) { double new_cost = cost;
if (offset > (18*60)-(*step)) {
new_cost += ((*step-30)/5)*10;
qCritical() << __LINE__ << "new_cost" << new_cost << "(cost" << cost << ")";
}
if (!test_neuhauser_kirchdorf(*step, new_cost)) {
qCritical() << "ERROR AT OFFSET" << offset; qCritical() << "ERROR AT OFFSET" << offset;
return -1; //return -1;
} }
} else } else
if (offset < 15*60) { if (offset < 15*60) {
if (!test_neuhauser_kirchdorf(*step, cost)) { double new_cost = cost;
if (offset > (18*60)-(*step)) {
new_cost += ((*step-30)/5)*10;
qCritical() << __LINE__ << "new_cost" << new_cost << "(cost" << cost << ")";
}
if (!test_neuhauser_kirchdorf(*step, new_cost)) {
qCritical() << "ERROR AT OFFSET" << offset; qCritical() << "ERROR AT OFFSET" << offset;
return -1; //return -1;
} }
} else } else
if (offset < 16*60) { if (offset < 16*60) {
if (!test_neuhauser_kirchdorf(*step, cost)) { double new_cost = cost;
if (offset > (18*60)-(*step)) {
new_cost += ((*step-30)/5)*10;
qCritical() << __LINE__ << "new_cost" << new_cost << "(cost" << cost << ")";
}
if (!test_neuhauser_kirchdorf(*step, new_cost)) {
qCritical() << "ERROR AT OFFSET" << offset; qCritical() << "ERROR AT OFFSET" << offset;
return -1; //return -1;
} }
} else } else
if (offset < 17*60) { if (offset < 17*60) {
if (!test_neuhauser_kirchdorf(*step, cost)) { double new_cost = cost;
if (offset > (18*60)-(*step)) {
double const f = ((*step-30)/5)*10;
new_cost += f;
new_cost = std::min(new_cost, f+30);
qCritical() << __LINE__ << "new_cost" << new_cost << "(cost" << cost << ")";
}
if (!test_neuhauser_kirchdorf(*step, new_cost)) {
qCritical() << "ERROR AT OFFSET" << offset; qCritical() << "ERROR AT OFFSET" << offset;
return -1; //return -1;
}
} else
if (offset < 18*60) {
double new_cost = cost;
if (offset > (18*60)-(*step)) {
double const f = ((*step-30)/5)*10;
new_cost += f;
new_cost = std::min(new_cost, f+30);
qCritical() << __LINE__ << "new_cost" << new_cost << "(cost" << cost << ")";
}
if (!test_neuhauser_kirchdorf(*step, new_cost)) {
qCritical() << "ERROR AT OFFSET" << offset;
// return -1;
} }
} else { } else {
qCritical() << "WARN OFFSET TOO HIGH" << offset; qCritical() << "ERROR OFFSET TOO HIGH" << offset;
return -1;
} }
} else { } else {
@@ -354,6 +704,17 @@ int main() {
return -1; return -1;
} }
QDateTime end2 = QDateTime();
if (compute_duration_for_parking_ticket(&cfg, start, cost, end2)) { // return value
qCritical() << "start" << start.toString(Qt::ISODate)
<< "offset" << offset
<< "cost" << cost
<< "end" << end2.toString(Qt::ISODate);
if (end != end2) {
qCritical() << end.toString(Qt::ISODate)
<< end2.toString(Qt::ISODate);
}
}
} }
} }
} }
@@ -485,15 +846,16 @@ int main() {
int Up = 1; int Up = 1;
//compute_next_timestep(&cfg, ) //compute_next_timestep(&cfg, )
QDateTime const start = QDateTime::currentDateTime();
for (int i=0; i<timeSteps.size(); ++i) { for (int i=0; i<timeSteps.size(); ++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;
// uint32_t price = calculator.GetPriceForTimeStep(&cfg, timeSteps.at(i)); uint32_t price = Calculator::GetInstance().GetPriceForTimeStep(&cfg, timeSteps.at(i));
// uint32_t duration = calculator.GetDurationForPrice(&cfg, price); uint32_t duration = Calculator::GetInstance().GetDurationForPrice(&cfg, price);
// qCritical() << "nextTimeStep relative to start:" qCritical() << "nextTimeStep relative to start:"
// << duration << start.addSecs(duration * 60) << duration << start.addSecs(duration * 60).toString(Qt::ISODate)
// << "(price so far:" << price << ")"; << "(price so far:" << price << ")";
} }
} }
#endif #endif
@@ -518,39 +880,28 @@ int main() {
int w = compute_product_price(&cfg, PERMIT_TYPE::DAY_TICKET_TEEN); int w = compute_product_price(&cfg, PERMIT_TYPE::DAY_TICKET_TEEN);
qCritical() << "price teen" << w; qCritical() << "price teen" << w;
return 0;
QDateTime s(QDate(2023, 11, 30), QTime()); QDateTime s(QDate(2023, 11, 30), QTime());
QDateTime end; QDateTime end;
struct price_t price; struct price_t price;
#define ADULT 0 #define ADULT 1
#define TEEN 1 //#define TEEN 1
for (int offset = 480; offset < 1200; ++offset) {
QDateTime start = s.addSecs(offset * 60);
CalcState cs = compute_price_for_daily_ticket(&cfg, start, end,
#if ADULT==1 #if ADULT==1
for (int offset = 480; offset < 1080; ++offset) { PERMIT_TYPE::DAY_TICKET_ADULT,
QDateTime start = s.addSecs(offset * 60); #elif TEEN==1
PERMIT_TYPE::DAY_TICKET_TEEN,
// qCritical() << QString(Calculator::GetInstance().isParkingAllowed(&cfg, start)); #endif
&price);
CalcState cs = compute_price_for_daily_ticket(&cfg, start, end,
PERMIT_TYPE::DAY_TICKET_ADULT, &price);
qCritical() << "start=" << start.toString(Qt::ISODate) qCritical() << "start=" << start.toString(Qt::ISODate)
<< "end" << end.toString(Qt::ISODate) << "price" << price.netto; << "end" << end.toString(Qt::ISODate) << "price" << price.netto;
} }
#endif
#if TEEN==1
for (int offset = 480; offset < 1080; ++offset) {
QDateTime start = s.addSecs(offset * 60);
CalcState cs = compute_price_for_daily_ticket(&cfg, start, end,
PERMIT_TYPE::DAY_TICKET_TEEN, &price);
qCritical() << "start=" << start.toString(Qt::ISODate)
<< "end" << end.toString(Qt::ISODate) << "price" << price.netto;
} }
#endif #undef ADULT
} #undef TEEN
#endif #endif
#if NEUHAUSER_LINSINGER_MASCHINENBAU==1 #if NEUHAUSER_LINSINGER_MASCHINENBAU==1
@@ -566,50 +917,19 @@ int main() {
cout << endl; cout << endl;
if (isParsed) { if (isParsed) {
bool nextDay = false; int const price = compute_product_price(&cfg, PERMIT_TYPE::FOOD_STAMP);
bool prePaid = false; qCritical() << "price food stamp" << price;
// zone 1 (lila)
QDateTime s(QDate(2023, 11, 30), QTime());
QDateTime end;
int marken[] = { 3*60, 5*60, 10*60};
for (int duration = 0; duration < 3; ++duration) {
for (int offset = 360; offset <= 360; ++offset) {
// for (int offset = 360; offset < 1080; ++offset) {
QDateTime start = s.addSecs(offset * 60);
//qCritical() << "start" << start.toString(Qt::ISODate);
// note: prepaid == false (!)
// double cost = Calculator::GetInstance().GetCostFromDuration(&cfg, 4, start, end, marken[duration], nextDay, prePaid);
struct price_t price;
if (compute_price_for_parking_ticket(&cfg, start, marken[duration], end, &price, prePaid)) {
double cost = price.netto;
qCritical() << "start" << start.toString(Qt::ISODate)
<< "end" << end.toString(Qt::ISODate)
<< "duration" << marken[duration]
<< "cost" << cost;
}
//std::string d = Calculator::GetInstance().GetDurationFromCost(&cfg, 4, start.toString(Qt::ISODate).toStdString().c_str(), cost);
//qCritical() << "start" << start.toString(Qt::ISODate)
// << "cost" << cost
// << "until" << d.c_str() << start.secsTo(QDateTime::fromString(d.c_str(), Qt::ISODate)) / 60;
}
}
} }
#endif #endif
#if NEUHAUSER_KORNEUBURG==1 #if NEUHAUSER_KORNEUBURG==1
std::ifstream input("/tmp/tariff_korneuburg.json"); std::ifstream input("/opt/ptu5/opt/customer_714/etc/psa_tariff/tariff01.json");
int pop_max_time; int pop_max_time;
std::stringstream sstr; std::stringstream sstr;
while(input >> sstr.rdbuf()); while(input >> sstr.rdbuf());
std::string json(sstr.str()); std::string json(sstr.str());
Calculator calculator;
Configuration cfg; Configuration cfg;
bool isParsed = cfg.ParseJson(&cfg, json.c_str()); bool isParsed = cfg.ParseJson(&cfg, json.c_str());
@@ -631,19 +951,19 @@ int main() {
QDateTime start = s.addSecs(offset * 60); QDateTime start = s.addSecs(offset * 60);
//qCritical() << "start" << start.toString(Qt::ISODate); //qCritical() << "start" << start.toString(Qt::ISODate);
double cost = calculator.GetCostFromDuration(&cfg, 3, start, end, duration, nextDay, prePaid); double cost = Calculator::GetInstance().GetCostFromDuration(&cfg, 3, start, end, duration, nextDay, prePaid);
//Q_ASSERT(cost == duration*2.5); //Q_ASSERT(cost == duration*2.5);
//qCritical() << ""; //qCritical() << "";
//qCritical() << "start" << start.toString(Qt::ISODate)
// << "end" << end.toString(Qt::ISODate)
// << "duration" << duration
// << "cost" << cost;
std::string duration = calculator.GetDurationFromCost(&cfg, 3, start.toString(Qt::ISODate).toStdString().c_str(), cost);
//Q_ASSERT(cost == duration*2.5);
qCritical() << "start" << start.toString(Qt::ISODate) qCritical() << "start" << start.toString(Qt::ISODate)
<< "cost" << cost << "end" << end.toString(Qt::ISODate)
<< "until" << duration.c_str() << start.secsTo(QDateTime::fromString(duration.c_str(), Qt::ISODate)) / 60; << "duration" << duration
<< "cost" << cost;
//std::string duration = Calculator::GetInstance().GetDurationFromCost(&cfg, 3, start.toString(Qt::ISODate).toStdString().c_str(), cost);
//Q_ASSERT(cost == duration*2.5);
//qCritical() << "start" << start.toString(Qt::ISODate)
// << "cost" << cost
// << "until" << duration.c_str() << start.secsTo(QDateTime::fromString(duration.c_str(), Qt::ISODate)) / 60;
} }
} }
} }
@@ -660,7 +980,7 @@ int main() {
int pop_max_price; int pop_max_price;
int pop_daily_card_price; int pop_daily_card_price;
for (int zone=6; zone < 7; ++zone) { for (int zone=1; zone < 2; ++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: {
@@ -736,7 +1056,7 @@ int main() {
{ {
// zone 1 (lila) // zone 1 (lila)
QDateTime s(QDate(2023, 11, 30), QTime()); QDateTime s(QDate(2024, 3, 26), QTime());
QDateTime end; QDateTime end;
int cnt = 1; int cnt = 1;
if (zone == 1) { if (zone == 1) {