start repository for mobilisis tariff-calculation

This commit is contained in:
2023-04-24 15:31:46 +02:00
parent e5ed5f05f6
commit 90cf509d97
98 changed files with 21712 additions and 0 deletions

View File

@@ -0,0 +1 @@
p 500.0/600*45

View File

@@ -0,0 +1 @@
#pragma once

View File

@@ -0,0 +1,9 @@
#pragma once
#include "tariff_time_range.h"
struct ActiveTimeRange {
bool isActive;
TariffTimeRange timeRange;
ActiveTimeRange() : isActive(false) {
}
};

View File

@@ -0,0 +1,35 @@
#ifndef CALCULATE_PRICE_H
#define CALCULATE_PRICE_H
#include <time.h>
#include <inttypes.h>
class Configuration;
typedef Configuration parking_tariff_t;
#ifdef __cplusplus
extern "C" {
#endif
struct price_t {
uint32_t units;
double netto;
double brutto;
double vat_percentage;
double vat;
};
bool init_tariff(parking_tariff_t **tariff, char const *config_file);
void free_tariff(parking_tariff_t *tariff);
int get_zone_nr();
bool 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
#endif // CALCULATE_PRICE_H

View File

@@ -0,0 +1,29 @@
#pragma once
#include <iostream>
#include "configuration.h"
using namespace std;
class Calculator
{
public:
/// <summary>
/// Gets duration in seconds from cost
/// </summary>
/// <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="price"></param>
/// <returns>Returns duration in seconds (data type: double)</returns>
std::string GetDurationFromCost(Configuration* cfg, uint8_t vehicle_type, char const* start_datetime, double price, bool nextDay = false, bool prepaid = false);
/// <summary>
/// Gets cost from duration in seconds
/// </summary>
/// <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="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);
};

View File

@@ -0,0 +1,58 @@
#pragma once
#include <map>
#include <variant>
#include <cstddef>
#include <stdio.h>
#include <algorithm>
#include <rapidjson/rapidjson.h>
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
#include "member_type.h"
#include "currency.h"
#include "duration.h"
#include "payment_mtd.h"
#include "payment_opt.h"
#include "spec_days.h"
#include "payment_opt.h"
#include "weekdays.h"
#include "weekdays_worktime.h"
#include "spec_days_worktime.h"
#include "member_type.h"
#include "period_year.h"
#include "payment_rate.h"
using namespace std;
using namespace rapidjson;
class Configuration
{
public:
ATBCurrency Currency;
ATBDuration duration;
multimap<int, ATBDuration> Duration;
multimap<int, ATBPaymentMethod> PaymentMethod;
multimap<int, ATBPaymentRate> PaymentRate;
multimap<int, ATBSpecialDaysWorktime> SpecialDaysWorktime;
multimap<int, ATBSpecialDays> SpecialDays;
multimap<int, ATBWeekDays> WeekDays;
multimap<int, ATBPeriodYear> YearPeriod;
multimap<int, ATBWeekDaysWorktime> WeekDaysWorktime;
multimap<int, ATBPaymentOption> PaymentOption;
/// <summary>
/// Parse JSON string
/// </summary>
/// <param name="json"></param>
/// <returns>Returns operation status bool (OK | FAIL) </returns>
bool ParseJson(Configuration* cfg, const char* json);
private:
/// <summary>
/// Identify type of JSON member
/// </summary>
/// <param name="member_name"></param>
/// <returns></returns>
MemberType IdentifyJsonMember(const char* member_name);
};

View File

@@ -0,0 +1,12 @@
#pragma once
#include <string>
class ATBCurrency
{
public:
int pcu_id;
std::string pcu_sign;
std::string pcu_major;
std::string pcu_minor;
bool pcu_active;
};

View File

@@ -0,0 +1,13 @@
#pragma once
enum DayOfWeek
{
Saturday = 0x06,
Sunday = 0x01,
Monday = 0x02,
Tuesday = 0x02,
Wednesday = 0x03,
Thursday = 0x04,
Friday = 0x05,
UndefinedDay = 0xFF
};

View File

@@ -0,0 +1,10 @@
#pragma once
#include <string>
class ATBDuration
{
public:
int pun_id;
std::string pun_label;
int pun_duration;
};

View File

View File

@@ -0,0 +1,16 @@
#pragma once
enum MemberType
{
UnknownType = 0xFF,
CurrencyType = 0x00,
PaymentMethodType = 0x01,
PaymentRateType = 0x20,
PaymentOptionType = 0x03,
DurationType = 0x04,
WeekDaysType = 0x05,
WeekDaysWorkTimeType = 0x06,
SpecialDaysWorktimeType = 0x07,
SpecialDaysType = 0x08,
PeriodYearType = 0x09
};

View File

@@ -0,0 +1,10 @@
#pragma once
enum PaymentMethod
{
Undefined = 0xFF,
Progressive = 0x01,
Degressive = 0x02,
Linear = 0x03,
Steps = 0x04
};

View File

@@ -0,0 +1,9 @@
#pragma once
#include <string>
class ATBPaymentMethod
{
public:
int pme_id;
std::string pme_label;
};

View File

@@ -0,0 +1,17 @@
#pragma once
#include <string>
class ATBPaymentOption
{
public:
int pop_id;
std::string pop_label;
int pop_payment_method_id;
std::string pop_day_end_time;
std::string pop_day_night_end_time;
double pop_price_night;
double pop_min_time;
double pop_max_time;
double pop_min_price;
int pop_carry_over;
};

View File

@@ -0,0 +1,9 @@
#pragma once
// Payment option is related to payment_method_id (e.g. option 1 = linear)
enum PaymentOption
{
Option1 = 0x03,
Option2 = 0x02,
Option3 = 0x01
};

View File

@@ -0,0 +1,9 @@
#pragma once
class ATBPaymentRate
{
public:
int pra_payment_option_id;
int pra_payment_unit_id;
double pra_price;
};

View File

@@ -0,0 +1,13 @@
#pragma once
#include <string>
class ATBPeriodYear
{
public:
int pye_id;
std::string pye_label;
int pye_start_month;
int pye_start_day;
int pye_end_month;
int pye_end_day;
};

View File

@@ -0,0 +1,13 @@
#pragma once
#include <string>
class ATBSpecialDays
{
public:
int ped_id;
std::string ped_label;
std::string ped_date_start;
std::string ped_date_end;
int ped_period_special_day_id;
int ped_year;
};

View File

@@ -0,0 +1,12 @@
#pragma once
#include <string>
class ATBSpecialDaysWorktime
{
public:
int pedwt_id;
int pedwt_period_exc_day_id;
std::string pedwt_time_from;
std::string pedwt_time_to;
double pedwt_price;
};

View File

@@ -0,0 +1,34 @@
#pragma once
#include <cstdint>
#include "tariff_cfg.h"
#include "tariff_utils.h"
#include "tariff_payment_method.h"
#include "tariff_vehicle_types.h"
#include "tariff_time_range.h"
/// <summary>
/// Definition of TariffCalculator class
/// </summary>
class TariffCalculator
{
public:
/// <summary>
/// Gets duration in seconds from cost
/// </summary>
/// <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="price"></param>
/// <returns>Returns duration in seconds (data type: double)</returns>
double GetDurationFromCost(TariffConfiguration* tariff_cfg, uint8_t vehicle_type, char const *start_datetime, double price);
/// <summary>
/// Gets cost from duration in seconds
/// </summary>
/// <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="durationMin">Duration of parking in minutes</param>
/// <returns>Returns cost (data type: double)</returns>
double GetCostFromDuration(TariffConfiguration* tariff_cfg, uint8_t vehicle_type, char const *start_datetime, double durationMin);
};

View File

@@ -0,0 +1,58 @@
#pragma once
#include <variant>
#include <cstddef>
#include <stdio.h>
#include <unordered_map>
#include <rapidjson/rapidjson.h>
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
#include <algorithm>
#include "tariff_currency.h"
#include "tariff_duration.h"
#include "tariff_payment_mtd.h"
#include "tariff_payment_opt.h"
#include "tariff_spec_days.h"
#include "tariff_payment_opt.h"
#include "tariff_weekdays.h"
#include "tariff_weekdays_worktime.h"
#include "tariff_spec_days_worktime.h"
#include "tariff_member_type.h"
#include "tariff_period_year.h"
#include "tariff_payment_rate.h"
#include <vector>
using namespace std;
using namespace rapidjson;
/// <summary>
/// Tariff configuration class
/// </summary>
class TariffConfiguration
{
public:
vector<TariffCurrency> Currency;
vector<TariffDuration> Duration;
vector<TariffPaymentMethod> PaymentMethod;
vector<TariffPaymentRate> PaymentRate;
vector<TariffSpecialDaysWorktime> SpecialDaysWorktime;
vector<TariffSpecialDays> SpecialDays;
vector<TariffWeekDays> WeekDays;
vector<TariffPeriodYear> YearPeriod;
vector<TariffWeekDaysWorktime> WeekDaysWorktime;
vector<TariffPaymentOption> PaymentOption;
/// <summary>
/// Parse JSON string
/// </summary>
/// <param name="json"></param>
/// <returns>Returns operation status bool (OK | FAIL) </returns>
bool ParseJson(TariffConfiguration* tariff_cfg, const char* json);
private:
/// <summary>
/// Identify type of JSON member
/// </summary>
/// <param name="member_name"></param>
/// <returns></returns>
MemberType IdentifyJsonMember(const char* member_name);
};

View File

@@ -0,0 +1,18 @@
// #pragma once
#ifndef TARIFF_CURRENCY_H_INCLUDED
#define TARIFF_CURRENCY_H_INCLUDED
/// <summary>
/// Currency data
/// </summary>
class TariffCurrency
{
public:
int pcu_id;
std::string pcu_sign;
std::string pcu_major;
std::string pcu_minor;
bool pcu_active;
};
#endif // TARIFF_CURRENCY_H_INCLUDED

View File

@@ -0,0 +1,19 @@
// #pragma once
#ifndef TARIFF_DAY_OF_WEEK_H_INCLUDED
#define TARIFF_DAY_OF_WEEK_H_INCLUDED
/// <summary>
/// Day of week enumeration
enum DayOfWeek
{
Saturday = 0x00,
Sunday = 0x01,
Monday = 0x02,
Tuesday = 0x03,
Wednesday = 0x04,
Thursday = 0x05,
Friday = 0x06
};
#endif // TARIFF_DAY_OF_WEEK_H_INCLUDED

View File

@@ -0,0 +1,12 @@
// #pragma once
/// <summary>
/// Duration data
/// </summary>
class TariffDuration
{
public:
int pun_id;
std::string pun_label;
int pun_duration;
};

View File

@@ -0,0 +1,78 @@
#ifndef TARIFF_LOG_INCLUDED_H
#define TARIFF_LOG_INCLUDED_H
#include <string>
#include <iostream>
#define DBG_LEVEL_DEBUG 0
#define DBG_LEVEL_INFO 1
#define DBG_LEVEL_WARN 2
#define DBG_LEVEL_CRITICAL 3
#define DBG_LEVEL_ERROR 4
#define DBG_LEVEL_FATAL 5
void setDebugLevel(int level);
int getDebugLevel();
static void print() {
std::cerr << "\n";
if (getDebugLevel() == DBG_LEVEL_FATAL) {
exit(-1);
}
} // termination version
template<typename Arg1, typename... Args>
static void print(const Arg1& arg1, Args&&... args) {
std::cerr << arg1;
print(args...);
}
template<typename Arg1, typename... Args>
static void LOG_DEBUG(const Arg1& arg1, Args&&... args) {
if (getDebugLevel() <= DBG_LEVEL_DEBUG) {
std::cerr << "DEBUG " << arg1;
print(args...);
}
}
template<typename Arg1, typename... Args>
static void LOG_INFO(const Arg1& arg1, Args&&... args) {
if (getDebugLevel() <= DBG_LEVEL_INFO) {
std::cerr << "INFO " << arg1;
print(args...);
}
}
template<typename Arg1, typename... Args>
static void LOG_WARNING(const Arg1& arg1, const Args&&... args) {
if (getDebugLevel() <= DBG_LEVEL_WARN) {
std::cerr << "WARNING " << arg1;
print(args...);
}
}
template<typename Arg1, typename... Args>
static void LOG_CRITICAL(const Arg1& arg1, const Args&&... args) {
if (getDebugLevel() <= DBG_LEVEL_CRITICAL) {
std::cerr << "CRITICAL " << arg1;
print(args...);
}
}
template<typename Arg1, typename... Args>
static void LOG_ERROR(const Arg1& arg1, const Args&&... args) {
if (getDebugLevel() <= DBG_LEVEL_ERROR) {
std::cerr << "ERROR " << arg1;
print(args...);
}
}
template<typename Arg1, typename... Args>
static void LOG_FATAL(const Arg1& arg1, const Args&&... args) {
if (getDebugLevel() <= DBG_LEVEL_FATAL) {
std::cerr << "FATAL " << arg1;
print(args...);
}
}
#endif // TARIFF_LOG_INCLUDED_H

View File

@@ -0,0 +1,19 @@
// #pragma once
/// <summary>
/// JSON configuration member type enumeration
/// </summary>
enum MemberType
{
Unknown = 0xFF,
Currency = 0x00,
PaymentMethod = 0x01,
PaymentRate = 0x20,
PaymentOption = 0x03,
Duration = 0x04,
WeekDays = 0x05,
WeekDaysWorkTime = 0x06,
SpecialDaysWorktime = 0x07,
SpecialDays = 0x08,
PeriodYear = 0x09
};

View File

@@ -0,0 +1,13 @@
// #pragma once
/// <summary>
/// Payment method (byte represents payment option id)
/// </summary>
enum PaymentMethod
{
Undefined = 0xFF,
Progressive = 0x01,
Degressive = 0x02,
Linear = 0x03,
Steps = 0x04
};

View File

@@ -0,0 +1,15 @@
// #pragma once
#ifndef TARIFF_PAYMENT_MTH_H_INCLUDED
#define TARIFF_PAYMENT_MTH_H_INCLUDED
/// <summary>
/// Payment method data
/// </summary>
class TariffPaymentMethod
{
public:
int pme_id;
std::string pme_label;
};
#endif // TARIFF_PAYMENT_MTH_H_INCLUDED

View File

@@ -0,0 +1,21 @@
//#pragma once
#ifndef TARIFF_PAYMENT_OPT_H_INCLUDED
#define TARIFF_PAYMENT_OPT_H_INCLUDED
#include <string>
/// <summary>
/// Vehicly type data
/// </summary>
class TariffPaymentOption
{
public:
int pop_id;
std::string pop_label;
int pop_payment_method_id;
std::string pop_day_end_time;
std::string pop_day_night_end_time;
double pop_price_night;
};
#endif // TARIFF_PAYMENT_OPT_H_INCLUDED

View File

@@ -0,0 +1,17 @@
// #pragma once
#ifndef TARIFF_PAYMENT_RATE_H_INCLUDED
#define TARIFF_PAYMENT_RATE_H_INCLUDED
/// <summary>
/// Payment option data
/// </summary>
// class TariffPaymentRate
struct TariffPaymentRate
{
// public:
int pra_payment_option_id;
int pra_payment_unit_id;
double pra_price;
};
#endif // TARIFF_PAYMENT_RATE_H_INCLUDED

View File

@@ -0,0 +1,15 @@
// #pragma once
/// <summary>
/// Year period definition
/// </summary>
class TariffPeriodYear
{
public:
int pye_id;
std::string pye_label;
int pye_start_month;
int pye_start_day;
int pye_end_month;
int pye_end_day;
};

View File

@@ -0,0 +1,14 @@
// #pragma once
/// <summary>
/// Special days data
/// </summary>
class TariffSpecialDays
{
public:
int ped_id;
std::string ped_label;
std::string ped_date_start;
std::string ped_date_end;
int ped_period_special_day_id;
};

View File

@@ -0,0 +1,14 @@
// #pragma once
/// <summary>
/// Range data
/// </summary>
class TariffSpecialDaysWorktime
{
public:
int pedwt_id;
int pedwt_period_exc_day_id;
std::string pedwt_time_from;
std::string pedwt_time_to;
double pedwt_price;
};

View File

@@ -0,0 +1,17 @@
// #pragma once
#ifndef TARIFF_TIME_RANGE_H_INCLUDED
#define TARIFF_TIME_RANGE_H_INCLUDED
#include <ctime>
/// <summary>
/// Time range definition
/// </summary>
class TariffTimeRange {
public:
time_t time_from;
time_t time_to;
TariffTimeRange() : time_from(0), time_to(0) {}
};
#endif // TARIFF_TIME_RANGE_H_INCLUDED

View File

@@ -0,0 +1,95 @@
// #pragma once
#ifndef TARIFF_UTILS_H_INCLUDED
#define TARIFF_UTILS_H_INCLUDED
#include "tariff_day_of_week.h"
#include "tariff_cfg.h"
#include "tariff_time_range.h"
#include "active_time_range.h"
#include <stdio.h>
#include <cstring>
#include <ctime>
#include <stddef.h>
#include <locale.h>
#include <iostream>
#include <math.h>
/// <summary>
/// Definition of TariffUtilities class
/// </summary>
class TariffUtils {
public:
/// <summary>
/// Validate parking ticket
/// </summary>
/// <param name="initial"></param>
/// <param name="durationMin"></param>
/// <param name="time_range"></param>
/// <param name="isSpecialDay"></param>
/// <param name="spec_day_id"></param>
/// <returns></returns>
static bool
ValidateParkingTicket(TariffConfiguration const *tariff_cfg,
time_t initial, int durationMin,
double price, TariffTimeRange time_range,
bool isSpecialDay, int spec_day_id);
/// <summary>
/// Check if time is in range between start and end of active payment hours
/// </summary>
/// <param name="tariff_cfg">Tariff configuration</param>
/// <param name="datetimeStr">Current datetime string</param>
/// <param name="isSpecialDay">Special day flag</param>
/// <param name="spec_day_id">Special day ID</param>
/// <returns>Returns if parking time range is active</returns>
static ActiveTimeRange
isParkingTimeRangeActive(TariffConfiguration *tariff_cfg,
std::string datetimeStr, bool isSpecialDay,
int spec_day_id);
/// <summary>
/// Get day of week from current date (Zeller's Algorithm),
/// starting day is Sunday
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
static DayOfWeek GetDayOfWeek(struct tm const *t);
/// <summary>
/// Identifies special day (e.g. Christmas)
/// </summary>
/// <param name="tariff_cfg">Pointer to tariff configuration data</param>
/// <param name="date">Date to be validated</param>
/// <param name="date">Reference to special day ID</param>
/// <returns>Returns if the date is a special day</returns>
static bool IsSpecialDay(TariffConfiguration const *tariff_cfg, const char *dateTimeStr, int& specialDayId);
static bool PriceForSpecialDay(TariffConfiguration const* tariff_cfg, int specialDayId, double *price);
/// <summary>
/// Date and time parse helper function
/// </summary>
/// <returns>Returns time (tm) structure</returns>
static bool DateTimeToStructTm(const char* dateTimeStr, struct tm *t);
/// <summary>
/// Date parse helper function
/// </summary>
/// <returns>Returns time (tm) structure</returns>
static bool DateToStructTm(char const* dateStr, struct tm *t);
/// <summary>
/// Time parse helper function
/// </summary>
/// <returns>Returns time (tm) structure</returns>
static bool TimeToStructTm(const char* timeStr, struct tm *t);
/// <summary>
/// Get current local time
/// </summary>
/// <returns>Returns time_t structure</returns>
static time_t GetCurrentLocalTime();
};
#endif // TARIFF_UTILS_H_INCLUDED

View File

@@ -0,0 +1,11 @@
// #pragma once
/// <summary>
/// Vehicle type enumeration (byte represents payment method id)
/// </summary>
enum PaymentOption
{
Car = 0x03,
HeavyVehicle = 0x02,
Daily = 0x01
};

View File

@@ -0,0 +1,12 @@
// #pragma once
/// <summary>
/// Weekdays data
/// </summary>
class TariffWeekDays
{
public:
int pdiw_id;
std::string pdiw_label;
int pdiw_index;
};

View File

@@ -0,0 +1,14 @@
// #pragma once
/// <summary>
/// Weekdays worktime data
/// </summary>
class TariffWeekDaysWorktime
{
public:
int pwd_id;
int pwd_period_week_day_id;
int pwd_period_day_in_week_id;
std::string pwd_time_from;
std::string pwd_time_to;
};

View File

@@ -0,0 +1,8 @@
#pragma once
#include "time_range_header.h"
struct TimeRange {
public:
bool IsActive;
ATBTimeRange TimeRangeStructure;
};

View File

@@ -0,0 +1,8 @@
#pragma once
#include <ctime>
class ATBTimeRange {
public:
time_t time_from;
time_t time_to;
};

View File

@@ -0,0 +1,72 @@
#pragma once
#include <cstring>
#include <string.h>
#include <ctime>
#include <iostream>
#include <cmath>
#include "day_of_week.h"
#include "configuration.h"
#include "time_range.h"
using namespace std;
class Utilities {
public:
/// <summary>
/// Get day of week from current date (Zeller's Algorithm), starting day is Sunday
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
static DayOfWeek GetDayOfWeek(struct tm* tm);
/// <summary>
/// Date and time parse helper function
/// </summary>
/// <returns>Returns time (tm) structure</returns>
static struct tm DateTimeToStructTm(const char* dateTimeStr);
/// <summary>
/// Date parse helper function
/// </summary>
/// <returns>Returns time (tm) structure</returns>
static struct tm DateToStructTm(const char* dateStr);
/// <summary>
/// Time parse helper function
/// </summary>
/// <returns>Returns time (tm) structure</returns>
static struct tm TimeToStructTm(const char* timeStr, int year, int mon, int mday, int wday);
/// <summary>
/// Get current local time
/// </summary>
/// <returns>Returns time_t structure</returns>
static time_t GetCurrentLocalTime();
/// <summary>
/// Zeller's algorithm for determining day of week
/// </summary>
static int ZellersAlgorithm(int day, int month, int year);
/// <summary>
/// Checks if current datetime is in range between start and end month of parking worktime
/// </summary>
/// <param name="tariff_cfg"></param>
/// <param name="currentDateTime"></param>
/// <returns></returns>
static bool IsYearPeriodActive(Configuration* cfg, struct tm* currentDateTime);
/// <summary>
/// Check permissions
/// </summary>
static bool CheckSpecialDay(Configuration* cfg, const char* currentDateTimeStr, int* specialDayId, double* specialDayPrice);
/// <summary>
/// Calculates price per unit
/// </summary>
/// <param name="pra_price"></param>
/// <returns></returns>
static double CalculatePricePerUnit(double pra_price);
};

View File

@@ -0,0 +1,10 @@
#pragma once
#include <string>
class ATBWeekDays
{
public:
int pdiw_id;
std::string pdiw_label;
int pdiw_index;
};

View File

@@ -0,0 +1,12 @@
#pragma once
#include <string>
class ATBWeekDaysWorktime
{
public:
int pwd_id;
int pwd_period_week_day_id;
int pwd_period_day_in_week_id;
std::string pwd_time_from;
std::string pwd_time_to;
};