diff --git a/dmoj/urls.py b/dmoj/urls.py index a7b6d82..70fa053 100644 --- a/dmoj/urls.py +++ b/dmoj/urls.py @@ -280,6 +280,7 @@ urlpatterns = [ url(r'^mailgun/mail_activate/$', mailgun.MailgunActivationView.as_view(), name='mailgun_activate'), url(r'^widgets/', include([ + url(r'^contest_mode$', contests.update_contest_mode, name='contest_mode_ajax'), url(r'^rejudge$', widgets.rejudge_submission, name='submission_rejudge'), url(r'^single_submission$', submission.single_submission_query, name='submission_single_query'), url(r'^submission_testcases$', submission.SubmissionTestCaseQuery.as_view(), name='submission_testcases_query'), diff --git a/judge/middleware.py b/judge/middleware.py index 4a58882..b35e1a3 100644 --- a/judge/middleware.py +++ b/judge/middleware.py @@ -57,7 +57,9 @@ class ContestMiddleware(object): profile.update_contest() request.participation = profile.current_contest request.in_contest = request.participation is not None + request.contest_mode = request.session.get('contest_mode', True) else: request.in_contest = False request.participation = None + request.in_contest_mode = request.in_contest and request.contest_mode return self.get_response(request) diff --git a/judge/views/contests.py b/judge/views/contests.py index 0833a33..7bdccac 100644 --- a/judge/views/contests.py +++ b/judge/views/contests.py @@ -15,7 +15,7 @@ from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist from django.db import IntegrityError from django.db.models import Case, Count, F, FloatField, IntegerField, Max, Min, Q, Sum, Value, When from django.db.models.expressions import CombinedExpression -from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseRedirect, JsonResponse +from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseRedirect, JsonResponse, HttpResponseNotAllowed from django.shortcuts import get_object_or_404, render from django.template.defaultfilters import date as date_filter from django.urls import reverse, reverse_lazy @@ -46,7 +46,7 @@ from judge.widgets import HeavyPreviewPageDownWidget __all__ = ['ContestList', 'ContestDetail', 'ContestRanking', 'ContestJoin', 'ContestLeave', 'ContestCalendar', 'ContestClone', 'ContestStats', 'ContestMossView', 'ContestMossDelete', 'contest_ranking_ajax', 'ContestParticipationList', 'ContestParticipationDisqualify', 'get_contest_ranking_list', - 'base_contest_ranking_list', 'ContestClarificationView'] + 'base_contest_ranking_list', 'ContestClarificationView', 'update_contest_mode'] def _find_contest(request, key, private_check=True): @@ -428,6 +428,7 @@ class ContestLeave(LoginRequiredMixin, ContestMixin, BaseDetailView): _('You are not in contest "%s".') % contest.key, 404) profile.remove_contest() + request.session['contest_mode'] = True # reset contest_mode return HttpResponseRedirect(reverse('contest_view', args=(contest.key,))) @@ -953,3 +954,12 @@ class ContestClarificationAjax(ContestMixin, DetailView): cla['order'] = self.object.get_label_for_problem(problems.index(cla['problem'])) return JsonResponse(queryset, safe=False, json_dumps_params={'ensure_ascii': False}) + + +def update_contest_mode(request): + if not request.is_ajax() or not request.method=='POST': + return HttpResponseNotAllowed(['POST']) + + old_mode = request.session.get('contest_mode', True) + request.session['contest_mode'] = not old_mode + return HttpResponse() \ No newline at end of file diff --git a/judge/views/problem.py b/judge/views/problem.py index de07cbe..e7f2763 100644 --- a/judge/views/problem.py +++ b/judge/views/problem.py @@ -71,7 +71,8 @@ class ProblemMixin(object): def get(self, request, *args, **kwargs): try: return super(ProblemMixin, self).get(request, *args, **kwargs) - except Http404: + except Http404 as e: + print(e) return self.no_such_problem() @@ -90,7 +91,8 @@ class SolvedProblemMixin(object): @cached_property def in_contest(self): - return self.profile is not None and self.profile.current_contest is not None + return self.profile is not None and self.profile.current_contest is not None \ + and self.request.in_contest_mode @cached_property def contest(self): @@ -120,10 +122,9 @@ class ProblemSolution(SolvedProblemMixin, ProblemMixin, TitleMixin, CommentedDet solution = get_object_or_404(Solution, problem=self.object) if (not solution.is_public or solution.publish_on > timezone.now()) and \ - not self.request.user.has_perm('judge.see_private_solution') or \ - (self.request.user.is_authenticated and - self.request.profile.current_contest): + not self.request.user.has_perm('judge.see_private_solution'): raise Http404() + context['solution'] = solution context['has_solved_problem'] = self.object.id in self.get_completed_problems() return context diff --git a/judge/views/submission.py b/judge/views/submission.py index 1c10872..e5f8b69 100644 --- a/judge/views/submission.py +++ b/judge/views/submission.py @@ -262,7 +262,8 @@ class SubmissionsListBase(DiggPaginatorMixin, TitleMixin, ListView): @cached_property def in_contest(self): - return self.request.user.is_authenticated and self.request.profile.current_contest is not None + return self.request.user.is_authenticated and self.request.profile.current_contest is not None \ + and self.request.in_contest_mode @cached_property def contest(self): diff --git a/judge/views/user.py b/judge/views/user.py index b874d65..2265979 100644 --- a/judge/views/user.py +++ b/judge/views/user.py @@ -92,7 +92,8 @@ class UserPage(TitleMixin, UserMixin, DetailView): @cached_property def in_contest(self): - return self.profile is not None and self.profile.current_contest is not None + return self.profile is not None and self.profile.current_contest is not None \ + and self.request.in_contest_mode def get_completed_problems(self): if self.in_contest: @@ -374,8 +375,8 @@ class FixedContestRanking(ContestRanking): def users(request): if request.user.is_authenticated: - participation = request.profile.current_contest - if participation is not None: + if request.in_contest_mode: + participation = request.profile.current_contest contest = participation.contest return FixedContestRanking.as_view(contest=contest)(request, contest=contest.key) return user_list_view(request) diff --git a/resources/base.scss b/resources/base.scss index 0b316fc..369b91b 100644 --- a/resources/base.scss +++ b/resources/base.scss @@ -485,12 +485,8 @@ noscript #noscript { #contest-info { font-size: 1.25em; border: 5px solid $highlight_blue; - border-left: 5px dotted white; border-radius: 0 $widget_border_radius $widget_border_radius 0; - background: rgba(0, 0, 0, 0.77); z-index: 100000; - padding: 10px 12px; - color: white; cursor: move; position: fixed; left: 20px; @@ -506,6 +502,34 @@ noscript #noscript { } } +#contest-info-main { + border-left: 5px dotted white; + background: rgba(0, 0, 0, 0.77); + padding: 10px 12px; + color: white; + display: inline; +} + +#contest-info-toggle { + display: inline; + padding: 10px 12px; + border-radius: 0 10px 10px 0; + cursor: pointer; +} + +.contest-info-toggle-mode-on { + background: rgba(0, 205, 0, 0.57); +} +.contest-info-toggle-mode-on:hover { + background: rgba(0, 205, 0, 0.97); +} +.contest-info-toggle-mode-off { + background: rgba(255, 0, 0, 0.57); +} +.contest-info-toggle-mode-off:hover { + background: rgba(255, 0, 0, 0.97); +} + #contest-time-remaining { display: inline-block; } diff --git a/templates/base.html b/templates/base.html index 54c6eba..f3371d4 100644 --- a/templates/base.html +++ b/templates/base.html @@ -117,6 +117,12 @@ $("#contest-info").show(); + $("#contest-info-toggle").on('click', function() { + $.post("{{url('contest_mode_ajax')}}", function() { + window.location.reload(); + }) + }); + $(document).mousemove(function (e) { x_pos = e.screenX; y_pos = e.screenY; @@ -190,6 +196,42 @@
@@ -284,18 +326,27 @@ {% if request.in_contest %} {% endif %}