hydro OJ hack 添加方法

hydro OJ hack 添加方法

开启 hack 功能

  1. 确保您拥有题目管理权限(管理员或题目提供者)。
  2. 添加一个空的 subtask,依赖前面的 subtask,分数可以调成 3,前面选一个 subtask 降 3 分。(注意:hydro OJ 不允许 0 分 subtask)
  3. 编写数据校验器(建议使用 testlib.h)并上传 val.cpp。
  4. 找到本题的标程(一般是题目提供者的通过提交)并上传 std.cpp。
  5. 如果本题不是自定义评测(即文本比较),则上传 chk.cpp,模板见下文;否则,如果本题的 chk.cpp 依赖答案文件,则需要在模板 chk.cpp 的基础上作改动,见下文。
  6. 打开评测设置,添加相关的配置。
checker_type: testlib
checker: chk.cpp
validator: val.cpp
judge_extra_files:
- std.cpp

chk.cpp 模板(原题为文本比较)

#include "testlib.h"

#include <bits/stdc++.h>
#include <unistd.h>

namespace e32dd050_3952_11f0_a195_00155de49fe7_std {
#include "std.cpp"
}

// wcmp.cpp
#include "testlib.h"

using namespace std;

int main(int argc, char *argv[]) {
  char tmpFile[] = "f757d41e-394c-11f0-8e1b-00155de49fe7.ans";
  if (argc >= 4 && ifstream(argv[3]).peek() == EOF) {
    freopen(argv[1], "r", stdin);
    freopen(argv[3] = tmpFile, "w", stdout);
    int saved_stderr = dup(2);
    int null_fd = open("/dev/null", O_WRONLY);
    dup2(null_fd, 2), close(null_fd);
    e32dd050_3952_11f0_a195_00155de49fe7_std::main();
    cout.flush(), fflush(stdout);
    dup2(saved_stderr, 2), close(saved_stderr);
  }
  setName("compare sequences of tokens");
  registerTestlibCmd(argc, argv);

  int n = 0;
  string j, p;

  while (!ans.seekEof() && !ouf.seekEof()) {
    n++;

    ans.readWordTo(j);
    ouf.readWordTo(p);

    if (j != p)
      quitf(_wa, "%d%s words differ - expected: '%s', found: '%s'", n,
            englishEnding(n).c_str(), compress(j).c_str(), compress(p).c_str());
  }

  if (ans.seekEof() && ouf.seekEof()) {
    if (n == 1)
      quitf(_ok, "\"%s\"", compress(j).c_str());
    else
      quitf(_ok, "%d tokens", n);
  } else {
    if (ans.seekEof())
      quitf(_wa, "Participant output contains extra tokens");
    else
      quitf(_wa, "Unexpected EOF in the participants output");
  }
}

注:该模板将 std.cpp 内嵌在 chk.cpp 中,如果发现答案文件为空(hydro OJ hack 数据的答案文件是空的),则运行一遍 std.cpp 获得答案文件,然后再使用 wcmp.cpp 进行答案比较。

运行过程中,首先重定向 stdin,接着篡改答案文件为一个实际存在的文件并将 stdout 重定向,然后冰冻 stderr 防止 std.cpp 向 stderr 输出内容造成错误,最后刷新缓冲区并解冻 stderr。

chk.cpp 模板(原题有 chk.cpp)

#include "testlib.h"

#include <bits/stdc++.h>
#include <unistd.h>

namespace e32dd050_3952_11f0_a195_00155de49fe7_std {
#include "std.cpp"
}

// 复制原来的 checker

int main(int argc, char *argv[]) {
  char tmpFile[] = "f757d41e-394c-11f0-8e1b-00155de49fe7.ans";
  if (argc >= 4 && ifstream(argv[3]).peek() == EOF) {
    freopen(argv[1], "r", stdin);
    freopen(argv[3] = tmpFile, "w", stdout);
    int saved_stderr = dup(2);
    int null_fd = open("/dev/null", O_WRONLY);
    dup2(null_fd, 2), close(null_fd);
    e32dd050_3952_11f0_a195_00155de49fe7_std::main();
    cout.flush(), fflush(stdout);
    dup2(saved_stderr, 2), close(saved_stderr);
  }
  // 剩下部分相同
}

hack 步骤

  1. 确保题目已开启 hack 功能。
  2. 通过题目。
  3. 点开非自己的 AC 提交记录,右上角会有一个 hack 按钮,进入 hack 界面。
  4. 上传输入文件后建议勾选“自动整理输入”。如果是手动输入的数据建议加上行末换行。
posted @ 2025-05-25 19:50  caijianhong  阅读(100)  评论(0)    收藏  举报