Hướng dẫn checker

Tham khảo từ LQDOJVNOJ

Hướng dẫn viết checker dùng testlib từ anh Phạm Văn Hạnh

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: 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='', 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.htestlib_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);
}