def submit_view(request): try: token = request.POST['token'] current_token = SubmitServiceToken.objects.filter(token=token) if not current_token.exists(): raise PermissionDenied('AUTHORIZATION_FAILED') request.user = current_token[0].user if not can_enter_contest(request): raise PermissionDenied('AUTHORIZATION_FAILED') task_name = request.POST['task'] file_name, file_extension = os.path.splitext( request.FILES['file'].name) if task_name: file_name = task_name pi = match_problem(visible_problem_instances(request), file_name) if not pi: raise SubmitServiceException( 'NO_SUCH_PROBLEM', ', '.join([ x.short_name for x in visible_problem_instances(request) ]), ) lang_exts = get_allowed_languages_extensions(pi) if file_extension[1:] not in lang_exts: raise ValueError('UNSUPPORTED_EXTENSION') form = SubmissionForm( request, { 'problem_instance_id': pi.id, 'user': request.user, 'kind': 'NORMAL' }, request.FILES, ) if not form.is_valid(): raise SubmitServiceException('INVALID_SUBMISSION', form.errors) submission = request.contest.controller.create_submission( request, pi, form.cleaned_data) result_url = reverse( 'submission', kwargs={ 'contest_id': request.contest.id, 'submission_id': submission.id }, ) result = {'result_url': result_url, 'submission_id': submission.id} except SubmitServiceException as exception_info: result = { 'error_code': exception_info.args[0], 'error_data': exception_info.args[1] if len(exception_info.args) == 2 else '', } except Exception as e: result = {'error_code': 'UNKNOWN_ERROR', 'error_data': str(e)} return result
def statistics_available_plots(self, request, category, object): """Available plots for given object in given category. Does not check user's permission for viewing those statistics.""" result = [] rtimes = rounds_times(request, self.contest) def plot_kind(name, object): return (statistics_plot_kinds[name], object) def pi_results_visible(pi): return rtimes[pi.round].public_results_visible(request.timestamp) \ or is_contest_admin(request) or is_contest_observer(request) if category == 'CONTEST': if not object: object = request.contest result.append(plot_kind('SUBMISSIONS_HISTOGRAM_CONTEST', object)) pis = visible_problem_instances(request) # Do not add this plot if it would be empty. if any( pi_results_visible(pi) and not pi.round.is_trial for pi in pis): result.append(plot_kind('POINTS_HISTOGRAM_CONTEST', object)) if category == 'PROBLEM': result.append(plot_kind('POINTS_HISTOGRAM_PROBLEM', object)) result.append(plot_kind('POINTS_TABLE_PROBLEM', object)) result.append(plot_kind('POINTS_TO_SOURCE_LENGTH_PROBLEM', object)) result.append(plot_kind('TEST_SCORES_TABLE_PROBLEM', object)) return result
def problems_list_view(request): controller = request.contest.controller problem_instances = visible_problem_instances(request) # Problem statements in order # 1) problem instance # 2) statement_visible # 3) round end time # 4) user result # Sorted by (start_date, end_date, round name, problem name) problems_statements = sorted( [(pi, controller.can_see_statement( request, pi), controller.get_round_times(request, pi.round), UserResultForProblem.objects.filter(user=request.user, problem_instance=pi).first()) for pi in problem_instances], key=lambda p: (p[2].get_start(), p[2].get_end(), p[0].round.name, p[0].short_name)) show_rounds = len(frozenset(pi.round_id for pi in problem_instances)) > 1 return TemplateResponse( request, 'contests/problems_list.html', { 'problem_instances': problems_statements, 'show_rounds': show_rounds, 'problems_on_page': getattr(settings, 'PROBLEMS_ON_PAGE', 100) })
def contest_files_view(request): contest_files = ContestAttachment.objects.filter(contest=request.contest) \ .filter(Q(round__isnull=True) | Q(round__in=visible_rounds(request))) \ .select_related('round') round_file_exists = contest_files.filter(round__isnull=False).exists() problem_instances = visible_problem_instances(request) problem_ids = [pi.problem_id for pi in problem_instances] problem_files = ProblemAttachment.objects \ .filter(problem_id__in=problem_ids) \ .select_related('problem') add_category_field = round_file_exists or problem_files.exists() rows = [{ 'category': cf.round if cf.round else '', 'name': cf.filename, 'description': cf.description, 'link': reverse('contest_attachment', kwargs={'contest_id': request.contest.id, 'attachment_id': cf.id}), } for cf in contest_files] rows += [{ 'category': pf.problem, 'name': pf.filename, 'description': pf.description, 'link': reverse('problem_attachment', kwargs={'contest_id': request.contest.id, 'attachment_id': pf.id}), } for pf in problem_files] rows.sort(key=itemgetter('name')) return TemplateResponse(request, 'contests/files.html', {'files': rows, 'files_on_page': getattr(settings, 'FILES_ON_PAGE', 100), 'add_category_field': add_category_field})
def problem_attachment_view(request, contest_id, attachment_id): attachment = get_object_or_404(ProblemAttachment, id=attachment_id) problem_instances = visible_problem_instances(request) problem_ids = [pi.problem_id for pi in problem_instances] if attachment.problem_id not in problem_ids: raise PermissionDenied return stream_file(attachment.content)
def __init__(self, request, *args, **kwargs): self.kind = 'MAILSUBMIT' problem_filter = kwargs.pop('problem_filter', None) super(MailSubmissionForm, self).__init__(*args, **kwargs) self.request = request pis = visible_problem_instances(request) if problem_filter: pis = problem_filter(pis) pi_choices = [(pi.id, unicode(pi)) for pi in pis] pi_field = self.fields['problem_instance_id'] pi_field.choices = pi_choices pi_field.widget.attrs['class'] = 'input-xlarge' # if problem_instance does not exist any from the current # contest is chosen. To change in future. # ALSO in contests.forms contest = request.contest assert contest is not None problem_instance = ProblemInstance.objects \ .filter(contest=contest)[0] contest.controller.adjust_submission_form(request, self, problem_instance)
def visible_tests_packages(request): problems = [pi.problem for pi in visible_problem_instances(request)] tests_packages = TestsPackage.objects.filter(problem__in=problems) return [ tp for tp in tests_packages if tp.is_visible(request.timestamp) and tp.package is not None ]
def contest_files_view(request): contest_files = ContestAttachment.objects.filter(contest=request.contest) \ .filter(Q(round__isnull=True) | Q(round__in=visible_rounds(request))) \ .select_related('round') if not is_contest_admin(request): contest_files = contest_files.filter(Q(pub_date__isnull=True) | Q(pub_date__lte=request.timestamp)) round_file_exists = contest_files.filter(round__isnull=False).exists() problem_instances = visible_problem_instances(request) problem_ids = [pi.problem_id for pi in problem_instances] problem_files = ProblemAttachment.objects \ .filter(problem_id__in=problem_ids) \ .select_related('problem') add_category_field = round_file_exists or problem_files.exists() rows = [{ 'category': cf.round if cf.round else '', 'name': cf.download_name, 'description': cf.description, 'link': reverse('contest_attachment', kwargs={'contest_id': request.contest.id, 'attachment_id': cf.id}), 'pub_date': cf.pub_date } for cf in contest_files] rows += [{ 'category': pf.problem, 'name': pf.download_name, 'description': pf.description, 'link': reverse('problem_attachment', kwargs={'contest_id': request.contest.id, 'attachment_id': pf.id}), 'pub_date': None } for pf in problem_files] rows.sort(key=itemgetter('name')) return TemplateResponse(request, 'contests/files.html', {'files': rows, 'files_on_page': getattr(settings, 'FILES_ON_PAGE', 100), 'add_category_field': add_category_field, 'show_pub_dates': True})
def statistics_available_plots(self, request, category, object): """Available plots for given object in given category. Does not check user's permission for viewing those statistics.""" result = [] rtimes = rounds_times(request) def plot_kind(name, object): return (statistics_plot_kinds[name], object) def pi_results_visible(pi): return rtimes[pi.round].public_results_visible(request.timestamp) \ or is_contest_admin(request) or is_contest_observer(request) if category == 'CONTEST': if not object: object = request.contest result.append(plot_kind('SUBMISSIONS_HISTOGRAM_CONTEST', object)) pis = visible_problem_instances(request) # Do not add this plot if it would be empty. if any(pi_results_visible(pi) and not pi.round.is_trial for pi in pis): result.append(plot_kind('POINTS_HISTOGRAM_CONTEST', object)) if category == 'PROBLEM': result.append(plot_kind('POINTS_HISTOGRAM_PROBLEM', object)) result.append(plot_kind('POINTS_TABLE_PROBLEM', object)) result.append(plot_kind('POINTS_TO_SOURCE_LENGTH_PROBLEM', object)) result.append(plot_kind('TEST_SCORES_TABLE_PROBLEM', object)) return result
def problem_attachment_view(request, attachment_id): attachment = get_object_or_404(ProblemAttachment, id=attachment_id) problem_instances = visible_problem_instances(request) problem_ids = [pi.problem_id for pi in problem_instances] if attachment.problem_id not in problem_ids: raise PermissionDenied return stream_file(attachment.content, attachment.download_name)
def filter_my_visible_submissions(self, request, queryset): if not request.user.is_authenticated: return queryset.none() try: tm = TeamMembership.objects.get(user=request.user, team__contest=request.contest) qs = queryset.filter(user=tm.team.user, problem_instance__in=visible_problem_instances(request)) except TeamMembership.DoesNotExist: qs = queryset.filter(user=request.user, problem_instance__in=visible_problem_instances(request)) if is_contest_admin(request): return qs else: return qs.filter(date__lte=request.timestamp)
def problems_list_view(request): controller = request.contest.controller problem_instances = visible_problem_instances(request) # Problem statements in order # 1) problem instance # 2) statement_visible # 3) round end time # 4) user result # 5) number of submissions left # 6) submissions_limit # 7) can_submit # Sorted by (start_date, end_date, round name, problem name) problems_statements = sorted( [ ( pi, controller.can_see_statement(request, pi), controller.get_round_times(request, pi.round), # Because this view can be accessed by an anynomous user we can't # use `user=request.user` (it would cause TypeError). Surprisingly # using request.user.id is ok since for AnynomousUser id is set # to None. next( (r for r in UserResultForProblem.objects.filter( user__id=request.user.id, problem_instance=pi) if r and r.submission_report and controller.can_see_submission_score( request, r.submission_report.submission)), None, ), pi.controller.get_submissions_left(request, pi), pi.controller.get_submissions_limit(request, pi), controller.can_submit(request, pi), ) for pi in problem_instances ], key=lambda p: (p[2].get_key_for_comparison(), p[0].round.name, p[0].short_name), ) show_submissions_limit = any([p[5] for p in problems_statements]) show_submit_button = any([p[6] for p in problems_statements]) show_rounds = len(frozenset(pi.round_id for pi in problem_instances)) > 1 table_columns = 3 + int(show_submissions_limit) + int(show_submit_button) return TemplateResponse( request, 'contests/problems_list.html', { 'problem_instances': problems_statements, 'show_rounds': show_rounds, 'show_scores': request.user.is_authenticated, 'show_submissions_limit': show_submissions_limit, 'show_submit_button': show_submit_button, 'table_columns': table_columns, 'problems_on_page': getattr(settings, 'PROBLEMS_ON_PAGE', 100), }, )
def submit_view(request): try: token = request.POST['token'] current_token = SubmitServiceToken.objects.filter(token=token) if not current_token.exists(): raise PermissionDenied('AUTHORIZATION_FAILED') request.user = current_token[0].user if not can_enter_contest(request): raise PermissionDenied('AUTHORIZATION_FAILED') task_name = request.POST['task'] file_name, file_extension = \ os.path.splitext(request.FILES['file'].name) if task_name: file_name = task_name pi = match_problem(visible_problem_instances(request), file_name) if not pi: raise SubmitServiceException('NO_SUCH_PROBLEM', ', '.join([ x.short_name for x in visible_problem_instances(request)])) lang_exts = sum( getattr(settings, 'SUBMITTABLE_EXTENSIONS', {}).values(), []) if file_extension[1:] not in lang_exts: raise ValueError('UNSUPPORTED_EXTENSION') form = SubmissionForm(request, { 'problem_instance_id': pi.id, 'user': request.user, 'kind': 'NORMAL' }, request.FILES) if not form.is_valid(): raise SubmitServiceException('INVALID_SUBMISSION', form.errors) submission = request.contest.controller \ .create_submission(request, pi, form.cleaned_data) result_url = reverse('oioioi.contests.views.submission_view', kwargs={'contest_id': request.contest.id, 'submission_id': submission.id}) result = {'result_url': result_url, 'submission_id': submission.id} except SubmitServiceException as exception_info: result = {'error_code': exception_info.args[0], 'error_data': exception_info.args[1] if len(exception_info.args) == 2 else ''} except StandardError as e: result = {'error_code': 'UNKNOWN_ERROR', 'error_data': str(e)} return result
def problems_list_view(request, contest_id): problem_instances = visible_problem_instances(request) show_rounds = len(frozenset(pi.round_id for pi in problem_instances)) > 1 return TemplateResponse( request, 'contests/problems_list.html', { 'problem_instances': problem_instances, 'show_rounds': show_rounds, 'problems_on_page': getattr(settings, 'PROBLEMS_ON_PAGE', 100) })
def problems_list_view(request): controller = request.contest.controller problem_instances = visible_problem_instances(request) problems_statements = [(pi, controller.can_see_statement(request, pi)) for pi in problem_instances] show_rounds = len(frozenset(pi.round_id for pi in problem_instances)) > 1 return TemplateResponse(request, 'contests/problems_list.html', {'problem_instances': problems_statements, 'show_rounds': show_rounds, 'problems_on_page': getattr(settings, 'PROBLEMS_ON_PAGE', 100)})
def filter_my_visible_submissions(self, request, queryset): if not request.user.is_authenticated(): return queryset.none() try: tm = TeamMembership.objects.get(user=request.user, team__contest=request.contest) qs = queryset.filter( user=tm.team.user, problem_instance__in=visible_problem_instances(request)) except TeamMembership.DoesNotExist: qs = queryset.filter( user=request.user, problem_instance__in=visible_problem_instances(request)) if is_contest_admin(request): return qs else: return qs.filter(date__lte=request.timestamp)
def visible_messages(request): problem_instances = visible_problem_instances(request) problem_ids = [pi.problem_id for pi in problem_instances] messages = Message.objects.filter(Q(contest=request.contest.id) | Q(problem_id__in=problem_ids)).order_by("-date") if not request.user.has_perm("contests.contest_admin", request.contest): q_expression = Q(kind="PUBLIC") if request.user.is_authenticated(): q_expression = ( q_expression | (Q(author=request.user) & Q(kind="QUESTION")) | Q(top_reference__author=request.user) ) messages = messages.filter(q_expression) return messages
def __init__(self, request, *args, **kwargs): super(AddContestMessageForm, self).__init__(*args, **kwargs) self.fields['topic'].widget.attrs['class'] = 'input-xxlarge' self.fields['content'].widget.attrs['class'] = 'input-xxlarge monospace' self.request = request problem_instances = visible_problem_instances(request) categories = [('__general__', _("General"))] + \ [(pi.id, _("Problem %s") % (pi.problem.name,)) for pi in problem_instances] self.fields['category'].choices = categories
def filter_my_visible_submissions(self, request, queryset): """Returns the submissions which the user should see in the "My submissions" view. The default implementation returns all submissions belonging to the user for the problems that are visible. Should return the updated queryset. """ if not request.user.is_authenticated(): return queryset.none() qs = queryset.filter(user=request.user) \ .filter(problem_instance__in=visible_problem_instances(request)) if is_contest_admin(request): return qs else: return qs.filter(date__lte=request.timestamp)
def statistics_available_plot_groups(self, request): problem_instances = visible_problem_instances(request) result = [] times = rounds_times(request) can_see_any_problems = False for pi in problem_instances: can_see_round = times[pi.round].results_visible(request.timestamp) if can_see_round: result.append(('PROBLEM', pi.short_name, pi.problem.name)) can_see_any_problems = True if can_see_any_problems: result.insert( 0, ('CONTEST', request.contest.id, request.contest.name)) return result
def filter_my_visible_submissions(self, request, queryset): """Returns the submissions which the user should see in the "My submissions" view. The default implementation returns all submissions belonging to the user for the problems that are visible, except for admins, which get all their submissions. Should return the updated queryset. """ if not request.user.is_authenticated: return queryset.none() qs = queryset.filter(user=request.user) if is_contest_basicadmin(request): return qs else: return qs.filter(date__lte=request.timestamp) \ .filter(problem_instance__in=visible_problem_instances(request)) \ .exclude(kind='IGNORED_HIDDEN')
def problems_list_view(request): controller = request.contest.controller problem_instances = visible_problem_instances(request) # Problem statements in order # 1) problem instance # 2) statement_visible # 3) round end time # 4) user result # 5) number of submissions left # Sorted by (start_date, end_date, round name, problem name) problems_statements = sorted([ ( pi, controller.can_see_statement(request, pi), controller.get_round_times(request, pi.round), # Because this view can be accessed by an anynomous user we can't # use `user=request.user` (it would cause TypeError). Surprisingly # using request.user.id is ok since for AnynomousUser id is set # to None. next((r for r in UserResultForProblem.objects.filter( user__id=request.user.id, problem_instance=pi) if r and r.submission_report and controller.can_see_submission_score(request, r.submission_report.submission)), None), pi.controller.get_submissions_left(request, pi), pi.controller.get_submissions_limit(request, pi) ) for pi in problem_instances ], key=lambda p: (p[2].get_start(), p[2].get_end(), p[0].round.name, p[0].short_name)) show_submissions_limit = any([p[5] for p in problems_statements]) show_rounds = len(frozenset(pi.round_id for pi in problem_instances)) > 1 return TemplateResponse(request, 'contests/problems_list.html', {'problem_instances': problems_statements, 'show_rounds': show_rounds, 'show_scores': request.user.is_authenticated, 'show_submissions_limit': show_submissions_limit, 'problems_on_page': getattr(settings, 'PROBLEMS_ON_PAGE', 100)})
def files_view(request, contest_id): contest_files = ContestAttachment.objects.filter(contest=request.contest) problem_instances = visible_problem_instances(request) problem_ids = [pi.problem_id for pi in problem_instances] problem_files = \ ProblemAttachment.objects.filter(problem_id__in=problem_ids) rows = [{ 'name': cf.filename, 'description': cf.description, 'link': reverse('contest_attachment', kwargs={'contest_id': contest_id, 'attachment_id': cf.id}), } for cf in contest_files] rows += [{ 'name': pf.filename, 'description': u'%s: %s' % (pf.problem, pf.description), 'link': reverse('problem_attachment', kwargs={'contest_id': contest_id, 'attachment_id': pf.id}), } for pf in problem_files] rows.sort(key=itemgetter('name')) return TemplateResponse(request, 'contests/files.html', {'files': rows})
def filter_my_visible_submissions(self, request, queryset, filter_user=True): if not request.user.is_authenticated: return queryset.none() if not filter_user: raise NotImplementedError try: tm = TeamMembership.objects.get(user=request.user, team__contest=request.contest) qs = queryset.filter( user=tm.team.user, problem_instance__in=visible_problem_instances(request)) filter_user = False except TeamMembership.DoesNotExist: qs = queryset return super(TeamsMixinForContestController, self). \ filter_my_visible_submissions(request, qs, filter_user)
def __init__(self, request, *args, **kwargs): self.kind = 'MAILSUBMIT' problem_filter = kwargs.pop('problem_filter', None) super(MailSubmissionForm, self).__init__(*args, **kwargs) self.request = request pis = visible_problem_instances(request) if problem_filter: pis = problem_filter(pis) pi_choices = [(pi.id, six.text_type(pi)) for pi in pis] pi_field = self.fields['problem_instance_id'] pi_field.choices = pi_choices pi_field.widget.attrs['class'] = 'input-xlarge' # add fields etc. contest = request.contest assert contest is not None problem_instances = ProblemInstance.objects.filter(contest=contest) for pi in problem_instances: pi.controller.adjust_submission_form(request, self, pi)
def problems_list_view(request): controller = request.contest.controller problem_instances = visible_problem_instances(request) # Problem statements in order # 1) problem instance # 2) statement_visible # 3) round end time # 4) user result # Sorted by (start_date, end_date, round name, problem name) problems_statements = sorted( [ ( pi, controller.can_see_statement(request, pi), controller.get_round_times(request, pi.round), # Because this view can be accessed by an anynomous user we can't # use `user=request.user` (it would cause TypeError). Suprisingly # using request.user.id is ok since for AnynomousUser id is set # to None. UserResultForProblem.objects.filter( user__id=request.user.id, problem_instance=pi).first()) for pi in problem_instances ], key=lambda p: (p[2].get_start(), p[2].get_end(), p[0].round.name, p[0].short_name)) show_rounds = len(frozenset(pi.round_id for pi in problem_instances)) > 1 return TemplateResponse( request, 'contests/problems_list.html', { 'problem_instances': problems_statements, 'show_rounds': show_rounds, 'show_scores': request.user.is_authenticated(), 'problems_on_page': getattr(settings, 'PROBLEMS_ON_PAGE', 100) })
def __init__(self, request, *args, **kwargs): self.kind = "MAILSUBMIT" problem_filter = kwargs.pop("problem_filter", None) super(MailSubmissionForm, self).__init__(*args, **kwargs) self.request = request pis = visible_problem_instances(request) if problem_filter: pis = problem_filter(pis) pi_choices = [(pi.id, unicode(pi)) for pi in pis] pi_field = self.fields["problem_instance_id"] pi_field.choices = pi_choices pi_field.widget.attrs["class"] = "input-xlarge" # if problem_instance does not exist any from the current # contest is chosen. To change in future. # ALSO in contests.forms contest = request.contest assert contest is not None problem_instance = ProblemInstance.objects.filter(contest=contest)[0] contest.controller.adjust_submission_form(request, self, problem_instance)
def get_categories(request): categories = [('p_%d' % (pi.id,), _("Problem %s") % (pi.problem.name,)) for pi in visible_problem_instances(request)] categories += [('r_%d' % (round.id,), _("General, %s") % (round.name,)) for round in visible_rounds(request)] return categories
def get_categories(request): categories = [('p_%d' % (pi.id, ), _("Problem %s") % (pi.problem.name, )) for pi in visible_problem_instances(request)] categories += [('r_%d' % (round.id, ), _("General, %s") % (round.name, )) for round in visible_rounds(request)] return categories
def get_problem_instances(self): return visible_problem_instances(self.request)
def problems_list_view(request, contest_id): problem_instances = visible_problem_instances(request) show_rounds = len(frozenset(pi.round_id for pi in problem_instances)) > 1 return TemplateResponse(request, 'contests/problems_list.html', {'problem_instances': problem_instances, 'show_rounds': show_rounds})
def visible_tests_packages(request): problems = [pi.problem for pi in visible_problem_instances(request)] tests_packages = TestsPackage.objects.filter(problem__in=problems) return [tp for tp in tests_packages if tp.is_visible(request.timestamp) and tp.package is not None]