def test_rejudge(self): """ Test that rejudge correctly detects submission whose verdict changes """ collection = create_collection("test collection") problem = create_select_problem(collection, "example") user = create_user(passwd='1111', username='******') subs = [ Submission(code=problem.solution, verdict_code=VerdictCode.IE, user=user, problem=problem), # IE->AC Submission(code='SELECT * FROM dual', verdict_code=VerdictCode.IE, user=user, problem=problem), # IE->WA Submission(code='SELECT * FRO dual', verdict_code=VerdictCode.IE, user=user, problem=problem), # IE->RE ] for sub in subs: sub.save() sub.creation_date = datetime.datetime(2020, 9, 15) # Sets an older date sub.save() file_desc, filename = mkstemp('_rejudge') os.close(file_desc) # To avoid problems when removing the file in Windows rejudge(VerdictCode.IE, filename, tests=True) with open(filename, 'r') as summary_file: summary = summary_file.read() self.assertIn('IE --> AC', summary) self.assertIn('IE --> WA', summary) self.assertIn('IE --> RE', summary) self.assertNotIn('IE --> IE', summary) os.remove(filename)
def test_solved_n_position(self): """ Test that solved_n_position does not count staff or inactive users """ staff_user = get_user_model().objects.create_user('teacher', password='******', is_staff=True, is_active=True) inactive_user = get_user_model().objects.create_user('inactive', password='******', is_staff=False, is_active=False) user = get_user_model().objects.create_user('normal', password='******', is_staff=False, is_active=True) collection = Collection(name_md='ABC', description_md='blablabla') collection.clean() collection.save() create = 'CREATE TABLE tabla (xx NUMBER);' solution = 'SELECT * FROM tabla' problem = SelectProblem(title_md='Example', text_md='Enunciado', create_sql=create, insert_sql="", collection=collection, solution=solution) problem.clean() problem.save() sub1 = Submission(code='nada', verdict_code=VerdictCode.AC, user=staff_user, problem=problem) sub2 = Submission(code='nada', verdict_code=VerdictCode.AC, user=inactive_user, problem=problem) sub3 = Submission(code='nada', verdict_code=VerdictCode.AC, user=user, problem=problem) for sub in (sub1, sub2, sub3): sub.clean() sub.save() # First non-staff active user to solve the problem is 'user' self.assertEqual(problem.solved_first(), user) self.assertIsNone(problem.solved_second()) self.assertIsNone(problem.solved_third()) # Non-active or staff users are not counted in solved_position self.assertIsNone(problem.solved_position(staff_user)) self.assertIsNone(problem.solved_position(inactive_user)) self.assertEqual(problem.solved_position(user), 1)
def on_compile_error(self, packet): super(DjangoJudgeHandler, self).on_compile_error(packet) if Submission.objects.filter(id=packet['submission-id']).update( status='CE', result='CE', error=packet['log']): event.post( 'sub_%s' % Submission.get_id_secret(packet['submission-id']), { 'type': 'compile-error', 'log': packet['log'] }) self._post_update_submission(packet['submission-id'], 'compile-error', done=True) json_log.info( self._make_json_log(packet, action='compile-error', log=packet['log'], finish=True, result='CE')) else: logger.warning('Unknown submission: %d', packet['submission-id']) json_log.error( self._make_json_log(packet, action='compile-error', info='unknown submission', log=packet['log'], finish=True, result='CE'))
def handle_submission(source_file, problem, user, language): source = "" for chunk in source_file.chunks(): source += chunk s = Submission.create(problem, source, user, language) print s s.save()
def on_grading_begin(self, packet): logger.info('%s: Grading has begun on: %s', self.name, packet['submission-id']) self.batch_id = None if Submission.objects.filter(id=packet['submission-id']).update( status='G', is_pretested=packet['pretested'], current_testcase=1, batch=False, judged_date=timezone.now()): SubmissionTestCase.objects.filter( submission_id=packet['submission-id']).delete() event.post( 'sub_%s' % Submission.get_id_secret(packet['submission-id']), {'type': 'grading-begin'}) self._post_update_submission(packet['submission-id'], 'grading-begin') json_log.info(self._make_json_log(packet, action='grading-begin')) else: logger.warning('Unknown submission: %s', packet['submission-id']) json_log.error( self._make_json_log(packet, action='grading-begin', info='unknown submission'))
def on_compile_error(self, packet): logger.info('%s: Submission failed to compile: %s', self.name, packet['submission-id']) self._free_self(packet) if Submission.objects.filter(id=packet['submission-id']).update( status='CE', result='CE', error=packet['log']): event.post( 'sub_%s' % Submission.get_id_secret(packet['submission-id']), { 'type': 'compile-error', 'log': packet['log'], }) self._post_update_submission(packet['submission-id'], 'compile-error', done=True) json_log.info( self._make_json_log(packet, action='compile-error', log=packet['log'], finish=True, result='CE')) else: logger.warning('Unknown submission: %s', packet['submission-id']) json_log.error( self._make_json_log(packet, action='compile-error', info='unknown submission', log=packet['log'], finish=True, result='CE'))
def on_internal_error(self, packet): try: raise ValueError('\n\n' + packet['message']) except ValueError: logger.exception('Judge %s failed while handling submission %s', self.name, packet['submission-id']) self._free_self(packet) id = packet['submission-id'] if Submission.objects.filter(id=id).update(status='IE', result='IE', error=packet['message']): event.post('sub_%s' % Submission.get_id_secret(id), {'type': 'internal-error'}) self._post_update_submission(id, 'internal-error', done=True) json_log.info( self._make_json_log(packet, action='internal-error', message=packet['message'], finish=True, result='IE')) else: logger.warning('Unknown submission: %s', id) json_log.error( self._make_json_log(packet, action='internal-error', info='unknown submission', message=packet['message'], finish=True, result='IE'))
def on_submission_terminated(self, packet): logger.info('%s: Submission aborted: %s', self.name, packet['submission-id']) self._free_self(packet) if Submission.objects.filter(id=packet['submission-id']).update( status='AB', result='AB'): event.post( 'sub_%s' % Submission.get_id_secret(packet['submission-id']), {'type': 'aborted-submission'}) self._post_update_submission(packet['submission-id'], 'terminated', done=True) json_log.info( self._make_json_log(packet, action='aborted', finish=True, result='AB')) else: logger.warning('Unknown submission: %s', packet['submission-id']) json_log.error( self._make_json_log(packet, action='aborted', info='unknown submission', finish=True, result='AB'))
def on_internal_error(self, packet): super(DjangoJudgeHandler, self).on_internal_error(packet) id = packet['submission-id'] if Submission.objects.filter(id=id).update(status='IE', result='IE', error=packet['message']): event.post('sub_%s' % Submission.get_id_secret(id), {'type': 'internal-error'}) self._post_update_submission(id, 'internal-error', done=True) json_log.info( self._make_json_log(packet, action='internal-error', message=packet['message'], finish=True, result='IE')) else: logger.warning('Unknown submission: %d', id) json_log.error( self._make_json_log(packet, action='internal-error', info='unknown submission', message=packet['message'], finish=True, result='IE'))
def on_submission_processing(self, packet): id = packet['submission-id'] if Submission.objects.filter(id=id).update(status='P', judged_on=self.judge): event.post('sub_%s' % Submission.get_id_secret(id), {'type': 'processing'}) self._post_update_submission(id, 'processing') json_log.info(self._make_json_log(packet, action='processing')) else: logger.warning('Unknown submission: %d', id) json_log.error(self._make_json_log(packet, action='processing', info='unknown submission'))
def on_compile_message(self, packet): logger.info('%s: Submission generated compiler messages: %s', self.name, packet['submission-id']) if Submission.objects.filter(id=packet['submission-id']).update(error=packet['log']): event.post('sub_%s' % Submission.get_id_secret(packet['submission-id']), {'type': 'compile-message'}) json_log.info(self._make_json_log(packet, action='compile-message', log=packet['log'])) else: logger.warning('Unknown submission: %s', packet['submission-id']) json_log.error(self._make_json_log(packet, action='compile-message', info='unknown submission', log=packet['log']))
def test_obtained_achievements_date(self): """Test if the dates of the obtained achievements are correct""" user = create_user('passwordmichu', 'michu') coll = create_collection('Coleccion de cartas') problem_1 = create_select_problem(coll, 'Problema 1') problem_2 = create_select_problem(coll, 'Problema 2') sub_1 = Submission(code='nada', veredict_code=VeredictCode.AC, user=user, problem=problem_1) sub_2 = Submission(code='nada', veredict_code=VeredictCode.AC, user=user, problem=problem_2) sub_1.save() sub_2.save() Submission.objects.filter(id=sub_1.id).update(creation_date=datetime(2006, 3, 5)) sub_1_u = Submission.objects.get(id=sub_1.id) Submission.objects.filter(id=sub_2.id).update(creation_date=datetime(2020, 3, 5)) sub_2_u = Submission.objects.get(id=sub_2.id) # Test NumSolvedAchievementDefinition ach_solved = NumSolvedAchievementDefinition(name='Resolvista', description='Resuelve 2 problemas', num_problems=2) ach_solved.save() date = ObtainedAchievement.objects.filter(user=user).values_list('obtained_date', flat=True) self.assertEqual(date[0], sub_2_u.creation_date) ach_solved.num_problems = 1 ach_solved.save() date = ObtainedAchievement.objects.filter(user=user).values_list('obtained_date', flat=True) self.assertEqual(date[0], sub_1_u.creation_date) ObtainedAchievement.objects.all().delete() # Test NumSolvedCollectionAchievementDefinition ach_coll = NumSolvedCollectionAchievementDefinition(name='Coleccionista', description='Resuelve 2 \ problemas de esta coleccion', num_problems=2, collection=coll) ach_coll.save() date = ObtainedAchievement.objects.filter(user=user).values_list('obtained_date', flat=True) self.assertEqual(date[0], sub_2_u.creation_date) ach_coll.num_problems = 1 ach_coll.save() date = ObtainedAchievement.objects.filter(user=user).values_list('obtained_date', flat=True) self.assertEqual(date[0], sub_1_u.creation_date) ObtainedAchievement.objects.all().delete() # Test PodiumAchievementDefinition ach_podium = PodiumAchievementDefinition(name='Presidente del podio', description='Consigue ser el primero', num_problems=2, position=1) ach_podium.save() date = ObtainedAchievement.objects.filter(user=user).values_list('obtained_date', flat=True) self.assertEqual(date[0], sub_2_u.creation_date) ach_podium.num_problems = 1 ach_podium.save() date = ObtainedAchievement.objects.filter(user=user).values_list('obtained_date', flat=True) self.assertEqual(date[0], sub_1_u.creation_date) ObtainedAchievement.objects.all().delete()
def on_compile_message(self, packet): super(DjangoJudgeHandler, self).on_compile_message(packet) if Submission.objects.filter(id=packet['submission-id']).update(error=packet['log']): event.post('sub_%s' % Submission.get_id_secret(packet['submission-id']), {'type': 'compile-message'}) json_log.info(self._make_json_log(packet, action='compile-message', log=packet['log'])) else: logger.warning('Unknown submission: %d', packet['submission-id']) json_log.error(self._make_json_log(packet, action='compile-message', info='unknown submission', log=packet['log']))
def on_grading_begin(self, packet): super(DjangoJudgeHandler, self).on_grading_begin(packet) if Submission.objects.filter(id=packet['submission-id']).update( status='G', is_pretested=packet['pretested'], current_testcase=1, batch=False): SubmissionTestCase.objects.filter(submission_id=packet['submission-id']).delete() event.post('sub_%s' % Submission.get_id_secret(packet['submission-id']), {'type': 'grading-begin'}) self._post_update_submission(packet['submission-id'], 'grading-begin') json_log.info(self._make_json_log(packet, action='grading-begin')) else: logger.warning('Unknown submission: %d', packet['submission-id']) json_log.error(self._make_json_log(packet, action='grading-begin', info='unknown submission'))
def get_form_kwargs(self): kwargs = super().get_form_kwargs() kwargs['instance'] = Submission(user=self.request.profile, problem=self.object) if self.object.is_editable_by(self.request.user): kwargs['judge_choices'] = tuple( Judge.objects.filter(online=True, problems=self.object).values_list('name', 'name'), ) else: kwargs['judge_choices'] = () return kwargs
def create_submission(problem, user, veredict, code='nada'): """Creates and stores a submission""" sub = Submission(code=code, veredict_code=veredict, user=user, problem=problem) sub.clean() sub.save() return sub
def migrate_submissions(db): SUBMISSION_MAPPING = { "No": "id", "Submitted": "submitted_on", "IsPublic": "is_public", "Language": "language", "State": "state", "Length": "length", "Source": "source", "Message": "message", "Time": "time", "Memory": "memory" } imported = 0 submissions = fetch_all(db, "GDN_Submission") Submission.objects.all().delete() Activity.objects.filter(key__startswith="solved-").delete() start = time.time() for submission in submissions: kwargs = {} try: kwargs["problem"] = Problem.objects.get(id=submission["Problem"]) except: continue kwargs["user"] = User.objects.get(id=submission["Author"]) for k, v in SUBMISSION_MAPPING.items(): kwargs[v] = submission[k] if not kwargs["message"]: kwargs["message"] = "" kwargs["state"] = Submission.RECEIVED new_submission = Submission(**kwargs) new_submission.save() new_submission.state = submission["State"] new_submission.submitted_on = submission["Submitted"] new_submission.save() if kwargs["state"] == Submission.ACCEPTED: patch( "solved-%d-%d" % (submission["Problem"], submission["Author"]), submission["Submitted"]) imported += 1 if imported % 100 == 0: print "Migrated %d of %d submissions. (%d submissions/sec)" % ( imported, len(submissions), imported / (time.time() - start)) print "Migrated %d submissions." % imported
def migrate_submissions(db): SUBMISSION_MAPPING = { "No": "id", "Submitted": "submitted_on", "IsPublic": "is_public", "Language": "language", "State": "state", "Length": "length", "Source": "source", "Message": "message", "Time": "time", "Memory": "memory", } imported = 0 submissions = fetch_all(db, "GDN_Submission") Submission.objects.all().delete() Activity.objects.filter(key__startswith="solved-").delete() start = time.time() for submission in submissions: kwargs = {} try: kwargs["problem"] = Problem.objects.get(id=submission["Problem"]) except: continue kwargs["user"] = User.objects.get(id=submission["Author"]) for k, v in SUBMISSION_MAPPING.items(): kwargs[v] = submission[k] if not kwargs["message"]: kwargs["message"] = "" kwargs["state"] = Submission.RECEIVED new_submission = Submission(**kwargs) new_submission.save() new_submission.state = submission["State"] new_submission.submitted_on = submission["Submitted"] new_submission.save() if kwargs["state"] == Submission.ACCEPTED: patch("solved-%d-%d" % (submission["Problem"], submission["Author"]), submission["Submitted"]) imported += 1 if imported % 100 == 0: print "Migrated %d of %d submissions. (%d submissions/sec)" % ( imported, len(submissions), imported / (time.time() - start), ) print "Migrated %d submissions." % imported
def test_participation(self): """ Test the count of participating users in a group """ group = create_group('Grupo test') user1 = create_user(username='******', passwd='1111') user2 = create_user(username='******', passwd='1111') user3 = create_user(username='******', passwd='1111') user4 = create_user(username='******', passwd='1111') collection = create_collection('Test for statistics') problem = create_select_problem(collection, 'Dummy for statistics') for user in [user1, user2, user3, user4]: group.user_set.add(user) subs = [ Submission(verdict_code=VerdictCode.AC, user=user1, problem=problem), Submission(verdict_code=VerdictCode.WA, user=user2, problem=problem), Submission(verdict_code=VerdictCode.RE, user=user2, problem=problem), Submission(verdict_code=VerdictCode.TLE, user=user2, problem=problem), Submission(verdict_code=VerdictCode.VE, user=user1, problem=problem), Submission(verdict_code=VerdictCode.AC, user=user4, problem=problem), ] for sub in subs: sub.save() data = participation_per_group() expected = { 'Grupo test': { 'all': 4, 'acc': 2, 'participating': 3, 'avg': 2, 'stdev': 1.0, 'quantiles': '1 - 1.0 - 2.0 - 3.0 - 3', } } self.assertDictEqual(data, expected)
if id in self.update_counter: cnt, reset = self.update_counter[id] cnt += 1 if TIMER() - reset > UPDATE_RATE_TIME: del self.update_counter[id] else: self.update_counter[id] = (cnt, reset) if cnt > UPDATE_RATE_LIMIT: do_post = False if id not in self.update_counter: self.update_counter[id] = (1, TIMER()) if do_post: event.post( 'sub_%s' % Submission.get_id_secret(id), { 'type': 'test-case', 'id': packet['position'], 'status': test_case.status, 'time': '%.3f' % round(float(packet['time']), 3), 'memory': packet['memory'], 'points': float(test_case.points), 'total': float(test_case.total), 'output': packet['output'], }) self._post_update_submission(id, state='test-case') def on_supported_problems(self, packet): super(DjangoJudgeHandler, self).on_supported_problems(packet) self.judge.problems.set( Problem.objects.filter(code__in=list(self.problems.keys())))
def get_submission_chart_url(user): by_user = Submission.objects.filter(user=user) return Submission.get_verdict_distribution_graph(by_user)
def test_problem_collection_stats(self): """Methods that compute statistics in collections and problems""" collection = Collection(name_md='ABC', description_md='blablabla') collection.clean() collection.save() self.assertTrue('ABC' in str(collection)) user_model = django.contrib.auth.get_user_model() create = 'CREATE TABLE mytable (dd DATE);' insert = "INSERT INTO mytable VALUES (TO_DATE('2020/01/31', 'yyyy/mm/dd'))" solution = 'SELECT * FROM mytable' problem1 = SelectProblem(title_md='Dates', text_md='Example with dates', create_sql=create, insert_sql=insert, collection=collection, solution=solution) problem2 = SelectProblem(title_md='Dates', text_md='Example with dates', create_sql=create, insert_sql=insert, collection=collection, solution=solution) problem3 = SelectProblem(title_md='Dates', text_md='Example with dates', create_sql=create, insert_sql=insert, collection=collection, solution=solution) user1 = user_model.objects.create_user(username='******', email='*****@*****.**', password='******') user2 = user_model.objects.create_user(username='******', email='*****@*****.**', password='******') problem1.clean() problem1.save() problem2.clean() problem2.save() problem3.clean() problem3.save() user1.save() user2.save() sub1 = Submission(code='nada', veredict_code=VeredictCode.WA, user=user1, problem=problem1) sub2 = Submission(code='nada', veredict_code=VeredictCode.AC, user=user1, problem=problem1) sub3 = Submission(code='nada', veredict_code=VeredictCode.TLE, user=user1, problem=problem1) sub4 = Submission(code='nada', veredict_code=VeredictCode.RE, user=user1, problem=problem1) sub5 = Submission(code='nada', veredict_code=VeredictCode.VE, user=user1, problem=problem1) sub6 = Submission(code='nada', veredict_code=VeredictCode.IE, user=user1, problem=problem1) self.assertTrue('WA' in str(sub1)) self.assertTrue('AC' in str(sub2)) for sub in [sub1, sub2, sub3, sub4, sub5, sub6]: sub.save() # Problem solved self.assertTrue(problem1.solved_by_user(user1)) self.assertFalse(problem1.solved_by_user(user2)) self.assertFalse(problem2.solved_by_user(user1)) self.assertFalse(problem2.solved_by_user(user2)) # Number of submissions self.assertEqual(problem1.num_submissions_by_user(user1), 6) self.assertEqual(problem1.num_submissions_by_user(user2), 0) self.assertEqual(problem2.num_submissions_by_user(user1), 0) self.assertEqual(problem2.num_submissions_by_user(user2), 0) # Problems in collection self.assertEqual(collection.problems().count(), 3) self.assertEqual(collection.num_problems(), 3) # Numbers of problems solved by a user self.assertEqual(collection.num_solved_by_user(user1), 1) self.assertEqual(collection.num_solved_by_user(user2), 0)
def test_all_submissions(self): """ Test the list [epoch, count] for different types of verdicts and days, and also the counter of submissions """ collection = create_collection('Test for statistics') problem = create_select_problem(collection, 'Dummy for statistics') user1 = create_user('0000', 'ana') user2 = create_user('0000', 'juan') subs = [ Submission(veredict_code=VeredictCode.AC, user=user1, problem=problem), Submission(veredict_code=VeredictCode.WA, user=user2, problem=problem), Submission(veredict_code=VeredictCode.RE, user=user2, problem=problem), Submission(veredict_code=VeredictCode.TLE, user=user2, problem=problem), Submission(veredict_code=VeredictCode.VE, user=user1, problem=problem), Submission(veredict_code=VeredictCode.AC, user=user2, problem=problem), ] dates = [ datetime(2020, 2, 12, 0, 0, 0, 0, tzinfo=pytz.utc), datetime(2020, 2, 12, 0, 0, 0, 0, tzinfo=pytz.utc), datetime(2020, 2, 15, 0, 0, 0, 0, tzinfo=pytz.utc), datetime(2020, 2, 15, 0, 0, 0, 0, tzinfo=pytz.utc), datetime(2020, 2, 16, 0, 0, 0, 0, tzinfo=pytz.utc), datetime(2020, 2, 20, 0, 0, 0, 0, tzinfo=pytz.utc), ] dates_epoch_ms = [int(date.timestamp()) * 1000 for date in dates] for (sub, date) in zip(subs, dates): sub.save() sub.creation_date = date sub.save() # Overwrites date, because it is automatically set to 'now' in the first save count_all = submissions_by_day() self.assertEqual(len(count_all), (dates[-1] - dates[0]).days + 1) # 9 days between first and last submission self.assertEqual(count_all[0], [dates_epoch_ms[0], 2]) # 2 submissions on 1st day (2020-2-12) self.assertEqual(count_all[1][1], 0) # 0 submissions on 2nd day self.assertEqual(count_all[2][1], 0) # 0 submissions on 3rd day self.assertEqual(count_all[3], [dates_epoch_ms[2], 2]) # 2 submissions on 4th day (2020-2-15) self.assertEqual(count_all[4], [dates_epoch_ms[4], 1]) # 1 submission on 5th day (2020-2-16) self.assertEqual(count_all[6][1], 0) # 0 submissions on 3rd day self.assertEqual(count_all[8], [dates_epoch_ms[5], 1]) # 1 submission on 9th day (2020-2-20) count_ac = submissions_by_day(verdict_code=VeredictCode.AC) self.assertEqual(len(count_ac), (dates[-1] - dates[0]).days + 1) # 9 days between first and last AC submission self.assertEqual(count_ac[0], [dates_epoch_ms[0], 1]) # 1 AC submissions on 1st day (2020-2-12) self.assertEqual(count_ac[1][1], 0) # 0 submissions on 2nd day self.assertEqual(count_ac[4][1], 0) # 0 submission on 5th day (2020-2-16) self.assertEqual(count_ac[8], [dates_epoch_ms[5], 1]) # 1 submission on 9th day (2020-2-20) count_wa = submissions_by_day(verdict_code=VeredictCode.WA) self.assertEqual(len(count_wa), 1) # Only one entry count_wa = submissions_by_day(verdict_code=VeredictCode.WA, start=dates_epoch_ms[0], end=dates_epoch_ms[-1]) self.assertEqual(len(count_wa), (dates[-1] - dates[0]).days + 1) # 9 days when forcing the start-end count_re = submissions_by_day(verdict_code=VeredictCode.RE) self.assertEqual(len(count_re), 1) # Only one entry count_re = submissions_by_day(verdict_code=VeredictCode.RE, start=dates_epoch_ms[0], end=dates_epoch_ms[-1]) self.assertEqual(len(count_re), (dates[-1] - dates[0]).days + 1) # 9 days when forcing the start-end self.assertEqual(count_re[0], [dates_epoch_ms[0], 0]) # 0 RE submissions on 1st day (2020-2-12) self.assertEqual(count_re[3], [dates_epoch_ms[2], 1]) # 1 submissions on 4th day self.assertEqual(count_re[8], [dates_epoch_ms[5], 0]) # 0 RE submission on 9th day (2020-2-20) # Test the counter of submissions sub_count = submission_count() self.assertEqual(sub_count['all'], 6) self.assertEqual(sub_count[VeredictCode.AC], 2) self.assertEqual(sub_count[VeredictCode.WA], 1) self.assertEqual(sub_count[VeredictCode.RE], 1) self.assertEqual(sub_count[VeredictCode.TLE], 1) self.assertEqual(sub_count[VeredictCode.VE], 1) self.assertEqual(sub_count[VeredictCode.IE], 0)
def problem_submit(request, problem=None, submission=None): if submission is not None and not request.user.has_perm('judge.resubmit_other') and \ get_object_or_404(Submission, id=int(submission)).user.user != request.user: raise PermissionDenied() profile = request.user.profile if request.method == 'POST': form = ProblemSubmitForm(request.POST, instance=Submission(user=profile)) if form.is_valid(): if (not request.user.has_perm('judge.spam_submission') and Submission.objects.filter( user=profile, was_rejudged=False).exclude( status__in=['D', 'IE', 'CE', 'AB']).count() > 2): return HttpResponse( '<h1>You submitted too many submissions.</h1>', status=503) if not form.cleaned_data['problem'].allowed_languages.filter( id=form.cleaned_data['language'].id).exists(): raise PermissionDenied() if not form.cleaned_data['problem'].is_accessible_by(request.user): user_logger.info( 'Naughty user %s wants to submit to %s without permission', request.user.username, form.cleaned_data['problem'].code) return HttpResponseForbidden( '<h1>Do you want me to ban you?</h1>') if not request.user.is_superuser and form.cleaned_data[ 'problem'].banned_users.filter(id=profile.id).exists(): return generic_message( request, _('Banned from submitting'), _('You have been declared persona non grata for this problem. ' 'You are permanently barred from submitting this problem.' )) if profile.current_contest is not None: try: contest_problem = form.cleaned_data[ 'problem'].contests.get( contest=profile.current_contest.contest) except ContestProblem.DoesNotExist: model = form.save() else: max_subs = contest_problem.max_submissions if max_subs and get_contest_submission_count( problem, profile) >= max_subs: return generic_message( request, _('Too many submissions'), _('You have exceeded the submission limit for this problem.' )) model = form.save() contest = ContestSubmission( submission=model, problem=contest_problem, participation=profile.current_contest) contest.save() else: model = form.save() profile.update_contest() model.judge(rejudge=False) return HttpResponseRedirect( reverse('submission_status', args=[str(model.id)])) else: form_data = form.cleaned_data if submission is not None: sub = get_object_or_404(Submission, id=int(submission)) else: initial = {'language': profile.language} if problem is not None: initial['problem'] = get_object_or_404(Problem, code=problem) problem_object = initial['problem'] if not problem_object.is_accessible_by(request.user): raise Http404() if submission is not None: try: sub = get_object_or_404(Submission, id=int(submission)) initial['source'] = sub.source initial['language'] = sub.language except ValueError: raise Http404() form = ProblemSubmitForm(initial=initial) form_data = initial if 'problem' in form_data: form.fields['language'].queryset = ( form_data['problem'].usable_languages.order_by( 'name', 'key').prefetch_related( Prefetch('runtimeversion_set', RuntimeVersion.objects.order_by('priority')))) problem_object = form_data['problem'] if 'language' in form_data: form.fields['source'].widget.mode = form_data['language'].ace form.fields['source'].widget.theme = profile.ace_theme if submission is not None: default_lang = sub.language else: default_lang = request.user.profile.language submission_limit = submissions_left = None if profile.current_contest is not None: try: submission_limit = problem_object.contests.get( contest=profile.current_contest.contest).max_submissions except ContestProblem.DoesNotExist: pass else: if submission_limit: submissions_left = submission_limit - get_contest_submission_count( problem, profile) return render( request, 'problem/submit.html', { 'form': form, 'title': _('Submit to %(problem)s') % { 'problem': problem_object.translated_name( request.LANGUAGE_CODE), }, 'content_title': mark_safe( escape(_('Submit to %(problem)s')) % { 'problem': format_html( u'<a href="{0}">{1}</a>', reverse('problem_detail', args=[problem_object.code]), problem_object.translated_name(request.LANGUAGE_CODE)) }), 'langs': Language.objects.all(), 'no_judges': not form.fields['language'].queryset, 'submission_limit': submission_limit, 'submissions_left': submissions_left, 'ACE_URL': ACE_URL, 'default_lang': default_lang, })
do_post = True if id in self.update_counter: cnt, reset = self.update_counter[id] cnt += 1 if TIMER() - reset > UPDATE_RATE_TIME: del self.update_counter[id] else: self.update_counter[id] = (cnt, reset) if cnt > UPDATE_RATE_LIMIT: do_post = False if id not in self.update_counter: self.update_counter[id] = (1, TIMER()) if do_post: event.post('sub_%s' % Submission.get_id_secret(id), { 'type': 'test-case', 'id': packet['position'], 'status': test_case.status, 'time': '%.3f' % round(float(packet['time']), 3), 'memory': packet['memory'], 'points': float(test_case.points), 'total': float(test_case.total), 'output': packet['output'] }) self._post_update_submission(id, state='test-case') def on_supported_problems(self, packet): super(DjangoJudgeHandler, self).on_supported_problems(packet) self.judge.problems.set(Problem.objects.filter(code__in=list(self.problems.keys()))) json_log.info(self._make_json_log(action='update-problems', count=len(self.problems)))
def on_test_case(self, packet, max_feedback=SubmissionTestCase._meta.get_field('feedback').max_length): logger.info('%s: %d test case(s) completed on: %s', self.name, len(packet['cases']), packet['submission-id']) id = packet['submission-id'] updates = packet['cases'] max_position = max(map(itemgetter('position'), updates)) if not Submission.objects.filter(id=id).update(current_testcase=max_position + 1): logger.warning('Unknown submission: %s', id) json_log.error(self._make_json_log(packet, action='test-case', info='unknown submission')) return bulk_test_case_updates = [] for result in updates: test_case = SubmissionTestCase(submission_id=id, case=result['position']) status = result['status'] if status & 4: test_case.status = 'TLE' elif status & 8: test_case.status = 'MLE' elif status & 64: test_case.status = 'OLE' elif status & 2: test_case.status = 'RTE' elif status & 16: test_case.status = 'IR' elif status & 1: test_case.status = 'WA' elif status & 32: test_case.status = 'SC' else: test_case.status = 'AC' test_case.time = result['time'] test_case.memory = result['memory'] test_case.points = result['points'] test_case.total = result['total-points'] test_case.batch = self.batch_id if self.in_batch else None test_case.feedback = (result.get('feedback') or '')[:max_feedback] test_case.extended_feedback = result.get('extended-feedback') or '' test_case.output = result['output'] bulk_test_case_updates.append(test_case) json_log.info(self._make_json_log( packet, action='test-case', case=test_case.case, batch=test_case.batch, time=test_case.time, memory=test_case.memory, feedback=test_case.feedback, extended_feedback=test_case.extended_feedback, output=test_case.output, points=test_case.points, total=test_case.total, status=test_case.status, )) do_post = True if id in self.update_counter: cnt, reset = self.update_counter[id] cnt += 1 if time.monotonic() - reset > UPDATE_RATE_TIME: del self.update_counter[id] else: self.update_counter[id] = (cnt, reset) if cnt > UPDATE_RATE_LIMIT: do_post = False if id not in self.update_counter: self.update_counter[id] = (1, time.monotonic()) if do_post: event.post('sub_%s' % Submission.get_id_secret(id), { 'type': 'test-case', 'id': max_position, }) self._post_update_submission(id, state='test-case') SubmissionTestCase.objects.bulk_create(bulk_test_case_updates)
def get_pp_breakdown(user, start=0, end=PP_ENTRIES): with connection.cursor() as cursor: cursor.execute(''' SELECT max_points_table.problem_code, max_points_table.problem_name, max_points_table.max_points, judge_submission.id, judge_submission.date, judge_submission.case_points, judge_submission.case_total, judge_submission.result, judge_language.short_name, judge_language.key FROM judge_submission JOIN (SELECT judge_problem.id problem_id, judge_problem.name problem_name, judge_problem.code problem_code, MAX(judge_submission.points) AS max_points FROM judge_problem INNER JOIN judge_submission ON (judge_problem.id = judge_submission.problem_id) WHERE (judge_problem.is_public = True AND judge_problem.is_organization_private = False AND judge_submission.points IS NOT NULL AND judge_submission.user_id = %s) GROUP BY judge_problem.id HAVING MAX(judge_submission.points) > 0.0) AS max_points_table ON (judge_submission.problem_id = max_points_table.problem_id AND judge_submission.points = max_points_table.max_points AND judge_submission.user_id = %s) JOIN judge_language ON judge_submission.language_id = judge_language.id GROUP BY max_points_table.problem_id ORDER BY max_points DESC, judge_submission.date DESC LIMIT %s OFFSET %s ''', (user.id, user.id, end - start + 1, start)) data = cursor.fetchall() breakdown = [] for weight, contrib in zip(PP_WEIGHT_TABLE[start:end], data): code, name, points, id, date, case_points, case_total, result, lang_short_name, lang_key = contrib # Replicates a lot of the logic usually done on Submission objects lang_short_display_name = lang_short_name or lang_key result_class = Submission.result_class_from_code(result, case_points, case_total) long_status = Submission.USER_DISPLAY_CODES.get(result, '') breakdown.append(PPBreakdown( points=points, weight=weight * 100, scaled_points=points * weight, problem_name=name, problem_code=code, sub_id=id, sub_date=from_database_time(date), sub_points=case_points, sub_total=case_total, sub_short_status=result, sub_long_status=long_status, sub_result_class=result_class, sub_lang=lang_short_display_name, )) has_more = end < min(len(PP_WEIGHT_TABLE), start + len(data)) return breakdown, has_more
def get_pp_breakdown(user, start=0, end=100): cursor = connection.cursor() cursor.execute( ''' SELECT max_points_table.problem_code, max_points_table.problem_name, max_points_table.max_points, judge_submission.date, judge_submission.case_points, judge_submission.case_total, judge_submission.result, judge_language.short_name, judge_language.key FROM judge_submission JOIN (SELECT judge_problem.id problem_id, judge_problem.name problem_name, judge_problem.code problem_code, MAX(judge_submission.points) AS max_points FROM judge_problem INNER JOIN judge_submission ON (judge_problem.id = judge_submission.problem_id) WHERE (judge_problem.is_public = True AND judge_submission.points IS NOT NULL AND judge_submission.user_id = %s) GROUP BY judge_problem.id HAVING MAX(judge_submission.points) > 0.0) AS max_points_table ON (judge_submission.problem_id = max_points_table.problem_id AND judge_submission.points = max_points_table.max_points AND judge_submission.user_id = %s) JOIN judge_language ON judge_submission.language_id = judge_language.id GROUP BY max_points_table.problem_id ORDER BY max_points DESC, judge_submission.date DESC ''', (user.id, user.id)) data = cursor.fetchall() cursor.close() breakdown = [] for weight, contrib in zip(PP_WEIGHT_TABLE[start:end], data[start:end]): code, name, points, date, case_points, case_total, result, lang_short_name, lang_key = contrib # Replicates a lot of the logic usually done on Submission objects lang_short_display_name = lang_short_name or lang_key result_class = Submission.result_class_from_code( result, case_points, case_total) long_status = Submission.USER_DISPLAY_CODES.get(result, '') breakdown.append( PPBreakdown(points=points, weight=weight * 100, scaled_points=points * weight, problem_name=name, problem_code=code, sub_date=date, sub_points=case_points, sub_total=case_total, sub_short_status=result, sub_long_status=long_status, sub_result_class=result_class, sub_lang=lang_short_display_name)) has_more = end < min(len(PP_WEIGHT_TABLE), len(data)) return breakdown, has_more
def test_podium(self): """Test the correct performance of the podium""" collection = Collection(name_md='ABC', description_md='blablabla') collection.clean() collection.save() self.assertIn('ABC', str(collection)) user_model = django.contrib.auth.get_user_model() create = 'CREATE TABLE mytable (dd DATE);' insert = "INSERT INTO mytable VALUES (TO_DATE('2020/01/31', 'yyyy/mm/dd'))" solution = 'SELECT * FROM mytable' problem1 = SelectProblem(title_md='Dates', text_md='Example with dates', create_sql=create, insert_sql=insert, collection=collection, solution=solution) problem2 = SelectProblem(title_md='Dates', text_md='Example with dates', create_sql=create, insert_sql=insert, collection=collection, solution=solution) user1 = user_model.objects.create_user(username='******', email='*****@*****.**', password='******') user2 = user_model.objects.create_user(username='******', email='*****@*****.**', password='******') user3 = user_model.objects.create_user(username='******', email='*****@*****.**', password='******') user4 = user_model.objects.create_user(username='******', email='*****@*****.**', password='******') problem1.clean() problem1.save() problem2.clean() problem2.save() user1.save() user2.save() user3.save() self.assertIsNone(problem1.solved_first()) self.assertIsNone(problem1.solved_second()) self.assertIsNone(problem1.solved_third()) sub1 = Submission(code='nada', veredict_code=VeredictCode.WA, user=user1, problem=problem1) sub2 = Submission(code='nada', veredict_code=VeredictCode.IE, user=user1, problem=problem1) sub3 = Submission(code='nada', veredict_code=VeredictCode.TLE, user=user1, problem=problem1) sub4 = Submission(code='nada', veredict_code=VeredictCode.RE, user=user1, problem=problem1) sub5 = Submission(code='nada', veredict_code=VeredictCode.VE, user=user1, problem=problem1) for sub in [sub1, sub2, sub3, sub4, sub5]: sub.save() self.assertIsNone(problem1.solved_first()) self.assertIsNone(problem1.solved_second()) self.assertIsNone(problem1.solved_third()) Submission(code='nada', veredict_code=VeredictCode.AC, user=user1, problem=problem1).save() self.assertEqual(problem1.solved_first(), user1) self.assertIsNone(problem1.solved_second()) self.assertIsNone(problem1.solved_third()) Submission(code='nada', veredict_code=VeredictCode.AC, user=user1, problem=problem1).save() Submission(code='nada', veredict_code=VeredictCode.AC, user=user1, problem=problem1).save() self.assertEqual(problem1.solved_first(), user1) self.assertIsNone(problem1.solved_second()) self.assertIsNone(problem1.solved_third()) Submission(code='nada', veredict_code=VeredictCode.AC, user=user2, problem=problem1).save() self.assertEqual(problem1.solved_first(), user1) self.assertEqual(problem1.solved_second(), user2) self.assertIsNone(problem1.solved_third()) Submission(code='nada', veredict_code=VeredictCode.AC, user=user1, problem=problem1).save() Submission(code='nada', veredict_code=VeredictCode.AC, user=user3, problem=problem1).save() self.assertEqual(problem1.solved_first(), user1) self.assertEqual(problem1.solved_second(), user2) self.assertEqual(problem1.solved_third(), user3) Submission(code='nada', veredict_code=VeredictCode.AC, user=user1, problem=problem1).save() Submission(code='nada', veredict_code=VeredictCode.AC, user=user1, problem=problem1).save() Submission(code='nada', veredict_code=VeredictCode.AC, user=user4, problem=problem1).save() self.assertEqual(problem1.solved_first(), user1) self.assertEqual(problem1.solved_second(), user2) self.assertEqual(problem1.solved_third(), user3) self.assertIsNone(problem2.solved_first()) self.assertIsNone(problem2.solved_second()) self.assertIsNone(problem2.solved_third())
def problem_submit(request, problem=None, submission=None): try: if submission is not None and not request.user.has_perm('judge.resubmit_other') and \ Submission.objects.get(id=int(submission)).user.user != request.user: raise PermissionDenied() except Submission.DoesNotExist: raise Http404() profile = request.user.profile if request.method == 'POST': form = ProblemSubmitForm(request.POST, instance=Submission(user=profile)) if form.is_valid(): if (not request.user.has_perm('judge.spam_submission') and Submission.objects.filter(user=profile).exclude( status__in=['D', 'IE', 'CE', 'AB']).count() > 2): return HttpResponse( '<h1>You submitted too many submissions.</h1>', status=503) if not form.cleaned_data['problem'].allowed_languages.filter( id=form.cleaned_data['language'].id).exists(): raise PermissionDenied() if not request.user.is_superuser and form.cleaned_data[ 'problem'].banned_users.filter(id=profile.id).exists(): return generic_message( request, 'Banned from Submitting', 'You have been declared persona non grata for this problem. ' 'You are permanently barred from submitting this problem.') model = form.save() cp = profile.contest if cp.current is not None: try: contest_problem = model.problem.contests.get( contest=cp.current.contest) except ContestProblem.DoesNotExist: pass else: contest = ContestSubmission(submission=model, problem=contest_problem, participation=cp.current) contest.save() model.judge() return HttpResponseRedirect( reverse('submission_status', args=[str(model.id)])) else: form_data = form.cleaned_data else: initial = {'language': profile.language} if problem is not None: try: initial['problem'] = Problem.objects.get(code=problem) except ObjectDoesNotExist: raise Http404() if submission is not None: try: sub = Submission.objects.get(id=int(submission)) initial['source'] = sub.source initial['language'] = sub.language except (ObjectDoesNotExist, ValueError): raise Http404() form = ProblemSubmitForm(initial=initial) form_data = initial if 'problem' in form_data: form.fields['language'].queryset = form_data[ 'problem'].usable_languages if 'language' in form_data: form.fields['source'].widget.mode = form_data['language'].ace form.fields['source'].widget.theme = profile.ace_theme return render( request, 'problem/submit.jade', { 'form': form, 'title': 'Submit', 'langs': Language.objects.all(), 'no_judges': not form.fields['language'].queryset })