summaryrefslogtreecommitdiffstats
path: root/hw2/judge.c
diff options
context:
space:
mode:
authorLAN-TW <lantw44@gmail.com>2013-11-15 22:35:34 +0800
committerLAN-TW <lantw44@gmail.com>2013-11-15 22:35:34 +0800
commitfd5eea92e3f2337e5fd5f336863e5356eda4226f (patch)
treecb8316405feec1254e5532a03ad96a33bd83323a /hw2/judge.c
parent985f001f57343e0329df4824362708c163b91fd5 (diff)
downloadsp2013-fd5eea92e3f2337e5fd5f336863e5356eda4226f.tar.gz
sp2013-fd5eea92e3f2337e5fd5f336863e5356eda4226f.tar.zst
sp2013-fd5eea92e3f2337e5fd5f336863e5356eda4226f.zip
HW2: 基本的 judge 功能,但不按順序讀入仍會有問題
Diffstat (limited to 'hw2/judge.c')
-rw-r--r--hw2/judge.c245
1 files changed, 168 insertions, 77 deletions
diff --git a/hw2/judge.c b/hw2/judge.c
index 8c87724..bfd8e31 100644
--- a/hw2/judge.c
+++ b/hw2/judge.c
@@ -9,32 +9,45 @@
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
+#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
-#define FDATA_BUFSIZ 512
-
typedef struct {
int fd;
int fd_unused;
char* fname;
- int last;
- int score;
+ long last;
+ long score;
+ int rank;
int ignore : 1;
pid_t pid;
long key;
- char buf[FDATA_BUFSIZ];
- size_t buf_start;
- size_t buf_len;
} FData;
+static volatile sig_atomic_t player_tle;
+
+static void player_tle_setter (int signo) {
+ player_tle = 1;
+}
+
+static void fdata_clear (FData* d) {
+ d->last = 0;
+ d->score = 0;
+ d->rank = 0;
+ d->ignore = 0;
+ d->pid = 0;
+ d->key = 0;
+}
+
static int str2list (char* str, char* result[], int maxlen) {
int complen = 0;
char* now = str;
@@ -66,11 +79,11 @@ int main (int argc, char* argv[]) {
const char* judgename = argv[1];
FData ffd[5] = {
- { .fname = xstrcat ("judge", judgename, ".FIFO", NULL) }, // read
- { .fname = xstrcat ("judge", judgename, "_A.FIFO", NULL) }, // write
- { .fname = xstrcat ("judge", judgename, "_B.FIFO", NULL) }, // write
- { .fname = xstrcat ("judge", judgename, "_C.FIFO", NULL) }, // write
- { .fname = xstrcat ("judge", judgename, "_D.FIFO", NULL) } // write
+ { .fname = xstrcat ("judge", judgename, ".FIFO", (char*)NULL) }, // read
+ { .fname = xstrcat ("judge", judgename, "_A.FIFO", (char*)NULL) }, // write
+ { .fname = xstrcat ("judge", judgename, "_B.FIFO", (char*)NULL) }, // write
+ { .fname = xstrcat ("judge", judgename, "_C.FIFO", (char*)NULL) }, // write
+ { .fname = xstrcat ("judge", judgename, "_D.FIFO", (char*)NULL) } // write
};
for (int i = 0; i < ARRAY_LEN (ffd, FData); i++) {
@@ -101,12 +114,11 @@ int main (int argc, char* argv[]) {
ffd[i].fd_unused = fdw;
}
- ffd[i].score = 0;
- ffd[i].ignore = false;
- ffd[i].buf_start = 0;
- ffd[i].buf_len = 0;
+ fdata_clear (&ffd[i]);
}
+ xfdelfl (ffd[0].fd, O_NONBLOCK);
+
Comp135 comp_struct, *comp;
comp = &comp_struct;
@@ -114,6 +126,13 @@ int main (int argc, char* argv[]) {
srandom (time (NULL) + getpid () + argv[0][0]);
+ struct sigaction sa = {
+ .sa_handler = player_tle_setter,
+ .sa_flags = 0
+ };
+ sigemptyset (&sa.sa_mask);
+ sigaction (SIGALRM, &sa, NULL);
+
char *linestr = NULL;
size_t linelen = 0;
bool request_exit = false;
@@ -124,6 +143,7 @@ int main (int argc, char* argv[]) {
FD_SET (ffd[0].fd, &rset);
nfds = ffd[0].fd + 1;
+ comp135_log (comp, "Waiting for initial request from big_judge");
while (!request_exit && getline (&linestr, &linelen, stdin) >= 0) {
char* pl[4];
int i, c;
@@ -147,15 +167,18 @@ int main (int argc, char* argv[]) {
}
for (i = 1, c = 'A'; i <= 4; i++, c++) {
+ fdata_clear (&ffd[i]);
ffd[i].key = random ();
ffd[i].pid = fork ();
if (ffd[i].pid < 0) {
fprintf (stderr, "Cannot fork: %s\n", strerror (errno));
break;
} else if (ffd[i].pid == 0) {
- char* plname = xstrcat ("player", pl[i - 1], NULL);
+ char* plname = xstrcat ("player_", pl[i - 1], NULL);
char* plthis = xgetres (plname);
- execl (plthis, plname, judgename, c, ffd[i].key);
+ char* plkey = xsprintf ("%ld", ffd[i].key);
+ char plid[2] = { c, '\0' };
+ execl (plthis, plname, judgename, plid, plkey, (char*)NULL);
fprintf (stderr, "Cannot execl `%s\': %s\n",
plthis, strerror (errno));
_exit (127);
@@ -173,9 +196,12 @@ int main (int argc, char* argv[]) {
char lastmsg[20];
int lastlen;
- lastlen = snprintf (lastmsg, 20, "%d %d %d %d\n",
+ lastlen = snprintf (lastmsg, 20, "%ld %ld %ld %ld\n",
ffd[1].last, ffd[2].last, ffd[3].last, ffd[4].last);
- comp135_log (comp, "Previous round: %*s", lastlen - 1, lastmsg);
+ lastmsg[lastlen - 1] = '\0';
+ comp135_log (comp, "Previous round: %s", lastmsg);
+ lastmsg[lastlen - 1] = '\n';
+ comp135_log (comp, "This is round %d", t + 1);
for (i = 1, c = 'A'; i <= 4; i++, c++) {
if (t) {
@@ -186,82 +212,147 @@ int main (int argc, char* argv[]) {
continue;
}
- bool readok = false;
- bool inputyes = false;
- char* plstart = &ffd[0].buf[ffd[0].buf_start];
- while (!readok) {
-
- comp135_log (comp, "%u bytes in buffer ...", ffd[0].buf_len);
- if (ffd[0].buf_len) {
- int k;
- for (k = 0; k < ffd[0].buf_len; k++) {
- if (ffd[0].buf[ffd[0].buf_start + k] == '\n') {
- ffd[0].buf[ffd[0].buf_start + k] = '\0';
- break;
- }
+ XBuf rbuf;
+ char* rline;
+ xbufinit (&rbuf);
+
+ player_tle = 0;
+ setitimer (ITIMER_REAL, &(struct itimerval) {
+ .it_interval = (struct timeval) { 0, 0 },
+ .it_value = (struct timeval) { 3, 0 }
+ }, NULL);
+
+ rline = NULL;
+ while (!player_tle) {
+ comp135_log (comp, "Waiting for player %c input ...", c);
+ while (
+ (rline = xgetline (ffd[0].fd, &rbuf, '\n')) == NULL &&
+ !(rbuf.buf_error) && !(rbuf.buf_eof) && !player_tle);
+ if (rbuf.buf_error) {
+ fprintf (stderr, "Read error: %s\n", strerror (errno));
+ }
+ if (rbuf.buf_eof) {
+ fputs ("Unexpected EOF!!!\n", stderr);
+ }
+ if (rline != NULL) {
+ comp135_log (comp, "Read: %s", rline);
+
+ char* p[3];
+ int pnum = str2list (rline, p, 3);
+ if (pnum < 3) {
+ comp135_log (comp,
+ "Too few arguments (3 required, %d got)", pnum);
+ free (rline), rline = NULL;
+ continue;
+ }
+
+ char plfrom = p[0][0];
+ long checknum, ans;
+
+ if (xatol (p[1], &checknum) < 0) {
+ comp135_log (comp, "Invalid checknum (%s)", p[1]);
+ free (rline), rline = NULL;
+ continue;
}
- ffd[0].buf_start += ffd[0].buf_len;
- ffd[0].buf_len = 0;
- if (k < ffd[0].buf_len) {
- readok = true;
- inputyes = true;
+ if (xatol (p[2], &ans) < 0) {
+ comp135_log (comp, "Invalid choose (%s)", p[2]);
+ free (rline), rline = NULL;
continue;
}
- }
- fd_set rresult = rset;
- struct timeval tv = { 3, 0 };
- int rbytes;
+ free (rline), rline = NULL;
- comp135_log (comp, "Waiting for player %c input ...", c);
- switch (select (nfds, &rresult, NULL, NULL, &tv)) {
- case -1:
- if (errno == EINTR || errno == ENOMEM) {
- continue;
- } else {
- fprintf (stderr, "Select error: %s\n", strerror (errno));
- readok = true;
- continue;
- }
- case 0:
- ffd[i].last = 0;
- ffd[i].ignore = true;
- readok = true;
+ if (checknum != ffd[i].key) {
+ comp135_log (comp,
+ "Incorrect checknum %ld (should be %ld)",
+ ffd[i].key, checknum);
continue;
- default:
- rbytes = read (ffd[0].fd,
- ffd[0].buf + ffd[0].buf_start,
- FDATA_BUFSIZ - ffd[0].buf_start);
- if (rbytes < 0) {
- if (errno == EINTR || errno == EAGAIN) {
- continue;
- } else {
- fprintf (stderr, "Read error: %s\n", strerror (errno));
- readok = true;
- continue;
- }
- } else if (rbytes == 0) {
- fputs ("Unexpected EOF!!!\n", stderr);
- readok = true;
- continue;
- }
- ffd[0].buf_len = rbytes;
+ }
+
+ if (ans != 1 && ans != 3 && ans != 5) {
+ comp135_log (comp,
+ "Incorrect choose %ld (should be 1, 3, 5)",
+ ans);
+ continue;
+ }
+
+ comp135_log (comp, "Player %c (checknum %ld) says %ld",
+ plfrom, checknum, ans);
+ ffd[i].last = ans;
+
+ break;
}
}
- if (ffd[0].buf_start) {
- memmove (ffd[0].buf,
- ffd[0].buf + ffd[0].buf_start, ffd[0].buf_len);
+ setitimer (ITIMER_REAL, &(struct itimerval) {
+ .it_interval = (struct timeval) { 0, 0 },
+ .it_value = (struct timeval) { 0, 0 }
+ }, NULL);
+
+ if (player_tle) {
+ comp135_log (comp, "Player %c TLE!!!", c);
+ ffd[i].last = 0;
+ ffd[i].ignore = true;
+ }
+ }
+
+ int c1 = 0, c3 = 0, c5 = 0;
+ for (i = 1; i <= 4; i++) {
+ switch (ffd[i].last) {
+ case 1: c1++; break;
+ case 3: c3++; break;
+ case 5: c5++; break;
+ }
+ }
+ for (i = 1; i <= 4; i++) {
+ if (ffd[i].last == 1 && c1 == 1) {
+ ffd[i].score += 1;
+ } else if (ffd[i].last == 3 && c3 == 1) {
+ ffd[i].score += 3;
+ } else if (ffd[i].last == 5 && c5 == 1) {
+ ffd[i].score += 5;
+ }
+ }
+ comp135_log (comp, "Player score: %ld %ld %ld %ld",
+ ffd[1].score, ffd[2].score, ffd[3].score, ffd[4].score);
+ }
+
+ int rank[4];
+ long lastmin = LONG_MAX;
+ int lastrank = 4;
+ for (int j = 4; j > 0; j--) {
+ long vmin = LONG_MAX;
+ int pmin = 0;
+ for (i = 1; i <= 4; i++) {
+ if (!ffd[i].rank && ffd[i].score < vmin) {
+ vmin = ffd[i].score;
+ pmin = i;
}
}
+ if (vmin == lastmin) {
+ ffd[pmin].rank = lastrank;
+ rank[j - 1] = pmin;
+ } else {
+ ffd[pmin].rank = j;
+ rank[j - 1] = pmin;
+ lastrank = j;
+ }
+ lastmin = vmin;
+ }
+
+ for (int j = 0; j < 4; j++) {
+ printf ("%s %d\n", pl[j], ffd[rank[j]].rank);
}
new_loop_end:
free (linestr);
linestr = NULL;
linelen = 0;
+
+ comp135_log (comp, "Waiting for the next request from big_judge");
}
+ free (linestr);
comp135_destroy (comp);
for (int i = 0; i < ARRAY_LEN (ffd, FData); i++) {