From 487c041148ba75fda466f08155f82310f05cbb6c Mon Sep 17 00:00:00 2001 From: Shuming Liu Date: Sat, 11 Oct 2025 12:33:24 +0800 Subject: [PATCH] upgrade to python3;add some validator examples --- examples/README_自定义验证程序.md | 295 ++++++++++++++++++++ examples/StringFormatValidator.java | 69 +++++ examples/custom_validators.md | 328 +++++++++++++++++++++++ examples/float_validator.cpp | 54 ++++ examples/integration_example.py | 183 +++++++++++++ examples/multi_solution_validator.py | 58 ++++ examples/range_validator.cpp | 68 +++++ examples/test_validator.py | 103 +++++++ python/datasource.py | 118 ++++---- python/datasource.pyc | Bin 21089 -> 0 bytes python/engine.py | 24 +- python/engine.pyc | Bin 2917 -> 0 bytes python/engineconfig.py | 62 ++--- python/engineconfig.pyc | Bin 7209 -> 0 bytes python/entity.py | 50 ++-- python/entity.pyc | Bin 9964 -> 0 bytes python/judgescript.py | 48 ++-- python/judgescript.pyc | Bin 10437 -> 0 bytes python/ojunit.py | 2 +- python/ojunit.pyc | Bin 1139 -> 0 bytes python/tester.py | 66 ++--- python/tester.pyc | Bin 27508 -> 0 bytes scripts/compare-file.py | 13 +- scripts/run-guard.py | 81 +++--- utils/xmlrpc-debug-proxy.py | 187 +++++++------ 25 files changed, 1492 insertions(+), 317 deletions(-) create mode 100644 examples/README_自定义验证程序.md create mode 100644 examples/StringFormatValidator.java create mode 100644 examples/custom_validators.md create mode 100644 examples/float_validator.cpp create mode 100644 examples/integration_example.py create mode 100644 examples/multi_solution_validator.py create mode 100644 examples/range_validator.cpp create mode 100644 examples/test_validator.py delete mode 100644 python/datasource.pyc delete mode 100644 python/engine.pyc delete mode 100644 python/engineconfig.pyc delete mode 100644 python/entity.pyc delete mode 100644 python/judgescript.pyc delete mode 100644 python/ojunit.pyc delete mode 100644 python/tester.pyc diff --git a/examples/README_自定义验证程序.md b/examples/README_自定义验证程序.md new file mode 100644 index 0000000..18db35f --- /dev/null +++ b/examples/README_自定义验证程序.md @@ -0,0 +1,295 @@ +# BitOJ 自定义验证程序完整指南 + +## 概述 + +BitOJ系统支持4种判题方式: + +1. **字符串精确比较** - 逐字符对比输出 +2. **字符串容错比较** - 允许格式错误(PE),主要比较数字内容 +3. **文件MD5校验** - 比较文件大小和MD5值 +4. **自定义验证程序** - 编写专门的验证逻辑 + +本文档重点介绍第4种方式:自定义验证程序的编写和使用。 + +## 自定义验证程序原理 + +### 工作流程 +1. 系统执行用户提交的代码 +2. 将输入、期望输出、实际输出传递给验证程序 +3. 验证程序分析这些文件并返回判题结果 +4. 系统根据返回结果确定最终评分 + +### 参数说明 +验证程序接收以下参数: +- `argv[1]`: 标准输入文件路径 +- `argv[2]`: 期望输出文件路径 +- `argv[3]`: 用户程序输出文件路径 + +### 返回值 +验证程序必须输出以下结果之一: +- `AC` - Accepted(答案正确) +- `PE` - Presentation Error(格式错误) +- `WA` - Wrong Answer(答案错误) + +## 实际示例 + +### 1. 浮点数误差比较 (C++) + +**适用场景**: 计算几何、数值计算等需要浮点数比较的题目 + +```cpp +#include +#include +#include +using namespace std; + +const double EPS = 1e-9; + +int main(int argc, char* argv[]) { + ifstream expected(argv[2]); // 标准答案 + ifstream result(argv[3]); // 用户输出 + + double exp_val, res_val; + if (!(expected >> exp_val) || !(result >> res_val)) { + cout << "WA" << endl; + return 0; + } + + if (fabs(exp_val - res_val) <= EPS) { + cout << "AC" << endl; + } else { + cout << "WA" << endl; + } + + return 0; +} +``` + +### 2. 多解答案验证 (Python) + +**适用场景**: 排序题、图论路径题等有多种正确答案的题目 + +```python +#!/usr/bin/env python +import sys + +def main(): + try: + with open(sys.argv[2], 'r') as f: + expected = f.read().strip() + with open(sys.argv[3], 'r') as f: + result = f.read().strip() + + # 解析数字并排序比较 + expected_nums = sorted(map(int, expected.split())) + result_nums = sorted(map(int, result.split())) + + if expected_nums == result_nums: + print("AC") + else: + print("WA") + except: + print("WA") + +if __name__ == "__main__": + main() +``` + +### 3. 输出格式验证 (Java) + +**适用场景**: 需要严格输出格式的竞赛题目 + +```java +import java.io.*; +import java.util.*; +import java.util.regex.Pattern; + +public class StringFormatValidator { + public static void main(String[] args) { + try { + Scanner result = new Scanner(new File(args[2])); + + int lineNum = 1; + while (result.hasNextLine()) { + String line = result.nextLine().trim(); + + // 检查格式:Case #X: Y + Pattern pattern = Pattern.compile("^Case #" + lineNum + ": \\d+$"); + if (!pattern.matcher(line).matches()) { + System.out.println("PE"); + return; + } + lineNum++; + } + + System.out.println("AC"); + } catch (Exception e) { + System.out.println("WA"); + } + } +} +``` + +## 在BitOJ中配置自定义验证程序 + +### 代码配置示例 + +```python +from judgescript import ExternalJudge + +# 创建自定义验证程序 +validator = ExternalJudge( + problemid='P1001', # 题目ID + vlang='gcc-3.3', # 验证程序语言 + vcode=validator_code # 验证程序源代码 +) + +# 在测试过程中调用 +result = validator.judge( + sid='S123', # 提交ID + tid='T001', # 测试用例ID + tin='/path/to/input.txt', # 输入文件 + tout='/path/to/output.txt', # 期望输出 + result='/path/to/result.txt', # 实际输出 + errfile='/path/to/error.txt' # 错误输出 +) +``` + +### 支持的编程语言 + +| 语言 | 标识符 | 说明 | +|------|--------|------| +| C | gcc-3.3 | 适合高性能验证 | +| C++ | g++-3.3 | 支持STL容器 | +| Java | java-1.6 | 强类型安全 | +| Python | python-2.5 | 快速开发 | +| Pascal | fpc-2.2 | 简单逻辑 | + +## 最佳实践 + +### 1. 错误处理 +```cpp +// 文件读取失败处理 +if (!input_file.is_open()) { + cout << "WA" << endl; + return 0; +} + +// 数据解析失败处理 +try { + value = stod(line); +} catch (const exception& e) { + cout << "WA" << endl; + return 0; +} +``` + +### 2. 性能优化 +- 使用适当的数据结构 +- 避免不必要的字符串操作 +- 合理设置缓冲区大小 +- 注意内存使用限制 + +### 3. 安全考虑 +- 验证输入参数数量 +- 处理异常文件路径 +- 限制递归深度 +- 避免无限循环 + +### 4. 可维护性 +- 添加清晰的注释 +- 使用有意义的变量名 +- 模块化验证逻辑 +- 提供调试输出选项 + +## 常见应用场景 + +### 1. 数值计算题 +- 浮点数精度比较 +- 矩阵运算结果验证 +- 统计数值的近似比较 + +### 2. 图论算法题 +- 最短路径验证(允许多条等长路径) +- 最小生成树验证(权重相等即可) +- 图遍历结果验证 + +### 3. 字符串处理题 +- 忽略大小写比较 +- 忽略空白字符差异 +- 正则表达式匹配 + +### 4. 组合数学题 +- 排列组合结果验证 +- 集合操作结果比较 +- 数学证明步骤检查 + +### 5. 交互式题目 +- 模拟交互过程 +- 验证查询次数限制 +- 检查答案正确性 + +## 调试技巧 + +### 1. 本地测试 +```bash +# 编译验证程序 +g++ -o validator validator.cpp + +# 准备测试文件 +echo "3.14159" > expected.txt +echo "3.14160" > result.txt + +# 运行测试 +./validator input.txt expected.txt result.txt +``` + +### 2. 日志输出 +```cpp +#ifdef DEBUG + cerr << "Expected: " << exp_val << ", Got: " << res_val << endl; + cerr << "Difference: " << fabs(exp_val - res_val) << endl; +#endif +``` + +### 3. 边界情况测试 +- 空输出文件 +- 超大数值 +- 特殊字符 +- 格式错误的输入 + +## 故障排除 + +### 常见问题 + +1. **编译失败** + - 检查语言版本兼容性 + - 确认头文件引用正确 + - 验证语法错误 + +2. **运行超时** + - 优化算法复杂度 + - 减少不必要的计算 + - 检查是否有死循环 + +3. **内存不足** + - 减少内存分配 + - 及时释放资源 + - 使用流式处理 + +4. **判题结果异常** + - 验证输出格式 + - 检查返回值规范 + - 确认异常处理逻辑 + +## 总结 + +自定义验证程序是BitOJ系统最灵活的判题方式,能够处理各种复杂的判题需求。通过合理设计验证逻辑,可以支持: + +- 多解答案题目 +- 浮点数精度要求 +- 特殊输出格式 +- 交互式评测 +- 复杂的正确性检查 + +掌握自定义验证程序的编写技巧,能够大大扩展在线评测系统的应用范围,为各种类型的编程竞赛和教学需求提供支持。 \ No newline at end of file diff --git a/examples/StringFormatValidator.java b/examples/StringFormatValidator.java new file mode 100644 index 0000000..b65e54d --- /dev/null +++ b/examples/StringFormatValidator.java @@ -0,0 +1,69 @@ +/* + * 字符串格式验证程序 + * 验证输出是否符合特定格式要求 + * 编译: javac StringFormatValidator.java + * 使用: java StringFormatValidator input.txt expected.txt result.txt + */ + +import java.io.*; +import java.util.*; +import java.util.regex.Pattern; + +public class StringFormatValidator { + public static void main(String[] args) { + if (args.length != 3) { + System.out.println("WA"); + return; + } + + try { + // 读取期望的行数和格式信息 + Scanner expected = new Scanner(new File(args[1])); + Scanner result = new Scanner(new File(args[2])); + + // 假设期望文件第一行是期望的行数 + int expectedLines = expected.nextInt(); + expected.nextLine(); // 消费换行符 + + // 读取用户输出 + List userLines = new ArrayList<>(); + while (result.hasNextLine()) { + String line = result.nextLine().trim(); + if (!line.isEmpty()) { + userLines.add(line); + } + } + + // 检查行数 + if (userLines.size() != expectedLines) { + System.out.println("WA"); + return; + } + + // 检查每行格式 + boolean formatCorrect = true; + for (int i = 0; i < userLines.size(); i++) { + String line = userLines.get(i); + + // 检查是否符合 "Case #X: Y" 格式 + Pattern pattern = Pattern.compile("^Case #" + (i + 1) + ": \\d+$"); + if (!pattern.matcher(line).matches()) { + formatCorrect = false; + break; + } + } + + if (formatCorrect) { + System.out.println("AC"); + } else { + System.out.println("PE"); // 格式错误 + } + + expected.close(); + result.close(); + + } catch (Exception e) { + System.out.println("WA"); + } + } +} \ No newline at end of file diff --git a/examples/custom_validators.md b/examples/custom_validators.md new file mode 100644 index 0000000..ec619f4 --- /dev/null +++ b/examples/custom_validators.md @@ -0,0 +1,328 @@ +# BitOJ 自定义验证程序示例 + +## 1. 基本验证程序结构 + +自定义验证程序接收以下参数: +- 标准输入文件 +- 标准输出文件(期望答案) +- 用户输出文件(用户程序的输出) + +验证程序需要输出以下结果之一: +- `AC` - 答案正确 +- `PE` - 格式错误(如果支持) +- `WA` - 答案错误 + +## 2. 示例1:数值误差比较验证程序(C++) + +适用于需要浮点数比较的题目: + +```cpp +#include +#include +#include +#include +using namespace std; + +const double EPS = 1e-9; + +int main(int argc, char* argv[]) { + // argv[1]: 标准输入文件 + // argv[2]: 标准输出文件 + // argv[3]: 用户输出文件 + + ifstream expected(argv[2]); // 标准答案 + ifstream result(argv[3]); // 用户输出 + + double exp_val, res_val; + + // 读取期望的浮点数 + if (!(expected >> exp_val)) { + cout << "WA" << endl; + return 0; + } + + // 读取用户输出的浮点数 + if (!(result >> res_val)) { + cout << "WA" << endl; + return 0; + } + + // 比较数值,允许误差 + if (fabs(exp_val - res_val) <= EPS) { + cout << "AC" << endl; + } else { + cout << "WA" << endl; + } + + return 0; +} +``` + +## 3. 示例2:多解答案验证程序(Python) + +适用于有多个正确答案的题目: + +```python +#!/usr/bin/env python +import sys + +def main(): + # sys.argv[1]: 标准输入文件 + # sys.argv[2]: 标准输出文件 + # sys.argv[3]: 用户输出文件 + + try: + with open(sys.argv[2], 'r') as f: + expected = f.read().strip() + + with open(sys.argv[3], 'r') as f: + result = f.read().strip() + + # 假设这是一个排序题目,任何正确的排序都是对的 + expected_nums = list(map(int, expected.split())) + result_nums = list(map(int, result.split())) + + # 检查数量是否相同 + if len(expected_nums) != len(result_nums): + print("WA") + return + + # 检查排序后是否相同(原始数据相同) + if sorted(expected_nums) != sorted(result_nums): + print("WA") + return + + # 检查用户输出是否有序 + if result_nums == sorted(result_nums): + print("AC") + else: + print("WA") + + except Exception as e: + print("WA") + +if __name__ == "__main__": + main() +``` + +## 4. 示例3:图论路径验证程序(C++) + +验证最短路径问题,检查路径是否合法且最优: + +```cpp +#include +#include +#include +#include +#include +using namespace std; + +struct Edge { + int to, weight; +}; + +int main(int argc, char* argv[]) { + ifstream input(argv[1]); // 输入数据 + ifstream expected(argv[2]); // 期望答案 + ifstream result(argv[3]); // 用户答案 + + // 读取图的信息 + int n, m; + input >> n >> m; + + vector> graph(n + 1); + for (int i = 0; i < m; i++) { + int u, v, w; + input >> u >> v >> w; + graph[u].push_back({v, w}); + graph[v].push_back({u, w}); // 无向图 + } + + int start, end; + input >> start >> end; + + // 读取期望的最短距离 + int expected_dist; + expected >> expected_dist; + + // 读取用户输出的路径 + string line; + getline(result, line); + istringstream iss(line); + vector path; + int node; + while (iss >> node) { + path.push_back(node); + } + + // 验证路径 + if (path.empty() || path[0] != start || path.back() != end) { + cout << "WA" << endl; + return 0; + } + + // 计算路径长度 + int total_dist = 0; + for (int i = 0; i < path.size() - 1; i++) { + int u = path[i], v = path[i + 1]; + bool found = false; + for (const Edge& e : graph[u]) { + if (e.to == v) { + total_dist += e.weight; + found = true; + break; + } + } + if (!found) { + cout << "WA" << endl; // 路径不存在 + return 0; + } + } + + // 检查是否是最短路径 + if (total_dist == expected_dist) { + cout << "AC" << endl; + } else { + cout << "WA" << endl; + } + + return 0; +} +``` + +## 5. 示例4:字符串格式验证程序(Java) + +验证输出格式是否正确: + +```java +import java.io.*; +import java.util.*; + +public class Main { + public static void main(String[] args) throws IOException { + // args[0]: 标准输入文件 + // args[1]: 标准输出文件 + // args[2]: 用户输出文件 + + Scanner expected = new Scanner(new File(args[1])); + Scanner result = new Scanner(new File(args[2])); + + try { + // 读取期望的行数 + int expectedLines = expected.nextInt(); + + // 检查用户输出的行数 + int actualLines = 0; + List userLines = new ArrayList<>(); + + while (result.hasNextLine()) { + String line = result.nextLine().trim(); + if (!line.isEmpty()) { + userLines.add(line); + actualLines++; + } + } + + if (actualLines != expectedLines) { + System.out.println("WA"); + return; + } + + // 检查每行格式:必须是 "Case #X: Y" 的格式 + for (int i = 0; i < userLines.size(); i++) { + String line = userLines.get(i); + String pattern = "Case #" + (i + 1) + ": \\d+"; + if (!line.matches(pattern)) { + System.out.println("PE"); // 格式错误 + return; + } + } + + System.out.println("AC"); + + } catch (Exception e) { + System.out.println("WA"); + } finally { + expected.close(); + result.close(); + } + } +} +``` + +## 6. 示例5:交互式题目验证程序(C++) + +模拟交互过程: + +```cpp +#include +#include +#include +#include +using namespace std; + +int main(int argc, char* argv[]) { + ifstream input(argv[1]); // 输入数据 + ifstream expected(argv[2]); // 期望的查询次数等 + ifstream result(argv[3]); // 用户的查询序列 + + // 读取隐藏的数字 + int secret; + input >> secret; + + // 读取最大查询次数 + int maxQueries; + expected >> maxQueries; + + // 模拟交互过程 + int queryCount = 0; + int guess; + bool found = false; + + while (result >> guess && queryCount < maxQueries) { + queryCount++; + + if (guess == secret) { + found = true; + break; + } + // 在实际交互中,这里会给用户反馈 "too high" 或 "too low" + } + + // 检查结果 + if (found && queryCount <= maxQueries) { + cout << "AC" << endl; + } else { + cout << "WA" << endl; + } + + return 0; +} +``` + +## 使用方法 + +1. **编写验证程序**:选择合适的编程语言编写验证逻辑 +2. **设置题目**:在题目配置中指定使用自定义验证程序 +3. **上传验证代码**:将验证程序代码保存到系统中 +4. **测试验证**:确保验证程序能正确处理各种情况 + +## 注意事项 + +1. **异常处理**:验证程序必须处理所有可能的异常情况 +2. **性能考虑**:验证程序也有时间限制,需要高效实现 +3. **输出格式**:验证程序必须严格按照 AC/PE/WA 格式输出 +4. **安全性**:验证程序在沙箱环境中运行,有资源限制 +5. **可移植性**:确保验证程序在评测环境中能正常编译运行 + +## 配置示例 + +在 BitOJ 中配置自定义验证程序: + +```python +# 在题目配置中设置自定义验证程序 +problem.validator_language = 'gcc-3.3' # 验证程序语言 +problem.validator_code = ''' +// 这里放置验证程序的源代码 +''' +``` \ No newline at end of file diff --git a/examples/float_validator.cpp b/examples/float_validator.cpp new file mode 100644 index 0000000..e6736b3 --- /dev/null +++ b/examples/float_validator.cpp @@ -0,0 +1,54 @@ +// 浮点数误差比较验证程序 +// 编译: g++ -o float_validator float_validator.cpp +// 使用: ./float_validator input.txt expected.txt result.txt + +#include +#include +#include +#include +using namespace std; + +const double EPS = 1e-9; + +int main(int argc, char* argv[]) { + if (argc != 4) { + cout << "WA" << endl; + return 0; + } + + ifstream expected(argv[2]); // 标准答案 + ifstream result(argv[3]); // 用户输出 + + if (!expected.is_open() || !result.is_open()) { + cout << "WA" << endl; + return 0; + } + + double exp_val, res_val; + + // 读取期望的浮点数 + if (!(expected >> exp_val)) { + cout << "WA" << endl; + return 0; + } + + // 读取用户输出的浮点数 + if (!(result >> res_val)) { + cout << "WA" << endl; + return 0; + } + + // 比较数值,允许相对误差和绝对误差 + double diff = fabs(exp_val - res_val); + double rel_error = (fabs(exp_val) > EPS) ? diff / fabs(exp_val) : diff; + + if (diff <= 1e-6 || rel_error <= 1e-6) { // 放宽误差范围 + cout << "AC" << endl; + } else { + cout << "WA" << endl; + } + + expected.close(); + result.close(); + return 0; +} \ No newline at end of file diff --git a/examples/integration_example.py b/examples/integration_example.py new file mode 100644 index 0000000..fa193d1 --- /dev/null +++ b/examples/integration_example.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +BitOJ 自定义验证程序集成示例 +演示如何在实际的BitOJ系统中使用自定义验证程序 +""" + +import sys +sys.path.append('../python') + +try: + from judgescript import InternalJudge +except ImportError: + # 如果无法导入,创建一个模拟的类 + class InternalJudge: + def __init__(self, allowpe=False): + self.allowpe = allowpe + + def compare_string(self, output, result): + if output == result: + return 'AC' + if self.allowpe: + # 简化的PE检查 + if ''.join(output.split()) == ''.join(result.split()): + return 'PE' + return 'WA' + + +def demo_internal_judge(): + """演示内置判题器的使用""" + print("=== 内置判题器演示 ===") + + # 标准文本比较 + ij_strict = InternalJudge(allowpe=False) + print("严格文本比较:") + result = ij_strict.compare_string("hello world\n", "hello world\n") + print(f" 'hello world\\n' vs 'hello world\\n' => {result}") + + result = ij_strict.compare_string("hello world", "hello world\n") + print(f" 'hello world' vs 'hello world\\n' => {result}") + + # 允许格式错误的比较 + ij_pe = InternalJudge(allowpe=True) + print("\n允许格式错误的比较:") + result = ij_pe.compare_string("1 2 3 4 5\n", "1\n2\n3\n4\n5\n") + print(f" '1 2 3 4 5\\n' vs '1\\n2\\n3\\n4\\n5\\n' => {result}") + + result = ij_pe.compare_string("12345\n", "1 2 3 4 5\n") + print(f" '12345\\n' vs '1 2 3 4 5\\n' => {result}") + + +def demo_custom_judge_config(): + """演示如何配置自定义验证程序""" + print("\n=== 自定义验证程序配置示例 ===") + + # 浮点数比较验证程序代码 + float_validator_code = """ +#include +#include +#include +using namespace std; + +const double EPS = 1e-9; + +int main(int argc, char* argv[]) { + if (argc != 4) { + cout << "WA" << endl; + return 0; + } + + ifstream expected(argv[2]); + ifstream result(argv[3]); + + double exp_val, res_val; + if (!(expected >> exp_val) || !(result >> res_val)) { + cout << "WA" << endl; + return 0; + } + + if (fabs(exp_val - res_val) <= EPS) { + cout << "AC" << endl; + } else { + cout << "WA" << endl; + } + + return 0; +} +""" + + print("浮点数比较验证程序配置:") + print(" 语言: gcc-3.3") + print(" 代码长度:", len(float_validator_code), "字符") + print(" 功能: 允许浮点数误差比较") + + # 多解验证程序代码 + multi_solution_code = """ +import sys + +def main(): + try: + with open(sys.argv[2], 'r') as f: + expected = f.read().strip() + with open(sys.argv[3], 'r') as f: + result = f.read().strip() + + exp_nums = sorted(map(int, expected.split())) + res_nums = sorted(map(int, result.split())) + + if exp_nums == res_nums: + print("AC") + else: + print("WA") + except: + print("WA") + +if __name__ == "__main__": + main() +""" + + print("\n多解验证程序配置:") + print(" 语言: python-2.5") + print(" 代码长度:", len(multi_solution_code), "字符") + print(" 功能: 允许多种正确答案") + + +def demo_judge_usage_scenarios(): + """演示不同判题方式的使用场景""" + print("\n=== 判题方式使用场景 ===") + + scenarios = [ + { + "名称": "字符串精确比较", + "适用": "输出结果固定的算法题", + "示例": "计算1+1的结果", + "验证方式": "InternalJudge(allowpe=False)" + }, + { + "名称": "字符串容错比较", + "适用": "允许格式差异的题目", + "示例": "输出多个数字,允许不同的分隔符", + "验证方式": "InternalJudge(allowpe=True)" + }, + { + "名称": "文件大小+MD5校验", + "适用": "二进制文件输出", + "示例": "图像处理、音频处理等", + "验证方式": "文件级别的校验" + }, + { + "名称": "自定义验证程序", + "适用": "复杂的判题逻辑", + "示例": "浮点数比较、多解题目、交互题等", + "验证方式": "ExternalJudge" + } + ] + + for i, scenario in enumerate(scenarios, 1): + print(f"{i}. {scenario['名称']}") + print(f" 适用场景: {scenario['适用']}") + print(f" 典型示例: {scenario['示例']}") + print(f" 实现方式: {scenario['验证方式']}") + print() + + +def main(): + """主演示函数""" + print("BitOJ 判题系统验证程序演示") + print("=" * 50) + + demo_internal_judge() + demo_custom_judge_config() + demo_judge_usage_scenarios() + + print("演示完成!") + print("\n更多示例文件:") + print(" - float_validator.cpp: 浮点数比较验证程序") + print(" - multi_solution_validator.py: 多解验证程序") + print(" - StringFormatValidator.java: 格式验证程序") + print(" - range_validator.cpp: 数值范围验证程序") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/examples/multi_solution_validator.py b/examples/multi_solution_validator.py new file mode 100644 index 0000000..c32c725 --- /dev/null +++ b/examples/multi_solution_validator.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +多解答案验证程序 +适用于有多个正确答案的题目,如排序、排列等 +使用: python multi_solution_validator.py input.txt expected.txt result.txt +""" + +import sys +import re + + +def main(): + if len(sys.argv) != 4: + print("WA") + return + + try: + # 读取标准答案 + with open(sys.argv[2], 'r') as f: + expected = f.read().strip() + + # 读取用户输出 + with open(sys.argv[3], 'r') as f: + result = f.read().strip() + + # 去除多余的空白字符 + expected = re.sub(r'\s+', ' ', expected) + result = re.sub(r'\s+', ' ', result) + + # 解析数字 + try: + expected_nums = list(map(int, expected.split())) + result_nums = list(map(int, result.split())) + except ValueError: + print("WA") + return + + # 检查数量是否相同 + if len(expected_nums) != len(result_nums): + print("WA") + return + + # 检查是否包含相同的元素(允许不同的排列) + if sorted(expected_nums) != sorted(result_nums): + print("WA") + return + + # 如果需要检查特定的排序顺序,可以添加额外的验证 + # 这里我们接受任何包含相同元素的排列 + print("AC") + + except Exception: + print("WA") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/examples/range_validator.cpp b/examples/range_validator.cpp new file mode 100644 index 0000000..83c3c11 --- /dev/null +++ b/examples/range_validator.cpp @@ -0,0 +1,68 @@ +// 数值范围验证程序 +// 验证输出的数值是否在合理范围内 +// 编译: g++ -o range_validator range_validator.cpp + +#include +#include +#include +#include +using namespace std; + +int main(int argc, char* argv[]) { + if (argc != 4) { + cout << "WA" << endl; + return 0; + } + + ifstream input(argv[1]); // 输入数据,包含范围信息 + ifstream expected(argv[2]); // 期望答案 + ifstream result(argv[3]); // 用户输出 + + if (!input.is_open() || !expected.is_open() || !result.is_open()) { + cout << "WA" << endl; + return 0; + } + + // 读取输入数据中的范围信息 + int n; + input >> n; + vector arr(n); + for (int i = 0; i < n; i++) { + input >> arr[i]; + } + + int min_val = *min_element(arr.begin(), arr.end()); + int max_val = *max_element(arr.begin(), arr.end()); + + // 读取期望答案 + int exp_result; + if (!(expected >> exp_result)) { + cout << "WA" << endl; + return 0; + } + + // 读取用户答案 + int user_result; + if (!(result >> user_result)) { + cout << "WA" << endl; + return 0; + } + + // 验证答案是否在合理范围内 + if (user_result < min_val || user_result > max_val) { + cout << "WA" << endl; + return 0; + } + + // 验证答案是否正确 + if (user_result == exp_result) { + cout << "AC" << endl; + } else { + cout << "WA" << endl; + } + + input.close(); + expected.close(); + result.close(); + return 0; +} \ No newline at end of file diff --git a/examples/test_validator.py b/examples/test_validator.py new file mode 100644 index 0000000..124313f --- /dev/null +++ b/examples/test_validator.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +验证程序测试脚本 +用于测试自定义验证程序是否工作正常 +""" + +import os +import subprocess +import tempfile + + +def test_float_validator(): + """测试浮点数验证程序""" + print("测试浮点数验证程序...") + + # 创建测试文件 + input_file = tempfile.NamedTemporaryFile(mode='w', delete=False) + input_file.write("1.0") + input_file.close() + + expected_file = tempfile.NamedTemporaryFile(mode='w', delete=False) + expected_file.write("3.14159") + expected_file.close() + + result_file = tempfile.NamedTemporaryFile(mode='w', delete=False) + result_file.write("3.14159001") # 轻微误差 + result_file.close() + + try: + # 编译验证程序 + cmd = ['g++', '-o', 'float_validator', 'float_validator.cpp'] + compile_result = subprocess.run(cmd, capture_output=True, text=True) + if compile_result.returncode != 0: + print("编译失败:", compile_result.stderr) + return + + # 运行验证程序 + cmd = ['./float_validator', input_file.name, + expected_file.name, result_file.name] + run_result = subprocess.run(cmd, capture_output=True, text=True) + + print("验证结果:", run_result.stdout.strip()) + + # 清理 + if os.path.exists('float_validator'): + os.remove('float_validator') + + finally: + # 清理临时文件 + for f in [input_file, expected_file, result_file]: + if os.path.exists(f.name): + os.unlink(f.name) + + +def test_multi_solution_validator(): + """测试多解验证程序""" + print("测试多解验证程序...") + + # 创建测试文件 + input_file = tempfile.NamedTemporaryFile(mode='w', delete=False) + input_file.write("") + input_file.close() + + expected_file = tempfile.NamedTemporaryFile(mode='w', delete=False) + expected_file.write("1 2 3 4 5") + expected_file.close() + + result_file = tempfile.NamedTemporaryFile(mode='w', delete=False) + result_file.write("5 4 3 2 1") # 相同元素,不同顺序 + result_file.close() + + try: + # 运行验证程序 + cmd = ['python3', 'multi_solution_validator.py', + input_file.name, expected_file.name, result_file.name] + run_result = subprocess.run(cmd, capture_output=True, text=True) + + print("验证结果:", run_result.stdout.strip()) + + finally: + # 清理临时文件 + for f in [input_file, expected_file, result_file]: + if os.path.exists(f.name): + os.unlink(f.name) + + +def main(): + """主测试函数""" + print("=== 自定义验证程序测试 ===") + + # 切换到示例目录 + os.chdir('/Users/liushuming/Desktop/bitoj/examples') + + test_float_validator() + print() + test_multi_solution_validator() + + print("\n测试完成!") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/python/datasource.py b/python/datasource.py index 381e5b0..2c84073 100755 --- a/python/datasource.py +++ b/python/datasource.py @@ -1,10 +1,22 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- -import logging, os, sys, socket, time, xmlrpclib, bz2, Cookie +import logging +import os +import sys +import socket +import time +import xmlrpc.client as xmlrpclib +import bz2 +import http.cookies as Cookie import unittest from engineconfig import getConfig from entity import Submit, Problem, TestCase, PresetCode, DataFile -class DataSourceError(Exception): pass + +class DataSourceError(Exception): + pass + class DataSource: @@ -17,12 +29,14 @@ class DataSource: def _get_config_retry(self): ret = self.config.retry - if ret < 1: ret = 1 + if ret < 1: + ret = 1 return ret def _get_config_retry_wait(self): ret = self.config.retry_wait - if ret < 0.1: ret = 0.1 + if ret < 0.1: + ret = 0.1 return ret def _do_action(self, func, args): @@ -32,7 +46,7 @@ class DataSource: while retry > 0: try: ret = func(*args) - except DataSourceError, e: + except DataSourceError: self.logger.exception("DataSourceError") if retry > 0: time.sleep(retry_wait) @@ -74,7 +88,7 @@ class DataSource: ret.append(TestCase(self, row)) return ret - def get_test(self, tid, raw = True): + def get_test(self, tid, raw=True): func = self.driver.get_test args = (tid, ) row = self._do_action(func, args) @@ -87,13 +101,13 @@ class DataSource: func = self.driver.get_presetcodes args = (pid, lang) rows = self._do_action(func, args) - return map(lambda row: PresetCode(self, row), rows) + return list(map(lambda row: PresetCode(self, row), rows)) def get_datafiles(self, pid): func = self.driver.get_datafiles args = (pid, ) rows = self._do_action(func, args) - return map(lambda row: DataFile(self, row), rows) + return list(map(lambda row: DataFile(self, row), rows)) def get_datafile_data(self, datafileid): func = self.driver.get_datafile_data @@ -139,7 +153,7 @@ class DataSource: class JspAuthTransport(xmlrpclib.Transport): def __init__(self): xmlrpclib.Transport.__init__(self) - self.__cookies = Cookie.SmartCookie() + self.__cookies = Cookie.SimpleCookie() def request(self, host, handler, request_body, verbose=0): # issue XML-RPC request @@ -168,17 +182,17 @@ class JspAuthTransport(xmlrpclib.Transport): def get_jsession_id(self): - if self.__cookies.has_key('MoodleSession'): + if 'MoodleSession' in self.__cookies: return self.__cookies['MoodleSession'].value return None def __sendJsessionCookie(self, connection): - if self.__cookies.has_key('MoodleSession'): + if 'MoodleSession' in self.__cookies: connection.putheader( 'Cookie', 'MoodleSession=%s' % self.__cookies['MoodleSession'].value) - if self.__cookies.has_key('MoodleSessionTest'): + if 'MoodleSessionTest' in self.__cookies: connection.putheader( 'Cookie', 'MoodleSessionTest=%s' % self.__cookies['MoodleSessionTest'].value) @@ -209,9 +223,9 @@ class XmlRpcDataSource: while True: try: return self.server.oj.get_judge_id() - except xmlrpclib.Error, e: + except xmlrpclib.Error as e: raise DataSourceError(e) - except socket.error, e: + except socket.error as e: self.logger.exception('Failed to get_judge_id') time.sleep(self.config.retry_wait) @@ -219,9 +233,9 @@ class XmlRpcDataSource: while True: try: return self.server.oj.reset_submits(judgeid) - except xmlrpclib.Error, e: + except xmlrpclib.Error as e: raise DataSourceError(e) - except socket.error, e: + except socket.error as e: self.logger.exception('Failed to reset_submits') time.sleep(self.config.retry_wait) @@ -230,12 +244,12 @@ class XmlRpcDataSource: try: submits = self.server.oj.get_submits(judgeid, limit) for submit in submits: - if not isinstance(submit['code'], (str, unicode)): + if not isinstance(submit['code'], str): submit['code'] = submit['code'].__str__() return submits - except xmlrpclib.Error, e: + except xmlrpclib.Error as e: raise DataSourceError(e) - except socket.error, e: + except socket.error as e: time.sleep(self.config.retry_wait) self.logger.exception('Failed to get_submits') @@ -243,9 +257,9 @@ class XmlRpcDataSource: while True: try: return self.server.oj.get_problem(problemid) - except xmlrpclib.Error, e: + except xmlrpclib.Error as e: raise DataSourceError(e) - except socket.error, e: + except socket.error as e: self.logger.exception('Failed to get_problem') time.sleep(self.config.retry_wait) @@ -254,15 +268,15 @@ class XmlRpcDataSource: try: tests = self.server.oj.get_tests(problemid, full) for test in tests: - if not isinstance(test['input'], (str, unicode)): + if not isinstance(test['input'], str): test['input'] = test['input'].__str__() - if not isinstance(test['output'], (str, unicode)): + if not isinstance(test['output'], str): test['output'] = test['output'].__str__() self.logger.debug('Got %d test case(s)', len(tests)) return tests - except xmlrpclib.Error, e: + except xmlrpclib.Error as e: raise DataSourceError(e) - except socket.error, e: + except socket.error as e: self.logger.exception('Failed to get_tests') time.sleep(self.config.retry_wait) @@ -270,16 +284,16 @@ class XmlRpcDataSource: while True: try: test = self.server.oj.get_gztest(testid) - if not isinstance(test['input'], (str, unicode)): + if not isinstance(test['input'], str): test['input'] = test['input'].__str__() - if not isinstance(test['output'], (str, unicode)): + if not isinstance(test['output'], str): test['output'] = test['output'].__str__() test['input'] = bz2.decompress(test['input']) test['output'] = bz2.decompress(test['output']) return test - except xmlrpclib.Error, e: + except xmlrpclib.Error as e: raise DataSourceError(e) - except socket.error, e: + except socket.error as e: self.logger.exception('Failed to get_tests') time.sleep(self.config.retry_wait) @@ -288,13 +302,13 @@ class XmlRpcDataSource: try: codes = self.server.oj.get_presetcodes(problemid, lang) for code in codes: - if not isinstance(code['code'], (str, unicode)): + if not isinstance(code['code'], str): code['code'] = code['code'].__str__() self.logger.debug('Got %d presetcodes', len(codes)) return codes - except xmlrpclib.Error, e: + except xmlrpclib.Error as e: raise DataSourceError(e) - except socket.error, e: + except socket.error as e: self.logger.exception('Failed to get_presetcodes') time.sleep(self.config.retry_wait) @@ -304,9 +318,9 @@ class XmlRpcDataSource: files = self.server.oj.get_datafiles(problemid) self.logger.debug('Got %d datafiles', len(files)) return files - except xmlrpclib.Error, e: + except xmlrpclib.Error as e: raise DataSourceError(e) - except socket.error, e: + except socket.error as e: self.logger.exception('Failed to get_datafiles') time.sleep(self.config.retry_wait) @@ -315,9 +329,9 @@ class XmlRpcDataSource: try: data = self.server.oj.get_datafile_data(datafileid) return str(data) - except xmlrpclib.Error, e: + except xmlrpclib.Error as e: raise DataSourceError(e) - except socket.error, e: + except socket.error as e: self.logger.exception('Failed to get_datafiles') time.sleep(self.config.retry_wait) @@ -327,24 +341,24 @@ class XmlRpcDataSource: try: return self.server.oj.update_submit_compilemessage( id, compilemsg) - except xmlrpclib.Error, e: + except xmlrpclib.Error as e: raise DataSourceError(e) - except socket.error, e: + except socket.error as e: self.logger.exception('Failed to update_submit_compilemessage') time.sleep(self.config.retry_wait) def update_submit_test_results(self, id, results): for r in results: - if not isinstance(r['stdout'], (str, unicode)): r['stdout'] = '' - if not isinstance(r['stderr'], (str, unicode)): r['stderr'] = '' + if not isinstance(r['stdout'], str): r['stdout'] = '' + if not isinstance(r['stderr'], str): r['stderr'] = '' r['stdout'] = xmlrpclib.Binary(r['stdout']) r['stderr'] = xmlrpclib.Binary(r['stderr']) while True: try: return self.server.oj.update_submit_test_results(id, results) - except xmlrpclib.Error, e: + except xmlrpclib.Error as e: raise DataSourceError(e) - except socket.error, e: + except socket.error as e: self.logger.exception('Failed to update_submit_compilemessage') time.sleep(self.config.retry_wait) @@ -355,9 +369,9 @@ class XmlRpcDataSource: mc.oj.update_submit_status(id, newstatus) try: return mc() - except xmlrpclib.Error, e: + except xmlrpclib.Error as e: raise DataSourceError(e) - except socket.error, e: + except socket.error as e: self.logger.exception('Failed to update_submits_status') time.sleep(self.config.retry_wait) @@ -365,9 +379,9 @@ class XmlRpcDataSource: while True: try: return self.server.oj.get_submit_status(sid) - except xmlrpclib.Error, e: + except xmlrpclib.Error as e: return DataSourceError(e) - except socket.error, e: + except socket.error as e: self.logger.exception('Failed to get_submit_status') time.sleep(self.config.retry_wait) @@ -375,13 +389,13 @@ class XmlRpcDataSource: while True: try: msg = self.server.oj.get_submit_compilemessage(sid) - if isinstance(msg, (str, unicode)): + if isinstance(msg, str): return msg else: return msg.__str__() - except xmlrpclib.Error, e: + except xmlrpclib.Error as e: return DataSourceError(e) - except socket.error, e: + except socket.error as e: self.logger.exception('Failed to get_submit_status') time.sleep(self.config.retry_wait) @@ -389,16 +403,16 @@ class XmlRpcDataSource: while True: try: return self.server.oj.get_submit(sid) - except xmlrpclib.Error, e: + except xmlrpclib.Error as e: return DataSourceError(e) - except socket.error, e: + except socket.error as e: self.logger.exception('Failed to get_submit') time.sleep(self.config.retry_wait) class DataSourceTest(unittest.TestCase): def setUp(self): - execfile(os.path.join('..', 'testdata', 'test_config.py')) + exec(open(os.path.join('..', 'testdata', 'test_config.py')).read()) self.config = getConfig() self.datasource = self.config.datasources[0] self.dbname = os.path.join('..', 'testdata', self.config.testdb) diff --git a/python/datasource.pyc b/python/datasource.pyc deleted file mode 100644 index f16987f60d082cb1fe03bd46c44403fbcc1f8f66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21089 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 diff --git a/python/engine.py b/python/engine.py index 3f5838a..6773746 100755 --- a/python/engine.py +++ b/python/engine.py @@ -1,11 +1,17 @@ -import logging, os, thread, threading, time, Queue +import logging +import _thread +import threading +import time +import queue from engineconfig import getConfig + + class JudgeEngine: def __init__(self): self.quit_event = threading.Event() - self.test_queue = Queue.Queue() + self.test_queue = queue.Queue() self.config = getConfig() self.quit_event.clear() @@ -14,11 +20,11 @@ class JudgeEngine: def run(self): # one thread mode is good for debugging if self.config.test_threads == 1: - thread.start_new_thread(self.transport, ()) + _thread.start_new_thread(self.transport, ()) self.test() else: for i in range(self.config.test_threads): - thread.start_new_thread(self.test, ()) + _thread.start_new_thread(self.test, ()) self.transport() for ds in self.config.datasources: @@ -30,7 +36,7 @@ class JudgeEngine: total = 0 while not self.quit_event.isSet(): self.logger.info( - "%d submit in test queue, %d processed" % \ + "%d submit in test queue, %d processed" % (self.test_queue.qsize(), total)) c = 16 - self.test_queue.qsize() if c > 0: @@ -45,10 +51,10 @@ class JudgeEngine: def test(self): while not self.quit_event.isSet(): - #pdb.set_trace() + # pdb.set_trace() try: submit = self.test_queue.get(True, self.config.fetch_interval) - except Queue.Empty: + except queue.Empty: continue tester = self.config.get_tester(submit.language) if tester: @@ -64,6 +70,8 @@ class JudgeEngine: self.quit_event.set() return -class JudgeError(Exception): pass + +class JudgeError(Exception): + pass # vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/python/engine.pyc b/python/engine.pyc deleted file mode 100644 index 7c8ea01db0e6d9452d050873d4de85adfe1e856c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2917 zcmbVO+m0JW5Un12?X?r{C7auVAPy+P44D#NVih9tJ1BO?KSDHX*-g~H5u2XTNg8cXk7+X`BCId zDZ5n(Yh}Ae0T+p@bHs#oaSiT%W^^SS6gWuL2ce33(sOBt9;uVzD7U?VOGi*B zvj4=UArPP0+=awymlI#i?cC}_us$R+c4Lf7sG;f?VNzelwwH%G2FKY5!5WpJ{0v>2 zt2k$DUIdyJc{?6<@D;86HMI8TKHnR=!@WZnvPXNyV|W1E z;nEf=g4HfCY7>%Gm=wa8aR}#G5tc&GYmkd}pb{SdNs`*{76JwEc`x{L% z6uc)r2EEYp**x!Ks)c@Ty$y+~mpCCHXwv zz{g)jCDD%AF&oj2)XWvrj9U0^n5_a_#)(D2{R<6X3RI5&D1)v?XZm}Ar=pB77w8o5 zo){TMa#8iW(0XhIWAjRJ(p}K+U#-LpQ z(w!&-VU5{;WETO94zH;_;$z&X}^uBp$+|`XBfAM(U_rDemMWY z21P%*qotSy|y;VNOmpDcWfk`D{loD=$EG9CY2mOwbY)GNtCRTO$v9;4c0;m}{ z-@)cjdSlI!1;5mgEcC|8w7zDV1t*pEMf=5=7hk}Rub}wXP>HFTifoyNsepDn$R@j{ zt`xjzE}E+)0qMvxyZnaE@h{I(?`JVjudPS{PsxNeaWz4*0O$|XU8%wW5b9A=vZfgP zW)(@1O1@smHUv~biXh!Ie`MRBBj^D3Xo}|oLz(l7oUff$nNv8c4B8O4$s1_NAO`+G zW8KdtQ#ZEBu!nl!iQYlhUX12#Kec@~beJK3lwAK!NE}pp#4od@d|+&Vy@LB?j+=sM zDt?_6L#9~oPp09i-Y8@V)#7%b+!z^X-W%C?hoa2uns-7k%zYqI>@KXEfY=meHc~#W zGEw{nm+N+_`vob%&2MqDmrw}_5mn4Jvu)PRB~v%sQOjH)73gYN?o*z}k>KHv*8uKd zvq}ScjL)D>Q@vivUOjT7v^Q?&wr|}N`wmWRhw!Z2D$XDGf%7XL3&vyde4;TO=Dmr1 zF-H|6-Yj>ioZ%9%yk$BHB=Ja+6k3x+p-7TRHkgAfNz7v!Gdg;F6s`CzbXWUp>v>Xt z%v*yV>os1B8taYC#&%;%w=5oBd7kBcNa&B^_fS0Tv-VTsiX`!=EmSa@#pI&qvCPLxdjb+)XQezN3yUX8@gUL%lKQ4M?*4Hf+0A8X%q{+h VX?i@~D*(7l>lCj~K*OE){{@PCC%pgw diff --git a/python/engineconfig.py b/python/engineconfig.py index 4d56a53..e4d5c08 100755 --- a/python/engineconfig.py +++ b/python/engineconfig.py @@ -1,9 +1,8 @@ -#!/usr/bin/env python2.6 +#!/usr/bin/env python3 import string -from string import split from os import path -from Queue import Queue +from queue import Queue from subprocess import Popen, PIPE class EngineConfig: @@ -39,9 +38,10 @@ class EngineConfig: stdin=pa.stdout, stdout=PIPE) output = pb.communicate()[0] if output: - for user in string.split(output, '\n'): - user = string.strip(user) - if user: self.runas.put(user) + for user in output.decode().split('\n'): + user = user.strip() + if user: + self.runas.put(user) pa.wait() pb.wait() @@ -49,7 +49,7 @@ class EngineConfig: self.languages[profile] = tester def get_tester(self, profile): - if self.languages.has_key(profile): + if profile in self.languages: return self.languages[profile] def add_datasource(self, ds): @@ -65,41 +65,37 @@ class EngineConfig: default_compileguard = ( '/scripts/compile-guard', ' ' ) - default_runguard = split( - '/usr/bin/sudo -u /scripts/binary-guard ' + + default_runguard = ( + '/usr/bin/sudo -u /scripts/binary-guard ' + '-e ' + - '-t -T 5 -m -d -o -p -x', - ' ' - ) - maxmem_runguard = split( - '/usr/bin/sudo -u /scripts/binary-guard ' + + '-t -T 5 -m -d -o -p -x' + ).split(' ') + maxmem_runguard = ( + '/usr/bin/sudo -u /scripts/binary-guard ' + '-e ' + - '-t -T 5 -m -d -o -p -x', - ' ' - ) - java_runguard = split( + '-t -T 5 -m -d -o -p -x' + ).split(' ') + java_runguard = ( '/usr/bin/sudo -u ' + '/scripts/java-guard -t -T 5 -m 262144 ' + '-e ' + - '-d -o -p -x', ' ' - ) - python_runguard = split( + '-d -o -p -x' + ).split(' ') + python_runguard = ( '/scripts/python-guardd ' + - '-t -T 5 -m -d -o -p -x', - ' ' - ) - mono_runguard = split( + '-t -T 5 -m -d -o -p -x' + ).split(' ') + mono_runguard = ( '/usr/bin/sudo -u ' + '/scripts/mono-guard -t -T 5 -m ' + '-e ' + - '-d -o -p -x', ' ' - ) - bash_runguard = split( + '-d -o -p -x' + ).split(' ') + bash_runguard = ( '/usr/bin/sudo -u /scripts/bash-guard ' + '-e ' + - '-t -T 5 -m -d -o -p -x', - ' ' - ) + '-t -T 5 -m -d -o -p -x' + ).split(' ') default_compare = ( '/scripts/compare-guard', '', '', '', '', '' @@ -151,7 +147,7 @@ class EngineConfig: j2se15 = SimpleTester( source = 'Main.java', target = 'Main.class', compile = ('/scripts/javac-1.5',), - run = split('/usr/bin/java -cp -Xms8M -Xmx64M Main'), + run = ('/usr/bin/java -cp -Xms8M -Xmx64M Main').split(), runenv = {}, basemem = {'RSS' : 7560 }, baseproc = 8, @@ -163,7 +159,7 @@ class EngineConfig: j2se16 = SimpleTester( source = 'Main.java', target = 'Main.class', compile = ('/scripts/javac-1.6',), - run = split('/usr/bin/java -cp -Xms8M -Xmx64M Main'), + run = ('/usr/bin/java -cp -Xms8M -Xmx64M Main').split(), runenv = {}, basemem = {'RSS' : 7560 }, baseproc = 8, diff --git a/python/engineconfig.pyc b/python/engineconfig.pyc deleted file mode 100644 index 95948e4e2ff9bb50f5fda3553c68b2b1a8a2b07c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7209 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 0 and input[-1] != '\n': f.write('\n') - f.close() + with open(self.infile, 'w') as f: + f.write(input) + if len(input) > 0 and input[-1] != '\n': + f.write('\n') - f = file(self.outfile, 'w') - f.write(output) - if len(output) > 0 and output[-1] != '\n': f.write('\n') - f.close() + with open(self.outfile, 'w') as f: + f.write(output) + if len(output) > 0 and output[-1] != '\n': + f.write('\n') logger.debug('Finished') else: logger.debug('Skip input/output file creation') @@ -255,13 +253,11 @@ class DataFile: data = datasource.get_datafile_data(self.id) data = bz2.decompress(data) if self.type == 'text': - f = open(self.absolute_path, 'w') - f.write(string.replace(data, '\r\n', '\n')) - f.close() + with open(self.absolute_path, 'w') as f: + f.write(string.replace(data, '\r\n', '\n')) else: - f = open(self.absolute_path, 'wb') - f.write(data) - f.close() + with open(self.absolute_path, 'wb') as f: + f.write(data) DataFile.write_lock.release() diff --git a/python/entity.pyc b/python/entity.pyc deleted file mode 100644 index ef16f4c0cf6e02e7a4a8b9e4df66802d88a928e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9964 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 K^_lt$HRnHk=KXL0 diff --git a/python/judgescript.py b/python/judgescript.py index 7a2a6ec..bde37e8 100755 --- a/python/judgescript.py +++ b/python/judgescript.py @@ -23,20 +23,23 @@ class InternalJudge: return self.compare_file(tin, tout, result, self.allowpe) def compare_file(self, input, output, result, allowpe): - fo = file(output, 'rb'); fr = file(result, 'rb') + with open(output, 'rb') as fo, open(result, 'rb') as fr: - if not allowpe: - r = 'AC' - while r == 'AC': - so = fo.read(8192); sr = fr.read(8192) - if so == '' and sr == '': break - if so != sr: r = 'WA' - else: - so = fo.read(); sr = fr.read() - r = self.compare_string(so, sr) - - fo.close(); fr.close() - return r + if not allowpe: + r = 'AC' + while r == 'AC': + so = fo.read(8192) + sr = fr.read(8192) + if so == b'' and sr == b'': + break + if so != sr: + r = 'WA' + else: + so = fo.read() + sr = fr.read() + r = self.compare_string(so.decode('utf-8', errors='ignore'), + sr.decode('utf-8', errors='ignore')) + return r def compare_string(self, output, result): if output == result: return 'AC' @@ -76,10 +79,10 @@ class ExternalJudge: os.makedirs(datadir) self.comparecmd = tester.comparecmd self.codefile = os.path.abspath(os.path.join(datadir, tester.source)) - f = file(self.codefile, 'w') - f.write(string.replace(vcode, '\r\n', '\n')) - if len(vcode) > 0 and vcode[-1] != '\n': f.write('\n') - f.close() + with open(self.codefile, 'w') as f: + f.write(string.replace(vcode, '\r\n', '\n')) + if len(vcode) > 0 and vcode[-1] != '\n': + f.write('\n') self.logger.debug("Save validator code as %s" % self.codefile) @@ -119,7 +122,7 @@ class ExternalJudge: if rundir: os.chdir(rundir) os.execv(cmd[0], cmd) - print 'WA' + print('WA') remaintime = self.config.judgescript_wait pid1 = 0 @@ -133,13 +136,12 @@ class ExternalJudge: while pid1 == 0: try: os.kill(pid, 9) - except os.OSError, e: + except OSError: pass pid1, status = os.waitpid(pid, os.WNOHANG) - f = file(rfile, 'r') - ret = string.strip(f.readline()) - f.close() + with open(rfile, 'r') as f: + ret = f.readline().strip() if ret != 'AC' and ret != 'PE': ret = 'WA' return ret @@ -268,7 +270,7 @@ public class Main { def testPython(self): code = """#!/usr/bin/env python -print 'AC' +print('AC') """ self.j = ExternalJudge('p1', 'python-2.5', code) x = self.j.judge('s1', 't1', self.tin.name, self.tout.name, self.rst.name, self.err.name) diff --git a/python/judgescript.pyc b/python/judgescript.pyc deleted file mode 100644 index 4a8bba8fdd02f18c506e1d8ea26386dba9fafe8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10437 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 diff --git a/python/tester.py b/python/tester.py index 1233a08..1912a5f 100755 --- a/python/tester.py +++ b/python/tester.py @@ -1,6 +1,6 @@ import math, os, resource, signal, string, sys, threading, logging, time, pickle -import shutil, Queue +import shutil, queue import unittest import pdb from engineconfig import getConfig @@ -103,12 +103,12 @@ class SimpleTester(TesterBase): if os.path.exists(pcname): try: os.unlink(pcname) - except OSError, e: + except OSError: self.logger.exception( "Failed to delete presetcode file %s" % pcname) return False f = open(pcname, 'w') - f.write(string.replace(presetcode.code, '\r\n', '\n')) + f.write(presetcode.code.replace('\r\n', '\n')) f.write('\n'); f.close() @@ -118,24 +118,24 @@ class SimpleTester(TesterBase): if os.path.exists(datadirsource): try: os.unlink(datadirsource) - except OSError, e: + except OSError: self.logger.exception("Failed to delete source") return False if os.path.exists(datadirtarget): try: os.unlink(datadirtarget) - except OSError, e: + except OSError: self.logger.exception("Failed to delete target") return False # preprocess source code - code = string.replace(submit.code, '\r\n', '\n') - code = string.replace(code, chr(0x1a), '') # char generated by tc - code = string.replace(code, 'getch()', '') - code = string.replace(code, 'getch ()', '') - code = string.replace(code, 'getch ( )', '') + code = submit.code.replace('\r\n', '\n') + code = code.replace(chr(0x1a), '') # char generated by tc + code = code.replace('getch()', '') + code = code.replace('getch ()', '') + code = code.replace('getch ( )', '') - code = string.replace(code, '\r\n', '\n') + code = code.replace('\r\n', '\n') # write source to disk f = open(datadirsource, 'w') f.write(code) @@ -146,7 +146,7 @@ class SimpleTester(TesterBase): config = getConfig() try: submit.user = config.runas.get_nowait() - except Queue.Empty: + except queue.Empty: self.logger.exception("No runas user left, please create more!") return False rundir = self.get_rundir(submit) @@ -157,12 +157,12 @@ class SimpleTester(TesterBase): if os.path.exists(rundir): try: self._remove(rundir) - except OSError, e: + except OSError: self.logger.exception("Failed to delete rundir") config.runas.put(submit.user) return False os.mkdir(rundir) - os.chmod(rundir, 0775) + os.chmod(rundir, 0o775) return True @@ -199,7 +199,7 @@ class SimpleTester(TesterBase): for code in submit.get_presetcodes(): if not code.isheader: cmd.append(code.name) - self.logger.debug(string.join(cmd, '_')) + self.logger.debug('_'.join(cmd)) errfile = os.path.join(datadir, 'compile.err') @@ -210,9 +210,8 @@ class SimpleTester(TesterBase): compilemsg = None if os.path.exists(errfile): - f = file(errfile, 'r') - compilemsg = string.join(f.readlines(), '') - f.close() + with open(errfile, 'r') as f: + compilemsg = ''.join(f.readlines()) if compilemsg: submit.set_compilemessage(compilemsg) @@ -283,7 +282,7 @@ class SimpleTester(TesterBase): s = s.replace('', datadir) s = s.replace('', submit.user) self.runenv[k] = s - self.logger.debug(string.join(cmd, ' ') + ' ' + str(self.runenv)) + self.logger.debug(' '.join(cmd) + ' ' + str(self.runenv)) (exitcode, sig, timeused, memused) = \ self._execute(submit, cmd, timelimit = testcase.timelimit * 10, @@ -365,22 +364,22 @@ class SimpleTester(TesterBase): try: os.close(0) os.open(infile, os.O_RDONLY) - except Exception, e: - print e + except Exception as e: + print(e) sys.exit(125) if outfile: try: os.close(1) - os.open(outfile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666) - except Exception, e: - print e + os.open(outfile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0o666) + except Exception as e: + print(e) sys.exit(125) if errfile: try: os.close(2) - os.open(errfile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666) - except Exception, e: - print e + os.open(errfile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0o666) + except Exception as e: + print(e) sys.exit(125) #os.chdir(self.get_datadir(submit)) @@ -398,22 +397,23 @@ class SimpleTester(TesterBase): # read information form statfile if statfile: try: - stat = pickle.load(file(statfile, 'r')) + with open(statfile, 'rb') as f: + stat = pickle.load(f) exitcode = stat['exitcode'] sig = stat['sig'] timeused = stat['timeused'] memused = 0 - if self.basemem.has_key('RSS'): + if 'RSS' in self.basemem: memused += stat['memrss'] - self.basemem['RSS'] - if self.basemem.has_key('Data'): + if 'Data' in self.basemem: memused += stat['memdata'] - self.basemem['Data'] - if self.basemem.has_key('Stack'): + if 'Stack' in self.basemem: memused += stat['memstack'] - self.basemem['Stack'] memused = max(0, memused) - except Exception, e: + except Exception as e: self.logger.exception(e) self.logger.error("Failed to read statfile: %s" % statfile) - exitcode = 127 # judge script error + exitcode = 127 # judge script error return (exitcode, sig, timeused, memused) diff --git a/python/tester.pyc b/python/tester.pyc deleted file mode 100644 index 012c2cd7c0c8289bbad8f8f2bac4147aa1f67071..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27508 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 NlUIgvgI(j^{{{bxLyG_a diff --git a/scripts/compare-file.py b/scripts/compare-file.py index 5830283..8e6e168 100755 --- a/scripts/compare-file.py +++ b/scripts/compare-file.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import sys, string, hashlib, os from stat import * @@ -9,9 +9,9 @@ def check_file(name, size, md5sum): m = hashlib.md5() if os.path.isfile(name): s = os.stat(name)[ST_SIZE] - if s == string.atoi(size): + if s == int(size): f = open(name, 'rb') - m.update(f.read(string.atoi(size))) + m.update(f.read(int(size))) f.close() d = m.hexdigest() result.write("%s %d %s\n" % (name, s, d)) @@ -26,9 +26,10 @@ if __name__ == '__main__': result = open(sys.argv[3], 'w+') fstdout = open(sys.argv[2], 'r') for line in fstdout: - name, size, md5sum = string.split(string.strip(line), ' ') + name, size, md5sum = line.strip().split(' ') if not check_file(name, size, md5sum): - print 'WA'; break + print('WA') + break fstdout.close() result.close() - print 'AC' + print('AC') diff --git a/scripts/run-guard.py b/scripts/run-guard.py index 4f77dd5..33af69a 100755 --- a/scripts/run-guard.py +++ b/scripts/run-guard.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os, sys, string, signal, resource, time, getopt, pickle @@ -43,22 +43,23 @@ class RunGuard: optlist, self.args = getopt.gnu_getopt(sys.argv, 'e:t:m:d:o:T:p') for o, v in optlist: if o == '-e': - self.nproc += string.atoi(v) + self.nproc += int(v) if o == '-t': - self.timelimit = string.atoi(v) + self.timelimit = int(v) if o == '-m': - self.memlimit = string.atoi(v) * 1024 + self.memlimit = int(v) * 1024 if o == '-d': self.rundir = v if o == '-o': self.writeto = v if o == '-T': - self.timetime = string.atoi(v) + self.timetime = int(v) if o == '-p': self.usepickle = True v = os.getenv('GUARD_RLIMIT_OFILE') - if v: self.ofile = string.atoi(v) + if v: + self.ofile = int(v) self.ldpreload = os.getenv('GUARD_LD_PRELOAD') def execute(self): @@ -90,7 +91,7 @@ class RunGuard: while pid == 0: try: os.kill(self.childpid, signal.SIGKILL) - except OSError, e: + except OSError: pass pid, status, ru = os.wait4(self.childpid, os.WNOHANG) time.sleep(0.1) @@ -106,24 +107,27 @@ class RunGuard: def _get_memused(self): procdir = '/proc/%d' % self.childpid if os.path.isdir(procdir): - cmdline = file(procdir + '/cmdline', 'r').readlines() + with open(procdir + '/cmdline', 'r') as f: + cmdline = f.readlines() # do not get memory usage of this script after just fork if len(cmdline) > 0 and \ - string.strip(cmdline[0], '\0') != \ - string.join(self.args[1:], '\0'): + cmdline[0].strip('\0') != \ + '\0'.join(self.args[1:]): return - procstatus = file(procdir + '/status', 'r') - rss = 0; data = 0; stack = 0 - for line in procstatus: - n = line[0:6] - if n == 'VmRSS:': - rss = string.atoi(line[7:-3]) - if n == 'VmData': - data = string.atoi(line[8:-3]) - if n == 'VmStk:': - stack = string.atoi(line[7:-3]) + with open(procdir + '/status', 'r') as procstatus: + rss = 0 + data = 0 + stack = 0 + for line in procstatus: + n = line[0:6] + if n == 'VmRSS:': + rss = int(line[7:-3]) + if n == 'VmData': + data = int(line[8:-3]) + if n == 'VmStk:': + stack = int(line[7:-3]) self.memrss = max(self.memrss, rss) if self.memdata + self.memstack < data + stack: self.memdata = data @@ -134,26 +138,23 @@ class RunGuard: if self.writeto == None: f = sys.stdout else: - f = file(self.writeto, 'w') - - if self.usepickle: - obj = { 'exitcode' : self.exitcode, - 'sig' : self.sig, - 'timeused' : self.timeused, - 'memrss' : self.memrss, - 'memdata' : self.memdata, - 'memstack' : self.memstack } - pickle.dump(obj, f) - else: - print >>f, "exitcode: %d" % self.exitcode - print >>f, "sig: %d" % self.sig - print >>f, "time: %.3f" % self.timeused - print >>f, "rss: %d" % self.memrss - print >>f, "data: %d" % self.memdata - print >>f, "stack: %d" % self.memstack - - if self.writeto != None: f.close() + with open(self.writeto, 'w') as f: + if self.usepickle: + obj = { 'exitcode' : self.exitcode, + 'sig' : self.sig, + 'timeused' : self.timeused, + 'memrss' : self.memrss, + 'memdata' : self.memdata, + 'memstack' : self.memstack } + pickle.dump(obj, f) + else: + print("exitcode: %d" % self.exitcode, file=f) + print("sig: %d" % self.sig, file=f) + print("time: %.3f" % self.timeused, file=f) + print("rss: %d" % self.memrss, file=f) + print("data: %d" % self.memdata, file=f) + print("stack: %d" % self.memstack, file=f) if __name__ == '__main__': - os.umask(0002) + os.umask(0o002) RunGuard().run() diff --git a/utils/xmlrpc-debug-proxy.py b/utils/xmlrpc-debug-proxy.py index 3d30839..89dc129 100755 --- a/utils/xmlrpc-debug-proxy.py +++ b/utils/xmlrpc-debug-proxy.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 """HTTP debugging proxy @@ -34,108 +34,107 @@ http://localhost:5335/RPC2) import asynchat import asyncore import socket -import string -class proxy_server (asyncore.dispatcher): +class proxy_server(asyncore.dispatcher): - def __init__ (self, host, port): - asyncore.dispatcher.__init__ (self) - self.create_socket (socket.AF_INET, socket.SOCK_STREAM) - self.set_reuse_addr() - self.there = (host, port) - here = ('', port + 8000) - self.bind (here) - self.listen (5) - - def handle_accept (self): - print 'New connection' - proxy_receiver (self, self.accept()) + def __init__(self, host, port): + asyncore.dispatcher.__init__(self) + self.create_socket(socket.AF_INET, socket.SOCK_STREAM) + self.set_reuse_addr() + self.there = (host, port) + here = ('', port + 8000) + self.bind(here) + self.listen(5) + + def handle_accept(self): + print('New connection') + proxy_receiver(self, self.accept()) -class proxy_sender (asynchat.async_chat): +class proxy_sender(asynchat.async_chat): - "Sends data to the server" + "Sends data to the server" - def __init__ (self, receiver, address): - asynchat.async_chat.__init__ (self) - self.receiver = receiver - self.set_terminator (None) - self.create_socket (socket.AF_INET, socket.SOCK_STREAM) - self.buffer = '' - self.set_terminator ('\n') - self.connect (address) - - def handle_connect (self): - print 'Sender connected' - - def collect_incoming_data (self, data): - self.buffer = self.buffer + data - - def found_terminator (self): - data = self.buffer - self.buffer = '' - print (u'==> (%d) %s' % (self.id, unicode(repr(data), 'utf-8'))).encode('utf-8') - self.receiver.push (data + '\n') - - def handle_close (self): - print 'Sender closing (inbuf len %d (%s), ac_in %d, ac_out %d )' % ( - len( self.buffer ), - self.buffer, - len( self.ac_in_buffer ), - len( self.ac_out_buffer ) - ) + def __init__(self, receiver, address): + asynchat.async_chat.__init__(self) + self.receiver = receiver + self.set_terminator(None) + self.create_socket(socket.AF_INET, socket.SOCK_STREAM) + self.buffer = '' + self.set_terminator('\n') + self.connect(address) + + def handle_connect(self): + print('Sender connected') + + def collect_incoming_data(self, data): + self.buffer = self.buffer + data.decode('utf-8', errors='ignore') + + def found_terminator(self): + data = self.buffer + self.buffer = '' + print('==> (%d) %s' % (self.id, repr(data))) + self.receiver.push(data + '\n') + + def handle_close(self): + print('Sender closing (inbuf len %d (%s), ac_in %d, ac_out %d )' % ( + len(self.buffer), + self.buffer, + len(self.ac_in_buffer), + len(self.ac_out_buffer) + )) - if len( self.buffer ): - self.found_terminator() - - self.receiver.close_when_done() - self.close() + if len(self.buffer): + self.found_terminator() + + self.receiver.close_when_done() + self.close() -class proxy_receiver (asynchat.async_chat): +class proxy_receiver(asynchat.async_chat): - "Receives data from the caller" + "Receives data from the caller" - channel_counter = 0 - - def __init__ (self, server, (conn, addr)): - asynchat.async_chat.__init__ (self, conn) - self.set_terminator ('\n') - self.server = server - self.id = self.channel_counter - self.channel_counter = self.channel_counter + 1 - self.sender = proxy_sender (self, server.there) - self.sender.id = self.id - self.buffer = '' - - def collect_incoming_data (self, data): - self.buffer = self.buffer + data - - def found_terminator (self): - import re - data = re.sub( r'\:8080', '', self.buffer ) - data = re.sub( r'localhost', self.server.there[0], data ) - self.buffer = '' - print (u'<== (%d) %s' % (self.id, unicode(repr(data), 'utf-8'))).encode('utf-8') - self.sender.push (data + '\n') - - def handle_close (self): - print 'Receiver closing (inbuf len %d (%s), ac_in %d, ac_out %d )' % ( - len( self.buffer ), - self.buffer, - len( self.ac_in_buffer ), - len( self.ac_out_buffer ) - ) + channel_counter = 0 + + def __init__(self, server, conn_addr): + conn, addr = conn_addr + asynchat.async_chat.__init__(self, conn) + self.set_terminator('\n') + self.server = server + self.id = self.channel_counter + self.channel_counter = self.channel_counter + 1 + self.sender = proxy_sender(self, server.there) + self.sender.id = self.id + self.buffer = '' + + def collect_incoming_data(self, data): + self.buffer = self.buffer + data.decode('utf-8', errors='ignore') + + def found_terminator(self): + import re + data = re.sub(r'\:8080', '', self.buffer) + data = re.sub(r'localhost', self.server.there[0], data) + self.buffer = '' + print('<== (%d) %s' % (self.id, repr(data))) + self.sender.push(data + '\n') + + def handle_close(self): + print('Receiver closing (inbuf len %d (%s), ac_in %d, ac_out %d )' % ( + len(self.buffer), + self.buffer, + len(self.ac_in_buffer), + len(self.ac_out_buffer) + )) - if len( self.buffer ): - self.found_terminator() - - self.sender.close_when_done() - self.close() + if len(self.buffer): + self.found_terminator() + + self.sender.close_when_done() + self.close() if __name__ == '__main__': - import sys - import string - if len(sys.argv) < 3: - print 'Usage: %s ' % sys.argv[0] - else: - ps = proxy_server (sys.argv[1], string.atoi (sys.argv[2])) - asyncore.loop() + import sys + if len(sys.argv) < 3: + print('Usage: %s ' % sys.argv[0]) + else: + ps = proxy_server(sys.argv[1], int(sys.argv[2])) + asyncore.loop() \ No newline at end of file