Mercurial > repo
view interps/bfjoust/report.c @ 12518:2d8fe55c6e65 draft default tip
<int-e> learn The password of the month is release incident pilot.
author | HackEso <hackeso@esolangs.org> |
---|---|
date | Sun, 03 Nov 2024 00:31:02 +0000 |
parents | 859f9b4339e6 |
children |
line wrap: on
line source
/* * 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; }