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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (hide 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 sysadm 1.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