From 64495be79934a9f746ee6801ae8158d74cfa6ee8 Mon Sep 17 00:00:00 2001
From: cuom1999
Date: Tue, 1 Aug 2023 12:26:15 +0700
Subject: [PATCH] Add IOI signature to UI
---
judge/migrations/0156_auto_20230801_0107.py | 48 ++++
judge/migrations/0157_auto_20230801_1145.py | 22 ++
judge/models/problem_data.py | 33 +++
judge/utils/problem_data.py | 15 +-
judge/views/about.py | 232 ++++++++++++++++++++
judge/views/problem_data.py | 4 +
locale/vi/LC_MESSAGES/django.po | 147 ++++++++-----
templates/about/custom-checker-sample.html | 212 +-----------------
templates/problem/data.html | 28 ++-
9 files changed, 469 insertions(+), 272 deletions(-)
create mode 100644 judge/migrations/0156_auto_20230801_0107.py
create mode 100644 judge/migrations/0157_auto_20230801_1145.py
diff --git a/judge/migrations/0156_auto_20230801_0107.py b/judge/migrations/0156_auto_20230801_0107.py
new file mode 100644
index 0000000..a5f2b9a
--- /dev/null
+++ b/judge/migrations/0156_auto_20230801_0107.py
@@ -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",
+ ),
+ ),
+ ]
diff --git a/judge/migrations/0157_auto_20230801_1145.py b/judge/migrations/0157_auto_20230801_1145.py
new file mode 100644
index 0000000..802c56c
--- /dev/null
+++ b/judge/migrations/0157_auto_20230801_1145.py
@@ -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",
+ ),
+ ),
+ ]
diff --git a/judge/models/problem_data.py b/judge/models/problem_data.py
index 38a214b..d61b528 100644
--- a/judge/models/problem_data.py
+++ b/judge/models/problem_data.py
@@ -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
diff --git a/judge/utils/problem_data.py b/judge/utils/problem_data.py
index 8be05ae..eb56229 100644
--- a/judge/utils/problem_data.py
+++ b/judge/utils/problem_data.py
@@ -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):
diff --git a/judge/views/about.py b/judge/views/about.py
index e503724..3f6d266 100644
--- a/judge/views/about.py
+++ b/judge/views/about.py
@@ -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 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:
+```py
+def check(process_output, judge_output, **kwargs):
+ # return True/False
+```
+
+Trong đó, `**kwargs` có 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` có thể được gọi như sau `CheckerResult(case_passed_bool, points_awarded, feedback='')`
+
+**Ví dụ:**
+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.
+
+```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, có 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)
+
+**Ví dụ:**
+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.
+
+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.
+
+```cpp
+#include
+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 và đáp án (nếu cần thiết).
+
+Để 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):
+
+```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ẽ là feedback hiển thị cho người dùng.
+
+**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.
+
+```cpp
+#include
+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
+ }
+}
+```
+## 4. IOI Signature (CPP)
+Đây là chức năng để sử dụng hàm như trong IOI. Thí sinh được cho một định nghĩa hàm và 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 là file định nghĩa hàm (đuôi phải là `.h`)
+- Handler: Đây là chương trình xử lý input và xuất ra output dựa trên hàm (đuôi phải là `.cpp`)
+
+**Ví 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 là multitest có dạng:
+- Dòng đầu chứa `t` là 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
+#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,
},
)
diff --git a/judge/views/problem_data.py b/judge/views/problem_data.py
index 587d10a..121d570 100644
--- a/judge/views/problem_data.py
+++ b/judge/views/problem_data.py
@@ -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,
}
diff --git a/locale/vi/LC_MESSAGES/django.po b/locale/vi/LC_MESSAGES/django.po
index 9fa8966..0ab0dd6 100644
--- a/locale/vi/LC_MESSAGES/django.po
+++ b/locale/vi/LC_MESSAGES/django.po
@@ -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 {0}"
msgstr "So sánh các bài nộp cho {0}"
-#: 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 {0}"
msgstr "Tất cả bài nộp của {0}"
-#: 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 ""
"{0}'s submissions for {2} in {0} cho {2} trong {4}"
-#: judge/views/submission.py:921
+#: judge/views/submission.py:926
#, python-brace-format
msgid ""
"{0}'s submissions for problem {2} in {3}"
@@ -3303,7 +3327,7 @@ msgstr ""
"Các bài nộp của {0} cho bài {2} trong {3}"
""
-#: 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 to view it."
msgid ""
"This comment is hidden due to too much negative feedback. Click here to "
-"view it."
+" href=\"javascript:comment_show_content(%(id)s)\">here "
+"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 đây để 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"
diff --git a/templates/about/custom-checker-sample.html b/templates/about/custom-checker-sample.html
index b6497df..26aae70 100644
--- a/templates/about/custom-checker-sample.html
+++ b/templates/about/custom-checker-sample.html
@@ -1,208 +1,12 @@
{% extends "common-content.html" %}
-{% block description %}
+{% block content_media %}
-
- 1. Custom checker (PY)
-
-
- Đâ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:
-
-
- {{
- """
- def check(process_output, judge_output, **kwargs):
- # return True/False
- """|highlight('py')}}
-
-
- Trong đó, **kwargs
có 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:
-
-
- Ví dụ:
- 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.
-
- {{
- """
- 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')}}
-
-
- 2. Custom validator (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, có thể dùng lệnh như sau (Windows):
-
-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)
-
-
- Ví dụ:
- 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.
- 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.
- {{
- """
- #include
- 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')}}
-
-
- 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 và đáp án (nếu cần thiết).
-
-
- Để 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] [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ẽ là feedback hiển thị cho người dùng.
-
-
- 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
- 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')}}
-
-{% endblock %}
\ No newline at end of file
+{% endblock %}
+{% block description %}
+ {{ content|markdown|str|safe}}
+{% endblock %}
diff --git a/templates/problem/data.html b/templates/problem/data.html
index 696cab8..0bc8f4c 100644
--- a/templates/problem/data.html
+++ b/templates/problem/data.html
@@ -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 = $("",{
@@ -152,13 +157,24 @@
href: "{{url('custom_checker_sample')}}"
}).appendTo($td);
+ $("",{
+ 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'));