diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index fc3bd4b..8740838 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -11,3 +11,7 @@ repos:
rev: 22.12.0
hooks:
- id: black
+ - repo: https://github.com/hadialqattan/pycln
+ rev: 'v2.3.0'
+ hooks:
+ - id: pycln
diff --git a/chat_box/migrations/0015_room_last_msg_time.py b/chat_box/migrations/0015_room_last_msg_time.py
new file mode 100644
index 0000000..a32f21b
--- /dev/null
+++ b/chat_box/migrations/0015_room_last_msg_time.py
@@ -0,0 +1,33 @@
+# Generated by Django 3.2.18 on 2023-11-02 01:41
+
+from django.db import migrations, models
+
+
+def migrate(apps, schema_editor):
+ Room = apps.get_model("chat_box", "Room")
+ Message = apps.get_model("chat_box", "Message")
+
+ for room in Room.objects.all():
+ messages = room.message_set
+ last_msg = messages.first()
+ if last_msg:
+ room.last_msg_time = last_msg.time
+ room.save()
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("chat_box", "0014_userroom_unread_count"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="room",
+ name="last_msg_time",
+ field=models.DateTimeField(
+ db_index=True, null=True, verbose_name="last seen"
+ ),
+ ),
+ migrations.RunPython(migrate, migrations.RunPython.noop, atomic=True),
+ ]
diff --git a/chat_box/models.py b/chat_box/models.py
index fb6de76..fd35430 100644
--- a/chat_box/models.py
+++ b/chat_box/models.py
@@ -1,6 +1,7 @@
from django.db import models
from django.db.models import CASCADE, Q
from django.utils.translation import gettext_lazy as _
+from django.utils.functional import cached_property
from judge.models.profile import Profile
@@ -17,25 +18,40 @@ class Room(models.Model):
user_two = models.ForeignKey(
Profile, related_name="user_two", verbose_name="user 2", on_delete=CASCADE
)
+ last_msg_time = models.DateTimeField(
+ verbose_name=_("last seen"), null=True, db_index=True
+ )
class Meta:
app_label = "chat_box"
- @cache_wrapper(prefix="Rc")
- def contain(self, profile):
- return self.user_one == profile or self.user_two == profile
+ @cache_wrapper(prefix="Rinfo")
+ def _info(self):
+ last_msg = self.message_set.first()
+ return {
+ "user_ids": [self.user_one.id, self.user_two.id],
+ "last_message": last_msg.body if last_msg else None,
+ }
+
+ @cached_property
+ def _cached_info(self):
+ return self._info()
+
+ def contain(self, profile):
+ return profile.id in self._cached_info["user_ids"]
- @cache_wrapper(prefix="Rou")
def other_user(self, profile):
return self.user_one if profile == self.user_two else self.user_two
- @cache_wrapper(prefix="Rus")
+ def other_user_id(self, profile):
+ user_ids = self._cached_info["user_ids"]
+ return sum(user_ids) - profile.id
+
def users(self):
return [self.user_one, self.user_two]
- @cache_wrapper(prefix="Rlmb")
def last_message_body(self):
- return self.message_set.first().body
+ return self._cached_info["last_message"]
class Message(models.Model):
diff --git a/chat_box/views.py b/chat_box/views.py
index 48fa37a..b01994a 100644
--- a/chat_box/views.py
+++ b/chat_box/views.py
@@ -29,7 +29,6 @@ from django.utils import timezone
from django.contrib.auth.decorators import login_required
from django.urls import reverse
-import datetime
from judge import event_poster as event
from judge.jinja2.gravatar import gravatar
@@ -38,8 +37,6 @@ from judge.models import Friend
from chat_box.models import Message, Profile, Room, UserRoom, Ignore
from chat_box.utils import encrypt_url, decrypt_url, encrypt_channel, get_unread_boxes
-import json
-
class ChatView(ListView):
context_object_name = "message"
@@ -87,8 +84,8 @@ class ChatView(ListView):
self.room_id = request_room
self.messages = (
Message.objects.filter(hidden=False, room=self.room_id, id__lt=last_id)
- .select_related("author", "author__user")
- .defer("author__about", "author__user_script")[:page_size]
+ .select_related("author")
+ .only("body", "time", "author__rating", "author__display_rank")[:page_size]
)
if not only_messages:
return super().get(request, *args, **kwargs)
@@ -207,7 +204,9 @@ def post_message(request):
},
)
else:
- Room.last_message_body.dirty(room)
+ Room._info.dirty(room)
+ room.last_msg_time = new_message.time
+ room.save()
for user in room.users():
event.post(
@@ -354,11 +353,11 @@ def get_online_status(profile, other_profile_ids, rooms=None):
room = Room.objects.get(id=i["room"])
other_profile = room.other_user(profile)
count[other_profile.id] = i["unread_count"]
+ rooms = Room.objects.filter(id__in=rooms)
for room in rooms:
- room = Room.objects.get(id=room)
- other_profile = room.other_user(profile)
- last_msg[other_profile.id] = room.last_message_body()
- room_of_user[other_profile.id] = room.id
+ other_profile_id = room.other_user_id(profile)
+ last_msg[other_profile_id] = room.last_message_body()
+ room_of_user[other_profile_id] = room.id
for other_profile in other_profiles:
is_online = False
@@ -392,9 +391,6 @@ def get_status_context(profile, include_ignored=False):
recent_profile = (
Room.objects.filter(Q(user_one=profile) | Q(user_two=profile))
.annotate(
- last_msg_time=Subquery(
- Message.objects.filter(room=OuterRef("pk")).values("time")[:1]
- ),
other_user=Case(
When(user_one=profile, then="user_two"),
default="user_one",
@@ -415,28 +411,15 @@ def get_status_context(profile, include_ignored=False):
.values_list("id", flat=True)
)
- all_user_status = (
- queryset.filter(last_access__gte=last_5_minutes)
- .annotate(is_online=Case(default=True, output_field=BooleanField()))
- .order_by("-rating")
- .exclude(id__in=admin_list)
- .exclude(id__in=recent_profile_ids)
- .values_list("id", flat=True)[:30]
- )
-
return [
{
- "title": "Recent",
+ "title": _("Recent"),
"user_list": get_online_status(profile, recent_profile_ids, recent_rooms),
},
{
- "title": "Admin",
+ "title": _("Admin"),
"user_list": get_online_status(profile, admin_list),
},
- {
- "title": "Other",
- "user_list": get_online_status(profile, all_user_status),
- },
]
diff --git a/dmoj/settings.py b/dmoj/settings.py
index e136a4d..1035969 100644
--- a/dmoj/settings.py
+++ b/dmoj/settings.py
@@ -9,7 +9,6 @@ https://docs.djangoproject.com/en/1.11/ref/settings/
"""
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
-import datetime
import os
import tempfile
diff --git a/dmoj/urls.py b/dmoj/urls.py
index e6610f8..8ac0a29 100644
--- a/dmoj/urls.py
+++ b/dmoj/urls.py
@@ -1100,6 +1100,11 @@ urlpatterns = [
internal.InternalProblem.as_view(),
name="internal_problem",
),
+ url(
+ r"^problem_votes$",
+ internal.get_problem_votes,
+ name="internal_problem_votes",
+ ),
url(
r"^request_time$",
internal.InternalRequestTime.as_view(),
diff --git a/judge/bridge/judge_handler.py b/judge/bridge/judge_handler.py
index 2f13b8a..6aefc5c 100644
--- a/judge/bridge/judge_handler.py
+++ b/judge/bridge/judge_handler.py
@@ -3,7 +3,6 @@ import json
import logging
import threading
import time
-import os
from collections import deque, namedtuple
from operator import itemgetter
@@ -25,6 +24,7 @@ from judge.models import (
Submission,
SubmissionTestCase,
)
+from judge.bridge.utils import VanishedSubmission
logger = logging.getLogger("judge.bridge")
json_log = logging.getLogger("judge.json.bridge")
@@ -94,12 +94,6 @@ class JudgeHandler(ZlibPacketHandler):
def on_disconnect(self):
self._stop_ping.set()
- if self._working:
- logger.error(
- "Judge %s disconnected while handling submission %s",
- self.name,
- self._working,
- )
self.judges.remove(self)
if self.name is not None:
self._disconnected()
@@ -119,16 +113,6 @@ class JudgeHandler(ZlibPacketHandler):
None,
0,
)
- # Submission.objects.filter(id=self._working).update(
- # status="IE", result="IE", error=""
- # )
- # json_log.error(
- # self._make_json_log(
- # sub=self._working,
- # action="close",
- # info="IE due to shutdown on grading",
- # )
- # )
def _authenticate(self, id, key):
try:
@@ -327,6 +311,9 @@ class JudgeHandler(ZlibPacketHandler):
def submit(self, id, problem, language, source):
data = self.get_related_submission_data(id)
+ if not data:
+ self._update_internal_error_submission(id, "Submission vanished")
+ raise VanishedSubmission()
self._working = id
self._working_data = {
"problem": problem,
@@ -675,8 +662,11 @@ class JudgeHandler(ZlibPacketHandler):
self._free_self(packet)
id = packet["submission-id"]
+ self._update_internal_error_submission(id, packet["message"])
+
+ def _update_internal_error_submission(self, id, message):
if Submission.objects.filter(id=id).update(
- status="IE", result="IE", error=packet["message"]
+ status="IE", result="IE", error=message
):
event.post(
"sub_%s" % Submission.get_id_secret(id), {"type": "internal-error"}
@@ -684,9 +674,9 @@ class JudgeHandler(ZlibPacketHandler):
self._post_update_submission(id, "internal-error", done=True)
json_log.info(
self._make_json_log(
- packet,
+ sub=id,
action="internal-error",
- message=packet["message"],
+ message=message,
finish=True,
result="IE",
)
@@ -695,10 +685,10 @@ class JudgeHandler(ZlibPacketHandler):
logger.warning("Unknown submission: %s", id)
json_log.error(
self._make_json_log(
- packet,
+ sub=id,
action="internal-error",
info="unknown submission",
- message=packet["message"],
+ message=message,
finish=True,
result="IE",
)
diff --git a/judge/bridge/judge_list.py b/judge/bridge/judge_list.py
index 0552de4..bf2b54a 100644
--- a/judge/bridge/judge_list.py
+++ b/judge/bridge/judge_list.py
@@ -3,6 +3,8 @@ from collections import namedtuple
from operator import attrgetter
from threading import RLock
+from judge.bridge.utils import VanishedSubmission
+
try:
from llist import dllist
except ImportError:
@@ -39,6 +41,8 @@ class JudgeList(object):
)
try:
judge.submit(id, problem, language, source)
+ except VanishedSubmission:
+ pass
except Exception:
logger.exception(
"Failed to dispatch %d (%s, %s) to %s",
diff --git a/judge/bridge/utils.py b/judge/bridge/utils.py
new file mode 100644
index 0000000..dfb2ac9
--- /dev/null
+++ b/judge/bridge/utils.py
@@ -0,0 +1,2 @@
+class VanishedSubmission(Exception):
+ pass
diff --git a/judge/caching.py b/judge/caching.py
index 43479da..029cf08 100644
--- a/judge/caching.py
+++ b/judge/caching.py
@@ -40,7 +40,10 @@ def cache_wrapper(prefix, timeout=None):
def _get(key):
if not l0_cache:
return cache.get(key)
- return l0_cache.get(key) or cache.get(key)
+ result = l0_cache.get(key)
+ if result is None:
+ result = cache.get(key)
+ return result
def _set_l0(key, value):
if l0_cache:
@@ -56,7 +59,7 @@ def cache_wrapper(prefix, timeout=None):
result = _get(cache_key)
if result is not None:
_set_l0(cache_key, result)
- if result == NONE_RESULT:
+ if type(result) == str and result == NONE_RESULT:
result = None
return result
result = func(*args, **kwargs)
diff --git a/judge/comments.py b/judge/comments.py
index dde97a0..98434cf 100644
--- a/judge/comments.py
+++ b/judge/comments.py
@@ -144,14 +144,16 @@ class CommentedDetailView(TemplateResponseMixin, SingleObjectMixin, View):
def get(self, request, *args, **kwargs):
target_comment = None
+ self.object = self.get_object()
if "comment-id" in request.GET:
- comment_id = int(request.GET["comment-id"])
try:
+ comment_id = int(request.GET["comment-id"])
comment_obj = Comment.objects.get(id=comment_id)
- except Comment.DoesNotExist:
+ except (Comment.DoesNotExist, ValueError):
+ raise Http404
+ if comment_obj.linked_object != self.object:
raise Http404
target_comment = comment_obj.get_root()
- self.object = self.get_object()
return self.render_to_response(
self.get_context_data(
object=self.object,
diff --git a/judge/forms.py b/judge/forms.py
index e6bbd67..35251ae 100644
--- a/judge/forms.py
+++ b/judge/forms.py
@@ -11,7 +11,6 @@ from django.contrib.auth.models import User
from django.contrib.auth.forms import AuthenticationForm
from django.core.exceptions import ValidationError, ObjectDoesNotExist
from django.core.validators import RegexValidator
-from django.db import transaction
from django.db.models import Q
from django.forms import (
CharField,
@@ -52,7 +51,6 @@ from judge.widgets import (
DateTimePickerWidget,
ImageWidget,
)
-from judge.tasks import rescore_contest
def fix_unicode(string, unsafe=tuple("\u202a\u202b\u202d\u202e")):
@@ -282,16 +280,9 @@ class EditOrganizationContestForm(ModelForm):
"view_contest_scoreboard",
]:
self.fields[field].widget.data_url = (
- self.fields[field].widget.get_url() + "?org_id=1"
+ self.fields[field].widget.get_url() + f"?org_id={self.org_id}"
)
- def save(self, commit=True):
- res = super(EditOrganizationContestForm, self).save(commit=False)
- if commit:
- res.save()
- transaction.on_commit(rescore_contest.s(res.key).delay)
- return res
-
class Meta:
model = Contest
fields = (
diff --git a/judge/logging.py b/judge/logging.py
new file mode 100644
index 0000000..8d9f154
--- /dev/null
+++ b/judge/logging.py
@@ -0,0 +1,7 @@
+import logging
+
+error_log = logging.getLogger("judge.errors")
+
+
+def log_exception(msg):
+ error_log.exception(msg)
diff --git a/judge/management/commands/generate_data.py b/judge/management/commands/generate_data.py
index 83827d9..4fcaa4e 100644
--- a/judge/management/commands/generate_data.py
+++ b/judge/management/commands/generate_data.py
@@ -1,6 +1,5 @@
from django.core.management.base import BaseCommand
from judge.models import *
-from collections import defaultdict
import csv
import os
from django.conf import settings
diff --git a/judge/migrations/0150_alter_profile_timezone.py b/judge/migrations/0150_alter_profile_timezone.py
index 94287b7..20b3e12 100644
--- a/judge/migrations/0150_alter_profile_timezone.py
+++ b/judge/migrations/0150_alter_profile_timezone.py
@@ -6,13 +6,671 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('judge', '0149_auto_20230202_0902'),
+ ("judge", "0149_auto_20230202_0902"),
]
operations = [
migrations.AlterField(
- model_name='profile',
- name='timezone',
- field=models.CharField(choices=[('Africa', [('Africa/Abidjan', 'Abidjan'), ('Africa/Accra', 'Accra'), ('Africa/Addis_Ababa', 'Addis_Ababa'), ('Africa/Algiers', 'Algiers'), ('Africa/Asmara', 'Asmara'), ('Africa/Asmera', 'Asmera'), ('Africa/Bamako', 'Bamako'), ('Africa/Bangui', 'Bangui'), ('Africa/Banjul', 'Banjul'), ('Africa/Bissau', 'Bissau'), ('Africa/Blantyre', 'Blantyre'), ('Africa/Brazzaville', 'Brazzaville'), ('Africa/Bujumbura', 'Bujumbura'), ('Africa/Cairo', 'Cairo'), ('Africa/Casablanca', 'Casablanca'), ('Africa/Ceuta', 'Ceuta'), ('Africa/Conakry', 'Conakry'), ('Africa/Dakar', 'Dakar'), ('Africa/Dar_es_Salaam', 'Dar_es_Salaam'), ('Africa/Djibouti', 'Djibouti'), ('Africa/Douala', 'Douala'), ('Africa/El_Aaiun', 'El_Aaiun'), ('Africa/Freetown', 'Freetown'), ('Africa/Gaborone', 'Gaborone'), ('Africa/Harare', 'Harare'), ('Africa/Johannesburg', 'Johannesburg'), ('Africa/Juba', 'Juba'), ('Africa/Kampala', 'Kampala'), ('Africa/Khartoum', 'Khartoum'), ('Africa/Kigali', 'Kigali'), ('Africa/Kinshasa', 'Kinshasa'), ('Africa/Lagos', 'Lagos'), ('Africa/Libreville', 'Libreville'), ('Africa/Lome', 'Lome'), ('Africa/Luanda', 'Luanda'), ('Africa/Lubumbashi', 'Lubumbashi'), ('Africa/Lusaka', 'Lusaka'), ('Africa/Malabo', 'Malabo'), ('Africa/Maputo', 'Maputo'), ('Africa/Maseru', 'Maseru'), ('Africa/Mbabane', 'Mbabane'), ('Africa/Mogadishu', 'Mogadishu'), ('Africa/Monrovia', 'Monrovia'), ('Africa/Nairobi', 'Nairobi'), ('Africa/Ndjamena', 'Ndjamena'), ('Africa/Niamey', 'Niamey'), ('Africa/Nouakchott', 'Nouakchott'), ('Africa/Ouagadougou', 'Ouagadougou'), ('Africa/Porto-Novo', 'Porto-Novo'), ('Africa/Sao_Tome', 'Sao_Tome'), ('Africa/Timbuktu', 'Timbuktu'), ('Africa/Tripoli', 'Tripoli'), ('Africa/Tunis', 'Tunis'), ('Africa/Windhoek', 'Windhoek')]), ('America', [('America/Adak', 'Adak'), ('America/Anchorage', 'Anchorage'), ('America/Anguilla', 'Anguilla'), ('America/Antigua', 'Antigua'), ('America/Araguaina', 'Araguaina'), ('America/Argentina/Buenos_Aires', 'Argentina/Buenos_Aires'), ('America/Argentina/Catamarca', 'Argentina/Catamarca'), ('America/Argentina/ComodRivadavia', 'Argentina/ComodRivadavia'), ('America/Argentina/Cordoba', 'Argentina/Cordoba'), ('America/Argentina/Jujuy', 'Argentina/Jujuy'), ('America/Argentina/La_Rioja', 'Argentina/La_Rioja'), ('America/Argentina/Mendoza', 'Argentina/Mendoza'), ('America/Argentina/Rio_Gallegos', 'Argentina/Rio_Gallegos'), ('America/Argentina/Salta', 'Argentina/Salta'), ('America/Argentina/San_Juan', 'Argentina/San_Juan'), ('America/Argentina/San_Luis', 'Argentina/San_Luis'), ('America/Argentina/Tucuman', 'Argentina/Tucuman'), ('America/Argentina/Ushuaia', 'Argentina/Ushuaia'), ('America/Aruba', 'Aruba'), ('America/Asuncion', 'Asuncion'), ('America/Atikokan', 'Atikokan'), ('America/Atka', 'Atka'), ('America/Bahia', 'Bahia'), ('America/Bahia_Banderas', 'Bahia_Banderas'), ('America/Barbados', 'Barbados'), ('America/Belem', 'Belem'), ('America/Belize', 'Belize'), ('America/Blanc-Sablon', 'Blanc-Sablon'), ('America/Boa_Vista', 'Boa_Vista'), ('America/Bogota', 'Bogota'), ('America/Boise', 'Boise'), ('America/Buenos_Aires', 'Buenos_Aires'), ('America/Cambridge_Bay', 'Cambridge_Bay'), ('America/Campo_Grande', 'Campo_Grande'), ('America/Cancun', 'Cancun'), ('America/Caracas', 'Caracas'), ('America/Catamarca', 'Catamarca'), ('America/Cayenne', 'Cayenne'), ('America/Cayman', 'Cayman'), ('America/Chicago', 'Chicago'), ('America/Chihuahua', 'Chihuahua'), ('America/Coral_Harbour', 'Coral_Harbour'), ('America/Cordoba', 'Cordoba'), ('America/Costa_Rica', 'Costa_Rica'), ('America/Creston', 'Creston'), ('America/Cuiaba', 'Cuiaba'), ('America/Curacao', 'Curacao'), ('America/Danmarkshavn', 'Danmarkshavn'), ('America/Dawson', 'Dawson'), ('America/Dawson_Creek', 'Dawson_Creek'), ('America/Denver', 'Denver'), ('America/Detroit', 'Detroit'), ('America/Dominica', 'Dominica'), ('America/Edmonton', 'Edmonton'), ('America/Eirunepe', 'Eirunepe'), ('America/El_Salvador', 'El_Salvador'), ('America/Ensenada', 'Ensenada'), ('America/Fort_Nelson', 'Fort_Nelson'), ('America/Fort_Wayne', 'Fort_Wayne'), ('America/Fortaleza', 'Fortaleza'), ('America/Glace_Bay', 'Glace_Bay'), ('America/Godthab', 'Godthab'), ('America/Goose_Bay', 'Goose_Bay'), ('America/Grand_Turk', 'Grand_Turk'), ('America/Grenada', 'Grenada'), ('America/Guadeloupe', 'Guadeloupe'), ('America/Guatemala', 'Guatemala'), ('America/Guayaquil', 'Guayaquil'), ('America/Guyana', 'Guyana'), ('America/Halifax', 'Halifax'), ('America/Havana', 'Havana'), ('America/Hermosillo', 'Hermosillo'), ('America/Indiana/Indianapolis', 'Indiana/Indianapolis'), ('America/Indiana/Knox', 'Indiana/Knox'), ('America/Indiana/Marengo', 'Indiana/Marengo'), ('America/Indiana/Petersburg', 'Indiana/Petersburg'), ('America/Indiana/Tell_City', 'Indiana/Tell_City'), ('America/Indiana/Vevay', 'Indiana/Vevay'), ('America/Indiana/Vincennes', 'Indiana/Vincennes'), ('America/Indiana/Winamac', 'Indiana/Winamac'), ('America/Indianapolis', 'Indianapolis'), ('America/Inuvik', 'Inuvik'), ('America/Iqaluit', 'Iqaluit'), ('America/Jamaica', 'Jamaica'), ('America/Jujuy', 'Jujuy'), ('America/Juneau', 'Juneau'), ('America/Kentucky/Louisville', 'Kentucky/Louisville'), ('America/Kentucky/Monticello', 'Kentucky/Monticello'), ('America/Knox_IN', 'Knox_IN'), ('America/Kralendijk', 'Kralendijk'), ('America/La_Paz', 'La_Paz'), ('America/Lima', 'Lima'), ('America/Los_Angeles', 'Los_Angeles'), ('America/Louisville', 'Louisville'), ('America/Lower_Princes', 'Lower_Princes'), ('America/Maceio', 'Maceio'), ('America/Managua', 'Managua'), ('America/Manaus', 'Manaus'), ('America/Marigot', 'Marigot'), ('America/Martinique', 'Martinique'), ('America/Matamoros', 'Matamoros'), ('America/Mazatlan', 'Mazatlan'), ('America/Mendoza', 'Mendoza'), ('America/Menominee', 'Menominee'), ('America/Merida', 'Merida'), ('America/Metlakatla', 'Metlakatla'), ('America/Mexico_City', 'Mexico_City'), ('America/Miquelon', 'Miquelon'), ('America/Moncton', 'Moncton'), ('America/Monterrey', 'Monterrey'), ('America/Montevideo', 'Montevideo'), ('America/Montreal', 'Montreal'), ('America/Montserrat', 'Montserrat'), ('America/Nassau', 'Nassau'), ('America/New_York', 'New_York'), ('America/Nipigon', 'Nipigon'), ('America/Nome', 'Nome'), ('America/Noronha', 'Noronha'), ('America/North_Dakota/Beulah', 'North_Dakota/Beulah'), ('America/North_Dakota/Center', 'North_Dakota/Center'), ('America/North_Dakota/New_Salem', 'North_Dakota/New_Salem'), ('America/Nuuk', 'Nuuk'), ('America/Ojinaga', 'Ojinaga'), ('America/Panama', 'Panama'), ('America/Pangnirtung', 'Pangnirtung'), ('America/Paramaribo', 'Paramaribo'), ('America/Phoenix', 'Phoenix'), ('America/Port-au-Prince', 'Port-au-Prince'), ('America/Port_of_Spain', 'Port_of_Spain'), ('America/Porto_Acre', 'Porto_Acre'), ('America/Porto_Velho', 'Porto_Velho'), ('America/Puerto_Rico', 'Puerto_Rico'), ('America/Punta_Arenas', 'Punta_Arenas'), ('America/Rainy_River', 'Rainy_River'), ('America/Rankin_Inlet', 'Rankin_Inlet'), ('America/Recife', 'Recife'), ('America/Regina', 'Regina'), ('America/Resolute', 'Resolute'), ('America/Rio_Branco', 'Rio_Branco'), ('America/Rosario', 'Rosario'), ('America/Santa_Isabel', 'Santa_Isabel'), ('America/Santarem', 'Santarem'), ('America/Santiago', 'Santiago'), ('America/Santo_Domingo', 'Santo_Domingo'), ('America/Sao_Paulo', 'Sao_Paulo'), ('America/Scoresbysund', 'Scoresbysund'), ('America/Shiprock', 'Shiprock'), ('America/Sitka', 'Sitka'), ('America/St_Barthelemy', 'St_Barthelemy'), ('America/St_Johns', 'St_Johns'), ('America/St_Kitts', 'St_Kitts'), ('America/St_Lucia', 'St_Lucia'), ('America/St_Thomas', 'St_Thomas'), ('America/St_Vincent', 'St_Vincent'), ('America/Swift_Current', 'Swift_Current'), ('America/Tegucigalpa', 'Tegucigalpa'), ('America/Thule', 'Thule'), ('America/Thunder_Bay', 'Thunder_Bay'), ('America/Tijuana', 'Tijuana'), ('America/Toronto', 'Toronto'), ('America/Tortola', 'Tortola'), ('America/Vancouver', 'Vancouver'), ('America/Virgin', 'Virgin'), ('America/Whitehorse', 'Whitehorse'), ('America/Winnipeg', 'Winnipeg'), ('America/Yakutat', 'Yakutat'), ('America/Yellowknife', 'Yellowknife')]), ('Antarctica', [('Antarctica/Casey', 'Casey'), ('Antarctica/Davis', 'Davis'), ('Antarctica/DumontDUrville', 'DumontDUrville'), ('Antarctica/Macquarie', 'Macquarie'), ('Antarctica/Mawson', 'Mawson'), ('Antarctica/McMurdo', 'McMurdo'), ('Antarctica/Palmer', 'Palmer'), ('Antarctica/Rothera', 'Rothera'), ('Antarctica/South_Pole', 'South_Pole'), ('Antarctica/Syowa', 'Syowa'), ('Antarctica/Troll', 'Troll'), ('Antarctica/Vostok', 'Vostok')]), ('Arctic', [('Arctic/Longyearbyen', 'Longyearbyen')]), ('Asia', [('Asia/Aden', 'Aden'), ('Asia/Almaty', 'Almaty'), ('Asia/Amman', 'Amman'), ('Asia/Anadyr', 'Anadyr'), ('Asia/Aqtau', 'Aqtau'), ('Asia/Aqtobe', 'Aqtobe'), ('Asia/Ashgabat', 'Ashgabat'), ('Asia/Ashkhabad', 'Ashkhabad'), ('Asia/Atyrau', 'Atyrau'), ('Asia/Baghdad', 'Baghdad'), ('Asia/Bahrain', 'Bahrain'), ('Asia/Baku', 'Baku'), ('Asia/Bangkok', 'Bangkok'), ('Asia/Barnaul', 'Barnaul'), ('Asia/Beirut', 'Beirut'), ('Asia/Bishkek', 'Bishkek'), ('Asia/Brunei', 'Brunei'), ('Asia/Calcutta', 'Calcutta'), ('Asia/Chita', 'Chita'), ('Asia/Choibalsan', 'Choibalsan'), ('Asia/Chongqing', 'Chongqing'), ('Asia/Chungking', 'Chungking'), ('Asia/Colombo', 'Colombo'), ('Asia/Dacca', 'Dacca'), ('Asia/Damascus', 'Damascus'), ('Asia/Dhaka', 'Dhaka'), ('Asia/Dili', 'Dili'), ('Asia/Dubai', 'Dubai'), ('Asia/Dushanbe', 'Dushanbe'), ('Asia/Famagusta', 'Famagusta'), ('Asia/Gaza', 'Gaza'), ('Asia/Harbin', 'Harbin'), ('Asia/Hebron', 'Hebron'), ('Asia/Ho_Chi_Minh', 'Ho_Chi_Minh'), ('Asia/Hong_Kong', 'Hong_Kong'), ('Asia/Hovd', 'Hovd'), ('Asia/Irkutsk', 'Irkutsk'), ('Asia/Istanbul', 'Istanbul'), ('Asia/Jakarta', 'Jakarta'), ('Asia/Jayapura', 'Jayapura'), ('Asia/Jerusalem', 'Jerusalem'), ('Asia/Kabul', 'Kabul'), ('Asia/Kamchatka', 'Kamchatka'), ('Asia/Karachi', 'Karachi'), ('Asia/Kashgar', 'Kashgar'), ('Asia/Kathmandu', 'Kathmandu'), ('Asia/Katmandu', 'Katmandu'), ('Asia/Khandyga', 'Khandyga'), ('Asia/Kolkata', 'Kolkata'), ('Asia/Krasnoyarsk', 'Krasnoyarsk'), ('Asia/Kuala_Lumpur', 'Kuala_Lumpur'), ('Asia/Kuching', 'Kuching'), ('Asia/Kuwait', 'Kuwait'), ('Asia/Macao', 'Macao'), ('Asia/Macau', 'Macau'), ('Asia/Magadan', 'Magadan'), ('Asia/Makassar', 'Makassar'), ('Asia/Manila', 'Manila'), ('Asia/Muscat', 'Muscat'), ('Asia/Nicosia', 'Nicosia'), ('Asia/Novokuznetsk', 'Novokuznetsk'), ('Asia/Novosibirsk', 'Novosibirsk'), ('Asia/Omsk', 'Omsk'), ('Asia/Oral', 'Oral'), ('Asia/Phnom_Penh', 'Phnom_Penh'), ('Asia/Pontianak', 'Pontianak'), ('Asia/Pyongyang', 'Pyongyang'), ('Asia/Qatar', 'Qatar'), ('Asia/Qostanay', 'Qostanay'), ('Asia/Qyzylorda', 'Qyzylorda'), ('Asia/Rangoon', 'Rangoon'), ('Asia/Riyadh', 'Riyadh'), ('Asia/Saigon', 'Saigon'), ('Asia/Sakhalin', 'Sakhalin'), ('Asia/Samarkand', 'Samarkand'), ('Asia/Seoul', 'Seoul'), ('Asia/Shanghai', 'Shanghai'), ('Asia/Singapore', 'Singapore'), ('Asia/Srednekolymsk', 'Srednekolymsk'), ('Asia/Taipei', 'Taipei'), ('Asia/Tashkent', 'Tashkent'), ('Asia/Tbilisi', 'Tbilisi'), ('Asia/Tehran', 'Tehran'), ('Asia/Tel_Aviv', 'Tel_Aviv'), ('Asia/Thimbu', 'Thimbu'), ('Asia/Thimphu', 'Thimphu'), ('Asia/Tokyo', 'Tokyo'), ('Asia/Tomsk', 'Tomsk'), ('Asia/Ujung_Pandang', 'Ujung_Pandang'), ('Asia/Ulaanbaatar', 'Ulaanbaatar'), ('Asia/Ulan_Bator', 'Ulan_Bator'), ('Asia/Urumqi', 'Urumqi'), ('Asia/Ust-Nera', 'Ust-Nera'), ('Asia/Vientiane', 'Vientiane'), ('Asia/Vladivostok', 'Vladivostok'), ('Asia/Yakutsk', 'Yakutsk'), ('Asia/Yangon', 'Yangon'), ('Asia/Yekaterinburg', 'Yekaterinburg'), ('Asia/Yerevan', 'Yerevan')]), ('Atlantic', [('Atlantic/Azores', 'Azores'), ('Atlantic/Bermuda', 'Bermuda'), ('Atlantic/Canary', 'Canary'), ('Atlantic/Cape_Verde', 'Cape_Verde'), ('Atlantic/Faeroe', 'Faeroe'), ('Atlantic/Faroe', 'Faroe'), ('Atlantic/Jan_Mayen', 'Jan_Mayen'), ('Atlantic/Madeira', 'Madeira'), ('Atlantic/Reykjavik', 'Reykjavik'), ('Atlantic/South_Georgia', 'South_Georgia'), ('Atlantic/St_Helena', 'St_Helena'), ('Atlantic/Stanley', 'Stanley')]), ('Australia', [('Australia/ACT', 'ACT'), ('Australia/Adelaide', 'Adelaide'), ('Australia/Brisbane', 'Brisbane'), ('Australia/Broken_Hill', 'Broken_Hill'), ('Australia/Canberra', 'Canberra'), ('Australia/Currie', 'Currie'), ('Australia/Darwin', 'Darwin'), ('Australia/Eucla', 'Eucla'), ('Australia/Hobart', 'Hobart'), ('Australia/LHI', 'LHI'), ('Australia/Lindeman', 'Lindeman'), ('Australia/Lord_Howe', 'Lord_Howe'), ('Australia/Melbourne', 'Melbourne'), ('Australia/NSW', 'NSW'), ('Australia/North', 'North'), ('Australia/Perth', 'Perth'), ('Australia/Queensland', 'Queensland'), ('Australia/South', 'South'), ('Australia/Sydney', 'Sydney'), ('Australia/Tasmania', 'Tasmania'), ('Australia/Victoria', 'Victoria'), ('Australia/West', 'West'), ('Australia/Yancowinna', 'Yancowinna')]), ('Brazil', [('Brazil/Acre', 'Acre'), ('Brazil/DeNoronha', 'DeNoronha'), ('Brazil/East', 'East'), ('Brazil/West', 'West')]), ('Canada', [('Canada/Atlantic', 'Atlantic'), ('Canada/Central', 'Central'), ('Canada/Eastern', 'Eastern'), ('Canada/Mountain', 'Mountain'), ('Canada/Newfoundland', 'Newfoundland'), ('Canada/Pacific', 'Pacific'), ('Canada/Saskatchewan', 'Saskatchewan'), ('Canada/Yukon', 'Yukon')]), ('Chile', [('Chile/Continental', 'Continental'), ('Chile/EasterIsland', 'EasterIsland')]), ('Etc', [('Etc/Greenwich', 'Greenwich'), ('Etc/UCT', 'UCT'), ('Etc/UTC', 'UTC'), ('Etc/Universal', 'Universal'), ('Etc/Zulu', 'Zulu')]), ('Europe', [('Europe/Amsterdam', 'Amsterdam'), ('Europe/Andorra', 'Andorra'), ('Europe/Astrakhan', 'Astrakhan'), ('Europe/Athens', 'Athens'), ('Europe/Belfast', 'Belfast'), ('Europe/Belgrade', 'Belgrade'), ('Europe/Berlin', 'Berlin'), ('Europe/Bratislava', 'Bratislava'), ('Europe/Brussels', 'Brussels'), ('Europe/Bucharest', 'Bucharest'), ('Europe/Budapest', 'Budapest'), ('Europe/Busingen', 'Busingen'), ('Europe/Chisinau', 'Chisinau'), ('Europe/Copenhagen', 'Copenhagen'), ('Europe/Dublin', 'Dublin'), ('Europe/Gibraltar', 'Gibraltar'), ('Europe/Guernsey', 'Guernsey'), ('Europe/Helsinki', 'Helsinki'), ('Europe/Isle_of_Man', 'Isle_of_Man'), ('Europe/Istanbul', 'Istanbul'), ('Europe/Jersey', 'Jersey'), ('Europe/Kaliningrad', 'Kaliningrad'), ('Europe/Kiev', 'Kiev'), ('Europe/Kirov', 'Kirov'), ('Europe/Lisbon', 'Lisbon'), ('Europe/Ljubljana', 'Ljubljana'), ('Europe/London', 'London'), ('Europe/Luxembourg', 'Luxembourg'), ('Europe/Madrid', 'Madrid'), ('Europe/Malta', 'Malta'), ('Europe/Mariehamn', 'Mariehamn'), ('Europe/Minsk', 'Minsk'), ('Europe/Monaco', 'Monaco'), ('Europe/Moscow', 'Moscow'), ('Europe/Nicosia', 'Nicosia'), ('Europe/Oslo', 'Oslo'), ('Europe/Paris', 'Paris'), ('Europe/Podgorica', 'Podgorica'), ('Europe/Prague', 'Prague'), ('Europe/Riga', 'Riga'), ('Europe/Rome', 'Rome'), ('Europe/Samara', 'Samara'), ('Europe/San_Marino', 'San_Marino'), ('Europe/Sarajevo', 'Sarajevo'), ('Europe/Saratov', 'Saratov'), ('Europe/Simferopol', 'Simferopol'), ('Europe/Skopje', 'Skopje'), ('Europe/Sofia', 'Sofia'), ('Europe/Stockholm', 'Stockholm'), ('Europe/Tallinn', 'Tallinn'), ('Europe/Tirane', 'Tirane'), ('Europe/Tiraspol', 'Tiraspol'), ('Europe/Ulyanovsk', 'Ulyanovsk'), ('Europe/Uzhgorod', 'Uzhgorod'), ('Europe/Vaduz', 'Vaduz'), ('Europe/Vatican', 'Vatican'), ('Europe/Vienna', 'Vienna'), ('Europe/Vilnius', 'Vilnius'), ('Europe/Volgograd', 'Volgograd'), ('Europe/Warsaw', 'Warsaw'), ('Europe/Zagreb', 'Zagreb'), ('Europe/Zaporozhye', 'Zaporozhye'), ('Europe/Zurich', 'Zurich')]), ('Indian', [('Indian/Antananarivo', 'Antananarivo'), ('Indian/Chagos', 'Chagos'), ('Indian/Christmas', 'Christmas'), ('Indian/Cocos', 'Cocos'), ('Indian/Comoro', 'Comoro'), ('Indian/Kerguelen', 'Kerguelen'), ('Indian/Mahe', 'Mahe'), ('Indian/Maldives', 'Maldives'), ('Indian/Mauritius', 'Mauritius'), ('Indian/Mayotte', 'Mayotte'), ('Indian/Reunion', 'Reunion')]), ('Mexico', [('Mexico/BajaNorte', 'BajaNorte'), ('Mexico/BajaSur', 'BajaSur'), ('Mexico/General', 'General')]), ('Other', [('CET', 'CET'), ('CST6CDT', 'CST6CDT'), ('Cuba', 'Cuba'), ('EET', 'EET'), ('EST', 'EST'), ('EST5EDT', 'EST5EDT'), ('Egypt', 'Egypt'), ('Eire', 'Eire'), ('GB', 'GB'), ('GB-Eire', 'GB-Eire'), ('Greenwich', 'Greenwich'), ('HST', 'HST'), ('Hongkong', 'Hongkong'), ('Iceland', 'Iceland'), ('Iran', 'Iran'), ('Israel', 'Israel'), ('Jamaica', 'Jamaica'), ('Japan', 'Japan'), ('Kwajalein', 'Kwajalein'), ('Libya', 'Libya'), ('MET', 'MET'), ('MST', 'MST'), ('MST7MDT', 'MST7MDT'), ('NZ', 'NZ'), ('NZ-CHAT', 'NZ-CHAT'), ('Navajo', 'Navajo'), ('PRC', 'PRC'), ('PST8PDT', 'PST8PDT'), ('Poland', 'Poland'), ('Portugal', 'Portugal'), ('ROC', 'ROC'), ('ROK', 'ROK'), ('Singapore', 'Singapore'), ('Turkey', 'Turkey'), ('UCT', 'UCT'), ('UTC', 'UTC'), ('Universal', 'Universal'), ('W-SU', 'W-SU'), ('WET', 'WET'), ('Zulu', 'Zulu')]), ('Pacific', [('Pacific/Apia', 'Apia'), ('Pacific/Auckland', 'Auckland'), ('Pacific/Bougainville', 'Bougainville'), ('Pacific/Chatham', 'Chatham'), ('Pacific/Chuuk', 'Chuuk'), ('Pacific/Easter', 'Easter'), ('Pacific/Efate', 'Efate'), ('Pacific/Enderbury', 'Enderbury'), ('Pacific/Fakaofo', 'Fakaofo'), ('Pacific/Fiji', 'Fiji'), ('Pacific/Funafuti', 'Funafuti'), ('Pacific/Galapagos', 'Galapagos'), ('Pacific/Gambier', 'Gambier'), ('Pacific/Guadalcanal', 'Guadalcanal'), ('Pacific/Guam', 'Guam'), ('Pacific/Honolulu', 'Honolulu'), ('Pacific/Johnston', 'Johnston'), ('Pacific/Kanton', 'Kanton'), ('Pacific/Kiritimati', 'Kiritimati'), ('Pacific/Kosrae', 'Kosrae'), ('Pacific/Kwajalein', 'Kwajalein'), ('Pacific/Majuro', 'Majuro'), ('Pacific/Marquesas', 'Marquesas'), ('Pacific/Midway', 'Midway'), ('Pacific/Nauru', 'Nauru'), ('Pacific/Niue', 'Niue'), ('Pacific/Norfolk', 'Norfolk'), ('Pacific/Noumea', 'Noumea'), ('Pacific/Pago_Pago', 'Pago_Pago'), ('Pacific/Palau', 'Palau'), ('Pacific/Pitcairn', 'Pitcairn'), ('Pacific/Pohnpei', 'Pohnpei'), ('Pacific/Ponape', 'Ponape'), ('Pacific/Port_Moresby', 'Port_Moresby'), ('Pacific/Rarotonga', 'Rarotonga'), ('Pacific/Saipan', 'Saipan'), ('Pacific/Samoa', 'Samoa'), ('Pacific/Tahiti', 'Tahiti'), ('Pacific/Tarawa', 'Tarawa'), ('Pacific/Tongatapu', 'Tongatapu'), ('Pacific/Truk', 'Truk'), ('Pacific/Wake', 'Wake'), ('Pacific/Wallis', 'Wallis'), ('Pacific/Yap', 'Yap')]), ('US', [('US/Alaska', 'Alaska'), ('US/Aleutian', 'Aleutian'), ('US/Arizona', 'Arizona'), ('US/Central', 'Central'), ('US/East-Indiana', 'East-Indiana'), ('US/Eastern', 'Eastern'), ('US/Hawaii', 'Hawaii'), ('US/Indiana-Starke', 'Indiana-Starke'), ('US/Michigan', 'Michigan'), ('US/Mountain', 'Mountain'), ('US/Pacific', 'Pacific'), ('US/Samoa', 'Samoa')])], default='Asia/Ho_Chi_Minh', max_length=50, verbose_name='location'),
+ model_name="profile",
+ name="timezone",
+ field=models.CharField(
+ choices=[
+ (
+ "Africa",
+ [
+ ("Africa/Abidjan", "Abidjan"),
+ ("Africa/Accra", "Accra"),
+ ("Africa/Addis_Ababa", "Addis_Ababa"),
+ ("Africa/Algiers", "Algiers"),
+ ("Africa/Asmara", "Asmara"),
+ ("Africa/Asmera", "Asmera"),
+ ("Africa/Bamako", "Bamako"),
+ ("Africa/Bangui", "Bangui"),
+ ("Africa/Banjul", "Banjul"),
+ ("Africa/Bissau", "Bissau"),
+ ("Africa/Blantyre", "Blantyre"),
+ ("Africa/Brazzaville", "Brazzaville"),
+ ("Africa/Bujumbura", "Bujumbura"),
+ ("Africa/Cairo", "Cairo"),
+ ("Africa/Casablanca", "Casablanca"),
+ ("Africa/Ceuta", "Ceuta"),
+ ("Africa/Conakry", "Conakry"),
+ ("Africa/Dakar", "Dakar"),
+ ("Africa/Dar_es_Salaam", "Dar_es_Salaam"),
+ ("Africa/Djibouti", "Djibouti"),
+ ("Africa/Douala", "Douala"),
+ ("Africa/El_Aaiun", "El_Aaiun"),
+ ("Africa/Freetown", "Freetown"),
+ ("Africa/Gaborone", "Gaborone"),
+ ("Africa/Harare", "Harare"),
+ ("Africa/Johannesburg", "Johannesburg"),
+ ("Africa/Juba", "Juba"),
+ ("Africa/Kampala", "Kampala"),
+ ("Africa/Khartoum", "Khartoum"),
+ ("Africa/Kigali", "Kigali"),
+ ("Africa/Kinshasa", "Kinshasa"),
+ ("Africa/Lagos", "Lagos"),
+ ("Africa/Libreville", "Libreville"),
+ ("Africa/Lome", "Lome"),
+ ("Africa/Luanda", "Luanda"),
+ ("Africa/Lubumbashi", "Lubumbashi"),
+ ("Africa/Lusaka", "Lusaka"),
+ ("Africa/Malabo", "Malabo"),
+ ("Africa/Maputo", "Maputo"),
+ ("Africa/Maseru", "Maseru"),
+ ("Africa/Mbabane", "Mbabane"),
+ ("Africa/Mogadishu", "Mogadishu"),
+ ("Africa/Monrovia", "Monrovia"),
+ ("Africa/Nairobi", "Nairobi"),
+ ("Africa/Ndjamena", "Ndjamena"),
+ ("Africa/Niamey", "Niamey"),
+ ("Africa/Nouakchott", "Nouakchott"),
+ ("Africa/Ouagadougou", "Ouagadougou"),
+ ("Africa/Porto-Novo", "Porto-Novo"),
+ ("Africa/Sao_Tome", "Sao_Tome"),
+ ("Africa/Timbuktu", "Timbuktu"),
+ ("Africa/Tripoli", "Tripoli"),
+ ("Africa/Tunis", "Tunis"),
+ ("Africa/Windhoek", "Windhoek"),
+ ],
+ ),
+ (
+ "America",
+ [
+ ("America/Adak", "Adak"),
+ ("America/Anchorage", "Anchorage"),
+ ("America/Anguilla", "Anguilla"),
+ ("America/Antigua", "Antigua"),
+ ("America/Araguaina", "Araguaina"),
+ (
+ "America/Argentina/Buenos_Aires",
+ "Argentina/Buenos_Aires",
+ ),
+ ("America/Argentina/Catamarca", "Argentina/Catamarca"),
+ (
+ "America/Argentina/ComodRivadavia",
+ "Argentina/ComodRivadavia",
+ ),
+ ("America/Argentina/Cordoba", "Argentina/Cordoba"),
+ ("America/Argentina/Jujuy", "Argentina/Jujuy"),
+ ("America/Argentina/La_Rioja", "Argentina/La_Rioja"),
+ ("America/Argentina/Mendoza", "Argentina/Mendoza"),
+ (
+ "America/Argentina/Rio_Gallegos",
+ "Argentina/Rio_Gallegos",
+ ),
+ ("America/Argentina/Salta", "Argentina/Salta"),
+ ("America/Argentina/San_Juan", "Argentina/San_Juan"),
+ ("America/Argentina/San_Luis", "Argentina/San_Luis"),
+ ("America/Argentina/Tucuman", "Argentina/Tucuman"),
+ ("America/Argentina/Ushuaia", "Argentina/Ushuaia"),
+ ("America/Aruba", "Aruba"),
+ ("America/Asuncion", "Asuncion"),
+ ("America/Atikokan", "Atikokan"),
+ ("America/Atka", "Atka"),
+ ("America/Bahia", "Bahia"),
+ ("America/Bahia_Banderas", "Bahia_Banderas"),
+ ("America/Barbados", "Barbados"),
+ ("America/Belem", "Belem"),
+ ("America/Belize", "Belize"),
+ ("America/Blanc-Sablon", "Blanc-Sablon"),
+ ("America/Boa_Vista", "Boa_Vista"),
+ ("America/Bogota", "Bogota"),
+ ("America/Boise", "Boise"),
+ ("America/Buenos_Aires", "Buenos_Aires"),
+ ("America/Cambridge_Bay", "Cambridge_Bay"),
+ ("America/Campo_Grande", "Campo_Grande"),
+ ("America/Cancun", "Cancun"),
+ ("America/Caracas", "Caracas"),
+ ("America/Catamarca", "Catamarca"),
+ ("America/Cayenne", "Cayenne"),
+ ("America/Cayman", "Cayman"),
+ ("America/Chicago", "Chicago"),
+ ("America/Chihuahua", "Chihuahua"),
+ ("America/Coral_Harbour", "Coral_Harbour"),
+ ("America/Cordoba", "Cordoba"),
+ ("America/Costa_Rica", "Costa_Rica"),
+ ("America/Creston", "Creston"),
+ ("America/Cuiaba", "Cuiaba"),
+ ("America/Curacao", "Curacao"),
+ ("America/Danmarkshavn", "Danmarkshavn"),
+ ("America/Dawson", "Dawson"),
+ ("America/Dawson_Creek", "Dawson_Creek"),
+ ("America/Denver", "Denver"),
+ ("America/Detroit", "Detroit"),
+ ("America/Dominica", "Dominica"),
+ ("America/Edmonton", "Edmonton"),
+ ("America/Eirunepe", "Eirunepe"),
+ ("America/El_Salvador", "El_Salvador"),
+ ("America/Ensenada", "Ensenada"),
+ ("America/Fort_Nelson", "Fort_Nelson"),
+ ("America/Fort_Wayne", "Fort_Wayne"),
+ ("America/Fortaleza", "Fortaleza"),
+ ("America/Glace_Bay", "Glace_Bay"),
+ ("America/Godthab", "Godthab"),
+ ("America/Goose_Bay", "Goose_Bay"),
+ ("America/Grand_Turk", "Grand_Turk"),
+ ("America/Grenada", "Grenada"),
+ ("America/Guadeloupe", "Guadeloupe"),
+ ("America/Guatemala", "Guatemala"),
+ ("America/Guayaquil", "Guayaquil"),
+ ("America/Guyana", "Guyana"),
+ ("America/Halifax", "Halifax"),
+ ("America/Havana", "Havana"),
+ ("America/Hermosillo", "Hermosillo"),
+ ("America/Indiana/Indianapolis", "Indiana/Indianapolis"),
+ ("America/Indiana/Knox", "Indiana/Knox"),
+ ("America/Indiana/Marengo", "Indiana/Marengo"),
+ ("America/Indiana/Petersburg", "Indiana/Petersburg"),
+ ("America/Indiana/Tell_City", "Indiana/Tell_City"),
+ ("America/Indiana/Vevay", "Indiana/Vevay"),
+ ("America/Indiana/Vincennes", "Indiana/Vincennes"),
+ ("America/Indiana/Winamac", "Indiana/Winamac"),
+ ("America/Indianapolis", "Indianapolis"),
+ ("America/Inuvik", "Inuvik"),
+ ("America/Iqaluit", "Iqaluit"),
+ ("America/Jamaica", "Jamaica"),
+ ("America/Jujuy", "Jujuy"),
+ ("America/Juneau", "Juneau"),
+ ("America/Kentucky/Louisville", "Kentucky/Louisville"),
+ ("America/Kentucky/Monticello", "Kentucky/Monticello"),
+ ("America/Knox_IN", "Knox_IN"),
+ ("America/Kralendijk", "Kralendijk"),
+ ("America/La_Paz", "La_Paz"),
+ ("America/Lima", "Lima"),
+ ("America/Los_Angeles", "Los_Angeles"),
+ ("America/Louisville", "Louisville"),
+ ("America/Lower_Princes", "Lower_Princes"),
+ ("America/Maceio", "Maceio"),
+ ("America/Managua", "Managua"),
+ ("America/Manaus", "Manaus"),
+ ("America/Marigot", "Marigot"),
+ ("America/Martinique", "Martinique"),
+ ("America/Matamoros", "Matamoros"),
+ ("America/Mazatlan", "Mazatlan"),
+ ("America/Mendoza", "Mendoza"),
+ ("America/Menominee", "Menominee"),
+ ("America/Merida", "Merida"),
+ ("America/Metlakatla", "Metlakatla"),
+ ("America/Mexico_City", "Mexico_City"),
+ ("America/Miquelon", "Miquelon"),
+ ("America/Moncton", "Moncton"),
+ ("America/Monterrey", "Monterrey"),
+ ("America/Montevideo", "Montevideo"),
+ ("America/Montreal", "Montreal"),
+ ("America/Montserrat", "Montserrat"),
+ ("America/Nassau", "Nassau"),
+ ("America/New_York", "New_York"),
+ ("America/Nipigon", "Nipigon"),
+ ("America/Nome", "Nome"),
+ ("America/Noronha", "Noronha"),
+ ("America/North_Dakota/Beulah", "North_Dakota/Beulah"),
+ ("America/North_Dakota/Center", "North_Dakota/Center"),
+ (
+ "America/North_Dakota/New_Salem",
+ "North_Dakota/New_Salem",
+ ),
+ ("America/Nuuk", "Nuuk"),
+ ("America/Ojinaga", "Ojinaga"),
+ ("America/Panama", "Panama"),
+ ("America/Pangnirtung", "Pangnirtung"),
+ ("America/Paramaribo", "Paramaribo"),
+ ("America/Phoenix", "Phoenix"),
+ ("America/Port-au-Prince", "Port-au-Prince"),
+ ("America/Port_of_Spain", "Port_of_Spain"),
+ ("America/Porto_Acre", "Porto_Acre"),
+ ("America/Porto_Velho", "Porto_Velho"),
+ ("America/Puerto_Rico", "Puerto_Rico"),
+ ("America/Punta_Arenas", "Punta_Arenas"),
+ ("America/Rainy_River", "Rainy_River"),
+ ("America/Rankin_Inlet", "Rankin_Inlet"),
+ ("America/Recife", "Recife"),
+ ("America/Regina", "Regina"),
+ ("America/Resolute", "Resolute"),
+ ("America/Rio_Branco", "Rio_Branco"),
+ ("America/Rosario", "Rosario"),
+ ("America/Santa_Isabel", "Santa_Isabel"),
+ ("America/Santarem", "Santarem"),
+ ("America/Santiago", "Santiago"),
+ ("America/Santo_Domingo", "Santo_Domingo"),
+ ("America/Sao_Paulo", "Sao_Paulo"),
+ ("America/Scoresbysund", "Scoresbysund"),
+ ("America/Shiprock", "Shiprock"),
+ ("America/Sitka", "Sitka"),
+ ("America/St_Barthelemy", "St_Barthelemy"),
+ ("America/St_Johns", "St_Johns"),
+ ("America/St_Kitts", "St_Kitts"),
+ ("America/St_Lucia", "St_Lucia"),
+ ("America/St_Thomas", "St_Thomas"),
+ ("America/St_Vincent", "St_Vincent"),
+ ("America/Swift_Current", "Swift_Current"),
+ ("America/Tegucigalpa", "Tegucigalpa"),
+ ("America/Thule", "Thule"),
+ ("America/Thunder_Bay", "Thunder_Bay"),
+ ("America/Tijuana", "Tijuana"),
+ ("America/Toronto", "Toronto"),
+ ("America/Tortola", "Tortola"),
+ ("America/Vancouver", "Vancouver"),
+ ("America/Virgin", "Virgin"),
+ ("America/Whitehorse", "Whitehorse"),
+ ("America/Winnipeg", "Winnipeg"),
+ ("America/Yakutat", "Yakutat"),
+ ("America/Yellowknife", "Yellowknife"),
+ ],
+ ),
+ (
+ "Antarctica",
+ [
+ ("Antarctica/Casey", "Casey"),
+ ("Antarctica/Davis", "Davis"),
+ ("Antarctica/DumontDUrville", "DumontDUrville"),
+ ("Antarctica/Macquarie", "Macquarie"),
+ ("Antarctica/Mawson", "Mawson"),
+ ("Antarctica/McMurdo", "McMurdo"),
+ ("Antarctica/Palmer", "Palmer"),
+ ("Antarctica/Rothera", "Rothera"),
+ ("Antarctica/South_Pole", "South_Pole"),
+ ("Antarctica/Syowa", "Syowa"),
+ ("Antarctica/Troll", "Troll"),
+ ("Antarctica/Vostok", "Vostok"),
+ ],
+ ),
+ ("Arctic", [("Arctic/Longyearbyen", "Longyearbyen")]),
+ (
+ "Asia",
+ [
+ ("Asia/Aden", "Aden"),
+ ("Asia/Almaty", "Almaty"),
+ ("Asia/Amman", "Amman"),
+ ("Asia/Anadyr", "Anadyr"),
+ ("Asia/Aqtau", "Aqtau"),
+ ("Asia/Aqtobe", "Aqtobe"),
+ ("Asia/Ashgabat", "Ashgabat"),
+ ("Asia/Ashkhabad", "Ashkhabad"),
+ ("Asia/Atyrau", "Atyrau"),
+ ("Asia/Baghdad", "Baghdad"),
+ ("Asia/Bahrain", "Bahrain"),
+ ("Asia/Baku", "Baku"),
+ ("Asia/Bangkok", "Bangkok"),
+ ("Asia/Barnaul", "Barnaul"),
+ ("Asia/Beirut", "Beirut"),
+ ("Asia/Bishkek", "Bishkek"),
+ ("Asia/Brunei", "Brunei"),
+ ("Asia/Calcutta", "Calcutta"),
+ ("Asia/Chita", "Chita"),
+ ("Asia/Choibalsan", "Choibalsan"),
+ ("Asia/Chongqing", "Chongqing"),
+ ("Asia/Chungking", "Chungking"),
+ ("Asia/Colombo", "Colombo"),
+ ("Asia/Dacca", "Dacca"),
+ ("Asia/Damascus", "Damascus"),
+ ("Asia/Dhaka", "Dhaka"),
+ ("Asia/Dili", "Dili"),
+ ("Asia/Dubai", "Dubai"),
+ ("Asia/Dushanbe", "Dushanbe"),
+ ("Asia/Famagusta", "Famagusta"),
+ ("Asia/Gaza", "Gaza"),
+ ("Asia/Harbin", "Harbin"),
+ ("Asia/Hebron", "Hebron"),
+ ("Asia/Ho_Chi_Minh", "Ho_Chi_Minh"),
+ ("Asia/Hong_Kong", "Hong_Kong"),
+ ("Asia/Hovd", "Hovd"),
+ ("Asia/Irkutsk", "Irkutsk"),
+ ("Asia/Istanbul", "Istanbul"),
+ ("Asia/Jakarta", "Jakarta"),
+ ("Asia/Jayapura", "Jayapura"),
+ ("Asia/Jerusalem", "Jerusalem"),
+ ("Asia/Kabul", "Kabul"),
+ ("Asia/Kamchatka", "Kamchatka"),
+ ("Asia/Karachi", "Karachi"),
+ ("Asia/Kashgar", "Kashgar"),
+ ("Asia/Kathmandu", "Kathmandu"),
+ ("Asia/Katmandu", "Katmandu"),
+ ("Asia/Khandyga", "Khandyga"),
+ ("Asia/Kolkata", "Kolkata"),
+ ("Asia/Krasnoyarsk", "Krasnoyarsk"),
+ ("Asia/Kuala_Lumpur", "Kuala_Lumpur"),
+ ("Asia/Kuching", "Kuching"),
+ ("Asia/Kuwait", "Kuwait"),
+ ("Asia/Macao", "Macao"),
+ ("Asia/Macau", "Macau"),
+ ("Asia/Magadan", "Magadan"),
+ ("Asia/Makassar", "Makassar"),
+ ("Asia/Manila", "Manila"),
+ ("Asia/Muscat", "Muscat"),
+ ("Asia/Nicosia", "Nicosia"),
+ ("Asia/Novokuznetsk", "Novokuznetsk"),
+ ("Asia/Novosibirsk", "Novosibirsk"),
+ ("Asia/Omsk", "Omsk"),
+ ("Asia/Oral", "Oral"),
+ ("Asia/Phnom_Penh", "Phnom_Penh"),
+ ("Asia/Pontianak", "Pontianak"),
+ ("Asia/Pyongyang", "Pyongyang"),
+ ("Asia/Qatar", "Qatar"),
+ ("Asia/Qostanay", "Qostanay"),
+ ("Asia/Qyzylorda", "Qyzylorda"),
+ ("Asia/Rangoon", "Rangoon"),
+ ("Asia/Riyadh", "Riyadh"),
+ ("Asia/Saigon", "Saigon"),
+ ("Asia/Sakhalin", "Sakhalin"),
+ ("Asia/Samarkand", "Samarkand"),
+ ("Asia/Seoul", "Seoul"),
+ ("Asia/Shanghai", "Shanghai"),
+ ("Asia/Singapore", "Singapore"),
+ ("Asia/Srednekolymsk", "Srednekolymsk"),
+ ("Asia/Taipei", "Taipei"),
+ ("Asia/Tashkent", "Tashkent"),
+ ("Asia/Tbilisi", "Tbilisi"),
+ ("Asia/Tehran", "Tehran"),
+ ("Asia/Tel_Aviv", "Tel_Aviv"),
+ ("Asia/Thimbu", "Thimbu"),
+ ("Asia/Thimphu", "Thimphu"),
+ ("Asia/Tokyo", "Tokyo"),
+ ("Asia/Tomsk", "Tomsk"),
+ ("Asia/Ujung_Pandang", "Ujung_Pandang"),
+ ("Asia/Ulaanbaatar", "Ulaanbaatar"),
+ ("Asia/Ulan_Bator", "Ulan_Bator"),
+ ("Asia/Urumqi", "Urumqi"),
+ ("Asia/Ust-Nera", "Ust-Nera"),
+ ("Asia/Vientiane", "Vientiane"),
+ ("Asia/Vladivostok", "Vladivostok"),
+ ("Asia/Yakutsk", "Yakutsk"),
+ ("Asia/Yangon", "Yangon"),
+ ("Asia/Yekaterinburg", "Yekaterinburg"),
+ ("Asia/Yerevan", "Yerevan"),
+ ],
+ ),
+ (
+ "Atlantic",
+ [
+ ("Atlantic/Azores", "Azores"),
+ ("Atlantic/Bermuda", "Bermuda"),
+ ("Atlantic/Canary", "Canary"),
+ ("Atlantic/Cape_Verde", "Cape_Verde"),
+ ("Atlantic/Faeroe", "Faeroe"),
+ ("Atlantic/Faroe", "Faroe"),
+ ("Atlantic/Jan_Mayen", "Jan_Mayen"),
+ ("Atlantic/Madeira", "Madeira"),
+ ("Atlantic/Reykjavik", "Reykjavik"),
+ ("Atlantic/South_Georgia", "South_Georgia"),
+ ("Atlantic/St_Helena", "St_Helena"),
+ ("Atlantic/Stanley", "Stanley"),
+ ],
+ ),
+ (
+ "Australia",
+ [
+ ("Australia/ACT", "ACT"),
+ ("Australia/Adelaide", "Adelaide"),
+ ("Australia/Brisbane", "Brisbane"),
+ ("Australia/Broken_Hill", "Broken_Hill"),
+ ("Australia/Canberra", "Canberra"),
+ ("Australia/Currie", "Currie"),
+ ("Australia/Darwin", "Darwin"),
+ ("Australia/Eucla", "Eucla"),
+ ("Australia/Hobart", "Hobart"),
+ ("Australia/LHI", "LHI"),
+ ("Australia/Lindeman", "Lindeman"),
+ ("Australia/Lord_Howe", "Lord_Howe"),
+ ("Australia/Melbourne", "Melbourne"),
+ ("Australia/NSW", "NSW"),
+ ("Australia/North", "North"),
+ ("Australia/Perth", "Perth"),
+ ("Australia/Queensland", "Queensland"),
+ ("Australia/South", "South"),
+ ("Australia/Sydney", "Sydney"),
+ ("Australia/Tasmania", "Tasmania"),
+ ("Australia/Victoria", "Victoria"),
+ ("Australia/West", "West"),
+ ("Australia/Yancowinna", "Yancowinna"),
+ ],
+ ),
+ (
+ "Brazil",
+ [
+ ("Brazil/Acre", "Acre"),
+ ("Brazil/DeNoronha", "DeNoronha"),
+ ("Brazil/East", "East"),
+ ("Brazil/West", "West"),
+ ],
+ ),
+ (
+ "Canada",
+ [
+ ("Canada/Atlantic", "Atlantic"),
+ ("Canada/Central", "Central"),
+ ("Canada/Eastern", "Eastern"),
+ ("Canada/Mountain", "Mountain"),
+ ("Canada/Newfoundland", "Newfoundland"),
+ ("Canada/Pacific", "Pacific"),
+ ("Canada/Saskatchewan", "Saskatchewan"),
+ ("Canada/Yukon", "Yukon"),
+ ],
+ ),
+ (
+ "Chile",
+ [
+ ("Chile/Continental", "Continental"),
+ ("Chile/EasterIsland", "EasterIsland"),
+ ],
+ ),
+ (
+ "Etc",
+ [
+ ("Etc/Greenwich", "Greenwich"),
+ ("Etc/UCT", "UCT"),
+ ("Etc/UTC", "UTC"),
+ ("Etc/Universal", "Universal"),
+ ("Etc/Zulu", "Zulu"),
+ ],
+ ),
+ (
+ "Europe",
+ [
+ ("Europe/Amsterdam", "Amsterdam"),
+ ("Europe/Andorra", "Andorra"),
+ ("Europe/Astrakhan", "Astrakhan"),
+ ("Europe/Athens", "Athens"),
+ ("Europe/Belfast", "Belfast"),
+ ("Europe/Belgrade", "Belgrade"),
+ ("Europe/Berlin", "Berlin"),
+ ("Europe/Bratislava", "Bratislava"),
+ ("Europe/Brussels", "Brussels"),
+ ("Europe/Bucharest", "Bucharest"),
+ ("Europe/Budapest", "Budapest"),
+ ("Europe/Busingen", "Busingen"),
+ ("Europe/Chisinau", "Chisinau"),
+ ("Europe/Copenhagen", "Copenhagen"),
+ ("Europe/Dublin", "Dublin"),
+ ("Europe/Gibraltar", "Gibraltar"),
+ ("Europe/Guernsey", "Guernsey"),
+ ("Europe/Helsinki", "Helsinki"),
+ ("Europe/Isle_of_Man", "Isle_of_Man"),
+ ("Europe/Istanbul", "Istanbul"),
+ ("Europe/Jersey", "Jersey"),
+ ("Europe/Kaliningrad", "Kaliningrad"),
+ ("Europe/Kiev", "Kiev"),
+ ("Europe/Kirov", "Kirov"),
+ ("Europe/Lisbon", "Lisbon"),
+ ("Europe/Ljubljana", "Ljubljana"),
+ ("Europe/London", "London"),
+ ("Europe/Luxembourg", "Luxembourg"),
+ ("Europe/Madrid", "Madrid"),
+ ("Europe/Malta", "Malta"),
+ ("Europe/Mariehamn", "Mariehamn"),
+ ("Europe/Minsk", "Minsk"),
+ ("Europe/Monaco", "Monaco"),
+ ("Europe/Moscow", "Moscow"),
+ ("Europe/Nicosia", "Nicosia"),
+ ("Europe/Oslo", "Oslo"),
+ ("Europe/Paris", "Paris"),
+ ("Europe/Podgorica", "Podgorica"),
+ ("Europe/Prague", "Prague"),
+ ("Europe/Riga", "Riga"),
+ ("Europe/Rome", "Rome"),
+ ("Europe/Samara", "Samara"),
+ ("Europe/San_Marino", "San_Marino"),
+ ("Europe/Sarajevo", "Sarajevo"),
+ ("Europe/Saratov", "Saratov"),
+ ("Europe/Simferopol", "Simferopol"),
+ ("Europe/Skopje", "Skopje"),
+ ("Europe/Sofia", "Sofia"),
+ ("Europe/Stockholm", "Stockholm"),
+ ("Europe/Tallinn", "Tallinn"),
+ ("Europe/Tirane", "Tirane"),
+ ("Europe/Tiraspol", "Tiraspol"),
+ ("Europe/Ulyanovsk", "Ulyanovsk"),
+ ("Europe/Uzhgorod", "Uzhgorod"),
+ ("Europe/Vaduz", "Vaduz"),
+ ("Europe/Vatican", "Vatican"),
+ ("Europe/Vienna", "Vienna"),
+ ("Europe/Vilnius", "Vilnius"),
+ ("Europe/Volgograd", "Volgograd"),
+ ("Europe/Warsaw", "Warsaw"),
+ ("Europe/Zagreb", "Zagreb"),
+ ("Europe/Zaporozhye", "Zaporozhye"),
+ ("Europe/Zurich", "Zurich"),
+ ],
+ ),
+ (
+ "Indian",
+ [
+ ("Indian/Antananarivo", "Antananarivo"),
+ ("Indian/Chagos", "Chagos"),
+ ("Indian/Christmas", "Christmas"),
+ ("Indian/Cocos", "Cocos"),
+ ("Indian/Comoro", "Comoro"),
+ ("Indian/Kerguelen", "Kerguelen"),
+ ("Indian/Mahe", "Mahe"),
+ ("Indian/Maldives", "Maldives"),
+ ("Indian/Mauritius", "Mauritius"),
+ ("Indian/Mayotte", "Mayotte"),
+ ("Indian/Reunion", "Reunion"),
+ ],
+ ),
+ (
+ "Mexico",
+ [
+ ("Mexico/BajaNorte", "BajaNorte"),
+ ("Mexico/BajaSur", "BajaSur"),
+ ("Mexico/General", "General"),
+ ],
+ ),
+ (
+ "Other",
+ [
+ ("CET", "CET"),
+ ("CST6CDT", "CST6CDT"),
+ ("Cuba", "Cuba"),
+ ("EET", "EET"),
+ ("EST", "EST"),
+ ("EST5EDT", "EST5EDT"),
+ ("Egypt", "Egypt"),
+ ("Eire", "Eire"),
+ ("GB", "GB"),
+ ("GB-Eire", "GB-Eire"),
+ ("Greenwich", "Greenwich"),
+ ("HST", "HST"),
+ ("Hongkong", "Hongkong"),
+ ("Iceland", "Iceland"),
+ ("Iran", "Iran"),
+ ("Israel", "Israel"),
+ ("Jamaica", "Jamaica"),
+ ("Japan", "Japan"),
+ ("Kwajalein", "Kwajalein"),
+ ("Libya", "Libya"),
+ ("MET", "MET"),
+ ("MST", "MST"),
+ ("MST7MDT", "MST7MDT"),
+ ("NZ", "NZ"),
+ ("NZ-CHAT", "NZ-CHAT"),
+ ("Navajo", "Navajo"),
+ ("PRC", "PRC"),
+ ("PST8PDT", "PST8PDT"),
+ ("Poland", "Poland"),
+ ("Portugal", "Portugal"),
+ ("ROC", "ROC"),
+ ("ROK", "ROK"),
+ ("Singapore", "Singapore"),
+ ("Turkey", "Turkey"),
+ ("UCT", "UCT"),
+ ("UTC", "UTC"),
+ ("Universal", "Universal"),
+ ("W-SU", "W-SU"),
+ ("WET", "WET"),
+ ("Zulu", "Zulu"),
+ ],
+ ),
+ (
+ "Pacific",
+ [
+ ("Pacific/Apia", "Apia"),
+ ("Pacific/Auckland", "Auckland"),
+ ("Pacific/Bougainville", "Bougainville"),
+ ("Pacific/Chatham", "Chatham"),
+ ("Pacific/Chuuk", "Chuuk"),
+ ("Pacific/Easter", "Easter"),
+ ("Pacific/Efate", "Efate"),
+ ("Pacific/Enderbury", "Enderbury"),
+ ("Pacific/Fakaofo", "Fakaofo"),
+ ("Pacific/Fiji", "Fiji"),
+ ("Pacific/Funafuti", "Funafuti"),
+ ("Pacific/Galapagos", "Galapagos"),
+ ("Pacific/Gambier", "Gambier"),
+ ("Pacific/Guadalcanal", "Guadalcanal"),
+ ("Pacific/Guam", "Guam"),
+ ("Pacific/Honolulu", "Honolulu"),
+ ("Pacific/Johnston", "Johnston"),
+ ("Pacific/Kanton", "Kanton"),
+ ("Pacific/Kiritimati", "Kiritimati"),
+ ("Pacific/Kosrae", "Kosrae"),
+ ("Pacific/Kwajalein", "Kwajalein"),
+ ("Pacific/Majuro", "Majuro"),
+ ("Pacific/Marquesas", "Marquesas"),
+ ("Pacific/Midway", "Midway"),
+ ("Pacific/Nauru", "Nauru"),
+ ("Pacific/Niue", "Niue"),
+ ("Pacific/Norfolk", "Norfolk"),
+ ("Pacific/Noumea", "Noumea"),
+ ("Pacific/Pago_Pago", "Pago_Pago"),
+ ("Pacific/Palau", "Palau"),
+ ("Pacific/Pitcairn", "Pitcairn"),
+ ("Pacific/Pohnpei", "Pohnpei"),
+ ("Pacific/Ponape", "Ponape"),
+ ("Pacific/Port_Moresby", "Port_Moresby"),
+ ("Pacific/Rarotonga", "Rarotonga"),
+ ("Pacific/Saipan", "Saipan"),
+ ("Pacific/Samoa", "Samoa"),
+ ("Pacific/Tahiti", "Tahiti"),
+ ("Pacific/Tarawa", "Tarawa"),
+ ("Pacific/Tongatapu", "Tongatapu"),
+ ("Pacific/Truk", "Truk"),
+ ("Pacific/Wake", "Wake"),
+ ("Pacific/Wallis", "Wallis"),
+ ("Pacific/Yap", "Yap"),
+ ],
+ ),
+ (
+ "US",
+ [
+ ("US/Alaska", "Alaska"),
+ ("US/Aleutian", "Aleutian"),
+ ("US/Arizona", "Arizona"),
+ ("US/Central", "Central"),
+ ("US/East-Indiana", "East-Indiana"),
+ ("US/Eastern", "Eastern"),
+ ("US/Hawaii", "Hawaii"),
+ ("US/Indiana-Starke", "Indiana-Starke"),
+ ("US/Michigan", "Michigan"),
+ ("US/Mountain", "Mountain"),
+ ("US/Pacific", "Pacific"),
+ ("US/Samoa", "Samoa"),
+ ],
+ ),
+ ],
+ default="Asia/Ho_Chi_Minh",
+ max_length=50,
+ verbose_name="location",
+ ),
),
]
diff --git a/judge/ml/collab_filter.py b/judge/ml/collab_filter.py
index 1b0a1db..d19c5e5 100644
--- a/judge/ml/collab_filter.py
+++ b/judge/ml/collab_filter.py
@@ -1,9 +1,10 @@
import numpy as np
-from django.conf import settings
import os
-from django.core.cache import cache
import hashlib
+from django.core.cache import cache
+from django.conf import settings
+
from judge.caching import cache_wrapper
@@ -13,14 +14,13 @@ class CollabFilter:
# name = 'collab_filter' or 'collab_filter_time'
def __init__(self, name):
- embeddings = np.load(
+ self.embeddings = np.load(
os.path.join(settings.ML_OUTPUT_PATH, name + "/embeddings.npz"),
allow_pickle=True,
)
- arr0, arr1 = embeddings.files
+ _, problem_arr = self.embeddings.files
self.name = name
- self.user_embeddings = embeddings[arr0]
- self.problem_embeddings = embeddings[arr1]
+ self.problem_embeddings = self.embeddings[problem_arr]
def __str__(self):
return self.name
@@ -44,18 +44,32 @@ class CollabFilter:
scores = u.dot(V.T)
return scores
+ def _get_embedding_version(self):
+ first_problem = self.problem_embeddings[0]
+ array_bytes = first_problem.tobytes()
+ hash_object = hashlib.sha256(array_bytes)
+ hash_bytes = hash_object.digest()
+ return hash_bytes.hex()[:5]
+
+ @cache_wrapper(prefix="CFgue", timeout=86400)
+ def _get_user_embedding(self, user_id, embedding_version):
+ user_arr, _ = self.embeddings.files
+ user_embeddings = self.embeddings[user_arr]
+ if user_id >= len(user_embeddings):
+ return user_embeddings[0]
+ return user_embeddings[user_id]
+
+ def get_user_embedding(self, user_id):
+ version = self._get_embedding_version()
+ return self._get_user_embedding(user_id, version)
+
@cache_wrapper(prefix="user_recommendations", timeout=3600)
- def user_recommendations(self, user, problems, measure=DOT, limit=None):
- uid = user.id
- if uid >= len(self.user_embeddings):
- uid = 0
- scores = self.compute_scores(
- self.user_embeddings[uid], self.problem_embeddings, measure
- )
+ def user_recommendations(self, user_id, problems, measure=DOT, limit=None):
+ user_embedding = self.get_user_embedding(user_id)
+ scores = self.compute_scores(user_embedding, self.problem_embeddings, measure)
res = [] # [(score, problem)]
for pid in problems:
- # pid = problem.id
if pid < len(scores):
res.append((scores[pid], pid))
diff --git a/judge/models/contest.py b/judge/models/contest.py
index bda262d..1432d94 100644
--- a/judge/models/contest.py
+++ b/judge/models/contest.py
@@ -99,11 +99,13 @@ class Contest(models.Model, PageVotable, Bookmarkable):
)
authors = models.ManyToManyField(
Profile,
+ verbose_name=_("authors"),
help_text=_("These users will be able to edit the contest."),
related_name="authors+",
)
curators = models.ManyToManyField(
Profile,
+ verbose_name=_("curators"),
help_text=_(
"These users will be able to edit the contest, "
"but will not be listed as authors."
@@ -113,6 +115,7 @@ class Contest(models.Model, PageVotable, Bookmarkable):
)
testers = models.ManyToManyField(
Profile,
+ verbose_name=_("testers"),
help_text=_(
"These users will be able to view the contest, " "but not edit it."
),
diff --git a/judge/models/problem.py b/judge/models/problem.py
index 47741e9..98e477b 100644
--- a/judge/models/problem.py
+++ b/judge/models/problem.py
@@ -1,6 +1,5 @@
import errno
from operator import attrgetter
-from math import sqrt
from django.conf import settings
from django.contrib.contenttypes.fields import GenericRelation
@@ -557,7 +556,7 @@ class Problem(models.Model, PageVotable, Bookmarkable):
def save(self, *args, **kwargs):
super(Problem, self).save(*args, **kwargs)
- if self.code != self.__original_code:
+ if self.__original_code and self.code != self.__original_code:
if hasattr(self, "data_files") or self.pdf_description:
try:
problem_data_storage.rename(self.__original_code, self.code)
diff --git a/judge/models/problem_data.py b/judge/models/problem_data.py
index d61b528..b04d2ab 100644
--- a/judge/models/problem_data.py
+++ b/judge/models/problem_data.py
@@ -162,10 +162,10 @@ class ProblemData(models.Model):
get_file_cachekey(file),
)
cache.delete(cache_key)
- except BadZipFile:
+ except (BadZipFile, FileNotFoundError):
pass
- if self.zipfile != self.__original_zipfile and self.__original_zipfile:
- self.__original_zipfile.delete(save=False)
+ if self.zipfile != self.__original_zipfile:
+ self.__original_zipfile.delete(save=False)
return super(ProblemData, self).save(*args, **kwargs)
def has_yml(self):
diff --git a/judge/tasks/import_users.py b/judge/tasks/import_users.py
index 5584687..07acd4e 100644
--- a/judge/tasks/import_users.py
+++ b/judge/tasks/import_users.py
@@ -1,5 +1,4 @@
import csv
-from tempfile import mktemp
import re
from django.conf import settings
diff --git a/judge/utils/fine_uploader.py b/judge/utils/fine_uploader.py
index 2a22ccf..8f64d78 100644
--- a/judge/utils/fine_uploader.py
+++ b/judge/utils/fine_uploader.py
@@ -5,7 +5,6 @@ from django import forms
from django.forms import ClearableFileInput
import os, os.path
-import tempfile
import shutil
__all__ = ("handle_upload", "save_upload", "FineUploadForm", "FineUploadFileInput")
diff --git a/judge/utils/problem_data.py b/judge/utils/problem_data.py
index eb56229..023c0be 100644
--- a/judge/utils/problem_data.py
+++ b/judge/utils/problem_data.py
@@ -2,7 +2,6 @@ import hashlib
import json
import os
import re
-import shutil
import yaml
import zipfile
@@ -13,6 +12,8 @@ from django.urls import reverse
from django.utils.translation import gettext as _
from django.core.cache import cache
+from judge.logging import log_exception
+
if os.altsep:
def split_path_first(
@@ -324,11 +325,13 @@ def get_problem_case(problem, files):
settings.DMOJ_PROBLEM_DATA_ROOT, str(problem.data_files.zipfile)
)
if not os.path.exists(archive_path):
- raise Exception('archive file "%s" does not exist' % archive_path)
+ log_exception('archive file "%s" does not exist' % archive_path)
+ return {}
try:
archive = zipfile.ZipFile(archive_path, "r")
except zipfile.BadZipfile:
- raise Exception('bad archive: "%s"' % archive_path)
+ log_exception('bad archive: "%s"' % archive_path)
+ return {}
for file in uncached_files:
cache_key = "problem_archive:%s:%s" % (problem.code, get_file_cachekey(file))
diff --git a/judge/utils/problems.py b/judge/utils/problems.py
index 67ef163..0b69267 100644
--- a/judge/utils/problems.py
+++ b/judge/utils/problems.py
@@ -1,8 +1,8 @@
from collections import defaultdict
from math import e
-import os, zipfile
-from datetime import datetime
+from datetime import datetime, timedelta
import random
+from enum import Enum
from django.conf import settings
from django.core.cache import cache
@@ -10,6 +10,7 @@ from django.db.models import Case, Count, ExpressionWrapper, F, Max, Q, When
from django.db.models.fields import FloatField
from django.utils import timezone
from django.utils.translation import gettext as _, gettext_noop
+from django.http import Http404
from judge.models import Problem, Submission
from judge.ml.collab_filter import CollabFilter
@@ -249,3 +250,72 @@ def finished_submission(sub):
keys += ["contest_complete:%d" % participation.id]
keys += ["contest_attempted:%d" % participation.id]
cache.delete_many(keys)
+
+
+class RecommendationType(Enum):
+ HOT_PROBLEM = 1
+ CF_DOT = 2
+ CF_COSINE = 3
+ CF_TIME_DOT = 4
+ CF_TIME_COSINE = 5
+
+
+# Return a list of list. Each inner list correspond to each type in types
+def get_user_recommended_problems(
+ user_id,
+ problem_ids,
+ recommendation_types,
+ limits,
+ shuffle=False,
+):
+ cf_model = CollabFilter("collab_filter")
+ cf_time_model = CollabFilter("collab_filter_time")
+
+ def get_problem_ids_from_type(rec_type, limit):
+ if type(rec_type) == int:
+ try:
+ rec_type = RecommendationType(rec_type)
+ except ValueError:
+ raise Http404()
+ if rec_type == RecommendationType.HOT_PROBLEM:
+ return [
+ problem.id
+ for problem in hot_problems(timedelta(days=7), limit)
+ if problem.id in set(problem_ids)
+ ]
+ if rec_type == RecommendationType.CF_DOT:
+ return cf_model.user_recommendations(
+ user_id, problem_ids, cf_model.DOT, limit
+ )
+ if rec_type == RecommendationType.CF_COSINE:
+ return cf_model.user_recommendations(
+ user_id, problem_ids, cf_model.COSINE, limit
+ )
+ if rec_type == RecommendationType.CF_TIME_DOT:
+ return cf_time_model.user_recommendations(
+ user_id, problem_ids, cf_model.DOT, limit
+ )
+ if rec_type == RecommendationType.CF_TIME_COSINE:
+ return cf_time_model.user_recommendations(
+ user_id, problem_ids, cf_model.COSINE, limit
+ )
+ return []
+
+ all_problems = []
+ for rec_type, limit in zip(recommendation_types, limits):
+ all_problems += get_problem_ids_from_type(rec_type, limit)
+ if shuffle:
+ seed = datetime.now().strftime("%d%m%Y")
+ random.Random(seed).shuffle(all_problems)
+
+ # deduplicate problems
+ res = []
+ used_pid = set()
+
+ for obj in all_problems:
+ if type(obj) == tuple:
+ obj = obj[1]
+ if obj not in used_pid:
+ res.append(obj)
+ used_pid.add(obj)
+ return res
diff --git a/judge/views/contests.py b/judge/views/contests.py
index a84d98b..80e5fb5 100644
--- a/judge/views/contests.py
+++ b/judge/views/contests.py
@@ -144,7 +144,11 @@ class ContestList(
context_object_name = "past_contests"
all_sorts = frozenset(("name", "user_count", "start_time"))
default_desc = frozenset(("name", "user_count"))
- default_sort = "-start_time"
+
+ def get_default_sort_order(self, request):
+ if request.GET.get("contest") and settings.ENABLE_FTS:
+ return "-relevance"
+ return "-start_time"
@cached_property
def _now(self):
@@ -157,7 +161,7 @@ class ContestList(
if request.GET.get("show_orgs"):
self.show_orgs = 1
- if "orgs" in self.request.GET and self.request.profile:
+ if self.request.GET.get("orgs") and self.request.profile:
try:
self.org_query = list(map(int, request.GET.getlist("orgs")))
if not self.request.user.is_superuser:
@@ -165,8 +169,10 @@ class ContestList(
i
for i in self.org_query
if i
- in self.request.profile.organizations.values_list(
- "id", flat=True
+ in set(
+ self.request.profile.organizations.values_list(
+ "id", flat=True
+ )
)
]
except ValueError:
@@ -181,7 +187,7 @@ class ContestList(
.prefetch_related("tags", "organizations", "authors", "curators", "testers")
)
- if "contest" in self.request.GET:
+ if self.request.GET.get("contest"):
self.contest_query = query = " ".join(
self.request.GET.getlist("contest")
).strip()
@@ -249,10 +255,7 @@ class ContestList(
context["org_query"] = self.org_query
context["show_orgs"] = int(self.show_orgs)
if self.request.profile:
- if self.request.user.is_superuser:
- context["organizations"] = Organization.objects.all()
- else:
- context["organizations"] = self.request.profile.organizations.all()
+ context["organizations"] = self.request.profile.organizations.all()
context["page_type"] = "list"
context.update(self.get_sort_context())
context.update(self.get_sort_paginate_context())
@@ -419,7 +422,14 @@ class ContestDetail(
return []
res = []
for organization in self.object.organizations.all():
+ can_edit = False
if self.request.profile.can_edit_organization(organization):
+ can_edit = True
+ if self.request.profile in organization and self.object.is_editable_by(
+ self.request.user
+ ):
+ can_edit = True
+ if can_edit:
res.append(organization)
return res
@@ -441,16 +451,32 @@ class ContestDetail(
.add_i18n_name(self.request.LANGUAGE_CODE)
)
context["editable_organizations"] = self.get_editable_organizations()
+ context["is_clonable"] = is_contest_clonable(self.request, self.object)
return context
-class ContestClone(
- ContestMixin, PermissionRequiredMixin, TitleMixin, SingleObjectFormView
-):
+def is_contest_clonable(request, contest):
+ if not request.profile:
+ return False
+ if not Organization.objects.filter(admins=request.profile).exists():
+ return False
+ if request.user.has_perm("judge.clone_contest"):
+ return True
+ if contest.ended:
+ return True
+ return False
+
+
+class ContestClone(ContestMixin, TitleMixin, SingleObjectFormView):
title = _("Clone Contest")
template_name = "contest/clone.html"
form_class = ContestCloneForm
- permission_required = "judge.clone_contest"
+
+ def get_object(self, queryset=None):
+ contest = super().get_object(queryset)
+ if not is_contest_clonable(self.request, contest):
+ raise Http404()
+ return contest
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
@@ -475,6 +501,7 @@ class ContestClone(
contest.is_visible = False
contest.user_count = 0
contest.key = form.cleaned_data["key"]
+ contest.is_rated = False
contest.save()
contest.tags.set(tags)
diff --git a/judge/views/internal.py b/judge/views/internal.py
index eff02a4..060a2c3 100644
--- a/judge/views/internal.py
+++ b/judge/views/internal.py
@@ -6,6 +6,7 @@ from django.utils.translation import gettext as _, gettext_lazy
from django.db.models import Count, Q
from django.http import HttpResponseForbidden
from django.urls import reverse
+from django.shortcuts import render
from judge.utils.diggpaginator import DiggPaginator
from judge.models import VolunteerProblemVote, Problem
@@ -21,7 +22,7 @@ class InternalView(object):
class InternalProblem(InternalView, ListView):
model = Problem
title = _("Internal problems")
- template_name = "internal/problem.html"
+ template_name = "internal/problem/problem.html"
paginate_by = 100
context_object_name = "problems"
@@ -63,6 +64,28 @@ class InternalProblem(InternalView, ListView):
return context
+def get_problem_votes(request):
+ if not request.user.is_superuser:
+ return HttpResponseForbidden()
+ try:
+ problem = Problem.objects.get(id=request.GET.get("id"))
+ except:
+ return HttpResponseForbidden()
+ votes = (
+ problem.volunteer_user_votes.select_related("voter")
+ .prefetch_related("types")
+ .order_by("id")
+ )
+ return render(
+ request,
+ "internal/problem/votes.html",
+ {
+ "problem": problem,
+ "votes": votes,
+ },
+ )
+
+
class RequestTimeMixin(object):
def get_requests_data(self):
logger = logging.getLogger(self.log_name)
diff --git a/judge/views/organization.py b/judge/views/organization.py
index be80203..eff02d4 100644
--- a/judge/views/organization.py
+++ b/judge/views/organization.py
@@ -73,6 +73,7 @@ from judge.views.problem import ProblemList
from judge.views.contests import ContestList
from judge.views.submission import AllSubmissions, SubmissionsListBase
from judge.views.feed import FeedView
+from judge.tasks import rescore_contest
__all__ = [
"OrganizationList",
@@ -394,7 +395,7 @@ class OrganizationContestMixin(
model = Contest
def is_contest_editable(self, request, contest):
- return request.profile in contest.authors.all() or self.can_edit_organization(
+ return contest.is_editable_by(request.user) or self.can_edit_organization(
self.organization
)
@@ -947,7 +948,7 @@ class EditOrganizationContest(
def get_content_title(self):
href = reverse("contest_view", args=[self.contest.key])
- return mark_safe(f'Edit {self.contest.key}')
+ return mark_safe(_("Edit") + f' {self.contest.key}')
def get_object(self):
return self.contest
@@ -960,6 +961,19 @@ class EditOrganizationContest(
self.object.organizations.add(self.organization)
self.object.is_organization_private = True
self.object.save()
+
+ if any(
+ f in form.changed_data
+ for f in (
+ "start_time",
+ "end_time",
+ "time_limit",
+ "format_config",
+ "format_name",
+ "freeze_after",
+ )
+ ):
+ transaction.on_commit(rescore_contest.s(self.object.key).delay)
return res
def get_problem_formset(self, post=False):
diff --git a/judge/views/problem.py b/judge/views/problem.py
index 0bf304b..3b7cd84 100644
--- a/judge/views/problem.py
+++ b/judge/views/problem.py
@@ -1,10 +1,8 @@
import logging
import os
import shutil
-from datetime import timedelta, datetime
from operator import itemgetter
from random import randrange
-import random
from copy import deepcopy
from django.core.cache import cache
@@ -77,6 +75,8 @@ from judge.utils.problems import (
user_attempted_ids,
user_completed_ids,
get_related_problems,
+ get_user_recommended_problems,
+ RecommendationType,
)
from judge.utils.strings import safe_float_or_none, safe_int_or_none
from judge.utils.tickets import own_ticket_filter
@@ -834,24 +834,34 @@ class ProblemFeed(ProblemList, FeedView):
title = _("Problem feed")
feed_type = None
- # arr = [[], [], ..]
- def merge_recommendation(self, arr):
- seed = datetime.now().strftime("%d%m%Y")
- merged_array = []
- for a in arr:
- merged_array += a
- random.Random(seed).shuffle(merged_array)
+ def get_recommended_problem_ids(self, queryset):
+ user_id = self.request.profile.id
+ problem_ids = queryset.values_list("id", flat=True)
+ rec_types = [
+ RecommendationType.CF_DOT,
+ RecommendationType.CF_COSINE,
+ RecommendationType.CF_TIME_DOT,
+ RecommendationType.CF_TIME_COSINE,
+ RecommendationType.HOT_PROBLEM,
+ ]
+ limits = [100, 100, 100, 100, 20]
+ shuffle = True
- res = []
- used_pid = set()
+ allow_debug_type = (
+ self.request.user.is_impersonate or self.request.user.is_superuser
+ )
+ if allow_debug_type and "debug_type" in self.request.GET:
+ try:
+ debug_type = int(self.request.GET.get("debug_type"))
+ except ValueError:
+ raise Http404()
+ rec_types = [debug_type]
+ limits = [100]
+ shuffle = False
- for obj in merged_array:
- if type(obj) == tuple:
- obj = obj[1]
- if obj not in used_pid:
- res.append(obj)
- used_pid.add(obj)
- return res
+ return get_user_recommended_problems(
+ user_id, problem_ids, rec_types, limits, shuffle
+ )
def get_queryset(self):
if self.feed_type == "volunteer":
@@ -885,40 +895,8 @@ class ProblemFeed(ProblemList, FeedView):
if not settings.ML_OUTPUT_PATH or not user:
return queryset.order_by("?").add_i18n_name(self.request.LANGUAGE_CODE)
- cf_model = CollabFilter("collab_filter")
- cf_time_model = CollabFilter("collab_filter_time")
+ q = self.get_recommended_problem_ids(queryset)
- queryset = queryset.values_list("id", flat=True)
- hot_problems_recommendations = [
- problem.id
- for problem in hot_problems(timedelta(days=7), 20)
- if problem.id in set(queryset)
- ]
-
- q = self.merge_recommendation(
- [
- cf_model.user_recommendations(user, queryset, cf_model.DOT, 100),
- cf_model.user_recommendations(
- user,
- queryset,
- cf_model.COSINE,
- 100,
- ),
- cf_time_model.user_recommendations(
- user,
- queryset,
- cf_time_model.COSINE,
- 100,
- ),
- cf_time_model.user_recommendations(
- user,
- queryset,
- cf_time_model.DOT,
- 100,
- ),
- hot_problems_recommendations,
- ]
- )
queryset = Problem.objects.filter(id__in=q)
queryset = queryset.add_i18n_name(self.request.LANGUAGE_CODE)
diff --git a/judge/views/problem_data.py b/judge/views/problem_data.py
index 121d570..0525395 100644
--- a/judge/views/problem_data.py
+++ b/judge/views/problem_data.py
@@ -56,6 +56,7 @@ from judge.utils.fine_uploader import (
FineUploadForm,
)
from judge.views.problem import ProblemMixin
+from judge.logging import log_exception
mimetypes.init()
mimetypes.add_type("application/x-yaml", ".yml")
@@ -249,6 +250,9 @@ class ProblemDataView(TitleMixin, ProblemManagerMixin):
return ZipFile(data.zipfile.path).namelist()
except BadZipfile:
return []
+ except FileNotFoundError as e:
+ log_exception(e)
+ return []
return []
def get_context_data(self, **kwargs):
diff --git a/judge/views/resolver.py b/judge/views/resolver.py
index cf8a193..84e5dff 100644
--- a/judge/views/resolver.py
+++ b/judge/views/resolver.py
@@ -1,6 +1,6 @@
from django.views.generic import TemplateView
from django.utils.translation import gettext as _
-from django.http import HttpResponseForbidden
+from django.http import HttpResponseForbidden, JsonResponse
from judge.models import Contest
from django.utils.safestring import mark_safe
@@ -21,7 +21,7 @@ class Resolver(TemplateView):
hidden_subtasks = self.contest.format.get_hidden_subtasks()
num_problems = len(problems)
problem_sub = [0] * num_problems
- sub_frozen = [0] * num_problems
+ sub_frozen = [[] for _ in range(num_problems)]
problems_json = {str(i): {} for i in range(1, num_problems + 1)}
users = {}
@@ -126,10 +126,8 @@ class Resolver(TemplateView):
for i in hidden_subtasks:
order = id_to_order[i]
- if hidden_subtasks[i]:
- sub_frozen[order - 1] = min(hidden_subtasks[i])
- else:
- sub_frozen[order - 1] = problem_sub[order - 1] + 1
+ sub_frozen[order - 1] = list(hidden_subtasks[i])
+
return {
"problem_sub": problem_sub,
"sub_frozen": sub_frozen,
@@ -143,8 +141,15 @@ class Resolver(TemplateView):
return context
def get(self, request, *args, **kwargs):
- if request.user.is_superuser:
- self.contest = Contest.objects.get(key=kwargs.get("contest"))
- if self.contest.format.has_hidden_subtasks:
- return super(Resolver, self).get(request, *args, **kwargs)
- return HttpResponseForbidden()
+ if not request.user.is_superuser:
+ return HttpResponseForbidden()
+ self.contest = Contest.objects.get(key=kwargs.get("contest"))
+ if not self.contest.format.has_hidden_subtasks:
+ return HttpResponseForbidden()
+
+ if self.request.GET.get("json"):
+ json_dumps_params = {"ensure_ascii": False}
+ return JsonResponse(
+ self.get_contest_json(), json_dumps_params=json_dumps_params
+ )
+ return super(Resolver, self).get(request, *args, **kwargs)
diff --git a/judge/views/submission.py b/judge/views/submission.py
index eae961b..26300b0 100644
--- a/judge/views/submission.py
+++ b/judge/views/submission.py
@@ -1,6 +1,5 @@
import json
import os.path
-import zipfile
from operator import attrgetter
from django.conf import settings
@@ -196,8 +195,8 @@ def get_cases_data(submission):
continue
count += 1
problem_data[count] = {
- "input": case_data[case.input_file] if case.input_file else "",
- "answer": case_data[case.output_file] if case.output_file else "",
+ "input": case_data.get(case.input_file, "") if case.input_file else "",
+ "answer": case_data.get(case.output_file, "") if case.output_file else "",
}
return problem_data
diff --git a/locale/vi/LC_MESSAGES/django.po b/locale/vi/LC_MESSAGES/django.po
index 4497f98..338f920 100644
--- a/locale/vi/LC_MESSAGES/django.po
+++ b/locale/vi/LC_MESSAGES/django.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: lqdoj2\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-09-17 12:21+0700\n"
+"POT-Creation-Date: 2023-11-02 08:11+0700\n"
"PO-Revision-Date: 2021-07-20 03:44\n"
"Last-Translator: Icyene\n"
"Language-Team: Vietnamese\n"
@@ -18,58 +18,75 @@ msgstr ""
"X-Crowdin-Project-ID: 466004\n"
"X-Crowdin-File-ID: 5\n"
-#: chat_box/models.py:39 chat_box/models.py:64 chat_box/models.py:79
-#: judge/admin/interface.py:150 judge/models/contest.py:641
-#: judge/models/contest.py:847 judge/models/course.py:115
-#: judge/models/profile.py:390 judge/models/profile.py:468
+#: chat_box/models.py:54 chat_box/models.py:80 chat_box/models.py:96
+#: judge/admin/interface.py:150 judge/models/contest.py:647
+#: judge/models/contest.py:853 judge/models/course.py:115
+#: judge/models/profile.py:433 judge/models/profile.py:511
msgid "user"
msgstr "người dùng"
-#: chat_box/models.py:41 judge/models/comment.py:44 judge/models/comment.py:189
+#: chat_box/models.py:56 judge/models/comment.py:44
+#: judge/models/notification.py:17
msgid "posted time"
msgstr "thời gian đăng"
-#: chat_box/models.py:43 judge/models/comment.py:49
+#: chat_box/models.py:58 judge/models/comment.py:49
msgid "body of comment"
msgstr "nội dung bình luận"
-#: chat_box/models.py:68
+#: chat_box/models.py:84
msgid "last seen"
msgstr "xem lần cuối"
-#: chat_box/views.py:47
+#: chat_box/views.py:44
msgid "LQDOJ Chat"
msgstr ""
-#: dmoj/settings.py:365
+#: chat_box/views.py:417
+msgid "Recent"
+msgstr "Gần đây"
+
+#: chat_box/views.py:421 templates/base.html:187
+#: templates/comments/content-list.html:78
+#: templates/contest/contest-list-tabs.html:4
+#: templates/contest/ranking-table.html:47 templates/internal/problem.html:62
+#: templates/organization/org-left-sidebar.html:12
+#: templates/problem/left-sidebar.html:6
+#: templates/problem/problem-list-tabs.html:6
+#: templates/submission/info-base.html:12 templates/submission/list.html:395
+#: templates/submission/submission-list-tabs.html:15
+msgid "Admin"
+msgstr "Admin"
+
+#: dmoj/settings.py:364
msgid "Vietnamese"
msgstr "Tiếng Việt"
-#: dmoj/settings.py:366
+#: dmoj/settings.py:365
msgid "English"
msgstr ""
-#: dmoj/urls.py:108
+#: dmoj/urls.py:109
msgid "Activation key invalid"
msgstr "Mã kích hoạt không hợp lệ"
-#: dmoj/urls.py:113
+#: dmoj/urls.py:114
msgid "Register"
msgstr "Đăng ký"
-#: dmoj/urls.py:120
+#: dmoj/urls.py:121
msgid "Registration Completed"
msgstr "Đăng ký hoàn thành"
-#: dmoj/urls.py:128
+#: dmoj/urls.py:129
msgid "Registration not allowed"
msgstr "Đăng ký không thành công"
-#: dmoj/urls.py:136
+#: dmoj/urls.py:137
msgid "Login"
msgstr "Đăng nhập"
-#: dmoj/urls.py:224 templates/base.html:218
+#: dmoj/urls.py:225 templates/base.html:111
#: templates/organization/org-left-sidebar.html:2
msgid "Home"
msgstr "Trang chủ"
@@ -99,7 +116,7 @@ msgid "Included contests"
msgstr ""
#: judge/admin/contest.py:79 judge/admin/volunteer.py:54
-#: templates/contest/clarification.html:42 templates/contest/contest.html:100
+#: templates/contest/clarification.html:42 templates/contest/contest.html:105
#: templates/contest/moss.html:41 templates/internal/left-sidebar.html:2
#: templates/internal/problem.html:40 templates/problem/list.html:17
#: templates/problem/list.html:34 templates/problem/list.html:153
@@ -119,9 +136,9 @@ msgstr ""
msgid "Details"
msgstr "Chi tiết"
-#: judge/admin/contest.py:185 templates/contest/list.html:265
-#: templates/contest/list.html:306 templates/contest/list.html:351
-#: templates/contest/list.html:388
+#: judge/admin/contest.py:185 templates/contest/list.html:263
+#: templates/contest/list.html:304 templates/contest/list.html:349
+#: templates/contest/list.html:386
msgid "Format"
msgstr "Thể thức"
@@ -130,23 +147,11 @@ msgstr "Thể thức"
msgid "Rating"
msgstr ""
-#: templates/markdown_editor/markdown_editor.html:107
-msgid "Insert Image"
-msgstr "Chèn hình ảnh"
-
-#: templates/markdown_editor/markdown_editor.html:110
-msgid "From the web"
-msgstr "Từ web"
-
-#: templates/markdown_editor/markdown_editor.html:116
-msgid "From your computer"
-msgstr "Từ máy tính của bạn"
-
#: judge/admin/contest.py:201
msgid "Access"
msgstr "Truy cập"
-#: judge/admin/contest.py:211 judge/admin/problem.py:218
+#: judge/admin/contest.py:211 judge/admin/problem.py:220
msgid "Justice"
msgstr "Xử phạt"
@@ -190,7 +195,7 @@ msgstr "Tính toán lại kết quả"
msgid "username"
msgstr "tên đăng nhập"
-#: judge/admin/contest.py:503 templates/base.html:341
+#: judge/admin/contest.py:503 templates/base.html:239
msgid "virtual"
msgstr "ảo"
@@ -218,95 +223,96 @@ msgstr ""
msgid "diff"
msgstr ""
-#: judge/admin/organization.py:61 judge/admin/problem.py:275
+#: judge/admin/organization.py:61 judge/admin/problem.py:277
#: judge/admin/profile.py:117
msgid "View on site"
msgstr "Xem trên trang"
-#: judge/admin/problem.py:53
+#: judge/admin/problem.py:55
msgid "Describe the changes you made (optional)"
msgstr "Mô tả các thay đổi (tùy chọn)"
-#: judge/admin/problem.py:109
+#: judge/admin/problem.py:111
msgid "Memory unit"
msgstr "Đơn vị bộ nhớ"
-#: judge/admin/problem.py:211
+#: judge/admin/problem.py:213
msgid "Social Media"
msgstr "Mạng Xã Hội"
-#: judge/admin/problem.py:214
+#: judge/admin/problem.py:216
msgid "Taxonomy"
msgstr ""
-#: judge/admin/problem.py:215 judge/admin/problem.py:438
-#: templates/contest/contest.html:101 templates/problem/data.html:533
+#: judge/admin/problem.py:217 judge/admin/problem.py:452
+#: templates/contest/contest.html:106
+#: templates/contest/contests_summary.html:41 templates/problem/data.html:533
#: templates/problem/list.html:22 templates/problem/list.html:48
#: templates/user/base-users-table.html:10 templates/user/user-about.html:36
#: templates/user/user-about.html:52 templates/user/user-problems.html:58
msgid "Points"
msgstr "Điểm"
-#: judge/admin/problem.py:216
+#: judge/admin/problem.py:218
msgid "Limits"
msgstr "Giới hạn"
-#: judge/admin/problem.py:217 judge/admin/submission.py:351
-#: templates/base.html:254 templates/stats/tab.html:4
+#: judge/admin/problem.py:219 judge/admin/submission.py:351
+#: templates/base.html:155 templates/stats/tab.html:4
#: templates/submission/list.html:347
msgid "Language"
msgstr "Ngôn ngữ"
-#: judge/admin/problem.py:219
+#: judge/admin/problem.py:221
msgid "History"
msgstr "Lịch sử"
-#: judge/admin/problem.py:271 templates/problem/list-base.html:99
+#: judge/admin/problem.py:273 templates/problem/list-base.html:93
msgid "Authors"
msgstr "Các tác giả"
-#: judge/admin/problem.py:292
+#: judge/admin/problem.py:294
#, python-format
msgid "%d problem successfully marked as public."
msgid_plural "%d problems successfully marked as public."
msgstr[0] "%d bài tập đã được đánh dấu công khai."
-#: judge/admin/problem.py:299
+#: judge/admin/problem.py:301
msgid "Mark problems as public"
msgstr "Công khai bài tập"
-#: judge/admin/problem.py:308
+#: judge/admin/problem.py:310
#, python-format
msgid "%d problem successfully marked as private."
msgid_plural "%d problems successfully marked as private."
msgstr[0] "%d bài tập đã được đánh dấu riêng tư."
-#: judge/admin/problem.py:315
+#: judge/admin/problem.py:317
msgid "Mark problems as private"
msgstr "Đánh dấu các bài tập là riêng tư"
-#: judge/admin/problem.py:432 judge/admin/submission.py:314
+#: judge/admin/problem.py:446 judge/admin/submission.py:314
#: templates/problem/list.html:18 templates/problem/list.html:37
msgid "Problem code"
msgstr "Mã bài"
-#: judge/admin/problem.py:444 judge/admin/submission.py:320
+#: judge/admin/problem.py:458 judge/admin/submission.py:320
msgid "Problem name"
msgstr "Tên bài"
-#: judge/admin/problem.py:450
+#: judge/admin/problem.py:464
#, fuzzy
#| msgid "contest rating"
msgid "Voter rating"
msgstr "rating kỳ thi"
-#: judge/admin/problem.py:456
+#: judge/admin/problem.py:470
#, fuzzy
#| msgid "Total points"
msgid "Voter point"
msgstr "Tổng điểm"
-#: judge/admin/problem.py:462
+#: judge/admin/problem.py:476
msgid "Vote"
msgstr ""
@@ -315,7 +321,7 @@ msgid "timezone"
msgstr "múi giờ"
#: judge/admin/profile.py:126 judge/admin/submission.py:327
-#: templates/notification/list.html:12
+#: templates/notification/list.html:9
#: templates/organization/requests/log.html:9
#: templates/organization/requests/pending.html:19
#: templates/ticket/list.html:263
@@ -412,9 +418,9 @@ msgstr[0] "%d bài nộp đã được tính điểm lại."
msgid "Rescore the selected submissions"
msgstr "Tính điểm lại cái bài nộp"
-#: judge/admin/submission.py:332 templates/contest/list.html:250
-#: templates/contest/list.html:295 templates/contest/list.html:340
-#: templates/contest/list.html:382 templates/notification/list.html:15
+#: judge/admin/submission.py:332 templates/contest/list.html:248
+#: templates/contest/list.html:293 templates/contest/list.html:338
+#: templates/contest/list.html:380 templates/notification/list.html:12
#: templates/organization/requests/log.html:10
#: templates/organization/requests/pending.html:20
#: templates/problem/list.html:154
@@ -458,20 +464,20 @@ msgstr "Dạng"
msgid "Online Judge"
msgstr ""
-#: judge/comments.py:64
+#: judge/comments.py:63
msgid "Comment body"
msgstr "Nội dung bình luận"
-#: judge/comments.py:70 judge/views/ticket.py:78
+#: judge/comments.py:69 judge/views/ticket.py:73
msgid "Your part is silent, little toad."
msgstr "Bạn không được phép bình luận."
-#: judge/comments.py:79 templates/comments/list.html:17
+#: judge/comments.py:78 templates/comments/list.html:17
msgid ""
"You need to have solved at least one problem before your voice can be heard."
msgstr "Bạn phải giải ít nhất một bài trước khi được phép bình luận."
-#: judge/comments.py:123
+#: judge/comments.py:122
msgid "Posted comment"
msgstr "Bình luận đã đăng"
@@ -503,80 +509,79 @@ msgstr "IOI mới"
msgid "Ultimate"
msgstr ""
-#: judge/forms.py:115
+#: judge/forms.py:113
msgid "File size exceeds the maximum allowed limit of 5MB."
msgstr "File tải lên không được quá 5MB."
-#: judge/forms.py:146
+#: judge/forms.py:144
msgid "Any judge"
msgstr ""
-#: judge/forms.py:353
+#: judge/forms.py:344
msgid "Enter usernames separating by space"
msgstr "Nhập các tên đăng nhập, cách nhau bởi dấu cách"
-#: judge/forms.py:354 judge/views/stats.py:166 templates/stats/site.html:27
+#: judge/forms.py:345 judge/views/stats.py:166 templates/stats/site.html:27
msgid "New users"
msgstr "Thành viên mới"
-#: judge/forms.py:371
+#: judge/forms.py:362
#, python-brace-format
msgid "These usernames don't exist: {usernames}"
msgstr "Các tên đăng nhập này không tồn tại: {usernames}"
-#: judge/forms.py:430 judge/views/register.py:30
+#: judge/forms.py:421 judge/views/register.py:30
#: templates/registration/registration_form.html:34
#: templates/user/base-users-table.html:5
#: templates/user/import/table_csv.html:4
msgid "Username"
msgstr "Tên đăng nhập"
-#: judge/forms.py:431 judge/views/email.py:22
+#: judge/forms.py:422 judge/views/email.py:22
#: templates/registration/registration_form.html:46
#: templates/registration/registration_form.html:60
#: templates/user/edit-profile.html:108 templates/user/import/table_csv.html:5
msgid "Password"
msgstr "Mật khẩu"
-#: judge/forms.py:457
+#: judge/forms.py:448
msgid "Two Factor Authentication tokens must be 6 decimal digits."
msgstr "Two Factor Authentication phải chứa 6 chữ số."
-#: judge/forms.py:470 templates/registration/totp_auth.html:32
+#: judge/forms.py:461 templates/registration/totp_auth.html:32
msgid "Invalid Two Factor Authentication token."
msgstr "Token Two Factor Authentication không hợp lệ."
-#: judge/forms.py:477 judge/models/problem.py:133
+#: judge/forms.py:468 judge/models/problem.py:130
msgid "Problem code must be ^[a-z0-9]+$"
msgstr "Mã bài phải có dạng ^[a-z0-9]+$"
-#: judge/forms.py:484
+#: judge/forms.py:475
msgid "Problem with code already exists."
msgstr "Mã bài đã tồn tại."
-#: judge/forms.py:491 judge/models/contest.py:93
+#: judge/forms.py:482 judge/models/contest.py:95
msgid "Contest id must be ^[a-z0-9]+$"
msgstr "Mã kỳ thi phải có dạng ^[a-z0-9]+$"
-#: judge/forms.py:498 templates/problem/search-form.html:46
+#: judge/forms.py:489 templates/contest/clone.html:47
+#: templates/problem/search-form.html:39
msgid "Group"
-msgstr ""
+msgstr "Nhóm"
-#: judge/forms.py:506
+#: judge/forms.py:497
msgid "Contest with key already exists."
msgstr "Mã kỳ thi đã tồn tại."
-#: judge/forms.py:514
+#: judge/forms.py:505
msgid "Group doesn't exist."
-msgstr ""
+msgstr "Nhóm không tồn tại."
-#: judge/forms.py:516
-#, fuzzy
-#| msgid "You do not have the permission to rejudge submissions."
+#: judge/forms.py:507
msgid "You don't have permission in this group."
-msgstr "Bạn không có quyền chấm lại bài."
+msgstr "Bạn không có quyền trong nhóm này."
-#: judge/forms.py:566
+#: judge/forms.py:557
msgid "This problem is duplicated."
msgstr "Bài này bị lặp"
@@ -586,7 +591,7 @@ msgid "N j, Y, g:i a"
msgstr "g:i a j b, Y"
#: judge/jinja2/datetime.py:26 templates/chat/message.html:13
-#: templates/comments/content-list.html:36
+#: templates/comments/content-list.html:33
#, python-brace-format
msgid "{time}"
msgstr "{time}"
@@ -609,12 +614,12 @@ msgid "No such group"
msgstr "Nhóm không tồn tại"
#: judge/models/bookmark.py:16 judge/models/comment.py:171
-#: judge/models/pagevote.py:15
+#: judge/models/pagevote.py:16
msgid "associated page"
msgstr "trang tương ứng"
#: judge/models/bookmark.py:19 judge/models/comment.py:48
-#: judge/models/pagevote.py:18 judge/models/problem.py:713
+#: judge/models/pagevote.py:19 judge/models/problem.py:718
msgid "votes"
msgstr "bình chọn"
@@ -674,7 +679,7 @@ msgstr "ẩn bình luận"
msgid "parent"
msgstr ""
-#: judge/models/comment.py:63 judge/models/comment.py:191
+#: judge/models/comment.py:63 judge/models/notification.py:31
msgid "comment"
msgstr "bình luận"
@@ -700,124 +705,117 @@ msgstr ""
msgid "Override comment lock"
msgstr ""
-#: judge/models/comment.py:185
-msgid "owner"
-msgstr ""
-
-#: judge/models/comment.py:193 judge/models/message.py:28
-msgid "read"
-msgstr ""
-
-#: judge/models/comment.py:194
-msgid "category"
-msgstr ""
-
-#: judge/models/comment.py:197
-msgid "html link to comments, used for non-comments"
-msgstr ""
-
-#: judge/models/comment.py:203
-msgid "who trigger, used for non-comment"
-msgstr ""
-
-#: judge/models/contest.py:40
+#: judge/models/contest.py:42
msgid "Invalid colour."
msgstr ""
-#: judge/models/contest.py:44
+#: judge/models/contest.py:46
msgid "tag name"
msgstr ""
-#: judge/models/contest.py:48
+#: judge/models/contest.py:50
msgid "Lowercase letters and hyphens only."
msgstr ""
-#: judge/models/contest.py:53
+#: judge/models/contest.py:55
msgid "tag colour"
msgstr ""
-#: judge/models/contest.py:55
+#: judge/models/contest.py:57
msgid "tag description"
msgstr ""
-#: judge/models/contest.py:76
+#: judge/models/contest.py:78
msgid "contest tag"
msgstr ""
-#: judge/models/contest.py:77 judge/models/contest.py:250
+#: judge/models/contest.py:79 judge/models/contest.py:255
msgid "contest tags"
msgstr "nhãn kỳ thi"
-#: judge/models/contest.py:85
+#: judge/models/contest.py:87
msgid "Visible"
msgstr "Hiển thị"
-#: judge/models/contest.py:86
+#: judge/models/contest.py:88
msgid "Hidden for duration of contest"
msgstr "Ẩn trong thời gian kỳ thi"
-#: judge/models/contest.py:87
+#: judge/models/contest.py:89
msgid "Hidden for duration of participation"
msgstr "Ẩn trong thời gian tham gia"
-#: judge/models/contest.py:91
+#: judge/models/contest.py:93
msgid "contest id"
msgstr "ID kỳ thi"
-#: judge/models/contest.py:96
+#: judge/models/contest.py:98
msgid "contest name"
msgstr "tên kỳ thi"
-#: judge/models/contest.py:100
+#: judge/models/contest.py:102 judge/models/interface.py:79
+#: judge/models/problem.py:672
+msgid "authors"
+msgstr "tác giả"
+
+#: judge/models/contest.py:103
msgid "These users will be able to edit the contest."
msgstr "Những người dùng này có quyền chỉnh sửa kỳ thi."
-#: judge/models/contest.py:106
+#: judge/models/contest.py:108 judge/models/problem.py:154
+msgid "curators"
+msgstr "quản lý"
+
+#: judge/models/contest.py:110
msgid ""
"These users will be able to edit the contest, but will not be listed as "
"authors."
msgstr "Những người dùng này là tác giả và có quyền chỉnh sửa kỳ thi."
-#: judge/models/contest.py:115
+#: judge/models/contest.py:118 judge/models/problem.py:164
+msgid "testers"
+msgstr ""
+
+#: judge/models/contest.py:120
msgid "These users will be able to view the contest, but not edit it."
msgstr ""
"Những người dùng này có thể thấy kỳ thi nhưng không có quyền chỉnh sửa."
-#: judge/models/contest.py:120 judge/models/course.py:158
+#: judge/models/contest.py:125 judge/models/course.py:158
#: judge/models/runtime.py:211
msgid "description"
msgstr "mô tả"
-#: judge/models/contest.py:122 judge/models/problem.py:583
+#: judge/models/contest.py:127 judge/models/problem.py:588
#: judge/models/runtime.py:216
msgid "problems"
msgstr "bài tập"
-#: judge/models/contest.py:124 judge/models/contest.py:646
+#: judge/models/contest.py:129 judge/models/contest.py:652
msgid "start time"
msgstr "thời gian bắt đầu"
-#: judge/models/contest.py:125
+#: judge/models/contest.py:130
msgid "end time"
msgstr "thời gian kết thúc"
-#: judge/models/contest.py:127 judge/models/problem.py:186
-#: judge/models/problem.py:618
+#: judge/models/contest.py:132 judge/models/problem.py:183
+#: judge/models/problem.py:623
msgid "time limit"
msgstr "giới hạn thời gian"
-#: judge/models/contest.py:131
+#: judge/models/contest.py:136
msgid ""
"Format hh:mm:ss. For example, if you want a 2-hour contest, enter 02:00:00"
msgstr ""
"Định dạng hh:mm:ss (giờ:phút:giây). Ví dụ, nếu muốn tạo kỳ thi dài 2h, hãy "
"nhập 02:00:00"
-#: judge/models/contest.py:135
+#: judge/models/contest.py:140
msgid "freeze after"
msgstr "đóng băng sau"
-#: judge/models/contest.py:139
+#: judge/models/contest.py:144
msgid ""
"Format hh:mm:ss. For example, if you want to freeze contest after 2 hours, "
"enter 02:00:00"
@@ -825,12 +823,12 @@ msgstr ""
"Định dạng hh:mm:ss (giờ:phút:giây). Ví dụ, nếu muốn đóng băng kỳ thi sau 2h, "
"hãy nhập 02:00:00"
-#: judge/models/contest.py:143 judge/models/course.py:28
-#: judge/models/course.py:164 judge/models/problem.py:225
+#: judge/models/contest.py:148 judge/models/course.py:28
+#: judge/models/course.py:164 judge/models/problem.py:222
msgid "publicly visible"
msgstr "công khai"
-#: judge/models/contest.py:146
+#: judge/models/contest.py:151
msgid ""
"Should be set even for organization-private contests, where it determines "
"whether the contest is visible to members of the specified organizations."
@@ -838,92 +836,92 @@ msgstr ""
"Đánh dấu ngay cả với các kỳ thi riêng tư của nhóm, quyết định việc kỳ thi có "
"được hiển thị với các thành viên hay không."
-#: judge/models/contest.py:152
+#: judge/models/contest.py:157
msgid "contest rated"
msgstr "kỳ thi được xếp hạng"
-#: judge/models/contest.py:153
+#: judge/models/contest.py:158
msgid "Whether this contest can be rated."
msgstr "Quyết định kỳ thi có được xếp hạng không."
-#: judge/models/contest.py:157
+#: judge/models/contest.py:162
msgid "scoreboard visibility"
msgstr "khả năng hiển thị của bảng điểm"
-#: judge/models/contest.py:160
+#: judge/models/contest.py:165
msgid "Scoreboard visibility through the duration of the contest"
msgstr "Khả năng hiển thị của bảng điểm trong thời gian kỳ thi"
-#: judge/models/contest.py:165
+#: judge/models/contest.py:170
msgid "view contest scoreboard"
msgstr "xem bảng điểm kỳ thi"
-#: judge/models/contest.py:168
+#: judge/models/contest.py:173
msgid "These users will be able to view the scoreboard."
msgstr "Những người dùng này được phép xem bảng điểm."
-#: judge/models/contest.py:171
+#: judge/models/contest.py:176
msgid "public scoreboard"
msgstr "công khai bảng điểm"
-#: judge/models/contest.py:172
+#: judge/models/contest.py:177
msgid "Ranking page is public even for private contests."
msgstr "Trang xếp hạng được công khai, kể cả cho kỳ thi riêng tư."
-#: judge/models/contest.py:176
+#: judge/models/contest.py:181
msgid "no comments"
msgstr "không bình luận"
-#: judge/models/contest.py:177
+#: judge/models/contest.py:182
msgid "Use clarification system instead of comments."
msgstr "Dùng hệ thống thông báo thay vì bình luận."
-#: judge/models/contest.py:182
+#: judge/models/contest.py:187
msgid "Rating floor for contest"
msgstr "Cận dưới rating được xếp hạng trong kỳ thi"
-#: judge/models/contest.py:188
+#: judge/models/contest.py:193
msgid "Rating ceiling for contest"
msgstr "Cận trên rating được xếp hạng trong kỳ thi"
-#: judge/models/contest.py:193
+#: judge/models/contest.py:198
msgid "rate all"
msgstr "xếp hạng tất cả"
-#: judge/models/contest.py:194
+#: judge/models/contest.py:199
msgid "Rate all users who joined."
msgstr "Xếp hạng tất cả người dùng đã tham gia (kể cả không nộp)."
-#: judge/models/contest.py:199
+#: judge/models/contest.py:204
msgid "exclude from ratings"
msgstr "không xếp hạng"
-#: judge/models/contest.py:204
+#: judge/models/contest.py:209
msgid "private to specific users"
msgstr "riêng tư với các người dùng này"
-#: judge/models/contest.py:209
+#: judge/models/contest.py:214
msgid "private contestants"
msgstr "thí sinh riêng tư"
-#: judge/models/contest.py:210
+#: judge/models/contest.py:215
msgid "If private, only these users may see the contest"
msgstr "Nếu riêng tư, chỉ những người dùng này mới thấy kỳ thi"
-#: judge/models/contest.py:214
+#: judge/models/contest.py:219
msgid "hide problem tags"
msgstr "ẩn nhãn kỳ thi"
-#: judge/models/contest.py:215
+#: judge/models/contest.py:220
msgid "Whether problem tags should be hidden by default."
msgstr ""
"Quyết định việc nhãn bài tập (DP, Tham lam, ...) được ẩn trong kỳ thi không."
-#: judge/models/contest.py:219
+#: judge/models/contest.py:224
msgid "run pretests only"
msgstr "chỉ chạy pretests"
-#: judge/models/contest.py:221
+#: judge/models/contest.py:226
msgid ""
"Whether judges should grade pretests only, versus all testcases. Commonly "
"set during a contest, then unset prior to rejudging user submissions when "
@@ -932,51 +930,51 @@ msgstr ""
"Quyết định việc các máy chấm chỉ chấm pretests thay vì tất cả các test. Sau "
"kỳ thi, hãy bỏ đánh dấu ô này và chấm lại tất cả các bài."
-#: judge/models/contest.py:228 judge/models/interface.py:96
-#: judge/models/problem.py:285
+#: judge/models/contest.py:233 judge/models/interface.py:96
+#: judge/models/problem.py:282
msgid "private to organizations"
msgstr "riêng tư với các tổ chức"
-#: judge/models/contest.py:233 judge/models/course.py:34
-#: judge/models/interface.py:92 judge/models/problem.py:281
-#: judge/models/profile.py:144
+#: judge/models/contest.py:238 judge/models/course.py:34
+#: judge/models/interface.py:92 judge/models/problem.py:278
+#: judge/models/profile.py:149
msgid "organizations"
msgstr "tổ chức"
-#: judge/models/contest.py:234
+#: judge/models/contest.py:239
msgid "If private, only these organizations may see the contest"
msgstr "Nếu riêng tư, chỉ những tổ chức này thấy được kỳ thi"
-#: judge/models/contest.py:237 judge/models/problem.py:256
+#: judge/models/contest.py:242 judge/models/problem.py:253
msgid "OpenGraph image"
msgstr "Hình ảnh OpenGraph"
-#: judge/models/contest.py:240 judge/models/profile.py:92
+#: judge/models/contest.py:245 judge/models/profile.py:97
msgid "Logo override image"
msgstr "Hình ảnh ghi đè logo"
-#: judge/models/contest.py:245
+#: judge/models/contest.py:250
msgid ""
"This image will replace the default site logo for users inside the contest."
msgstr "Ảnh này sẽ thay thế cho logo mặc định trong kỳ thi."
-#: judge/models/contest.py:253
+#: judge/models/contest.py:258
msgid "the amount of live participants"
msgstr "số lượng thí sinh thi trực tiếp"
-#: judge/models/contest.py:257
+#: judge/models/contest.py:262
msgid "contest summary"
msgstr "tổng kết kỳ thi"
-#: judge/models/contest.py:259 judge/models/problem.py:262
+#: judge/models/contest.py:264 judge/models/problem.py:259
msgid "Plain-text, shown in meta description tag, e.g. for social media."
msgstr ""
-#: judge/models/contest.py:263 judge/models/profile.py:87
+#: judge/models/contest.py:268 judge/models/profile.py:92
msgid "access code"
msgstr "mật khẩu truy cập"
-#: judge/models/contest.py:268
+#: judge/models/contest.py:273
msgid ""
"An optional code to prompt contestants before they are allowed to join the "
"contest. Leave it blank to disable."
@@ -984,302 +982,314 @@ msgstr ""
"Mật khẩu truy cập cho các thí sinh muốn tham gia kỳ thi. Để trống nếu không "
"dùng."
-#: judge/models/contest.py:274 judge/models/problem.py:244
+#: judge/models/contest.py:279 judge/models/problem.py:241
msgid "personae non gratae"
msgstr "Chặn tham gia"
-#: judge/models/contest.py:276
+#: judge/models/contest.py:281
msgid "Bans the selected users from joining this contest."
msgstr "Cấm những người dùng được chọn tham gia kỳ thi."
-#: judge/models/contest.py:279
+#: judge/models/contest.py:284
msgid "contest format"
msgstr "format kỳ thi"
-#: judge/models/contest.py:283
+#: judge/models/contest.py:288
msgid "The contest format module to use."
msgstr "Format kỳ thi sử dụng."
-#: judge/models/contest.py:286
+#: judge/models/contest.py:291
msgid "contest format configuration"
msgstr "Tùy chỉnh format kỳ thi"
-#: judge/models/contest.py:290
+#: judge/models/contest.py:295
msgid ""
"A JSON object to serve as the configuration for the chosen contest format "
"module. Leave empty to use None. Exact format depends on the contest format "
"selected."
msgstr ""
-#: judge/models/contest.py:303
+#: judge/models/contest.py:308
msgid "precision points"
msgstr "Hiển thị điểm"
-#: judge/models/contest.py:306
+#: judge/models/contest.py:311
msgid "Number of digits to round points to."
msgstr "Số chữ số thập phân trên bảng điểm."
-#: judge/models/contest.py:614
+#: judge/models/contest.py:620
msgid "See private contests"
msgstr ""
-#: judge/models/contest.py:615
+#: judge/models/contest.py:621
msgid "Edit own contests"
msgstr ""
-#: judge/models/contest.py:616
+#: judge/models/contest.py:622
msgid "Edit all contests"
msgstr ""
-#: judge/models/contest.py:617
+#: judge/models/contest.py:623
msgid "Clone contest"
msgstr ""
-#: judge/models/contest.py:618 templates/contest/moss.html:72
+#: judge/models/contest.py:624 templates/contest/moss.html:72
msgid "MOSS contest"
msgstr ""
-#: judge/models/contest.py:619
+#: judge/models/contest.py:625
msgid "Rate contests"
msgstr ""
-#: judge/models/contest.py:620
+#: judge/models/contest.py:626
msgid "Contest access codes"
msgstr ""
-#: judge/models/contest.py:621
+#: judge/models/contest.py:627
msgid "Create private contests"
msgstr ""
-#: judge/models/contest.py:622
+#: judge/models/contest.py:628
msgid "Change contest visibility"
msgstr ""
-#: judge/models/contest.py:623
+#: judge/models/contest.py:629
msgid "Edit contest problem label script"
msgstr "Cách hiển thị thứ tự bài tập"
-#: judge/models/contest.py:625 judge/models/contest.py:772
-#: judge/models/contest.py:850 judge/models/contest.py:880
+#: judge/models/contest.py:631 judge/models/contest.py:778
+#: judge/models/contest.py:856 judge/models/contest.py:886
#: judge/models/course.py:178 judge/models/submission.py:116
msgid "contest"
msgstr "kỳ thi"
-#: judge/models/contest.py:626
+#: judge/models/contest.py:632
msgid "contests"
msgstr "kỳ thi"
-#: judge/models/contest.py:635
+#: judge/models/contest.py:641
msgid "associated contest"
msgstr ""
-#: judge/models/contest.py:648
+#: judge/models/contest.py:654
msgid "score"
msgstr "điểm"
-#: judge/models/contest.py:649
+#: judge/models/contest.py:655
msgid "cumulative time"
msgstr "tổng thời gian"
-#: judge/models/contest.py:651
+#: judge/models/contest.py:657
msgid "is disqualified"
msgstr "đã bị loại"
-#: judge/models/contest.py:653
+#: judge/models/contest.py:659
msgid "Whether this participation is disqualified."
msgstr "Quyết định thí sinh có bị loại không."
-#: judge/models/contest.py:655
+#: judge/models/contest.py:661
msgid "tie-breaking field"
msgstr ""
-#: judge/models/contest.py:657
+#: judge/models/contest.py:663
msgid "virtual participation id"
msgstr "id lần tham gia ảo"
-#: judge/models/contest.py:659
+#: judge/models/contest.py:665
msgid "0 means non-virtual, otherwise the n-th virtual participation."
msgstr "0 nghĩa là tham gia chính thức, ngược lại là lần tham gia ảo thứ n."
-#: judge/models/contest.py:662
+#: judge/models/contest.py:668
msgid "contest format specific data"
msgstr ""
-#: judge/models/contest.py:665
+#: judge/models/contest.py:671
msgid "same as format_data, but including frozen results"
msgstr ""
-#: judge/models/contest.py:669
+#: judge/models/contest.py:675
#, fuzzy
#| msgid "score"
msgid "final score"
msgstr "điểm"
-#: judge/models/contest.py:671
+#: judge/models/contest.py:677
#, fuzzy
#| msgid "cumulative time"
msgid "final cumulative time"
msgstr "tổng thời gian"
-#: judge/models/contest.py:747
+#: judge/models/contest.py:753
#, python-format
msgid "%s spectating in %s"
msgstr "%s đang theo dõi trong %s"
-#: judge/models/contest.py:752
+#: judge/models/contest.py:758
#, python-format
msgid "%s in %s, v%d"
msgstr "%s trong %s, v%d"
-#: judge/models/contest.py:757
+#: judge/models/contest.py:763
#, python-format
msgid "%s in %s"
msgstr "%s trong %s"
-#: judge/models/contest.py:760
+#: judge/models/contest.py:766
msgid "contest participation"
msgstr "lần tham gia kỳ thi"
-#: judge/models/contest.py:761
+#: judge/models/contest.py:767
msgid "contest participations"
msgstr "lần tham gia kỳ thi"
-#: judge/models/contest.py:768 judge/models/contest.py:821
-#: judge/models/contest.py:883 judge/models/problem.py:582
-#: judge/models/problem.py:589 judge/models/problem.py:610
-#: judge/models/problem.py:641 judge/models/problem_data.py:50
+#: judge/models/contest.py:774 judge/models/contest.py:827
+#: judge/models/contest.py:889 judge/models/problem.py:587
+#: judge/models/problem.py:594 judge/models/problem.py:615
+#: judge/models/problem.py:646 judge/models/problem_data.py:50
msgid "problem"
msgstr "bài tập"
-#: judge/models/contest.py:776 judge/models/contest.py:833
-#: judge/models/course.py:182 judge/models/problem.py:209
+#: judge/models/contest.py:782 judge/models/contest.py:839
+#: judge/models/course.py:182 judge/models/problem.py:206
msgid "points"
msgstr "điểm"
-#: judge/models/contest.py:777
+#: judge/models/contest.py:783
msgid "partial"
msgstr "thành phần"
-#: judge/models/contest.py:778 judge/models/contest.py:835
+#: judge/models/contest.py:784 judge/models/contest.py:841
msgid "is pretested"
msgstr "dùng pretest"
-#: judge/models/contest.py:779 judge/models/interface.py:47
+#: judge/models/contest.py:785 judge/models/interface.py:47
msgid "order"
msgstr "thứ tự"
-#: judge/models/contest.py:781
+#: judge/models/contest.py:787
msgid "visible testcases"
msgstr "hiển thị test"
-#: judge/models/contest.py:786
+#: judge/models/contest.py:792
msgid "Maximum number of submissions for this problem, or 0 for no limit."
msgstr "Số lần nộp tối đa, đặt là 0 nếu không có giới hạn."
-#: judge/models/contest.py:788
+#: judge/models/contest.py:794
msgid "max submissions"
msgstr "số lần nộp tối đa"
-#: judge/models/contest.py:791
+#: judge/models/contest.py:797
msgid "Why include a problem you can't submit to?"
msgstr ""
-#: judge/models/contest.py:795
+#: judge/models/contest.py:801
#, fuzzy
#| msgid "Only for format new IOI. Separated by commas, e.g: 2, 3"
msgid "Separated by commas, e.g: 2, 3"
msgstr ""
"Chỉ dùng với format IOI mới. Các sub cách nhau bởi dấu phẩy. Ví dụ: 2, 3"
-#: judge/models/contest.py:796
+#: judge/models/contest.py:802
#, fuzzy
#| msgid "frozen subtasks"
msgid "hidden subtasks"
msgstr "Đóng băng subtasks"
-#: judge/models/contest.py:808
+#: judge/models/contest.py:814
msgid "contest problem"
msgstr "bài trong kỳ thi"
-#: judge/models/contest.py:809
+#: judge/models/contest.py:815
msgid "contest problems"
msgstr "bài trong kỳ thi"
-#: judge/models/contest.py:815 judge/models/submission.py:233
+#: judge/models/contest.py:821 judge/models/submission.py:273
msgid "submission"
msgstr "bài nộp"
-#: judge/models/contest.py:828 judge/models/contest.py:854
+#: judge/models/contest.py:834 judge/models/contest.py:860
msgid "participation"
msgstr "lần tham gia"
-#: judge/models/contest.py:836
+#: judge/models/contest.py:842
msgid "Whether this submission was ran only on pretests."
msgstr "Quyết định bài nộp chỉ được chạy trên pretest không."
-#: judge/models/contest.py:841
+#: judge/models/contest.py:847
msgid "contest submission"
msgstr "bài nộp kỳ thi"
-#: judge/models/contest.py:842
+#: judge/models/contest.py:848
msgid "contest submissions"
msgstr "bài nộp kỳ thi"
-#: judge/models/contest.py:858
+#: judge/models/contest.py:864
msgid "rank"
msgstr "rank"
-#: judge/models/contest.py:859
+#: judge/models/contest.py:865
msgid "rating"
msgstr "rating"
-#: judge/models/contest.py:860
+#: judge/models/contest.py:866
msgid "raw rating"
msgstr "rating thật"
-#: judge/models/contest.py:861
+#: judge/models/contest.py:867
msgid "contest performance"
msgstr ""
-#: judge/models/contest.py:862
+#: judge/models/contest.py:868
msgid "last rated"
msgstr "lần cuối được xếp hạng"
-#: judge/models/contest.py:866
+#: judge/models/contest.py:872
msgid "contest rating"
msgstr "rating kỳ thi"
-#: judge/models/contest.py:867
+#: judge/models/contest.py:873
msgid "contest ratings"
msgstr "rating kỳ thi"
-#: judge/models/contest.py:891
+#: judge/models/contest.py:897
msgid "contest moss result"
msgstr "kết quả MOSS kỳ thi"
-#: judge/models/contest.py:892
+#: judge/models/contest.py:898
msgid "contest moss results"
msgstr "kết quả MOSS kỳ thi"
-#: judge/models/contest.py:897
+#: judge/models/contest.py:903
msgid "clarified problem"
msgstr ""
-#: judge/models/contest.py:899
+#: judge/models/contest.py:905
msgid "clarification body"
msgstr ""
-#: judge/models/contest.py:901
+#: judge/models/contest.py:907
msgid "clarification timestamp"
msgstr ""
+#: judge/models/contest.py:925
+#, fuzzy
+#| msgid "contest summary"
+msgid "contests summary"
+msgstr "tổng kết kỳ thi"
+
+#: judge/models/contest.py:926
+#, fuzzy
+#| msgid "contest summary"
+msgid "contests summaries"
+msgstr "tổng kết kỳ thi"
+
#: judge/models/course.py:21
#, fuzzy
#| msgid "username"
msgid "course name"
msgstr "tên đăng nhập"
-#: judge/models/course.py:23 judge/models/profile.py:53
+#: judge/models/course.py:23 judge/models/profile.py:58
msgid "organization description"
msgstr "mô tả tổ chức"
@@ -1305,7 +1315,7 @@ msgstr ""
msgid "Course name shown in URL"
msgstr "Tên được hiển thị trong đường dẫn"
-#: judge/models/course.py:43 judge/models/profile.py:45
+#: judge/models/course.py:43 judge/models/profile.py:50
msgid "Only alphanumeric and hyphens"
msgstr ""
@@ -1382,15 +1392,11 @@ msgstr "mục cha"
msgid "post title"
msgstr "tiêu đề bài đăng"
-#: judge/models/interface.py:79 judge/models/problem.py:667
-msgid "authors"
-msgstr "tác giả"
-
#: judge/models/interface.py:80
msgid "slug"
msgstr "slug"
-#: judge/models/interface.py:81 judge/models/problem.py:665
+#: judge/models/interface.py:81 judge/models/problem.py:670
msgid "public visibility"
msgstr "khả năng hiển thị công khai"
@@ -1450,168 +1456,180 @@ msgstr "người nhận"
msgid "message timestamp"
msgstr "thời gian gửi"
+#: judge/models/message.py:28 judge/models/notification.py:33
+msgid "read"
+msgstr ""
+
#: judge/models/message.py:33
msgid "messages in the thread"
msgstr "tin nhắn trong chuỗi"
-#: judge/models/pagevote.py:24
+#: judge/models/notification.py:13
+msgid "owner"
+msgstr ""
+
+#: judge/models/notification.py:18
+msgid "category"
+msgstr ""
+
+#: judge/models/notification.py:21
+msgid "html link to comments, used for non-comments"
+msgstr ""
+
+#: judge/models/notification.py:27
+msgid "who trigger, used for non-comment"
+msgstr ""
+
+#: judge/models/pagevote.py:25
#, fuzzy
#| msgid "votes"
msgid "pagevote"
msgstr "bình chọn"
-#: judge/models/pagevote.py:25
+#: judge/models/pagevote.py:26
#, fuzzy
#| msgid "votes"
msgid "pagevotes"
msgstr "bình chọn"
-#: judge/models/pagevote.py:49
+#: judge/models/pagevote.py:51
#, fuzzy
#| msgid "volunteer vote"
msgid "pagevote vote"
msgstr "vote từ TNV"
-#: judge/models/pagevote.py:50
+#: judge/models/pagevote.py:52
#, fuzzy
#| msgid "volunteer votes"
msgid "pagevote votes"
msgstr "vote từ TNV"
-#: judge/models/problem.py:44
+#: judge/models/problem.py:43
msgid "problem category ID"
msgstr "mã của nhóm bài"
-#: judge/models/problem.py:47
+#: judge/models/problem.py:46
msgid "problem category name"
msgstr "tên nhóm bài"
-#: judge/models/problem.py:55
+#: judge/models/problem.py:54
msgid "problem type"
msgstr "dạng bài"
-#: judge/models/problem.py:56 judge/models/problem.py:176
+#: judge/models/problem.py:55 judge/models/problem.py:173
#: judge/models/volunteer.py:28
msgid "problem types"
msgstr "dạng bài"
-#: judge/models/problem.py:61
+#: judge/models/problem.py:60
msgid "problem group ID"
msgstr "mã của nhóm bài"
-#: judge/models/problem.py:63
+#: judge/models/problem.py:62
msgid "problem group name"
msgstr "tên nhóm bài"
-#: judge/models/problem.py:70 judge/models/problem.py:181
+#: judge/models/problem.py:69 judge/models/problem.py:178
msgid "problem group"
msgstr "nhóm bài"
-#: judge/models/problem.py:71
+#: judge/models/problem.py:70
msgid "problem groups"
msgstr "nhóm bài"
-#: judge/models/problem.py:78
+#: judge/models/problem.py:77
msgid "key"
msgstr ""
-#: judge/models/problem.py:81
+#: judge/models/problem.py:80
msgid "link"
msgstr "đường dẫn"
-#: judge/models/problem.py:82
+#: judge/models/problem.py:81
msgid "full name"
msgstr "tên đầy đủ"
-#: judge/models/problem.py:86 judge/models/profile.py:50
+#: judge/models/problem.py:85 judge/models/profile.py:55
#: judge/models/runtime.py:34
msgid "short name"
msgstr "tên ngắn"
-#: judge/models/problem.py:87
+#: judge/models/problem.py:86
msgid "Displayed on pages under this license"
msgstr "Được hiển thị trên các trang theo giấy phép này"
-#: judge/models/problem.py:92
+#: judge/models/problem.py:91
msgid "icon"
msgstr "icon"
-#: judge/models/problem.py:93
+#: judge/models/problem.py:92
msgid "URL to the icon"
msgstr "Đường dẫn icon"
-#: judge/models/problem.py:95
+#: judge/models/problem.py:94
msgid "license text"
msgstr "văn bản giấy phép"
-#: judge/models/problem.py:104
+#: judge/models/problem.py:103
msgid "license"
msgstr ""
-#: judge/models/problem.py:105
+#: judge/models/problem.py:104
msgid "licenses"
msgstr ""
-#: judge/models/problem.py:130
+#: judge/models/problem.py:127
msgid "problem code"
msgstr "mã bài"
-#: judge/models/problem.py:136
+#: judge/models/problem.py:133
msgid "A short, unique code for the problem, used in the url after /problem/"
msgstr "Mã bài ngắn, độc nhất cho bài tập, được dùng trong url sau /problem/"
-#: judge/models/problem.py:141
+#: judge/models/problem.py:138
msgid "problem name"
msgstr "Tên bài"
-#: judge/models/problem.py:143
+#: judge/models/problem.py:140
msgid "The full name of the problem, as shown in the problem list."
msgstr "Tên đầy đủ của bài, như được hiển thị trên danh sách bài tập"
-#: judge/models/problem.py:145
+#: judge/models/problem.py:142
msgid "problem body"
msgstr "Nội dung"
-#: judge/models/problem.py:148
+#: judge/models/problem.py:145
msgid "creators"
msgstr ""
-#: judge/models/problem.py:152
+#: judge/models/problem.py:149
msgid "These users will be able to edit the problem, and be listed as authors."
msgstr ""
"Những người dùng này sẽ có thể chỉnh sửa bài tập, và nằm trong danh sách các "
"tác giả"
-#: judge/models/problem.py:157
-msgid "curators"
-msgstr ""
-
-#: judge/models/problem.py:161
+#: judge/models/problem.py:158
msgid ""
"These users will be able to edit the problem, but not be listed as authors."
msgstr ""
"Những người dùng này sẽ có thể chỉnh sửa bài tập, nhưng không nằm trong danh "
"sách các tác giả"
-#: judge/models/problem.py:167
-msgid "testers"
-msgstr ""
-
-#: judge/models/problem.py:171
+#: judge/models/problem.py:168
msgid "These users will be able to view the private problem, but not edit it."
msgstr ""
"Những người dùng này sẽ thấy được bài tập này (dù riêng tư), nhưng không "
"chỉnh sửa được"
-#: judge/models/problem.py:177 judge/models/volunteer.py:29
+#: judge/models/problem.py:174 judge/models/volunteer.py:29
msgid "The type of problem, as shown on the problem's page."
msgstr "Dạng bài, giống như trên trang bài tập"
-#: judge/models/problem.py:183
+#: judge/models/problem.py:180
msgid "The group of problem, shown under Category in the problem list."
msgstr "Nhóm bài, hiện ở mục Nhóm bài trong danh sách bài tập"
-#: judge/models/problem.py:188
+#: judge/models/problem.py:185
msgid ""
"The time limit for this problem, in seconds. Fractional seconds (e.g. 1.5) "
"are supported."
@@ -1619,11 +1637,11 @@ msgstr ""
"Giới hạn thời gian cho bài tập này, theo đơn vị giây. Có thể nhập số thực "
"(ví dụ 1.5)"
-#: judge/models/problem.py:197 judge/models/problem.py:625
+#: judge/models/problem.py:194 judge/models/problem.py:630
msgid "memory limit"
msgstr "Giới hạn bộ nhớ"
-#: judge/models/problem.py:199
+#: judge/models/problem.py:196
msgid ""
"The memory limit for this problem, in kilobytes (e.g. 256mb = 262144 "
"kilobytes)."
@@ -1631,7 +1649,7 @@ msgstr ""
"Giới hạn bộ nhớ cho bài này, theo đơn vị kilobytes (ví dụ 256mb = 262144 "
"kilobytes)"
-#: judge/models/problem.py:211
+#: judge/models/problem.py:208
msgid ""
"Points awarded for problem completion. Points are displayed with a 'p' "
"suffix if partial."
@@ -1639,148 +1657,148 @@ msgstr ""
"Điểm thưởng khi hoàn thành bài tập. Điểm có thêm chữ 'p' ở sau cùng nếu như "
"chấp nhận cho điểm thành phần (có điểm ngay khi không đúng toàn bộ test)"
-#: judge/models/problem.py:217
+#: judge/models/problem.py:214
msgid "allows partial points"
msgstr "cho phép điểm thành phần"
-#: judge/models/problem.py:221
+#: judge/models/problem.py:218
msgid "allowed languages"
msgstr "các ngôn ngữ được cho phép"
-#: judge/models/problem.py:222
+#: judge/models/problem.py:219
msgid "List of allowed submission languages."
msgstr "Danh sách các ngôn ngữ lập trình cho phép"
-#: judge/models/problem.py:228
+#: judge/models/problem.py:225
msgid "manually managed"
msgstr ""
-#: judge/models/problem.py:231
+#: judge/models/problem.py:228
msgid "Whether judges should be allowed to manage data or not."
msgstr ""
-#: judge/models/problem.py:234
+#: judge/models/problem.py:231
msgid "date of publishing"
msgstr "Ngày công bố"
-#: judge/models/problem.py:239
+#: judge/models/problem.py:236
msgid ""
"Doesn't have magic ability to auto-publish due to backward compatibility"
msgstr ""
-#: judge/models/problem.py:246
+#: judge/models/problem.py:243
msgid "Bans the selected users from submitting to this problem."
msgstr "Cấm những người dùng được chọn nộp bài tập này."
-#: judge/models/problem.py:253
+#: judge/models/problem.py:250
msgid "The license under which this problem is published."
msgstr "Giấy phép xuất bản bài tập"
-#: judge/models/problem.py:260
+#: judge/models/problem.py:257
msgid "problem summary"
msgstr "Tóm tắt bài tập"
-#: judge/models/problem.py:266
+#: judge/models/problem.py:263
msgid "number of users"
msgstr ""
-#: judge/models/problem.py:268
+#: judge/models/problem.py:265
msgid "The number of users who solved the problem."
msgstr "Số lượng người dùng đã giải được bài"
-#: judge/models/problem.py:270
+#: judge/models/problem.py:267
msgid "solve rate"
msgstr "Tỉ lệ giải đúng"
-#: judge/models/problem.py:282
+#: judge/models/problem.py:279
msgid "If private, only these organizations may see the problem."
msgstr "Nếu bài riêng tư, chỉ những tổ chức này thấy được"
-#: judge/models/problem.py:288
+#: judge/models/problem.py:285
msgid "pdf statement"
msgstr "Đề bài bằng file pdf"
-#: judge/models/problem.py:594 judge/models/problem.py:615
-#: judge/models/problem.py:646 judge/models/runtime.py:161
+#: judge/models/problem.py:599 judge/models/problem.py:620
+#: judge/models/problem.py:651 judge/models/runtime.py:161
msgid "language"
msgstr ""
-#: judge/models/problem.py:597
+#: judge/models/problem.py:602
msgid "translated name"
msgstr ""
-#: judge/models/problem.py:599
+#: judge/models/problem.py:604
msgid "translated description"
msgstr ""
-#: judge/models/problem.py:603
+#: judge/models/problem.py:608
msgid "problem translation"
msgstr ""
-#: judge/models/problem.py:604
+#: judge/models/problem.py:609
msgid "problem translations"
msgstr ""
-#: judge/models/problem.py:634
+#: judge/models/problem.py:639
msgid "language-specific resource limit"
msgstr ""
-#: judge/models/problem.py:635
+#: judge/models/problem.py:640
msgid "language-specific resource limits"
msgstr ""
-#: judge/models/problem.py:648 judge/models/submission.py:249
+#: judge/models/problem.py:653 judge/models/submission.py:289
msgid "source code"
msgstr "mã nguồn"
-#: judge/models/problem.py:652
+#: judge/models/problem.py:657
msgid "language-specific template"
msgstr ""
-#: judge/models/problem.py:653
+#: judge/models/problem.py:658
msgid "language-specific templates"
msgstr ""
-#: judge/models/problem.py:660
+#: judge/models/problem.py:665
msgid "associated problem"
msgstr ""
-#: judge/models/problem.py:666
+#: judge/models/problem.py:671
msgid "publish date"
msgstr ""
-#: judge/models/problem.py:668
+#: judge/models/problem.py:673
msgid "editorial content"
msgstr "nội dung lời giải"
-#: judge/models/problem.py:681
+#: judge/models/problem.py:686
#, python-format
msgid "Editorial for %s"
msgstr ""
-#: judge/models/problem.py:685
+#: judge/models/problem.py:690
msgid "solution"
msgstr "lời giải"
-#: judge/models/problem.py:686
+#: judge/models/problem.py:691
msgid "solutions"
msgstr "lời giải"
-#: judge/models/problem.py:691
+#: judge/models/problem.py:696
#, fuzzy
#| msgid "point value"
msgid "proposed point value"
msgstr "điểm"
-#: judge/models/problem.py:692
+#: judge/models/problem.py:697
msgid "The amount of points you think this problem deserves."
msgstr "Bạn nghĩ bài này đáng bao nhiêu điểm?"
-#: judge/models/problem.py:706
+#: judge/models/problem.py:711
msgid "The time this vote was cast"
msgstr ""
-#: judge/models/problem.py:712
+#: judge/models/problem.py:717
msgid "vote"
msgstr ""
@@ -1802,7 +1820,7 @@ msgstr "Số thực (chênh lệch tương đối)"
#: judge/models/problem_data.py:36
msgid "Non-trailing spaces"
-msgstr "Không cho phép dấu cách cuối dòng"
+msgstr "Không xét dấu cách cuối dòng"
#: judge/models/problem_data.py:37
msgid "Unordered"
@@ -1952,214 +1970,214 @@ msgstr "điểm"
msgid "case is pretest?"
msgstr "test là pretest?"
-#: judge/models/profile.py:38
+#: judge/models/profile.py:43
msgid "organization title"
msgstr "tiêu đề tổ chức"
-#: judge/models/profile.py:41
+#: judge/models/profile.py:46
msgid "organization slug"
msgstr "tên ngắn đường dẫn"
-#: judge/models/profile.py:42
+#: judge/models/profile.py:47
msgid "Organization name shown in URL"
msgstr "Tên được hiển thị trong đường dẫn"
-#: judge/models/profile.py:51
+#: judge/models/profile.py:56
msgid "Displayed beside user name during contests"
msgstr "Hiển thị bên cạnh tên người dùng trong kỳ thi"
-#: judge/models/profile.py:56
+#: judge/models/profile.py:61
msgid "registrant"
msgstr "người tạo"
-#: judge/models/profile.py:59
+#: judge/models/profile.py:64
msgid "User who registered this organization"
msgstr "Người tạo tổ chức"
-#: judge/models/profile.py:63
+#: judge/models/profile.py:68
msgid "administrators"
msgstr "người quản lý"
-#: judge/models/profile.py:65
+#: judge/models/profile.py:70
msgid "Those who can edit this organization"
msgstr "Những người có thể chỉnh sửa tổ chức"
-#: judge/models/profile.py:68
+#: judge/models/profile.py:73
msgid "creation date"
msgstr "ngày tạo"
-#: judge/models/profile.py:71
+#: judge/models/profile.py:76
msgid "is open organization?"
msgstr "tổ chức mở?"
-#: judge/models/profile.py:72
+#: judge/models/profile.py:77
msgid "Allow joining organization"
msgstr "Cho phép mọi người tham gia tổ chức"
-#: judge/models/profile.py:76
+#: judge/models/profile.py:81
msgid "maximum size"
msgstr "số lượng thành viên tối đa"
-#: judge/models/profile.py:80
+#: judge/models/profile.py:85
msgid ""
"Maximum amount of users in this organization, only applicable to private "
"organizations"
msgstr "Số người tối đa trong tổ chức, chỉ áp dụng với tổ chức riêng tư"
-#: judge/models/profile.py:86
+#: judge/models/profile.py:91
msgid "Student access code"
msgstr "Mã truy cập cho học sinh"
-#: judge/models/profile.py:97
+#: judge/models/profile.py:102
msgid ""
"This image will replace the default site logo for users viewing the "
"organization."
msgstr "Ảnh này sẽ thay thế logo mặc định khi ở trong tổ chức."
-#: judge/models/profile.py:143 judge/models/profile.py:172
-#: judge/models/profile.py:396 judge/models/profile.py:475
+#: judge/models/profile.py:148 judge/models/profile.py:178
+#: judge/models/profile.py:439 judge/models/profile.py:518
msgid "organization"
msgstr ""
-#: judge/models/profile.py:149
+#: judge/models/profile.py:155
msgid "user associated"
msgstr ""
-#: judge/models/profile.py:151
+#: judge/models/profile.py:157
msgid "self-description"
msgstr ""
-#: judge/models/profile.py:154
+#: judge/models/profile.py:160
msgid "location"
msgstr ""
-#: judge/models/profile.py:160
+#: judge/models/profile.py:166
msgid "preferred language"
msgstr ""
-#: judge/models/profile.py:168
+#: judge/models/profile.py:174
msgid "last access time"
msgstr ""
-#: judge/models/profile.py:169
+#: judge/models/profile.py:175
msgid "last IP"
msgstr ""
-#: judge/models/profile.py:180
+#: judge/models/profile.py:186
msgid "display rank"
msgstr ""
-#: judge/models/profile.py:189
+#: judge/models/profile.py:195
msgid "comment mute"
msgstr ""
-#: judge/models/profile.py:190
+#: judge/models/profile.py:196
msgid "Some users are at their best when silent."
msgstr ""
-#: judge/models/profile.py:194
+#: judge/models/profile.py:200
msgid "unlisted user"
msgstr ""
-#: judge/models/profile.py:195
+#: judge/models/profile.py:201
msgid "User will not be ranked."
msgstr ""
-#: judge/models/profile.py:199
+#: judge/models/profile.py:205
#, fuzzy
#| msgid "Banned from joining"
msgid "banned from voting"
msgstr "Bị cấm tham gia"
-#: judge/models/profile.py:200
+#: judge/models/profile.py:206
msgid "User will not be able to vote on problems' point values."
msgstr ""
-#: judge/models/profile.py:205
+#: judge/models/profile.py:211
msgid "user script"
msgstr ""
-#: judge/models/profile.py:209
+#: judge/models/profile.py:215
msgid "User-defined JavaScript for site customization."
msgstr ""
-#: judge/models/profile.py:213
+#: judge/models/profile.py:219
msgid "current contest"
msgstr "kỳ thi hiện tại"
-#: judge/models/profile.py:220
+#: judge/models/profile.py:226
msgid "math engine"
msgstr ""
-#: judge/models/profile.py:224
+#: judge/models/profile.py:230
msgid "the rendering engine used to render math"
msgstr ""
-#: judge/models/profile.py:227
+#: judge/models/profile.py:233
msgid "2FA enabled"
msgstr ""
-#: judge/models/profile.py:229
+#: judge/models/profile.py:235
msgid "check to enable TOTP-based two factor authentication"
msgstr "đánh dấu để sử dụng TOTP-based two factor authentication"
-#: judge/models/profile.py:235
+#: judge/models/profile.py:241
msgid "TOTP key"
msgstr "mã TOTP"
-#: judge/models/profile.py:236
+#: judge/models/profile.py:242
msgid "32 character base32-encoded key for TOTP"
msgstr ""
-#: judge/models/profile.py:238
+#: judge/models/profile.py:244
msgid "TOTP key must be empty or base32"
msgstr ""
-#: judge/models/profile.py:242
+#: judge/models/profile.py:248
msgid "internal notes"
msgstr "ghi chú nội bộ"
-#: judge/models/profile.py:245
+#: judge/models/profile.py:251
msgid "Notes for administrators regarding this user."
msgstr "Ghi chú riêng cho quản trị viên."
-#: judge/models/profile.py:250
+#: judge/models/profile.py:256
msgid "Custom background"
msgstr "Background tự chọn"
-#: judge/models/profile.py:253
+#: judge/models/profile.py:259
msgid "CSS custom background properties: url(\"image_url\"), color, etc"
msgstr "CSS background tự chọn. Ví dụ: url(\"image_url\"), white, ..."
-#: judge/models/profile.py:383
+#: judge/models/profile.py:426
msgid "user profile"
msgstr "thông tin người dùng"
-#: judge/models/profile.py:384
+#: judge/models/profile.py:427
msgid "user profiles"
msgstr "thông tin người dùng"
-#: judge/models/profile.py:400
+#: judge/models/profile.py:443
msgid "request time"
msgstr "thời gian đăng ký"
-#: judge/models/profile.py:403
+#: judge/models/profile.py:446
msgid "state"
msgstr "trạng thái"
-#: judge/models/profile.py:410
+#: judge/models/profile.py:453
msgid "reason"
msgstr "lý do"
-#: judge/models/profile.py:413
+#: judge/models/profile.py:456
msgid "organization join request"
msgstr "đơn đăng ký tham gia"
-#: judge/models/profile.py:414
+#: judge/models/profile.py:457
msgid "organization join requests"
msgstr "đơn đăng ký tham gia"
-#: judge/models/profile.py:480
+#: judge/models/profile.py:523
#, fuzzy
#| msgid "last seen"
msgid "last visit"
@@ -2401,15 +2419,15 @@ msgstr "Lỗi máy chấm"
msgid "submission time"
msgstr "thời gian bài nộp"
-#: judge/models/submission.py:69 judge/models/submission.py:268
+#: judge/models/submission.py:69 judge/models/submission.py:308
msgid "execution time"
msgstr "thời gian chạy"
-#: judge/models/submission.py:70 judge/models/submission.py:269
+#: judge/models/submission.py:70 judge/models/submission.py:309
msgid "memory usage"
msgstr "bộ nhớ sử dụng"
-#: judge/models/submission.py:72 judge/models/submission.py:270
+#: judge/models/submission.py:72 judge/models/submission.py:310
msgid "points granted"
msgstr "điểm"
@@ -2457,47 +2475,47 @@ msgstr "được chấm lại bởi admin"
msgid "was ran on pretests only"
msgstr "chỉ chấm pretest"
-#: judge/models/submission.py:234 templates/contest/moss.html:56
+#: judge/models/submission.py:274 templates/contest/moss.html:56
msgid "submissions"
msgstr "bài nộp"
-#: judge/models/submission.py:246 judge/models/submission.py:260
+#: judge/models/submission.py:286 judge/models/submission.py:300
msgid "associated submission"
msgstr "bài nộp tương ứng"
-#: judge/models/submission.py:264
+#: judge/models/submission.py:304
msgid "test case ID"
msgstr "test case ID"
-#: judge/models/submission.py:266
+#: judge/models/submission.py:306
msgid "status flag"
msgstr ""
-#: judge/models/submission.py:271
+#: judge/models/submission.py:311
msgid "points possible"
msgstr ""
-#: judge/models/submission.py:272
+#: judge/models/submission.py:312
msgid "batch number"
msgstr "số thứ tự của nhóm"
-#: judge/models/submission.py:274
+#: judge/models/submission.py:314
msgid "judging feedback"
msgstr "phản hồi từ máy chấm"
-#: judge/models/submission.py:277
+#: judge/models/submission.py:317
msgid "extended judging feedback"
msgstr "phản hồi thêm từ máy chấm"
-#: judge/models/submission.py:279
+#: judge/models/submission.py:319
msgid "program output"
msgstr "output chương trình"
-#: judge/models/submission.py:287
+#: judge/models/submission.py:327
msgid "submission test case"
msgstr "cái testcase trong bài nộp"
-#: judge/models/submission.py:288
+#: judge/models/submission.py:328
msgid "submission test cases"
msgstr "cái testcase trong bài nộp"
@@ -2603,59 +2621,59 @@ msgstr "Chỉnh sửa bài nộp"
msgid "Recalculating user points"
msgstr "Tính lại điểm người dùng"
-#: judge/utils/problem_data.py:72
+#: judge/utils/problem_data.py:73
msgid "Empty batches not allowed."
msgstr "Nhóm test trống là không hợp lệ."
-#: judge/utils/problem_data.py:80 judge/utils/problem_data.py:88
-#: judge/utils/problem_data.py:103
+#: judge/utils/problem_data.py:81 judge/utils/problem_data.py:89
+#: judge/utils/problem_data.py:104
msgid "How did you corrupt the custom checker path?"
msgstr "How did you corrupt the custom checker path?"
-#: judge/utils/problem_data.py:131
+#: judge/utils/problem_data.py:132
#, python-format
msgid "Points must be defined for non-batch case #%d."
msgstr "Ô điểm số cho test #%d phải được điền."
-#: judge/utils/problem_data.py:138
+#: judge/utils/problem_data.py:139
#, python-format
msgid "Input file for case %d does not exist: %s"
msgstr "File input cho test %d không tồn tại: %s"
-#: judge/utils/problem_data.py:143
+#: judge/utils/problem_data.py:144
#, python-format
msgid "Output file for case %d does not exist: %s"
msgstr "File output cho test %d không tồn tại: %s"
-#: judge/utils/problem_data.py:170
+#: judge/utils/problem_data.py:171
#, python-format
msgid "Batch start case #%d requires points."
msgstr "Nhóm test #%d cần được điền điểm số."
-#: judge/utils/problem_data.py:193
+#: judge/utils/problem_data.py:194
#, python-format
msgid "Attempt to end batch outside of one in case #%d"
msgstr "Nhóm test #%d kết thúc không hợp lệ"
-#: judge/utils/problem_data.py:212
+#: judge/utils/problem_data.py:213
msgid "How did you corrupt the zip path?"
msgstr ""
-#: judge/utils/problem_data.py:218
+#: judge/utils/problem_data.py:219
msgid "How did you corrupt the generator path?"
msgstr ""
-#: judge/utils/problem_data.py:236
+#: judge/utils/problem_data.py:237
msgid "Invalid interactor judge"
msgstr ""
-#: judge/utils/problem_data.py:260
+#: judge/utils/problem_data.py:261
#, fuzzy
#| msgid "Invalid Return"
msgid "Invalid signature handler"
msgstr "Invalid Return"
-#: judge/utils/problem_data.py:263
+#: judge/utils/problem_data.py:264
msgid "Invalid signature header"
msgstr ""
@@ -2735,165 +2753,171 @@ msgstr "Báo cáo"
msgid "Comment feed"
msgstr "Bình luận"
-#: judge/views/comment.py:53 judge/views/pagevote.py:31
+#: judge/views/comment.py:47 judge/views/pagevote.py:31
msgid "Messing around, are we?"
msgstr "Messing around, are we?"
-#: judge/views/comment.py:69 judge/views/pagevote.py:47
+#: judge/views/comment.py:63 judge/views/pagevote.py:47
msgid "You must solve at least one problem before you can vote."
msgstr "Bạn phải giải ít nhất 1 bài trước khi được vote."
-#: judge/views/comment.py:100
+#: judge/views/comment.py:94
msgid "You already voted."
msgstr "Bạn đã vote."
-#: judge/views/comment.py:253 judge/views/organization.py:807
-#: judge/views/organization.py:957 judge/views/organization.py:1122
+#: judge/views/comment.py:246 judge/views/organization.py:808
+#: judge/views/organization.py:958 judge/views/organization.py:1120
msgid "Edited from site"
msgstr "Chỉnh sửa từ web"
-#: judge/views/comment.py:274
+#: judge/views/comment.py:267
msgid "Editing comment"
msgstr "Chỉnh sửa bình luận"
-#: judge/views/contests.py:120 judge/views/contests.py:370
-#: judge/views/contests.py:375 judge/views/contests.py:646
+#: judge/views/contests.py:123 judge/views/contests.py:386
+#: judge/views/contests.py:391 judge/views/contests.py:685
msgid "No such contest"
msgstr "Không có contest nào như vậy"
-#: judge/views/contests.py:121 judge/views/contests.py:371
+#: judge/views/contests.py:124 judge/views/contests.py:387
#, python-format
msgid "Could not find a contest with the key \"%s\"."
msgstr "Không tìm thấy kỳ thi với mã \"%s\"."
-#: judge/views/contests.py:140 judge/views/stats.py:178
-#: templates/contest/list.html:246 templates/contest/list.html:291
-#: templates/contest/list.html:336 templates/contest/list.html:378
+#: judge/views/contests.py:143 judge/views/stats.py:178
+#: templates/contest/list.html:244 templates/contest/list.html:289
+#: templates/contest/list.html:334 templates/contest/list.html:376
#: templates/organization/org-left-sidebar.html:5 templates/stats/site.html:21
#: templates/user/user-bookmarks.html:56
msgid "Contests"
msgstr "Kỳ thi"
-#: judge/views/contests.py:375
+#: judge/views/contests.py:391
msgid "Could not find such contest."
msgstr "Không tìm thấy kỳ thi nào như vậy."
-#: judge/views/contests.py:383
+#: judge/views/contests.py:399
#, python-format
msgid "Access to contest \"%s\" denied"
msgstr "Truy cập tới kỳ thi \"%s\" bị từ chối"
-#: judge/views/contests.py:434
+#: judge/views/contests.py:468
msgid "Clone Contest"
msgstr "Nhân bản kỳ thi"
-#: judge/views/contests.py:520
+#: judge/views/contests.py:559
msgid "Contest not ongoing"
msgstr "Kỳ thi đang không diễn ra"
-#: judge/views/contests.py:521
+#: judge/views/contests.py:560
#, python-format
msgid "\"%s\" is not currently ongoing."
msgstr "\"%s\" kỳ thi đang không diễn ra."
-#: judge/views/contests.py:528
+#: judge/views/contests.py:567
msgid "Already in contest"
msgstr "Đã ở trong kỳ thi"
-#: judge/views/contests.py:529
+#: judge/views/contests.py:568
#, python-format
msgid "You are already in a contest: \"%s\"."
msgstr "Bạn đã ở trong kỳ thi: \"%s\"."
-#: judge/views/contests.py:539
+#: judge/views/contests.py:578
msgid "Banned from joining"
msgstr "Bị cấm tham gia"
-#: judge/views/contests.py:541
+#: judge/views/contests.py:580
msgid ""
"You have been declared persona non grata for this contest. You are "
"permanently barred from joining this contest."
msgstr "Bạn không được phép tham gia kỳ thi này."
-#: judge/views/contests.py:630
+#: judge/views/contests.py:669
#, python-format
msgid "Enter access code for \"%s\""
msgstr "Nhập mật khẩu truy cập cho \"%s\""
-#: judge/views/contests.py:647
+#: judge/views/contests.py:686
#, python-format
msgid "You are not in contest \"%s\"."
msgstr "Bạn không ở trong kỳ thi \"%s\"."
-#: judge/views/contests.py:670
+#: judge/views/contests.py:709
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"
-#: judge/views/contests.py:728
+#: judge/views/contests.py:767
#, python-format
msgid "Contests in %(month)s"
msgstr "Các kỳ thi trong %(month)s"
-#: judge/views/contests.py:729
+#: judge/views/contests.py:768
msgid "F Y"
msgstr "F Y"
-#: judge/views/contests.py:789
+#: judge/views/contests.py:828
#, python-format
msgid "%s Statistics"
msgstr "%s Thống kê"
-#: judge/views/contests.py:1085
+#: judge/views/contests.py:1124
#, python-format
msgid "%s Rankings"
msgstr "%s Bảng điểm"
-#: judge/views/contests.py:1096
+#: judge/views/contests.py:1135
msgid "???"
msgstr "???"
-#: judge/views/contests.py:1123
+#: judge/views/contests.py:1162
#, python-format
msgid "Your participation in %s"
msgstr "Lần tham gia trong %s"
-#: judge/views/contests.py:1124
+#: judge/views/contests.py:1163
#, python-format
msgid "%s's participation in %s"
msgstr "Lần tham gia của %s trong %s"
-#: judge/views/contests.py:1138
+#: judge/views/contests.py:1177
msgid "Live"
msgstr "Trực tiếp"
-#: judge/views/contests.py:1157 templates/contest/contest-tabs.html:19
+#: judge/views/contests.py:1196 templates/contest/contest-tabs.html:21
msgid "Participation"
msgstr "Lần tham gia"
-#: judge/views/contests.py:1206
+#: judge/views/contests.py:1245
#, python-format
msgid "%s MOSS Results"
msgstr "%s Kết quả MOSS"
-#: judge/views/contests.py:1242
+#: judge/views/contests.py:1281
#, python-format
msgid "Running MOSS for %s..."
msgstr "Đang chạy MOSS cho %s..."
-#: judge/views/contests.py:1265
+#: judge/views/contests.py:1304
#, python-format
msgid "Contest tag: %s"
msgstr "Nhãn kỳ thi: %s"
-#: judge/views/contests.py:1280 judge/views/ticket.py:72
+#: judge/views/contests.py:1319 judge/views/ticket.py:67
msgid "Issue description"
msgstr "Mô tả vấn đề"
-#: judge/views/contests.py:1323
+#: judge/views/contests.py:1362
#, python-format
msgid "New clarification for %s"
msgstr "Thông báo mới cho %s"
+#: judge/views/contests.py:1468
+#, fuzzy
+#| msgid "contest summary"
+msgid "Contests Summary"
+msgstr "tổng kết kỳ thi"
+
#: judge/views/email.py:21
msgid "New Email"
msgstr "Email mới"
@@ -2974,103 +2998,107 @@ msgstr "thời gian đăng ký"
msgid "Runtimes"
msgstr "Runtimes"
-#: judge/views/notification.py:43
+#: judge/views/markdown_editor.py:12
+msgid "Markdown Editor"
+msgstr ""
+
+#: judge/views/notification.py:29
#, python-format
msgid "Notifications (%d unseen)"
msgstr "Thông báo (%d chưa xem)"
-#: judge/views/organization.py:148 judge/views/organization.py:155
+#: judge/views/organization.py:149 judge/views/organization.py:156
msgid "No such organization"
msgstr "Không có tổ chức như vậy"
-#: judge/views/organization.py:149
+#: judge/views/organization.py:150
#, python-format
msgid "Could not find an organization with the key \"%s\"."
msgstr "Không tìm thấy tổ chức với mã \"%s\"."
-#: judge/views/organization.py:156
+#: judge/views/organization.py:157
msgid "Could not find such organization."
msgstr ""
-#: judge/views/organization.py:180
+#: judge/views/organization.py:181
msgid "Can't edit organization"
msgstr "Không thể chỉnh sửa tổ chức"
-#: judge/views/organization.py:181
+#: judge/views/organization.py:182
msgid "You are not allowed to edit this organization."
msgstr "Bạn không được phép chỉnh sửa tổ chức này."
-#: judge/views/organization.py:193 judge/views/organization.py:337
+#: judge/views/organization.py:194 judge/views/organization.py:338
msgid "Can't access organization"
msgstr "Không thể truy cập nhóm"
-#: judge/views/organization.py:194 judge/views/organization.py:338
+#: judge/views/organization.py:195 judge/views/organization.py:339
msgid "You are not allowed to access this organization."
msgstr "Bạn không được phép chỉnh sửa tổ chức này."
-#: judge/views/organization.py:230 judge/views/stats.py:184
-#: templates/contest/list.html:93 templates/problem/list-base.html:97
+#: judge/views/organization.py:231 judge/views/stats.py:184
+#: templates/contest/list.html:93 templates/problem/list-base.html:91
#: templates/stats/site.html:33 templates/user/user-left-sidebar.html:4
#: templates/user/user-list-tabs.html:6
msgid "Groups"
msgstr "Nhóm"
-#: judge/views/organization.py:344
+#: judge/views/organization.py:345
#, python-format
msgid "%s Members"
msgstr "%s Thành viên"
-#: judge/views/organization.py:466
+#: judge/views/organization.py:467
#, python-brace-format
msgid "All submissions in {0}"
msgstr "Bài nộp trong {0}"
-#: judge/views/organization.py:496 judge/views/organization.py:502
-#: judge/views/organization.py:509
+#: judge/views/organization.py:497 judge/views/organization.py:503
+#: judge/views/organization.py:510
msgid "Joining group"
msgstr "Tham gia nhóm"
-#: judge/views/organization.py:497
+#: judge/views/organization.py:498
msgid "You are already in the group."
msgstr "Bạn đã ở trong nhóm."
-#: judge/views/organization.py:502
+#: judge/views/organization.py:503
msgid "This group is not open."
msgstr "Nhóm này là nhóm kín."
-#: judge/views/organization.py:510
+#: judge/views/organization.py:511
#, python-brace-format
msgid "You may not be part of more than {count} public groups."
msgstr "Bạn không thể tham gia nhiều hơn {count} nhóm công khai."
-#: judge/views/organization.py:525
+#: judge/views/organization.py:526
msgid "Leaving group"
msgstr "Rời nhóm"
-#: judge/views/organization.py:526
+#: judge/views/organization.py:527
#, python-format
msgid "You are not in \"%s\"."
msgstr "Bạn không ở trong \"%s\"."
-#: judge/views/organization.py:551
+#: judge/views/organization.py:552
#, python-format
msgid "Request to join %s"
msgstr "Đăng ký tham gia %s"
-#: judge/views/organization.py:581
+#: judge/views/organization.py:582
msgid "Join request detail"
msgstr "Chi tiết đơn đăng ký"
-#: judge/views/organization.py:623
+#: judge/views/organization.py:624
msgid "Manage join requests"
msgstr "Quản lý đơn đăng ký"
-#: judge/views/organization.py:627
+#: judge/views/organization.py:628
#, python-format
msgid "Managing join requests for %s"
msgstr "Quản lý đơn đăng ký cho %s"
-#: judge/views/organization.py:667
+#: judge/views/organization.py:668
#, python-format
msgid ""
"Your organization can only receive %d more members. You cannot approve %d "
@@ -3079,96 +3107,105 @@ msgstr ""
"Tổ chức chỉ có thể chứa %d thành viên. Bạn không thể chấp thuận nhiều hơn %d "
"người."
-#: judge/views/organization.py:685
+#: judge/views/organization.py:686
#, python-format
msgid "Approved %d user."
msgid_plural "Approved %d users."
msgstr[0] "Đã chấp thuận %d người."
-#: judge/views/organization.py:688
+#: judge/views/organization.py:689
#, python-format
msgid "Rejected %d user."
msgid_plural "Rejected %d users."
msgstr[0] "Đã từ chối %d người."
-#: judge/views/organization.py:728
+#: judge/views/organization.py:729
#, python-format
msgid "Add member for %s"
msgstr "Thêm thành viên cho %s"
-#: judge/views/organization.py:740
+#: judge/views/organization.py:741
#, fuzzy
#| msgid "Edited from site"
msgid "Added members from site"
msgstr "Chỉnh sửa từ web"
-#: judge/views/organization.py:760 judge/views/organization.py:768
+#: judge/views/organization.py:761 judge/views/organization.py:769
msgid "Can't kick user"
msgstr "Không thể đuổi"
-#: judge/views/organization.py:761
+#: judge/views/organization.py:762
msgid "The user you are trying to kick does not exist!"
msgstr ""
-#: judge/views/organization.py:769
+#: judge/views/organization.py:770
#, python-format
msgid "The user you are trying to kick is not in organization: %s."
msgstr ""
-#: judge/views/organization.py:790 judge/views/organization.py:946
-#, fuzzy, python-format
-#| msgid "Editing %s"
+#: judge/views/organization.py:791 judge/views/organization.py:947
+#, python-format
msgid "Edit %s"
-msgstr "Đang chỉnh sửa %s"
+msgstr "Chỉnh sửa %s"
-#: judge/views/organization.py:818 templates/organization/list.html:45
+#: judge/views/organization.py:819 templates/organization/list.html:45
msgid "Create group"
msgstr "Tạo nhóm"
-#: judge/views/organization.py:833
+#: judge/views/organization.py:834
msgid "Exceeded limit"
msgstr ""
-#: judge/views/organization.py:834
+#: judge/views/organization.py:835
#, python-format
msgid "You created too many groups. You can only create at most %d groups"
msgstr ""
-#: judge/views/organization.py:839 judge/views/organization.py:864
-#: judge/views/organization.py:1012
+#: judge/views/organization.py:840 judge/views/organization.py:865
+#: judge/views/organization.py:1026
msgid "Added from site"
msgstr "Thêm từ web"
-#: judge/views/organization.py:855
+#: judge/views/organization.py:856
#: templates/organization/org-right-sidebar.html:52
msgid "Add contest"
msgstr "Thêm kỳ thi"
-#: judge/views/organization.py:898 judge/views/organization.py:1064
+#: judge/views/organization.py:899 judge/views/organization.py:1071
msgid "Permission denied"
msgstr "Truy cập bị từ chối"
-#: judge/views/organization.py:899
+#: judge/views/organization.py:900
#, fuzzy
#| msgid "You are not allowed to edit this organization."
msgid "You are not allowed to edit this contest"
msgstr "Bạn không được phép chỉnh sửa tổ chức này."
-#: judge/views/organization.py:1001
+#: judge/views/organization.py:951 templates/blog/blog.html:31
+#: templates/comments/content-list.html:59
+#: templates/comments/content-list.html:73
+#: templates/contest/contest-tabs.html:37 templates/contest/list.html:128
+#: templates/contest/tag-title.html:9 templates/flatpages/admin_link.html:3
+#: templates/license.html:10 templates/problem/editorial.html:15
+#: templates/problem/feed/problems.html:50
+msgid "Edit"
+msgstr "Chỉnh sửa"
+
+#: judge/views/organization.py:1015
#, python-format
msgid "Add blog for %s"
msgstr "Thêm bài đăng cho %s"
-#: judge/views/organization.py:1065
+#: judge/views/organization.py:1072
msgid "Not allowed to edit this blog"
msgstr "Bạn không được phép chỉnh sửa bài đăng này."
-#: judge/views/organization.py:1097
+#: judge/views/organization.py:1104
#, python-format
msgid "Edit blog %s"
msgstr "Chỉnh sửa %s"
-#: judge/views/organization.py:1148
+#: judge/views/organization.py:1146
#, python-format
msgid "Pending blogs in %s"
msgstr "Bài đang đợi duyệt trong %s"
@@ -3192,77 +3229,77 @@ msgstr "Hướng dẫn cho {0}"
msgid "Editorial for {0}"
msgstr "Hướng dẫn cho {0}"
-#: judge/views/problem.py:461 templates/contest/contest.html:96
+#: judge/views/problem.py:461 templates/contest/contest.html:101
#: templates/organization/org-left-sidebar.html:4
#: templates/user/user-about.html:28 templates/user/user-bookmarks.html:35
#: templates/user/user-tabs.html:5 templates/user/users-table.html:19
msgid "Problems"
msgstr "Bài tập"
-#: judge/views/problem.py:837
+#: judge/views/problem.py:834
msgid "Problem feed"
msgstr "Bài tập"
-#: judge/views/problem.py:1062
+#: judge/views/problem.py:1057
msgid "Banned from submitting"
msgstr "Bị cấm nộp bài"
-#: judge/views/problem.py:1064
+#: judge/views/problem.py:1059
msgid ""
"You have been declared persona non grata for this problem. You are "
"permanently barred from submitting this problem."
msgstr "Bạn đã bị cấm nộp bài này."
-#: judge/views/problem.py:1087
+#: judge/views/problem.py:1082
msgid "Too many submissions"
msgstr "Quá nhiều lần nộp"
-#: judge/views/problem.py:1089
+#: judge/views/problem.py:1084
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."
-#: judge/views/problem.py:1168 judge/views/problem.py:1173
+#: judge/views/problem.py:1163 judge/views/problem.py:1168
#, python-format
msgid "Submit to %(problem)s"
msgstr "Nộp bài cho %(problem)s"
-#: judge/views/problem.py:1199
+#: judge/views/problem.py:1194
msgid "Clone Problem"
msgstr "Nhân bản bài tập"
-#: judge/views/problem_data.py:70
+#: judge/views/problem_data.py:71
msgid "Checker arguments must be a JSON object"
msgstr ""
-#: judge/views/problem_data.py:72
+#: judge/views/problem_data.py:73
msgid "Checker arguments is invalid JSON"
msgstr ""
-#: judge/views/problem_data.py:79
+#: judge/views/problem_data.py:80
msgid "Your zip file is invalid!"
msgstr "File Zip không hợp lệ!"
-#: judge/views/problem_data.py:169
+#: judge/views/problem_data.py:170
#, python-brace-format
msgid "Comparing submissions for {0}"
msgstr "So sánh các bài nộp cho {0}"
-#: judge/views/problem_data.py:173
+#: judge/views/problem_data.py:174
#, python-brace-format
msgid "Comparing submissions for {0}"
msgstr "So sánh các bài nộp cho {0}"
-#: judge/views/problem_data.py:210
+#: judge/views/problem_data.py:211
#, python-brace-format
msgid "Editing data for {0}"
msgstr "Chỉnh sửa dữ liệu cho {0}"
-#: judge/views/problem_data.py:214
+#: judge/views/problem_data.py:215
#, python-format
msgid "Editing data for %s"
msgstr "Chỉnh sửa dữ liệu cho %s"
-#: judge/views/problem_data.py:344 judge/views/problem_data.py:346
+#: judge/views/problem_data.py:348 judge/views/problem_data.py:350
#, python-format
msgid "Generated init.yml for %s"
msgstr "File init.yml cho %s"
@@ -3330,7 +3367,7 @@ msgstr "Đăng ký"
msgid "Authentication failure"
msgstr "Xác thực thất bại"
-#: judge/views/resolver.py:11 templates/contest/contest-tabs.html:26
+#: judge/views/resolver.py:11 templates/contest/contest-tabs.html:28
#, fuzzy
#| msgid "solve rate"
msgid "Resolver"
@@ -3370,60 +3407,60 @@ msgstr "Kết quả chấm"
msgid "Version matrix"
msgstr "Ma trận phiên bản"
-#: judge/views/submission.py:118 judge/views/submission.py:126
+#: judge/views/submission.py:93 judge/views/submission.py:101
#, python-format
msgid "Submission of %(problem)s by %(user)s"
msgstr "Bài nộp của %(user)s cho bài %(problem)s"
-#: judge/views/submission.py:318 judge/views/submission.py:319
+#: judge/views/submission.py:293 judge/views/submission.py:294
#: templates/problem/problem.html:168
msgid "All submissions"
msgstr "Tất cả bài nộp"
-#: judge/views/submission.py:595 judge/views/submission.py:600
+#: judge/views/submission.py:560 judge/views/submission.py:565
msgid "All my submissions"
msgstr "Tất cả bài nộp của tôi"
-#: judge/views/submission.py:596
+#: judge/views/submission.py:561
#, python-format
msgid "All submissions by %s"
msgstr "Tất cả bài nộp của %s"
-#: judge/views/submission.py:602
+#: judge/views/submission.py:567
#, python-brace-format
msgid "All submissions by {0}"
msgstr "Tất cả bài nộp của {0}"
-#: judge/views/submission.py:623
+#: judge/views/submission.py:588
#, fuzzy
#| msgid "All submissions"
msgid "All friend submissions"
msgstr "Tất cả bài nộp"
-#: judge/views/submission.py:652
+#: judge/views/submission.py:617
#, python-format
msgid "All submissions for %s"
msgstr "Tất cả bài nộp cho %s"
-#: judge/views/submission.py:680
+#: judge/views/submission.py:645
msgid "Must pass a problem"
msgstr "Phải làm được một bài"
-#: judge/views/submission.py:738
+#: judge/views/submission.py:703
#, python-format
msgid "My submissions for %(problem)s"
msgstr "Bài nộp của tôi cho %(problem)s"
-#: judge/views/submission.py:739
+#: judge/views/submission.py:704
#, python-format
msgid "%(user)s's submissions for %(problem)s"
msgstr "Các bài nộp của %(user)s cho %(problem)s"
-#: judge/views/submission.py:884
+#: judge/views/submission.py:840
msgid "Must pass a contest"
msgstr "Phải qua một kỳ thi"
-#: judge/views/submission.py:914
+#: judge/views/submission.py:870
#, python-brace-format
msgid ""
"{0}'s submissions for {2} in {0} cho {2} trong {4}"
-#: judge/views/submission.py:926
+#: judge/views/submission.py:882
#, python-brace-format
msgid ""
"{0}'s submissions for problem {2} in {3}"
@@ -3441,50 +3478,50 @@ msgstr ""
"Các bài nộp của {0} cho bài {2} trong {3}"
""
-#: judge/views/submission.py:1063
+#: judge/views/submission.py:1016
#, fuzzy
#| msgid "You do not have the permission to rejudge submissions."
msgid "You don't have permission to access."
msgstr "Bạn không có quyền chấm lại bài."
-#: judge/views/ticket.py:65 judge/views/ticket.py:71
+#: judge/views/ticket.py:60 judge/views/ticket.py:66
msgid "Ticket title"
msgstr "Tiêu đề báo cáo"
-#: judge/views/ticket.py:129 judge/views/ticket.py:133
+#: judge/views/ticket.py:124 judge/views/ticket.py:128
#, python-format
msgid "New ticket for %s"
msgstr "Báo cáo mới cho %s"
-#: judge/views/ticket.py:210
+#: judge/views/ticket.py:205
#, python-format
msgid "%(title)s - Ticket %(id)d"
msgstr "%(title)s - Báo cáo %(id)d"
-#: judge/views/ticket.py:339
+#: judge/views/ticket.py:334
#, python-format
msgid "Tickets - Page %(number)d of %(total)d"
msgstr "Báo cáo - Trang %(number)d trên %(total)d"
-#: judge/views/ticket.py:405
+#: judge/views/ticket.py:400
#, python-format
msgid "New Ticket: %s"
msgstr "Báo cáo mới: %s"
-#: judge/views/ticket.py:408
+#: judge/views/ticket.py:403
#, python-format
msgid "#%(id)d, assigned to: %(users)s"
msgstr "#%(id)d, được phân cho: %(users)s"
-#: judge/views/ticket.py:412
+#: judge/views/ticket.py:407
msgid ", "
msgstr ", "
-#: judge/views/ticket.py:417
+#: judge/views/ticket.py:412
msgid "no one"
msgstr "không người nào"
-#: judge/views/ticket.py:444
+#: judge/views/ticket.py:439
#, python-format
msgid "New Ticket Message For: %s"
msgstr "Tin nhắn báo cáo mới cho: %s"
@@ -3532,7 +3569,7 @@ msgid "Updated on site"
msgstr "Được cập nhật trên web"
#: judge/views/user.py:431 templates/admin/auth/user/change_form.html:14
-#: templates/admin/auth/user/change_form.html:17 templates/base.html:300
+#: templates/admin/auth/user/change_form.html:17 templates/base.html:199
#: templates/user/user-tabs.html:11
msgid "Edit profile"
msgstr "Chỉnh sửa thông tin"
@@ -3575,6 +3612,10 @@ msgstr "Chia sẻ"
msgid "Report"
msgstr "Báo cáo"
+#: templates/actionbar/media-js.html:116
+msgid "Copied link"
+msgstr "Đã sao chép link"
+
#: templates/admin/judge/contest/change_form.html:9
msgid "Are you sure you want to rejudge ALL the submissions?"
msgstr "Bạn có muốn chấm lại tất cả bài nộp?"
@@ -3623,72 +3664,56 @@ msgstr "Chỉnh sửa thông tin"
msgid "Rejudge"
msgstr "Chấm lại"
-#: templates/base.html:236 templates/chat/chat.html:65
+#: templates/base.html:137
msgid "Chat"
msgstr "Chat"
-#: templates/base.html:246
+#: templates/base.html:147
msgid "Notification"
msgstr "Thông báo"
-#: templates/base.html:267
+#: templates/base.html:173
msgid "Dark Mode"
msgstr ""
-#: templates/base.html:284
+#: templates/base.html:183
msgid "Profile"
msgstr "Trang cá nhân"
-#: templates/base.html:288 templates/chat/chat_js.html:5
-#: templates/comments/content-list.html:81
-#: templates/contest/contest-list-tabs.html:4
-#: templates/contest/ranking-table.html:47 templates/internal/problem.html:62
-#: templates/organization/org-left-sidebar.html:12
-#: templates/problem/left-sidebar.html:6
-#: templates/problem/problem-list-tabs.html:6
-#: templates/submission/info-base.html:12 templates/submission/list.html:395
-#: templates/submission/submission-list-tabs.html:15
-msgid "Admin"
-msgstr "Admin"
-
-#: templates/base.html:293
+#: templates/base.html:192
msgid "Internal"
msgstr "Nội bộ"
-#: templates/base.html:296
+#: templates/base.html:195
msgid "Stats"
msgstr "Thống kê"
-#: templates/base.html:309
+#: templates/base.html:208
msgid "Log out"
msgstr "Đăng xuất"
-#: templates/base.html:319
+#: templates/base.html:218
#: templates/registration/password_reset_complete.html:4
msgid "Log in"
msgstr "Đăng nhập"
-#: templates/base.html:320 templates/registration/registration_form.html:72
-msgid "or"
-msgstr "hoặc"
-
-#: templates/base.html:321
+#: templates/base.html:219
msgid "Sign up"
msgstr "Đăng ký"
-#: templates/base.html:335
+#: templates/base.html:233
msgid "spectating"
msgstr "đang theo dõi"
-#: templates/base.html:347
+#: templates/base.html:245
msgid "Compete"
msgstr "Thi"
-#: templates/base.html:349
+#: templates/base.html:247
msgid "General"
msgstr "Chung"
-#: templates/base.html:356
+#: templates/base.html:254
msgid "This site works best with JavaScript enabled."
msgstr ""
@@ -3697,15 +3722,6 @@ msgstr ""
msgid " posted on %(time)s"
msgstr "đã đăng vào %(time)s"
-#: templates/blog/blog.html:31 templates/comments/content-list.html:62
-#: templates/comments/content-list.html:76
-#: templates/contest/contest-tabs.html:35 templates/contest/list.html:129
-#: templates/contest/tag-title.html:9 templates/flatpages/admin_link.html:3
-#: templates/license.html:10 templates/problem/editorial.html:15
-#: templates/problem/feed/problems.html:50
-msgid "Edit"
-msgstr "Chỉnh sửa"
-
#: templates/blog/blog.html:35 templates/contest/contest.html:88
msgid "Edit in"
msgstr "Chỉnh sửa trong"
@@ -3760,45 +3776,29 @@ msgstr "Thêm mới"
msgid "No clarifications have been made at this time."
msgstr "Không có thông báo nào."
-#: templates/chat/chat.html:5 templates/chat/chat_js.html:548
+#: templates/chat/chat.html:5 templates/chat/chat_js.html:539
msgid "Chat Box"
msgstr "Chat Box"
-#: templates/chat/chat.html:67
-msgid "Online Users"
-msgstr "Trực tuyến"
-
-#: templates/chat/chat.html:78 templates/chat/chat_js.html:510
+#: templates/chat/chat.html:72 templates/chat/chat_js.html:501
#: templates/user/base-users-js.html:10
#: templates/user/base-users-two-col.html:19
msgid "Search by handle..."
msgstr "Tìm kiếm theo tên..."
-#: templates/chat/chat.html:97
+#: templates/chat/chat.html:91
msgid "Enter your message"
msgstr "Nhập tin nhắn"
-#: templates/chat/chat.html:98
+#: templates/chat/chat.html:92
msgid "Emoji"
msgstr ""
-#: templates/chat/chat_js.html:3
-msgid "Recent"
-msgstr "Gần đây"
-
-#: templates/chat/chat_js.html:4
-msgid "Following"
-msgstr "Bạn bè"
-
-#: templates/chat/chat_js.html:6
-msgid "Other"
-msgstr "Thành viên khác"
-
-#: templates/chat/chat_js.html:124
+#: templates/chat/chat_js.html:118
msgid "New message(s)"
msgstr "Tin nhắn mới"
-#: templates/chat/chat_js.html:401
+#: templates/chat/chat_js.html:412
msgid "Mute this user and delete all messages?"
msgstr "Mute người dùng này và xóa tất cả tin nhắn chung?"
@@ -3816,57 +3816,57 @@ msgid "You are connect now. Say something to start the conversation."
msgstr "Các bạn đã kết nối. Nhắn gì đó để bắt đầu cuộc trò chuyện."
#: templates/chat/online_status.html:6
-#: templates/chat/user_online_status.html:14
+#: templates/chat/user_online_status.html:21
msgid "Lobby"
msgstr "Sảnh chung"
-#: templates/chat/user_online_status.html:19
+#: templates/chat/user_online_status.html:26
#, python-brace-format
msgid "Last online on {time}"
msgstr "Trực tuyến vào {time}"
-#: templates/chat/user_online_status.html:31
+#: templates/chat/user_online_status.html:38
msgid "Unignore"
msgstr "Mở lại thông báo"
-#: templates/chat/user_online_status.html:33
+#: templates/chat/user_online_status.html:40
msgid "Ignore"
msgstr "Tắt thông báo"
-#: templates/chat/user_online_status.html:40
+#: templates/chat/user_online_status.html:47
msgid "users are online"
msgstr "người đang trực tuyến"
-#: templates/comments/content-list.html:14
-#: templates/comments/content-list.html:15
-#: templates/comments/content-list.html:23
-#: templates/comments/content-list.html:24
+#: templates/comments/content-list.html:11
+#: templates/comments/content-list.html:12
+#: templates/comments/content-list.html:20
+#: templates/comments/content-list.html:21
msgid "Please login to vote"
msgstr "Đăng nhập để vote"
-#: templates/comments/content-list.html:44
+#: templates/comments/content-list.html:41
#, python-format
msgid "edit %(edits)s"
msgstr "chỉnh sửa %(edits)s"
-#: templates/comments/content-list.html:46 templates/comments/media-js.html:97
+#: templates/comments/content-list.html:43 templates/comments/media-js.html:97
msgid "edited"
msgstr "đã chỉnh sửa"
-#: templates/comments/content-list.html:55 templates/notification/list.html:14
+#: templates/comments/content-list.html:52 templates/notification/list.html:11
msgid "Link"
msgstr "Link"
-#: templates/comments/content-list.html:66
-#: templates/comments/content-list.html:72
+#: templates/comments/content-list.html:63
+#: templates/comments/content-list.html:69
msgid "Reply"
msgstr "Phản hồi"
-#: templates/comments/content-list.html:79
+#: templates/comments/content-list.html:76
msgid "Hide"
msgstr "Ẩn"
-#: templates/comments/content-list.html:94
+#: templates/comments/content-list.html:91
#, python-format
msgid ""
"This comment is hidden due to too much negative feedback. Click đây để mở."
-#: templates/comments/content-list.html:111
+#: templates/comments/content-list.html:108
msgid "reply"
msgid_plural "replies"
msgstr[0] "phản hồi"
-#: templates/comments/content-list.html:136
+#: templates/comments/content-list.html:133
msgid "more comment"
msgid_plural "more comments"
msgstr[0] "bình luận nữa"
@@ -3975,7 +3975,7 @@ msgstr "Thứ sáu"
msgid "Saturday"
msgstr "Thứ bảy"
-#: templates/contest/clarification.html:52 templates/contest/list.html:232
+#: templates/contest/clarification.html:52 templates/contest/list.html:230
#: templates/organization/new.html:10 templates/ticket/new.html:38
msgid "Create"
msgstr "Tạo mới"
@@ -3984,12 +3984,6 @@ msgstr "Tạo mới"
msgid "Enter a new key for the cloned contest:"
msgstr "Nhập mã kỳ thi cho kỳ thi nhân bản:"
-#: templates/contest/clone.html:47
-#, fuzzy
-#| msgid "Groups"
-msgid "Group:"
-msgstr "Nhóm"
-
#: templates/contest/clone.html:55 templates/problem/clone.html:40
msgid "Clone!"
msgstr "Nhân bản!"
@@ -4069,39 +4063,35 @@ msgstr "Danh sách"
msgid "Calendar"
msgstr "Lịch"
-#: templates/contest/contest-tabs.html:10
+#: templates/contest/contest-tabs.html:11
msgid "Info"
msgstr "Thông tin"
-#: templates/contest/contest-tabs.html:12 templates/submission/list.html:363
+#: templates/contest/contest-tabs.html:13 templates/submission/list.html:363
msgid "Statistics"
msgstr "Thống kê"
-#: templates/contest/contest-tabs.html:17
+#: templates/contest/contest-tabs.html:19
msgid "Rankings"
msgstr "Bảng xếp hạng"
-#: templates/contest/contest-tabs.html:22
+#: templates/contest/contest-tabs.html:24
msgid "Hidden Rankings"
msgstr "Bảng xếp hạng ẩn"
-#: templates/contest/contest-tabs.html:29
+#: templates/contest/contest-tabs.html:31
msgid "Final rankings"
msgstr "BXH chung cuộc"
-#: templates/contest/contest-tabs.html:33
+#: templates/contest/contest-tabs.html:35
msgid "MOSS"
msgstr "MOSS"
-#: templates/contest/contest-tabs.html:38
-msgid "Clone"
-msgstr "Nhân bản"
-
#: templates/contest/contest.html:35 templates/contest/contest.html:55
msgid "Leave contest"
msgstr "Rời kỳ thi"
-#: templates/contest/contest.html:42 templates/contest/list.html:400
+#: templates/contest/contest.html:42 templates/contest/list.html:398
msgid "Virtual join"
msgstr "Tham gia ảo"
@@ -4121,21 +4111,36 @@ msgstr "Tham gia kỳ thi"
msgid "Login to participate"
msgstr "Đăng nhập để tham gia"
-#: templates/contest/contest.html:102
+#: templates/contest/contest.html:92
+msgid "Clone"
+msgstr "Nhân bản"
+
+#: templates/contest/contest.html:107
msgid "AC Rate"
msgstr "Tỷ lệ AC"
-#: templates/contest/contest.html:103 templates/contest/list.html:269
-#: templates/contest/list.html:310 templates/contest/list.html:392
+#: templates/contest/contest.html:108 templates/contest/list.html:267
+#: templates/contest/list.html:308 templates/contest/list.html:390
#: templates/problem/list.html:24
msgid "Users"
msgstr "Người nộp"
-#: templates/contest/contest.html:128 templates/problem/list.html:58
+#: templates/contest/contest.html:133 templates/problem/list.html:58
#: templates/problem/list.html:133
msgid "Editorial"
msgstr "Hướng dẫn"
+#: templates/contest/contests_summary.html:36
+#: templates/user/base-users-table.html:3
+msgid "Rank"
+msgstr "Rank"
+
+#: templates/contest/contests_summary.html:37
+#: templates/status/language-list.html:34
+#: templates/user/import/table_csv.html:6
+msgid "Name"
+msgstr "Tên"
+
#: templates/contest/list.html:89 templates/contest/media-js.html:152
msgid "Are you sure you want to join?"
msgstr "Bạn có chắc tham gia?"
@@ -4148,83 +4153,83 @@ msgstr ""
"Tham gia kỳ thi lần đầu sẽ kích hoạt thời gian đếm ngược, không thể dừng lại "
"sau đó."
-#: templates/contest/list.html:123
+#: templates/contest/list.html:122
msgid "hidden"
msgstr "ẩn"
-#: templates/contest/list.html:135
+#: templates/contest/list.html:134
msgid "private"
msgstr "riêng tư"
-#: templates/contest/list.html:151
+#: templates/contest/list.html:150
msgid "rated"
msgstr "rated"
-#: templates/contest/list.html:177
+#: templates/contest/list.html:175
#, python-format
msgid "%(time_limit)s window"
msgstr "Cửa sổ thi dài %(time_limit)s"
-#: templates/contest/list.html:179
+#: templates/contest/list.html:177
#, python-format
msgid "%(duration)s long"
msgstr "Kéo dài %(duration)s"
-#: templates/contest/list.html:198
+#: templates/contest/list.html:196
msgid "Spectate"
msgstr "Theo dõi"
-#: templates/contest/list.html:204 templates/organization/home.html:30
+#: templates/contest/list.html:202 templates/organization/home.html:30
msgid "Join"
msgstr "Tham gia"
-#: templates/contest/list.html:214
+#: templates/contest/list.html:212
msgid "Search contests..."
msgstr "Tìm kiếm kỳ thi..."
-#: templates/contest/list.html:224 templates/internal/problem.html:33
+#: templates/contest/list.html:222 templates/internal/problem.html:33
msgid "Search"
msgstr "Tìm kiếm"
-#: templates/contest/list.html:228
+#: templates/contest/list.html:226
msgid "Hide organization contests"
msgstr "Ẩn các kỳ thi riêng tư của nhóm"
-#: templates/contest/list.html:238
+#: templates/contest/list.html:236
msgid "Active Contests"
msgstr "Kỳ thi bạn đang tham gia"
-#: templates/contest/list.html:255
+#: templates/contest/list.html:253
#, python-format
msgid "Window ends in %(countdown)s"
msgstr "Cửa số thi còn %(countdown)s"
-#: templates/contest/list.html:258 templates/contest/list.html:299
+#: templates/contest/list.html:256 templates/contest/list.html:297
#, python-format
msgid "Ends in %(countdown)s"
msgstr "Kết thúc trong %(countdown)s"
-#: templates/contest/list.html:284
+#: templates/contest/list.html:282
msgid "Ongoing Contests"
msgstr "Kỳ thi đang diễn ra"
-#: templates/contest/list.html:322
+#: templates/contest/list.html:320
msgid "There is no ongoing contest at this time."
msgstr "Không có kỳ thi nào đang diễn ra hiện tại."
-#: templates/contest/list.html:329
+#: templates/contest/list.html:327
msgid "Upcoming Contests"
msgstr "Kỳ thi sắp tới"
-#: templates/contest/list.html:359
+#: templates/contest/list.html:357
msgid "There is no scheduled contest at this time."
msgstr "Không có kỳ thi nào được lên lịch hiện tại."
-#: templates/contest/list.html:366
+#: templates/contest/list.html:364
msgid "Past Contests"
msgstr "Kỳ thi trong quá khứ"
-#: templates/contest/list.html:413
+#: templates/contest/list.html:411
msgid "There is no past contest."
msgstr "Không có kỳ thi nào trong quá khứ."
@@ -4395,6 +4400,7 @@ msgid "Upload file"
msgstr "Tải file lên"
#: templates/fine_uploader/script.html:23
+#: templates/markdown_editor/markdown_editor.html:131
msgid "Cancel"
msgstr "Hủy"
@@ -4458,14 +4464,23 @@ msgstr "Gợi ý"
msgid "Source:"
msgstr "Nguồn:"
-#: templates/notification/list.html:7
-msgid "You have no notifications"
-msgstr "Bạn không có thông báo"
+#: templates/markdown_editor/markdown_editor.html:111 templates/pagedown.html:9
+msgid "Update Preview"
+msgstr "Cập nhật xem trước"
-#: templates/notification/list.html:13
-msgid "Activity"
-msgstr "Hoạt động"
+#: templates/markdown_editor/markdown_editor.html:115
+msgid "Insert Image"
+msgstr "Chèn hình ảnh"
+#: templates/markdown_editor/markdown_editor.html:118
+msgid "From the web"
+msgstr "Từ web"
+
+#: templates/markdown_editor/markdown_editor.html:124
+msgid "From your computer"
+msgstr "Từ máy tính của bạn"
+
+#: templates/markdown_editor/markdown_editor.html:130
#: templates/organization/blog/edit.html:36
#: templates/organization/contest/add.html:36
#: templates/organization/contest/edit.html:86
@@ -4473,12 +4488,20 @@ msgstr "Hoạt động"
msgid "Save"
msgstr "Lưu"
+#: templates/notification/list.html:5
+msgid "You have no notifications"
+msgstr "Bạn không có thông báo"
+
+#: templates/notification/list.html:10
+msgid "Activity"
+msgstr "Hoạt động"
+
#: templates/organization/blog/pending.html:8
msgid "Blog"
msgstr ""
#: templates/organization/blog/pending.html:11
-#: templates/problem/search-form.html:57
+#: templates/problem/search-form.html:50
msgid "Author"
msgstr "Tác giả"
@@ -4632,10 +4655,6 @@ msgstr "Từ chối"
msgid "Kick"
msgstr "Đuổi"
-#: templates/pagedown.html:9
-msgid "Update Preview"
-msgstr "Cập nhật xem trước"
-
#: templates/problem/clone.html:37
msgid "Enter a new code for the cloned problem:"
msgstr "Nhập mã bài mới cho bài tập được nhân bản:"
@@ -4749,7 +4768,7 @@ msgid "Thinking point"
msgstr "Độ khó nghĩ"
#: templates/problem/feed/problems.html:83
-#: templates/problem/search-form.html:68
+#: templates/problem/search-form.html:61
msgid "Problem types"
msgstr "Dạng bài"
@@ -4761,23 +4780,23 @@ msgstr "Lưu ý thêm cho admin"
msgid "Feed"
msgstr "Gợi ý"
-#: templates/problem/list-base.html:95
+#: templates/problem/list-base.html:89
msgid "Filter by type..."
msgstr "Lọc theo dạng..."
-#: templates/problem/list-base.html:158 templates/problem/list-base.html:184
+#: templates/problem/list-base.html:152 templates/problem/list-base.html:178
msgid "Add types..."
msgstr "Thêm dạng"
-#: templates/problem/list-base.html:200
+#: templates/problem/list-base.html:194
msgid "Fail to vote!"
msgstr "Hệ thống lỗi!"
-#: templates/problem/list-base.html:203
+#: templates/problem/list-base.html:197
msgid "Successful vote! Thank you!"
msgstr "Đã gửi thành công! Cảm ơn bạn!"
-#: templates/problem/list.html:40 templates/problem/search-form.html:79
+#: templates/problem/list.html:40 templates/problem/search-form.html:72
#: templates/user/user-problems.html:57
msgid "Category"
msgstr "Nhóm bài"
@@ -5041,26 +5060,22 @@ msgstr "Hiển thị dạng bài"
msgid "Show editorial"
msgstr "Hiển thị hướng dẫn"
-#: templates/problem/search-form.html:41
-msgid "Have editorial"
-msgstr "Có hướng dẫn"
-
-#: templates/problem/search-form.html:82 templates/problem/search-form.html:84
+#: templates/problem/search-form.html:75 templates/problem/search-form.html:77
#: templates/submission/list.html:381
#: templates/submission/submission-list-tabs.html:4
msgid "All"
msgstr "Tất cả"
-#: templates/problem/search-form.html:94
+#: templates/problem/search-form.html:87
msgid "Point range"
msgstr "Mốc điểm"
-#: templates/problem/search-form.html:100 templates/submission/list.html:356
+#: templates/problem/search-form.html:93 templates/submission/list.html:356
#: templates/ticket/list.html:248
msgid "Go"
msgstr "Lọc"
-#: templates/problem/search-form.html:101
+#: templates/problem/search-form.html:94
msgid "Random"
msgstr "Ngẫu nhiên"
@@ -5283,6 +5298,10 @@ msgstr "(một lần nữa)"
msgid "(select your closest major city)"
msgstr "(chọn thành phố gần nhất)"
+#: templates/registration/registration_form.html:72
+msgid "or"
+msgstr "hoặc"
+
#: templates/registration/registration_form.html:73
msgid "pick from map"
msgstr "chọn từ bản đồ"
@@ -5369,11 +5388,6 @@ msgstr "Không có máy chấm nào hoạt động."
msgid "ID"
msgstr "ID"
-#: templates/status/language-list.html:34
-#: templates/user/import/table_csv.html:6
-msgid "Name"
-msgstr "Tên"
-
#: templates/status/language-list.html:35
msgid "Runtime Info"
msgstr "Thông tin Runtime"
@@ -5636,7 +5650,7 @@ msgstr "Người được ủy thác"
#: templates/ticket/new_problem.html:7
msgid "Thanks for opening a ticket!"
-msgstr "Cảm ơn đã báo cáo!"
+msgstr "Cảm ơn bạn đã báo cáo!"
#: templates/ticket/new_problem.html:9
msgid ""
@@ -5683,10 +5697,6 @@ msgstr "Top Rating"
msgid "Top Score"
msgstr "Top Score"
-#: templates/user/base-users-table.html:3
-msgid "Rank"
-msgstr "Rank"
-
#: templates/user/edit-profile.html:111
msgid "Change your password"
msgstr "Đổi mật khẩu"
@@ -5800,72 +5810,72 @@ msgstr "Rank theo điểm"
msgid "Admin Notes"
msgstr "Lưu ý của admin"
-#: templates/user/user-about.html:79
+#: templates/user/user-about.html:77
msgid "You have not shared any information."
msgstr "Bạn chưa chia sẻ thông tin nào."
-#: templates/user/user-about.html:81
+#: templates/user/user-about.html:79
msgid "This user has not shared any information."
msgstr "Người dùng này chưa chia sẻ thông tin nào."
-#: templates/user/user-about.html:90
+#: templates/user/user-about.html:88
msgid "Awards"
msgstr "Thành tích"
-#: templates/user/user-about.html:101
+#: templates/user/user-about.html:99
#, python-format
msgid "%(label)s (%(date)s)"
msgstr "%(label)s (%(date)s)"
-#: templates/user/user-about.html:119
+#: templates/user/user-about.html:117
msgid "Mon"
msgstr "Thứ 2"
-#: templates/user/user-about.html:124
+#: templates/user/user-about.html:122
msgid "Tues"
msgstr "Thứ 3"
-#: templates/user/user-about.html:129
+#: templates/user/user-about.html:127
msgid "Wed"
msgstr "Thứ 4"
-#: templates/user/user-about.html:134
+#: templates/user/user-about.html:132
msgid "Thurs"
msgstr "Thứ 5"
-#: templates/user/user-about.html:139
+#: templates/user/user-about.html:137
msgid "Fri"
msgstr "Thứ 6"
-#: templates/user/user-about.html:144
+#: templates/user/user-about.html:142
msgid "Sat"
msgstr "Thứ 7"
-#: templates/user/user-about.html:149
+#: templates/user/user-about.html:147
msgid "Sun"
msgstr "CN"
-#: templates/user/user-about.html:158
+#: templates/user/user-about.html:156
msgid "Less"
msgstr "Ít"
-#: templates/user/user-about.html:164
+#: templates/user/user-about.html:162
msgid "More"
msgstr "Nhiều"
-#: templates/user/user-about.html:173
+#: templates/user/user-about.html:171
msgid "Rating History"
msgstr "Các lần thi"
-#: templates/user/user-about.html:244
+#: templates/user/user-about.html:242
msgid "past year"
msgstr "năm ngoái"
-#: templates/user/user-about.html:261
+#: templates/user/user-about.html:259
msgid "total submission(s)"
msgstr "bài nộp"
-#: templates/user/user-about.html:265
+#: templates/user/user-about.html:263
msgid "submissions in the last year"
msgstr "bài nộp trong năm qua"
@@ -5951,6 +5961,21 @@ msgstr "Thông tin"
msgid "Check all"
msgstr "Chọn tất cả"
+#~ msgid "Following"
+#~ msgstr "Bạn bè"
+
+#~ msgid "Other"
+#~ msgstr "Thành viên khác"
+
+#~ msgid "Online Users"
+#~ msgstr "Trực tuyến"
+
+#~ msgid "Group:"
+#~ msgstr "Nhóm:"
+
+#~ msgid "Have editorial"
+#~ msgstr "Có hướng dẫn"
+
#~ msgid "Contest"
#~ msgstr "Kỳ thi"
@@ -6267,4 +6292,3 @@ msgstr "Chọn tất cả"
#~ msgid "Hard"
#~ msgstr "Khó"
-
diff --git a/locale/vi/LC_MESSAGES/dmoj-user.po b/locale/vi/LC_MESSAGES/dmoj-user.po
index 4ea605c..d99d288 100644
--- a/locale/vi/LC_MESSAGES/dmoj-user.po
+++ b/locale/vi/LC_MESSAGES/dmoj-user.po
@@ -39,12 +39,6 @@ msgstr "Đăng ký tên"
msgid "Report"
msgstr "Báo cáo"
-msgid "Insert Image"
-msgstr "Chèn hình ảnh"
-
-msgid "Save"
-msgstr "Lưu"
-
msgid "2sat"
msgstr ""
@@ -600,3 +594,8 @@ msgstr ""
msgid "z-function"
msgstr ""
+#~ msgid "Insert Image"
+#~ msgstr "Chèn hình ảnh"
+
+#~ msgid "Save"
+#~ msgstr "Lưu"
diff --git a/resources/blog.scss b/resources/blog.scss
index 4c57cfe..265ebb9 100644
--- a/resources/blog.scss
+++ b/resources/blog.scss
@@ -147,8 +147,9 @@
}
}
-.blog-box:hover {
+.blog-box:hover, .blog-box:not(.pre-expand-blog) {
border-color: #8a8a8a;
+ box-shadow: 0 0 2px rgba(0, 0, 0, 0.1);
}
.blog-description {
diff --git a/resources/comments.scss b/resources/comments.scss
index 05ef84f..dd2fe50 100644
--- a/resources/comments.scss
+++ b/resources/comments.scss
@@ -269,10 +269,10 @@ a {
.actionbar-button {
cursor: pointer;
padding: 0.8em;
- border: 0.2px solid lightgray;
border-radius: 5em;
font-weight: bold;
display: inherit;
+ background: lightgray;
}
.actionbar-block {
display: flex;
@@ -287,7 +287,7 @@ a {
border-radius: 5em 0 0 5em;
}
.actionbar-button:hover {
- background: lightgray;
+ background: darkgray;
}
.dislike-button {
padding-left: 0.5em;
diff --git a/resources/content-description.scss b/resources/content-description.scss
index 69ff279..442be32 100644
--- a/resources/content-description.scss
+++ b/resources/content-description.scss
@@ -42,7 +42,6 @@
white-space: pre-wrap;
word-wrap: break-word;
- margin: 1.5em 0 1.5em 0;
padding: 1em;
border: 1px solid $border_gray;
background-color: #f8f8f8;
diff --git a/resources/darkmode.css b/resources/darkmode.css
index f9a4884..a50a400 100644
--- a/resources/darkmode.css
+++ b/resources/darkmode.css
@@ -1956,8 +1956,10 @@ input::placeholder {
background-color: rgb(24, 26, 27);
box-shadow: rgba(0, 0, 0, 0.2) 0px 0px 5px;
}
-.blog-box:hover {
+.blog-box:hover,
+.blog-box:not(.pre-expand-blog) {
border-color: rgb(81, 88, 91);
+ box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 2px;
}
.problem-feed-name a {
color: rgb(102, 177, 250);
@@ -2091,6 +2093,9 @@ ul.problem-list {
#comment-announcement:hover {
background-color: rgb(96, 104, 108);
}
+.new-problem-info {
+ background-color: rgb(54, 39, 0);
+}
.admin a,
.admin {
color: rgb(232, 230, 227) !important;
@@ -2780,11 +2785,12 @@ a.voted {
border-left-color: rgb(48, 52, 54);
}
.actionbar .actionbar-button {
- border-color: rgb(60, 65, 68);
+ background-image: initial;
+ background-color: rgb(49, 53, 55);
}
.actionbar .actionbar-button:hover {
background-image: initial;
- background-color: rgb(49, 53, 55);
+ background-color: rgb(73, 79, 82);
}
.actionbar .dislike-button {
border-left-color: initial;
diff --git a/resources/dmmd-preview.scss b/resources/dmmd-preview.scss
index a3236b7..98cdbaa 100644
--- a/resources/dmmd-preview.scss
+++ b/resources/dmmd-preview.scss
@@ -25,17 +25,17 @@ div.dmmd-preview-has-content div.dmmd-preview-content {
}
div.dmmd-no-button div.dmmd-preview-update {
- display: none;
+ display: none;
}
div.dmmd-no-button div.dmmd-preview-content {
- padding-bottom: 0;
+ padding-bottom: 0;
}
div.dmmd-no-button:not(.dmmd-preview-has-content) {
- display: none;
+ display: none;
}
div.dmmd-preview-stale {
- background: repeating-linear-gradient(-45deg, #fff, #fff 10px, #f8f8f8 10px, #f8f8f8 20px);
+ background: repeating-linear-gradient(-45deg, #fff, #fff 10px, #f8f8f8 10px, #f8f8f8 20px);
}
diff --git a/resources/fine-uploader/templates/default.html b/resources/fine-uploader/templates/default.html
index e3285ad..11c1502 100644
--- a/resources/fine-uploader/templates/default.html
+++ b/resources/fine-uploader/templates/default.html
@@ -4,59 +4,59 @@
if you are not yet familiar with Fine Uploader UI.
-->
diff --git a/resources/fine-uploader/templates/gallery.html b/resources/fine-uploader/templates/gallery.html
index 3c7d69e..44827a6 100644
--- a/resources/fine-uploader/templates/gallery.html
+++ b/resources/fine-uploader/templates/gallery.html
@@ -5,78 +5,78 @@
on how to customize this template.
-->
diff --git a/resources/fine-uploader/templates/simple-thumbnails.html b/resources/fine-uploader/templates/simple-thumbnails.html
index 668c0c0..767d2d1 100644
--- a/resources/fine-uploader/templates/simple-thumbnails.html
+++ b/resources/fine-uploader/templates/simple-thumbnails.html
@@ -5,60 +5,60 @@
on how to customize this template.
-->
diff --git a/templates/loading-page.html b/resources/html/loading-page.html
similarity index 100%
rename from templates/loading-page.html
rename to resources/html/loading-page.html
diff --git a/resources/math.scss b/resources/math.scss
index f3dae2d..dac4680 100644
--- a/resources/math.scss
+++ b/resources/math.scss
@@ -1,49 +1,49 @@
.mwe-math-mathml-inline {
- display: inline !important;
+ display: inline !important;
}
.mwe-math-mathml-display {
- display: block !important;
- margin-left: auto;
- margin-right: auto;
+ display: block !important;
+ margin-left: auto;
+ margin-right: auto;
}
.mwe-math-mathml-a11y {
- clip: rect(1px, 1px, 1px, 1px);
- overflow: hidden;
- position: absolute;
- width: 1px;
- height: 1px;
- opacity: 0;
+ clip: rect(1px, 1px, 1px, 1px);
+ overflow: hidden;
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ opacity: 0;
}
.mwe-math-fallback-image-inline {
- display: inline-block;
- vertical-align: middle;
+ display: inline-block;
+ vertical-align: middle;
}
.mwe-math-fallback-image-display {
- display: block;
- margin-left: auto !important;
- margin-right: auto !important;
+ display: block;
+ margin-left: auto !important;
+ margin-right: auto !important;
}
@font-face {
- font-family: 'Latin Modern Math';
- src: url('libs/latinmodernmath/latinmodern-math.eot'); /* IE9 Compat Modes */
- src: local('Latin Modern Math'), local('LatinModernMath-Regular'),
+ font-family: 'Latin Modern Math';
+ src: url('libs/latinmodernmath/latinmodern-math.eot'); /* IE9 Compat Modes */
+ src: local('Latin Modern Math'), local('LatinModernMath-Regular'),
url('libs/latinmodernmath/latinmodern-math.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('libs/latinmodernmath/latinmodern-math.woff2') format('woff2'), /* Modern Browsers */
url('libs/latinmodernmath/latinmodern-math.woff') format('woff'), /* Modern Browsers */
url('libs/latinmodernmath/latinmodern-math.ttf') format('truetype'); /* Safari, Android, iOS */
- font-weight: normal;
- font-style: normal;
+ font-weight: normal;
+ font-style: normal;
}
math {
- font-family: "Latin Modern Math";
+ font-family: "Latin Modern Math";
}
img.inline-math {
- display: inline;
+ display: inline;
}
\ No newline at end of file
diff --git a/resources/problem.scss b/resources/problem.scss
index ddb3690..ff2b8d1 100644
--- a/resources/problem.scss
+++ b/resources/problem.scss
@@ -416,3 +416,19 @@ ul.problem-list {
}
}
}
+
+.new-problem-info {
+ background-color: #fff6dd;
+ border-radius: 25px;
+ font-size: 14px;
+ height: 25px;
+ width: 100%;
+ display: table;
+ padding: 5px;
+ margin-top: 12px;
+}
+
+.info-block {
+ display:table-cell;
+ vertical-align:middle;
+}
\ No newline at end of file
diff --git a/resources/users.scss b/resources/users.scss
index 152ffab..841e7bd 100644
--- a/resources/users.scss
+++ b/resources/users.scss
@@ -50,7 +50,7 @@ th.header.rank {
th a:hover {
color: #0F0;
}
-
+
.about-column {
width: 30%;
}
@@ -362,7 +362,7 @@ a.edit-profile {
}
.follow {
- background: green;
+ background: green;
border-color: lightgreen;
}
.follow:hover {
diff --git a/templates/actionbar/media-js.html b/templates/actionbar/media-js.html
index e4f281e..f1dec97 100644
--- a/templates/actionbar/media-js.html
+++ b/templates/actionbar/media-js.html
@@ -113,7 +113,7 @@
navigator.clipboard
.writeText(link)
.then(() => {
- showTooltip(element, "Copied link", 'n');
+ showTooltip(element, "{{_('Copied link')}}", 'n');
});
};
diff --git a/templates/base.html b/templates/base.html
index e595387..c82368d 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -75,112 +75,6 @@
{% endcompress %}
{% endif %}
- {% if not INLINE_JQUERY %}
-
- {% endif %}
-
- {% compress js %}
-
- {% if INLINE_JQUERY %}
-
- {% endif %}
-
-
-
-
-
-
- {% include "extra_js.html" %}
-
-
-
- {% endcompress %}
-
- {% block js_media %}{% endblock %}
- {% if request.in_contest %}
-
- {% endif %}
-
- {% if request.user.is_authenticated %}
-
- {% else %}
-
- {% endif %}
-
- {% if misc_config.analytics %}
- {{ misc_config.analytics|safe }}
- {% endif %}
-
- {# Don't run userscript since it may be malicious #}
- {% if request.user.is_authenticated and request.profile.user_script and not request.user.is_impersonate %}
-
- {% endif %}