Mercurial > repo
diff interps/bfjoust/report.c @ 996:859f9b4339e6
<Gregor> tar xf egobot.tar.xz
author | HackBot |
---|---|
date | Sun, 09 Dec 2012 19:30:08 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/interps/bfjoust/report.c Sun Dec 09 19:30:08 2012 +0000 @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2009, 2011 Gregor Richards + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* NOTE: I am aware of how ugly this code is. It was quick hack. */ + +#ifndef _BSD_SOURCE +#define _BSD_SOURCE +#endif + +#include <pthread.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#include "helpers.h" + +#define MINTAPELEN 10 +#define MAXTAPELEN 30 +#define POLARITIES 2 +#define RUNCOUNT (((MAXTAPELEN-MINTAPELEN) + 1) * POLARITIES) + +#define KEEP_PROGRAMS 47 + +char *fyb, *cachedir; +int programCount; +char **programs; +signed char *scores; +int breakdown; + +struct ProgramScore { + int id; + double pts; + double prc; +}; + +void *runnerThread(void *pvp) +{ + int p = (int) (size_t) pvp; + int row = p * programCount; + pid_t pid; + int i, tmpi; + int st; + int scorepipe[2]; + char scorepipes[128]; + char *cacheFilename; + FILE *cacheF; + + /* go through each program ... */ + for (i = p + 1; i < programCount; i++) { + /* check the cache */ + SF(cacheFilename, malloc, NULL, (strlen(cachedir) + strlen(programs[p]) + strlen(programs[i]) + 5)); + sprintf(cacheFilename, "%s/:%s:%s:", cachedir, programs[p], programs[i]); + cacheF = fopen(cacheFilename, "r"); + + st = -1; + if (cacheF != NULL) { + /* get the result out of the cache */ + st = (signed char) getc(cacheF); + fclose(cacheF); + if (st == EOF) + st = -1; + scores[row + i] = st; + + } + + if (st == -1) { + /* and run p vs i */ + SF(tmpi, pipe, -1, (scorepipe)); + sprintf(scorepipes, "%d", scorepipe[1]); + SF(pid, fork, -1, ()); + if (pid == 0) { + close(0); + close(1); + close(2); + dup2(breakdown, 1); + execlp(fyb, fyb, programs[p], programs[i], scorepipes, NULL); + exit(0); + } + close(scorepipe[1]); + + /* wait for it */ + waitpid(pid, &st, 0); + + if (WEXITSTATUS(st) != 0) { + st = 0; + } else { + /* read in the score */ + st = 0; + SF(tmpi, read, -1, (scorepipe[0], &st, sizeof(int))); + scores[row + i] = st; + } + close(scorepipe[0]); + + /* and cache it */ + cacheF = fopen(cacheFilename, "w"); + if (cacheF != NULL) { + putc(st, cacheF); + fclose(cacheF); + } + } + + free(cacheFilename); + } + + return NULL; +} + +/* returns points won by p1 against p2 */ +int winner(int p1, int p2) +{ + signed char win; + + if (p1 < p2) { + win = scores[p1*programCount + p2] * -1; + } else { + win = scores[p2*programCount + p1]; + } + + return win; +} + +int ptscompar(const void *lv, const void *rv) +{ + const struct ProgramScore *l = *((const struct ProgramScore **) lv); + const struct ProgramScore *r = *((const struct ProgramScore **) rv); + + if (l->pts < r->pts) { + return -1; + } else if (l->pts > r->pts) { + return 1; + } else { + return 0; + } +} + +int prccompar(const void *lv, const void *rv) +{ + const struct ProgramScore *l = *((const struct ProgramScore **) lv); + const struct ProgramScore *r = *((const struct ProgramScore **) rv); + + if (l->prc < r->prc) { + return -1; + } else if (l->prc > r->prc) { + return 1; + } else { + return 0; + } +} + +int main(int argc, char **argv) +{ + pthread_t *threads; + int i, j; + double *plainScores; + double *preciseScores; + struct ProgramScore **allScores; + char *scoreFilename; + FILE *scoreF; + + if (argc < 4) { + fprintf(stderr, "Use: report <bfjoust program> <cache dir> <bfjoust files>\n"); + return 1; + } + + fyb = argv[1]; + cachedir = argv[2]; + programCount = argc - 3; + programs = argv + 3; + + signal(SIGCHLD, SIG_DFL); + + /* allocate space for the scores */ + SF(scores, malloc, NULL, (programCount * programCount)); + + /* now run them in threads */ + breakdown = open("breakdown.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666); + SF(threads, malloc, NULL, (programCount * sizeof(pthread_t))); + for (i = 0; i < programCount; i++) { + /*pthread_create(&threads[i], NULL, runnerThread, (void *) (size_t) i);*/ + runnerThread((void *) (size_t) i); + } + close(breakdown); + + /* wait for the threads to finish * / + for (i = 0; i < programCount; i++) { + pthread_join(threads[i], NULL); + } */ + + /* allocate the score buffers */ + SF(allScores, malloc, NULL, (programCount * sizeof(struct ProgramScore *))); + for (i = 0; i < programCount; i++) { + SF(allScores[i], malloc, NULL, (sizeof(struct ProgramScore))); + allScores[i]->id = i; + } + + /* now calculate the plain score for each */ + SF(plainScores, malloc, NULL, (programCount * sizeof(double))); + for (i = 0; i < programCount; i++) { + double score = 0; + for (j = 0; j < programCount; j++) { + if (i == j) continue; + + score += winner(i, j) / (double) RUNCOUNT; + } + allScores[i]->pts = plainScores[i] = score; + } + + /* and the precise scores for each */ + SF(preciseScores, malloc, NULL, (programCount * sizeof(double))); + for (i = 0; i < programCount; i++) { + double score = 0; + for (j = 0; j < programCount; j++) { + double value; + double win; + + if (i == j) continue; + + /* get the value of j */ + value = (double) (plainScores[j] + programCount) / (double) (2*programCount-2); + + /* and add the value if correct */ + win = winner(i, j) / (double) RUNCOUNT; + if (win > 0) { + score += value * win; + } + } + allScores[i]->prc = preciseScores[i] = score * 200 / (programCount-1); + + /* save it to the cache */ + SF(scoreFilename, malloc, NULL, (strlen(cachedir) + strlen(programs[i]) + 8)); + sprintf(scoreFilename, "%s/%s.score", cachedir, programs[i]); + scoreF = fopen(scoreFilename, "w"); + if (scoreF != NULL) { + fprintf(scoreF, "%.1f", preciseScores[i]); + fclose(scoreF); + } + free(scoreFilename); + } + + /* now print out the scores */ + qsort(allScores, programCount, sizeof(struct ProgramScore *), prccompar); + printf("Pos ID Score Points Program\n"); + for (i = programCount - 1; i >= 0; i--) { + struct ProgramScore *sc = allScores[i]; + printf(" %2d %2d %6.2f %6.2f %s\n", + programCount - i, (int) sc->id, sc->prc, sc->pts, programs[sc->id]); + } + printf("\n"); + + /* and the full scoreboard */ + + /* header */ + printf(" | "); + for (i = 0; i < programCount; i++) { + if (i < 10) printf(" "); + else printf("%1d ", (int) (i/10%10)); + } + printf("|\n | "); + for (i = 0; i < programCount; i++) { + printf("%1d ", (int) (i%10)); + } + printf("| score | pts | id | program\n"); + + /* scores */ + for (i = 0; i < programCount; i++) { + printf("%2d | ", (int) i); + for (j = 0; j < programCount; j++) { + double win; + + if (i == j) { + printf(" "); + continue; + } + + win = winner(i, j); + if (win > 0) { + printf("+ "); + } else if (win < 0) { + printf("- "); + } else { + printf("0 "); + } + } + + printf("| %5.1f | %5.1f | %2d | %s\n", preciseScores[i], plainScores[i], (int) i, programs[i]); + } + + /* kill any poorly-performing programs */ + if (programCount > KEEP_PROGRAMS) { + for (i = 0; i < programCount - KEEP_PROGRAMS; i++) { + char buf[1024]; + snprintf(buf, 1024, "hg rm -f %s", programs[allScores[i]->id]); + system(buf); + system(buf + 3); + } + system("hg commit -m Trimming."); + } + + return 0; +}