0b1498dc12e558acaadc01e05d2b5e8634013511
[supertux.git] / src / statistics.cpp
1 //
2 //  SuperTux -  A Jump'n Run
3 //  Copyright (C) 2004 Ricardo Cruz <rick2@aeiou.pt>
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 2
8 //  of the License, or (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 // 
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 //  02111-1307, USA.
19
20 #include <config.h>
21
22 #include "utils/lispreader.h"
23 #include "utils/lispwriter.h"
24 #include "video/drawing_context.h"
25 #include "app/gettext.h"
26 #include "app/globals.h"
27 #include "resources.h"
28 #include "statistics.h"
29
30 Statistics global_stats;
31
32 std::string
33 stat_name_to_string(int stat_enum)
34 {
35   switch(stat_enum)
36     {
37     case SCORE_STAT:
38       return "score";
39     case COINS_COLLECTED_STAT:
40       return "coins-collected";
41     case BADGUYS_KILLED_STAT:
42       return "badguys-killed";
43     case TIME_NEEDED_STAT:
44       return "time-needed";;
45     }
46   return "";
47 }
48
49 int
50 my_min(int a, int b)
51 {
52 if(a == -1)
53   return b;
54 if(b == -1)
55   return a;
56 return std::min(a, b);
57 }
58
59 Statistics::Statistics()
60 {
61   display_stat = 1;
62
63   for(int i = 0; i < NUM_STATS; i++)
64     for(int j = 0; j < 2; j++)
65       stats[i][j] = -1;
66 }
67
68 Statistics::~Statistics()
69 {
70 }
71
72 void
73 Statistics::parse(LispReader& reader)
74 {
75   for(int i = 0; i < NUM_STATS; i++)
76     {
77     reader.read_int(stat_name_to_string(i).c_str(), stats[i][SPLAYER]);
78     reader.read_int((stat_name_to_string(i) + "-total").c_str(), stats[i][STOTAL]);
79     }
80 }
81
82 void
83 Statistics::write(LispWriter& writer)
84 {
85   for(int i = 0; i < NUM_STATS; i++)
86     {
87     writer.write_int(stat_name_to_string(i), stats[i][SPLAYER]);
88     writer.write_int(stat_name_to_string(i) + "-total", stats[i][STOTAL]);
89     }
90 }
91
92 #define TOTAL_DISPLAY_TIME 3400
93 #define FADING_TIME         600
94
95 #define WMAP_INFO_LEFT_X  520
96 #define WMAP_INFO_RIGHT_X 740
97
98 void
99 Statistics::draw_worldmap_info(DrawingContext& context)
100 {
101   if(stats[SCORE_STAT][SPLAYER] == -1)  // not initialized yet
102     return;
103
104   if(timer.check())
105     {
106     timer.start(TOTAL_DISPLAY_TIME);
107     display_stat++;
108     if(display_stat >= NUM_STATS)
109       display_stat = 1;
110     }
111
112   char str[128];
113
114   context.draw_text(white_small_text, _("- Best Level Statistics -"),
115                     Vector((WMAP_INFO_LEFT_X + WMAP_INFO_RIGHT_X) / 2, 470),
116                     CENTER_ALLIGN, LAYER_GUI);
117
118   sprintf(str, _("Max score:"));
119   context.draw_text(white_small_text, str, Vector(WMAP_INFO_LEFT_X, 490), LEFT_ALLIGN, LAYER_GUI);
120
121   sprintf(str, "%d", stats[SCORE_STAT][SPLAYER]);
122   context.draw_text(white_small_text, str, Vector(WMAP_INFO_RIGHT_X, 490), RIGHT_ALLIGN, LAYER_GUI);
123
124   // draw other small info
125
126   int alpha;
127   if(timer.get_timegone() < FADING_TIME)
128     alpha = int(timer.get_timegone() * 255 / FADING_TIME);
129   else if(timer.get_timeleft() < FADING_TIME)
130     alpha = int(timer.get_timeleft() * 255 / FADING_TIME);
131   else
132     alpha = 255;
133
134   context.push_transform();
135   context.set_alpha(alpha);
136
137   if(display_stat == COINS_COLLECTED_STAT)
138     sprintf(str, _("Max coins collected:"));
139   else if(display_stat == BADGUYS_KILLED_STAT)
140     sprintf(str, _("Max fragging:"));
141   else// if(display_stat == TIME_NEEDED_STAT)
142     sprintf(str, _("Min time needed:"));
143
144   context.draw_text(white_small_text, str, Vector(WMAP_INFO_LEFT_X, 508), LEFT_ALLIGN, LAYER_GUI);
145
146   if(display_stat == COINS_COLLECTED_STAT)
147     sprintf(str, "%d/%d", stats[COINS_COLLECTED_STAT][SPLAYER],
148                           stats[COINS_COLLECTED_STAT][STOTAL]);
149   else if(display_stat == BADGUYS_KILLED_STAT)
150     sprintf(str, "%d/%d", stats[BADGUYS_KILLED_STAT][SPLAYER],
151                           stats[BADGUYS_KILLED_STAT][STOTAL]);
152   else// if(display_stat == TIME_NEEDED_STAT)
153     sprintf(str, "%d/%d", stats[TIME_NEEDED_STAT][SPLAYER],
154                           stats[TIME_NEEDED_STAT][STOTAL]);
155
156   context.draw_text(white_small_text, str, Vector(WMAP_INFO_RIGHT_X, 508), RIGHT_ALLIGN, LAYER_GUI);
157
158   context.pop_transform();
159 }
160
161 void
162 Statistics::draw_message_info(DrawingContext& context, std::string title)
163 {
164   if(stats[SCORE_STAT][SPLAYER] == -1)  // not initialized yet
165     return;
166
167   context.draw_text(gold_text, title, Vector(screen->w/2, 410), CENTER_ALLIGN, LAYER_GUI);
168
169   char str[128];
170
171   sprintf(str, _(    "Max score:             %d"), stats[SCORE_STAT][SPLAYER]);
172   context.draw_text(white_text, str, Vector(screen->w/2, 450), CENTER_ALLIGN, LAYER_GUI);
173
174   for(int i = 1; i < NUM_STATS; i++)
175     {
176     if(i == COINS_COLLECTED_STAT)
177       sprintf(str, _("Max coins collected:   %d / %d"),
178               stats[COINS_COLLECTED_STAT][SPLAYER],
179               stats[COINS_COLLECTED_STAT][STOTAL]);
180     else if(i == BADGUYS_KILLED_STAT)
181       sprintf(str, _("Max fragging:          %d / %d"),
182               stats[BADGUYS_KILLED_STAT][SPLAYER],
183               stats[BADGUYS_KILLED_STAT][STOTAL]);
184     else// if(i == TIME_NEEDED_STAT)
185       sprintf(str, _("Min time needed:       %d / %d"),
186               stats[TIME_NEEDED_STAT][SPLAYER],
187               stats[TIME_NEEDED_STAT][STOTAL]);
188
189
190     context.draw_text(white_small_text, str, Vector(screen->w/2, 462 + i*18), CENTER_ALLIGN, LAYER_GUI);
191     }
192 }
193
194 void
195 Statistics::add_points(int stat, int points)
196 {
197   stats[stat][SPLAYER] += points;
198 }
199
200 int
201 Statistics::get_points(int stat)
202 {
203   return stats[stat][SPLAYER];
204 }
205
206 void
207 Statistics::set_points(int stat, int points)
208 {
209   stats[stat][SPLAYER] = points;
210 }
211
212 void
213 Statistics::set_total_points(int stat, int points)
214 {
215   stats[stat][STOTAL] = points;
216 }
217
218 void
219 Statistics::reset()
220 {
221   for(int i = 0; i < NUM_STATS; i++)
222     stats[i][SPLAYER] = 0;
223 }
224
225 void
226 Statistics::merge(Statistics& stats_)
227 {
228   stats[SCORE_STAT][SPLAYER] = std::max(stats[SCORE_STAT][SPLAYER], stats_.stats[SCORE_STAT][SPLAYER]);
229   stats[COINS_COLLECTED_STAT][SPLAYER] = std::max(stats[COINS_COLLECTED_STAT][SPLAYER], stats_.stats[COINS_COLLECTED_STAT][SPLAYER]);
230   stats[BADGUYS_KILLED_STAT][SPLAYER] =
231     std::max(stats[BADGUYS_KILLED_STAT][SPLAYER], stats_.stats[BADGUYS_KILLED_STAT][SPLAYER]);
232   stats[TIME_NEEDED_STAT][SPLAYER] =
233     my_min(stats[TIME_NEEDED_STAT][SPLAYER], stats_.stats[TIME_NEEDED_STAT][SPLAYER]);
234
235   stats[COINS_COLLECTED_STAT][STOTAL] = stats_.stats[COINS_COLLECTED_STAT][STOTAL];
236   stats[BADGUYS_KILLED_STAT][STOTAL] = stats_.stats[BADGUYS_KILLED_STAT][STOTAL];
237   stats[TIME_NEEDED_STAT][STOTAL] = stats_.stats[TIME_NEEDED_STAT][STOTAL];
238 }
239
240 void
241 Statistics::operator+=(const Statistics& stats_)
242 {
243   for(int i = 0; i < NUM_STATS; i++)
244     {
245     if(stats_.stats[i][SPLAYER] == -1)
246       continue;
247     stats[i][SPLAYER] += stats_.stats[i][SPLAYER];
248     if(stats_.stats[i][STOTAL] != -1)
249       stats[i][STOTAL] += stats_.stats[i][STOTAL];
250     }
251 }