update fps parser

This commit is contained in:
virusdefender 2017-02-19 12:58:36 +08:00
parent a16701a320
commit bb3d4f7f02

View File

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