diff --git a/library/src/calculator_functions.cpp b/library/src/calculator_functions.cpp
index d3ed4ed..39c4994 100644
--- a/library/src/calculator_functions.cpp
+++ b/library/src/calculator_functions.cpp
@@ -12,11 +12,11 @@ double total_cost = 0.0f;
bool overtime = false;
#ifdef _WIN32
- inline struct tm* localtime_r(const time_t *clock, struct tm* result){
+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
///
@@ -27,292 +27,216 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
bool nextDay,
bool prepaid)
{
- // Get current date time from input
- struct tm current_datetime = Utilities::DateTimeToStructTm(start_datetime);
- time_t current_datetime_t;
+ // Get input date
+ QDateTime inputDate = QDateTime::fromString(start_datetime,Qt::ISODate);
- // Get day of week
- DayOfWeek weekdayId = DayOfWeek::UndefinedDay;
- weekdayId = Utilities::GetDayOfWeek(¤t_datetime);
+ // Get day of week
+ int weekdayId = 0;
+ weekdayId = Utilities::ZellersAlgorithm(inputDate.date().day(),inputDate.date().month(),inputDate.date().year());
- //std::stringstream ss;
+ //Get min and max time defined in JSON
+ double minMin = 0;
+ minMin = cfg->PaymentOption.find(payment_option)->second.pop_min_time;
- // ss << "*** Input date is: " << start_datetime << " [weekday id = " << weekdayId << "]" << endl;
- LOG_DEBUG("*** Input date is: ", start_datetime, " [weekday id = ", weekdayId, "]");
+ double maxMin = 0;
+ maxMin = cfg->PaymentOption.find(payment_option)->second.pop_max_time;
- double minMin = 0;
- minMin = cfg->PaymentOption.find(payment_option)->second.pop_min_time;
- if (minMin < 0) minMin = 0;
-
- double maxMin = 0;
- maxMin = cfg->PaymentOption.find(payment_option)->second.pop_max_time;
- if (maxMin <= 0) maxMin = 60;
-
- if (minMin >= maxMin)
- {
- LOG_ERROR("Error: min_min cannot be greater or equal to max_min");
- return "PARKING NOT ALLOWED";
- }
-
- if (maxMin <= minMin)
- {
- LOG_ERROR("Error: max_min cannot be lower or equal than min_min");
- return "PARKING NOT ALLOWED";
- }
-
- uint8_t p_method = PaymentMethod::Undefined;
- p_method = payment_option;
- LOG_DEBUG("Payment method id: ", (unsigned)p_method);
-
- double day_price = 0.0f;
- int current_special_day_id = -1;
- bool is_special_day = Utilities::CheckSpecialDay(cfg, start_datetime, ¤t_special_day_id, &day_price);
- LOG_DEBUG("Special day: ", is_special_day);
-
- double money_left = price;
- LOG_DEBUG("Total money:", money_left);
-
- double price_per_unit = 0.0f;
-
- string worktime_from = "";
- string worktime_to = "";
-
- if (is_special_day)
- {
- // Set special day price
- 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)
- size_t found = 0;
- found = cfg->WeekDaysWorktime.count(weekdayId);
-
- if (found <= 0)
- {
- 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];
- 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);
- }
-
- worktime_from = cfg->WeekDaysWorktime.find(weekdayId)->second.pwd_time_from;
- worktime_to = cfg->WeekDaysWorktime.find(weekdayId)->second.pwd_time_to;
- }
-
- if (price_per_unit < 0) price_per_unit = 1.0f;
- LOG_DEBUG("Calculated price per minute: ", price_per_unit);
-
- LOG_DEBUG("Worktime from: ", worktime_from);
- LOG_DEBUG("Worktime to: ", worktime_to);
-
- struct tm from_tm;
- struct tm to_tm;
-
- from_tm = Utilities::TimeToStructTm(worktime_from.c_str(), current_datetime.tm_year, current_datetime.tm_mon, current_datetime.tm_mday, current_datetime.tm_wday);
- from_tm.tm_year = current_datetime.tm_year;
- from_tm.tm_mon = current_datetime.tm_mon;
- 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);
- to_tm.tm_year = current_datetime.tm_year;
- 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
- 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)
- if (money_left <= 0)
- {
- LOG_DEBUG("No money left ");
- break;
- }
- else
- {
- if (total_duration_min >= maxMin)
- {
- LOG_DEBUG("Total duration is greater or equal to max_min");
-
- current_datetime_t = mktime(¤t_datetime);
- current_datetime_t -= 60;
- current_datetime = *localtime(¤t_datetime_t);
- total_duration_min = maxMin;
- break;
- }
-
- // If money has left but the end of worktime has been reached (go to next day)
- if (current_datetime_t >= to_datetime_t)
- {
- total_duration_min -= 1.0f;
-
- int carry_over_status = 0;
- carry_over_status = cfg->PaymentOption.find(payment_option)->second.pop_carry_over;
- 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, money left = ", money_left);
- 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 GetDurationFromCost(cfg, payment_option, start_datetime, price);
- }
- }
- }
-
- time_t valid_until_datetime_t = current_datetime_t;
-
- if ((total_duration_min < minMin) || (price / price_per_unit) < minMin)
- {
- 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;
- 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)
- {
- valid_until_datetime_t -= (int)ceil(calc_price) * 60;
- ret_val = total_duration_min - calc_price;
- }
- else ret_val = total_duration_min;
-
- cout << "Total minutes: " << (int)ret_val << endl;
- if (ret_val <= 0) return "PARKING NOT ALLOWED";
-
-#ifdef __linux__
- #if !defined(_SVID_SOURCE) && !defined(_XOPEN_SOURCE)
- // needed for timezone-correction
- #error "!defined(_SVID_SOURCE) && !defined(_XOPEN_SOURCE)"
- #else
- // timezone correction: localtime() needs argument in UTC-timezone
- // The global variable 'timezone' is set by tzset(), see
- // https://linux.die.net/man/3/tzset, so I change of the timezone will
- // also change the value of the variable 'timezone'.
- valid_until_datetime_t += timezone;
- #endif
-#else // windows, only for testing
- static const long timezone = -3600;
- valid_until_datetime_t += timezone;
-#endif
-
- struct tm valid_until_datetime;
- memset(&valid_until_datetime, 0x00, sizeof(valid_until_datetime));
-
- if (!localtime_r(&valid_until_datetime_t, &valid_until_datetime)) {
- return "LOCALTIME_R() ERROR";
+ double min_price = 0;
+ min_price = cfg->PaymentOption.find(payment_option)->second.pop_min_price;
+ if(price < min_price)
+ {
+ return "PARKING NOT ALLOWED";
}
- // return in ISO-format: "%Y-%m-%dT%H:%M:%S"
- char buf[128];
- memset(buf, 0x00, sizeof(buf));
- strftime(buf, sizeof(buf)-1, "%Y-%m-%dT%H:%M:%S", &valid_until_datetime);
+ if (minMin < 0) minMin = 0;
+ if (maxMin < 0) maxMin = 0;
+ if (minMin >= maxMin)
+ {
+ LOG_ERROR("Error: min_min cannot be greater or equal to max_min");
+ return "PARKING NOT ALLOWED";
+ }
- LOG_DEBUG("Ticket is valid until ", buf);
+ if (maxMin <= minMin)
+ {
+ LOG_ERROR("Error: max_min cannot be lower or equal than min_min");
+ return "PARKING NOT ALLOWED";
+ }
- total_duration_min = 0.0f;
- return std::string(buf);
+
+ // Get payment method
+ uint8_t p_method = PaymentMethod::Undefined;
+ p_method = payment_option;
+ LOG_DEBUG("Payment method id: ", (unsigned)p_method);
+
+ // Check special day
+ double day_price = 0.0f;
+ 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 money_left = price;
+ double price_per_unit = 0.0f;
+
+ QTime worktime_from;
+ QTime worktime_to;
+
+ 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
+ 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)
+ size_t found = 0;
+ found = cfg->WeekDaysWorktime.count(weekdayId);
+
+ // 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 (price_per_unit < 0) price_per_unit = 1.0f;
+ LOG_DEBUG("Calculated price per minute: ", price_per_unit);
+
+ if (price_per_unit < 0)
+ {
+ inputDate = inputDate.addDays(1);
+ inputDate.setTime(worktime_from);
+ return GetDurationFromCost(cfg, payment_option, inputDate.toString(Qt::ISODate).toStdString().c_str(), money_left, true);
+ }
+
+ // If overtime flag is set
+ if (overtime || nextDay)
+ {
+ inputDate.setTime(worktime_from);
+ overtime = false;
+ }
+
+ // Check prepaid
+ if (!prepaid)
+ {
+ if ((inputDate.time() < worktime_from) || (inputDate.time() > worktime_to))
+ {
+ 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);
+ }
+ }
+
+ while(true)
+ {
+ if(money_left <= 0) break;
+
+ // Check year period
+ bool isYearPeriodActive = false;
+
+ //// Parse input date
+ int dayCurrent = inputDate.date().day();
+ int monthCurrent = inputDate.date().month();
+
+ // Current date time
+ int cdt = (monthCurrent * 100) + dayCurrent;
+
+ multimap::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);
+ }
+
+ 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.addSecs(-(int)ceil(calc_price) * 60);
+ }
+ ret_val = total_duration_min;
+
+ if(price >= min_price && total_duration_min >= minMin)
+ qDebug() << "Valid until: " << inputDate.toString(Qt::ISODate);
+ else qDebug() << "Parking not allowed";
+
+ 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();
}
///////////////////////////////////////
diff --git a/main/main.cpp b/main/main.cpp
index c9e2e5f..db78f5e 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -36,20 +36,20 @@ int main() {
memset(&price, 0x00, sizeof(price));
QDateTime start = QDateTime::fromString("2023-05-11T07:50:00",Qt::ISODate); //QDateTime::currentDateTime();
time_t start_parking_time = start.toSecsSinceEpoch() / 60;
- time_t end_parking_time = start_parking_time + 1230;
+ time_t end_parking_time = start_parking_time + 1236;
if (compute_price_for_parking_ticket(tariff,
start_parking_time,
end_parking_time,
&price)) {
- qDebug() << "price=" << price.netto;
+ qDebug() << "GetCostFromDuration() => price=" << price.netto;
}
-// QString duration;
-// if(compute_duration_for_parking_ticket(tariff,start_parking_time,3090,duration))
-// {
-// qDebug() << "duration=" << duration;
-// }
+ QString duration;
+ if(compute_duration_for_parking_ticket(tariff,start_parking_time,3090,duration))
+ {
+ qDebug() << "GetDurationFromCost() => duration=" << duration;
+ }
// // tests
// struct tm now;