Add IOI signature to UI

This commit is contained in:
cuom1999 2023-08-01 12:26:15 +07:00
parent 220a7e7237
commit 64495be799
9 changed files with 469 additions and 272 deletions

View file

@ -0,0 +1,48 @@
# Generated by Django 3.2.18 on 2023-07-31 18:07
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", "0155_output_only"),
]
operations = [
migrations.AddField(
model_name="problemdata",
name="signature_handler",
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="signature handler",
),
),
migrations.AddField(
model_name="problemdata",
name="signature_header",
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=["h"]
)
],
verbose_name="signature header",
),
),
]

View file

@ -0,0 +1,22 @@
# Generated by Django 3.2.18 on 2023-08-01 04:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("judge", "0156_auto_20230801_0107"),
]
operations = [
migrations.AddField(
model_name="problemdata",
name="use_ioi_signature",
field=models.BooleanField(
help_text="Use IOI Signature",
null=True,
verbose_name="is IOI signature",
),
),
]

View file

@ -123,6 +123,27 @@ class ProblemData(models.Model):
help_text=_("Support output-only problem"),
null=True,
)
use_ioi_signature = models.BooleanField(
verbose_name=_("is IOI signature"),
help_text=_("Use IOI Signature"),
null=True,
)
signature_handler = models.FileField(
verbose_name=_("signature handler"),
storage=problem_data_storage,
null=True,
blank=True,
upload_to=problem_directory_file,
validators=[FileExtensionValidator(allowed_extensions=["cpp"])],
)
signature_header = models.FileField(
verbose_name=_("signature header"),
storage=problem_data_storage,
null=True,
blank=True,
upload_to=problem_directory_file,
validators=[FileExtensionValidator(allowed_extensions=["h"])],
)
__original_zipfile = None
@ -169,6 +190,18 @@ class ProblemData(models.Model):
self.custom_validator.name = problem_directory_file_helper(
new, self.custom_validator.name
)
if self.interactive_judge:
self.interactive_judge.name = problem_directory_file_helper(
new, self.interactive_judge.name
)
if self.signature_header:
self.signature_header.name = problem_directory_file_helper(
new, self.signature_header.name
)
if self.signature_handler:
self.signature_handler.name = problem_directory_file_helper(
new, self.signature_handler.name
)
self.save()
_update_code.alters_data = True

View file

@ -233,9 +233,7 @@ class ProblemDataCompiler(object):
if self.data.checker == "interact":
interactor_path = split_path_first(self.data.interactive_judge.name)
if len(interactor_path) != 2:
raise ProblemDataError(
_("How did you corrupt the interactor path?")
)
raise ProblemDataError(_("Invalid interactor judge"))
init["interactive"] = {
"files": interactor_path[1],
"feedback": True,
@ -256,7 +254,18 @@ class ProblemDataCompiler(object):
init["file_io"]["output"] = self.data.fileio_output
if self.data.output_only:
init["output_only"] = True
if self.data.use_ioi_signature:
handler_path = split_path_first(self.data.signature_handler.name)
if len(handler_path) != 2:
raise ProblemDataError(_("Invalid signature handler"))
header_path = split_path_first(self.data.signature_header.name)
if len(header_path) != 2:
raise ProblemDataError(_("Invalid signature header"))
init["signature_grader"] = {
"entry": handler_path[1],
"header": header_path[1],
}
return init
def compile(self):

View file

@ -13,10 +13,242 @@ def about(request):
def custom_checker_sample(request):
content = """
1. Trình chấm tự viết (PY)
2. Trình chấm tự viết (CPP)
3. Interactive (CPP)
4. Dùng hàm như IOI (CPP)
---
##1. Trình chấm tự viết (PY)
Đây checker mặc định của website, cho phép người dùng cập nhật được nhiều thông tin nhất (chi tiết xem bên dưới). Chúng ta cần hoàn thành hàm `check` dưới đây:
```py
def check(process_output, judge_output, **kwargs):
# return True/False
```
Trong đó, `**kwargs` thể chứa các biến sau:
- `process_output`: output
- `judge_output`: đáp án
- `submission_source`: Code bài nộp
- `judge_input`: input
- `point_value`: điểm của test đang chấm
- `case_position`: thứ tự của test
- `submission_language`: ngôn ngữ của bài nộp
- `execution_time`: thời gian chạy
**Return**:
- Cách 1: Trả về True/False
- Cách 2: Trả về một object `CheckerResult` thể được gọi như sau `CheckerResult(case_passed_bool, points_awarded, feedback='')`
** dụ:**
Dưới đây dụ cho bài toán: Input gồm 1 số nguyên n. In ra 2 số nguyên a, b sao cho a + b = n.
```py
from dmoj.result import CheckerResult
def wa(feedback):
return CheckerResult(False, 0, feedback)
def check(process_output, judge_output, judge_input, **kwargs):
# process the input
input_arr = judge_input.split()
assert(len(input_arr) == 1)
n = int(input_arr[0])
# process the contestant's output
output_arr = process_output.split()
if (len(output_arr) != 2):
return wa('Wrong output format')
try:
a, b = int(output_arr[0]), int(output_arr[1])
except:
return wa('Wrong output format')
if (n == a + b):
return True
return wa('a + b != n')
```
## 2. Trình chấm tự viết (CPP)
Để sử dụng chức năng này, cần viết một chương trình C++ pass vào 3 arguments theo thứ tự `input_file`, `output_file`, `ans_file` tương ứng với các file input, output, đáp án.
Để test chương trình trên máy tính, thể dùng lệnh như sau (Windows):
```bash
main.exe [input_file] [output_file] [ans_file]
```
hoặc thay bằng `./main` trên Linux/MacOS.
**Return:**
Chương trình trả về giá trị:
- 0 nếu AC (100% điểm)
- 1 nếu WA (0 điểm)
- 2 nếu điểm thành phần. Khi đó cần in ra stderr một số thực trong đoạn [0, 1] thể hiện cho tỷ lệ điểm. Nếu điểm < 1 thì hiển thị WA, điểm = 1 thì hiển thị AC.
Những thông tin được viết ra stdout (bằng cout) sẽ được in ra màn hình cho người nộp bài(feedback)
** dụ:**
Chương trình sau dùng để chấm bài toán: Cho n một số nguyên dương. In ra hai số tự nhiên a, b sao cho a + b = n.
Nếu in ra a + b = n a, b >= 0 thì được 100% số điểm, nếu a + b = n nhưng một trong 2 số a, b âm thì được 50% số điểm.
```cpp
#include <bits/stdc++.h>
using namespace std;
int main(int argc, char** argv) {
ifstream inp(argv[1]);
ifstream out(argv[2]);
ifstream ans(argv[3]);
int n, a, b, c, d;
inp >> n;
out >> a >> b;
ans >> c >> d;
if (a + b == c + d) {
cout << a << " + " << b << " = " << c << " + " << d << endl;
if (a >= 0 && b >= 0) {
return 0; // AC
}
else {
cerr << 0.5;
return 2; // PARTIAL
}
}
else {
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 2 arguments `input_file` `answer_file` tương ứng file input đáp án (nếu cần thiết).
Để test chương trình trên máy tính với cách thí sinh, thể dùng lệnh như sau (Windows):
```bash
main.exe [input_file] [answer_file]
```
hoặc thay bằng `./main` trên Linux/MacOS.
**Return:**
Chương trình trả về giá trị:
- 0 nếu AC (100% điểm)
- 1 nếu WA (0 điểm)
- 2 nếu điểm thành phần. Khi đó cần in ra stderr một số thực trong đoạn [0, 1] thể hiện cho tỷ lệ điểm. Nếu điểm < 1 thì hiển thị WA, điểm = 1 thì hiển thị AC.
Thông tin được in ra trong stderr (bằng cerr) sẽ feedback hiển thị cho người dùng.
** 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ố mật n (n chứa trong file input). Mỗi lần họ được hỏi một số x, chương trình sẽ trả về "SMALLER", "BIGGER" hoặc "HOLA" dựa trên giá trị của n x. Cần tìm ra n sau không quá 31 câu hỏi.
```cpp
#include <bits/stdc++.h>
using namespace std;
void quit(string reason) {
cerr << reason << endl;
exit(1);
}
void read(long long& guess) {
if (!(cin >> guess)) exit(1); // Nếu không dòng này, chương trình sẽ chờ 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++;
}
cerr << "Number of used guesses: " << guesses << endl;
if (guesses <= 31)
return 0; // AC
else {
cerr << "Used too many guesses" << endl;
return 1; // WA
}
}
```
## 4. IOI Signature (CPP)
Đây chức năng để sử dụng hàm như trong IOI. Thí sinh được cho một định nghĩa hàm cần cài đặt hàm đó trả về giá trị đúng.
Để sử dụng chức năng này, cần viết 2 chương trình:
- Header: Đây file định nghĩa hàm (đuôi phải `.h`)
- Handler: Đây chương trình xử input xuất ra output dựa trên hàm (đuôi phải `.cpp`)
** dụ:**
Cho bài toán: nhập vào số n. Viết hàm `solve(int n)` trả về `n * 2`. Giả sử input multitest dạng:
- Dòng đầu chứa `t` số test
- Mỗi dòng chứa một số nguyên `n`
**Header (header.h):**
```cpp
#ifndef _HEADER_INCLUDED
#define _HEADER_INCLUDED
long long solve(long long n);
#endif
```
**Handler (handler.cpp):**
```cpp
#include <bits/stdc++.h>
#include "header.h"
using namespace std;
int main() {
int t;
cin >> t;
for (int z = 1; z <= t; z++) {
long long n;
cin >> n;
cout << solve(n) << "\\n";
}
return 0;
}
```
**Bài nộp thí sinh:**
```cpp
int solve(int n) {
return n * 2;
}
```
"""
return render(
request,
"about/custom-checker-sample.html",
{
"title": _("Custom Checker Sample"),
"content": content,
},
)

View file

@ -93,6 +93,9 @@ class ProblemDataForm(ModelForm):
"fileio_input",
"fileio_output",
"output_only",
"use_ioi_signature",
"signature_handler",
"signature_header",
]
widgets = {
"zipfile": FineUploadFileInput,
@ -103,6 +106,7 @@ class ProblemDataForm(ModelForm):
"fileio_input": TextInput,
"fileio_output": TextInput,
"output_only": CheckboxInput,
"use_ioi_signature": CheckboxInput,
}

View file

@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: lqdoj2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-07-26 22:55+0700\n"
"POT-Creation-Date: 2023-08-01 12:22+0700\n"
"PO-Revision-Date: 2021-07-20 03:44\n"
"Last-Translator: Icyene\n"
"Language-Team: Vietnamese\n"
@ -210,7 +210,7 @@ msgid "Taxonomy"
msgstr ""
#: judge/admin/problem.py:215 judge/admin/problem.py:438
#: templates/contest/contest.html:101 templates/problem/data.html:517
#: templates/contest/contest.html:101 templates/problem/data.html:533
#: templates/problem/list.html:22 templates/problem/list.html:48
#: templates/user/base-users-table.html:10 templates/user/user-about.html:36
#: templates/user/user-about.html:52 templates/user/user-problems.html:58
@ -1783,11 +1783,11 @@ msgstr "file zip chứa test"
msgid "generator file"
msgstr "file tạo test"
#: judge/models/problem_data.py:69 judge/models/problem_data.py:205
#: judge/models/problem_data.py:69 judge/models/problem_data.py:238
msgid "output prefix length"
msgstr "độ dài hiển thị output"
#: judge/models/problem_data.py:72 judge/models/problem_data.py:208
#: judge/models/problem_data.py:72 judge/models/problem_data.py:241
msgid "output limit length"
msgstr "giới hạn hiển thị output"
@ -1795,15 +1795,15 @@ msgstr "giới hạn hiển thị output"
msgid "init.yml generation feedback"
msgstr "phản hồi của quá trình tạo file init.yml"
#: judge/models/problem_data.py:78 judge/models/problem_data.py:211
#: judge/models/problem_data.py:78 judge/models/problem_data.py:244
msgid "checker"
msgstr "trình chấm"
#: judge/models/problem_data.py:81 judge/models/problem_data.py:214
#: judge/models/problem_data.py:81 judge/models/problem_data.py:247
msgid "checker arguments"
msgstr "các biến trong trình chấm"
#: judge/models/problem_data.py:83 judge/models/problem_data.py:216
#: judge/models/problem_data.py:83 judge/models/problem_data.py:249
msgid "checker arguments as a JSON object"
msgstr "các biến trong trình chấm theo dạng JSON"
@ -1819,7 +1819,7 @@ msgstr "file trình chấm"
msgid "interactive judge"
msgstr ""
#: judge/models/problem_data.py:110 judge/models/problem_data.py:196
#: judge/models/problem_data.py:110 judge/models/problem_data.py:229
msgid "input file name"
msgstr "tên file input"
@ -1827,7 +1827,7 @@ msgstr "tên file input"
msgid "Leave empty for stdin"
msgstr "Để trống nếu nhập từ bàn phím"
#: judge/models/problem_data.py:116 judge/models/problem_data.py:199
#: judge/models/problem_data.py:116 judge/models/problem_data.py:232
msgid "output file name"
msgstr "tên file output"
@ -1843,39 +1843,55 @@ msgstr "Output-only?"
msgid "Support output-only problem"
msgstr "Dùng cho các bài output-only (nộp bằng file zip)"
#: judge/models/problem_data.py:180
#: judge/models/problem_data.py:127
msgid "is IOI signature"
msgstr "Nộp bài bằng hàm?"
#: judge/models/problem_data.py:128
msgid "Use IOI Signature"
msgstr "Nộp bài bằng hàm như IOI"
#: judge/models/problem_data.py:132
msgid "signature handler"
msgstr "File xử lý hàm"
#: judge/models/problem_data.py:140
msgid "signature header"
msgstr "File định nghĩa hàm"
#: judge/models/problem_data.py:213
msgid "problem data set"
msgstr "tập hợp dữ liệu bài"
#: judge/models/problem_data.py:184
#: judge/models/problem_data.py:217
msgid "case position"
msgstr "vị trí test"
#: judge/models/problem_data.py:187
#: judge/models/problem_data.py:220
msgid "case type"
msgstr "loại test"
#: judge/models/problem_data.py:189
#: judge/models/problem_data.py:222
msgid "Normal case"
msgstr "Test bình thường"
#: judge/models/problem_data.py:190
#: judge/models/problem_data.py:223
msgid "Batch start"
msgstr "Bắt đầu nhóm"
#: judge/models/problem_data.py:191
#: judge/models/problem_data.py:224
msgid "Batch end"
msgstr "Kết thúc nhóm"
#: judge/models/problem_data.py:201
#: judge/models/problem_data.py:234
msgid "generator arguments"
msgstr "biến trong file sinh test"
#: judge/models/problem_data.py:202
#: judge/models/problem_data.py:235
msgid "point value"
msgstr "điểm"
#: judge/models/problem_data.py:203
#: judge/models/problem_data.py:236
msgid "case is pretest?"
msgstr "test là pretest?"
@ -2565,10 +2581,18 @@ msgid "How did you corrupt the generator path?"
msgstr ""
#: judge/utils/problem_data.py:237
msgid "Invalid interactor judge"
msgstr ""
#: judge/utils/problem_data.py:249
#, fuzzy
#| msgid "How did you corrupt the custom checker path?"
msgid "How did you corrupt the interactor path?"
msgstr "How did you corrupt the custom checker path?"
#| msgid "Invalid Return"
msgid "Invalid signature handler"
msgstr "Invalid Return"
#: judge/utils/problem_data.py:254
msgid "Invalid signature header"
msgstr ""
#: judge/utils/problems.py:115
msgid "Wrong"
@ -2629,7 +2653,7 @@ msgstr "%h:%m"
msgid "About"
msgstr "Giới thiệu"
#: judge/views/about.py:20
#: judge/views/about.py:251
msgid "Custom Checker Sample"
msgstr "Hướng dẫn viết trình chấm"
@ -3104,27 +3128,27 @@ msgstr ""
msgid "Your zip file is invalid!"
msgstr "File Zip không hợp lệ!"
#: judge/views/problem_data.py:165
#: judge/views/problem_data.py:169
#, python-brace-format
msgid "Comparing submissions for {0}"
msgstr "So sánh các bài nộp cho {0}"
#: judge/views/problem_data.py:169
#: judge/views/problem_data.py:173
#, python-brace-format
msgid "Comparing submissions for <a href=\"{1}\">{0}</a>"
msgstr "So sánh các bài nộp cho <a href=\"{1}\">{0}</a>"
#: judge/views/problem_data.py:206
#: judge/views/problem_data.py:210
#, python-brace-format
msgid "Editing data for {0}"
msgstr "Chỉnh sửa dữ liệu cho {0}"
#: judge/views/problem_data.py:210
#: judge/views/problem_data.py:214
#, python-format
msgid "Editing data for %s"
msgstr "Chỉnh sửa dữ liệu cho %s"
#: judge/views/problem_data.py:340 judge/views/problem_data.py:342
#: judge/views/problem_data.py:344 judge/views/problem_data.py:346
#, python-format
msgid "Generated init.yml for %s"
msgstr "File init.yml cho %s"
@ -3242,50 +3266,50 @@ msgstr "Bài nộp của %(user)s cho bài %(problem)s"
msgid "All submissions"
msgstr "Tất cả bài nộp"
#: judge/views/submission.py:590 judge/views/submission.py:595
#: judge/views/submission.py:595 judge/views/submission.py:600
msgid "All my submissions"
msgstr "Tất cả bài nộp của tôi"
#: judge/views/submission.py:591
#: judge/views/submission.py:596
#, python-format
msgid "All submissions by %s"
msgstr "Tất cả bài nộp của %s"
#: judge/views/submission.py:597
#: judge/views/submission.py:602
#, python-brace-format
msgid "All submissions by <a href=\"{1}\">{0}</a>"
msgstr "Tất cả bài nộp của <a href=\"{1}\">{0}</a>"
#: judge/views/submission.py:618
#: judge/views/submission.py:623
#, fuzzy
#| msgid "All submissions"
msgid "All friend submissions"
msgstr "Tất cả bài nộp"
#: judge/views/submission.py:647
#: judge/views/submission.py:652
#, python-format
msgid "All submissions for %s"
msgstr "Tất cả bài nộp cho %s"
#: judge/views/submission.py:675
#: judge/views/submission.py:680
msgid "Must pass a problem"
msgstr "Phải làm được một bài"
#: judge/views/submission.py:733
#: judge/views/submission.py:738
#, python-format
msgid "My submissions for %(problem)s"
msgstr "Bài nộp của tôi cho %(problem)s"
#: judge/views/submission.py:734
#: judge/views/submission.py:739
#, python-format
msgid "%(user)s's submissions for %(problem)s"
msgstr "Các bài nộp của %(user)s cho %(problem)s"
#: judge/views/submission.py:879
#: judge/views/submission.py:884
msgid "Must pass a contest"
msgstr "Phải qua một kỳ thi"
#: judge/views/submission.py:909
#: judge/views/submission.py:914
#, python-brace-format
msgid ""
"<a href=\"{1}\">{0}</a>'s submissions for <a href=\"{3}\">{2}</a> in <a href="
@ -3294,7 +3318,7 @@ msgstr ""
"Các bài nộp của <a href=\"{1}\">{0}</a> cho <a href=\"{3}\">{2}</a> trong <a "
"href=\"{5}\">{4}</a>"
#: judge/views/submission.py:921
#: judge/views/submission.py:926
#, python-brace-format
msgid ""
"<a href=\"{1}\">{0}</a>'s submissions for problem {2} in <a href=\"{4}\">{3}"
@ -3303,7 +3327,7 @@ msgstr ""
"Các bài nộp của <a href=\"{1}\">{0}</a> cho bài {2} trong <a href=\"{4}\">{3}"
"</a>"
#: judge/views/submission.py:1058
#: judge/views/submission.py:1063
#, fuzzy
#| msgid "You do not have the permission to rejudge submissions."
msgid "You don't have permission to access."
@ -3711,7 +3735,7 @@ msgstr "Đăng nhập để vote"
msgid "edit %(edits)s"
msgstr "chỉnh sửa %(edits)s"
#: templates/comments/content-list.html:46 templates/comments/media-js.html:96
#: templates/comments/content-list.html:46 templates/comments/media-js.html:97
msgid "edited"
msgstr "đã chỉnh sửa"
@ -3735,8 +3759,8 @@ msgstr "Ẩn"
#| "\"javascript:comment_show_content(%(id)s)\">here</a> to view it."
msgid ""
"This comment is hidden due to too much negative feedback. Click <a\n"
" href=\"javascript:comment_show_content(%(id)s)\">here</a> to "
"view it."
" href=\"javascript:comment_show_content(%(id)s)\">here</a> "
"to view it."
msgstr ""
"Bình luận bị ẩn vì nhiều phản hồi tiêu cực. Nhấp vào <a href=\"javascript:"
"comment_show_content(%(id)s)\">đây</a> để mở."
@ -3775,16 +3799,16 @@ msgstr "Không có bình luận nào."
msgid "Comments are disabled on this page."
msgstr "Bình luận bị tắt trong trang này."
#: templates/comments/media-js.html:39
#: templates/comments/media-js.html:40
msgid "Replying to comment"
msgstr "Trả lời bình luận"
#: templates/comments/media-js.html:91
#: templates/comments/media-js.html:92
#, python-brace-format
msgid "edit {edits}"
msgstr "chỉnh sửa {edits}"
#: templates/comments/media-js.html:94
#: templates/comments/media-js.html:95
msgid "original"
msgstr "original"
@ -4424,7 +4448,7 @@ msgid "There are no requests to approve."
msgstr "Không có đơn đăng ký."
#: templates/organization/requests/pending.html:24
#: templates/problem/data.html:520
#: templates/problem/data.html:536
msgid "Delete?"
msgstr "Xóa?"
@ -4465,32 +4489,32 @@ msgstr "Đuổi"
msgid "Enter a new code for the cloned problem:"
msgstr "Nhập mã bài mới cho bài tập được nhân bản:"
#: templates/problem/data.html:149
#: templates/problem/data.html:154 templates/problem/data.html:161
msgid "Instruction"
msgstr "Hướng dẫn"
#: templates/problem/data.html:469
#: templates/problem/data.html:485
msgid "View YAML"
msgstr "Xem YAML"
#: templates/problem/data.html:486
#: templates/problem/data.html:502
msgid "Autofill testcases"
msgstr "Tự động điền test"
#: templates/problem/data.html:490 templates/problem/problem.html:276
#: templates/problem/data.html:506 templates/problem/problem.html:276
msgid "Problem type"
msgid_plural "Problem types"
msgstr[0] "Dạng bài"
#: templates/problem/data.html:497
#: templates/problem/data.html:513
msgid "Fill testcases"
msgstr "Điền test"
#: templates/problem/data.html:501
#: templates/problem/data.html:517
msgid "Batch start positions"
msgstr "Vị trí bắt đầu nhóm"
#: templates/problem/data.html:505
#: templates/problem/data.html:521
msgid ""
"Leave empty if not use batch. If you want to divide to three batches [1, 4], "
"[5, 8], [9, 10], enter: 1, 5, 9"
@ -4498,27 +4522,27 @@ msgstr ""
"Để trống nếu không dùng nhóm. Nếu muốn chia test thành các nhóm [1, 4], [5, "
"8], [9, 10], nhập: 1, 5, 9"
#: templates/problem/data.html:509 templates/problem/data.html:560
#: templates/problem/data.html:525 templates/problem/data.html:576
msgid "Apply!"
msgstr "Lưu!"
#: templates/problem/data.html:514
#: templates/problem/data.html:530
msgid "Type"
msgstr "Kiểu"
#: templates/problem/data.html:515
#: templates/problem/data.html:531
msgid "Input file"
msgstr "File Input"
#: templates/problem/data.html:516
#: templates/problem/data.html:532
msgid "Output file"
msgstr "File Output"
#: templates/problem/data.html:518
#: templates/problem/data.html:534
msgid "Pretest?"
msgstr "Pretest?"
#: templates/problem/data.html:561
#: templates/problem/data.html:577
msgid "Add new case"
msgstr "Thêm test mới"
@ -5733,6 +5757,11 @@ msgstr "Thông tin"
msgid "Check all"
msgstr "Chọn tất cả"
#, fuzzy
#~| msgid "How did you corrupt the custom checker path?"
#~ msgid "How did you corrupt the interactor path?"
#~ msgstr "How did you corrupt the custom checker path?"
#~ msgid "replies"
#~ msgstr "phản hồi"

View file

@ -1,208 +1,12 @@
{% extends "common-content.html" %}
{% block description %}
{% block content_media %}
<style>
article {
padding: 2.5em 3.5em;
font-size: 1.1em;
}
li {
padding: 0.2em;
}
#content-right {
display: none;
#content-left {
margin-left: 10%;
width: 80%;
}
</style>
<article id="py">
<h2>1. Custom checker (PY)</h2>
<hr>
<p>
Đây là checker mặc định của website, cho phép người dùng cập nhật được nhiều thông tin nhất (chi tiết xem ở bên dưới). Chúng ta cần hoàn thành hàm check dưới đây:
</p>
{{
"""
def check(process_output, judge_output, **kwargs):
# return True/False
"""|highlight('py')}}
<p>
Trong đó, <code>**kwargs</code> có thể chứa các biến sau:
</p>
<ul>
<li><code>process_output:</code> output</li>
<li><code>judge_output:</code> đáp án</li>
<li><code>submission_source</code>: Code bài nộp</li>
<li><code>judge_input</code>: input</li>
<li><code>point_value:</code> điểm của test đang chấm</li>
<li><code>case_position:</code> thứ tự của test</li>
<li><code>submission_language:</code> ngôn ngữ của bài nộp</li>
<li><code>execution_time:</code> thời gian chạy</li>
</ul>
<h2>Return: </h2>
<ul>
<li>Cách 1: Trả về True/False</li>
<li>Cách 2: Trả về một object <code>CheckerResult</code> có thể được gọi như sau <pre class="code2">CheckerResult(case_passed_bool, points_awarded, feedback='')</pre></li>
</ul>
<h2>Ví dụ: </h2>
<p>Dưới đây là ví dụ cho bài toán: Input gồm 1 số nguyên n. In ra 2 số nguyên a, b sao cho a + b = n.
</p>
{{
"""
from dmoj.result import CheckerResult
def wa(feedback):
return CheckerResult(False, 0, feedback)
def check(process_output, judge_output, judge_input, **kwargs):
# process the input
input_arr = judge_input.split()
assert(len(input_arr) == 1)
n = int(input_arr[0])
# process the contestant's output
output_arr = process_output.split()
if (len(output_arr) != 2):
return wa('Wrong output format')
try:
a, b = int(output_arr[0]), int(output_arr[1])
except:
return wa('Wrong output format')
if (n == a + b):
return True
return wa('a + b != n')
"""| highlight('py')}}
</article>
<article id="cpp">
<h2>2. Custom validator (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 3 arguments theo thứ tự <code>input_file</code>, <code>output_file</code>, <code>ans_file</code> tương ứng với các file input, output, đáp án.
</p>
<p>
Để test chương trình trên máy tính, có thể dùng lệnh như sau (Windows):
<pre class="code2">
main.exe [input_file] [output_file] [ans_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>
<li> 2 nếu điểm thành phần. Khi đó cần in ra stderr một số thực trong đoạn [0, 1] thể hiện cho tỷ lệ điểm. Nếu điểm < 1 thì hiển thị WA, điểm = 1 thì hiển thị AC. </li>
</ul>
Những thông tin được viết ra stdout (bằng cout) sẽ được in ra màn hình cho người nộp bài(feedback)
</p>
<h2>Ví dụ: </h2>
<p>Chương trình sau dùng để chấm bài toán: Cho n là một số nguyên dương. In ra hai số tự nhiên a, b sao cho a + b = n. </p>
<p>Nếu in ra a + b = n và a, b >= 0 thì được 100% số điểm, nếu a + b = n nhưng một trong 2 số a, b âm thì được 50% số điểm. </p>
{{
"""
#include <bits/stdc++.h>
using namespace std;
int main(int argc, char** argv) {
ifstream inp(argv[1]);
ifstream out(argv[2]);
ifstream ans(argv[3]);
int n, a, b, c, d;
inp >> n;
out >> a >> b;
ans >> c >> d;
if (a + b == c + d) {
cout << a << \" + \" << b << \" = \" << c << \" + \" << d << endl;
if (a >= 0 && b >= 0) {
return 0; // AC
}
else {
cerr << 0.5;
return 2; // PARTIAL
}
}
else {
cout << \"a + b = \" << a + b << \" != \" << n << endl;
return 1; // WA
}
}
""" | highlight('cpp')}}
</article>
<article id="interactive">
<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 2 arguments <code>input_file</code> <code>answer_file</code> tương ứng file input và đáp án (nếu cần thiết).
</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] [answer_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>
<li> 2 nếu điểm thành phần. Khi đó cần in ra stderr một số thực trong đoạn [0, 1] thể hiện cho tỷ lệ điểm. Nếu điểm < 1 thì hiển thị WA, điểm = 1 thì hiển thị AC. </li>
</ul>
Thông tin được in ra trong stderr (bằng cerr) sẽ là feedback hiển thị cho người dùng.
</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>
{{
"""
#include <bits/stdc++.h>
using namespace std;
void quit(string reason) {
cerr << reason << endl;
exit(1);
}
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++;
}
cerr << \"Number of used guesses: \" << guesses << endl;
if (guesses <= 31)
return 0; // AC
else {
cerr << \"Used too many guesses\" << endl;
return 1; // WA
}
}
""" | highlight('cpp')}}
</article>
{% endblock %}
{% block description %}
{{ content|markdown|str|safe}}
{% endblock %}

View file

@ -136,13 +136,18 @@
(function toggle_custom() {
let $checker = $('#id_problem-data-checker')
let $custom_checker = $('#id_problem-data-custom_checker')
let $validator = $('#id_problem-data-custom_validator')
let $interactive = $('#id_problem-data-interactive_judge')
let $custom_checker = $('#id_problem-data-custom_checker');
let $validator = $('#id_problem-data-custom_validator');
let $interactive = $('#id_problem-data-interactive_judge');
let $sig_handler = $('#id_problem-data-signature_handler');
let $sig_header = $('#id_problem-data-signature_header');
let $ioi_signature = $("#id_problem-data-use_ioi_signature");
$tr_checker = $custom_checker.parent().parent();
$tr_validator = $validator.parent().parent()
$tr_interactive = $interactive.parent().parent()
$tr_validator = $validator.parent().parent();
$tr_interactive = $interactive.parent().parent();
$tr_sig_handler = $sig_handler.parent().parent();
$tr_sig_header = $sig_header.parent().parent();
$td = $checker.parent();
var $sample = $("<a/>",{
@ -152,13 +157,24 @@
href: "{{url('custom_checker_sample')}}"
}).appendTo($td);
$("<a/>",{
text: " ({{_('Instruction')}})",
target: "_blank",
href: "{{url('custom_checker_sample')}}"
}).appendTo($ioi_signature.parent());
$checker.change(function () {
$tr_checker.toggle($checker.val() == 'custom').change();
$tr_validator.toggle($checker.val() == 'customval' || $checker.val() == 'testlib').change();
$tr_interactive.toggle($checker.val() == 'interact').change();
$sample.toggle(['custom', 'customval', 'interact'].includes($checker.val())).change();
}).change();
$ioi_signature.change(function() {
$tr_interactive.toggle($ioi_signature.is(':checked')).change();
$tr_sig_header.toggle($ioi_signature.is(':checked')).change();
$tr_sig_handler.toggle($ioi_signature.is(':checked')).change();
}).change();
})();
checker_precision($('#id_problem-data-checker'));