Add interactive option
This commit is contained in:
parent
122cd0fa73
commit
ff8f12c134
6 changed files with 112 additions and 5 deletions
31
judge/migrations/0121_auto_20220415_0135.py
Normal file
31
judge/migrations/0121_auto_20220415_0135.py
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# Generated by Django 2.2.25 on 2022-04-14 18:35
|
||||||
|
|
||||||
|
import django.core.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
import judge.models.problem_data
|
||||||
|
import judge.utils.problem_data
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('judge', '0120_auto_20220306_1124'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='problemdata',
|
||||||
|
name='interactive_judge',
|
||||||
|
field=models.FileField(blank=True, null=True, storage=judge.utils.problem_data.ProblemDataStorage(), upload_to=judge.models.problem_data.problem_directory_file, validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['cpp'])], verbose_name='interactive judge'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='problemdata',
|
||||||
|
name='checker',
|
||||||
|
field=models.CharField(blank=True, choices=[('standard', 'Standard'), ('floats', 'Floats'), ('floatsabs', 'Floats (absolute)'), ('floatsrel', 'Floats (relative)'), ('rstripped', 'Non-trailing spaces'), ('sorted', 'Unordered'), ('identical', 'Byte identical'), ('linecount', 'Line-by-line'), ('custom', 'Custom checker (PY)'), ('customval', 'Custom validator (CPP)'), ('interact', 'Interactive')], max_length=10, verbose_name='checker'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='problemtestcase',
|
||||||
|
name='checker',
|
||||||
|
field=models.CharField(blank=True, choices=[('standard', 'Standard'), ('floats', 'Floats'), ('floatsabs', 'Floats (absolute)'), ('floatsrel', 'Floats (relative)'), ('rstripped', 'Non-trailing spaces'), ('sorted', 'Unordered'), ('identical', 'Byte identical'), ('linecount', 'Line-by-line'), ('custom', 'Custom checker (PY)'), ('customval', 'Custom validator (CPP)'), ('interact', 'Interactive')], max_length=10, verbose_name='checker'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -33,6 +33,7 @@ CHECKERS = (
|
||||||
('linecount', _('Line-by-line')),
|
('linecount', _('Line-by-line')),
|
||||||
('custom', _('Custom checker (PY)')),
|
('custom', _('Custom checker (PY)')),
|
||||||
('customval', _('Custom validator (CPP)')),
|
('customval', _('Custom validator (CPP)')),
|
||||||
|
('interact', _('Interactive')),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,6 +62,13 @@ class ProblemData(models.Model):
|
||||||
blank=True,
|
blank=True,
|
||||||
upload_to=problem_directory_file,
|
upload_to=problem_directory_file,
|
||||||
validators=[FileExtensionValidator(allowed_extensions=['cpp'])])
|
validators=[FileExtensionValidator(allowed_extensions=['cpp'])])
|
||||||
|
interactive_judge = models.FileField(verbose_name=_('interactive judge'),
|
||||||
|
storage=problem_data_storage,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
upload_to=problem_directory_file,
|
||||||
|
validators=[FileExtensionValidator(allowed_extensions=['cpp'])])
|
||||||
|
|
||||||
__original_zipfile = None
|
__original_zipfile = None
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
|
@ -210,9 +210,16 @@ class ProblemDataCompiler(object):
|
||||||
if self.data.output_prefix is not None:
|
if self.data.output_prefix is not None:
|
||||||
init['output_prefix_length'] = self.data.output_prefix
|
init['output_prefix_length'] = self.data.output_prefix
|
||||||
if self.data.checker:
|
if self.data.checker:
|
||||||
init['checker'] = make_checker(self.data)
|
if self.data.checker == 'interact':
|
||||||
|
init['interactive'] = {
|
||||||
|
'files': split_path_first(self.data.interactive_judge.name)[1]
|
||||||
|
}
|
||||||
|
init['unbuffered'] = True
|
||||||
|
else:
|
||||||
|
init['checker'] = make_checker(self.data)
|
||||||
else:
|
else:
|
||||||
self.data.checker_args = ''
|
self.data.checker_args = ''
|
||||||
|
|
||||||
return init
|
return init
|
||||||
|
|
||||||
def compile(self):
|
def compile(self):
|
||||||
|
|
|
@ -61,7 +61,7 @@ class ProblemDataForm(ModelForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ProblemData
|
model = ProblemData
|
||||||
fields = ['zipfile', 'checker', 'checker_args', 'custom_checker', 'custom_validator']
|
fields = ['zipfile', 'checker', 'checker_args', 'custom_checker', 'custom_validator', 'interactive_judge']
|
||||||
widgets = {
|
widgets = {
|
||||||
'zipfile': FineUploadFileInput,
|
'zipfile': FineUploadFileInput,
|
||||||
'checker_args': HiddenInput,
|
'checker_args': HiddenInput,
|
||||||
|
|
|
@ -140,6 +140,62 @@ int main(int argc, char** argv) {
|
||||||
cout << "a + b = " << a + b << " != " << n << endl;
|
cout << "a + b = " << a + b << " != " << n << endl;
|
||||||
return 1; // WA
|
return 1; // WA
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<h2>3. Interactive (CPP)</h2>
|
||||||
|
<hr>
|
||||||
|
<p>
|
||||||
|
Để sử dụng chức năng này, cần viết một chương trình C++ pass vào 1 argument <code>input_file</code> tương ứng file input.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Để test chương trình trên máy tính với tư cách thí sinh, có thể dùng lệnh như sau (Windows):
|
||||||
|
<pre class="code2">
|
||||||
|
main.exe [input_file]</pre>
|
||||||
|
hoặc thay bằng <code>./main</code> trên Linux/MacOS.
|
||||||
|
</p>
|
||||||
|
<h2>Return: </h2>
|
||||||
|
<p>
|
||||||
|
Chương trình trả về giá trị:
|
||||||
|
<ul>
|
||||||
|
<li> 0 nếu AC (100% điểm)</li>
|
||||||
|
<li> 1 nếu WA (0 điểm)</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Ví dụ: </h2>
|
||||||
|
<p>Chương trình sau dùng để chấm bài toán guessgame: Người chơi phải tìm 1 số bí mật n (n chứa trong file input). Mỗi lần họ được hỏi một số x, và chương trình sẽ trả về "SMALLER", "BIGGER" hoặc "HOLA" dựa trên giá trị của n và x. Cần tìm ra n sau không quá 31 câu hỏi. </p>
|
||||||
|
<pre class="code2">
|
||||||
|
#include <bits/stdc++.h>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
void read(long long& guess) {
|
||||||
|
if (!(cin >> guess)) exit(1); // Nếu không có dòng này, chương trình sẽ chờ vô hạn
|
||||||
|
if (guess < 1 || guess > 2e9) exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
ifstream inp(argv[1]);
|
||||||
|
int N, guesses = 0;
|
||||||
|
long long guess;
|
||||||
|
inp >> N;
|
||||||
|
|
||||||
|
while (guess != N && guesses < 31) {
|
||||||
|
read(guess);
|
||||||
|
if (guess == N) {
|
||||||
|
cout << "HOLA" << endl;
|
||||||
|
} else if (guess > N) {
|
||||||
|
cout << "SMALLER" << endl;
|
||||||
|
} else {
|
||||||
|
cout << "BIGGER" << endl;
|
||||||
|
}
|
||||||
|
guesses++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (guesses <= 31)
|
||||||
|
return 0; // AC
|
||||||
|
else {
|
||||||
|
return 1; // WA
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
</article>
|
</article>
|
||||||
|
|
|
@ -132,12 +132,15 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
(function toggle_custom() {
|
(function toggle_custom() {
|
||||||
let $custom_checker = $('#id_problem-data-custom_checker')
|
|
||||||
let $checker = $('#id_problem-data-checker')
|
let $checker = $('#id_problem-data-checker')
|
||||||
let $validator = $('#id_problem-data-custom_validator')
|
|
||||||
|
|
||||||
|
let $custom_checker = $('#id_problem-data-custom_checker')
|
||||||
|
let $validator = $('#id_problem-data-custom_validator')
|
||||||
|
let $interactive = $('#id_problem-data-interactive_judge')
|
||||||
|
|
||||||
$tr_checker = $custom_checker.parent().parent();
|
$tr_checker = $custom_checker.parent().parent();
|
||||||
$tr_validator = $validator.parent().parent()
|
$tr_validator = $validator.parent().parent()
|
||||||
|
$tr_interactive = $interactive.parent().parent()
|
||||||
|
|
||||||
$td = $checker.parent();
|
$td = $checker.parent();
|
||||||
var $sample = $("<a/>",{
|
var $sample = $("<a/>",{
|
||||||
|
@ -150,7 +153,9 @@
|
||||||
$checker.change(function () {
|
$checker.change(function () {
|
||||||
$tr_checker.toggle($checker.val() == 'custom').change();
|
$tr_checker.toggle($checker.val() == 'custom').change();
|
||||||
$tr_validator.toggle($checker.val() == 'customval').change();
|
$tr_validator.toggle($checker.val() == 'customval').change();
|
||||||
$sample.toggle($checker.val().startsWith('custom')).change();
|
$tr_interactive.toggle($checker.val() == 'interact').change();
|
||||||
|
|
||||||
|
$sample.toggle(['custom', 'customval', 'interact'].includes($checker.val())).change();
|
||||||
}).change();
|
}).change();
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue