From: Elena Mamontova Date: Fri, 21 Oct 2016 11:17:02 +0000 (+0300) Subject: Merge remote-tracking branch 'origin/master' into ticket X-Git-Url: https://git.stg.codes/stg.git/commitdiff_plain/d1ddf1df6b8987cc1be7dc96608e22998c3e9cb6?hp=0d5bff91a33dc190351adc0010f8218c81423799 Merge remote-tracking branch 'origin/master' into ticket --- diff --git a/include/stg/tariff.h b/include/stg/tariff.h index 5d01cba0..879c4ecc 100644 --- a/include/stg/tariff.h +++ b/include/stg/tariff.h @@ -32,10 +32,15 @@ struct TARIFF_DATA; class TARIFF { public: + enum CHANGE_POLICY { ALLOW = 0, TO_CHEAP, TO_EXPENSIVE, DENY }; + enum PERIOD { DAY = 0, MONTH }; enum TRAFF_TYPE { TRAFF_UP = 0, TRAFF_DOWN, TRAFF_UP_DOWN, TRAFF_MAX }; + static std::string ChangePolicyToString(CHANGE_POLICY changePolicy); + static CHANGE_POLICY StringToChangePolicy(const std::string& value); + static std::string PeriodToString(PERIOD period); static PERIOD StringToPeriod(const std::string& value); @@ -53,6 +58,7 @@ public: virtual double GetFee() const = 0; virtual double GetFree() const = 0; virtual PERIOD GetPeriod() const = 0; + virtual CHANGE_POLICY GetChangePolicy() const = 0; virtual const std::string & GetName() const = 0; virtual void SetName(const std::string & name) = 0; @@ -63,6 +69,31 @@ public: virtual const TARIFF_DATA & GetTariffData() const = 0; }; +inline +std::string TARIFF::ChangePolicyToString(TARIFF::CHANGE_POLICY changePolicy) +{ +switch (changePolicy) + { + case ALLOW: return "allow"; + case TO_CHEAP: return "to_cheap"; + case TO_EXPENSIVE: return "to_expensive"; + case DENY: return "deny"; + } +return "allow"; // Classic behaviour. +} + +inline +TARIFF::CHANGE_POLICY TARIFF::StringToChangePolicy(const std::string& value) +{ +if (strcasecmp(value.c_str(), "to_cheap") == 0) + return TO_CHEAP; +if (strcasecmp(value.c_str(), "to_expensive") == 0) + return TO_EXPENSIVE; +if (strcasecmp(value.c_str(), "deny") == 0) + return DENY; +return ALLOW; // Classic behaviour. +} + inline std::string TARIFF::PeriodToString(TARIFF::PERIOD period) { diff --git a/include/stg/tariff_conf.h b/include/stg/tariff_conf.h index fe94b6e5..d8684bd9 100644 --- a/include/stg/tariff_conf.h +++ b/include/stg/tariff_conf.h @@ -148,6 +148,7 @@ struct TARIFF_CONF double passiveCost; std::string name; TARIFF::PERIOD period; + TARIFF::CHANGE_POLICY changePolicy; TARIFF_CONF() : fee(0), @@ -155,7 +156,8 @@ struct TARIFF_CONF traffType(TARIFF::TRAFF_UP_DOWN), passiveCost(0), name(), - period(TARIFF::MONTH) + period(TARIFF::MONTH), + changePolicy(TARIFF::ALLOW) {} TARIFF_CONF(const std::string & n) @@ -164,7 +166,8 @@ struct TARIFF_CONF traffType(TARIFF::TRAFF_UP_DOWN), passiveCost(0), name(n), - period(TARIFF::MONTH) + period(TARIFF::MONTH), + changePolicy(TARIFF::ALLOW) {} }; //----------------------------------------------------------------------------- @@ -176,7 +179,8 @@ struct TARIFF_CONF_RES traffType(), passiveCost(), name(), - period() + period(), + changePolicy() {} TARIFF_CONF_RES & operator=(const TARIFF_CONF & tc) @@ -187,6 +191,7 @@ struct TARIFF_CONF_RES passiveCost = tc.passiveCost; name = tc.name; period = tc.period; + changePolicy = tc.changePolicy; return *this; } @@ -199,6 +204,7 @@ struct TARIFF_CONF_RES passiveCost.maybeSet(tc.passiveCost); traffType.maybeSet(tc.traffType); period.maybeSet(tc.period); + changePolicy.maybeSet(tc.changePolicy); return tc; } @@ -208,6 +214,7 @@ struct TARIFF_CONF_RES RESETABLE passiveCost; RESETABLE name; RESETABLE period; + RESETABLE changePolicy; }; //----------------------------------------------------------------------------- struct TARIFF_DATA diff --git a/projects/sgconf/tariffs.cpp b/projects/sgconf/tariffs.cpp index 3d63d2a8..c384df1f 100644 --- a/projects/sgconf/tariffs.cpp +++ b/projects/sgconf/tariffs.cpp @@ -28,6 +28,18 @@ if (level == 0) return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' '); } +std::string ChangePolicyToString(TARIFF::CHANGE_POLICY changePolicy) +{ +switch (changePolicy) + { + case TARIFF::ALLOW: return "allow"; + case TARIFF::TO_CHEAP: return "to_cheap"; + case TARIFF::TO_EXPENSIVE: return "to_expensive"; + case TARIFF::DENY: return "deny"; + } +return "unknown"; +} + std::string PeriodToString(TARIFF::PERIOD period) { switch (period) @@ -67,6 +79,21 @@ else throw SGCONF::ACTION::ERROR("Period should be 'daily' or 'monthly'. Got: '" + value + "'"); } +void ConvChangePolicy(const std::string & value, RESETABLE & res) +{ +std::string lowered = ToLower(value); +if (lowered == "allow") + res = TARIFF::ALLOW; +else if (lowered == "to_cheap") + res = TARIFF::TO_CHEAP; +else if (lowered == "to_expensive") + res = TARIFF::TO_EXPENSIVE; +else if (lowered == "deny") + res = TARIFF::DENY; +else + throw SGCONF::ACTION::ERROR("Change policy should be 'allow', 'to_cheap', 'to_expensive' or 'deny'. Got: '" + value + "'"); +} + void ConvTraffType(const std::string & value, RESETABLE & res) { std::string lowered = ToLower(value); @@ -214,7 +241,8 @@ std::cout << Indent(level, true) << "name: " << conf.name << "\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"; } void PrintTariff(const STG::GET_TARIFF::INFO & info, size_t level = 0) @@ -233,6 +261,7 @@ 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("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")); @@ -337,6 +366,7 @@ 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, "times", conf.dirPrice, ConvTimes); SGCONF::MaybeSet(options, "day-prices", conf.dirPrice, ConvDayPrices); SGCONF::MaybeSet(options, "night-prices", conf.dirPrice, ConvNightPrices); @@ -370,6 +400,7 @@ 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, "times", conf.dirPrice, ConvTimes); SGCONF::MaybeSet(options, "day-prices", conf.dirPrice, ConvDayPrices); SGCONF::MaybeSet(options, "night-prices", conf.dirPrice, ConvNightPrices); diff --git a/projects/stargazer/inst/var/02-alter-03.postgresql.sql b/projects/stargazer/inst/var/02-alter-03.postgresql.sql new file mode 100644 index 00000000..a686aa68 --- /dev/null +++ b/projects/stargazer/inst/var/02-alter-03.postgresql.sql @@ -0,0 +1,13 @@ +/* + * DB migration from v02 to v03 (postgres) + */ +BEGIN; + +CREATE DOMAIN DM_TARIFF_CHANGE_POLICY AS TEXT NOT NULL + CONSTRAINT valid_value CHECK (VALUE IN ('allow', 'to_cheap', 'to_expensive', 'deny')); + +ALTER TABLE tb_tariffs ADD change_policy DM_TARIFF_CHANGE_POLICY DEFAULT 'allow'; + +UPDATE tb_info SET version = 8; + +COMMIT; diff --git a/projects/stargazer/inst/var/02-alter-03.sql b/projects/stargazer/inst/var/02-alter-03.sql new file mode 100644 index 00000000..a0199173 --- /dev/null +++ b/projects/stargazer/inst/var/02-alter-03.sql @@ -0,0 +1,10 @@ +/* + * DB migration from v02 to v03 (firebird) + */ + +CREATE DOMAIN DM_TARIFF_CHANGE_POLICY AS VARCHAR(32) NOT NULL + CHECK (VALUE IN ('allow', 'to_cheap', 'to_expensive', 'deny')); + +ALTER TABLE tb_tariffs ADD change_policy DM_TARIFF_CHANGE_POLICY DEFAULT 'allow'; + +UPDATE tb_info SET version = 2; diff --git a/projects/stargazer/plugins/configuration/rpcconfig/tariff_helper.cpp b/projects/stargazer/plugins/configuration/rpcconfig/tariff_helper.cpp index 26b4e993..c96b7d31 100644 --- a/projects/stargazer/plugins/configuration/rpcconfig/tariff_helper.cpp +++ b/projects/stargazer/plugins/configuration/rpcconfig/tariff_helper.cpp @@ -13,6 +13,7 @@ structVal["freemb"] = xmlrpc_c::value_double(data.tariffConf.free); structVal["passivecost"] = xmlrpc_c::value_double(data.tariffConf.passiveCost); structVal["traffType"] = xmlrpc_c::value_int(data.tariffConf.traffType); structVal["period"] = xmlrpc_c::value_string(TARIFF::PeriodToString(data.tariffConf.period)); +structVal["changePolicy"] = xmlrpc_c::value_string(TARIFF::ChangePolicyToString(data.tariffConf.changePolicy)); std::vector prices(DIR_NUM); @@ -71,6 +72,11 @@ if ((it = structVal.find("period")) != structVal.end()) data.tariffConf.period = TARIFF::StringToPeriod(xmlrpc_c::value_string(it->second)); } +if ((it = structVal.find("changePolicy")) != structVal.end()) + { + data.tariffConf.changePolicy = TARIFF::StringToChangePolicy(xmlrpc_c::value_string(it->second)); + } + if ((it = structVal.find("dirprices")) != structVal.end()) { std::vector prices( diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_tariffs.cpp b/projects/stargazer/plugins/configuration/sgconfig/parser_tariffs.cpp index 0607db6f..b33b1305 100644 --- a/projects/stargazer/plugins/configuration/sgconfig/parser_tariffs.cpp +++ b/projects/stargazer/plugins/configuration/sgconfig/parser_tariffs.cpp @@ -114,6 +114,7 @@ void GET_TARIFFS::CreateAnswer() "tariffConf.free) + "\"/>" + "tariffConf.traffType) + "\"/>" + "tariffConf.period) + "\"/>" + + "tariffConf.changePolicy) + "\"/>" + ""; } @@ -288,6 +289,12 @@ int CHG_TARIFF::Start(void *, const char * el, const char ** attr) td.tariffConf.period = TARIFF::StringToPeriod(attr[1]); return 0; } + + if (strcasecmp(el, "ChangePolicy") == 0) + { + td.tariffConf.changePolicy = TARIFF::StringToChangePolicy(attr[1]); + return 0; + } } return -1; } diff --git a/projects/stargazer/plugins/store/files/file_store.cpp b/projects/stargazer/plugins/store/files/file_store.cpp index 96add48f..d4b29ad9 100644 --- a/projects/stargazer/plugins/store/files/file_store.cpp +++ b/projects/stargazer/plugins/store/files/file_store.cpp @@ -1518,6 +1518,11 @@ if (conf.ReadString("Period", &str, "month") < 0) td->tariffConf.period = TARIFF::MONTH; else td->tariffConf.period = TARIFF::StringToPeriod(str); + +if (conf.ReadString("ChangePolicy", &str, "allow") < 0) + td->tariffConf.changePolicy = TARIFF::ALLOW; +else + td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(str); return 0; } //----------------------------------------------------------------------------- @@ -1579,6 +1584,7 @@ std::string fileName = storeSettings.GetTariffsDir() + "/" + tariffName + ".tf"; cf.WriteDouble("Free", td.tariffConf.free); cf.WriteString("TraffType", TARIFF::TraffTypeToString(td.tariffConf.traffType)); cf.WriteString("Period", TARIFF::PeriodToString(td.tariffConf.period)); + cf.WriteString("ChangePolicy", TARIFF::ChangePolicyToString(td.tariffConf.changePolicy)); } return 0; diff --git a/projects/stargazer/plugins/store/firebird/firebird_store_tariffs.cpp b/projects/stargazer/plugins/store/firebird/firebird_store_tariffs.cpp index 138a9ed9..cdee5398 100644 --- a/projects/stargazer/plugins/store/firebird/firebird_store_tariffs.cpp +++ b/projects/stargazer/plugins/store/firebird/firebird_store_tariffs.cpp @@ -150,7 +150,7 @@ try int32_t id; st->Get(1, id); st->Close(); - if (schemaVersion > 0) + if (schemaVersion == 1) { st->Prepare("update tb_tariffs set \ fee = ?, \ @@ -166,6 +166,24 @@ try st->Set(5, TARIFF::PeriodToString(td.tariffConf.period)); st->Set(6, id); } + else if (schemaVersion > 1) + { + st->Prepare("update tb_tariffs set \ + fee = ?, \ + free = ?, \ + passive_cost = ?, \ + traff_type = ?, \ + period = ?, \ + change_policy = ? \ + where pk_tariff = ?"); + st->Set(1, td.tariffConf.fee); + st->Set(2, td.tariffConf.free); + st->Set(3, td.tariffConf.passiveCost); + st->Set(4, td.tariffConf.traffType); + st->Set(5, TARIFF::PeriodToString(td.tariffConf.period)); + st->Set(6, TARIFF::ChangePolicyToString(td.tariffConf.changePolicy)); + st->Set(7, id); + } else { st->Prepare("update tb_tariffs set \ @@ -285,6 +303,8 @@ try td->tariffConf.traffType = TARIFF::IntToTraffType(Get(st, 6)); if (schemaVersion > 0) td->tariffConf.period = TARIFF::StringToPeriod(Get(st, 7)); + if (schemaVersion > 1) + td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(Get(st, 8)); st->Close(); st->Prepare("select * from tb_tariffs_params where fk_tariff = ?"); st->Set(1, id); diff --git a/projects/stargazer/plugins/store/mysql/mysql_store.cpp b/projects/stargazer/plugins/store/mysql/mysql_store.cpp index 6b16a99d..f3539dd6 100644 --- a/projects/stargazer/plugins/store/mysql/mysql_store.cpp +++ b/projects/stargazer/plugins/store/mysql/mysql_store.cpp @@ -368,7 +368,8 @@ if(!IsTablePresent("tariffs",sock)) res += "PassiveCost DOUBLE DEFAULT 0.0, Fee DOUBLE DEFAULT 0.0," "Free DOUBLE DEFAULT 0.0, TraffType VARCHAR(10) DEFAULT ''," - "period VARCHAR(32) NOT NULL DEFAULT 'month')"; + "period VARCHAR(32) NOT NULL DEFAULT 'month'," + "change_policy VARCHAR(32) NOT NULL DEFAULT 'allow')"; if(MysqlQuery(res.c_str(),sock)) { @@ -422,7 +423,8 @@ if(!IsTablePresent("tariffs",sock)) res += "PassiveCost=0.0, Fee=10.0, Free=0,"\ "SinglePrice0=1, SinglePrice1=1,PriceDayA1=0.75,PriceDayB1=0.75,"\ - "PriceNightA0=1.0,PriceNightB0=1.0,TraffType='up+down',period='month'"; + "PriceNightA0=1.0,PriceNightB0=1.0,TraffType='up+down',period='month',"\ + "change_policy='allow'"; if(MysqlQuery(res.c_str(),sock)) { @@ -441,7 +443,7 @@ if(!IsTablePresent("tariffs",sock)) mysql_close(sock); return -1; } - schemaVersion = 1; + schemaVersion = 2; } //users----------------------------------------------------------------------- @@ -599,6 +601,26 @@ if (schemaVersion < 1) schemaVersion = 1; logger("MYSQL_STORE: Updated DB schema to version %d", schemaVersion); } + +if (schemaVersion < 2) + { + if (MysqlQuery("ALTER TABLE tariffs ADD change_policy VARCHAR(32) NOT NULL DEFAULT 'allow'", sock)) + { + errorStr = "Couldn't update tariffs table to version 2. With error:\n"; + errorStr += mysql_error(sock); + mysql_close(sock); + return -1; + } + if (MysqlQuery("UPDATE info SET version = 2", sock)) + { + errorStr = "Couldn't update DB schema version to 2. With error:\n"; + errorStr += mysql_error(sock); + mysql_close(sock); + return -1; + } + schemaVersion = 2; + logger("MYSQL_STORE: Updated DB schema to version %d", schemaVersion); + } return 0; } //----------------------------------------------------------------------------- @@ -1639,6 +1661,26 @@ else td->tariffConf.period = TARIFF::MONTH; } +if (schemaVersion > 1) +{ + str = row[6+8*DIR_NUM]; + param = "ChangePolicy"; + + if (str.length() == 0) + { + mysql_free_result(res); + errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param; + mysql_close(sock); + return -1; + } + + td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(str); + } +else + { + td->tariffConf.changePolicy = TARIFF::ALLOW; + } + mysql_free_result(res); mysql_close(sock); return 0; @@ -1706,6 +1748,9 @@ res += " TraffType='" + TARIFF::TraffTypeToString(td.tariffConf.traffType) + "'" if (schemaVersion > 0) res += ", Period='" + TARIFF::PeriodToString(td.tariffConf.period) + "'"; +if (schemaVersion > 1) + res += ", change_policy='" + TARIFF::ChangePolicyToString(td.tariffConf.changePolicy) + "'"; + strprintf(¶m, " WHERE name='%s' LIMIT 1", tariffName.c_str()); res += param; diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp b/projects/stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp index 045411b1..c509c39c 100644 --- a/projects/stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp +++ b/projects/stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp @@ -317,6 +317,9 @@ int32_t id; if (version > 6) query << ", period = '" << TARIFF::PeriodToString(td.tariffConf.period) << "'"; + if (version > 7) + query << ", change_policy = '" << TARIFF::ChangePolicyToString(td.tariffConf.changePolicy) << "'"; + query << " WHERE pk_tariff = " << id; result = PQexec(connection, query.str().c_str()); @@ -455,6 +458,9 @@ query << "SELECT pk_tariff, \ if (version > 6) query << ", period"; +if (version > 7) + query << ", change_policy"; + query << " FROM tb_tariffs WHERE name = '" << ename << "'"; result = PQexec(connection, query.str().c_str()); @@ -505,6 +511,9 @@ int id; if (version > 6) td->tariffConf.period = TARIFF::StringToPeriod(PQgetvalue(result, 0, 5)); +if (version > 7) + td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(PQgetvalue(result, 0, 6)); + PQclear(result); query.str(""); diff --git a/projects/stargazer/tariff_impl.h b/projects/stargazer/tariff_impl.h index f2f84d26..324be186 100644 --- a/projects/stargazer/tariff_impl.h +++ b/projects/stargazer/tariff_impl.h @@ -72,6 +72,7 @@ public: double GetFee() const { return tariffData.tariffConf.fee; } double GetFree() const { return tariffData.tariffConf.free; } PERIOD GetPeriod() const { return tariffData.tariffConf.period; } + CHANGE_POLICY GetChangePolicy() const { return tariffData.tariffConf.changePolicy; } void Print() const; diff --git a/stglibs/srvconf.lib/parsers/chg_tariff.cpp b/stglibs/srvconf.lib/parsers/chg_tariff.cpp index 158e6f89..bdc7f42b 100644 --- a/stglibs/srvconf.lib/parsers/chg_tariff.cpp +++ b/stglibs/srvconf.lib/parsers/chg_tariff.cpp @@ -69,6 +69,15 @@ if (!data.tariffConf.period.empty()) case TARIFF::MONTH: stream << ""; break; } +if (!data.tariffConf.changePolicy.empty()) + switch (data.tariffConf.changePolicy.data()) + { + case TARIFF::ALLOW: stream << ""; break; + case TARIFF::TO_CHEAP: stream << ""; break; + case TARIFF::TO_EXPENSIVE: stream << ""; break; + case TARIFF::DENY: stream << ""; break; + } + for (size_t i = 0; i < DIR_NUM; ++i) if (!data.dirPrice[i].hDay.empty() && !data.dirPrice[i].mDay.empty() && diff --git a/stglibs/srvconf.lib/parsers/get_tariff.cpp b/stglibs/srvconf.lib/parsers/get_tariff.cpp index 0804b269..4844fd6c 100644 --- a/stglibs/srvconf.lib/parsers/get_tariff.cpp +++ b/stglibs/srvconf.lib/parsers/get_tariff.cpp @@ -97,6 +97,25 @@ else return true; } +template +bool GetChangePolicy(const char ** attr, T & value, const std::string & attrName) +{ +if (!CheckValue(attr, attrName)) + return false; +std::string type(attr[1]); +if (type == "allow") + value = TARIFF::ALLOW; +else if (type == "to_cheap") + value = TARIFF::TO_CHEAP; +else if (type == "to_expensive") + value = TARIFF::TO_EXPENSIVE; +else if (type == "deny") + value = TARIFF::DENY; +else + return false; +return true; +} + template bool GetSlashedValue(const char ** attr, A & array, T A::value_type:: * field) { @@ -131,6 +150,7 @@ GET_TARIFF::PARSER::PARSER(CALLBACK f, void * d, const std::string & e) AddParser(propertyParsers, "free", info.tariffConf.free); AddParser(propertyParsers, "traffType", info.tariffConf.traffType, GetTraffType); AddParser(propertyParsers, "period", info.tariffConf.period, GetPeriod); + AddParser(propertyParsers, "changePolicy", info.tariffConf.changePolicy, GetChangePolicy); for (size_t i = 0; i < DIR_NUM; ++i) AddParser(propertyParsers, "time" + unsigned2str(i), info.dirPrice[i], GetTimeSpan); AddAOSParser(propertyParsers, "priceDayA", info.dirPrice, &DIRPRICE_DATA::priceDayA, GetSlashedValue);