1 /*
2 * Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com)
3 * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu)
4 * Copyright (C) 1999,2000 D.Moreaux (vapula@linuxbe.org)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20 #define LADDER_INTERNAL_ACCESS
21 #include "common/setup_before.h"
22 #ifdef HAVE_STDDEF_H
23 # include <stddef.h>
24 #else
25 # ifndef NULL
26 # define NULL ((void *)0)
27 # endif
28 #endif
29 #ifdef STDC_HEADERS
30 # include <stdlib.h>
31 #else
32 # ifdef HAVE_MALLOC_H
33 # include <malloc.h>
34 # endif
35 #endif
36 #ifdef HAVE_STRING_H
37 # include <string.h>
38 #else
39 # ifdef HAVE_STRINGS_H
40 # include <strings.h>
41 # endif
42 #endif
43 #include <errno.h>
44 #include <compat/strerror.h>
45 #include "common/field_sizes.h"
46 #include "account.h"
47 #include "account_wrap.h"
48 #include "common/eventlog.h"
49 #include "common/util.h"
50 #include "game.h"
51 #include "common/tag.h"
52 #include "common/list.h"
53 #include "common/bnettime.h"
54 #include "prefs.h"
55 #include "common/hashtable.h"
56 #include "ladder_calc.h"
57 #include "ladder.h"
58 #include "compat/strcasecmp.h"
59 #include "compat/strncasecmp.h"
60 #include "ladder_binary.h"
61 #include "storage.h"
62 #include "account.h"
63 #include "common/bnet_protocol.h"
64 #include "common/xalloc.h"
65 #include "common/setup_after.h"
66
67 #define MaxRankKeptInLadder 1000
68
69 /* for War3 XP computations */
70 static t_xpcalc_entry * xpcalc;
71 static t_xplevel_entry * xplevels;
72 int w3_xpcalc_maxleveldiff;
73
74 const char * WAR3_solo_file = "WAR3_solo";
75 const char * W3XP_solo_file = "W3XP_solo";
76 const char * WAR3_team_file = "WAR3_team";
77 const char * W3XP_team_file = "W3XP_team";
78 const char * WAR3_ffa_file = "WAR3_ffa";
79 const char * W3XP_ffa_file = "W3XP_ffa";
80 const char * WAR3_at_file = "WAR3_atteam";
81 const char * W3XP_at_file = "W3XP_atteam";
82 const char * STAR_ar_file = "STAR_active_rating";
83 const char * STAR_cr_file = "STAR_current_rating";
84 const char * SEXP_ar_file = "SEXP_active_rating";
85 const char * SEXP_cr_file = "SEXP_current_rating";
86 const char * W2BN_ar_file = "W2BN_active_rating";
87 const char * W2BN_cr_file = "W2BN_current_rating";
88 const char * W2BN_ari_file = "W2BN_active_rating_iron";
89 const char * W2BN_cri_file = "W2BN_current_rating_iron";
90 const char * std_end = ".dat";
91 const char * xml_end = ".xml";
92
93 char * ladder_id_str[] = {"0","1","","3","","solo","team","ffa"};
94
95 char * WAR3_solo_filename, * WAR3_team_filename, * WAR3_ffa_filename, * WAR3_at_filename;
96 char * W3XP_solo_filename, * W3XP_team_filename, * W3XP_ffa_filename, * W3XP_at_filename;
97 char * STAR_ar_filename, * STAR_cr_filename, * SEXP_ar_filename, * SEXP_cr_filename;
98 char * W2BN_ar_filename, * W2BN_cr_filename, * W2BN_ari_filename, * W2BN_cri_filename;
99
100 t_ladder WAR3_solo_ladder, WAR3_team_ladder, WAR3_ffa_ladder, WAR3_at_ladder;
101 t_ladder W3XP_solo_ladder, W3XP_team_ladder, W3XP_ffa_ladder, W3XP_at_ladder;
102 t_ladder STAR_active_rating, STAR_active_wins, STAR_active_games,
103 STAR_current_rating, STAR_current_wins, STAR_current_games;
104 t_ladder SEXP_active_rating, SEXP_active_wins, SEXP_active_games,
105 SEXP_current_rating, SEXP_current_wins, SEXP_current_games;
106 t_ladder W2BN_active_rating, W2BN_active_wins, W2BN_active_games,
107 W2BN_active_rating_ironman, W2BN_active_wins_ironman, W2BN_active_games_ironman;
108 t_ladder W2BN_current_rating, W2BN_current_wins, W2BN_current_games,
109 W2BN_current_rating_ironman, W2BN_current_wins_ironman, W2BN_current_games_ironman;
110
111 t_ladder_internal * last_internal = NULL;
112 t_ladder * last_ladder = NULL;
113 int last_rank = 0;
114
115 /*
116 * Make the current ladder statistics the active ones.
117 */
118
119 extern int ladder_make_active(t_ladder *current, t_ladder *active,int set_attributes);
120
ladderlist_make_all_active(void)121 extern int ladderlist_make_all_active(void)
122 {
123 ladder_make_active(ladder_cr(CLIENTTAG_STARCRAFT_UINT,ladder_id_normal), ladder_ar(CLIENTTAG_STARCRAFT_UINT,ladder_id_normal),1);
124 ladder_make_active(ladder_cw(CLIENTTAG_STARCRAFT_UINT,ladder_id_normal), ladder_aw(CLIENTTAG_STARCRAFT_UINT,ladder_id_normal),0);
125 ladder_make_active(ladder_cg(CLIENTTAG_STARCRAFT_UINT,ladder_id_normal), ladder_ag(CLIENTTAG_STARCRAFT_UINT,ladder_id_normal),0);
126 ladder_make_active(ladder_cr(CLIENTTAG_BROODWARS_UINT,ladder_id_normal), ladder_ar(CLIENTTAG_BROODWARS_UINT,ladder_id_normal),1);
127 ladder_make_active(ladder_cw(CLIENTTAG_BROODWARS_UINT,ladder_id_normal), ladder_aw(CLIENTTAG_BROODWARS_UINT,ladder_id_normal),0);
128 ladder_make_active(ladder_cg(CLIENTTAG_BROODWARS_UINT,ladder_id_normal), ladder_ag(CLIENTTAG_BROODWARS_UINT,ladder_id_normal),0);
129 ladder_make_active(ladder_cr(CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal), ladder_ar(CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal),1);
130 ladder_make_active(ladder_cw(CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal), ladder_aw(CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal),0);
131 ladder_make_active(ladder_cg(CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal), ladder_ag(CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal),0);
132 ladder_make_active(ladder_cr(CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),ladder_ar(CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),1);
133 ladder_make_active(ladder_cw(CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),ladder_aw(CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),0);
134 ladder_make_active(ladder_cg(CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),ladder_ag(CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),0);
135 ladder_update_all_accounts();
136 return 0;
137 }
138
139
140 /*
141 * Prepare an account for first ladder play if necessary.
142 */
ladder_init_account(t_account * account,t_clienttag clienttag,t_ladder_id id)143 extern int ladder_init_account(t_account * account, t_clienttag clienttag, t_ladder_id id)
144 {
145 int uid;
146
147 if (!account)
148 {
149 eventlog(eventlog_level_error,__FUNCTION__,"got NULL account");
150 return -1;
151 }
152 if (!clienttag)
153 {
154 eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag");
155 return -1;
156 }
157
158 if (account_get_ladder_rating(account,clienttag,id)==0)
159 {
160 if (account_get_ladder_wins(account,clienttag,id)+
161 account_get_ladder_losses(account,clienttag,id)>0) /* no ladder games so far... */
162 {
163 eventlog(eventlog_level_warn,__FUNCTION__,"account for \"%s\" (%s) has %u wins and %u losses but has zero rating",account_get_name(account),clienttag_uint_to_str(clienttag),account_get_ladder_wins(account,clienttag,id),account_get_ladder_losses(account,clienttag,id));
164 return -1;
165 }
166 account_adjust_ladder_rating(account,clienttag,id,prefs_get_ladder_init_rating());
167
168 uid = account_get_uid(account);
169
170 war3_ladder_add(ladder_cr(clienttag,id),uid,0,account_get_ladder_rating(account,clienttag,id),account,0,clienttag);
171 war3_ladder_add(ladder_cw(clienttag,id),uid,0,0,account,0,clienttag);
172 war3_ladder_add(ladder_cg(clienttag,id),uid,0,0,account,0,clienttag);
173
174 eventlog(eventlog_level_info,__FUNCTION__,"initialized account for \"%s\" for \"%s\" ladder",account_get_name(account),clienttag_uint_to_str(clienttag));
175 }
176
177 return 0;
178 }
179
180
181 /*
182 * Update player ratings, rankings, etc due to game results.
183 */
ladder_update(t_clienttag clienttag,t_ladder_id id,unsigned int count,t_account ** players,t_game_result * results,t_ladder_info * info,t_ladder_option opns)184 extern int ladder_update(t_clienttag clienttag, t_ladder_id id, unsigned int count, t_account * * players, t_game_result * results, t_ladder_info * info, t_ladder_option opns)
185 {
186 unsigned int curr;
187 unsigned int winners=0;
188 unsigned int losers=0;
189 unsigned int draws=0;
190 int uid;
191
192 if (count<1 || count>8)
193 {
194 eventlog(eventlog_level_error,__FUNCTION__,"got invalid player count %u",count);
195 return -1;
196 }
197 if (!players)
198 {
199 eventlog(eventlog_level_error,__FUNCTION__,"got NULL players");
200 return -1;
201 }
202 if (!results)
203 {
204 eventlog(eventlog_level_error,__FUNCTION__,"got NULL results");
205 return -1;
206 }
207 if (!clienttag)
208 {
209 eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag");
210 return -1;
211 }
212 if (!info)
213 {
214 eventlog(eventlog_level_error,__FUNCTION__,"got NULL info");
215 return -1;
216 }
217
218 for (curr=0; curr<count; curr++)
219 {
220 if (!players[curr])
221 {
222 eventlog(eventlog_level_error,__FUNCTION__,"got NULL player[%u] (of %u)",curr,count);
223 return -1;
224 }
225
226 switch (results[curr])
227 {
228 case game_result_win:
229 winners++;
230 break;
231 case game_result_loss:
232 losers++;
233 break;
234 case game_result_draw:
235 draws++;
236 break;
237 case game_result_disconnect:
238 if (opns&ladder_option_disconnectisloss)
239 losers++;
240 break;
241 default:
242 eventlog(eventlog_level_error,__FUNCTION__,"bad results[%u]=%u",curr,(unsigned int)results[curr]);
243 return -1;
244 }
245 }
246
247 if (draws>0)
248 {
249 if (draws!=count)
250 {
251 eventlog(eventlog_level_error,__FUNCTION__,"some, but not all players had a draw count=%u (winners=%u losers=%u draws=%u)",count,winners,losers,draws);
252 return -1;
253 }
254
255 return -1; /* no change in case of draw */
256 }
257 if ((losers<1) || (winners<1) || (winners>1 && (winners!=losers)))
258 {
259 eventlog(eventlog_level_info,__FUNCTION__,"missing winner or loser for count=%u (winners=%u losers=%u draws=%u) - discarding result",count,winners,losers,draws);
260 return -1;
261 }
262
263 if (ladder_calc_info(clienttag,id,count,players,results,info)<0)
264 {
265 eventlog(eventlog_level_error,__FUNCTION__,"unable to calculate info from game results");
266 return -1;
267 }
268
269 for (curr=0; curr<count; curr++)
270 {
271 int won,wins,games;
272 t_account * account;
273
274 if (results[curr]==game_result_win) won=1; else won=0;
275
276 account = players[curr];
277 uid = account_get_uid(account);
278 wins = account_get_ladder_wins(account,clienttag,id);
279 games = wins + account_get_ladder_losses(account,clienttag,id) + account_get_ladder_disconnects(account,clienttag,id);
280
281 account_adjust_ladder_rating(account,clienttag,id,info[curr].adj);
282
283 war3_ladder_update(ladder_cr(clienttag,id),uid,won,account_get_ladder_rating(account,clienttag,id),players[curr],0);
284
285 if (results[curr]!=game_result_draw)
286 war3_ladder_update(ladder_cg(clienttag,id),uid,info[curr].adj,games,players[curr],0);
287
288 if (results[curr]==game_result_win)
289 war3_ladder_update(ladder_cw(clienttag,id),uid,info[curr].adj,wins,players[curr],0);
290 }
291
292 ladder_update_all_accounts();
293
294 return 0;
295 }
296
297
ladder_check_map(char const * mapname,t_game_maptype maptype,t_clienttag clienttag)298 extern int ladder_check_map(char const * mapname, t_game_maptype maptype, t_clienttag clienttag)
299 {
300 if (!mapname)
301 {
302 eventlog(eventlog_level_error,__FUNCTION__,"got NULL mapname");
303 return -1;
304 }
305 if (!clienttag)
306 {
307 eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag");
308 return -1;
309 }
310
311 eventlog(eventlog_level_debug,__FUNCTION__,"checking mapname \"%s\" maptype=%d",mapname,(int)maptype);
312 if (maptype==game_maptype_ladder) /* FIXME: what about Ironman? */
313 return 1;
314
315 return 0;
316 }
317
318
ladder_get_account_by_rank(unsigned int rank,t_ladder_sort lsort,t_ladder_time ltime,t_clienttag clienttag,t_ladder_id id)319 extern t_account * ladder_get_account_by_rank(unsigned int rank, t_ladder_sort lsort, t_ladder_time ltime, t_clienttag clienttag, t_ladder_id id)
320 {
321 unsigned int dummy;
322
323 if (rank<1)
324 {
325 eventlog(eventlog_level_error,__FUNCTION__,"got zero rank");
326 return NULL;
327 }
328 if (!clienttag)
329 {
330 eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag");
331 return NULL;
332 }
333
334 switch (lsort)
335 {
336 case ladder_sort_highestrated:
337 if (ltime == ladder_time_current)
338 return ladder_get_account(ladder_cr(clienttag,id),rank,&dummy,clienttag);
339 else
340 return ladder_get_account(ladder_ar(clienttag,id),rank,&dummy,clienttag);
341 case ladder_sort_mostwins:
342 if (ltime == ladder_time_current)
343 return ladder_get_account(ladder_cw(clienttag,id),rank,&dummy,clienttag);
344 else
345 return ladder_get_account(ladder_aw(clienttag,id),rank,&dummy,clienttag);
346 case ladder_sort_mostgames:
347 if (ltime == ladder_time_current)
348 return ladder_get_account(ladder_cg(clienttag,id),rank,&dummy,clienttag);
349 else
350 return ladder_get_account(ladder_ag(clienttag,id),rank,&dummy,clienttag);
351 default:
352 eventlog(eventlog_level_error,__FUNCTION__,"got bad ladder sort %u",(unsigned int)lsort);
353 }
354 return NULL;
355 }
356
357
ladder_get_rank_by_account(t_account * account,t_ladder_sort lsort,t_ladder_time ltime,t_clienttag clienttag,t_ladder_id id)358 extern unsigned int ladder_get_rank_by_account(t_account * account, t_ladder_sort lsort, t_ladder_time ltime, t_clienttag clienttag, t_ladder_id id)
359 {
360 int uid;
361
362 if (!account)
363 {
364 eventlog(eventlog_level_error,__FUNCTION__,"got NULL account");
365 return 0;
366 }
367 if (!clienttag)
368 {
369 eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag");
370 return 0;
371 }
372
373 uid = account_get_uid(account);
374
375 switch (lsort)
376 {
377 case ladder_sort_highestrated:
378 if (ltime == ladder_time_current)
379 return ladder_get_rank(ladder_cr(clienttag,id),uid,0,clienttag);
380 else
381 return ladder_get_rank(ladder_ar(clienttag,id),uid,0,clienttag);
382 case ladder_sort_mostwins:
383 if (ltime == ladder_time_current)
384 return ladder_get_rank(ladder_cw(clienttag,id),uid,0,clienttag);
385 else
386 return ladder_get_rank(ladder_aw(clienttag,id),uid,0,clienttag);
387 case ladder_sort_mostgames:
388 if (ltime == ladder_time_current)
389 return ladder_get_rank(ladder_cg(clienttag,id),uid,0,clienttag);
390 else
391 return ladder_get_rank(ladder_ag(clienttag,id),uid,0,clienttag);
392 default:
393 eventlog(eventlog_level_error,__FUNCTION__,"got bad ladder sort %u",(unsigned int)lsort);
394 }
395
396 return 0;
397 }
398
in_same_team(t_account * acc1,t_account * acc2,unsigned int tc1,unsigned int tc2,t_clienttag clienttag)399 int in_same_team(t_account * acc1, t_account * acc2, unsigned int tc1, unsigned int tc2, t_clienttag clienttag)
400 {
401 return 0;
402 }
403
solo_ladder(t_clienttag clienttag)404 extern t_ladder * solo_ladder(t_clienttag clienttag)
405 {
406 if (clienttag==CLIENTTAG_WARCRAFT3_UINT)
407 return &WAR3_solo_ladder;
408 if (clienttag==CLIENTTAG_WAR3XP_UINT)
409 return &W3XP_solo_ladder;
410 else
411 return NULL;
412 }
413
team_ladder(t_clienttag clienttag)414 extern t_ladder * team_ladder(t_clienttag clienttag)
415 {
416 if (clienttag==CLIENTTAG_WARCRAFT3_UINT)
417 return &WAR3_team_ladder;
418 if (clienttag==CLIENTTAG_WAR3XP_UINT)
419 return &W3XP_team_ladder;
420 else
421 return NULL;
422 }
423
ffa_ladder(t_clienttag clienttag)424 extern t_ladder * ffa_ladder(t_clienttag clienttag)
425 {
426 if (clienttag==CLIENTTAG_WARCRAFT3_UINT)
427 return &WAR3_ffa_ladder;
428 else
429 return &W3XP_ffa_ladder;
430 }
431
at_ladder(t_clienttag clienttag)432 extern t_ladder * at_ladder(t_clienttag clienttag)
433 {
434 if (clienttag==CLIENTTAG_WARCRAFT3_UINT)
435 return &WAR3_at_ladder;
436 else
437 return &W3XP_at_ladder;
438 }
439
ladder_ar(t_clienttag clienttag,t_ladder_id ladder_id)440 extern t_ladder * ladder_ar(t_clienttag clienttag, t_ladder_id ladder_id)
441 {
442 if (clienttag==CLIENTTAG_STARCRAFT_UINT)
443 return &STAR_active_rating;
444 else if (clienttag==CLIENTTAG_BROODWARS_UINT)
445 return &SEXP_active_rating;
446 else if (clienttag==CLIENTTAG_WARCIIBNE_UINT)
447 {
448 if (ladder_id == ladder_id_normal)
449 return &W2BN_active_rating;
450 else
451 return &W2BN_active_rating_ironman;
452 }
453 else return NULL;
454 }
455
ladder_aw(t_clienttag clienttag,t_ladder_id ladder_id)456 extern t_ladder * ladder_aw(t_clienttag clienttag, t_ladder_id ladder_id)
457 {
458 if (clienttag==CLIENTTAG_STARCRAFT_UINT)
459 return &STAR_active_wins;
460 else if (clienttag==CLIENTTAG_BROODWARS_UINT)
461 return &SEXP_active_wins;
462 else if (clienttag==CLIENTTAG_WARCIIBNE_UINT)
463 {
464 if (ladder_id == ladder_id_normal)
465 return &W2BN_active_wins;
466 else
467 return &W2BN_active_wins_ironman;
468 }
469 else return NULL;
470 }
471
ladder_ag(t_clienttag clienttag,t_ladder_id ladder_id)472 extern t_ladder * ladder_ag(t_clienttag clienttag, t_ladder_id ladder_id)
473 {
474 if (clienttag==CLIENTTAG_STARCRAFT_UINT)
475 return &STAR_active_games;
476 else if (clienttag==CLIENTTAG_BROODWARS_UINT)
477 return &SEXP_active_games;
478 else if (clienttag==CLIENTTAG_WARCIIBNE_UINT)
479 {
480 if (ladder_id == ladder_id_normal)
481 return &W2BN_active_games;
482 else
483 return &W2BN_active_games_ironman;
484 }
485 else return NULL;
486 }
487
ladder_cr(t_clienttag clienttag,t_ladder_id ladder_id)488 extern t_ladder * ladder_cr(t_clienttag clienttag, t_ladder_id ladder_id)
489 {
490 if (clienttag==CLIENTTAG_STARCRAFT_UINT)
491 return &STAR_current_rating;
492 else if (clienttag==CLIENTTAG_BROODWARS_UINT)
493 return &SEXP_current_rating;
494 else if (clienttag==CLIENTTAG_WARCIIBNE_UINT)
495 {
496 if (ladder_id == ladder_id_normal)
497 return &W2BN_current_rating;
498 else
499 return &W2BN_current_rating_ironman;
500 }
501 else return NULL;
502 }
503
ladder_cw(t_clienttag clienttag,t_ladder_id ladder_id)504 extern t_ladder * ladder_cw(t_clienttag clienttag, t_ladder_id ladder_id)
505 {
506 if (clienttag==CLIENTTAG_STARCRAFT_UINT)
507 return &STAR_current_wins;
508 else if (clienttag==CLIENTTAG_BROODWARS_UINT)
509 return &SEXP_current_wins;
510 else if (clienttag==CLIENTTAG_WARCIIBNE_UINT)
511 {
512 if (ladder_id == ladder_id_normal)
513 return &W2BN_current_wins;
514 else
515 return &W2BN_current_wins_ironman;
516 }
517 else return NULL;
518 }
519
ladder_cg(t_clienttag clienttag,t_ladder_id ladder_id)520 extern t_ladder * ladder_cg(t_clienttag clienttag, t_ladder_id ladder_id)
521 {
522 if (clienttag==CLIENTTAG_STARCRAFT_UINT)
523 return &STAR_current_games;
524 else if (clienttag==CLIENTTAG_BROODWARS_UINT)
525 return &SEXP_current_games;
526 else if (clienttag==CLIENTTAG_WARCIIBNE_UINT)
527 {
528 if (ladder_id == ladder_id_normal)
529 return &W2BN_current_games;
530 else
531 return &W2BN_current_games_ironman;
532 }
533 else return NULL;
534 }
535
ladder_get_clienttag(t_ladder * ladder)536 t_clienttag ladder_get_clienttag(t_ladder * ladder)
537 {
538 return ladder->clienttag;
539 }
540
w3_ladder_to_binary_ladder_types(t_ladder * ladder)541 t_binary_ladder_types w3_ladder_to_binary_ladder_types(t_ladder * ladder)
542 {
543 return ladder->type;
544 }
545
binary_ladder_types_to_w3_ladder(t_binary_ladder_types type)546 t_ladder * binary_ladder_types_to_w3_ladder(t_binary_ladder_types type)
547 {
548 t_ladder * ladder;
549
550 switch (type)
551 {
552 case WAR3_SOLO:
553 ladder = &WAR3_solo_ladder;
554 break;
555 case WAR3_TEAM:
556 ladder = &WAR3_team_ladder;
557 break;
558 case WAR3_FFA:
559 ladder = &WAR3_ffa_ladder;
560 break;
561 case WAR3_AT:
562 ladder = &WAR3_at_ladder;
563 break;
564 case W3XP_SOLO:
565 ladder = &W3XP_solo_ladder;
566 break;
567 case W3XP_TEAM:
568 ladder = &W3XP_team_ladder;
569 break;
570 case W3XP_FFA:
571 ladder = &W3XP_ffa_ladder;
572 break;
573 case W3XP_AT:
574 ladder = &W3XP_at_ladder;
575 break;
576 case STAR_AR :
577 ladder = &STAR_active_rating;
578 break;
579 case STAR_AW :
580 ladder = &STAR_active_wins;
581 break;
582 case STAR_AG :
583 ladder = &STAR_active_games;
584 break;
585 case STAR_CR :
586 ladder = &STAR_current_rating;
587 break;
588 case STAR_CW :
589 ladder = &STAR_current_wins;
590 break;
591 case STAR_CG :
592 ladder = &STAR_current_games;
593 break;
594 case SEXP_AR :
595 ladder = &SEXP_active_rating;
596 break;
597 case SEXP_AW :
598 ladder = &SEXP_active_wins;
599 break;
600 case SEXP_AG :
601 ladder = &SEXP_active_games;
602 break;
603 case SEXP_CR :
604 ladder = &SEXP_current_rating;
605 break;
606 case SEXP_CW :
607 ladder = &SEXP_current_wins;
608 break;
609 case SEXP_CG :
610 ladder = &SEXP_current_games;
611 break;
612 case W2BN_AR :
613 ladder = &W2BN_active_rating;
614 break;
615 case W2BN_AW :
616 ladder = &W2BN_active_wins;
617 break;
618 case W2BN_AG :
619 ladder = &W2BN_active_games;
620 break;
621 case W2BN_CR :
622 ladder = &W2BN_current_rating;
623 break;
624 case W2BN_CW :
625 ladder = &W2BN_current_wins;
626 break;
627 case W2BN_CG :
628 ladder = &W2BN_current_games;
629 break;
630 case W2BN_ARI :
631 ladder = &W2BN_active_rating_ironman;
632 break;
633 case W2BN_AWI :
634 ladder = &W2BN_active_wins_ironman;
635 break;
636 case W2BN_AGI :
637 ladder = &W2BN_active_games_ironman;
638 break;
639 case W2BN_CRI :
640 ladder = &W2BN_current_rating_ironman;
641 break;
642 case W2BN_CWI :
643 ladder = &W2BN_current_wins_ironman;
644 break;
645 case W2BN_CGI :
646 ladder = &W2BN_current_games_ironman;
647 break;
648
649 default:
650 eventlog(eventlog_level_error,__FUNCTION__,"got invalid ladder type %d",type);
651 return NULL;
652 }
653 return ladder;
654 }
655
ladder_init(t_ladder * ladder,t_binary_ladder_types type,t_clienttag clienttag,t_ladder_id ladder_id)656 void ladder_init(t_ladder *ladder,t_binary_ladder_types type, t_clienttag clienttag, t_ladder_id ladder_id)
657 {
658 ladder->first = NULL;
659 ladder->last = NULL;
660 ladder->dirty = 1;
661 ladder->type = type;
662 ladder->clienttag = clienttag;
663 ladder->ladder_id = ladder_id;
664 }
665
ladder_destroy(t_ladder * ladder)666 void ladder_destroy(t_ladder *ladder)
667 {
668 t_ladder_internal *pointer;
669
670 while (ladder->first!=NULL)
671 {
672 pointer = ladder->first;
673 ladder->first = pointer->prev;
674 xfree((void *)pointer);
675 }
676 }
677
war3_ladder_add(t_ladder * ladder,int uid,int xp,int level,t_account * account,unsigned int teamcount,t_clienttag clienttag)678 extern int war3_ladder_add(t_ladder *ladder, int uid, int xp, int level, t_account *account, unsigned int teamcount,t_clienttag clienttag)
679 {
680 t_ladder_internal *ladder_entry;
681 ladder_entry = xmalloc(sizeof(t_ladder_internal));
682
683 ladder_entry->uid = uid;
684 ladder_entry->xp = xp;
685 ladder_entry->level = level;
686 ladder_entry->account = account;
687 ladder_entry->teamcount = teamcount;
688 ladder_entry->prev = NULL;
689 ladder_entry->next = NULL;
690
691 if (ladder->first == NULL)
692 { // ladder empty, so just insert element
693 ladder->first = ladder_entry;
694 ladder->last = ladder_entry;
695 }
696 else
697 { // already elements in list
698 // determine if first or last user in ladder has XP
699 // closest to current, cause should be the shorter way to insert
700 // new user
701 if ((ladder->first->xp - xp) >= (xp - ladder->last->xp))
702 // we should enter from last to first
703 {
704 t_ladder_internal *search;
705 search = ladder->last;
706 while ((search != NULL) && (search->level < level))
707 {
708 search = search->next;
709 }
710 while ((search != NULL) && (search->level == level) && (search->xp < xp))
711 {
712 search = search->next;
713 }
714
715 if (teamcount!=0) // this only happens for atteams
716 {
717 t_ladder_internal *teamsearch;
718 t_ladder_internal *teamfound;
719
720 teamsearch = search;
721 teamfound = NULL;
722
723 while ((teamsearch != NULL) && (teamsearch->xp == xp) && (teamsearch->level == level))
724 {
725 if (in_same_team(account,teamsearch->account,teamcount,teamsearch->teamcount,clienttag))
726 {
727 teamfound = teamsearch;
728 break;
729 }
730 teamsearch = teamsearch->next;
731 }
732 if (teamfound!=NULL) search = teamfound;
733 }
734
735 if (search == NULL)
736 {
737 ladder->first->next = ladder_entry;
738 ladder_entry->prev = ladder->first;
739 ladder->first = ladder_entry;
740 }
741 else
742 {
743 ladder_entry->next = search;
744 ladder_entry->prev = search->prev;
745 if (search == ladder->last)
746 // enter at end of list
747 {
748 search->prev = ladder_entry;
749 ladder->last = ladder_entry;
750 }
751 else
752 {
753 search->prev->next = ladder_entry;
754 search->prev = ladder_entry;
755 }
756 }
757 }
758 else
759 // start from first and the search towards last
760 {
761 t_ladder_internal *search;
762 search = ladder->first;
763 while ((search != NULL) && (search->level > level))
764 {
765 search = search->prev;
766 }
767 while ((search != NULL) && (search->level == level) && (search->xp > xp))
768 {
769 search = search->prev;
770 }
771
772 if (teamcount!=0) // this only happens for atteams
773 {
774 t_ladder_internal *teamsearch;
775 t_ladder_internal *teamfound;
776
777 teamsearch = search;
778 teamfound = NULL;
779
780 while ((teamsearch != NULL) && (teamsearch->xp == xp))
781 {
782 if (in_same_team(account,teamsearch->account,teamcount,teamsearch->teamcount,clienttag))
783 {
784 teamfound = teamsearch;
785 break;
786 }
787 teamsearch = teamsearch->prev;
788 }
789 if (teamfound!=NULL) search = teamfound;
790
791 }
792
793
794 if (search == NULL)
795 {
796 ladder->last->prev = ladder_entry;
797 ladder_entry->next = ladder->last;
798 ladder->last = ladder_entry;
799 }
800 else
801 {
802 ladder_entry->prev = search;
803 ladder_entry->next = search->next;
804 if (search == ladder->first)
805 // enter at beginning of list
806 {
807 search->next = ladder_entry;
808 ladder->first = ladder_entry;
809 }
810 else
811 {
812 search->next->prev = ladder_entry;
813 search->next = ladder_entry;
814 }
815 }
816 }
817 }
818 ladder->dirty = 1;
819 return 0;
820 }
821
war3_ladder_update(t_ladder * ladder,int uid,int xp,int level,t_account * account,unsigned int teamcount)822 extern int war3_ladder_update(t_ladder *ladder, int uid, int xp, int level, t_account *account, unsigned int teamcount)
823 {
824 t_ladder_internal *search, *newpos;
825 search = ladder->first;
826 while (search && ((search->uid != uid) || (search->teamcount!=teamcount))) { search = search->prev; }
827 if (search != NULL)
828 {
829 search->xp += xp;
830 search->level = level;
831 ladder->dirty = 1;
832
833 // make sure, we don't get negative XP
834 if (search->xp < 0) search->xp = 0;
835
836 if (xp>0)
837 // XP gained.... maybe getting better ranking
838 {
839 newpos = search->next;
840 while ((newpos != NULL) && (newpos->level < level))
841 {
842 newpos = newpos->next;
843 }
844 while ((newpos != NULL) && (newpos->level == level) && (newpos->xp < search->xp))
845 {
846 newpos = newpos->next;
847 }
848 if (newpos != search->next)
849 // so we really have to change ranking now
850 {
851 // first close gap, where we've been...
852 search->next->prev = search->prev;
853 if (search->prev != NULL)
854 search->prev->next = search->next;
855 else
856 ladder->last = search->next;
857 // and then move to new position
858 search->next = newpos;
859 if (newpos == NULL)
860 {
861 search->prev = ladder->first;
862 ladder->first->next = search;
863 ladder->first = search;
864 }
865 else
866 {
867 search->prev = newpos->prev;
868 newpos->prev->next = search;
869 newpos->prev = search;
870 }
871 }
872 }
873 if (xp<0)
874 // XP lost.... maybe ranking gets worse
875 {
876 newpos = search->prev;
877 while ((newpos != NULL) && (newpos->level > level))
878 {
879 newpos = newpos->prev;
880 }
881 while ((newpos != NULL) && (newpos->level == level) && (newpos->xp > search->xp))
882 {
883 newpos = newpos->prev;
884 }
885 if (newpos != search->prev)
886 // so we really have to change ranking now
887 {
888 // first close gap, where we've been...
889 search->prev->next = search->next;
890 if (search->next != NULL)
891 search->next->prev = search->prev;
892 else
893 ladder->first = search->prev;
894 // and then move to new position
895 search->prev = newpos;
896 if (newpos == NULL)
897 {
898 search->next = ladder->last;
899 ladder->last->prev = search;
900 ladder->last = search;
901 }
902 else
903 {
904 search->next = newpos->next;
905 newpos->next->prev = search;
906 newpos->next = search;
907 }
908 }
909 }
910 return 0;
911 }
912 else
913 return -1;
914 }
915
ladder_get_rank(t_ladder * ladder,int uid,unsigned int teamcount,t_clienttag clienttag)916 extern int ladder_get_rank(t_ladder *ladder, int uid, unsigned int teamcount, t_clienttag clienttag)
917 {
918 int ranking = 1;
919 t_ladder_internal *search;
920 search = ladder->first;
921 while ((search!=NULL) && ((search->uid != uid) || (search->teamcount!=teamcount)))
922 {
923 search = search->prev;
924 ranking++;
925 if (ladder==at_ladder(clienttag))
926 {
927 // if in the same team as previous account
928 if ((search) && (search->next)
929 && in_same_team(search->account,search->next->account,teamcount,search->next->teamcount,clienttag))
930 ranking--;
931 }
932 }
933 if (search != NULL)
934 {
935 return ranking;
936 }
937 else
938 {
939 return 0;
940 }
941 }
942
ladder_get_rank_internal(t_ladder * ladder,int rank,t_clienttag clienttag)943 t_ladder_internal * ladder_get_rank_internal(t_ladder * ladder,int rank, t_clienttag clienttag)
944 {
945 int ranking;
946 t_ladder_internal *search;
947
948 // this should be a huge speedup when getting many subsequent entries from ladder
949 // like used in saving of binary ladders
950 if ((last_ladder == ladder) && (last_rank < rank) && (last_internal != NULL))
951 {
952 ranking = last_rank;
953 search = last_internal;
954 }
955 else
956 {
957 ranking = 1;
958 search = ladder->first;
959 }
960
961 while ((search!=NULL) && (ranking<rank))
962 {
963 search = search->prev;
964 ranking++;
965 if (ladder == at_ladder(clienttag))
966 {
967 if ((search) && (search->next)
968 && in_same_team(search->account,search->next->account,search->teamcount,search->next->teamcount,clienttag))
969 ranking--;
970 }
971 }
972 last_ladder = ladder;
973 last_internal = search;
974 last_rank = rank;
975 return search;
976 }
977
ladder_get_account(t_ladder * ladder,int rank,unsigned int * teamcount,t_clienttag clienttag)978 extern t_account * ladder_get_account(t_ladder *ladder, int rank, unsigned int * teamcount,t_clienttag clienttag)
979 {
980 t_ladder_internal *search;
981
982 if (!(ladder))
983 {
984 // eventlog(eventlog_level_error,__FUNCTION__,"got request for non-existant ladder");
985 return NULL;
986 }
987
988 search = ladder_get_rank_internal(ladder,rank,clienttag);
989
990 if (search)
991 {
992 *teamcount = search->teamcount;
993 return search->account;
994 }
995 else
996 {
997 *teamcount = 0;
998 return NULL;
999 }
1000 }
1001
1002 typedef int (* t_set_fct)(t_account *account,t_clienttag cltag, t_ladder_id ldr_id,unsigned int rank);
1003 typedef int (* t_get_fct)(t_account *account,t_clienttag cltag, t_ladder_id ldr_id);
1004
ladder_update_accounts(t_ladder * ladder,t_set_fct set_fct,t_get_fct get_fct1)1005 extern int ladder_update_accounts(t_ladder *ladder, t_set_fct set_fct, t_get_fct get_fct1)
1006 {
1007 t_ladder_internal *pointer, *tmp_pointer;
1008 t_account *account;
1009 t_clienttag clienttag;
1010 int rank = 1;
1011 int update = 0;
1012 char clienttag_str[5];
1013
1014 if (ladder->dirty == 1)
1015 {
1016 if ((set_fct!=NULL) && (get_fct1!=NULL))
1017 {
1018 clienttag = ladder_get_clienttag(ladder);
1019 pointer = ladder->first;
1020 while (pointer!=NULL)
1021 {
1022 account = pointer->account;
1023 if (rank <= MaxRankKeptInLadder)
1024 {
1025 if (ladder->ladder_id == ladder_id_none) //war3/w3xp AT ladder
1026 {
1027 // do nothing now
1028 }
1029 else //other ladders...
1030 {
1031 if ((*get_fct1)(account,clienttag,ladder->ladder_id)!=rank)
1032 {
1033 (*set_fct)(account,clienttag,ladder->ladder_id,rank);
1034 update++;
1035 }
1036 }
1037
1038 pointer=pointer->prev;
1039 rank++;
1040
1041 }
1042 else
1043 {
1044 // leave while loop
1045 break;
1046 }
1047 }
1048 while (pointer!=NULL)
1049 {
1050 // all accounts following now are out of the ladder range we keep track of....
1051 // so set rank to 0 and remove account from ladder
1052 if (ladder->ladder_id == ladder_id_none) //war3/w3xp AT ladder
1053 {
1054 if ((*get_fct1)(account,pointer->teamcount,clienttag)!=0)
1055 (*set_fct)(account,pointer->teamcount,clienttag,0);
1056 }
1057 else
1058 {
1059 if ((*get_fct1)(account,clienttag,ladder->ladder_id)!=0)
1060 (*set_fct)(account,clienttag,ladder->ladder_id,0);
1061 }
1062
1063 // remove account from ladder
1064 if (pointer->next!=NULL) pointer->next->prev = pointer->prev;
1065 if (pointer->prev!=NULL) pointer->prev->next = pointer->next;
1066 if (ladder->last == pointer) ladder->last = pointer->next;
1067 if (ladder->first == pointer) ladder->first = pointer->prev;
1068 tmp_pointer = pointer->prev;
1069 xfree((void *)pointer);
1070 pointer = tmp_pointer;
1071 }
1072 }
1073 binary_ladder_save(w3_ladder_to_binary_ladder_types(ladder),4,&ladder_get_from_ladder);
1074 if (update != 0)
1075 eventlog(eventlog_level_info,__FUNCTION__,"updated %u accounts for clienttag %s",update,tag_uint_to_str(clienttag_str,ladder->clienttag));
1076 }
1077 ladder->dirty = 0;
1078 return 0;
1079 }
1080
ladder_update_all_accounts(void)1081 extern int ladder_update_all_accounts(void)
1082 {
1083 eventlog(eventlog_level_info,__FUNCTION__,"updating ranking for all accounts");
1084 ladder_update_accounts(&WAR3_solo_ladder, &account_set_ladder_rank, &account_get_ladder_rank);
1085 ladder_update_accounts(&WAR3_team_ladder, &account_set_ladder_rank, &account_get_ladder_rank);
1086 ladder_update_accounts(&WAR3_ffa_ladder, &account_set_ladder_rank, &account_get_ladder_rank);
1087 //ladder_update_accounts(&WAR3_at_ladder, &account_set_atteamrank, &account_get_atteamrank);
1088 ladder_update_accounts(&W3XP_solo_ladder, &account_set_ladder_rank, &account_get_ladder_rank);
1089 ladder_update_accounts(&W3XP_team_ladder, &account_set_ladder_rank, &account_get_ladder_rank);
1090 ladder_update_accounts(&W3XP_ffa_ladder, &account_set_ladder_rank, &account_get_ladder_rank);
1091 //ladder_update_accounts(&W3XP_at_ladder, &account_set_atteamrank, &account_get_atteamrank);
1092 ladder_update_accounts(&STAR_current_rating,&account_set_ladder_rank, &account_get_ladder_rank);
1093 ladder_update_accounts(&STAR_current_wins, NULL, NULL);
1094 ladder_update_accounts(&STAR_current_games, NULL, NULL);
1095 ladder_update_accounts(&SEXP_current_rating,&account_set_ladder_rank, &account_get_ladder_rank);
1096 ladder_update_accounts(&SEXP_current_wins, NULL, NULL);
1097 ladder_update_accounts(&SEXP_current_games, NULL, NULL);
1098 ladder_update_accounts(&STAR_active_rating, &account_set_ladder_active_rank, &account_get_ladder_active_rank);
1099 ladder_update_accounts(&STAR_active_wins, NULL, NULL);
1100 ladder_update_accounts(&STAR_active_games, NULL, NULL);
1101 ladder_update_accounts(&SEXP_active_rating, &account_set_ladder_active_rank, &account_get_ladder_active_rank);
1102 ladder_update_accounts(&SEXP_active_wins, NULL, NULL);
1103 ladder_update_accounts(&SEXP_active_games, NULL, NULL);
1104 ladder_update_accounts(&W2BN_current_rating,&account_set_ladder_rank, &account_get_ladder_rank);
1105 ladder_update_accounts(&W2BN_current_wins, NULL, NULL);
1106 ladder_update_accounts(&W2BN_current_games, NULL, NULL);
1107 ladder_update_accounts(&W2BN_active_rating, &account_set_ladder_rank, &account_get_ladder_rank);
1108 ladder_update_accounts(&W2BN_active_wins, NULL, NULL);
1109 ladder_update_accounts(&W2BN_active_games, NULL, NULL);
1110 ladder_update_accounts(&W2BN_current_rating_ironman, &account_set_ladder_rank, &account_get_ladder_rank);
1111 ladder_update_accounts(&W2BN_current_wins_ironman, NULL, NULL);
1112 ladder_update_accounts(&W2BN_current_games_ironman, NULL, NULL);
1113 ladder_update_accounts(&W2BN_active_rating_ironman, &account_set_ladder_rank, &account_get_ladder_rank);
1114 ladder_update_accounts(&W2BN_active_wins_ironman, NULL, NULL);
1115 ladder_update_accounts(&W2BN_active_games_ironman, NULL, NULL);
1116
1117 eventlog(eventlog_level_info,__FUNCTION__,"finished updating ranking for all accounts");
1118 return 0;
1119 }
1120
binary_load(t_binary_ladder_types type)1121 t_binary_ladder_load_result binary_load(t_binary_ladder_types type)
1122 {
1123 t_binary_ladder_load_result result;
1124 t_ladder * ladder;
1125
1126 result = binary_ladder_load(type,4,&ladder_put_into_ladder);
1127 if (result == illegal_checksum)
1128 {
1129 t_clienttag clienttag;
1130 t_ladder_id ladder_id;
1131
1132 ladder = binary_ladder_types_to_w3_ladder(type);
1133 clienttag = ladder_get_clienttag(ladder);
1134 ladder_id = ladder->ladder_id;
1135 ladder_destroy(ladder);
1136 ladder_init(ladder,type,clienttag,ladder_id);
1137 }
1138 return result;
1139 }
1140
ladders_load_accounts_to_ladderlists(void)1141 extern void ladders_load_accounts_to_ladderlists(void)
1142 {
1143 t_entry * curr;
1144 t_account * account;
1145 int xp;
1146
1147 t_binary_ladder_load_result war3_solo_res, war3_team_res, war3_ffa_res, war3_at_res;
1148 t_binary_ladder_load_result w3xp_solo_res, w3xp_team_res, w3xp_ffa_res, w3xp_at_res;
1149 t_binary_ladder_load_result star_ar_res, star_aw_res, star_ag_res, star_cr_res, star_cw_res, star_cg_res;
1150 t_binary_ladder_load_result sexp_ar_res, sexp_aw_res, sexp_ag_res, sexp_cr_res, sexp_cw_res, sexp_cg_res;
1151 t_binary_ladder_load_result w2bn_cr_res, w2bn_cw_res, w2bn_cg_res, w2bn_cri_res, w2bn_cwi_res, w2bn_cgi_res;
1152 t_binary_ladder_load_result w2bn_ar_res, w2bn_aw_res, w2bn_ag_res, w2bn_ari_res, w2bn_awi_res, w2bn_agi_res;
1153
1154 war3_solo_res = binary_load(WAR3_SOLO);
1155 war3_team_res = binary_load(WAR3_TEAM);
1156 war3_ffa_res = binary_load(WAR3_FFA);
1157 war3_at_res = load_success; // binary_load(WAR3_AT);
1158 w3xp_solo_res = binary_load(W3XP_SOLO);
1159 w3xp_team_res = binary_load(W3XP_TEAM);
1160 w3xp_ffa_res = binary_load(W3XP_FFA);
1161 w3xp_at_res = load_success; // binary_load(W3XP_AT);
1162 star_ar_res = binary_load(STAR_AR);
1163 star_aw_res = binary_load(STAR_AW);
1164 star_ag_res = binary_load(STAR_AG);
1165 star_cr_res = binary_load(STAR_CR);
1166 star_cw_res = binary_load(STAR_CW);
1167 star_cg_res = binary_load(STAR_CG);
1168 sexp_ar_res = binary_load(SEXP_AR);
1169 sexp_aw_res = binary_load(SEXP_AW);
1170 sexp_ag_res = binary_load(SEXP_AG);
1171 sexp_cr_res = binary_load(SEXP_CR);
1172 sexp_cw_res = binary_load(SEXP_CW);
1173 sexp_cg_res = binary_load(SEXP_CG);
1174 w2bn_cr_res = binary_load(W2BN_CR);
1175 w2bn_cw_res = binary_load(W2BN_CW);
1176 w2bn_cg_res = binary_load(W2BN_CG);
1177 w2bn_cri_res = binary_load(W2BN_CRI);
1178 w2bn_cwi_res = binary_load(W2BN_CWI);
1179 w2bn_cgi_res = binary_load(W2BN_CGI);
1180 w2bn_ar_res = binary_load(W2BN_AR);
1181 w2bn_aw_res = binary_load(W2BN_AW);
1182 w2bn_ag_res = binary_load(W2BN_AG);
1183 w2bn_ari_res = binary_load(W2BN_ARI);
1184 w2bn_awi_res = binary_load(W2BN_AWI);
1185 w2bn_agi_res = binary_load(W2BN_AGI);
1186
1187 if ((war3_solo_res + war3_team_res + war3_ffa_res + war3_at_res +
1188 w3xp_solo_res + w3xp_team_res + w3xp_ffa_res + w3xp_at_res +
1189 star_ar_res + star_aw_res + star_ag_res + star_cr_res + star_cw_res + star_cg_res +
1190 sexp_ar_res + sexp_aw_res + sexp_ag_res + sexp_cr_res + sexp_cw_res + sexp_cg_res +
1191 w2bn_cr_res + w2bn_cw_res + w2bn_cg_res +
1192 w2bn_cri_res + w2bn_cwi_res + w2bn_cgi_res +
1193 w2bn_ar_res + w2bn_aw_res + w2bn_ag_res +
1194 w2bn_ari_res + w2bn_awi_res + w2bn_agi_res ) == load_success)
1195 {
1196 eventlog(eventlog_level_trace,__FUNCTION__,"everything went smooth... taking shortcut");
1197 return;
1198 }
1199
1200 eventlog(eventlog_level_warn, __FUNCTION__, "binary ladders missing or incomplete, going to load all accounts to rebuild them");
1201 if (accountlist_load_all(ST_FORCE)) {
1202 eventlog(eventlog_level_error, __FUNCTION__, "error loading all accounts");
1203 return;
1204 }
1205 HASHTABLE_TRAVERSE(accountlist(),curr)
1206 {
1207 if ((account=((t_account *)entry_get_data(curr))))
1208 {
1209 int rating, wins;
1210 int uid = account_get_uid(account);
1211
1212 if ((war3_solo_res!=load_success) && ((xp = account_get_ladder_xp(account,CLIENTTAG_WARCRAFT3_UINT,ladder_id_solo))))
1213 {
1214 war3_ladder_add(&WAR3_solo_ladder,
1215 uid, xp,
1216 account_get_ladder_level(account,CLIENTTAG_WARCRAFT3_UINT,ladder_id_solo),
1217 account,0,CLIENTTAG_WARCRAFT3_UINT);
1218 }
1219 if ((war3_team_res!=load_success) && ((xp = account_get_ladder_xp(account,CLIENTTAG_WARCRAFT3_UINT,ladder_id_team))))
1220 {
1221 war3_ladder_add(&WAR3_team_ladder,
1222 uid, xp,
1223 account_get_ladder_level(account,CLIENTTAG_WARCRAFT3_UINT,ladder_id_team),
1224 account,0,CLIENTTAG_WARCRAFT3_UINT);
1225
1226 }
1227 if ((war3_ffa_res!=load_success) && ((xp = account_get_ladder_xp(account,CLIENTTAG_WARCRAFT3_UINT,ladder_id_ffa))))
1228 {
1229 war3_ladder_add(&WAR3_ffa_ladder,
1230 uid, xp,
1231 account_get_ladder_level(account,CLIENTTAG_WARCRAFT3_UINT,ladder_id_ffa),
1232 account,0,CLIENTTAG_WARCRAFT3_UINT);
1233 }
1234 // user is part of a team
1235 /*
1236 if ((war3_at_res!=load_success) && ((teamcount = account_get_atteamcount(account,CLIENTTAG_WARCRAFT3_UINT))))
1237 {
1238 int counter;
1239 for (counter=1; counter<=teamcount; counter++)
1240 {
1241 if ((xp = account_get_atteamxp(account,counter,CLIENTTAG_WARCRAFT3_UINT)) &&
1242 account_get_atteammembers(account,counter,CLIENTTAG_WARCRAFT3_UINT))
1243 {
1244 war3_ladder_add(&WAR3_at_ladder,
1245 uid, xp,
1246 account_get_atteamlevel(account,counter,CLIENTTAG_WARCRAFT3_UINT),
1247 account,
1248 counter,CLIENTTAG_WARCRAFT3_UINT);
1249 }
1250 }
1251 }
1252 */
1253 if ((w3xp_solo_res!=load_success) && ((xp = account_get_ladder_xp(account,CLIENTTAG_WAR3XP_UINT,ladder_id_solo))))
1254 {
1255 war3_ladder_add(&W3XP_solo_ladder,
1256 uid, xp,
1257 account_get_ladder_level(account,CLIENTTAG_WAR3XP_UINT,ladder_id_solo),
1258 account,0,CLIENTTAG_WAR3XP_UINT);
1259 }
1260 if ((w3xp_team_res!=load_success) && ((xp = account_get_ladder_xp(account,CLIENTTAG_WAR3XP_UINT,ladder_id_team))))
1261 {
1262 war3_ladder_add(&W3XP_team_ladder,
1263 uid, xp,
1264 account_get_ladder_level(account,CLIENTTAG_WAR3XP_UINT,ladder_id_team),
1265 account,0,CLIENTTAG_WAR3XP_UINT);
1266
1267 }
1268 if ((w3xp_ffa_res!=load_success) && ((xp = account_get_ladder_xp(account,CLIENTTAG_WAR3XP_UINT,ladder_id_ffa))))
1269 {
1270 war3_ladder_add(&W3XP_ffa_ladder,
1271 uid, xp,
1272 account_get_ladder_level(account,CLIENTTAG_WAR3XP_UINT,ladder_id_ffa),
1273 account,0,
1274 CLIENTTAG_WAR3XP_UINT);
1275 }
1276 // user is part of a team
1277 /*
1278 if ((w3xp_at_res!=load_success) && ((teamcount = account_get_atteamcount(account,CLIENTTAG_WAR3XP_UINT))))
1279 {
1280 int counter;
1281 for (counter=1; counter<=teamcount; counter++)
1282 {
1283
1284 if ((xp = account_get_atteamxp(account,counter,CLIENTTAG_WAR3XP_UINT)) &&
1285 account_get_atteammembers(account,counter,CLIENTTAG_WAR3XP_UINT))
1286 {
1287 war3_ladder_add(&W3XP_at_ladder,
1288 uid, xp,
1289 account_get_atteamlevel(account,counter,CLIENTTAG_WAR3XP_UINT),
1290 account,
1291 counter,CLIENTTAG_WAR3XP_UINT);
1292 }
1293 }
1294 }
1295 */
1296
1297 if ((rating = account_get_ladder_rating(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal))>0)
1298 {
1299 wins = account_get_ladder_wins(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal);
1300
1301 if (star_cr_res!=load_success)
1302 {
1303 war3_ladder_add(&STAR_current_rating, uid,wins,rating,account,0,CLIENTTAG_STARCRAFT_UINT);
1304 }
1305
1306 if (star_cw_res!=load_success)
1307 {
1308 war3_ladder_add(&STAR_current_wins, uid,rating,wins,account,0,CLIENTTAG_STARCRAFT_UINT);
1309 }
1310
1311 if (star_cg_res!=load_success)
1312 {
1313 int games = wins +
1314 account_get_ladder_losses(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal)+
1315 account_get_ladder_disconnects(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal);
1316
1317 war3_ladder_add(&STAR_current_games, uid,rating,games,account,0,CLIENTTAG_STARCRAFT_UINT);
1318 }
1319 }
1320
1321 if ((rating = account_get_ladder_active_rating(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal))>0)
1322 {
1323 wins = account_get_ladder_active_wins(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal);
1324
1325 if (star_ar_res!=load_success)
1326 {
1327 war3_ladder_add(&STAR_active_rating, uid,wins,rating,account,0,CLIENTTAG_STARCRAFT_UINT);
1328 }
1329
1330 if (star_aw_res!=load_success)
1331 {
1332 war3_ladder_add(&STAR_active_wins, uid,rating,wins,account,0,CLIENTTAG_STARCRAFT_UINT);
1333 }
1334
1335 if (star_ag_res!=load_success)
1336 {
1337 int games = wins +
1338 account_get_ladder_active_losses(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal)+
1339 account_get_ladder_active_disconnects(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal);
1340
1341 war3_ladder_add(&STAR_active_games, uid,rating,games,account,0,CLIENTTAG_STARCRAFT_UINT);
1342 }
1343 }
1344
1345 if ((rating = account_get_ladder_rating(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal))>0)
1346 {
1347 wins = account_get_ladder_wins(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal);
1348
1349 if (sexp_cr_res!=load_success)
1350 {
1351 war3_ladder_add(&SEXP_current_rating, uid,wins,rating,account,0,CLIENTTAG_BROODWARS_UINT);
1352 }
1353
1354 if (sexp_cw_res!=load_success)
1355 {
1356 war3_ladder_add(&SEXP_current_wins, uid,rating,wins,account,0,CLIENTTAG_BROODWARS_UINT);
1357 }
1358
1359 if (sexp_cg_res!=load_success)
1360 {
1361 int games = wins +
1362 account_get_ladder_losses(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal)+
1363 account_get_ladder_disconnects(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal);
1364
1365 war3_ladder_add(&SEXP_current_games, uid,rating,games,account,0,CLIENTTAG_BROODWARS_UINT);
1366 }
1367 }
1368
1369 if ((rating = account_get_ladder_active_rating(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal))>0)
1370 {
1371 wins = account_get_ladder_active_wins(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal);
1372
1373 if (sexp_ar_res!=load_success)
1374 {
1375 war3_ladder_add(&SEXP_active_rating, uid,wins,rating,account,0,CLIENTTAG_BROODWARS_UINT);
1376 }
1377
1378 if (sexp_aw_res!=load_success)
1379 {
1380 war3_ladder_add(&SEXP_active_wins, uid,rating,wins,account,0,CLIENTTAG_BROODWARS_UINT);
1381 }
1382
1383 if (sexp_ag_res!=load_success)
1384 {
1385 int games = wins +
1386 account_get_ladder_active_losses(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal)+
1387 account_get_ladder_active_disconnects(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal);
1388
1389 war3_ladder_add(&SEXP_active_games, uid,rating,games,account,0,CLIENTTAG_BROODWARS_UINT);
1390 }
1391 }
1392
1393 if ((rating = account_get_ladder_rating(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal))>0)
1394 {
1395 wins = account_get_ladder_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal);
1396
1397 if (w2bn_cr_res!=load_success)
1398 {
1399 war3_ladder_add(&W2BN_current_rating, uid,wins,rating,account,0,CLIENTTAG_WARCIIBNE_UINT);
1400 }
1401
1402 if (w2bn_cw_res!=load_success)
1403 {
1404 war3_ladder_add(&W2BN_current_wins, uid,rating,wins,account,0,CLIENTTAG_WARCIIBNE_UINT);
1405 }
1406
1407 if (w2bn_cg_res!=load_success)
1408 {
1409 int games = wins +
1410 account_get_ladder_losses(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal)+
1411 account_get_ladder_disconnects(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal);
1412
1413 war3_ladder_add(&W2BN_current_games, uid,rating,games,account,0,CLIENTTAG_WARCIIBNE_UINT);
1414 }
1415 }
1416
1417 if ((rating = account_get_ladder_active_rating(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal))>0)
1418 {
1419 wins = account_get_ladder_active_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal);
1420
1421 if (w2bn_ar_res!=load_success)
1422 {
1423 war3_ladder_add(&W2BN_active_rating, uid,wins,rating,account,0,CLIENTTAG_WARCIIBNE_UINT);
1424 }
1425
1426 if (w2bn_aw_res!=load_success)
1427 {
1428 war3_ladder_add(&W2BN_active_wins, uid,rating,wins,account,0,CLIENTTAG_WARCIIBNE_UINT);
1429 }
1430
1431 if (w2bn_ag_res!=load_success)
1432 {
1433 int games = wins +
1434 account_get_ladder_active_losses(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal)+
1435 account_get_ladder_active_disconnects(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal);
1436
1437 war3_ladder_add(&W2BN_active_games, uid,rating,games,account,0,CLIENTTAG_WARCIIBNE_UINT);
1438 }
1439 }
1440
1441 if ((rating = account_get_ladder_rating(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman))>0)
1442 {
1443 wins = account_get_ladder_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman);
1444
1445 if (w2bn_cri_res!=load_success)
1446 {
1447 war3_ladder_add(&W2BN_current_rating_ironman, uid,wins,rating,account,0,CLIENTTAG_WARCIIBNE_UINT);
1448 }
1449
1450 if (w2bn_cwi_res!=load_success)
1451 {
1452 war3_ladder_add(&W2BN_current_wins_ironman, uid,rating,wins,account,0,CLIENTTAG_WARCIIBNE_UINT);
1453 }
1454
1455 if (w2bn_cgi_res!=load_success)
1456 {
1457 int games = wins +
1458 account_get_ladder_losses(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman)+
1459 account_get_ladder_disconnects(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman);
1460
1461 war3_ladder_add(&W2BN_current_games_ironman, uid,rating,games,account,0,CLIENTTAG_WARCIIBNE_UINT);
1462 }
1463 }
1464
1465 if ((rating = account_get_ladder_active_rating(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman))>0)
1466 {
1467 wins = account_get_ladder_active_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman);
1468
1469 if (w2bn_ari_res!=load_success)
1470 {
1471 war3_ladder_add(&W2BN_active_rating_ironman, uid,wins,rating,account,0,CLIENTTAG_WARCIIBNE_UINT);
1472 }
1473
1474 if (w2bn_awi_res!=load_success)
1475 {
1476 war3_ladder_add(&W2BN_active_wins_ironman, uid,rating,wins,account,0,CLIENTTAG_WARCIIBNE_UINT);
1477 }
1478
1479 if (w2bn_agi_res!=load_success)
1480 {
1481 int games = account_get_ladder_active_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman)+
1482 account_get_ladder_active_losses(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman)+
1483 account_get_ladder_active_disconnects(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman);
1484
1485 war3_ladder_add(&W2BN_active_games_ironman, uid,rating, games,account,0,CLIENTTAG_WARCIIBNE_UINT);
1486 }
1487 }
1488
1489 }
1490 }
1491 }
1492
1493
standard_writer(FILE * fp,t_ladder * ladder,t_clienttag clienttag)1494 int standard_writer(FILE * fp, t_ladder * ladder, t_clienttag clienttag)
1495 {
1496 t_ladder_internal * pointer;
1497 unsigned int rank=0;
1498
1499 pointer = ladder->first;
1500 while (pointer != NULL)
1501 {
1502 rank++;
1503 if (clienttag==CLIENTTAG_WARCRAFT3_UINT || clienttag==CLIENTTAG_WAR3XP_UINT)
1504 {
1505 if (ladder==at_ladder(clienttag))
1506 {
1507 // if in the same team as previous account
1508 if ((pointer) && (pointer->next)
1509 && in_same_team(pointer->account,pointer->next->account,pointer->teamcount,pointer->next->teamcount,clienttag))
1510 {
1511 rank--;
1512 }
1513 // other team... so write all team members names, xp and rank to file
1514 else
1515 {
1516 //fprintf(fp,"%s,%u,%u\n",account_get_atteammembers(pointer->account,pointer->teamcount,clienttag),pointer->xp,rank);
1517 }
1518 }
1519 else
1520 // write username, xp and rank to file
1521 fprintf(fp,"%s,%u,%u\n",account_get_name(pointer->account),pointer->xp,rank);
1522 }
1523 else if (clienttag==CLIENTTAG_STARCRAFT_UINT || clienttag==CLIENTTAG_BROODWARS_UINT || clienttag==CLIENTTAG_WARCIIBNE_UINT)
1524 {
1525 fprintf(fp,"%u %s %u (%u / %u / %u)\n",rank, account_get_name(pointer->account),pointer->level,
1526 account_get_ladder_wins(pointer->account,ladder->clienttag,ladder->ladder_id),
1527 account_get_ladder_losses(pointer->account,ladder->clienttag,ladder->ladder_id),
1528 account_get_ladder_disconnects(pointer->account,ladder->clienttag,ladder->ladder_id));
1529 }
1530 pointer=pointer->prev;
1531 }
1532 return 0;
1533 }
1534
XML_writer(FILE * fp,t_ladder * ladder,t_clienttag clienttag)1535 int XML_writer(FILE * fp, t_ladder * ladder, t_clienttag clienttag)
1536 /* XML Ladder files
1537 * added by jfro
1538 * 1/2/2003
1539 */
1540 {
1541 t_ladder_internal * pointer;
1542 unsigned int rank=0;
1543 unsigned int level;
1544 unsigned int wins;
1545 unsigned int losses;
1546 unsigned int discs;
1547 unsigned int orc_wins,human_wins,undead_wins,nightelf_wins,random_wins;
1548 unsigned int orc_losses,human_losses,undead_losses,nightelf_losses,random_losses;
1549
1550 fprintf(fp,"<?xml version=\"1.0\"?>\n<ladder>\n");
1551 pointer = ladder->first;
1552 while (pointer != NULL)
1553 {
1554 rank++;
1555
1556 if (clienttag==CLIENTTAG_WARCRAFT3_UINT || clienttag==CLIENTTAG_WAR3XP_UINT)
1557 {
1558
1559 if (ladder==at_ladder(clienttag))
1560 {
1561 // if in the same team as previous account
1562 if ((pointer) && (pointer->next)
1563 && in_same_team(pointer->account,pointer->next->account,pointer->teamcount,pointer->next->teamcount,clienttag))
1564 rank--;
1565 else
1566 {
1567 /* other team... so write all team members names, xp and rank to file
1568 fprintf(fp,"\t<team>\n");
1569 if (account_get_atteammembers(pointer->account,pointer->teamcount,clienttag)==NULL)
1570 {
1571 eventlog(eventlog_level_error,__FUNCTION__,"got invalid team, skipping");
1572 pointer=pointer->prev;
1573 continue;
1574 }
1575
1576 members = xstrdup(account_get_atteammembers(pointer->account,pointer->teamcount,clienttag));
1577 for ( member = strtok(members," ");
1578 member;
1579 member = strtok(NULL," "))
1580 fprintf(fp,"\t\t<member>%s</member>\n",member);
1581 xfree(members);
1582 fprintf(fp,"\t\t<xp>%u</xp>\n\t\t<rank>%u</rank>\n\t</team>\n",pointer->xp,rank);
1583 */
1584 }
1585 }
1586 else {
1587 if (ladder==solo_ladder(clienttag)) {
1588 level = account_get_ladder_level(pointer->account,clienttag,ladder_id_solo);
1589 wins = account_get_ladder_wins(pointer->account,clienttag,ladder_id_solo);
1590 losses = account_get_ladder_losses(pointer->account,clienttag,ladder_id_solo);
1591 }
1592 else if (ladder==team_ladder(clienttag)) {
1593 level = account_get_ladder_level(pointer->account,clienttag,ladder_id_team);
1594 wins = account_get_ladder_wins(pointer->account,clienttag,ladder_id_team);
1595 losses = account_get_ladder_losses(pointer->account,clienttag,ladder_id_team);
1596 }
1597 else if (ladder==ffa_ladder(clienttag)) {
1598 level = account_get_ladder_level(pointer->account,clienttag,ladder_id_ffa);
1599 wins = account_get_ladder_wins(pointer->account,clienttag,ladder_id_ffa);
1600 losses = account_get_ladder_losses(pointer->account,clienttag,ladder_id_ffa);
1601 }
1602 else {
1603 level = 0;
1604 wins = 0;
1605 losses = 0;
1606 }
1607 orc_wins = account_get_racewins(pointer->account,W3_RACE_ORCS,clienttag);
1608 orc_losses = account_get_racelosses(pointer->account,W3_RACE_ORCS,clienttag);
1609 undead_wins = account_get_racewins(pointer->account,W3_RACE_UNDEAD,clienttag);
1610 undead_losses = account_get_racelosses(pointer->account,W3_RACE_UNDEAD,clienttag);
1611 human_wins = account_get_racewins(pointer->account,W3_RACE_HUMANS,clienttag);
1612 human_losses = account_get_racelosses(pointer->account,W3_RACE_HUMANS,clienttag);
1613 nightelf_wins = account_get_racewins(pointer->account,W3_RACE_NIGHTELVES,clienttag);
1614 nightelf_losses = account_get_racelosses(pointer->account,W3_RACE_NIGHTELVES,clienttag);
1615 random_wins = account_get_racewins(pointer->account,W3_RACE_RANDOM,clienttag);
1616 random_losses = account_get_racelosses(pointer->account,W3_RACE_RANDOM,clienttag);
1617 // write username, xp and rank to file and everyhing else needed for nice ladder pages
1618 fprintf(fp,"\t<player>\n\t\t<name>%s</name>\n\t\t<level>%u</level>\n\t\t<xp>%u</xp>\n",
1619 account_get_name(pointer->account),level,pointer->xp);
1620 fprintf(fp,"\t\t<wins>%u</wins>\n\t\t<losses>%u</losses>\n\t\t<rank>%u</rank>\n",
1621 wins,losses,rank);
1622 fprintf(fp,"\t\t<races>\n\t\t\t<orc>\n\t\t\t\t<wins>%u</wins>\n\t\t\t\t<losses>%u</losses>\n\t\t\t</orc>\n",
1623 orc_wins,orc_losses);
1624 fprintf(fp,"\t\t\t<human>\n\t\t\t\t<wins>%u</wins>\n\t\t\t\t<losses>%u</losses>\n\t\t\t</human>\n",
1625 human_wins,human_losses);
1626 fprintf(fp,"\t\t\t<nightelf>\n\t\t\t\t<wins>%u</wins>\n\t\t\t\t<losses>%u</losses>\n\t\t\t</nightelf>\n",
1627 nightelf_wins,nightelf_losses);
1628 fprintf(fp,"\t\t\t<undead>\n\t\t\t\t<wins>%u</wins>\n\t\t\t\t<losses>%u</losses>\n\t\t\t</undead>\n",
1629 undead_wins,undead_losses);
1630 fprintf(fp,"\t\t\t<random>\n\t\t\t\t<wins>%u</wins>\n\t\t\t\t<losses>%u</losses>\n\t\t\t</random>\n\t\t</races>\n\t</player>\n",
1631 random_wins,random_losses);
1632 }
1633
1634 } // end: if clienttag WAR3 or WAR3XP
1635 else if (clienttag==CLIENTTAG_STARCRAFT_UINT || clienttag==CLIENTTAG_BROODWARS_UINT || clienttag==CLIENTTAG_WARCIIBNE_UINT)
1636 {
1637 wins = account_get_ladder_wins(pointer->account,ladder->clienttag,ladder->ladder_id);
1638 losses = account_get_ladder_losses(pointer->account,ladder->clienttag,ladder->ladder_id);
1639 discs = account_get_ladder_disconnects(pointer->account,ladder->clienttag,ladder->ladder_id);
1640
1641 fprintf(fp,"\t<player>\n\t\t<rank>%u</rank>\n\t\t<name>%s</name>\n\t\t<rating>%u</rating>\n",
1642 rank, account_get_name(pointer->account),pointer->level);
1643 fprintf(fp,"\t\t<wins>%u</wins>\n\t\t<losses>%u</losses>\n\t\t<discs>%u</discs>\n\t</player>\n",
1644 wins,losses,discs);
1645 }
1646
1647 pointer=pointer->prev;
1648 }
1649 fprintf(fp,"</ladder>\n");
1650 return 0;
1651 }
1652
1653
ladder_write_to_file(char const * filename,t_ladder * ladder,t_clienttag clienttag)1654 extern int ladder_write_to_file(char const * filename, t_ladder * ladder, t_clienttag clienttag)
1655 {
1656 FILE * fp;
1657
1658 if (!filename)
1659 {
1660 eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename");
1661 return -1;
1662 }
1663
1664 if (!(fp = fopen(filename,"w")))
1665 {
1666 eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for writing (fopen: %s)",filename,pstrerror(errno));
1667 return -1;
1668 }
1669
1670 if (prefs_get_XML_output_ladder())
1671 XML_writer(fp,ladder,clienttag);
1672 else
1673 standard_writer(fp,ladder,clienttag);
1674
1675 fclose(fp);
1676 return 0;
1677 }
1678
ladders_write_to_file()1679 extern int ladders_write_to_file()
1680 {
1681
1682 ladder_write_to_file(WAR3_solo_filename, &WAR3_solo_ladder,CLIENTTAG_WARCRAFT3_UINT);
1683 ladder_write_to_file(WAR3_team_filename, &WAR3_team_ladder,CLIENTTAG_WARCRAFT3_UINT);
1684 ladder_write_to_file(WAR3_ffa_filename, &WAR3_ffa_ladder, CLIENTTAG_WARCRAFT3_UINT);
1685 ladder_write_to_file(WAR3_at_filename, &WAR3_at_ladder, CLIENTTAG_WARCRAFT3_UINT);
1686 ladder_write_to_file(W3XP_solo_filename, &W3XP_solo_ladder, CLIENTTAG_WAR3XP_UINT);
1687 ladder_write_to_file(W3XP_team_filename, &W3XP_team_ladder, CLIENTTAG_WAR3XP_UINT);
1688 ladder_write_to_file(W3XP_ffa_filename, &W3XP_ffa_ladder, CLIENTTAG_WAR3XP_UINT);
1689 ladder_write_to_file(W3XP_at_filename, &W3XP_at_ladder, CLIENTTAG_WAR3XP_UINT);
1690 ladder_write_to_file(STAR_ar_filename, &STAR_active_rating, CLIENTTAG_STARCRAFT_UINT);
1691 ladder_write_to_file(STAR_cr_filename, &STAR_current_rating,CLIENTTAG_STARCRAFT_UINT);
1692 ladder_write_to_file(SEXP_ar_filename, &SEXP_active_rating, CLIENTTAG_BROODWARS_UINT);
1693 ladder_write_to_file(SEXP_cr_filename, &SEXP_current_rating,CLIENTTAG_BROODWARS_UINT);
1694 ladder_write_to_file(W2BN_ar_filename, &W2BN_active_rating, CLIENTTAG_WARCIIBNE_UINT);
1695 ladder_write_to_file(W2BN_cr_filename, &W2BN_current_rating,CLIENTTAG_WARCIIBNE_UINT);
1696 ladder_write_to_file(W2BN_ari_filename, &W2BN_active_rating_ironman, CLIENTTAG_WARCIIBNE_UINT);
1697 ladder_write_to_file(W2BN_cri_filename, &W2BN_current_rating_ironman,CLIENTTAG_WARCIIBNE_UINT);
1698
1699 return 0;
1700 }
1701
create_filename(const char * path,const char * filename,const char * ending)1702 extern char * create_filename(const char * path, const char * filename, const char * ending)
1703 {
1704 char * result;
1705
1706 result = xmalloc(strlen(path)+1+strlen(filename)+strlen(ending)+1);
1707 sprintf(result,"%s/%s%s",path,filename,ending);
1708
1709 return result;
1710 }
1711
dispose_filename(char * filename)1712 static void dispose_filename(char * filename)
1713 {
1714 if (filename) xfree(filename);
1715 }
1716
create_filenames(void)1717 void create_filenames(void)
1718 {
1719 // In the ladderdir are binary ladder files, the human readable ladderlist output
1720 // is better in other place, in the outputdir [KWS]
1721
1722 if (prefs_get_XML_output_ladder())
1723 {
1724 WAR3_solo_filename = create_filename(prefs_get_outputdir(),WAR3_solo_file,xml_end);
1725 WAR3_team_filename = create_filename(prefs_get_outputdir(),WAR3_team_file,xml_end);
1726 WAR3_ffa_filename = create_filename(prefs_get_outputdir(),WAR3_ffa_file,xml_end);
1727 WAR3_at_filename = create_filename(prefs_get_outputdir(),WAR3_at_file,xml_end);
1728 W3XP_solo_filename = create_filename(prefs_get_outputdir(),W3XP_solo_file,xml_end);
1729 W3XP_team_filename = create_filename(prefs_get_outputdir(),W3XP_team_file,xml_end);
1730 W3XP_ffa_filename = create_filename(prefs_get_outputdir(),W3XP_ffa_file,xml_end);
1731 W3XP_at_filename = create_filename(prefs_get_outputdir(),W3XP_at_file,xml_end);
1732 STAR_ar_filename = create_filename(prefs_get_outputdir(),STAR_ar_file,xml_end);
1733 STAR_cr_filename = create_filename(prefs_get_outputdir(),STAR_cr_file,xml_end);
1734 SEXP_ar_filename = create_filename(prefs_get_outputdir(),SEXP_ar_file,xml_end);
1735 SEXP_cr_filename = create_filename(prefs_get_outputdir(),SEXP_cr_file,xml_end);
1736 W2BN_ar_filename = create_filename(prefs_get_outputdir(),W2BN_ar_file,xml_end);
1737 W2BN_cr_filename = create_filename(prefs_get_outputdir(),W2BN_cr_file,xml_end);
1738 W2BN_ari_filename = create_filename(prefs_get_outputdir(),W2BN_ari_file,xml_end);
1739 W2BN_cri_filename = create_filename(prefs_get_outputdir(),W2BN_cri_file,xml_end);
1740 }
1741 else
1742 {
1743 WAR3_solo_filename = create_filename(prefs_get_outputdir(),WAR3_solo_file,std_end);
1744 WAR3_team_filename = create_filename(prefs_get_outputdir(),WAR3_team_file,std_end);
1745 WAR3_ffa_filename = create_filename(prefs_get_outputdir(),WAR3_ffa_file,std_end);
1746 WAR3_at_filename = create_filename(prefs_get_outputdir(),WAR3_at_file,std_end);
1747 W3XP_solo_filename = create_filename(prefs_get_outputdir(),W3XP_solo_file,std_end);
1748 W3XP_team_filename = create_filename(prefs_get_outputdir(),W3XP_team_file,std_end);
1749 W3XP_ffa_filename = create_filename(prefs_get_outputdir(),W3XP_ffa_file,std_end);
1750 W3XP_at_filename = create_filename(prefs_get_outputdir(),W3XP_at_file,std_end);
1751 STAR_ar_filename = create_filename(prefs_get_outputdir(),STAR_ar_file,std_end);
1752 STAR_cr_filename = create_filename(prefs_get_outputdir(),STAR_cr_file,std_end);
1753 SEXP_ar_filename = create_filename(prefs_get_outputdir(),SEXP_ar_file,std_end);
1754 SEXP_cr_filename = create_filename(prefs_get_outputdir(),SEXP_cr_file,std_end);
1755 W2BN_ar_filename = create_filename(prefs_get_outputdir(),W2BN_ar_file,std_end);
1756 W2BN_cr_filename = create_filename(prefs_get_outputdir(),W2BN_cr_file,std_end);
1757 W2BN_ari_filename = create_filename(prefs_get_outputdir(),W2BN_ari_file,std_end);
1758 W2BN_cri_filename = create_filename(prefs_get_outputdir(),W2BN_cri_file,std_end);
1759 }
1760 }
1761
ladders_init(void)1762 extern void ladders_init(void)
1763 {
1764 eventlog(eventlog_level_info,__FUNCTION__,"initializing war3 ladders");
1765 ladder_init(&WAR3_solo_ladder, WAR3_SOLO, CLIENTTAG_WARCRAFT3_UINT,ladder_id_solo);
1766 ladder_init(&WAR3_team_ladder, WAR3_TEAM, CLIENTTAG_WARCRAFT3_UINT,ladder_id_team);
1767 ladder_init(&WAR3_ffa_ladder, WAR3_FFA, CLIENTTAG_WARCRAFT3_UINT,ladder_id_ffa);
1768 ladder_init(&WAR3_at_ladder, WAR3_AT, CLIENTTAG_WARCRAFT3_UINT,ladder_id_none);
1769 ladder_init(&W3XP_solo_ladder, W3XP_SOLO, CLIENTTAG_WAR3XP_UINT,ladder_id_solo);
1770 ladder_init(&W3XP_team_ladder, W3XP_TEAM, CLIENTTAG_WAR3XP_UINT,ladder_id_team);
1771 ladder_init(&W3XP_ffa_ladder, W3XP_FFA, CLIENTTAG_WAR3XP_UINT,ladder_id_ffa);
1772 ladder_init(&W3XP_at_ladder, W3XP_AT, CLIENTTAG_WAR3XP_UINT,ladder_id_none);
1773 ladder_init(&STAR_active_rating, STAR_AR, CLIENTTAG_STARCRAFT_UINT,ladder_id_normal);
1774 ladder_init(&STAR_active_wins, STAR_AW, CLIENTTAG_STARCRAFT_UINT,ladder_id_normal);
1775 ladder_init(&STAR_active_games, STAR_AG, CLIENTTAG_STARCRAFT_UINT,ladder_id_normal);
1776 ladder_init(&STAR_current_rating, STAR_CR, CLIENTTAG_STARCRAFT_UINT,ladder_id_normal);
1777 ladder_init(&STAR_current_wins, STAR_CW, CLIENTTAG_STARCRAFT_UINT,ladder_id_normal);
1778 ladder_init(&STAR_current_games, STAR_CG, CLIENTTAG_STARCRAFT_UINT,ladder_id_normal);
1779 ladder_init(&SEXP_active_rating, SEXP_AR, CLIENTTAG_BROODWARS_UINT,ladder_id_normal);
1780 ladder_init(&SEXP_active_wins, SEXP_AW, CLIENTTAG_BROODWARS_UINT,ladder_id_normal);
1781 ladder_init(&SEXP_active_games, SEXP_AG, CLIENTTAG_BROODWARS_UINT,ladder_id_normal);
1782 ladder_init(&SEXP_current_rating, SEXP_CR, CLIENTTAG_BROODWARS_UINT,ladder_id_normal);
1783 ladder_init(&SEXP_current_wins, SEXP_CW, CLIENTTAG_BROODWARS_UINT,ladder_id_normal);
1784 ladder_init(&SEXP_current_games, SEXP_CG, CLIENTTAG_BROODWARS_UINT,ladder_id_normal);
1785 ladder_init(&W2BN_current_rating, W2BN_CR, CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal);
1786 ladder_init(&W2BN_current_wins, W2BN_CW, CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal);
1787 ladder_init(&W2BN_current_games, W2BN_CG, CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal);
1788 ladder_init(&W2BN_current_rating_ironman, W2BN_CRI, CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman);
1789 ladder_init(&W2BN_current_wins_ironman, W2BN_CWI, CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman);
1790 ladder_init(&W2BN_current_games_ironman, W2BN_CGI, CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman);
1791 ladder_init(&W2BN_active_rating, W2BN_AR, CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal);
1792 ladder_init(&W2BN_active_wins, W2BN_AW, CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal);
1793 ladder_init(&W2BN_active_games, W2BN_AG, CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal);
1794 ladder_init(&W2BN_active_rating_ironman, W2BN_ARI, CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman);
1795 ladder_init(&W2BN_active_wins_ironman, W2BN_AWI, CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman);
1796 ladder_init(&W2BN_active_games_ironman, W2BN_AGI, CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman);
1797
1798 create_filenames();
1799 }
1800
dispose_filenames(void)1801 void dispose_filenames(void)
1802 {
1803 dispose_filename(WAR3_solo_filename);
1804 dispose_filename(WAR3_team_filename);
1805 dispose_filename(WAR3_ffa_filename);
1806 dispose_filename(WAR3_at_filename);
1807 dispose_filename(W3XP_solo_filename);
1808 dispose_filename(W3XP_team_filename);
1809 dispose_filename(W3XP_ffa_filename);
1810 dispose_filename(W3XP_at_filename);
1811 dispose_filename(STAR_ar_filename);
1812 dispose_filename(STAR_cr_filename);
1813 dispose_filename(SEXP_ar_filename);
1814 dispose_filename(SEXP_cr_filename);
1815 dispose_filename(W2BN_ar_filename);
1816 dispose_filename(W2BN_cr_filename);
1817 dispose_filename(W2BN_ari_filename);
1818 dispose_filename(W2BN_cri_filename);
1819 }
1820
ladders_destroy(void)1821 extern void ladders_destroy(void)
1822 {
1823 eventlog(eventlog_level_info,__FUNCTION__,"destroying war3 ladders");
1824 ladder_destroy(&WAR3_solo_ladder);
1825 ladder_destroy(&WAR3_team_ladder);
1826 ladder_destroy(&WAR3_ffa_ladder);
1827 ladder_destroy(&WAR3_at_ladder);
1828 ladder_destroy(&W3XP_solo_ladder);
1829 ladder_destroy(&W3XP_team_ladder);
1830 ladder_destroy(&W3XP_ffa_ladder);
1831 ladder_destroy(&W3XP_at_ladder);
1832 ladder_destroy(&STAR_active_rating);
1833 ladder_destroy(&STAR_active_wins);
1834 ladder_destroy(&STAR_active_games);
1835 ladder_destroy(&STAR_current_rating);
1836 ladder_destroy(&STAR_current_wins);
1837 ladder_destroy(&STAR_current_games);
1838 ladder_destroy(&SEXP_active_rating);
1839 ladder_destroy(&SEXP_active_wins);
1840 ladder_destroy(&SEXP_active_games);
1841 ladder_destroy(&SEXP_current_rating);
1842 ladder_destroy(&SEXP_current_wins);
1843 ladder_destroy(&SEXP_current_games);
1844 ladder_destroy(&W2BN_current_rating);
1845 ladder_destroy(&W2BN_current_wins);
1846 ladder_destroy(&W2BN_current_games);
1847 ladder_destroy(&W2BN_current_rating_ironman);
1848 ladder_destroy(&W2BN_current_wins_ironman);
1849 ladder_destroy(&W2BN_current_games_ironman);
1850 ladder_destroy(&W2BN_active_rating);
1851 ladder_destroy(&W2BN_active_wins);
1852 ladder_destroy(&W2BN_active_games);
1853 ladder_destroy(&W2BN_active_rating_ironman);
1854 ladder_destroy(&W2BN_active_wins_ironman);
1855 ladder_destroy(&W2BN_active_games_ironman);
1856 dispose_filenames();
1857 }
1858
ladder_reload_conf(void)1859 extern void ladder_reload_conf(void)
1860 {
1861 dispose_filenames();
1862 create_filenames();
1863 }
1864
ladder_get_from_ladder(t_binary_ladder_types type,int rank,int * results)1865 int ladder_get_from_ladder(t_binary_ladder_types type, int rank,int * results)
1866 {
1867 t_ladder * ladder;
1868 t_ladder_internal * internal;
1869
1870 if (!(results))
1871 {
1872 eventlog(eventlog_level_error,__FUNCTION__,"got NULL results");
1873 return -1;
1874 }
1875
1876 if (!(ladder = binary_ladder_types_to_w3_ladder(type)))
1877 return -1;
1878
1879 if (!(internal = ladder_get_rank_internal(ladder,rank,ladder_get_clienttag(ladder))))
1880 {
1881 return -1;
1882 }
1883
1884 results[0] = internal->uid;
1885 results[1] = internal->xp;
1886 results[2] = internal->level;
1887 results[3] = internal->teamcount;
1888
1889 return 0;
1890 }
1891
ladder_put_into_ladder(t_binary_ladder_types type,int * values)1892 int ladder_put_into_ladder(t_binary_ladder_types type, int * values)
1893 {
1894 t_ladder * ladder;
1895 t_account * acct;
1896
1897 if (!(values))
1898 {
1899 eventlog(eventlog_level_error,__FUNCTION__,"got NULL values");
1900 return -1;
1901 }
1902
1903 if (!(ladder = binary_ladder_types_to_w3_ladder(type)))
1904 return -1;
1905
1906 if ((acct = accountlist_find_account_by_uid(values[0])))
1907 war3_ladder_add(ladder,values[0],values[1],values[2],acct,values[3],ladder_get_clienttag(ladder));
1908 else
1909 eventlog(eventlog_level_error,__FUNCTION__,"no account with this UID - skip");
1910
1911 return 0;
1912 }
1913
ladder_make_active(t_ladder * current,t_ladder * active,int set_attributes)1914 extern int ladder_make_active(t_ladder *current, t_ladder *active,int set_attributes)
1915 {
1916 t_ladder_id id;
1917 t_clienttag clienttag;
1918 t_binary_ladder_types type;
1919 t_ladder_internal * internal;
1920 t_account * account;
1921 char const * timestr;
1922 t_bnettime bt;
1923 int rank = 1;
1924
1925 id = active->ladder_id;
1926 clienttag = active->clienttag;
1927 type = active->type;
1928
1929 //FIXME: take care of ppl that might have drop'ed from ladder !!!
1930 ladder_destroy(active);
1931 ladder_init(active,type,clienttag,id);
1932
1933 while ((internal = ladder_get_rank_internal(current,rank,clienttag)))
1934 {
1935 account = internal->account;
1936 war3_ladder_add(active,internal->uid,internal->xp,internal->level,account,0,clienttag);
1937 if (set_attributes)
1938 {
1939 account_set_ladder_active_wins(account,clienttag,id,account_get_ladder_wins(account,clienttag,id));
1940 account_set_ladder_active_losses(account,clienttag,id,account_get_ladder_losses(account,clienttag,id));
1941 account_set_ladder_active_draws(account,clienttag,id,account_get_ladder_draws(account,clienttag,id));
1942 account_set_ladder_active_disconnects(account,clienttag,id,account_get_ladder_disconnects(account,clienttag,id));
1943 account_set_ladder_active_rating(account,clienttag,id,account_get_ladder_rating(account,clienttag,id));
1944 account_set_ladder_active_rank(account,clienttag,id,account_get_ladder_rank(account,clienttag,id));
1945 if (!(timestr = account_get_ladder_last_time(account,clienttag,id)))
1946 timestr = BNETD_LADDER_DEFAULT_TIME;
1947 bnettime_set_str(&bt,timestr);
1948 account_set_ladder_active_last_time(account,clienttag,id,bt);
1949 }
1950 rank++;
1951 }
1952
1953 //now traverse the current ladder and put everything into the active one....
1954
1955
1956 return 0;
1957 }
1958
ladder_createxptable(const char * xplevelfile,const char * xpcalcfile)1959 extern int ladder_createxptable(const char *xplevelfile, const char *xpcalcfile)
1960 {
1961 FILE *fd1, *fd2;
1962 char buffer[256];
1963 char *p;
1964 t_xpcalc_entry * newxpcalc;
1965 int len,i ,j;
1966 int level, startxp, neededxp, mingames;
1967 float lossfactor;
1968 int minlevel, leveldiff, higher_xpgained, higher_xplost, lower_xpgained, lower_xplost = 10;
1969
1970 if (xplevelfile == NULL || xpcalcfile == NULL) {
1971 eventlog(eventlog_level_error, "ladder_createxptable", "got NULL filename(s)");
1972 return -1;
1973 }
1974
1975 /* first lets open files */
1976 if ((fd1 = fopen(xplevelfile, "rt")) == NULL) {
1977 eventlog(eventlog_level_error, "ladder_createxptable", "could not open XP level file : \"%s\"", xplevelfile);
1978 return -1;
1979 }
1980
1981 if ((fd2 = fopen(xpcalcfile, "rt")) == NULL) {
1982 eventlog(eventlog_level_error, "ladder_createxptable", "could not open XP calc file : \"%s\"", xpcalcfile);
1983 fclose(fd1);
1984 return -1;
1985 }
1986
1987 /* then lets allocate mem for all the arrays */
1988 xpcalc = xmalloc(sizeof(t_xpcalc_entry) * W3_XPCALC_MAXLEVEL); //presume the maximal leveldiff is level number
1989
1990 w3_xpcalc_maxleveldiff = -1;
1991 memset(xpcalc, 0, sizeof(t_xpcalc_entry) * W3_XPCALC_MAXLEVEL);
1992 xplevels = xmalloc(sizeof(t_xplevel_entry) * W3_XPCALC_MAXLEVEL);
1993 memset(xplevels, 0, sizeof(t_xplevel_entry) * W3_XPCALC_MAXLEVEL);
1994
1995 /* finally, lets read from the files */
1996
1997 while(fgets(buffer, 256, fd1)) {
1998 len = strlen(buffer);
1999 if (len < 2) continue;
2000 if (buffer[len - 1] == '\n') buffer[len - 1] = '\0';
2001
2002 /* support comments */
2003 for(p=buffer; *p && *p != '#'; p++);
2004 if (*p == '#') *p = '\0';
2005
2006 if (sscanf(buffer, "%d %d %d %f %d", &level, &startxp, &neededxp, &lossfactor, &mingames) != 5)
2007 continue;
2008
2009 if (level < 1 || level > W3_XPCALC_MAXLEVEL) { /* invalid level */
2010 eventlog(eventlog_level_error, "ladder_createxptable", "read INVALID player level : %d", level);
2011 continue;
2012 }
2013
2014 level--; /* the index in a C array starts from 0 */
2015 xplevels[level].startxp = startxp;
2016 xplevels[level].neededxp = neededxp;
2017 xplevels[level].lossfactor = lossfactor * 100; /* we store the loss factor as % */
2018 xplevels[level].mingames = mingames;
2019 eventlog(eventlog_level_trace, "ladder_createxptable", "inserting level XP info (level: %d, startxp: %d neededxp: %d lossfactor: %d mingames: %d)", level+1, xplevels[level].startxp, xplevels[level].neededxp, xplevels[level].lossfactor, xplevels[level].mingames);
2020 }
2021 fclose(fd1);
2022
2023 while(fgets(buffer, 256, fd2)) {
2024 len = strlen(buffer);
2025 if (len < 2) continue;
2026 if (buffer[len - 1] == '\n') buffer[len - 1] = '\0';
2027
2028 /* support comments */
2029 for(p=buffer; *p && *p != '#'; p++);
2030 if (*p == '#') *p = '\0';
2031
2032 if (sscanf(buffer, " %d %d %d %d %d %d ", &minlevel, &leveldiff, &higher_xpgained, &higher_xplost, &lower_xpgained, &lower_xplost) != 6)
2033 continue;
2034
2035 eventlog(eventlog_level_trace, "ladder_createxptable", "parsed xpcalc leveldiff : %d", leveldiff);
2036
2037 if (leveldiff <0) {
2038 eventlog(eventlog_level_error, "ladder_createxptable", "got invalid level diff : %d", leveldiff);
2039 continue;
2040 }
2041
2042 if (leveldiff> (w3_xpcalc_maxleveldiff+1)) {
2043 eventlog(eventlog_level_error, __FUNCTION__,"expected entry for leveldiff=%u but found %u",w3_xpcalc_maxleveldiff+1,leveldiff);
2044 continue;
2045 }
2046
2047 w3_xpcalc_maxleveldiff = leveldiff;
2048
2049 xpcalc[leveldiff].higher_winxp = higher_xpgained;
2050 xpcalc[leveldiff].higher_lossxp = higher_xplost;
2051 xpcalc[leveldiff].lower_winxp = lower_xpgained;
2052 xpcalc[leveldiff].lower_lossxp = lower_xplost;
2053 }
2054 fclose(fd2);
2055
2056 newxpcalc = xrealloc(xpcalc, sizeof(t_xpcalc_entry) * (w3_xpcalc_maxleveldiff+1));
2057 xpcalc=newxpcalc;
2058
2059 /* OK, now we need to test couse if the user forgot to put some values
2060 * lots of profiles could get screwed up
2061 */
2062
2063 if (w3_xpcalc_maxleveldiff<0)
2064 {
2065 eventlog(eventlog_level_error,__FUNCTION__,"found no valid entries for WAR3 xp calculation");
2066 ladder_destroyxptable();
2067 return -1;
2068 }
2069
2070 eventlog(eventlog_level_info,__FUNCTION__,"set war3 xpcalc maxleveldiff to %u",w3_xpcalc_maxleveldiff);
2071
2072 for(j=0;j<=w3_xpcalc_maxleveldiff;j++)
2073 if (xpcalc[j].higher_winxp == 0 || xpcalc[j].higher_lossxp == 0 ||
2074 xpcalc[j].lower_winxp == 0 || xpcalc[j].lower_lossxp == 0) {
2075 eventlog(eventlog_level_error, "ladder_createxptable", "i found 0 for a win/loss XP, please check your config file");
2076 ladder_destroyxptable();
2077 return -1;
2078 }
2079
2080 for (i=0; i<W3_XPCALC_MAXLEVEL; i++)
2081 if ((i > 0 && xplevels[i].neededxp == 0) || xplevels[i].lossfactor == 0
2082 || xplevels[i].neededxp > xplevels[i].startxp
2083 || (i > 0 && (xplevels[i].startxp <= xplevels[i-1].startxp || xplevels[i].neededxp < xplevels[i-1].neededxp))) {
2084 eventlog(eventlog_level_error, "ladder_createxptable", "i found 0 for a level XP, please check your config file (level: %d neededxp: %d lossfactor: %d)", i+1, xplevels[i].neededxp , xplevels[i].lossfactor);
2085 ladder_destroyxptable();
2086 return -1;
2087 }
2088
2089 return 0;
2090 }
2091
ladder_destroyxptable()2092 extern void ladder_destroyxptable()
2093 {
2094 if (xpcalc != NULL) xfree(xpcalc);
2095 if (xplevels != NULL) xfree(xplevels);
2096 }
2097
war3_get_maxleveldiff()2098 extern int war3_get_maxleveldiff()
2099 {
2100 return w3_xpcalc_maxleveldiff;
2101 }
2102
2103
ladder_war3_xpdiff(unsigned int winnerlevel,unsigned int looserlevel,int * winxpdiff,int * loosxpdiff)2104 extern int ladder_war3_xpdiff(unsigned int winnerlevel, unsigned int looserlevel, int *winxpdiff, int *loosxpdiff)
2105 {
2106 int diff, absdiff;
2107
2108 diff = winnerlevel - looserlevel;
2109 absdiff = (diff < 0)?(-diff):diff;
2110
2111 if (absdiff > w3_xpcalc_maxleveldiff) {
2112 eventlog(eventlog_level_error, "ladder_war3_xpdiff", "got invalid level difference : %d", absdiff);
2113 return -1;
2114 }
2115
2116 if (winnerlevel > W3_XPCALC_MAXLEVEL || looserlevel > W3_XPCALC_MAXLEVEL || winnerlevel <1 || looserlevel<1) {
2117 eventlog(eventlog_level_error, "ladder_war3_xpdiff", "got invalid account levels (win: %d loss: %d)",winnerlevel, looserlevel);
2118 return -1;
2119 }
2120
2121 if (winxpdiff == NULL || loosxpdiff == NULL) {
2122 eventlog(eventlog_level_error, "ladder_war3_xpdiff", "got NULL winxpdiff, loosxpdiff");
2123 return -1;
2124 }
2125 /* we return the xp difference for the winner and the looser
2126 * we compute that from the xp charts also applying the loss factor for
2127 * lower level profiles
2128 * FIXME: ?! loss factor doesnt keep the sum of xp won/lost constant
2129 * DON'T CARE, cause current win/loss values aren't symetrical any more
2130 */
2131 if (diff >= 0) {
2132 *winxpdiff = xpcalc[absdiff].higher_winxp;
2133 *loosxpdiff = - (xpcalc[absdiff].lower_lossxp * xplevels[looserlevel - 1].lossfactor) / 100;
2134 } else {
2135 *winxpdiff = xpcalc[absdiff].lower_winxp;
2136 *loosxpdiff = - (xpcalc[absdiff].higher_lossxp * xplevels[looserlevel - 1].lossfactor) / 100;
2137 }
2138
2139 return 0;
2140 }
2141
ladder_war3_updatelevel(unsigned int oldlevel,int xp)2142 extern int ladder_war3_updatelevel(unsigned int oldlevel, int xp)
2143 {
2144 int i, mylevel;
2145
2146 if (oldlevel < 1 || oldlevel > W3_XPCALC_MAXLEVEL) {
2147 eventlog(eventlog_level_error, "ladder_war3_updatelevel", "got invalid level: %d", oldlevel);
2148 return oldlevel;
2149 }
2150
2151 if (xp <= 0) return 1;
2152
2153 mylevel = oldlevel;
2154
2155 for(i=mylevel ; i < W3_XPCALC_MAXLEVEL; i++)
2156 if (xplevels[i].startxp > xp) { mylevel = i; break;}
2157
2158 for(i=mylevel - 1; i >0 ; i--)
2159 if (xplevels[i-1].startxp < xp) { mylevel = i+1; break; }
2160
2161 return mylevel;
2162 }
2163
ladder_war3_get_min_xp(unsigned int Level)2164 extern int ladder_war3_get_min_xp(unsigned int Level)
2165 {
2166 if (Level < 1 || Level > W3_XPCALC_MAXLEVEL)
2167 {
2168 eventlog(eventlog_level_error,__FUNCTION__,"got invalid Level %d",Level);
2169 return -1;
2170 }
2171 return xplevels[Level-1].startxp;
2172 }
2173