import io import logging import textwrap from collections import namedtuple import flask import lxml.etree as xmltree import mermaid from . import core, gamedata pth_upgrade_schema = core.path_appdir / "basepak/rules/schemas/upgrades.xsd" doc_upgrade_schema = xmltree.parse(pth_upgrade_schema.as_posix()) upgrade_schema = xmltree.XMLSchema(doc_upgrade_schema) upgrade_schema_parser = xmltree.XMLParser(schema=upgrade_schema) UpgradeData = namedtuple("UpgradeData", ["id", "name", "desc", "requires"]) ## \brief Renders an upgrade tree. # \param tree The upgrade tree to retrieve. # \api{GET} /upgrades/`` # \return An SVG. @core.app.route("/upgrades/") def get_upgrade_tree(tree): buf_mmd = io.StringIO() rulefile = xmltree.parse(gamedata.vfs.open(f"/rules/upgrades/{tree}.xml"), upgrade_schema_parser) ruleset = rulefile.getroot() hnd_treedata = ruleset.xpath("./upgrades:TreeData", namespaces=core.xml_namespaces)[0] hnd_name = hnd_treedata.xpath("./upgrades:Name", namespaces=core.xml_namespaces)[0] hnd_primary_color = hnd_treedata.xpath("./upgrades:PrimaryColor", namespaces=core.xml_namespaces)[0] buf_mmd.write(textwrap.dedent(f""" ---- title: {hnd_name.text} theme: base themeVariables: primaryColor: {hnd_primary_color.text} ---- flowchart LR """)) tree_upgrades = [] for hnd_upgrade in ruleset.iter("{seagull:rules/upgrades}Upgrade"): hnd_id = hnd_upgrade.xpath("./upgrades:Id", namespaces=core.xml_namespaces)[0] hnd_upgrade_name = hnd_upgrade.xpath("./upgrades:Name", namespaces=core.xml_namespaces)[0] hnd_desc = hnd_upgrade.xpath("./upgrades:Desc", namespaces=core.xml_namespaces)[0] try: hnd_requires = hnd_upgrade.xpath("./upgrades:Requirements", namespaces=core.xml_namespaces)[0] require_list = [elem.text for elem in hnd_requires.iter("{seagull:rules/upgrades}Require")] except IndexError: require_list = [] upgrade = UpgradeData( id=hnd_id.text, name=hnd_upgrade_name.text, desc=hnd_desc.text, requires=require_list ) tree_upgrades.append(upgrade) tiers = {} dependency_lines = [] for upgrade in tree_upgrades: deptier = 0 buf_mmd.write(f" {upgrade.id}@{{label: \"{upgrade.name}\"}}\n") collected_tiers = [] for require in upgrade.requires: if require in tiers: collected_tiers.append(tiers[require]) dependency_lines.append(f" {require} --> {upgrade.id}\n") if len(collected_tiers) > 0: deptier = max(collected_tiers) tiers[upgrade.id] = deptier + 1 for line in dependency_lines: buf_mmd.write(line) buf_mmd.seek(0) print(buf_mmd.read()) return get_upgrade_tree_mmd(tree) # TEMP def get_upgrade_tree_mmd(tree): if not gamedata.vfs.exists(f"upgrades/{tree}.mmd"): return flask.make_response("No Upgrade Tree", 404) with gamedata.vfs.open(f"upgrades/{tree}.mmd") as fd_upgradetree: mmd_upgradetree = mermaid.Mermaid(fd_upgradetree.read(), height=400) return mmd_upgradetree.svg_response.content