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