Mercurial > repo
comparison interps/fukyorbrane/report.c @ 996:859f9b4339e6
<Gregor> tar xf egobot.tar.xz
author | HackBot |
---|---|
date | Sun, 09 Dec 2012 19:30:08 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
995:6883f5911eb7 | 996:859f9b4339e6 |
---|---|
1 /* | |
2 * Copyright (c) 2009, 2011 Gregor Richards | |
3 * | |
4 * Permission is hereby granted, free of charge, to any person obtaining a copy | |
5 * of this software and associated documentation files (the "Software"), to deal | |
6 * in the Software without restriction, including without limitation the rights | |
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
8 * copies of the Software, and to permit persons to whom the Software is | |
9 * furnished to do so, subject to the following conditions: | |
10 * | |
11 * The above copyright notice and this permission notice shall be included in | |
12 * all copies or substantial portions of the Software. | |
13 * | |
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
20 * SOFTWARE. | |
21 */ | |
22 | |
23 /* NOTE: I am aware of how ugly this code is. It was quick hack. */ | |
24 | |
25 #ifndef _BSD_SOURCE | |
26 #define _BSD_SOURCE | |
27 #endif | |
28 | |
29 #include <pthread.h> | |
30 #include <fcntl.h> | |
31 #include <signal.h> | |
32 #include <stdio.h> | |
33 #include <stdlib.h> | |
34 #include <string.h> | |
35 #include <sys/types.h> | |
36 #include <sys/wait.h> | |
37 #include <unistd.h> | |
38 | |
39 #include "helpers.h" | |
40 | |
41 #define MINTAPELEN 10 | |
42 #define MAXTAPELEN 30 | |
43 #define POLARITIES 4 | |
44 #define RUNCOUNT (((MAXTAPELEN-MINTAPELEN) + 1) * POLARITIES) | |
45 | |
46 #define KEEP_PROGRAMS 47 | |
47 | |
48 char *fyb, *cachedir; | |
49 int programCount; | |
50 char **programs; | |
51 char *scores; | |
52 int breakdown; | |
53 | |
54 struct ProgramScore { | |
55 int id; | |
56 int pts; | |
57 double prc; | |
58 }; | |
59 | |
60 void *runnerThread(void *pvp) | |
61 { | |
62 int p = (int) (size_t) pvp; | |
63 int row = p * programCount; | |
64 pid_t pid; | |
65 int i; | |
66 int st; | |
67 char *cacheFilename; | |
68 FILE *cacheF; | |
69 | |
70 /* go through each program ... */ | |
71 for (i = 0; i < programCount; i++) { | |
72 if (p == i) continue; | |
73 | |
74 /* check the cache */ | |
75 SF(cacheFilename, malloc, NULL, (strlen(cachedir) + strlen(programs[p]) + strlen(programs[i]) + 5)); | |
76 sprintf(cacheFilename, "%s/:%s:%s:", cachedir, programs[p], programs[i]); | |
77 cacheF = fopen(cacheFilename, "r"); | |
78 | |
79 st = -1; | |
80 if (cacheF != NULL) { | |
81 /* get the result out of the cache */ | |
82 st = getc(cacheF); | |
83 fclose(cacheF); | |
84 if (st == EOF) | |
85 st = -1; | |
86 scores[row + i] = st; | |
87 | |
88 } | |
89 | |
90 if (st == -1) { | |
91 /* and run p vs i */ | |
92 SF(pid, fork, -1, ()); | |
93 if (pid == 0) { | |
94 close(0); | |
95 close(1); | |
96 close(2); | |
97 dup2(breakdown, 1); | |
98 execlp(fyb, fyb, programs[p], programs[i], NULL); | |
99 exit(0); | |
100 } | |
101 | |
102 /* wait for it */ | |
103 waitpid(pid, &st, 0); | |
104 | |
105 /* then get the score */ | |
106 if (WIFEXITED(st)) { | |
107 st = WEXITSTATUS(st); | |
108 } else { | |
109 st = 0; | |
110 } | |
111 scores[row + i] = st; | |
112 | |
113 /* and cache it */ | |
114 cacheF = fopen(cacheFilename, "w"); | |
115 if (cacheF != NULL) { | |
116 putc(st, cacheF); | |
117 fclose(cacheF); | |
118 } | |
119 } | |
120 | |
121 free(cacheFilename); | |
122 } | |
123 | |
124 return NULL; | |
125 } | |
126 | |
127 int winner(int p1, int p2) | |
128 { | |
129 char win1, win2; | |
130 | |
131 win1 = scores[p1*programCount + p2]; | |
132 win2 = scores[p2*programCount + p1]; | |
133 if (win1 == 1 && win2 != 1) | |
134 return p1; | |
135 else if (win1 == 2 && win2 != 2) | |
136 return p2; | |
137 else if (win2 == 2 && win1 != 2) | |
138 return p1; | |
139 else if (win2 == 1 && win1 != 1) | |
140 return p2; | |
141 | |
142 return -1; | |
143 } | |
144 | |
145 int ptscompar(const void *lv, const void *rv) | |
146 { | |
147 const struct ProgramScore *l = *((const struct ProgramScore **) lv); | |
148 const struct ProgramScore *r = *((const struct ProgramScore **) rv); | |
149 | |
150 if (l->pts < r->pts) { | |
151 return -1; | |
152 } else if (l->pts > r->pts) { | |
153 return 1; | |
154 } else { | |
155 return 0; | |
156 } | |
157 } | |
158 | |
159 int prccompar(const void *lv, const void *rv) | |
160 { | |
161 const struct ProgramScore *l = *((const struct ProgramScore **) lv); | |
162 const struct ProgramScore *r = *((const struct ProgramScore **) rv); | |
163 | |
164 if (l->prc < r->prc) { | |
165 return -1; | |
166 } else if (l->prc > r->prc) { | |
167 return 1; | |
168 } else { | |
169 return 0; | |
170 } | |
171 } | |
172 | |
173 int main(int argc, char **argv) | |
174 { | |
175 pthread_t *threads; | |
176 int i, j; | |
177 int *plainScores; | |
178 double *preciseScores; | |
179 struct ProgramScore **allScores; | |
180 char *scoreFilename; | |
181 FILE *scoreF; | |
182 | |
183 if (argc < 4) { | |
184 fprintf(stderr, "Use: report <fyb program> <cache dir> <fyb files>\n"); | |
185 return 1; | |
186 } | |
187 | |
188 fyb = argv[1]; | |
189 cachedir = argv[2]; | |
190 programCount = argc - 3; | |
191 programs = argv + 3; | |
192 | |
193 signal(SIGCHLD, SIG_DFL); | |
194 | |
195 /* allocate space for the scores */ | |
196 SF(scores, malloc, NULL, (programCount * programCount)); | |
197 | |
198 /* now run them in threads */ | |
199 breakdown = open("breakdown.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666); | |
200 SF(threads, malloc, NULL, (programCount * sizeof(pthread_t))); | |
201 for (i = 0; i < programCount; i++) { | |
202 /*pthread_create(&threads[i], NULL, runnerThread, (void *) (size_t) i);*/ | |
203 runnerThread((void *) (size_t) i); | |
204 } | |
205 close(breakdown); | |
206 | |
207 /* wait for the threads to finish * / | |
208 for (i = 0; i < programCount; i++) { | |
209 pthread_join(threads[i], NULL); | |
210 } */ | |
211 | |
212 /* allocate the score buffers */ | |
213 SF(allScores, malloc, NULL, (programCount * sizeof(struct ProgramScore *))); | |
214 for (i = 0; i < programCount; i++) { | |
215 SF(allScores[i], malloc, NULL, (sizeof(struct ProgramScore))); | |
216 allScores[i]->id = i; | |
217 } | |
218 | |
219 /* now calculate the plain score for each */ | |
220 SF(plainScores, malloc, NULL, (programCount * sizeof(int))); | |
221 for (i = 0; i < programCount; i++) { | |
222 int score = 0; | |
223 for (j = 0; j < programCount; j++) { | |
224 int win; | |
225 | |
226 if (i == j) continue; | |
227 | |
228 win = winner(i, j); | |
229 if (win == i) { | |
230 score++; | |
231 } else if (win == j) { | |
232 score--; | |
233 } | |
234 } | |
235 allScores[i]->pts = plainScores[i] = score; | |
236 } | |
237 | |
238 /* and the precise scores for each */ | |
239 SF(preciseScores, malloc, NULL, (programCount * sizeof(double))); | |
240 for (i = 0; i < programCount; i++) { | |
241 double score = 0; | |
242 for (j = 0; j < programCount; j++) { | |
243 double value; | |
244 int win; | |
245 | |
246 if (i == j) continue; | |
247 | |
248 /* get the value of j */ | |
249 value = (double) (plainScores[j] + programCount) / (double) (2*programCount-2); | |
250 | |
251 /* and add the value if correct */ | |
252 win = winner(i, j); | |
253 if (win == i) { | |
254 score += value; | |
255 } else if (win == 0) { | |
256 score += value/2; | |
257 } | |
258 } | |
259 allScores[i]->prc = preciseScores[i] = score * 200 / (programCount-1); | |
260 | |
261 /* save it to the cache */ | |
262 SF(scoreFilename, malloc, NULL, (strlen(cachedir) + strlen(programs[i]) + 8)); | |
263 sprintf(scoreFilename, "%s/%s.score", cachedir, programs[i]); | |
264 scoreF = fopen(scoreFilename, "w"); | |
265 if (scoreF != NULL) { | |
266 fprintf(scoreF, "%.1f", preciseScores[i]); | |
267 fclose(scoreF); | |
268 } | |
269 free(scoreFilename); | |
270 } | |
271 | |
272 /* now print out the scores */ | |
273 qsort(allScores, programCount, sizeof(struct ProgramScore *), prccompar); | |
274 printf("Pos ID Score Points Program\n"); | |
275 for (i = programCount - 1; i >= 0; i--) { | |
276 struct ProgramScore *sc = allScores[i]; | |
277 printf(" %2d %2d %6.2f %6.2f %s\n", | |
278 programCount - i, (int) sc->id, sc->prc, sc->pts, programs[sc->id]); | |
279 } | |
280 printf("\n"); | |
281 | |
282 /* and the full scoreboard */ | |
283 | |
284 /* header */ | |
285 printf(" | "); | |
286 for (i = 0; i < programCount; i++) { | |
287 if (i < 10) printf(" "); | |
288 else printf("%1d ", (int) (i/10%10)); | |
289 } | |
290 printf("|\n | "); | |
291 for (i = 0; i < programCount; i++) { | |
292 printf("%1d ", (int) (i%10)); | |
293 } | |
294 printf("| score | pts | program\n"); | |
295 | |
296 /* scores */ | |
297 for (i = 0; i < programCount; i++) { | |
298 printf("%2d | ", (int) i); | |
299 for (j = 0; j < programCount; j++) { | |
300 int win; | |
301 | |
302 if (i == j) { | |
303 printf(" "); | |
304 continue; | |
305 } | |
306 | |
307 win = winner(i, j); | |
308 if (win == i) { | |
309 printf("+ "); | |
310 } else if (win == j) { | |
311 printf("- "); | |
312 } else { | |
313 printf("0 "); | |
314 } | |
315 } | |
316 | |
317 printf("| %5.1f | %3d | %s\n", preciseScores[i], plainScores[i], programs[i]); | |
318 } | |
319 | |
320 /* kill any poorly-performing programs */ | |
321 if (programCount > KEEP_PROGRAMS) { | |
322 for (i = 0; i < programCount - KEEP_PROGRAMS; i++) { | |
323 char buf[1024]; | |
324 snprintf(buf, 1024, "hg rm -f %s", programs[allScores[i]->id]); | |
325 system(buf); | |
326 system(buf + 3); | |
327 } | |
328 system("hg commit -m Trimming."); | |
329 } | |
330 | |
331 return 0; | |
332 } |