Ejemplo n.º 1
0
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))
Ejemplo n.º 2
0
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"]))
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
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)