Merge lp:~widelands-dev/widelands/bug-1573057-graph-relative-plotmode into lp:widelands

Proposed by GunChleoc
Status: Merged
Merged at revision: 8022
Proposed branch: lp:~widelands-dev/widelands/bug-1573057-graph-relative-plotmode
Merge into: lp:widelands
Diff against target: 918 lines (+231/-248)
6 files modified
src/logic/cmd_calculate_statistics.cc (+1/-1)
src/logic/constants.h (+4/-2)
src/wui/general_statistics_menu.cc (+3/-3)
src/wui/plot_area.cc (+176/-203)
src/wui/plot_area.h (+35/-27)
src/wui/ware_statistics_menu.cc (+12/-12)
To merge this branch: bzr merge lp:~widelands-dev/widelands/bug-1573057-graph-relative-plotmode
Reviewer Review Type Date Requested Status
TiborB Approve
kaputtnik (community) testing Approve
Review via email: mp+295198@code.launchpad.net

Commit message

Fixed relative plot mode and flickering graphs on button click. Only draw active statistics tab. Some refactoring.

To post a comment you must log in.
Revision history for this message
GunChleoc (gunchleoc) wrote :

Good savegames for testing are attached to bug https://bugs.launchpad.net/widelands/+bug/1573057

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 1139. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/131399247.
Appveyor build 976. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1573057_graph_relative_plotmode-976.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 1143. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/131622951.
Appveyor build 980. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1573057_graph_relative_plotmode-980.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 1143. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/131622951.
Appveyor build 980. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1573057_graph_relative_plotmode-980.

Revision history for this message
kaputtnik (franku) wrote :

Works as expected :-)

review: Approve (testing)
Revision history for this message
bunnybot (widelandsofficial) wrote :

Bunnybot encountered an error while working on this merge proposal:

<urlopen error _ssl.c:495: The handshake operation timed out>

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 1143. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/131622951.
Appveyor build 980. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1573057_graph_relative_plotmode-980.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Bunnybot encountered an error while working on this merge proposal:

The read operation timed out

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 1143. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/131622951.
Appveyor build 980. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1573057_graph_relative_plotmode-980.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 1156. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/136762248.
Appveyor build 994. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1573057_graph_relative_plotmode-994.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Bunnybot encountered an error while working on this merge proposal:

<urlopen error _ssl.c:495: The handshake operation timed out>

Revision history for this message
bunnybot (widelandsofficial) wrote :

Bunnybot encountered an error while working on this merge proposal:

<urlopen error _ssl.c:495: The handshake operation timed out>

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 1156. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/136762248.
Appveyor build 994. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1573057_graph_relative_plotmode-994.

Revision history for this message
GunChleoc (gunchleoc) wrote :

Ping?

It would be good to get this branch in so that we can go into official feature freeze.

Revision history for this message
TiborB (tiborb95) wrote :

oh, too complicated for me, but it at least LOOKS good to me :)

review: Approve
Revision history for this message
GunChleoc (gunchleoc) wrote :

Now you know how I feel when I review your AI code *lol* Thanks!

@bunnybot merge

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/logic/cmd_calculate_statistics.cc'
2--- src/logic/cmd_calculate_statistics.cc 2015-10-24 15:42:37 +0000
3+++ src/logic/cmd_calculate_statistics.cc 2016-06-10 17:28:35 +0000
4@@ -31,7 +31,7 @@
5 game.sample_statistics();
6 game.enqueue_command
7 (new CmdCalculateStatistics
8- (game.get_gametime() + STATISTICS_SAMPLE_TIME));
9+ (game.get_gametime() + kStatisticsSampleTime));
10 }
11
12 constexpr uint16_t kCurrentPacketVersion = 1;
13
14=== modified file 'src/logic/constants.h'
15--- src/logic/constants.h 2015-03-01 09:21:20 +0000
16+++ src/logic/constants.h 2016-06-10 17:28:35 +0000
17@@ -1,5 +1,5 @@
18 /*
19- * Copyright (C) 2006-2015 by the Widelands Development Team
20+ * Copyright (C) 2006-2016 by the Widelands Development Team
21 *
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24@@ -20,6 +20,8 @@
25 #ifndef WL_LOGIC_CONSTANTS_H
26 #define WL_LOGIC_CONSTANTS_H
27
28+#include <cstdint>
29+
30 /// Maximum numbers of players in a game. The game logic code reserves 5 bits
31 /// for player numbers, so it can keep track of 32 different player numbers, of
32 /// which the value 0 means neutral and the values 1 .. 31 can be used as the
33@@ -27,6 +29,6 @@
34 #define MAX_PLAYERS 8
35
36 /// How often are statistics to be sampled.
37-#define STATISTICS_SAMPLE_TIME 30000
38+constexpr uint32_t kStatisticsSampleTime = 30000;
39
40 #endif // end of include guard: WL_LOGIC_CONSTANTS_H
41
42=== modified file 'src/wui/general_statistics_menu.cc'
43--- src/wui/general_statistics_menu.cc 2016-01-29 08:37:22 +0000
44+++ src/wui/general_statistics_menu.cc 2016-06-10 17:28:35 +0000
45@@ -67,7 +67,9 @@
46 440, 400, _("General Statistics")),
47 my_registry_ (&registry),
48 box_ (this, 0, 0, UI::Box::Vertical, 0, 0, 5),
49- plot_ (&box_, 0, 0, 430, PLOT_HEIGHT),
50+ plot_ (&box_, 0, 0, 430, PLOT_HEIGHT,
51+ kStatisticsSampleTime,
52+ WuiPlotArea::Plotmode::kAbsolute),
53 selected_information_(0)
54 {
55 assert (my_registry_);
56@@ -78,8 +80,6 @@
57 box_.set_border(5, 5, 5, 5);
58
59 // Setup plot data
60- plot_.set_sample_rate(STATISTICS_SAMPLE_TIME);
61- plot_.set_plotmode(WuiPlotArea::PLOTMODE_ABSOLUTE);
62 Game & game = *parent.get_game();
63 const Game::GeneralStatsVector & genstats =
64 game.get_general_statistics();
65
66=== modified file 'src/wui/plot_area.cc'
67--- src/wui/plot_area.cc 2016-03-29 17:28:15 +0000
68+++ src/wui/plot_area.cc 2016-06-10 17:28:35 +0000
69@@ -39,24 +39,24 @@
70
71 constexpr int32_t kUpdateTimeInGametimeMs = 1000; // 1 second, gametime
72
73-const uint32_t minutes = 60 * 1000;
74-const uint32_t hours = 60 * 60 * 1000;
75-const uint32_t days = 24 * 60 * 60 * 1000;
76+constexpr uint32_t kMinutes = 60 * 1000;
77+constexpr uint32_t kHours = 60 * 60 * 1000;
78+constexpr uint32_t kDays = 24 * 60 * 60 * 1000;
79
80-const int32_t spacing = 5;
81-const int32_t space_at_bottom = 20;
82-const int32_t space_at_right = 10;
83-const int32_t space_left_of_label = 15;
84-const uint32_t nr_samples = 30; // How many samples per diagramm when relative plotting
85+constexpr int32_t kSpacing = 5;
86+constexpr int32_t kSpaceBottom = 20;
87+constexpr int32_t kSpaceRight = 10;
88+constexpr int32_t kSpaceLeftOfLabel = 15;
89+constexpr uint32_t KNoSamples = 30; // How many samples per diagramm when relative plotting
90
91 const uint32_t time_in_ms[] = {
92- 15 * minutes,
93- 30 * minutes,
94- 1 * hours,
95- 2 * hours,
96- 5 * hours,
97- 10 * hours,
98- 30 * hours
99+ 15 * kMinutes,
100+ 30 * kMinutes,
101+ 1 * kHours,
102+ 2 * kHours,
103+ 5 * kHours,
104+ 10 * kHours,
105+ 30 * kHours
106 };
107
108 const char BG_PIC[] = "images/wui/plot_area_bg.png";
109@@ -99,18 +99,18 @@
110 Units get_suggested_unit(uint32_t game_time, bool is_generic = false) {
111 // Find a nice unit for max_x
112 if (is_generic) {
113- if (game_time > 4 * days) {
114+ if (game_time > 4 * kDays) {
115 return Units::kDayGeneric;
116- } else if (game_time > 4 * hours) {
117+ } else if (game_time > 4 * kHours) {
118 return Units::kHourGeneric;
119 } else {
120 return Units::kMinutesGeneric;
121 }
122 }
123 else {
124- if (game_time > 4 * days) {
125+ if (game_time > 4 * kDays) {
126 return Units::kDayNarrow;
127- } else if (game_time > 4 * hours) {
128+ } else if (game_time > 4 * kHours) {
129 return Units::kHourNarrow;
130 } else {
131 return Units::kMinutesNarrow;
132@@ -153,13 +153,13 @@
133 switch (unit) {
134 case Units::kDayGeneric:
135 case Units::kDayNarrow:
136- return ms / days;
137+ return ms / kDays;
138 case Units::kHourGeneric:
139 case Units::kHourNarrow:
140- return ms / hours;
141+ return ms / kHours;
142 case Units::kMinutesGeneric:
143 case Units::kMinutesNarrow:
144- return ms / minutes;
145+ return ms / kMinutes;
146 }
147 NEVER_HERE();
148 }
149@@ -167,11 +167,11 @@
150 /**
151 * calculate how many values are taken together when plot mode is relative
152 */
153-int32_t calc_how_many(uint32_t time_ms, int32_t sample_rate) {
154+int32_t calc_how_many(uint32_t time_ms, uint32_t sample_rate) {
155 int32_t how_many = static_cast<int32_t>
156 ((static_cast<float>(time_ms)
157 /
158- static_cast<float>(nr_samples))
159+ static_cast<float>(KNoSamples))
160 /
161 static_cast<float>(sample_rate));
162
163@@ -230,28 +230,28 @@
164 // Draw coordinate system
165 // X Axis
166 dst.draw_line_strip({
167- FloatPoint(spacing, inner_h - space_at_bottom),
168- FloatPoint(inner_w - space_at_right, inner_h - space_at_bottom)},
169+ FloatPoint(kSpacing, inner_h - kSpaceBottom),
170+ FloatPoint(inner_w - kSpaceRight, inner_h - kSpaceBottom)},
171 kAxisLineColor, kAxisLinesWidth);
172 // Arrow
173 dst.draw_line_strip({
174- FloatPoint(spacing + 5, inner_h - space_at_bottom - 3),
175- FloatPoint(spacing, inner_h - space_at_bottom),
176- FloatPoint(spacing + 5, inner_h - space_at_bottom + 3),
177+ FloatPoint(kSpacing + 5, inner_h - kSpaceBottom - 3),
178+ FloatPoint(kSpacing, inner_h - kSpaceBottom),
179+ FloatPoint(kSpacing + 5, inner_h - kSpaceBottom + 3),
180 }, kAxisLineColor, kAxisLinesWidth);
181
182 // Y Axis
183- dst.draw_line_strip({FloatPoint(inner_w - space_at_right, spacing),
184- FloatPoint(inner_w - space_at_right, inner_h - space_at_bottom)},
185+ dst.draw_line_strip({FloatPoint(inner_w - kSpaceRight, kSpacing),
186+ FloatPoint(inner_w - kSpaceRight, inner_h - kSpaceBottom)},
187 kAxisLineColor, kAxisLinesWidth);
188 // No Arrow here, since this doesn't continue.
189
190- float sub = (xline_length - space_left_of_label) / how_many_ticks;
191- float posx = inner_w - space_at_right;
192+ float sub = (xline_length - kSpaceLeftOfLabel) / how_many_ticks;
193+ float posx = inner_w - kSpaceRight;
194
195 for (uint32_t i = 0; i <= how_many_ticks; ++i) {
196- dst.draw_line_strip({FloatPoint(static_cast<int32_t>(posx), inner_h - space_at_bottom),
197- FloatPoint(static_cast<int32_t>(posx), inner_h - space_at_bottom + 3)},
198+ dst.draw_line_strip({FloatPoint(static_cast<int32_t>(posx), inner_h - kSpaceBottom),
199+ FloatPoint(static_cast<int32_t>(posx), inner_h - kSpaceBottom + 3)},
200 kAxisLineColor, kAxisLinesWidth);
201
202 // The space at the end is intentional to have the tick centered
203@@ -259,7 +259,7 @@
204 const Image* xtick = UI::g_fh1->render
205 (xtick_text_style((boost::format("-%u ") % (max_x / how_many_ticks * i)).str()));
206 dst.blit
207- (Point(static_cast<int32_t>(posx), inner_h - space_at_bottom + 10),
208+ (Point(static_cast<int32_t>(posx), inner_h - kSpaceBottom + 10),
209 xtick, BlendMode::UseAlpha, UI::Align::kCenter);
210
211 posx -= sub;
212@@ -267,29 +267,32 @@
213
214 // draw yticks, one at full, one at half
215 dst.draw_line_strip({
216- FloatPoint(inner_w - space_at_right, spacing), FloatPoint(inner_w - space_at_right - 3, spacing)},
217+ FloatPoint(inner_w - kSpaceRight, kSpacing), FloatPoint(inner_w - kSpaceRight - 3, kSpacing)},
218 kAxisLineColor, kAxisLinesWidth);
219 dst.draw_line_strip({
220- FloatPoint(inner_w - space_at_right, spacing + ((inner_h - space_at_bottom) - spacing) / 2),
221- FloatPoint(inner_w - space_at_right - 3, spacing + ((inner_h - space_at_bottom) - spacing) / 2)},
222+ FloatPoint(inner_w - kSpaceRight, kSpacing + ((inner_h - kSpaceBottom) - kSpacing) / 2),
223+ FloatPoint(inner_w - kSpaceRight - 3, kSpacing + ((inner_h - kSpaceBottom) - kSpacing) / 2)},
224 kAxisLineColor, kAxisLinesWidth);
225
226 // print the used unit
227 const Image* xtick = UI::g_fh1->render(xtick_text_style(get_generic_unit_name(unit)));
228- dst.blit(Point(2, spacing + 2), xtick, BlendMode::UseAlpha, UI::Align::kCenterLeft);
229+ dst.blit(Point(2, kSpacing + 2), xtick, BlendMode::UseAlpha, UI::Align::kCenterLeft);
230 }
231
232 } // namespace
233
234 WuiPlotArea::WuiPlotArea
235 (UI::Panel * const parent,
236- int32_t const x, int32_t const y, int32_t const w, int32_t const h)
237+ int32_t const x, int32_t const y, int32_t const w, int32_t const h,
238+ uint32_t sample_rate, Plotmode plotmode)
239 :
240 UI::Panel (parent, x, y, w, h),
241-plotmode_(PLOTMODE_ABSOLUTE),
242-sample_rate_(0),
243+plotmode_(plotmode),
244+sample_rate_(sample_rate),
245 needs_update_(true),
246 lastupdate_(0),
247+xline_length_(get_inner_w() - kSpaceRight - kSpacing),
248+yline_length_(get_inner_h() - kSpaceBottom - kSpacing),
249 time_ms_(0),
250 highest_scale_(0),
251 sub_(0.0f),
252@@ -300,19 +303,19 @@
253 }
254
255
256-uint32_t WuiPlotArea::get_game_time() {
257+uint32_t WuiPlotArea::get_game_time() const {
258 uint32_t game_time = 0;
259
260 // Find running time of the game, based on the plot data
261 for (uint32_t plot = 0; plot < plotdata_.size(); ++plot)
262- if (game_time < plotdata_[plot].dataset->size() * sample_rate_)
263- game_time = plotdata_[plot].dataset->size() * sample_rate_;
264+ if (game_time < plotdata_[plot].absolute_data->size() * sample_rate_)
265+ game_time = plotdata_[plot].absolute_data->size() * sample_rate_;
266 return game_time;
267 }
268
269-std::vector<std::string> WuiPlotArea::get_labels() {
270+std::vector<std::string> WuiPlotArea::get_labels() const {
271 std::vector<std::string> labels;
272- for (int32_t i = 0; i < game_time_id_; i++) {
273+ for (uint32_t i = 0; i < game_time_id_; i++) {
274 Units unit = get_suggested_unit(time_in_ms[i], false);
275 labels.push_back(get_value_with_unit(unit, ms_to_unit(unit, time_in_ms[i])));
276 }
277@@ -320,7 +323,7 @@
278 return labels;
279 }
280
281-uint32_t WuiPlotArea::get_plot_time() {
282+uint32_t WuiPlotArea::get_plot_time() const {
283 if (time_ == TIME_GAME) {
284 // Start with the game time
285 uint32_t time_ms = get_game_time();
286@@ -331,14 +334,14 @@
287 // or a multiple of 2h
288 // or a multiple of 20h
289 // or a multiple of 4 days
290- if (time_ms > 8 * days) {
291- time_ms += - (time_ms % (4 * days)) + 4 * days;
292- } else if (time_ms > 40 * hours) {
293- time_ms += - (time_ms % (20 * hours)) + 20 * hours;
294- } else if (time_ms > 4 * hours) {
295- time_ms += - (time_ms % (2 * hours)) + 2 * hours;
296+ if (time_ms > 8 * kDays) {
297+ time_ms += - (time_ms % (4 * kDays)) + 4 * kDays;
298+ } else if (time_ms > 40 * kHours) {
299+ time_ms += - (time_ms % (20 * kHours)) + 20 * kHours;
300+ } else if (time_ms > 4 * kHours) {
301+ time_ms += - (time_ms % (2 * kHours)) + 2 * kHours;
302 } else {
303- time_ms += - (time_ms % (15 * minutes)) + 15 * minutes;
304+ time_ms += - (time_ms % (15 * kMinutes)) + 15 * kMinutes;
305 }
306 return time_ms;
307 } else {
308@@ -356,7 +359,7 @@
309 * We start to search with i=1 to ensure that at least one option besides
310 * "game" will be offered to the user.
311 */
312-int32_t WuiPlotArea::get_game_time_id() {
313+uint32_t WuiPlotArea::get_game_time_id() {
314 uint32_t game_time = get_game_time();
315 uint32_t i;
316 for (i = 1; i < 7 && time_in_ms[i] <= game_time; i++) {
317@@ -376,29 +379,47 @@
318 needs_update_ = false;
319 }
320
321+int32_t WuiPlotArea::initialize_update() {
322+ // Initialize
323+ for (uint32_t i = 0; i < plotdata_.size(); ++i) {
324+ plotdata_[i].relative_data->clear();
325+ }
326+ // Get range
327+ time_ms_ = get_plot_time();
328+ if (plotmode_ == Plotmode::kAbsolute) {
329+ sub_ =
330+ (xline_length_ - kSpaceLeftOfLabel)
331+ /
332+ (static_cast<float>(time_ms_)
333+ /
334+ static_cast<float>(sample_rate_));
335+ } else {
336+ sub_ = (xline_length_ - kSpaceLeftOfLabel) / static_cast<float>(KNoSamples);
337+ }
338+
339+ // How many do we aggregate when relative plotting
340+ return calc_how_many(time_ms_, sample_rate_);
341+}
342
343 // Find the maximum value.
344 void WuiPlotArea::update() {
345- float const xline_length = get_inner_w() - space_at_right - spacing;
346-
347- time_ms_ = get_plot_time();
348-
349- // How many do we take together when relative ploting
350- const int32_t how_many = calc_how_many(time_ms_, sample_rate_);
351+ const int32_t how_many = initialize_update();
352+
353+ // Calculate highest scale
354 highest_scale_ = 0;
355- if (plotmode_ == PLOTMODE_ABSOLUTE) {
356+ if (plotmode_ == Plotmode::kAbsolute) {
357 for (uint32_t i = 0; i < plotdata_.size(); ++i)
358 if (plotdata_[i].showplot) {
359- for (uint32_t l = 0; l < plotdata_[i].dataset->size(); ++l)
360- if (highest_scale_ < (*plotdata_[i].dataset)[l])
361- highest_scale_ = (*plotdata_[i].dataset)[l];
362+ for (uint32_t l = 0; l < plotdata_[i].absolute_data->size(); ++l) {
363+ if (highest_scale_ < (*plotdata_[i].absolute_data)[l]) {
364+ highest_scale_ = (*plotdata_[i].absolute_data)[l];
365+ }
366+ }
367 }
368 } else {
369 for (uint32_t plot = 0; plot < plotdata_.size(); ++plot) {
370 if (plotdata_[plot].showplot) {
371-
372- const std::vector<uint32_t> & dataset = *plotdata_[plot].dataset;
373-
374+ const std::vector<uint32_t> & dataset = *plotdata_[plot].absolute_data;
375 uint32_t add = 0;
376 // Relative data, first entry is always zero.
377 for (uint32_t i = 0; i < dataset.size(); ++i) {
378@@ -413,31 +434,21 @@
379 }
380 }
381
382- // Update the datasets
383- sub_ =
384- (xline_length - space_left_of_label)
385- /
386- (static_cast<float>(time_ms_)
387- /
388- static_cast<float>(sample_rate_));
389- for (uint32_t plot = 0; plot < plotdata_.size(); ++plot) {
390- if (plotdata_[plot].showplot) {
391- std::vector<uint32_t> const * dataset = plotdata_[plot].dataset;
392-
393- std::vector<uint32_t> data;
394- if (plotmode_ == PLOTMODE_RELATIVE) {
395+ // Calculate plot data
396+ if (plotmode_ == Plotmode::kRelative) {
397+ for (uint32_t plot = 0; plot < plotdata_.size(); ++plot) {
398+ if (plotdata_[plot].showplot) {
399+ std::vector<uint32_t> const * dataset = plotdata_[plot].absolute_data;
400 uint32_t add = 0;
401 // Relative data, first entry is always zero
402- data.push_back(0);
403+ plotdata_[plot].relative_data->push_back(0);
404 for (uint32_t i = 0; i < dataset->size(); ++i) {
405 add += (*dataset)[i];
406 if (0 == ((i + 1) % how_many)) {
407- data.push_back(add);
408+ plotdata_[plot].relative_data->push_back(add);
409 add = 0;
410 }
411 }
412- dataset = &data;
413- sub_ = (xline_length - space_left_of_label) / static_cast<float>(nr_samples);
414 }
415 }
416 }
417@@ -449,23 +460,26 @@
418 * Draw this. This is the main function
419 */
420 void WuiPlotArea::draw(RenderTarget & dst) {
421- float const xline_length = get_inner_w() - space_at_right - spacing;
422- float const yline_length = get_inner_h() - space_at_bottom - spacing;
423+ draw_plot(dst, get_inner_h() - kSpaceBottom, std::to_string(highest_scale_), highest_scale_);
424+}
425
426- draw_diagram(time_ms_, get_inner_w(), get_inner_h(), xline_length, dst);
427+void WuiPlotArea::draw_plot(RenderTarget& dst, float yoffset, const std::string& yscale_label,
428+ uint32_t highest_scale) {
429+ draw_diagram(time_ms_, get_inner_w(), get_inner_h(), xline_length_, dst);
430
431 // print the maximal value into the top right corner
432 draw_value
433- (std::to_string(highest_scale_), RGBColor(60, 125, 0),
434- Point(get_inner_w() - space_at_right - 2, spacing + 2), dst);
435+ (yscale_label, RGBColor(60, 125, 0),
436+ Point(get_inner_w() - kSpaceRight - 2, kSpacing + 2), dst);
437
438 // plot the pixels
439 for (uint32_t plot = 0; plot < plotdata_.size(); ++plot) {
440 if (plotdata_[plot].showplot) {
441- RGBColor color = plotdata_[plot].plotcolor;
442- std::vector<uint32_t> const * dataset = plotdata_[plot].dataset;
443 draw_plot_line
444- (dst, dataset, yline_length, highest_scale_, sub_, color, get_inner_h() - space_at_bottom);
445+ (dst,
446+ (plotmode_ == Plotmode::kRelative) ?
447+ plotdata_[plot].relative_data : plotdata_[plot].absolute_data,
448+ highest_scale, sub_, plotdata_[plot].plotcolor, yoffset);
449 }
450 }
451 }
452@@ -476,34 +490,37 @@
453 * \param sub horizontal difference between 2 y values
454 */
455 void WuiPlotArea::draw_plot_line
456- (RenderTarget & dst, std::vector<uint32_t> const * dataset, float const yline_length,
457+ (RenderTarget & dst, std::vector<uint32_t> const * dataset,
458 uint32_t const highest_scale, float const sub, RGBColor const color, int32_t const yoffset)
459 {
460- float posx = get_inner_w() - space_at_right;
461- const int lx = get_inner_w() - space_at_right;
462- int ly = yoffset;
463- // Init start point of the plot line with the first data value.
464- // This prevents that the plot starts always at zero
465- if (int value = (*dataset)[dataset->size() - 1]) {
466- ly -= static_cast<int32_t>(scale_value(yline_length, highest_scale, value));
467- }
468-
469- std::vector<FloatPoint> points;
470- points.emplace_back(lx, ly);
471-
472- for (int32_t i = dataset->size() - 1; i > 0 && posx > spacing; --i) {
473- int32_t const curx = static_cast<int32_t>(posx);
474- int32_t cury = yoffset;
475-
476- // Scale the line to the available space
477- if (int32_t value = (*dataset)[i]) {
478- const float length_y = scale_value(yline_length, highest_scale, value);
479- cury -= static_cast<int32_t>(length_y);
480- }
481- points.emplace_back(curx, cury);
482- posx -= sub;
483- }
484- dst.draw_line_strip(points, color, kPlotLinesWidth);
485+ if (!dataset->empty()) {
486+ float posx = get_inner_w() - kSpaceRight;
487+ const int lx = get_inner_w() - kSpaceRight;
488+ int ly = yoffset;
489+ // Init start point of the plot line with the first data value.
490+ // This prevents that the plot starts always at zero
491+
492+ if (int value = (*dataset)[dataset->size() - 1]) {
493+ ly -= static_cast<int32_t>(scale_value(yline_length_, highest_scale, value));
494+ }
495+
496+ std::vector<FloatPoint> points;
497+ points.emplace_back(lx, ly);
498+
499+ for (int32_t i = dataset->size() - 1; i > 0 && posx > kSpacing; --i) {
500+ int32_t const curx = static_cast<int32_t>(posx);
501+ int32_t cury = yoffset;
502+
503+ // Scale the line to the available space
504+ if (int32_t value = (*dataset)[i]) {
505+ const float length_y = scale_value(yline_length_, highest_scale, value);
506+ cury -= static_cast<int32_t>(length_y);
507+ }
508+ points.emplace_back(curx, cury);
509+ posx -= sub;
510+ }
511+ dst.draw_line_strip(points, color, kPlotLinesWidth);
512+ }
513 }
514
515 /*
516@@ -517,7 +534,8 @@
517 if (id >= plotdata_.size())
518 plotdata_.resize(id + 1);
519
520- plotdata_[id].dataset = data;
521+ plotdata_[id].absolute_data = data;
522+ plotdata_[id].relative_data = new std::vector<uint32_t>(); // Will be filled in the update() function.
523 plotdata_[id].showplot = false;
524 plotdata_[id].plotcolor = color;
525
526@@ -544,17 +562,9 @@
527 needs_update_ = true;
528 }
529
530-/*
531- * Set sample rate the data uses
532- */
533-void WuiPlotArea::set_sample_rate(uint32_t const id) {
534- sample_rate_ = id;
535- needs_update_ = true;
536-}
537-
538
539 void WuiPlotAreaSlider::draw(RenderTarget & dst) {
540- int32_t new_game_time_id = plot_area_.get_game_time_id();
541+ uint32_t new_game_time_id = plot_area_.get_game_time_id();
542 if (new_game_time_id != last_game_time_id_) {
543 last_game_time_id_ = new_game_time_id;
544 set_labels(plot_area_.get_labels());
545@@ -565,31 +575,27 @@
546
547 DifferentialPlotArea::DifferentialPlotArea
548 (UI::Panel * const parent,
549- int32_t const x, int32_t const y, int32_t const w, int32_t const h)
550+ int32_t const x, int32_t const y, int32_t const w, int32_t const h,
551+ uint32_t sample_rate, Plotmode plotmode)
552 :
553-WuiPlotArea (parent, x, y, w, h)
554+WuiPlotArea (parent, x, y, w, h, sample_rate, plotmode)
555 {
556 update();
557 }
558
559 void DifferentialPlotArea::update() {
560- float const xline_length = get_inner_w() - space_at_right - spacing;
561-
562- time_ms_ = get_plot_time();
563-
564- // How many do we take together when relative ploting
565- const int32_t how_many = calc_how_many(time_ms_, sample_rate_);
566-
567- // Find max and min value
568+ const int32_t how_many = initialize_update();
569+
570+ // Calculate highest scale
571 int32_t max = 0;
572 int32_t min = 0;
573
574- if (plotmode_ == PLOTMODE_ABSOLUTE) {
575+ if (plotmode_ == Plotmode::kAbsolute) {
576 for (uint32_t i = 0; i < plotdata_.size(); ++i)
577 if (plotdata_[i].showplot) {
578- for (uint32_t l = 0; l < plotdata_[i].dataset->size(); ++l) {
579- int32_t temp = (*plotdata_[i].dataset)[l] -
580- (*negative_plotdata_[i].dataset)[l];
581+ for (uint32_t l = 0; l < plotdata_[i].absolute_data->size(); ++l) {
582+ int32_t temp = (*plotdata_[i].absolute_data)[l] -
583+ (*negative_plotdata_[i].absolute_data)[l];
584 if (max < temp) max = temp;
585 if (min > temp) min = temp;
586 }
587@@ -598,8 +604,8 @@
588 for (uint32_t plot = 0; plot < plotdata_.size(); ++plot)
589 if (plotdata_[plot].showplot) {
590
591- const std::vector<uint32_t> & dataset = *plotdata_[plot].dataset;
592- const std::vector<uint32_t> & ndataset = *negative_plotdata_[plot].dataset;
593+ const std::vector<uint32_t> & dataset = *plotdata_[plot].absolute_data;
594+ const std::vector<uint32_t> & ndataset = *negative_plotdata_[plot].absolute_data;
595
596 int32_t add = 0;
597 // Relative data, first entry is always zero.
598@@ -616,77 +622,43 @@
599
600 // Use equal positive and negative range
601 min = abs(min);
602- highest_scale_ = 0;
603- if (min > max) {
604- highest_scale_ = min;
605- } else {
606- highest_scale_ = max;
607- }
608-
609- // plot the pixels
610- sub_ =
611- xline_length
612- /
613- (static_cast<float>(time_ms_)
614- /
615- static_cast<float>(sample_rate_));
616- for (uint32_t plot = 0; plot < plotdata_.size(); ++plot)
617- if (plotdata_[plot].showplot) {
618- std::vector<uint32_t> const * dataset = plotdata_[plot].dataset;
619- std::vector<uint32_t> const * ndataset = negative_plotdata_[plot].dataset;
620-
621- std::vector<uint32_t> data_;
622- if (plotmode_ == PLOTMODE_RELATIVE) {
623- int32_t add = 0;
624+ highest_scale_ = (min > max) ? min : max;
625+
626+ // Calculate plot data
627+ if (plotmode_ == Plotmode::kRelative) {
628+ for (uint32_t plot = 0; plot < plotdata_.size(); ++plot) {
629+ if (plotdata_[plot].showplot) {
630+ std::vector<uint32_t> const * dataset = plotdata_[plot].absolute_data;
631+ std::vector<uint32_t> const * ndataset = negative_plotdata_[plot].absolute_data;
632+ uint32_t add = 0;
633 // Relative data, first entry is always zero
634- data_.push_back(0);
635+ plotdata_[plot].relative_data->push_back(0);
636 for (uint32_t i = 0; i < dataset->size(); ++i) {
637 add += (*dataset)[i] - (*ndataset)[i];
638 if (0 == ((i + 1) % how_many)) {
639- data_.push_back(add);
640+ plotdata_[plot].relative_data->push_back(add);
641 add = 0;
642 }
643 }
644- dataset = &data_;
645- sub_ = xline_length / static_cast<float>(nr_samples);
646 }
647 }
648+ }
649 }
650
651 void DifferentialPlotArea::draw(RenderTarget & dst) {
652- float const xline_length = get_inner_w() - space_at_right - spacing;
653- float const yline_length = get_inner_h() - space_at_bottom - spacing;
654 // yoffset of the zero line
655- float const yoffset = spacing + ((get_inner_h() - space_at_bottom) - spacing) / 2;
656+ float const yoffset = kSpacing + ((get_inner_h() - kSpaceBottom) - kSpacing) / 2;
657+ draw_plot(dst, yoffset, std::to_string(highest_scale_), 2 * highest_scale_);
658
659- time_ms_ = get_plot_time();
660- draw_diagram(time_ms_, get_inner_w(), get_inner_h(), xline_length, dst);
661+ // Print the min value
662+ draw_value
663+ ((boost::format("-%u") % (highest_scale_)).str(), RGBColor(125, 0, 0),
664+ Point(get_inner_w() - kSpaceRight - 2, get_inner_h() - kSpacing - 15), dst);
665
666 // draw zero line
667- dst.draw_line_strip({FloatPoint(get_inner_w() - space_at_right, yoffset),
668- FloatPoint(get_inner_w() - space_at_right - xline_length, yoffset)},
669+ dst.draw_line_strip({FloatPoint(get_inner_w() - kSpaceRight, yoffset),
670+ FloatPoint(get_inner_w() - kSpaceRight - xline_length_, yoffset)},
671 kZeroLineColor, kPlotLinesWidth);
672-
673- // Print the min and max values
674- draw_value
675- (std::to_string(highest_scale_), RGBColor(60, 125, 0),
676- Point(get_inner_w() - space_at_right - 2, spacing + 2), dst);
677-
678- draw_value
679- ((boost::format("-%u") % highest_scale_).str(), RGBColor(125, 0, 0),
680- Point(get_inner_w() - space_at_right - 2, get_inner_h() - spacing - 15), dst);
681-
682- // plot the pixels
683- for (uint32_t plot = 0; plot < plotdata_.size(); ++plot)
684- if (plotdata_[plot].showplot) {
685-
686- RGBColor color = plotdata_[plot].plotcolor;
687- std::vector<uint32_t> const * dataset = plotdata_[plot].dataset;
688-
689- // Highest_scale represent the space between zero line and top.
690- // -> half of the whole differential plot area
691- draw_plot_line(dst, dataset, yline_length, highest_scale_ * 2, sub_, color, yoffset);
692- }
693 }
694
695 /**
696@@ -696,9 +668,10 @@
697 void DifferentialPlotArea::register_negative_plot_data
698 (uint32_t const id, std::vector<uint32_t> const * const data) {
699
700- if (id >= negative_plotdata_.size())
701+ if (id >= negative_plotdata_.size()) {
702 negative_plotdata_.resize(id + 1);
703+ }
704
705- negative_plotdata_[id].dataset = data;
706+ negative_plotdata_[id].absolute_data = data;
707 needs_update_ = true;
708 }
709
710=== modified file 'src/wui/plot_area.h'
711--- src/wui/plot_area.h 2016-03-19 17:30:37 +0000
712+++ src/wui/plot_area.h 2016-06-10 17:28:35 +0000
713@@ -44,16 +44,17 @@
714 TIME_16_HOURS,
715 TIME_GAME,
716 };
717- enum PLOTMODE {
718- // Always take the samples of some times together, so that the graph is
719- // not completely zigg-zagged.
720- PLOTMODE_RELATIVE,
721-
722- PLOTMODE_ABSOLUTE
723+ enum class Plotmode {
724+ // Always aggregate the samples of some time periods, so that the graph is
725+ // not completely zig-zagged.
726+ kRelative,
727+ kAbsolute
728 };
729
730+ // sample_rate is in in milliseconds
731 WuiPlotArea
732- (UI::Panel * parent, int32_t x, int32_t y, int32_t w, int32_t h);
733+ (UI::Panel * parent, int32_t x, int32_t y, int32_t w, int32_t h,
734+ uint32_t sample_rate, Plotmode plotmode);
735
736 /// Calls update() if needed
737 void think() override;
738@@ -65,51 +66,54 @@
739 needs_update_ = true;
740 }
741
742- void set_time_id(int32_t time) {
743+ void set_time_id(uint32_t time) {
744 if (time == game_time_id_)
745 set_time(TIME_GAME);
746 else
747 set_time(static_cast<TIME>(time));
748 needs_update_ = true;
749 }
750- TIME get_time() {return static_cast<TIME>(time_); }
751- int32_t get_time_id() {
752+ TIME get_time() const {return static_cast<TIME>(time_); }
753+ int32_t get_time_id() const {
754 if (time_ == TIME_GAME)
755 return game_time_id_;
756 else
757 return time_;
758 }
759- void set_sample_rate(uint32_t id); // in milliseconds
760
761- int32_t get_game_time_id();
762+ uint32_t get_game_time_id();
763
764 void register_plot_data
765 (uint32_t id, const std::vector<uint32_t> * data, RGBColor);
766 void show_plot(uint32_t id, bool t);
767
768- void set_plotmode(int32_t id) {plotmode_ = id;}
769-
770 void set_plotcolor(uint32_t id, RGBColor color);
771
772- std::vector<std::string> get_labels();
773+ std::vector<std::string> get_labels() const;
774
775 protected:
776+ void draw_plot(RenderTarget& dst, float yoffset, const std::string& yscale_label,
777+ uint32_t highest_scale);
778 void draw_plot_line
779- (RenderTarget & dst, std::vector<uint32_t> const * dataset, float const yline_length,
780+ (RenderTarget & dst, std::vector<uint32_t> const * dataset,
781 uint32_t const highest_scale, float const sub, RGBColor const color, int32_t yoffset);
782- uint32_t get_plot_time();
783+ uint32_t get_plot_time() const;
784 /// Recalculates the data
785 virtual void update();
786+ // Initializes relative_dataset and time scaling.
787+ // Returns how many values will be aggregated when relative plotting
788+ int32_t initialize_update();
789
790 struct PlotData {
791- const std::vector<uint32_t> * dataset;
792+ const std::vector<uint32_t> * absolute_data; // The absolute dataset
793+ std::vector<uint32_t> * relative_data; // The relative dataset
794 bool showplot;
795 RGBColor plotcolor;
796 };
797 std::vector<PlotData> plotdata_;
798
799- int32_t plotmode_;
800- int32_t sample_rate_;
801+ Plotmode plotmode_;
802+ uint32_t sample_rate_;
803
804 /// Whether there has ben a data update since the last time that think() was executed
805 bool needs_update_;
806@@ -117,15 +121,17 @@
807 uint32_t lastupdate_;
808
809 /// For first updating and then plotting the data
810+ float const xline_length_;
811+ float const yline_length_;
812 uint32_t time_ms_;
813 uint32_t highest_scale_;
814 float sub_;
815
816 private:
817- uint32_t get_game_time();
818+ uint32_t get_game_time() const;
819
820 TIME time_; // How much do you want to list
821- int32_t game_time_id_; // what label is used for TIME_GAME
822+ uint32_t game_time_id_; // what label is used for TIME_GAME
823 };
824
825 /**
826@@ -161,7 +167,7 @@
827
828 private:
829 WuiPlotArea & plot_area_;
830- int32_t last_game_time_id_;
831+ uint32_t last_game_time_id_;
832 };
833
834 /**
835@@ -172,7 +178,8 @@
836 struct DifferentialPlotArea : public WuiPlotArea {
837 public:
838 DifferentialPlotArea
839- (UI::Panel * parent, int32_t x, int32_t y, int32_t w, int32_t h);
840+ (UI::Panel * parent, int32_t x, int32_t y, int32_t w, int32_t h,
841+ uint32_t sample_rate, Plotmode plotmode);
842
843 void draw(RenderTarget &) override;
844
845@@ -184,13 +191,14 @@
846 void update() override;
847
848 private:
849-
850 /**
851- * for the negative plotdata only the values matter. The color and
852+ * For the negative plotdata, only the values matter. The color and
853 * visibility is determined by the normal plotdata.
854+ * We don't need relative data to fill - this is also done in the
855+ * normal plotdata
856 */
857 struct ReducedPlotData {
858- const std::vector<uint32_t> * dataset;
859+ const std::vector<uint32_t> * absolute_data;
860 };
861 std::vector<ReducedPlotData> negative_plotdata_;
862 };
863
864=== modified file 'src/wui/ware_statistics_menu.cc'
865--- src/wui/ware_statistics_menu.cc 2016-03-30 07:20:05 +0000
866+++ src/wui/ware_statistics_menu.cc 2016-06-10 17:28:35 +0000
867@@ -164,9 +164,9 @@
868 plot_production_ =
869 new WuiPlotArea
870 (tabs,
871- 0, 0, kPlotWidth, kPlotHeight + kSpacing);
872- plot_production_->set_sample_rate(STATISTICS_SAMPLE_TIME);
873- plot_production_->set_plotmode(WuiPlotArea::PLOTMODE_RELATIVE);
874+ 0, 0, kPlotWidth, kPlotHeight + kSpacing,
875+ kStatisticsSampleTime,
876+ WuiPlotArea::Plotmode::kRelative);
877
878 tabs->add
879 ("production", g_gr->images().get(pic_tab_production),
880@@ -175,9 +175,9 @@
881 plot_consumption_ =
882 new WuiPlotArea
883 (tabs,
884- 0, 0, kPlotWidth, kPlotHeight + kSpacing);
885- plot_consumption_->set_sample_rate(STATISTICS_SAMPLE_TIME);
886- plot_consumption_->set_plotmode(WuiPlotArea::PLOTMODE_RELATIVE);
887+ 0, 0, kPlotWidth, kPlotHeight + kSpacing,
888+ kStatisticsSampleTime,
889+ WuiPlotArea::Plotmode::kRelative);
890
891 tabs->add
892 ("consumption", g_gr->images().get(pic_tab_consumption),
893@@ -186,9 +186,9 @@
894 plot_economy_ =
895 new DifferentialPlotArea
896 (tabs,
897- 0, 0, kPlotWidth, kPlotHeight + kSpacing);
898- plot_economy_->set_sample_rate(STATISTICS_SAMPLE_TIME);
899- plot_economy_->set_plotmode(WuiPlotArea::PLOTMODE_RELATIVE);
900+ 0, 0, kPlotWidth, kPlotHeight + kSpacing,
901+ kStatisticsSampleTime,
902+ WuiPlotArea::Plotmode::kRelative);
903
904 tabs->add
905 ("economy_health", g_gr->images().get(pic_tab_economy),
906@@ -196,9 +196,9 @@
907
908 plot_stock_ = new WuiPlotArea
909 (tabs,
910- 0, 0, kPlotWidth, kPlotHeight + kSpacing);
911- plot_stock_->set_sample_rate(STATISTICS_SAMPLE_TIME);
912- plot_stock_->set_plotmode(WuiPlotArea::PLOTMODE_ABSOLUTE);
913+ 0, 0, kPlotWidth, kPlotHeight + kSpacing,
914+ kStatisticsSampleTime,
915+ WuiPlotArea::Plotmode::kAbsolute);
916
917 tabs->add
918 ("stock", g_gr->images().get(pic_tab_stock),

Subscribers

People subscribed via source and target branches

to status/vote changes: