From 5025d3fafe4963ca246b9006607cdc22ea373a6a Mon Sep 17 00:00:00 2001 From: object-Object Date: Tue, 1 Oct 2024 13:42:09 -0400 Subject: [PATCH] Add Hexical, fix error during registry load if lookup pattern page looks up a duplicate pattern that will fail later --- .vscode/launch.json | 11 ++++++ pyproject.toml | 1 + src/HexBug/hexdecode/buildpatterns.py | 37 +++++++++++++----- src/HexBug/hexdecode/registry.py | 2 + src/HexBug/utils/extra_patterns.py | 36 +++++++++++++++++- src/HexBug/utils/mods.py | 11 ++++++ src/HexBug/utils/special_handlers.py | 54 +++++++++++++++++++++++++++ 7 files changed, 141 insertions(+), 11 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..3dd7d08 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "configurations": [ + { + "name": "main.py", + "type": "debugpy", + "request": "launch", + "program": "main.py", + "console": "integratedTerminal" + } + ] +} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 1a19dd2..daa9891 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,6 +35,7 @@ runtime = [ "hexdoc-oneironaut==0.3.4.1.0", "hexdoc-hexdebug==0.2.2.1.19.2.1.0", "hexdoc-hexcellular==1.0.2.1.0.dev0", + "hexdoc-hexical==1.3.2.1.0.dev0", "hexdoc==1!0.1.0a18", "importlib_resources>=5.10", "jproperties~=2.1", diff --git a/src/HexBug/hexdecode/buildpatterns.py b/src/HexBug/hexdecode/buildpatterns.py index 8e14526..cbf66e8 100644 --- a/src/HexBug/hexdecode/buildpatterns.py +++ b/src/HexBug/hexdecode/buildpatterns.py @@ -32,6 +32,8 @@ from .hex_math import Direction from .registry import DuplicatePatternException, NormalPatternInfo, Registry +logger = logging.getLogger(__name__) + translation_regex = re.compile(r"hexcasting.spell.[a-z]+:(.+)") header_regex = re.compile(r"\s*\(.+\)") @@ -196,9 +198,14 @@ def _build_hexdoc_urls(registry: Registry, categories: Iterable[Category], mod: page, text, ): - pattern = registry.from_name[page.patterns[0].id.path] - if pattern.translation: - urls[pattern.translation] = value + pattern_id = page.patterns[0].id + if pattern := registry.from_name.get(pattern_id.path): + if pattern.translation: + urls[pattern.translation] = value + else: + logger.warning( + f"Unknown pattern for {mod.name} in lookup page #{entry.id.path}@{page.anchor}: {pattern_id}" + ) case PageWithPattern() if value := _build_hexdoc_pattern_urls( registry, @@ -271,12 +278,6 @@ async def build_registry(session: ClientSession) -> Registry | None: classname_to_path, file_path.stem, mod, file_path.as_posix() ) - for info in build_extra_patterns(name_to_translation): - if info.classname and info.class_mod and info.path: - _insert_classname( - classname_to_path, info.classname, info.class_mod, info.path - ) - for classname, path in mod_info.extra_classname_paths.items(): _insert_classname(classname_to_path, classname, mod, path) @@ -330,6 +331,13 @@ async def build_registry(session: ClientSession) -> Registry | None: # TODO: load classnames + # do this last so all the translations are loaded + for info in build_extra_patterns(name_to_translation): + if info.classname and info.class_mod and info.path: + _insert_classname( + classname_to_path, info.classname, info.class_mod, info.path + ) + # patterns and books duplicate_exceptions: list[DuplicatePatternException] = [] @@ -439,6 +447,17 @@ async def build_registry(session: ClientSession) -> Registry | None: if isinstance(mod_info, APIWithBookModInfo): _build_urls(registry, categories, mod) + # FIXME: hack + if ( + name_to_translation.get("get_light") + == name_to_translation.get("blockstate_glow") + == "Luminance Purification" + ): + name_to_translation |= { + "get_light": "Luminance Purification (get_light)", + "blockstate_glow": "Luminance Purification (blockstate_glow)", + } + for mod in HexdocMod: mod_info = mod.value diff --git a/src/HexBug/hexdecode/registry.py b/src/HexBug/hexdecode/registry.py index d20a625..6984929 100644 --- a/src/HexBug/hexdecode/registry.py +++ b/src/HexBug/hexdecode/registry.py @@ -108,6 +108,8 @@ async def generate_pattern( def parse_shorthand(self, shorthand: str) -> SpecialHandlerArgument: """Attempts to parse a full shorthand pattern into an argument for this pattern. + + Optional. """ return None diff --git a/src/HexBug/utils/extra_patterns.py b/src/HexBug/utils/extra_patterns.py index ee284a5..3cc4dbd 100644 --- a/src/HexBug/utils/extra_patterns.py +++ b/src/HexBug/utils/extra_patterns.py @@ -4,8 +4,12 @@ PatternInfo, SpecialHandlerPatternInfo, ) -from .mods import RegistryMod -from .special_handlers import MaskSpecialHandler, NumberSpecialHandler +from .mods import HexdocMod, RegistryMod +from .special_handlers import ( + MaskSpecialHandler, + NumberSpecialHandler, + TailDepthSpecialHandler, +) _extra_patterns: list[PatternInfo] | None = None @@ -74,5 +78,33 @@ def build_extra_patterns(name_to_translation: dict[str, str]) -> list[PatternInf shorthand_names=("book",), handler=MaskSpecialHandler(), ), + SpecialHandlerPatternInfo( + name="nephthys", + translation=name_to_translation.get("nephthys"), + mod=HexdocMod.Hexical, + path="src/main/java/miyucomics/hexical/casting/patterns/eval/OpNephthys.kt", + classname="OpNephthys", + class_mod=HexdocMod.Hexical, + is_great=False, + handler=TailDepthSpecialHandler( + direction=Direction.SOUTH_EAST, + prefix="deaqqd", + initial_depth=1, + ), + ), + SpecialHandlerPatternInfo( + name="sekhmet", + translation=name_to_translation.get("sekhmet"), + mod=HexdocMod.Hexical, + path="src/main/java/miyucomics/hexical/casting/patterns/eval/OpSekhmet.kt", + classname="OpSekhmet", + class_mod=HexdocMod.Hexical, + is_great=False, + handler=TailDepthSpecialHandler( + direction=Direction.SOUTH_WEST, + prefix="qaqdd", + initial_depth=0, + ), + ), ] return _extra_patterns diff --git a/src/HexBug/utils/mods.py b/src/HexBug/utils/mods.py index 014ab7b..7df3f33 100644 --- a/src/HexBug/utils/mods.py +++ b/src/HexBug/utils/mods.py @@ -566,6 +566,17 @@ class HexdocMod(Enum): modloaders=[FABRIC, QUILT], ) + Hexical = HexdocModInfo( + name="Hexical", + modid="hexical", + book_id="hexical:hexicalbook", + description="A fun addon containing genie lamps, mage blocks, specks, world scrying, and more!", + curseforge_url=None, + modrinth_slug="hexical", + icon_url="https://raw.githubusercontent.com/miyucomics/hexical/8ad329395acfdaa30db01d5ce00d61dd446b2db4/src/main/resources/assets/hexical/icon.png", + modloaders=[FABRIC, QUILT], + ) + ModInfo = RegistryModInfo | APIModInfo | HexdocModInfo Mod = RegistryMod | APIMod | HexdocMod diff --git a/src/HexBug/utils/special_handlers.py b/src/HexBug/utils/special_handlers.py index 2f43ca4..b958de3 100644 --- a/src/HexBug/utils/special_handlers.py +++ b/src/HexBug/utils/special_handlers.py @@ -1,3 +1,4 @@ +from dataclasses import dataclass from fractions import Fraction from typing import Any @@ -17,6 +18,8 @@ from .parse_rational import parse_rational from .patterns import parse_mask +# hex casting + class NumberSpecialHandler(SpecialHandler): def parse_pattern(self, direction: Direction, pattern: str) -> Any | None: @@ -68,3 +71,54 @@ async def generate_pattern( raise InvalidSpecialHandlerArgumentException(self.info.display_name) return [generate_bookkeeper(arg)] + + +# hexical + + +@dataclass(kw_only=True) +class TailDepthSpecialHandler(SpecialHandler): + direction: Direction + prefix: str + initial_depth: int + + def parse_pattern(self, direction: Direction, pattern: str) -> Any | None: + tail = pattern.removeprefix(self.prefix) + if tail == pattern: + return None + + depth = self.initial_depth + for index, char in enumerate(tail): + if char != "qe"[index % 2]: + return None + depth += 1 + + return depth + + def parse_argument(self, value: str) -> SpecialHandlerArgument: + # number, eg. Nephthys' Gambit: 3 + try: + return int(value) + except ValueError: + pass + + # visual tail, eg. Nephthys' Gambit: --- + if value == "-" * len(value): + return len(value) + + return None + + async def generate_pattern( + self, + registry: Registry, + arg: SpecialHandlerArgument, + should_align_horizontal: bool, + ) -> list[tuple[Direction, str]]: + if not isinstance(arg, int) or arg < self.initial_depth: + raise InvalidSpecialHandlerArgumentException(self.info.display_name) + + pattern = self.prefix + for index in range(arg - self.initial_depth): + pattern += "qe"[index % 2] + + return [(self.direction, pattern)]