Cloned DMOJ

This commit is contained in:
thanhluong 2020-01-21 15:35:58 +09:00
parent f623974b58
commit 49dc9ff10c
513 changed files with 132349 additions and 39 deletions

View file

@ -0,0 +1,42 @@
{% extends "base.html" %}
{% block media %}
<style>
#problem-clone-panel {
position: relative;
margin: 5em auto auto -10em;
top: 40%;
left: 50%;
}
#problem-code-container {
margin: 0.5em 0;
}
#id_code {
width: 100%;
}
ul.errorlist {
list-style-type: none;
padding-left: 0;
text-align: center;
}
</style>
{% endblock %}
{% block body %}
<form id="problem-clone-panel" action="" method="post" class="form-area">
{% csrf_token %}
{% if form.errors %}
<div id="form-errors">
{{ form.code.errors }}
</div>
{% endif %}
<div><label class="inline-header grayed">{{ _('Enter a new code for the cloned problem:') }}</label></div>
<div id="problem-code-container"><span class="fullwidth">{{ form.code }}</span></div>
<hr>
<button style="float:right;" type="submit">{{ _('Clone!') }}</button>
</form>
{% endblock %}

451
templates/problem/data.html Normal file
View file

@ -0,0 +1,451 @@
{% extends "base.html" %}
{% block js_media %}
<script type="text/javascript">
window.valid_files = {{valid_files_json}};
$(function () {
});
</script>
<script type="text/javascript" src="{{ static('libs/jquery-sortable.js') }}"></script>
<script type="text/javascript" src="{{ static('libs/featherlight/featherlight.min.js') }}"></script>
<script type="text/javascript">
$(function () {
function update_select2() {
$('tbody:not(.extra-row-body) .type-column select').select2({
minimumResultsForSearch: -1
});
}
update_select2();
function autofill_if_exists($select, file) {
if (!$select.val() && ~window.valid_files.indexOf(file))
$select.val(file).trigger('change');
}
var $table = $('#case-table');
$table.on('add-row', function (e, $tr) {
update_select2();
$tr.find('input').filter('[id$=file]').each(function () {
var $select, val = $(this).replaceWith($select = $('<select>').attr({
id: $(this).attr('id'),
name: $(this).attr('name'),
style: 'width: 100%'
})).val();
$select.select2({
data: window.valid_files,
allowClear: true,
placeholder: ''
}).val(val).trigger('change').on('change', function () {
var val = $select.val();
if (val) {
if ($select.attr('id').endsWith('input_file'))
autofill_if_exists($tr.find('select[id$=output_file]'), val.replace(/in(?!.*?in)/, 'out'));
else
autofill_if_exists($tr.find('select[id$=input_file]'), val.replace(/out(?!.*?out)/, 'in'));
}
});
});
});
var order = 0;
function handle_table_reorder() {
var in_batch = false;
$table.find('tbody:first tr').each(function () {
switch ($(this).attr('data-type')) {
case 'C':
$(this).find('input[id$=points], input[id$=pretest]').toggle(!in_batch);
break;
case 'S':
in_batch = true;
break;
case 'E':
in_batch = false;
}
});
}
function try_parse_json(json) {
try {
return JSON.parse(json);
} catch (e) {
return {};
}
}
function checker_precision($checker) {
var $td = $checker.parent();
var $args = $td.find('input');
var $precision = $('<input>', {
type: 'number',
value: try_parse_json($args.val()).precision || 6,
title: 'precision (decimal digits)',
style: 'width: 4em'
}).change(function () {
if ($checker.val().startsWith('floats'))
$args.val(JSON.stringify({precision: parseInt($(this).val())}));
else
$args.val('');
}).appendTo($td);
$checker.change(function () {
$precision.toggle($checker.val().startsWith('floats')).change();
}).change();
}
function swap_row($a, $b) {
var $a_order = $a.find('input[id$=order]'), $b_order = $b.find('input[id$=order]');
var order = $a_order.val();
$a_order.val($b_order.val());
$b_order.val(order);
$b.after($a);
$a.find('span.order').text($a_order.val());
$b.find('span.order').text($b_order.val());
handle_table_reorder();
}
checker_precision($('#id_problem-data-checker'));
$table.on('add-row', function (e, $tr) {
var $order = $tr.find('input').filter('[id$=order]').attr('type', 'hidden').val(++order);
$order.after($('<span>', {'class': 'order'}).text($order.val()))
.after($('<i>', {'class': 'fa fa-fw fa-lg fa-ellipsis-v'}));
var $opts = $tr.find('input').slice(2, 6);
var $files = $tr.find('select').slice(1, 3);
var $checker = $files.end().last();
$tr.find('select[id$=type]').change(function () {
var $this = $(this), val = $this.val(), disabled;
switch (val) {
case 'S':
case 'E':
disabled = val == 'S';
$opts.toggle(val == 'S');
$files.siblings('.select2').hide();
$checker.toggle(val == 'S');
break;
default:
$opts.toggle(val == 'C');
$files.siblings('.select2').toggle(val == 'C');
$checker.toggle(val == 'C');
var $prevs = $tr.prevAll('tr[data-type=S], tr[data-type=E]');
disabled = $prevs.length && $prevs.get(0).getAttribute('data-type') == 'S';
$tr.find('input[id$=points], input[id$=pretest]').toggle(val == 'C' && !disabled);
}
$tr.attr('data-type', val).nextUntil('tr[data-type=S], tr[data-type=E], tr[data-type=""]')
.find('input[id$=points], input[id$=pretest]').toggle(!disabled);
}).change();
var tooltip_classes = 'tooltipped tooltipped-s';
$tr.find('a.edit-generator-args').mouseover(function () {
switch ($tr.attr('data-type')) {
case 'C':
case 'S':
var $this = $(this).addClass(tooltip_classes);
$this.attr('aria-label', $this.prev().val() || '(none)');
}
}).mouseout(function () {
$(this).removeClass(tooltip_classes).removeAttr('aria-label');
}).featherlight($('.generator-args-editor'), {
beforeOpen: function () {
switch ($tr.attr('data-type')) {
case 'C':
case 'S':
return true;
default:
return false;
}
},
afterOpen: function () {
var $input = this.$currentTarget.prev();
this.$instance.find('.generator-args-editor')
.find('textarea').val($input.val()).end()
.find('.button').click(function () {
$input.val($(this).prev().val());
$.featherlight.current().close();
}).end()
.show();
}
});
checker_precision($tr.find('select[id$=checker]'));
}).find('tbody:first').find('tr').each(function () {
$table.trigger('add-row', [$(this)]);
});
$('form').submit(function () {
$table.find('tbody:first').find('tr').each(function () {
var filled = false;
$(this).find('input, select').each(function () {
var $this = $(this);
if (!$this.attr('name'))
return;
if ($this.attr('type') === 'checkbox')
filled |= $this.is(':checked');
else if (!$this.attr('name').endsWith('order'))
filled |= !!$this.val();
});
if (!filled)
$(this).find('input[id$=order]').val('');
});
});
var $total = $('#id_cases-TOTAL_FORMS');
$('a#add-case-row').click(function () {
var $tr;
$table.find('tbody:first').append($tr = $($table.find('.extra-row-body').html()
.replace(/__prefix__/g, $total.val())));
$tr.find('.type-column select option[value="C"]').attr('selected', true);
$total.val(parseInt($total.val()) + 1);
$table.trigger('add-row', [$tr]);
window.scrollBy(0, $tr.height());
return false;
});
var oldIndex;
$table.sortable({
containerSelector: 'table',
itemPath: '> tbody:first',
itemSelector: 'tr',
handle: 'i.fa-ellipsis-v',
placeholder: '<tr class="placeholder">',
onDragStart: function ($item, container, _super) {
oldIndex = $item.index();
_super($item, container);
},
onDrop: function ($item, container, _super) {
var newIndex = $item.index();
if (newIndex > oldIndex) {
var order = parseInt($item.parent().children().slice(oldIndex, newIndex).each(function () {
var $order = $(this).find('input[id$=order]');
$order.val(parseInt($order.val()) - 1).siblings('span.order').text($order.val());
}).last().after($item).find('input[id$=order]').val());
$item.find('input[id$=order]').val(order + 1).siblings('span.order').text(order + 1);
} else if (newIndex < oldIndex) {
var order = parseInt($item.parent().children().slice(newIndex + 1, oldIndex + 1).each(function () {
var $order = $(this).find('input[id$=order]');
$order.val(parseInt($order.val()) + 1).siblings('span.order').text($order.val());
}).first().before($item).find('input[id$=order]').val());
$item.find('input[id$=order]').val(order - 1).siblings('span.order').text(order - 1);
}
if (newIndex != oldIndex)
handle_table_reorder();
_super($item, container);
}
});
var $controls = $('#column-visible');
var problem = $controls.attr('data-problem');
$controls.find('input').change(function () {
var $this = $(this), suffix = $this.attr('data-suffix'), checked = $this.is(':checked');
$table.find('.' + suffix.replace(/_/g, '-')).toggle(checked);
localStorage.setItem('data-visible:' + problem + ':' + suffix, checked ? '1' : '0')
}).each(function () {
var $this = $(this), suffix = $this.attr('data-suffix'), filled = false;
filled = localStorage.getItem('data-visible:' + problem + ':' + suffix);
if (filled !== null)
filled = filled == '1';
else {
filled = false;
$table.find('[id$=' + suffix + ']').each(function () {
filled |= !!$(this).val();
});
}
$this.prop('checked', filled).trigger('change');
});
});
</script>
{% endblock %}
{% block media %}
<style>
#case-table .select2 {
text-align: initial;
}
.order-column {
width: 1em;
}
.bad-file input, .bad-file .select2-selection {
border-color: red;
}
span.order {
padding-right: 0.5em;
}
body.dragging, body.dragging * {
cursor: move !important;
}
.dragged {
position: absolute;
opacity: 0.5;
z-index: 2000;
}
tr.placeholder {
display: block;
background: red;
position: relative;
margin: 0;
padding: 0;
border: none;
}
tr.placeholder:before {
content: "";
position: absolute;
width: 0;
height: 0;
border: 5px solid transparent;
border-left-color: red;
margin-top: -5px;
left: -5px;
border-right: none;
}
i.fa-ellipsis-v {
cursor: move;
}
.edit-generator-args {
position: relative;
}
.generator-args-editor textarea {
display: block;
width: 100%;
margin-bottom: 0.5em;
height: 8em;
}
.generator-args-editor .button {
display: block;
float: right;
}
#case-table tbody td {
white-space: nowrap;
}
.type-column {
width: 8em;
}
ul.errorlist {
border: 3px red solid;
border-radius: 5px;
padding-top: 1em;
padding-bottom: 1em;
background: #e99;
}
</style>
{% endblock %}
{% block header %}
{% if data_form.instance.has_yml %}
<div class="title-line-action">
[<a href="{{ url('problem_data_init', problem.code) }}">{{ _('View YAML') }}</a>]
</div>
{% endif %}
{% endblock %}
{% block body %}
{% if data_form.instance.feedback %}
<ul class="errorlist">
<li>{{ data_form.instance.feedback }}</li>
</ul>
{% endif %}
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ cases_formset.management_form }}
<table class="table">{{ data_form.as_table() }}</table>
<div id="column-visible" data-problem="{{ problem.code }}">
<strong>{{ _('Show columns:') }}</strong>
<label>
<input type="checkbox" data-suffix="output_prefix">
{{ _('Output prefix') }}
</label>
<label>
<input type="checkbox" data-suffix="output_limit">
{{ _('Output limit') }}
</label>
<label>
<input type="checkbox" data-suffix="checker">
{{ _('Checker') }}
</label>
<label>
<input type="checkbox" data-suffix="generator_args">
{{ _('Generator args') }}
</label>
</div>
<table id="case-table" class="table">
<thead>
<tr>
<th class="order-column"></th>
<th class="type-column">{{ _('Type') }}</th>
<th>{{ _('Input file') }}</th>
<th>{{ _('Output file') }}</th>
<th>{{ _('Points') }}</th>
<th>{{ _('Pretest?') }}</th>
<th class="output-prefix">{{ _('Output prefix') }}</th>
<th class="output-limit">{{ _('Output limit') }}</th>
<th class="checker">{{ _('Checker') }}</th>
<th class="generator-args">{{ _('Generator args') }}</th>
{% if cases_formset.can_delete %}
<th>{{ _('Delete?') }}</th>
{% endif %}
</tr>
</thead>
<tbody>
{% for form in all_case_forms %}
{% if form.non_field_errors() %}
<tr>
<td colspan="{{ 9 + cases_formset.can_delete }}">{{ form.non_field_errors() }}</td>
</tr>
{% endif %}
{% if form.prefix and '__prefix__' in form.prefix %}
</tbody>
<tbody class="extra-row-body" style="display: none">
{% endif %}
<tr data-type="{{ form['type'].value() }}">
<td>{{ form.id }}{{ form.order.errors }}{{ form.order }}</td>
<td class="type-column">{{ form.type.errors }}{{ form.type }}</td>
<td{% if not (form.empty_permitted or form['type'].value() != 'C' or
form['input_file'].value() in valid_files) %} class="bad-file"{% endif %}>
{{ form.input_file.errors }}{{ form.input_file }}
</td>
<td{% if not (form.empty_permitted or form['type'].value() != 'C' or
form['output_file'].value() in valid_files) %} class="bad-file"{% endif %}>
{{ form.output_file.errors }}{{ form.output_file }}
</td>
<td>{{ form.points.errors }}{{ form.points }}</td>
<td>{{ form.is_pretest.errors }}{{ form.is_pretest }}</td>
<td class="output-prefix">{{ form.output_prefix.errors }}{{ form.output_prefix }}</td>
<td class="output-limit">{{ form.output_limit.errors }}{{ form.output_limit }}</td>
<td class="checker">
{{ form.checker.errors }}{{ form.checker }}{{ form.checker_args.errors }}{{ form.checker_args }}
</td>
<td class="generator-args">{{ form.generator_args.errors }}{{ form.generator_args }}
<a href="javascript:void(0)" class="edit-generator-args">
<i class="fa fa-pencil"></i>
{{ _('Edit') }}
</a>
</td>
{% if cases_formset.can_delete %}
<td>{{ form.DELETE }}</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
<input type="submit" value="{{ _('Submit!') }}" class="button">
<a id="add-case-row" href="#"><i class="fa fa-plus"></i> {{ _('Add new case') }}</a>
</form>
<div style="display: none" class="generator-args-editor"><textarea></textarea><a class="button">Save</a></div>
{% endblock %}

View file

@ -0,0 +1,40 @@
{% extends "common-content.html" %}
{% block content_js_media %}
{% include "comments/media-js.html" %}
{% endblock %}
{% block content_media %}
{% include "comments/media-css.html" %}
{% endblock %}
{% block header %}
<div style="float:right">
{% if perms.judge.change_problem %}
[<a href="{{ url('admin:judge_problem_change', problem.id) }}">{{ _('Edit') }}</a>]
{% endif %}
</div>
{% endblock %}
{% block body %}
<div class="content-description">
{% if not has_solved_problem %}
<div class="alert alert-danger">{{ _('Remember to use this editorial <b>only</b> when stuck, and <b>not to copy-paste code from it</b>. Please be respectful to the problem author and editorialist. <br><br> <b>Submitting an official solution before solving the problem yourself is a bannable offence.</b>') }}</div>
{% endif %}
{% with authors=solution.authors.all() %}
{% if authors %}
<p>Authors: {{ link_users(authors) }}</p>
{% endif %}
{% endwith %}
{{ solution.content|markdown('solution', MATH_ENGINE)|reference|str|safe }}
</div>
<hr>
{% include "comments/list.html" %}
{% endblock %}
{% block bodyend %}
{% if REQUIRE_JAX %}
{% include "mathjax-load.html" %}
{% endif %}
{% include "comments/math.html" %}
{% endblock %}

311
templates/problem/list.html Normal file
View file

@ -0,0 +1,311 @@
{% extends "common-content.html" %}
{% block media %}
<link rel="stylesheet" href="{{ static('libs/nouislider.min.css') }}">
<noscript>
<style>#category, #types {
visibility: visible;
}
</style>
</noscript>
{% if not request.in_contest %}
<style>
#problem-table th {
padding: 0;
}
a.hot-problem-link:hover > .hot-problem-count {
visibility: visible;
}
span.hot-problem-count {
color: #555;
font-size: 0.75em;
vertical-align: super;
visibility: hidden;
padding-left: 0.25em;
position: relative;
}
ul.problem-list {
padding: 0 !important;
}
</style>
{% endif %}
{% endblock %}
{% block js_media %}
<script>
window.point_start = {{point_start}};
window.point_end = {{point_end}};
window.point_values = {{point_values|json|safe}};
</script>
{% compress js %}
<script src="{{ static('libs/nouislider.min.js') }}" type="text/javascript"></script>
<script>
$(function () {
var $form = $('form#filter-form');
var $search = $('#search');
var $category = $('#category');
function prep_form() {
$search.prop('disabled', !$search.val());
$category.prop('disabled', !$category.val());
}
function clean_submit() {
prep_form();
$form.submit();
}
$category.select2().css({'visibility': 'visible'}).change(clean_submit);
$('#types').select2({multiple: 1, placeholder: '{{ _('Filter by type...') }}'})
.css({'visibility': 'visible'});
// This is incredibly nasty to do but it's needed because otherwise the select2 steals the focus
$search.keypress(function (e) {
if (e.keyCode == 13)
$('#go').click();
});
$('#random').click(function (e) {
var action = $form.attr('action');
$form.attr('action', '{{ url('problem_random') }}').attr('target', '_blank').submit();
$form.attr('action', action).attr('target', '');
e.preventDefault();
});
$('#go').click(clean_submit);
$('input#full_text, input#hide_solved, input#show_types').click(function () {
prep_form();
($('<form>').attr('action', window.location.pathname + '?' + $form.serialize())
.append($('<input>').attr('type', 'hidden').attr('name', 'csrfmiddlewaretoken')
.attr('value', $.cookie('csrftoken')))
.attr('method', 'POST').appendTo($('body')).submit());
});
var info_float = $('.info-float');
var container = $('#content-right');
if (window.bad_browser) {
container.css('float', 'right');
} else if (!featureTest('position', 'sticky')) {
fix_div(info_float, 55);
$(window).resize(function () {
info_float.width(container.width());
});
info_float.width(container.width());
}
var intFormatter = {
to: function (value) {
return value;
},
from: function (value) {
return +value;
}
};
var $slider = $('#point-slider');
if ($slider.length) {
var $start = $('#point-start');
var $end = $('#point-end');
noUiSlider.create($slider[0], {
start: [point_start, point_end],
connect: true,
snap: true,
tooltips: [intFormatter, intFormatter],
range: point_values
}).on('change', function (values) {
var start = +values[0], end = +values[1];
$start.prop('disabled', start === point_values.min).val(start);
$end.prop('disabled', end === point_values.max).val(end);
});
}
});
</script>
{% endcompress %}
{% if request.in_contest %}
{% compress js %}
<script src="{{ static('libs/tablesorter.js') }}" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
$.tablesorter.addParser({
id: 'solvedsort',
is: function (s) {
return false;
},
format: function (s, table, cell, cellIndex) {
return $(cell).attr('solved');
},
type: 'numeric'
});
$('#problem-table').tablesorter({
headers: {
0: {
sorter: 'solvedsort'
}
},
textExtraction: function (node) {
node = $(node);
var text = node.text().replace(/^\s+|\s+$/g, '');
return (node.hasClass('p') ? text.replace(/p$/, '') : text);
}
});
});
</script>
{% endcompress %}
{% endif %}
{% endblock %}
{% block title_ruler %}{% endblock %}
{% block title_row %}
{% set tab = 'list' %}
{% set title = 'Problems' %}
{% include "problem/problem-list-tabs.html" %}
{% endblock %}
{% block body %}
{% if page_obj.num_pages > 1 %}
<div style="margin-bottom: 7px; margin-top: 11px;">
{% include "list-pages.html" %}
</div>
{% endif %}
<div id="common-content">
{% block before_table %}{% endblock %}
{% if not request.in_contest %}
<div id="content-right" class="problems">
<div class="info-float">
{% include "problem/search-form.html" %}
{% if hot_problems %}
<div class="sidebox">
<h3>{{ _('Hot problems') }} <i class="fa fa-fire"></i></h3>
<div class="sidebox-content">
<ul class="problem-list">{% for problem in hot_problems %}
<li><a href="{{ url('problem_detail', problem.code) }}" class="hot-problem-link">
{{ problem.name }}
</a></li>
{% endfor %}</ul>
</div>
</div>
{% endif %}
</div>
</div>
{% endif %}
<div id="content-left" class="problems">
<table id="problem-table" class="table striped">
<thead>
<tr>
{% if request.in_contest %}
{% if request.user.is_authenticated %}
<th class="solved"><i class="fa fa-check"></i></th>
{% endif %}
<th class="problem">{{ _('Problem') }}</th>
<th class="category">{{ _('Category') }}</th>
{% if show_types %}
<th>{{ _('Types') }}</th>
{% endif %}
<th class="points">{{ _('Points') }}</th>
<th class="users">{{ _('Users') }}</th>
{% else %}
{% if request.user.is_authenticated %}
<th class="solved">
<a href="{{ sort_links.solved }}"><i class="fa fa-check"></i>{{ sort_order.solved }}
</a>
</th>
{% endif %}
<th class="problem">
<a href="{{ sort_links.name }}">{{ _('Problem') }}{{ sort_order.name }}</a>
</th>
<th class="category">
<a href="{{ sort_links.group }}">{{ _('Category') }}{{ sort_order.group }}</a>
</th>
{% if show_types %}
<th>
<a href="{{ sort_links.type }}">{{ _('Types') }}{{ sort_order.type }}</a>
</th>
{% endif %}
<th class="points">
<a href="{{ sort_links.points }}">{{ _('Points') }}{{ sort_order.points }}</a>
</th>
<th class="ac-rate">
<a href="{{ sort_links.ac_rate }}">{{ _('AC %%') }}{{ sort_order.ac_rate }}</a>
</th>
<th class="users">
<a href="{{ sort_links.user_count }}">{{ _('Users') }}{{ sort_order.user_count }}</a>
</th>
{% endif %}
</tr>
</thead>
<tbody>
{% for problem in problems %}
<tr>
{% if request.user.is_authenticated %}
{% if problem.id in completed_problem_ids %}
<td solved="1">
<a href="{{ url('user_submissions', problem.code, request.user.username) }}">
{% if problem.is_public or request.in_contest %}
<i class="solved-problem-color fa fa-check-circle"></i>
{% else %}
<i class="solved-problem-color fa fa-lock"></i>
{% endif %}
</a>
</td>
{% elif problem.id in attempted_problems %}
<td solved="0">
<a href="{{ url('user_submissions', problem.code, request.user.username) }}">
{% if problem.is_public or request.in_contest %}
<i class="attempted-problem-color fa fa-minus-circle"></i>
{% else %}
<i class="attempted-problem-color fa fa-lock"></i>
{% endif %}
</a>
</td>
{% else %}
<td solved="-1">
{% if problem.is_public or request.in_contest %}
<i class="unsolved-problem-color fa fa-minus-circle"></i>
{% else %}
<i class="unsolved-problem-color fa fa-lock"></i>
{% endif %}
</td>
{% endif %}
{% endif %}
<td class="problem">
<a href="{{ url('problem_detail', problem.code) }}">{{ problem.i18n_name }}</a>
</td>
<td class="category">{{ problem.group.full_name }}</td>
{% if show_types %}
<td class="types">
{% for type in problem.types_list %}
<span class="type-tag">{{ type }}</span>{% if not loop.last %}, {% endif %}
{% endfor %}
</td>
{% endif %}
<td class="p">{{ problem.points|floatformat }}{% if problem.partial %}p{% endif %}</td>
{% if not request.in_contest %}
<td class="ac-rate">{{ problem.ac_rate|floatformat(1) }}%</td>
{% endif %}
<td class="users">
<a href="{{ url('ranked_submissions', problem.code) }}">
{% if not request.in_contest or not hide_contest_scoreboard %}
{{ problem.user_count }}
{% else %}
???
{% endif %}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if page_obj.num_pages > 1 %}
<div style="margin-top:10px;">{% include "list-pages.html" %}</div>
{% endif %}
</div>
</div>
<br>
{% endblock %}

View file

@ -0,0 +1,168 @@
{% extends "base.html" %}
{% block media %}
<style>
.panes {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.pane {
display: block;
max-width: 20em;
border: 1px #ccc solid;
border-radius: 5px;
padding: 10px;
margin: 10px;
}
.pane h3 {
display: block;
background: #3b3b3b;
padding: 5px 10px 10px;
margin: -10px -10px 10px;
border-radius: 5px 5px 0 0;
color: white;
}
.control-group {
margin: 1em 0;
}
.control-group:not(:first-of-type) {
border-top: 1px solid #ccc;
padding-top: 0.5em;
}
.control-group label {
display: block;
margin-bottom: 0.5em;
}
.control-group select {
display: block;
width: 100%;
}
</style>
{% endblock %}
{% block js_media %}
<script>
$(function () {
$('#by-lang-filter').select2({
multiple: true,
placeholder: '{{ _('Leave empty to not filter by language') }}'
});
$('#by-result-filter').select2({
multiple: true,
placeholder: '{{ _('Leave empty to not filter by result') }}'
});
$('#rescore-all').click(function (e) {
e.preventDefault();
if (confirm(this.dataset.warning)) {
$(this).parents('form').submit();
}
});
var $use_id = $('#by-range-check');
var $id_start = $('#by-range-start');
var $id_end = $('#by-range-end');
$('#rejudge-selected').click(function (e) {
e.preventDefault();
if ($use_id.prop('checked')) {
var start = parseInt($id_start.val());
var end = parseInt($id_end.val());
if (!start || !end) {
alert("{{ _('Need valid values for both start and end IDs.') }}");
return;
} else if (start > end) {
alert("{{ _('End ID must be after start ID.') }}");
return;
}
}
var $form = $(this).parents('form');
$.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))) {
$form.submit();
}
})
.fail(function () {
if (confirm("{{ _('You are about to rejudge a few submissions. Are you sure you want to do this?') }}")) {
$form.submit();
}
});
});
$use_id.change(function () {
$('#by-range-filter').find('input').prop('disabled', !this.checked);
});
});
</script>
{% endblock %}
{% block body %}
{% include "messages.html" %}
<div class="panes">
{% if request.user.has_perm('judge.rejudge_submission_lot') %}
<div class="pane">
<h3>{{ _('Rejudge Submissions') }}</h3>
<form action="{{ url('problem_submissions_rejudge', problem.code) }}" method="post">
{% csrf_token %}
<div class="control-group">
<label><input id="by-range-check" type="checkbox" name="use_range" value="on">
{{ _('Filter by ID:') }}</label>
<table id="by-range-filter" class="table">
<tr>
<th><label for="by-range-start">{{ _('Starting ID:') }}</label></th>
<td><input id="by-range-start" name="start" type="number" disabled></td>
</tr>
<tr>
<th><label for="by-range-end">{{ _('Ending ID:') }}</label></th>
<td><input id="by-range-end" name="end" type="number" disabled></td>
</tr>
</table>
<p>{{ _('This range includes both endpoints.') }}</p>
</div>
<div class="control-group">
<label for="by-lang-filter">{{ _('Filter by language:') }}</label>
<select id="by-lang-filter" name="language" multiple>
{% for id, name in languages %}
<option value="{{ id }}">{{ name }}</option>
{% endfor %}
</select>
</div>
<div class="control-group">
<label for="by-result-filter">{{ _('Filter by result:') }}</label>
<select id="by-result-filter" name="result" multiple>
{% for name in results %}
<option>{{ name }}</option>
{% endfor %}
</select>
</div>
<a id="rejudge-selected" class="unselectable button full" href="#">
{{ _('Rejudge selected submissions') }}
</a>
</form>
</div>
{% endif %}
<div class="pane">
<h3>{{ _('Rescore Everything') }}</h3>
<p id="rescore-warning">{{ _('This will rescore %(count)d submissions.', count=submission_count) }}</p>
<form action="{{ url('problem_submissions_rescore_all', problem.code) }}" method="post">
{% csrf_token %}
<a id="rescore-all" class="unselectable button full" href="#"
data-warning="{{ _('Are you sure you want to rescore %(count)d submissions?', count=submission_count) }}">
{{ _('Rescore all submissions') }}
</a>
</form>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,4 @@
{{ preview_data|markdown('problem', MATH_ENGINE)|reference|str|safe }}
{% if REQUIRE_JAX %}
<div data-config="{{ static('mathjax_config.js') }}" class="require-mathjax-support"></div>
{% endif %}

View file

@ -0,0 +1,8 @@
{% extends "tabs-base.html" %}
{% block tabs %}
{% if perms.judge.edit_all_problem or perms.judge.edit_public_problem or perms.judge.edit_own_problem %}
{{ make_tab('list', 'fa-list', url('problem_list'), _('List')) }}
{{ make_tab('admin', 'fa-edit', url('admin:judge_problem_changelist'), _('Admin')) }}
{% endif %}
{% endblock %}

View file

@ -0,0 +1,332 @@
{% extends "common-content.html" %}
{% block content_media %}
{% include "comments/media-css.html" %}
<style>
.title-state {
font-size: 2em;
float: left;
width: 1.1em;
display: block;
margin-top: 0.16em;
}
.info-float a {
vertical-align: middle;
}
.problem-clarification {
border-bottom: 1px solid #ccc;
margin-top: 1em;
margin-bottom: 1em;
}
.clarifications-area h2 {
margin-bottom: 20px;
}
.problem-clarification .body {
display: inline-block;
padding-left: 3em;
}
#content-right {
max-width: 12.5em;
min-width: 12.5em;
}
#problem-types, #allowed-langs, #available-judges {
padding-top: 1em;
}
.problem-info-entry {
padding-top: 0.5em;
}
</style>
{% endblock %}
{% block content_js_media %}
{% include "comments/media-js.html" %}
{% endblock %}
{% block title_row %}
<div class="problem-title">
{% if request.user.is_authenticated %}
{% if problem.id in completed_problem_ids %}
<a href="{{ url('user_submissions', problem.code, request.user.username) }}">
{% if problem.is_public or request.in_contest %}
<i class="solved-problem-color title-state fa fa-check-circle"></i>
{% else %}
<i class="solved-problem-color title-state fa fa-lock"></i>
{% endif %}
</a>
{% elif problem.id in attempted_problems %}
<a href="{{ url('user_submissions', problem.code, request.user.username) }}">
{% if problem.is_public or request.in_contest %}
<i class="attempted-problem-color title-state fa fa-minus-circle"></i>
{% else %}
<i class="attempted-problem-color title-state fa fa-lock"></i>
{% endif %}
</a>
{% endif %}
{% endif %}
<h2 style="color:#393630; display: inline-block">{{ title }}</h2>
{% if problem.is_organization_private %}
<span class="organization-tags">
{% for org in problem.organizations.all() %}
<span class="organization-tag">
<a href="{{ org.get_absolute_url() }}">
<i class="fa fa-lock"></i> {{ org.name }}
</a>
</span>
{% endfor %}
</span>
{% endif %}
{% if has_pdf_render %}
<span class="spacer"></span>
<a href="{{ url('problem_pdf', problem.code) }}" class="view-pdf">
<span class="pdf-icon">
<span class="fa fa-file-pdf-o pdf-icon-logo"></span>
<span class="pdf-icon-bar"></span>
</span>
{{ _('View as PDF') }}
</a>
{% endif %}
</div>
{% endblock %}
{% block info_float %}
{% if request.user.is_authenticated and request.in_contest and submission_limit %}
{% if submissions_left > 0 %}
<a href="{{ url('problem_submit', problem.code) }}" class="unselectable button full">
{{ _('Submit solution') }}
</a>
<div class="submissions-left">
{% trans trimmed counter=submissions_left %}
{{ counter }} submission left
{% pluralize %}
{{ counter }} submissions left
{% endtrans %}
</div>
{% else %}
<a class="unselectable button full disabled">{{ _('Submit solution') }}</a>
<div class="no-submissions-left submissions-left">{{ _('0 submissions left') }}</div>
{% endif %}
{% else %}
<a href="{{ url('problem_submit', problem.code) }}" class="unselectable button full">
{{ _('Submit solution') }}
</a>
{% endif %}
<hr style="padding-bottom: 0.3em">
{% if request.user.is_authenticated and has_submissions %}
<div>
<a href="{{ url('user_submissions', problem.code, request.user.username) }}">{{ _('My submissions') }}</a>
</div>
{% endif %}
<div><a href="{{ url('chronological_submissions', problem.code) }}">{{ _('All submissions') }}</a></div>
<div><a href="{{ url('ranked_submissions', problem.code) }}">{{ _('Best submissions') }}</a></div>
{% if editorial and editorial.is_public and
not (request.user.is_authenticated and request.profile.current_contest) %}
<hr>
<div><a href="{{ url('problem_editorial', problem.code) }}">{{ _('Read editorial') }}</a></div>
{% endif %}
{% if can_edit_problem %}
<hr>
<div>
<a href="{{ url('problem_ticket_list', problem.code) }}">{{ _('Manage tickets') }}
{% if num_open_tickets %}<span class="badge">{{ num_open_tickets }}</span>{% endif %}
</a>
</div>
<div><a href="{{ url('admin:judge_problem_change', problem.id) }}">{{ _('Edit problem') }}</a></div>
{% if not problem.is_manually_managed %}
<div><a href="{{ url('problem_data', problem.code) }}">{{ _('Edit test data') }}</a></div>
{% endif %}
{% elif request.user.is_authenticated and has_tickets %}
<hr>
<div>
<a href="{{ url('problem_ticket_list', problem.code) }}">{{ _('My tickets') }}
{% if num_open_tickets %}<span class="badge">{{ num_open_tickets }}</span>{% endif %}
</a>
</div>
{% endif %}
{% if problem.is_subs_manageable_by(request.user) %}
<div>
<a href="{{ url('problem_manage_submissions', problem.code) }}">{{ _('Manage submissions') }}</a>
</div>
{% endif %}
{% if perms.judge.clone_problem %}
<div>
<a href="{{ url('problem_clone', problem.code) }}">{{ _('Clone problem') }}</a>
</div>
{% endif %}
<hr style="padding-top: 0.3em">
<div class="problem-info-entry">
<i class="fa fa-check fa-fw"></i><span class="pi-name">{{ _('Points:') }}</span>
<span class="pi-value">
{% if contest_problem %}
{{ contest_problem.points }}{% if contest_problem.partial %} {{ _('(partial)') }}{% endif %}
{% else %}
{{ problem.points|floatformat }}{% if problem.partial %} {{ _('(partial)') }}{% endif %}
{% endif %}
</span>
</div>
<div class="problem-info-entry">
<i class="fa fa-clock-o fa-fw"></i><span class="pi-name">{{ _('Time limit:') }}</span>
<span class="pi-value">{{ problem.time_limit }}s</span>
</div>
<div class="problem-lang-limits">
{% for name, limit in problem.language_time_limit %}
<div class="lang-limit">
<span class="lang-name">{{ name }}</span>
<span class="lang-tl">{{ limit }}s</span>
</div>
{% endfor %}
</div>
<div class="problem-info-entry">
<i class="fa fa-server fa-fw"></i><span class="pi-name">{{ _('Memory limit:') }}</span>
<span class="pi-value">{{ problem.memory_limit|kbsimpleformat }}</span>
</div>
<div class="problem-lang-limits">
{% for name, limit in problem.language_memory_limit %}
<div class="lang-limit">
<span class="lang-name">{{ name }}</span>
<span class="lang-ml">{{ limit|kbsimpleformat }}</span>
</div>
{% endfor %}
</div>
<hr style="padding-top: 0.7em">
{% cache 86400 'problem_authors' problem.id LANGUAGE_CODE %}
{% with authors=problem.authors.all() %}
{% if authors %}
<div class="problem-info-entry">
<i class="fa fa-pencil-square-o fa-fw"></i><span
class="pi-name">{% trans trimmed count=authors|length %}
Author:
{% pluralize count %}
Authors:
{% endtrans %}</span>
<div class="pi-value authors-value">{{ link_users(authors) }}</div>
</div>
{% endif %}
{% endwith %}
{% endcache %}
{% if not contest_problem or not contest_problem.contest.hide_problem_tags %}
<div id="problem-types">
{% with types=problem.types_list %}
<div class="toggle closed unselectable">
<i class="fa fa-chevron-right fa-fw"></i>{% trans trimmed count=problem.types_list|length %}
Problem type
{% pluralize count %}
Problem types
{% endtrans %}
</div>
<div style="display:none" class="toggled">{{ problem.types_list|join(", ") }}</div>
{% endwith %}
</div>
{% endif %}
{% if show_languages %}
<div id="allowed-langs">
<div class="toggle open unselectable">
<i class="fa fa-chevron-right fa-fw"></i>{{ _('Allowed languages') }}
</div>
<div class="toggled">
{% with usable=problem.usable_common_names, langs=problem.languages_list() %}
{% for lang in langs %}
{%- if lang in usable -%}
{{ lang }}
{%- else -%}
<s title="{{ _('No %(lang)s judge online', lang=lang) }}">{{ lang }}</s>
{%- endif -%}
{% if not loop.last %}, {% endif -%}
{% endfor %}
{% endwith %}
</div>
</div>
{% endif %}
{% if problem.is_editable_by(request.user) %}
<div id="available-judges">
<i class="fa fa-database fa-fw"></i><span
class="pi-name">{% trans trimmed count=available_judges|length %}
Judge:
{% pluralize count %}
Judges:
{% endtrans %}
</span>
<div class="pi-value judges-value">
{% if available_judges %}
{% if perms.judge.change_judge %}
{% for judge in available_judges %}
<a href="{{ url('admin:judge_judge_change', judge.id) }}">{{ judge.name }}</a>
{%- if not loop.last %}, {% endif %}
{% endfor %}
{% else %}
{{ available_judges|join(", ") }}
{% endif %}
{% else %}
<i>{{ _('none available') }}</i>
{% endif %}
</div>
</div>
{% endif %}
{% endblock %}
{% block description %}
{% cache 86400 'problem_html' problem.id MATH_ENGINE LANGUAGE_CODE %}
{{ description|markdown("problem", MATH_ENGINE)|reference|str|safe }}
{% endcache %}
{% with license=problem.license %}
{% if license %}
<span class="license">
<a href="{{ url('license', license.key) }}">{{ license.display or license.name }}</a>
</span>
{% endif %}
{% endwith %}
{% endblock %}
{% block post_description_end %}
{% if request.user.is_authenticated and not request.profile.mute %}
<a href="{{ url('new_problem_ticket', problem.code) }}" class="button clarify">
{%- if contest_problem and contest_problem.contest.use_clarifications and request.profile.current_contest.live -%}
{{ _('Request clarification') }}
{%- else -%}
{{ _('Report an issue') }}
{%- endif -%}
</a>
{% endif %}
{% endblock %}
{% block comments %}
{% if contest_problem and contest_problem.contest.use_clarifications %}
<div class="clarifications-area">
<h2><i class="fa fa-question-circle"></i> {{ _('Clarifications') }}</h2>
{% if has_clarifications %}
{% for clarification in clarifications %}
<div class="problem-clarification">
<div class="time">{{ relative_time(clarification.date) }}</div>
<span class="body">
{{ clarification.description|markdown('problem', MATH_ENGINE)|reference }}
</span>
</div>
{% endfor %}
{% else %}
<p class="no-comments-message">{{ _('No clarifications have been made at this time.') }}</p>
{% endif %}
</div>
{% else %}
{% include "comments/list.html" %}
{% endif %}
{% endblock %}
{% block bodyend %}
{{ super() }}
{% include "comments/math.html" %}
{% endblock %}

View file

@ -0,0 +1,96 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="pygment-github.css" type="text/css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>
html {
background: white;
}
body {
overflow: hidden;
page-break-after: always;
background: white;
}
tr {
page-break-inside: avoid;
}
#info-table {
width: auto;
background: white;
}
#info-table td {
text-align: left;
}
#info-table td.value {
min-width: 10em;
}
#info-table td.key {
font-weight: bold;
}
.lang-limit {
margin-left: 1.5em;
}
.lang-name:after {
content: ": ";
}
.problem-info-entry {
vertical-align: top;
float: center;
padding: 0.6em;
display: inline-block;
text-align: left;
}
</style>
</head>
<body>
<h2 style="color:#393630; display: inline-block;">{{ problem_name }}</h2>
<hr>
<div align="center" style="position: relative;">
<div class="problem-info-entry">
<b>{{ _('Time Limit:') }}</b> {{ problem.time_limit }}s
{% for name, limit in problem.language_time_limit %}
<div class="lang-limit">
<span class="lang-name">{{ name }}</span>
<span>{{ limit }}s</span>
</div>
{% endfor %}
</div>
<div class="problem-info-entry">
<b>{{ _('Memory Limit:') }}</b> {{ problem.memory_limit|kbsimpleformat}}
{% for name, limit in problem.language_memory_limit %}
<div class="lang-limit">
<span class="lang-name">{{ name }}</span>
<span>{{ limit|kbsimpleformat }}</span>
</div>
{% endfor %}
</div>
</div>
<hr style="clear: both;">
<div class="content-description printing">
{{ description|markdown('problem', 'tex' if math_engine == 'jax' else math_engine)|reference|absolutify(url)|str|safe }}
</div>
{% if math_engine == 'jax' %}
<script type="text/javascript" src="mathjax_config.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS_HTML"></script>
<script type="text/javascript">
MathJax.Hub.Register.StartupHook("End", function () {
if (typeof window.callPhantom === 'function')
window.callPhantom({'action': 'snapshot'});
document.body.classList.add('math-loaded');
});
</script>
{% endif %}
</body>
</html>

View file

@ -0,0 +1,68 @@
<div class="sidebox">
<h3>{{ _('Problem search') }} <i class="fa fa-search"></i>
</h3>
<div class="sidebox-content">
<form id="filter-form" name="form" action="" method="get">
<div>
<input id="search" type="text" name="search" value="{{ search_query or '' }}"
placeholder="{{ _('Search problems...') }}">
</div>
{% if has_fts %}
<div>
<input id="full_text" type="checkbox" name="full_text" value="1"
{% if full_text %}checked{% endif %}>
<label for="full_text">{{ _('Full text search') }}</label>
</div>
{% endif %}
{% if request.user.is_authenticated %}
<div>
<input id="hide_solved" type="checkbox" name="hide_solved" value="1"
{% if hide_solved %}checked{% endif %}>
<label for="hide_solved">{{ _('Hide solved problems') }}</label>
</div>
{% endif %}
<div>
<input id="show_types" type="checkbox" name="show_types" value="1"
{% if show_types %} checked{% endif %}>
<label for="show_types">{{ _('Show problem types') }}</label>
</div>
<div class="filter-form-group">
<label for="category"><i>{{ _('Category') }}</i></label>
<select id="category" name="category">
{% if category %}
<option value="" selected="selected">{{ _('All') }}</option>
{% else %}
<option value="">{{ _('All') }}</option>{% endif %}
<option disabled="disabled">---</option>
{% for group in categories %}
<option value="{{ group.id }}"{% if group.id == category %} selected{% endif %}>
{{ group.full_name }}
</option>
{% endfor %}
</select>
</div>
{% if show_types %}
<div class="filter-form-group">
<label for="type"><i>{{ _('Problem types') }}</i></label>
<select id="types" name="type" multiple>
{% for type in problem_types %}
<option value="{{ type.id }}"{% if type.id in selected_types %} selected{% endif %}>
{{ type.full_name }}
</option>
{% endfor %}
</select>
</div>
{% endif %}
{% if point_values %}
<div class="form-label">{{ _('Point range') }}</div>
<div id="point-slider"></div>
{% endif %}
<input id="point-start" type="hidden" name="point_start" {% if point_start and point_start != point_values.min %}value="{{ point_start }}"{% else %}disabled{% endif %}>
<input id="point-end" type="hidden" name="point_end" {% if point_end and point_end != point_values.max %}value="{{ point_end }}"{% else %}disabled{% endif %}>
<div class="form-submit-group">
<a id="go" class="button">{{ _('Go') }}</a>
<a id="random" class="button">{{ _('Random') }}</a>
</div>
</form>
</div>
</div>

View file

@ -0,0 +1,100 @@
{% extends "common-content.html" %}
{% block js_media %}
<script type="text/javascript">
$(function () {
$('a.sub-case-status').featherlight($('.partial-output-window'), {
afterOpen: function () {
var $parent = this.$currentTarget.parent();
var partial = $parent.attr('data-partial-output');
this.$instance.find('.partial-output-window').find('code').text(partial).end().show();
}
});
});
</script>
<script type="text/javascript" src="{{ static('libs/featherlight/featherlight.min.js') }}"></script>
<script type="text/javascript">
</script>
{% endblock %}
{% block media %}
<style>
#content-body {
overflow-x: auto;
padding-bottom: 0;
}
.sub-id {
width: 4em;
min-width: 4em;
}
.sub-username {
width: 5em;
}
.sub-result {
width: 3em;
}
.sub-language {
width: 6em;
}
.sub-date {
min-width: 8em;
}
.sub-case {
min-width: 3em;
}
.sub-case-status {
text-decoration: underline;
}
</style>
{% endblock %}
{% block body %}
<table id="case-table" class="table">
<thead>
<tr>
<th class="sub-id">ID</th>
<th class="sub-username">Username</th>
<th class="sub-result">Result</th>
<th class="sub-language">Language</th>
<th class="sub-date">Date</th>
{% for case in range(num_cases) %}
<th class="sub-case">{{ loop.index }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for sub in submissions %}
<tr>
<td><a href="{{ url('submission_source', sub.id) }}">{{ sub.id }}</a></td>
<td>{{ link_user(sub.user) }}</td>
<td><span class="case-{{ sub.result }}">{{ sub.result }}</span></td>
<td>{{ sub.language.name }}</td>
<td><span class="time">{{ relative_time(sub.date) }}</span></td>
{% for case in sub.test_cases.all() %}
<td data-partial-output="{{ case.output }}">
{% if case.status == 'SC' %}
<span class="case-SC">---</span>
{% else %}
<a href="javascript:void(0);" class="sub-case-status case-{{ case.status }}">
{% if case.status == 'AC' %}
{{ case.time|floatformat(2) }}
{% else %}
{{ case.status }}
{% endif %}
</a>
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
<div style="display: none" class="partial-output-window"><pre><code></code></pre></div>
{% endblock %}

View file

@ -0,0 +1,256 @@
{% extends "base.html" %}
{% block js_media %}
<script type="text/javascript" src="{{ ACE_URL }}/ace.js"></script>
{% compress js %}
{{ form.media.js }}
<script type="text/javascript">
$(function () {
function format(state) {
if (!state.id) return state.text; // optgroup
return state.text;
}
window.previous_template = '';
function update_language_template() {
var source = $('textarea#id_source');
if (source.val() == window.previous_template.replace(/\r/g, '') || source.val() == '') {
var lang_id = $('#id_language').val();
var code = localStorage.getItem('submit:' + $('#id_language').val());
function update_submit_area(code) {
window.previous_template = code;
source.val(code);
window.ace_source.getSession().setValue(code);
}
if (code != null) {
update_submit_area(code);
} else {
$.get('{{ url('language_template_ajax') }}', {
id: lang_id
}).done(function (template) {
update_submit_area(template);
});
}
}
}
function makeDisplayData(data) {
var site_data = data.attr('data-info');
var judge_data = data.attr('data-judge-info');
var display_data = site_data || judge_data;
return display_data;
}
function formatSelection(state) {
if (!state.id) return state.text; // optgroup
var data = makeDisplayData($("option[data-id=" + state.id + "]"));
return "<b>" + state.text + "</b> (" + data + ")";
}
// Terrible hack, adapted from https://github.com/select2/select2/issues/4436
$.fn.select2.amd.define('select2/data/customAdapter', ['select2/results', 'select2/utils'], function (Result, Utils) {
RefPresenter = function ($element, options, dataAdapter) {
RefPresenter.__super__.constructor.call(this, $element, options, dataAdapter);
};
Utils.Extend(RefPresenter, Result);
RefPresenter.prototype.bind = function (container, $container) {
container.on('results:focus', function (params) {
var data = makeDisplayData($("option[data-id=" + params.data.id + "]"));
$("#result-version-info").text(data);
});
RefPresenter.__super__.bind.call(this, container, $container);
};
return RefPresenter;
});
var customAdapter = $.fn.select2.amd.require('select2/data/customAdapter');
$("#id_language").select2({
templateResult: format,
templateSelection: formatSelection,
escapeMarkup: function (m) {
return m;
},
resultsAdapter: customAdapter
});
$('#id_language').on('select2:open', function (evt) {
var dropdown = $('.select2-dropdown');
if (!$('#result-version-info').length)
dropdown.append($("<span id=\"result-version-info\">"));
});
$('#id_language').change(function () {
var lang = $("#id_language").find("option:selected").attr('data-ace');
window.ace_source.getSession().setMode("ace/mode/" + lang);
update_language_template();
});
$('#ace_source').on('ace_load', function (e, editor) {
update_language_template();
editor.commands.addCommand({
name: 'save',
bindKey: {win: 'Ctrl-S', mac: 'Command-S'},
exec: function () {
localStorage.setItem('submit:' + $('#id_language').val(), editor.getSession().getValue());
}
});
editor.getSession().setUseWrapMode(true);
editor.setFontSize(14);
editor.setPrintMarginColumn(100);
editor.focus();
});
$(window).resize(function () {
$('#ace_source').height(Math.max($(window).height() - 353, 100));
}).resize();
});
</script>
{% endcompress %}
{% endblock %}
{% block media %}
{% compress css %}
{{ form.media.css }}
<style media="screen">
#submit-wrapper {
margin-top: 0.7em;
}
#submit-wrapper #problem-id, #submit-wrapper #editor, #submit-wrapper #language {
margin-top: 4px;
}
#id_language {
width: 100%;
}
#result-version-info {
border-bottom: 1px solid rgb(148, 148, 148);
margin: 0px 1em;
color: #757575;
font-weight: 600;
padding: 0.2em 0;
text-align: right;
}
.select2-results__message {
white-space: nowrap
}
.select2-dropdown--above {
display: flex;
flex-direction: column-reverse;
}
.select2-results__option {
color: #757575 !important;
background: white !important;
}
.select2-results__option--highlighted {
text-decoration: underline;
}
.select2-results__option[aria-selected=true] {
font-weight: bold;
color: black !important;
}
.select2-results__option {
padding: 4px 0px;
}
.select2-results__options {
overflow-y: visible !important;
}
.select2-results__option {
break-inside: avoid-column;
}
.select2-results {
-webkit-columns: 10 7em;
-moz-columns: 10 7em;
columns: 10 7em;
padding-left: 1.5em;
padding-top: 0.5em;
}
</style>
{% endcompress %}
{% endblock %}
{% block body %}
<br>
{% if not no_judges %}
{% if default_lang not in form.fields.language.queryset %}
<div class="alert alert-warning alert-dismissable">
<a class="close">x</a>
{% trans trimmed default_language=default_lang.name %}
<b>Warning!</b> Your default language, <b>{{ default_language }}</b>,
is unavailable for this problem and has been deselected.
{% endtrans %}
</div>
{% endif %}
{% if request.in_contest and submission_limit %}
{% if submissions_left > 0 %}
<div class="alert alert-warning alert-dismissable">
<a class="close">x</a>
{% trans left=submissions_left %}
You have {{ left }} submission left
{% pluralize %}
You have {{ left }} submissions left
{% endtrans %}
</div>
{% else %}
<div class="alert alert-warning alert-dismissable">
<a class="close">x</a>
{{ _('You have 0 submissions left') }}
</div>
{% endif %}
{% endif %}
{% endif %}
<form id="problem_submit" action="" method="post" class="form-area">
{% csrf_token %}
{{ form.non_field_errors() }}
<div id="submit-wrapper">
<div id="problem-id">
{{ form.problem.errors }}
{{ form.problem }}
</div>
<div id="editor">
{{ form.source.errors }}
{{ form.source }}
</div>
{% if not no_judges %}
<div id="language">
{{ form.language.errors }}
<div id="language-select">
<select id="id_language" name="language">
{% for lang in form.fields.language.queryset %}
<option value="{{ lang.id }}" data-id="{{ lang.id }}" data-name="{{ lang.name }}"
data-info="{{ lang.info }}" data-ace="{{ lang.ace }}"
data-judge-info="{{ runtime_versions(lang.runtime_versions()) }}"
{% if lang.id == default_lang.id %}selected{% endif %}>{{ lang.name }}</option>
{% endfor %}
</select>
</div>
</div>
{% endif %}
</div>
<hr>
{% if no_judges %}
<span style="color: red">{{ _('No judge is available for this problem.') }}</span>
{% else %}
<input type="submit" value="{{ _('Submit!') }}" class="button"
{% if request.in_contest and submission_limit and not submissions_left %}disabled{% endif %}>
{% endif %}
</form>
{% endblock %}

View file

@ -0,0 +1,20 @@
{% extends "base.html" %}
{% block body %}
<div class="source-wrap">
<table>
<tr>
<td class="source-ln">
<div>
{% for line in raw_source.split('\n') %}
<a href="#line-{{ loop.index }}" name="line-{{ loop.index }}">
<pre>{{ loop.index }}</pre>
</a>
{% endfor %}
</div>
</td>
<td class="source-code">{{ highlighted_source }}</td>
</tr>
</table>
</div>
{% endblock %}