Skip to content

Commit

Permalink
Add page to view all user submissions in given contest
Browse files Browse the repository at this point in the history
  • Loading branch information
kiritofeng authored and Xyene committed Aug 10, 2020
1 parent 396df0e commit 758b689
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 18 deletions.
2 changes: 2 additions & 0 deletions dmoj/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ def paged_list_view(view, name):
url(r'^/rank/(?P<problem>\w+)/',
paged_list_view(ranked_submission.ContestRankedSubmission, 'contest_ranked_submissions')),

url(r'^/submissions/(?P<user>\w+)/',
paged_list_view(submission.UserAllContestSubmissions, 'contest_all_user_submissions')),
url(r'^/submissions/(?P<user>\w+)/(?P<problem>\w+)/',
paged_list_view(submission.UserContestSubmissions, 'contest_user_submissions')),

Expand Down
4 changes: 3 additions & 1 deletion judge/contest_format/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ def display_user_problem(self, participation, contest_problem):

def display_participation_result(self, participation):
return format_html(
u'<td class="user-points">{points}<div class="solving-time">{cumtime}</div></td>',
u'<td class="user-points"><a href="{url}">{points}<div class="solving-time">{cumtime}</div></a></td>',
url=reverse('contest_all_user_submissions',
args=[self.contest.key, participation.user.user.username]),
points=floatformat(participation.score),
cumtime=nice_repr(timedelta(seconds=participation.cumtime), 'noday'),
)
Expand Down
4 changes: 3 additions & 1 deletion judge/contest_format/ecoo.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ def display_user_problem(self, participation, contest_problem):

def display_participation_result(self, participation):
return format_html(
'<td class="user-points">{points}<div class="solving-time">{cumtime}</div></td>',
'<td class="user-points"><a href="{url}">{points}<div class="solving-time">{cumtime}</div></a></td>',
url=reverse('contest_all_user_submissions',
args=[self.contest.key, participation.user.user.username]),
points=floatformat(participation.score),
cumtime=nice_repr(timedelta(seconds=participation.cumtime), 'noday') if self.config['cumtime'] else '',
)
4 changes: 3 additions & 1 deletion judge/contest_format/legacy_ioi.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ def display_user_problem(self, participation, contest_problem):

def display_participation_result(self, participation):
return format_html(
'<td class="user-points">{points}<div class="solving-time">{cumtime}</div></td>',
'<td class="user-points"><a href="{url}">{points}<div class="solving-time">{cumtime}</div></a></td>',
url=reverse('contest_all_user_submissions',
args=[self.contest.key, participation.user.user.username]),
points=floatformat(participation.score),
cumtime=nice_repr(timedelta(seconds=participation.cumtime), 'noday') if self.config['cumtime'] else '',
)
62 changes: 48 additions & 14 deletions judge/views/submission.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,16 @@ def abort_submission(request, submission):
return HttpResponseRedirect(reverse('submission_status', args=(submission.id,)))


def filter_submissions_by_visible_problems(queryset, user):
join_sql_subquery(
queryset,
subquery=str(Problem.get_visible_problems(user).distinct().only('id').query),
params=[],
join_fields=[('problem_id', 'id')],
alias='visible_problems',
)


class SubmissionsListBase(DiggPaginatorMixin, TitleMixin, ListView):
model = Submission
paginate_by = 50
Expand Down Expand Up @@ -248,13 +258,7 @@ def _get_queryset(self):
def get_queryset(self):
queryset = self._get_queryset()
if not self.in_contest:
join_sql_subquery(
queryset,
subquery=str(Problem.get_visible_problems(self.request.user).distinct().only('id').query),
params=[],
join_fields=[('problem_id', 'id')],
alias='visible_problems',
)
filter_submissions_by_visible_problems(queryset, self.request.user)

return queryset

Expand Down Expand Up @@ -319,9 +323,13 @@ def get(self, request, *args, **kwargs):


class ConditionalUserTabMixin(object):
@cached_property
def is_own(self):
return self.request.user.is_authenticated and self.request.profile == self.profile

def get_context_data(self, **kwargs):
context = super(ConditionalUserTabMixin, self).get_context_data(**kwargs)
if self.request.user.is_authenticated and self.request.profile == self.profile:
if self.is_own:
context['tab'] = 'my_submissions_tab'
else:
context['tab'] = 'user_submissions_tab'
Expand All @@ -334,12 +342,12 @@ def get_queryset(self):
return super(AllUserSubmissions, self).get_queryset().filter(user_id=self.profile.id)

def get_title(self):
if self.request.user.is_authenticated and self.request.profile == self.profile:
if self.is_own:
return _('All my submissions')
return _('All submissions by %s') % self.username

def get_content_title(self):
if self.request.user.is_authenticated and self.request.profile == self.profile:
if self.is_own:
return format_html('All my submissions')
return format_html('All submissions by <a href="{1}">{0}</a>', self.username,
reverse('user_page', args=[self.username]))
Expand Down Expand Up @@ -414,10 +422,6 @@ def get_my_submissions_page(self):
class UserProblemSubmissions(ConditionalUserTabMixin, UserMixin, ProblemSubmissions):
check_contest_in_access_check = False

@cached_property
def is_own(self):
return self.request.user.is_authenticated and self.request.profile == self.profile

def access_check(self, request):
super(UserProblemSubmissions, self).access_check(request)

Expand Down Expand Up @@ -531,6 +535,36 @@ def get(self, request, *args, **kwargs):
return super(ForceContestMixin, self).get(request, *args, **kwargs)


class UserAllContestSubmissions(ForceContestMixin, AllUserSubmissions):
def get_title(self):
if self.is_own:
return _('My submissions in %(contest)s') % {'contest': self.contest.name}
return _("%(user)s's submissions in %(contest)s") % {
'user': self.username,
'contest': self.contest.name,
}

def access_check(self, request):
super().access_check(request)
if not self.contest.users.filter(user_id=self.profile.id).exists():
raise Http404()
if not self.is_own and not self.contest.can_see_full_scoreboard(self.request.user):
raise Http404()

def get_content_title(self):
if self.is_own:
return format_html(_('My submissions in <a href="{1}">{0}</a>'),
self.contest.name, reverse("contest_view", args=[self.contest.key]))
return format_html(_('<a href="{1}">{0}</a>\'s submissions in <a href="{3}">{2}</a>'),
self.username, reverse('user_page', args=[self.username]),
self.contest.name, reverse('contest_view', args=[self.contest.key]))

def get_queryset(self):
queryset = super().get_queryset()
filter_submissions_by_visible_problems(queryset, self.request.user)
return queryset


class UserContestSubmissions(ForceContestMixin, UserProblemSubmissions):
def get_title(self):
if self.problem.is_accessible_by(self.request.user):
Expand Down
2 changes: 1 addition & 1 deletion templates/contest/ranking.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
color: red;
}

.user-points {
.user-points, .user-points a {
font-weight: bold;
color: black;
}
Expand Down

0 comments on commit 758b689

Please sign in to comment.