diff options
author | LAN-TW <lantw44@gmail.com> | 2013-11-15 22:35:34 +0800 |
---|---|---|
committer | LAN-TW <lantw44@gmail.com> | 2013-11-15 22:35:34 +0800 |
commit | fd5eea92e3f2337e5fd5f336863e5356eda4226f (patch) | |
tree | cb8316405feec1254e5532a03ad96a33bd83323a | |
parent | 985f001f57343e0329df4824362708c163b91fd5 (diff) | |
download | sp2013-fd5eea92e3f2337e5fd5f336863e5356eda4226f.tar.gz sp2013-fd5eea92e3f2337e5fd5f336863e5356eda4226f.tar.zst sp2013-fd5eea92e3f2337e5fd5f336863e5356eda4226f.zip |
HW2: 基本的 judge 功能,但不按順序讀入仍會有問題
-rw-r--r-- | hw2/big_judge.c | 2 | ||||
-rw-r--r-- | hw2/judge.c | 245 | ||||
-rw-r--r-- | hw2/xwrap.c | 72 | ||||
-rw-r--r-- | hw2/xwrap.h | 15 |
4 files changed, 254 insertions, 80 deletions
diff --git a/hw2/big_judge.c b/hw2/big_judge.c index c7103f0..92ca701 100644 --- a/hw2/big_judge.c +++ b/hw2/big_judge.c @@ -97,7 +97,7 @@ int main (int argc, char* argv[]) { close (fdr[0]); close (fdw[1]); char* myjudge = xgetres ("judge"); - execl (myjudge, "judge", xsprintf ("%d", i + 1), NULL); + execl (myjudge, "judge", xsprintf ("%d", i + 1), (char*)NULL); fprintf (stderr, "%s: execl: %s: %s\n", argv[0], myjudge, strerror (errno)); _exit (1); } 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++) { diff --git a/hw2/xwrap.c b/hw2/xwrap.c index 8c12873..f43d029 100644 --- a/hw2/xwrap.c +++ b/hw2/xwrap.c @@ -257,9 +257,9 @@ char* xgetres (const char* filename) { } if (xstrend (myexec, "/")) { - myres = xstrcat (myexec, filename, NULL); + myres = xstrcat (myexec, filename, (char*)NULL); } else { - myres = xstrcat (myexec, "/", filename, NULL); + myres = xstrcat (myexec, "/", filename, (char*)NULL); } if (!myexec_static) { free (myexec); @@ -289,3 +289,71 @@ size_t xwrite (int fd, const char* str, size_t size) { rem = rem > 0 ? rem : 0; return size - rem; } + +void xbufinit (XBuf* buf) { + buf->buf_start = 0; + buf->buf_len = 0; + buf->buf_line = NULL; + buf->buf_line_len = 0; + buf->buf_error = false; + buf->buf_eof = false; +} + +char* xgetline (int fd, XBuf* buf, int delim) { + if (buf->buf_error || buf->buf_eof) { + return NULL; + } + + if (buf->buf_len == 0) { + int rval = read (fd, buf->buf, XBUFSIZ); + if (rval < 0) { + if (errno != EAGAIN && errno != EINTR) { + buf->buf_error = true; + } + return NULL; + } + if (rval == 0) { + buf->buf_eof = true; + return NULL; + } + buf->buf_start = 0; + buf->buf_len = rval; + } + + int i; + for (i = 0; i < buf->buf_len; i++) { + if (buf->buf[buf->buf_start + i] == delim) { + break; + } + } + + int buf_line_start = buf->buf_line_len; + buf->buf_line_len += i; + buf->buf_line = xrealloc (buf->buf_line, buf->buf_line_len + 1); + memcpy (buf->buf_line + buf_line_start, buf->buf + buf->buf_start, i); + buf->buf_line[buf->buf_line_len] = '\0'; + + /* remove CR if delim is LF and delim is found */ + if (i < buf->buf_len && delim == '\n' && buf->buf_line_len - 1 >= 0 && + buf->buf_line[buf->buf_line_len - 1] == '\r') { + buf->buf_line[buf->buf_line_len - 1] = '\0'; + buf->buf_line_len--; + } + + int buf_len_saved = buf->buf_len; + buf->buf_start += i + 1; + buf->buf_len -= i + 1; + if (buf->buf_len <= 0) { + buf->buf_start = 0; + buf->buf_len = 0; + } + + if (i < buf_len_saved) { + /* delim is found */ + char* newstr = buf->buf_line; + buf->buf_line = NULL; + return newstr; + } + + return NULL; +} diff --git a/hw2/xwrap.h b/hw2/xwrap.h index 7759ae9..05504c3 100644 --- a/hw2/xwrap.h +++ b/hw2/xwrap.h @@ -31,4 +31,19 @@ static inline int xmin (int a, int b) { return a < b ? a : b; } +#define XBUFSIZ 512 + +typedef struct { + char buf[XBUFSIZ]; + off_t buf_start; + off_t buf_len; + char* buf_line; + ssize_t buf_line_len; + int buf_error : 1; + int buf_eof : 1; +} XBuf; + +void xbufinit (XBuf* buf); +char* xgetline (int fd, XBuf* buf, int delim); + #endif /* X_GENERAL_WRAPPER */ |