1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
| import io import json import sys import tkinter as tk import zipfile from tkinter import filedialog
from FlexMenu import FlexMenu
def replace_single_quotes(s): """ 安全地将Python单引号替换为JSON双引号 处理各种边界情况 """ result = [] in_string = False quote_char = None
for i, char in enumerate(s): if not in_string and char in ("'", '"'): # 字符串开始 in_string = True quote_char = char result.append('"') # JSON总是用双引号 elif in_string and char == quote_char: # 字符串结束 in_string = False result.append('"') elif in_string and char == "\\" and i + 1 < len(s): # 处理转义字符 result.append(char) result.append(s[i + 1]) # 跳过下一个字符 continue else: result.append(char)
return "".join(result)
def clear_screen(): print(f"\033[A", end="") print("\033[0J", end="") sys.stdout.flush()
def edit_test(testid): global test_in, test_out while True: which_file_menu = FlexMenu("请选择要编辑的文件", ["输入文件", "输出文件"]) which_file = which_file_menu.run() if which_file == -1: break if which_file == 0: while True: if test_in[testid]: options = [ (i[:20] + ("..." if len(i) > 20 else "")) for i in test_in[testid] ] else: options = ["(空)"] options.append("新建一行")
which_line_menu = FlexMenu("请选择要编辑的行", options) which_line = which_line_menu.run() if which_line == -1: break if which_line == len(options) - 1: # "新建一行"选项 inp = input("请输入新内容: ") clear_screen() if inp: test_in[testid].append(inp) elif len(test_in[testid]) != 0: print(which_line) print(f"当前内容: {test_in[testid][which_line]}") inp = input("输入新内容 (直接回车删除此行): ") clear_screen() if inp: test_in[testid][which_line] = inp else: del test_in[testid][which_line] else: # 编辑输出文件 while True: if test_out[testid]: options = [ (i[:20] + ("..." if len(i) > 20 else "")) for i in test_out[testid] ] else: options = ["(空)"] options.append("新建一行")
which_line_menu = FlexMenu("请选择要编辑的行", options) which_line = which_line_menu.run() if which_line == -1: break if which_line == len(options) - 1: # "新建一行"选项 inp = input("请输入新内容: ") clear_screen() if inp: test_out[testid].append(inp) else: print(f"当前内容: {test_out[testid][which_line]}") inp = input("输入新内容 (直接回车删除此行): ") clear_screen() if inp: test_out[testid][which_line] = inp else: del test_out[testid][which_line]
test_in = [] test_out = []
while True: cmd_menu = FlexMenu("测试点编辑器", ["编辑测试点", "生成压缩包", "直接设置"]) cmd = cmd_menu.run()
if cmd == -1: sys.exit()
if cmd == 2: which_var_menu = FlexMenu("哪一个变量", ["输入", "输出"]) which_var = which_var_menu.run()
if which_var != -1: inp = input( f"请输入 {'输入' if which_var == 0 else '输出'} 变量的新内容 (格式: [[输入1行1, 输入1行2, ...], [输入2行1, 输入2行2, ...], ... ]): " ) clear_screen() if inp: new_inp = [] try: inp = json.loads(s=replace_single_quotes(inp)) except: pass else: if isinstance(inp, list): for test in inp: if not isinstance(test, list): continue new_inp.append([]) for line in test: try: str(line) except: pass else: new_inp[-1].append(str(line))
if new_inp: if which_var == 0: test_in = new_inp else: test_out = new_inp
if cmd == 0: # 编辑测试点 while True: if test_in: options = [ f"测试点 #{i+1} (输入行数:{len(test_in[i])}, 输出行数:{len(test_out[i])})" for i in range(len(test_in)) ] else: options = ["(暂无测试点)"] options.append("新建测试点")
which_test_menu = FlexMenu("请选择测试点", options) which_test = which_test_menu.run()
if which_test == -1: break
if which_test == len(options) - 1: # "新建测试点"选项 test_in.append([]) test_out.append([]) edit_test(len(test_in) - 1) # 编辑新建的测试点 elif which_test < len(test_in): edit_test(which_test) # 编辑现有测试点
if cmd == 1: # 生成压缩包 if not test_in: print("没有测试点可以生成压缩包!") continue
zip_buffer = io.BytesIO()
with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file: for i in range(len(test_in)): in_content = "\n".join(test_in[i]).encode("utf-8") out_content = "\n".join(test_out[i]).encode("utf-8")
zip_file.writestr(f"{i+1}.in", in_content) zip_file.writestr(f"{i+1}.out", out_content)
zip_buffer.seek(0) zip_data = zip_buffer.getvalue()
print(f"生成的ZIP文件包含 {len(test_in)} 个测试点,大小: {len(zip_data)} 字节")
root = tk.Tk() root.withdraw()
file_path = filedialog.asksaveasfilename( title="选择 ZIP 文件保存位置", defaultextension=".zip", filetypes=[("ZIP 压缩包文件", "*.zip"), ("所有文件", "*.*")], )
if file_path: try: with open(file_path, "wb") as f: f.write(zip_data) print(f"ZIP 文件已保存至: {file_path}") print("可以直接上传到洛谷测试用例") except Exception as e: print(f"保存失败: {e}") else: print("保存已取消")
root.destroy()
|