├── 1.png ├── .gitignore ├── package.json ├── compile.sh ├── compile.cpp ├── judge.sh ├── judge.cpp ├── checker.cpp ├── LICENSE ├── grader.cpp ├── readme.md ├── generator.cpp └── main.js /1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/platelett/tc/HEAD/1.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | Cookie.txt 3 | node_modules 4 | *.exe 5 | 12543 6 | 13213 -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "jsdom": "^25.0.1" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /compile.sh: -------------------------------------------------------------------------------- 1 | g++ grader.cpp -o foo -Wall -O2 -std=c++17 -lm -fdiagnostics-color=always -DONLINE_JUDGE 2 | -------------------------------------------------------------------------------- /compile.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(){ 4 | system("g++ grader.cpp -o foo.exe -Wall -O2 -std=c++17 -lm -fdiagnostics-color=always -DONLINE_JUDGE"); 5 | 6 | return 0; 7 | } -------------------------------------------------------------------------------- /judge.sh: -------------------------------------------------------------------------------- 1 | g++ grader.cpp -o foo -O2 -std=c++17 2 | if (($? == 0)); then 3 | isAC=1 4 | for ((i = 1; i <= $count; i++)); do 5 | ./foo < data/$i.in > out 6 | diff out data/$i.out 7 | if (($? != 0)); then $isAC=0; break; fi 8 | echo "Passed $i of $count test cases" 9 | done 10 | if ((isAC)); then echo Accepted; touch Accepted; fi; 11 | rm out 12 | fi -------------------------------------------------------------------------------- /judge.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char cmd1[1000],cmd2[1000]; 4 | 5 | int main(){ 6 | system("g++ grader.cpp -o foo.exe -Wall -O2 -std=c++17 -lm -fdiagnostics-color=always -DONLINE_JUDGE"); 7 | 8 | for(int i=1;i<=count;++i){ 9 | sprintf(cmd1,"fooout",i); 10 | sprintf(cmd2,"fc out data/%d.out",i); 11 | printf("%s %s\n",cmd1,cmd2); 12 | system(cmd1); 13 | if(system(cmd2)){ 14 | puts("wa"); 15 | return 0; 16 | } 17 | } 18 | 19 | puts("ac"); 20 | 21 | return 0; 22 | } -------------------------------------------------------------------------------- /checker.cpp: -------------------------------------------------------------------------------- 1 | // at least C++11 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | const int eps = 1e-6; 10 | 11 | ofstream fout, fstd; 12 | 13 | template inline T read() { 14 | T pans, jans; 15 | fread(&pans, sizeof(T), 1, fstd); 16 | if(fread(&jans, sizeof(T), 1, fout) != sizeof(T)) 17 | cerr << "The output file is too short\n", exit(1); 18 | if(std::is_floating_point::value ? 19 | abs(pans - jans) > eps * max({pans, jans, (T)1}) : pans != jans 20 | ) cerr << "expected " << jans << " but found " << pans << '\n'; 21 | return jans; 22 | } 23 | template void diffData(int cnt) { 24 | if(cnt == 0) read(); 25 | else { 26 | size_t size = read(); 27 | while(size--) diffData(cnt - 1); 28 | } 29 | } 30 | int main(int argc, const char* argv[]) { 31 | if(argc < 3) exit(-1); 32 | fout.open(argv[1], ios::binary); 33 | fstd.open(argv[2], ios::binary); 34 | if(!fout.is_open() || !fstd.is_open()) exit(-1); 35 | 36 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 platelett 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /grader.cpp: -------------------------------------------------------------------------------- 1 | // at least C++11 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "foo.cc" 8 | 9 | namespace graderIO { 10 | template inline void read(T& res) { 11 | fread(&res, sizeof(T), 1, stdin); 12 | } 13 | template<> inline void read(std::string& res) { 14 | size_t size; 15 | read(size), res.resize(size); 16 | fread(&res[0], 1, size, stdin); 17 | } 18 | template inline void read(std::vector& res) { 19 | size_t size; 20 | read(size), res.resize(size); 21 | if(std::is_arithmetic::value) fread(res.data(), sizeof(T), size, stdin); 22 | else for(auto& i : res) read(i); 23 | } 24 | template inline void write(const T& res) { 25 | fwrite(&res, sizeof(T), 1, stdout); 26 | } 27 | template<> inline void write(const std::string& res) { 28 | write(res.size()), fwrite(res.data(), 1, res.size(), stdout); 29 | } 30 | template inline void write(const std::vector& res) { 31 | write(res.size()); 32 | if(std::is_arithmetic::value) fwrite(res.data(), sizeof(T), res.size(), stdout); 33 | else for(auto&& i : res) write(i); 34 | } 35 | template inline T read() { 36 | T res; 37 | read(res); 38 | return res; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 由于原来的下载数据方式已经失效,这里换了一种解析方式,但是无法生成 config.yaml 文件。 2 | 3 | ### 依赖 4 | 5 | #### node.js v16 6 | 7 | - windows 去[官网](https://nodejs.org/zh-cn/)下载安装包。 8 | 9 | - ubuntu apt 的默认版本是 v12.22.9,按如下方式安装 v16.18.1 10 | 11 | ```bash 12 | cd ~ 13 | curl -sL https://deb.nodesource.com/setup_16.x -o nodesource_setup.sh 14 | sudo bash nodesource_setup.sh 15 | sudo apt install nodejs 16 | ``` 17 | 18 | #### 几个库 19 | 20 | 完成上一步骤后再进行以下命令,如果 windows 下[无法运行 npm 怎么办](https://blog.csdn.net/oYinHeZhiGuang/article/details/124713422)。 21 | 22 | ```bash 23 | npm install jsdom 24 | npm install adm-zip 25 | ``` 26 | 27 | ### 使用 28 | 29 | #### 设置 Cookie 30 | 31 | 可以不设置 Cookie,如需设置访问 [Topcoder Archives](https://archive.topcoder.com/),把 TopCoder 的 Cookie 放进 Cookie.txt 里,失效的时候再更新。注意访问的是 [Topcoder Archives](https://archive.topcoder.com/),不是主站。 32 | 33 | 关于如何复制 Cookie 字符串,Chrome 浏览器如图所示,F12 打开开发者工具,点到网络,ctrl + R,点击第一条请求,在请求标头中找到 cookie,再右键,复制值。 34 | 35 | ![](1.png) 36 | 37 | #### 下载题目数据 38 | 39 | 比如需要的题号为 14588,直接运行: 40 | 41 | ```bash 42 | node main.js 14588 43 | ``` 44 | 45 | 大概要运行 3~10s,如果时间太长了应该是遇到故障了。 46 | 47 | 之后生成一个目录 14588,目录包含如下内容: 48 | 49 | - 目录 data,包含二进制格式的测试数据 50 | - 1.in, 1.out 51 | - 2.in, 2.out 52 | - ... 53 | - 文件 data.txt,测试数据的文本形式 54 | - 文件 grader.cpp,评测用文件 55 | - 文件 compile.sh,用于 HydroOJ 的文件。 56 | - 文件 compile.cpp,Windows 下编译用文件。 57 | - ~~文件 config.yaml,用于 HydroOJ 的配置文件(以前同学部署了一个 Hydro 给大家用,所以实现了该项)。~~ 58 | 59 | 另外,有几个可选参数: 60 | 61 | - `-j` 或 `-judge`,额外生成一个 `judge.sh` 和 `judge.cpp`,在 Linux 和 Windows 下对同目录下的 C++ 程序 `foo.cc` 进行简单测试(只测试正确性,不限制时间空间)。 62 | 63 | ### 注意事项 64 | 65 | - 源程序应采用和 TopCoder 一样的实现方式,不能使用 `stdin` 和 `stdout`,并且参数和返回值类型应当严格按照要求,比如要求返回值为 `int` 不能返回 `long long`。 66 | 67 | - 由于 grader.cpp 用了 C++11,所以评测时至少开 C++11。 68 | 69 | - Windows 下和 Linux 下生成的 grader.cpp 并不一致,不能混用。 -------------------------------------------------------------------------------- /generator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | const size_t ss = sizeof(size_t); 11 | 12 | struct buffer { 13 | char *data, *now, *end; 14 | inline buffer() { data = now = new char[128], end = data + 128; } 15 | inline void add(size_t n) { 16 | now += n; 17 | if(now >= end) [[unlikely]] { 18 | size_t size = now - data, cap = end - data; 19 | do cap <<= 1; while(cap < size); 20 | char *newData = new char[cap]; 21 | memcpy(newData, data, size); 22 | data = newData, now = data + size, end = data + cap; 23 | } 24 | } 25 | template inline void push(const string& s) { 26 | if(is_same::value) { 27 | add(ss), *(size_t*)(now - ss) = s.size(); 28 | add(s.size()), memcpy(now - s.size(), s.data(), s.size()); 29 | } else { 30 | add(sizeof(T)); 31 | T res; 32 | if(is_same::value) res = stoi(s); 33 | if(is_same::value) res = stoll(s); 34 | if(is_same::value) res = stod(s); 35 | *(T*)(now - sizeof(T)) = res; 36 | } 37 | } 38 | }; 39 | template bool readData(int cnt, ifstream& fin, buffer& buf) { 40 | if(cnt == 0) { 41 | if(is_same::value) { 42 | string s; 43 | while(1){ 44 | s.clear(); 45 | char flg=1; 46 | char c; 47 | while(c = fin.get(), c != '\"'){ 48 | if(c == '}') return false; 49 | if(c != ' ') flg=0; 50 | } 51 | while(c = fin.get(), c != '\"') s += c; 52 | if(flg) break; 53 | } 54 | buf.push(s); 55 | return true; 56 | } else { 57 | string s; 58 | loop:; 59 | try{ 60 | fin >> s; 61 | T res; 62 | if(is_same::value) res = stoi(s); 63 | if(is_same::value) res = stoll(s); 64 | if(is_same::value) res = stod(s); 65 | }catch(...){ 66 | goto loop; 67 | } 68 | buf.push(s); 69 | return true; 70 | } 71 | } else { 72 | size_t size = 0, idx = buf.now - buf.data; 73 | buf.add(ss); 74 | while(fin.get() != '{'); 75 | while(readData(cnt - 1, fin, buf)) size++; 76 | *(size_t*)(buf.data + idx) = size; 77 | return true; 78 | } 79 | } 80 | void readData(const string& type, int cnt, ifstream& fin, buffer& buf) { 81 | if(type == "int") readData(cnt, fin, buf); 82 | if(type == "long") readData(cnt, fin, buf); 83 | if(type == "double") readData(cnt, fin, buf); 84 | if(type == "String") readData(cnt, fin, buf); 85 | } 86 | int main(int argc, const char* argv[]) { 87 | string path = argc == 1 ? "." : argv[1]; 88 | path += '/'; 89 | ifstream fin(path + "/temp"); 90 | vector> Parameters; 91 | pair Returns; 92 | 93 | int pcnt, cnt; 94 | string type; 95 | fin >> pcnt; 96 | while(pcnt--) fin >> type >> cnt, Parameters.emplace_back(type, cnt); 97 | fin >> Returns.first >> Returns.second; 98 | 99 | int tcnt; 100 | fin >> tcnt; 101 | for(int k = 1; k <= tcnt; k++) { 102 | buffer in, out; 103 | for(auto&& i : Parameters) readData(i.first, i.second, fin, in); 104 | readData(Returns.first, Returns.second, fin, out); 105 | string name = path + "data/" + to_string(k); 106 | ofstream(name + ".in", ios::binary).write(in.data, in.now - in.data); 107 | ofstream(name + ".out", ios::binary).write(out.data, out.now - out.data); 108 | } 109 | 110 | return 0; 111 | } -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | const { JSDOM } = require("jsdom"); 2 | const https = require("https"); 3 | const fs = require("fs"); 4 | const cp = require("child_process"); 5 | const path = require("path"); 6 | const platform=process.platform 7 | 8 | // 配置变量 9 | var problemID, haveJudge = false; // 问题 ID,从命令行参数传入 10 | 11 | for (let i = 2; i < process.argv.length; i++) { 12 | let arg = process.argv[i]; 13 | if (arg[0] != "-") problemID = arg; 14 | else { 15 | arg = arg.slice(1); 16 | if (arg == "j" || arg == "judge") haveJudge = true; 17 | } 18 | } 19 | 20 | const cookieFile = "Cookie.txt"; // 存储 Cookie 的文件 21 | const graderTemplateFile = "grader.cpp"; // Grader 模板文件 22 | const outputFolder = `${problemID}`; // 输出的文件夹路径 23 | 24 | // 检查文件是否存在 25 | if (!fs.existsSync(cookieFile)) { 26 | console.error(`Cookie file not found: ${cookieFile}`); 27 | process.exit(1); 28 | } 29 | 30 | // 读取 Cookie 和 Grader 模板 31 | const cookie = fs.readFileSync(cookieFile).toString().trim(); 32 | const graderTemplate = fs.readFileSync(graderTemplateFile).toString(); 33 | 34 | // 创建输出文件夹 35 | fs.mkdirSync(outputFolder, { recursive: true }); 36 | fs.mkdirSync(path.join(outputFolder, "data"), { recursive: true }); 37 | 38 | // HTTPS 请求工具 39 | const userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'; // 常用的 User-Agent 40 | 41 | function httpsRequest(url) { 42 | return new Promise((resolve, reject) => { 43 | const req = https.request(url, { 44 | headers: { 45 | Cookie: cookie, 46 | 'User-Agent': userAgent 47 | } 48 | }, (res) => { 49 | if (res.statusCode < 200 || res.statusCode >= 300) { 50 | reject(new Error(`Request failed with status code: ${res.statusCode}`)); 51 | return; 52 | } 53 | let body = ""; 54 | res.on("data", (chunk) => (body += chunk)); 55 | res.on("end", () => resolve(body)); 56 | }); 57 | req.on("error", (err) => reject(err)); 58 | req.end(); 59 | }); 60 | } 61 | 62 | // 提取问题相关信息 63 | function fetchProblemInfo() { 64 | const url = `https://community.topcoder.com/stat?c=problem_statement&pm=${problemID}`; 65 | console.log(`Fetching problem info from ${url}`); 66 | return httpsRequest(url) 67 | .then(html => { 68 | const dom = new JSDOM(html); 69 | const selector = 70 | "body > table > tbody > tr > td.bodyText > table.paddingTable > tbody > tr:nth-child(1) > td > table > tbody > tr:nth-child(6) > td > table > tbody > tr:nth-child(5) > td:nth-child(2) > table > tbody > tr > td:nth-child(2)"; 71 | const info = dom.window.document.querySelectorAll(selector); 72 | if (info.length < 4) { 73 | throw new Error("Failed to extract problem information. Check the selector."); 74 | } 75 | return { 76 | className: info[0].textContent.trim(), 77 | methodName: info[1].textContent.trim(), 78 | parameters: info[2].textContent.trim().split(",").map((param) => param.trim()), 79 | returnType: info[3].textContent.trim(), 80 | }; 81 | }); 82 | } 83 | 84 | const graderFilePath = path.join(outputFolder, "grader.cpp"); 85 | const compileFilePath = path.join(outputFolder, "compile.sh"); 86 | const compileCppFilePath = path.join(outputFolder, "compile.cpp"); 87 | const judgeFilePath = path.join(outputFolder, "judge.sh"); 88 | const judgeCppFilePath = path.join(outputFolder, "judge.cpp"); 89 | const tempFilePath = path.join(outputFolder, "temp"); 90 | 91 | const compile = fs.readFileSync("compile.sh").toString(); 92 | const compileCpp = fs.readFileSync("compile.cpp").toString(); 93 | const judge = fs.readFileSync("judge.sh").toString(); 94 | const judgecpp = fs.readFileSync("judge.cpp").toString(); 95 | 96 | 97 | function typeInfo(s) { 98 | let len = s.indexOf("[]"); 99 | if(len < 0) len = s.length; 100 | this.type = s.slice(0, len), this.count = (s.length - len) / 2; 101 | this.toCpp = () => { 102 | let type = this.type.toLowerCase(); 103 | if(type == "long") type = "long long"; 104 | if(type == "string") type = "std::string"; 105 | return "std::vector<".repeat(this.count) + type + ">".repeat(this.count); 106 | } 107 | } 108 | // 生成 grader 文件 109 | function generateGraderFile(info) { 110 | let graderContent = graderTemplate + "\nint main() {\n"; 111 | if(platform=="win32") graderContent=graderContent+" _setmode(_fileno(stdin), _O_BINARY);\n"; 112 | info.parameters.forEach((param, index) => { 113 | graderContent += ` auto _${index} = graderIO::read<${new typeInfo(param).toCpp()}>();\n`; 114 | }); 115 | graderContent += ` graderIO::write(${info.className}().${info.methodName}(`; 116 | graderContent += info.parameters.map((_, index) => `_${index}`).join(", "); 117 | graderContent += `));\n return 0;\n}`; 118 | fs.writeFileSync(graderFilePath, graderContent); 119 | console.log(`Grader file generated: ${graderFilePath}`); 120 | } 121 | 122 | const htmlEntitiesMap = { 123 | '&': '&', 124 | '<': '<', 125 | '>': '>', 126 | '"': '"', 127 | ''': "'", 128 | '/': '/', 129 | ' ': ' ', // 非断空格 130 | ' ': ' ', // 非断空格(十六进制表示法) 131 | // 可以根据需要添加更多实体符号 132 | }; 133 | 134 | // 处理带有 HTML 实体符号的字符串,将其替换为对应的字符 135 | function decodeHTMLEntities(str) { 136 | return str.replace(/&[a-zA-Z0-9#]+;/g, (entity) => { 137 | return htmlEntitiesMap[entity] || entity; // 如果未找到匹配的实体,则保持原状 138 | }); 139 | } 140 | 141 | 142 | // 提取测试数据 143 | function fetchTestData() { 144 | const url = `https://archive.topcoder.com/ProblemStatement/pm/${problemID}`; 145 | console.log(`Fetching test data from ${url}`); 146 | return httpsRequest(url) 147 | .then(html => { 148 | fs.writeFileSync("t.html",html); 149 | // 定义一个数组来存储提取的结果 150 | const resultArray = []; 151 | 152 | // 使用正则表达式提取每个
  • ...
  • 的内容 153 | const liDivRegex = /
  • \s*
    (.*?)<\/div>\s*<\/li>/gs; 154 | 155 | let match; 156 | while ((match = liDivRegex.exec(html)) !== null) { 157 | // match[1] 是
    ...
    中的内容 158 | let divContent = match[1]; 159 | divContent=divContent.replaceAll("

    ",""); 160 | divContent=divContent.replaceAll("

    ","\n"); 161 | 162 | // 将拼接好的字符串放入结果数组中 163 | resultArray.push(divContent); 164 | } 165 | 166 | return resultArray; 167 | }); 168 | } 169 | 170 | // 处理每个测试用例 171 | function processTestCase(testCase) { 172 | const dataFolder = path.join(outputFolder, "data"); 173 | const lines = testCase.split("\n"); 174 | 175 | let inputContent = ""; 176 | let outputContent = ""; 177 | 178 | for (const line of lines) { 179 | const trimmedLine = line.trim(); 180 | 181 | if (trimmedLine.startsWith("Returns:")) { 182 | // 输出部分(Returns 后的内容) 183 | outputContent = trimmedLine.replace("Returns:", "").trim(); 184 | break; 185 | } else if (trimmedLine) { 186 | // 普通输入部分 187 | inputContent += trimmedLine + "\n"; 188 | } 189 | } 190 | 191 | return { 192 | "input": inputContent, 193 | "output": outputContent, 194 | } 195 | } 196 | 197 | function parse(s) { 198 | let res = "", inq = false; 199 | let cnt=0; 200 | for(let c of s) { 201 | if(c == "\"") inq = !inq; 202 | if(inq) res += c; 203 | else if(c == "{") res += " { ",++cnt; 204 | else if(c == "}") res += " } ",--cnt; 205 | else res += c == "," || c == "\n" ? " " : c; 206 | } 207 | if(cnt>0) res+=" } ".repeat(cnt); 208 | return res + " "; 209 | } 210 | function myTrim(s) { 211 | let res = "", inq = false, lst = " "; 212 | for(let c of s) { 213 | if(c == "\"") inq = !inq; 214 | if(inq) res += c; 215 | else if(c != " " || lst != " ") res += c; 216 | lst = c; 217 | } 218 | return res; 219 | } 220 | function makeDataFile(data,info) { 221 | let parameters=info.parameters 222 | let raw = `${parameters.length} `; 223 | parameters.push(info.returnType); 224 | for(let i of parameters) { 225 | let v = new typeInfo(i); 226 | raw += `${v.type} ${v.count} `; 227 | } 228 | raw += data.length + " "; 229 | data.forEach((v, i) => { 230 | raw += parse(v.input) + parse(v.output); 231 | }); 232 | fs.writeFile(tempFilePath, myTrim(raw), err => { 233 | if(err) return console.error(err); 234 | let cmd=`generator ${problemID}`; 235 | if(platform!="win32") cmd="./"+cmd; 236 | cp.exec((cmd), (err, stdout, stderr) => { 237 | if(err) return console.error(err); 238 | fs.unlink(tempFilePath, err => { if(err) console.error(err); }); 239 | }); 240 | }); 241 | } 242 | 243 | // 生成 compile.sh 文件 244 | function generateCompileScript() { 245 | fs.writeFileSync(compileFilePath, compile); 246 | fs.writeFileSync(compileCppFilePath, compileCpp); 247 | } 248 | 249 | // 生成 judge.sh 文件 250 | function generateJudgeScript(count) { 251 | fs.writeFileSync(judgeFilePath, `count=${count}\n` + judge); 252 | fs.writeFileSync(judgeCppFilePath, `const int count=${count};\n` + judgecpp); 253 | } 254 | 255 | // 主函数 256 | function main() { 257 | console.log(`Problem ID: ${problemID}`); 258 | 259 | // Step 1: 获取问题的基本信息 260 | fetchProblemInfo() 261 | .then(problemInfo => { 262 | console.log("Problem Info:", problemInfo); 263 | 264 | // Step 2: 生成 grader.cpp 文件 265 | generateGraderFile(problemInfo); 266 | 267 | // Step 3: 获取测试数据 268 | return fetchTestData() 269 | .then(testCases => { 270 | console.log(`Found ${testCases.length} test cases.`); 271 | 272 | // Step 4: 处理每个测试用例 273 | let data=new Array(); 274 | testCases.forEach((testCase, index) => data.push(processTestCase(testCase))); 275 | makeDataFile(data,problemInfo) 276 | 277 | // Step 5: 生成 compile.sh 文件 278 | generateCompileScript(); 279 | 280 | // Step 6: 生成 judge.sh 文件 281 | if (haveJudge) 282 | generateJudgeScript(testCases.length); 283 | 284 | console.log(`All files saved to folder: ${outputFolder}`); 285 | }) 286 | }) 287 | .catch(error => { 288 | console.error("An error occurred:", error.message); 289 | }); 290 | } 291 | 292 | main(); --------------------------------------------------------------------------------