#include "utilities.h" #include "tariff_log.h" #include #include static int protection_counter = 0; /// /// Helper function /// /// /// double Utilities::CalculatePricePerUnit(double pra_price, double durationUnit) { try { double price_per_unit = pra_price; double unit = durationUnit; if(unit < 0 || unit > 65535 ) unit = 60.0f; price_per_unit /= unit; // Divided by 60 because price per unit is set per hour and we are using minutes //printf("Price per unit (min) is: %lf\n", price_per_unit); return price_per_unit; } catch (...) { throw std::invalid_argument("An error has occurred in CalculatePricePerUnit() function\n"); } } /// time_t Utilities::GetCurrentLocalTime() { try { time_t curr_time = time(NULL); tm tm_curr_time = {}; memset(&tm_curr_time, '\0', sizeof(struct tm)); tm_curr_time = *localtime(&curr_time); curr_time = mktime(&tm_curr_time); //- timezone; return curr_time; } catch (...) { throw std::invalid_argument("An error has occurred in GetCurrentLocalTime() function\n"); } } /// int Utilities::ZellersAlgorithm(int day, int month, int year) { int mon; if (month > 2) mon = month; //for march to december month code is same as month else { mon = (12 + month); //for Jan and Feb, month code will be 13 and 14 year--; //decrease year for month Jan and Feb } int y = year % 100; //last two digit int c = year / 100; //first two digit int w = (day + floor((13 * (mon + 1)) / 5) + y + floor(y / 4) + floor(c / 4) + (5 * c)); w = ((w + 5) % 7) + 1; //w % 7; return w; } /// struct tm Utilities::DateToStructTm(const char* dateStr) { struct tm t = {}; memset(&t, '\0', sizeof(struct tm)); if (dateStr == nullptr || strlen(dateStr) <= 0) throw std::invalid_argument("DateToStructTm has failed parsing date string (null or empty)\n"); try { int success = sscanf(dateStr, "%d-%d-%d", &t.tm_year, &t.tm_mon, &t.tm_mday); if (success != 3) throw std::invalid_argument("DateToStructTm() has failed parsing datetime string\n"); t.tm_year = t.tm_year - 1900; t.tm_mon = t.tm_mon - 1; t.tm_isdst = 0; return t; } catch (...) { throw std::invalid_argument("An error has occurred in DateToStructTm() function\n"); } } /// struct tm Utilities::TimeToStructTm(const char* timeStr, int year, int mon, int mday, int wday) { struct tm t = {}; memset(&t, '\0', sizeof(struct tm)); if (timeStr == nullptr || strlen(timeStr) <= 0) throw std::invalid_argument("TimeToStructTm() has failed parsing time string (null or empty)\n"); try { int success_time = sscanf(timeStr, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec); if (success_time != 3) throw std::invalid_argument("TimeToStructTm() has failed parsing time string\n"); struct tm tm_struct; t.tm_year = year; t.tm_mon = mon; t.tm_mday = mday; t.tm_wday = wday; t.tm_isdst = 0; return t; } catch (...) { throw std::invalid_argument("An error has occurred in TimeToStructTm() function\n"); } } /// struct tm Utilities::DateTimeToStructTm(const char* dateTimeStr) { struct tm t = {}; memset(&t, '\0', sizeof(struct tm)); if (dateTimeStr == nullptr || strlen(dateTimeStr) <= 0) throw std::invalid_argument("DateTimeToStructTm() has failed parsing date string (null or empty)"); try { int success = sscanf(dateTimeStr, "%d-%d-%dT%d:%d:%dZ", &t.tm_year, &t.tm_mon, &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec); if (success != 6) throw std::invalid_argument("DateTimeToStructTm() has failed parsing datetime string\n"); t.tm_year = t.tm_year - 1900; t.tm_mon = t.tm_mon - 1; t.tm_isdst = 0; return t; } catch (...) { throw std::invalid_argument("An error has occurred in DateTimeToStructTm() function\n"); } } /// DayOfWeek Utilities::GetDayOfWeek(struct tm* t) { if (t == nullptr) throw std::invalid_argument("GetDayOfWeekFromDate() => parameter 't' is null\n"); try { int d = t->tm_mday; int m = t->tm_mon + 1; int y = t->tm_year + 1900; int wd = Utilities::ZellersAlgorithm(d, m, y); return static_cast(wd); } catch (...) { throw std::invalid_argument("An error has occurred in GetDayOfWeekFromDate() function\n"); } } /// bool Utilities::IsYearPeriodActive(Configuration* cfg, struct tm* currentDateTime_tm) { if (cfg == nullptr) throw std::invalid_argument("IsYearPeriodActive() = > Configuration not set\n"); if (currentDateTime_tm == nullptr) throw std::invalid_argument("IsYearPeriodActive() = > Current datetime not set\n"); try { //// Parse input date int dayCurrent = currentDateTime_tm->tm_mday; int monthCurrent = currentDateTime_tm->tm_mon + 1; // 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) { return true; } } return false; } catch (...) { cout << "IsYearPeriodActive() => An exception has occurred, ignoring check, returning true" << endl; return true; } } bool Utilities::IsYearPeriodActive(Configuration const *cfg, QDateTime const &dt) { if ((cfg->YearPeriod.size() > 0) && std::none_of(cfg->YearPeriod.cbegin(), cfg->YearPeriod.cend(), [&dt](std::pair const &year) { QDate const d(2004, // 2004 is a leap year dt.date().month(), dt.date().day()); QDate const s(2004, year.second.pye_start_month, year.second.pye_start_day); QDate const e(2004, year.second.pye_end_month, year.second.pye_end_day); return (d >= s && d <= e); })) { qCritical() << "NO VALID YEAR PERIOD"; return false; } return true; } /// bool Utilities::CheckSpecialDay(Configuration* cfg, const char* currentDateTimeStr, int* specialDayId, double* specialDayPrice) { try { *specialDayId = -1; *specialDayPrice = 0.0f; if (cfg == nullptr) throw std::invalid_argument("CheckSpecialDay() => configuration is not set\n"); if (currentDateTimeStr == nullptr) throw std::invalid_argument("CheckSpecialDay() => invalid date/time string set\n"); struct tm current_tm = Utilities::DateTimeToStructTm(currentDateTimeStr); //cout << "CheckSpecialDay() => Current: " << asctime(¤t_tm) << endl; multimap::iterator spec_days_itr; for (spec_days_itr = cfg->SpecialDays.begin(); spec_days_itr != cfg->SpecialDays.end(); spec_days_itr++) { int repeat_every_year = 0; repeat_every_year = spec_days_itr->second.ped_year; string start = spec_days_itr->second.ped_date_start; if (start.length() <= 0) continue; //cout << "CheckSpecialDay() => Start: " << start << endl; string end = spec_days_itr->second.ped_date_end; if (end.length() <= 0) continue; //cout << "CheckSpecialDay() => End: " << end << endl; struct tm start_tm = Utilities::DateToStructTm(start.c_str()); //cout << "CheckSpecialDay() => Start: " << asctime(&start_tm) << endl; struct tm end_tm = Utilities::DateToStructTm(end.c_str()); //cout << "CheckSpecialDay() => End: " << asctime(&end_tm) << endl; if (repeat_every_year <= 0) { //cout << "CheckSpecialDay() => Repeat every year is: 0" << endl; if ((current_tm.tm_year == start_tm.tm_year) && (current_tm.tm_year == end_tm.tm_year)) { if ((current_tm.tm_mon >= start_tm.tm_mon) && (current_tm.tm_mon <= end_tm.tm_mon)) { //cout << "CheckSpecialDay() => Month is in range between start and end" << endl; if ((current_tm.tm_mday >= start_tm.tm_mday) && (current_tm.tm_mday <= end_tm.tm_mday)) { LOG_DEBUG("CheckSpecialDay() => SPECIAL DAY"); *specialDayId = spec_days_itr->second.ped_id; *specialDayPrice = cfg->SpecialDaysWorktime.find(*specialDayId)->second.pedwt_price; return true; } } } } else { if ((current_tm.tm_mon >= start_tm.tm_mon) && (current_tm.tm_mon <= end_tm.tm_mon)) { //cout << "CheckSpecialDay() => Month is in range between start and end" << endl; if ((current_tm.tm_mday >= start_tm.tm_mday) && (current_tm.tm_mday <= end_tm.tm_mday)) { LOG_DEBUG("CheckSpecialDay() => SPECIAL DAY"); *specialDayId = spec_days_itr->second.ped_id; *specialDayPrice = cfg->SpecialDaysWorktime.find(*specialDayId)->second.pedwt_price; return true; } } } } //cout << "CheckSpecialDay() => NOT SPECIAL DAY" << endl; return false; } catch (...) { throw std::invalid_argument("CheckSpecialDay() => An error has occurred\n"); return false; } } bool Utilities::CheckSpecialDay(Configuration const *cfg, QDateTime const ¤tDateTime, int* specialDayId, uint32_t *specialDayPrice) { *specialDayId = -1; *specialDayPrice = 0; std::multimap::const_iterator spec_days_itr; for (spec_days_itr = cfg->SpecialDays.cbegin(); spec_days_itr != cfg->SpecialDays.cend(); ++spec_days_itr) { int repeat_every_year = spec_days_itr->second.ped_year; QDate start = QDate::fromString(spec_days_itr->second.ped_date_start.c_str(), Qt::ISODate); QDate end = QDate::fromString(spec_days_itr->second.ped_date_end.c_str(), Qt::ISODate); if (start.isValid() && end.isValid()) { if ((currentDateTime.date().month() >= start.month()) && (currentDateTime.date().month() <= end.month())) { if ((currentDateTime.date().day() >= start.day()) && (currentDateTime.date().day() <= end.day())) { if (repeat_every_year <= 0) { if ((currentDateTime.date().year() != start.year()) || (currentDateTime.date().year() != end.year())) { continue; } } qDebug() << "CheckSpecialDay() => SPECIAL DAY"; *specialDayId = spec_days_itr->second.ped_id; *specialDayPrice = cfg->SpecialDaysWorktime.find(*specialDayId)->second.pedwt_price; return true; } } } } return false; } QTime Utilities::SpecialDaysWorkTimeFrom(Configuration const *cfg, int specialDayId) { return QTime::fromString(cfg->SpecialDaysWorktime.find(specialDayId)->second.pedwt_time_from.c_str(), Qt::ISODate); } QTime Utilities::SpecialDaysWorkTimeUntil(Configuration const *cfg, int specialDayId) { return QTime::fromString(cfg->SpecialDaysWorktime.find(specialDayId)->second.pedwt_time_to.c_str(), Qt::ISODate); } QTime Utilities::WeekDaysWorkTimeFrom(std::multimap::const_iterator itr) { return QTime::fromString(itr->second.pwd_time_from.c_str(), Qt::ISODate); } QTime Utilities::WeekDaysWorkTimeUntil(std::multimap::const_iterator itr) { return QTime::fromString(itr->second.pwd_time_to.c_str(), Qt::ISODate); } bool Utilities::isCarryOverSet(Configuration const *cfg, PaymentMethod paymentMethodId) { return !isCarryOverNotSet(cfg, paymentMethodId); } bool Utilities::isCarryOverNotSet(Configuration const *cfg, PaymentMethod paymentMethodId) { return (cfg->PaymentOption.find(paymentMethodId)->second.pop_carry_over < 1); } PaymentMethod Utilities::getPaymentMethodId(Configuration const *cfg) { if (cfg->PaymentOption.size() != 1) { return PaymentMethod::Undefined; } std::multimap::const_iterator it = cfg->PaymentOption.cbegin(); switch (it->first) { case PaymentMethod::Linear: return PaymentMethod::Linear; case PaymentMethod::Steps: return PaymentMethod::Steps; case PaymentMethod::Degressive: return PaymentMethod::Degressive; case PaymentMethod::Progressive: return PaymentMethod::Progressive; } return PaymentMethod::Undefined; } int Utilities::getMinimalParkingTime(Configuration const *cfg, PaymentMethod methodId) { return std::max((int)cfg->PaymentOption.find(methodId)->second.pop_min_time, 0); } int Utilities::getMaximalParkingTime(Configuration const *cfg, PaymentMethod methodId) { return std::max((int)cfg->PaymentOption.find(methodId)->second.pop_max_time, 0); } uint32_t Utilities::getMinimalParkingPrice(Configuration const *cfg, PaymentMethod methodId) { return std::max((int)cfg->PaymentOption.find(methodId)->second.pop_min_price, 0); } uint32_t Utilities::getFirstDurationStep(Configuration const *cfg, PaymentMethod methodId) { int const popId = cfg->PaymentOption.find(methodId)->second.pop_id; int const punId = cfg->PaymentRate.find(popId)->second.pra_payment_unit_id; uint32_t const firstDurationStep= cfg->Duration.find(punId)->second.pun_duration; qCritical() << "getFirstDurationStep() payment-method-id:" << (int)methodId; qCritical() << "getFirstDurationStep() pop-id:" << popId; qCritical() << "getFirstDurationStep() pun-id:" << punId; qCritical() << "getFirstDurationStep() first-step:" << firstDurationStep; return firstDurationStep; } BusinessHours Utilities::getBusinessHours(Configuration const *cfg, PaymentMethod methodId) { int businessHours = cfg->PaymentOption.find(methodId)->second.pop_business_hours; switch (businessHours) { case NoRestriction_24_7: return NoRestriction_24_7; case OnlyWorkingDays: return OnlyWorkingDays; case OnlyWeekDays: return OnlyWeekDays; case OnlyWeekEnd: return OnlyWeekEnd; case OnlyOfficialHolidays: return OnlyOfficialHolidays; case OnlySpecialDays: return OnlySpecialDays; case OnlySchoolHolidays: return OnlySchoolHolidays; case SpecialAndSchoolHolidays: return SpecialAndSchoolHolidays; case OnlyOpenForBusinessDays: return OnlyOpenForBusinessDays; } return NoBusinessHoursDefined; } uint32_t Utilities::computeWeekDaysPrice(Configuration const *cfg, PaymentMethod id) { int pop_id = cfg->PaymentOption.find(id)->second.pop_id; return cfg->PaymentRate.find(pop_id)->second.pra_price; } double Utilities::computeWeekDaysDurationUnit(Configuration const *cfg, PaymentMethod id) { int pop_id = cfg->PaymentOption.find(id)->second.pop_id; int durationId = cfg->PaymentRate.find(pop_id)->second.pra_payment_unit_id; return (double)(cfg->Duration.find(durationId)->second.pun_duration); }