Compare commits

...

76 Commits
0.0.1 ... 2.0.0

Author SHA1 Message Date
9bfea0f46d Add compute_next_timestep() 2023-11-27 08:59:51 +01:00
7ee90a9e8a Fix: GetDurationForPrice return proper value not only '0' 2023-11-23 15:06:57 +01:00
8f2609c4ae Fix: GetDurationFromCost for PaymentMethod::Steps 2023-11-23 11:14:21 +01:00
453ca266a5 Merge remote-tracking branch 'origin/schoenau_23112023' 2023-11-23 09:46:42 +01:00
0217bb8918 GetTimeStep() and GetPriceForTimeStep(): use getPaymentOptions(). 2023-11-23 09:41:40 +01:00
4b35b1ffb7 Implement GetDurationForPrice(). 2023-11-23 09:41:02 +01:00
80e228b498 GetCostFromDuration(): don't use condiftion PaymentMethod::Steps,
but the multimap YearPeriod, which must be empty.
2023-11-23 09:39:26 +01:00
574161ff76 Call getDurationForPrice() in GetDurationForCost(). 2023-11-23 09:38:34 +01:00
b80cd5e6ef Remove parameter paymentMethod.
Add GetDurationForPrice().
2023-11-23 09:36:50 +01:00
ccbf07a654 Use new getPaymentOptions interface 2023-11-23 08:42:35 +01:00
3a2e521345 Add interface to access 'PaymentOptions' 2023-11-22 16:27:41 +01:00
cd77e380ef Read project/version-info from tariff-config ...
... if available
2023-11-22 11:27:09 +01:00
aaa4348a9a Add ATBProject to configuration 2023-11-22 11:14:48 +01:00
17c4aac452 Add header file atb_project.h 2023-11-22 11:14:38 +01:00
68c438bfe0 Add header file for project-variables 2023-11-22 11:13:37 +01:00
509bc29d7e Fix: read tariff configuration file 2023-11-22 10:17:40 +01:00
f7e462188f Add methods for PaymentMethod::Steps 2023-11-22 09:53:07 +01:00
d15c9dad29 Update tariff04 (virtual dayticket) 2023-06-27 17:43:58 +02:00
cb8cd5dead Merge branch 'moransBranch' 2023-06-14 11:28:27 +02:00
9d64350e4f Merge branch 'moransBranch' of git.mimbach49.de:GerhardHoffmann/MOBILISIS-Calculator into moransBranch 2023-06-14 11:27:43 +02:00
1a71edc274 max_time=300, unit_id=1 2023-06-13 13:32:16 +02:00
51d8beda2a max_time=300, unit_id=1 2023-06-13 13:32:12 +02:00
7bab9d6ba2 max_time=300, unit_id=1 2023-06-13 13:32:08 +02:00
8b4d64bd0c max_time=300, unit_id=1 2023-06-13 13:31:42 +02:00
eefdde4693 Removed section whith superfluous 'price_per_unit < 0' check.
Removed calc_price-caculation followed by shift of inputDate.
2023-06-13 12:12:23 +02:00
6157861d62 Monday starts with 1 2023-06-13 12:11:09 +02:00
23748966de Merge branch 'moransBranch' of git.mimbach49.de:GerhardHoffmann/MOBILISIS-Calculator into moransBranch 2023-05-19 15:49:38 +02:00
7bd7f66666 Fixed pra_payment_unit_id 2023-05-17 10:08:02 +02:00
268d43cdea GetDailyTicketDuration: use QDateTime for timestamps 2023-05-16 16:43:45 +02:00
a453886f0a Merge branch 'master' into moransBranch 2023-05-16 15:35:47 +02:00
eef94a3fb3 Change interface: use QDateTime
- use QDateTime instead of char*-string
 - GetCostFromDuration: add end_datetime as a return value
2023-05-16 15:31:53 +02:00
88a0b6ebe2 Make main.c compile again 2023-05-16 11:10:49 +02:00
3097819c01 Update interface for 'compute_duration_for_daily_ticket() 2023-05-16 11:07:21 +02:00
acf799da7e Add explaining comments 2023-05-15 17:37:51 +02:00
3bf71f84d5 Merge branch 'moransBranch' 2023-05-15 17:33:51 +02:00
73f5eca656 Tariff config: add day ticket 2023-05-15 17:23:10 +02:00
b8753cc2ed Update tariff config for test 2023-05-15 17:06:57 +02:00
29986e0451 Merge branch 'moransBranch' of git.mimbach49.de:GerhardHoffmann/MOBILISIS-Calculator into moransBranch 2023-05-15 16:58:48 +02:00
1146db743c Add explaining comments 2023-05-15 16:58:28 +02:00
c6302edec5 Format all json files 2023-05-15 16:57:45 +02:00
617eee39ed Daily ticket 2023-05-15 14:05:55 +02:00
6b3c1cbf0c Fix with min time in GetDurationFromCost 2023-05-14 17:19:24 +02:00
1142efaec2 Rounding minutes seems to be fixed ... 2023-05-14 16:15:37 +02:00
90eae152bf Merge branch 'moransBranch' 2023-05-12 14:48:19 +02:00
6d001f1501 Fix: QDateTime.addSecs() creates a new object 2023-05-12 14:28:30 +02:00
de32022b89 Merge branch 'moransBranch' of git.mimbach49.de:GerhardHoffmann/MOBILISIS-Calculator into moransBranch 2023-05-12 14:10:57 +02:00
1e2f1589ac Fix: QDateTime::fromString() 2023-05-12 14:10:16 +02:00
2f8c8cab4c Another small fix on GetDurationFromCost() 2023-05-12 13:02:10 +02:00
ee1f7eca44 Merge branch 'master' of git.mimbach49.de:GerhardHoffmann/MOBILISIS-Calculator 2023-05-12 12:43:49 +02:00
1069c5ad90 main: add test for GetDurationFromCost 2023-05-12 12:43:07 +02:00
46bffc250d Fix: includepath for main 2023-05-12 12:41:37 +02:00
2599513ef9 Minor fixes with +/- 1 minute offset. 2023-05-12 12:40:25 +02:00
ef66c1f0c0 Fixed GetDurationFromCost() 2023-05-12 11:55:35 +02:00
219d820104 GetCostFromDuration fixed 2023-05-12 09:20:46 +02:00
ed9166c226 Windows: set timezone as -3600. 2023-05-11 13:58:33 +02:00
818c67ad63 Windows debug: for init-Tariff, do not read zone_ne, but use the path given directly. 2023-05-11 13:57:31 +02:00
4a076e1dad Fix: string to QDateTime 2023-05-11 09:59:37 +02:00
62426e60d5 Fix: use toSecsSinceEpoch() 2023-05-11 09:58:54 +02:00
c28351b1bf Add debug messages 2023-05-11 09:58:15 +02:00
69c469c918 Merge branch 'master' of git.mimbach49.de:GerhardHoffmann/MOBILISIS-Calculator 2023-05-10 16:27:34 +02:00
e7606b6568 Added overoaded versions for compute_price_for_parking_ticket() and
compute_duration_for_parking_ticket() using QDateTime parameters.
Added new error code WRONG_ISO_TIME_FORMAT.
2023-05-10 16:16:24 +02:00
fe0ebb409a Merge branch 'master' of git.mimbach49.de:GerhardHoffmann/MOBILISIS-Calculator 2023-05-10 13:34:18 +02:00
3d88c8e67e Fix: setting calcState description 2023-05-10 13:33:28 +02:00
eebb6d926e Merge branch 'master' of https://git.mimbach49.de/GerhardHoffmann/MOBILISIS-Calculator 2023-05-10 13:11:47 +02:00
69c48e3acc Correction for argument-value of localtime_r()-function
(expects UTC-time instead of local time.)
2023-05-10 13:08:28 +02:00
5c0bbf1502 Fix: init_tariff(): cleanup on error 2023-05-09 13:05:02 +02:00
31df676b57 Merge branch 'master' of git.mimbach49.de:GerhardHoffmann/MOBILISIS-Calculator 2023-05-09 13:04:23 +02:00
889fceaae0 Use strftime to get ISO time format for valid ticket end time. 2023-05-09 13:03:51 +02:00
5ec2a6d730 Merge branch 'master' of git.mimbach49.de:GerhardHoffmann/MOBILISIS-Calculator 2023-05-09 11:53:31 +02:00
136e6687b8 remove wrong debug-out-put. Use ceil() instead on floor() to prevent rounding error.:w 2023-05-09 11:52:17 +02:00
3cc447ca87 Merge branch 'master' of git.mimbach49.de:GerhardHoffmann/MOBILISIS-Calculator 2023-05-09 11:47:05 +02:00
b02115bf75 Prepare the use of ceil() instead of floor(). 2023-05-09 11:41:41 +02:00
ceb545b432 Implemented compute_duration_for_parking_ticket(). 2023-05-09 11:40:14 +02:00
01f2dc07ce Added INVALID_START_DATE.
Added compute_duration_for_parking_ticket().
2023-05-09 11:38:39 +02:00
c5960a031e init_tariff, compute_price_for_parking_ticket:
return instance of CalcState as info for errors or success status.
2023-05-08 12:34:01 +02:00
1c03745333 Add CalcState to be used as return type of tarif_init and compute_price_for_parking_ticket. 2023-05-08 12:32:44 +02:00
18 changed files with 4463 additions and 634 deletions

View File

@@ -0,0 +1,13 @@
#ifndef ATB_PROJECT_H_INCLUDED
#define ATB_PROJECT_H_INCLUDED
#include <QString>
class ATBProject {
public:
QString project;
QString version;
QString info;
};
#endif // ATB_PROJECT_H_INCLUDED

View File

@@ -4,6 +4,9 @@
#include <time.h>
#include <inttypes.h>
#include <QString>
#include <QDateTime>
#ifdef WIN32
#ifdef CALCULATE_LIBRARY_EXPORTS
#define CALCULATE_LIBRARY_API __declspec(dllexport)
@@ -18,9 +21,9 @@ class Configuration;
typedef Configuration parking_tariff_t;
#ifdef __cplusplus
extern "C" {
#endif
//#ifdef __cplusplus
//extern "C" {
//#endif
struct CALCULATE_LIBRARY_API price_t {
uint32_t units;
@@ -30,16 +33,115 @@ struct CALCULATE_LIBRARY_API price_t {
double vat;
};
bool CALCULATE_LIBRARY_API init_tariff(parking_tariff_t **tariff, char const *config_file);
void CALCULATE_LIBRARY_API free_tariff(parking_tariff_t *tariff);
int CALCULATE_LIBRARY_API get_zone_nr();
struct CALCULATE_LIBRARY_API CalcState {
enum class State : uint8_t {
SUCCESS,
ERROR_PARSING_ZONE_NR,
ERROR_LOADING_TARIFF,
ERROR_PARSING_TARIFF,
NEGATIVE_PARING_TIME,
INVALID_START_DATE,
WRONG_PARAM_VALUES,
WRONG_ISO_TIME_FORMAT,
ABOVE_MAX_PARKING_TIME,
BELOW_MIN_PARKING_TIME,
BELOW_MIN_PARKING_PRICE,
OVERPAID
};
bool CALCULATE_LIBRARY_API compute_price_for_parking_ticket(parking_tariff_t *tariff,
time_t start_parking_time,
time_t end_parking_time,
struct price_t *price);
#ifdef __cplusplus
} // extern "C"
#endif
State m_status;
QString m_desc;
explicit CalcState() : m_status(State::SUCCESS), m_desc("") {}
explicit operator bool() const noexcept {
return (m_status == State::SUCCESS);
}
explicit operator QString () const noexcept {
QString s;
switch (m_status) {
case State::SUCCESS:
s = "SUCCESS";
break;
case State::ERROR_PARSING_ZONE_NR:
s = "ERROR_PARSING_ZONE_NR";
break;
case State::ERROR_LOADING_TARIFF:
s = "ERROR_LOADING_TARIFF";
break;
case State::ERROR_PARSING_TARIFF:
s = "ERROR_PARSING_TARIFF";
break;
case State::NEGATIVE_PARING_TIME:
s = "NEGATIVE_PARKING_TIME";
break;
case State::ABOVE_MAX_PARKING_TIME:
s = "ABOVE_MAX_PARKING_TIME";
break;
case State::WRONG_PARAM_VALUES:
s = "WRONG_PARAM_VALUES";
break;
case State::BELOW_MIN_PARKING_TIME:
s = "BELOW_MIN_PARKING_TIME";
break;
case State::BELOW_MIN_PARKING_PRICE:
s = "BELOW_MIN_PARKING_PRICE";
break;
case State::OVERPAID:
s = "OVERPAID";
break;
case State::INVALID_START_DATE:
s = "INVALID_START_DATE";
break;
case State::WRONG_ISO_TIME_FORMAT:
s = "WRONG_ISO_TIME_FORMAT";
}
return s + ":" + m_desc;
}
CalcState &set(State s) { m_status = s; return *this; }
CalcState &setDesc(QString s) { m_desc = s; return *this; }
};
CalcState CALCULATE_LIBRARY_API init_tariff(parking_tariff_t **tariff,
char const *config_file);
void CALCULATE_LIBRARY_API free_tariff(parking_tariff_t *tariff);
int CALCULATE_LIBRARY_API get_zone_nr(int zone = -1);
int CALCULATE_LIBRARY_API compute_next_timestep(parking_tariff_t *tariff, int currentTimeMinutes, int UpDown);
CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( // deprecated
parking_tariff_t *tariff,
time_t start_parking_time,
time_t end_parking_time,
struct price_t *price);
CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
parking_tariff_t *tariff,
QDateTime const &start_parking_time,
int netto_parking_time,
QDateTime &end_parking_time, // return value
struct price_t *price); // return value
CalcState CALCULATE_LIBRARY_API compute_duration_for_parking_ticket( // deprecated
parking_tariff_t *tariff,
time_t start_parking_time,
double cost,
QString &duration);
CalcState CALCULATE_LIBRARY_API compute_duration_for_parking_ticket(
parking_tariff_t *tariff,
QDateTime const &start_parking_time,
double cost,
QDateTime &ticketEndTime); // return value
CalcState CALCULATE_LIBRARY_API compute_duration_for_daily_ticket(
parking_tariff_t *tariff,
QDateTime const &start_parking_time,
QDateTime &ticketEndTime);
//#ifdef __cplusplus
//} // extern "C"
//#endif
#endif // CALCULATE_PRICE_H

View File

@@ -1,7 +1,8 @@
#pragma once
#include <iostream>
#include "configuration.h"
#include "payment_method.h"
#include <QDateTime>
using namespace std;
class Calculator
@@ -23,7 +24,25 @@ public:
/// <param name="tariff_cfg">Pointer to configuration</param>
/// <param name="vehicle_type">Type of vehicle</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="end_datetime">Date/time of park end to be conducted in ISO8601 format (e.g. 2022-12-25T08:00:00Z) </param>
/// <param name="durationMin">Duration of parking in minutes</param>
/// <returns>Returns cost (data type: double)</returns>
double GetCostFromDuration(Configuration* cfg, uint8_t vehicle_type, char const* start_datetime, double durationMin, bool nextDay = false, bool prepaid = false);
};
double GetCostFromDuration(Configuration* cfg, uint8_t vehicle_type, const QDateTime start_datetime, QDateTime & end_datetime, double durationMin, bool nextDay = false, bool prepaid = false);
// Daily ticket
QDateTime GetDailyTicketDuration(Configuration* cfg, const QDateTime start_datetime, uint8_t payment_option, bool carry_over);
//
// helper function to find time steps for a tariff with PaymentMethod::Steps
// (e.g. Schoenau/Koenigsee)
//
QList<int> GetTimeSteps(Configuration *cfg) const;
private:
// Introduced for PaymentMethod::Steps (e.g. Schoenau)
// For tariff of following structure: only steps, no special days, nonstop.
uint32_t GetCostFromDuration(Configuration *cfg, QDateTime const &start, quint64 durationMinutes) const;
uint32_t GetCostFromDuration(Configuration *cfg, QDateTime const &start, QDateTime const &end) const;
uint32_t GetPriceForTimeStep(Configuration *cfg, int timeStep) const;
uint32_t GetDurationForPrice(Configuration *cfg, int price) const;
};

View File

@@ -20,6 +20,7 @@
#include "member_type.h"
#include "period_year.h"
#include "payment_rate.h"
#include "atb_project.h"
using namespace std;
using namespace rapidjson;
@@ -27,8 +28,8 @@ using namespace rapidjson;
class Configuration
{
public:
ATBCurrency Currency;
ATBProject project;
ATBCurrency Currency;
ATBDuration duration;
multimap<int, ATBDuration> Duration;
@@ -48,6 +49,8 @@ public:
/// <returns>Returns operation status bool (OK | FAIL) </returns>
bool ParseJson(Configuration* cfg, const char* json);
ATBPaymentOption const & getPaymentOptions();
private:
/// <summary>
/// Identify type of JSON member
@@ -55,4 +58,6 @@ private:
/// <param name="member_name"></param>
/// <returns></returns>
MemberType IdentifyJsonMember(const char* member_name);
};
ATBPaymentOption currentPaymentOptions;
};

View File

@@ -2,12 +2,12 @@
enum DayOfWeek
{
Saturday = 0x06,
Sunday = 0x01,
Monday = 0x02,
Tuesday = 0x02,
Wednesday = 0x03,
Thursday = 0x04,
Friday = 0x05,
UndefinedDay = 0xFF
};
Monday = 0x01,
Tuesday = 0x02,
Wednesday = 0x03,
Thursday = 0x04,
Friday = 0x05,
Saturday = 0x06,
Sunday = 0x07,
UndefinedDay = 0xFF
};

View File

@@ -14,4 +14,5 @@ public:
double pop_max_time;
double pop_min_price;
int pop_carry_over;
};
int pop_daily_card_price;
};

View File

@@ -68,5 +68,6 @@ public:
/// </summary>
/// <param name="pra_price"></param>
/// <returns></returns>
static double CalculatePricePerUnit(double pra_price);
static double CalculatePricePerUnit(double pra_price, double durationUnit = -1);
};

View File

@@ -1,6 +1,6 @@
TEMPLATE = lib
TARGET = mobilisis_calc
# CONFIG += staticlib
#CONFIG += staticlib
QMAKE_CXXFLAGS += -std=c++17 -g -O0
@@ -65,7 +65,8 @@ HEADERS += \
include/mobilisis/tariff_period_year.h \
include/mobilisis/tariff_payment_rate.h \
include/mobilisis/tariff_log.h \
include/mobilisis/calculate_price.h
include/mobilisis/calculate_price.h \
include/mobilisis/atb_project.h
OTHER_FILES += src/main.cpp

View File

@@ -10,25 +10,31 @@
static Calculator calculator;
int CALCULATE_LIBRARY_API get_zone_nr() {
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();
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;
}
return -1;
}
bool CALCULATE_LIBRARY_API init_tariff(parking_tariff_t **tariff, char const *config_file) {
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
@@ -36,7 +42,9 @@ bool CALCULATE_LIBRARY_API init_tariff(parking_tariff_t **tariff, char const *co
qCritical() << " ... zone = " << zone;
if (zone <= 0) {
return false;
delete *tariff;
*tariff = nullptr;
return calcState.set(CalcState::State::ERROR_PARSING_ZONE_NR);
}
QString confFile(config_file);
@@ -48,62 +56,294 @@ bool CALCULATE_LIBRARY_API init_tariff(parking_tariff_t **tariff, char const *co
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()) {
if (fname.exists() &&
fname.open(QIODevice::ReadOnly | QIODevice::Text)) {
// DEBUG
qCritical() << " ... confFile exists";
qCritical() << " ... confFile is open";
if (fname.open(QIODevice::ReadOnly | QIODevice::Text)) {
// DEBUG
qCritical() << " ... confFile is open";
QString json = fname.readAll();
return (*tariff)->ParseJson(*tariff, json.toStdString().c_str());
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 << ") failed!";
qCritical() << "init_tariff: Parsing tariff config (" << confFile << ")";
return false;
return calcState;
}
void CALCULATE_LIBRARY_API free_tariff(parking_tariff_t *tariff) {
delete tariff;
if (tariff != nullptr) {
delete tariff;
}
}
bool CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
parking_tariff_t *tariff,
time_t start_parking_time, // in minutes
time_t end_parking_time, // in minutes
struct price_t *price) {
int const duration = end_parking_time - start_parking_time;
if (duration > 0) {
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);
double cost = calculator.GetCostFromDuration(
tariff, PaymentOption::Option1,
cs.toLocal8Bit().constData(),
duration, false, true);
price->units = cost;
price->netto = cost;
return true;
//
// UpDown 1 -> up; 0 -> down
int CALCULATE_LIBRARY_API compute_next_timestep(parking_tariff_t *tariff, int currentTimeMinutes, int UpDown)
{
static const QList<int> stepList = calculator.GetTimeSteps(tariff);
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
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];
}
}
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_PARING_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) {
memset(price, 0x00, sizeof(*price));
return true;
return calcState.set(CalcState::State::SUCCESS);
}
qCritical() << "ERROR start_parking_time (" << start_parking_time << ") <"
<< "end_parking_time (" << end_parking_time << ")";
return false;
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.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 const &start_parking_time,
int netto_parking_time,
QDateTime &end_parking_time,
struct price_t *price)
{
CalcState calcState;
double minMin = tariff->getPaymentOptions().pop_min_time;
double maxMin = tariff->getPaymentOptions().pop_max_time;
// DEBUG
qCritical() << "compute_price_for_parking_ticket() " << 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_PARING_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) {
memset(price, 0x00, sizeof(*price));
return calcState.set(CalcState::State::SUCCESS);
}
if (start_parking_time.isValid()) {
double cost = calculator.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, true);
double minCost = tariff->getPaymentOptions().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() << " -> calculated cost (price->netto) = " << cost;
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.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.GetDurationFromCost(
tariff,
tariff->getPaymentOptions().pop_payment_method_id,
cs.toLocal8Bit().constData(),
price, false, true).c_str();
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.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);
}

File diff suppressed because it is too large Load Diff

View File

@@ -59,8 +59,9 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
|| !document.HasMember("PaymentRate")
|| !document.HasMember("Duration")
//|| !document.HasMember("WeekDays")
|| !document.HasMember("SpecialDaysWorktime")
|| !document.HasMember("SpecialDays"))
//|| !document.HasMember("SpecialDaysWorktime")
//|| !document.HasMember("SpecialDays")
)
{
printf("%s", "Error: not a valid configuration JSON\n");
return false;
@@ -87,13 +88,26 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
const char* mb_name = i->name.GetString();
if (mb_name == NULL) continue;
// if (!document[mb_name].IsArray()) {
std::string const _mb_name(mb_name);
if (_mb_name == "version" || _mb_name == "project" ||
_mb_name == "zone" || _mb_name == "info") {
if (document[mb_name].IsString()) {
QString const _mb_name(mb_name);
if (_mb_name.startsWith("Project", Qt::CaseInsensitive)) {
cfg->project.project = document[mb_name].GetString();
continue;
}
if (_mb_name.startsWith("Version", Qt::CaseInsensitive)) {
cfg->project.version = document[mb_name].GetString();
continue;
}
// }
if (_mb_name.startsWith("Info", Qt::CaseInsensitive)) {
cfg->project.info = document[mb_name].GetString();
continue;
}
}
// ... everything else should be an array
if (!document[mb_name].IsArray()) {
continue;
}
//printf(" -%s\n", mb_name);
@@ -154,7 +168,9 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
else if (strcmp(inner_obj_name, "pop_max_time") == 0) PaymentOption.pop_max_time = k->value.GetDouble();
else if (strcmp(inner_obj_name, "pop_min_price") == 0) PaymentOption.pop_min_price = k->value.GetDouble();
else if (strcmp(inner_obj_name, "pop_carry_over") == 0) PaymentOption.pop_carry_over = k->value.GetInt();
break;
else if (strcmp(inner_obj_name, "pop_daily_card_price") == 0) PaymentOption.pop_daily_card_price = k->value.GetInt();
this->currentPaymentOptions = PaymentOption;
break;
case MemberType::DurationType:
if (strcmp(inner_obj_name, "pun_id") == 0) Duration.pun_id = k->value.GetInt();
else if (strcmp(inner_obj_name, "pun_label") == 0) Duration.pun_label = k->value.GetString();
@@ -209,7 +225,7 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
cfg->PaymentMethod.insert(pair<int, ATBPaymentMethod>(PaymentMethod.pme_id, PaymentMethod));
break;
case MemberType::PaymentRateType:
cfg->PaymentRate.insert(pair<int, ATBPaymentRate>(PaymentRate.pra_payment_unit_id, PaymentRate));
cfg->PaymentRate.insert(pair<int, ATBPaymentRate>(PaymentRate.pra_payment_option_id, PaymentRate));
break;
case MemberType::PaymentOptionType:
cfg->PaymentOption.insert(pair<int, ATBPaymentOption>(PaymentOption.pop_payment_method_id, PaymentOption));
@@ -244,3 +260,10 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
return false;
}
}
const ATBPaymentOption & Configuration::getPaymentOptions()
{
return this->currentPaymentOptions;
}

View File

@@ -8,12 +8,15 @@ static int protection_counter = 0;
/// </summary>
/// <param name="pra_price"></param>
/// <returns></returns>
double Utilities::CalculatePricePerUnit(double pra_price)
double Utilities::CalculatePricePerUnit(double pra_price, double durationUnit)
{
try
{
double price_per_unit = pra_price;
price_per_unit /= 60.0f; // Divided by 60 because price per unit is set per hour and we are using minutes
double unit = durationUnit;
if(unit < 0 || unit > 65535 ) unit = 60.0f;
price_per_unit /= unit; // Divided by 60 because price per unit is set per hour and we are using minutes
//printf("Price per unit (min) is: %lf\n", price_per_unit);
return price_per_unit;
}
@@ -33,7 +36,7 @@ time_t Utilities::GetCurrentLocalTime()
memset(&tm_curr_time, '\0', sizeof(struct tm));
tm_curr_time = *localtime(&curr_time);
curr_time = mktime(&tm_curr_time) - timezone;
curr_time = mktime(&tm_curr_time); //- timezone;
return curr_time;
}
catch (...)

View File

@@ -1,10 +1,9 @@
#include <calculate_price.h>
#ifdef WIN32
#include <time.h>
#include <iomanip>
#include <sstream>
#include <calculate_price.h>
extern "C" char* strptime(const char* s,
const char* f,
@@ -27,87 +26,135 @@ extern "C" char* strptime(const char* s,
#include <QDebug>
#include <QDateTime>
#include <QDir>
#include <fstream>
#include <sstream>
#include "calculator_functions.h"
#include <calculate_price.h>
int main() {
std::ifstream input(QDir::homePath().append("/tariff01.json").toStdString());
std::stringstream sstr;
while(input >> sstr.rdbuf());
std::string json(sstr.str());
Calculator calculator;
Configuration cfg;
bool isParsed = cfg.ParseJson(&cfg, json.c_str());
cout << endl;
char const *startDate = "";
if (isParsed)
{
startDate = "2023-05-10T13:52:18.665Z";
std::string duration = calculator.GetDurationFromCost(&cfg, 3, (char *)startDate, 33, false, true);
cout << "---> startDate " << startDate << " _price_ = " << 33
<< " Total duration is: " << duration << endl;
}
return 0;
parking_tariff_t *tariff = 0;
if (init_tariff(&tariff, "/etc/psa_tariff/")) {
if (init_tariff(&tariff, "/etc/psa_tariff/")) {
struct price_t price;
memset(&price, 0x00, sizeof(price));
QDateTime start = QDateTime::currentDateTime();
QDateTime start = QDateTime::fromString("2023-05-11T07:50:00",Qt::ISODate); //QDateTime::currentDateTime();
time_t start_parking_time = start.toSecsSinceEpoch() / 60;
time_t end_parking_time = start_parking_time + 60;
time_t end_parking_time = start_parking_time + 615;
if (compute_price_for_parking_ticket(tariff,
start_parking_time,
end_parking_time,
&price)) {
qDebug() << "price=" << price.netto;
&price))
{
qDebug() << "GetCostFromDuration() => price=" << price.netto;
}
// tests
struct tm now;
memset(&now, 0, sizeof(now));
// 3.Jan 2023 -> Tuesday
strptime("2023-01-03T14:00:00", "%Y-%m-%dT%H:%M:%S", &now);
for (int i = 0; i < 600; ++i) {
start_parking_time = mktime(&now);
end_parking_time = start_parking_time + 240; // duration == 240
if (compute_price_for_parking_ticket(tariff,
start_parking_time,
end_parking_time,
&price)) {
int const zone = get_zone_nr();
switch (zone) {
case 1:
assert(price.netto == 879); // expected value: 880
break;
case 2:
/* fall through */
case 3:
assert(price.netto == 1920);
break;
}
}
time_t t = start_parking_time + 60;
now = *localtime(&t);
QString duration;
if(compute_duration_for_parking_ticket(tariff,start_parking_time,3090,duration))
{
qDebug() << "GetDurationFromCost() => duration=" << duration;
}
//
// test May 1st 2023
//
memset(&now, 0, sizeof(now));
strptime("2023-04-30T06:00:00", "%Y-%m-%dT%H:%M:%S", &now);
now.tm_hour -= 1; // for ctime
for (int i=0; i<6*24; ++i) {
int const duration = 120;
time_t t = mktime(&now);
start_parking_time = t / 60;
end_parking_time = start_parking_time + duration;
if (compute_price_for_parking_ticket(tariff,
start_parking_time,
end_parking_time,
&price)) {
int const zone = get_zone_nr();
switch (zone) {
case 1:
qDebug() << i << zone << ctime(&t) << price.netto << " FT";
assert(price.netto == 440);
break;
case 2:
/* fall through */
case 3:
qDebug() << i << zone << ctime(&t) << price.netto << " FT";
assert(price.netto == 960);
break;
}
}
// Daily ticket
//compute_duration_for_daily_ticket(tariff,start.toString(Qt::ISODate),3);
t = (start_parking_time + 60)*60;
now = *localtime(&t);
}
//Configuration* cfg, QString start_datetime, uint8_t payment_option, bool carry_over
// // tests
// struct tm now;
// memset(&now, 0, sizeof(now));
// // 3.Jan 2023 -> Tuesday
// strptime("2023-01-03T14:00:00", "%Y-%m-%dT%H:%M:%S", &now);
// for (int i = 0; i < 600; ++i) {
// start_parking_time = mktime(&now);
// end_parking_time = start_parking_time + 240; // duration == 240
// if (compute_price_for_parking_ticket(tariff,
// start_parking_time,
// end_parking_time,
// &price)) {
// int const zone = get_zone_nr(1);
// switch (zone) {
// case 1:
// assert(price.netto == 879); // expected value: 880
// break;
// case 2:
// /* fall through */
// case 3:
// assert(price.netto == 1920);
// break;
// }
// }
// time_t t = start_parking_time + 60;
// now = *localtime(&t);
// }
// //
// // test May 1st 2023
// //
// memset(&now, 0, sizeof(now));
// strptime("2023-04-30T06:00:00", "%Y-%m-%dT%H:%M:%S", &now);
// now.tm_hour -= 1; // for ctime
// // for (int i=0; i<6*24; ++i) {
// for (int i=0; i<1; ++i) {
// int const duration = 120;
// time_t t = mktime(&now);
// start_parking_time = t / 60;
// end_parking_time = start_parking_time + duration;
// if (compute_price_for_parking_ticket(tariff,
// start_parking_time,
// end_parking_time,
// &price)) {
// int const zone = get_zone_nr();
// switch (zone) {
// case 1:
// qDebug() << i << zone << ctime(&t) << price.netto << " FT";
// assert(price.netto == 440);
// break;
// case 2:
// /* fall through */
// case 3:
// qDebug() << i << zone << ctime(&t) << price.netto << " FT";
// assert(price.netto == 960);
// break;
// }
// }
// t = (start_parking_time + 60)*60;
// now = *localtime(&t);
// }
free_tariff(tariff);
}
@@ -144,7 +191,7 @@ int main() {
struct tm now; // = Utilities::DateTimeToStructTm("2023-03-01T16:00:00");
memset(&now, 0, sizeof(now));
char buffer[64];
//#if 0
//#if 0
// 3.Jan 2023 -> Tuesday
strptime("2023-01-03T14:00:00", "%Y-%m-%dT%H:%M:%S", &now);
for (int i = 0; i < 600; ++i) {
@@ -219,8 +266,8 @@ int main() {
int const duration = 120;
double cost = calculator.GetCostFromDuration(&cfg,
PaymentOption::Option1, buffer, duration,
false, true);
PaymentOption::Option1, buffer, duration,
false, true);
switch (zone) {
case 1:
@@ -258,8 +305,8 @@ int main() {
int const duration = 120;
double cost = calculator.GetCostFromDuration(&cfg,
PaymentOption::Option1, buffer, duration,
false, true);
PaymentOption::Option1, buffer, duration,
false, true);
switch (zone) {
case 1:
@@ -292,8 +339,8 @@ int main() {
double const compCost = (duration < 15) ? 0 : duration * ((zone == 1) ? 3.6666 : 8.0);
double cost = calculator.GetCostFromDuration(&cfg,
PaymentOption::Option1, buffer, duration,
false, true);
PaymentOption::Option1, buffer, duration,
false, true);
if (fabs(cost - compCost) > 1.0) { // zone 1 has rounding errors
cout << "ERROR ===> [" << i << "] " << asctime(&now)
<< " - Total cost is: " << cost << " FT (computed="

View File

@@ -7,6 +7,8 @@ QMAKE_CFLAGS = -c -pipe -std=c11 -g -O0 -Wall -Wno-attributes -W -DDEBUG -D_REEN
QMAKE_CXX_FLAGS += -std=c11
INCLUDEPATH += $$_PRO_FILE_PWD_/../../MOBILISIS-Calculator/library/include/mobilisis/
INCLUDEPATH += $$_PRO_FILE_PWD_/../../MOBILISIS-Calculator/library/include/rapidjson/
INCLUDEPATH += $$_PRO_FILE_PWD_/../../MOBILISIS-Calculator/library/include/
INCLUDEPATH += .
unix {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long