commit
127284e812
24 changed files with 303 additions and 145 deletions
|
@ -375,9 +375,10 @@ def get_or_create_room(request):
|
||||||
# TODO: each user can only create <= 300 rooms
|
# TODO: each user can only create <= 300 rooms
|
||||||
room = get_room(other_user, user)
|
room = get_room(other_user, user)
|
||||||
for u in [other_user, user]:
|
for u in [other_user, user]:
|
||||||
user_room, _ = UserRoom.objects.get_or_create(user=u, room=room)
|
user_room, created = UserRoom.objects.get_or_create(user=u, room=room)
|
||||||
user_room.last_seen = timezone.now()
|
if created:
|
||||||
user_room.save()
|
user_room.last_seen = timezone.now()
|
||||||
|
user_room.save()
|
||||||
|
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
return JsonResponse({'room': room.id, 'other_user_id': other_user.id})
|
return JsonResponse({'room': room.id, 'other_user_id': other_user.id})
|
||||||
|
|
23
dmoj/urls.py
23
dmoj/urls.py
|
@ -1,4 +1,4 @@
|
||||||
from chat_box.views import *
|
import chat_box.views as chat
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls import include, url
|
from django.conf.urls import include, url
|
||||||
|
@ -280,6 +280,7 @@ urlpatterns = [
|
||||||
url(r'^mailgun/mail_activate/$', mailgun.MailgunActivationView.as_view(), name='mailgun_activate'),
|
url(r'^mailgun/mail_activate/$', mailgun.MailgunActivationView.as_view(), name='mailgun_activate'),
|
||||||
|
|
||||||
url(r'^widgets/', include([
|
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'^rejudge$', widgets.rejudge_submission, name='submission_rejudge'),
|
||||||
url(r'^single_submission$', submission.single_submission_query, name='submission_single_query'),
|
url(r'^single_submission$', submission.single_submission_query, name='submission_single_query'),
|
||||||
url(r'^submission_testcases$', submission.SubmissionTestCaseQuery.as_view(), name='submission_testcases_query'),
|
url(r'^submission_testcases$', submission.SubmissionTestCaseQuery.as_view(), name='submission_testcases_query'),
|
||||||
|
@ -376,16 +377,16 @@ urlpatterns = [
|
||||||
url(r'^custom_checker_sample/', about.custom_checker_sample, name='custom_checker_sample'),
|
url(r'^custom_checker_sample/', about.custom_checker_sample, name='custom_checker_sample'),
|
||||||
|
|
||||||
url(r'^chat/', include([
|
url(r'^chat/', include([
|
||||||
url(r'^(?P<room_id>\d*)$', login_required(ChatView.as_view()), name='chat'),
|
url(r'^(?P<room_id>\d*)$', login_required(chat.ChatView.as_view()), name='chat'),
|
||||||
url(r'^delete/$', delete_message, name='delete_chat_message'),
|
url(r'^delete/$', chat.delete_message, name='delete_chat_message'),
|
||||||
url(r'^post/$', post_message, name='post_chat_message'),
|
url(r'^post/$', chat.post_message, name='post_chat_message'),
|
||||||
url(r'^ajax$', chat_message_ajax, name='chat_message_ajax'),
|
url(r'^ajax$', chat.chat_message_ajax, name='chat_message_ajax'),
|
||||||
url(r'^online_status/ajax$', online_status_ajax, name='online_status_ajax'),
|
url(r'^online_status/ajax$', chat.online_status_ajax, name='online_status_ajax'),
|
||||||
url(r'^get_or_create_room$', get_or_create_room, name='get_or_create_room'),
|
url(r'^get_or_create_room$', chat.get_or_create_room, name='get_or_create_room'),
|
||||||
url(r'^update_last_seen$', update_last_seen, name='update_last_seen'),
|
url(r'^update_last_seen$', chat.update_last_seen, name='update_last_seen'),
|
||||||
url(r'^online_status/user/ajax$', user_online_status_ajax, name='user_online_status_ajax'),
|
url(r'^online_status/user/ajax$', chat.user_online_status_ajax, name='user_online_status_ajax'),
|
||||||
url(r'^toggle_ignore/(?P<user_id>\d+)$', toggle_ignore, name='toggle_ignore'),
|
url(r'^toggle_ignore/(?P<user_id>\d+)$', chat.toggle_ignore, name='toggle_ignore'),
|
||||||
url(r'^get_unread_boxes$', get_unread_boxes, name='get_unread_boxes'),
|
url(r'^get_unread_boxes$', chat.get_unread_boxes, name='get_unread_boxes'),
|
||||||
])),
|
])),
|
||||||
|
|
||||||
url(r'^notifications/',
|
url(r'^notifications/',
|
||||||
|
|
|
@ -57,7 +57,9 @@ class ContestMiddleware(object):
|
||||||
profile.update_contest()
|
profile.update_contest()
|
||||||
request.participation = profile.current_contest
|
request.participation = profile.current_contest
|
||||||
request.in_contest = request.participation is not None
|
request.in_contest = request.participation is not None
|
||||||
|
request.contest_mode = request.session.get('contest_mode', True)
|
||||||
else:
|
else:
|
||||||
request.in_contest = False
|
request.in_contest = False
|
||||||
request.participation = None
|
request.participation = None
|
||||||
|
request.in_contest_mode = request.in_contest and request.contest_mode
|
||||||
return self.get_response(request)
|
return self.get_response(request)
|
||||||
|
|
|
@ -286,7 +286,11 @@ def get_problem_case(problem, files):
|
||||||
s.decode('utf-8')
|
s.decode('utf-8')
|
||||||
break
|
break
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
s += f.read(1)
|
next_char = f.read(1)
|
||||||
|
if next_char:
|
||||||
|
s += next_char
|
||||||
|
else:
|
||||||
|
raise Exception('File %s is not able to decode in utf-8' % file)
|
||||||
qs = get_visible_content(s)
|
qs = get_visible_content(s)
|
||||||
cache.set(cache_key, qs, 86400)
|
cache.set(cache_key, qs, 86400)
|
||||||
result[file] = qs
|
result[file] = qs
|
||||||
|
|
|
@ -15,7 +15,7 @@ from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
|
||||||
from django.db import IntegrityError
|
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 import Case, Count, F, FloatField, IntegerField, Max, Min, Q, Sum, Value, When
|
||||||
from django.db.models.expressions import CombinedExpression
|
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.shortcuts import get_object_or_404, render
|
||||||
from django.template.defaultfilters import date as date_filter
|
from django.template.defaultfilters import date as date_filter
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
|
@ -46,7 +46,7 @@ from judge.widgets import HeavyPreviewPageDownWidget
|
||||||
__all__ = ['ContestList', 'ContestDetail', 'ContestRanking', 'ContestJoin', 'ContestLeave', 'ContestCalendar',
|
__all__ = ['ContestList', 'ContestDetail', 'ContestRanking', 'ContestJoin', 'ContestLeave', 'ContestCalendar',
|
||||||
'ContestClone', 'ContestStats', 'ContestMossView', 'ContestMossDelete', 'contest_ranking_ajax',
|
'ContestClone', 'ContestStats', 'ContestMossView', 'ContestMossDelete', 'contest_ranking_ajax',
|
||||||
'ContestParticipationList', 'ContestParticipationDisqualify', 'get_contest_ranking_list',
|
'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):
|
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)
|
_('You are not in contest "%s".') % contest.key, 404)
|
||||||
|
|
||||||
profile.remove_contest()
|
profile.remove_contest()
|
||||||
|
request.session['contest_mode'] = True # reset contest_mode
|
||||||
return HttpResponseRedirect(reverse('contest_view', args=(contest.key,)))
|
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']))
|
cla['order'] = self.object.get_label_for_problem(problems.index(cla['problem']))
|
||||||
|
|
||||||
return JsonResponse(queryset, safe=False, json_dumps_params={'ensure_ascii': False})
|
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()
|
|
@ -71,7 +71,8 @@ class ProblemMixin(object):
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
return super(ProblemMixin, self).get(request, *args, **kwargs)
|
return super(ProblemMixin, self).get(request, *args, **kwargs)
|
||||||
except Http404:
|
except Http404 as e:
|
||||||
|
print(e)
|
||||||
return self.no_such_problem()
|
return self.no_such_problem()
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,7 +91,8 @@ class SolvedProblemMixin(object):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def in_contest(self):
|
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
|
@cached_property
|
||||||
def contest(self):
|
def contest(self):
|
||||||
|
@ -120,10 +122,9 @@ class ProblemSolution(SolvedProblemMixin, ProblemMixin, TitleMixin, CommentedDet
|
||||||
solution = get_object_or_404(Solution, problem=self.object)
|
solution = get_object_or_404(Solution, problem=self.object)
|
||||||
|
|
||||||
if (not solution.is_public or solution.publish_on > timezone.now()) and \
|
if (not solution.is_public or solution.publish_on > timezone.now()) and \
|
||||||
not self.request.user.has_perm('judge.see_private_solution') or \
|
not self.request.user.has_perm('judge.see_private_solution'):
|
||||||
(self.request.user.is_authenticated and
|
|
||||||
self.request.profile.current_contest):
|
|
||||||
raise Http404()
|
raise Http404()
|
||||||
|
|
||||||
context['solution'] = solution
|
context['solution'] = solution
|
||||||
context['has_solved_problem'] = self.object.id in self.get_completed_problems()
|
context['has_solved_problem'] = self.object.id in self.get_completed_problems()
|
||||||
return context
|
return context
|
||||||
|
|
|
@ -249,7 +249,7 @@ def problem_init_view(request, problem):
|
||||||
raise Http404()
|
raise Http404()
|
||||||
|
|
||||||
return render(request, 'problem/yaml.html', {
|
return render(request, 'problem/yaml.html', {
|
||||||
'raw_source': data, 'highlighted_source': highlight_code(data, 'yaml'),
|
'raw_source': data, 'highlighted_source': highlight_code(data, 'yaml', linenos=False),
|
||||||
'title': _('Generated init.yml for %s') % problem.name,
|
'title': _('Generated init.yml for %s') % problem.name,
|
||||||
'content_title': mark_safe(escape(_('Generated init.yml for %s')) % (
|
'content_title': mark_safe(escape(_('Generated init.yml for %s')) % (
|
||||||
format_html('<a href="{1}">{0}</a>', problem.name,
|
format_html('<a href="{1}">{0}</a>', problem.name,
|
||||||
|
|
|
@ -262,7 +262,8 @@ class SubmissionsListBase(DiggPaginatorMixin, TitleMixin, ListView):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def in_contest(self):
|
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
|
@cached_property
|
||||||
def contest(self):
|
def contest(self):
|
||||||
|
|
|
@ -92,7 +92,8 @@ class UserPage(TitleMixin, UserMixin, DetailView):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def in_contest(self):
|
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):
|
def get_completed_problems(self):
|
||||||
if self.in_contest:
|
if self.in_contest:
|
||||||
|
@ -374,8 +375,8 @@ class FixedContestRanking(ContestRanking):
|
||||||
|
|
||||||
def users(request):
|
def users(request):
|
||||||
if request.user.is_authenticated:
|
if request.user.is_authenticated:
|
||||||
participation = request.profile.current_contest
|
if request.in_contest_mode:
|
||||||
if participation is not None:
|
participation = request.profile.current_contest
|
||||||
contest = participation.contest
|
contest = participation.contest
|
||||||
return FixedContestRanking.as_view(contest=contest)(request, contest=contest.key)
|
return FixedContestRanking.as_view(contest=contest)(request, contest=contest.key)
|
||||||
return user_list_view(request)
|
return user_list_view(request)
|
||||||
|
|
|
@ -2,7 +2,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: lqdoj2\n"
|
"Project-Id-Version: lqdoj2\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-12-29 13:13+0700\n"
|
"POT-Creation-Date: 2022-01-10 18:14+0700\n"
|
||||||
"PO-Revision-Date: 2021-07-20 03:44\n"
|
"PO-Revision-Date: 2021-07-20 03:44\n"
|
||||||
"Last-Translator: Icyene\n"
|
"Last-Translator: Icyene\n"
|
||||||
"Language-Team: Vietnamese\n"
|
"Language-Team: Vietnamese\n"
|
||||||
|
@ -108,7 +108,7 @@ msgstr ""
|
||||||
msgid "Login"
|
msgid "Login"
|
||||||
msgstr "Đăng nhập"
|
msgstr "Đăng nhập"
|
||||||
|
|
||||||
#: dmoj/urls.py:106 templates/base.html:207
|
#: dmoj/urls.py:106 templates/base.html:249
|
||||||
msgid "Home"
|
msgid "Home"
|
||||||
msgstr "Trang chủ"
|
msgstr "Trang chủ"
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ msgstr "Tính toán lại kết quả"
|
||||||
msgid "username"
|
msgid "username"
|
||||||
msgstr "tên đăng nhập"
|
msgstr "tên đăng nhập"
|
||||||
|
|
||||||
#: judge/admin/contest.py:320 templates/base.html:294
|
#: judge/admin/contest.py:320 templates/base.html:337
|
||||||
msgid "virtual"
|
msgid "virtual"
|
||||||
msgstr "ảo"
|
msgstr "ảo"
|
||||||
|
|
||||||
|
@ -318,7 +318,7 @@ msgstr "Email"
|
||||||
|
|
||||||
#: judge/admin/profile.py:96 judge/views/register.py:29
|
#: judge/admin/profile.py:96 judge/views/register.py:29
|
||||||
#: templates/registration/registration_form.html:173
|
#: templates/registration/registration_form.html:173
|
||||||
#: templates/user/edit-profile.html:114
|
#: templates/user/edit-profile.html:116
|
||||||
msgid "Timezone"
|
msgid "Timezone"
|
||||||
msgstr "Múi giờ"
|
msgstr "Múi giờ"
|
||||||
|
|
||||||
|
@ -2438,71 +2438,71 @@ msgstr "Nhập mật khẩu truy cập cho \"%s\""
|
||||||
msgid "You are not in contest \"%s\"."
|
msgid "You are not in contest \"%s\"."
|
||||||
msgstr "Bạn không ở trong kỳ thi \"%s\"."
|
msgstr "Bạn không ở trong kỳ thi \"%s\"."
|
||||||
|
|
||||||
#: judge/views/contests.py:447
|
#: judge/views/contests.py:448
|
||||||
msgid "ContestCalendar requires integer year and month"
|
msgid "ContestCalendar requires integer year and month"
|
||||||
msgstr "Lịch thi yêu cầu giá trị cho năm và tháng là số nguyên"
|
msgstr "Lịch thi yêu cầu giá trị cho năm và tháng là số nguyên"
|
||||||
|
|
||||||
#: judge/views/contests.py:487
|
#: judge/views/contests.py:488
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Contests in %(month)s"
|
msgid "Contests in %(month)s"
|
||||||
msgstr "Các kỳ thi trong %(month)s"
|
msgstr "Các kỳ thi trong %(month)s"
|
||||||
|
|
||||||
#: judge/views/contests.py:487
|
#: judge/views/contests.py:488
|
||||||
msgid "F Y"
|
msgid "F Y"
|
||||||
msgstr "F Y"
|
msgstr "F Y"
|
||||||
|
|
||||||
#: judge/views/contests.py:535
|
#: judge/views/contests.py:536
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%s Statistics"
|
msgid "%s Statistics"
|
||||||
msgstr "%s Thống kê"
|
msgstr "%s Thống kê"
|
||||||
|
|
||||||
#: judge/views/contests.py:730
|
#: judge/views/contests.py:731
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%s Rankings"
|
msgid "%s Rankings"
|
||||||
msgstr "%s Bảng điểm"
|
msgstr "%s Bảng điểm"
|
||||||
|
|
||||||
#: judge/views/contests.py:738
|
#: judge/views/contests.py:739
|
||||||
msgid "???"
|
msgid "???"
|
||||||
msgstr "???"
|
msgstr "???"
|
||||||
|
|
||||||
#: judge/views/contests.py:754
|
#: judge/views/contests.py:755
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Your participation in %s"
|
msgid "Your participation in %s"
|
||||||
msgstr "Lần tham gia trong %s"
|
msgstr "Lần tham gia trong %s"
|
||||||
|
|
||||||
#: judge/views/contests.py:755
|
#: judge/views/contests.py:756
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%s's participation in %s"
|
msgid "%s's participation in %s"
|
||||||
msgstr "Lần tham gia của %s trong %s"
|
msgstr "Lần tham gia của %s trong %s"
|
||||||
|
|
||||||
#: judge/views/contests.py:762
|
#: judge/views/contests.py:763
|
||||||
msgid "Live"
|
msgid "Live"
|
||||||
msgstr "Trực tiếp"
|
msgstr "Trực tiếp"
|
||||||
|
|
||||||
#: judge/views/contests.py:774 templates/contest/contest-tabs.html:13
|
#: judge/views/contests.py:775 templates/contest/contest-tabs.html:13
|
||||||
msgid "Participation"
|
msgid "Participation"
|
||||||
msgstr "Lần tham gia"
|
msgstr "Lần tham gia"
|
||||||
|
|
||||||
#: judge/views/contests.py:821
|
#: judge/views/contests.py:822
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%s MOSS Results"
|
msgid "%s MOSS Results"
|
||||||
msgstr "%s Kết quả MOSS"
|
msgstr "%s Kết quả MOSS"
|
||||||
|
|
||||||
#: judge/views/contests.py:848
|
#: judge/views/contests.py:849
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Running MOSS for %s..."
|
msgid "Running MOSS for %s..."
|
||||||
msgstr "Đang chạy MOSS cho %s..."
|
msgstr "Đang chạy MOSS cho %s..."
|
||||||
|
|
||||||
#: judge/views/contests.py:871
|
#: judge/views/contests.py:872
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Contest tag: %s"
|
msgid "Contest tag: %s"
|
||||||
msgstr "Nhãn kỳ thi: %s"
|
msgstr "Nhãn kỳ thi: %s"
|
||||||
|
|
||||||
#: judge/views/contests.py:881 judge/views/ticket.py:57
|
#: judge/views/contests.py:882 judge/views/ticket.py:57
|
||||||
msgid "Issue description"
|
msgid "Issue description"
|
||||||
msgstr "Mô tả vấn đề"
|
msgstr "Mô tả vấn đề"
|
||||||
|
|
||||||
#: judge/views/contests.py:924
|
#: judge/views/contests.py:925
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "New clarification for %s"
|
msgid "New clarification for %s"
|
||||||
msgstr "Thông báo mới cho %s"
|
msgstr "Thông báo mới cho %s"
|
||||||
|
@ -2656,56 +2656,56 @@ msgstr "Không có bài nào như vậy"
|
||||||
msgid "Could not find a problem with the code \"%s\"."
|
msgid "Could not find a problem with the code \"%s\"."
|
||||||
msgstr "Không tìm thấy bài tập với mã bài \"%s\"."
|
msgstr "Không tìm thấy bài tập với mã bài \"%s\"."
|
||||||
|
|
||||||
#: judge/views/problem.py:111
|
#: judge/views/problem.py:113
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Editorial for {0}"
|
msgid "Editorial for {0}"
|
||||||
msgstr "Hướng dẫn cho {0}"
|
msgstr "Hướng dẫn cho {0}"
|
||||||
|
|
||||||
#: judge/views/problem.py:114
|
#: judge/views/problem.py:116
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Editorial for <a href=\"{1}\">{0}</a>"
|
msgid "Editorial for <a href=\"{1}\">{0}</a>"
|
||||||
msgstr "Hướng dẫn cho <a href=\"{1}\">{0}</a>"
|
msgstr "Hướng dẫn cho <a href=\"{1}\">{0}</a>"
|
||||||
|
|
||||||
#: judge/views/problem.py:226
|
#: judge/views/problem.py:227
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Disscuss {0}"
|
msgid "Disscuss {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: judge/views/problem.py:229
|
#: judge/views/problem.py:230
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Discuss <a href=\"{1}\">{0}</a>"
|
msgid "Discuss <a href=\"{1}\">{0}</a>"
|
||||||
msgstr "Thảo luận <a href=\"{1}\">{0}</a>"
|
msgstr "Thảo luận <a href=\"{1}\">{0}</a>"
|
||||||
|
|
||||||
#: judge/views/problem.py:297 templates/contest/contest.html:79
|
#: judge/views/problem.py:298 templates/contest/contest.html:79
|
||||||
#: templates/user/user-about.html:28 templates/user/user-tabs.html:5
|
#: templates/user/user-about.html:28 templates/user/user-tabs.html:5
|
||||||
#: templates/user/users-table.html:29
|
#: templates/user/users-table.html:29
|
||||||
msgid "Problems"
|
msgid "Problems"
|
||||||
msgstr "Bài tập"
|
msgstr "Bài tập"
|
||||||
|
|
||||||
#: judge/views/problem.py:597
|
#: judge/views/problem.py:598
|
||||||
msgid "Banned from submitting"
|
msgid "Banned from submitting"
|
||||||
msgstr "Bị cấm nộp bài"
|
msgstr "Bị cấm nộp bài"
|
||||||
|
|
||||||
#: judge/views/problem.py:598
|
#: judge/views/problem.py:599
|
||||||
msgid ""
|
msgid ""
|
||||||
"You have been declared persona non grata for this problem. You are "
|
"You have been declared persona non grata for this problem. You are "
|
||||||
"permanently barred from submitting this problem."
|
"permanently barred from submitting this problem."
|
||||||
msgstr "Bạn đã bị cấm nộp bài này."
|
msgstr "Bạn đã bị cấm nộp bài này."
|
||||||
|
|
||||||
#: judge/views/problem.py:612
|
#: judge/views/problem.py:613
|
||||||
msgid "Too many submissions"
|
msgid "Too many submissions"
|
||||||
msgstr "Quá nhiều lần nộp"
|
msgstr "Quá nhiều lần nộp"
|
||||||
|
|
||||||
#: judge/views/problem.py:613
|
#: judge/views/problem.py:614
|
||||||
msgid "You have exceeded the submission limit for this problem."
|
msgid "You have exceeded the submission limit for this problem."
|
||||||
msgstr "Bạn đã vượt quá số lần nộp cho bài này."
|
msgstr "Bạn đã vượt quá số lần nộp cho bài này."
|
||||||
|
|
||||||
#: judge/views/problem.py:673 judge/views/problem.py:676
|
#: judge/views/problem.py:674 judge/views/problem.py:677
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Submit to %(problem)s"
|
msgid "Submit to %(problem)s"
|
||||||
msgstr "Nộp bài cho %(problem)s"
|
msgstr "Nộp bài cho %(problem)s"
|
||||||
|
|
||||||
#: judge/views/problem.py:691
|
#: judge/views/problem.py:692
|
||||||
msgid "Clone Problem"
|
msgid "Clone Problem"
|
||||||
msgstr "Nhân bản bài tập"
|
msgstr "Nhân bản bài tập"
|
||||||
|
|
||||||
|
@ -2803,7 +2803,7 @@ msgstr "Các bài nộp tốt nhất cho bài {0} trong <a href=\"{2}\">{1}</a>"
|
||||||
msgid "A username must contain letters, numbers, or underscores"
|
msgid "A username must contain letters, numbers, or underscores"
|
||||||
msgstr "Tên đăng nhập phải chứa ký tự, chữ số, hoặc dấu gạch dưới"
|
msgstr "Tên đăng nhập phải chứa ký tự, chữ số, hoặc dấu gạch dưới"
|
||||||
|
|
||||||
#: judge/views/register.py:31 templates/user/edit-profile.html:118
|
#: judge/views/register.py:31 templates/user/edit-profile.html:120
|
||||||
msgid "Preferred language"
|
msgid "Preferred language"
|
||||||
msgstr "Ngôn ngữ ưa thích"
|
msgstr "Ngôn ngữ ưa thích"
|
||||||
|
|
||||||
|
@ -2857,39 +2857,39 @@ msgstr "Bài nộp của %(user)s cho bài %(problem)s"
|
||||||
msgid "All submissions"
|
msgid "All submissions"
|
||||||
msgstr "Tất cả bài nộp"
|
msgstr "Tất cả bài nộp"
|
||||||
|
|
||||||
#: judge/views/submission.py:404
|
#: judge/views/submission.py:405
|
||||||
msgid "All my submissions"
|
msgid "All my submissions"
|
||||||
msgstr "Tất cả bài nộp của tôi"
|
msgstr "Tất cả bài nộp của tôi"
|
||||||
|
|
||||||
#: judge/views/submission.py:405
|
#: judge/views/submission.py:406
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "All submissions by %s"
|
msgid "All submissions by %s"
|
||||||
msgstr "Tất cả bài nộp của %s"
|
msgstr "Tất cả bài nộp của %s"
|
||||||
|
|
||||||
#: judge/views/submission.py:436
|
#: judge/views/submission.py:437
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "All submissions for %s"
|
msgid "All submissions for %s"
|
||||||
msgstr "Tất cả bài nộp cho %s"
|
msgstr "Tất cả bài nộp cho %s"
|
||||||
|
|
||||||
#: judge/views/submission.py:455
|
#: judge/views/submission.py:456
|
||||||
msgid "Must pass a problem"
|
msgid "Must pass a problem"
|
||||||
msgstr "Phải làm được một bài"
|
msgstr "Phải làm được một bài"
|
||||||
|
|
||||||
#: judge/views/submission.py:501
|
#: judge/views/submission.py:502
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "My submissions for %(problem)s"
|
msgid "My submissions for %(problem)s"
|
||||||
msgstr "Bài nộp của tôi cho %(problem)s"
|
msgstr "Bài nộp của tôi cho %(problem)s"
|
||||||
|
|
||||||
#: judge/views/submission.py:502
|
#: judge/views/submission.py:503
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(user)s's submissions for %(problem)s"
|
msgid "%(user)s's submissions for %(problem)s"
|
||||||
msgstr "Các bài nộp của %(user)s cho %(problem)s"
|
msgstr "Các bài nộp của %(user)s cho %(problem)s"
|
||||||
|
|
||||||
#: judge/views/submission.py:603
|
#: judge/views/submission.py:604
|
||||||
msgid "Must pass a contest"
|
msgid "Must pass a contest"
|
||||||
msgstr "Phải qua một kỳ thi"
|
msgstr "Phải qua một kỳ thi"
|
||||||
|
|
||||||
#: judge/views/submission.py:622
|
#: judge/views/submission.py:623
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"<a href=\"{1}\">{0}</a>'s submissions for <a href=\"{3}\">{2}</a> in <a href="
|
"<a href=\"{1}\">{0}</a>'s submissions for <a href=\"{3}\">{2}</a> in <a href="
|
||||||
|
@ -2898,7 +2898,7 @@ msgstr ""
|
||||||
"Các bài nộp của <a href=\"{1}\">{0}</a> cho <a href=\"{3}\">{2}</a> trong <a "
|
"Các bài nộp của <a href=\"{1}\">{0}</a> cho <a href=\"{3}\">{2}</a> trong <a "
|
||||||
"href=\"{5}\">{4}</a>"
|
"href=\"{5}\">{4}</a>"
|
||||||
|
|
||||||
#: judge/views/submission.py:629
|
#: judge/views/submission.py:630
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"<a href=\"{1}\">{0}</a>'s submissions for problem {2} in <a href=\"{4}\">{3}"
|
"<a href=\"{1}\">{0}</a>'s submissions for problem {2} in <a href=\"{4}\">{3}"
|
||||||
|
@ -2979,29 +2979,29 @@ msgstr "Tài khoản của tôi"
|
||||||
msgid "User %s"
|
msgid "User %s"
|
||||||
msgstr "Thành viên %s"
|
msgstr "Thành viên %s"
|
||||||
|
|
||||||
#: judge/views/user.py:148
|
#: judge/views/user.py:149
|
||||||
msgid "M j, Y"
|
msgid "M j, Y"
|
||||||
msgstr "j M, Y"
|
msgstr "j M, Y"
|
||||||
|
|
||||||
#: judge/views/user.py:171
|
#: judge/views/user.py:172
|
||||||
msgid "M j, Y, G:i"
|
msgid "M j, Y, G:i"
|
||||||
msgstr "j M, Y, G:i"
|
msgstr "j M, Y, G:i"
|
||||||
|
|
||||||
#: judge/views/user.py:290
|
#: judge/views/user.py:291
|
||||||
msgid "Updated on site"
|
msgid "Updated on site"
|
||||||
msgstr "Được cập nhật trên web"
|
msgstr "Được cập nhật trên web"
|
||||||
|
|
||||||
#: judge/views/user.py:324 templates/admin/auth/user/change_form.html:14
|
#: judge/views/user.py:326 templates/admin/auth/user/change_form.html:14
|
||||||
#: templates/admin/auth/user/change_form.html:17 templates/base.html:255
|
#: templates/admin/auth/user/change_form.html:17 templates/base.html:297
|
||||||
#: templates/user/user-tabs.html:10
|
#: templates/user/user-tabs.html:10
|
||||||
msgid "Edit profile"
|
msgid "Edit profile"
|
||||||
msgstr "Chỉnh sửa thông tin"
|
msgstr "Chỉnh sửa thông tin"
|
||||||
|
|
||||||
#: judge/views/user.py:333 templates/user/user-list-tabs.html:4
|
#: judge/views/user.py:335 templates/user/user-list-tabs.html:4
|
||||||
msgid "Leaderboard"
|
msgid "Leaderboard"
|
||||||
msgstr "Bảng xếp hạng"
|
msgstr "Bảng xếp hạng"
|
||||||
|
|
||||||
#: judge/views/user.py:408
|
#: judge/views/user.py:410
|
||||||
msgid "Import Users"
|
msgid "Import Users"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -3197,20 +3197,20 @@ msgstr "Chỉnh sửa thông tin"
|
||||||
msgid "Rejudge"
|
msgid "Rejudge"
|
||||||
msgstr "Chấm lại"
|
msgstr "Chấm lại"
|
||||||
|
|
||||||
#: templates/base.html:224 templates/chat/chat.html:566
|
#: templates/base.html:266 templates/chat/chat.html:566
|
||||||
msgid "Chat"
|
msgid "Chat"
|
||||||
msgstr "Chat"
|
msgstr "Chat"
|
||||||
|
|
||||||
#: templates/base.html:230
|
#: templates/base.html:272
|
||||||
msgid "Notification"
|
msgid "Notification"
|
||||||
msgstr "Thông báo"
|
msgstr "Thông báo"
|
||||||
|
|
||||||
#: templates/base.html:247
|
#: templates/base.html:289
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Hello, <b>%(username)s</b>."
|
msgid "Hello, <b>%(username)s</b>."
|
||||||
msgstr "Xin chào, <b>%(username)s</b>."
|
msgstr "Xin chào, <b>%(username)s</b>."
|
||||||
|
|
||||||
#: templates/base.html:253 templates/chat/chat.html:20
|
#: templates/base.html:295 templates/chat/chat.html:20
|
||||||
#: templates/comments/list.html:89 templates/contest/contest-list-tabs.html:24
|
#: templates/comments/list.html:89 templates/contest/contest-list-tabs.html:24
|
||||||
#: templates/contest/ranking-table.html:53
|
#: templates/contest/ranking-table.html:53
|
||||||
#: templates/problem/problem-list-tabs.html:6
|
#: templates/problem/problem-list-tabs.html:6
|
||||||
|
@ -3219,28 +3219,36 @@ msgstr "Xin chào, <b>%(username)s</b>."
|
||||||
msgid "Admin"
|
msgid "Admin"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/base.html:262
|
#: templates/base.html:304
|
||||||
msgid "Log out"
|
msgid "Log out"
|
||||||
msgstr "Đăng xuất"
|
msgstr "Đăng xuất"
|
||||||
|
|
||||||
#: templates/base.html:271
|
#: templates/base.html:313
|
||||||
#: templates/registration/password_reset_complete.html:4
|
#: templates/registration/password_reset_complete.html:4
|
||||||
msgid "Log in"
|
msgid "Log in"
|
||||||
msgstr "Đăng nhập"
|
msgstr "Đăng nhập"
|
||||||
|
|
||||||
#: templates/base.html:272 templates/registration/registration_form.html:177
|
#: templates/base.html:314 templates/registration/registration_form.html:177
|
||||||
msgid "or"
|
msgid "or"
|
||||||
msgstr "hoặc"
|
msgstr "hoặc"
|
||||||
|
|
||||||
#: templates/base.html:273
|
#: templates/base.html:315
|
||||||
msgid "Sign up"
|
msgid "Sign up"
|
||||||
msgstr "Đăng ký"
|
msgstr "Đăng ký"
|
||||||
|
|
||||||
#: templates/base.html:288
|
#: templates/base.html:331
|
||||||
msgid "spectating"
|
msgid "spectating"
|
||||||
msgstr "đang theo dõi"
|
msgstr "đang theo dõi"
|
||||||
|
|
||||||
#: templates/base.html:301
|
#: templates/base.html:343
|
||||||
|
msgid "Compete"
|
||||||
|
msgstr "Thi"
|
||||||
|
|
||||||
|
#: templates/base.html:345
|
||||||
|
msgid "General"
|
||||||
|
msgstr "Chung"
|
||||||
|
|
||||||
|
#: templates/base.html:352
|
||||||
msgid "This site works best with JavaScript enabled."
|
msgid "This site works best with JavaScript enabled."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -4638,12 +4646,12 @@ msgid "Default language"
|
||||||
msgstr "Ngôn ngữ ưa thích"
|
msgstr "Ngôn ngữ ưa thích"
|
||||||
|
|
||||||
#: templates/registration/registration_form.html:186
|
#: templates/registration/registration_form.html:186
|
||||||
#: templates/user/edit-profile.html:181
|
#: templates/user/edit-profile.html:183
|
||||||
msgid "Affiliated organizations"
|
msgid "Affiliated organizations"
|
||||||
msgstr "Tổ chức bạn muốn tham gia"
|
msgstr "Tổ chức bạn muốn tham gia"
|
||||||
|
|
||||||
#: templates/registration/registration_form.html:195
|
#: templates/registration/registration_form.html:195
|
||||||
#: templates/user/edit-profile.html:136
|
#: templates/user/edit-profile.html:138
|
||||||
msgid "Notify me about upcoming contests"
|
msgid "Notify me about upcoming contests"
|
||||||
msgstr "Nhận thông báo về các kỳ thi tương lai"
|
msgstr "Nhận thông báo về các kỳ thi tương lai"
|
||||||
|
|
||||||
|
@ -4986,55 +4994,55 @@ msgstr "Không có gì."
|
||||||
msgid "Rank"
|
msgid "Rank"
|
||||||
msgstr "Rank"
|
msgstr "Rank"
|
||||||
|
|
||||||
#: templates/user/edit-profile.html:98
|
#: templates/user/edit-profile.html:99
|
||||||
msgid "Name and School"
|
msgid "Name and School"
|
||||||
msgstr "Họ tên và Trường"
|
msgstr "Họ tên và Trường"
|
||||||
|
|
||||||
#: templates/user/edit-profile.html:100
|
#: templates/user/edit-profile.html:101
|
||||||
msgid "Enter this form"
|
msgid "Enter this form"
|
||||||
msgstr "Điền vào link này"
|
msgstr "Điền vào link này"
|
||||||
|
|
||||||
#: templates/user/edit-profile.html:101
|
#: templates/user/edit-profile.html:102
|
||||||
msgid "It takes some time for admin to approve"
|
msgid "It takes some time for admin to approve"
|
||||||
msgstr "Ban quản trị sẽ phê duyệt"
|
msgstr "Ban quản trị sẽ phê duyệt"
|
||||||
|
|
||||||
#: templates/user/edit-profile.html:105
|
#: templates/user/edit-profile.html:107
|
||||||
msgid "Self-description"
|
msgid "Self-description"
|
||||||
msgstr "Tự giới thiệu"
|
msgstr "Tự giới thiệu"
|
||||||
|
|
||||||
#: templates/user/edit-profile.html:113
|
#: templates/user/edit-profile.html:115
|
||||||
msgid "Select your closest major city"
|
msgid "Select your closest major city"
|
||||||
msgstr "Chọn thành phố gần nhất"
|
msgstr "Chọn thành phố gần nhất"
|
||||||
|
|
||||||
#: templates/user/edit-profile.html:122
|
#: templates/user/edit-profile.html:124
|
||||||
msgid "Editor theme"
|
msgid "Editor theme"
|
||||||
msgstr "Giao diện cho code editor"
|
msgstr "Giao diện cho code editor"
|
||||||
|
|
||||||
#: templates/user/edit-profile.html:127
|
#: templates/user/edit-profile.html:129
|
||||||
msgid "Math engine"
|
msgid "Math engine"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/user/edit-profile.html:151 templates/user/edit-profile.html:152
|
#: templates/user/edit-profile.html:153 templates/user/edit-profile.html:154
|
||||||
msgid "Change your avatar"
|
msgid "Change your avatar"
|
||||||
msgstr "Đổi ảnh đại diện"
|
msgstr "Đổi ảnh đại diện"
|
||||||
|
|
||||||
#: templates/user/edit-profile.html:158
|
#: templates/user/edit-profile.html:160
|
||||||
msgid "Change your password"
|
msgid "Change your password"
|
||||||
msgstr "Đổi mật khẩu"
|
msgstr "Đổi mật khẩu"
|
||||||
|
|
||||||
#: templates/user/edit-profile.html:165
|
#: templates/user/edit-profile.html:167
|
||||||
msgid "Two Factor Authentication is enabled."
|
msgid "Two Factor Authentication is enabled."
|
||||||
msgstr "Two Factor Authentication đã được kích hoạt."
|
msgstr "Two Factor Authentication đã được kích hoạt."
|
||||||
|
|
||||||
#: templates/user/edit-profile.html:172
|
#: templates/user/edit-profile.html:174
|
||||||
msgid "Two Factor Authentication is disabled."
|
msgid "Two Factor Authentication is disabled."
|
||||||
msgstr "Two Factor Authentication đã được hủy kích hoạt."
|
msgstr "Two Factor Authentication đã được hủy kích hoạt."
|
||||||
|
|
||||||
#: templates/user/edit-profile.html:189
|
#: templates/user/edit-profile.html:191
|
||||||
msgid "User-script"
|
msgid "User-script"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/user/edit-profile.html:193
|
#: templates/user/edit-profile.html:195
|
||||||
msgid "Update profile"
|
msgid "Update profile"
|
||||||
msgstr "Cập nhật thông tin"
|
msgstr "Cập nhật thông tin"
|
||||||
|
|
||||||
|
|
|
@ -485,12 +485,8 @@ noscript #noscript {
|
||||||
#contest-info {
|
#contest-info {
|
||||||
font-size: 1.25em;
|
font-size: 1.25em;
|
||||||
border: 5px solid $highlight_blue;
|
border: 5px solid $highlight_blue;
|
||||||
border-left: 5px dotted white;
|
|
||||||
border-radius: 0 $widget_border_radius $widget_border_radius 0;
|
border-radius: 0 $widget_border_radius $widget_border_radius 0;
|
||||||
background: rgba(0, 0, 0, 0.77);
|
|
||||||
z-index: 100000;
|
z-index: 100000;
|
||||||
padding: 10px 12px;
|
|
||||||
color: white;
|
|
||||||
cursor: move;
|
cursor: move;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 20px;
|
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 {
|
#contest-time-remaining {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding-top: 0.1em;
|
padding-top: 0.1em;
|
||||||
padding-bottom: 0.1em;
|
padding-bottom: 0.1em;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
.chatbtn_remove_mess {
|
.chatbtn_remove_mess {
|
||||||
float: right;
|
float: right;
|
||||||
|
@ -60,14 +61,13 @@
|
||||||
|
|
||||||
#chat-input {
|
#chat-input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0.4em;
|
padding: 0.4em 4em 0.6em 1.2em;
|
||||||
padding-bottom: 0.6em;
|
|
||||||
border: 0;
|
border: 0;
|
||||||
color: black;
|
color: black;
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
font-size: 14px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
#chat-online-content {
|
#chat-online-content {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -172,6 +172,20 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
}
|
}
|
||||||
|
.message-text {
|
||||||
|
padding: 0.4em 0.6em 0.5em;
|
||||||
|
border-radius: 15px;
|
||||||
|
max-width: 70%;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
.message-text-other {
|
||||||
|
background: #eeeeee;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
.message-text-myself {
|
||||||
|
background: rgb(0, 132, 255);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 799px) {
|
@media (max-width: 799px) {
|
||||||
#chat-area {
|
#chat-area {
|
||||||
|
|
|
@ -94,7 +94,9 @@
|
||||||
{% block js_media %}{% endblock %}
|
{% block js_media %}{% endblock %}
|
||||||
{% if request.in_contest %}
|
{% if request.in_contest %}
|
||||||
<script>$(function () {
|
<script>$(function () {
|
||||||
count_down($("#contest-time-remaining"));
|
if ($("#contest-time-remaining").length) {
|
||||||
|
count_down($("#contest-time-remaining"));
|
||||||
|
}
|
||||||
|
|
||||||
var selected = null,
|
var selected = null,
|
||||||
x_pos = 0, y_pos = 0,
|
x_pos = 0, y_pos = 0,
|
||||||
|
@ -117,6 +119,12 @@
|
||||||
|
|
||||||
$("#contest-info").show();
|
$("#contest-info").show();
|
||||||
|
|
||||||
|
$("#contest-info-toggle").on('click', function() {
|
||||||
|
$.post("{{url('contest_mode_ajax')}}", function() {
|
||||||
|
window.location.reload();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
$(document).mousemove(function (e) {
|
$(document).mousemove(function (e) {
|
||||||
x_pos = e.screenX;
|
x_pos = e.screenX;
|
||||||
y_pos = e.screenY;
|
y_pos = e.screenY;
|
||||||
|
@ -190,6 +198,42 @@
|
||||||
</style>
|
</style>
|
||||||
</noscript>
|
</noscript>
|
||||||
<style>
|
<style>
|
||||||
|
#contest-info {
|
||||||
|
font-size: 1.25em;
|
||||||
|
border: 5px solid $highlight_blue;
|
||||||
|
border-radius: 0 $widget_border_radius $widget_border_radius 0;
|
||||||
|
z-index: 100000;
|
||||||
|
cursor: move;
|
||||||
|
position: fixed;
|
||||||
|
left: 20px;
|
||||||
|
top: 90%;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#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);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -284,18 +328,27 @@
|
||||||
</nav>
|
</nav>
|
||||||
{% if request.in_contest %}
|
{% if request.in_contest %}
|
||||||
<div id="contest-info">
|
<div id="contest-info">
|
||||||
<a href="{{ url('contest_view', request.participation.contest.key) }}" style="vertical-align: middle">
|
<div id="contest-info-main">
|
||||||
{{ request.participation.contest.name }} -
|
<a href="{{ url('contest_view', request.participation.contest.key) }}" style="vertical-align: middle; display: inline">
|
||||||
{% if request.participation.spectate %}
|
{{ request.participation.contest.name }} -
|
||||||
{{ _('spectating') }}
|
{% if request.participation.spectate %}
|
||||||
{% elif request.participation.end_time %}
|
{{ _('spectating') }}
|
||||||
<div id="contest-time-remaining" data-secs="{{request.participation.end_time}}">
|
{% elif request.participation.end_time %}
|
||||||
{{ request.participation.time_remaining|timedelta("localized") }}
|
<div id="contest-time-remaining" data-secs="{{request.participation.end_time}}">
|
||||||
</div>
|
{{ request.participation.time_remaining|timedelta("localized") }}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ _('virtual') }}
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div id="contest-info-toggle" class="{{'contest-info-toggle-mode-on' if request.contest_mode else 'contest-info-toggle-mode-off'}}">
|
||||||
|
{% if request.contest_mode %}
|
||||||
|
<i class="fa fa-toggle-on" style="color: white"></i> {{_('Compete')}}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ _('virtual') }}
|
<i class="fa fa-toggle-off" style="color: white"></i> {{_('General')}}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</a>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div id="page-container">
|
<div id="page-container">
|
||||||
|
|
|
@ -110,7 +110,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="blog-sidebar">
|
<div class="blog-sidebar">
|
||||||
{% if request.in_contest and request.participation.contest.use_clarifications %}
|
{% if request.in_contest_mode and request.participation.contest.use_clarifications %}
|
||||||
<div class="blog-sidebox sidebox">
|
<div class="blog-sidebox sidebox">
|
||||||
<h3>{{ _('Clarifications') }}
|
<h3>{{ _('Clarifications') }}
|
||||||
<i class="fa fa-question-circle"></i>
|
<i class="fa fa-question-circle"></i>
|
||||||
|
|
|
@ -206,6 +206,7 @@ let META_HEADER = [
|
||||||
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
|
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
|
||||||
register_time($('.time-with-rel'));
|
register_time($('.time-with-rel'));
|
||||||
remove_unread_current_user();
|
remove_unread_current_user();
|
||||||
|
merge_authors();
|
||||||
},
|
},
|
||||||
error: function (data) {
|
error: function (data) {
|
||||||
console.log('Fail to check message');
|
console.log('Fail to check message');
|
||||||
|
@ -230,6 +231,12 @@ let META_HEADER = [
|
||||||
var time = moment($(this).find(".time-with-rel").attr('data-iso'));
|
var time = moment($(this).find(".time-with-rel").attr('data-iso'));
|
||||||
var $content = $(this).children('.content-message');
|
var $content = $(this).children('.content-message');
|
||||||
|
|
||||||
|
if (username == window.user.name) {
|
||||||
|
$(this).find('.message-text').each(function() {
|
||||||
|
$(this).removeClass('message-text-other').addClass('message-text-myself');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (username == last.username && time.diff(last.time, 'minutes') <= time_limit) {
|
if (username == last.username && time.diff(last.time, 'minutes') <= time_limit) {
|
||||||
last.$content.append($body);
|
last.$content.append($body);
|
||||||
$(this).parent().remove();
|
$(this).parent().remove();
|
||||||
|
|
|
@ -92,10 +92,8 @@
|
||||||
}
|
}
|
||||||
.body-block {
|
.body-block {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding-left: 0.2em;
|
padding: 0.05em 0.6em;
|
||||||
}
|
width: 100%;
|
||||||
.body-block:hover {
|
|
||||||
background: #eee;
|
|
||||||
}
|
}
|
||||||
.active-span {
|
.active-span {
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
|
|
|
@ -20,7 +20,9 @@
|
||||||
{{_('Delete')}}
|
{{_('Delete')}}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{message.body | markdown('comment', MATH_ENGINE)|reference|str|safe }}
|
<div class="message-text message-text-other">
|
||||||
|
{{message.body | markdown('comment', MATH_ENGINE)|reference|str|safe }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -319,6 +319,31 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function get_initial_rank() {
|
||||||
|
var ranks = $('.rank-td').map(function() {return this.innerHTML}).get();
|
||||||
|
var usernames = $('.user-name .rating a').map(function() {return this.text}).get();
|
||||||
|
window.user_rank = new Map();
|
||||||
|
for (var i = 0; i < ranks.length; i++) {
|
||||||
|
window.user_rank[usernames[i]] = ranks[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_initial_friend_rank() {
|
||||||
|
var usernames = $('.user-name .rating a').map(function() {return this.text}).get();
|
||||||
|
|
||||||
|
var is_virtual = [];
|
||||||
|
$('.user-name').each(function() {
|
||||||
|
if($(this).children('sup').length) {
|
||||||
|
is_virtual.push(1);
|
||||||
|
}
|
||||||
|
else is_virtual.push(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.rank-td').each(function(i) {
|
||||||
|
if (!is_virtual[i]) this.innerHTML += ' (' + window.user_rank[usernames[i]] + ')';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function update_ranking() {
|
function update_ranking() {
|
||||||
var friend = $('#show-friends-checkbox').is(':checked');
|
var friend = $('#show-friends-checkbox').is(':checked');
|
||||||
var virtual = $('#show-virtual-checkbox').is(':checked');
|
var virtual = $('#show-virtual-checkbox').is(':checked');
|
||||||
|
@ -328,8 +353,13 @@
|
||||||
success: function(HTML) {
|
success: function(HTML) {
|
||||||
$('#users-table').html(HTML);
|
$('#users-table').html(HTML);
|
||||||
highlightFirstSolve();
|
highlightFirstSolve();
|
||||||
renew_filter();
|
|
||||||
$('#loading-gif').hide();
|
$('#loading-gif').hide();
|
||||||
|
if (!virtual && !friend) {
|
||||||
|
get_initial_rank();
|
||||||
|
}
|
||||||
|
if (friend) {
|
||||||
|
add_initial_friend_rank();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
fail: function() {
|
fail: function() {
|
||||||
console.log('Fail to update ranking');
|
console.log('Fail to update ranking');
|
||||||
|
@ -394,6 +424,7 @@
|
||||||
|
|
||||||
highlightFirstSolve();
|
highlightFirstSolve();
|
||||||
renew_filter();
|
renew_filter();
|
||||||
|
get_initial_rank();
|
||||||
{% if participation_tab %}
|
{% if participation_tab %}
|
||||||
$('#show-virtual-checkbox').hide();
|
$('#show-virtual-checkbox').hide();
|
||||||
$('#show-virtual-label').hide();
|
$('#show-virtual-label').hide();
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</noscript>
|
</noscript>
|
||||||
{% if not request.in_contest %}
|
{% if not request.in_contest_mode %}
|
||||||
<style>
|
<style>
|
||||||
#search-org {
|
#search-org {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -131,7 +131,7 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endcompress %}
|
{% endcompress %}
|
||||||
{% if request.in_contest %}
|
{% if request.in_contest_mode %}
|
||||||
{% compress js %}
|
{% compress js %}
|
||||||
<script src="{{ static('libs/tablesorter.js') }}" type="text/javascript"></script>
|
<script src="{{ static('libs/tablesorter.js') }}" type="text/javascript"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
@ -184,7 +184,7 @@
|
||||||
|
|
||||||
<div id="common-content">
|
<div id="common-content">
|
||||||
{% block before_table %}{% endblock %}
|
{% block before_table %}{% endblock %}
|
||||||
{% if not request.in_contest %}
|
{% if not request.in_contest_mode %}
|
||||||
<div id="content-right" class="problems">
|
<div id="content-right" class="problems">
|
||||||
<div class="info-float">
|
<div class="info-float">
|
||||||
{% include "problem/search-form.html" %}
|
{% include "problem/search-form.html" %}
|
||||||
|
@ -207,7 +207,7 @@
|
||||||
<table id="problem-table" class="table striped">
|
<table id="problem-table" class="table striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
{% if request.in_contest %}
|
{% if request.in_contest_mode %}
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
<th class="solved"><i class="fa fa-check"></i></th>
|
<th class="solved"><i class="fa fa-check"></i></th>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -268,7 +268,7 @@
|
||||||
{% if problem.id in completed_problem_ids %}
|
{% if problem.id in completed_problem_ids %}
|
||||||
<td solved="1">
|
<td solved="1">
|
||||||
<a href="{{ url('user_submissions', problem.code, request.user.username) }}">
|
<a href="{{ url('user_submissions', problem.code, request.user.username) }}">
|
||||||
{% if problem.is_public or request.in_contest %}
|
{% if problem.is_public or request.in_contest_mode %}
|
||||||
<i class="solved-problem-color fa fa-check-circle"></i>
|
<i class="solved-problem-color fa fa-check-circle"></i>
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="solved-problem-color fa fa-lock"></i>
|
<i class="solved-problem-color fa fa-lock"></i>
|
||||||
|
@ -278,7 +278,7 @@
|
||||||
{% elif problem.id in attempted_problems %}
|
{% elif problem.id in attempted_problems %}
|
||||||
<td solved="0">
|
<td solved="0">
|
||||||
<a href="{{ url('user_submissions', problem.code, request.user.username) }}">
|
<a href="{{ url('user_submissions', problem.code, request.user.username) }}">
|
||||||
{% if problem.is_public or request.in_contest %}
|
{% if problem.is_public or request.in_contest_mode %}
|
||||||
<i class="attempted-problem-color fa fa-minus-circle"></i>
|
<i class="attempted-problem-color fa fa-minus-circle"></i>
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="attempted-problem-color fa fa-lock"></i>
|
<i class="attempted-problem-color fa fa-lock"></i>
|
||||||
|
@ -287,7 +287,7 @@
|
||||||
</td>
|
</td>
|
||||||
{% else %}
|
{% else %}
|
||||||
<td solved="-1">
|
<td solved="-1">
|
||||||
{% if problem.is_public or request.in_contest %}
|
{% if problem.is_public or request.in_contest_mode %}
|
||||||
<i class="unsolved-problem-color fa fa-minus-circle"></i>
|
<i class="unsolved-problem-color fa fa-minus-circle"></i>
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="unsolved-problem-color fa fa-lock"></i>
|
<i class="unsolved-problem-color fa fa-lock"></i>
|
||||||
|
@ -312,12 +312,12 @@
|
||||||
</td>
|
</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<td class="p">{{ problem.points|floatformat }}{% if problem.partial %}p{% endif %}</td>
|
<td class="p">{{ problem.points|floatformat }}{% if problem.partial %}p{% endif %}</td>
|
||||||
{% if not request.in_contest %}
|
{% if not request.in_contest_mode %}
|
||||||
<td class="ac-rate">{{ problem.ac_rate|floatformat(1) }}%</td>
|
<td class="ac-rate">{{ problem.ac_rate|floatformat(1) }}%</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<td class="users">
|
<td class="users">
|
||||||
<a href="{{ url('ranked_submissions', problem.code) }}">
|
<a href="{{ url('ranked_submissions', problem.code) }}">
|
||||||
{% if not request.in_contest or not hide_contest_scoreboard %}
|
{% if not request.in_contest_mode or not hide_contest_scoreboard %}
|
||||||
{{ problem.user_count }}
|
{{ problem.user_count }}
|
||||||
{% else %}
|
{% else %}
|
||||||
???
|
???
|
||||||
|
@ -335,7 +335,7 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% if request.in_contest and request.participation.contest.use_clarifications %}
|
{% if request.in_contest_mode and request.participation.contest.use_clarifications %}
|
||||||
<br><br>
|
<br><br>
|
||||||
{% if can_edit_contest %}
|
{% if can_edit_contest %}
|
||||||
<div style="float: right; font-size: 1.2em">
|
<div style="float: right; font-size: 1.2em">
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content_js_media %}
|
{% block content_js_media %}
|
||||||
{% if request.in_contest %}
|
{% if request.in_contest_mode %}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
window.register_contest_notification("{{url('contest_clarification_ajax', request.participation.contest.key)}}");
|
window.register_contest_notification("{{url('contest_clarification_ajax', request.participation.contest.key)}}");
|
||||||
</script>
|
</script>
|
||||||
|
@ -88,7 +88,7 @@
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
{% if problem.id in completed_problem_ids %}
|
{% if problem.id in completed_problem_ids %}
|
||||||
<a href="{{ url('user_submissions', problem.code, request.user.username) }}">
|
<a href="{{ url('user_submissions', problem.code, request.user.username) }}">
|
||||||
{% if problem.is_public or request.in_contest %}
|
{% if problem.is_public or request.in_contest_mode %}
|
||||||
<i class="solved-problem-color title-state fa fa-check-circle"></i>
|
<i class="solved-problem-color title-state fa fa-check-circle"></i>
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="solved-problem-color title-state fa fa-lock"></i>
|
<i class="solved-problem-color title-state fa fa-lock"></i>
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
</a>
|
</a>
|
||||||
{% elif problem.id in attempted_problems %}
|
{% elif problem.id in attempted_problems %}
|
||||||
<a href="{{ url('user_submissions', problem.code, request.user.username) }}">
|
<a href="{{ url('user_submissions', problem.code, request.user.username) }}">
|
||||||
{% if problem.is_public or request.in_contest %}
|
{% if problem.is_public or request.in_contest_mode %}
|
||||||
<i class="attempted-problem-color title-state fa fa-minus-circle"></i>
|
<i class="attempted-problem-color title-state fa fa-minus-circle"></i>
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="attempted-problem-color title-state fa fa-lock"></i>
|
<i class="attempted-problem-color title-state fa fa-lock"></i>
|
||||||
|
@ -133,7 +133,7 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block info_float %}
|
{% block info_float %}
|
||||||
{% if request.user.is_authenticated and request.in_contest and submission_limit %}
|
{% if request.user.is_authenticated and request.in_contest_mode and submission_limit %}
|
||||||
{% if submissions_left > 0 %}
|
{% if submissions_left > 0 %}
|
||||||
<a href="{{ url('problem_submit', problem.code) }}" class="unselectable button full">
|
<a href="{{ url('problem_submit', problem.code) }}" class="unselectable button full">
|
||||||
{{ _('Submit solution') }}
|
{{ _('Submit solution') }}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% if request.in_contest and request.participation.contest.logo_override_image %}
|
{% if request.in_contest_mode and request.participation.contest.logo_override_image %}
|
||||||
<img src="{{ request.participation.contest.logo_override_image|camo }}" alt="{{ SITE_NAME }}" height="44" style="border: none">
|
<img src="{{ request.participation.contest.logo_override_image|camo }}" alt="{{ SITE_NAME }}" height="44" style="border: none">
|
||||||
{% elif logo_override_image is defined and logo_override_image %}
|
{% elif logo_override_image is defined and logo_override_image %}
|
||||||
<img src="{{ logo_override_image|camo }}" alt="{{ SITE_NAME }}" height="44" style="border: none">
|
<img src="{{ logo_override_image|camo }}" alt="{{ SITE_NAME }}" height="44" style="border: none">
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
{% block js_media %}
|
{% block js_media %}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
{% if dynamic_update and last_msg %}
|
{% if dynamic_update and last_msg %}
|
||||||
{% if request.in_contest %}
|
{% if request.in_contest_mode %}
|
||||||
window.current_contest = '{{request.participation.contest.key}}';
|
window.current_contest = '{{request.participation.contest.key}}';
|
||||||
{% else %}
|
{% else %}
|
||||||
window.current_contest = null;
|
window.current_contest = null;
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
<div>
|
<div>
|
||||||
{{ link_user(submission.user) }}
|
{{ link_user(submission.user) }}
|
||||||
<span class="time">{{ relative_time(submission.date) }}</span>
|
<span class="time">{{ relative_time(submission.date) }}</span>
|
||||||
{% if not request.in_contest and submission.contest_object_id %}
|
{% if not request.in_contest_mode and submission.contest_object_id %}
|
||||||
<a href="{{ url('contest_view', submission.contest_object.key) }}"
|
<a href="{{ url('contest_view', submission.contest_object.key) }}"
|
||||||
class="submission-contest">
|
class="submission-contest">
|
||||||
<i title="{{ submission.contest_object.name }}" class="fa fa-dot-circle-o"></i>
|
<i title="{{ submission.contest_object.name }}" class="fa fa-dot-circle-o"></i>
|
||||||
|
|
|
@ -32,10 +32,10 @@
|
||||||
<tr id="overall-row" class="case-row overall-result-{{submission.result}}">
|
<tr id="overall-row" class="case-row overall-result-{{submission.result}}">
|
||||||
|
|
||||||
<td><span class="col-title">{{_('Overall: ')}}</span>
|
<td><span class="col-title">{{_('Overall: ')}}</span>
|
||||||
{% if request.in_contest and submission.contest_or_none %}
|
{% if request.in_contest_mode and submission.contest_or_none %}
|
||||||
{% with contest=submission.contest_or_none %}
|
{% with contest=submission.contest_or_none %}
|
||||||
({{ _('%(points)s/%(total)s points', points=contest.points|roundfloat(3),
|
{{ _('%(points)s/%(total)s', points=contest.points|roundfloat(3),
|
||||||
total=contest.problem.points|floatformat(-1)) }})
|
total=contest.problem.points|floatformat(-1)) }}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ _('%(points)s/%(total)s', points=submission.points|roundfloat(3),
|
{{ _('%(points)s/%(total)s', points=submission.points|roundfloat(3),
|
||||||
|
|
Loading…
Reference in a new issue