diff --git a/dmoj/urls.py b/dmoj/urls.py
index f53b373..c5b8875 100644
--- a/dmoj/urls.py
+++ b/dmoj/urls.py
@@ -1,4 +1,5 @@
from chat_box.views import ChatView, delete_message, post_message, chat_message_ajax, online_status_ajax
+
from django.conf import settings
from django.conf.urls import include, url
from django.contrib import admin
@@ -226,6 +227,7 @@ urlpatterns = [
name='contest_participation_disqualify'),
url(r'^/clarification$', contests.NewContestClarificationView.as_view(), name='new_contest_clarification'),
+ url(r'^/clarification/ajax$', contests.ContestClarificationAjax.as_view(), name='contest_clarification_ajax'),
url(r'^/$', lambda _, contest: HttpResponsePermanentRedirect(reverse('contest_view', args=[contest]))),
])),
diff --git a/judge/models/problem.py b/judge/models/problem.py
index e56b1c7..4f7e545 100644
--- a/judge/models/problem.py
+++ b/judge/models/problem.py
@@ -11,9 +11,7 @@ from django.db.models.functions import Coalesce
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.translation import gettext_lazy as _
-from django.utils import timezone
-from judge import event_poster as event
from judge.fulltext import SearchQuerySet
from judge.models.profile import Organization, Profile
from judge.models.runtime import Language
@@ -409,26 +407,6 @@ class ProblemClarification(models.Model):
description = models.TextField(verbose_name=_('clarification body'))
date = models.DateTimeField(verbose_name=_('clarification timestamp'), auto_now_add=True)
- def save(self, *args, **kwargs):
- super(ProblemClarification, self).save(*args, **kwargs)
-
- if event.real:
- from judge.models import ContestProblem
-
- now = timezone.now()
- # List all ongoing contests containing this problem
- contest_problems = ContestProblem.objects.filter(
- contest__start_time__lte=now,
- contest__end_time__gt=now,
- problem=self.problem).values_list('order', 'contest')
-
- for order, contest_id in contest_problems.iterator():
- event.post('contest_clarification_' + str(contest_id), {
- 'problem_label': order,
- 'problem_name': self.problem.name,
- 'problem_code': self.problem.code,
- 'body': self.description
- })
class LanguageLimit(models.Model):
problem = models.ForeignKey(Problem, verbose_name=_('problem'), related_name='language_limits', on_delete=CASCADE)
diff --git a/judge/views/contests.py b/judge/views/contests.py
index 90dc3c2..843fe04 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
+from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseRedirect, JsonResponse
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
@@ -915,4 +915,40 @@ class NewContestClarificationView(ContestMixin, TitleMixin, SingleObjectFormView
context = super(NewContestClarificationView, self).get_context_data(**kwargs)
context['problems'] = ContestProblem.objects.filter(contest=self.object)\
.order_by('order')
- return context
\ No newline at end of file
+ return context
+
+
+class ContestClarificationAjax(ContestMixin, DetailView):
+ template_name = 'contest/clarification-ajax.html'\
+
+ def is_accessible(self):
+ if not self.request.user.is_authenticated:
+ return False
+ if not self.request.in_contest:
+ return False
+ if not self.request.participation.contest == self.object:
+ return False
+ return self.request.user.is_superuser or \
+ self.request.profile in self.request.participation.contest.authors.all() or \
+ self.request.profile in self.request.participation.contest.curators.all()
+
+ def get(self, request, *args, **kwargs):
+ self.object = self.get_object()
+ if not self.is_accessible():
+ raise Http404()
+
+ polling_time = 1 # minute
+ last_one_minute = last_five_minutes = timezone.now()-timezone.timedelta(minutes=polling_time)
+
+ queryset = list(ProblemClarification.objects.filter(
+ problem__in=self.object.problems.all(),
+ date__gte=last_one_minute
+ ).values('problem', 'problem__name', 'description'))
+
+ problems = list(ContestProblem.objects.filter(contest=self.object)\
+ .order_by('order').values('problem'))
+ problems = [i['problem'] for i in problems]
+ for cla in queryset:
+ cla['order'] = self.object.get_label_for_problem(problems.index(cla['problem']))
+
+ return JsonResponse(queryset, safe=False, json_dumps_params={'ensure_ascii': False})
diff --git a/judge/views/problem.py b/judge/views/problem.py
index bfa6bb0..d039252 100644
--- a/judge/views/problem.py
+++ b/judge/views/problem.py
@@ -25,7 +25,6 @@ from django.views.generic import ListView, View
from django.views.generic.base import TemplateResponseMixin
from django.views.generic.detail import SingleObjectMixin
-from judge import event_poster as event
from judge.comments import CommentedDetailView
from judge.forms import ProblemCloneForm, ProblemSubmitForm
from judge.models import ContestProblem, ContestSubmission, Judge, Language, Problem, ProblemGroup, \
@@ -174,7 +173,6 @@ class ProblemDetail(ProblemMixin, SolvedProblemMixin, CommentedDetailView):
if contest_problem:
clarifications = self.object.clarifications
- context['last_msg'] = event.last()
context['has_clarifications'] = clarifications.count() > 0
context['clarifications'] = clarifications.order_by('-date')
context['submission_limit'] = contest_problem.max_submissions
@@ -437,7 +435,6 @@ class ProblemList(QueryStringSortMixin, TitleMixin, SolvedProblemMixin, ListView
context['hot_problems'] = hot_problems(timedelta(days=1), 7)
context['point_start'], context['point_end'], context['point_values'] = self.get_noui_slider_points()
else:
- context['last_msg'] = event.last()
context['hot_problems'] = None
context['point_start'], context['point_end'], context['point_values'] = 0, 0, {}
context['hide_contest_scoreboard'] = self.contest.scoreboard_visibility in \
diff --git a/resources/common.js b/resources/common.js
index 01f71b8..609a654 100644
--- a/resources/common.js
+++ b/resources/common.js
@@ -324,10 +324,34 @@ window.register_notify = function (type, options) {
};
window.notify_clarification = function(msg) {
- var message = `Problem ${msg.problem_label} (${msg.problem_name}):\n` + msg.body;
+ var message = `Problem ${msg.order} (${msg.problem__name}):\n` + msg.description;
alert(message);
}
+window.register_contest_notification = function(url) {
+ function get_clarifications() {
+ $.get(url)
+ .fail(function() {
+ console.log("Fail to update clarification");
+ })
+ .done(function(data) {
+ for (i of data) {
+ window.notify_clarification(i);
+ }
+ if (data.status == 403) {
+ console.log("Fail to retrieve data");
+ }
+ else {
+ $('#chat-online-content').html(data).find('.toggle').each(function () {
+ register_toggle($(this));
+ });;
+ }
+ })
+ }
+ get_clarifications();
+ setInterval(get_clarifications, 60 * 1000);
+}
+
$(function () {
// Close dismissable boxes
$("a.close").click(function () {
diff --git a/templates/problem/list.html b/templates/problem/list.html
index 7057d74..a79b94b 100644
--- a/templates/problem/list.html
+++ b/templates/problem/list.html
@@ -132,21 +132,6 @@
{% endcompress %}
{% if request.in_contest %}
- {% if last_msg %}
-
-
- {% endif %}
{% compress js %}
{% endcompress %}
diff --git a/templates/problem/problem.html b/templates/problem/problem.html
index 8e67164..54b9623 100644
--- a/templates/problem/problem.html
+++ b/templates/problem/problem.html
@@ -61,21 +61,9 @@
{% block content_js_media %}
{% include "comments/media-js.html" %}
{% if request.in_contest %}
- {% if last_msg %}
-
-
- {% endif %}
+
{% endif %}