Add IOI signature to UI
This commit is contained in:
parent
220a7e7237
commit
64495be799
9 changed files with 469 additions and 272 deletions
48
judge/migrations/0156_auto_20230801_0107.py
Normal file
48
judge/migrations/0156_auto_20230801_0107.py
Normal 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",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
22
judge/migrations/0157_auto_20230801_1145.py
Normal file
22
judge/migrations/0157_auto_20230801_1145.py
Normal 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",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -123,6 +123,27 @@ class ProblemData(models.Model):
|
||||||
help_text=_("Support output-only problem"),
|
help_text=_("Support output-only problem"),
|
||||||
null=True,
|
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
|
__original_zipfile = None
|
||||||
|
|
||||||
|
@ -169,6 +190,18 @@ class ProblemData(models.Model):
|
||||||
self.custom_validator.name = problem_directory_file_helper(
|
self.custom_validator.name = problem_directory_file_helper(
|
||||||
new, self.custom_validator.name
|
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()
|
self.save()
|
||||||
|
|
||||||
_update_code.alters_data = True
|
_update_code.alters_data = True
|
||||||
|
|
|
@ -233,9 +233,7 @@ class ProblemDataCompiler(object):
|
||||||
if self.data.checker == "interact":
|
if self.data.checker == "interact":
|
||||||
interactor_path = split_path_first(self.data.interactive_judge.name)
|
interactor_path = split_path_first(self.data.interactive_judge.name)
|
||||||
if len(interactor_path) != 2:
|
if len(interactor_path) != 2:
|
||||||
raise ProblemDataError(
|
raise ProblemDataError(_("Invalid interactor judge"))
|
||||||
_("How did you corrupt the interactor path?")
|
|
||||||
)
|
|
||||||
init["interactive"] = {
|
init["interactive"] = {
|
||||||
"files": interactor_path[1],
|
"files": interactor_path[1],
|
||||||
"feedback": True,
|
"feedback": True,
|
||||||
|
@ -256,7 +254,18 @@ class ProblemDataCompiler(object):
|
||||||
init["file_io"]["output"] = self.data.fileio_output
|
init["file_io"]["output"] = self.data.fileio_output
|
||||||
if self.data.output_only:
|
if self.data.output_only:
|
||||||
init["output_only"] = True
|
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
|
return init
|
||||||
|
|
||||||
def compile(self):
|
def compile(self):
|
||||||
|
|
|
@ -13,10 +13,242 @@ def about(request):
|
||||||
|
|
||||||
|
|
||||||
def custom_checker_sample(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 <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 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 <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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## 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 <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(
|
return render(
|
||||||
request,
|
request,
|
||||||
"about/custom-checker-sample.html",
|
"about/custom-checker-sample.html",
|
||||||
{
|
{
|
||||||
"title": _("Custom Checker Sample"),
|
"title": _("Custom Checker Sample"),
|
||||||
|
"content": content,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -93,6 +93,9 @@ class ProblemDataForm(ModelForm):
|
||||||
"fileio_input",
|
"fileio_input",
|
||||||
"fileio_output",
|
"fileio_output",
|
||||||
"output_only",
|
"output_only",
|
||||||
|
"use_ioi_signature",
|
||||||
|
"signature_handler",
|
||||||
|
"signature_header",
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
"zipfile": FineUploadFileInput,
|
"zipfile": FineUploadFileInput,
|
||||||
|
@ -103,6 +106,7 @@ class ProblemDataForm(ModelForm):
|
||||||
"fileio_input": TextInput,
|
"fileio_input": TextInput,
|
||||||
"fileio_output": TextInput,
|
"fileio_output": TextInput,
|
||||||
"output_only": CheckboxInput,
|
"output_only": CheckboxInput,
|
||||||
|
"use_ioi_signature": CheckboxInput,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: lqdoj2\n"
|
"Project-Id-Version: lqdoj2\n"
|
||||||
"Report-Msgid-Bugs-To: \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"
|
"PO-Revision-Date: 2021-07-20 03:44\n"
|
||||||
"Last-Translator: Icyene\n"
|
"Last-Translator: Icyene\n"
|
||||||
"Language-Team: Vietnamese\n"
|
"Language-Team: Vietnamese\n"
|
||||||
|
@ -210,7 +210,7 @@ msgid "Taxonomy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: judge/admin/problem.py:215 judge/admin/problem.py:438
|
#: 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/problem/list.html:22 templates/problem/list.html:48
|
||||||
#: templates/user/base-users-table.html:10 templates/user/user-about.html:36
|
#: 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
|
#: 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"
|
msgid "generator file"
|
||||||
msgstr "file tạo test"
|
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"
|
msgid "output prefix length"
|
||||||
msgstr "độ dài hiển thị output"
|
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"
|
msgid "output limit length"
|
||||||
msgstr "giới hạn hiển thị output"
|
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"
|
msgid "init.yml generation feedback"
|
||||||
msgstr "phản hồi của quá trình tạo file init.yml"
|
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"
|
msgid "checker"
|
||||||
msgstr "trình chấm"
|
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"
|
msgid "checker arguments"
|
||||||
msgstr "các biến trong trình chấm"
|
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"
|
msgid "checker arguments as a JSON object"
|
||||||
msgstr "các biến trong trình chấm theo dạng JSON"
|
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"
|
msgid "interactive judge"
|
||||||
msgstr ""
|
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"
|
msgid "input file name"
|
||||||
msgstr "tên file input"
|
msgstr "tên file input"
|
||||||
|
|
||||||
|
@ -1827,7 +1827,7 @@ msgstr "tên file input"
|
||||||
msgid "Leave empty for stdin"
|
msgid "Leave empty for stdin"
|
||||||
msgstr "Để trống nếu nhập từ bàn phím"
|
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"
|
msgid "output file name"
|
||||||
msgstr "tên file output"
|
msgstr "tên file output"
|
||||||
|
|
||||||
|
@ -1843,39 +1843,55 @@ msgstr "Output-only?"
|
||||||
msgid "Support output-only problem"
|
msgid "Support output-only problem"
|
||||||
msgstr "Dùng cho các bài output-only (nộp bằng file zip)"
|
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"
|
msgid "problem data set"
|
||||||
msgstr "tập hợp dữ liệu bài"
|
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"
|
msgid "case position"
|
||||||
msgstr "vị trí test"
|
msgstr "vị trí test"
|
||||||
|
|
||||||
#: judge/models/problem_data.py:187
|
#: judge/models/problem_data.py:220
|
||||||
msgid "case type"
|
msgid "case type"
|
||||||
msgstr "loại test"
|
msgstr "loại test"
|
||||||
|
|
||||||
#: judge/models/problem_data.py:189
|
#: judge/models/problem_data.py:222
|
||||||
msgid "Normal case"
|
msgid "Normal case"
|
||||||
msgstr "Test bình thường"
|
msgstr "Test bình thường"
|
||||||
|
|
||||||
#: judge/models/problem_data.py:190
|
#: judge/models/problem_data.py:223
|
||||||
msgid "Batch start"
|
msgid "Batch start"
|
||||||
msgstr "Bắt đầu nhóm"
|
msgstr "Bắt đầu nhóm"
|
||||||
|
|
||||||
#: judge/models/problem_data.py:191
|
#: judge/models/problem_data.py:224
|
||||||
msgid "Batch end"
|
msgid "Batch end"
|
||||||
msgstr "Kết thúc nhóm"
|
msgstr "Kết thúc nhóm"
|
||||||
|
|
||||||
#: judge/models/problem_data.py:201
|
#: judge/models/problem_data.py:234
|
||||||
msgid "generator arguments"
|
msgid "generator arguments"
|
||||||
msgstr "biến trong file sinh test"
|
msgstr "biến trong file sinh test"
|
||||||
|
|
||||||
#: judge/models/problem_data.py:202
|
#: judge/models/problem_data.py:235
|
||||||
msgid "point value"
|
msgid "point value"
|
||||||
msgstr "điểm"
|
msgstr "điểm"
|
||||||
|
|
||||||
#: judge/models/problem_data.py:203
|
#: judge/models/problem_data.py:236
|
||||||
msgid "case is pretest?"
|
msgid "case is pretest?"
|
||||||
msgstr "test là pretest?"
|
msgstr "test là pretest?"
|
||||||
|
|
||||||
|
@ -2565,10 +2581,18 @@ msgid "How did you corrupt the generator path?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: judge/utils/problem_data.py:237
|
#: judge/utils/problem_data.py:237
|
||||||
|
msgid "Invalid interactor judge"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: judge/utils/problem_data.py:249
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "How did you corrupt the custom checker path?"
|
#| msgid "Invalid Return"
|
||||||
msgid "How did you corrupt the interactor path?"
|
msgid "Invalid signature handler"
|
||||||
msgstr "How did you corrupt the custom checker path?"
|
msgstr "Invalid Return"
|
||||||
|
|
||||||
|
#: judge/utils/problem_data.py:254
|
||||||
|
msgid "Invalid signature header"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: judge/utils/problems.py:115
|
#: judge/utils/problems.py:115
|
||||||
msgid "Wrong"
|
msgid "Wrong"
|
||||||
|
@ -2629,7 +2653,7 @@ msgstr "%h:%m"
|
||||||
msgid "About"
|
msgid "About"
|
||||||
msgstr "Giới thiệu"
|
msgstr "Giới thiệu"
|
||||||
|
|
||||||
#: judge/views/about.py:20
|
#: judge/views/about.py:251
|
||||||
msgid "Custom Checker Sample"
|
msgid "Custom Checker Sample"
|
||||||
msgstr "Hướng dẫn viết trình chấm"
|
msgstr "Hướng dẫn viết trình chấm"
|
||||||
|
|
||||||
|
@ -3104,27 +3128,27 @@ msgstr ""
|
||||||
msgid "Your zip file is invalid!"
|
msgid "Your zip file is invalid!"
|
||||||
msgstr "File Zip không hợp lệ!"
|
msgstr "File Zip không hợp lệ!"
|
||||||
|
|
||||||
#: judge/views/problem_data.py:165
|
#: judge/views/problem_data.py:169
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Comparing submissions for {0}"
|
msgid "Comparing submissions for {0}"
|
||||||
msgstr "So sánh các bài nộp cho {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
|
#, python-brace-format
|
||||||
msgid "Comparing submissions for <a href=\"{1}\">{0}</a>"
|
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>"
|
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
|
#, python-brace-format
|
||||||
msgid "Editing data for {0}"
|
msgid "Editing data for {0}"
|
||||||
msgstr "Chỉnh sửa dữ liệu cho {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
|
#, python-format
|
||||||
msgid "Editing data for %s"
|
msgid "Editing data for %s"
|
||||||
msgstr "Chỉnh sửa dữ liệu cho %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
|
#, python-format
|
||||||
msgid "Generated init.yml for %s"
|
msgid "Generated init.yml for %s"
|
||||||
msgstr "File init.yml cho %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"
|
msgid "All submissions"
|
||||||
msgstr "Tất cả bài nộp"
|
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"
|
msgid "All my submissions"
|
||||||
msgstr "Tất cả bài nộp của tôi"
|
msgstr "Tất cả bài nộp của tôi"
|
||||||
|
|
||||||
#: judge/views/submission.py:591
|
#: judge/views/submission.py:596
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "All submissions by %s"
|
msgid "All submissions by %s"
|
||||||
msgstr "Tất cả bài nộp của %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
|
#, python-brace-format
|
||||||
msgid "All submissions by <a href=\"{1}\">{0}</a>"
|
msgid "All submissions by <a href=\"{1}\">{0}</a>"
|
||||||
msgstr "Tất cả bài nộp của <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
|
#, fuzzy
|
||||||
#| msgid "All submissions"
|
#| msgid "All submissions"
|
||||||
msgid "All friend submissions"
|
msgid "All friend submissions"
|
||||||
msgstr "Tất cả bài nộp"
|
msgstr "Tất cả bài nộp"
|
||||||
|
|
||||||
#: judge/views/submission.py:647
|
#: judge/views/submission.py:652
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "All submissions for %s"
|
msgid "All submissions for %s"
|
||||||
msgstr "Tất cả bài nộp cho %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"
|
msgid "Must pass a problem"
|
||||||
msgstr "Phải làm được một bài"
|
msgstr "Phải làm được một bài"
|
||||||
|
|
||||||
#: judge/views/submission.py:733
|
#: judge/views/submission.py:738
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "My submissions for %(problem)s"
|
msgid "My submissions for %(problem)s"
|
||||||
msgstr "Bài nộp của tôi cho %(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
|
#, python-format
|
||||||
msgid "%(user)s's submissions for %(problem)s"
|
msgid "%(user)s's submissions for %(problem)s"
|
||||||
msgstr "Các bài nộp của %(user)s cho %(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"
|
msgid "Must pass a contest"
|
||||||
msgstr "Phải qua một kỳ thi"
|
msgstr "Phải qua một kỳ thi"
|
||||||
|
|
||||||
#: judge/views/submission.py:909
|
#: judge/views/submission.py:914
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"<a href=\"{1}\">{0}</a>'s submissions for <a href=\"{3}\">{2}</a> in <a href="
|
"<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 "
|
"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>"
|
"href=\"{5}\">{4}</a>"
|
||||||
|
|
||||||
#: judge/views/submission.py:921
|
#: judge/views/submission.py:926
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"<a href=\"{1}\">{0}</a>'s submissions for problem {2} in <a href=\"{4}\">{3}"
|
"<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}"
|
"Các bài nộp của <a href=\"{1}\">{0}</a> cho bài {2} trong <a href=\"{4}\">{3}"
|
||||||
"</a>"
|
"</a>"
|
||||||
|
|
||||||
#: judge/views/submission.py:1058
|
#: judge/views/submission.py:1063
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "You do not have the permission to rejudge submissions."
|
#| msgid "You do not have the permission to rejudge submissions."
|
||||||
msgid "You don't have permission to access."
|
msgid "You don't have permission to access."
|
||||||
|
@ -3711,7 +3735,7 @@ msgstr "Đăng nhập để vote"
|
||||||
msgid "edit %(edits)s"
|
msgid "edit %(edits)s"
|
||||||
msgstr "chỉnh sửa %(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"
|
msgid "edited"
|
||||||
msgstr "đã chỉnh sửa"
|
msgstr "đã chỉnh sửa"
|
||||||
|
|
||||||
|
@ -3735,8 +3759,8 @@ msgstr "Ẩn"
|
||||||
#| "\"javascript:comment_show_content(%(id)s)\">here</a> to view it."
|
#| "\"javascript:comment_show_content(%(id)s)\">here</a> to view it."
|
||||||
msgid ""
|
msgid ""
|
||||||
"This comment is hidden due to too much negative feedback. Click <a\n"
|
"This comment is hidden due to too much negative feedback. Click <a\n"
|
||||||
" href=\"javascript:comment_show_content(%(id)s)\">here</a> to "
|
" href=\"javascript:comment_show_content(%(id)s)\">here</a> "
|
||||||
"view it."
|
"to view it."
|
||||||
msgstr ""
|
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:"
|
"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ở."
|
"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."
|
msgid "Comments are disabled on this page."
|
||||||
msgstr "Bình luận bị tắt trong trang này."
|
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"
|
msgid "Replying to comment"
|
||||||
msgstr "Trả lời bình luận"
|
msgstr "Trả lời bình luận"
|
||||||
|
|
||||||
#: templates/comments/media-js.html:91
|
#: templates/comments/media-js.html:92
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "edit {edits}"
|
msgid "edit {edits}"
|
||||||
msgstr "chỉnh sửa {edits}"
|
msgstr "chỉnh sửa {edits}"
|
||||||
|
|
||||||
#: templates/comments/media-js.html:94
|
#: templates/comments/media-js.html:95
|
||||||
msgid "original"
|
msgid "original"
|
||||||
msgstr "original"
|
msgstr "original"
|
||||||
|
|
||||||
|
@ -4424,7 +4448,7 @@ msgid "There are no requests to approve."
|
||||||
msgstr "Không có đơn đăng ký."
|
msgstr "Không có đơn đăng ký."
|
||||||
|
|
||||||
#: templates/organization/requests/pending.html:24
|
#: templates/organization/requests/pending.html:24
|
||||||
#: templates/problem/data.html:520
|
#: templates/problem/data.html:536
|
||||||
msgid "Delete?"
|
msgid "Delete?"
|
||||||
msgstr "Xóa?"
|
msgstr "Xóa?"
|
||||||
|
|
||||||
|
@ -4465,32 +4489,32 @@ msgstr "Đuổi"
|
||||||
msgid "Enter a new code for the cloned problem:"
|
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:"
|
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"
|
msgid "Instruction"
|
||||||
msgstr "Hướng dẫn"
|
msgstr "Hướng dẫn"
|
||||||
|
|
||||||
#: templates/problem/data.html:469
|
#: templates/problem/data.html:485
|
||||||
msgid "View YAML"
|
msgid "View YAML"
|
||||||
msgstr "Xem YAML"
|
msgstr "Xem YAML"
|
||||||
|
|
||||||
#: templates/problem/data.html:486
|
#: templates/problem/data.html:502
|
||||||
msgid "Autofill testcases"
|
msgid "Autofill testcases"
|
||||||
msgstr "Tự động điền test"
|
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 "Problem type"
|
||||||
msgid_plural "Problem types"
|
msgid_plural "Problem types"
|
||||||
msgstr[0] "Dạng bài"
|
msgstr[0] "Dạng bài"
|
||||||
|
|
||||||
#: templates/problem/data.html:497
|
#: templates/problem/data.html:513
|
||||||
msgid "Fill testcases"
|
msgid "Fill testcases"
|
||||||
msgstr "Điền test"
|
msgstr "Điền test"
|
||||||
|
|
||||||
#: templates/problem/data.html:501
|
#: templates/problem/data.html:517
|
||||||
msgid "Batch start positions"
|
msgid "Batch start positions"
|
||||||
msgstr "Vị trí bắt đầu nhóm"
|
msgstr "Vị trí bắt đầu nhóm"
|
||||||
|
|
||||||
#: templates/problem/data.html:505
|
#: templates/problem/data.html:521
|
||||||
msgid ""
|
msgid ""
|
||||||
"Leave empty if not use batch. If you want to divide to three batches [1, 4], "
|
"Leave empty if not use batch. If you want to divide to three batches [1, 4], "
|
||||||
"[5, 8], [9, 10], enter: 1, 5, 9"
|
"[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, "
|
"Để 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"
|
"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!"
|
msgid "Apply!"
|
||||||
msgstr "Lưu!"
|
msgstr "Lưu!"
|
||||||
|
|
||||||
#: templates/problem/data.html:514
|
#: templates/problem/data.html:530
|
||||||
msgid "Type"
|
msgid "Type"
|
||||||
msgstr "Kiểu"
|
msgstr "Kiểu"
|
||||||
|
|
||||||
#: templates/problem/data.html:515
|
#: templates/problem/data.html:531
|
||||||
msgid "Input file"
|
msgid "Input file"
|
||||||
msgstr "File Input"
|
msgstr "File Input"
|
||||||
|
|
||||||
#: templates/problem/data.html:516
|
#: templates/problem/data.html:532
|
||||||
msgid "Output file"
|
msgid "Output file"
|
||||||
msgstr "File Output"
|
msgstr "File Output"
|
||||||
|
|
||||||
#: templates/problem/data.html:518
|
#: templates/problem/data.html:534
|
||||||
msgid "Pretest?"
|
msgid "Pretest?"
|
||||||
msgstr "Pretest?"
|
msgstr "Pretest?"
|
||||||
|
|
||||||
#: templates/problem/data.html:561
|
#: templates/problem/data.html:577
|
||||||
msgid "Add new case"
|
msgid "Add new case"
|
||||||
msgstr "Thêm test mới"
|
msgstr "Thêm test mới"
|
||||||
|
|
||||||
|
@ -5733,6 +5757,11 @@ msgstr "Thông tin"
|
||||||
msgid "Check all"
|
msgid "Check all"
|
||||||
msgstr "Chọn tất cả"
|
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"
|
#~ msgid "replies"
|
||||||
#~ msgstr "phản hồi"
|
#~ msgstr "phản hồi"
|
||||||
|
|
||||||
|
|
|
@ -1,208 +1,12 @@
|
||||||
{% extends "common-content.html" %}
|
{% extends "common-content.html" %}
|
||||||
{% block description %}
|
{% block content_media %}
|
||||||
<style>
|
<style>
|
||||||
article {
|
#content-left {
|
||||||
padding: 2.5em 3.5em;
|
margin-left: 10%;
|
||||||
font-size: 1.1em;
|
width: 80%;
|
||||||
}
|
|
||||||
li {
|
|
||||||
padding: 0.2em;
|
|
||||||
}
|
|
||||||
#content-right {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<article id="py">
|
{% endblock %}
|
||||||
<h2>1. Custom checker (PY)</h2>
|
{% block description %}
|
||||||
<hr>
|
{{ content|markdown|str|safe}}
|
||||||
<p>
|
{% endblock %}
|
||||||
Đâ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 %}
|
|
||||||
|
|
|
@ -136,13 +136,18 @@
|
||||||
(function toggle_custom() {
|
(function toggle_custom() {
|
||||||
let $checker = $('#id_problem-data-checker')
|
let $checker = $('#id_problem-data-checker')
|
||||||
|
|
||||||
let $custom_checker = $('#id_problem-data-custom_checker')
|
let $custom_checker = $('#id_problem-data-custom_checker');
|
||||||
let $validator = $('#id_problem-data-custom_validator')
|
let $validator = $('#id_problem-data-custom_validator');
|
||||||
let $interactive = $('#id_problem-data-interactive_judge')
|
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_checker = $custom_checker.parent().parent();
|
||||||
$tr_validator = $validator.parent().parent()
|
$tr_validator = $validator.parent().parent();
|
||||||
$tr_interactive = $interactive.parent().parent()
|
$tr_interactive = $interactive.parent().parent();
|
||||||
|
$tr_sig_handler = $sig_handler.parent().parent();
|
||||||
|
$tr_sig_header = $sig_header.parent().parent();
|
||||||
|
|
||||||
$td = $checker.parent();
|
$td = $checker.parent();
|
||||||
var $sample = $("<a/>",{
|
var $sample = $("<a/>",{
|
||||||
|
@ -152,13 +157,24 @@
|
||||||
href: "{{url('custom_checker_sample')}}"
|
href: "{{url('custom_checker_sample')}}"
|
||||||
}).appendTo($td);
|
}).appendTo($td);
|
||||||
|
|
||||||
|
$("<a/>",{
|
||||||
|
text: " ({{_('Instruction')}})",
|
||||||
|
target: "_blank",
|
||||||
|
href: "{{url('custom_checker_sample')}}"
|
||||||
|
}).appendTo($ioi_signature.parent());
|
||||||
|
|
||||||
$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' || $checker.val() == 'testlib').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();
|
$sample.toggle(['custom', 'customval', 'interact'].includes($checker.val())).change();
|
||||||
}).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'));
|
checker_precision($('#id_problem-data-checker'));
|
||||||
|
|
Loading…
Add table
Reference in a new issue