Compare commits

..

6 Commits

6 changed files with 30607 additions and 38 deletions

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,7 @@ HEADERS += \
calculate_parking_tickets_algorithms.h \ calculate_parking_tickets_algorithms.h \
calculate_parking_tickets_tariff.h calculate_parking_tickets_tariff.h
OTHER_FILES += germersheim.conf OTHER_FILES += germering.conf apcoa_prio_1.conf
# Default rules for deployment. # Default rules for deployment.
unix { unix {

View File

@ -59,6 +59,23 @@
extern "C" { extern "C" {
#endif #endif
static minute_t computeEffectiveStartMinute(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();
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;
}
return (startMinute + free_of_charge);
}
static bool checkCalculatePreConditions(parking_tariff_t const* tariff, static bool checkCalculatePreConditions(parking_tariff_t const* tariff,
minute_t startMinute, // CET minute_t startMinute, // CET
minute_t endMinute, // CET minute_t endMinute, // CET
@ -85,16 +102,26 @@ static bool checkCalculatePreConditions(parking_tariff_t const* tariff,
} }
} }
minute_t const effectiveStartMinute = startMinute + tariff->free_of_charge;
QDateTime const start = TUtils::fromMinutes(startMinute); QDateTime const start = TUtils::fromMinutes(startMinute);
//QDateTime const effStart = TUtils::fromMinutes(effectiveStartMinute); //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); QDateTime const end = TUtils::fromMinutes(endMinute);
if (effectiveStartMinute > endMinute) { if (effectiveStartMinute > endMinute) {
fprintf(stderr, fprintf(stderr,
"[start:%02d:%02d, ende:%02d:%02d]: %ld free minutes. no charge.\n", "[start:%02d:%02d, ende:%02d:%02d]: %ld free minutes. no charge.\n",
start.time().hour(), start.time().minute(), start.time().hour(), start.time().minute(),
end.time().hour(), end.time().minute(), tariff->free_of_charge); end.time().hour(), end.time().minute(), tariff->free_of_charge_day_tariff);
memset(price, 0x00, sizeof(*price)); memset(price, 0x00, sizeof(*price));
return false; return false;
} }
@ -103,7 +130,7 @@ static bool checkCalculatePreConditions(parking_tariff_t const* tariff,
return true; return true;
} }
#define DEBUG_INTERNAL 1 #define DEBUG_INTERNAL 0
TariffStep const * TariffStep const *
compute_price_for_parking_ticket_internal(parking_tariff_t const *tariff, compute_price_for_parking_ticket_internal(parking_tariff_t const *tariff,
@ -117,7 +144,7 @@ compute_price_for_parking_ticket_internal(parking_tariff_t const *tariff,
int const minute = start.time().minute(); int const minute = start.time().minute();
int const hour = start.time().hour(); int const hour = start.time().hour();
int const day = start.date().dayOfWeek()-Qt::Monday; int const day = start.date().dayOfWeek()-1;
int const week = 0; int const week = 0;
// printf("%d%d%04d\n", week, day, hour*60+minute); // printf("%d%d%04d\n", week, day, hour*60+minute);
@ -129,12 +156,14 @@ compute_price_for_parking_ticket_internal(parking_tariff_t const *tariff,
uint32_t price_units = 0; uint32_t price_units = 0;
if (tariff->max_price_for_24_hours == (uint32_t)(-1)) { //if (tariff->max_price_for_24_hours == (uint32_t)(-1)) {
if (tariff->basic_tariff) {
while (step->dateTime() < end) { while (step->dateTime() < end) {
price_units += step->price(); price_units += step->price();
step = step->next(); step = step->next();
} }
} else { }
if (tariff->max_price_24h_after_arrival){
QDateTime stepDateTime = step->dateTime(); QDateTime stepDateTime = step->dateTime();
QDateTime nextStepDateTime; QDateTime nextStepDateTime;
// QDateTime prevStepDateTime; // QDateTime prevStepDateTime;
@ -196,6 +225,63 @@ compute_price_for_parking_ticket_internal(parking_tariff_t const *tariff,
} }
price_units += _24h_price_units; price_units += _24h_price_units;
} }
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 = price_units; price->units = price_units;
price->netto = roundf((price->units * tariff->unit_scale_factor) / tariff->unit_definition); price->netto = roundf((price->units * tariff->unit_scale_factor) / tariff->unit_definition);
@ -218,10 +304,10 @@ bool compute_price_for_parking_ticket(parking_tariff_t const *tariff,
// minute_t const parkingTime = endMinute - startMinute; // minute_t const parkingTime = endMinute - startMinute;
memset(price, 0x00, sizeof(*price)); memset(price, 0x00, sizeof(*price));
minute_t const effectiveStartMinute = startMinute + tariff->free_of_charge; minute_t const effectiveStartMinute = computeEffectiveStartMinute(tariff, startMinute);
QDateTime const start = TUtils::fromMinutes(startMinute); // QDateTime const start = TUtils::fromMinutes(startMinute);
QDateTime const effStart = TUtils::fromMinutes(effectiveStartMinute); // QDateTime const effStart = TUtils::fromMinutes(effectiveStartMinute);
QDateTime const end = TUtils::fromMinutes(endMinute); // QDateTime const end = TUtils::fromMinutes(endMinute);
//qDebug() << effStart; //qDebug() << effStart;
//qDebug() << end; //qDebug() << end;

View File

@ -17,18 +17,26 @@
using namespace rapidjson; using namespace rapidjson;
#define FREE_OF_CHARGE "free_of_charge" #define DAY_TARIFF_START "day_tariff_start"
#define UNIT_SCALE_FACTOR "unit_scale_factor" #define DAY_TARIFF_END "day_tariff_end"
#define UNIT_DEFINITION "unit_definition" #define NIGHT_TARIFF_START "night_tariff_start"
#define VAT "vat" #define NIGHT_TARIFF_END "night_tariff_end"
#define MAX_PARKING_PRICE "max_parking_price" #define FREE_OF_CHARGE_DAY_TARIFF "free_of_charge_day_tariff"
#define MAX_PRICE_FOR_24_HOURS "max_price_for_24_hours" #define FREE_OF_CHARGE_NIGHT_TARIFF "free_of_charge_night_tariff"
#define MAX_PARKING_TIME "max_parking_time" #define UNIT_SCALE_FACTOR "unit_scale_factor"
#define TARIFF_VERSION "version" #define UNIT_DEFINITION "unit_definition"
#define TARIFF_FEATURES "tariff_features" #define VAT "vat"
#define WAITING_PERIOD "waiting_period" #define MAX_PARKING_PRICE "max_parking_price"
#define PARKING_TIME_MIN "parking_time_min" #define MAX_PRICE_FOR_24_HOURS "max_price_for_24_hours"
#define PARKING_TIME_MAX "parking_time_max" #define MAX_PARKING_TIME "max_parking_time"
#define TARIFF_VERSION "version"
#define TARIFF_FEATURES "tariff_features"
#define WAITING_PERIOD "waiting_period"
#define PARKING_TIME_MIN "parking_time_min"
#define PARKING_TIME_MAX "parking_time_max"
#define BASIC_TARIFF "basic_tariff"
#define MAX_PRICE_24H_AFTER_ARRIVAL "max_price_24h_after_arrival"
#define MAX_PRICE_AT_MIDNIGHT "max_price_at_midnight"
static const char *weekStr[] { static const char *weekStr[] {
"week1", "week2", "week3" "week1", "week2", "week3"
@ -89,6 +97,34 @@ parking_tariff_t *parking_tariff_t::parseTariff(const char *confFile) {
sizeof(tariff->_tariff_features)); sizeof(tariff->_tariff_features));
} }
} }
if (d.HasMember(DAY_TARIFF_START)) {
Value::MemberIterator o = d.FindMember(DAY_TARIFF_START);
assert(o != d.MemberEnd());
assert(o->value.IsString());
std::string s = o->value.GetString();
tariff->day_tariff_start = std::stoi(s);
}
if (d.HasMember(DAY_TARIFF_END)) {
Value::MemberIterator o = d.FindMember(DAY_TARIFF_END);
assert(o != d.MemberEnd());
assert(o->value.IsString());
std::string s = o->value.GetString();
tariff->day_tariff_end = std::stoi(s);
}
if (d.HasMember(NIGHT_TARIFF_START)) {
Value::MemberIterator o = d.FindMember(NIGHT_TARIFF_START);
assert(o != d.MemberEnd());
assert(o->value.IsString());
std::string s = o->value.GetString();
tariff->night_tariff_start = std::stoi(s);
}
if (d.HasMember(NIGHT_TARIFF_END)) {
Value::MemberIterator o = d.FindMember(NIGHT_TARIFF_END);
assert(o != d.MemberEnd());
assert(o->value.IsString());
std::string s = o->value.GetString();
tariff->night_tariff_end = std::stoi(s);
}
if (d.HasMember(WAITING_PERIOD)) { if (d.HasMember(WAITING_PERIOD)) {
Value::MemberIterator o = d.FindMember(WAITING_PERIOD); Value::MemberIterator o = d.FindMember(WAITING_PERIOD);
assert(o != d.MemberEnd()); assert(o != d.MemberEnd());
@ -96,12 +132,19 @@ parking_tariff_t *parking_tariff_t::parseTariff(const char *confFile) {
std::string wp = o->value.GetString(); std::string wp = o->value.GetString();
tariff->waiting_period = std::stoi(wp); tariff->waiting_period = std::stoi(wp);
} }
if (d.HasMember(FREE_OF_CHARGE)) { if (d.HasMember(FREE_OF_CHARGE_DAY_TARIFF)) {
Value::MemberIterator o = d.FindMember(FREE_OF_CHARGE); Value::MemberIterator o = d.FindMember(FREE_OF_CHARGE_DAY_TARIFF);
assert(o != d.MemberEnd()); assert(o != d.MemberEnd());
assert(o->value.IsString()); assert(o->value.IsString());
std::string foc = o->value.GetString(); std::string foc = o->value.GetString();
tariff->free_of_charge = std::stoi(foc); tariff->free_of_charge_day_tariff = std::stoi(foc);
}
if (d.HasMember(FREE_OF_CHARGE_NIGHT_TARIFF)) {
Value::MemberIterator o = d.FindMember(FREE_OF_CHARGE_NIGHT_TARIFF);
assert(o != d.MemberEnd());
assert(o->value.IsString());
std::string foc = o->value.GetString();
tariff->free_of_charge_night_tariff = std::stoi(foc);
} }
if (d.HasMember(UNIT_SCALE_FACTOR)) { if (d.HasMember(UNIT_SCALE_FACTOR)) {
Value::MemberIterator o = d.FindMember(UNIT_SCALE_FACTOR); Value::MemberIterator o = d.FindMember(UNIT_SCALE_FACTOR);
@ -160,18 +203,40 @@ parking_tariff_t *parking_tariff_t::parseTariff(const char *confFile) {
std::string mp = o->value.GetString(); std::string mp = o->value.GetString();
if (mp == "unlimited") { if (mp == "unlimited") {
tariff->max_price_for_24_hours = ~0; tariff->max_price_for_24_hours = ~0;
} else if (mp == "n/a") {
tariff->max_price_for_24_hours = 0;
} else { } else {
tariff->max_price_for_24_hours = (uint32_t)std::stoul(mp); tariff->max_price_for_24_hours = (uint32_t)std::stoul(mp);
} }
} }
if (d.HasMember(BASIC_TARIFF)) {
Value::MemberIterator o = d.FindMember(BASIC_TARIFF);
assert(o != d.MemberEnd());
assert(o->value.IsString());
std::string s = o->value.GetString();
tariff->basic_tariff = (s == "1");
}
if (d.HasMember(MAX_PRICE_24H_AFTER_ARRIVAL)) {
Value::MemberIterator o = d.FindMember(MAX_PRICE_24H_AFTER_ARRIVAL);
assert(o != d.MemberEnd());
assert(o->value.IsString());
std::string s = o->value.GetString();
tariff->max_price_24h_after_arrival = (uint32_t)std::stoul(s);
}
if (d.HasMember(MAX_PRICE_AT_MIDNIGHT)) {
Value::MemberIterator o = d.FindMember(MAX_PRICE_AT_MIDNIGHT);
assert(o != d.MemberEnd());
assert(o->value.IsString());
std::string s = o->value.GetString();
tariff->max_price_at_midnight = (uint32_t)std::stoul(s);
}
QDate today = QDate::currentDate(); QDate today = QDate::currentDate();
int const todayWeekDay = today.dayOfWeek(); // qt: 1 (mon) - 7 (sun) int const todayWeekDay = today.dayOfWeek(); // qt: 1 (mon) - 7 (sun)
if (todayWeekDay > Qt::Monday) { if (todayWeekDay > Qt::Monday) {
int day = today.day(); today = today.addDays(Qt::Monday - todayWeekDay);
day -= (todayWeekDay - Qt::Monday); if (!today.isValid()) {
if (!today.setDate(today.year(), today.month(), day)) {
qFatal("Setting today failed"); qFatal("Setting today failed");
} }
} }

View File

@ -16,7 +16,13 @@
#define VERANSTALTUNG_AUSWAHL_KULTUR (uint64_t)(0x0000000000000010) #define VERANSTALTUNG_AUSWAHL_KULTUR (uint64_t)(0x0000000000000010)
struct parking_tariff_t { struct parking_tariff_t {
// parking_tariff_t(); explicit parking_tariff_t()
: day_tariff_start(0)
, day_tariff_end(0)
, night_tariff_start(0)
, night_tariff_end(0) {
}
static parking_tariff_t *parseTariff(const char *confFile); static parking_tariff_t *parseTariff(const char *confFile);
/// \brief Express computational units in cent. /// \brief Express computational units in cent.
@ -41,6 +47,26 @@ struct parking_tariff_t {
/// ///
TariffStep m_tariffSteps[3][7][MIN_PER_DAY]; TariffStep m_tariffSteps[3][7][MIN_PER_DAY];
///
/// \brief day_tariff_start
///
minute_t day_tariff_start;
///
/// \brief day_tariff_end
///
minute_t day_tariff_end;
///
/// \brief night_tariff_start
///
minute_t night_tariff_start;
///
/// \brief night_tariff_end
///
minute_t night_tariff_end;
/// ///
/// \brief waiting_period /// \brief waiting_period
/// @note Also called "Karenzzeit". Allowed values: [0, 3] /// @note Also called "Karenzzeit". Allowed values: [0, 3]
@ -49,7 +75,12 @@ struct parking_tariff_t {
/// ///
/// \brief free_of_charge /// \brief free_of_charge
/// ///
minute_t free_of_charge; minute_t free_of_charge_day_tariff;
///
/// \brief free_of_charge_night_tariff
///
minute_t free_of_charge_night_tariff;
/// ///
/// \brief max_parking_price_units /// \brief max_parking_price_units
@ -86,6 +117,21 @@ struct parking_tariff_t {
/// ///
minute_t parking_time_max; minute_t parking_time_max;
///
/// \brief basic_tariff
///
bool basic_tariff;
///
/// \brief max_price_24h_after_arrival
///
uint32_t max_price_24h_after_arrival;
///
/// \brief max_price_at_midnight
///
uint32_t max_price_at_midnight;
#if 0 #if 0
/// Minimal amount of money for buying a ticket. /// Minimal amount of money for buying a ticket.
/// ///

View File

@ -18,13 +18,15 @@ int main() {
} }
parking_tariff_t *tariff = parking_tariff_t *tariff =
parking_tariff_t::parseTariff("/opt/ptu5/opt/calculate_parking/calculate_parking_tickets/germersheim.conf"); //parking_tariff_t::parseTariff("/opt/ptu5/opt/calculate_parking/calculate_parking_tickets/germersheim.conf");
parking_tariff_t::parseTariff("/opt/ptu5/opt/calculate_parking/calculate_parking_tickets/apcoa_prio_1.conf");
if (tariff) { if (tariff) {
price_t price; price_t price;
memset(&price, 0x00, sizeof(price)); memset(&price, 0x00, sizeof(price));
QDateTime start = QDateTime::currentDateTime(); QDateTime start = QDateTime::currentDateTime();
QDateTime end; QDateTime st = start;
QDateTime end, tmp;
start.setTime(QTime()); start.setTime(QTime());
int d1, d2 = 0; int d1, d2 = 0;
@ -34,7 +36,9 @@ int main() {
for (int h = 0; h < 6; ++h) { for (int h = 0; h < 6; ++h) {
for (int i = 0; i < MIN_PER_DAY; ++i) { for (int i = 0; i < MIN_PER_DAY; ++i) {
fprintf(stderr, "\n*** %5d *** (parkdauer:%dh)", i*(h+1), hour[h]); //int __x = i*(h+1);
//if (__x == 3060) {
fprintf(stderr, "\n*** %d:%d *** (parkdauer:%dh)", h, i, hour[h]);
if (d1 != d2) { if (d1 != d2) {
qDebug() << ((i==0) ? 0: i/MIN_PER_DAY) << d1 << "***\n"; qDebug() << ((i==0) ? 0: i/MIN_PER_DAY) << d1 << "***\n";
@ -44,25 +48,30 @@ int main() {
//start = start.addSecs(i*60); //start = start.addSecs(i*60);
//start = start.addSecs(420*60); //start = start.addSecs(420*60);
minute_t const s = TUtils::toMinutes(start); minute_t const s = TUtils::toMinutes(start);
end = start.addSecs(hour[h]*60*60); tmp = start;
end = tmp.addSecs(hour[h]*60*60);
minute_t const e = TUtils::toMinutes(end); minute_t const e = TUtils::toMinutes(end);
//minute_t const e = s + 24*60*3 + 123; //minute_t const e = s + 24*60*3 + 123;
fprintf(stderr, fprintf(stderr,
"[EINFAHRT: %s:%02d:%02d, %ld Minuten frei, " "[EINFAHRT: %s:%02d:%02d, (day:%ld,night:%ld) Minuten frei, "
"AUSFAHRT: %s:%02d:%02d]\n", "AUSFAHRT: %s:%02d:%02d]\n",
start.date().toString().toStdString().c_str(), start.date().toString().toStdString().c_str(),
start.time().hour(), start.time().minute(), start.time().hour(), start.time().minute(),
tariff->free_of_charge, tariff->free_of_charge_day_tariff,
tariff->free_of_charge_night_tariff,
end.date().toString().toStdString().c_str(), end.date().toString().toStdString().c_str(),
end.time().hour(), end.time().minute()); end.time().hour(), end.time().minute());
if (compute_price_for_parking_ticket(tariff, s, e, &price)) { if (compute_price_for_parking_ticket(tariff, s, e, &price)) {
} }
//}
start = start.addSecs(60); start = start.addSecs(60);
d1 = start.date().dayOfWeek(); d1 = start.date().dayOfWeek();
} }
start = st;
d1 = start.date().dayOfWeek();
} }
} }