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 find_widget<listbox>(
"stats_list_main").add_row(
widget_data{
131 str <<
"+0% (0 + 0)";
133 str << (
formatter() << std::showpos << std::round((actual - expected) * 100 / expected) <<
"% (").str();
134 str << expected << (actual >= expected ?
" + " :
" − ")
135 <<
static_cast<unsigned int>(std::round(std::abs(expected - actual)));
142 const std::string&
type,
143 const long long& damage,
144 const long long& expected,
145 const long long& turn_damage,
146 const long long& turn_expected,
147 const bool show_this_turn)
149 listbox& damage_list = find_widget<listbox>(
"stats_list_damage");
154 item[
"label"] =
type;
155 data.emplace(
"damage_type", item);
159 const auto damage_str = [](
long long damage,
long long expected) {
160 const long long shifted = ((expected * 20) + shift) / (2 * shift);
161 std::ostringstream str;
166 item[
"label"] = damage_str(damage, expected);
167 data.emplace(
"damage_overall", item);
170 data.emplace(
"overall_score", item);
173 label& this_turn_header = find_widget<label>(
"damage_this_turn_header");
176 item[
"label"] = damage_str(turn_damage, turn_expected);
177 data.emplace(
"damage_this_turn", item);
180 data.emplace(
"this_turn_score", item);
183 label& this_turn_header = find_widget<label>(
"damage_this_turn_header");
204 unsigned int overall_hits = 0;
205 double expected_hits = 0;
206 unsigned int overall_strikes = 0;
208 std::ostringstream str, str2,
tooltip;
210 tooltip <<
'\n' <<
'\n' <<
_(
"Actual hit rates, by chance to hit:");
212 tooltip <<
'\n' <<
_(
"(no attacks have taken place yet)");
213 for(
const auto&
i : by_cth) {
215 overall_hits +=
i.second.hits;
216 expected_hits += (cth * 0.01) *
i.second.strikes;
217 overall_strikes +=
i.second.strikes;
218 tooltip <<
"\n" << cth <<
"%: "
220 <<
"% (N=" <<
i.second.strikes <<
")";
228 "id",
"statistics_dialog_dummy_defender",
231 "hitpoints", overall_strikes
237 auto current_defender = std::make_unique<combatant>(defender_bc);
239 for(
const auto&
i : by_cth) {
242 "id",
"statistics_dialog_dummy_attacker" + std::to_string(cth),
250 auto attack = std::make_shared<attack_type>(
config(
253 "name",
"dummy attack",
255 "number",
i.second.strikes
262 current_defender.reset(
new combatant(*current_defender, defender_bc));
265 attacker.
fight(*current_defender);
268 const std::vector<double>& final_hp_dist = current_defender->hp_dist;
269 const auto chance_of_exactly_N_hits = [&final_hp_dist](
int n) {
return final_hp_dist[final_hp_dist.size() - 1 -
n]; };
273 double probability_lt = 0.0;
274 for(
unsigned int i = 0;
i < overall_hits; ++
i) {
275 probability_lt += chance_of_exactly_N_hits(
i);
278 double probability_eq = chance_of_exactly_N_hits(overall_hits);
280 double probability_gt = 1.0 - (probability_lt + probability_eq);
282 if(overall_strikes == 0) {
286 const auto add_probability = [&str2](
double probability,
bool more_is_better) {
295 const double percentile = (probability_lt + (1.0 - probability_gt)) / 2.0;
296 add_probability(percentile, more_is_better);
304 const std::string&
type,
305 const bool more_is_better,
308 const bool show_this_turn)
310 listbox& hits_list = find_widget<listbox>(
"stats_list_hits");
317 item[
"label"] =
type;
318 data.emplace(
"hits_type", item);
320 const auto tooltip_static_part =
_(
321 "stats dialog^Difference of actual outcome to expected outcome, as a percentage.\n"
322 "The first number in parentheses is the expected number of hits inflicted/taken.\n"
323 "The sum (or difference) of the two numbers in parentheses is the actual number of hits inflicted/taken.");
324 element =
tally(by_cth, more_is_better);
325 item[
"tooltip"] = tooltip_static_part + element.
tooltip;
327 data.emplace(
"hits_overall", item);
333 label& this_turn_header = find_widget<label>(
"hits_this_turn_header");
336 element =
tally(turn_by_cth, more_is_better);
337 item[
"tooltip"] = tooltip_static_part + element.
tooltip;
339 data.emplace(
"hits_this_turn", item);
345 label& this_turn_header = find_widget<label>(
"hits_this_turn_header");
357 listbox& stat_list = find_widget<listbox>(
"stats_list_main");
372 if(last_selected_stat_row != -1) {
384 listbox& damage_list = find_widget<listbox>(
"stats_list_damage");
388 listbox& hits_list = find_widget<listbox>(
"stats_list_hits");
420 const std::size_t new_index = find_widget<menu_button>(
"scenario_menu").get_value();
430 const int selected_row = find_widget<listbox>(
"stats_list_main").get_selected_row();
431 if(selected_row == -1) {
435 listbox& unit_list = find_widget<listbox>(
"stats_list_units");
449 data.emplace(
"unit_image", item);
452 item[
"label"] =
VGETTEXT(
"$count|× $name", {{
"count", std::to_string(
i.second)}, {
"name",
type->type_name()}});
453 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.
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)
Applies Pango markup to the input specifying its display color.
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