From bb3d4f7f02e833f1f09da622e41d00a98c2e9783 Mon Sep 17 00:00:00 2001 From: virusdefender Date: Sun, 19 Feb 2017 12:58:36 +0800 Subject: [PATCH] update fps parser --- fps/parser.py | 206 +++++++++++++++++++++++++++----------------------- 1 file changed, 110 insertions(+), 96 deletions(-) diff --git a/fps/parser.py b/fps/parser.py index 369a5824..44b37da5 100644 --- a/fps/parser.py +++ b/fps/parser.py @@ -1,119 +1,126 @@ +#!/usr/bin/env python3 +import copy import base64 -import os import random import string import xml.etree.ElementTree as ET class FPSParser(object): - def __init__(self, path): - self.path = path - self._root = None - self._parse_result = None + def __init__(self, fps_path): + self.fps_path = fps_path @property - def root(self): - if self._root is None: - self._root = ET.ElementTree(file=self.path).getroot() - if self._root.attrib["version"] != "1.2": - raise ValueError("Unsupported version") - return self._root + def _root(self): + root = ET.ElementTree(file=self.fps_path).getroot() + version = root.attrib.get("version", "No Version") + if version not in ["1.1", "1.2"]: + raise ValueError("Unsupported version '" + version + "'") + return root def parse(self): - problem = {"title": None, "description": None, - "memory_limit": {"unit": None, "value": None}, - "time_limit": {"unit": None, "value": None}, - "images": [], "input": None, "output": None, "samples": [], - "append": [], "template": [], "prepend": [], - "test_cases": [], "hint": None, "source": None, - "spj": [], "solution": []} + ret = [] + for node in self._root: + if node.tag == "item": + ret.append(self._parse_one_problem(node)) + return ret + + def _parse_one_problem(self, node): sample_start = True test_case_start = True - for node in self.root: - if node.tag == "item": - for item in node: - tag = item.tag - if tag in ["title", "description", "input", "output", "hint", "source"]: - problem[item.tag] = item.text - elif tag == "time_limit": - unit = item.attrib.get("unit", "s") - if unit not in ["s", "ms"]: - raise ValueError("Invalid time limit unit") - problem["time_limit"]["unit"] = item.attrib.get("unit", "s") - value = int(item.text) - if value <= 0: - raise ValueError("Invalid time limit value") - problem["time_limit"]["value"] = value - elif tag == "memory_limit": - unit = item.attrib.get("unit", "MB") - if unit not in ["MB", "KB", "mb", "kb"]: - raise ValueError("Invalid memory limit unit") - problem["memory_limit"]["unit"] = unit.upper() - value = int(item.text) - if value <= 0: - raise ValueError("Invalid memory limit value") - problem["memory_limit"]["value"] = value - elif tag in ["template", "append", "prepend", "solution", "spj"]: - lang = item.attrib.get("language") - if not lang: - raise ValueError("Invalid " + tag + ", language name is missed") - problem[tag].append({"language": lang, "code": item.text}) - elif tag == "img": - problem["images"].append({"src": None, "blob": None}) - for child in item: - if child.tag == "src": - problem["images"][-1]["src"] = child.text - elif child.tag == "base64": - problem["images"][-1]["blob"] = base64.b64decode(child.text) - elif tag == "sample_input": - if not sample_start: - raise ValueError("Invalid xml, error 'sample_input' tag order") - problem["samples"].append({"input": item.text, "output": None}) - sample_start = False - elif tag == "sample_output": - if sample_start: - raise ValueError("Invalid xml, error 'sample_output' tag order") - problem["samples"][-1]["output"] = item.text - sample_start = True - elif tag == "test_input": - if not test_case_start: - raise ValueError("Invalid xml, error 'test_input' tag order") - problem["test_cases"].append({"input": item.text, "output": None}) - test_case_start = False - elif tag == "test_output": - if test_case_start: - raise ValueError("Invalid xml, error 'test_output' tag order") - problem["test_cases"][-1]["output"] = item.text - test_case_start = True + problem = {"title": "No Title", "description": "No Description", + "input": "No Input Description", + "output": "No Output Description", + "memory_limit": {"unit": None, "value": None}, + "time_limit": {"unit": None, "value": None}, + "samples": [], "images": [], "append": [], + "template": [], "prepend": [], "test_cases": [], + "hint": None, "source": None, "spj": None, "solution": []} + for item in node: + tag = item.tag + if tag in ["title", "description", "input", "output", "hint", "source"]: + problem[item.tag] = item.text + elif tag == "time_limit": + unit = item.attrib.get("unit", "s") + if unit not in ["s", "ms"]: + raise ValueError("Invalid time limit unit") + problem["time_limit"]["unit"] = item.attrib.get("unit", "s") + value = int(item.text) + if value <= 0: + raise ValueError("Invalid time limit value") + problem["time_limit"]["value"] = value + elif tag == "memory_limit": + unit = item.attrib.get("unit", "MB") + if unit not in ["MB", "KB", "mb", "kb"]: + raise ValueError("Invalid memory limit unit") + problem["memory_limit"]["unit"] = unit.upper() + value = int(item.text) + if value <= 0: + raise ValueError("Invalid memory limit value") + problem["memory_limit"]["value"] = value + elif tag in ["template", "append", "prepend", "solution"]: + lang = item.attrib.get("language") + if not lang: + raise ValueError("Invalid " + tag + ", language name is missed") + problem[tag].append({"language": lang, "code": item.text}) + elif tag == 'spj': + lang = item.attrib.get("language") + if not lang: + raise ValueError("Invalid spj, language name if missed") + problem["spj"] = {"language": lang, "code": item.text} + elif tag == "img": + problem["images"].append({"src": None, "blob": None}) + for child in item: + if child.tag == "src": + problem["images"][-1]["src"] = child.text + elif child.tag == "base64": + problem["images"][-1]["blob"] = base64.b64decode(child.text) + elif tag == "sample_input": + if not sample_start: + raise ValueError("Invalid xml, error 'sample_input' tag order") + problem["samples"].append({"input": item.text, "output": None}) + sample_start = False + elif tag == "sample_output": + if sample_start: + raise ValueError("Invalid xml, error 'sample_output' tag order") + problem["samples"][-1]["output"] = item.text + sample_start = True + elif tag == "test_input": + if not test_case_start: + raise ValueError("Invalid xml, error 'test_input' tag order") + problem["test_cases"].append({"input": item.text, "output": None}) + test_case_start = False + elif tag == "test_output": + if test_case_start: + raise ValueError("Invalid xml, error 'test_output' tag order") + problem["test_cases"][-1]["output"] = item.text + test_case_start = True - self._parse_result = problem - return problem - raise ValueError("Invalid xml") + return problem - def save_image(self, file_base_path, base_url): - if not self._parse_result: - self.parse() - for item in self._parse_result["images"]: + +class FPSHelper(object): + def save_image(self, problem, base_dir, base_url): + _problem = copy.deepcopy(problem) + for img in _problem["images"]: name = "".join(random.choice(string.ascii_lowercase + string.digits) for _ in range(12)) - ext = os.path.splitext(item["src"])[1] + ext = os.path.splitext(img["src"])[1] file_name = name + ext - with open(os.path.join(file_base_path, file_name), "wb") as f: - f.write(item["blob"]) - desc = self._parse_result["description"].replace(item["src"], os.path.join(base_url, file_name)) - self._parse_result["description"] = desc - return self._parse_result + with open(os.path.join(base_dir, file_name), "wb") as f: + f.write(img["blob"]) + for item in ["description", "input", "output"]: + _problem[item] = _problem[item].replace(img["src"], os.path.join(base_url, file_name)) + return _problem - def save_test_case(self, file_base_path, input_preprocessor=None, output_preprocessor=None): - if not self._parse_result: - self.parse() - for index, item in enumerate(self._parse_result["test_cases"]): - with open(os.path.join(file_base_path, str(index + 1) + ".in"), "w") as f: + def save_test_case(self, problem, base_dir, input_preprocessor=None, output_preprocessor=None): + for index, item in enumerate(problem["test_cases"]): + with open(os.path.join(base_dir, str(index + 1) + ".in"), "w", encoding="utf-8") as f: if input_preprocessor: input_content = input_preprocessor(item["input"]) else: input_content = item["input"] f.write(input_content) - with open(os.path.join(file_base_path, str(index + 1) + ".out"), "w") as f: + with open(os.path.join(base_dir, str(index + 1) + ".out"), "w", encoding="utf-8") as f: if output_preprocessor: output_content = output_preprocessor(item["output"]) else: @@ -123,7 +130,14 @@ class FPSParser(object): if __name__ == "__main__": import pprint + import os + parser = FPSParser("fps.xml") - parser.parse() - pprint.pprint(parser.save_image("/tmp", "/static/img")) - parser.save_test_case("/tmp") + helper = FPSHelper() + problems = parser.parse() + for index, problem in enumerate(problems): + path = os.path.join("/tmp/", str(index + 1)) + os.mkdir(path) + helper.save_test_case(problem, path) + + pprint.pprint(helper.save_image(problem, "/tmp", "/static/img"))