/[LeafOK_CVS]/pvpgn-1.7.4/src/bnetd/ladder.c
ViewVC logotype

Contents of /pvpgn-1.7.4/src/bnetd/ladder.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (show annotations) (vendor branch)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
Branch: GNU, MAIN
CVS Tags: pvpgn_1-7-4-0_MIL, arelease, HEAD
Changes since 1.1: +0 -0 lines
Content type: text/x-csrc
no message

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

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1