Change live notification to polling

This commit is contained in:
cuom1999 2021-10-16 17:40:02 -05:00
parent 2539b3e071
commit 425354a2de
7 changed files with 70 additions and 58 deletions

View file

@ -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]))),
])),

View file

@ -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)

View file

@ -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
@ -916,3 +916,39 @@ class NewContestClarificationView(ContestMixin, TitleMixin, SingleObjectFormView
context['problems'] = ContestProblem.objects.filter(contest=self.object)\
.order_by('order')
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})

View file

@ -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 \

View file

@ -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 () {

View file

@ -132,21 +132,6 @@
</script>
{% endcompress %}
{% if request.in_contest %}
{% if last_msg %}
<script type="text/javascript" src="{{ static('event.js') }}"></script>
<script>
function setup_event_contest(last_msg) {
var channel = ['contest_clarification_' + {{request.participation.contest.id}}]
return new EventReceiver(
"{{ EVENT_DAEMON_LOCATION }}", "{{ EVENT_DAEMON_POLL_LOCATION }}",
channel, last_msg, function (message) {
notify_clarification(message);
}
);
}
setup_event_contest();
</script>
{% endif %}
{% compress js %}
<script src="{{ static('libs/tablesorter.js') }}" type="text/javascript"></script>
<script type="text/javascript">
@ -174,6 +159,8 @@
return (node.hasClass('p') ? text.replace(/p$/, '') : text);
}
});
window.register_contest_notification("{{url('contest_clarification_ajax', request.participation.contest.key)}}");
});
</script>
{% endcompress %}

View file

@ -61,22 +61,10 @@
{% block content_js_media %}
{% include "comments/media-js.html" %}
{% if request.in_contest %}
{% if last_msg %}
<script type="text/javascript" src="{{ static('event.js') }}"></script>
<script>
function setup_event_contest(last_msg) {
var channel = ['contest_clarification_' + {{request.participation.contest.id}}]
return new EventReceiver(
"{{ EVENT_DAEMON_LOCATION }}", "{{ EVENT_DAEMON_POLL_LOCATION }}",
channel, last_msg, function (message) {
notify_clarification(message);
}
);
}
setup_event_contest();
<script type="text/javascript">
window.register_contest_notification("{{url('contest_clarification_ajax', request.participation.contest.key)}}");
</script>
{% endif %}
{% endif %}
<script type="text/javascript">
$(function() {
$('#pdf_button').click(async function(e) {