#include "calculate_parking_tickets_tariff.h" #include #include #include #include #include #include #include #include #include #include "rapidjson/stringbuffer.h" #include #include using namespace rapidjson; #define DAY_TARIFF_START "day_tariff_start" #define DAY_TARIFF_END "day_tariff_end" #define NIGHT_TARIFF_START "night_tariff_start" #define NIGHT_TARIFF_END "night_tariff_end" #define FREE_OF_CHARGE_DAY_TARIFF "free_of_charge_day_tariff" #define FREE_OF_CHARGE_NIGHT_TARIFF "free_of_charge_night_tariff" #define UNIT_SCALE_FACTOR "unit_scale_factor" #define UNIT_DEFINITION "unit_definition" #define VAT "vat" #define MAX_PARKING_PRICE "max_parking_price" #define MAX_PRICE_FOR_24_HOURS "max_price_for_24_hours" #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[] { "week1", "week2", "week3" }; static const char *weekDayStr[] { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }; static const int constexpr STEP_PRICE = 1; static const int constexpr STEP_NEXT = 2; parking_tariff_t *parking_tariff_t::parseTariff(const char *confFile) { parking_tariff_t *tariff = 0; FILE* fp = fopen(confFile, "r"); if (fp) { fseek(fp, 0 , SEEK_END); long const bufSize = ftell(fp) + 1024; fseek(fp, 0 , SEEK_SET); char *readBuffer = (char *)malloc(bufSize); if (readBuffer) { memset(readBuffer, 0x00, bufSize); FileReadStream is(fp, readBuffer, bufSize); Document d; if (d.ParseStream(is).HasParseError()) { fprintf(stderr, "\nError(offset %u): %s\n", (unsigned)d.GetErrorOffset(), GetParseError_En(d.GetParseError())); free(readBuffer); fclose(fp); return 0; } tariff = new parking_tariff_t(); if (d.HasMember(TARIFF_VERSION)) { Value::MemberIterator o = d.FindMember(TARIFF_VERSION); assert(o != d.MemberEnd()); assert(o->value.IsString()); std::string version = o->value.GetString(); strncpy(tariff->tariff_version, version.c_str(), std::min((int)version.size(), (int)sizeof(tariff->tariff_version)-1)); tariff->tariff_version[sizeof(tariff->tariff_version)-1] = '\0'; } if (d.HasMember(TARIFF_FEATURES)) { Value::MemberIterator o = d.FindMember(TARIFF_FEATURES); assert(o != d.MemberEnd()); assert(o->value.IsArray()); int const s = o->value.Size(); if (s > 0) { // TODO } else { tariff->tariff_features = 0; memset(tariff->_tariff_features, 0x00, 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)) { Value::MemberIterator o = d.FindMember(WAITING_PERIOD); assert(o != d.MemberEnd()); assert(o->value.IsString()); std::string wp = o->value.GetString(); tariff->waiting_period = std::stoi(wp); } if (d.HasMember(FREE_OF_CHARGE_DAY_TARIFF)) { Value::MemberIterator o = d.FindMember(FREE_OF_CHARGE_DAY_TARIFF); assert(o != d.MemberEnd()); assert(o->value.IsString()); std::string foc = o->value.GetString(); 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)) { Value::MemberIterator o = d.FindMember(UNIT_SCALE_FACTOR); assert(o != d.MemberEnd()); assert(o->value.IsString()); std::string usf = o->value.GetString(); tariff->unit_scale_factor = std::stof(usf); } if (d.HasMember(UNIT_DEFINITION)) { Value::MemberIterator o = d.FindMember(UNIT_DEFINITION); assert(o != d.MemberEnd()); assert(o->value.IsString()); std::string udef = o->value.GetString(); tariff->unit_definition = std::stoi(udef); } if (d.HasMember(VAT)) { Value::MemberIterator o = d.FindMember(VAT); assert(o != d.MemberEnd()); assert(o->value.IsString()); std::string vat = o->value.GetString(); tariff->vat = std::stof(vat); } if (d.HasMember(MAX_PARKING_PRICE)) { Value::MemberIterator o = d.FindMember(MAX_PARKING_PRICE); assert(o != d.MemberEnd()); assert(o->value.IsString()); std::string mp = o->value.GetString(); if (mp == "unlimited") { tariff->max_parking_price_units = ~0; } else { tariff->max_parking_price_units = (uint32_t)std::stoul(mp); } } if (d.HasMember(PARKING_TIME_MIN)) { Value::MemberIterator o = d.FindMember(PARKING_TIME_MIN); assert(o != d.MemberEnd()); assert(o->value.IsString()); std::string mp = o->value.GetString(); tariff->parking_time_min = (uint32_t)std::stoul(mp); } if (d.HasMember(PARKING_TIME_MAX)) { Value::MemberIterator o = d.FindMember(PARKING_TIME_MAX); assert(o != d.MemberEnd()); assert(o->value.IsString()); std::string mp = o->value.GetString(); if (mp == "unlimited") { tariff->parking_time_max = ~0; } else { tariff->parking_time_max = (uint32_t)std::stoul(mp); } } if (d.HasMember(MAX_PRICE_FOR_24_HOURS)) { Value::MemberIterator o = d.FindMember(MAX_PRICE_FOR_24_HOURS); assert(o != d.MemberEnd()); assert(o->value.IsString()); std::string mp = o->value.GetString(); if (mp == "unlimited") { tariff->max_price_for_24_hours = ~0; } else if (mp == "n/a") { tariff->max_price_for_24_hours = 0; } else { 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(); int const todayWeekDay = today.dayOfWeek(); // qt: 1 (mon) - 7 (sun) if (todayWeekDay > Qt::Monday) { today = today.addDays(Qt::Monday - todayWeekDay); if (!today.isValid()) { qFatal("Setting today failed"); } } assert(today.dayOfWeek() == Qt::Monday); QDate monday = today; // "week1" : { for (int w = 0; w < 3; ++w) { assert(d.HasMember(weekStr[w])); // "Monday": { for (int j = Qt::Monday - 1; j < Qt::Sunday; ++j) { QDateTime startMinute(monday.addDays(w*7+j), QTime( 0, 0)); Value::MemberIterator wObj = d.FindMember(weekStr[w]); assert(wObj != d.MemberEnd()); assert(wObj->value.IsObject()); Value::MemberIterator stepsForDay = wObj->value.FindMember(weekDayStr[j]); assert(stepsForDay != wObj->value.MemberEnd()); assert(stepsForDay->value.IsObject()); // name : time, price, next-tariff-step // "000000" : [ "00:00", "800000", "000001" ], // "000001" : [ "07:00", "350000", "000002" ], // ... // "000014" : [ "20:00", "800000", "000011" ] // }, int k = 0; for (Value::ConstMemberIterator step = stepsForDay->value.MemberBegin(); step != stepsForDay->value.MemberEnd(); ++step) { assert(step->name.IsString()); assert(step->value.IsArray()); QString name(step->name.GetString()); int const week = name.midRef(0, 1).toInt(); int const weekDay = name.midRef(1, 1).toInt(); int const stepIndex = name.midRef(2).toInt(); assert(w == week); assert(j == weekDay); assert(k == stepIndex); uint32_t price_units = QString(step->value[STEP_PRICE].GetString()).toUInt(); QString next = QString(step->value[STEP_NEXT].GetString()); int const nextWeek = next.midRef(0, 1).toInt(); int const nextWeekDay = next.midRef(1, 1).toInt(); int const nextStepIndex = next.midRef(2).toInt(); //qDebug() << startMinute.addSecs(stepIndex*60) // << "(" << week << weekDay << stepIndex << ")" // << "(" << nextWeek << nextWeekDay << nextStepIndex << ")"; tariff->m_tariffSteps[week][weekDay][stepIndex] = TariffStep(startMinute.addSecs(stepIndex*60), price_units, &tariff->m_tariffSteps[nextWeek][nextWeekDay][nextStepIndex]); ++k; } } } free(readBuffer); #if 0 for (int w = 0; w < 3; ++w) { for (int j = Qt::Monday - 1; j < Qt::Sunday; ++j) { for (int k = 0; k < MIN_PER_DAY; ++k) { //if (tariff->m_tariffSteps[w][j][k].next()) { TariffStep const *s = &tariff->m_tariffSteps[w][j][k]; qDebug() << s->dateTime() << s->price() << "next:" << s->next()->dateTime(); //} } } } #endif } fclose(fp); } return tariff; }