28 #define DBG_NG LOG_STREAM(debug, log_engine)
29 #define ERR_NG LOG_STREAM(err, log_engine)
37 for(stats_t::str_int_map::const_iterator
i = m.begin();
i != m.end(); ++
i) {
38 std::string
n = std::to_string(
i->second);
40 res[
n] = res[
n].str() +
"," +
i->first;
51 using reverse_map = std::multimap<int, std::string>;
53 std::transform(m.begin(), m.end(), std::inserter(rev, rev.begin()),
54 [](
const stats_t::str_int_map::value_type
p) { return std::pair(p.second, p.first); });
55 reverse_map::const_iterator
i = rev.begin(), j;
56 while(
i != rev.end()) {
57 j = rev.upper_bound(
i->first);
58 std::vector<std::string> vals;
59 std::transform(
i, j, std::back_inserter(vals), [](
const reverse_map::value_type&
p) {
return p.second; });
71 m[val] = std::stoi(
i.first);
73 }
catch(
const std::invalid_argument&) {
74 ERR_NG <<
"Invalid statistics entry; skipping";
84 for(stats_t::battle_result_map::const_iterator
i = m.begin();
i != m.end(); ++
i) {
87 new_cfg[
"_num"] =
i->first;
95 for(stats_t::battle_result_map::const_iterator
i = m.begin();
i != m.end(); ++
i) {
108 int key =
item[
"_num"];
109 item.remove_attribute(
"_num");
119 for(
const auto&
i : m) {
120 res.
add_child(
"hitrate_map_entry",
config{
"cth",
i.first,
"stats",
i.second.write()});
135 for(
const auto&
i : merged) {
138 for(
const auto& j : frequency_map) {
139 const std::string& res = j.first;
140 const int occurrences = j.second;
141 unsigned int misses = std::count(res.begin(), res.end(),
'0');
142 unsigned int hits = std::count(res.begin(), res.end(),
'1');
143 if(misses + hits == 0) {
146 misses *= occurrences;
148 m[cth].strikes += misses + hits;
167 for(stats_t::str_int_map::const_iterator
i =
b.begin();
i !=
b.end(); ++
i) {
168 a[
i->first] +=
i->second;
174 for(stats_t::battle_result_map::const_iterator
i =
b.begin();
i !=
b.end(); ++
i) {
181 for(
const auto&
i :
b) {
182 a[
i.first].hits +=
i.second.hits;
183 a[
i.first].strikes +=
i.second.strikes;
196 , attacks_inflicted()
197 , defends_inflicted()
200 , damage_inflicted(0)
202 , turn_damage_inflicted(0)
203 , turn_damage_taken(0)
206 , turn_by_cth_inflicted()
207 , turn_by_cth_taken()
208 , expected_damage_inflicted(0)
209 , expected_damage_taken(0)
210 , turn_expected_damage_inflicted(0)
211 , turn_expected_damage_taken(0)
224 , attacks_inflicted()
225 , defends_inflicted()
228 , damage_inflicted(0)
230 , turn_damage_inflicted(0)
231 , turn_damage_taken(0)
234 , turn_by_cth_inflicted()
235 , turn_by_cth_taken()
236 , expected_damage_inflicted(0)
237 , expected_damage_taken(0)
238 , turn_expected_damage_inflicted(0)
239 , turn_expected_damage_taken(0)
388 save_id = cfg[
"save_id"].str();
394 DBG_NG <<
"Merging statistics";
409 a.recruit_cost +=
b.recruit_cost;
410 a.recall_cost +=
b.recall_cost;
412 a.damage_inflicted +=
b.damage_inflicted;
413 a.damage_taken +=
b.damage_taken;
414 a.expected_damage_inflicted +=
b.expected_damage_inflicted;
415 a.expected_damage_taken +=
b.expected_damage_taken;
417 a.turn_damage_inflicted =
b.turn_damage_inflicted;
418 a.turn_damage_taken =
b.turn_damage_taken;
419 a.turn_expected_damage_inflicted =
b.turn_expected_damage_inflicted;
420 a.turn_expected_damage_taken =
b.turn_expected_damage_taken;
421 a.turn_by_cth_inflicted =
b.turn_by_cth_inflicted;
422 a.turn_by_cth_taken =
b.turn_by_cth_taken;
428 , scenario_name(cfg[
"scenario"])
451 i->second.write(out);
462 : strikes(cfg[
"strikes"])
471 for(std::vector<scenario_stats_t>::const_iterator
i = master_record.begin();
i != master_record.end(); ++
i) {
480 for(std::vector<scenario_stats_t>::const_iterator
i = master_record.begin();
i != master_record.end(); ++
i) {
490 master_record.clear();
493 master_record.emplace_back(
s);
499 master_record.emplace_back(name);
504 if(master_record.empty() ==
false) {
505 master_record.back().team_stats.clear();
513 outstream <<
"[" << by_cth.
hits <<
"/" << by_cth.
strikes <<
"]";
Class for writing a config out to a file in pieces.
void close_child(const std::string &key)
void write(const config &cfg)
void write_key_val(const std::string &key, const T &value)
This template function will work with any type that can be assigned to an attribute_value.
void open_child(const std::string &key)
A config object defines a single node in a WML file, with access to child nodes.
const_attr_itors attribute_range() const
bool has_attribute(config_key_type key) const
child_itors child_range(config_key_type key)
attribute_map::value_type attribute
optional_config_impl< config > optional_child(config_key_type key, int n=0)
Euivalent to mandatory_child, but returns an empty optional if the nth child was not found.
config & add_child(config_key_type key)
This class stores all the data for a single 'side' (in game nomenclature).
Standard logging facilities (interface).
std::pair< std::string, unsigned > item
static stats_t::hitrate_map read_by_cth_map_from_battle_result_maps(const stats_t::battle_result_map &attacks, const stats_t::battle_result_map &defends)
static config write_by_cth_map(const stats_t::hitrate_map &m)
static stats_t::hitrate_map read_by_cth_map(const config &cfg)
static stats_t::str_int_map read_str_int_map(const config &cfg)
static stats_t::battle_result_map read_battle_result_map(const config &cfg)
static void merge_battle_result_maps(stats_t::battle_result_map &a, const stats_t::battle_result_map &b)
static config write_battle_result_map(const stats_t::battle_result_map &m)
static void merge_cth_map(stats_t::hitrate_map &a, const stats_t::hitrate_map &b)
static config write_str_int_map(const stats_t::str_int_map &m)
static void merge_str_int_map(stats_t::str_int_map &a, const stats_t::str_int_map &b)
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
std::vector< std::string > split(const config_attribute_value &val)
static lg::log_domain log_engine("engine")
std::ostream & operator<<(std::ostream &outstream, const statistics_record::stats_t::hitrate_t &by_cth)
void new_scenario(const std::string &scenario_name)
Adds an entry for anew scenario to wrte to.
void read(const config &cfg, bool append=false)
void clear_current_scenario()
Delete the current scenario from the stats.
void write(config_writer &out) const
std::string scenario_name
scenario_stats_t(const std::string &name)
void merge_with(const stats_t &other)
long long turn_damage_taken
long long turn_expected_damage_taken
battle_result_map attacks_inflicted
Statistics of this side's attacks on its own turns.
battle_result_map defends_inflicted
Statistics of this side's attacks on enemies' turns.
hitrate_map by_cth_inflicted
std::map< int, battle_sequence_frequency_map > battle_result_map
A type that will map different % chances to hit to different results.
hitrate_map turn_by_cth_inflicted
void read(const config &cfg)
str_int_map battle_sequence_frequency_map
std::map< int, hitrate_t > hitrate_map
A type that maps chance-to-hit percentage to number of hits and strikes at that CTH.
long long turn_damage_inflicted
std::map< std::string, int > str_int_map
battle_result_map attacks_taken
Statistics of enemies' counter attacks on this side's turns.
long long turn_expected_damage_inflicted
hitrate_map turn_by_cth_taken
long long expected_damage_inflicted
long long expected_damage_taken
battle_result_map defends_taken
Statistics of enemies' attacks against this side on their turns.
long long damage_inflicted
static map_location::DIRECTION n
static map_location::DIRECTION s