Added Total to statistics.
[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 "utils/lispreader.h"
21 #include "utils/lispwriter.h"
22 #include "statistics.h"
23 #include "video/drawing_context.h"
24 #include "app/gettext.h"
25 #include "app/globals.h"
26 #include "resources.h"
27
28 Statistics global_stats;
29
30 std::string
31 stat_name_to_string(int stat_enum)
32 {
33   switch(stat_enum)
34     {
35     case SCORE_STAT:
36       return "score";
37     case COINS_COLLECTED_STAT:
38       return "coins-collected";
39     case BADGUYS_KILLED_STAT:
40       return "badguys-killed";
41     case TIME_NEEDED_STAT:
42       return "time-needed";;
43     }
44 }
45
46 int
47 my_min(int a, int b)
48 {
49 if(a == -1)
50   return b;
51 if(b == -1)
52   return a;
53 return std::min(a, b);
54 }
55
56 Statistics::Statistics()
57 {
58   timer.init(true);
59   display_stat = 1;
60
61   for(int i = 0; i < NUM_STATS; i++)
62     for(int j = 0; j < 2; j++)
63       stats[i][j] = -1;
64 }
65
66 Statistics::~Statistics()
67 {
68 }
69
70 void
71 Statistics::parse(LispReader& reader)
72 {
73   for(int i = 0; i < NUM_STATS; i++)
74     {
75     reader.read_int(stat_name_to_string(i).c_str(), stats[i][SPLAYER]);
76     reader.read_int((stat_name_to_string(i) + "-total").c_str(), stats[i][STOTAL]);
77     }
78 }
79
80 void
81 Statistics::write(LispWriter& writer)
82 {
83   for(int i = 0; i < NUM_STATS; i++)
84     {
85     writer.write_int(stat_name_to_string(i), stats[i][SPLAYER]);
86     writer.write_int(stat_name_to_string(i) + "-total", stats[i][STOTAL]);
87     }
88 }
89
90 #define TOTAL_DISPLAY_TIME 3400
91 #define FADING_TIME         600
92
93 #define WMAP_INFO_LEFT_X  540
94 #define WMAP_INFO_RIGHT_X 720
95
96 void
97 Statistics::draw_worldmap_info(DrawingContext& context)
98 {
99   if(stats[SCORE_STAT][SPLAYER] == -1)  // not initialized yet
100     return;
101
102   if(!timer.check())
103     {
104     timer.start(TOTAL_DISPLAY_TIME);
105     display_stat++;
106     if(display_stat >= NUM_STATS)
107       display_stat = 1;
108     }
109
110   int alpha;
111   if(timer.get_gone() < FADING_TIME)
112     alpha = timer.get_gone() * 255 / FADING_TIME;
113   else if(timer.get_left() < FADING_TIME)
114     alpha = timer.get_left() * 255 / FADING_TIME;
115   else
116     alpha = 255;
117
118   char str[128];
119
120   context.draw_text(white_small_text, _("Best Level Statistics"),
121                     Vector((WMAP_INFO_LEFT_X + WMAP_INFO_RIGHT_X) / 2, 490),
122                     CENTER_ALLIGN, LAYER_GUI);
123
124   sprintf(str, _("Max score:"));
125   context.draw_text(white_small_text, str, Vector(WMAP_INFO_LEFT_X, 506), LEFT_ALLIGN, LAYER_GUI);
126
127   sprintf(str, "%d", stats[SCORE_STAT][SPLAYER]);
128   context.draw_text(white_small_text, str, Vector(WMAP_INFO_RIGHT_X, 506), RIGHT_ALLIGN, LAYER_GUI);
129
130   // draw other small info
131
132   if(display_stat == COINS_COLLECTED_STAT)
133     sprintf(str, _("Max coins collected:"));
134   else if(display_stat == BADGUYS_KILLED_STAT)
135     sprintf(str, _("Max fragging:"));
136   else// if(display_stat == TIME_NEEDED_STAT)
137     sprintf(str, _("Min time needed:"));
138
139   context.draw_text(white_small_text, str, Vector(WMAP_INFO_LEFT_X, 522), LEFT_ALLIGN, LAYER_GUI, NONE_EFFECT, alpha);
140
141   if(display_stat == COINS_COLLECTED_STAT)
142     sprintf(str, "%d/%d", stats[COINS_COLLECTED_STAT][SPLAYER],
143                           stats[COINS_COLLECTED_STAT][STOTAL]);
144   else if(display_stat == BADGUYS_KILLED_STAT)
145     sprintf(str, "%d/%d", stats[BADGUYS_KILLED_STAT][SPLAYER],
146                           stats[BADGUYS_KILLED_STAT][STOTAL]);
147   else// if(display_stat == TIME_NEEDED_STAT)
148     sprintf(str, "%d/%d", stats[TIME_NEEDED_STAT][SPLAYER],
149                           stats[TIME_NEEDED_STAT][STOTAL]);
150
151   context.draw_text(white_small_text, str, Vector(WMAP_INFO_RIGHT_X, 522), RIGHT_ALLIGN, LAYER_GUI, NONE_EFFECT, alpha);
152 }
153
154 void
155 Statistics::draw_message_info(DrawingContext& context, std::string title)
156 {
157   if(stats[SCORE_STAT][SPLAYER] == -1)  // not initialized yet
158     return;
159
160   context.draw_text(gold_text, title, Vector(screen->w/2, 410), CENTER_ALLIGN, LAYER_GUI);
161
162   char str[128];
163
164   sprintf(str, _(    "Max score:           %d"), stats[SCORE_STAT][SPLAYER]);
165   context.draw_text(white_text, str, Vector(screen->w/2, 450), CENTER_ALLIGN, LAYER_GUI);
166
167   for(int i = 1; i < NUM_STATS; i++)
168     {
169     if(i == COINS_COLLECTED_STAT)
170       sprintf(str, _("Max coins collected: %d"), ((float)stats[COINS_COLLECTED_STAT][SPLAYER] /
171                                                  (float)stats[COINS_COLLECTED_STAT][STOTAL]) * 100);
172     else if(i == BADGUYS_KILLED_STAT)
173       sprintf(str, _("Max fragging:        %d"), ((float)stats[BADGUYS_KILLED_STAT][SPLAYER] /
174                                                  (float)stats[BADGUYS_KILLED_STAT][STOTAL]) * 100);
175     else// if(i == TIME_NEEDED_STAT)
176       sprintf(str, _("Min time needed:     %d"), ((float)stats[TIME_NEEDED_STAT][SPLAYER] /
177                                                  (float)stats[TIME_NEEDED_STAT][STOTAL]) * 100);
178
179     context.draw_text(white_small_text, str, Vector(screen->w/2, 462 + i*18), CENTER_ALLIGN, LAYER_GUI);
180     }
181 }
182
183 void
184 Statistics::add_points(int stat, int points)
185 {
186   stats[stat][SPLAYER] += points;
187 }
188
189 int
190 Statistics::get_points(int stat)
191 {
192   return stats[stat][SPLAYER];
193 }
194
195 void
196 Statistics::set_points(int stat, int points)
197 {
198   stats[stat][SPLAYER] = points;
199 }
200
201 void
202 Statistics::set_total_points(int stat, int points)
203 {
204   stats[stat][STOTAL] = points;
205 }
206
207 void
208 Statistics::reset()
209 {
210   for(int i = 0; i < NUM_STATS; i++)
211     stats[i][SPLAYER] = 0;
212 }
213
214 void
215 Statistics::merge(Statistics& stats_)
216 {
217   stats[SCORE_STAT][SPLAYER] = std::max(stats[SCORE_STAT][SPLAYER], stats_.stats[SCORE_STAT][SPLAYER]);
218   stats[COINS_COLLECTED_STAT][SPLAYER] = std::max(stats[COINS_COLLECTED_STAT][SPLAYER], stats_.stats[COINS_COLLECTED_STAT][SPLAYER]);
219   stats[BADGUYS_KILLED_STAT][SPLAYER] =
220     std::max(stats[BADGUYS_KILLED_STAT][SPLAYER], stats_.stats[BADGUYS_KILLED_STAT][SPLAYER]);
221   stats[TIME_NEEDED_STAT][SPLAYER] =
222     my_min(stats[TIME_NEEDED_STAT][SPLAYER], stats_.stats[TIME_NEEDED_STAT][SPLAYER]);
223
224   stats[COINS_COLLECTED_STAT][STOTAL] = stats_.stats[COINS_COLLECTED_STAT][STOTAL];
225   stats[BADGUYS_KILLED_STAT][STOTAL] = stats_.stats[BADGUYS_KILLED_STAT][STOTAL];
226   stats[TIME_NEEDED_STAT][STOTAL] = stats_.stats[TIME_NEEDED_STAT][STOTAL];
227 }
228
229 void
230 Statistics::operator+=(const Statistics& stats_)
231 {
232   for(int i = 0; i < NUM_STATS; i++)
233     {
234     stats[i][SPLAYER] += stats_.stats[i][SPLAYER];
235     if(stats_.stats[i][STOTAL] != -1)
236       stats[i][STOTAL] += stats_.stats[i][STOTAL];
237     }
238 }