151 lines
5.3 KiB
C++
151 lines
5.3 KiB
C++
|
#include "tariff_calc.h"
|
||
|
#include "tariff_utils.h"
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// Helper function
|
||
|
/// </summary>
|
||
|
/// <param name="pra_price"></param>
|
||
|
/// <returns></returns>
|
||
|
double CalculatePricePerUnit(double pra_price)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
double price_per_unit = pra_price;
|
||
|
price_per_unit /= 60.0f;
|
||
|
// Divided by 60 because price per unit is set per hour and we are using minutes
|
||
|
printf("Price per unit (min) is: %lf EUR\n", price_per_unit);
|
||
|
return price_per_unit;
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
printf("An error has occurred in CalculatePricePerUnit() function\n");
|
||
|
return 0.0f;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/// <inheritdoc/>
|
||
|
double TariffCalculator::GetDurationFromCost(TariffConfiguration* tariff_cfg,
|
||
|
uint8_t vehicle_type, char const* start_datetime, double price) {
|
||
|
uint8_t pay_method = PaymentMethod::Undefined;
|
||
|
double cost = 0.0f;
|
||
|
|
||
|
// Payment method is automatically selected by vehicle type
|
||
|
// (vehicle type byte actually represents payment type according to documentation)
|
||
|
// e.g. car (0x03) in tariff_vehicles_type == linear payment method (0x03)
|
||
|
// tariff_payment_method
|
||
|
|
||
|
pay_method = vehicle_type; // car = 0x03
|
||
|
printf("Payment method: %d\n", pay_method);
|
||
|
|
||
|
double price_per_unit = 0;
|
||
|
double durationMin = 0;
|
||
|
|
||
|
bool isSpecialDay = false;
|
||
|
int spec_day_id = -1;
|
||
|
|
||
|
for (size_t i = 0; i <= tariff_cfg->PaymentRate.size(); i++)
|
||
|
{
|
||
|
if (pay_method == tariff_cfg->PaymentRate.at(i).pra_payment_option_id)
|
||
|
{
|
||
|
double pra_price = tariff_cfg->PaymentRate.at(i).pra_price;
|
||
|
|
||
|
// If is special day, pra_price will be overriden with special day's price
|
||
|
if ((isSpecialDay = TariffUtils::IsSpecialDay(tariff_cfg, start_datetime, spec_day_id))) {
|
||
|
if (TariffUtils::PriceForSpecialDay(tariff_cfg, spec_day_id, &pra_price)) {
|
||
|
printf("Date %s is special day\n", start_datetime);
|
||
|
printf("Setting new price per hour: %f EUR\n", pra_price);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
price_per_unit = CalculatePricePerUnit(pra_price);
|
||
|
if (price_per_unit <= 0) price_per_unit = 1; // Division by zero protection
|
||
|
|
||
|
durationMin = price / price_per_unit;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Check active hours for parking (override with special day active hours if special day flag is set)
|
||
|
ActiveTimeRange active_time_range =
|
||
|
TariffUtils::isParkingTimeRangeActive(tariff_cfg, start_datetime,
|
||
|
isSpecialDay, spec_day_id);
|
||
|
printf("Is active parking payment: %d\n", active_time_range.isActive);
|
||
|
|
||
|
// TODO: CHECK
|
||
|
|
||
|
struct tm initial_tm;
|
||
|
TariffUtils::DateTimeToStructTm(start_datetime, &initial_tm);
|
||
|
time_t initial = mktime(&initial_tm);
|
||
|
TariffUtils::ValidateParkingTicket(tariff_cfg, initial, durationMin, price,
|
||
|
active_time_range.timeRange, isSpecialDay, spec_day_id);
|
||
|
|
||
|
// If parking payment active hours have passed, do not calculate duration
|
||
|
if (!active_time_range.isActive) return 0.0f;
|
||
|
return durationMin;
|
||
|
}
|
||
|
|
||
|
/// <inheritdoc/>
|
||
|
double TariffCalculator::GetCostFromDuration(TariffConfiguration* tariff_cfg,
|
||
|
uint8_t vehicle_type, char const* start_datetime, double durationMin) {
|
||
|
uint8_t pay_method = PaymentMethod::Undefined;
|
||
|
double cost = 0.0f;
|
||
|
|
||
|
// Payment method is automatically selected by vehicle type
|
||
|
// (vehicle type byte actually represents payment type according to documentation)
|
||
|
// e.g. car (0x03) in tariff_vehicles_type == linear payment method (0x03)
|
||
|
// tariff_payment_method
|
||
|
|
||
|
pay_method = vehicle_type; // car = 0x03
|
||
|
printf("Payment method: %d\n", pay_method);
|
||
|
|
||
|
int unit = 1.0f; // Unit factor, as parameter 'durationMin'
|
||
|
// represents minutes, this should stay 1
|
||
|
double price_per_unit = 0;
|
||
|
|
||
|
bool isSpecialDay = false;
|
||
|
int spec_day_id = -1;
|
||
|
|
||
|
for (size_t i = 0; i <= tariff_cfg->PaymentRate.size(); i++)
|
||
|
{
|
||
|
if (pay_method == tariff_cfg->PaymentRate.at(i).pra_payment_option_id)
|
||
|
{
|
||
|
double pra_price = tariff_cfg->PaymentRate.at(i).pra_price;
|
||
|
if ((isSpecialDay
|
||
|
= TariffUtils::IsSpecialDay(tariff_cfg,
|
||
|
start_datetime, spec_day_id))) {
|
||
|
// If is special day, pra_price will be
|
||
|
// overriden with special day's price
|
||
|
if (TariffUtils::PriceForSpecialDay(tariff_cfg, spec_day_id, &pra_price)) {
|
||
|
printf("Date %s is special day\n", start_datetime);
|
||
|
printf("Setting new price per hour: %f EUR\n", pra_price);
|
||
|
}
|
||
|
}
|
||
|
price_per_unit = CalculatePricePerUnit(pra_price);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cost = durationMin * price_per_unit;
|
||
|
|
||
|
// Check active hours for parking (override with special day active hours
|
||
|
// if special day flag is set)
|
||
|
ActiveTimeRange active_time_range
|
||
|
= TariffUtils::isParkingTimeRangeActive(tariff_cfg, start_datetime,
|
||
|
isSpecialDay, spec_day_id);
|
||
|
printf("Is active parking payment: %d\n", active_time_range.isActive);
|
||
|
|
||
|
// TODO: CHECK
|
||
|
struct tm initial_tm;
|
||
|
TariffUtils::DateTimeToStructTm(start_datetime, &initial_tm);
|
||
|
time_t initial = mktime(&initial_tm);
|
||
|
TariffUtils::ValidateParkingTicket(tariff_cfg, initial, durationMin, cost,
|
||
|
active_time_range.timeRange, isSpecialDay, spec_day_id);
|
||
|
|
||
|
// If parking payment active hours have passed, do not calculate price
|
||
|
if (!active_time_range.isActive) return 0.0f;
|
||
|
|
||
|
return cost;
|
||
|
}
|