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;
+}