Mercurial > ~darius > hgwebdir.cgi > paradise_server
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tool-hs.c Sat Dec 06 04:37:05 1997 +0000 @@ -0,0 +1,559 @@ +/*-------------------------------------------------------------------------- +NETREK II -- Paradise + +Permission to use, copy, modify, and distribute this software and its +documentation, or any derivative works thereof, for any NON-COMMERCIAL +purpose and without fee is hereby granted, provided that this copyright +notice appear in all copies. No representations are made about the +suitability of this software for any purpose. This software is provided +"as is" without express or implied warranty. + + Xtrek Copyright 1986 Chris Guthrie + Netrek (Xtrek II) Copyright 1989 Kevin P. Smith + Scott Silvey + Paradise II (Netrek II) Copyright 1993 Larry Denys + Kurt Olsen + Brandon Gillespie +--------------------------------------------------------------------------*/ + +/* + * This is probably broken in anything but the default config + */ + +#include "config.h" + +#include <stdio.h> +#include <malloc.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "struct.h" +#include "data.h" + +int topn = 1; +char name[40] = ""; /* if we want stats for a particular name */ +int nplayers; +struct statentry *database; + +struct highscore +{ + char name[32]; + int di, tkills, tlosses, tarmsbomb, tresbomb, tdooshes, tplanets; + int ticks; + struct highscore *next; +}; + +struct highscore *scores; +int scoresize, nscores; + +void +subbrag(name, stuff, time, title, descr, num) + char *name; + int stuff, time; + char *title; + char *descr; + int num; +{ + char full[64]; + char line[80]; + int len, tlen; + int i; + double rate; + + if (title) + { + sprintf(full, "%s: %s", title, name); + + len = strlen(full); + tlen = title ? strlen(title) : 0; + + for (i = len; i - tlen < 10; i++) + full[i] = ' '; + full[i] = 0; + } + else + { + strcpy(full, name); + } + + if (topn != 1) + sprintf(line, "%15s %3d over ", full, stuff); + else + sprintf(line, "%-30s (%2d) %3d %s, over ", full, num, stuff, descr); + + if (time / 10.0 > 3600) + sprintf(line, "%s%1.2f hours ", line, time / 36000.0); + else + sprintf(line, "%s%1.2f minutes ", line, time / 600.0); + + if (topn == 1) + sprintf(line, "%s\n%40s", line, ""); + + rate = stuff / (time / 600.0); + + if (rate < 1) + { + printf(line); + printf("(%1.2f minutes per)\n", 1 / rate); + } + else if (rate > 60) + { + printf(line); + printf("(%1.2f per hour)\n", rate / 60); + } + else + { + printf(line); + printf("(%1.2f per minute)\n", rate); + } +} + +void +brag(title, descr, offset) + char *title, *descr; +{ + int i; + if (name[0] != 0) + { + for (i = 0; i < nscores; i++) + { + if (0 == strcmp(scores[i].name, name)) + { + printf("#%5d: ", i + 1); + subbrag("", *(int *) (offset + (char *) &scores[i]), + scores[i].ticks, title, descr, i); + break; + } + } + } + else + { + if (topn != 1) + printf("\n%s (%s)\n", title, descr); + for (i = 0; i < topn && i < nscores; i++) + { + printf("%10s", ""); + subbrag(scores[i].name, *(int *) (offset + (char *) &scores[i]), + scores[i].ticks, topn == 1 ? title : (char *) 0, descr, i); + } + } +} + +#if __STDC__ +#define COMPUTE(STN) \ + do { \ + currscore->STN = currplayer.stats.st_ ## STN - \ + prevplayer->stats.st_ ## STN; \ + } while (0) + + +#define COMPARE(STN) \ +int cmp_raw ## STN(a,b) \ + struct highscore *a, *b; \ +{ \ + int diff = a->STN - b->STN; \ + \ + if (diff<0) \ + return 1; \ + else if (diff==0) \ + return 0; \ + else \ + return -1; \ +} \ + \ +int cmp_per ## STN(a,b) \ + struct highscore *a, *b; \ +{ \ + double diff = a->STN/(double)a->ticks - b->STN/(double)b->ticks; \ + \ + if (diff<0) \ + return 1; \ + else if (diff==0) \ + return 0; \ + else \ + return -1; \ +} +#else +#define COMPUTE(STN) \ + do { \ + currscore->STN = currplayer.stats.st_/**/STN - \ + prevplayer->stats.st_/**/STN; \ + } while (0) + + +#define COMPARE(STN) \ +int cmp_raw/**/STN(a,b) \ + struct highscore *a, *b; \ +{ \ + int diff = a->STN - b->STN; \ + \ + if (diff<0) \ + return 1; \ + else if (diff==0) \ + return 0; \ + else \ + return -1; \ +} \ + \ +int cmp_per/**/STN(a,b) \ + struct highscore *a, *b; \ +{ \ + double diff = a->STN/(double)a->ticks - b->STN/(double)b->ticks; \ + \ + if (diff<0) \ + return 1; \ + else if (diff==0) \ + return 0; \ + else \ + return -1; \ +} +#endif + +COMPARE(di) +COMPARE(tkills) +COMPARE(tlosses) +COMPARE(tarmsbomb) +COMPARE(tresbomb) +COMPARE(tdooshes) +COMPARE(tplanets) + int cmp_ticks(a, b) + struct highscore *a, *b; +{ + int diff = a->ticks - b->ticks; + + if (diff < 0) + return 1; + else if (diff == 0) + return 0; + else + return -1; +} + +struct statentry zeroplayer; + +int +different(one, two) + struct highscore *one, *two; +{ + return 0 != strcmp(one->name, two->name); +} + +double atof(); + +int +main(argc, argv) + int argc; + char **argv; +{ + struct stat fstats; + FILE *fp; + int i; + int code = 0; + struct statentry currplayer; + char **av; + int usage = 0; + float mintime = 30.0; + + for (av = &argv[1]; *av && (*av)[0] == '-'; av++) + { + if (0 == strcmp(*av, "-n") && av[1]) + { + topn = atoi(*++av); + } + else if (0 == strcmp(*av, "-c") && av[1]) + { + code = atoi(*++av); + } + else if (0 == strcmp(*av, "-name") && av[1]) + { + strcpy(name, *++av); + } + else if (0 == strcmp(*av, "-time") && av[1]) + { + mintime = atof(*++av); + } + else + { + usage = 1; + break; + } + } + if (argc - (av - argv) != 2) + { + usage = 1; + } + + if (usage) + { + int x; + char message[][255] = { + "\nHigh Scores, created by comparing two databases.\n", + "\n\t'%s -n <num> -c <num> [-name <name>] <old db> <new db>'\n\n", + "Options:\n", + "\t-n num How many high scores to print\n", + "\t-c num Which category (0 is all, max available is 15)\n", + "\t-name string print ranking for a particular player\n", + "\nExample:\t'%s -n 5 -c 1 .players.bak .players'\n\n", + "\0" + }; + + fprintf(stderr, "--- %s ---\n", PARAVERS); + for (x = 0; *message[x] != '\0'; x++) + fprintf(stderr, message[x], argv[0]); + + exit(1); + } + + fp = fopen(av[0], "r"); + if (fp == 0) + { + fprintf(stderr, "Couldn't open file %s for read", av[0]); + perror(""); + exit(1); + } + + if (fstat(fileno(fp), &fstats) < 0) + { + fprintf(stderr, "Couldn't fstat file %s", av[0]); + perror(""); + exit(1); + } + + nplayers = fstats.st_size / sizeof(*database); + database = (struct statentry *) malloc(sizeof(*database) * nplayers); + + i = fread(database, sizeof(*database), nplayers, fp); + + if (i == 0) + { + fprintf(stderr, "failed to read any player records from file %s\n", av[0]); + exit(1); + } + if (i != nplayers) + { + fprintf(stderr, "failed to read all player records from file %s (%d of %d)\n", av[0], i, nplayers); + nplayers = i; + } + + fclose(fp); + + fp = fopen(av[1], "r"); + if (fp == 0) + { + fprintf(stderr, "Couldn't open file %s for read", av[1]); + perror(""); + exit(1); + } + + + scores = (struct highscore *) malloc(sizeof(*scores) * (scoresize = 256)); + nscores = 0; + + while (1) + { + int delta; + int dt; + struct statentry *prevplayer; + struct highscore *currscore; + + i = fread(&currplayer, sizeof(currplayer), 1, fp); + if (i < 0) + { + fprintf(stderr, "error reading player record, aborting loop\n"); + perror(""); + } + if (i <= 0) + break; + + for (i = 0; i < nplayers; i++) + { + if (0 == strcmp(database[i].name, currplayer.name)) + break; + } + if (i < nplayers) + prevplayer = &database[i]; + else + prevplayer = &zeroplayer; + + dt = currplayer.stats.st_tticks - prevplayer->stats.st_tticks; + + if (dt < mintime /* minutes */ * 60 * 10) + continue; + + if (nscores >= scoresize) + { + scores = (struct highscore *) realloc(scores, sizeof(*scores) * (scoresize *= 2)); + } + currscore = &scores[nscores++]; + strcpy(currscore->name, currplayer.name); + currscore->ticks = dt; + + COMPUTE(di); + COMPUTE(tkills); + COMPUTE(tlosses); + COMPUTE(tarmsbomb); + COMPUTE(tresbomb); + COMPUTE(tdooshes); + COMPUTE(tplanets); + } + + +#define offset(field) ( (int)&(((struct highscore*)0)->field) ) + + if (!code || code == 1) + { + qsort(scores, nscores, sizeof(*scores), cmp_rawdi); + brag("Lord of Destruction", "most destruction inflicted", offset(di)); + } + + if (!code && topn > 5) + printf("\t@@b\n"); + + if (!code || code == 2) + { + qsort(scores, nscores, sizeof(*scores), cmp_perdi); + brag("BlitzMeister", "fastest destruction inflicted", offset(di)); + } + + if (!code && topn > 5) + printf("\t@@b\n"); + + if (!code || code == 3) + { + qsort(scores, nscores, sizeof(*scores), cmp_rawtkills); + brag("Hitler", "most opponents defeated", offset(tkills)); + } + + if (!code && topn > 5) + printf("\t@@b\n"); + + if (!code || code == 4) + { + qsort(scores, nscores, sizeof(*scores), cmp_pertkills); + brag("Terminator", "fastest opponents defeated", offset(tkills)); + } + + if (!code && topn > 5) + printf("\t@@b\n"); + + if (!code || code == 5) + { + qsort(scores, nscores, sizeof(*scores), cmp_rawtlosses); + brag("Kamikaze", "most times down in flames", offset(tlosses)); + } + + if (!code && topn > 5) + printf("\t@@b\n"); + + if (!code || code == 6) + { + qsort(scores, nscores, sizeof(*scores), cmp_pertlosses); + brag("Speed Kamikaze", "fastest times down in flames", offset(tlosses)); + } + + if (!code && topn > 5) + printf("\t@@b\n"); + + if (!code || code == 7) + { + qsort(scores, nscores, sizeof(*scores), cmp_rawtarmsbomb); + brag("Carpet Bomber", "most armies bombed", offset(tarmsbomb)); + } + + if (!code && topn > 5) + printf("\t@@b\n"); + + if (!code || code == 8) + { + qsort(scores, nscores, sizeof(*scores), cmp_pertarmsbomb); + brag("NukeMeister", "fastest armies bombed", offset(tarmsbomb)); + } + + if (!code && topn > 5) + printf("\t@@b\n"); + + if (!code || code == 9) + { + qsort(scores, nscores, sizeof(*scores), cmp_rawtresbomb); + brag("Terrorist", "most resources leveled", offset(tresbomb)); + } + + if (!code && topn > 5) + printf("\t@@b\n"); + + if (!code || code == 10) + { + qsort(scores, nscores, sizeof(*scores), cmp_pertresbomb); + brag("Democrat", "fastest resources leveled", offset(tresbomb)); + } + + if (!code && topn > 5) + printf("\t@@b\n"); + + if (!code || code == 11) + { + qsort(scores, nscores, sizeof(*scores), cmp_rawtdooshes); + brag("Executioner", "most armies dooshed", offset(tdooshes)); + } + + if (!code && topn > 5) + printf("\t@@b\n"); + + if (!code || code == 12) + { + qsort(scores, nscores, sizeof(*scores), cmp_pertdooshes); + brag("DooshMeister", "fastest armies dooshed", offset(tdooshes)); + } + + if (!code && topn > 5) + printf("\t@@b\n"); + + if (!code || code == 13) + { + qsort(scores, nscores, sizeof(*scores), cmp_rawtplanets); + brag("Diplomat", "most planets taken", offset(tplanets)); + } + + if (!code && topn > 5) + printf("\t@@b\n"); + + if (!code || code == 14) + { + qsort(scores, nscores, sizeof(*scores), cmp_pertplanets); + brag("speed Diplomat", "fastest planets taken", offset(tplanets)); + } + + if (!code && topn > 5) + printf("\t@@b\n"); + + if (!code || code == 15) + { + qsort(scores, nscores, sizeof(*scores), cmp_ticks); + if (name[0] != 0) + { + for (i = 0; i < nscores; i++) + { + if (0 == strcmp(scores[i].name, name)) + { + printf("#%5d:%30s with %1.2f hours\n", i + 1, scores[i].name, + scores[i].ticks / 36000.0); + break; + } + } + } + else if (topn > 1) + { + int i; + printf("Addicts:\n"); + for (i = 0; i < topn && i < nscores; i++) + { + printf("%30s with %1.2f hours\n", scores[i].name, scores[i].ticks / 36000.0); + } + } + else + { + printf("Addict: %s with %1.2f hours\n", scores[0].name, scores[0].ticks / 36000.0); + } + } + + exit(0); +}