Hướng dẫn checker
Hướng dẫn viết checker dùng testlib từ anh Phạm Văn Hạnh
- Thư viện sử dụng:
testlib_themis_cms.h
. - Link video hướng dẫn
- Link google docs
- Link các checker mẫu
1. Checker mặc định
Hệ thống có hỗ trợ các checker mặc định của DMOJ, các bạn có thể xem ở đây
2. 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_with_timeout
dưới đây:
from dmoj.result import CheckerResult
import threading
def check(*args, **kwargs):
result = None
def target():
nonlocal result
result = check_with_timeout(*args, **kwargs)
# Create a thread for the check function
function_thread = threading.Thread(target=target)
# Start the thread
function_thread.start()
# Wait for the thread to complete or time out
function_thread.join(timeout=10)
# Check if the thread is still alive (timed out)
if function_thread.is_alive():
return CheckerResult(False, 0, "Checker Error. Checker Timeout")
else:
if result is not None:
return result
else:
return CheckerResult(False, 0, "Checker Error. Checker Return No Result")
def check_with_timeout(process_output, judge_output, judge_input, point_value, **kwargs):
# main code goes here
if True:
return CheckerResult(True, point_value, "Correct Answer")
else:
return CheckerResult(False, 0, "Wrong Answer")
Trong đó, **kwargs
có thể chứa các biến sau:
process_output
: outputjudge_output
: đáp ánsubmission_source
: Code bài nộpjudge_input
: inputpoint_value
: điểm của test đang chấmcase_position
: thứ tự của testsubmission_language
: ngôn ngữ của bài nộpexecution_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ư sauCheckerResult(case_passed_bool, points_awarded, feedback='', extended_feedback='')
Lưu ý feedback chỉ hiển thị được khoảng ~20~ ký tự. Nếu muốn người dùng xem được nhiều feedback hơn thì dùng extendedfeedback. Khuyến khích dùng extendedfeedback.
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 check(process_output, judge_output, judge_input, point_value, **kwargs):
# process the input
process_output = process_output.decode("ascii")
judge_output = judge_output.decode("ascii")
judge_input = judge_input.decode("ascii")
input_arr = judge_input.split('\n')
output_arr = process_output.split('\n')
n = int(input_arr[0])
for i in range(n):
a, b = (int(x) for x in input_arr[i + 1].split())
if a + b != int(output_arr[i]):
return CheckerResult(False, 0, f"{a} + {b} != {output_arr[i]}")
return CheckerResult(True, point_value, "Ok dung rui")
3. Custom Checker (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)
Những thông tin được viết ra stdout
sẽ được in ra màn hình cho người nộp bài (feedback), nhưng thông tin này chỉ hiển thị được khoảng ~20~ ký tự. Nếu muốn người dùng xem được nhiều feedback hơn (extended feedback), thì in feedback vào stderr
(lưu ý in sau khi in điểm ở dòng đầu tiên). Khuyến khích dùng extended_feedback.
Ví dụ:
Chương trình sau dùng để chấm bài toán: Cho hai số nguyên ~a, b~. In ra tổng ~a+b~.
#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 a, b, ansSum, userSum;
inp >> a >> b;
out >> userSum;
ans >> ansSum;
if (ansSum == userSum) {
cerr << a << " + " << b << " = " << userSum;
return 0; // CORRECT
}
else {
cerr << "a + b = " << ansSum << " != " << userSum;
return 1; // WA
}
}
4. Custom Checker (CPP + testlib.h)
VNOJ cũng hỗ trợ các checker được viết bằng testlib.h và testlib_themis_cms.h
của anh Phạm Văn Hạnh, về checker này, các bạn xem hướng dẫn ở đầu trang.
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 "testlib.h"
using namespace std;
int main(int argc, char* argv[]) {
registerTestlibCmd(argc, argv);
int n = inf.readInt();
int a = ouf.readInt();
int b = ouf.readInt();
ensuref(a + b == n, "%d + %d != %d", a, b, n);
if (a < 0) {
quitf(_points, "0.5 \n a = %d < 0", a);
}
if (b < 0) {
quitf(_points, "0.5 \n b = %d < 0", a);
}
quitf(_ok, "%d + %d = %d", a, b, n);
}