Compare commits
59 Commits
Author | SHA1 | Date | |
---|---|---|---|
d15c9dad29
|
|||
cb8cd5dead
|
|||
9d64350e4f
|
|||
1a71edc274 | |||
51d8beda2a | |||
7bab9d6ba2 | |||
8b4d64bd0c | |||
eefdde4693 | |||
6157861d62 | |||
23748966de
|
|||
7bd7f66666 | |||
268d43cdea
|
|||
a453886f0a
|
|||
eef94a3fb3
|
|||
88a0b6ebe2
|
|||
3097819c01
|
|||
acf799da7e
|
|||
3bf71f84d5
|
|||
73f5eca656
|
|||
b8753cc2ed
|
|||
29986e0451
|
|||
1146db743c
|
|||
c6302edec5
|
|||
617eee39ed | |||
6b3c1cbf0c | |||
1142efaec2 | |||
90eae152bf
|
|||
6d001f1501
|
|||
de32022b89
|
|||
1e2f1589ac
|
|||
2f8c8cab4c | |||
ee1f7eca44
|
|||
1069c5ad90
|
|||
46bffc250d
|
|||
2599513ef9 | |||
ef66c1f0c0 | |||
219d820104 | |||
ed9166c226 | |||
818c67ad63 | |||
4a076e1dad
|
|||
62426e60d5
|
|||
c28351b1bf
|
|||
69c469c918
|
|||
e7606b6568 | |||
fe0ebb409a
|
|||
3d88c8e67e
|
|||
eebb6d926e | |||
69c48e3acc | |||
5c0bbf1502
|
|||
31df676b57
|
|||
889fceaae0 | |||
5ec2a6d730
|
|||
136e6687b8 | |||
3cc447ca87
|
|||
b02115bf75 | |||
ceb545b432 | |||
01f2dc07ce | |||
c5960a031e | |||
1c03745333 |
@@ -4,6 +4,9 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#ifdef CALCULATE_LIBRARY_EXPORTS
|
#ifdef CALCULATE_LIBRARY_EXPORTS
|
||||||
#define CALCULATE_LIBRARY_API __declspec(dllexport)
|
#define CALCULATE_LIBRARY_API __declspec(dllexport)
|
||||||
@@ -18,9 +21,9 @@ class Configuration;
|
|||||||
|
|
||||||
typedef Configuration parking_tariff_t;
|
typedef Configuration parking_tariff_t;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
//#ifdef __cplusplus
|
||||||
extern "C" {
|
//extern "C" {
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
struct CALCULATE_LIBRARY_API price_t {
|
struct CALCULATE_LIBRARY_API price_t {
|
||||||
uint32_t units;
|
uint32_t units;
|
||||||
@@ -30,16 +33,113 @@ struct CALCULATE_LIBRARY_API price_t {
|
|||||||
double vat;
|
double vat;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool CALCULATE_LIBRARY_API init_tariff(parking_tariff_t **tariff, char const *config_file);
|
struct CALCULATE_LIBRARY_API CalcState {
|
||||||
void CALCULATE_LIBRARY_API free_tariff(parking_tariff_t *tariff);
|
enum class State : uint8_t {
|
||||||
int CALCULATE_LIBRARY_API get_zone_nr();
|
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,
|
State m_status;
|
||||||
time_t start_parking_time,
|
QString m_desc;
|
||||||
time_t end_parking_time,
|
|
||||||
struct price_t *price);
|
explicit CalcState() : m_status(State::SUCCESS), m_desc("") {}
|
||||||
#ifdef __cplusplus
|
|
||||||
} // extern "C"
|
explicit operator bool() const noexcept {
|
||||||
#endif
|
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);
|
||||||
|
|
||||||
|
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
|
#endif // CALCULATE_PRICE_H
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
#include <QDateTime>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
class Calculator
|
class Calculator
|
||||||
@@ -23,7 +23,11 @@ public:
|
|||||||
/// <param name="tariff_cfg">Pointer to configuration</param>
|
/// <param name="tariff_cfg">Pointer to configuration</param>
|
||||||
/// <param name="vehicle_type">Type of vehicle</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="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>
|
/// <param name="durationMin">Duration of parking in minutes</param>
|
||||||
/// <returns>Returns cost (data type: double)</returns>
|
/// <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);
|
||||||
|
};
|
||||||
|
@@ -55,4 +55,4 @@ private:
|
|||||||
/// <param name="member_name"></param>
|
/// <param name="member_name"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
MemberType IdentifyJsonMember(const char* member_name);
|
MemberType IdentifyJsonMember(const char* member_name);
|
||||||
};
|
};
|
||||||
|
@@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
enum DayOfWeek
|
enum DayOfWeek
|
||||||
{
|
{
|
||||||
Saturday = 0x06,
|
Monday = 0x01,
|
||||||
Sunday = 0x01,
|
Tuesday = 0x02,
|
||||||
Monday = 0x02,
|
Wednesday = 0x03,
|
||||||
Tuesday = 0x02,
|
Thursday = 0x04,
|
||||||
Wednesday = 0x03,
|
Friday = 0x05,
|
||||||
Thursday = 0x04,
|
Saturday = 0x06,
|
||||||
Friday = 0x05,
|
Sunday = 0x07,
|
||||||
UndefinedDay = 0xFF
|
UndefinedDay = 0xFF
|
||||||
};
|
};
|
||||||
|
@@ -14,4 +14,5 @@ public:
|
|||||||
double pop_max_time;
|
double pop_max_time;
|
||||||
double pop_min_price;
|
double pop_min_price;
|
||||||
int pop_carry_over;
|
int pop_carry_over;
|
||||||
};
|
int pop_daily_card_price;
|
||||||
|
};
|
||||||
|
@@ -68,5 +68,6 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pra_price"></param>
|
/// <param name="pra_price"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
static double CalculatePricePerUnit(double pra_price);
|
static double CalculatePricePerUnit(double pra_price, double durationUnit = -1);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
TARGET = mobilisis_calc
|
TARGET = mobilisis_calc
|
||||||
# CONFIG += staticlib
|
#CONFIG += staticlib
|
||||||
|
|
||||||
QMAKE_CXXFLAGS += -std=c++17 -g -O0
|
QMAKE_CXXFLAGS += -std=c++17 -g -O0
|
||||||
|
|
||||||
|
@@ -10,25 +10,31 @@
|
|||||||
|
|
||||||
static Calculator calculator;
|
static Calculator calculator;
|
||||||
|
|
||||||
int CALCULATE_LIBRARY_API get_zone_nr() {
|
int CALCULATE_LIBRARY_API get_zone_nr(int zone)
|
||||||
QFile zone("/etc/zone_nr");
|
{
|
||||||
if (zone.exists()) {
|
if(zone > -1) return zone;
|
||||||
QFileInfo finfo(zone);
|
else
|
||||||
if (finfo.size() <= 4) { // decimal 000\n
|
{
|
||||||
if (zone.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
QFile zone("/etc/zone_nr");
|
||||||
|
if (zone.exists()) {
|
||||||
QTextStream in(&zone);
|
QFileInfo finfo(zone);
|
||||||
return in.readLine(100).toInt();
|
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();
|
*tariff = new Configuration();
|
||||||
|
|
||||||
|
CalcState calcState;
|
||||||
|
#if __linux__
|
||||||
|
|
||||||
int const zone = get_zone_nr();
|
int const zone = get_zone_nr();
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
@@ -36,7 +42,9 @@ bool CALCULATE_LIBRARY_API init_tariff(parking_tariff_t **tariff, char const *co
|
|||||||
qCritical() << " ... zone = " << zone;
|
qCritical() << " ... zone = " << zone;
|
||||||
|
|
||||||
if (zone <= 0) {
|
if (zone <= 0) {
|
||||||
return false;
|
delete *tariff;
|
||||||
|
*tariff = nullptr;
|
||||||
|
return calcState.set(CalcState::State::ERROR_PARSING_ZONE_NR);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString confFile(config_file);
|
QString confFile(config_file);
|
||||||
@@ -48,62 +56,252 @@ bool CALCULATE_LIBRARY_API init_tariff(parking_tariff_t **tariff, char const *co
|
|||||||
memset(buffer, 0x00, sizeof(buffer));
|
memset(buffer, 0x00, sizeof(buffer));
|
||||||
snprintf(buffer, sizeof(buffer)-1, "tariff%02d.json", zone);
|
snprintf(buffer, sizeof(buffer)-1, "tariff%02d.json", zone);
|
||||||
confFile += buffer;
|
confFile += buffer;
|
||||||
|
#else // windows
|
||||||
|
QString confFile(config_file);
|
||||||
|
#endif
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
qCritical() << " ... confFile = " << confFile;
|
qCritical() << " ... confFile = " << confFile;
|
||||||
|
|
||||||
QFile fname(confFile);
|
QFile fname(confFile);
|
||||||
if (fname.exists()) {
|
if (fname.exists() &&
|
||||||
|
fname.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
// DEBUG
|
// DEBUG
|
||||||
qCritical() << " ... confFile exists";
|
qCritical() << " ... confFile is open";
|
||||||
|
|
||||||
if (fname.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
QString json = fname.readAll();
|
||||||
|
if (! (*tariff)->ParseJson(*tariff, json.toStdString().c_str())) {
|
||||||
// DEBUG
|
delete *tariff;
|
||||||
qCritical() << " ... confFile is open";
|
*tariff = nullptr;
|
||||||
|
return calcState.set(CalcState::State::ERROR_PARSING_TARIFF);
|
||||||
QString json = fname.readAll();
|
|
||||||
return (*tariff)->ParseJson(*tariff, json.toStdString().c_str());
|
|
||||||
}
|
}
|
||||||
|
} 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) {
|
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,
|
// this is currently not used
|
||||||
time_t start_parking_time, // in minutes
|
CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
|
||||||
time_t end_parking_time, // in minutes
|
parking_tariff_t *tariff,
|
||||||
struct price_t *price) {
|
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(PaymentOption::Option1)->second.pop_min_time;
|
||||||
|
double maxMin = tariff->PaymentOption.find(PaymentOption::Option1)->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;
|
int const duration = end_parking_time - start_parking_time;
|
||||||
if (duration > 0) {
|
if (duration < 0) {
|
||||||
QDate const d(1970, 1, 1);
|
calcState.setDesc(QString("end=%1, start=%2")
|
||||||
QTime const t(0, 0, 0);
|
.arg(end_parking_time, start_parking_time));
|
||||||
QDateTime start(d, t, Qt::UTC);
|
return calcState.set(CalcState::State::NEGATIVE_PARING_TIME);
|
||||||
start = start.toLocalTime().addSecs(start_parking_time * 60);
|
}
|
||||||
if (start.isValid()) {
|
if (duration > maxMin) {
|
||||||
QString cs = start.toString(Qt::ISODate);
|
calcState.setDesc(QString("duration=%1, maxMin=%2").arg(duration).arg(maxMin));
|
||||||
double cost = calculator.GetCostFromDuration(
|
return calcState.set(CalcState::State::ABOVE_MAX_PARKING_TIME);
|
||||||
tariff, PaymentOption::Option1,
|
}
|
||||||
cs.toLocal8Bit().constData(),
|
if (duration < minMin) {
|
||||||
duration, false, true);
|
calcState.setDesc(QString("duration=%1, minMin=%2").arg(duration).arg(minMin));
|
||||||
price->units = cost;
|
return calcState.set(CalcState::State::BELOW_MIN_PARKING_TIME);
|
||||||
price->netto = cost;
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
if (duration == 0) {
|
if (duration == 0) {
|
||||||
memset(price, 0x00, sizeof(*price));
|
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 << ")";
|
QDate const d(1970, 1, 1);
|
||||||
return false;
|
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, PaymentOption::Option1,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
duration, false, true);
|
||||||
|
double minCost = tariff->PaymentOption.find(PaymentOption::Option1)->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->PaymentOption.find(PaymentOption::Option1)->second.pop_min_time;
|
||||||
|
double maxMin = tariff->PaymentOption.find(PaymentOption::Option1)->second.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, PaymentOption::Option1,
|
||||||
|
start_parking_time, // starting time
|
||||||
|
end_parking_time, // return value: end time
|
||||||
|
netto_parking_time, // minutes, netto
|
||||||
|
false, true);
|
||||||
|
double minCost = tariff->PaymentOption.find(PaymentOption::Option1)->second.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, PaymentOption::Option1,
|
||||||
|
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, PaymentOption::Option1,
|
||||||
|
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,
|
||||||
|
PaymentOption::Option1,
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -4,510 +4,540 @@
|
|||||||
#include "tariff_log.h"
|
#include "tariff_log.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <qdebug.h>
|
||||||
|
|
||||||
double total_duration_min = 0.0f;
|
double total_duration_min = 0.0f;
|
||||||
double total_cost = 0.0f;
|
double total_cost = 0.0f;
|
||||||
bool overtime = false;
|
bool overtime = false;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
#ifdef _WIN32
|
||||||
std::string Calculator::GetDurationFromCost(Configuration* cfg, uint8_t payment_option, char const* start_datetime, double price, bool nextDay, bool prepaid)
|
inline struct tm* localtime_r(const time_t *clock, struct tm* result){
|
||||||
|
if(!clock || !result) return NULL;
|
||||||
|
memcpy(result,localtime(clock),sizeof(*result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QDateTime Calculator::GetDailyTicketDuration(Configuration* cfg, const QDateTime start_datetime, uint8_t payment_option, bool carry_over)
|
||||||
{
|
{
|
||||||
// Get current date time from input
|
if(!start_datetime.isValid()) {
|
||||||
struct tm current_datetime = Utilities::DateTimeToStructTm(start_datetime);
|
return QDateTime();
|
||||||
time_t current_datetime_t;
|
}
|
||||||
|
|
||||||
// Get day of week
|
double day_price = 0.0f;
|
||||||
DayOfWeek weekdayId = DayOfWeek::UndefinedDay;
|
int current_special_day_id = -1;
|
||||||
weekdayId = Utilities::GetDayOfWeek(¤t_datetime);
|
bool is_special_day = Utilities::CheckSpecialDay(cfg, start_datetime.toString(Qt::ISODate).toStdString().c_str(), ¤t_special_day_id, &day_price);
|
||||||
|
|
||||||
//std::stringstream ss;
|
QDateTime inputDateTime = start_datetime;
|
||||||
|
QTime worktime_from;
|
||||||
|
QTime worktime_to;
|
||||||
|
|
||||||
// ss << "*** Input date is: " << start_datetime << " [weekday id = " << weekdayId << "]" << endl;
|
int daily_card_price = cfg->PaymentOption.find(payment_option)->second.pop_daily_card_price;
|
||||||
LOG_DEBUG("*** Input date is: ", start_datetime, " [weekday id = ", weekdayId, "]");
|
if(daily_card_price <= 0) {
|
||||||
|
LOG_ERROR("Calculator::GetDailyTicketDuration(): Daily ticket price zero or less");
|
||||||
|
return QDateTime();
|
||||||
|
}
|
||||||
|
|
||||||
double minMin = 0;
|
if(is_special_day)
|
||||||
minMin = cfg->PaymentOption.find(payment_option)->second.pop_min_time;
|
{
|
||||||
if (minMin < 0) minMin = 0;
|
worktime_from = QTime::fromString(cfg->SpecialDaysWorktime.find(current_special_day_id)->second.pedwt_time_from.c_str(), Qt::ISODate);
|
||||||
|
worktime_to = QTime::fromString(cfg->SpecialDaysWorktime.find(current_special_day_id)->second.pedwt_time_to.c_str(),Qt::ISODate);
|
||||||
|
|
||||||
double maxMin = 0;
|
if(inputDateTime.time() < worktime_from) inputDateTime.setTime(worktime_from);
|
||||||
maxMin = cfg->PaymentOption.find(payment_option)->second.pop_max_time;
|
if(carry_over) inputDateTime.setTime(worktime_from);
|
||||||
if (maxMin <= 0) maxMin = 60;
|
|
||||||
|
|
||||||
if (minMin >= maxMin)
|
if(inputDateTime.time() >= worktime_to)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Error: min_min cannot be greater or equal to max_min");
|
// Go to next day if outside worktime
|
||||||
return "PARKING NOT ALLOWED";
|
inputDateTime = inputDateTime.addSecs(86400);
|
||||||
}
|
return GetDailyTicketDuration(cfg,inputDateTime, payment_option,true);
|
||||||
|
}
|
||||||
|
|
||||||
if (maxMin <= minMin)
|
if(day_price <=0)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Error: max_min cannot be lower or equal than min_min");
|
// Go to next day if special day price is 0
|
||||||
return "PARKING NOT ALLOWED";
|
inputDateTime = inputDateTime.addSecs(86400);
|
||||||
}
|
return GetDailyTicketDuration(cfg,inputDateTime, payment_option,true);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t p_method = PaymentMethod::Undefined;
|
int diff = abs(inputDateTime.time().secsTo(worktime_to));
|
||||||
p_method = payment_option;
|
inputDateTime = inputDateTime.addSecs(diff);
|
||||||
LOG_DEBUG("Payment method id: ", (unsigned)p_method);
|
|
||||||
|
|
||||||
double day_price = 0.0f;
|
//qDebug() << "Ticket is valid until: " << inputDateTime.toString(Qt::ISODate) << "price = " << daily_card_price << ", duration = " << diff / 60;
|
||||||
int current_special_day_id = -1;
|
return inputDateTime;
|
||||||
bool is_special_day = Utilities::CheckSpecialDay(cfg, start_datetime, ¤t_special_day_id, &day_price);
|
}
|
||||||
LOG_DEBUG("Special day: ", is_special_day);
|
else
|
||||||
|
{
|
||||||
|
// Get day of week
|
||||||
|
int weekdayId = 0;
|
||||||
|
weekdayId = Utilities::ZellersAlgorithm(inputDateTime.date().day(),inputDateTime.date().month(),inputDateTime.date().year());
|
||||||
|
|
||||||
double money_left = price;
|
// If no working day found, skip it (recursively call method again)
|
||||||
LOG_DEBUG("Total money:", money_left);
|
size_t found = 0;
|
||||||
|
found = cfg->WeekDaysWorktime.count(weekdayId);
|
||||||
|
|
||||||
double price_per_unit = 0.0f;
|
// When no workday found, go to next available day
|
||||||
|
if(found <=0)
|
||||||
|
{
|
||||||
|
inputDateTime = inputDateTime.addSecs(86400);
|
||||||
|
return GetDailyTicketDuration(cfg,inputDateTime, payment_option,true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
worktime_from = QTime::fromString(cfg->WeekDaysWorktime.find(weekdayId)->second.pwd_time_from.c_str(),Qt::ISODate);
|
||||||
|
worktime_to = QTime::fromString(cfg->WeekDaysWorktime.find(weekdayId)->second.pwd_time_to.c_str(),Qt::ISODate);
|
||||||
|
if(inputDateTime.time() < worktime_from)
|
||||||
|
inputDateTime.setTime(worktime_from);
|
||||||
|
|
||||||
string worktime_from = "";
|
if(carry_over)
|
||||||
string worktime_to = "";
|
inputDateTime.setTime(worktime_from);
|
||||||
|
|
||||||
if (is_special_day)
|
if(inputDateTime.time() >= worktime_to)
|
||||||
{
|
{
|
||||||
// Set special day price
|
// Go to next day if outside worktime
|
||||||
price_per_unit = Utilities::CalculatePricePerUnit(day_price);
|
inputDateTime = inputDateTime.addSecs(86400);
|
||||||
worktime_from = cfg->SpecialDaysWorktime.find(current_special_day_id)->second.pedwt_time_from;
|
return GetDailyTicketDuration(cfg,inputDateTime, payment_option,true);
|
||||||
worktime_to = cfg->SpecialDaysWorktime.find(current_special_day_id)->second.pedwt_time_to;
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Set new price for the normal day
|
|
||||||
day_price = cfg->PaymentRate.find(payment_option)->second.pra_price;
|
|
||||||
price_per_unit = Utilities::CalculatePricePerUnit(day_price);
|
|
||||||
|
|
||||||
// If no working day found, skip it (recursively call method again)
|
int diff = abs(inputDateTime.time().secsTo(worktime_to));
|
||||||
size_t found = 0;
|
inputDateTime = inputDateTime.addSecs(diff);
|
||||||
found = cfg->WeekDaysWorktime.count(weekdayId);
|
|
||||||
|
|
||||||
if (found <= 0)
|
//qDebug() << "Ticket is valid until: " << inputDateTime.toString(Qt::ISODate) << "price = " << daily_card_price << ", duration = " << diff / 60;
|
||||||
{
|
return inputDateTime;
|
||||||
LOG_DEBUG("- No workday found, trying to find next available day");
|
}
|
||||||
current_datetime_t = mktime(¤t_datetime);
|
}
|
||||||
current_datetime_t += 86400;
|
|
||||||
current_datetime = *localtime(¤t_datetime_t);
|
|
||||||
|
|
||||||
char buffer_datetime[80];
|
return QDateTime();
|
||||||
strftime(buffer_datetime, 80, "%Y-%m-%dT%H:%M:%S", ¤t_datetime);
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
std::string Calculator::GetDurationFromCost(Configuration* cfg,
|
||||||
|
uint8_t payment_option,
|
||||||
|
char const* start_datetime, // given in local time
|
||||||
|
double price,
|
||||||
|
bool nextDay,
|
||||||
|
bool prepaid)
|
||||||
|
{
|
||||||
|
// Get input date
|
||||||
|
QDateTime inputDate = QDateTime::fromString(start_datetime,Qt::ISODate);
|
||||||
|
|
||||||
// Make new datetime string and call function again recursively
|
// Get day of week
|
||||||
start_datetime = buffer_datetime;
|
int weekdayId = 0;
|
||||||
return GetDurationFromCost(cfg, payment_option, start_datetime, price, true);
|
weekdayId = Utilities::ZellersAlgorithm(inputDate.date().day(),inputDate.date().month(),inputDate.date().year());
|
||||||
}
|
|
||||||
|
|
||||||
worktime_from = cfg->WeekDaysWorktime.find(weekdayId)->second.pwd_time_from;
|
//Get min and max time defined in JSON
|
||||||
worktime_to = cfg->WeekDaysWorktime.find(weekdayId)->second.pwd_time_to;
|
double minMin = 0;
|
||||||
}
|
minMin = cfg->PaymentOption.find(payment_option)->second.pop_min_time;
|
||||||
|
|
||||||
if (price_per_unit < 0) price_per_unit = 1.0f;
|
double maxMin = 0;
|
||||||
LOG_DEBUG("Calculated price per minute: ", price_per_unit);
|
maxMin = cfg->PaymentOption.find(payment_option)->second.pop_max_time;
|
||||||
|
|
||||||
LOG_DEBUG("Worktime from: ", worktime_from);
|
double min_price = 0;
|
||||||
LOG_DEBUG("Worktime to: ", worktime_to);
|
min_price = cfg->PaymentOption.find(payment_option)->second.pop_min_price;
|
||||||
|
|
||||||
struct tm from_tm;
|
if(price < min_price)
|
||||||
struct tm to_tm;
|
{
|
||||||
|
return "PARKING NOT ALLOWED";
|
||||||
|
}
|
||||||
|
|
||||||
from_tm = Utilities::TimeToStructTm(worktime_from.c_str(), current_datetime.tm_year, current_datetime.tm_mon, current_datetime.tm_mday, current_datetime.tm_wday);
|
if (minMin < 0) minMin = 0;
|
||||||
from_tm.tm_year = current_datetime.tm_year;
|
if (maxMin < 0) maxMin = 0;
|
||||||
from_tm.tm_mon = current_datetime.tm_mon;
|
if (minMin >= maxMin)
|
||||||
from_tm.tm_wday = current_datetime.tm_wday;
|
{
|
||||||
from_tm.tm_mday = current_datetime.tm_mday;
|
LOG_ERROR("Error: min_min cannot be greater or equal to max_min");
|
||||||
|
return "PARKING NOT ALLOWED";
|
||||||
|
}
|
||||||
|
|
||||||
to_tm = Utilities::TimeToStructTm(worktime_to.c_str(), current_datetime.tm_year, current_datetime.tm_mon, current_datetime.tm_mday, current_datetime.tm_wday);
|
if (maxMin <= minMin)
|
||||||
to_tm.tm_year = current_datetime.tm_year;
|
{
|
||||||
to_tm.tm_mon = current_datetime.tm_mon;
|
LOG_ERROR("Error: max_min cannot be lower or equal than min_min");
|
||||||
to_tm.tm_wday = current_datetime.tm_wday;
|
return "PARKING NOT ALLOWED";
|
||||||
to_tm.tm_mday = current_datetime.tm_mday;
|
}
|
||||||
|
|
||||||
// Convert tm structures to time_t
|
|
||||||
current_datetime_t = mktime(¤t_datetime);
|
|
||||||
time_t from_datetime_t = mktime(&from_tm);
|
|
||||||
time_t to_datetime_t = mktime(&to_tm);
|
|
||||||
|
|
||||||
/*Newly added */
|
|
||||||
//current_datetime.tm_hour = from_tm.tm_hour;
|
|
||||||
//current_datetime.tm_min = from_tm.tm_min;
|
|
||||||
//current_datetime.tm_sec = from_tm.tm_sec;
|
|
||||||
//current_datetime_t = mktime(¤t_datetime);
|
|
||||||
|
|
||||||
// If overtime flag is set
|
|
||||||
if (overtime || nextDay)
|
|
||||||
{
|
|
||||||
current_datetime.tm_hour = from_tm.tm_hour;
|
|
||||||
current_datetime.tm_min = from_tm.tm_min;
|
|
||||||
current_datetime.tm_sec = from_tm.tm_sec;
|
|
||||||
current_datetime_t = mktime(¤t_datetime);
|
|
||||||
LOG_DEBUG(" *** New input date set according to worktime: ", asctime(¤t_datetime));
|
|
||||||
overtime = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate ticket
|
|
||||||
if (!prepaid)
|
|
||||||
{
|
|
||||||
if ((current_datetime_t < from_datetime_t) || (current_datetime_t > to_datetime_t))
|
|
||||||
{
|
|
||||||
LOG_DEBUG("[STOP] * Ticket is not valid * ");
|
|
||||||
return "PARKING NOT ALLOWED";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_DEBUG("* PREPAID MODE ACTIVE *");
|
|
||||||
|
|
||||||
if (current_datetime_t < from_datetime_t)
|
|
||||||
{
|
|
||||||
current_datetime.tm_hour = from_tm.tm_hour;
|
|
||||||
current_datetime.tm_min = from_tm.tm_min;
|
|
||||||
current_datetime.tm_sec = from_tm.tm_sec;
|
|
||||||
current_datetime_t = mktime(¤t_datetime);
|
|
||||||
LOG_DEBUG(" *** PREPAID *** Current time is before the time range start, adjusting time to: ", asctime(¤t_datetime));
|
|
||||||
}
|
|
||||||
else if (current_datetime_t > to_datetime_t)
|
|
||||||
{
|
|
||||||
LOG_DEBUG(" *** PREPAID *** Current time is past the time range end, searching for next available day");
|
|
||||||
current_datetime_t = mktime(¤t_datetime);
|
|
||||||
current_datetime_t += 86400;
|
|
||||||
current_datetime = *localtime(¤t_datetime_t);
|
|
||||||
|
|
||||||
char buffer_datetime[80];
|
|
||||||
strftime(buffer_datetime, 80, "%Y-%m-%dT%H:%M:%S", ¤t_datetime);
|
|
||||||
|
|
||||||
//Make new datetime string and call function again recursively
|
|
||||||
start_datetime = buffer_datetime;
|
|
||||||
return GetDurationFromCost(cfg, payment_option, start_datetime, price, true, prepaid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (!Utilities::IsYearPeriodActive(cfg, ¤t_datetime))
|
|
||||||
{
|
|
||||||
LOG_DEBUG("Year period is not valid");
|
|
||||||
return "PARKING NOT ALLOWED";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increment by 1 minute
|
|
||||||
current_datetime_t = mktime(¤t_datetime);
|
|
||||||
current_datetime_t += 60;
|
|
||||||
current_datetime = *localtime(¤t_datetime_t);
|
|
||||||
total_duration_min += 1.0f;
|
|
||||||
money_left -= price_per_unit;
|
|
||||||
|
|
||||||
|
|
||||||
// If no money left (e.g. spent all of the money before reaching end of worktime)
|
// Get payment method
|
||||||
if (money_left <= 0)
|
uint8_t p_method = PaymentMethod::Undefined;
|
||||||
{
|
p_method = payment_option;
|
||||||
LOG_DEBUG("No money left ");
|
LOG_DEBUG("Payment method id: ", (unsigned)p_method);
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (total_duration_min >= maxMin)
|
|
||||||
{
|
|
||||||
LOG_DEBUG("Total duration is greater or equal to max_min");
|
|
||||||
|
|
||||||
current_datetime_t = mktime(¤t_datetime);
|
// Check special day
|
||||||
current_datetime_t -= 60;
|
double day_price = 0.0f;
|
||||||
current_datetime = *localtime(¤t_datetime_t);
|
int current_special_day_id = -1;
|
||||||
total_duration_min = maxMin;
|
bool is_special_day = Utilities::CheckSpecialDay(cfg, inputDate.toString(Qt::ISODate).toStdString().c_str(), ¤t_special_day_id, &day_price);
|
||||||
break;
|
LOG_DEBUG("Special day: ", is_special_day);
|
||||||
}
|
|
||||||
|
|
||||||
// If money has left but the end of worktime has been reached (go to next day)
|
double money_left = price;
|
||||||
if (current_datetime_t >= to_datetime_t)
|
double price_per_unit = 0.0f;
|
||||||
{
|
|
||||||
total_duration_min -= 1.0f;
|
|
||||||
|
|
||||||
int carry_over_status = 0;
|
QTime worktime_from;
|
||||||
carry_over_status = cfg->PaymentOption.find(payment_option)->second.pop_carry_over;
|
QTime worktime_to;
|
||||||
LOG_DEBUG("Carry over status: ", carry_over_status);
|
|
||||||
if (carry_over_status < 1) break;
|
|
||||||
|
|
||||||
LOG_DEBUG("Reached end of worktime");
|
if(is_special_day)
|
||||||
LOG_DEBUG("Trying to find next available day, money left = ", money_left);
|
{
|
||||||
current_datetime_t = mktime(¤t_datetime);
|
// Set special day price
|
||||||
current_datetime_t += 86400;
|
price_per_unit = Utilities::CalculatePricePerUnit(day_price);
|
||||||
current_datetime = *localtime(¤t_datetime_t);
|
worktime_from = QTime::fromString(cfg->SpecialDaysWorktime.find(current_special_day_id)->second.pedwt_time_from.c_str());
|
||||||
|
worktime_to = QTime::fromString(cfg->SpecialDaysWorktime.find(current_special_day_id)->second.pedwt_time_to.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set new price for the normal day
|
||||||
|
int pop_id = cfg->PaymentOption.find(payment_option)->second.pop_id;
|
||||||
|
day_price = cfg->PaymentRate.find(pop_id)->second.pra_price;
|
||||||
|
|
||||||
char buffer_datetime[80];
|
int durationId = cfg->PaymentRate.find(pop_id)->second.pra_payment_unit_id;
|
||||||
strftime(buffer_datetime, 80, "%Y-%m-%dT%H:%M:%S", ¤t_datetime);
|
double durationUnit = cfg->Duration.find(durationId)->second.pun_duration;
|
||||||
|
price_per_unit = Utilities::CalculatePricePerUnit(day_price,durationUnit);
|
||||||
|
|
||||||
// Make new datetime string and call function again recursively
|
// If no working day found, skip it (recursively call method again)
|
||||||
start_datetime = buffer_datetime;
|
size_t found = 0;
|
||||||
overtime = true;
|
found = cfg->WeekDaysWorktime.count(weekdayId);
|
||||||
return GetDurationFromCost(cfg, payment_option, start_datetime, price);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t valid_until_datetime_t = current_datetime_t;
|
// When no workday found, go to next available day
|
||||||
|
if(found <=0)
|
||||||
|
{
|
||||||
|
LOG_DEBUG("- No workday found, trying to find next available day");
|
||||||
|
inputDate = inputDate.addDays(1);
|
||||||
|
return GetDurationFromCost(cfg, payment_option, inputDate.toString(Qt::ISODate).toStdString().c_str(), money_left,true,prepaid);
|
||||||
|
}
|
||||||
|
worktime_from = QTime::fromString(cfg->WeekDaysWorktime.find(weekdayId)->second.pwd_time_from.c_str());
|
||||||
|
worktime_to = QTime::fromString(cfg->WeekDaysWorktime.find(weekdayId)->second.pwd_time_to.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
if ((total_duration_min < minMin) || (price / price_per_unit) < minMin)
|
if (price_per_unit < 0) price_per_unit = 1.0f;
|
||||||
{
|
|
||||||
LOG_DEBUG("Total duration is lower than min_min");
|
|
||||||
//valid_until_datetime_t += (minMin - total_duration_min) * 60;
|
|
||||||
//total_duration_min = minMin;
|
|
||||||
//return "PARKING NOT ALLOWED";
|
|
||||||
|
|
||||||
valid_until_datetime_t = from_datetime_t;
|
// if((price/price_per_unit) < minMin) return "PARKING NOT ALLOWED";
|
||||||
total_duration_min = 0;
|
LOG_DEBUG("Calculated price per minute: ", price_per_unit);
|
||||||
}
|
|
||||||
|
|
||||||
double ret_val = 0;
|
// If overtime flag is set
|
||||||
double calc_price = (int)total_duration_min - (int)price / price_per_unit;
|
if (overtime || nextDay)
|
||||||
|
{
|
||||||
|
inputDate.setTime(worktime_from);
|
||||||
|
overtime = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (calc_price > 0 && total_duration_min > 0)
|
// Check prepaid
|
||||||
{
|
if (!prepaid)
|
||||||
valid_until_datetime_t -= (int)ceil(calc_price) * 60;
|
{
|
||||||
ret_val = total_duration_min - calc_price;
|
if ((inputDate.time() < worktime_from) || (inputDate.time() > worktime_to))
|
||||||
}
|
{
|
||||||
else ret_val = total_duration_min;
|
LOG_DEBUG("[STOP] * Ticket is not valid * ");
|
||||||
|
return "PARKING NOT ALLOWED";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_DEBUG("* PREPAID MODE ACTIVE *");
|
||||||
|
if (inputDate.time() < worktime_from)
|
||||||
|
{
|
||||||
|
inputDate.setTime(worktime_from);
|
||||||
|
}
|
||||||
|
else if(inputDate.time() > worktime_to)
|
||||||
|
{
|
||||||
|
LOG_DEBUG(" *** PREPAID *** Current time is past the time range end, searching for next available day");
|
||||||
|
inputDate = inputDate.addDays(1);
|
||||||
|
return GetDurationFromCost(cfg, payment_option, inputDate.toString(Qt::ISODate).toStdString().c_str(), money_left, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cout << "Total minutes: " << (int)ret_val << endl;
|
while(true)
|
||||||
if (ret_val <= 0) return "PARKING NOT ALLOWED";
|
{
|
||||||
|
if((int)money_left <= 0) break;
|
||||||
|
|
||||||
struct tm valid_until_datetime = *localtime(&valid_until_datetime_t);
|
// Check year period
|
||||||
LOG_DEBUG("Ticket is valid until ", asctime(&valid_until_datetime));
|
bool isYearPeriodActive = false;
|
||||||
|
|
||||||
total_duration_min = 0.0f;
|
//// Parse input date
|
||||||
return asctime(&valid_until_datetime);
|
int dayCurrent = inputDate.date().day();
|
||||||
|
int monthCurrent = inputDate.date().month();
|
||||||
|
|
||||||
|
// Current date time
|
||||||
|
int cdt = (monthCurrent * 100) + dayCurrent;
|
||||||
|
|
||||||
|
multimap<int, ATBPeriodYear>::iterator year_period_itr;
|
||||||
|
for (year_period_itr = cfg->YearPeriod.begin(); year_period_itr != cfg->YearPeriod.end(); ++year_period_itr)
|
||||||
|
{
|
||||||
|
int dStart = year_period_itr->second.pye_start_day;
|
||||||
|
int dEnd = year_period_itr->second.pye_end_day;
|
||||||
|
|
||||||
|
int mStart = year_period_itr->second.pye_start_month;
|
||||||
|
int mEnd = year_period_itr->second.pye_end_month;
|
||||||
|
|
||||||
|
int start = (mStart * 100) + dStart;
|
||||||
|
int end = (mEnd * 100) + dEnd;
|
||||||
|
|
||||||
|
if (cdt >= start && cdt <= end) {
|
||||||
|
isYearPeriodActive = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isYearPeriodActive)
|
||||||
|
{
|
||||||
|
LOG_DEBUG("Year period is not valid");
|
||||||
|
return "PARKING NOT ALLOWED";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(total_duration_min > maxMin)
|
||||||
|
{
|
||||||
|
total_duration_min = maxMin;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If reached end of worktime go to next day
|
||||||
|
if(inputDate.time() >= worktime_to)
|
||||||
|
{
|
||||||
|
int carry_over_status = 0;
|
||||||
|
carry_over_status = cfg->PaymentOption.find(payment_option)->second.pop_carry_over;
|
||||||
|
if (carry_over_status < 1) break;
|
||||||
|
|
||||||
|
inputDate = inputDate.addDays(1);
|
||||||
|
overtime = true;
|
||||||
|
return GetDurationFromCost(cfg, payment_option, inputDate.toString(Qt::ISODate).toStdString().c_str(), money_left ,true, prepaid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(money_left > 1)
|
||||||
|
inputDate = inputDate.addSecs(60);
|
||||||
|
|
||||||
|
if(price_per_unit > 0) total_duration_min +=1;
|
||||||
|
money_left -= price_per_unit;
|
||||||
|
|
||||||
|
//qDebug() <<"Timestamp:" << inputDate << ", total duration min: " << total_duration_min << ", money left = " << money_left;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if ((total_duration_min < minMin) || (price / price_per_unit) < minMin)
|
||||||
|
// {
|
||||||
|
// LOG_DEBUG("Total duration is lower than min_min");
|
||||||
|
// inputDate.time() = worktime_from;
|
||||||
|
// total_duration_min = 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
double ret_val = 0;
|
||||||
|
// double calc_price = (int)total_duration_min - (int)price / price_per_unit;
|
||||||
|
|
||||||
|
//if (calc_price > 0 && total_duration_min > 0)
|
||||||
|
//{
|
||||||
|
// inputDate = inputDate.addSecs(-(int)ceil(calc_price) * 60);
|
||||||
|
//}
|
||||||
|
|
||||||
|
if(price >= min_price && total_duration_min >= minMin)
|
||||||
|
qDebug() << "GetDurationFromCost(): Valid until: " << inputDate.toString(Qt::ISODate);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug() << "Parking not allowed";
|
||||||
|
total_duration_min = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret_val = total_duration_min;
|
||||||
|
if(ret_val < 0) ret_val = 0;
|
||||||
|
qDebug() << "Duration: " << ret_val;
|
||||||
|
if (ret_val <= 0) return "PARKING NOT ALLOWED";
|
||||||
|
|
||||||
|
total_duration_min = 0;
|
||||||
|
return inputDate.toString(Qt::ISODate).toStdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
double Calculator::GetCostFromDuration(Configuration* cfg, uint8_t payment_option, const char* start_datetime, double durationMin, bool nextDay, bool prepaid)
|
double Calculator::GetCostFromDuration(Configuration* cfg, uint8_t payment_option, const QDateTime start_datetime, QDateTime & end_datetime, double durationMin, bool nextDay, bool prepaid)
|
||||||
{
|
{
|
||||||
// Get current date time from input
|
// Get input date
|
||||||
struct tm current_datetime = Utilities::DateTimeToStructTm(start_datetime);
|
QDateTime inputDate = start_datetime;
|
||||||
time_t current_datetime_t;
|
|
||||||
|
|
||||||
// Get day of week
|
// Get day of week
|
||||||
DayOfWeek weekdayId = DayOfWeek::UndefinedDay;
|
int weekdayId = 0;
|
||||||
weekdayId = Utilities::GetDayOfWeek(¤t_datetime);
|
weekdayId = Utilities::ZellersAlgorithm(inputDate.date().day(),inputDate.date().month(),inputDate.date().year());
|
||||||
LOG_DEBUG("*** Input date is: ", start_datetime, " [weekday id = ", weekdayId, "]");
|
|
||||||
|
|
||||||
double minMin = 0;
|
//Get min and max time defined in JSON
|
||||||
minMin = cfg->PaymentOption.find(payment_option)->second.pop_min_time;
|
double minMin = 0;
|
||||||
if (minMin < 0) minMin = 0;
|
minMin = cfg->PaymentOption.find(payment_option)->second.pop_min_time;
|
||||||
|
|
||||||
double maxMin = 0;
|
double maxMin = 0;
|
||||||
maxMin = cfg->PaymentOption.find(payment_option)->second.pop_max_time;
|
maxMin = cfg->PaymentOption.find(payment_option)->second.pop_max_time;
|
||||||
if (maxMin <= 0) maxMin = 60;
|
|
||||||
|
|
||||||
if (minMin >= maxMin)
|
if (minMin < 0) minMin = 0;
|
||||||
{
|
if (maxMin < 0) maxMin = 0;
|
||||||
LOG_ERROR("Error: min_min cannot be greater or equal to max_min");
|
if (minMin >= maxMin)
|
||||||
return 0.0f;
|
{
|
||||||
}
|
LOG_ERROR("Error: min_min cannot be greater or equal to max_min");
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
if (maxMin <= minMin)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Error: max_min cannot be lower or equal than min_min");
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
if (maxMin <= minMin)
|
// Check overtime
|
||||||
{
|
if (!overtime)
|
||||||
LOG_ERROR("Error: max_min cannot be lower or equal than min_min");
|
{
|
||||||
return 0.0f;
|
if (durationMin > maxMin)
|
||||||
}
|
{
|
||||||
|
LOG_WARNING("Total duration is greater or equal to max_min");
|
||||||
|
return maxMin;
|
||||||
|
}
|
||||||
|
|
||||||
if (!overtime)
|
if (durationMin < minMin)
|
||||||
{
|
{
|
||||||
if (durationMin > maxMin)
|
LOG_WARNING("Total duration is lower or equal to min_min");
|
||||||
{
|
return 0.0f;
|
||||||
LOG_WARNING("Total duration is greater or equal to max_min");
|
}
|
||||||
return 0.0f;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (durationMin < minMin)
|
// Get payment method
|
||||||
{
|
uint8_t p_method = PaymentMethod::Undefined;
|
||||||
LOG_WARNING("Total duration is lower or equal to min_min");
|
p_method = payment_option;
|
||||||
return 0.0f;
|
LOG_DEBUG("Payment method id: ", (unsigned)p_method);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t p_method = PaymentMethod::Undefined;
|
// Check special day
|
||||||
p_method = payment_option;
|
double day_price = 0.0f;
|
||||||
LOG_DEBUG("Payment method id: ", (unsigned)p_method);
|
int current_special_day_id = -1;
|
||||||
|
bool is_special_day = Utilities::CheckSpecialDay(cfg, inputDate.toString(Qt::ISODate).toStdString().c_str(), ¤t_special_day_id, &day_price);
|
||||||
|
LOG_DEBUG("Special day: ", is_special_day);
|
||||||
|
|
||||||
double day_price = 0.0f;
|
total_duration_min = durationMin;
|
||||||
int current_special_day_id = -1;
|
LOG_DEBUG("Total min:", total_duration_min);
|
||||||
bool is_special_day = Utilities::CheckSpecialDay(cfg, start_datetime, ¤t_special_day_id, &day_price);
|
|
||||||
LOG_DEBUG("Special day: ", is_special_day);
|
|
||||||
|
|
||||||
total_duration_min = durationMin;
|
double price_per_unit = 0.0f;
|
||||||
LOG_DEBUG("Total min:", total_duration_min);
|
QTime worktime_from;
|
||||||
|
QTime worktime_to;
|
||||||
|
|
||||||
double price_per_unit = 0.0f;
|
if(is_special_day)
|
||||||
|
{
|
||||||
|
// Set special day price
|
||||||
|
price_per_unit = Utilities::CalculatePricePerUnit(day_price);
|
||||||
|
worktime_from = QTime::fromString(cfg->SpecialDaysWorktime.find(current_special_day_id)->second.pedwt_time_from.c_str());
|
||||||
|
worktime_to = QTime::fromString(cfg->SpecialDaysWorktime.find(current_special_day_id)->second.pedwt_time_to.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set new price for the normal day
|
||||||
|
|
||||||
string worktime_from = "";
|
int pop_id = cfg->PaymentOption.find(payment_option)->second.pop_id;
|
||||||
string worktime_to = "";
|
day_price = cfg->PaymentRate.find(pop_id)->second.pra_price;
|
||||||
|
|
||||||
if (is_special_day)
|
int durationId = cfg->PaymentRate.find(pop_id)->second.pra_payment_unit_id;
|
||||||
{
|
double durationUnit = cfg->Duration.find(durationId)->second.pun_duration;
|
||||||
// Set special day price
|
price_per_unit = Utilities::CalculatePricePerUnit(day_price,durationUnit);
|
||||||
price_per_unit = Utilities::CalculatePricePerUnit(day_price);
|
|
||||||
worktime_from = cfg->SpecialDaysWorktime.find(current_special_day_id)->second.pedwt_time_from;
|
|
||||||
worktime_to = cfg->SpecialDaysWorktime.find(current_special_day_id)->second.pedwt_time_to;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Set new price for the normal day
|
|
||||||
day_price = cfg->PaymentRate.find(payment_option)->second.pra_price;
|
|
||||||
price_per_unit = Utilities::CalculatePricePerUnit(day_price);
|
|
||||||
|
|
||||||
// If no working day found, skip it (recursively call method again)
|
// If no working day found, skip it (recursively call method again)
|
||||||
size_t found = 0;
|
size_t found = 0;
|
||||||
found = cfg->WeekDaysWorktime.count(weekdayId);
|
found = cfg->WeekDaysWorktime.count(weekdayId);
|
||||||
|
|
||||||
if (found <= 0)
|
// When no workday found, go to next available day
|
||||||
{
|
if(found <=0)
|
||||||
LOG_DEBUG("- No workday found, trying to find next available day");
|
{
|
||||||
current_datetime_t = mktime(¤t_datetime);
|
LOG_DEBUG("- No workday found, trying to find next available day");
|
||||||
current_datetime_t += 86400;
|
inputDate = inputDate.addDays(1);
|
||||||
current_datetime = *localtime(¤t_datetime_t);
|
return floor(GetCostFromDuration(cfg, payment_option, inputDate, end_datetime, durationMin, true, prepaid));
|
||||||
|
}
|
||||||
|
worktime_from = QTime::fromString(cfg->WeekDaysWorktime.find(weekdayId)->second.pwd_time_from.c_str());
|
||||||
|
worktime_to = QTime::fromString(cfg->WeekDaysWorktime.find(weekdayId)->second.pwd_time_to.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
char buffer_datetime[80];
|
if (price_per_unit < 0) price_per_unit = 1.0f;
|
||||||
strftime(buffer_datetime, 80, "%Y-%m-%dT%H:%M:%S", ¤t_datetime);
|
LOG_DEBUG("Calculated price per minute: ", price_per_unit);
|
||||||
|
|
||||||
//Make new datetime string and call function again recursively
|
if (price_per_unit == 0)
|
||||||
start_datetime = buffer_datetime;
|
{
|
||||||
return floor(GetCostFromDuration(cfg, payment_option, start_datetime, durationMin, true, prepaid));
|
inputDate = inputDate.addDays(1);
|
||||||
}
|
inputDate.setTime(worktime_from);
|
||||||
|
return GetCostFromDuration(cfg, payment_option, inputDate, end_datetime, durationMin, true, prepaid);
|
||||||
|
}
|
||||||
|
|
||||||
worktime_from = cfg->WeekDaysWorktime.find(weekdayId)->second.pwd_time_from;
|
// If overtime flag is set
|
||||||
worktime_to = cfg->WeekDaysWorktime.find(weekdayId)->second.pwd_time_to;
|
if (overtime || nextDay)
|
||||||
}
|
{
|
||||||
|
inputDate.setTime(worktime_from);
|
||||||
|
overtime = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (price_per_unit < 0) price_per_unit = 1.0f;
|
// Check prepaid
|
||||||
LOG_DEBUG("Calculated price per minute: ", price_per_unit);
|
if (!prepaid)
|
||||||
|
{
|
||||||
|
if ((inputDate.time() < worktime_from) || (inputDate.time() > worktime_to))
|
||||||
|
{
|
||||||
|
LOG_DEBUG("[STOP] * Ticket is not valid * ");
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_DEBUG("* PREPAID MODE ACTIVE *");
|
||||||
|
if (inputDate.time() < worktime_from)
|
||||||
|
{
|
||||||
|
inputDate.setTime(worktime_from);
|
||||||
|
}
|
||||||
|
else if(inputDate.time() > worktime_to)
|
||||||
|
{
|
||||||
|
LOG_DEBUG(" *** PREPAID *** Current time is past the time range end, searching for next available day");
|
||||||
|
inputDate = inputDate.addDays(1);
|
||||||
|
return GetCostFromDuration(cfg, payment_option, inputDate, end_datetime, durationMin, true, prepaid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DEBUG("Worktime from: ", worktime_from);
|
while(true)
|
||||||
LOG_DEBUG("Worktime to: ", worktime_to);
|
{
|
||||||
|
if(total_duration_min <= 0) break;
|
||||||
|
|
||||||
struct tm from_tm;
|
// Check year period
|
||||||
struct tm to_tm;
|
bool isYearPeriodActive = false;
|
||||||
|
|
||||||
from_tm = Utilities::TimeToStructTm(worktime_from.c_str(), current_datetime.tm_year, current_datetime.tm_mon, current_datetime.tm_mday, current_datetime.tm_wday);
|
//// Parse input date
|
||||||
from_tm.tm_year = current_datetime.tm_year;
|
int dayCurrent = inputDate.date().day();
|
||||||
from_tm.tm_mon = current_datetime.tm_mon;
|
int monthCurrent = inputDate.date().month();
|
||||||
from_tm.tm_wday = current_datetime.tm_wday;
|
|
||||||
from_tm.tm_mday = current_datetime.tm_mday;
|
|
||||||
|
|
||||||
to_tm = Utilities::TimeToStructTm(worktime_to.c_str(), current_datetime.tm_year, current_datetime.tm_mon, current_datetime.tm_mday, current_datetime.tm_wday);
|
// Current date time
|
||||||
to_tm.tm_year = current_datetime.tm_year;
|
int cdt = (monthCurrent * 100) + dayCurrent;
|
||||||
to_tm.tm_mon = current_datetime.tm_mon;
|
|
||||||
to_tm.tm_wday = current_datetime.tm_wday;
|
|
||||||
to_tm.tm_mday = current_datetime.tm_mday;
|
|
||||||
|
|
||||||
// Convert tm structures to time_t
|
multimap<int, ATBPeriodYear>::iterator year_period_itr;
|
||||||
current_datetime_t = mktime(¤t_datetime);
|
for (year_period_itr = cfg->YearPeriod.begin(); year_period_itr != cfg->YearPeriod.end(); ++year_period_itr)
|
||||||
|
{
|
||||||
|
int dStart = year_period_itr->second.pye_start_day;
|
||||||
|
int dEnd = year_period_itr->second.pye_end_day;
|
||||||
|
|
||||||
time_t from_datetime_t = mktime(&from_tm);
|
int mStart = year_period_itr->second.pye_start_month;
|
||||||
time_t to_datetime_t = mktime(&to_tm);
|
int mEnd = year_period_itr->second.pye_end_month;
|
||||||
|
|
||||||
// If overtime flag is set
|
int start = (mStart * 100) + dStart;
|
||||||
if (overtime || nextDay)
|
int end = (mEnd * 100) + dEnd;
|
||||||
{
|
|
||||||
current_datetime.tm_hour = from_tm.tm_hour;
|
|
||||||
current_datetime.tm_min = from_tm.tm_min;
|
|
||||||
current_datetime.tm_sec = from_tm.tm_sec;
|
|
||||||
current_datetime_t = mktime(¤t_datetime);
|
|
||||||
LOG_DEBUG(" *** New input date set according to worktime: ", asctime(¤t_datetime));
|
|
||||||
overtime = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate ticket
|
if (cdt >= start && cdt <= end) {
|
||||||
if (!prepaid)
|
isYearPeriodActive = true;
|
||||||
{
|
break;
|
||||||
if ((current_datetime_t < from_datetime_t) || (current_datetime_t > to_datetime_t))
|
}
|
||||||
{
|
}
|
||||||
LOG_DEBUG("[STOP] * Ticket is not valid * ");
|
if (!isYearPeriodActive)
|
||||||
return 0.0f;
|
{
|
||||||
}
|
LOG_DEBUG("Year period is not valid");
|
||||||
}
|
return 0.0f;
|
||||||
else
|
}
|
||||||
{
|
|
||||||
LOG_DEBUG("* PREPAID MODE ACTIVE *");
|
|
||||||
|
|
||||||
if (current_datetime_t < from_datetime_t)
|
int carry_over_status = 0;
|
||||||
{
|
carry_over_status = cfg->PaymentOption.find(payment_option)->second.pop_carry_over;
|
||||||
current_datetime.tm_hour = from_tm.tm_hour;
|
|
||||||
current_datetime.tm_min = from_tm.tm_min;
|
|
||||||
current_datetime.tm_sec = from_tm.tm_sec;
|
|
||||||
current_datetime_t = mktime(¤t_datetime);
|
|
||||||
LOG_DEBUG(" *** PREPAID *** Current time is before the time range start, adjusting time to: ", asctime(¤t_datetime));
|
|
||||||
}
|
|
||||||
else if (current_datetime_t > to_datetime_t)
|
|
||||||
{
|
|
||||||
LOG_DEBUG(" *** PREPAID *** Current time is past the time range end, searching for next available day");
|
|
||||||
current_datetime_t = mktime(¤t_datetime);
|
|
||||||
current_datetime_t += 86400;
|
|
||||||
current_datetime = *localtime(¤t_datetime_t);
|
|
||||||
|
|
||||||
char buffer_datetime[80];
|
// Go to next day if minutes not spent
|
||||||
strftime(buffer_datetime, 80, "%Y-%m-%dT%H:%M:%S", ¤t_datetime);
|
if(inputDate.time() >= worktime_to)
|
||||||
|
{
|
||||||
|
if (carry_over_status < 1) break;
|
||||||
|
|
||||||
//Make new datetime string and call function again recursively
|
LOG_DEBUG("Reached end of worktime, searching for the next working day");
|
||||||
start_datetime = buffer_datetime;
|
inputDate = inputDate.addDays(1);
|
||||||
return floor(GetCostFromDuration(cfg, payment_option, start_datetime, durationMin, true, prepaid));
|
overtime = true;
|
||||||
}
|
return GetCostFromDuration(cfg, payment_option, inputDate, end_datetime, total_duration_min);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true)
|
// Increment input date minutes for each monetary unit
|
||||||
{
|
inputDate = inputDate.addSecs(60);
|
||||||
if (!Utilities::IsYearPeriodActive(cfg, ¤t_datetime))
|
total_duration_min -=1;
|
||||||
{
|
total_cost += price_per_unit;
|
||||||
LOG_DEBUG("Year period is not valid");
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrement by 1 minute
|
}
|
||||||
current_datetime_t = mktime(¤t_datetime);
|
qDebug() << "GetCostFromDuration(): Valid until:" << inputDate.toString(Qt::ISODate).toStdString().c_str();
|
||||||
current_datetime_t += 60;
|
|
||||||
current_datetime = *localtime(¤t_datetime_t);
|
|
||||||
|
|
||||||
total_duration_min -= 1.0f;
|
end_datetime = inputDate;
|
||||||
total_cost += price_per_unit;
|
|
||||||
|
|
||||||
// If no minutes left (e.g. spent all of the money before reaching end of worktime)
|
double ret_val = total_cost;
|
||||||
if (total_duration_min <= 0)
|
total_cost = 0.0f;
|
||||||
{
|
return ceil(ret_val);
|
||||||
//total_duration_min -= 1.0f;
|
|
||||||
LOG_DEBUG("No minutes left ");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If minutes has left but the end of worktime has been reached (go to next day)
|
|
||||||
if (current_datetime_t >= to_datetime_t)
|
|
||||||
{
|
|
||||||
int carry_over_status = 0;
|
|
||||||
carry_over_status = cfg->PaymentOption.find(payment_option)->second.pop_carry_over;
|
|
||||||
total_duration_min += 1.0f;
|
|
||||||
total_cost -= price_per_unit;
|
|
||||||
|
|
||||||
LOG_DEBUG("Carry over status: ", carry_over_status);
|
|
||||||
if (carry_over_status < 1) break;
|
|
||||||
|
|
||||||
LOG_DEBUG("Reached end of worktime");
|
|
||||||
LOG_DEBUG("Trying to find next available day, min left = ", total_duration_min);
|
|
||||||
current_datetime_t = mktime(¤t_datetime);
|
|
||||||
current_datetime_t += 86400;
|
|
||||||
current_datetime = *localtime(¤t_datetime_t);
|
|
||||||
|
|
||||||
char buffer_datetime[80];
|
|
||||||
strftime(buffer_datetime, 80, "%Y-%m-%dT%H:%M:%S", ¤t_datetime);
|
|
||||||
|
|
||||||
// Make new datetime string and call function again recursively
|
|
||||||
start_datetime = buffer_datetime;
|
|
||||||
overtime = true;
|
|
||||||
return floor(GetCostFromDuration(cfg, payment_option, start_datetime, total_duration_min));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t valid_until_datetime_t = current_datetime_t;
|
|
||||||
struct tm valid_until_datetime = *localtime(&valid_until_datetime_t);
|
|
||||||
LOG_DEBUG("Ticket is valid until ", asctime(&valid_until_datetime));
|
|
||||||
|
|
||||||
double ret_val = total_cost;
|
|
||||||
total_cost = 0.0f;
|
|
||||||
return floor(ret_val);
|
|
||||||
}
|
}
|
||||||
|
@@ -154,6 +154,7 @@ 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_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_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();
|
else if (strcmp(inner_obj_name, "pop_carry_over") == 0) PaymentOption.pop_carry_over = k->value.GetInt();
|
||||||
|
else if (strcmp(inner_obj_name, "pop_daily_card_price") == 0) PaymentOption.pop_daily_card_price = k->value.GetInt();
|
||||||
break;
|
break;
|
||||||
case MemberType::DurationType:
|
case MemberType::DurationType:
|
||||||
if (strcmp(inner_obj_name, "pun_id") == 0) Duration.pun_id = k->value.GetInt();
|
if (strcmp(inner_obj_name, "pun_id") == 0) Duration.pun_id = k->value.GetInt();
|
||||||
@@ -209,7 +210,7 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
|
|||||||
cfg->PaymentMethod.insert(pair<int, ATBPaymentMethod>(PaymentMethod.pme_id, PaymentMethod));
|
cfg->PaymentMethod.insert(pair<int, ATBPaymentMethod>(PaymentMethod.pme_id, PaymentMethod));
|
||||||
break;
|
break;
|
||||||
case MemberType::PaymentRateType:
|
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;
|
break;
|
||||||
case MemberType::PaymentOptionType:
|
case MemberType::PaymentOptionType:
|
||||||
cfg->PaymentOption.insert(pair<int, ATBPaymentOption>(PaymentOption.pop_payment_method_id, PaymentOption));
|
cfg->PaymentOption.insert(pair<int, ATBPaymentOption>(PaymentOption.pop_payment_method_id, PaymentOption));
|
||||||
|
@@ -8,12 +8,15 @@ static int protection_counter = 0;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pra_price"></param>
|
/// <param name="pra_price"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
double Utilities::CalculatePricePerUnit(double pra_price)
|
double Utilities::CalculatePricePerUnit(double pra_price, double durationUnit)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
double price_per_unit = pra_price;
|
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);
|
//printf("Price per unit (min) is: %lf\n", price_per_unit);
|
||||||
return price_per_unit;
|
return price_per_unit;
|
||||||
}
|
}
|
||||||
@@ -33,7 +36,7 @@ time_t Utilities::GetCurrentLocalTime()
|
|||||||
memset(&tm_curr_time, '\0', sizeof(struct tm));
|
memset(&tm_curr_time, '\0', sizeof(struct tm));
|
||||||
|
|
||||||
tm_curr_time = *localtime(&curr_time);
|
tm_curr_time = *localtime(&curr_time);
|
||||||
curr_time = mktime(&tm_curr_time) - timezone;
|
curr_time = mktime(&tm_curr_time); //- timezone;
|
||||||
return curr_time;
|
return curr_time;
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
|
197
main/main.cpp
197
main/main.cpp
@@ -1,10 +1,9 @@
|
|||||||
#include <calculate_price.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <calculate_price.h>
|
||||||
|
|
||||||
|
|
||||||
extern "C" char* strptime(const char* s,
|
extern "C" char* strptime(const char* s,
|
||||||
const char* f,
|
const char* f,
|
||||||
@@ -27,87 +26,135 @@ extern "C" char* strptime(const char* s,
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include "calculator_functions.h"
|
||||||
|
#include <calculate_price.h>
|
||||||
|
|
||||||
|
|
||||||
int main() {
|
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;
|
parking_tariff_t *tariff = 0;
|
||||||
if (init_tariff(&tariff, "/etc/psa_tariff/")) {
|
if (init_tariff(&tariff, "/etc/psa_tariff/")) {
|
||||||
struct price_t price;
|
struct price_t price;
|
||||||
memset(&price, 0x00, sizeof(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 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,
|
if (compute_price_for_parking_ticket(tariff,
|
||||||
start_parking_time,
|
start_parking_time,
|
||||||
end_parking_time,
|
end_parking_time,
|
||||||
&price)) {
|
&price))
|
||||||
qDebug() << "price=" << price.netto;
|
{
|
||||||
|
qDebug() << "GetCostFromDuration() => price=" << price.netto;
|
||||||
}
|
}
|
||||||
|
|
||||||
// tests
|
QString duration;
|
||||||
struct tm now;
|
if(compute_duration_for_parking_ticket(tariff,start_parking_time,3090,duration))
|
||||||
memset(&now, 0, sizeof(now));
|
{
|
||||||
|
qDebug() << "GetDurationFromCost() => duration=" << duration;
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// 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,
|
// Daily ticket
|
||||||
start_parking_time,
|
//compute_duration_for_daily_ticket(tariff,start.toString(Qt::ISODate),3);
|
||||||
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;
|
//Configuration* cfg, QString start_datetime, uint8_t payment_option, bool carry_over
|
||||||
now = *localtime(&t);
|
// // 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);
|
free_tariff(tariff);
|
||||||
}
|
}
|
||||||
@@ -144,7 +191,7 @@ int main() {
|
|||||||
struct tm now; // = Utilities::DateTimeToStructTm("2023-03-01T16:00:00");
|
struct tm now; // = Utilities::DateTimeToStructTm("2023-03-01T16:00:00");
|
||||||
memset(&now, 0, sizeof(now));
|
memset(&now, 0, sizeof(now));
|
||||||
char buffer[64];
|
char buffer[64];
|
||||||
//#if 0
|
//#if 0
|
||||||
// 3.Jan 2023 -> Tuesday
|
// 3.Jan 2023 -> Tuesday
|
||||||
strptime("2023-01-03T14:00:00", "%Y-%m-%dT%H:%M:%S", &now);
|
strptime("2023-01-03T14:00:00", "%Y-%m-%dT%H:%M:%S", &now);
|
||||||
for (int i = 0; i < 600; ++i) {
|
for (int i = 0; i < 600; ++i) {
|
||||||
@@ -219,8 +266,8 @@ int main() {
|
|||||||
|
|
||||||
int const duration = 120;
|
int const duration = 120;
|
||||||
double cost = calculator.GetCostFromDuration(&cfg,
|
double cost = calculator.GetCostFromDuration(&cfg,
|
||||||
PaymentOption::Option1, buffer, duration,
|
PaymentOption::Option1, buffer, duration,
|
||||||
false, true);
|
false, true);
|
||||||
|
|
||||||
switch (zone) {
|
switch (zone) {
|
||||||
case 1:
|
case 1:
|
||||||
@@ -258,8 +305,8 @@ int main() {
|
|||||||
|
|
||||||
int const duration = 120;
|
int const duration = 120;
|
||||||
double cost = calculator.GetCostFromDuration(&cfg,
|
double cost = calculator.GetCostFromDuration(&cfg,
|
||||||
PaymentOption::Option1, buffer, duration,
|
PaymentOption::Option1, buffer, duration,
|
||||||
false, true);
|
false, true);
|
||||||
|
|
||||||
switch (zone) {
|
switch (zone) {
|
||||||
case 1:
|
case 1:
|
||||||
@@ -292,8 +339,8 @@ int main() {
|
|||||||
|
|
||||||
double const compCost = (duration < 15) ? 0 : duration * ((zone == 1) ? 3.6666 : 8.0);
|
double const compCost = (duration < 15) ? 0 : duration * ((zone == 1) ? 3.6666 : 8.0);
|
||||||
double cost = calculator.GetCostFromDuration(&cfg,
|
double cost = calculator.GetCostFromDuration(&cfg,
|
||||||
PaymentOption::Option1, buffer, duration,
|
PaymentOption::Option1, buffer, duration,
|
||||||
false, true);
|
false, true);
|
||||||
if (fabs(cost - compCost) > 1.0) { // zone 1 has rounding errors
|
if (fabs(cost - compCost) > 1.0) { // zone 1 has rounding errors
|
||||||
cout << "ERROR ===> [" << i << "] " << asctime(&now)
|
cout << "ERROR ===> [" << i << "] " << asctime(&now)
|
||||||
<< " - Total cost is: " << cost << " FT (computed="
|
<< " - Total cost is: " << cost << " FT (computed="
|
||||||
|
@@ -7,6 +7,8 @@ QMAKE_CFLAGS = -c -pipe -std=c11 -g -O0 -Wall -Wno-attributes -W -DDEBUG -D_REEN
|
|||||||
QMAKE_CXX_FLAGS += -std=c11
|
QMAKE_CXX_FLAGS += -std=c11
|
||||||
|
|
||||||
INCLUDEPATH += $$_PRO_FILE_PWD_/../../MOBILISIS-Calculator/library/include/mobilisis/
|
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 += .
|
INCLUDEPATH += .
|
||||||
|
|
||||||
unix {
|
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
Reference in New Issue
Block a user