diff --git a/dmoj/urls.py b/dmoj/urls.py index fcd24b6..1573c4b 100644 --- a/dmoj/urls.py +++ b/dmoj/urls.py @@ -119,7 +119,6 @@ urlpatterns = [ url(r'^/pdf$', problem.ProblemPdfView.as_view(), name='problem_pdf'), url(r'^/pdf/(?P[a-z-]+)$', problem.ProblemPdfView.as_view(), name='problem_pdf'), url(r'^/clone', problem.ProblemClone.as_view(), name='problem_clone'), - url(r'^/downloadAC$', problem.download_submissions, name='download_submissions'), url(r'^/submit$', problem.problem_submit, name='problem_submit'), url(r'^/resubmit/(?P\d+)$', problem.problem_submit, name='problem_submit'), @@ -139,8 +138,8 @@ urlpatterns = [ url(r'^/manage/submission', include([ url('^$', problem_manage.ManageProblemSubmissionView.as_view(), name='problem_manage_submissions'), - url('^/rejudge$', problem_manage.RejudgeSubmissionsView.as_view(), name='problem_submissions_rejudge'), - url('^/rejudge/preview$', problem_manage.PreviewRejudgeSubmissionsView.as_view(), + url('^/action$', problem_manage.ActionSubmissionsView.as_view(), name='problem_submissions_action'), + url('^/action/preview$', problem_manage.PreviewActionSubmissionsView.as_view(), name='problem_submissions_rejudge_preview'), url('^/rejudge/success/(?P[A-Za-z0-9-]*)$', problem_manage.rejudge_success, name='problem_submissions_rejudge_success'), diff --git a/judge/views/problem.py b/judge/views/problem.py index dcd474c..e5ba33c 100644 --- a/judge/views/problem.py +++ b/judge/views/problem.py @@ -4,7 +4,6 @@ import shutil from datetime import timedelta from operator import itemgetter from random import randrange -import zipfile, tempfile from django.conf import settings from django.contrib.auth.decorators import login_required @@ -677,25 +676,4 @@ class ProblemClone(ProblemMixin, PermissionRequiredMixin, TitleMixin, SingleObje problem.language_limits.set(language_limits) problem.types.set(types) - return HttpResponseRedirect(reverse('admin:judge_problem_change', args=(problem.id,))) - - -def download_submissions(request, problem): - if not request.user.is_superuser: - raise Http404 - - submissions = Submission.objects.filter(problem__code=problem, result='AC') - - with tempfile.SpooledTemporaryFile() as tmp: - with zipfile.ZipFile(tmp, 'w', zipfile.ZIP_DEFLATED) as archive: - for submission in submissions: - file_name = str(submission.id) + '.' + str(submission.language.key) - archive.writestr(file_name, submission.source.source) - - # Reset file pointer - tmp.seek(0) - - # Write file data to response - response = HttpResponse(tmp.read(), content_type='application/x-zip-compressed') - response['Content-Disposition'] = 'attachment; filename="%s"' % (str(problem) + '_submissions.zip') - return response \ No newline at end of file + return HttpResponseRedirect(reverse('admin:judge_problem_change', args=(problem.id,))) \ No newline at end of file diff --git a/judge/views/problem_manage.py b/judge/views/problem_manage.py index 0fe8b1a..07e94ec 100644 --- a/judge/views/problem_manage.py +++ b/judge/views/problem_manage.py @@ -1,5 +1,7 @@ from operator import itemgetter +import zipfile, tempfile + from celery.result import AsyncResult from django.contrib import messages from django.contrib.auth.mixins import PermissionRequiredMixin @@ -63,7 +65,7 @@ class ManageProblemSubmissionView(TitleMixin, ManageProblemSubmissionMixin, Deta return context -class BaseRejudgeSubmissionsView(PermissionRequiredMixin, ManageProblemSubmissionActionMixin, BaseDetailView): +class BaseActionSubmissionsView(PermissionRequiredMixin, ManageProblemSubmissionActionMixin, BaseDetailView): permission_required = 'judge.rejudge_submission_lot' def perform_action(self): @@ -88,16 +90,45 @@ class BaseRejudgeSubmissionsView(PermissionRequiredMixin, ManageProblemSubmissio raise NotImplementedError() -class RejudgeSubmissionsView(BaseRejudgeSubmissionsView): - def generate_response(self, id_range, languages, results): +class ActionSubmissionsView(BaseActionSubmissionsView): + def rejudge_response(self, id_range, languages, results): status = rejudge_problem_filter.delay(self.object.id, id_range, languages, results) return redirect_to_task_status( status, message=_('Rejudging selected submissions for %s...') % (self.object.name,), redirect=reverse('problem_submissions_rejudge_success', args=[self.object.code, status.id]), ) + def download_response(self, id_range, languages, results): + if not self.request.user.is_superuser: + raise Http404 + + queryset = Submission.objects.filter(problem_id=self.object.id) + submissions = apply_submission_filter(queryset, id_range, languages, results) -class PreviewRejudgeSubmissionsView(BaseRejudgeSubmissionsView): + with tempfile.SpooledTemporaryFile() as tmp: + with zipfile.ZipFile(tmp, 'w', zipfile.ZIP_DEFLATED) as archive: + for submission in submissions: + file_name = str(submission.id) + '_' + str(submission.user) + '.' + str(submission.language.key) + archive.writestr(file_name, submission.source.source) + + # Reset file pointer + tmp.seek(0) + + # Write file data to response + response = HttpResponse(tmp.read(), content_type='application/x-zip-compressed') + response['Content-Disposition'] = 'attachment; filename="%s"' % (str(self.object.code) + '_submissions.zip') + return response + + def generate_response(self, id_range, languages, results): + action = self.request.POST.get('action') + if (action == 'rejudge'): + return self.rejudge_response(id_range, languages, results) + elif (action == 'download'): + return self.download_response(id_range, languages, results) + else: + return Http404() + +class PreviewActionSubmissionsView(BaseActionSubmissionsView): def generate_response(self, id_range, languages, results): queryset = apply_submission_filter(self.object.submission_set.all(), id_range, languages, results) return HttpResponse(str(queryset.count())) diff --git a/templates/problem/manage_submission.html b/templates/problem/manage_submission.html index 9bc0a3c..0670f2e 100644 --- a/templates/problem/manage_submission.html +++ b/templates/problem/manage_submission.html @@ -10,7 +10,7 @@ .pane { display: block; - max-width: 20em; + max-width: 25em; border: 1px #ccc solid; border-radius: 5px; padding: 10px; @@ -70,7 +70,8 @@ var $use_id = $('#by-range-check'); var $id_start = $('#by-range-start'); var $id_end = $('#by-range-end'); - $('#rejudge-selected').click(function (e) { + + var actionClick = function (e) { e.preventDefault(); if ($use_id.prop('checked')) { var start = parseInt($id_start.val()); @@ -84,24 +85,35 @@ } } - var $form = $(this).parents('form'); + var $form = $('#form-action'); + var input = $("") + .attr("type", "hidden") + .attr("name", "action").val(e.data.action); + $form.append(input); + $.post('{{ url('problem_submissions_rejudge_preview', problem.code) }}', $form.serialize(), 'text') .done(function (count) { - if (confirm("{{ _('You are about to rejudge {count} submissions. Are you sure you want to do this?') }}" - .replace('{count}', count))) { + if (confirm("{{ _('You are about to {action} {count} submissions. Are you sure you want to do this?') }}" + .replace('{count}', count) + .replace('{action}', e.data.action))) { $form.submit(); } }) .fail(function () { - if (confirm("{{ _('You are about to rejudge a few submissions. Are you sure you want to do this?') }}")) { + if (confirm("{{ _('You are about to {action} a few submissions. Are you sure you want to do this?') }}".replace('{action}', e.data.action))) { $form.submit(); } }); - }); + }; + + $('#rejudge-selected').on('click', {action: 'rejudge'}, actionClick); + $('#download-selected').on('click', {action: 'download'}, actionClick); + $use_id.change(function () { $('#by-range-filter').find('input').prop('disabled', !this.checked); }); + }); {% endblock %} @@ -112,8 +124,8 @@
{% if request.user.has_perm('judge.rejudge_submission_lot') %}
-

{{ _('Rejudge Submissions') }}

-
+

{{ _('Filter submissions') }}

+ {% csrf_token %}
- - {{ _('Rejudge selected submissions') }} + +
+ {% endif %} - -
-

{{ _('Rescore Everything') }}

-

{{ _('This will rescore %(count)d submissions.', count=submission_count) }}

-
- {% csrf_token %} - - {{ _('Rescore all submissions') }} - -
-
{% endblock %} diff --git a/templates/problem/problem.html b/templates/problem/problem.html index 5e6b3ce..65bd6a3 100644 --- a/templates/problem/problem.html +++ b/templates/problem/problem.html @@ -126,12 +126,6 @@ {% endif %}
{{ _('All submissions') }}
{{ _('Best submissions') }}
- {% if request.user.is_superuser %} -
- {{ _('Download AC submissions') }} -
- {% endif %} - {% if editorial and editorial.is_public and not (request.user.is_authenticated and request.profile.current_contest) %}