From 330846a4a5b4a31d8b30393d65d94e478c2f2f01 Mon Sep 17 00:00:00 2001 From: david-ajax Date: Sat, 8 Nov 2025 13:23:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20Recognition=20=E9=83=A8?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/heurams/interface/shim.py | 6 +- src/heurams/interface/widgets/basic_puzzle.py | 2 +- src/heurams/interface/widgets/cloze_puzzle.py | 2 +- src/heurams/interface/widgets/recognition.py | 84 +++++++++++-------- src/heurams/kernel/particles/atom.py | 62 +++++++++++--- src/heurams/kernel/reactor/fission.py | 2 +- src/heurams/kernel/reactor/phaser.py | 2 +- tests/test_working_particles.py | 2 +- 8 files changed, 108 insertions(+), 54 deletions(-) diff --git a/src/heurams/interface/shim.py b/src/heurams/interface/shim.py index 960b527..6ee4f0e 100644 --- a/src/heurams/interface/shim.py +++ b/src/heurams/interface/shim.py @@ -10,10 +10,10 @@ def clear(): staging = dict() def deploy_to_electron(): for atom_ident, quality in staging.items(): - if pt.atom_registry[atom_ident].register['electron'].is_activated: - pt.atom_registry[atom_ident].register['electron'].revisor(quality=quality) + if pt.atom_registry[atom_ident].registry['electron'].is_activated: + pt.atom_registry[atom_ident].registry['electron'].revisor(quality=quality) else: - pt.atom_registry[atom_ident].register['electron'].revisor(quality=quality, is_new_activation=True) + pt.atom_registry[atom_ident].registry['electron'].revisor(quality=quality, is_new_activation=True) clear() puzzle2widget = { pz.RecognitionPuzzle: pzw.Recognition, diff --git a/src/heurams/interface/widgets/basic_puzzle.py b/src/heurams/interface/widgets/basic_puzzle.py index 75db2e0..55ae0bc 100644 --- a/src/heurams/interface/widgets/basic_puzzle.py +++ b/src/heurams/interface/widgets/basic_puzzle.py @@ -25,7 +25,7 @@ class BasicEvaluation(BasePuzzleWidget): } def compose(self): - yield Label(self.atom.register["nucleon"]["content"], id="main") + yield Label(self.atom.registry["nucleon"]["content"], id="main") with Container(id="button_container"): btn = {} btn["5"] = Button( diff --git a/src/heurams/interface/widgets/cloze_puzzle.py b/src/heurams/interface/widgets/cloze_puzzle.py index 8302110..f8f9942 100644 --- a/src/heurams/interface/widgets/cloze_puzzle.py +++ b/src/heurams/interface/widgets/cloze_puzzle.py @@ -23,7 +23,7 @@ class ClozePuzzle(BasePuzzleWidget): self._work() def _work(self): - self.puzzle = pz.ClozePuzzle(text=self.atom.register["nucleon"]["content"], min_denominator=2) + self.puzzle = pz.ClozePuzzle(text=self.atom.registry["nucleon"]["content"], min_denominator=2) self.puzzle.refresh() self.ans = copy.copy(self.puzzle.answer) random.shuffle(self.ans) diff --git a/src/heurams/interface/widgets/recognition.py b/src/heurams/interface/widgets/recognition.py index faaa576..18fc42a 100644 --- a/src/heurams/interface/widgets/recognition.py +++ b/src/heurams/interface/widgets/recognition.py @@ -24,56 +24,72 @@ import copy from .base_puzzle_widget import BasePuzzleWidget from heurams.context import config_var from .. import shim +from typing import TypedDict, List + +class RecognitionConfig(TypedDict): + __origin__: str + __hint__: str + primary: str + secondary: List[str] + top_dim: List[str] class Recognition(BasePuzzleWidget): - def __init__(self, *children: Widget, atom: pt.Atom, name: str | None = None, id: str | None = None, classes: str | None = None, disabled: bool = False, markup: bool = True) -> None: - super().__init__(*children, atom=atom, name=name, id=id, classes=classes, disabled=disabled, markup=markup) + rate_mapping = { + "ok": 5 + } + + def __init__(self, *children: Widget, atom: pt.Atom, alia: str = "", name: str | None = None, id: str | None = None, classes: str | None = None, disabled: bool = False, markup: bool = True) -> None: + super().__init__(*children, atom=atom, name=name, id=id, classes=classes, disabled=disabled, markup=markup) + if alia == "": + alia = "Recognition" + self.alia = alia def compose(self): - with Center(): - yield Static(f"[dim]{self.atom.register['nucleon']['translation']}[/]") - yield Label(f"") - s = str(self.atom.register['nucleon']["content"]) + cfg: RecognitionConfig = self.atom.registry["orbital"]["puzzles"][self.alia] + delim = self.atom.registry['nucleon'].metadata["formation"]["delimiter"] replace_dict = { ", ": ",", ". ": ".", "; ": ";", ": ": ":", - "/,": ",", - "./": ".", - "/;": ";", - ";/": ";", - ":/": ":", + f"{delim},": ",", + f".{delim}": ".", + f"{delim};": ";", + f";{delim}": ";", + f":{delim}": ":", } + + nucleon = self.atom.registry['nucleon'] + metadata = self.atom.registry['nucleon'].metadata + primary = nucleon[cfg["primary"]] + + with Center(): + yield Static(f"[dim]{nucleon[cfg["top_dim"]]}[/]") + yield Label(f"") + for old, new in replace_dict.items(): - s = s.replace(old, new) - result = re.split(r"(?<=[,;:|])", s.replace("/", " ")) - for i in result: + primary = primary.replace(old, new) + primary_splited = re.split(r"(?<=[,;:|])", cfg['primary']) + for item in primary_splited: with Center(): yield Label( - f"[b][b]{i.replace('/', ' ')}[/][/]", - id="sentence" + str(hash(i)), + f"[b][b]{item.replace(delim, ' ')}[/][/]", + id="sentence" + str(hash(item)), ) - - # 处理orbital/展示配置 - for i in - # eval 环境设置 - nucleon = self.atom.register['nucleon'] - default = config_var.get()["puzzles"] - metadata = nucleon.metadata + for item in nucleon[cfg["secondary"]]: + if isinstance(item, list): + for j in item: + yield Markdown(f"### {metadata["annotation"][item]}: {j}") + continue + if isinstance(item, Dict): + total = "" + for j, k in item.items(): # type: ignore + total += f"> **{j}**: {k} \n" + yield Markdown(total) + if isinstance(item, str): + yield Markdown(item) - for i in self.atom.register["orbital"] ["testdata"]["additional_inf"]: - if self.atom.register['nucleon'][i]: - if isinstance(self.atom.register['nucleon'][i], list): - for j in self.atom.register['nucleon'][i]: - yield Markdown(f"### {self.atom.register["orbital"] ['keydata'][i]}: {j}") - continue - if isinstance(self.atom.register['nucleon'][i], Dict): - t = "" - for j, k in self.atom.register['nucleon'][i].items(): # type: ignore - t += f"> **{j}**: {k} \n" - yield Markdown(t, id="tran") with Center(): yield Button("我已知晓", id="ok") diff --git a/src/heurams/kernel/particles/atom.py b/src/heurams/kernel/particles/atom.py index 51daa20..5d3ab77 100644 --- a/src/heurams/kernel/particles/atom.py +++ b/src/heurams/kernel/particles/atom.py @@ -7,6 +7,7 @@ import typing import toml import json import bidict +from heurams.context import config_var class AtomRegister(TypedDict): nucleon: Nucleon @@ -32,7 +33,8 @@ class Atom(): def __init__(self, ident = ""): self.ident = ident atom_registry[ident] = self - self.register: AtomRegister = { # type: ignore + # self.is_evaled = False + self.registry: AtomRegister = { # type: ignore "nucleon": None, "nucleon_path": None, "nucleon_fmt": "toml", @@ -43,37 +45,73 @@ class Atom(): "orbital_path": None, # 允许设置为 None, 此时使用 nucleon 文件内的推荐配置 "orbital_fmt": "toml", } + self.do_eval() def link(self, key, value): - if key in self.register.keys(): - self.register[key] = value + if key in self.registry.keys(): + self.registry[key] = value + self.do_eval() else: raise ValueError("不受支持的原子元数据链接操作") + def do_eval(self): + """ + 执行并以结果替换当前单元的所有 eval 语句 + TODO: 带有限制的 eval, 异步/多线程执行避免堵塞 + """ + # eval 环境设置 + def eval_with_env(s: str): + nucleon = self.registry['nucleon'] + default = config_var.get()["puzzles"] + metadata = nucleon.metadata + try: + ret = str(eval(s)) + except: + ret = "此 eval 实例发生错误" + return ret + + def traverse(data, modifier): + if isinstance(data, dict): + for key, value in data.items(): + data[key] = traverse(value, modifier) + return data + elif isinstance(data, list): + for i, item in enumerate(data): + data[i] = traverse(item, modifier) + return data + elif isinstance(data, tuple): + return tuple(traverse(item, modifier) for item in data) + else: + return modifier(data) + + traverse(self.registry["nucleon"], eval_with_env) + traverse(self.registry["orbital"], eval_with_env) + + def persist(self, key): - path: pathlib.Path | None = self.register[key + "_path"] + path: pathlib.Path | None = self.registry[key + "_path"] if isinstance(path, pathlib.Path): path = typing.cast(pathlib.Path, path) path.parent.mkdir(parents=True, exist_ok=True) - if self.register[key + "_fmt"] == "toml": + if self.registry[key + "_fmt"] == "toml": with open(path, "w") as f: - toml.dump(self.register[key], f) - elif self.register[key + "_fmt"] == "json": + toml.dump(self.registry[key], f) + elif self.registry[key + "_fmt"] == "json": with open(path, "w") as f: - json.dump(self.register[key], f) + json.dump(self.registry[key], f) else: raise KeyError("不受支持的持久化格式") else: raise TypeError("对未初始化的路径对象操作") def __getitem__(self, key): - if key in self.register: - return self.register[key] + if key in self.registry: + return self.registry[key] raise KeyError(f"不支持的键: {key}") def __setitem__(self, key, value): - if key in self.register: - self.register[key] = value + if key in self.registry: + self.registry[key] = value else: raise KeyError(f"不支持的键: {key}") diff --git a/src/heurams/kernel/reactor/fission.py b/src/heurams/kernel/reactor/fission.py index 8507198..26702ed 100644 --- a/src/heurams/kernel/reactor/fission.py +++ b/src/heurams/kernel/reactor/fission.py @@ -7,7 +7,7 @@ class Fission(): """裂变器: 单原子调度展开器""" def __init__(self, atom: pt.Atom, phase = PhaserState.RECOGNITION): self.atom = atom - self.orbital = atom.register["orbital"][phase.value] + self.orbital = atom.registry["orbital"][phase.value] print(self.orbital) self.puzzles = list() for item, possibility in self.orbital: # type: ignore diff --git a/src/heurams/kernel/reactor/phaser.py b/src/heurams/kernel/reactor/phaser.py index eed964a..5a43ce9 100644 --- a/src/heurams/kernel/reactor/phaser.py +++ b/src/heurams/kernel/reactor/phaser.py @@ -11,7 +11,7 @@ class Phaser(): old_atoms = list() self.state = PhaserState.UNSURE for i in atoms: - if not i.register["electron"].is_activated(): + if not i.registry["electron"].is_activated(): new_atoms.append(i) else: old_atoms.append(i) diff --git a/tests/test_working_particles.py b/tests/test_working_particles.py index 6841f20..23c6b85 100644 --- a/tests/test_working_particles.py +++ b/tests/test_working_particles.py @@ -153,7 +153,7 @@ class TestAtom: atom = Atom("test_atom") assert atom.ident == "test_atom" - assert isinstance(atom.register, dict) + assert isinstance(atom.registry, dict) def test_atom_link(self): """Test Atom linking components."""