Skip to content

Commit

Permalink
maor
Browse files Browse the repository at this point in the history
  • Loading branch information
JasonLovesDoggo committed Jan 6, 2024
1 parent 91be43c commit f2e3c13
Show file tree
Hide file tree
Showing 11 changed files with 305 additions and 90 deletions.
32 changes: 25 additions & 7 deletions judge/models/submission.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,7 @@ class Submission(models.Model):
is_pretested = models.BooleanField(verbose_name=_('was ran on pretests only'), default=False)
contest_object = models.ForeignKey('Contest', verbose_name=_('contest'), null=True, blank=True,
on_delete=models.SET_NULL, related_name='+', db_index=False)
locked_after = models.DateTimeField(verbose_name=_('submission lock'), null=True, blank=True)

is_locked = models.BooleanField(verbose_name=_('lock submission'), default=False)
@classmethod
def result_class_from_code(cls, result, case_points, case_total):
if result == 'AC':
Expand Down Expand Up @@ -116,12 +115,10 @@ def short_status(self):
def long_status(self):
return Submission.USER_DISPLAY_CODES.get(self.short_status, '')

@cached_property
def is_locked(self):
return self.locked_after is not None and self.locked_after < timezone.now()


def judge(self, *args, rejudge=False, force_judge=False, rejudge_user=None, **kwargs):
if force_judge or not self.is_locked:
if not self.is_locked:
if rejudge:
with revisions.create_revision(manage_manually=True):
if rejudge_user:
Expand Down Expand Up @@ -176,12 +173,33 @@ def update_contest(self):
return

contest_problem = contest.problem
participation = contest.participation

if participation.contest.is_locked and participation.live:
contest.updated_frozen = True
contest.save()
return

contest.updated_frozen = False
contest.points = round(self.case_points / self.case_total * contest_problem.points
if self.case_total > 0 else 0, 3)
if not contest_problem.partial and contest.points != contest_problem.points:
contest.points = 0
contest.bonus = 0
if contest.points != 0 and not participation.spectate:
config = participation.contest.format.config
if config:
time_bonus = config.get('time_bonus') or 0
first_submission_bonus = config.get('first_submission_bonus') or 0
if time_bonus:
dt = (participation.end_time - self.date).total_seconds()
contest.bonus = (contest.points / contest_problem.points) * (dt // (60 * time_bonus))
if first_submission_bonus and contest.points == contest_problem.points and \
not participation.submissions.filter(problem=contest_problem,
submission__date__lt=self.date).exists():
contest.bonus += first_submission_bonus
contest.save()
contest.participation.recompute_results()
participation.recompute_results()

update_contest.alters_data = True

Expand Down
80 changes: 79 additions & 1 deletion judge/models/tests/test_contest.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,13 @@ def setUpTestData(self):
is_visible=False,
testers=('non_staff_tester',),
)
self.external_contest = create_contest(
key='external',
start_time=_now - timezone.timedelta(days=1),
end_time=_now + timezone.timedelta(days=100),
authors=('superuser', 'staff_contest_edit_own'),
is_external=True,
)

def setUp(self):
self.users['normal'].profile.refresh_from_db()
Expand Down Expand Up @@ -362,6 +369,13 @@ def test_basic_contest_methods(self):
'is_editable_by': self.assertFalse,
'is_in_contest': self.assertFalse,
},
'external': {
'can_see_own_scoreboard': self.assertTrue,
'can_see_full_scoreboard': self.assertTrue,
'is_accessible_by': self.assertFalse,
'is_editable_by': self.assertFalse,
'is_in_contest': self.assertFalse,
},
'non_staff_tester': {
'can_see_own_scoreboard': self.assertTrue,
'can_see_full_scoreboard': self.assertTrue,
Expand Down Expand Up @@ -423,7 +437,7 @@ def test_hidden_scoreboard_contest_methods(self):
'anonymous': {
'can_see_own_scoreboard': self.assertFalse,
'can_see_full_scoreboard': self.assertFalse,
'is_accessible_by': self.assertTrue,
'is_accessible_by': self.assertFalse,
'is_editable_by': self.assertFalse,
'is_in_contest': self.assertFalse,
},
Expand Down Expand Up @@ -833,6 +847,63 @@ def test_private_user_contest_methods(self):
},
}
self._test_object_methods_with_users(self.private_user_contest, data)

def test_external_contest_methods(self):
with self.assertRaises(Contest.Inaccessible):
self.basic_contest.access_check(self.users['normal'])

data = {
'superuser': {
'can_see_own_scoreboard': self.assertTrue,
'can_see_full_scoreboard': self.assertTrue,
'is_accessible_by': self.assertTrue,
'is_editable_by': self.assertTrue,
'is_in_contest': self.assertFalse,
},
'staff_contest_edit_own': {
'can_see_own_scoreboard': self.assertTrue,
'can_see_full_scoreboard': self.assertTrue,
'is_accessible_by': self.assertTrue,
'is_editable_by': self.assertTrue,
'is_in_contest': self.assertFalse,
},
'staff_contest_see_all': {
'can_see_own_scoreboard': self.assertTrue,
'can_see_full_scoreboard': self.assertTrue,
'is_accessible_by': self.assertTrue,
'is_editable_by': self.assertFalse,
'is_in_contest': self.assertFalse,
},
'staff_contest_edit_all': {
'can_see_own_scoreboard': self.assertTrue,
'can_see_full_scoreboard': self.assertTrue,
'is_accessible_by': self.assertTrue,
'is_editable_by': self.assertTrue,
'is_in_contest': self.assertFalse,
},
'normal': {
'can_see_own_scoreboard': self.assertTrue,
'can_see_full_scoreboard': self.assertTrue,
'is_accessible_by': self.assertFalse,
'is_editable_by': self.assertFalse,
'is_in_contest': self.assertFalse,
},
'external': {
'can_see_own_scoreboard': self.assertTrue,
'can_see_full_scoreboard': self.assertTrue,
'is_accessible_by': self.assertFalse,
'is_editable_by': self.assertFalse,
'is_in_contest': self.assertFalse,
},
'anonymous': {
'can_see_own_scoreboard': self.assertTrue,
'can_see_full_scoreboard': self.assertTrue,
'is_accessible_by': self.assertFalse,
'is_editable_by': self.assertFalse,
'is_in_contest': self.assertFalse,
},
}
self._test_object_methods_with_users(self.external_contest, data)

def test_non_visible_contest_contest_methods(self):
data = {
Expand All @@ -858,6 +929,13 @@ def test_non_visible_contest_contest_methods(self):
'is_editable_by': self.assertFalse,
'is_in_contest': self.assertFalse,
},
'external': {
'can_see_own_scoreboard': self.assertTrue,
'can_see_full_scoreboard': self.assertTrue,
'is_accessible_by': self.assertFalse,
'is_editable_by': self.assertFalse,
'is_in_contest': self.assertFalse,
},
'anonymous': {
'can_see_own_scoreboard': self.assertTrue,
'can_see_full_scoreboard': self.assertTrue,
Expand Down
27 changes: 0 additions & 27 deletions judge/models/tests/test_submission.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ def setUpTestData(self):
case_points=99,
case_total=100,
memory=20,
locked_after=None,
)

self.full_ac_submission = Submission.objects.create(
Expand All @@ -45,27 +44,6 @@ def setUpTestData(self):
source='',
)

self.locked_submission = Submission.objects.create(
user=self.users['normal'].profile,
problem=create_problem(code='locked'),
language=Language.get_python3(),
result='WA',
status='D',
case_points=1,
case_total=1,
locked_after=timezone.now() - timezone.timedelta(days=100),
)

self.future_locked_submission = Submission.objects.create(
user=self.users['normal'].profile,
problem=create_problem(code='future_locked'),
language=Language.get_python3(),
result='WA',
status='D',
case_points=1,
case_total=1,
locked_after=timezone.now() + timezone.timedelta(days=100),
)

self.ie_submission = Submission.objects.create(
user=self.users['superuser'].profile,
Expand Down Expand Up @@ -105,7 +83,6 @@ def test_basic_submission(self):
self.assertIsNone(self.basic_submission.contest_key)
self.assertIsNone(self.basic_submission.contest_or_none)
self.assertEqual(len(self.basic_submission.id_secret), 24)
self.assertFalse(self.basic_submission.is_locked)

def test_full_ac_submission(self):
self.assertEqual(self.full_ac_submission.result_class, 'AC')
Expand All @@ -116,10 +93,6 @@ def test_full_ac_submission(self):
'Source of Submission %d of full_ac by normal' % self.full_ac_submission.id,
)

def test_submission_lock(self):
self.assertTrue(self.locked_submission.is_locked)
self.assertFalse(self.future_locked_submission.is_locked)

def test_ie_submission(self):
self.assertEqual(self.ie_submission.result_class, 'IE')
self.assertEqual(self.ie_submission.memory_bytes, 0)
Expand Down
6 changes: 6 additions & 0 deletions judge/models/tests/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,14 @@ def setUpTestData(self):
'normal': create_user(
username='normal',
),
'external': create_user(
username='external',
),
'anonymous': AnonymousUser(),
}
external_user = Profile.objects.get(user__username='external')
external_user.is_external_user = True
external_user.save()

self.organizations = {
'open': create_organization(
Expand Down
10 changes: 9 additions & 1 deletion judge/models/ticket.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django.utils.translation import gettext_lazy as _

from judge.models.profile import Profile
from judge.utils.tickets import filter_visible_tickets


class Ticket(models.Model):
Expand All @@ -20,7 +21,14 @@ class Ticket(models.Model):
object_id = models.PositiveIntegerField(verbose_name=_('linked item ID'))
linked_item = GenericForeignKey()
is_open = models.BooleanField(verbose_name=_('is ticket open?'), default=True)


@classmethod
def tickets_list(cls, user):
queryset = cls.objects.filter(is_open=True).order_by('-id') \
.prefetch_related('linked_item').select_related('user__user')

return filter_visible_tickets(queryset, user)

class Meta:
verbose_name = _('ticket')
verbose_name_plural = _('tickets')
Expand Down
5 changes: 2 additions & 3 deletions judge/sitemap.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from django.contrib.auth.models import User
from django.contrib.auth.models import User, AnonymousUser
from django.contrib.sitemaps import Sitemap
from django.urls import reverse
from django.utils import timezone
Expand Down Expand Up @@ -33,8 +33,7 @@ class ContestSitemap(Sitemap):
priority = 0.7

def items(self):
return Contest.objects.filter(is_visible=True, is_private=False,
is_organization_private=False).values_list('key')
return Contest.get_visible_contests(AnonymousUser()).values_list('key')

def location(self, obj):
return reverse('contest_view', args=obj)
Expand Down
3 changes: 1 addition & 2 deletions judge/tasks/submission.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ def apply_submission_filter(queryset, id_range, languages, results):
queryset = queryset.filter(language_id__in=languages)
if results:
queryset = queryset.filter(result__in=results)
queryset = queryset.exclude(locked_after__lt=timezone.now()) \
.exclude(status__in=Submission.IN_PROGRESS_GRADING_STATUS)
queryset = queryset.filter(is_locked=False).exclude(status__in=Submission.IN_PROGRESS_GRADING_STATUS)
return queryset


Expand Down
32 changes: 17 additions & 15 deletions judge/views/blog.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.conf import settings
from django.db.models import Count, Max
from django.db.models import Count, Max, Q
from django.http import Http404
from django.urls import reverse
from django.utils import timezone
Expand Down Expand Up @@ -29,8 +29,15 @@ def get_paginator(self, queryset, per_page, orphans=0,
orphans=orphans, allow_empty_first_page=allow_empty_first_page, **kwargs)

def get_queryset(self):
return (BlogPost.objects.filter(visible=True, publish_on__lte=timezone.now()).order_by('-sticky', '-publish_on')
.prefetch_related('authors__user'))
queryset = BlogPost.objects.filter(visible=True, publish_on__lte=timezone.now()) \
.order_by('-sticky', '-publish_on') \
.prefetch_related('authors__user', 'organizations')
if not self.request.user.has_perm('judge.edit_all_post'):
filter = Q(is_organization_private=False)
if self.request.user.is_authenticated:
filter |= Q(organizations__in=self.request.profile.organizations.all())
queryset = queryset.filter(filter)
return queryset

def get_context_data(self, **kwargs):
context = super(PostList, self).get_context_data(**kwargs)
Expand Down Expand Up @@ -63,26 +70,21 @@ def get_context_data(self, **kwargs):
}

now = timezone.now()

visible_contests = Contest.get_visible_contests(self.request.user).filter(is_visible=True) \
.order_by('start_time')


visible_contests = Contest.get_visible_contests(self.request.user).order_by('start_time')

context['current_contests'] = visible_contests.filter(start_time__lte=now, end_time__gt=now)
context['future_contests'] = visible_contests.filter(start_time__gt=now)

if self.request.user.is_authenticated:
context['own_open_tickets'] = (
Ticket.objects.filter(user=self.request.profile, is_open=True).order_by('-id')
.prefetch_related('linked_item').select_related('user__user')
)
context['own_open_tickets'] = Ticket.tickets_list(self.request.user).filter(user=self.request.profile)
else:
context['own_open_tickets'] = []

# Superusers better be staffs, not the spell-casting kind either.
if self.request.user.is_staff:
tickets = (Ticket.objects.order_by('-id').filter(is_open=True).prefetch_related('linked_item')
.select_related('user__user'))
context['open_tickets'] = filter_visible_tickets(tickets, self.request.user)[:10]
context['open_tickets'] = Ticket.tickets_list(self.request.user)[:10]

else:
context['open_tickets'] = []
return context
Expand All @@ -92,7 +94,7 @@ class PostView(TitleMixin, CommentedDetailView):
model = BlogPost
pk_url_kwarg = 'id'
context_object_name = 'post'
template_name = 'blog/content.html'
template_name = 'blog/blog.html'

def get_title(self):
return self.object.title
Expand Down
Loading

0 comments on commit f2e3c13

Please sign in to comment.