Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
statslist.qc
Go to the documentation of this file.
1#include "statslist.qh"
3
5{
6 entity me;
8 me.configureXonoticStatsList(me);
9 return me;
10}
11
13{
14 me.configureXonoticListBox(me);
15 me.getStats(me);
16}
17
18string XonoticStatsList_convertDate(string input)
19{
20 // 2013-12-21
21 // 0123456789
22 if(strlen(input) != 10)
23 return input;
24
25 string monthname = "";
26
27 switch(stof(substring(input, 5, 2)))
28 {
29 case 1: monthname = _("January"); break;
30 case 2: monthname = _("February"); break;
31 case 3: monthname = _("March"); break;
32 case 4: monthname = _("April"); break;
33 case 5: monthname = _("May"); break;
34 case 6: monthname = _("June"); break;
35 case 7: monthname = _("July"); break;
36 case 8: monthname = _("August"); break;
37 case 9: monthname = _("September"); break;
38 case 10: monthname = _("October"); break;
39 case 11: monthname = _("November"); break;
40 case 12: monthname = _("December"); break;
41 default: return input; // failed, why?
42 }
43
44 // without no-c-format this string looks messed up in Transifex since only %d is a valid c placeholder
45 /* xgettext:no-c-format */
46 string date = ZCTX(_("DATE^%m %d, %Y"));
47 date = strreplace("%Y", substring(input, 0, 4), date);
48 date = strreplace("%d", ftos(stof(substring(input, 8, 2))), date); // ftos-stof removes leading 0
49 date = strreplace("%m", monthname, date);
50 return date;
51}
52
54{
55 LOG_TRACE("XonoticStatsList_getStats() at time: ", ftos(time));
56 // delete the old buffer if it exists
57 if(me.listStats >= 0)
58 buf_del(me.listStats);
59
60 // create the new buffer if we have a stats buffer
61 if(PS_D_IN_DB >= 0)
62 me.listStats = buf_create();
63
64 // now confirmation, if we didn't create a buffer then just return now
65 if(me.listStats < 0)
66 {
67 me.nItems = 0;
68 return;
69 }
70
71 float order = 0;
72 string e = "", en = "", data = "";
73
74 string outstr = ""; // NOTE: out string MUST use underscores for spaces here, we'll replace them later
75 string orderstr = "";
76
77 float out_total_matches = -1;
78 float out_total_wins = -1;
79 float out_total_losses = -1;
80
81 float out_total_kills = -1;
82 float out_total_deaths = -1;
83
84 for(e = PS_D_IN_EVL; (en = db_get(PS_D_IN_DB, e)) != ""; e = en)
85 {
86 order = 0;
87 outstr = "";
88 orderstr = "";
89 data = db_get(PS_D_IN_DB, sprintf("#%s", e));
90
91 // non-gametype specific stuff
92 switch(e)
93 {
94 case "overall/joined_dt":
95 {
96 order = 1;
97 outstr = _("Joined:");
99 break;
100 }
101 case "overall/last_seen_dt":
102 {
103 order = 1;
104 outstr = _("Last match:");
105 data = XonoticStatsList_convertDate(car(data));
106 break;
107 }
108 case "overall/alivetime":
109 {
110 order = 1;
111 outstr = _("Time played:");
112 data = process_time(3, stof(data));
113 break;
114 }
115 case "overall/favorite-map":
116 {
117 order = 2;
118 outstr = _("Favorite map:");
119 data = car(data);
120 break;
121 }
122 case "overall/matches":
123 {
124 order = -1;
125 out_total_matches = stof(data);
126 break;
127 }
128 case "overall/wins":
129 {
130 order = -1;
131 out_total_wins = stof(data);
132 break;
133 }
134 case "overall/total-kills":
135 {
136 order = -1;
137 out_total_kills = stof(data);
138 break;
139 }
140 case "overall/total-deaths":
141 {
142 order = -1;
143 out_total_deaths = stof(data);
144 break;
145 }
146 }
147
148 if((order == -1) && (out_total_matches >= 0) && (out_total_wins >= 0))
149 {
150 bufstr_add(me.listStats, sprintf("003%s\n%d", _("Matches:"), out_total_matches), true);
151
152 if(out_total_matches > 0) // don't show extra info if there are no matches played
153 {
154 out_total_losses = max(0, (out_total_matches - out_total_wins));
155 bufstr_add(me.listStats, sprintf("003%s\n%d/%d", _("Wins/Losses:"), out_total_wins, out_total_losses), true);
156 bufstr_add(me.listStats, sprintf("004%s\n%s", _("Win percentage:"), ftos_decimals_percentage(out_total_wins / out_total_matches, 0)), true);
157 }
158
159 out_total_matches = -1;
160 out_total_wins = -1;
161 out_total_losses = -1;
162 continue;
163 }
164
165 if((order == -1) && (out_total_kills >= 0) && (out_total_deaths >= 0))
166 {
167 bufstr_add(me.listStats, sprintf("005%s\n%d/%d", _("Kills/Deaths:"), out_total_kills, out_total_deaths), true);
168
169 // if there are no deaths, just show kill count
170 if(out_total_deaths == 0)
171 out_total_deaths = 1;
172
173 bufstr_add(me.listStats, sprintf("006%s\n%.2f", _("Kill ratio:"), (out_total_kills / out_total_deaths)), true);
174
175 out_total_kills = -1;
176 out_total_deaths = -1;
177 continue;
178 }
179
180 // gametype specific stuff
181 if(order > 0)
182 {
183 orderstr = sprintf("%03d", order);
184 }
185 else
186 {
187 float dividerpos = strstrofs(e, "/", 0);
188
189 string gametype = substring(e, 0, dividerpos);
190 if(gametype == "overall") { continue; }
191
192 string event = substring(e, (dividerpos + 1), strlen(e) - (dividerpos + 1));
193
194 // if we are ranked, read these sets of possible options
195 if(stof(db_get(PS_D_IN_DB, sprintf("#%s/rank", gametype))))
196 {
197 switch(event)
198 {
199 case "matches":
200 {
201 order = 1;
202 outstr = _("Matches:");
203 break;
204 }
205 #if 0
206 case "skill":
207 {
208 order = 2;
209 outstr = _("Skill:");
210 data = sprintf("%d", stof(data));
211 break;
212 }
213 case "favorite-map":
214 {
215 order = 3;
216 outstr = _("Favorite map:");
217 break;
218 }
219 #endif
220
221 default: continue; // nothing to see here
222 }
223
224 outstr = strcat(strtoupper(gametype), " ", outstr);
225 // now set up order for sorting later
226 orderstr = sprintf("%2.2s%d", gametype, order);
227 }
228 else if(event == "matches")
229 {
230 outstr = _("Matches:");
231 outstr = strcat(strtoupper(gametype), " ", outstr);
232 data = sprintf(_("%d (unranked)"), stof(data));
233
234 // unranked gametypes ALWAYS get put last
235 orderstr = "zzz";
236 }
237 else { continue; }
238 }
239
240 bufstr_add(me.listStats, sprintf("%s%s\n%s", orderstr, outstr, data), true);
241 }
242
243 me.nItems = buf_getsize(me.listStats);
244 if(me.nItems > 0)
245 buf_sort(me.listStats, 128, false);
246}
247
249{
250 if(me.nItems > 0)
251 buf_del(me.listStats);
252}
253
254void XonoticStatsList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
255{
256 me.itemAbsSize = '0 0 0';
257 SUPER(XonoticStatsList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
258
259 me.itemAbsSize.y = absSize.y * me.itemHeight;
260 me.itemAbsSize.x = absSize.x * (1 - me.controlWidth);
261 me.realFontSize.y = me.fontSize / me.itemAbsSize.y;
262 me.realFontSize.x = me.fontSize / me.itemAbsSize.x;
263 me.realUpperMargin = 0.5 * (1 - me.realFontSize.y);
264
265#if 0
266 me.columnNameOrigin = me.realFontSize.x;
267 me.columnNameSize = 0.5 - me.realFontSize.x; // end halfway at maximum length
268 me.columnDataOrigin = me.columnNameOrigin + me.columnNameSize;
269 me.columnDataSize = 1 - me.columnNameSize - me.realFontSize.x; // fill the rest of the control
270#else
271 me.columnNameOrigin = me.realFontSize.x;
272 me.columnNameSize = 1 - 2 * me.realFontSize.x;
273#endif
274}
275
276void XonoticStatsList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
277{
278 if(isFocused)
279 {
280 me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
281 draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
282 }
283
284 string data = bufstr_get(me.listStats, i);
285 int ofs = strstrofs(data, "\n", 0);
286
287 string s = substring(data, 3, ofs - 3);
288 s = draw_TextShortenToWidth(s, 0.5 * me.columnNameSize, 0, me.realFontSize);
289 draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, '1 1 1', SKINALPHA_TEXT, 1);
290
291 string d = substring(data, ofs + 1, strlen(data) - (ofs + 1));
292 d = draw_TextShortenToWidth(d, me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize), 0, me.realFontSize);
293 draw_Text(me.realUpperMargin * eY + (me.columnNameOrigin + 1 * (me.columnNameSize - draw_TextWidth(d, 0, me.realFontSize))) * eX, d, me.realFontSize, '1 1 1', SKINALPHA_TEXT, 1);
294}
295
300
302{
303 //DemoConfirm_ListClick_Check_Gamestatus(me);
304}
305
306float XonoticStatsList_keyDown(entity me, float scan, float ascii, float shift)
307{
308 if(scan == K_ENTER || scan == K_KP_ENTER)
309 {
310 //DemoConfirm_ListClick_Check_Gamestatus(me);
311 return 1;
312 }
313 else
314 {
315 return SUPER(XonoticStatsList).keyDown(me, scan, ascii, shift);
316 }
317}
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
entity gametype
Definition main.qh:43
ERASEABLE string process_time(float outputtype, int seconds)
Definition counting.qh:120
float time
#define strstrofs
#define strlen
#define buf_create
#define ZCTX(s)
Definition i18n.qh:68
float K_ENTER
Definition keycodes.qc:8
float K_KP_ENTER
Definition keycodes.qc:74
#define LOG_TRACE(...)
Definition log.qh:76
ERASEABLE string db_get(int db, string key)
Definition map.qh:91
string draw_TextShortenToWidth(string theText, float maxWidth, float ICanHasKallerz, vector SizeThxBye)
Definition draw.qc:377
void draw_Text(vector theOrigin, string theText, vector theSize, vector theColor, float theAlpha, float ICanHasKallerz)
Definition draw.qc:282
float draw_TextWidth(string theText, float ICanHasKallerz, vector SizeThxBye)
Definition draw.qc:304
void draw_Fill(vector theOrigin, vector theSize, vector theColor, float theAlpha)
Definition draw.qc:97
float getFadedAlpha(float currentAlpha, float startAlpha, float targetAlpha)
Definition util.qc:816
float stof(string val,...)
string substring(string s, float start, float length)
string ftos(float f)
float max(float f,...)
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
#define NEW(cname,...)
Definition oo.qh:117
#define SUPER(cname)
Definition oo.qh:231
void PlayerStats_PlayerDetail_CheckUpdate()
string PS_D_IN_EVL
int PS_D_IN_DB
vector
Definition self.qh:92
void XonoticStatsList_configureXonoticStatsList(entity me)
Definition statslist.qc:12
float XonoticStatsList_keyDown(entity me, float scan, float ascii, float shift)
Definition statslist.qc:306
void XonoticStatsList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
Definition statslist.qc:276
void XonoticStatsList_getStats(entity me)
Definition statslist.qc:53
entity makeXonoticStatsList()
Definition statslist.qc:4
void XonoticStatsList_showNotify(entity me)
Definition statslist.qc:296
void XonoticStatsList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
Definition statslist.qc:254
void XonoticStatsList_doubleClickListBoxItem(entity me, float i, vector where)
Definition statslist.qc:301
string XonoticStatsList_convertDate(string input)
Definition statslist.qc:18
void XonoticStatsList_destroy(entity me)
Definition statslist.qc:248
ERASEABLE string car(string s)
returns first word
Definition string.qh:259
ERASEABLE string ftos_decimals_percentage(float number, int decimals)
converts a percentage to a string with the indicated number of decimals
Definition string.qh:480
const vector eY
Definition vector.qh:45
const vector eX
Definition vector.qh:44