Compare commits

..

153 Commits

Author SHA1 Message Date
f2156e4650
Merge branch 'include-tariff-files' 2025-05-09 09:25:49 +02:00
338a1a4ebc
Merge branch 'vorkauf-fix-2025-April-22' into include-tariff-files 2025-05-09 09:25:19 +02:00
b4818a3918 get_minimal_parkingtime()
get_maximal_parkingtime()
compute_product_price()
get_maximal_parkingprice()
compute_price_for_parking_ticket()
compute_duration_for_parking_ticket()
compute_duration_for_daily_ticket()
compute_price_for_daily_ticket():

In case main-tariff file contains an Includes-section, change to the
included tariff based on product-id (permit-type).
2025-05-08 11:15:23 +02:00
35294e99f0 Parse possible Includes-section in tariff-file 2025-05-06 12:00:22 +02:00
edfa5dc1b1 Minor: add case FREE_TICKET to prevent compiler warning. 2025-05-06 11:59:10 +02:00
d95741baae compute_duration_for_parking_ticket():
Switch to different tariff based on product-type/product-id.
2025-05-06 11:57:36 +02:00
e172e814e7 load and parse additional (included) tariff-files 2025-05-06 11:57:14 +02:00
37aa10fc85 Add product FREE_TICKET. 2025-05-06 11:55:35 +02:00
4b9edb0f47 Minor: add IncludeType to be used by json-parser 2025-05-06 11:54:49 +02:00
e70e9a8586 Add TariffIncludes: the main tariff-file will include (load) other tariff-files. 2025-05-06 11:52:47 +02:00
aec290fe26 test code 2025-05-06 11:52:16 +02:00
78cae24389 Fix: if start-time is out-of-range (after valid time for sell), switch
to next valid time, taking into account if next valid time is on next day.
2025-04-23 11:00:33 +02:00
de0be1d19b Minor: added/changed debug messages. 2025-04-23 10:59:39 +02:00
54921f0e85 If price (=key) is not found, compute the next smaller valid price (=key)
and use this as maxPrice.
Usage: (Innichen (508) with) direct coin input.
2025-04-17 13:33:22 +02:00
077c2334ca Restore pop_max_price in case it has been changed (for certain settings). 2025-04-17 13:09:53 +02:00
d605af5c5a Check prepaidIf and carryOverIf for null and emptyness. 2025-04-16 11:32:20 +02:00
c5900f9f2b Minor: extend debug output 2025-04-16 11:31:05 +02:00
9b137c2873 Fix in Calculator::GetPriceForTimeStep():
Allow some tolerance (of 3 minutes) when looking up the
	current time-step value in the duration-array.
	Otherwise, when corossing a minute-boundary, it can happen to
	not find the match and returning a price of 0 (which is almost
	always wrong).
2025-04-03 11:53:47 +02:00
dd249a87d5 Set cnt-limit to 20. This allows a bigger time-range for tariff, which
have in principle no time-limit.
2025-04-02 15:28:46 +02:00
575885c19e Merge branch 'master' into kleipeda-experimental 2025-04-02 09:44:20 +02:00
d82a732a8d if end of parking time equals carry-over-end, then, if configured, go back to carry-over-start. 2025-04-01 14:26:21 +02:00
99dbd7c194 Minor: debug output. 2025-04-01 14:24:42 +02:00
ae985d25ce
Merge branch 'kleipeda-experimental' 2025-02-04 14:58:58 +01:00
6a215d4cf9
Allow zone_nr > 999 2025-02-04 14:47:07 +01:00
a3f4a742ce
Read zone_nr from system_data 2025-02-04 14:44:28 +01:00
e6d8c04076 Fix: for time change summer -> winter term. Compute minutes until midnight manually. 2024-10-30 15:56:58 +01:00
1f6606f382 Add some tests for Forchach (749) 2024-10-10 11:40:29 +02:00
4b9a4319b3 ComputeDurationFromCost():
Fix: take into account that there may be more than just two
	carry-over-ranges. For instance, in Korneuburg (714), there are three
	as they have a break from 12:00-14:00.
2024-10-10 11:38:14 +02:00
5e673788b4 ComputeDurationFromCost():
Use helper function computeMinutesUntilCarryOverEnd() to compute
	the offset until the end of the carry-over-range.
2024-10-10 11:36:14 +02:00
7e2f40a7b5 Add assigment-operator (otherwise compilation error). 2024-10-10 11:33:33 +02:00
44e2ce24a3 Add helper computeMinutesUntilCarryOverEnd().
Used in new tariff-calculator. Replace of previous wrong approach of
        using m_range.duration.
2024-10-10 11:30:53 +02:00
5a55ad6ef0 ComputeDurationFromCost():
brutto-time must be updated in case of an carry-over-section.
2024-10-02 15:21:21 +02:00
5a77958e8d getOutOfService():
Check for special days (holidays) with out-of-service-time-ranges.
	Holidays have higher priority than usual days ("default").
2024-10-02 15:19:32 +02:00
a1e7f4629a getService():
Check for special days (holidays) with service-time-ranges.
	Holidays have higher priority than usual days ("default").
2024-10-02 15:18:16 +02:00
efc2582c36 getCarryOver():
Check for special days (holidays) with carry-over-sections.
	Holidays have higher priority than usual days.
2024-10-02 15:17:00 +02:00
a72f5a5019 getPrepaid():
Check for special days (holidays) with prepaid sections.
	Holidays have higher priority than usual days.
2024-10-02 15:15:19 +02:00
28f0ea9fce Merge from kleipeda-experimental-snapshot-2024-09-27:
started new implementation of tariff-calculator.
2024-10-01 09:25:53 +02:00
3109e82ef8 If out-of-service, use start of out-of-service action as output-date. 2024-10-01 09:23:15 +02:00
03dd6c44da Always reset pop_max_price to configured value. 2024-09-30 16:58:23 +02:00
212c792b77 compute_price_for_parking_ticket():
Include opverpaid option in price-computation.
2024-09-30 16:57:18 +02:00
ab3cdb32ae compute_next_timestep():
Restrict time-step-list when time-limit has been reached: +/-_button
	does not move upward anymore.
2024-09-30 16:55:25 +02:00
4f23ab3d68 ComputeCostFromDuration():
Add price when overpaid occurred.
2024-09-30 16:53:25 +02:00
acbc27cfb2 ComputeDurationFromCost():
If overapid or trunctae has been set, then truncated max. parking time
	to time-limit configured in tariff-file.
2024-09-30 16:51:51 +02:00
bcbe95d483 Add hard-coded trauncate flag. 2024-09-30 16:51:02 +02:00
e3bbca86d5 Minor: changed parameter type to non-const. 2024-09-30 16:50:21 +02:00
5868d3b510 Introduce computational state 2024-09-30 16:46:36 +02:00
d4363e71cd Keep bacjward compatibility before using payment-method Unified. 2024-09-27 14:24:10 +02:00
fd99c20bd9 Take into account new payment method 'Unified' to call new tariff-calculator. 2024-09-27 14:20:20 +02:00
dbccdba9fe isParkingAllowedForWeekDay():
Minor: adapt function call to changes parameter arity.
2024-09-27 14:18:31 +02:00
b035f4f887 Calculator::GetDurationFromCost():
Minor: move scope of some variables upward.
2024-09-27 14:17:35 +02:00
18f09fccb9 GetDurationFromCost():
Call ComputeDurationFromCost() of new tariff calculator for payment-method Unified.
2024-09-27 14:10:02 +02:00
1086e360e5 Start of implementing new tariff calculator:
Added serveral helper function for parsing tariff file:
	  * getPrepaid()
	  * getCarryOver()
          * getService()
          * getOutOfService()

	Added main functions of tariff calculator:

	  * ComputeDurationFromCost()
	  * ComputeCostFromDuration()
2024-09-27 14:04:39 +02:00
ada7bebd90 Minor: Add headers. 2024-09-27 13:57:30 +02:00
2b9ea67ef5 Added function to implement new tariff-calculator:
std::pair<CalcState, QDateTime> ComputeDurationFromCost(Configuration const* cfg, QDateTime const &startDatetimePassed,  int cost);
std::pair<CalcState, std::optional<int>> ComputeCostFromDuration(Configuration const* cfg, QDateTime const &startDatetime, QDateTime &endDatetime, int nettoParkingTime);
2024-09-27 13:48:30 +02:00
d117328bed Minor: removed default parameter in constructor 2024-09-27 13:47:26 +02:00
fd04531474 Added payment <unified> payment-methode 2024-09-27 13:45:45 +02:00
5749fa422e Added structures for parsing of tariff05 in bad neuenahr 2024-09-27 13:45:04 +02:00
1347f1f208 Added parsing for tariff05.json (bad neuenarh (249)) 2024-09-27 13:44:01 +02:00
576c3fefdd Added PaymentMethod::Unified 2024-09-27 13:42:44 +02:00
9ca7018fc1 tests for bad neuenahr 2024-09-27 13:42:04 +02:00
515dfaf35c reprogrammed to use ATBTime class 2024-09-27 13:41:30 +02:00
0ab833709c Added struct ATBTariffCarryOver 2024-09-27 13:40:18 +02:00
8e4f47c7b6 Added struct ATBTariffPrepaid 2024-09-27 13:39:35 +02:00
bc9645f1fa Minor: removed "pragma once" compiler flag 2024-09-27 13:38:39 +02:00
713b483918 Added/fixed several functions. final testing needed. 2024-09-27 13:37:54 +02:00
3c7af1cb32 Minor: Added tariff_service and tariff_out_of_service 2024-09-27 13:35:54 +02:00
356e451839 Add structures to encode service and out-of-service times 2024-09-27 13:35:03 +02:00
c4e1d412a5 Add some assinment operators to support assignment of tariff-time-ranges. 2024-09-27 13:31:01 +02:00
1b716c48d2
Fix: copy header files 2024-09-19 14:10:05 +02:00
77e1414c13 compute_duration_for_parking_ticket():
Recompute pop_max_price using netto-parking-time.
	Search Duration for the time-step with time-step == netto-parking-time,
	then search for the corresponding price in PaymentRate.
	The result is the new pop_max_price.
2024-09-17 17:05:23 +02:00
d95275a72d Compute real netto_parking_time.
This time will be used to find the real time-step, and from here the actual price to pay.
2024-09-17 17:04:27 +02:00
577a17dc6a Set seconds of serveral date-times to 0.
Compute netto_parking_time (which includes carry-over duration).
2024-09-17 17:03:29 +02:00
d8d32820a3 compute_price_for_parking_ticket():
Reset pop_max_price to original value using pop_max_price_saved.
2024-09-17 17:01:32 +02:00
2ce0aeef1d Minor: include atb_time.h 2024-09-17 16:59:07 +02:00
0cba85eafb Set pop_max_price_saved 2024-09-17 16:58:20 +02:00
4030a4b165 Add pop_max_price_save in case pop_max_price has to be re-computed dynamically, so it can be reset 2024-09-17 16:57:34 +02:00
8c7afdfcb1 Add additional constructor. 2024-09-17 16:53:45 +02:00
932d4e8cb9 check it ticket-end-time hits carry-over-start. if configured, move to end of carry-over. 2024-09-16 16:56:48 +02:00
38abc65425 compute_price_for_parking_ticket():
Check if minutesUntilCarryOver is positive (usually must be).
2024-09-16 16:54:25 +02:00
205896903b Handle SUCCESS_MAXPRICE (calc-state). 2024-09-16 16:53:44 +02:00
dbedfd094f Add some OTHER files 2024-09-16 16:52:00 +02:00
57b9d16abc GetDurationFromCost():
Handle carry-over for direct coin insertion.
	Carefully check if this might be a problem for other projects.
2024-09-16 16:50:16 +02:00
48afbc071c Added new calc-state: SUCCESS_MAXPRICE.
Return whenever cost (=price) equals max-price.
2024-09-16 16:49:00 +02:00
7a7b10260a Add untracked(!) files 2024-09-16 16:47:01 +02:00
1874b08210 Merge branch 'kleipeda-experimental-snapshot-2024-09-12' into kleipeda-experimental 2024-09-16 10:49:23 +02:00
88a0ebb688 Add atb-time. 2024-09-16 10:42:56 +02:00
a8ae9fc602 Add own Time class (similar QTime) 2024-09-16 10:42:08 +02:00
7c0514e241 save current state 2024-09-13 10:42:45 +02:00
f53e9ceaae Some testing added 2024-09-11 12:11:49 +02:00
dffc6e2a03 Minor: removed some debug output. 2024-09-11 11:56:06 +02:00
f9cc3af473 ParseJson():
Add parsing of "pop_apply_carry_over_to_ticket_endtime".
2024-09-11 11:55:03 +02:00
9dd0108731 ParseJson():
Add parsing for prepaid-options.
2024-09-11 11:54:16 +02:00
fa10ea4b89 compute_price_for_parking_ticket():
In case parking-time-limit is violated, return with an error.

	Commented out: use another possiblity: cut max-parking-time
	so that parking-time-limit is not violated.
2024-09-11 11:49:31 +02:00
05f03a623b compute_price_for_parking_ticket():
If after crossing a carry-over-time range (taking several days)
	check if we have to carry over again on the target day.
2024-09-11 11:47:50 +02:00
03e9076962 compute_price_for_parking_ticket():
Minor: add some debug output.
2024-09-11 11:46:36 +02:00
5dbd3645c6 compute_price_for_parking_ticket():
Fetch prepaid-option-id (possibly recalculating it depending
	on year-period), and fetch associated prepaid-options.
2024-09-11 11:44:09 +02:00
d21f69cb9b get_maximal_parkingprice():
Fetch maxPrice directly instead of using utility function.
2024-09-11 11:42:15 +02:00
e38a1bfe12 Add default constructor, update debug output. 2024-09-11 11:40:19 +02:00
f38a8d528c Minor: add getters for parking-time-limit. 2024-09-11 11:39:16 +02:00
08a593eb12 Add 'pop_apply_carry_over_to_ticket_endtime':
If ticket-end-time exactly hits the start of a carry-over-time-range,
	the move to the end of the carry-over-time-range, even if this
	were not strictly necessary.
2024-09-11 11:36:57 +02:00
f322d30e36 Add default constructor, fix debug output. 2024-09-11 11:35:17 +02:00
7a53a68850 getPaymentOptionIndex(): add start-time parameter 2024-09-06 12:05:41 +02:00
275c3ec869 compute_price_for_parking_ticket():
Pass start-date-time to parking-time-checker.
2024-09-03 11:19:23 +02:00
6d2bde1fe9 getPaymentOptionIndex():
Fix: make sure only one payment option can be chosen.
2024-09-03 11:17:31 +02:00
f02521d3c2 parseWeekDay():
for the park-time-limit checking take into account that the
 	start-date-time and end-date-time are on different days.
2024-09-03 11:15:08 +02:00
75f1c1bb76 Checking parking-time-limit:
provide start-date-time as well, because the limit counts only
	from one day to following day (e.g. Sunday to Monday or from
	holiday to next day).
2024-09-03 11:10:24 +02:00
f47695de8b Add pop_plus_steps_saved 2024-09-02 17:16:47 +02:00
cce3db301b Minor: comment out some code to prevent compiler warnings (about some unused
variables).
2024-09-02 17:15:33 +02:00
5cab0de9fb Use free function getPaymentOptionIndex() to compute index of valid
payment-option-section in tariff-file based on configured businessHours.
2024-09-02 17:14:20 +02:00
f92906f680 Minor: debug output. 2024-09-02 17:13:11 +02:00
8cdeef26fc Check if computed ticket-end-time violates a carry-over-limit defined in
tariff-file.
2024-09-02 17:11:48 +02:00
52ebbf7bc9 Use free function getPaymentOptionIndex() in serveral places to compute valid
index of a payment-option-section within tariff file. If this is not possible,
then try the already available functionality.
2024-09-02 17:09:26 +02:00
349e9d8b06 Add free functions isHoliday() to check if the current day is a holiday
and previousDayHoliday() to check if previous day (relative to endtime) is a
holiday.
2024-09-02 17:05:32 +02:00
68a1c24861 Add free function getPaymentOptionIndex():
Compute payment option index base on current start-date-time and
	businesshour-setiing in tariff-file.
	Returns -1 to indicate error.
2024-09-02 17:03:37 +02:00
c946c106d1 Configuration::ParseJson():
Save the pop_plus_steps setting: sometimes it is necessary to adapt the
	pop_plus_steps-variable in order to hit a time-limit-boundary exactly.
	Otherwise the next computed time-step might overshoot the time-limit,
	and when moving backwards (via Minus-Button) there is a better
	resolution: going backwards, the user could hit the exact time-limit,
	which he could not when going up.
2024-09-02 16:58:34 +02:00
f24f1fe646 Configuration::ParseJson():
Call parseWeekDay() to reading the week-day-settings.
2024-09-02 16:57:11 +02:00
c6b8a37263 ParseJson():
Minor: some reformatting of source code.
2024-09-02 16:55:48 +02:00
58d8f16681 ParseWeekDay():
Parsing "Monday" - "Sunday" section i a tariff-file.

	Each day has a memebr named "week_day_default".

	It contains the valid default tariff settings for a usual day (i.e. no
	holiday etc.)
	It also contains the carry-over-settings for the usual day.

	In case there is some holiday on this day (for instance on "Monday"),
	the the date of the holiday replaces the name "week_day_default".
	Otherwise the structure is the same as for a usual day.
2024-09-02 16:49:21 +02:00
431664d8b9 IdentifyJsonMember():
Add "Monday" - "Sunday" as level-1 sections in a tariff-file.
2024-09-02 16:47:46 +02:00
53cf9a7341 Add description for tariff-settings.w 2024-09-02 16:46:00 +02:00
3a18ee2d7c Add description for carry-over-settings 2024-09-02 16:45:35 +02:00
929a8a4a27 Reuse of "class ATBWeekDays":
Description of a weekday: Mon-Sun. For holidays contains a type-flag
	to indicate such a day.

	Each weekday has some tariff-settings and some carry-over-settings.
2024-09-02 16:41:26 +02:00
2b9657787d add tests for bad-neuenahr 2024-09-02 16:40:38 +02:00
eca285cc25 remove obsolete print-function 2024-09-02 16:40:07 +02:00
bda8914f1a Add free functions:
previousDayHoliday():
	Check if previous day was a holiday. Check is done relative to
	computed endtime.

isHoliday():
	Check if startDateTime is on a holiday.

getPaymentOptionIndex():
	Compute the index of the payment-options-section inside a tariff-file.
	This is done as workaround (and backward compatibility).

parseWeekDay():
	Parse new structure of tariff-file.
2024-09-02 16:35:25 +02:00
a3983ed427 check for time-step-config == STATIC 2024-08-21 17:46:35 +02:00
f8805e9e78 compute_duration_for_parking_ticket():
Fix: handle carry-over for coin-insertion.
2024-08-21 15:40:55 +02:00
7a6360f392 compute_duration_for_parking_ticket():
Fix: handle prepaid-setting for coin-insertion.
2024-08-21 15:39:44 +02:00
08a249f393 return OVERPAID in case overpay is not allowed 2024-08-21 15:39:05 +02:00
7c173ae292 parse for pop_allow_overpay 2024-08-21 15:38:06 +02:00
80637260f3 Utilities::IsYearPeriodActive():
Fix: take into account if start-date <= end-date or not.
	     Otherwise check is wrong, and no valid year period is returned.
2024-08-21 15:35:03 +02:00
9b524d63e5 Add 'pop_allow_overpay' setting: set vai tariff-file if operpay is allowed. 2024-08-21 15:33:02 +02:00
25b3143d88
Merge branch 'kleipeda-experimental' of /home/siegert/atbfs01entwicklung/Elektronik/PTU/git_bare_repos/libmobilisis-calc into kleipeda-experimental 2024-08-02 14:37:42 +02:00
0856f10ca9 GetDurationFromCost():
Fix computation of end-time when pop_accumulate_durations is set
	in tariff-file.
2024-08-02 14:34:44 +02:00
88c703ecc2
Merge branch 'kleipeda-experimental' of /home/siegert/atbfs01entwicklung/Elektronik/PTU/git_bare_repos/libmobilisis-calc into kleipeda-experimental 2024-08-02 13:21:54 +02:00
465b2274a1 compute_duration_for_parking_ticket():
Adapt end-time in case it is midnight: 00:00 -> 23:59
2024-08-02 13:15:11 +02:00
f946cd13e4
Merge branch 'kleipeda-experimental' of /home/siegert/atbfs01entwicklung/Elektronik/PTU/git_bare_repos/libmobilisis-calc into kleipeda-experimental 2024-08-02 11:55:12 +02:00
8d1cbe7337
Merge branch 'kleipeda-experimental' of /home/siegert/atbfs01entwicklung/Elektronik/PTU/git_bare_repos/libmobilisis-calc into kleipeda-experimental 2024-08-02 11:29:10 +02:00
62c52fd580 test case for fuchs, fane alm. 2024-08-02 11:13:50 +02:00
1023f6ede1 GetPriceForTimeStep():
Use "pop_accumulate_durations" setting to sum up the durations.
	Otherwise time-step will not be found in time-step-list.
2024-08-02 11:12:07 +02:00
36b3e85d1b GetCostFromDuration():
recompute timestep list to make sure that time step is found in it.
2024-08-02 11:11:20 +02:00
b394ed46cc In case end-parking-time ends with 00:00, set it to 23:59. 2024-08-02 11:09:20 +02:00
3dda2d8355 Check if prepaid-option is set. 2024-08-02 11:08:52 +02:00
1152c3824e Minor: add some debug output. 2024-08-02 11:08:32 +02:00
4271c0fb31 Fixed compute_next_timestep() for degressive tariff:
compute_next_timestep() was actually never called for such a tariff.
2024-08-02 10:50:25 +02:00
24d9d4a0ff test case for kleipeda and fuchs 2024-08-01 16:46:09 +02:00
4bce854d77 GetDurationFromCost():
Set durationInSecs in case 'pop_accumulate_prices' is not configured
        in tariff file.
2024-08-01 16:44:06 +02:00
138221759b GetDurationFromCost():
Minor: removed some debug ouput
2024-08-01 16:43:19 +02:00
9cb7d4aea6 compute_price_for_parking_ticket():
Added handling for prepaid and carry-over.
2024-08-01 16:04:57 +02:00
cde490bab2 compute_next_time_step():
Added handling with pop_plus_steps/pop_minus_steps:
	'+' usually takes more than one time step.
        '-' is usually 1.

	Changed behaviour when current time is not found in the list of time steps:
	Search for the entry with the smallest distance to 'current time'.
	If the distance is smaller than 3 minutes, then use 'current time' as new
 	entry in the list of time steps.
2024-08-01 16:00:10 +02:00
f0677374ec Parsing of pop_plus_steps/pop_minus_steps 2024-08-01 15:46:49 +02:00
89b05ffadc Added GetYearPeriodActive() to get active year period. 2024-08-01 15:45:50 +02:00
260973cd09 Added pop_plus_steps/pop_minus_steps to control step sizes 2024-08-01 15:44:06 +02:00
34 changed files with 9872 additions and 399 deletions

1
\ Normal file
View File

@ -0,0 +1 @@
return std::make_pair(CalcState(CalcState::State::OVERPAID), dt);

View File

@ -0,0 +1,83 @@
#ifndef ATB_TIME_H_INCLUDED
#define ATB_TIME_H_INCLUDED
#include <QDateTime>
class ATBTime {
static QDateTime const m_end;
mutable QDateTime m_time;
public:
explicit ATBTime();
explicit ATBTime(int h, int m, int s = 0, int ms = 0);
explicit ATBTime(QString const &time);
explicit ATBTime(QTime const &time);
explicit ATBTime(ATBTime const &atbTime) {
m_time = atbTime.m_time;
}
ATBTime &operator=(ATBTime && atbTime) {
m_time = std::move(atbTime.m_time);
return *this;
}
ATBTime &operator=(ATBTime const &atbTime) {
m_time = atbTime.m_time;
return *this;
}
int hour() const { return m_time.time().hour(); }
int minute() const { return m_time.time().minute(); }
int second() const { return m_time.time().second(); }
int msec() const { return m_time.time().msec(); }
int secsTo(QString const &t) const {
if (t == "24:00:00") {
return m_time.secsTo(m_end);
}
return m_time.time().secsTo(QTime::fromString(t, Qt::ISODate));
}
int msecsTo(QTime t) const { return m_time.time().msecsTo(t); }
bool setHMS(int h, int m, int s, int ms = 0);
bool isNull() const { return m_time.time().isNull(); }
bool isValid() const { return m_time.time().isValid(); }
QTime addMSecs(int ms) const;
QTime addMSecs(int ms);
QTime addSecs(int s) const;
QTime addSecs(int s);
int msecsSinceStartOfDay() const;
QString toString(Qt::DateFormat format = Qt::TextDate) const;
static bool isValid(int h, int m, int s, int ms = 0);
static QTime currentTime() { return QDateTime::currentDateTime().time(); }
static constexpr QTime fromMSecsSinceStartOfDay(int msecs);
static QTime fromString(QString const &string, Qt::DateFormat format = Qt::TextDate);
static QTime fromString(QString const &string, const QString &format);
friend bool operator!=(const ATBTime &lhs, const ATBTime &rhs) noexcept;
friend bool operator<(const ATBTime &lhs, const ATBTime &rhs) noexcept;
friend bool operator<=(const ATBTime &lhs, const ATBTime &rhs) noexcept;
friend bool operator>=(const ATBTime &lhs, const ATBTime &rhs) noexcept;
friend bool operator<(const ATBTime &lhs, const ATBTime &rhs) noexcept;
friend bool operator>(const ATBTime &lhs, const ATBTime &rhs) noexcept;
friend bool operator==(const ATBTime &lhs, const ATBTime &rhs) noexcept;
friend QDataStream &operator<<(QDataStream &out, ATBTime const &time);
friend QDebug &operator<<(QDebug &out, ATBTime const &time);
friend QDataStream &operator>>(QDataStream &in, ATBTime &time);
};
#endif // ATB_TIME_H_INCLUDED

View File

@ -56,6 +56,7 @@ struct CALCULATE_LIBRARY_API CalcState {
static QString const ABOVE_MAX_PARKING_PRICE; static QString const ABOVE_MAX_PARKING_PRICE;
static QString const OVERPAID; static QString const OVERPAID;
static QString const OUTSIDE_ALLOWED_PARKING_TIME; static QString const OUTSIDE_ALLOWED_PARKING_TIME;
static QString const SUCCESS_MAXPRICE;
enum class State : uint8_t { enum class State : uint8_t {
SUCCESS, SUCCESS,
@ -71,7 +72,8 @@ struct CALCULATE_LIBRARY_API CalcState {
BELOW_MIN_PARKING_PRICE, BELOW_MIN_PARKING_PRICE,
ABOVE_MAX_PARKING_PRICE, ABOVE_MAX_PARKING_PRICE,
OVERPAID, OVERPAID,
OUTSIDE_ALLOWED_PARKING_TIME OUTSIDE_ALLOWED_PARKING_TIME,
SUCCESS_MAXPRICE
}; };
State m_status; State m_status;
@ -88,9 +90,9 @@ struct CALCULATE_LIBRARY_API CalcState {
, m_desc(desc) { , m_desc(desc) {
} }
explicit CalcState(State state, QString desc = "", explicit CalcState(State state, QString desc,
QTime const &from = QTime(), QTime const &from,
QTime const &until = QTime()) QTime const &until)
: m_status(state) : m_status(state)
, m_desc(desc) , m_desc(desc)
, m_allowedTimeRange(from, until) { , m_allowedTimeRange(from, until) {
@ -106,6 +108,9 @@ struct CALCULATE_LIBRARY_API CalcState {
case State::SUCCESS: case State::SUCCESS:
s = CalcState::SUCCESS; s = CalcState::SUCCESS;
break; break;
case State::SUCCESS_MAXPRICE:
s = CalcState::SUCCESS_MAXPRICE;
break;
case State::ERROR_PARSING_ZONE_NR: case State::ERROR_PARSING_ZONE_NR:
s = CalcState::ERROR_PARSING_ZONE_NR; s = CalcState::ERROR_PARSING_ZONE_NR;
break; break;
@ -158,6 +163,9 @@ struct CALCULATE_LIBRARY_API CalcState {
case State::SUCCESS: case State::SUCCESS:
s = CalcState::SUCCESS; s = CalcState::SUCCESS;
break; break;
case State::SUCCESS_MAXPRICE:
s = CalcState::SUCCESS_MAXPRICE;
break;
case State::ERROR_PARSING_ZONE_NR: case State::ERROR_PARSING_ZONE_NR:
s = CalcState::ERROR_PARSING_ZONE_NR; s = CalcState::ERROR_PARSING_ZONE_NR;
break; break;
@ -207,6 +215,9 @@ struct CALCULATE_LIBRARY_API CalcState {
if (desc == SUCCESS) { if (desc == SUCCESS) {
m_status = State::SUCCESS; m_status = State::SUCCESS;
} else } else
if (desc == SUCCESS_MAXPRICE) {
m_status = State::SUCCESS_MAXPRICE;
}
if (desc == ERROR_PARSING_ZONE_NR) { if (desc == ERROR_PARSING_ZONE_NR) {
m_status = State::ERROR_PARSING_ZONE_NR; m_status = State::ERROR_PARSING_ZONE_NR;
} else } else

View File

@ -3,6 +3,7 @@
#include <iostream> #include <iostream>
#include <optional> #include <optional>
#include <utility>
#include "configuration.h" #include "configuration.h"
#include "calculate_price.h" #include "calculate_price.h"
@ -26,9 +27,16 @@ class Calculator {
QDateTime const &start, QDateTime const &start,
int netto_parking_time, int netto_parking_time,
int paymentOptionIndex); int paymentOptionIndex);
struct State {
bool m_timeLimitReached;
uint32_t m_costAtTimeLimit;
} m_state;
protected: protected:
explicit Calculator() = default; explicit Calculator() {
m_state.m_timeLimitReached = false;
m_state.m_costAtTimeLimit = ~0;
}
public: public:
Calculator(Calculator const &other) = delete; Calculator(Calculator const &other) = delete;
@ -39,6 +47,12 @@ public:
return c; return c;
} }
bool timeLimitReached() const { return m_state.m_timeLimitReached; }
void setTimeLimitReached(bool timeLimitReached) { m_state.m_timeLimitReached = timeLimitReached; }
bool costAtTimeLimit() const { return m_state.m_costAtTimeLimit; }
void setCostAtTimeLimit(uint32_t cost) { if (m_state.m_costAtTimeLimit > cost) m_state.m_costAtTimeLimit = cost; }
void resetCostAtTimeLimit() { m_state.m_costAtTimeLimit = ~0; }
void ResetTimeSteps(int paymentOptionIndex) { void ResetTimeSteps(int paymentOptionIndex) {
if (m_timeSteps.size() > 0 && paymentOptionIndex < m_timeSteps.size()) { if (m_timeSteps.size() > 0 && paymentOptionIndex < m_timeSteps.size()) {
m_timeSteps[paymentOptionIndex].clear(); m_timeSteps[paymentOptionIndex].clear();
@ -70,8 +84,9 @@ public:
/// <param name="start_datetime">Date/time of payment to be conducted in ISO8601 format (e.g. 2022-12-25T08:00:00Z)</param> /// <param name="start_datetime">Date/time of payment to be conducted in ISO8601 format (e.g. 2022-12-25T08:00:00Z)</param>
/// <param name="price"></param> /// <param name="price"></param>
/// <returns>Returns duration in seconds (data type: double)</returns> /// <returns>Returns duration in seconds (data type: double)</returns>
std::string GetDurationFromCost(Configuration* cfg, uint8_t vehicle_type, char const* start_datetime, double price, std::pair<std::string, QDateTime>
PermitType permitType, bool nextDay = false, bool prepaid = false); GetDurationFromCost(Configuration* cfg, uint8_t vehicle_type, char const* start_datetime, double price,
PermitType permitType, bool nextDay = false, bool prepaid = false);
/// <summary> /// <summary>
/// Gets cost from duration in seconds /// Gets cost from duration in seconds
@ -85,6 +100,9 @@ public:
double GetCostFromDuration(Configuration* cfg, uint8_t vehicle_type, QDateTime &start_datetime, QDateTime & end_datetime, int durationMin, double GetCostFromDuration(Configuration* cfg, uint8_t vehicle_type, QDateTime &start_datetime, QDateTime & end_datetime, int durationMin,
PermitType permitType, bool nextDay = false, bool prepaid = false); PermitType permitType, bool nextDay = false, bool prepaid = false);
std::pair<CalcState, QDateTime> ComputeDurationFromCost(Configuration *cfg, QDateTime const &startDatetimePassed, int cost);
std::pair<CalcState, std::optional<int>> ComputeCostFromDuration(Configuration *cfg, QDateTime const &startDatetime, QDateTime &endDatetime, int nettoParkingTime);
// Daily ticket // Daily ticket
QDateTime GetDailyTicketDuration(Configuration* cfg, const QDateTime start_datetime, uint8_t payment_option, bool carry_over); QDateTime GetDailyTicketDuration(Configuration* cfg, const QDateTime start_datetime, uint8_t payment_option, bool carry_over);
std::optional<struct price_t> GetDailyTicketPrice(Configuration* cfg, QDateTime const &startDatetime, QDateTime &endTime, PERMIT_TYPE permitType); std::optional<struct price_t> GetDailyTicketPrice(Configuration* cfg, QDateTime const &startDatetime, QDateTime &endTime, PERMIT_TYPE permitType);

View File

@ -29,6 +29,8 @@
#include "tariff_prepaid.h" #include "tariff_prepaid.h"
#include "tariff_carryover.h" #include "tariff_carryover.h"
#include "tariff_permit_type.h" #include "tariff_permit_type.h"
#include "tariff_service.h"
#include "tariff_out_of_service.h"
#include <QVector> #include <QVector>
#include <optional> #include <optional>
@ -36,6 +38,7 @@
using namespace std; using namespace std;
using namespace rapidjson; using namespace rapidjson;
class Calculator; class Calculator;
class Configuration class Configuration
{ {
@ -49,6 +52,10 @@ public:
using TariffPrepaidType = std::multimap<int, ATBPrepaid>; using TariffPrepaidType = std::multimap<int, ATBPrepaid>;
using TariffCarryOverType = std::multimap<int, ATBCarryOver>; using TariffCarryOverType = std::multimap<int, ATBCarryOver>;
using TariffDurationType = std::multimap<int, ATBDuration>; using TariffDurationType = std::multimap<int, ATBDuration>;
using TariffServiceType = std::multimap<int, ATBTariffService>;
using TariffOutOfServiceType = std::multimap<int, ATBTariffOutOfService>;
using ATBTariffPrepaidType = std::multimap<int, ATBTariffPrepaid>;
using ATBTariffCarryOverType = std::multimap<int, ATBTariffCarryOver>;
ATBProject project; ATBProject project;
ATBCurrency Currency; ATBCurrency Currency;
@ -59,7 +66,7 @@ public:
multimap<int, ATBPaymentRate> PaymentRate; multimap<int, ATBPaymentRate> PaymentRate;
SpecialDaysWorktimeType SpecialDaysWorktime; SpecialDaysWorktimeType SpecialDaysWorktime;
SpecialDaysType SpecialDays; SpecialDaysType SpecialDays;
multimap<int, ATBWeekDays> WeekDays; multimap<Qt::DayOfWeek, ATBWeekDay> WeekDays;
multimap<int, ATBPeriodYear> YearPeriod; multimap<int, ATBPeriodYear> YearPeriod;
multimap<int, ATBWeekDaysWorktime> WeekDaysWorktime; multimap<int, ATBWeekDaysWorktime> WeekDaysWorktime;
ATBPaymentOptionType PaymentOption; ATBPaymentOptionType PaymentOption;
@ -72,6 +79,11 @@ public:
TariffInterpolationType TariffInterpolations; TariffInterpolationType TariffInterpolations;
TariffPrepaidType TariffPrepaidOptions; TariffPrepaidType TariffPrepaidOptions;
TariffCarryOverType TariffCarryOverOptions; TariffCarryOverType TariffCarryOverOptions;
TariffServiceType TariffServices;
TariffOutOfServiceType TariffOutOfServices;
ATBTariffPrepaidType TariffPrepaids;
ATBTariffCarryOverType TariffCarryOvers;
QStringList TariffIncludes;
/// <summary> /// <summary>
/// Parse JSON string /// Parse JSON string
@ -112,6 +124,9 @@ public:
std::optional<ATBWeekDaysWorktime> getWeekDayWorkTime(QTime const &time, Qt::DayOfWeek dayOfWeek); std::optional<ATBWeekDaysWorktime> getWeekDayWorkTime(QTime const &time, Qt::DayOfWeek dayOfWeek);
std::optional<QVector<ATBWeekDaysWorktime>> getAllWeekDayWorkTimes(); std::optional<QVector<ATBWeekDaysWorktime>> getAllWeekDayWorkTimes();
QStringList const &getTariffIncludes() const { return TariffIncludes; }
QStringList &getTariffIncludes() { return TariffIncludes; }
std::optional<QDateTime> prepaidStart(QDateTime const &start, int prepaid_option_id); std::optional<QDateTime> prepaidStart(QDateTime const &start, int prepaid_option_id);
int getPaymentOptionIndex(PERMIT_TYPE permitType); int getPaymentOptionIndex(PERMIT_TYPE permitType);
int getPaymentOptionIndex(PERMIT_TYPE permitType) const; int getPaymentOptionIndex(PERMIT_TYPE permitType) const;
@ -126,3 +141,15 @@ private:
QVector<ATBPaymentOption> currentPaymentOptions; QVector<ATBPaymentOption> currentPaymentOptions;
}; };
bool previousDayHoliday(Configuration const &cfg, QDateTime const &t);
bool isHoliday(Configuration const &cfg, QDateTime const &t);
int getPaymentOptionIndex(Configuration const &cfg, QDateTime const& dt = QDateTime::currentDateTime());
ATBWeekDay parseWeekDay(Configuration &cfg,
rapidjson::GenericMemberIterator<false,
rapidjson::UTF8<char>,
rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>> k,
QString const &innerObjName,
Qt::DayOfWeek weekDay,
QString const &weekDayName);

View File

@ -22,7 +22,8 @@ enum MemberType
ProductType = 0x0F, ProductType = 0x0F,
InterpolationType = 0x10, InterpolationType = 0x10,
PrepaidType = 0x11, PrepaidType = 0x11,
CarryOverType = 0x12 CarryOverType = 0x12,
IncludesType = 0x13
}; };
#endif // MEMBER_TYPE_H_INCLUDED #endif // MEMBER_TYPE_H_INCLUDED

View File

@ -6,7 +6,8 @@ enum PaymentMethod {
Progressive = 0x01, Progressive = 0x01,
Degressive = 0x02, Degressive = 0x02,
Linear = 0x03, Linear = 0x03,
Steps = 0x04 Steps = 0x04,
Unified = 0x05
}; };
#endif // PAYMENT_METHOD_H_INCLUDED #endif // PAYMENT_METHOD_H_INCLUDED

View File

@ -25,6 +25,7 @@ public:
pop_max_time = 0; pop_max_time = 0;
pop_min_price = 0; pop_min_price = 0;
pop_max_price = 0; pop_max_price = 0;
pop_max_price_save = 0;
pop_carry_over = -1; pop_carry_over = -1;
pop_carry_over_option_id = -1; pop_carry_over_option_id = -1;
pop_prepaid_option_id = -1; pop_prepaid_option_id = -1;
@ -38,8 +39,13 @@ public:
pop_daily_card_price = -1; pop_daily_card_price = -1;
pop_business_hours = -1; pop_business_hours = -1;
pop_time_step_config = -1; pop_time_step_config = -1;
pop_use_only_upto_datetime = ""; pop_use_only_upto_datetime = ""; // deprecated
pop_use_only_for_duration = 0; pop_use_only_for_duration = 0; // deprecated
pop_plus_steps = 1; // +: jump <x=1> steps forward
pop_plus_steps_saved = 1;
pop_minus_steps = 1; // -: jump <x=1> steps backward
pop_allow_overpay = false;
pop_apply_carry_over_to_ticket_endtime = false;
} }
int pop_id; int pop_id;
@ -56,6 +62,7 @@ public:
double pop_max_time; double pop_max_time;
double pop_min_price; double pop_min_price;
double pop_max_price; double pop_max_price;
double pop_max_price_save;
int pop_carry_over; int pop_carry_over;
int pop_carry_over_option_id; int pop_carry_over_option_id;
bool pop_truncate_last_interpolation_step; bool pop_truncate_last_interpolation_step;
@ -69,6 +76,11 @@ public:
int pop_time_step_config; int pop_time_step_config;
bool pop_accumulate_prices; bool pop_accumulate_prices;
bool pop_accumulate_durations; bool pop_accumulate_durations;
int pop_plus_steps;
int pop_plus_steps_saved;
int pop_minus_steps;
bool pop_allow_overpay;
bool pop_apply_carry_over_to_ticket_endtime;
struct ATBMaxDateTime { struct ATBMaxDateTime {
int direction; int direction;

View File

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

View File

@ -3,6 +3,111 @@
#include <QTime> #include <QTime>
#include "time_range.h"
enum class ApplyCarryOver {
NEVER = 0,
MATCH_PREV_DAY = 1,
MATCH_NEXT_DAY = 2,
ALWAYS = 3
};
struct ATBTariffCarryOver {
int m_id;
QString m_weekDay;
TimeRange m_range;
QDate m_date;
ApplyCarryOver m_carryOverIf;
explicit ATBTariffCarryOver()
: m_id(-1)
, m_carryOverIf(ApplyCarryOver::NEVER) {
}
void setCarryOverIf(QString const &coif) {
if (coif == "never") {
m_carryOverIf = ApplyCarryOver::NEVER;
} else
if (coif == "match_prev_day") {
m_carryOverIf = ApplyCarryOver::MATCH_PREV_DAY;
} else
if (coif == "match_next_day") {
m_carryOverIf = ApplyCarryOver::MATCH_NEXT_DAY;
} else
if (coif == "always") {
m_carryOverIf = ApplyCarryOver::ALWAYS;
} else {
qCritical() << __func__ << ":" << __LINE__ << "ERROR unknown carry over application" << coif;
}
}
ApplyCarryOver carryOverIf() const {
return m_carryOverIf;
}
QString carryOverIfStr() const {
if (m_carryOverIf == ApplyCarryOver::NEVER) {
return "never";
}
if (m_carryOverIf == ApplyCarryOver::ALWAYS) {
return "always";
}
if (m_carryOverIf == ApplyCarryOver::MATCH_PREV_DAY) {
return "match prev day";
}
if (m_carryOverIf == ApplyCarryOver::MATCH_NEXT_DAY) {
return "match next day";
}
return QString("ERROR unknown carry over application: %1").arg(static_cast<int>(m_carryOverIf));
}
int computeMinutesUntilCarryOverEnd(QDateTime const &dt) {
int minutes = 0;
QString end = m_range.m_end.toString(Qt::ISODate);
if (end == "24:00:00") {
// note: this did not work
// QDateTime t(dt.addDays(1));
// t.setTime(QTime(0,0,0));
// dt: 2024-10-27T00:00:00 EEST, but t: 2024-10-28T00:00:00 EET (!)
// so the difference is 1500 instead of 1440
// reason: change from summer to winter time
// compute minutes directly
if (dt.time().isValid()) {
minutes = 1440 - (dt.time().hour() * 60 + dt.time().minute());
}
} else {
QTime t(QTime::fromString(end, Qt::ISODate));
if (t.isValid() && dt.time().isValid()) {
minutes = (t.hour() * 60 + t.minute()) - (dt.time().hour() * 60 + dt.time().minute());
}
}
if (minutes < 0 || minutes > m_range.m_duration) {
minutes = 0;
}
// qCritical() << __func__ << ":" << __LINE__ << "minutes" << minutes;
return minutes;
}
friend QDebug operator<<(QDebug debug, ATBTariffCarryOver const &co) {
QDebugStateSaver saver(debug);
debug.nospace()
<< "\nTariffCarryOver:\n"
<< " week day: " << co.m_weekDay << "\n"
<< " date: " << co.m_date.toString(Qt::ISODate) << "\n"
<< " id: " << co.m_id << "\n"
<< " start: " << co.m_range.m_start << "\n"
<< " end: " << co.m_range.m_end << "\n"
<< " duration: " << co.m_range.m_duration << "\n"
<< " carry over if: " << co.carryOverIfStr() << endl;
return debug;
}
};
struct ATBCarryOver { struct ATBCarryOver {
struct week { struct week {
int day; int day;
@ -15,6 +120,19 @@ struct ATBCarryOver {
int id; int id;
explicit ATBCarryOver()
: id(-1) {
for (int i = 0 ; i < 8; ++i) {
carryover[i].day = -1;
carryover[i].seemless = false;
carryover[i].never = false;
carryover[i].static_start = QTime(23, 59, 59);
carryover[i].static_end = QTime(0, 0, 0);
carryover[i].duration = -1;
}
}
friend QDebug operator<<(QDebug debug, ATBCarryOver const &co) { friend QDebug operator<<(QDebug debug, ATBCarryOver const &co) {
QDebugStateSaver saver(debug); QDebugStateSaver saver(debug);
@ -31,21 +149,21 @@ struct ATBCarryOver {
<< " day: " << co.carryover[(int)Qt::Tuesday].day << "\n" << " day: " << co.carryover[(int)Qt::Tuesday].day << "\n"
<< " static_start: " << co.carryover[(int)Qt::Tuesday].static_start.toString(Qt::ISODate) << "\n" << " static_start: " << co.carryover[(int)Qt::Tuesday].static_start.toString(Qt::ISODate) << "\n"
<< " static_end: " << co.carryover[(int)Qt::Tuesday].static_end.toString(Qt::ISODate) << "\n" << " static_end: " << co.carryover[(int)Qt::Tuesday].static_end.toString(Qt::ISODate) << "\n"
<< " duration: " << co.carryover[(int)Qt::Monday].duration << "\n" << " duration: " << co.carryover[(int)Qt::Tuesday].duration << "\n"
<< " anytime: " << co.carryover[(int)Qt::Tuesday].seemless << "\n" << " anytime: " << co.carryover[(int)Qt::Tuesday].seemless << "\n"
<< " never: " << co.carryover[(int)Qt::Tuesday].never << "\n" << " never: " << co.carryover[(int)Qt::Tuesday].never << "\n"
<< " **** Wednesday **** \n" << " **** Wednesday **** \n"
<< " day: " << co.carryover[(int)Qt::Wednesday].day << "\n" << " day: " << co.carryover[(int)Qt::Wednesday].day << "\n"
<< " static_start: " << co.carryover[(int)Qt::Wednesday].static_start.toString(Qt::ISODate) << "\n" << " static_start: " << co.carryover[(int)Qt::Wednesday].static_start.toString(Qt::ISODate) << "\n"
<< " static_end: " << co.carryover[(int)Qt::Wednesday].static_end.toString(Qt::ISODate) << "\n" << " static_end: " << co.carryover[(int)Qt::Wednesday].static_end.toString(Qt::ISODate) << "\n"
<< " duration: " << co.carryover[(int)Qt::Monday].duration << "\n" << " duration: " << co.carryover[(int)Qt::Wednesday].duration << "\n"
<< " anytime: " << co.carryover[(int)Qt::Wednesday].seemless << "\n" << " anytime: " << co.carryover[(int)Qt::Wednesday].seemless << "\n"
<< " never: " << co.carryover[(int)Qt::Wednesday].never << "\n" << " never: " << co.carryover[(int)Qt::Wednesday].never << "\n"
<< " **** Thursday **** \n" << " **** Thursday **** \n"
<< " day: " << co.carryover[(int)Qt::Thursday].day << "\n" << " day: " << co.carryover[(int)Qt::Thursday].day << "\n"
<< " static_start: " << co.carryover[(int)Qt::Thursday].static_start.toString(Qt::ISODate) << "\n" << " static_start: " << co.carryover[(int)Qt::Thursday].static_start.toString(Qt::ISODate) << "\n"
<< " static_end: " << co.carryover[(int)Qt::Thursday].static_end.toString(Qt::ISODate) << "\n" << " static_end: " << co.carryover[(int)Qt::Thursday].static_end.toString(Qt::ISODate) << "\n"
<< " duration: " << co.carryover[(int)Qt::Monday].duration << "\n" << " duration: " << co.carryover[(int)Qt::Thursday].duration << "\n"
<< " anytime: " << co.carryover[(int)Qt::Thursday].seemless << "\n" << " anytime: " << co.carryover[(int)Qt::Thursday].seemless << "\n"
<< " never: " << co.carryover[(int)Qt::Thursday].never << "\n" << " never: " << co.carryover[(int)Qt::Thursday].never << "\n"
<< " **** Friday **** \n" << " **** Friday **** \n"
@ -58,14 +176,14 @@ struct ATBCarryOver {
<< " day: " << co.carryover[(int)Qt::Saturday].day << "\n" << " day: " << co.carryover[(int)Qt::Saturday].day << "\n"
<< " static_start: " << co.carryover[(int)Qt::Saturday].static_start.toString(Qt::ISODate) << "\n" << " static_start: " << co.carryover[(int)Qt::Saturday].static_start.toString(Qt::ISODate) << "\n"
<< " static_end: " << co.carryover[(int)Qt::Saturday].static_end.toString(Qt::ISODate) << "\n" << " static_end: " << co.carryover[(int)Qt::Saturday].static_end.toString(Qt::ISODate) << "\n"
<< " duration: " << co.carryover[(int)Qt::Monday].duration << "\n" << " duration: " << co.carryover[(int)Qt::Saturday].duration << "\n"
<< " anytime: " << co.carryover[(int)Qt::Saturday].seemless << "\n" << " anytime: " << co.carryover[(int)Qt::Saturday].seemless << "\n"
<< " never: " << co.carryover[(int)Qt::Saturday].never << "\n" << " never: " << co.carryover[(int)Qt::Saturday].never << "\n"
<< " **** Sunday **** \n" << " **** Sunday **** \n"
<< " day: " << co.carryover[(int)Qt::Sunday].day << "\n" << " day: " << co.carryover[(int)Qt::Sunday].day << "\n"
<< " static_start: " << co.carryover[(int)Qt::Sunday].static_start.toString(Qt::ISODate) << "\n" << " static_start: " << co.carryover[(int)Qt::Sunday].static_start.toString(Qt::ISODate) << "\n"
<< " static_end: " << co.carryover[(int)Qt::Sunday].static_end.toString(Qt::ISODate) << "\n" << " static_end: " << co.carryover[(int)Qt::Sunday].static_end.toString(Qt::ISODate) << "\n"
<< " duration: " << co.carryover[(int)Qt::Monday].duration << "\n" << " duration: " << co.carryover[(int)Qt::Sunday].duration << "\n"
<< " anytime: " << co.carryover[(int)Qt::Sunday].seemless << "\n" << " anytime: " << co.carryover[(int)Qt::Sunday].seemless << "\n"
<< " never: " << co.carryover[(int)Qt::Sunday].never << "\n"; << " never: " << co.carryover[(int)Qt::Sunday].never << "\n";

View File

@ -0,0 +1,69 @@
#ifndef ATB_TARIFF_CARRYOVER_SETTINGS_H_INCLUDED
#define ATB_TARIFF_CARRYOVER_SETTINGS_H_INCLUDED
#include <QDebug>
#include <QDateTime>
#include <functional>
struct ATBTariffCarryOverSettings {
// parking time limit not violated: return false, otherwise: return true.
using ParkingTimeLimitChecker = std::function<bool(ATBTariffCarryOverSettings const&,
QDateTime const &startTime,
QDateTime const &endTime,
int paymentOptionIndex)>;
int m_duration;
QTime m_start;
QTime m_end;
ParkingTimeLimitChecker m_parkingTimeLimitChecker;
QTime m_parking_time_limit;
QTime m_about_to_exceed_parking_time_limit;
explicit ATBTariffCarryOverSettings()
: m_duration(0)
, m_start(QTime())
, m_end(QTime())
, m_parkingTimeLimitChecker([](ATBTariffCarryOverSettings const&,
QDateTime const&, QDateTime const&, int) { return false; })
, m_parking_time_limit(QTime())
, m_about_to_exceed_parking_time_limit(QTime()) {}
explicit ATBTariffCarryOverSettings(int duration, QTime const &start,
QTime const &end,
QTime const &parking_time_limit,
QTime const &about_to_exceed_parking_time_limit,
ParkingTimeLimitChecker parkingTimeLimitChecker)
: m_duration(duration)
, m_start(start)
, m_end(end)
, m_parkingTimeLimitChecker(std::move(parkingTimeLimitChecker))
, m_parking_time_limit(parking_time_limit)
, m_about_to_exceed_parking_time_limit(about_to_exceed_parking_time_limit) {
}
bool parkingTimeLimitExceeded(QDateTime const &startTime,
QDateTime const &endTime,
int paymentOptionIndex) const {
return m_parkingTimeLimitChecker(*this, startTime, endTime, paymentOptionIndex);
}
QTime const &parkingTimeLimit() const { return m_parking_time_limit; }
QTime &parkingTimeLimit() { return m_parking_time_limit; }
friend QDebug operator<<(QDebug debug, ATBTariffCarryOverSettings const &co) {
QDebugStateSaver saver(debug);
debug.nospace()
<< " duration: " << co.m_duration << "\n"
<< " start: " << co.m_start.toString(Qt::ISODate) << "\n"
<< " end: " << co.m_end.toString(Qt::ISODate) << "\n"
<< " parking_time_limit: " << co.m_parking_time_limit.toString(Qt::ISODate) << endl;
return debug;
}
};
#endif // ATB_TARIFF_CARRYOVER_SETTINGS_H_INCLUDED

View File

@ -1,4 +1,3 @@
#pragma once
#include <variant> #include <variant>
#include <cstddef> #include <cstddef>
#include <stdio.h> #include <stdio.h>

View File

@ -14,6 +14,8 @@
void setDebugLevel(int level); void setDebugLevel(int level);
int getDebugLevel(); int getDebugLevel();
#if 0
static void print() { static void print() {
std::cerr << "\n"; std::cerr << "\n";
if (getDebugLevel() == DBG_LEVEL_FATAL) { if (getDebugLevel() == DBG_LEVEL_FATAL) {
@ -75,4 +77,6 @@ static void LOG_FATAL(const Arg1& arg1, const Args&&... args) {
} }
} }
#endif
#endif // TARIFF_LOG_INCLUDED_H #endif // TARIFF_LOG_INCLUDED_H

View File

@ -0,0 +1,79 @@
#ifndef TARIFF_OUT_OF_SERVICE_H_INCLUDED
#define TARIFF_OUT_OF_SERVICE_H_INCLUDED
#include <QDateTime>
#include <QString>
#include "time_range.h"
enum class ApplyOutOfService {
NEVER = 0,
MATCH_PREV_DAY = 1,
MATCH_NEXT_DAY = 2,
ALWAYS = 3
};
struct ATBTariffOutOfService {
int m_id;
QString m_weekDay;
QDate m_date;
TimeRange m_range;
ApplyOutOfService m_outOfServiceIf;
explicit ATBTariffOutOfService()
: m_id(-1)
, m_outOfServiceIf(ApplyOutOfService::NEVER) {
}
void setOutOfServiceIf(QString const &oosif) {
if (oosif == "never") {
m_outOfServiceIf = ApplyOutOfService::NEVER;
} else
if (oosif == "match_prev_day") {
m_outOfServiceIf = ApplyOutOfService::MATCH_PREV_DAY;
} else
if (oosif == "match_next_day") {
m_outOfServiceIf = ApplyOutOfService::MATCH_NEXT_DAY;
} else
if (oosif == "always") {
m_outOfServiceIf = ApplyOutOfService::ALWAYS;
} else {
qCritical() << "ERROR unknown servcie application" << oosif;
}
}
ApplyOutOfService outOfServiceIf() const {
return m_outOfServiceIf;
}
QString outOfServiceIfStr() const {
if (m_outOfServiceIf == ApplyOutOfService::NEVER) {
return "never";
}
if (m_outOfServiceIf == ApplyOutOfService::ALWAYS) {
return "always";
}
if (m_outOfServiceIf == ApplyOutOfService::MATCH_PREV_DAY) {
return "match prev day";
}
if (m_outOfServiceIf == ApplyOutOfService::MATCH_NEXT_DAY) {
return "match next day";
}
return QString("ERROR unknown out of service application: %1").arg(static_cast<int>(m_outOfServiceIf));
}
friend QDebug operator<<(QDebug debug, ATBTariffOutOfService const &oos) {
QDebugStateSaver saver(debug);
debug.nospace()
<< "\nTariffOutOfService:\n"
<< " week day: " << oos.m_weekDay << "\n"
<< " date: " << oos.m_date.toString(Qt::ISODate) << "\n"
<< " id: " << oos.m_id << "\n"
<< " start: " << oos.m_range.m_start << "\n"
<< " end: " << oos.m_range.m_end << "\n"
<< " duration: " << oos.m_range.m_duration << endl;
return debug;
}
};
#endif // TARIFF_SERVICE_H_INCLUDED

View File

@ -19,7 +19,9 @@ enum class PERMIT_TYPE : quint8 {
SHORT_TERM_PARKING_CAMPER=12, SHORT_TERM_PARKING_CAMPER=12,
DAY_TICKET_PKW=13, DAY_TICKET_PKW=13,
DAY_TICKET_BUS=14, DAY_TICKET_BUS=14,
DAY_TICKET_CAMPER=15 DAY_TICKET_CAMPER=15,
FREE_TICKET=16,
PRODUCT_MAX
}; };
struct PermitType { struct PermitType {
@ -73,6 +75,9 @@ struct PermitType {
case 15: case 15:
m_permitType = PERMIT_TYPE::DAY_TICKET_CAMPER; m_permitType = PERMIT_TYPE::DAY_TICKET_CAMPER;
break; break;
case 16:
m_permitType = PERMIT_TYPE::FREE_TICKET;
break;
default: default:
m_permitType = PERMIT_TYPE::INVALID; m_permitType = PERMIT_TYPE::INVALID;
} }
@ -116,6 +121,8 @@ struct PermitType {
return 14; return 14;
case PERMIT_TYPE::DAY_TICKET_CAMPER: case PERMIT_TYPE::DAY_TICKET_CAMPER:
return 15; return 15;
case PERMIT_TYPE::FREE_TICKET:
return 16;
default: default:
break; break;
} }
@ -132,9 +139,6 @@ struct PermitType {
if (permitTypeStr == "DAY_TICKET_CHILD") { if (permitTypeStr == "DAY_TICKET_CHILD") {
return PERMIT_TYPE::DAY_TICKET_CHILD; return PERMIT_TYPE::DAY_TICKET_CHILD;
} else } else
if (permitTypeStr == "DAY_TICKET_ADULT") {
return PERMIT_TYPE::DAY_TICKET_ADULT;
} else
if (permitTypeStr == "DAY_TICKET_TEEN") { if (permitTypeStr == "DAY_TICKET_TEEN") {
return PERMIT_TYPE::DAY_TICKET_TEEN; return PERMIT_TYPE::DAY_TICKET_TEEN;
} else } else
@ -170,6 +174,9 @@ struct PermitType {
} else } else
if (permitTypeStr == "DAY_TICKET_CAMPER") { if (permitTypeStr == "DAY_TICKET_CAMPER") {
return PERMIT_TYPE::DAY_TICKET_CAMPER; return PERMIT_TYPE::DAY_TICKET_CAMPER;
} else
if (permitTypeStr == "FREE_TICKET") {
return PERMIT_TYPE::FREE_TICKET;
} }
return PERMIT_TYPE::INVALID; return PERMIT_TYPE::INVALID;
@ -207,6 +214,8 @@ struct PermitType {
return QString("DAY_TICKET_BUS"); return QString("DAY_TICKET_BUS");
case PERMIT_TYPE::DAY_TICKET_CAMPER: case PERMIT_TYPE::DAY_TICKET_CAMPER:
return QString("DAY_TICKET_CAMPER"); return QString("DAY_TICKET_CAMPER");
case PERMIT_TYPE::FREE_TICKET:
return QString("FREE_TICKET");
default: default:
break; break;
} }
@ -245,6 +254,8 @@ struct PermitType {
return QString("DAY_TICKET_BUS"); return QString("DAY_TICKET_BUS");
case PERMIT_TYPE::DAY_TICKET_CAMPER: case PERMIT_TYPE::DAY_TICKET_CAMPER:
return QString("DAY_TICKET_CAMPER"); return QString("DAY_TICKET_CAMPER");
case PERMIT_TYPE::FREE_TICKET:
return QString("FREE_TICKET");
default: default:
break; break;
} }

View File

@ -1,17 +1,114 @@
#ifndef TARIFF_PREPAID_H_INCLUDED #ifndef TARIFF_PREPAID_H_INCLUDED
#define TARIFF_PREPAID_H_INCLUDED #define TARIFF_PREPAID_H_INCLUDED
#include <QTime> #include <QDateTime>
#include <QString> #include <QString>
#include "time_range.h"
enum class ApplyPrepaid {
NEVER = 0,
MATCH_PREV_DAY = 1,
MATCH_NEXT_DAY = 2,
ALWAYS = 3
};
struct ATBTariffPrepaid {
int m_id;
QString m_weekDay;
QDate m_date;
TimeRange m_range;
ApplyPrepaid m_prepaidIf;
explicit ATBTariffPrepaid()
: m_id(-1)
, m_prepaidIf(ApplyPrepaid::NEVER) {
}
void setPrepaidIf(QString const &ppif) {
if (ppif == "never") {
m_prepaidIf = ApplyPrepaid::NEVER;
} else
if (ppif == "match_prev_day") {
m_prepaidIf = ApplyPrepaid::MATCH_PREV_DAY;
} else
if (ppif == "match_next_day") {
m_prepaidIf = ApplyPrepaid::MATCH_NEXT_DAY;
} else
if (ppif == "always") {
m_prepaidIf = ApplyPrepaid::ALWAYS;
} else {
qCritical() << __func__ << ":" << __LINE__ << "ERROR unknown carry over application" << ppif;
}
}
ApplyPrepaid prepaidIf() const {
return m_prepaidIf;
}
QString prepaidIfStr() const {
if (m_prepaidIf == ApplyPrepaid::NEVER) {
return "never";
}
if (m_prepaidIf == ApplyPrepaid::ALWAYS) {
return "always";
}
if (m_prepaidIf == ApplyPrepaid::MATCH_PREV_DAY) {
return "match prev day";
}
if (m_prepaidIf == ApplyPrepaid::MATCH_NEXT_DAY) {
return "match next day";
}
return QString("ERROR unknown prepaid application: %1").arg(static_cast<int>(m_prepaidIf));
}
friend QDebug operator<<(QDebug debug, ATBTariffPrepaid const &pp) {
QDebugStateSaver saver(debug);
debug.nospace()
<< "\nTariffPrepaid:\n"
<< " week day: " << pp.m_weekDay << "\n"
<< " date: " << pp.m_date.toString(Qt::ISODate) << "\n"
<< " id: " << pp.m_id << "\n"
<< " start: " << pp.m_range.m_start << "\n"
<< " end: " << pp.m_range.m_end << "\n"
<< " duration: " << pp.m_range.m_duration << "\n"
<< " prepaid if: " << pp.prepaidIfStr() << endl;
return debug;
}
};
// deprecated
struct ATBPrepaid { struct ATBPrepaid {
explicit ATBPrepaid() = default;
int id; int id;
bool anytime; bool anytime;
bool never; bool never;
QTime static_start; QTime static_start;
QTime static_end; QTime static_end;
struct week {
int day;
QTime static_start;
QTime static_end;
int duration;
} prepaid[8];
explicit ATBPrepaid()
: id(-1)
, anytime(false)
, never(false)
, static_start(QTime(23, 59, 59))
, static_end(QTime(0, 0, 0)) {
for (int i = 0 ; i < 8; ++i) {
prepaid[i].day = -1;
prepaid[i].static_start = QTime(23, 59, 59);
prepaid[i].static_end = QTime(0, 0, 0);
prepaid[i].duration = -1;
}
}
friend QDebug operator<<(QDebug debug, ATBPrepaid const &pp) { friend QDebug operator<<(QDebug debug, ATBPrepaid const &pp) {
QDebugStateSaver saver(debug); QDebugStateSaver saver(debug);
@ -20,7 +117,41 @@ struct ATBPrepaid {
<< " static_start: " << pp.static_start.toString(Qt::ISODate) << "\n" << " static_start: " << pp.static_start.toString(Qt::ISODate) << "\n"
<< " static_end: " << pp.static_end.toString(Qt::ISODate) << "\n" << " static_end: " << pp.static_end.toString(Qt::ISODate) << "\n"
<< " anytime: " << pp.anytime << "\n" << " anytime: " << pp.anytime << "\n"
<< " never: " << pp.never << "\n"; << " never: " << pp.never << "\n"
<< " **** Monday **** \n"
<< " day: " << pp.prepaid[(int)Qt::Monday].day << "\n"
<< " static_start: " << pp.prepaid[(int)Qt::Monday].static_start.toString(Qt::ISODate) << "\n"
<< " static_end: " << pp.prepaid[(int)Qt::Monday].static_end.toString(Qt::ISODate) << "\n"
<< " duration: " << pp.prepaid[(int)Qt::Monday].duration << "\n"
<< " **** Tuesday **** \n"
<< " day: " << pp.prepaid[(int)Qt::Tuesday].day << "\n"
<< " static_start: " << pp.prepaid[(int)Qt::Tuesday].static_start.toString(Qt::ISODate) << "\n"
<< " static_end: " << pp.prepaid[(int)Qt::Tuesday].static_end.toString(Qt::ISODate) << "\n"
<< " duration: " << pp.prepaid[(int)Qt::Tuesday].duration << "\n"
<< " **** Wednesday **** \n"
<< " day: " << pp.prepaid[(int)Qt::Wednesday].day << "\n"
<< " static_start: " << pp.prepaid[(int)Qt::Wednesday].static_start.toString(Qt::ISODate) << "\n"
<< " static_end: " << pp.prepaid[(int)Qt::Wednesday].static_end.toString(Qt::ISODate) << "\n"
<< " duration: " << pp.prepaid[(int)Qt::Wednesday].duration << "\n"
<< " **** Thursday **** \n"
<< " day: " << pp.prepaid[(int)Qt::Thursday].day << "\n"
<< " static_start: " << pp.prepaid[(int)Qt::Thursday].static_start.toString(Qt::ISODate) << "\n"
<< " static_end: " << pp.prepaid[(int)Qt::Thursday].static_end.toString(Qt::ISODate) << "\n"
<< " duration: " << pp.prepaid[(int)Qt::Thursday].duration << "\n"
<< " **** Friday **** \n"
<< " day: " << pp.prepaid[(int)Qt::Friday].day << "\n"
<< " static_start: " << pp.prepaid[(int)Qt::Friday].static_start.toString(Qt::ISODate) << "\n"
<< " static_end: " << pp.prepaid[(int)Qt::Friday].static_end.toString(Qt::ISODate) << "\n"
<< " **** Saturday **** \n"
<< " day: " << pp.prepaid[(int)Qt::Saturday].day << "\n"
<< " static_start: " << pp.prepaid[(int)Qt::Saturday].static_start.toString(Qt::ISODate) << "\n"
<< " static_end: " << pp.prepaid[(int)Qt::Saturday].static_end.toString(Qt::ISODate) << "\n"
<< " duration: " << pp.prepaid[(int)Qt::Saturday].duration << "\n"
<< " **** Sunday **** \n"
<< " day: " << pp.prepaid[(int)Qt::Sunday].day << "\n"
<< " static_start: " << pp.prepaid[(int)Qt::Sunday].static_start.toString(Qt::ISODate) << "\n"
<< " static_end: " << pp.prepaid[(int)Qt::Sunday].static_end.toString(Qt::ISODate) << "\n"
<< " duration: " << pp.prepaid[(int)Qt::Sunday].duration << "\n";
return debug; return debug;
} }

View File

@ -0,0 +1,81 @@
#ifndef TARIFF_SERVICE_H_INCLUDED
#define TARIFF_SERVICE_H_INCLUDED
#include <QDateTime>
#include <QString>
#include "time_range.h"
enum class ApplyService {
NEVER = 0,
MATCH_PREV_DAY = 1,
MATCH_NEXT_DAY = 2,
ALWAYS = 3
};
struct ATBTariffService {
int m_id;
QString m_weekDay;
QDate m_date;
TimeRange m_range;
ApplyService m_serviceIf;
explicit ATBTariffService()
: m_id(-1)
, m_serviceIf(ApplyService::NEVER) {
}
void setServiceIf(QString const &sif) {
if (sif == "never") {
m_serviceIf = ApplyService::NEVER;
} else
if (sif == "match_prev_day") {
m_serviceIf = ApplyService::MATCH_PREV_DAY;
} else
if (sif == "match_next_day") {
m_serviceIf = ApplyService::MATCH_NEXT_DAY;
} else
if (sif == "always") {
m_serviceIf = ApplyService::ALWAYS;
} else {
qCritical() << "ERROR unknown servcie application" << sif;
}
}
ApplyService serviceIf() const {
return m_serviceIf;
}
QString serviceIfStr() const {
if (m_serviceIf == ApplyService::NEVER) {
return "never";
}
if (m_serviceIf == ApplyService::ALWAYS) {
return "always";
}
if (m_serviceIf == ApplyService::MATCH_PREV_DAY) {
return "match prev day";
}
if (m_serviceIf == ApplyService::MATCH_NEXT_DAY) {
return "match next day";
}
return QString("ERROR unknown service application: %1").arg(static_cast<int>(m_serviceIf));
}
friend QDebug operator<<(QDebug debug, ATBTariffService const &ts) {
QDebugStateSaver saver(debug);
debug.nospace()
<< "\nTariffService:\n"
<< " week day: " << ts.m_weekDay << "\n"
<< " date: " << ts.m_date.toString(Qt::ISODate) << "\n"
<< " id: " << ts.m_id << "\n"
<< " start: " << ts.m_range.m_start << "\n"
<< " end: " << ts.m_range.m_end << "\n"
<< " duration: " << ts.m_range.m_duration << "\n"
<< " prepaid if: " << ts.serviceIfStr() << endl;
return debug;
}
};
#endif // TARIFF_SERVICE_H_INCLUDED

View File

@ -0,0 +1,40 @@
#ifndef ATB_TARIFF_SETTINGS_H_INCLUDED
#define ATB_TARIFF_SETTINGS_H_INCLUDED
#include <QDebug>
struct ATBTariffSettings {
int m_max_price;
int m_min_price;
int m_max_time;
int m_min_time;
explicit ATBTariffSettings()
: m_max_price(0)
, m_min_price(0)
, m_max_time(0)
, m_min_time(0) {
}
explicit ATBTariffSettings(int max_price, int min_price, int max_time, int min_time)
: m_max_price(max_price)
, m_min_price(min_price)
, m_max_time(max_time)
, m_min_time(min_time) {
}
friend QDebug operator<<(QDebug debug, ATBTariffSettings const &ts) {
QDebugStateSaver saver(debug);
debug.nospace()
<< " max_price: " << ts.m_max_price << "\n"
<< " min_price: " << ts.m_min_price << "\n"
<< " max_time: " << ts.m_max_time << "\n"
<< " min_time: " << ts.m_min_time << endl;
return debug;
}
};
#endif // ATB_TARIFF_SETTINGS_H_INCLUDED

View File

@ -1,12 +1,46 @@
#ifndef TIME_RANGE_H_INCLUDED #ifndef TIME_RANGE_H_INCLUDED
#define TIME_RANGE_H_INCLUDED #define TIME_RANGE_H_INCLUDED
#include "time_range_header.h" #include "atb_time.h"
#include <QString>
struct TimeRange { struct TimeRange {
public: ATBTime m_start;
bool IsActive; ATBTime m_end;
ATBTimeRange TimeRangeStructure; int m_duration;
explicit TimeRange() = default;
explicit TimeRange(QString const &start, QString const &end, int duration)
: m_start(start)
, m_end(end)
, m_duration(duration) {
}
explicit TimeRange(ATBTime const &start, ATBTime const &end, int duration)
: m_start(start)
, m_end(end)
, m_duration(duration) {
}
explicit TimeRange(TimeRange const &timeRange) {
m_start = timeRange.m_start;
m_end = timeRange.m_end;
m_duration = timeRange.m_duration;
}
TimeRange &operator=(TimeRange && timeRange) {
m_start = std::move(timeRange.m_start);
m_end = std::move(timeRange.m_end);
m_duration = timeRange.m_duration;
return *this;
}
TimeRange &operator=(TimeRange const &timeRange) {
m_start = timeRange.m_start;
m_end = timeRange.m_end;
m_duration = timeRange.m_duration;
return *this;
}
}; };
#endif // TIME_RANGE_H_INCLUDED #endif // TIME_RANGE_H_INCLUDED

View File

@ -3,6 +3,7 @@
#include <ctime> #include <ctime>
#include <iostream> #include <iostream>
#include <cmath> #include <cmath>
#include <optional>
#include "day_of_week.h" #include "day_of_week.h"
#include "configuration.h" #include "configuration.h"
@ -62,6 +63,7 @@ namespace Utilities {
/// <returns></returns> /// <returns></returns>
bool IsYearPeriodActive(Configuration* cfg, struct tm* currentDateTime); bool IsYearPeriodActive(Configuration* cfg, struct tm* currentDateTime);
bool IsYearPeriodActive(Configuration const *cfg, QDateTime const &currentDateTime); bool IsYearPeriodActive(Configuration const *cfg, QDateTime const &currentDateTime);
std::optional<ATBPeriodYear> GetYearPeriodActive(Configuration const *cfg, QDateTime const &currentDateTime);
/// <summary> /// <summary>
/// Check permissions /// Check permissions

View File

@ -1,10 +1,57 @@
#pragma once #include "tariff_settings.h"
#include <string> #include "tariff_carryover_settings.h"
class ATBWeekDays #include <QString>
{ #include <Qt>
public: #include <QDate>
int pdiw_id;
std::string pdiw_label; struct ATBWeekDay {
int pdiw_index; enum WeekDayType {USUAL_WEEKDAY=0, HOLIDAY=1};
Qt::DayOfWeek m_id;
QString m_name;
QDate m_date;
WeekDayType m_type;
ATBTariffSettings m_tariffSettings;
ATBTariffCarryOverSettings m_tariffCarryOverSettings;
explicit ATBWeekDay()
: m_id(Qt::Monday)
, m_name("")
, m_date(QDate())
, m_type(USUAL_WEEKDAY)
, m_tariffSettings()
, m_tariffCarryOverSettings() {}
explicit ATBWeekDay(Qt::DayOfWeek id, QString const &name, WeekDayType type,
QDate const &date,
ATBTariffSettings const &tariffSettings,
ATBTariffCarryOverSettings const &tariffCarryOverSettings)
: m_id(id)
, m_name(name)
, m_date(date)
, m_type(type)
, m_tariffSettings(tariffSettings)
, m_tariffCarryOverSettings(tariffCarryOverSettings) {}
ATBTariffCarryOverSettings &getTariffCarryOverSettings() { return m_tariffCarryOverSettings; }
ATBTariffCarryOverSettings const &getTariffCarryOverSettings() const { return m_tariffCarryOverSettings; }
ATBTariffSettings &getTariffSettings() { return m_tariffSettings; }
ATBTariffSettings const &getTariffSettings() const { return m_tariffSettings; }
friend QDebug operator<<(QDebug debug, ATBWeekDay const &wd) {
QDebugStateSaver saver(debug);
debug.nospace()
<< " id: " << (int)wd.m_id << "\n"
<< " name: " << wd.m_name << "\n"
<< " type: " << (int)wd.m_type << "\n\n"
<< " tariff settings: " << "\n"
<< wd.m_tariffSettings << "\n"
<< "tariff carryover settings: " << "\n"
<< wd.m_tariffCarryOverSettings << endl;
return debug;
}
}; };

File diff suppressed because it is too large Load Diff

View File

@ -35,7 +35,8 @@ SOURCES += \
src/tariff_log.cpp \ src/tariff_log.cpp \
src/calculate_price.cpp \ src/calculate_price.cpp \
src/ticket.cpp \ src/ticket.cpp \
src/tariff_global_defines.cpp src/tariff_global_defines.cpp \
src/atb_time.cpp
HEADERS += \ HEADERS += \
include/mobilisis/calculator_functions.h \ include/mobilisis/calculator_functions.h \
@ -89,7 +90,10 @@ HEADERS += \
include/mobilisis/tariff_interpolation.h \ include/mobilisis/tariff_interpolation.h \
include/mobilisis/tariff_prepaid.h \ include/mobilisis/tariff_prepaid.h \
include/mobilisis/tariff_carryover.h \ include/mobilisis/tariff_carryover.h \
include/mobilisis/tariff_global_defines.h include/mobilisis/tariff_global_defines.h \
include/mobilisis/atb_time.h \
include/mobilisis/tariff_service.h \
include/mobilisis/tariff_out_of_service.h
OTHER_FILES += src/main.cpp \ OTHER_FILES += src/main.cpp \
../tariffs/tariff_korneuburg.json \ ../tariffs/tariff_korneuburg.json \

151
library/src/atb_time.cpp Normal file
View File

@ -0,0 +1,151 @@
#include "atb_time.h"
#include <QDebugStateSaver>
QDateTime const ATBTime::m_end(QDateTime::fromString("1970-01-02T00:00:00", Qt::ISODate));
ATBTime::ATBTime()
: m_time(QDateTime::fromString("1970-01-01T00:00:00", Qt::ISODate)) {
}
ATBTime::ATBTime(int h, int m, int /*s*/, int /*ms*/)
: m_time(QDateTime::fromString("1970-01-01T00:00:00", Qt::ISODate)) {
if (h == 24 && m == 0) {
m_time = m_end;
} else {
QTime const t(h, m, 0, 0);
m_time.setTime(t);
}
}
ATBTime::ATBTime(QString const &t)
: m_time(QDateTime::fromString("1970-01-01T00:00:00")) {
if (t == "24:00:00") {
m_time = m_end;
} else {
QTime tmp = QTime::fromString(t, Qt::ISODate);
if (tmp.isValid()) {
m_time.setTime(tmp);
}
}
}
ATBTime::ATBTime(QTime const &t)
: m_time(QDateTime::fromString("1970-01-01T00:00:00")) {
m_time.setTime(t);
}
QTime ATBTime::addMSecs(int ms) const {
return m_time.time().addMSecs(ms);
}
QTime ATBTime::addMSecs(int ms) {
QTime t = m_time.time();
t = t.addMSecs(ms);
m_time.setTime(t);
return t;
}
QTime ATBTime::addSecs(int s) const {
return m_time.time().addSecs(s);
}
QTime ATBTime::addSecs(int s) {
QTime t = m_time.time();
t = t.addSecs(s);
m_time.setTime(t);
return t;
}
constexpr QTime ATBTime::fromMSecsSinceStartOfDay(int msecs) {
return QTime::fromMSecsSinceStartOfDay(msecs);
}
QTime ATBTime::fromString(QString const &string, Qt::DateFormat format) {
return QTime::fromString(string, format);
}
QTime ATBTime::fromString(QString const &string, QString const &format) {
return QTime::fromString(string, format);
}
bool ATBTime::isValid(int h, int m, int s, int ms) {
return QTime(h, m, s, ms).isValid();
}
int ATBTime::msecsSinceStartOfDay() const {
return m_time.time().msecsSinceStartOfDay();
}
bool ATBTime::setHMS(int h, int m, int s, int ms) {
if (isValid(h, m, s, ms)) {
QTime t(h, m, s, ms);
m_time.setTime(t);
return true;
}
return false;
}
QString ATBTime::toString(Qt::DateFormat format) const {
if (m_time == m_end) {
return "24:00:00";
}
return m_time.time().toString(format);
}
bool operator!=(const ATBTime &lhs, const ATBTime &rhs) noexcept {
return lhs.m_time.time() != rhs.m_time.time();
}
bool operator<=(const ATBTime &lhs, const ATBTime &rhs) noexcept {
if (rhs.m_time == rhs.m_end) {
return true;
}
return lhs.m_time.time() <= rhs.m_time.time();
}
bool operator>=(const ATBTime &lhs, const ATBTime &rhs) noexcept {
return lhs.m_time.time() >= rhs.m_time.time();
}
bool operator<(const ATBTime &lhs, const ATBTime &rhs) noexcept {
if (rhs.m_time == rhs.m_end) {
return true;
}
return lhs.m_time.time() < rhs.m_time.time();
}
bool operator>(const ATBTime &lhs, const ATBTime &rhs) noexcept {
return lhs.m_time.time() > rhs.m_time.time();
}
bool operator==(const ATBTime &lhs, const ATBTime &rhs) noexcept {
return lhs.m_time.time() == rhs.m_time.time();
}
QDebug &operator<<(QDebug &debug, ATBTime const &time) {
QDebugStateSaver saver(debug);
if (time.m_time == time.m_end) {
debug.nospace() << QString("24:00:00");
} else {
debug.nospace() << time.m_time.time().toString(Qt::ISODate);
}
return debug;
}
QDataStream &operator<<(QDataStream &out, ATBTime const &time) {
if (time.m_time == time.m_end) {
out << QString("24:00:00");
} else {
out << time.m_time.time();
}
return out;
}
QDataStream &operator>>(QDataStream &in, ATBTime &time) {
QTime t;
in >> t;
time.m_time.setTime(t);
return in;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,762 @@
#include "calculate_price.h"
#include "configuration.h"
#include "calculator_functions.h"
#include "payment_option.h"
#include "utilities.h"
#include <QFile>
#include <QFileInfo>
#include <QDateTime>
#include <QDebug>
#include <QList>
QString const CalcState::SUCCESS = "SUCCESS";
QString const CalcState::ERROR_PARSING_ZONE_NR = "ERROR_PARSING_ZONE_NR";
QString const CalcState::ERROR_LOADING_TARIFF = "ERROR_LOADING_TARIFF";
QString const CalcState::ERROR_PARSING_TARIFF = "ERROR_PARSING_TARIFF";
QString const CalcState::NEGATIVE_PARKING_TIME = "NEGATIVE_PARKING_TIME";
QString const CalcState::INVALID_START_DATE = "INVALID_START_DATE";
QString const CalcState::WRONG_PARAM_VALUES = "WRONG_PARAM_VALUES";
QString const CalcState::WRONG_ISO_TIME_FORMAT = "WRONG_ISO_TIME_FORMAT";
QString const CalcState::ABOVE_MAX_PARKING_TIME = "ABOVE_MAX_PARKING_TIME";
QString const CalcState::BELOW_MIN_PARKING_TIME = "BELOW_MIN_PARKING_TIME";
QString const CalcState::BELOW_MIN_PARKING_PRICE = "BELOW_MIN_PARKING_PRICE";
QString const CalcState::ABOVE_MAX_PARKING_PRICE = "ABOVE_MAX_PARKING_PRICE";
QString const CalcState::OVERPAID = "OVERPAID";
QString const CalcState::OUTSIDE_ALLOWED_PARKING_TIME = "OUTSIDE_ALLOWED_PARKING_TIME";
QList<int> CALCULATE_LIBRARY_API get_time_steps(Configuration *cfg) {
return Calculator::GetInstance().GetTimeSteps(cfg);
}
int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration const *cfg,
PERMIT_TYPE permitType,
int paymentOptionIndex) {
int minTime = 0;
switch(permitType) {
case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281)
QList<int> const tsteps = Calculator::GetInstance().GetTimeSteps((Configuration *)cfg, paymentOptionIndex);
Q_UNUSED(tsteps);
minTime = cfg->getPaymentOptions(paymentOptionIndex).pop_min_time;
} break;
case PERMIT_TYPE::DAY_TICKET_ADULT: {
} break;
case PERMIT_TYPE::DAY_TICKET_TEEN: {
} break;
case PERMIT_TYPE::DAY_TICKET_CHILD: {
} break;
default:
// for each new sell-procedure, recomute the timesteps. implicitly, set
// the minimal parking time.
Calculator::GetInstance().ResetTimeSteps(paymentOptionIndex);
Calculator::GetInstance().GetTimeSteps((Configuration *)cfg, paymentOptionIndex);
minTime = qRound(cfg->getPaymentOptions(paymentOptionIndex).pop_min_time);
}
return minTime;
}
int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration const *cfg,
PERMIT_TYPE permitType,
int paymentOptionIndex) {
int maxTime = 0;
switch(permitType) {
case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281)
maxTime = cfg->getPaymentOptions(paymentOptionIndex).pop_max_time;
} break;
case PERMIT_TYPE::DAY_TICKET_ADULT: {
} break;
case PERMIT_TYPE::DAY_TICKET_TEEN: {
} break;
case PERMIT_TYPE::DAY_TICKET_CHILD: {
} break;
default: ;
}
return maxTime;
}
int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg,
PERMIT_TYPE permitType,
int paymentOptionIndex,
QDateTime const &start) {
int minPrice = -1;
switch(permitType) {
case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281)
minPrice = cfg->getPaymentOptions(paymentOptionIndex).pop_min_price;
} break;
case PERMIT_TYPE::DAY_TICKET_ADULT: {
} break;
case PERMIT_TYPE::DAY_TICKET_TEEN: {
} break;
case PERMIT_TYPE::DAY_TICKET_CHILD: {
} break;
case PERMIT_TYPE::DAY_TICKET: {
minPrice = compute_product_price(cfg, permitType, start);
} break;
default: ;
}
return minPrice;
}
int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg,
PERMIT_TYPE permitType,
QDateTime const &start,
QDateTime *productStart,
QDateTime *productEnd) {
switch(permitType) {
case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281)
} break;
case PERMIT_TYPE::DAY_TICKET_CHILD:
// [[fallthrough]];
case PERMIT_TYPE::DAY_TICKET_TEEN:
// [[fallthrough]];
case PERMIT_TYPE::FOOD_STAMP:
// [[fallthrough]];
case PERMIT_TYPE::DAY_TICKET_ADULT: {
std::optional<QVector<ATBTariffProduct>> products = cfg->getTariffProductForProductId(permitType);
if (products) {
QVector<ATBTariffProduct> product = products.value();
if (product.size() > 0) {
ATBTariffProduct const &p = product[0];
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();
// qCritical() << __LINE__ << startTime.toString(Qt::ISODate);
// qCritical() << __LINE__ << endTime.toString(Qt::ISODate);
// qCritical() << __LINE__ << start.toString(Qt::ISODate);
if (start.time() >= startTime && start.time() < endTime) {
product_price = p.getProductPrice();
if (productStart && productEnd) {
productStart->setTime(startTime);
productEnd->setTime(endTime);
}
}
}
return product_price;
} else {
// SZEGED
int const pop_daily_card_price = cfg->getPaymentOptions().pop_daily_card_price;
qDebug() << QString("(%1:%2) no products defined in tariff-file").arg(__func__).arg(__LINE__);
qDebug() << QString("(%1:%2) pop_daily_card_price=%3").arg(__func__).arg(__LINE__).arg(pop_daily_card_price);
// static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg);
// return Utilities::getDailyTicketCardPrice(cfg, paymentMethodId);
return pop_daily_card_price;
}
} break;
case PERMIT_TYPE::TWENTY_FOUR_HOURS_TICKET: {
std::optional<QVector<ATBTariffProduct>> products = cfg->getTariffProductForProductId(permitType);
if (products) {
int product_price = 0;
QVector<ATBTariffProduct> product = products.value();
if (product.size() > 0) {
if (productStart && productEnd) {
int pop_min_time = get_minimal_parkingtime(cfg); // in minutes
int pop_max_time = get_maximal_parkingtime(cfg); // in minutes
if (pop_max_time >= pop_min_time) {
*productStart = start;
*productEnd = start.addSecs(pop_max_time*60);
product_price = product[0].getProductPrice();
}
}
}
return product_price;
}
} break;
default:
break;
}
return 0;
}
int CALCULATE_LIBRARY_API get_maximal_parkingprice(Configuration *cfg,
PERMIT_TYPE permitType,
int paymentOptionIndex) {
int maxPrice = -1;
static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg);
switch(permitType) {
case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281)
if (paymentMethodId == PaymentMethod::Progressive || paymentMethodId == PaymentMethod::Steps) {
maxPrice = Utilities::getMaximalParkingPrice(cfg, paymentMethodId);
} else { // PaymentMethod::Linear -> e.g. szeged
int const key = cfg->getPaymentOptions(paymentOptionIndex).pop_id;
int const maxTime = cfg->getPaymentOptions(paymentOptionIndex).pop_max_time; // maxTime is given in minutes
std::optional<QVector<ATBPaymentRate>> const &pv = cfg->getPaymentRateForKey(key);
if (pv) {
QVector<ATBPaymentRate> const &paymentRate = pv.value();
if (paymentRate.size() > 0) {
int const price = paymentRate.last().pra_price; // price is given per hour
maxPrice = qRound((maxTime * price) / 60.0f);
}
}
}
} break;
case PERMIT_TYPE::DAY_TICKET_ADULT:
break;
case PERMIT_TYPE::DAY_TICKET_TEEN:
break;
case PERMIT_TYPE::DAY_TICKET_CHILD:
break;
default: ;
}
return maxPrice;
}
int CALCULATE_LIBRARY_API get_zone_nr(int zone)
{
if(zone > -1) return zone;
else
{
QFile zone("/etc/zone_nr");
if (zone.exists()) {
QFileInfo finfo(zone);
if (finfo.size() <= 4) { // decimal 000\n
if (zone.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&zone);
return in.readLine(100).toInt();
}
}
}
return -1;
}
}
CalcState CALCULATE_LIBRARY_API init_tariff(parking_tariff_t **tariff, char const *config_file) {
*tariff = new Configuration();
CalcState calcState;
#if __linux__
int const zone = get_zone_nr();
// DEBUG
qCritical() << "init_tariff:";
qCritical() << " ... zone = " << zone;
if (zone <= 0) {
delete *tariff;
*tariff = nullptr;
return calcState.set(CalcState::State::ERROR_PARSING_ZONE_NR);
}
QString confFile(config_file);
if (!confFile.endsWith(QChar('/'))) {
confFile += "/";
}
char buffer[32];
memset(buffer, 0x00, sizeof(buffer));
snprintf(buffer, sizeof(buffer)-1, "tariff%02d.json", zone);
confFile += buffer;
#else // windows
QString confFile(config_file);
#endif
// DEBUG
qCritical() << " ... confFile = " << confFile;
QFile fname(confFile);
if (fname.exists() &&
fname.open(QIODevice::ReadOnly | QIODevice::Text)) {
// DEBUG
qCritical() << " ... confFile is open";
QString json = fname.readAll();
if (! (*tariff)->ParseJson(*tariff, json.toStdString().c_str())) {
delete *tariff;
*tariff = nullptr;
return calcState.set(CalcState::State::ERROR_PARSING_TARIFF);
}
} else {
delete *tariff;
*tariff = nullptr;
return calcState.set(CalcState::State::ERROR_LOADING_TARIFF);
}
qCritical() << "init_tariff: Parsing tariff config (" << confFile << ")";
return calcState;
}
void CALCULATE_LIBRARY_API free_tariff(parking_tariff_t *tariff) {
if (tariff != nullptr) {
delete tariff;
}
}
//
// UpDown 1 -> up; 0 -> down
int CALCULATE_LIBRARY_API compute_next_timestep(parking_tariff_t *tariff, int currentTimeMinutes, int UpDown)
{
qCritical() << " compute_next_timestep() currentTimeMinutes: " << currentTimeMinutes;
qCritical() << " compute_next_timestep() up/down (1=up, 0=down): " << UpDown;
Configuration const *cfg = tariff;
// compute payment method id (e.g. Linear=3, Steps=4)
PaymentMethod const paymentMethodId = Utilities::getPaymentMethodId(cfg);
switch (paymentMethodId) {
case PaymentMethod::Progressive:
qCritical() << " compute_next_timestep() paymentMethodId: Progressive";
break;
case PaymentMethod::Degressive:
qCritical() << " compute_next_timestep() paymentMethodId: Degressive";
break;
case PaymentMethod::Linear:
qCritical() << " compute_next_timestep() paymentMethodId: Linear";
break;
case PaymentMethod::Steps:
qCritical() << " compute_next_timestep() paymentMethodId: Steps";
break;
case PaymentMethod::Undefined:
qCritical() << " compute_next_timestep() paymentMethodId: Undefined";
break;
}
// use tariff with structure as for instance Schnau, Koenigsee:
// without given YearPeriod, SpecialDays and SpecialDaysWorktime
if ((paymentMethodId == PaymentMethod::Steps) ||
// progressive tariff: e.g. Neuhauser, Kirchdorf (743)
(paymentMethodId == PaymentMethod::Progressive))
{
const QList<int> stepList = Calculator::GetInstance().GetTimeSteps(tariff);
qCritical() << " compute_next_timestep() timeSteps:" << stepList;
int currentStepIndex = stepList.indexOf(currentTimeMinutes);
if (currentStepIndex == -1) {
qCritical() << "compute_next_timestep() *NO STEP* for currentTimeMinutes (" << currentTimeMinutes << ")";
return currentTimeMinutes;
}
if (UpDown == 1) { // UP
if (stepList[currentStepIndex] == stepList.last()) {
qCritical() << "compute_next_timestep() *NO NEXT STEP* for currentTimeMinutes (" << currentTimeMinutes << ")";
return currentTimeMinutes;
}
else {
return stepList[currentStepIndex + 1];
}
}
if (UpDown == 0) { // DOWN
if (stepList[currentStepIndex] == stepList.first()) {
qCritical() << "compute_next_timestep() *NO PREVIOUS STEP* for currentTimeMinutes (" << currentTimeMinutes << ")";
return currentTimeMinutes;
}
else {
return stepList[currentStepIndex - 1];
}
}
} else
if (paymentMethodId == PaymentMethod::Linear) {
// currentTimeMinutes is the number of minutes actually used. This
// value is an offset from the start time and cannot be used as a
// QDateTime.
qCritical() << "compute_next_timestep() up/down (1=up, 0=down):" << UpDown;
// get minimal and maximal parking times
int const minParkingTime = Utilities::getMinimalParkingTime(cfg, paymentMethodId);
int const maxParkingTime = Utilities::getMaximalParkingTime(cfg, paymentMethodId);
qCritical() << " compute_next_timestep() maxParkingTime:" << maxParkingTime;
qCritical() << " compute_next_timestep() minParkingTime:" << minParkingTime;
// use the first (i.e. main duration step contained in the tariff json-file)
int firstDurationStep = Utilities::getFirstDurationStep(cfg, paymentMethodId);
firstDurationStep = ((UpDown == 1) ? firstDurationStep : -firstDurationStep);
qCritical() << " compute_next_timestep() firstDurationStep:" << firstDurationStep;
int const nextTimeStep = currentTimeMinutes + firstDurationStep;
if (nextTimeStep >= minParkingTime && nextTimeStep <= maxParkingTime) {
qCritical() << " compute_next_timestep() nextTimeStep:" << nextTimeStep;
return nextTimeStep;
}
}
qCritical() << "compute_next_timestep() *CAN NOT COMPUTE* for currentTimeMinutes (" << currentTimeMinutes << ")";
return currentTimeMinutes;
}
// this is currently not used
CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
parking_tariff_t *tariff,
time_t start_parking_time, // in minutes
time_t end_parking_time, // netto time in minutes
struct price_t *price) {
CalcState calcState;
double minMin = tariff->PaymentOption.find(tariff->getPaymentOptions().pop_payment_method_id)->second.pop_min_time;
double maxMin = tariff->PaymentOption.find(tariff->getPaymentOptions().pop_payment_method_id)->second.pop_max_time;
if (minMin < 0 || maxMin < 0 || maxMin < minMin) {
calcState.setDesc(QString("minMin=%1, maxMin=%2").arg(minMin).arg(maxMin));
return calcState.set(CalcState::State::WRONG_PARAM_VALUES);
}
int const duration = end_parking_time - start_parking_time;
if (duration < 0) {
calcState.setDesc(QString("end=%1, start=%2")
.arg(end_parking_time, start_parking_time));
return calcState.set(CalcState::State::NEGATIVE_PARKING_TIME);
}
if (duration > maxMin) {
calcState.setDesc(QString("duration=%1, maxMin=%2").arg(duration).arg(maxMin));
return calcState.set(CalcState::State::ABOVE_MAX_PARKING_TIME);
}
if (duration < minMin) {
calcState.setDesc(QString("duration=%1, minMin=%2").arg(duration).arg(minMin));
return calcState.set(CalcState::State::BELOW_MIN_PARKING_TIME);
}
if (duration == 0) {
return calcState.set(CalcState::State::SUCCESS);
}
QDate const d(1970, 1, 1);
QTime const t(0, 0, 0);
QDateTime start(d, t, Qt::UTC);
start = start.toLocalTime().addSecs(start_parking_time * 60);
QDateTime end(start);
if (start.isValid()) {
double cost = Calculator::GetInstance().GetCostFromDuration(
tariff,
tariff->getPaymentOptions().pop_payment_method_id,
start,
end,
duration, false, true);
double minCost = tariff->PaymentOption.find(tariff->getPaymentOptions().pop_payment_method_id)->second.pop_min_price;
if (cost < minCost) {
calcState.setDesc(QString("minCost=%1, cost=%2").arg(minCost).arg(cost));
return calcState.set(CalcState::State::BELOW_MIN_PARKING_PRICE);
}
price->units = cost;
price->netto = cost;
} else {
return calcState.set(CalcState::State::INVALID_START_DATE);
}
return calcState.set(CalcState::State::SUCCESS);
}
CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
parking_tariff_t *tariff,
QDateTime &start_parking_time,
int netto_parking_time,
QDateTime &end_parking_time,
struct price_t *price,
bool prepaid)
{
CalcState calcState;
int paymentOptionIndex = tariff->getPaymentOptionIndex(start_parking_time);
double minMin = tariff->getPaymentOptions(paymentOptionIndex).pop_min_time;
double maxMin = tariff->getPaymentOptions(paymentOptionIndex).pop_max_time;
// DEBUG
qCritical() << "compute_price_for_parking_ticket() " << endl
<< " paymentOptionIndex: " << paymentOptionIndex << endl
<< " start_parking_time: " << start_parking_time << endl
<< " netto_parking_time: " << netto_parking_time << endl
<< " minMin: " << minMin << endl
<< " maxMin: " << maxMin;
if (netto_parking_time < 0) {
calcState.setDesc(QString("end=%1, start=%2")
.arg(end_parking_time.toString(Qt::ISODate),
start_parking_time.toString(Qt::ISODate)));
return calcState.set(CalcState::State::NEGATIVE_PARKING_TIME);
}
if (netto_parking_time > maxMin) {
calcState.setDesc(QString("duration=%1, maxMin=%2").arg(netto_parking_time).arg(maxMin));
return calcState.set(CalcState::State::ABOVE_MAX_PARKING_TIME);
}
if (netto_parking_time < minMin) {
calcState.setDesc(QString("duration=%1, minMin=%2").arg(netto_parking_time).arg(minMin));
return calcState.set(CalcState::State::BELOW_MIN_PARKING_TIME);
}
if (netto_parking_time == 0) {
return calcState.set(CalcState::State::SUCCESS);
}
double cost = -1;
if (start_parking_time.isValid()) {
if (tariff->getPaymentOptions(paymentOptionIndex).pop_payment_method_id == PaymentMethod::Steps) {
// hier muesste man unterscheiden: uebertrag oder nicht?
calcState = Calculator::GetInstance().isParkingAllowed(tariff, start_parking_time,
netto_parking_time, paymentOptionIndex);
if (calcState.getStatus() == CalcState::State::OUTSIDE_ALLOWED_PARKING_TIME) {
// qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
// << calcState.toString();
return calcState;
}
cost = Calculator::GetInstance().GetCostFromDuration(tariff, start_parking_time, netto_parking_time, paymentOptionIndex);
end_parking_time = start_parking_time.addSecs(netto_parking_time*60);
// qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
// << "end_parking_time" << end_parking_time.toString(Qt::ISODate);
} else {
cost = Calculator::GetInstance().GetCostFromDuration(
tariff,
tariff->getPaymentOptions().pop_payment_method_id,
start_parking_time, // starting time
end_parking_time, // return value: end time
netto_parking_time, // minutes, netto
false, prepaid);
}
double minCost = tariff->getPaymentOptions(paymentOptionIndex).pop_min_price;
if (cost < minCost) {
calcState.setDesc(QString("minCost=%1, cost=%2").arg(minCost, cost));
return calcState.set(CalcState::State::BELOW_MIN_PARKING_PRICE);
}
// DEBUG
qCritical() << " end_parking_time: " << end_parking_time;
qCritical() << " -> calculated cost (netto): " << cost;
price->brutto = price->vat = price->vat_percentage = 0;
price->units = cost;
price->netto = cost;
} else {
return calcState.set(CalcState::State::INVALID_START_DATE);
}
return calcState.set(CalcState::State::SUCCESS);
}
CalcState CALCULATE_LIBRARY_API compute_duration_for_parking_ticket(
parking_tariff_t *tariff,
time_t start_parking_time,
double price,
QString &duration) {
CalcState calcState;
QDate const d(1970, 1, 1);
QTime const t(0, 0, 0);
QDateTime start(d, t, Qt::UTC);
start = start.toLocalTime().addSecs(start_parking_time * 60);
if (start.isValid()) {
QString cs = start.toString(Qt::ISODate);
// DEBUG
qCritical() << "compute_duration_for_parking_ticket(): ";
qCritical() << " start (cs): " << cs;
qCritical() << " price: " << price;
duration = Calculator::GetInstance().GetDurationFromCost(tariff,
tariff->getPaymentOptions().pop_payment_method_id,
cs.toLocal8Bit().constData(),
price, false, true).c_str();
QDateTime d = QDateTime::fromString(duration, Qt::ISODate);
if (!d.isValid()) {
calcState.setDesc(QString("ticketEndTime=%1").arg(duration));
return calcState.set(CalcState::State::WRONG_ISO_TIME_FORMAT);
}
} else {
return calcState.set(CalcState::State::INVALID_START_DATE);
}
return calcState.set(CalcState::State::SUCCESS);
}
CalcState CALCULATE_LIBRARY_API compute_duration_for_parking_ticket(
parking_tariff_t *tariff,
QDateTime const &start_parking_time,
double price,
QDateTime &ticketEndTime)
{
CalcState calcState;
if (start_parking_time.isValid()) {
QString cs = start_parking_time.toString(Qt::ISODate);
QString endTime = Calculator::GetInstance().GetDurationFromCost(
tariff,
tariff->getPaymentOptions().pop_payment_method_id,
cs.toLocal8Bit().constData(),
price, false, true).c_str();
if (endTime == CalcState::SUCCESS) {
calcState.setDesc(QString("SUCCESS"));
calcState.setStatus(endTime);
} else
if (endTime == CalcState::ERROR_PARSING_ZONE_NR) {
calcState.setStatus(endTime);
return calcState;
} else
if (endTime == CalcState::ERROR_LOADING_TARIFF) {
calcState.setStatus(endTime);
return calcState;
} else
if (endTime == CalcState::ERROR_PARSING_TARIFF) {
calcState.setStatus(endTime);
return calcState;
} else
if (endTime == CalcState::NEGATIVE_PARKING_TIME) {
calcState.setStatus(endTime);
return calcState;
} else
if (endTime == CalcState::INVALID_START_DATE) {
calcState.setStatus(endTime);
return calcState;
} else
if (endTime == CalcState::WRONG_PARAM_VALUES) {
calcState.setStatus(endTime);
return calcState;
} else
if (endTime == CalcState::WRONG_ISO_TIME_FORMAT) {
calcState.setStatus(endTime);
return calcState;
} else
if (endTime == CalcState::ABOVE_MAX_PARKING_TIME) {
calcState.setStatus(endTime);
return calcState;
} else
if (endTime == CalcState::BELOW_MIN_PARKING_TIME) {
calcState.setStatus(endTime);
return calcState;
} else
if (endTime == CalcState::BELOW_MIN_PARKING_PRICE) {
calcState.setStatus(endTime);
return calcState;
} else
if (endTime == CalcState::ABOVE_MAX_PARKING_PRICE) {
calcState.setDesc(CalcState::ABOVE_MAX_PARKING_PRICE);
calcState.setStatus(CalcState::ABOVE_MAX_PARKING_PRICE);
return calcState;
} else
if (endTime == CalcState::OVERPAID) {
calcState.setDesc(CalcState::OVERPAID);
calcState.setStatus(CalcState::OVERPAID);
return calcState;
} else
if (endTime == CalcState::OUTSIDE_ALLOWED_PARKING_TIME) {
calcState.setStatus(endTime);
return calcState;
} else {
ticketEndTime = QDateTime::fromString(endTime,Qt::ISODate);
// DEBUG
//qCritical() << "compute_duration_for_parking_ticket(): ";
//qCritical() << " endTime: " << endTime;
//qCritical() << " ticketEndTime: " << ticketEndTime;
if (!ticketEndTime.isValid()) {
calcState.setDesc(QString("ticketEndTime=%1").arg(endTime));
return calcState.set(CalcState::State::WRONG_ISO_TIME_FORMAT);
}
}
} else {
return calcState.set(CalcState::State::INVALID_START_DATE);
}
return calcState.set(CalcState::State::SUCCESS);
}
CalcState CALCULATE_LIBRARY_API compute_duration_for_daily_ticket(parking_tariff_t *tariff, QDateTime const &start_parking_time, QDateTime &ticketEndTime)
{
CalcState calcState;
if (start_parking_time.isValid()) {
ticketEndTime = Calculator::GetInstance().GetDailyTicketDuration(tariff,
start_parking_time,
tariff->getPaymentOptions().pop_payment_method_id,
false); // carry over
// DEBUG
qCritical() << "compute_duration_for_daily_ticket(): ";
qCritical() << " ticketEndTime: " << ticketEndTime;
if (!ticketEndTime.isValid()) {
calcState.setDesc(QString("ticketEndTime=%1").arg(ticketEndTime.toString(Qt::ISODate)));
return calcState.set(CalcState::State::WRONG_ISO_TIME_FORMAT);
}
} else {
return calcState.set(CalcState::State::INVALID_START_DATE);
}
return calcState.set(CalcState::State::SUCCESS);
}
CalcState CALCULATE_LIBRARY_API compute_price_for_daily_ticket(
parking_tariff_t *tariff,
QDateTime const &startDatetime,
QDateTime &endDatetime,
PERMIT_TYPE permitType,
struct price_t *price) {// return value
CalcState calcState;
if (startDatetime.isValid()) {
if (std::optional<struct price_t> p =
Calculator::GetInstance().GetDailyTicketPrice(tariff,
startDatetime,
endDatetime,
permitType)) {
*price = p.value();
}
} else {
return calcState.set(CalcState::State::INVALID_START_DATE);
}
return calcState.set(CalcState::State::SUCCESS);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -207,7 +207,13 @@ bool Utilities::IsYearPeriodActive(Configuration const *cfg, QDateTime const &dt
dt.date().day()); dt.date().day());
QDate const s(2004, year.second.pye_start_month, year.second.pye_start_day); QDate const s(2004, year.second.pye_start_month, year.second.pye_start_day);
QDate const e(2004, year.second.pye_end_month, year.second.pye_end_day); QDate const e(2004, year.second.pye_end_month, year.second.pye_end_day);
return (d >= s && d <= e); //qCritical() << __func__ << __LINE__ << " d" << d.toString(Qt::ISODate);
//qCritical() << __func__ << __LINE__ << "start" << s.toString(Qt::ISODate);
//qCritical() << __func__ << __LINE__ << " end" << e.toString(Qt::ISODate);
if (s <= e) {
return (d >= s && d <= e);
}
return (d >= s || d <= e);
})) { })) {
qCritical() << "NO VALID YEAR PERIOD"; qCritical() << "NO VALID YEAR PERIOD";
return false; return false;
@ -215,6 +221,43 @@ bool Utilities::IsYearPeriodActive(Configuration const *cfg, QDateTime const &dt
return true; return true;
} }
std::optional<ATBPeriodYear>
Utilities::GetYearPeriodActive(Configuration const *cfg, QDateTime const &currentDateTime) {
ATBPeriodYear period;
std::optional<ATBPeriodYear> value;
for (multimap<int, ATBPeriodYear>::const_iterator it = cfg->YearPeriod.cbegin();
it != cfg->YearPeriod.cend();
++it) {
QDate const s(currentDateTime.date().year(), it->second.pye_start_month, it->second.pye_start_day);
QDate const e(currentDateTime.date().year(), it->second.pye_end_month, it->second.pye_end_day);
QDateTime start(currentDateTime);
QDateTime end(currentDateTime);
start.setDate(s);
end.setDate(e);
if (start.date().dayOfYear() < end.date().dayOfYear()) {
// start and end in the same year
if (currentDateTime.date().dayOfYear() >= start.date().dayOfYear() &&
currentDateTime.date().dayOfYear() <= end.date().dayOfYear()) {
value = value.value_or(it->second);
break;
}
} else {
if (currentDateTime.date().dayOfYear() >= start.date().dayOfYear() ||
currentDateTime.date().dayOfYear() <= end.date().dayOfYear()) {
value = value.value_or(it->second);
break;
}
}
}
return value;
}
/// <inheritdoc/> /// <inheritdoc/>
bool Utilities::CheckSpecialDay(Configuration* cfg, const char* currentDateTimeStr, int* specialDayId, double* specialDayPrice) bool Utilities::CheckSpecialDay(Configuration* cfg, const char* currentDateTimeStr, int* specialDayId, double* specialDayPrice)
{ {
@ -384,6 +427,8 @@ PaymentMethod Utilities::getPaymentMethodId(Configuration const *cfg) {
return PaymentMethod::Degressive; return PaymentMethod::Degressive;
case PaymentMethod::Progressive: case PaymentMethod::Progressive:
return PaymentMethod::Progressive; return PaymentMethod::Progressive;
case PaymentMethod::Unified:
return PaymentMethod::Unified;
} }
} }

View File

@ -39,7 +39,7 @@ extern "C" char* strptime(const char* s,
#define SZEGED (0) #define SZEGED (0)
#define SCHOENAU_KOENIGSEE (0) #define SCHOENAU_KOENIGSEE (0)
#define NEUHAUSER_KORNEUBURG (0) #define NEUHAUSER_KORNEUBURG (1)
#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)
@ -51,7 +51,8 @@ extern "C" char* strptime(const char* s,
#define SEXTEN (0) #define SEXTEN (0)
#define SCHNALS_LEITER_KIRCHL (0) #define SCHNALS_LEITER_KIRCHL (0)
#define SCHNALS_STAUMAUER (SCHNALS_LEITER_KIRCHL) #define SCHNALS_STAUMAUER (SCHNALS_LEITER_KIRCHL)
#define VALSER_ALM (1) #define VALSER_ALM (0)
#define NEUHAUSER_FORCHACH (0)
#if NEUHAUSER_KIRCHDORF==1 #if NEUHAUSER_KIRCHDORF==1
static bool test_neuhauser_kirchdorf(int step, double cost) { static bool test_neuhauser_kirchdorf(int step, double cost) {
@ -210,21 +211,73 @@ static bool test_neuhauser_kirchdorf(int step, double cost) {
return 0; return 0;
*/ */
#include <QProcess>
#include <QCoreApplication>
QString getCalculatorLibVersion() {
static QString v;
if (v.isEmpty()) {
QProcess shell;
QString command = QString("cat /proc/%1/maps | awk '{print $6;}' | grep 'libmobilisis_calc' | uniq").arg(QCoreApplication::applicationPid());
shell.start("/bin/bash", {"-c", command});
if ( shell.waitForFinished( 5000 )) {
v = shell.readAllStandardOutput();
// /usr/lib/libmobilisis_calc.so.2.3.99-18
if (!v.isEmpty()) {
QStringList vlst = v.trimmed().split("/", QString::SkipEmptyParts);
if (vlst.size() > 0) {
vlst = vlst.last().split(".", QString::SkipEmptyParts);
if (vlst.size() > 4) {
v = QString("%1.%2.%3").arg(vlst[2]).arg(vlst[3]).arg(vlst[4]);
}
}
}
}
}
return v;
}
bool isProductSupportedInCalculatorLib(QString const &product) {
bool supported{false};
QProcess shell;
QString command = QString("cat /proc/%1/maps | awk '{print $6;}' | grep 'libmobilisis_calc' | uniq | xargs strings | grep %2").arg(QCoreApplication::applicationPid()).arg(product);
shell.start("/bin/bash", {"-c", command});
if ( shell.waitForFinished( 5000 )) {
QString s = shell.readAllStandardOutput().trimmed();
// /usr/lib/libmobilisis_calc.so.2.3.99-18
if (!s.isEmpty() && (s == product)) {
qCritical() << "product" << s << "supported";
supported = true;
} else {
qCritical() << "product" << product << "not supported";
}
}
return supported;
}
int main() { int main() {
qCritical() << getCalculatorLibVersion();
isProductSupportedInCalculatorLib("FREE_TICKET");
return 0;
//487 { //487 {
// 488 "pra_payment_option_id": 1049, // 488 "pra_payment_option_id": 1049,
// 489 "pra_payment_unit_id": 84, // 489 "pra_payment_unit_id": 84,
// 490 "pra_price":"840" // 490 "pra_price":"840"
//>>491 } //>>491 }
//for (int i = 1; i < 85; ++i) { //for (int i = 1; i < 346; ++i) {
//printf("{\n \"\pra_payment_option_id\": 1049,\n \"\pra_payment_unit_id\": %d,\n \"pra_price\": %d\n},\n", //printf("{\n \"pun_id\": %i,\n \"pun_duration\": %d\n},\n",
// i, i*10); // i, 60 + i*4);
//} //}
//return 0; for (int i = 1; i < 361; ++i) {
printf("{\n \"pra_payment_option_id\": 1049,\n \"pra_payment_unit_id\": %i,\n \"pra_price\":%i\n},\n",
i, i*10);
}
return 0;
#if 0 #if 0
MessageHelper msgHelp; MessageHelper msgHelp;
// msgHelp.createLoginMessageChunksToSend(0x02); // msgHelp.createLoginMessageChunksToSend(0x02);
@ -339,22 +392,22 @@ int main() {
cout << endl; cout << endl;
if (isParsed) { if (isParsed) {
pop_min_time = get_minimal_parkingtime(&cfg); //pop_min_time = get_minimal_parkingtime(&cfg);
pop_max_time = get_maximal_parkingtime(&cfg); //pop_max_time = get_maximal_parkingtime(&cfg);
pop_min_price = get_minimal_parkingprice(&cfg); //pop_min_price = get_minimal_parkingprice(&cfg);
pop_max_price = get_maximal_parkingprice(&cfg); //pop_max_price = get_maximal_parkingprice(&cfg);
pop_daily_card_price = cfg.getPaymentOptions().pop_daily_card_price; //pop_daily_card_price = cfg.getPaymentOptions().pop_daily_card_price;
qCritical() << " pop_min_time: " << pop_min_time; //qCritical() << " pop_min_time: " << pop_min_time;
qCritical() << " pop_max_time: " << pop_max_time; //qCritical() << " pop_max_time: " << pop_max_time;
qCritical() << " pop_min_price: " << pop_min_price; //qCritical() << " pop_min_price: " << pop_min_price;
qCritical() << " pop_max_price: " << pop_max_price; //qCritical() << " pop_max_price: " << pop_max_price;
QList<int> timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg); //QList<int> timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg);
qCritical() << "TimeSteps" << timeSteps; //qCritical() << "TimeSteps" << timeSteps;
return 0; // return 0;
CalcState cs; CalcState cs;
double cost; double cost;
@ -363,8 +416,7 @@ int main() {
// for (int day = Qt::Monday; day <= Qt::Sunday; ++day) { // for (int day = Qt::Monday; day <= Qt::Sunday; ++day) {
for (int day = Qt::Monday; day <= Qt::Monday; ++day) { for (int day = Qt::Monday; day <= Qt::Monday; ++day) {
QDateTime s(QDate(2024, 5, 19 + day), QTime()); // 20: (whit) monday,..., 26: sunday QDateTime s(QDate(2024, 8, 19 + day), QTime()); // 20: (whit) monday,..., 26: sunday
QDateTime end;
switch (day) { switch (day) {
case (int)Qt::Monday: case (int)Qt::Monday:
@ -390,6 +442,30 @@ int main() {
break; break;
} }
QDateTime start(s);
start.setTime(QTime(21, 30, 0));
QDateTime end;
int netto_parking_time = 14 * 60;
struct price_t costs;
PermitType pt(PERMIT_TYPE::SHORT_TERM_PARKING);
double cost = 150;
//cs = compute_price_for_parking_ticket(&cfg, start, netto_parking_time,
// end, &costs, pt);
//qCritical() << "start" << start.toString(Qt::ISODate) << "< cost" << costs.netto
// << "> end" << end.toString(Qt::ISODate);
cs = compute_duration_for_parking_ticket(&cfg, start, cost, end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING));
qCritical() << "start" << start.toString(Qt::ISODate) << "< cost" << cost
<< "> end" << end.toString(Qt::ISODate);
//}
exit(0);
/* /*
CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
@ -401,9 +477,11 @@ int main() {
bool prepaid = true); bool prepaid = true);
*/ */
for (int minutes = 0; minutes < 1440; ++minutes) { //for (int minutes = 0; minutes < 1440; ++minutes) {
QDateTime start = s.addSecs(minutes * 60); for (int minutes = 540; minutes <= 540; ++minutes) {
QDateTime effectiveStart = start; // QDateTime start = s.addSecs(minutes * 60);
QDateTime start(QDateTime::currentDateTime());
QDateTime effectiveStart(QDateTime::currentDateTime());
if (start.time() < QTime(8, 0, 0)) { if (start.time() < QTime(8, 0, 0)) {
effectiveStart.setTime(QTime(8, 0, 0)); effectiveStart.setTime(QTime(8, 0, 0));
@ -415,55 +493,18 @@ int main() {
effectiveStart.setTime(QTime(8, 0, 0)); // next day effectiveStart.setTime(QTime(8, 0, 0)); // next day
} }
for (int i = 0; i <= 2100; i += 10) { for (int i = 30; i <= 30; i += 10) {
//for (int i = 2100; i <= 2100; i += 10) { //for (int i = 2100; i <= 2100; i += 10) {
cost = i; cost = i;
if ((cs = compute_duration_for_parking_ticket(&cfg, start, cost, end))) { // return value if ((cs = compute_duration_for_parking_ticket(&cfg, start, cost, end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)))) { // return value
durationInMinutes = pop_min_time; qCritical() << "start" << start.toString(Qt::ISODate) << "< cost" << cost
if (i > 0) { << "> end" << end.toString(Qt::ISODate);
durationInMinutes += (i/10) * 4;
}
offsetInMinutes = 0;
if (effectiveStart.time() >= QTime(8, 0, 0) && effectiveStart.time() <= QTime(22, 0, 0)) {
if (effectiveStart.time().secsTo(QTime(22, 0, 0)) < (durationInMinutes * 60)) {
offsetInMinutes = 600; // 22:00 -> 8:00
}
}
if (i == 0) {
i += 20;
}
if ((durationInMinutes + offsetInMinutes) == (effectiveStart.secsTo(end) / 60)) {
if (day == Qt::Monday && minutes >= 480 && minutes <= 1320) {
qCritical() << "| start ............................" << start.toString(Qt::ISODate);
qCritical() << "| cost ............................." << cost;
qCritical() << "| durationInMinutes ................" << durationInMinutes
<< "(" << (durationInMinutes - 60) << "+ 60 )";
qCritical() << "| offsetInMinutes .................." << offsetInMinutes;
qCritical() << "| end .............................." << end.toString(Qt::ISODate) << endl;
}
continue;
}
} }
if (!cs) { if (!cs) {
qCritical() << "ERROR CalcState" << cs.toString() << endl; qCritical() << "ERROR CalcState" << cs.toString() << endl;
} else {
qCritical() << cs.toString();
} }
qCritical() << __LINE__ << "start ............................" << start.toString(Qt::ISODate);
qCritical() << __LINE__ << "effectiveStart ..................." << effectiveStart.toString(Qt::ISODate);
qCritical() << __LINE__ << "cost ............................." << cost;
qCritical() << __LINE__ << "durationInMinutes ................" << durationInMinutes;
qCritical() << __LINE__ << "offsetInMinutes .................." << offsetInMinutes;
qCritical() << __LINE__ << "effectiveStart.secsTo(end) / 60 .." << effectiveStart.secsTo(end) / 60;
qCritical() << __LINE__ << "end .............................." << end.toString(Qt::ISODate) << endl;
exit(-1);
} }
} }
} }
@ -552,7 +593,7 @@ int main() {
*/ */
//for (int minutes = 0; minutes < 1440; ++minutes) { //for (int minutes = 0; minutes < 1440; ++minutes) {
for (int minutes = 0; minutes < 1440; minutes += 1) { for (int minutes = 480; minutes <= 480; minutes += 1) {
QDateTime start = s.addSecs(minutes * 60); QDateTime start = s.addSecs(minutes * 60);
// qCritical() << "start" << start.toString(Qt::ISODate); // qCritical() << "start" << start.toString(Qt::ISODate);
@ -569,66 +610,32 @@ int main() {
effectiveStart.setTime(QTime(8, 0, 0)); // next day effectiveStart.setTime(QTime(8, 0, 0)); // next day
} }
/*
for (int i = 10; i <= 400; i += 10) { for (int i = 10; i <= 400; i += 10) {
//for (int i = 2100; i <= 2100; i += 10) {
cost = i; cost = i;
if ((cs = compute_duration_for_parking_ticket(&cfg, start, cost, end))) { // return value if ((cs = compute_duration_for_parking_ticket(&cfg, start, cost, end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)))) { // return value
qCritical() << "start" << start.toString(Qt::ISODate) << "< cost" << cost qCritical() << "start" << start.toString(Qt::ISODate) << "< cost" << cost
<< "> end" << end.toString(Qt::ISODate); << "> end" << end.toString(Qt::ISODate);
durationInMinutes = pop_min_time;
if (i > 0) {
durationInMinutes += (i/10) * 4;
}
offsetInMinutes = 0;
if (effectiveStart.time() >= QTime(8, 0, 0) && effectiveStart.time() <= QTime(19, 0, 0)) {
if (effectiveStart.time().secsTo(QTime(19, 0, 0)) < (durationInMinutes * 60)) {
offsetInMinutes = 780; // 19:00 -> 8:00
}
}
if (i == 0) {
i += 20;
}
#if 0
if ((durationInMinutes + offsetInMinutes) == (effectiveStart.secsTo(end) / 60)) {
if (day == Qt::Monday && minutes >= 480 && minutes <= 1140) {
qCritical() << "| start ............................" << start.toString(Qt::ISODate);
qCritical() << "| cost ............................." << cost;
qCritical() << "| durationInMinutes ................" << durationInMinutes
<< "(" << (durationInMinutes - 60) << "+ 60 )";
qCritical() << "| offsetInMinutes .................." << offsetInMinutes;
qCritical() << "| end .............................." << end.toString(Qt::ISODate) << endl;
}
continue;
}
#endif
} }
if (!cs) { if (!cs) {
qCritical() << "ERROR CalcState" << cs.toString() << endl; qCritical() << "ERROR CalcState" << cs.toString() << endl;
} else {
// qCritical() << cs.toString();
} }
}
*/
int netto_parking_time = 60;
struct price_t price;
#if 0 qCritical() << "start" << start.toString(Qt::ISODate);
qCritical() << __LINE__ << "start ............................" << start.toString(Qt::ISODate);
qCritical() << __LINE__ << "effectiveStart ..................." << effectiveStart.toString(Qt::ISODate);
qCritical() << __LINE__ << "cost ............................." << cost;
qCritical() << __LINE__ << "durationInMinutes ................" << durationInMinutes;
qCritical() << __LINE__ << "offsetInMinutes .................." << offsetInMinutes;
qCritical() << __LINE__ << "effectiveStart.secsTo(end) / 60 .." << effectiveStart.secsTo(end) / 60;
qCritical() << __LINE__ << "end .............................." << end.toString(Qt::ISODate) << endl;
exit(-1);
#endif
QDateTime const s = start;
if ((cs = compute_price_for_parking_ticket(&cfg, start, netto_parking_time, end, &price, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)))) {
qCritical() << "start" << s.toString(Qt::ISODate)
<< "netto_parking_time" << netto_parking_time
<< "< price" << price.netto
<< "> end" << end.toString(Qt::ISODate);
} }
} }
} }
@ -737,7 +744,7 @@ int main() {
effectiveStart.setTime(QTime(7, 0, 0)); // next day effectiveStart.setTime(QTime(7, 0, 0)); // next day
} }
#if 1 #if 0
PermitType permitType(PERMIT_TYPE::SHORT_TERM_PARKING); PermitType permitType(PERMIT_TYPE::SHORT_TERM_PARKING);
for (int i = 200; i <= 200; i += 10) { for (int i = 200; i <= 200; i += 10) {
cost = i; cost = i;
@ -760,7 +767,7 @@ int main() {
//for (int i = 2100; i <= 2100; i += 10) { //for (int i = 2100; i <= 2100; i += 10) {
cost = i; cost = i;
if ((cs = compute_duration_for_parking_ticket(&cfg, start, cost, end))) { // return value if ((cs = compute_duration_for_parking_ticket(&cfg, start, cost, end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING_PKW)))) { // return value
} }
if (!cs) { if (!cs) {
@ -801,7 +808,7 @@ int main() {
int pop_max_price; int pop_max_price;
int pop_daily_card_price; int pop_daily_card_price;
int zone = 3; int zone = 1;
if (zone == 1) { if (zone == 1) {
input.open("/opt/ptu5/opt/customer_502/etc/psa_tariff/tariff01.json"); input.open("/opt/ptu5/opt/customer_502/etc/psa_tariff/tariff01.json");
@ -890,7 +897,7 @@ int main() {
CalcState calcState; CalcState calcState;
QDateTime s(QDateTime::currentDateTime()); QDateTime s(QDateTime::currentDateTime());
s.setTime(QTime(12, 0, 0)); // s.setTime(QTime(12, 0, 0));
//calcState = compute_duration_for_parking_ticket(&cfg, s, //calcState = compute_duration_for_parking_ticket(&cfg, s,
// (double)1200, end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING_PKW)); // (double)1200, end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING_PKW));
@ -901,6 +908,23 @@ int main() {
(double)9000, end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING_BUS)); (double)9000, end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING_BUS));
qCritical() << end.toString(Qt::ISODate); qCritical() << end.toString(Qt::ISODate);
qCritical() << calcState.toString(); qCritical() << calcState.toString();
struct price_t costs;
CalcState cs;
for (int i = 0, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) {
QDateTime end = start.addSecs(timeSteps.at(i)*60);
qCritical() << "XXXXX end" << end.toString(Qt::ISODate);
cs = compute_price_for_parking_ticket(&cfg, s, timeSteps.at(i), end, &costs,
PermitType(PERMIT_TYPE::SHORT_TERM_PARKING));
if (cs.getStatus() != CalcState::State::SUCCESS) {
qCritical() << "ERROR STATUS" << costs.netto;
exit(-1);
}
}
} }
if (zone == 2) { if (zone == 2) {
@ -991,6 +1015,7 @@ int main() {
PermitType(PERMIT_TYPE::SHORT_TERM_PARKING_PKW), PermitType(PERMIT_TYPE::SHORT_TERM_PARKING_PKW),
paymentOptionIndex, s); paymentOptionIndex, s);
#if 0
qCritical() << "minimal parking price" << minimal_parking_price; qCritical() << "minimal parking price" << minimal_parking_price;
for (int i = 0; i < 8; ++i) { for (int i = 0; i < 8; ++i) {
@ -1000,6 +1025,7 @@ int main() {
qCritical() << "RUN" << i << end.toString(Qt::ISODate) << calcState.toString(); qCritical() << "RUN" << i << end.toString(Qt::ISODate) << calcState.toString();
} }
#else
s.setTime(QTime(15, 0, 0)); s.setTime(QTime(15, 0, 0));
minimal_parking_price = get_minimal_parkingprice(&cfg, minimal_parking_price = get_minimal_parkingprice(&cfg,
@ -1014,6 +1040,7 @@ int main() {
end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING_PKW)); end, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING_PKW));
qCritical() << "RUN" << i << end.toString(Qt::ISODate) << calcState.toString(); qCritical() << "RUN" << i << end.toString(Qt::ISODate) << calcState.toString();
} }
#endif
} }
} }
#endif #endif
@ -1412,6 +1439,29 @@ int main() {
} }
} }
#endif
#if NEUHAUSER_FORCHACH==1
std::ifstream input;
input.open("/opt/ptu5/opt/customer_749/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) {
compute_product_price(&cfg, PermitType(PERMIT_TYPE::DAY_TICKET_PKW));
compute_product_price(&cfg, PermitType(PERMIT_TYPE::DAY_TICKET_CAMPER));
QDateTime start = QDateTime::currentDateTime();
QDateTime ticketEndTime;
compute_duration_for_daily_ticket(&cfg, start, ticketEndTime, PermitType(PERMIT_TYPE::DAY_TICKET));
}
#endif #endif
#if BAD_NEUENAHR_AHRWEILER==1 #if BAD_NEUENAHR_AHRWEILER==1
std::ifstream input; std::ifstream input;
@ -1423,7 +1473,7 @@ int main() {
int pop_carry_over; int pop_carry_over;
int pop_carry_over_time_range_id; int pop_carry_over_time_range_id;
for (int zone=1; zone < 2; ++zone) { for (int zone=2; zone < 3; ++zone) {
//for (int t=6; t < 7; t+=20) { //for (int t=6; t < 7; t+=20) {
switch (zone) { switch (zone) {
case 1: { case 1: {
@ -1432,8 +1482,10 @@ int main() {
//pop_max_time = 6*60; //pop_max_time = 6*60;
} break; } break;
case 2: { case 2: {
qCritical() << " ZONE 2: KURZZEIT 1";
// kuzzeit-1-tarif // kuzzeit-1-tarif
input.open("/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff02.json"); //input.open("/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff02.json");
input.open("/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff05.json");
//pop_max_time = 5*60; //pop_max_time = 5*60;
} break; } break;
case 3: { case 3: {
@ -1474,6 +1526,7 @@ int main() {
cout << endl; cout << endl;
if (isParsed) { if (isParsed) {
// test library functions // test library functions
if (zone == 1) { if (zone == 1) {
@ -1500,10 +1553,10 @@ int main() {
static QList<int> const timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg); static QList<int> const timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg);
qCritical() << "TimeSteps" << timeSteps; qCritical() << "TimeSteps" << timeSteps;
if (stepsConfigured != timeSteps) { //if (stepsConfigured != timeSteps) {
qCritical() << "TIME-STEPS SHOULD BE" << stepsConfigured; // qCritical() << "TIME-STEPS SHOULD BE" << stepsConfigured;
return -1; // return -1;
} //}
QDateTime start = QDateTime::currentDateTime(); QDateTime start = QDateTime::currentDateTime();
@ -1511,7 +1564,8 @@ int main() {
double price1 = 0; double price1 = 0;
double price2 = 0; double price2 = 0;
for (int m=0; m < 1440; ++m) { //for (int m=0; m < 1440; ++m) {
for (int m=480; m < 481; ++m) {
start.setTime(QTime(0, 0, 0)); start.setTime(QTime(0, 0, 0));
start = start.addSecs(m*60); start = start.addSecs(m*60);
@ -1528,11 +1582,11 @@ int main() {
//} //}
CalcState cs; CalcState cs;
#if 1
for (int i = 0, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) { for (int i = 0, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) {
QDateTime end = start.addSecs(timeSteps.at(i)*60); QDateTime end = start.addSecs(timeSteps.at(i)*60);
cs = compute_price_for_parking_ticket(&cfg, start, timeSteps.at(i), end, &costs); cs = compute_price_for_parking_ticket(&cfg, start, timeSteps.at(i), end, &costs, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING));
if (cs.getStatus() != CalcState::State::SUCCESS) { if (cs.getStatus() != CalcState::State::SUCCESS) {
if (start.time().hour() >= 8 && start.time().hour() < 18) { if (start.time().hour() >= 8 && start.time().hour() < 18) {
qCritical() << "ERROR CALC-STATE-1=" << QString(cs); qCritical() << "ERROR CALC-STATE-1=" << QString(cs);
@ -1555,7 +1609,7 @@ int main() {
} }
qCritical() << "compute_price_for_parking_ticket()/GetCostFromDuration() TIME: " qCritical() << "compute_price_for_parking_ticket()/GetCostFromDuration() TIME: "
<< timeSteps.at(i) << "PRICE=" << price1; << timeSteps.at(i) << "PRICE=" << price1 << "end=" << end.toString(Qt::ISODate);
//std::string duration = Calculator::GetInstance().GetDurationFromCost(&cfg, 4, //std::string duration = Calculator::GetInstance().GetDurationFromCost(&cfg, 4,
@ -1563,6 +1617,21 @@ int main() {
// cost[i], false, true); // cost[i], false, true);
//qCritical() << "duration" << duration.c_str(); //qCritical() << "duration" << duration.c_str();
} }
#else
double cost = 80;
qCritical() << "START" << start.toString(Qt::ISODate) << "cost" << cost;
QDateTime end;
cs = compute_duration_for_parking_ticket(&cfg, start, cost, end,
PermitType(PERMIT_TYPE::SHORT_TERM_PARKING));
qCritical() << __LINE__ << cs.toString()
<< "START" << start.toString(Qt::ISODate)
<< "<duration" << start.secsTo(end) / 60
<< "cost" << cost
<< "> end" << end.toString(Qt::ISODate);
//}
#endif
} }
} // zone == 1 } // zone == 1
if (zone == 2) { if (zone == 2) {
@ -1600,18 +1669,20 @@ int main() {
bool fail; bool fail;
QDateTime start; QDateTime start;
for (int i=0; i < 4; ++i) { for (int i=1; i < 2; ++i) {
switch (i) { switch (i) {
case 0: case 0:
start = QDateTime(QDate(2024, 5, 1), QTime(16, 0, 0)); // holiday start = QDateTime(QDate(2024, 5, 1), QTime(16, 0, 0)); // holiday
fail = false; fail = false;
break; break;
case 1: case 1:
start = QDateTime(QDate(2024, 4, 21), QTime(16, 0, 0)); // sunday //start = QDateTime(QDate(2024, 10, 3), QTime(17, 0, 0)); // sunday
//start = QDateTime(QDate(2025, 4, 20), QTime(18, 0, 0)); // sunday
start = QDateTime(QDate(2024, 9, 27), QTime(17, 0, 0)); // friday
fail = false; fail = false;
break; break;
case 2: case 2:
start = QDateTime(QDate(2024, 4, 22), QTime(8, 0, 0)); // monday start = QDateTime(QDate(2024, 4, 22), QTime(17, 30, 0)); // monday
fail = false; fail = false;
break; break;
case 3: case 3:
@ -1635,18 +1706,52 @@ int main() {
QList<int>::const_iterator step; QList<int>::const_iterator step;
for (step = timeSteps.cbegin(); step != timeSteps.cend(); ++step) { for (step = timeSteps.cbegin(); step != timeSteps.cend(); ++step) {
//qCritical() << __LINE__
// << "START" << start.toString(Qt::ISODate)
// << "<duration" << *step;
if (*step != 180)
continue;
double cost = 0; double cost = 0;
CalcState cs; CalcState cs;
if ((cs = compute_price_for_parking_ticket(&cfg, start, *step, end, &price))) { QDateTime s(start);
qCritical() << __LINE__
<< "START" << start.toString(Qt::ISODate)
<< "<duration" << *step;
#if 1
if ((cs = compute_price_for_parking_ticket(&cfg, s, *step, end, &price,
PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)))) {
cost = price.netto; cost = price.netto;
qCritical() << "step" << *step << ": cost" << cost; qCritical() << __LINE__
<< "START" << start.toString(Qt::ISODate)
<< "<duration" << *step
<< "cost" << cost
<< "> end" << end.toString(Qt::ISODate);
} else { } else {
if (fail == false) { if (fail == false) {
qCritical() << "<<<ERROR>>> cs =" << QString(cs); qCritical() << "<<<ERROR>>> cs =" << QString(cs);
} }
} }
#else
cost = 200;
qCritical() << "START" << start.toString(Qt::ISODate) << "cost" << cost;
cs = compute_duration_for_parking_ticket(&cfg, start, cost, end,
PermitType(PERMIT_TYPE::SHORT_TERM_PARKING));
qCritical() << __LINE__ << cs.toString()
<< "START" << start.toString(Qt::ISODate)
<< "<duration" << start.secsTo(end) / 60
<< "cost" << cost
<< "> end" << end.toString(Qt::ISODate);
break;
//}
#endif
} }
} else { } else {
qCritical() << "ERROR paymentOptionIndex =" << paymentOptionIndex; qCritical() << "ERROR paymentOptionIndex =" << paymentOptionIndex;
@ -1723,7 +1828,7 @@ int main() {
double cost = 0; double cost = 0;
CalcState cs; CalcState cs;
if ((cs = compute_price_for_parking_ticket(&cfg, start, *step, end, &price))) { if ((cs = compute_price_for_parking_ticket(&cfg, start, *step, end, &price, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)))) {
cost = price.netto; cost = price.netto;
qCritical() << "step" << *step << ": cost" << cost; qCritical() << "step" << *step << ": cost" << cost;
} else { } else {
@ -1808,7 +1913,7 @@ int main() {
double cost = 0; double cost = 0;
CalcState cs; CalcState cs;
if ((cs = compute_price_for_parking_ticket(&cfg, start, *step, end, &price))) { if ((cs = compute_price_for_parking_ticket(&cfg, start, *step, end, &price, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)))) {
cost = price.netto; cost = price.netto;
qCritical() << "step" << *step << ": cost" << cost; qCritical() << "step" << *step << ": cost" << cost;
} else { } else {
@ -1866,7 +1971,7 @@ int main() {
double cost = 0; double cost = 0;
CalcState cs; CalcState cs;
if ((cs = compute_price_for_parking_ticket(&cfg, start, *step, end, &price))) { if ((cs = compute_price_for_parking_ticket(&cfg, start, *step, end, &price, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING)))) {
cost = price.netto; cost = price.netto;
qCritical() << "step" << *step << ": cost" << cost; qCritical() << "step" << *step << ": cost" << cost;
} else { } else {
@ -1969,7 +2074,7 @@ int main() {
CalcState cs; CalcState cs;
for (int i = 13, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) { for (int i = 13, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) {
QDateTime end = start.addSecs(timeSteps.at(i)*60); QDateTime end = start.addSecs(timeSteps.at(i)*60);
cs = compute_price_for_parking_ticket(&cfg, start, timeSteps.at(i), end, &costs); cs = compute_price_for_parking_ticket(&cfg, start, timeSteps.at(i), end, &costs, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING));
qCritical() << endl; qCritical() << endl;
} }
@ -1994,7 +2099,7 @@ int main() {
for (int i = 0, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) { for (int i = 0, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) {
QDateTime end = start.addSecs(timeSteps.at(i)*60); QDateTime end = start.addSecs(timeSteps.at(i)*60);
cs = compute_price_for_parking_ticket(&cfg, start, timeSteps.at(i), end, &costs); cs = compute_price_for_parking_ticket(&cfg, start, timeSteps.at(i), end, &costs, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING));
if (cs.getStatus() != CalcState::State::SUCCESS) { if (cs.getStatus() != CalcState::State::SUCCESS) {
if (start.time().hour() >= 8 && start.time().hour() < 18) { if (start.time().hour() >= 8 && start.time().hour() < 18) {
qCritical() << "ERROR CALC-STATE-1=" << QString(cs); qCritical() << "ERROR CALC-STATE-1=" << QString(cs);
@ -2751,24 +2856,62 @@ int main() {
bool nextDay = false; bool nextDay = false;
bool prePaid = true; bool prePaid = true;
// zone 1 (lila) // zone 1 (lila)
QDateTime s(QDate(2023, 11, 30), QTime()); QDateTime s(QDate(2024, 10, 8), QTime());
QDateTime end; QDateTime end;
static QList<int> const timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg);
qCritical() << "TimeSteps" << timeSteps;
for (int duration = 30; duration <= pop_max_time; duration += 5) { for (int duration = 30; duration <= pop_max_time; duration += 5) {
for (int offset = 420; offset < 1140; ++offset) { int offset = 600;
if (offset > 720 && offset < 840) { //for (int offset = 720; offset < 601; ++offset) {
continue; //if (offset > 720 && offset < 840) {
} // continue;
//}
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::GetInstance().GetCostFromDuration(&cfg, 3, start, end, duration, nextDay, prePaid); CalcState cs;
#if 1
struct price_t costs;
for (int i = 0, j=timeSteps.size() ; i < timeSteps.size(); --j, ++i) {
QDateTime end = start.addSecs(timeSteps.at(i)*60);
// if (i != 2) continue;
cs = compute_price_for_parking_ticket(&cfg, start, timeSteps.at(i), end, &costs, PermitType(PERMIT_TYPE::SHORT_TERM_PARKING));
int price1 = costs.netto;
qCritical() << "compute_price_for_parking_ticket()/GetCostFromDuration() TIME: "
<< timeSteps.at(i) << "ZZZZZZZZZZZZZ PRICE=" << price1 << "end=" << end.toString(Qt::ISODate);
}
exit(0);
#else
double cost = 360;
qCritical() << "XXXXXXXX START" << start.toString(Qt::ISODate) << "cost" << cost;
QDateTime end;
cs = compute_duration_for_parking_ticket(&cfg, start, cost, end,
PermitType(PERMIT_TYPE::SHORT_TERM_PARKING));
qCritical() << __LINE__ << cs.toString()
<< "START" << start.toString(Qt::ISODate)
<< "<duration" << start.secsTo(end) / 60
<< "cost" << cost
<< "> end" << end.toString(Qt::ISODate);
//}
exit(0);
#endif
//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) //qCritical() << "start" << start.toString(Qt::ISODate)
<< "end" << end.toString(Qt::ISODate) // << "end" << end.toString(Qt::ISODate)
<< "duration" << duration // << "duration" << duration
<< "cost" << cost; // << "cost" << cost;
#if 0
switch(duration) { switch(duration) {
case 30: case 30:
if (cost == 60.0) { if (cost == 60.0) {
@ -2932,15 +3075,17 @@ int main() {
<< "cost" << cost; << "cost" << cost;
exit(-1); exit(-1);
} }
#endif
//std::string duration = Calculator::GetInstance().GetDurationFromCost(&cfg, 3, start.toString(Qt::ISODate).toStdString().c_str(), cost); //std::string duration = Calculator::GetInstance().GetDurationFromCost(&cfg, 3, start.toString(Qt::ISODate).toStdString().c_str(), cost);
//Q_ASSERT(cost == duration*2.5); //Q_ASSERT(cost == duration*2.5);
//qCritical() << "start" << start.toString(Qt::ISODate) //qCritical() << "start" << start.toString(Qt::ISODate)
// << "cost" << cost // << "cost" << cost
// << "until" << duration.c_str() << start.secsTo(QDateTime::fromString(duration.c_str(), Qt::ISODate)) / 60; // << "until" << duration.c_str() << start.secsTo(QDateTime::fromString(duration.c_str(), Qt::ISODate)) / 60;
} //}
} }
#if 0
Configuration::SpecialDaysType specialDays = cfg.SpecialDays; Configuration::SpecialDaysType specialDays = cfg.SpecialDays;
for (Configuration::SpecialDaysType::const_iterator it = specialDays.cbegin(); for (Configuration::SpecialDaysType::const_iterator it = specialDays.cbegin();
it != specialDays.cend(); ++it) { it != specialDays.cend(); ++it) {
@ -2961,7 +3106,7 @@ int main() {
<< "duration" << duration << "duration" << duration
<< "cost" << cost; << "cost" << cost;
} }
#endif
} }
} }
return 0; return 0;

View File

@ -1,3 +1,5 @@
QT += core
TEMPLATE = app TEMPLATE = app
TARGET = main TARGET = main
@ -30,9 +32,16 @@ SOURCES += main.cpp
# HEADERS += # HEADERS +=
OTHER_FILES += \ OTHER_FILES += \
/opt/ptu5/opt/customer_502/etc/psa_tariff/tariff01.json \ /opt/ptu5/opt/customer_335/etc/psa_tariff/tariff01.json \
/opt/ptu5/opt/customer_502/etc/psa_tariff/tariff02.json \ /opt/ptu5/opt/customer_335/etc/psa_tariff/tariff02.json \
/opt/ptu5/opt/customer_502/etc/psa_tariff/tariff03.json /opt/ptu5/opt/customer_249/etc/psa_tariff/tariff01.json \
/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff02.json \
/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff03.json \
/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff04.json \
/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff05.json \
/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff06.json \
/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff07.json \
/opt/ptu5/opt/customer_249/etc/psa_tariff/tariff08.json

1529
out.txt Normal file

File diff suppressed because it is too large Load Diff