summaryrefslogtreecommitdiffstats
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
parent985f001f57343e0329df4824362708c163b91fd5 (diff)
downloadsp2013-fd5eea92e3f2337e5fd5f336863e5356eda4226f.tar.gz
sp2013-fd5eea92e3f2337e5fd5f336863e5356eda4226f.tar.zst
sp2013-fd5eea92e3f2337e5fd5f336863e5356eda4226f.zip
HW2: 基本的 judge 功能,但不按順序讀入仍會有問題
-rw-r--r--hw2/big_judge.c2
-rw-r--r--hw2/judge.c245
-rw-r--r--hw2/xwrap.c72
-rw-r--r--hw2/xwrap.h15
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 */