Fix crash after recursive aliasing
[capablanca.git] / lasker-2.2.3 / src / makerank.c
1 /*
2    This program is free software; you can redistribute it and/or modify
3    it under the terms of the GNU General Public License as published by
4    the Free Software Foundation; either version 2 of the License, or
5    (at your option) any later version.
6    
7    This program is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10    GNU General Public License for more details.
11    
12    You should have received a copy of the GNU General Public License
13    along with this program; if not, write to the Free Software
14    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17
18 #include "includes.h"
19
20 #define COMPUTER_FILE LISTS_DIR "/computer"
21
22 static char *rnames[] = {"std", "blitz", "wild", "lightning"};
23
24 typedef struct _ratings {
25   int rating;
26   int num;
27   double rd;
28   long ltime;
29 } ratings;
30
31 typedef struct _Entry {
32   char name[MAX_LOGIN_NAME+2];
33   ratings r[4];
34   int computer;
35 } ENTRY;
36
37 static ENTRY **list;
38 static ENTRY **sortme;
39
40 unsigned chessd_reload_flag;
41
42 static void copy_stats(ratings *r, struct statistics *s)
43 {
44         r->num = s->num;
45         r->rating = s->rating;
46         r->rd = s->sterr;
47         r->ltime = s->ltime;
48 }
49
50 /*
51   read a player file using the new generic and extensible format 
52 */
53 static int GetPlayerInfo(char *fileName, ENTRY *e)
54 {
55         char *s, *s2;       
56         struct player player;
57         unsigned version;
58
59         s = file_load(fileName, NULL);
60         if (!s) {
61                 d_printf("Error reading player file '%s'\n", fileName);
62                 return 0;
63         }
64
65         if (sscanf(s, "v %u", &version) != 1 || 
66             (version != 100 && version != 9)) {
67                 free(s);
68                 return 0;
69         }
70
71         /* skip first line */
72         s2 = strchr(s, '\n');
73
74         ZERO_STRUCT(player);
75
76         if (!s2 || unmarshall_player(&player, s2) != 0) {
77                 d_printf("Error unmarshalling player data in '%s'!\n", fileName);
78                 free(s);
79                 return 0;
80         }
81         free(s);
82
83         strcpy(e->name, player.name);
84         copy_stats(&e->r[0], &player.s_stats);
85         copy_stats(&e->r[1], &player.b_stats);
86         copy_stats(&e->r[2], &player.w_stats);
87         copy_stats(&e->r[3], &player.l_stats);
88
89         player_free(&player);
90
91         return 1;
92 }
93
94 static int LoadEntries(void)
95 {
96   int listsize;
97   FILE *fpPlayerList;
98   char letter1;
99   char *command;
100   char pathInput[80];
101   ENTRY e;
102   int len, n = 0;
103
104   listsize = 100;
105   list = malloc(sizeof(ENTRY *)*listsize);
106
107   for (letter1 = 'a'; letter1 <= 'z'; letter1++) {
108     printf("Loading %c's.\n", letter1);
109     sprintf(pathInput, "%s/%c", PLAYER_DIR, letter1);
110     asprintf(&command, "ls -1 %s", pathInput);
111     fpPlayerList = popen(command, "r");
112     free(command);
113  
114     if (fpPlayerList == NULL)
115       continue;
116     while (1) {
117       fgets(e.name, MAX_LOGIN_NAME, fpPlayerList);
118       if (feof(fpPlayerList))
119         break;
120       len = strlen(e.name);
121       e.name[len - 1] = '\0';
122       if (e.name[0] != letter1)
123         printf("File %c/%s:  wrong directory.\n", letter1, e.name);
124       else {
125         sprintf(pathInput, "%s/%c/%s", PLAYER_DIR, letter1, e.name);
126         if (GetPlayerInfo(pathInput, &e)) {
127           if ((list[n] = malloc(sizeof(ENTRY))) == NULL) {
128             d_printf( "malloc() failed!\n");
129           } else {
130             memcpy(list[n], &e, sizeof(ENTRY));
131             n++;
132             if (n == listsize) {
133               listsize += 100;
134               list = realloc(list, listsize*sizeof(ENTRY *));
135             }
136           }
137         }
138       }
139     }
140     pclose(fpPlayerList);
141   }
142   return (n);
143 }
144
145 static int SetComputers(int n)
146 {
147   FILE *fpComp;
148   int i = 0;
149   char *line, comp[30];
150
151   asprintf(&line, "sort -f %s", COMPUTER_FILE);
152   fpComp = popen(line, "r");
153   free(line);
154
155   if (fpComp == NULL)
156     return 0;
157   while (i < n) {
158     fgets(comp, 29, fpComp);
159     if (feof(fpComp))
160       break;
161     comp[strlen(comp) - 1] = '\0';
162
163     while (i < n && strcasecmp(list[i]->name, comp) < 0)
164       i++;
165
166     if (i < n && strcasecmp(list[i]->name, comp) == 0) {
167       list[i++]->computer = 1;
168     }
169   }
170   pclose(fpComp);
171   return(1);
172 }
173
174 static int rtype;
175
176 static int sortfunc(const void *i, const void *j)
177 {
178   int n = (*(ENTRY **)j)->r[rtype].rating - (*(ENTRY **)i)->r[rtype].rating;
179   return n ? n : strcasecmp((*(ENTRY **)i)->name, (*(ENTRY **)j)->name);
180 }
181
182 static void makerank(void)
183 {
184   int sortnum, sortmesize, i, n;
185   FILE *fp;
186   char *fName;
187   long now = time(NULL);
188
189   printf("Loading players\n");
190   n = LoadEntries();
191   printf("Found %d players.\n", n);
192   printf("Setting computers.\n");
193   SetComputers(n);
194
195   for (rtype = 0; rtype < 4; rtype++) {
196     sortnum = 0; sortmesize = 100;
197     sortme = malloc(sizeof(ENTRY *)*sortmesize);
198
199     for (i = 0; i < n; i++) {
200       if (list[i]->r[rtype].rating) {
201         sortme[sortnum++] = list[i];
202         if (sortnum == sortmesize) {
203           sortmesize += 100;
204           sortme = realloc(sortme, sortmesize*sizeof(ENTRY *));
205         }
206       }
207     }
208     printf("Sorting %d %s.\n", sortnum, rnames[rtype]);
209     qsort(sortme, sortnum, sizeof(ENTRY *), sortfunc);
210     printf("Saving to file.\n");
211     asprintf(&fName, "%s/rank.%s", STATS_DIR, rnames[rtype]);
212     fp = fopen_s(fName, "w");
213     free(fName);
214
215     for (i = 0; i < sortnum; i++)
216       fprintf(fp, "%s %d %d %d %f\n", sortme[i]->name,
217               sortme[i]->r[rtype].rating, sortme[i]->r[rtype].num,
218               sortme[i]->computer, current_sterr(sortme[i]->r[rtype].rd,
219                                             now - sortme[i]->r[rtype].ltime));
220     fclose(fp);
221     free(sortme);
222   }
223 }
224
225 int main(int argc, char **argv)
226 {
227   if (argc > 1) {
228     printf("usage: %s.\n", argv[0]);
229     exit(0);
230   } else {
231     makerank();
232   }
233   return (0);
234 }
235