From 69ac97f01cfb8d1a93b2b2c74f4bc6c0bb5a8bce Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Thu, 2 Feb 2023 12:53:38 +0100 Subject: [PATCH] Added several functions: computeFreeOfCharge, computeEffectiveStartMinute, compute_price_for_max_price_at_midnight -> implementation of a special apcoa-tariff, implementation of compute_duration_for_parking_ticket --- .../calculate_parking_tickets_algorithms.cpp | 232 +++++++++++------- 1 file changed, 145 insertions(+), 87 deletions(-) diff --git a/calculate_parking_tickets/calculate_parking_tickets_algorithms.cpp b/calculate_parking_tickets/calculate_parking_tickets_algorithms.cpp index 724a766..d538bdc 100644 --- a/calculate_parking_tickets/calculate_parking_tickets_algorithms.cpp +++ b/calculate_parking_tickets/calculate_parking_tickets_algorithms.cpp @@ -59,8 +59,8 @@ extern "C" { #endif -static minute_t computeEffectiveStartMinute(parking_tariff_t const *tariff, - minute_t startMinute) { +static minute_t computeFreeOfCharge(parking_tariff_t const *tariff, + minute_t startMinute) { QDateTime const start = TUtils::fromMinutes(startMinute); minute_t free_of_charge = 0; minute_t startMinuteDay = start.time().hour()*60 +start.time().minute(); @@ -72,8 +72,12 @@ static minute_t computeEffectiveStartMinute(parking_tariff_t const *tariff, (startMinuteDay >= 0 && startMinuteDay < tariff->night_tariff_end)) { free_of_charge = tariff->free_of_charge_night_tariff; } + return free_of_charge; +} - return (startMinute + free_of_charge); +static minute_t computeEffectiveStartMinute(parking_tariff_t const *tariff, + minute_t startMinute) { + return (startMinute + computeFreeOfCharge(tariff, startMinute)); } static bool checkCalculatePreConditions(parking_tariff_t const* tariff, @@ -90,8 +94,9 @@ static bool checkCalculatePreConditions(parking_tariff_t const* tariff, minute_t const parkingTime = endMinute - startMinute; if (parkingTime == 0) { - qCritical() << "startMinute == endMinute => no parking time"; - return false; + price->units = 0; + //qInfo() << "startMinute == endMinute => no parking time"; + return true; } if (tariff->parking_time_max != -1) { @@ -103,26 +108,17 @@ static bool checkCalculatePreConditions(parking_tariff_t const* tariff, } QDateTime const start = TUtils::fromMinutes(startMinute); - //minute_t free_of_charge = 0; - //minute_t startMinuteDay = start.time().hour()*60 +start.time().minute(); - //if (startMinuteDay >= tariff->day_tariff_start && - // startMinuteDay < tariff->day_tariff_end) { - // free_of_charge = tariff->free_of_charge_day_tariff; - //} else - //if ((startMinuteDay >= tariff->night_tariff_start && startMinuteDay < MINUTES_PER_DAY) || - // (startMinuteDay >= 0 && startMinuteDay < tariff->night_tariff_end)) { - // free_of_charge = tariff->free_of_charge_night_tariff; - //} - minute_t const effectiveStartMinute = computeEffectiveStartMinute(tariff, startMinute); QDateTime const end = TUtils::fromMinutes(endMinute); if (effectiveStartMinute > endMinute) { - fprintf(stderr, - "[start:%02d:%02d, ende:%02d:%02d]: %ld free minutes. no charge.\n", - start.time().hour(), start.time().minute(), - end.time().hour(), end.time().minute(), tariff->free_of_charge_day_tariff); - memset(price, 0x00, sizeof(*price)); + //minute_t free_of_charge = computeFreeOfCharge(tariff, startMinute); + //fprintf(stderr, + // "[start:%02d:%02d, ende:%02d:%02d]: %ld free minutes. no charge.\n", + // start.time().hour(), start.time().minute(), + // end.time().hour(), end.time().minute(), free_of_charge); + price->units = 0; + price->valid = true; return false; } @@ -131,6 +127,68 @@ static bool checkCalculatePreConditions(parking_tariff_t const* tariff, } #define DEBUG_INTERNAL 0 +#define DEBUG_MAX_PRICE_AT_MIDNIGHT 1 + +uint32_t compute_price_for_max_price_at_midnight(parking_tariff_t const *tariff, + QDateTime const &end, + TariffStep const *step) { + uint32_t price_units = 0; + QDateTime stepDateTime = step->dateTime(); + QDateTime nextStepDateTime; + QDateTime midnight(stepDateTime.date().addDays(1), QTime(0,0)); + uint32_t day_price_units = 0; + bool dbg = true; + while (stepDateTime < end) { + uint32_t const price_units_tmp = step->price(); + step = step->next(); + nextStepDateTime = step->dateTime(); + if (stepDateTime < midnight) { + day_price_units += price_units_tmp; + if (day_price_units > tariff->max_price_at_midnight) { + day_price_units = tariff->max_price_at_midnight; + if (dbg) { +#if DEBUG_MAX_PRICE_AT_MIDNIGHT==1 + fprintf(stderr, + "[%s:%02d:%02d price_so_far=%d day_price=%d]\n", + stepDateTime.date().toString().toStdString().c_str(), + stepDateTime.time().hour(), stepDateTime.time().minute(), + price_units, day_price_units); + //dbg = false; +#endif + } + } else { +#if DEBUG_MAX_PRICE_AT_MIDNIGHT==1 + dbg = true; + fprintf(stderr, + "[%s:%02d:%02d price_so_far=%d day_price=%d]\n", + stepDateTime.date().toString().toStdString().c_str(), + stepDateTime.time().hour(), stepDateTime.time().minute(), + price_units, day_price_units); +#endif + } + } else { + if (day_price_units == tariff->max_price_at_midnight) { + price_units += day_price_units; + day_price_units = 0; + } else { + day_price_units += price_units_tmp; + } +#if DEBUG_MAX_PRICE_AT_MIDNIGHT==1 + fprintf(stderr, + "[%s:%02d:%02d 24h max. price_so_far=%d day_price=%d]\n", + stepDateTime.date().toString().toStdString().c_str(), + stepDateTime.time().hour(), stepDateTime.time().minute(), + price_units, day_price_units); +#endif + midnight = stepDateTime; + midnight.setDate(midnight.date().addDays(1)); + midnight.setTime(QTime(0, 0)); + } + stepDateTime = nextStepDateTime; + } + price_units += day_price_units; + return price_units; +} TariffStep const * compute_price_for_parking_ticket_internal(parking_tariff_t const *tariff, @@ -227,60 +285,7 @@ compute_price_for_parking_ticket_internal(parking_tariff_t const *tariff, } if (tariff->max_price_at_midnight) { // restart pricing at midnight if current price is max_price_at_midnight - QDateTime stepDateTime = step->dateTime(); - QDateTime nextStepDateTime; - QDateTime midnight(stepDateTime.date().addDays(1), QTime(0,0)); - uint32_t day_price_units = 0; - bool dbg = true; - while (stepDateTime < end) { - uint32_t const price_units_tmp = step->price(); - step = step->next(); - nextStepDateTime = step->dateTime(); - if (stepDateTime < midnight) { - day_price_units += price_units_tmp; - if (day_price_units > tariff->max_price_at_midnight) { - day_price_units = tariff->max_price_at_midnight; - if (dbg) { -#if DEBUG_INTERNAL - fprintf(stderr, - "[%s:%02d:%02d price_so_far=%d day_price=%d]\n", - stepDateTime.date().toString().toStdString().c_str(), - stepDateTime.time().hour(), stepDateTime.time().minute(), - price_units, day_price_units); - //dbg = false; -#endif - } - } else { -#if DEBUG_INTERNAL - dbg = true; - fprintf(stderr, - "[%s:%02d:%02d price_so_far=%d day_price=%d]\n", - stepDateTime.date().toString().toStdString().c_str(), - stepDateTime.time().hour(), stepDateTime.time().minute(), - price_units, day_price_units); -#endif - } - } else { - if (day_price_units == tariff->max_price_at_midnight) { - price_units += day_price_units; - day_price_units = 0; - } else { - day_price_units += price_units_tmp; - } -#if DEBUG_INTERNAL - fprintf(stderr, - "[%s:%02d:%02d 24h max. price_so_far=%d day_price=%d]\n", - stepDateTime.date().toString().toStdString().c_str(), - stepDateTime.time().hour(), stepDateTime.time().minute(), - price_units, day_price_units); -#endif - midnight = stepDateTime; - midnight.setDate(midnight.date().addDays(1)); - midnight.setTime(QTime(0, 0)); - } - stepDateTime = nextStepDateTime; - } - price_units += day_price_units; + price_units = compute_price_for_max_price_at_midnight(tariff, end, step); } price->units = price_units; @@ -296,9 +301,9 @@ bool compute_price_for_parking_ticket(parking_tariff_t const *tariff, minute_t startMinute, // CET minute_t endMinute, // CET struct price_t *price) { - + price->valid = false; if (!checkCalculatePreConditions(tariff, startMinute, endMinute, price)) { // CET - return false; + return price->valid; } // minute_t const parkingTime = endMinute - startMinute; @@ -309,8 +314,8 @@ bool compute_price_for_parking_ticket(parking_tariff_t const *tariff, // QDateTime const effStart = TUtils::fromMinutes(effectiveStartMinute); // QDateTime const end = TUtils::fromMinutes(endMinute); - //qDebug() << effStart; - //qDebug() << end; + // qDebug() << "XXX" << effStart; + // qDebug() << "XXX" << end; TariffStep const *stepDbg = compute_price_for_parking_ticket_internal(tariff, @@ -357,7 +362,8 @@ bool compute_price_for_parking_ticket(parking_tariff_t const *tariff, return false; } - fprintf(stderr, " : gesamt %.2f (netto: %.2f)\n", price->brutto/100, price->netto/100); + // fprintf(stderr, " : gesamt %.2f (netto: %.2f)\n", price->brutto/100, price->netto/100); + return true; } else { @@ -367,27 +373,78 @@ bool compute_price_for_parking_ticket(parking_tariff_t const *tariff, return false; } +#define DEBUG_COMPUTE_DURATION 1 + bool compute_duration_for_parking_ticket(parking_tariff_t const *tariff, minute_t start_parking_time, minute_t *end_parking_time, struct price_t const *price) { - price_t p; - for (int i = 0; i < tariff->parking_time_max; ++i) { - minute_t end_time = start_parking_time + i; - if (compute_price_for_parking_ticket(tariff, start_parking_time, - end_time, &p)) { - if (p.netto >= price->netto) { - *end_parking_time = end_time; + QDateTime const s = TUtils::fromMinutes(start_parking_time); + +#if DEBUG_COMPUTE_DURATION==1 + fprintf(stderr, "price %u, start_parking_time %s:%02d:%02d\n", + price->units, s.date().toString().toStdString().c_str(), + s.time().hour(), s.time().minute()); +#endif + + minute_t free_of_charge = computeFreeOfCharge(tariff, start_parking_time); + minute_t end_time_at_max_price = start_parking_time; + for (int now = 0; now < tariff->parking_time_max; ++now) { + if (price->units == 0) { + if (free_of_charge >= now) { + *end_parking_time = start_parking_time + free_of_charge; + +#if DEBUG_COMPUTE_DURATION==1 + QDateTime const e = TUtils::fromMinutes(*end_parking_time); + fprintf(stderr, "price %u, end_parking_time %s:%02d:%02d\n", + price->units, e.date().toString().toStdString().c_str(), + e.time().hour(), e.time().minute()); +#endif + return true; } + } else { + minute_t end_time = start_parking_time + now; + price_t p; + if (compute_price_for_parking_ticket(tariff, start_parking_time, + end_time, &p)) { + if (p.units <= price->units) { + end_time_at_max_price = end_time; + } else { + if (end_time_at_max_price >= free_of_charge) { + *end_parking_time = end_time_at_max_price - free_of_charge; + +#if DEBUG_COMPUTE_DURATION==1 + QDateTime const e = TUtils::fromMinutes(*end_parking_time); + fprintf(stderr, "price %u, end_parking_time %s:%02d:%02d\n", + price->units, e.date().toString().toStdString().c_str(), + e.time().hour(), e.time().minute()); +#endif + + return true; + } + fprintf(stderr, + "ERROR end_time_at_max_price(%lu) < free_of_charge(%lu)\n", + end_time_at_max_price, free_of_charge); + break; + } + } else { + // TODO ausgabe + //return false; + break; + } } } + fprintf(stderr, "ERROR %s start_parking_time for price %u: %s:%02d:%02d\n", + __func__, price->units, s.date().toString().toStdString().c_str(), + s.time().hour(), s.time().minute()); return false; } bool compute_price_for_tages_ticket(parking_tariff_t *tariff, time_t parking_time_start, // minutes struct price_t *price) { +// NOT TESTED QDateTime dateTime = TUtils::fromMinutes(parking_time_start).addDays(1); dateTime.setTime(QTime(0, 0)); time_t parking_time_end = dateTime.toSecsSinceEpoch() / 60; @@ -400,6 +457,7 @@ bool compute_price_for_24h_ticket(parking_tariff_t *tariff, struct price_t *price) { QDateTime dateTime = TUtils::fromMinutes(parking_time_start).addDays(1); time_t parking_time_end = dateTime.toSecsSinceEpoch() / 60; +// NOT TESTED return compute_price_for_parking_ticket(tariff, parking_time_start, parking_time_end, price); }