def getSubmissions(request, *args, **kwargs): submissions = [] cont = Contest.getCurrent() if not cont: return HttpResponse( Page(h1(" "), h1("Contest is Over", cls="center"))) user = User.getCurrent(request) Submission.forEach(lambda x: submissions.append(x) if x.user.id == user.id and cont.start <= x.timestamp <= cont.end else None) if len(submissions) == 0: return HttpResponse(Page(h1("No Submissions Yet", cls="page-title"), )) return HttpResponse( Page( h2("Your Submissions", cls="page-title"), SubmissionTable( sorted(submissions, key=lambda sub: (sub.problem.title, -sub.timestamp))), div(cls="modal", tabindex="-1", role="dialog", contents=[ div(cls="modal-dialog", role="document", contents=[div(id="modal-content")]) ])))
def __init__(self, submission: Submission): subTime = submission.timestamp probName = submission.problem.title cls = "gray" if submission.status == Submission.STATUS_REVIEW else "red" if submission.result != "ok" else "" self.html = div( cls="modal-content", contents=[ div(cls=f"modal-header {cls}", contents=[ h.h5(f"Submission to {probName} at ", h.span(subTime, cls="time-format")), """ <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button>""" ]), div(cls="modal-body", contents=[ h.strong( "Language: <span class='language-format'>{}</span>" .format(submission.language)), h.br(), h.strong("Result: "), verdict_name[submission.getContestantResult()], h.br(), h.br(), h.strong("Code:"), h.code(code_encode(submission.code), cls="code"), ]) ])
def __init__(self, prob: Problem, user: User): probpath = f"/problems/{prob.id}" btn = f"rejudgeAll('{prob.id}')" if user.isAdmin() else None title = prob.title if not user.isAdmin(): # Compute problem status icon = '' result = '' for sub in Submission.all(): if sub.problem != prob or sub.user != user or sub.status == Submission.STATUS_REVIEW: continue if sub.user == user and "ok" == sub.result: icon = "check" break else: icon = "times" if icon != '': result = f'<i class="fa fa-{icon}"></i> ' title = result + title self.html = Card(title, prob.description, probpath, rejudge=btn)
def rejudge(request): """Ajax method: Rejudge a single submission `id`""" user = User.getCurrent(request) id = request.POST["id"] submission = Submission.get(id) runCode(submission, user) return JsonResponse(submission.result, safe=False)
def get_user_subs_map(contest: Contest) -> dict: contest_prob_ids = [prob.id for prob in contest.problems] subs = {} for sub in Submission.all(): if contest.start <= sub.timestamp <= contest.end and not sub.user.isAdmin() and sub.problem.id in contest_prob_ids: subs[sub.user.id] = subs.get(sub.user.id, []) subs[sub.user.id].append(sub) return subs
def judge_submission(request, *args, **kwargs): submission = Submission.get(kwargs.get('id')) user = User.getCurrent(request) version = int(request.POST["version"]) force = kwargs.get('force') == "force" if submission.version != version: return JsonResponse(f"CHANGES", safe=False) elif not submission.checkoutToJudge(user.id, force): return JsonResponse( f"CONFLICT:{User.get(submission.checkout).username}", safe=False) return HttpResponse(SubmissionCard(submission, user, force))
def viewDiff(request, *args, **kwargs): submission = Submission.get(kwargs.get('id')) user = User.getCurrent(request) problem = submission.problem answers = submission.readFilesForDisplay('out') diffTables = [] for i in range(len(problem.testData)): if i < problem.samples: caseType = "Sample" caseNo = i else: caseType = "Judge" caseNo = i - problem.samples diffTables.append( h.div( h. h3(f"{caseType} Case #{caseNo} (Expected Output | Contestant Output)", id=f"case{i}diff"), h.div( h.script( f"document.getElementById('case{i}result').innerHTML = 'Result: ' + verdict_name.{submission.results[i]}" ), id=f"case{i}result", ), generateDiffTable(problem.testData[i].output, answers[i]), )) pass return HttpResponse( div(cls="center", contents=[ h.link( rel="stylesheet", href= "/static/styles/style.css?642ab0bc-f075-4c4c-a2ba-00f55392dafc", type="text/css"), h.script(src="/static/lib/jquery/jquery.min.js"), h.script(src="/static/lib/jqueryui/jquery-ui.min.js"), h.script( src= "/static/scripts/script.js?75c1bf1e-10e8-4c8d-9730-0903f6540439" ), h2(f"Diffs for {submission.id}", cls="center"), h. em("Insertions are in <span style=color:darkgreen;background-color:palegreen>green</span>, deletions are in <span style=color:darkred;background-color:#F6B0B0>red</span>" ), h.div(contents=diffTables) ]))
def generateLogReport(request): user = User.getCurrent(request) contest = Contest.getCurrent() or Contest.getPast() if not contest: return HttpResponse( Page(h1(" "), h1("No Contest Available", cls="center"))) elif contest.isScoreboardOff(user): return HttpResponse( Page(h1(" "), h1("Scoreboard is off.", cls="center"))) start = contest.start end = contest.end users = {} for sub in Submission.all(): if start <= sub.timestamp <= end and not sub.user.isAdmin( ) and sub.result == "ok": username = User.get(sub.user.id).username problemName = Problem.get(sub.problem.id).title if username not in users.keys(): users[username] = {} if problemName not in users[username].keys(): users[username][problemName] = sub if sub.timestamp < users[username][problemName].timestamp: users[username][problemName] = sub correctSubmissions = [] for user in users.keys(): for problem in users[user].keys(): correctSubmissions.append( (user, problem, users[user][problem].timestamp)) correctSubmissions.sort(key=lambda entry: entry[2]) tableRows = constructTableRows(correctSubmissions) return HttpResponse( Page( h2("Correct Submissions Log", cls="page-title"), h.table( h.thead( h.tr( h.th("Contestant Name"), h.th("Problem title"), h.th("Time"), )), h.tbody(*tableRows))))
def changeResult(request, *args, **kwargs): version = int(request.POST["version"]) id = request.POST["id"] sub = Submission.get(id) if not sub: return JsonResponse("Error: no such submission", safe=False) if sub.changeResult(request.POST["result"], request.POST["status"], version): sub.save() else: return JsonResponse( "The submission has been changed by another judge since you loaded it. Please reload the sumbission to " "modify it.", safe=False) return JsonResponse("ok", safe=False)
def download(request): id = request.POST["id"] submission = Submission.get(id) buf = io.BytesIO() with ZipFile(buf, 'w') as zip: sourceFile = f"source.{exts[submission.language]}" zip.writestr(sourceFile, submission.code) for index in range(submission.problem.tests): for fileType in ["in", "out", "answer", "error"]: filename = f"/db/submissions/{id}/{fileType}{index}.txt" output_dest_filename = f"{fileType}{index}.txt" if os.path.exists(filename): zip.write(filename, output_dest_filename) data = {"download.zip": base64.b64encode(buf.getvalue()).decode('ascii')} return JsonResponse(json.dumps(data), safe=False)
def __init__(self, contest): logger.warn(f"Submissions: {Submission.all()}") subs = sorted(filter( lambda sub: sub.user.type != "admin" and contest.start <= sub. timestamp <= contest.end, Submission.all()), key=lambda s: s.timestamp) self.html = h.table( h.thead( h.tr( h.th("Contestant"), h.th("Problem"), h.th("Id"), h.th("Language"), h.th("Result"), h.th("Status"), h.th("Checkout"), )), h.tbody(*map(lambda sub: SubmissionRow(sub), subs)), id="submissions")
def rejudgeAll(request): """Ajax method: Rejudge all submissions for problem `id`""" user = User.getCurrent(request) ctime = time.time() * 1000 id = request.POST["id"] subsToRejudge = [ sub for sub in Submission.all() if sub.problem.id == id and sub.timestamp < ctime and sub.result != 'reject' ] if not Status.instance().startRejudge(id, subsToRejudge): return JsonResponse( "Another rejudge all is still progress. See System Status below to monitor progress.", safe=False) RejudgeThread(user, subsToRejudge).start() return JsonResponse( "Rejudge started. Click System Status below to monitor progress.", safe=False)
def runCode(sub: Submission, user: User) -> list: """Executes submission `sub` and returns lists of data files""" extension = exts[sub.language] # Use semaphore to throttle number of concurrent submissions with Submission.runningSubmissions: try: shutil.rmtree(f"/tmp/{id}", ignore_errors=True) os.makedirs(f"/tmp/{sub.id}", exist_ok=True) # Copy the code over to the runner /tmp folder writeFile(f"/tmp/{sub.id}/code.{extension}", sub.code) prob = sub.problem if sub.type == Submission.TYPE_TEST and not user.isAdmin(): numTests = prob.samples elif sub.type == Submission.TYPE_CUSTOM: numTests = 1 else: numTests = prob.tests # Copy the input over to the tmp folder for the runner if sub.type == Submission.TYPE_CUSTOM: writeFile(f"/tmp/{sub.id}/in0.txt", sub.custominput) else: for i in range(numTests): shutil.copyfile(f"/db/problems/{prob.id}/input/in{i}.txt", f"/tmp/{sub.id}/in{i}.txt") # Output files will go here os.makedirs(f"/tmp/{sub.id}/out", exist_ok=True) # Run the runner cmd = f"docker run --rm --network=none -m 256MB -v /tmp/{sub.id}/:/source {OC_DOCKERIMAGE_BASE}-{sub.language}-runner {numTests} {prob.timelimit} > /tmp/{sub.id}/result.txt" logger.debug(cmd) rc = os.system(cmd) overall_result = readFile(f"/tmp/{sub.id}/result.txt") if rc != 0 or not overall_result: # Test failed to complete properly logger.warn( f"Result of submission {sub.id}: rc={rc}, overall_result={overall_result}" ) sub.result = "internal_error" if sub.type == Submission.TYPE_SUBMIT: sub.save() return [], [], [], [] logger.info("Overall result: '" + overall_result + "'") # Check for compile error if overall_result == "compile_error\n": logger.info("Compile error") sub.result = "compile_error" sub.delete() sub.compile = readFile(f"/tmp/{sub.id}/out/compile_error.txt") return None, None, None, None # Submission ran; process test results inputs = [] outputs = [] answers = [] errors = [] results = [] result = "ok" all_samples_correct = True for i in range(numTests): if sub.type == Submission.TYPE_CUSTOM: inputs.append(sub.custominput) answers.append("") else: inputs.append(sub.problem.testData[i].input) answers.append( readFile(f"/db/problems/{prob.id}/output/out{i}.txt")) errors.append(readFile(f"/tmp/{sub.id}/out/err{i}.txt")) outputs.append(readFile(f"/tmp/{sub.id}/out/out{i}.txt")) anstrip = strip(answers[-1]) outstrip = strip(outputs[-1]) answerLines = anstrip.split('\n') outLines = outstrip.split('\n') res = readFile(f"/tmp/{sub.id}/out/result{i}.txt") if res == None: res = "tle" elif res == "ok" and anstrip != outstrip: if sub.type == Submission.TYPE_CUSTOM: pass # custom input cannot produce incorrect result elif compareStrings(outLines, answerLines): res = "incomplete_output" elif compareStrings(answerLines, outLines): res = "extra_output" else: res = "wrong_answer" results.append(res) # Make result the first incorrect result if res != "ok" and result == "ok": result = res if i < prob.samples and res != "ok": all_samples_correct = False may_autojudge = True if res == "wrong_answer" and sub.result == "presentation_error": # During a rejudge, do not replace "presentation_error" with "wrong_answer" pass else: sub.result = result if Contest.getCurrent(): if Contest.getCurrent( ).tieBreaker and all_samples_correct and sub.result in [ "runtime_error", "tle" ]: # Force review of submissions where all sample tests were correct if samples break ties may_autojudge = False if sub.result == "ok" or sub.type == Submission.TYPE_TEST or ( may_autojudge and sub.result in ["runtime_error", "tle"]): sub.status = Submission.STATUS_JUDGED sub.results = results logger.debug(f"Result of testing {sub.id}: {sub}") saveData(sub, inputs, 'in') saveData(sub, outputs, 'out') saveData(sub, answers, 'answer') saveData(sub, errors, 'error') if sub.type == Submission.TYPE_SUBMIT: sub.save() return inputs, outputs, answers, errors finally: shutil.rmtree(f"/tmp/{sub.id}", ignore_errors=True)
def saveData(sub: Submission, data: list, fileType: str): for i in range(len(data)): if sub.type == Submission.TYPE_SUBMIT: writeFile(f"/db/submissions/{sub.id}/{fileType}{i}.txt", data[i]) data[i] = Submission.truncateForDisplay(data[i])
def __init__(self, submission: Submission, user, force): subTime = submission.timestamp probName = submission.problem.title cls = "red" if submission.result != "ok" else "" self.html = div( cls="modal-content", contents=[ div(cls=f"modal-header {cls}", contents=[ h.h5( f"{probName} from {submission.user.username} at ", h.span(subTime, cls="time-format"), f" (id {submission.id})", ), """ <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button>""" ]), div(cls="modal-body", contents=[ h.input(type="hidden", id="version", value=f"{submission.version}"), h.strong( "Result: ", h.select( cls=f"result-choice {submission.id}", contents=[*resultOptions(submission.result)])), h.strong( " Status: ", h.select( cls=f"status-choice {submission.id}", contents=[*statusOptions(submission.status)])), h.span(" "), h.button( "Save", type="button", onclick= f"changeSubmissionResult('{submission.id}', '{submission.version}')", cls="btn btn-primary"), h.span(" "), h.button("Retest", type="button", onclick=f"rejudge('{submission.id}')", cls="btn btn-primary rejudge"), h.span(" "), h.button("Download", type="button", onclick=f"download('{submission.id}')", cls="btn btn-primary rejudge"), h.br(), h.br(), h.strong( f"Language: <span class='language-format'>{submission.language}</span>" ), h.code(code_encode(submission.code), cls="code"), div(cls="result-tabs", id="result-tabs", contents=[ h.ul(*map(lambda x: TestCaseTab(x, submission), enumerate(submission.results))), *map( lambda x: TestCaseData(x, submission), zip( range(submission.problem.tests), submission.readFilesForDisplay('in'), submission.readFilesForDisplay('out'), submission.readFilesForDisplay( 'error'), submission.readFilesForDisplay( 'answer'))) ]) ]) ])
def __init__(self, x, cont): num, prob = x subs = filter( lambda sub: sub.problem == prob and cont.start <= sub.timestamp <= cont.end, Submission.all()) self.html = div(*map(SubmissionCard, subs), id=f"tabs-{num}")
def judge_submission_close(request): submission = Submission.get(request.POST["id"]) user = User.getCurrent(request) if submission.checkout == user.id: submission.checkout = None return JsonResponse('ok', safe=False)
def contestant_submission(request, *args, **kwargs): return HttpResponse(SubmissionCard(Submission.get(kwargs.get('id'))))
def addSubmission(probId, lang, code, user, type, custominput): sub = Submission() sub.problem = Problem.get(probId) sub.language = lang sub.code = code sub.result = Submission.RESULT_PENDING sub.custominput = custominput sub.user = user sub.timestamp = time.time() * 1000 sub.type = type sub.status = Submission.STATUS_REVIEW if type == Submission.TYPE_SUBMIT: sub.save() else: sub.id = str(uuid4()) return sub