change e testcase table UI and add CPP validator
This commit is contained in:
parent
0ff312e3ba
commit
f74f8b6e05
15 changed files with 803 additions and 181 deletions
|
@ -2,10 +2,7 @@
|
|||
|
||||
{% block body %}
|
||||
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><style>body {
|
||||
max-width: 980px;
|
||||
border: 1px solid #ddd;
|
||||
outline: 1300px solid #fff;
|
||||
margin: 16px auto;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body .markdown-body
|
||||
|
@ -1079,28 +1076,13 @@ body .markdown-body
|
|||
<p>Additionally, if the <code>check</code> method has the flag <code>run_on_error</code> set, it will be run against the submission’s output, even if it receives an IR/TLE/RTE/MLE verdict.
|
||||
The only built-in checker that has this flag set is the <code>linecount</code> checker.</p>
|
||||
<h2 id="return">Return:<a class="headerlink" href="#return" title="Permanent link"></a></h2>
|
||||
<p><code>True</code> for correct output, <code>False</code> for incorrect one</p>
|
||||
<p><code>check</code> can return either a <code>CheckerResult</code> object (<code>from dmoj.result import CheckerResult</code>), or a boolean (<code>case_passed_bool</code>).
|
||||
A <code>CheckerResult</code> can be instantiated through <code>CheckerResult(case_passed_bool, points_awarded, feedback='')</code>.</p>
|
||||
<h2 id="sample-checker">Sample Checker:<a class="headerlink" href="#sample-checker" title="Permanent link"></a></h2>
|
||||
<p>Here is the checker for the problem: Print 2 integers having sum equal to n (n is read from input).</p>
|
||||
<div class="codehilite"><pre><span class="k">def</span> <span class="nf">check</span><span class="p">(</span><span class="n">process_output</span><span class="p">,</span> <span class="n">judge_output</span><span class="p">,</span> <span class="n">judge_input</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
<span class="c1"># process the input</span>
|
||||
<span class="n">input_arr</span> <span class="o">=</span> <span class="n">judge_input</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
|
||||
<span class="k">assert</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">input_arr</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span>
|
||||
<span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">input_arr</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
||||
<iframe src="https://pastebin.com/embed_iframe/UvuchwbQ" style="border:none;width:100%;height:40em;"></iframe>
|
||||
|
||||
<span class="c1"># process the contestant's output</span>
|
||||
<span class="n">output_arr</span> <span class="o">=</span> <span class="n">process_output</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
|
||||
</article></body></html>
|
||||
|
||||
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">output_arr</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">2</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="bp">False</span>
|
||||
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">output_arr</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="nb">int</span><span class="p">(</span><span class="n">output_arr</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
|
||||
<span class="k">except</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="bp">False</span>
|
||||
|
||||
<span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="bp">True</span>
|
||||
<span class="k">return</span> <span class="bp">False</span>
|
||||
</pre></div></article></body></html>
|
||||
{% endblock body %}
|
|
@ -95,21 +95,29 @@
|
|||
}).change();
|
||||
}
|
||||
|
||||
function checker_custom($checker, $custom_checker) {
|
||||
$tr = $custom_checker.parent().parent();
|
||||
(function toggle_custom() {
|
||||
let $custom_checker = $('#id_problem-data-custom_checker')
|
||||
let $checker = $('#id_problem-data-checker')
|
||||
let $validator = $('#id_problem-data-custom_validator')
|
||||
|
||||
$tr_checker = $custom_checker.parent().parent();
|
||||
$tr_validator = $validator.parent().parent()
|
||||
|
||||
$td = $checker.parent();
|
||||
var $sample = $("<a/>",{
|
||||
text: "Sample Checker",
|
||||
text: "{{_('Instruction')}}",
|
||||
style: "margin-left:3em;",
|
||||
target: "_blank",
|
||||
href: "{{url('custom_checker_sample')}}"
|
||||
}).appendTo($td);
|
||||
|
||||
$checker.change(function () {
|
||||
$tr.toggle($checker.val().startsWith('custom')).change();
|
||||
$tr_checker.toggle($checker.val() == 'custom').change();
|
||||
$tr_validator.toggle($checker.val() == 'customval').change();
|
||||
$sample.toggle($checker.val().startsWith('custom')).change();
|
||||
}).change();
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
function swap_row($a, $b) {
|
||||
var $a_order = $a.find('input[id$=order]'), $b_order = $b.find('input[id$=order]');
|
||||
|
@ -123,8 +131,7 @@
|
|||
}
|
||||
|
||||
checker_precision($('#id_problem-data-checker'));
|
||||
checker_custom($('#id_problem-data-checker'), $('#id_problem-data-custom_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()))
|
||||
|
@ -306,26 +313,6 @@
|
|||
$("input[name$='DELETE']").attr('checked', false);
|
||||
}
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
}).change();
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@ -451,29 +438,7 @@
|
|||
</a>
|
||||
</td>
|
||||
</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>
|
||||
<label>
|
||||
<input type="checkbox" id="delete-all">
|
||||
{{ _('Delete all') }}
|
||||
</label>
|
||||
</div>
|
||||
<input type="submit" value="{{ _('Apply!') }}" class="button" id="submit-button">
|
||||
<table id="case-table" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -483,12 +448,10 @@
|
|||
<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>{{ _('Delete?') }}
|
||||
<br>
|
||||
<input type="checkbox" name="delete-all" id="delete-all">
|
||||
</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
|
@ -517,25 +480,15 @@
|
|||
</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>
|
||||
<td>{{ form.DELETE }}
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<input type="submit" value="{{ _('Submit!') }}" class="button" id="submit-button">
|
||||
<input type="submit" value="{{ _('Apply!') }}" class="button" id="submit-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>
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
<br>
|
||||
<hr class="half-hr">
|
||||
<hr>
|
||||
<br>
|
||||
<div class="source-wrap">
|
||||
<table>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
{% if submission.error %}
|
||||
<h3>{{ _('Compilation Warnings') }}</h3>
|
||||
<pre>{{ submission.error|ansi2html }}</pre>
|
||||
<hr class="half-hr"><br>
|
||||
<hr><br>
|
||||
{% endif %}
|
||||
{% if is_pretest %}
|
||||
<h3>{{ _('Pretest Execution Results') }}</h3>
|
||||
|
@ -33,7 +33,48 @@
|
|||
<br>
|
||||
<div class="batch-cases">
|
||||
{% endif %}
|
||||
<table>{% for case in batch.cases %}
|
||||
<table id="testcases-table">
|
||||
{% if submission.is_graded %}
|
||||
{% if submission.result != 'AB' %}
|
||||
<thead>
|
||||
|
||||
<tr id="overall-row" class="case-row overall-result-{{submission.result}}">
|
||||
|
||||
<td><span class="col-title">{{_('Overall: ')}}</span>
|
||||
{% if request.in_contest and submission.contest_or_none %}
|
||||
{% with contest=submission.contest_or_none %}
|
||||
({{ _('%(points)s/%(total)s points', points=contest.points|roundfloat(3),
|
||||
total=contest.problem.points|floatformat(-1)) }})
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
{{ _('%(points)s/%(total)s', points=submission.points|roundfloat(3),
|
||||
total=submission.problem.points|floatformat(-1)) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
<td><span class="case-{{submission.result}}">{{submission.long_status}}</span></td>
|
||||
|
||||
<td><span class="col-title">{{_('Point: ')}}</span>
|
||||
{{ submission.case_points|floatformat(0) }}/{{ submission.case_total|floatformat(0) }}
|
||||
|
||||
</td>
|
||||
|
||||
<td><span class="col-title">{{_('Time: ')}}</span>
|
||||
{% if submission.result == "TLE" %}
|
||||
<span>---</span>
|
||||
{% else %}
|
||||
<span title="{{ submission.time }}s">{{ (submission.time * 1000)|floatformat(0) }} ms</span>
|
||||
{% endif %}
|
||||
|
||||
</td>
|
||||
|
||||
<td><span class="col-title">{{_('Memory: ')}}</span>{{ submission.memory|kbdetailformat }}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% for case in batch.cases %}
|
||||
<tr id="{{ case.id }}" class="case-row toggle closed">
|
||||
<td>
|
||||
{%- if ((prefix_length is none or prefix_length > 0) or (request.user.is_superuser)) -%}
|
||||
|
@ -50,26 +91,25 @@
|
|||
|
||||
<td>
|
||||
<span title="{{ case.long_status }}" class="case-{{ case.status }}">
|
||||
{%- if case.status == 'SC' %}—{% else %}{{ case.status }}{% endif -%}
|
||||
{%- if case.status == 'SC' %}—{% else %}{{ case.long_status }}{% endif -%}
|
||||
</span>
|
||||
{%- if case.feedback %} ({{ case.feedback }}){% endif -%}
|
||||
</td>
|
||||
|
||||
{% if not batch.id %}
|
||||
<td><span class="col-title">{{_('Point')}}: </span> {{ case.points|floatformat(0) }}/{{ case.total|floatformat(0) }}</td>
|
||||
{% endif %}
|
||||
|
||||
<td>
|
||||
{%- if case.status != 'SC' -%}
|
||||
{%- if case.status == 'TLE' -%}
|
||||
[><span>{{ time_limit|floatformat(3) }}s,</span>
|
||||
<span><span class="col-title">{{_('Time')}}: ></span>{{ (time_limit * 1000)|floatformat(0) }} ms</span>
|
||||
{%- else -%}
|
||||
[<span title="{{ case.time }}s">{{ case.time|floatformat(3) }}s,</span>
|
||||
<span title="{{ case.time }}s"><span class="col-title">{{_('Time')}}: </span>{{ (case.time * 1000)|floatformat(0) }} ms</span>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
</td>
|
||||
|
||||
<td>{% if case.status != 'SC' %}{{ case.memory|kbdetailformat }}]{% endif %}</td>
|
||||
|
||||
{% if not batch.id %}
|
||||
<td>({{ case.points|floatformat(0) }}/{{ case.total|floatformat(0) }})</td>
|
||||
{% endif %}
|
||||
<td>{% if case.status != 'SC' %}<span class="col-title">{{_('Memory')}}: </span> {{ case.memory|kbdetailformat }}{% endif %}</td>
|
||||
</tr>
|
||||
|
||||
{% if ((prefix_length is none or prefix_length > 0) or (request.user.is_superuser)) %}
|
||||
|
@ -79,20 +119,22 @@
|
|||
{% set curr_data = cases_data[case.case] %}
|
||||
<strong>{{ _('Input:') }}</strong>
|
||||
<pre class="case-output">{{ curr_data['input']|linebreaksbr }}</pre>
|
||||
<strong>{{ _('Your output:') }}</strong>
|
||||
<strong>{{ _('Output:') }}</strong>
|
||||
<pre class="case-output">{{ case.output|linebreaksbr }}</pre>
|
||||
<strong>{{ _('Answer:') }}</strong>
|
||||
<pre class="case-output">{{ curr_data['answer']|linebreaksbr }}</pre>
|
||||
|
||||
{% if case.extended_feedback or case.feedback %}
|
||||
<strong>{{ _('Judge feedback:') }}</strong>
|
||||
{% if case.feedback %}
|
||||
<pre class="case-output">{{ case.feedback|linebreaksbr }}</pre>
|
||||
{% endif %}
|
||||
{% if case.extended_feedback %}
|
||||
<pre class="case-output">{{ case.extended_feedback|linebreaksbr }}</pre>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
{% if case.extended_feedback %}
|
||||
<td colspan="5" class="case-ext-feedback">
|
||||
<div class="case-info">
|
||||
<strong>{{ _('Judge feedback') }}</strong>
|
||||
<pre class="case-output">{{ case.extended_feedback|linebreaksbr }}</pre>
|
||||
</div>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
@ -104,29 +146,6 @@
|
|||
{% if submission.is_graded %}
|
||||
<br>
|
||||
{% if submission.result != "AB" %}
|
||||
<b>{{ _('Resources:') }}</b>
|
||||
{% if submission.result == "TLE" %}
|
||||
<span>---,</span>
|
||||
{% else %}
|
||||
<span title="{{ submission.time }}s">{{ submission.time|floatformat(3) }}s,</span>
|
||||
{% endif %}
|
||||
{{ submission.memory|kbdetailformat }}
|
||||
<br>
|
||||
{% if is_pretest %}
|
||||
<b>{{ _('Final pretest score:') }}</b>
|
||||
{% else %}
|
||||
<b>{{ _('Final score:') }}</b>
|
||||
{% endif %}
|
||||
{{ submission.case_points|floatformat(0) }}/{{ submission.case_total|floatformat(0) }}
|
||||
{% if request.in_contest and submission.contest_or_none %}
|
||||
{% with contest=submission.contest_or_none %}
|
||||
({{ _('%(points)s/%(total)s points', points=contest.points|roundfloat(3),
|
||||
total=contest.problem.points|floatformat(-1)) }})
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
({{ _('%(points)s/%(total)s points', points=submission.points|roundfloat(3),
|
||||
total=submission.problem.points|floatformat(-1)) }})
|
||||
{% endif %}
|
||||
{% if is_pretest and submission.result == "AC" %}
|
||||
<br>
|
||||
<i>{{ _('Passing pretests does not guarantee a full score on system tests.') }}</i>
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
{% endif %}
|
||||
|
||||
<br>
|
||||
<hr class="half-hr">
|
||||
<hr>
|
||||
<br>
|
||||
|
||||
<div id="test-cases">{% include "submission/status-testcases.html" %}</div>
|
||||
|
@ -81,7 +81,7 @@
|
|||
{% if request.user == submission.user.user or perms.judge.abort_any_submission %}
|
||||
<div id="abort-button">
|
||||
<br>
|
||||
<hr class="half-hr">
|
||||
<hr>
|
||||
<br>
|
||||
<form action="{{ url('submission_abort', submission.id) }}" method="post">
|
||||
{% csrf_token %}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue