diff --git a/judge/migrations/0121_auto_20220415_0135.py b/judge/migrations/0121_auto_20220415_0135.py new file mode 100644 index 0000000..bc70618 --- /dev/null +++ b/judge/migrations/0121_auto_20220415_0135.py @@ -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'), + ), + ] diff --git a/judge/models/problem_data.py b/judge/models/problem_data.py index fe79c49..2cfb4f9 100644 --- a/judge/models/problem_data.py +++ b/judge/models/problem_data.py @@ -33,6 +33,7 @@ CHECKERS = ( ('linecount', _('Line-by-line')), ('custom', _('Custom checker (PY)')), ('customval', _('Custom validator (CPP)')), + ('interact', _('Interactive')), ) @@ -61,6 +62,13 @@ class ProblemData(models.Model): blank=True, upload_to=problem_directory_file, 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 def __init__(self, *args, **kwargs): diff --git a/judge/utils/problem_data.py b/judge/utils/problem_data.py index b0a187b..653efbd 100644 --- a/judge/utils/problem_data.py +++ b/judge/utils/problem_data.py @@ -210,9 +210,16 @@ class ProblemDataCompiler(object): if self.data.output_prefix is not None: init['output_prefix_length'] = self.data.output_prefix 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: self.data.checker_args = '' + return init def compile(self): diff --git a/judge/views/problem_data.py b/judge/views/problem_data.py index 3908b8f..eb38b84 100644 --- a/judge/views/problem_data.py +++ b/judge/views/problem_data.py @@ -61,7 +61,7 @@ class ProblemDataForm(ModelForm): class Meta: model = ProblemData - fields = ['zipfile', 'checker', 'checker_args', 'custom_checker', 'custom_validator'] + fields = ['zipfile', 'checker', 'checker_args', 'custom_checker', 'custom_validator', 'interactive_judge'] widgets = { 'zipfile': FineUploadFileInput, 'checker_args': HiddenInput, diff --git a/templates/about/custom-checker-sample.html b/templates/about/custom-checker-sample.html index ad353c4..713a894 100644 --- a/templates/about/custom-checker-sample.html +++ b/templates/about/custom-checker-sample.html @@ -140,6 +140,62 @@ int main(int argc, char** argv) { cout << "a + b = " << a + b << " != " << n << endl; return 1; // WA } +} + +

3. Interactive (CPP)

+
+

+ Để 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 input_file tương ứng file input. +

+

+ Để 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): +

+main.exe [input_file]
+ hoặc thay bằng ./main trên Linux/MacOS. +

+

Return:

+

+ Chương trình trả về giá trị: +

+

+ +

Ví dụ:

+

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.

+
+#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
+    }
 }
         
diff --git a/templates/problem/data.html b/templates/problem/data.html index f358d3c..5f28808 100644 --- a/templates/problem/data.html +++ b/templates/problem/data.html @@ -132,12 +132,15 @@ } (function toggle_custom() { - let $custom_checker = $('#id_problem-data-custom_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_validator = $validator.parent().parent() + $tr_interactive = $interactive.parent().parent() $td = $checker.parent(); var $sample = $("",{ @@ -150,7 +153,9 @@ $checker.change(function () { $tr_checker.toggle($checker.val() == 'custom').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(); })();