def upload_file(id): """ 上传题目文件 参数: files: 上传列表 返回: { "code":0,//非0表示调用成功 "message":"qwq",//code非0的时候表示错误信息, "file_list":[{"name":"a.in","size":123456}]//现有的文件列表 } """ problem = db.session.query(Problem).filter( Problem.id == id) if problem.count() == 0: return make_response(-1, message="题目ID不存在") problem = problem.one() if not session.get("uid"): return make_response(-1, message="你没有权限执行此操作") user: User = db.session.query(User).filter( User.id == session.get("uid")).one() if not permission_manager.has_permission(user.id, "problem.manage") and user.id != problem.uploader_id: return make_response(-1, message="你没有权限执行此操作") import os import shutil import zipfile from io import BytesIO import pathlib upload_path = pathlib.Path(os.path.join( basedir, f"{config.UPLOAD_DIR}/%d" % id)) os.makedirs(upload_path, exist_ok=True) def handle_zipfile(fileobj): buf = BytesIO(fileobj.stream.read()) zipf = zipfile.ZipFile(buf) for f in zipf.filelist: if not f.is_dir() and "/" not in f.filename: zipf.extract(f, upload_path) new_file_name = secure_filename(f.filename) shutil.move(upload_path/f.filename, upload_path/new_file_name) with open(os.path.join(upload_path, new_file_name)+".lock", "w") as file: import time file.write(f"{time.time()}") for file in request.files: if request.files[file].filename.endswith(".zip"): handle_zipfile(request.files[file]) continue request.files[file].save(os.path.join( upload_path, secure_filename(file))) with open(os.path.join(upload_path, secure_filename(file))+".lock", "w") as file: import time file.write(f"{time.time()}") problem.files = generate_file_list(id) db.session.commit() return make_response(0, file_list=generate_file_list(id))
def remove_file(): """ 删除题目文件 参数: id:int 题目ID file:str 文件名 返回: { "code":0,//非0表示调用成功 "message":"qwq",//code非0的时候表示错误信息, "file_list":[{"name":"a.in","size":123456}]//现有的文件列表 } """ problem = db.session.query(Problem).filter( Problem.id == request.form["id"]) if problem.count() == 0: return make_response(-1, message="题目ID不存在") problem = problem.one() # if not problem.public and not session.get("uid"): # return make_response(-1, message="你没有权限执行此操作") if not session.get("uid"): return make_response(-1, message="你没有权限执行此操作") user: User = db.session.query(User).filter( User.id == session.get("uid")).one() if not permission_manager.has_permission( user.id, "problem.manage") and user.id != problem.uploader_id: return make_response(-1, message="你没有权限执行此操作") if not any((x["name"] == request.form["file"] for x in problem.files)): return make_response(-1, message="此文件不存在!") import os upload_path = os.path.join(basedir, f"{config.UPLOAD_DIR}/{request.form['id']}") os.makedirs(upload_path, exist_ok=True) try: os.remove(os.path.join(upload_path, request.form["file"])) os.remove(os.path.join(upload_path, request.form["file"] + ".lock")) except Exception as ex: pass problem.files = generate_file_list(request.form["id"]) def remove_and_return(seq, val): seq = seq.copy() if val in seq: seq.remove(val) return seq problem.downloads = remove_and_return(problem.downloads, request.form["file"]) problem.provides = remove_and_return(problem.provides, request.form["file"]) db.session.commit() return make_response(0, file_list=generate_file_list(request.form["id"]))
def regenerate_filelist(): """ 重新生成文件列表 problem_id:int 题目ID { "code":"" "data":[ "新生成的文件列表" ] } """ if not session.get("uid"): return make_response(-1, message="请先登录") user: User = User.by_id(session.get("uid")) problem: Problem = Problem.by_id(request.form["problem_id"]) if not permission_manager.has_permission(user.id, "problem.manage") and user.id != problem.uploader_id: return make_response(-1, message="你没有权限执行此操作") import pathlib import os import shutil path = pathlib.PurePath(config.UPLOAD_DIR)/str(problem.id) os.makedirs(path, exist_ok=True) for file in filter(lambda x: x.endswith(".lock"), os.listdir(path)): os.remove(path/file) for file in filter(lambda x: not x.endswith(".lock"), os.listdir(path)): with open(path/(file+".lock"), "w") as f: import time f.write(str(time.time())) from utils import generate_file_list file_list = generate_file_list(problem.id) file_list.sort(key=lambda x: x["name"]) problem.files = file_list db.session.commit() return make_response(0, data=file_list)
def import_from_syzoj(url: str, willPublic: bool): """ 从SYZOJ导入题目 参数: url:str SYZOJ题目URL willPublic:int 新题目是否公开 返回 { "code":0, "uuid":'用于websocket的uuid', "message":"" } """ import urllib import tempfile import pathlib import traceback import zipfile import shutil import os import yaml import requests from io import BytesIO from utils import decode_json if not session.get("uid"): return make_response(-1, message="请先登录") user: User = User.by_id(session.get("uid")) if not permission_manager.has_any_permission(user.id, "problem.create", "problem.manage"): return make_response(-1, message="你没有权限执行此操作") try: with requests.get(f"{url}/export") as urlf: data = decode_json(urlf.content.decode())["obj"] print("JSON data: {}".format(data)) import datetime problem = Problem(uploader_id=user.id, title=data["title"], content=data["description"], input_format=data["input_format"], output_format=data["output_format"], hint=data["limit_and_hint"], using_file_io=data["file_io"], input_file_name=data["file_io_input_name"], output_file_name=data["file_io_output_name"], create_time=datetime.datetime.now() ) if willPublic: if not permission_manager.has_any_permission(user.id, "problem.publicize", "problem.manage"): return make_response(-1, message="你没有权限公开题目") problem.public = True problem.example = [] problem.hint = "### 样例\n" + \ data["example"]+"\n\n### Hint\n"+problem.hint time_limit = int(data["time_limit"]) memory_limit = int(data["memory_limit"]) db.session.add(problem) db.session.commit() work_dir = pathlib.PurePath(tempfile.mkdtemp()) with requests.get(f"{url}/testdata/download") as urlf: pack = zipfile.ZipFile(BytesIO(urlf.content)) pack.extractall(work_dir) pack.close() problem_data_dir = pathlib.PurePath( f"{config.UPLOAD_DIR}/{problem.id}") shutil.rmtree(problem_data_dir, ignore_errors=True) shutil.copytree(work_dir, problem_data_dir) shutil.rmtree(work_dir) # 更换新的word_dir work_dir = problem_data_dir for file in filter(lambda x: x.endswith(".lock"), os.listdir(work_dir)): os.remove(work_dir/file) file_list = [] for file in filter(lambda x: not x.endswith(".lock"), os.listdir(work_dir)): with open(work_dir/(file+".lock"), "w") as f: import time last_modified_time = time.time() f.write(str(last_modified_time)) file_list.append({ "name": file, "size": os.path.getsize(work_dir/file), "last_modified_time": last_modified_time }) problem.files = file_list pure_file_list = list(map(lambda x: x["name"], file_list)) for x in pure_file_list: if x.startswith("spj_"): problem.spj_filename = x break auto_generate = True subtasks = [] if os.path.exists(work_dir/"data.yml"): # 存在data.yml with open(work_dir/"data.yml", "r", encoding="utf-8") as f: data_obj = yaml.safe_load(f) # data.yml中钦定spj if "specialJudge" in data_obj: new_spj_filename = work_dir/( "spj_"+data_obj["specialJudge"]["language"]+"."+data_obj["specialJudge"]["fileName"].split(".")[-1]) print(new_spj_filename) print(work_dir/data_obj["specialJudge"]["fileName"]) shutil.move( work_dir/data_obj["specialJudge"]["fileName"], new_spj_filename) problem.spj_filename = new_spj_filename.name if "subtasks" in data_obj: auto_generate = False def make_input(x): return data_obj["inputFile"].replace("#", str(x)) def make_output(x): return data_obj["outputFile"].replace("#", str(x)) for i, subtask in enumerate(data_obj["subtasks"]): print(subtask) subtasks.append({ "name": f"Subtask{i+1}", "score": int(subtask["score"]), "method": subtask["type"], "time_limit": time_limit, "memory_limit": memory_limit, "testcases": [] }) testcases = subtasks[-1]["testcases"] score = subtasks[-1]["score"]//len(subtask["cases"]) for testcase in subtask["cases"]: testcases.append({ "input": make_input(testcase), "output": make_output(testcase), "full_score": score }) testcases[-1]["full_score"] = subtasks[-1]["score"] - \ score*(len(testcases)-1) if auto_generate: # 不存在data.yml,直接生成子任务 input_files = list( filter(lambda x: x.endswith(".in"), pure_file_list)) output_files = list( filter(lambda x: x.endswith(".out") or x.endswith(".ans"), pure_file_list)) if len(input_files) == len(output_files): pass for i, file in enumerate(input_files): pure_file_name = file[:file.rindex(".")] subtasks.append({ "name": f"Subtask{i+1}", "score": 100//len(input_files), "method": "sum", "time_limit": time_limit, "memory_limit": memory_limit, "testcases": [{"full_score": 100//len(input_files), "input": file, "output": f"{pure_file_name}.ans" if f"{pure_file_name}.ans" in output_files else f"{pure_file_name}.out"}], "comment": "" }) diff = 100-sum(map(lambda x: x["score"], subtasks)) subtasks[-1]["score"] += diff subtasks[-1]["testcases"][0]["full_score"] += diff for file in filter(lambda x: x.endswith(".lock"), os.listdir(work_dir)): os.remove(work_dir/file) for file in filter(lambda x: not x.endswith(".lock"), os.listdir(work_dir)): with open(work_dir/(file+".lock"), "w") as f: import time last_modified_time = time.time() f.write(str(last_modified_time)) problem.files = generate_file_list(problem.id) problem.subtasks = subtasks db.session.commit() except Exception: print(traceback.format_exc()) return make_response(-1, message=traceback.format_exc()) return make_response(0, problem_id=problem.id)