实现 Recognition 部件

This commit is contained in:
2025-11-08 13:23:15 +08:00
parent 92f9903307
commit 330846a4a5
8 changed files with 108 additions and 54 deletions

View File

@@ -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,

View File

@@ -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(

View File

@@ -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)

View File

@@ -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 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}")
for item in nucleon[cfg["secondary"]]:
if isinstance(item, list):
for j in item:
yield Markdown(f"### {metadata["annotation"][item]}: {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")
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)
with Center():
yield Button("我已知晓", id="ok")

View File

@@ -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}")

View File

@@ -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

View File

@@ -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)

View File

@@ -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."""