15 #define GETTEXT_DOMAIN "wesnoth-lib"
39 std::ostringstream ss;
44 ss << std::fixed << std::setprecision(1) << 100.0 * prob;
57 , campaign_(statistics.calculate_stats(current_team.save_id_or_number()))
58 , scenarios_(statistics.level_stats(current_team.save_id_or_number()))
59 , selection_index_(scenarios_.
size())
69 label& title = find_widget<label>(
"title");
75 std::vector<config> menu_items;
78 menu_items.emplace_back(
"label",
_(
"All Scenarios"));
81 menu_items.emplace_back(
"label", *scenario.first);
84 menu_button& scenario_menu = find_widget<menu_button>(
"scenario_menu");
94 listbox& stat_list = find_widget<listbox>(
"stats_list_main");
109 listbox& stat_list = find_widget<listbox>(
"stats_list_main");
114 item[
"label"] =
type;
115 data.emplace(
"stat_type", item);
118 data.emplace(
"stat_detail", item);
121 data.emplace(
"stat_cost", item);
133 str <<
"+0% (0 + 0)";
135 str << (
formatter() << std::showpos << std::round((actual - expected) * 100 / expected) <<
"% (").str();
136 str << expected << (actual >= expected ?
" + " :
" − ")
137 <<
static_cast<unsigned int>(std::round(std::abs(expected - actual)));
144 const std::string&
type,
145 const long long& damage,
146 const long long& expected,
147 const long long& turn_damage,
148 const long long& turn_expected,
149 const bool show_this_turn)
151 listbox& damage_list = find_widget<listbox>(
"stats_list_damage");
156 item[
"label"] =
type;
157 data.emplace(
"damage_type", item);
161 const auto damage_str = [](
long long damage,
long long expected) {
162 const long long shifted = ((expected * 20) + shift) / (2 * shift);
163 std::ostringstream str;
168 item[
"label"] = damage_str(damage, expected);
169 data.emplace(
"damage_overall", item);
172 data.emplace(
"overall_score", item);
175 label& this_turn_header = find_widget<label>(
"damage_this_turn_header");
178 item[
"label"] = damage_str(turn_damage, turn_expected);
179 data.emplace(
"damage_this_turn", item);
182 data.emplace(
"this_turn_score", item);
185 label& this_turn_header = find_widget<label>(
"damage_this_turn_header");
206 unsigned int overall_hits = 0;
207 double expected_hits = 0;
208 unsigned int overall_strikes = 0;
210 std::ostringstream str, str2,
tooltip;
212 tooltip <<
'\n' <<
'\n' <<
_(
"Actual hit rates, by chance to hit:");
214 tooltip <<
'\n' <<
_(
"(no attacks have taken place yet)");
215 for(
const auto&
i : by_cth) {
217 overall_hits +=
i.second.hits;
218 expected_hits += (cth * 0.01) *
i.second.strikes;
219 overall_strikes +=
i.second.strikes;
220 tooltip <<
"\n" << cth <<
"%: "
222 <<
"% (N=" <<
i.second.strikes <<
")";
230 "id",
"statistics_dialog_dummy_defender",
233 "hitpoints", overall_strikes
239 auto current_defender = std::make_unique<combatant>(defender_bc);
241 for(
const auto&
i : by_cth) {
244 "id",
"statistics_dialog_dummy_attacker" + std::to_string(cth),
252 auto attack = std::make_shared<attack_type>(
config(
255 "name",
"dummy attack",
257 "number",
i.second.strikes
264 current_defender.reset(
new combatant(*current_defender, defender_bc));
267 attacker.
fight(*current_defender);
270 const std::vector<double>& final_hp_dist = current_defender->hp_dist;
271 const auto chance_of_exactly_N_hits = [&final_hp_dist](
int n) {
return final_hp_dist[final_hp_dist.size() - 1 -
n]; };
275 double probability_lt = 0.0;
276 for(
unsigned int i = 0;
i < overall_hits; ++
i) {
277 probability_lt += chance_of_exactly_N_hits(
i);
280 double probability_eq = chance_of_exactly_N_hits(overall_hits);
282 double probability_gt = 1.0 - (probability_lt + probability_eq);
284 if(overall_strikes == 0) {
288 const auto add_probability = [&str2](
double probability,
bool more_is_better) {
297 const double percentile = (probability_lt + (1.0 - probability_gt)) / 2.0;
298 add_probability(percentile, more_is_better);
306 const std::string&
type,
307 const bool more_is_better,
310 const bool show_this_turn)
312 listbox& hits_list = find_widget<listbox>(
"stats_list_hits");
319 item[
"label"] =
type;
320 data.emplace(
"hits_type", item);
322 const auto tooltip_static_part =
_(
323 "stats dialog^Difference of actual outcome to expected outcome, as a percentage.\n"
324 "The first number in parentheses is the expected number of hits inflicted/taken.\n"
325 "The sum (or difference) of the two numbers in parentheses is the actual number of hits inflicted/taken.");
326 element =
tally(by_cth, more_is_better);
327 item[
"tooltip"] = tooltip_static_part + element.
tooltip;
329 data.emplace(
"hits_overall", item);
335 label& this_turn_header = find_widget<label>(
"hits_this_turn_header");
338 element =
tally(turn_by_cth, more_is_better);
339 item[
"tooltip"] = tooltip_static_part + element.
tooltip;
341 data.emplace(
"hits_this_turn", item);
347 label& this_turn_header = find_widget<label>(
"hits_this_turn_header");
359 listbox& stat_list = find_widget<listbox>(
"stats_list_main");
374 if(last_selected_stat_row != -1) {
386 listbox& damage_list = find_widget<listbox>(
"stats_list_damage");
390 listbox& hits_list = find_widget<listbox>(
"stats_list_hits");
422 const std::size_t new_index = find_widget<menu_button>(
"scenario_menu").get_value();
432 const int selected_row = find_widget<listbox>(
"stats_list_main").get_selected_row();
433 if(selected_row == -1) {
451 data.emplace(
"unit_image", item);
454 item[
"label"] =
VGETTEXT(
"$count|× $name", {{
"count", std::to_string(
i.second)}, {
"name",
type->type_name()}});
455 data.emplace(
"unit_name", item);
Various functions that implement attacks and attack calculations.
A config object defines a single node in a WML file, with access to child nodes.
unsigned add_row(const unsigned count=1)
Abstract base class for all modal dialogs.
std::size_t selection_index_
const team & current_team_
const statistics_t::stats & current_stats()
Picks out the stats structure that was selected for displaying.
void on_primary_list_select()
const statistics_t::levels scenarios_
virtual void pre_show() override
Actions to be taken before showing the window.
void on_scenario_select()
void add_damage_row(const std::string &type, const long long &damage, const long long &expected, const long long &turn_damage, const long long &turn_expected, const bool show_this_turn)
Add a row to the Damage table.
const statistics_t::stats campaign_
void add_hits_row(const std::string &type, const bool more_is_better, const statistics_t::stats::hitrate_map &by_cth, const statistics_t::stats::hitrate_map &turn_by_cth, const bool show_this_turn)
Add a row to the Hits table.
void add_stat_row(const std::string &type, const statistics_t::stats::str_int_map &value, const bool has_cost=true)
std::vector< const statistics_t::stats::str_int_map * > main_stat_table_
grid & add_row(const widget_item &item, const int index=-1)
When an item in the list is selected by the user we need to update the state.
bool select_row(const unsigned row, const bool select=true)
Selects a row.
void clear()
Removes all the rows in the listbox, clearing it.
int get_selected_row() const
Returns the first selected row.
static const std::string & type()
Static type getter that does not rely on the widget being constructed.
static int sum_cost_str_int_map(const std::map< std::string, int > &m)
static int sum_str_int_map(const std::map< std::string, int > &m)
This class stores all the data for a single 'side' (in game nomenclature).
const std::string & color() const
const std::string & side_name() const
const unit_type * find(const std::string &key, unit_type::BUILD_STATUS status=unit_type::FULL) const
Finds a unit_type by its id() and makes sure it is built to the specified level.
void build_unit_type(const unit_type &ut, unit_type::BUILD_STATUS status) const
Makes sure the provided unit_type is built to the specified level.
A single unit type that the player may recruit.
static std::string _(const char *str)
std::string tooltip
Shown when hovering over an entry in the filter's drop-down list.
const std::string unicode_em_dash
color_t red_to_green(double val, bool for_text)
Return a color corresponding to the value val red for val=0.0 to green for val=100....
REGISTER_DIALOG(editor_edit_unit)
static std::ostream & write_actual_and_expected(std::ostream &str, const long long actual, const double expected)
static std::string get_probability_string(const double prob)
static hitrate_table_element tally(const statistics_t::stats::hitrate_map &by_cth, const bool more_is_better)
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification &signal)
Connects a signal handler for getting a notification upon modification.
std::map< std::string, widget_item > widget_data
std::map< std::string, t_string > widget_item
std::string span_color(const color_t &color, Args &&... data)
std::size_t size(std::string_view str)
Length in characters of a UTF-8 string.
static std::string get_probability_string(const double prob)
Structure describing the statistics of a unit involved in the battle.
void fight(combatant &opponent, bool levelup_considered=true)
Simulate a fight! Can be called multiple times for cumulative calculations.
long long turn_damage_taken
long long turn_expected_damage_taken
hitrate_map by_cth_inflicted
hitrate_map turn_by_cth_inflicted
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
static const int decimal_shift
long long turn_expected_damage_inflicted
hitrate_map turn_by_cth_taken
long long expected_damage_inflicted
long long expected_damage_taken
long long damage_inflicted
static map_location::direction n
unit_type_data unit_types