进一步实现 interface
This commit is contained in:
14
src/heurams/interface/shim.py
Normal file
14
src/heurams/interface/shim.py
Normal file
@@ -0,0 +1,14 @@
|
||||
"""Kernel 操作辅助函数库"""
|
||||
import heurams.kernel.particles as pt
|
||||
staging = {} # 细粒度缓存区, 是 ident -> quality 的封装
|
||||
def report_to_staging(atom: pt.Atom, quality):
|
||||
staging[atom.ident] = min(quality, staging[atom.ident])
|
||||
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)
|
||||
else:
|
||||
pt.atom_registry[atom_ident].register['electron'].revisor(quality=quality, is_new_activation=True)
|
||||
clear()
|
||||
@@ -1,60 +0,0 @@
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.events import Event
|
||||
from textual.widgets import (
|
||||
Collapsible,
|
||||
Header,
|
||||
Footer,
|
||||
Markdown,
|
||||
ListView,
|
||||
ListItem,
|
||||
Label,
|
||||
Static,
|
||||
Button,
|
||||
)
|
||||
from textual.containers import Container, Horizontal, Center
|
||||
from textual.screen import Screen
|
||||
from textual.widget import Widget
|
||||
import uuid
|
||||
from typing import Tuple, Dict
|
||||
import heurams.kernel.particles as pt
|
||||
import heurams.kernel.puzzles as pz
|
||||
import re
|
||||
import random
|
||||
import copy
|
||||
|
||||
|
||||
class BasicEvaluation(Composition):
|
||||
def __init__(self, screen: Screen, reactor, atom: Tuple[pt.Electron, pt.Nucleon, Dict], extra = {}):
|
||||
super().__init__(screen, reactor, atom)
|
||||
|
||||
def compose(self):
|
||||
yield Label(self.atom[1]["content"], id="sentence")
|
||||
with Container(id="button_container"):
|
||||
btn = {}
|
||||
btn["5"] = Button(
|
||||
"完美回想", variant="success", id=self.regid("feedback5"), classes="choice"
|
||||
)
|
||||
btn["4"] = Button(
|
||||
"犹豫后正确", variant="success", id=self.regid("feedback4"), classes="choice"
|
||||
)
|
||||
btn["3"] = Button(
|
||||
"困难地正确", variant="warning", id=self.regid("feedback3"), classes="choice"
|
||||
)
|
||||
btn["2"] = Button(
|
||||
"错误但熟悉", variant="warning", id=self.regid("feedback2"), classes="choice"
|
||||
)
|
||||
btn["1"] = Button(
|
||||
"错误且不熟", variant="error", id=self.regid("feedback1"), classes="choice"
|
||||
)
|
||||
btn["0"] = Button(
|
||||
"完全空白", variant="error", id=self.regid("feedback0"), classes="choice"
|
||||
)
|
||||
yield Horizontal(btn["5"], btn["4"])
|
||||
yield Horizontal(btn["3"], btn["2"])
|
||||
yield Horizontal(btn["1"], btn["0"])
|
||||
|
||||
def handler(self, event, type_):
|
||||
if "feedback" in event.button.id:
|
||||
assess = int(self.recid(event.button.id)[8:9])
|
||||
ret = self.reactor.report(self.atom, assess)
|
||||
return ret
|
||||
28
src/heurams/interface/widgets/base_puzzle_widget.py
Normal file
28
src/heurams/interface/widgets/base_puzzle_widget.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.events import Event
|
||||
from textual.widgets import (
|
||||
Collapsible,
|
||||
Header,
|
||||
Footer,
|
||||
Markdown,
|
||||
ListView,
|
||||
ListItem,
|
||||
Label,
|
||||
Static,
|
||||
Button,
|
||||
)
|
||||
from textual.containers import Container, Horizontal, Center
|
||||
from textual.screen import Screen
|
||||
from textual.widget import Widget
|
||||
import uuid
|
||||
from typing import Tuple, Dict
|
||||
import heurams.kernel.particles as pt
|
||||
import heurams.kernel.puzzles as pz
|
||||
import re
|
||||
import random
|
||||
import copy
|
||||
|
||||
class BasePuzzleWidget(Widget):
|
||||
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, name=name, id=id, classes=classes, disabled=disabled, markup=markup)
|
||||
self.atom = atom
|
||||
51
src/heurams/interface/widgets/basic_puzzle.py
Normal file
51
src/heurams/interface/widgets/basic_puzzle.py
Normal file
@@ -0,0 +1,51 @@
|
||||
from textual.widgets import (
|
||||
Markdown,
|
||||
Label,
|
||||
Static,
|
||||
Button,
|
||||
)
|
||||
from textual.containers import Container, Horizontal, Center
|
||||
from textual.screen import Screen
|
||||
from textual.widget import Widget
|
||||
import heurams.kernel.particles as pt
|
||||
import heurams.kernel.puzzles as pz
|
||||
from .base_puzzle_widget import BasePuzzleWidget
|
||||
|
||||
class BasicEvaluation(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)
|
||||
|
||||
feedback_mapping = {
|
||||
"feedback_5": 5,
|
||||
"feedback_4": 4,
|
||||
"feedback_3": 3,
|
||||
"feedback_2": 2,
|
||||
"feedback_1": 1,
|
||||
"feedback_0": 0,
|
||||
}
|
||||
|
||||
def compose(self):
|
||||
yield Label(self.atom.register["nucleon"]["content"], id="main")
|
||||
with Container(id="button_container"):
|
||||
btn = {}
|
||||
btn["5"] = Button(
|
||||
"完美回想", variant="success", id="feedback_5", classes="choice"
|
||||
)
|
||||
btn["4"] = Button(
|
||||
"犹豫后正确", variant="success", id="feedback_4", classes="choice"
|
||||
)
|
||||
btn["3"] = Button(
|
||||
"困难地正确", variant="warning", id="feedback_3", classes="choice"
|
||||
)
|
||||
btn["2"] = Button(
|
||||
"错误但熟悉", variant="warning", id="feedback_2", classes="choice"
|
||||
)
|
||||
btn["1"] = Button(
|
||||
"错误且不熟", variant="error", id="feedback_1", classes="choice"
|
||||
)
|
||||
btn["0"] = Button(
|
||||
"完全空白", variant="error", id="feedback_0", classes="choice"
|
||||
)
|
||||
yield Horizontal(btn["5"], btn["4"])
|
||||
yield Horizontal(btn["3"], btn["2"])
|
||||
yield Horizontal(btn["1"], btn["0"])
|
||||
@@ -1,12 +1,5 @@
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.events import Event
|
||||
from textual.widgets import (
|
||||
Collapsible,
|
||||
Header,
|
||||
Footer,
|
||||
Markdown,
|
||||
ListView,
|
||||
ListItem,
|
||||
Label,
|
||||
Static,
|
||||
Button,
|
||||
@@ -14,56 +7,52 @@ from textual.widgets import (
|
||||
from textual.containers import Container, Horizontal, Center
|
||||
from textual.screen import Screen
|
||||
from textual.widget import Widget
|
||||
import uuid
|
||||
from typing import Tuple, Dict
|
||||
import heurams.kernel.particles as pt
|
||||
import heurams.kernel.puzzles as pz
|
||||
import re
|
||||
import random
|
||||
from .base_puzzle_widget import BasePuzzleWidget
|
||||
import copy
|
||||
import random
|
||||
from .. import shim
|
||||
|
||||
class ClozePuzzle(BasePuzzleWidget):
|
||||
|
||||
class FillBlank(Composition):
|
||||
def __init__(self, screen: Screen, reactor, atom: Tuple[pt.Electron, pt.Nucleon, Dict], extra:Dict = {}):
|
||||
super().__init__(screen, reactor, atom)
|
||||
self.extra = extra
|
||||
self.inputlist = []
|
||||
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)
|
||||
self.inputlist = list()
|
||||
self.hashtable = {}
|
||||
self._work()
|
||||
|
||||
def _work(self):
|
||||
self.puzzle = pz.BlankPuzzle(self.atom[1]["content"], 2)
|
||||
self.puzzle = pz.ClozePuzzle(text=self.atom.register["nucleon"]["content"], min_denominator=2)
|
||||
self.puzzle.refresh()
|
||||
self.ans = copy.copy(self.puzzle.answer)
|
||||
random.shuffle(self.ans)
|
||||
|
||||
def compose(self):
|
||||
if self.extra.get("feedback_msg"):
|
||||
yield Label("反馈提示:" + self.extra["feedback_msg"])
|
||||
yield Label(self.puzzle.wording, id=self.regid("sentence"))
|
||||
yield Label(f"当前输入: {self.inputlist}", id=self.regid("inputpreview"))
|
||||
yield Label(self.puzzle.wording, id="sentence")
|
||||
yield Label(f"当前输入: {self.inputlist}", id="inputpreview")
|
||||
for i in self.ans:
|
||||
self.hashtable[str(hash(i))] = i
|
||||
yield Button(i, id=self.regid(f"select{hash(i)}"))
|
||||
yield Button("退格", id=self.regid(f"delete"))
|
||||
yield Button(i, id=f"{hash(i)}")
|
||||
yield Button("退格", id=f"delete")
|
||||
|
||||
def handler(self, event, type_):
|
||||
# TODO: 改动:在线错误纠正
|
||||
if type_ == "button":
|
||||
if self.recid(event.button.id) == "delete":
|
||||
if event.button.id == "delete":
|
||||
if len(self.inputlist) > 0:
|
||||
self.inputlist.pop()
|
||||
else:
|
||||
return 1
|
||||
else:
|
||||
self.inputlist.append(self.hashtable[self.recid(event.button.id)[6:]])
|
||||
self.inputlist.append(self.hashtable[event.button.id[6:]])
|
||||
if len(self.inputlist) < len(self.puzzle.answer):
|
||||
return 1
|
||||
else:
|
||||
if self.inputlist == self.puzzle.answer:
|
||||
self.reactor.report(self.atom, 4)
|
||||
shim.report_to_staging(self.atom, 4)
|
||||
return 0
|
||||
else:
|
||||
self.inputlist = []
|
||||
self.reactor.report(self.atom, 2)
|
||||
shim.report_to_staging(self.atom, 2)
|
||||
return 2
|
||||
@@ -22,9 +22,9 @@ import re
|
||||
import random
|
||||
import copy
|
||||
|
||||
class Finished(Composition):
|
||||
def __init__(self, screen: Screen, reactor, atom: Tuple[pt.Electron, pt.Nucleon, Dict], extra = {}):
|
||||
super().__init__(screen, reactor, atom)
|
||||
class Finished(Widget):
|
||||
def __init__(self, *children: Widget, name: str | None = None, id: str | None = None, classes: str | None = None, disabled: bool = False, markup: bool = True) -> None:
|
||||
super().__init__(*children, name=name, id=id, classes=classes, disabled=disabled, markup=markup)
|
||||
|
||||
def compose(self):
|
||||
yield Label("本次记忆进程结束", id=self.regid("msg"))
|
||||
yield Label("本次记忆进程结束, 下次再会!", id="finished_msg")
|
||||
|
||||
@@ -14,18 +14,17 @@ from textual.widgets import (
|
||||
from textual.containers import Container, Horizontal, Center
|
||||
from textual.screen import Screen
|
||||
from textual.widget import Widget
|
||||
import uuid
|
||||
from typing import Tuple, Dict
|
||||
import heurams.kernel.particles as pt
|
||||
import heurams.kernel.puzzles as pz
|
||||
import re
|
||||
import random
|
||||
from .base_puzzle_widget import BasePuzzleWidget
|
||||
import copy
|
||||
import random
|
||||
from .. import shim
|
||||
|
||||
|
||||
class DrawCard(Composition):
|
||||
def __init__(self, screen: Screen, reactor, atom: Tuple[pt.Electron, pt.Nucleon, Dict], extra = {}):
|
||||
super().__init__(screen, reactor, atom)
|
||||
class DrawCard(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)
|
||||
self.inputlist = []
|
||||
self.hashtable = {}
|
||||
self._work()
|
||||
@@ -35,30 +34,30 @@ class DrawCard(Composition):
|
||||
self.puzzle.refresh()
|
||||
|
||||
def compose(self):
|
||||
yield Label(self.atom[1].content.replace("/",""), id=self.regid("sentence"))
|
||||
yield Label(self.puzzle.wording[len(self.inputlist)], id=self.regid("puzzle"))
|
||||
yield Label(f"当前输入: {self.inputlist}", id=self.regid("inputpreview"))
|
||||
yield Label(self.atom[1].content.replace("/",""), id="sentence")
|
||||
yield Label(self.puzzle.wording[len(self.inputlist)], id="puzzle")
|
||||
yield Label(f"当前输入: {self.inputlist}", id="inputpreview")
|
||||
for i in self.puzzle.options[len(self.inputlist)]:
|
||||
self.hashtable[str(hash(i))] = i
|
||||
yield Button(i, id=self.regid(f"select{hash(i)}"))
|
||||
yield Button("退格", id=self.regid(f"delete"))
|
||||
yield Button(i, id=f"select{hash(i)}")
|
||||
yield Button("退格", id=f"delete")
|
||||
|
||||
def handler(self, event, type_):
|
||||
if type_ == "button":
|
||||
if self.recid(event.button.id) == "delete":
|
||||
if event.button.id == "delete":
|
||||
if len(self.inputlist) > 0:
|
||||
self.inputlist.pop()
|
||||
else:
|
||||
return 1
|
||||
else:
|
||||
self.inputlist.append(self.hashtable[self.recid(event.button.id)[6:]])
|
||||
self.inputlist.append(self.hashtable[event.button.id[6:]])
|
||||
if len(self.inputlist) < len(self.puzzle.answer):
|
||||
return 1
|
||||
else:
|
||||
if self.inputlist == self.puzzle.answer:
|
||||
self.reactor.report(self.atom, 4)
|
||||
shim.report_to_staging(self.atom, 4)
|
||||
return 0
|
||||
else:
|
||||
self.inputlist = []
|
||||
self.reactor.report(self.atom, 2)
|
||||
shim.report_to_staging(self.atom, 2)
|
||||
return 2
|
||||
@@ -11,20 +11,12 @@ from textual.widgets import (
|
||||
Static,
|
||||
Button,
|
||||
)
|
||||
from textual.containers import Container, Horizontal, Center
|
||||
from textual.screen import Screen
|
||||
from textual.widget import Widget
|
||||
import uuid
|
||||
from typing import Tuple, Dict
|
||||
import heurams.kernel.particles as pt
|
||||
import heurams.kernel.puzzles as pz
|
||||
import re
|
||||
import random
|
||||
import copy
|
||||
|
||||
class Placeholder(Composition):
|
||||
def __init__(self, screen: Screen, extra = {}):
|
||||
self.screen = screen
|
||||
|
||||
class Placeholder(Widget):
|
||||
def __init__(self, *children: Widget, name: str | None = None, id: str | None = None, classes: str | None = None, disabled: bool = False, markup: bool = True) -> None:
|
||||
super().__init__(*children, name=name, id=id, classes=classes, disabled=disabled, markup=markup)
|
||||
|
||||
def compose(self):
|
||||
yield Label("示例标签", id="testlabel")
|
||||
|
||||
@@ -21,10 +21,12 @@ import heurams.kernel.puzzles as pz
|
||||
import re
|
||||
import random
|
||||
import copy
|
||||
from .base_puzzle_widget import BasePuzzleWidget
|
||||
from .. import shim
|
||||
|
||||
class Recognition(Composition):
|
||||
def __init__(self, screen: Screen, reactor, atom: Tuple[pt.Electron, pt.Nucleon, Dict], extra = {}):
|
||||
super().__init__(screen, reactor, atom)
|
||||
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)
|
||||
|
||||
def compose(self):
|
||||
with Center():
|
||||
@@ -49,7 +51,7 @@ class Recognition(Composition):
|
||||
with Center():
|
||||
yield Label(
|
||||
f"[b][b]{i.replace('/', ' ')}[/][/]",
|
||||
id=self.regid("sentence" + str(hash(i))),
|
||||
id="sentence" + str(hash(i)),
|
||||
)
|
||||
for i in self.atom[2]["testdata"]["additional_inf"]:
|
||||
if self.atom[1][i]:
|
||||
@@ -60,15 +62,14 @@ class Recognition(Composition):
|
||||
if isinstance(self.atom[1][i], Dict):
|
||||
t = ""
|
||||
for j, k in self.atom[1][i].items(): # type: ignore
|
||||
# 弱智的 Pylance 类型推导
|
||||
t += f"> **{j}**: {k} \n"
|
||||
yield Markdown(t, id=self.regid("tran"))
|
||||
yield Markdown(t, id="tran")
|
||||
with Center():
|
||||
yield Button("我已知晓", id=self.regid("ok"))
|
||||
yield Button("我已知晓", id="ok")
|
||||
|
||||
def handler(self, event, type_):
|
||||
if type_ == "button":
|
||||
if event.button.id == self.getid("ok"):
|
||||
self.reactor.report(self.atom, 5)
|
||||
if event.button.id == "ok":
|
||||
shim.report_to_staging(self.atom, 5)
|
||||
return 0
|
||||
return -1
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from .electron import Electron
|
||||
from .nucleon import Nucleon
|
||||
from .orbital import Orbital
|
||||
from .atom import Atom
|
||||
from .atom import Atom, atom_registry
|
||||
from .probe import probe_all, probe_by_filename
|
||||
from .loader import load_nucleon, load_electron
|
||||
|
||||
@@ -14,4 +14,5 @@ __all__ = [
|
||||
"probe_by_filename",
|
||||
"load_nucleon",
|
||||
"load_electron",
|
||||
"atom_registry",
|
||||
]
|
||||
@@ -6,6 +6,7 @@ import pathlib
|
||||
import typing
|
||||
import toml
|
||||
import json
|
||||
import bidict
|
||||
|
||||
class AtomRegister(TypedDict):
|
||||
nucleon: Nucleon
|
||||
@@ -17,6 +18,7 @@ class AtomRegister(TypedDict):
|
||||
orbital: Orbital
|
||||
orbital_path: pathlib.Path
|
||||
orbital_fmt: str
|
||||
runtime: dict
|
||||
|
||||
class Atom():
|
||||
"""
|
||||
@@ -29,6 +31,7 @@ class Atom():
|
||||
|
||||
def __init__(self, ident = ""):
|
||||
self.ident = ident
|
||||
atom_registry[ident] = self
|
||||
self.register: AtomRegister = { # type: ignore
|
||||
"nucleon": None,
|
||||
"nucleon_path": None,
|
||||
@@ -76,4 +79,6 @@ class Atom():
|
||||
|
||||
@staticmethod
|
||||
def placeholder():
|
||||
return (Electron.placeholder(), Nucleon.placeholder(), {})
|
||||
return (Electron.placeholder(), Nucleon.placeholder(), {})
|
||||
|
||||
atom_registry: bidict.bidict[str, Atom] = bidict.bidict()
|
||||
|
||||
@@ -23,4 +23,4 @@ def load_electron(path: pathlib.Path, fmt = "json"):
|
||||
lst = list()
|
||||
for item, attr in dictdata.items():
|
||||
lst.append(Electron(hasher.hash(item), attr))
|
||||
return lst
|
||||
return lst
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# 版本控制集成服务
|
||||
|
||||
ver = "0.4.0"
|
||||
stage = "prototype"
|
||||
stage = "prototype"
|
||||
codename = "fledge" # 雏鸟, 0.4.x 版本
|
||||
Reference in New Issue
Block a user