comparison src/tool-hs.c @ 8:0836fb919dfa

First entry of Paradise Server 2.9 patch 10 Beta
author darius
date Sat, 06 Dec 1997 04:37:05 +0000
parents
children
comparison
equal deleted inserted replaced
7:814de70c9f67 8:0836fb919dfa
1 /*--------------------------------------------------------------------------
2 NETREK II -- Paradise
3
4 Permission to use, copy, modify, and distribute this software and its
5 documentation, or any derivative works thereof, for any NON-COMMERCIAL
6 purpose and without fee is hereby granted, provided that this copyright
7 notice appear in all copies. No representations are made about the
8 suitability of this software for any purpose. This software is provided
9 "as is" without express or implied warranty.
10
11 Xtrek Copyright 1986 Chris Guthrie
12 Netrek (Xtrek II) Copyright 1989 Kevin P. Smith
13 Scott Silvey
14 Paradise II (Netrek II) Copyright 1993 Larry Denys
15 Kurt Olsen
16 Brandon Gillespie
17 --------------------------------------------------------------------------*/
18
19 /*
20 * This is probably broken in anything but the default config
21 */
22
23 #include "config.h"
24
25 #include <stdio.h>
26 #include <malloc.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include "struct.h"
30 #include "data.h"
31
32 int topn = 1;
33 char name[40] = ""; /* if we want stats for a particular name */
34 int nplayers;
35 struct statentry *database;
36
37 struct highscore
38 {
39 char name[32];
40 int di, tkills, tlosses, tarmsbomb, tresbomb, tdooshes, tplanets;
41 int ticks;
42 struct highscore *next;
43 };
44
45 struct highscore *scores;
46 int scoresize, nscores;
47
48 void
49 subbrag(name, stuff, time, title, descr, num)
50 char *name;
51 int stuff, time;
52 char *title;
53 char *descr;
54 int num;
55 {
56 char full[64];
57 char line[80];
58 int len, tlen;
59 int i;
60 double rate;
61
62 if (title)
63 {
64 sprintf(full, "%s: %s", title, name);
65
66 len = strlen(full);
67 tlen = title ? strlen(title) : 0;
68
69 for (i = len; i - tlen < 10; i++)
70 full[i] = ' ';
71 full[i] = 0;
72 }
73 else
74 {
75 strcpy(full, name);
76 }
77
78 if (topn != 1)
79 sprintf(line, "%15s %3d over ", full, stuff);
80 else
81 sprintf(line, "%-30s (%2d) %3d %s, over ", full, num, stuff, descr);
82
83 if (time / 10.0 > 3600)
84 sprintf(line, "%s%1.2f hours ", line, time / 36000.0);
85 else
86 sprintf(line, "%s%1.2f minutes ", line, time / 600.0);
87
88 if (topn == 1)
89 sprintf(line, "%s\n%40s", line, "");
90
91 rate = stuff / (time / 600.0);
92
93 if (rate < 1)
94 {
95 printf(line);
96 printf("(%1.2f minutes per)\n", 1 / rate);
97 }
98 else if (rate > 60)
99 {
100 printf(line);
101 printf("(%1.2f per hour)\n", rate / 60);
102 }
103 else
104 {
105 printf(line);
106 printf("(%1.2f per minute)\n", rate);
107 }
108 }
109
110 void
111 brag(title, descr, offset)
112 char *title, *descr;
113 {
114 int i;
115 if (name[0] != 0)
116 {
117 for (i = 0; i < nscores; i++)
118 {
119 if (0 == strcmp(scores[i].name, name))
120 {
121 printf("#%5d: ", i + 1);
122 subbrag("", *(int *) (offset + (char *) &scores[i]),
123 scores[i].ticks, title, descr, i);
124 break;
125 }
126 }
127 }
128 else
129 {
130 if (topn != 1)
131 printf("\n%s (%s)\n", title, descr);
132 for (i = 0; i < topn && i < nscores; i++)
133 {
134 printf("%10s", "");
135 subbrag(scores[i].name, *(int *) (offset + (char *) &scores[i]),
136 scores[i].ticks, topn == 1 ? title : (char *) 0, descr, i);
137 }
138 }
139 }
140
141 #if __STDC__
142 #define COMPUTE(STN) \
143 do { \
144 currscore->STN = currplayer.stats.st_ ## STN - \
145 prevplayer->stats.st_ ## STN; \
146 } while (0)
147
148
149 #define COMPARE(STN) \
150 int cmp_raw ## STN(a,b) \
151 struct highscore *a, *b; \
152 { \
153 int diff = a->STN - b->STN; \
154 \
155 if (diff<0) \
156 return 1; \
157 else if (diff==0) \
158 return 0; \
159 else \
160 return -1; \
161 } \
162 \
163 int cmp_per ## STN(a,b) \
164 struct highscore *a, *b; \
165 { \
166 double diff = a->STN/(double)a->ticks - b->STN/(double)b->ticks; \
167 \
168 if (diff<0) \
169 return 1; \
170 else if (diff==0) \
171 return 0; \
172 else \
173 return -1; \
174 }
175 #else
176 #define COMPUTE(STN) \
177 do { \
178 currscore->STN = currplayer.stats.st_/**/STN - \
179 prevplayer->stats.st_/**/STN; \
180 } while (0)
181
182
183 #define COMPARE(STN) \
184 int cmp_raw/**/STN(a,b) \
185 struct highscore *a, *b; \
186 { \
187 int diff = a->STN - b->STN; \
188 \
189 if (diff<0) \
190 return 1; \
191 else if (diff==0) \
192 return 0; \
193 else \
194 return -1; \
195 } \
196 \
197 int cmp_per/**/STN(a,b) \
198 struct highscore *a, *b; \
199 { \
200 double diff = a->STN/(double)a->ticks - b->STN/(double)b->ticks; \
201 \
202 if (diff<0) \
203 return 1; \
204 else if (diff==0) \
205 return 0; \
206 else \
207 return -1; \
208 }
209 #endif
210
211 COMPARE(di)
212 COMPARE(tkills)
213 COMPARE(tlosses)
214 COMPARE(tarmsbomb)
215 COMPARE(tresbomb)
216 COMPARE(tdooshes)
217 COMPARE(tplanets)
218 int cmp_ticks(a, b)
219 struct highscore *a, *b;
220 {
221 int diff = a->ticks - b->ticks;
222
223 if (diff < 0)
224 return 1;
225 else if (diff == 0)
226 return 0;
227 else
228 return -1;
229 }
230
231 struct statentry zeroplayer;
232
233 int
234 different(one, two)
235 struct highscore *one, *two;
236 {
237 return 0 != strcmp(one->name, two->name);
238 }
239
240 double atof();
241
242 int
243 main(argc, argv)
244 int argc;
245 char **argv;
246 {
247 struct stat fstats;
248 FILE *fp;
249 int i;
250 int code = 0;
251 struct statentry currplayer;
252 char **av;
253 int usage = 0;
254 float mintime = 30.0;
255
256 for (av = &argv[1]; *av && (*av)[0] == '-'; av++)
257 {
258 if (0 == strcmp(*av, "-n") && av[1])
259 {
260 topn = atoi(*++av);
261 }
262 else if (0 == strcmp(*av, "-c") && av[1])
263 {
264 code = atoi(*++av);
265 }
266 else if (0 == strcmp(*av, "-name") && av[1])
267 {
268 strcpy(name, *++av);
269 }
270 else if (0 == strcmp(*av, "-time") && av[1])
271 {
272 mintime = atof(*++av);
273 }
274 else
275 {
276 usage = 1;
277 break;
278 }
279 }
280 if (argc - (av - argv) != 2)
281 {
282 usage = 1;
283 }
284
285 if (usage)
286 {
287 int x;
288 char message[][255] = {
289 "\nHigh Scores, created by comparing two databases.\n",
290 "\n\t'%s -n <num> -c <num> [-name <name>] <old db> <new db>'\n\n",
291 "Options:\n",
292 "\t-n num How many high scores to print\n",
293 "\t-c num Which category (0 is all, max available is 15)\n",
294 "\t-name string print ranking for a particular player\n",
295 "\nExample:\t'%s -n 5 -c 1 .players.bak .players'\n\n",
296 "\0"
297 };
298
299 fprintf(stderr, "--- %s ---\n", PARAVERS);
300 for (x = 0; *message[x] != '\0'; x++)
301 fprintf(stderr, message[x], argv[0]);
302
303 exit(1);
304 }
305
306 fp = fopen(av[0], "r");
307 if (fp == 0)
308 {
309 fprintf(stderr, "Couldn't open file %s for read", av[0]);
310 perror("");
311 exit(1);
312 }
313
314 if (fstat(fileno(fp), &fstats) < 0)
315 {
316 fprintf(stderr, "Couldn't fstat file %s", av[0]);
317 perror("");
318 exit(1);
319 }
320
321 nplayers = fstats.st_size / sizeof(*database);
322 database = (struct statentry *) malloc(sizeof(*database) * nplayers);
323
324 i = fread(database, sizeof(*database), nplayers, fp);
325
326 if (i == 0)
327 {
328 fprintf(stderr, "failed to read any player records from file %s\n", av[0]);
329 exit(1);
330 }
331 if (i != nplayers)
332 {
333 fprintf(stderr, "failed to read all player records from file %s (%d of %d)\n", av[0], i, nplayers);
334 nplayers = i;
335 }
336
337 fclose(fp);
338
339 fp = fopen(av[1], "r");
340 if (fp == 0)
341 {
342 fprintf(stderr, "Couldn't open file %s for read", av[1]);
343 perror("");
344 exit(1);
345 }
346
347
348 scores = (struct highscore *) malloc(sizeof(*scores) * (scoresize = 256));
349 nscores = 0;
350
351 while (1)
352 {
353 int delta;
354 int dt;
355 struct statentry *prevplayer;
356 struct highscore *currscore;
357
358 i = fread(&currplayer, sizeof(currplayer), 1, fp);
359 if (i < 0)
360 {
361 fprintf(stderr, "error reading player record, aborting loop\n");
362 perror("");
363 }
364 if (i <= 0)
365 break;
366
367 for (i = 0; i < nplayers; i++)
368 {
369 if (0 == strcmp(database[i].name, currplayer.name))
370 break;
371 }
372 if (i < nplayers)
373 prevplayer = &database[i];
374 else
375 prevplayer = &zeroplayer;
376
377 dt = currplayer.stats.st_tticks - prevplayer->stats.st_tticks;
378
379 if (dt < mintime /* minutes */ * 60 * 10)
380 continue;
381
382 if (nscores >= scoresize)
383 {
384 scores = (struct highscore *) realloc(scores, sizeof(*scores) * (scoresize *= 2));
385 }
386 currscore = &scores[nscores++];
387 strcpy(currscore->name, currplayer.name);
388 currscore->ticks = dt;
389
390 COMPUTE(di);
391 COMPUTE(tkills);
392 COMPUTE(tlosses);
393 COMPUTE(tarmsbomb);
394 COMPUTE(tresbomb);
395 COMPUTE(tdooshes);
396 COMPUTE(tplanets);
397 }
398
399
400 #define offset(field) ( (int)&(((struct highscore*)0)->field) )
401
402 if (!code || code == 1)
403 {
404 qsort(scores, nscores, sizeof(*scores), cmp_rawdi);
405 brag("Lord of Destruction", "most destruction inflicted", offset(di));
406 }
407
408 if (!code && topn > 5)
409 printf("\t@@b\n");
410
411 if (!code || code == 2)
412 {
413 qsort(scores, nscores, sizeof(*scores), cmp_perdi);
414 brag("BlitzMeister", "fastest destruction inflicted", offset(di));
415 }
416
417 if (!code && topn > 5)
418 printf("\t@@b\n");
419
420 if (!code || code == 3)
421 {
422 qsort(scores, nscores, sizeof(*scores), cmp_rawtkills);
423 brag("Hitler", "most opponents defeated", offset(tkills));
424 }
425
426 if (!code && topn > 5)
427 printf("\t@@b\n");
428
429 if (!code || code == 4)
430 {
431 qsort(scores, nscores, sizeof(*scores), cmp_pertkills);
432 brag("Terminator", "fastest opponents defeated", offset(tkills));
433 }
434
435 if (!code && topn > 5)
436 printf("\t@@b\n");
437
438 if (!code || code == 5)
439 {
440 qsort(scores, nscores, sizeof(*scores), cmp_rawtlosses);
441 brag("Kamikaze", "most times down in flames", offset(tlosses));
442 }
443
444 if (!code && topn > 5)
445 printf("\t@@b\n");
446
447 if (!code || code == 6)
448 {
449 qsort(scores, nscores, sizeof(*scores), cmp_pertlosses);
450 brag("Speed Kamikaze", "fastest times down in flames", offset(tlosses));
451 }
452
453 if (!code && topn > 5)
454 printf("\t@@b\n");
455
456 if (!code || code == 7)
457 {
458 qsort(scores, nscores, sizeof(*scores), cmp_rawtarmsbomb);
459 brag("Carpet Bomber", "most armies bombed", offset(tarmsbomb));
460 }
461
462 if (!code && topn > 5)
463 printf("\t@@b\n");
464
465 if (!code || code == 8)
466 {
467 qsort(scores, nscores, sizeof(*scores), cmp_pertarmsbomb);
468 brag("NukeMeister", "fastest armies bombed", offset(tarmsbomb));
469 }
470
471 if (!code && topn > 5)
472 printf("\t@@b\n");
473
474 if (!code || code == 9)
475 {
476 qsort(scores, nscores, sizeof(*scores), cmp_rawtresbomb);
477 brag("Terrorist", "most resources leveled", offset(tresbomb));
478 }
479
480 if (!code && topn > 5)
481 printf("\t@@b\n");
482
483 if (!code || code == 10)
484 {
485 qsort(scores, nscores, sizeof(*scores), cmp_pertresbomb);
486 brag("Democrat", "fastest resources leveled", offset(tresbomb));
487 }
488
489 if (!code && topn > 5)
490 printf("\t@@b\n");
491
492 if (!code || code == 11)
493 {
494 qsort(scores, nscores, sizeof(*scores), cmp_rawtdooshes);
495 brag("Executioner", "most armies dooshed", offset(tdooshes));
496 }
497
498 if (!code && topn > 5)
499 printf("\t@@b\n");
500
501 if (!code || code == 12)
502 {
503 qsort(scores, nscores, sizeof(*scores), cmp_pertdooshes);
504 brag("DooshMeister", "fastest armies dooshed", offset(tdooshes));
505 }
506
507 if (!code && topn > 5)
508 printf("\t@@b\n");
509
510 if (!code || code == 13)
511 {
512 qsort(scores, nscores, sizeof(*scores), cmp_rawtplanets);
513 brag("Diplomat", "most planets taken", offset(tplanets));
514 }
515
516 if (!code && topn > 5)
517 printf("\t@@b\n");
518
519 if (!code || code == 14)
520 {
521 qsort(scores, nscores, sizeof(*scores), cmp_pertplanets);
522 brag("speed Diplomat", "fastest planets taken", offset(tplanets));
523 }
524
525 if (!code && topn > 5)
526 printf("\t@@b\n");
527
528 if (!code || code == 15)
529 {
530 qsort(scores, nscores, sizeof(*scores), cmp_ticks);
531 if (name[0] != 0)
532 {
533 for (i = 0; i < nscores; i++)
534 {
535 if (0 == strcmp(scores[i].name, name))
536 {
537 printf("#%5d:%30s with %1.2f hours\n", i + 1, scores[i].name,
538 scores[i].ticks / 36000.0);
539 break;
540 }
541 }
542 }
543 else if (topn > 1)
544 {
545 int i;
546 printf("Addicts:\n");
547 for (i = 0; i < topn && i < nscores; i++)
548 {
549 printf("%30s with %1.2f hours\n", scores[i].name, scores[i].ticks / 36000.0);
550 }
551 }
552 else
553 {
554 printf("Addict: %s with %1.2f hours\n", scores[0].name, scores[0].ticks / 36000.0);
555 }
556 }
557
558 exit(0);
559 }