The Battle for Wesnoth  1.15.2+dev
game_stats.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2016 - 2018 by the Battle for Wesnoth Project https://www.wesnoth.org/
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY.
10 
11  See the COPYING file for more details.
12 */
13 
14 #define GETTEXT_DOMAIN "wesnoth-lib"
15 
17 
19 #include "gui/core/log.hpp"
20 #include "gui/dialogs/message.hpp"
21 #include "gui/widgets/listbox.hpp"
22 #include "gui/widgets/settings.hpp"
23 #include "gui/widgets/button.hpp"
24 #include "gui/widgets/image.hpp"
25 #include "gui/widgets/label.hpp"
28 #include "gui/widgets/window.hpp"
29 #include "display.hpp"
30 #include "formatter.hpp"
31 #include "game_board.hpp"
32 #include "game_classification.hpp"
33 #include "map/map.hpp"
34 #include "play_controller.hpp"
35 #include "resources.hpp"
36 #include "units/map.hpp"
37 #include "units/unit.hpp"
38 
39 #include "utils/functional.hpp"
40 
41 static lg::log_domain log_display("display");
42 #define LOG_DP LOG_STREAM(info, log_display)
43 
44 namespace gui2
45 {
46 namespace dialogs
47 {
48 
49 REGISTER_DIALOG(game_stats)
50 
51 game_stats::game_stats(const display_context& board, const int viewing_team, int& selected_side_number)
52  : board_(board)
53  , viewing_team_(board_.teams()[viewing_team])
54  , selected_side_number_(selected_side_number)
55 {
56 }
57 
59 {
61 
62  if(leader != board_.units().end()) {
63  return leader.get_shared_ptr();
64  }
65 
66  return nullptr;
67 }
68 
69 static std::string controller_name(const team& t)
70 {
71  static const std::array<t_string, 3> names {{_("controller^Human"), _("controller^AI"), _("controller^Idle")}};
72  return "<span color='#808080'><small>" + names[t.controller().v] + "</small></span>";
73 }
74 
76 {
77  listbox& stats_list = find_widget<listbox>(&window, "game_stats_list", false);
78  listbox& settings_list = find_widget<listbox>(&window, "scenario_settings_list", false);
79 
80  for(const auto& team : board_.teams()) {
81  if(team.hidden()) {
82  continue;
83  }
84 
85  team_data_.emplace_back(board_, team);
86 
87  std::map<std::string, string_map> row_data_stats;
88  string_map column_stats;
89 
90  const bool known = viewing_team_.knows_about_team(team.side() - 1);
91  const bool enemy = viewing_team_.is_enemy(team.side());
92 
93  const team_data& data = team_data_.back();
94 
95  unit_const_ptr leader = get_leader(team.side());
96 
97  std::string leader_name;
98  std::string leader_image;
99 
101  if(leader) {
102  const bool visible = leader->is_visible_to_team(leader->get_location(), viewing_team_, see_all);
103 
104  // Add leader image. If it's fogged/[hides], show only a random leader image.
105  if(visible || known) {
106  leader_image = leader->absolute_image() + leader->image_mods();
107  leader_name = leader->name();
108  } else {
109  leader_image = formatter() << "units/unknown-unit.png" << "~RC(magenta>" << team.color() << ")";
110  leader_name = _("Unknown");
111  }
112 
114  if(resources::controller->get_classification().campaign_type == game_classification::CAMPAIGN_TYPE::MULTIPLAYER) {
115  leader_name = team.side_name();
116  }
117  }
118 
119  leader_name = "<span color='" + team::get_side_highlight_pango(team.side()) + "'>" + leader_name + "</span>";
120  }
121 
122  //
123  // Status list
124  //
125  column_stats["use_markup"] = "true";
126 
127  column_stats["label"] = leader_image;
128  row_data_stats.emplace("team_leader_image", column_stats);
129 
130  column_stats["label"] = leader_name + "\n" + controller_name(team);
131  column_stats["tooltip"] = team::get_side_color_name_for_UI(team.side());
132  row_data_stats.emplace("team_leader_name", column_stats);
133  column_stats.erase("tooltip");
134 
135  column_stats["label"] = team.user_team_name().empty() ? team.team_name() : team.user_team_name().str();
136  row_data_stats.emplace("team_name", column_stats);
137 
138  // Only fill in the rest of the info if the side is known...
139  if(known || see_all) {
140  std::string gold_str;
141  if(see_all || !enemy || !viewing_team_.uses_fog()) {
142  gold_str = utils::half_signed_value(team.gold());
143  }
144 
145  column_stats["label"] = team.gold() < 0 ? "<span color='#ff0000'>" + gold_str + "</span>" : gold_str;
146  row_data_stats.emplace("team_gold", column_stats);
147 
148  std::string village_count = std::to_string(team.villages().size());
150  village_count += "/" + std::to_string(board_.map().villages().size());
151  }
152 
153  column_stats["label"] = village_count;
154  row_data_stats.emplace("team_villages", column_stats);
155 
156  column_stats["label"] = std::to_string(data.units);
157  row_data_stats.emplace("team_units", column_stats);
158 
159  column_stats["label"] = std::to_string(data.upkeep);
160  row_data_stats.emplace("team_upkeep", column_stats);
161 
162  const std::string income = utils::signed_value(data.net_income);
163  column_stats["label"] = data.net_income < 0 ? "<span color='#ff0000'>" + income + "</span>" : income;
164  row_data_stats.emplace("team_income", column_stats);
165  }
166 
167  stats_list.add_row(row_data_stats);
168 
169  //
170  // Settings list
171  //
172  std::map<std::string, string_map> row_data_settings;
173  string_map column_settings;
174 
175  column_settings["use_markup"] = "true";
176 
177  column_settings["label"] = leader_image;
178  row_data_settings.emplace("team_leader_image", column_settings);
179 
180  column_settings["label"] = leader_name + "\n" + controller_name(team);
181  row_data_settings.emplace("team_leader_name", column_settings);
182 
183  column_settings["label"] = std::to_string(team.side());
184  row_data_settings.emplace("team_side", column_settings);
185 
186  column_settings["label"] = std::to_string(team.start_gold());
187  row_data_settings.emplace("team_start_gold", column_settings);
188 
189  column_settings["label"] = std::to_string(team.base_income());
190  row_data_settings.emplace("team_base_income", column_settings);
191 
192  column_settings["label"] = std::to_string(team.village_gold());
193  row_data_settings.emplace("team_village_gold", column_settings);
194 
195  column_settings["label"] = std::to_string(team.village_support());
196  row_data_settings.emplace("team_village_support", column_settings);
197 
198  column_settings["label"] = team.uses_fog() ? _("yes") : _("no");
199  row_data_settings.emplace("team_fog", column_settings);
200 
201  column_settings["label"] = team.uses_shroud() ? _("yes") : _("no");
202  row_data_settings.emplace("team_shroud", column_settings);
203 
204  settings_list.add_row(row_data_settings);
205  }
206 
207  // Sorting options for the status list
208  stats_list.register_translatable_sorting_option(0, [this](const int i) {
209  unit_const_ptr leader = get_leader(i + 1);
210  return leader ? leader->name().str() : "";
211  });
212 
213  stats_list.register_translatable_sorting_option(1, [this](const int i) {
214  return board_.teams()[i].user_team_name().str(); });
215  stats_list.register_sorting_option(2, [this](const int i) { return board_.teams()[i].gold(); });
216  stats_list.register_sorting_option(3, [this](const int i) { return board_.teams()[i].villages(); });
217  stats_list.register_sorting_option(4, [this](const int i) { return team_data_[i].units; });
218  stats_list.register_sorting_option(5, [this](const int i) { return team_data_[i].upkeep; });
219  stats_list.register_sorting_option(6, [this](const int i) { return team_data_[i].net_income; });
220 
221  // Sorting options for the settings list
222  settings_list.register_translatable_sorting_option(0, [this](const int i) {
223  unit_const_ptr leader = get_leader(i + 1);
224  return leader ? leader->name().str() : "";
225  });
226 
227  settings_list.register_sorting_option(1, [this](const int i) { return board_.teams()[i].side(); });
228  settings_list.register_sorting_option(2, [this](const int i) { return board_.teams()[i].start_gold(); });
229  settings_list.register_sorting_option(3, [this](const int i) { return board_.teams()[i].base_income(); });
230  settings_list.register_sorting_option(4, [this](const int i) { return board_.teams()[i].village_gold(); });
231  settings_list.register_sorting_option(5, [this](const int i) { return board_.teams()[i].village_support(); });
232  settings_list.register_sorting_option(6, [this](const int i) { return board_.teams()[i].uses_fog(); });
233  settings_list.register_sorting_option(7, [this](const int i) { return board_.teams()[i].uses_shroud(); });
234 
235  //
236  // Set up tab control
237  //
238  listbox& tab_bar = find_widget<listbox>(&window, "tab_bar", false);
239 
240  window.keyboard_capture(&tab_bar);
241 
242  connect_signal_notify_modified(tab_bar, std::bind(&game_stats::on_tab_select, this, std::ref(window)));
243 
244  on_tab_select(window);
245 }
246 
248 {
249  const int i = find_widget<listbox>(&window, "tab_bar", false).get_selected_row();
250 
251  find_widget<stacked_widget>(&window, "pager", false).select_layer(i);
252 
253  // There are only two tabs, so this is simple
254  find_widget<label>(&window, "title", false).set_label(
255  i == 0 ? _("Current Status") : _("Scenario Settings")
256  );
257 }
258 
260 {
261  if(get_retval() == retval::OK) {
262  const int selected_tab = find_widget<listbox>(&window, "tab_bar", false).get_selected_row();
263 
264  const std::string list_id = selected_tab == 0 ? "game_stats_list" : "scenario_settings_list";
265  selected_side_number_ = team_data_[find_widget<listbox>(&window, list_id, false).get_selected_row()].side;
266  }
267 }
268 
269 } // namespace dialogs
270 } // namespace gui2
Define the common log macros for the gui toolkit.
play_controller * controller
Definition: resources.cpp:21
boost::intrusive_ptr< const unit > unit_const_ptr
Definition: ptr.hpp:30
unit_iterator end()
Definition: map.hpp:415
const std::string & side_name() const
Definition: team.hpp:308
unit_iterator find_leader(int side)
Definition: map.cpp:329
game_display & get_display() override
Get a reference to a display member a derived class uses.
This file contains the window object, this object is a top level container which has the event manage...
bool show_everything() const
Definition: display.hpp:90
void register_translatable_sorting_option(const int col, translatable_sorter_func_t f)
Registers a special sorting function specifically for translatable values.
Definition: listbox.cpp:632
virtual const gamemap & map() const =0
int village_support() const
Definition: team.hpp:199
static std::string get_side_highlight_pango(int side)
Definition: team.cpp:1019
Generic file dialog.
Definition: field-fwd.hpp:22
const team & viewing_team_
Definition: game_stats.hpp:54
bool uses_fog() const
Definition: team.hpp:319
int gold() const
Definition: team.hpp:189
static const t_string get_side_color_name_for_UI(unsigned side)
Definition: team.cpp:987
int village_gold() const
Definition: team.hpp:192
bool knows_about_team(std::size_t index) const
Definition: team.cpp:705
The listbox class.
Definition: listbox.hpp:40
This class stores all the data for a single &#39;side&#39; (in game nomenclature).
Definition: team.hpp:44
std::string half_signed_value(int val)
Sign with Unicode "−" if negative.
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:91
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification_function &signal)
Connects a signal handler for getting a notification upon modification.
Definition: dispatcher.cpp:248
bool uses_shroud() const
Definition: team.hpp:318
virtual void post_show(window &window) override
Inherited from modal_dialog.
Definition: game_stats.cpp:259
This file contains the settings handling of the widget library.
std::ostringstream wrapper.
Definition: formatter.hpp:38
bool is_enemy(int n) const
Definition: team.hpp:243
map_display and display: classes which take care of displaying the map and game-data on the screen...
virtual const unit_map & units() const =0
void on_tab_select(window &window)
Definition: game_stats.cpp:247
Various uncategorised dialogs.
bool hidden() const
Definition: team.hpp:347
pointer get_shared_ptr() const
This is exactly the same as operator-> but it&#39;s slightly more readable, and can replace &*iter syntax...
Definition: map.hpp:220
std::size_t i
Definition: function.cpp:933
virtual const std::vector< team > & teams() const =0
virtual void pre_show(window &window) override
Inherited from modal_dialog.
Definition: game_stats.cpp:75
std::vector< std::string > names
Definition: build_info.cpp:56
std::map< std::string, t_string > string_map
Definition: widget.hpp:24
grid & add_row(const string_map &item, const int index=-1)
When an item in the list is selected by the user we need to update the state.
Definition: listbox.cpp:66
const bool & debug
int start_gold() const
Definition: team.hpp:190
std::vector< team_data > team_data_
Definition: game_stats.hpp:56
bool empty() const
Definition: tstring.hpp:182
const std::string & color() const
Definition: team.hpp:256
double t
Definition: astarsearch.cpp:64
const std::vector< map_location > & villages() const
Return a list of the locations of villages on the map.
Definition: map.hpp:192
unit_const_ptr get_leader(const int side)
Definition: game_stats.cpp:58
static lg::log_domain log_display("display")
int base_income() const
Definition: team.hpp:191
std::string signed_value(int val)
Convert into a signed value (using the Unicode "−" and +0 convention.
Dialog was closed with the OK button.
Definition: retval.hpp:34
int side() const
Definition: team.hpp:188
void register_sorting_option(const int col, const Func &f)
Definition: listbox.hpp:269
const std::string & str() const
Definition: tstring.hpp:186
const std::set< map_location > & villages() const
Definition: team.hpp:184
base class of top level items, the only item which needs to store the final canvases to draw on ...
Definition: window.hpp:62
const std::string & team_name() const
Definition: team.hpp:297
const t_string & user_team_name() const
Definition: team.hpp:298
static std::string controller_name(const team &t)
Definition: game_stats.cpp:69
const display_context & board_
Definition: game_stats.hpp:52
CONTROLLER controller() const
Definition: team.hpp:255