- quotas
New submitter:
-- Checking of contest time (and per-contestant exceptions)
- contest: override failed check
- contest: local history
- contest: task status cache
#include "lib/mempool.h"
#include "lib/simple-lists.h"
#include "lib/stkstring.h"
+#include "lib/fastbuf.h"
#include "sherlock/object.h"
#include "sherlock/objread.h"
+#include <fcntl.h>
#include <time.h>
#include "submitd.h"
}
}
+/*** Contest timeout checks ***/
+
+static int
+load_time_limit(char *name)
+{
+ struct fastbuf *f = bopen_try(name, O_RDONLY, 1024);
+ if (!f)
+ return -1;
+ char buf[256];
+ int h, m;
+ if (bgets_nodie(f, buf, sizeof(buf)) < 0 ||
+ sscanf(buf, "%d:%d", &h, &m) != 2 ||
+ h < 0 || h > 23 || m < 0 || m > 59)
+ {
+ msg(L_ERROR, "Invalid timeout in %s", name);
+ bclose(f);
+ return -1;
+ }
+ bclose(f);
+ return 100*h + m;
+}
+
+static int
+contest_over(struct conn *c)
+{
+ time_t now = time(NULL);
+ struct tm *tm = localtime(&now);
+ int tstamp = tm->tm_hour*100 + tm->tm_min;
+ int local_limit = load_time_limit(stk_printf("solutions/%s/TIMEOUT", c->user));
+ int global_limit = load_time_limit("solutions/TIMEOUT");
+ if (trace_commands > 1)
+ msg(L_DEBUG, "Time check: current %d, global limit %d, user limit %d", tstamp, global_limit, local_limit);
+ if (local_limit >= 0)
+ return (tstamp >= local_limit);
+ return (global_limit >= 0 && tstamp >= global_limit);
+}
+
/*** SUBMIT ***/
static struct fastbuf *
static void
cmd_submit(struct conn *c)
{
+ if (contest_over(c))
+ {
+ err(c, "The contest is over, no more submits allowed");
+ return;
+ }
+
byte *tname = obj_find_aval(c->request, 'T');
if (!tname)
{
TraceTLS 1
# Trace command and their results
-TraceCommands 1
+TraceCommands 2
}
return o;
}
-static void task_record_history(byte *user, byte *task, byte *part, byte *ext, uns version, byte *submitted_name)
+static void
+task_record_history(byte *user, byte *task, byte *part, byte *ext, uns version, byte *submitted_name)
{
if (!history_format)
return;
bclose(orig);
}
-void task_submit_part(byte *user, byte *task, byte *part, byte *ext, uns version, struct fastbuf *fb)
+void
+task_submit_part(byte *user, byte *task, byte *part, byte *ext, uns version, struct fastbuf *fb)
{
byte *dir = stk_printf("solutions/%s/%s", user, task);
byte *name = stk_printf("%s/%s.%s", dir, part, ext);
task_record_history(user, task, part, ext, version, name);
}
-void task_delete_part(byte *user, byte *task, byte *part, byte *ext, uns version UNUSED)
+void
+task_delete_part(byte *user, byte *task, byte *part, byte *ext, uns version UNUSED)
{
byte *dir = stk_printf("solutions/%s/%s", user, task);
byte *name = stk_printf("%s/%s.%s", dir, part, ext);