X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/49ac42e64c982c16ca4421a50d15f36574ca0c10..38f134e6a96c08fdd7d4ed07ca3550e8434d56e9:/projects/sgconf/tariffs.cpp?ds=sidebyside diff --git a/projects/sgconf/tariffs.cpp b/projects/sgconf/tariffs.cpp index 663536fb..6c5ab3b7 100644 --- a/projects/sgconf/tariffs.cpp +++ b/projects/sgconf/tariffs.cpp @@ -9,13 +9,13 @@ #include "stg/servconf_types.h" #include "stg/tariff_conf.h" #include "stg/common.h" -#include "stg/os_int.h" #include #include #include #include #include +#include #include namespace @@ -28,62 +28,97 @@ if (level == 0) return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' '); } -std::string PeriodToString(TARIFF::PERIOD period) +std::string ChangePolicyToString(STG::Tariff::ChangePolicy changePolicy) +{ +switch (changePolicy) + { + case STG::Tariff::ALLOW: return "allow"; + case STG::Tariff::TO_CHEAP: return "to_cheap"; + case STG::Tariff::TO_EXPENSIVE: return "to_expensive"; + case STG::Tariff::DENY: return "deny"; + } +return "unknown"; +} + +std::string PeriodToString(STG::Tariff::Period period) { switch (period) { - case TARIFF::DAY: + case STG::Tariff::DAY: return "daily"; - case TARIFF::MONTH: + case STG::Tariff::MONTH: return "monthly"; } return "unknown"; } -std::string TraffTypeToString(int traffType) +std::string TraffTypeToString(STG::Tariff::TraffType traffType) { switch (traffType) { - case TRAFF_UP: + case STG::Tariff::TRAFF_UP: return "upload"; - case TRAFF_DOWN: + case STG::Tariff::TRAFF_DOWN: return "download"; - case TRAFF_UP_DOWN: + case STG::Tariff::TRAFF_UP_DOWN: return "upload + download"; - case TRAFF_MAX: + case STG::Tariff::TRAFF_MAX: return "max(upload, download)"; } return "unknown"; } -void ConvPeriod(const std::string & value, RESETABLE & res) +void ConvPeriod(const std::string & value, STG::Optional & res) { std::string lowered = ToLower(value); if (lowered == "daily") - res = TARIFF::DAY; + res = STG::Tariff::DAY; else if (lowered == "monthly") - res = TARIFF::MONTH; + res = STG::Tariff::MONTH; else throw SGCONF::ACTION::ERROR("Period should be 'daily' or 'monthly'. Got: '" + value + "'"); } -void ConvTraffType(const std::string & value, RESETABLE & res) +void ConvChangePolicy(const std::string & value, STG::Optional & res) +{ +std::string lowered = ToLower(value); +if (lowered == "allow") + res = STG::Tariff::ALLOW; +else if (lowered == "to_cheap") + res = STG::Tariff::TO_CHEAP; +else if (lowered == "to_expensive") + res = STG::Tariff::TO_EXPENSIVE; +else if (lowered == "deny") + res = STG::Tariff::DENY; +else + throw SGCONF::ACTION::ERROR("Change policy should be 'allow', 'to_cheap', 'to_expensive' or 'deny'. Got: '" + value + "'"); +} + +void ConvChangePolicyTimeout(const std::string & value, STG::Optional & res) +{ +struct tm brokenTime; +if (stg_strptime(value.c_str(), "%Y-%m-%d %H:%M:%S", &brokenTime) == NULL) + throw SGCONF::ACTION::ERROR("Credit expiration should be in format 'YYYY-MM-DD HH:MM:SS'. Got: '" + value + "'"); +res = stg_timegm(&brokenTime); +} + +void ConvTraffType(const std::string & value, STG::Optional & res) { std::string lowered = ToLower(value); lowered.erase(std::remove(lowered.begin(), lowered.end(), ' '), lowered.end()); if (lowered == "upload") - res = TRAFF_UP; + res = STG::Tariff::TRAFF_UP; else if (lowered == "download") - res = TRAFF_DOWN; + res = STG::Tariff::TRAFF_DOWN; else if (lowered == "upload+download") - res = TRAFF_UP_DOWN; + res = STG::Tariff::TRAFF_UP_DOWN; else if (lowered.substr(0, 3) == "max") - res = TRAFF_MAX; + res = STG::Tariff::TRAFF_MAX; else throw SGCONF::ACTION::ERROR("Traff type should be 'upload', 'download', 'upload + download' or 'max'. Got: '" + value + "'"); } -DIRPRICE_DATA_RES ConvTimeSpan(const std::string & value) +STG::DirPriceDataOpt ConvTimeSpan(const std::string & value) { size_t dashPos = value.find_first_of('-'); if (dashPos == std::string::npos) @@ -94,7 +129,7 @@ if (fromColon == std::string::npos || fromColon > dashPos) size_t toColon = value.find_first_of(':', dashPos); if (toColon == std::string::npos) throw SGCONF::ACTION::ERROR("Time span should be in format 'hh:mm-hh:mm'. Got: '" + value + "'"); -DIRPRICE_DATA_RES res; +STG::DirPriceDataOpt res; res.hDay = FromString(value.substr(0, fromColon)); if (res.hDay.data() < 0 || res.hDay.data() > 23) throw SGCONF::ACTION::ERROR("Invalid 'from' hours. Got: '" + value.substr(0, fromColon) + "'"); @@ -110,28 +145,28 @@ if (res.mNight.data() < 0 || res.mNight.data() > 59) return res; } -void Splice(std::vector & lhs, const std::vector & rhs) +void splice(std::vector & lhs, const std::vector & rhs) { for (size_t i = 0; i < lhs.size() && i < rhs.size(); ++i) - lhs[i].Splice(rhs[i]); + lhs[i].splice(rhs[i]); } -void ConvTimes(std::string value, std::vector & res) +void ConvTimes(std::string value, std::vector & res) { value.erase(std::remove(value.begin(), value.end(), ' '), value.end()); -Splice(res, Split >(value, ',', ConvTimeSpan)); +splice(res, Split >(value, ',', ConvTimeSpan)); } -struct ConvPrice : public std::unary_function +struct ConvPrice : public std::unary_function { - typedef RESETABLE (DIRPRICE_DATA_RES::* MemPtr); + typedef STG::Optional (STG::DirPriceDataOpt::* MemPtr); ConvPrice(MemPtr before, MemPtr after) : m_before(before), m_after(after) {} - DIRPRICE_DATA_RES operator()(const std::string & value) + STG::DirPriceDataOpt operator()(const std::string & value) { - DIRPRICE_DATA_RES res; + STG::DirPriceDataOpt res; size_t slashPos = value.find_first_of('/'); if (slashPos == std::string::npos) { @@ -159,21 +194,21 @@ struct ConvPrice : public std::unary_function MemPtr m_after; }; -void ConvDayPrices(std::string value, std::vector & res) +void ConvDayPrices(std::string value, std::vector & res) { value.erase(std::remove(value.begin(), value.end(), ' '), value.end()); -Splice(res, Split >(value, ',', ConvPrice(&DIRPRICE_DATA_RES::priceDayA, &DIRPRICE_DATA_RES::priceDayB))); +splice(res, Split >(value, ',', ConvPrice(&STG::DirPriceDataOpt::priceDayA, &STG::DirPriceDataOpt::priceDayB))); } -void ConvNightPrices(std::string value, std::vector & res) +void ConvNightPrices(std::string value, std::vector & res) { value.erase(std::remove(value.begin(), value.end(), ' '), value.end()); -Splice(res, Split >(value, ',', ConvPrice(&DIRPRICE_DATA_RES::priceNightA, &DIRPRICE_DATA_RES::priceNightB))); +splice(res, Split >(value, ',', ConvPrice(&STG::DirPriceDataOpt::priceNightA, &STG::DirPriceDataOpt::priceNightB))); } -DIRPRICE_DATA_RES ConvThreshold(std::string value) +STG::DirPriceDataOpt ConvThreshold(std::string value) { -DIRPRICE_DATA_RES res; + STG::DirPriceDataOpt res; double threshold = 0; if (str2x(value, threshold) < 0) throw SGCONF::ACTION::ERROR("Threshold should be a floating point value. Got: '" + value + "'"); @@ -181,10 +216,10 @@ res.threshold = threshold; return res; } -void ConvThresholds(std::string value, std::vector & res) +void ConvThresholds(std::string value, std::vector & res) { value.erase(std::remove(value.begin(), value.end(), ' '), value.end()); -Splice(res, Split >(value, ',', ConvThreshold)); +splice(res, Split >(value, ',', ConvThreshold)); } std::string TimeToString(int h, int m) @@ -195,7 +230,7 @@ stream << (h < 10 ? "0" : "") << h << ":" return stream.str(); } -void PrintDirPriceData(size_t dir, const DIRPRICE_DATA & data, size_t level) +void PrintDirPriceData(size_t dir, const STG::DirPriceData & data, size_t level) { std::string night = TimeToString(data.hNight, data.mNight); std::string day = TimeToString(data.hDay, data.mDay); @@ -207,17 +242,19 @@ std::cout << Indent(level, true) << "dir: " << dir << "\n" << Indent(level) << "discount: " << (data.noDiscount ? "no" : "yes") << "\n"; // Attention! } -void PrintTariffConf(const TARIFF_CONF & conf, size_t level) +void PrintTariffConf(const STG::TariffConf & conf, size_t level) { std::cout << Indent(level, true) << "name: " << conf.name << "\n" << Indent(level) << "fee: " << conf.fee << "\n" << Indent(level) << "free mb: " << conf.free << "\n" << Indent(level) << "passive cost: " << conf.passiveCost << "\n" << Indent(level) << "traff type: " << TraffTypeToString(conf.traffType) << "\n" - << Indent(level) << "period: " << PeriodToString(conf.period) << "\n"; + << Indent(level) << "period: " << PeriodToString(conf.period) << "\n" + << Indent(level) << "change policy: " << ChangePolicyToString(conf.changePolicy) << "\n" + << Indent(level) << "change policy timeout: " << formatTime(conf.changePolicyTimeout) << "\n"; } -void PrintTariff(const STG::GET_TARIFF::INFO & info, size_t level = 0) +void PrintTariff(const STG::GetTariff::Info & info, size_t level = 0) { PrintTariffConf(info.tariffConf, level); std::cout << Indent(level) << "dir prices:\n"; @@ -233,6 +270,8 @@ params.push_back(SGCONF::API_ACTION::PARAM("free", "", "\tprepaid traff params.push_back(SGCONF::API_ACTION::PARAM("passive-cost", "", "\tpassive cost")); params.push_back(SGCONF::API_ACTION::PARAM("traff-type", "", "\ttraffic type (up, down, up+down, max)")); params.push_back(SGCONF::API_ACTION::PARAM("period", "", "\ttarification period (daily, monthly)")); +params.push_back(SGCONF::API_ACTION::PARAM("change-policy", "", "tariff change policy (allow, to_cheap, to_expensive, deny)")); +params.push_back(SGCONF::API_ACTION::PARAM("change-policy-timeout", "", "tariff change policy timeout")); params.push_back(SGCONF::API_ACTION::PARAM("times", "", "coma-separated day time-spans for each direction")); params.push_back(SGCONF::API_ACTION::PARAM("day-prices", "", "coma-separated day prices for each direction")); params.push_back(SGCONF::API_ACTION::PARAM("night-prices", "", "coma-separated night prices for each direction")); @@ -254,7 +293,7 @@ std::cout << "Success.\n"; void GetTariffsCallback(bool result, const std::string & reason, - const std::vector & info, + const std::vector & info, void * /*data*/) { if (!result) @@ -269,7 +308,7 @@ for (size_t i = 0; i < info.size(); ++i) void GetTariffCallback(bool result, const std::string & reason, - const std::vector & info, + const std::vector & info, void * data) { assert(data != NULL && "Expecting pointer to std::string with the tariff's name."); @@ -288,7 +327,7 @@ bool GetTariffsFunction(const SGCONF::CONFIG & config, const std::string & /*arg*/, const std::map & /*options*/) { -STG::SERVCONF proto(config.server.data(), +STG::ServConf proto(config.server.data(), config.port.data(), config.localAddress.data(), config.localPort.data(), @@ -301,7 +340,7 @@ bool GetTariffFunction(const SGCONF::CONFIG & config, const std::string & arg, const std::map & /*options*/) { -STG::SERVCONF proto(config.server.data(), +STG::ServConf proto(config.server.data(), config.port.data(), config.localAddress.data(), config.localPort.data(), @@ -317,7 +356,7 @@ bool DelTariffFunction(const SGCONF::CONFIG & config, const std::string & arg, const std::map & /*options*/) { -STG::SERVCONF proto(config.server.data(), +STG::ServConf proto(config.server.data(), config.port.data(), config.localAddress.data(), config.localPort.data(), @@ -330,13 +369,15 @@ bool AddTariffFunction(const SGCONF::CONFIG & config, const std::string & arg, const std::map & options) { -TARIFF_DATA_RES conf; +STG::TariffDataOpt conf; conf.tariffConf.name = arg; SGCONF::MaybeSet(options, "fee", conf.tariffConf.fee); SGCONF::MaybeSet(options, "free", conf.tariffConf.free); SGCONF::MaybeSet(options, "passive-cost", conf.tariffConf.passiveCost); SGCONF::MaybeSet(options, "traff-type", conf.tariffConf.traffType, ConvTraffType); SGCONF::MaybeSet(options, "period", conf.tariffConf.period, ConvPeriod); +SGCONF::MaybeSet(options, "change-policy", conf.tariffConf.changePolicy, ConvChangePolicy); +SGCONF::MaybeSet(options, "change-policy-timeout", conf.tariffConf.changePolicyTimeout, ConvChangePolicyTimeout); SGCONF::MaybeSet(options, "times", conf.dirPrice, ConvTimes); SGCONF::MaybeSet(options, "day-prices", conf.dirPrice, ConvDayPrices); SGCONF::MaybeSet(options, "night-prices", conf.dirPrice, ConvNightPrices); @@ -350,7 +391,7 @@ for (size_t i = 0; i < conf.dirPrice.size(); ++i) conf.dirPrice[i].singlePrice = conf.dirPrice[i].priceDayA.data() == conf.dirPrice[i].priceNightA.data() && conf.dirPrice[i].priceDayB.data() == conf.dirPrice[i].priceNightB.data(); } -STG::SERVCONF proto(config.server.data(), +STG::ServConf proto(config.server.data(), config.port.data(), config.localAddress.data(), config.localPort.data(), @@ -363,13 +404,15 @@ bool ChgTariffFunction(const SGCONF::CONFIG & config, const std::string & arg, const std::map & options) { -TARIFF_DATA_RES conf; +STG::TariffDataOpt conf; conf.tariffConf.name = arg; SGCONF::MaybeSet(options, "fee", conf.tariffConf.fee); SGCONF::MaybeSet(options, "free", conf.tariffConf.free); SGCONF::MaybeSet(options, "passive-cost", conf.tariffConf.passiveCost); SGCONF::MaybeSet(options, "traff-type", conf.tariffConf.traffType, ConvTraffType); SGCONF::MaybeSet(options, "period", conf.tariffConf.period, ConvPeriod); +SGCONF::MaybeSet(options, "change-policy", conf.tariffConf.changePolicy, ConvChangePolicy); +SGCONF::MaybeSet(options, "change-policy-timeout", conf.tariffConf.changePolicyTimeout, ConvChangePolicyTimeout); SGCONF::MaybeSet(options, "times", conf.dirPrice, ConvTimes); SGCONF::MaybeSet(options, "day-prices", conf.dirPrice, ConvDayPrices); SGCONF::MaybeSet(options, "night-prices", conf.dirPrice, ConvNightPrices); @@ -383,7 +426,7 @@ for (size_t i = 0; i < conf.dirPrice.size(); ++i) conf.dirPrice[i].singlePrice = conf.dirPrice[i].priceDayA.data() == conf.dirPrice[i].priceNightA.data() && conf.dirPrice[i].priceDayB.data() == conf.dirPrice[i].priceNightB.data(); } -STG::SERVCONF proto(config.server.data(), +STG::ServConf proto(config.server.data(), config.port.data(), config.localAddress.data(), config.localPort.data(),