1 /* players.c
2
3 GNU Chess frontend
4
5 Copyright (C) 2001-2011 Free Software Foundation, Inc.
6
7 GNU Chess is based on the two research programs
8 Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
9
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22
23 Contact Info:
24 bug-gnu-chess@gnu.org
25 cracraft@ai.mit.edu, cracraft@stanfordalumni.org, cracraft@earthlink.net
26 */
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31
32 #include "common.h"
33
34 #define PLAYERFILE "players.dat"
35
36 int totalplayers = 0;
37
38 #define MAXPLAYERS 500
39
40 typedef struct {
41 char player[MAXNAMESZ];
42 int wins;
43 int losses;
44 int draws;
45 } playerentry;
46
47 playerentry playerdb[MAXPLAYERS];
48 static char lname[MAXNAMESZ];
49
rscorecompare(const void * aa,const void * bb)50 static int rscorecompare(const void *aa, const void *bb)
51 {
52 const playerentry *a = (const playerentry *)aa;
53 const playerentry *b = (const playerentry *)bb;
54 float ascore, bscore;
55 ascore = (a->wins+(a->draws/2))/(a->wins+a->draws+a->losses);
56 bscore = (b->wins+(b->draws/2))/(b->wins+b->draws+b->losses);
57 if (ascore > bscore) return(-1);
58 else if (bscore > ascore) return(1);
59 else return(0);
60 }
61
scorecompare(const void * aa,const void * bb)62 static int scorecompare(const void *aa, const void *bb)
63 {
64 const playerentry *a = (const playerentry *)aa;
65 const playerentry *b = (const playerentry *)bb;
66 int ascore, bscore;
67 ascore = 100*(a->wins+(a->draws/2))/(a->wins+a->draws+a->losses);
68 bscore = 100*(b->wins+(b->draws/2))/(b->wins+b->draws+b->losses);
69 if (bscore > ascore) return(1);
70 else if (bscore < ascore) return(-1);
71 else return(0);
72 }
73
namecompare(const void * aa,const void * bb)74 static int namecompare(const void *aa, const void *bb)
75 {
76 const playerentry *a = (const playerentry *)aa;
77 const playerentry *b = (const playerentry *)bb;
78 if (strcmp(a->player,b->player) > 0) return(1);
79 else if (strcmp(a->player,b->player) < 0) return(-1);
80 else return(0);
81 }
82
DBSortPlayer(const char * style)83 void DBSortPlayer (const char *style)
84 {
85 if (strncmp(style,"score",5) == 0) {
86 qsort(&playerdb,totalplayers,sizeof(playerentry),scorecompare);
87 } else if (strncmp(style,"name",4) == 0) {
88 qsort(&playerdb,totalplayers,sizeof(playerentry),namecompare);
89 } else if (strncmp(style,"reverse",7) == 0) {
90 qsort(&playerdb,totalplayers,sizeof(playerentry),rscorecompare);
91 }
92 }
93
DBListPlayer(const char * style)94 void DBListPlayer (const char *style)
95 {
96 int i;
97
98 DBReadPlayer ();
99 DBSortPlayer (style);
100 for (i = 0; i < totalplayers; i++) {
101 printf("%s %2.0f%% %d %d %d\n",
102 playerdb[i].player,
103 100.0*(playerdb[i].wins+((float)playerdb[i].draws/2))/
104 (playerdb[i].wins+playerdb[i].draws+playerdb[i].losses),
105 playerdb[i].wins,
106 playerdb[i].losses,
107 playerdb[i].draws);
108 if ((i+1) % 10 == 0) {printf("[Type a character to continue.]\n"); getchar();}
109 }
110 }
111
DBWritePlayer(void)112 void DBWritePlayer (void)
113 {
114 int i;
115 FILE *wfp;
116 DBSortPlayer ("reverse");
117 if ((wfp = fopen(PLAYERFILE,"w")) != NULL) {
118 for (i = 0; i < totalplayers; i++) {
119 fprintf(wfp,"%s %d %d %d\n",
120 playerdb[i].player,
121 playerdb[i].wins,
122 playerdb[i].losses,
123 playerdb[i].draws);
124 }
125 }
126 fclose(wfp);
127 }
128
DBReadPlayer(void)129 void DBReadPlayer (void)
130 {
131 FILE *rfp;
132 int n;
133 totalplayers = 0;
134 if ((rfp = fopen(PLAYERFILE,"r")) != NULL) {
135 while (!feof(rfp)) {
136 n = fscanf(rfp,"%49s %d %d %d\n", /* 49 MAXNAMESZ-1 */
137 playerdb[totalplayers].player,
138 &playerdb[totalplayers].wins,
139 &playerdb[totalplayers].losses,
140 &playerdb[totalplayers].draws);
141 if (n == 4) totalplayers++;
142 }
143 fclose(rfp);
144 }
145 }
146
DBSearchPlayer(const char * player)147 int DBSearchPlayer (const char *player)
148 {
149 int index = -1;
150 int i;
151
152 for (i = 0; i < totalplayers; i++)
153 if (strncmp(playerdb[i].player,player,strlen(playerdb[i].player)) == 0)
154 {
155 index = i;
156 break;
157 }
158 return (index);
159 }
160
DBUpdatePlayer(const char * player,const char * resultstr)161 void DBUpdatePlayer (const char *player, const char *resultstr)
162 {
163 const char *p;
164 char *x;
165 int index;
166 int result = R_NORESULT;
167
168 p = player;
169 x = lname;
170 strcpy(lname,player);
171 do {
172 if (*p != ' ')
173 *x++ = *p++;
174 else
175 p++;
176 } while (*p != '\0');
177 *x = '\000';
178 memset(playerdb,0,sizeof(playerdb));
179 DBReadPlayer ();
180 index = DBSearchPlayer (lname);
181 if (index == -1) {
182 strcpy(playerdb[totalplayers].player,lname);
183 playerdb[totalplayers].wins = 0;
184 playerdb[totalplayers].losses = 0;
185 playerdb[totalplayers].draws = 0;
186 index = totalplayers;
187 totalplayers++;
188 }
189 if (strncmp(resultstr,"1-0",3) == 0)
190 result = R_WHITE_WINS;
191 else if (strncmp(resultstr,"0-1",3) == 0)
192 result = R_BLACK_WINS;
193 else if (strncmp(resultstr,"1/2-1/2",7) == 0)
194 result = R_DRAW;
195
196 if ((computerplays == white && result == R_WHITE_WINS)||
197 (computerplays == black && result == R_BLACK_WINS))
198 playerdb[index].wins++;
199 else if ((computerplays == white && result == R_BLACK_WINS)||
200 (computerplays == black && result == R_WHITE_WINS))
201 playerdb[index].losses++;
202 else
203 /* Shouln't one check for draw here? Broken PGN files surely exist */
204 playerdb[index].draws++;
205 DBWritePlayer ();
206 }
207