OnlineJudge/fps/parser.py

144 lines
6.2 KiB
Python
Raw Normal View History

2017-02-19 04:58:36 +00:00
#!/usr/bin/env python3
import copy
2017-01-31 09:19:34 +00:00
import base64
import random
import string
import xml.etree.ElementTree as ET
class FPSParser(object):
2017-02-19 04:58:36 +00:00
def __init__(self, fps_path):
self.fps_path = fps_path
2017-01-31 09:19:34 +00:00
@property
2017-02-19 04:58:36 +00:00
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
2017-01-31 09:19:34 +00:00
def parse(self):
2017-02-19 04:58:36 +00:00
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):
2017-01-31 09:19:34 +00:00
sample_start = True
test_case_start = True
2017-02-19 04:58:36 +00:00
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})
2017-02-27 04:54:25 +00:00
elif tag == "spj":
2017-02-19 04:58:36 +00:00
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
return problem
2017-01-31 09:19:34 +00:00
2017-02-19 04:58:36 +00:00
class FPSHelper(object):
def save_image(self, problem, base_dir, base_url):
_problem = copy.deepcopy(problem)
for img in _problem["images"]:
2017-01-31 09:19:34 +00:00
name = "".join(random.choice(string.ascii_lowercase + string.digits) for _ in range(12))
2017-02-19 04:58:36 +00:00
ext = os.path.splitext(img["src"])[1]
2017-01-31 09:19:34 +00:00
file_name = name + ext
2017-02-19 04:58:36 +00:00
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
2017-01-31 09:19:34 +00:00
2017-02-19 04:58:36 +00:00
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:
2017-01-31 09:19:34 +00:00
if input_preprocessor:
input_content = input_preprocessor(item["input"])
else:
input_content = item["input"]
f.write(input_content)
2017-02-19 04:58:36 +00:00
with open(os.path.join(base_dir, str(index + 1) + ".out"), "w", encoding="utf-8") as f:
2017-01-31 09:19:34 +00:00
if output_preprocessor:
output_content = output_preprocessor(item["output"])
else:
output_content = item["output"]
f.write(output_content)
if __name__ == "__main__":
2017-02-19 02:26:35 +00:00
import pprint
2017-02-19 04:58:36 +00:00
import os
2017-01-31 09:19:34 +00:00
parser = FPSParser("fps.xml")
2017-02-19 04:58:36 +00:00
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"))