From 613b4ba045c6ffc8ee69c13eab2e8b80ce5f539e Mon Sep 17 00:00:00 2001 From: pluvium27 Date: Thu, 23 Apr 2026 00:13:57 +0800 Subject: [PATCH] =?UTF-8?q?style:=20=E4=BB=A3=E7=A0=81=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +- src/heurams/context.py | 2 +- src/heurams/interface/__init__.py | 10 ++-- src/heurams/interface/screens/about.py | 11 +++-- src/heurams/interface/screens/dashboard.py | 30 ++++++++---- src/heurams/interface/screens/favmgr.py | 8 ++-- src/heurams/interface/screens/memoqueue.py | 47 +++++++++++-------- src/heurams/interface/screens/navigator.py | 1 - src/heurams/interface/screens/precache.py | 9 ++-- src/heurams/interface/screens/preparation.py | 11 +++-- src/heurams/interface/screens/setting.py | 26 +++++----- src/heurams/interface/screens/synctool.py | 8 ++-- src/heurams/interface/shim.py | 2 +- src/heurams/interface/widgets/cloze_puzzle.py | 14 +++--- src/heurams/interface/widgets/mcq_puzzle.py | 18 +++---- src/heurams/interface/widgets/recognition.py | 2 +- src/heurams/kernel/particles/placeholders.py | 1 - src/heurams/kernel/puzzles/guess.py | 1 - src/heurams/kernel/reactor/router.py | 1 - src/heurams/services/attic.py | 26 ++++++---- src/heurams/services/exceptions.py | 2 - src/heurams/services/hasher.py | 10 ++-- src/heurams/unifront/session.py | 4 +- 23 files changed, 144 insertions(+), 104 deletions(-) diff --git a/README.md b/README.md index 3a1421c..bfd291a 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ - 此外, 算法模块是 "潜进" 内核 (heurams.kernel) 中的一等公民, 内核天然支持插拔各型算法 - 无需安装繁杂的插件即可分单元集完成算法快速切换与调优, 研究者可以方便地修改算法模块以便捷地进行研究与测试 - 内置 `SM-2` 简单间隔重复算法, 此算法亦用作 `Anki` 闪卡记忆软件的默认闪卡调度器 -- 还内置 `NSP-0` 筛选用非间隔重复算法以便快速筛选记忆内容, `FSRS` 先进间隔重复算法作为效率更高的调度器, 与 `SM-15M` 复杂间隔重复算法(逆向工程) +- 还内置 `NSP-0` 筛选用非间隔重复算法以便快速筛选记忆内容, `FSRS` 先进间隔重复算法作为效率更高的调度器, 与 `SM-15M (移植自 sm.js 项目)` 复杂间隔重复算法(逆向工程) - 算法模块可以标记记忆项目, 也可以动态规划每个记忆单元的记忆间隔时间表, 动态跟踪记忆反馈数据, 以优化长期记忆保留率与稳定性 - 得益于项目的模块化架构与单元集结构设计, 一个项目甚至可以与任意种算法共存并互通, 这对研究者及想探索/实验高效率方法的用户极其友好 @@ -35,7 +35,7 @@ - 软件内置多种谜题类型, 包括选择题 (MCQ), 填空题 (Cloze) 与识别题 (Recognition), 您可在同一单元应用多种, 或是选择启用 - 软件天然支持动态内容生成, 支持宏驱动的模板系统, 根据上下文乃至语言模型动态生成知识点的解析 - 在间隔重复研究尚被 SuperMemo 系列独占的时代, Wozniak 就早已表示 "如果不能理解知识, 就无需记忆它". 今天, 我们依然相信理解是记忆的基石 -- 云同步与分享优化: 由于我们的记忆数据和单元集文件都是文本文件, 故可进行快速的增量同步而无需完整地上传所有文件, 并且设计天然支持分享内容的版本控制 +- 云同步与分享优化: 由于我们的记忆数据和单元集文件都是文本文件, 故可进行快速的增量同步而无需完整地上传所有文件, 并且设计天然支持分享内容的版本控制, 如果您想分享单文件, 我们也支持 .zip/.tar.gz/.tar.xz 导入与导出 - 优越性能: 得益于现代的文件组织结构, 潜进能在保持高自由度的同时仅使用 python 就能达到敏捷且低占用的用户体验 ### 实用用户界面 diff --git a/src/heurams/context.py b/src/heurams/context.py index f8d36f8..b0e008d 100644 --- a/src/heurams/context.py +++ b/src/heurams/context.py @@ -51,4 +51,4 @@ class ConfigContext: return self def __exit__(self, exc_type, exc_val, exc_tb): - config_var.reset(self._token) # type: ignore \ No newline at end of file + config_var.reset(self._token) # type: ignore diff --git a/src/heurams/interface/__init__.py b/src/heurams/interface/__init__.py index b0b5a62..2011d63 100644 --- a/src/heurams/interface/__init__.py +++ b/src/heurams/interface/__init__.py @@ -63,9 +63,11 @@ class HeurAMSApp(App): self.push_screen("dashboard") def action_go_back(self) -> None: - self.exit() # go_back 在最顶层是退出, Screen 会再次定义为返回, 键位都是 q, 免得不一样 + self.exit() # go_back 在最顶层是退出, Screen 会再次定义为返回, 键位都是 q, 免得不一样 - def action_do_nothing(self) -> None: # 用来给没使用/禁用的快捷键占位, 因为 Binding 删除不了 + def action_do_nothing( + self, + ) -> None: # 用来给没使用/禁用的快捷键占位, 因为 Binding 删除不了 pass # 移除烦人的 "rich traceback" @@ -78,10 +80,10 @@ class HeurAMSApp(App): if hasattr(self, "_exception"): self._close_messages_no_wait() raise self._exception - super()._fatal_error() # fallback + super()._fatal_error() # fallback def panic(self, *args): if hasattr("_exception"): self._close_messages_no_wait() raise self._exception - super().panic(*args) # ditto + super().panic(*args) # ditto diff --git a/src/heurams/interface/screens/about.py b/src/heurams/interface/screens/about.py index d8170a2..15ff6b3 100644 --- a/src/heurams/interface/screens/about.py +++ b/src/heurams/interface/screens/about.py @@ -22,6 +22,7 @@ class AboutScreen(Screen): ("z", "go_back", "关于"), ] SUB_TITLE = "关于" + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -32,9 +33,11 @@ class AboutScreen(Screen): shim.set_term_title(f"{self.app.TITLE} - {self.SUB_TITLE}") def compose(self) -> ComposeResult: - - if config_var.get()['interface']['global']['show_header']: - yield Header(show_clock=config_var.get()['interface']['global']['clock_on_header']) + + if config_var.get()["interface"]["global"]["show_header"]: + yield Header( + show_clock=config_var.get()["interface"]["global"]["clock_on_header"] + ) with ScrollableContainer(id="about_container"): yield Label("[b]关于与版本信息[/b]") @@ -115,7 +118,7 @@ Textual 框架版本: {textual_version} import textual return textual.__version__ - except ImportError, AttributeError: + except (ImportError, AttributeError): return "未知" def _get_terminal_info(self) -> str: diff --git a/src/heurams/interface/screens/dashboard.py b/src/heurams/interface/screens/dashboard.py index 9075bc3..e7ecb56 100644 --- a/src/heurams/interface/screens/dashboard.py +++ b/src/heurams/interface/screens/dashboard.py @@ -47,8 +47,10 @@ class DashboardScreen(Screen): def compose(self) -> ComposeResult: """组合界面组件""" - if config_var.get()['interface']['global']['show_header']: - yield Header(show_clock=config_var.get()['interface']['global']['clock_on_header']) + if config_var.get()["interface"]["global"]["show_header"]: + yield Header( + show_clock=config_var.get()["interface"]["global"]["clock_on_header"] + ) with ScrollableContainer(): yield Horizontal( # 顶部的状态 Vertical( @@ -76,14 +78,19 @@ class DashboardScreen(Screen): ) yield ListView(id="repo_list", classes="repo-list") # 单元集选择 from heurams.services.attic import Attic - a = Attic('ana', {'totaltime': 0, 'openpuzzles': 0, 'puzzles_err': 0}) + + a = Attic("ana", {"totaltime": 0, "openpuzzles": 0, "puzzles_err": 0}) yield Label(f"版本 {version.ver} {version.stage.capitalize()}") # 版本信息 - yield Label(f"在 {round(a.data['totaltime'], 2)} 秒内处理了 {a.data['openpuzzles']} 个谜题, 正确率{'无法求解' if not a.data['openpuzzles'] else ' ' + str(round(100 * (1 - a.data['puzzles_err']/a.data['openpuzzles']), 2)) + '%'}, 平均速度{'无法求解' if not a.data['totaltime'] else ' ' + str(round(a.data['openpuzzles']/a.data['totaltime'], 2)) + '个/s'}", id='analysis') # 版本信息 + yield Label( + f"在 {round(a.data['totaltime'], 2)} 秒内处理了 {a.data['openpuzzles']} 个谜题, 正确率{'无法求解' if not a.data['openpuzzles'] else ' ' + str(round(100 * (1 - a.data['puzzles_err']/a.data['openpuzzles']), 2)) + '%'}, 平均速度{'无法求解' if not a.data['totaltime'] else ' ' + str(round(a.data['openpuzzles']/a.data['totaltime'], 2)) + '个/s'}", + id="analysis", + ) # 版本信息 yield Footer() @on(events.ScreenResume) def post_active(self, event): from heurams.interface import shim + shim.set_term_title(f"{self.app.TITLE} - {self.SUB_TITLE}") # https://github.com/Textualize/textual/discussions/4268 # self.refresh(recompose=True) 此函数有问题且官方不管 而且性能低 @@ -112,17 +119,21 @@ class DashboardScreen(Screen): } repo.preview = { "review": 0, - "new": repo.config["scheduled_num"], # TODO: 考虑之后在这里加点运算避免 SM-2 积压, 但现在需要的是直观! + "new": repo.config[ + "scheduled_num" + ], # TODO: 考虑之后在这里加点运算避免 SM-2 积压, 但现在需要的是直观! } initial_time = float("inf") - for i in range(repo.data_length): # TODO: 增加异步性能优化, 但是学习数据属实规模小... + for i in range( + repo.data_length + ): # TODO: 增加异步性能优化, 但是学习数据属实规模小... e = pt.Electron.from_data( electronic_data=repo.electronic_data_lict[i], algo_name=repo.config["algorithm"], ) # n = pt.Nucleon.from_data(repo.nucleonic_data_lict[i]) if e.is_activated(): - repo.progress["have_activated_ever"] = True # 被激活过~ + repo.progress["have_activated_ever"] = True # 被激活过~ repo.progress["touched"] += 1 repo.nearest_review_time = min(repo.nearest_review_time, e.nextdate()) if timer.get_daystamp() >= e.nextdate(): @@ -141,7 +152,7 @@ class DashboardScreen(Screen): repodirs = sorted( self.repos, key=lambda r: r.nearest_review_time, - reverse=True, # 紧张的先复习 + reverse=True, # 紧张的先复习 ) # 填充列表 @@ -159,7 +170,7 @@ class DashboardScreen(Screen): return for r in self.repos: - self.repolink[str(r.manifest['package'])] = r # 用于规避 ctype id 对象还原 + self.repolink[str(r.manifest["package"])] = r # 用于规避 ctype id 对象还原 # NOTE: 上一行不要使用 id(), id 可能被重用! list_item = ListItem( *[Label(line) for line in r.prompt.splitlines()], @@ -202,5 +213,6 @@ class DashboardScreen(Screen): logger.debug(f"event.button.id: {event.button.id}") if event.button.id.startswith("slaunch_repo_"): # type: ignore from .preparation import launch + launch(repo=self.repolink[event.button.id.removeprefix("slaunch_repo_")], app=self.app, scheduled_num=-1) # type: ignore # TODO: 这样启动的记忆实例的状态机无法绑定到 PreparationScreen 中 diff --git a/src/heurams/interface/screens/favmgr.py b/src/heurams/interface/screens/favmgr.py index e165ccd..55636a2 100644 --- a/src/heurams/interface/screens/favmgr.py +++ b/src/heurams/interface/screens/favmgr.py @@ -56,9 +56,11 @@ class FavoriteManagerScreen(Screen): def compose(self) -> ComposeResult: """组合界面组件""" - - if config_var.get()['interface']['global']['show_header']: - yield Header(show_clock=config_var.get()['interface']['global']['clock_on_header']) + + if config_var.get()["interface"]["global"]["show_header"]: + yield Header( + show_clock=config_var.get()["interface"]["global"]["clock_on_header"] + ) with ScrollableContainer(id="favorites-container"): if not self.favorites: yield Label("暂无收藏", classes="empty-label") diff --git a/src/heurams/interface/screens/memoqueue.py b/src/heurams/interface/screens/memoqueue.py index 452f847..55de24b 100644 --- a/src/heurams/interface/screens/memoqueue.py +++ b/src/heurams/interface/screens/memoqueue.py @@ -20,6 +20,7 @@ from .. import shim logger = get_logger(__name__) + class MemScreen(Screen): BINDINGS = [ ("q", "go_back", "返回"), @@ -59,14 +60,18 @@ class MemScreen(Screen): @on(events.ScreenResume) def post_active(self, event): from heurams.interface import shim + shim.set_term_title(f"{self.app.TITLE} - {self.SUB_TITLE}") def compose(self) -> ComposeResult: from heurams.services.attic import Attic - a = Attic('ana', {'openqueue': 0}) - a.data['openqueue'] += 1 - if config_var.get()['interface']['global']['show_header']: - yield Header(show_clock=config_var.get()['interface']['global']['clock_on_header']) + + a = Attic("ana", {"openqueue": 0}) + a.data["openqueue"] += 1 + if config_var.get()["interface"]["global"]["show_header"]: + yield Header( + show_clock=config_var.get()["interface"]["global"]["clock_on_header"] + ) with ScrollableContainer(): yield Label(self._get_progress_text(), id="head_stat") yield ScrollableContainer(id="puzzle_container") @@ -81,8 +86,9 @@ class MemScreen(Screen): self.expander = self.procession.get_expander() from heurams.services.attic import Attic import time - a = Attic('ana', {'last': time.time()}) - a.data['last'] = time.time() + + a = Attic("ana", {"last": time.time()}) + a.data["last"] = time.time() self.mount_puzzle() self.update_display() @@ -122,8 +128,8 @@ class MemScreen(Screen): def mount_finished_widget(self): """挂载已完成组件""" - a = Attic('ana', {'finished': 0}) - a.data['finished'] += 1 + a = Attic("ana", {"finished": 0}) + a.data["finished"] += 1 container = self.query_one("#puzzle_container") for i in container.children: i.remove() @@ -176,12 +182,14 @@ class MemScreen(Screen): self.forward_atom(self.expander.get_quality()) self.update_state() from heurams.services.attic import Attic - a = Attic('ana', {'openpuzzles': 0}) - a = Attic('ana', {'totaltime': 0}) - a.data['openpuzzles'] += 1 + + a = Attic("ana", {"openpuzzles": 0}) + a = Attic("ana", {"totaltime": 0}) + a.data["openpuzzles"] += 1 import time - a.data['totaltime'] += time.time() - a.data['last'] - a.data['last'] = time.time() + + a.data["totaltime"] += time.time() - a.data["last"] + a.data["last"] = time.time() self.mount_puzzle() self.update_display() @@ -201,8 +209,8 @@ class MemScreen(Screen): logger.debug(f"Quality: {quality}") self.atom_reporter(quality) if quality <= 3: - a = Attic('ana', {'puzzles_err': 0}) - a.data['puzzles_err'] += 1 + a = Attic("ana", {"puzzles_err": 0}) + a.data["puzzles_err"] += 1 self.procession.append() self.update_state() # 刷新状态 self.procession.forward(1) @@ -261,7 +269,8 @@ class MemScreen(Screen): def action_resume_mark(self): from heurams.services.attic import Attic import time - a = Attic('ana') - l = a.data['last'] - a.data['last'] = time.time() - self.app.notify(f"时间恢复已修正: {l} -> {a.data['last']}") \ No newline at end of file + + a = Attic("ana") + l = a.data["last"] + a.data["last"] = time.time() + self.app.notify(f"时间恢复已修正: {l} -> {a.data['last']}") diff --git a/src/heurams/interface/screens/navigator.py b/src/heurams/interface/screens/navigator.py index a86d31d..1793534 100644 --- a/src/heurams/interface/screens/navigator.py +++ b/src/heurams/interface/screens/navigator.py @@ -1,4 +1,3 @@ - from textual.app import ComposeResult from textual.containers import Grid from textual.screen import ModalScreen diff --git a/src/heurams/interface/screens/precache.py b/src/heurams/interface/screens/precache.py index 57f0a8e..cb7ffae 100644 --- a/src/heurams/interface/screens/precache.py +++ b/src/heurams/interface/screens/precache.py @@ -111,9 +111,11 @@ class PrecachingScreen(Screen): self.cache_stats["cache_rate"] = cache_rate def compose(self) -> ComposeResult: - - if config_var.get()['interface']['global']['show_header']: - yield Header(show_clock=config_var.get()['interface']['global']['clock_on_header']) + + if config_var.get()["interface"]["global"]["show_header"]: + yield Header( + show_clock=config_var.get()["interface"]["global"]["clock_on_header"] + ) with ScrollableContainer(id="precache_container"): yield Label("[b]音频预缓存[/b]", classes="title-label") with Container(): @@ -314,7 +316,6 @@ class PrecachingScreen(Screen): try: import shutil - shutil.rmtree(cache_dir, ignore_errors=True) self.update_status("已清空", "音频缓存已清空", 0) self._update_cache_display() # 更新缓存统计显示 diff --git a/src/heurams/interface/screens/preparation.py b/src/heurams/interface/screens/preparation.py index 873cb56..940a001 100644 --- a/src/heurams/interface/screens/preparation.py +++ b/src/heurams/interface/screens/preparation.py @@ -52,10 +52,13 @@ class PreparationScreen(Screen): def compose(self) -> ComposeResult: from heurams.services.attic import Attic - a = Attic('ana', {'openpre': 0}) - a.data['openpre'] += 1 - if config_var.get()['interface']['global']['show_header']: - yield Header(show_clock=config_var.get()['interface']['global']['clock_on_header']) + + a = Attic("ana", {"openpre": 0}) + a.data["openpre"] += 1 + if config_var.get()["interface"]["global"]["show_header"]: + yield Header( + show_clock=config_var.get()["interface"]["global"]["clock_on_header"] + ) with ScrollableContainer(id="main_container"): yield Markdown( f"**准备就绪**: `{self.repo.manifest['title']}`\n", id="title" diff --git a/src/heurams/interface/screens/setting.py b/src/heurams/interface/screens/setting.py index 387a0c4..cedef8f 100644 --- a/src/heurams/interface/screens/setting.py +++ b/src/heurams/interface/screens/setting.py @@ -1,6 +1,5 @@ """设置页面""" - from textual.app import ComposeResult from textual.containers import ScrollableContainer, Horizontal from textual.screen import Screen @@ -47,12 +46,15 @@ class SettingScreen(Screen): @on(events.ScreenResume) def post_active(self, event): from heurams.interface import shim + shim.set_term_title(f"{self.app.TITLE} - {self.SUB_TITLE}") def compose(self) -> ComposeResult: """组合界面组件""" - if config_var.get()['interface']['global']['show_header']: - yield Header(show_clock=config_var.get()['interface']['global']['clock_on_header']) + if config_var.get()["interface"]["global"]["show_header"]: + yield Header( + show_clock=config_var.get()["interface"]["global"]["clock_on_header"] + ) with ScrollableContainer(): yield Label("[b]设置页面[/b]") for i in config_var.get(): @@ -61,7 +63,8 @@ class SettingScreen(Screen): a = self._get_subcfg(f"{i}") if a: yield Collapsible( - *a, title=i + f'\n[d]{config_var.get().get(f"_{i}_desc", "")}[/d]' + *a, + title=i + f'\n[d]{config_var.get().get(f"_{i}_desc", "")}[/d]', ) yield Label( "退出页面时, 所作的更改会立即保存, 但仍建议重启软件以确保新的配置得到应用", @@ -113,7 +116,7 @@ class SettingScreen(Screen): prompt=f'{parent.get(f"{i}", "")}', id=domize(f"{parent_epath}.{i}"), ), - classes="setting-item" + classes="setting-item", ) ) elif isinstance(parent[f"_{i}_candidate"], list): @@ -125,7 +128,7 @@ class SettingScreen(Screen): prompt=f'{parent.get(f"{i}", "")}', id=domize(f"{parent_epath}.{i}"), ), - classes="setting-item" + classes="setting-item", ) ) else: @@ -139,7 +142,7 @@ class SettingScreen(Screen): type="number", id=domize(f"{parent_epath}.{i}"), ), - classes="setting-item" + classes="setting-item", ) ) elif isinstance(parent[i], str): @@ -152,7 +155,7 @@ class SettingScreen(Screen): type="text", id=domize(f"{parent_epath}.{i}"), ), - classes="setting-item" + classes="setting-item", ) ) elif isinstance(parent[i], bool): @@ -160,10 +163,11 @@ class SettingScreen(Screen): Horizontal( Label(i + f'\n[d]{parent.get(f"_{i}_desc", "")}[/d]'), Switch( - value=parent[i], id=domize(f"{parent_epath}.{i}"), + value=parent[i], + id=domize(f"{parent_epath}.{i}"), classes="setting-switch", ), - classes="setting-item" + classes="setting-item", ) ) elif isinstance(parent[i], int): @@ -176,7 +180,7 @@ class SettingScreen(Screen): type="integer", id=domize(f"{parent_epath}.{i}"), ), - classes="setting-item" + classes="setting-item", ) ) elif isinstance(parent[i], list): diff --git a/src/heurams/interface/screens/synctool.py b/src/heurams/interface/screens/synctool.py index 1cb364d..19dc485 100644 --- a/src/heurams/interface/screens/synctool.py +++ b/src/heurams/interface/screens/synctool.py @@ -33,9 +33,11 @@ class SyncScreen(Screen): shim.set_term_title(f"{self.app.TITLE} - {self.SUB_TITLE}") def compose(self) -> ComposeResult: - - if config_var.get()['interface']['global']['show_header']: - yield Header(show_clock=config_var.get()['interface']['global']['clock_on_header']) + + if config_var.get()["interface"]["global"]["show_header"]: + yield Header( + show_clock=config_var.get()["interface"]["global"]["clock_on_header"] + ) with ScrollableContainer(id="sync_container"): # 标题和连接状态 yield Static("同步工具", classes="title") diff --git a/src/heurams/interface/shim.py b/src/heurams/interface/shim.py index 2bb61f7..e2eae3b 100644 --- a/src/heurams/interface/shim.py +++ b/src/heurams/interface/shim.py @@ -15,7 +15,7 @@ puzzle2widget = { def set_term_title(title): - if not config_var.get()['interface']['global']['change_window_title']: + if not config_var.get()["interface"]["global"]["change_window_title"]: return system = platform.system() if system == "Windows": diff --git a/src/heurams/interface/widgets/cloze_puzzle.py b/src/heurams/interface/widgets/cloze_puzzle.py index 0c38deb..12a1f41 100644 --- a/src/heurams/interface/widgets/cloze_puzzle.py +++ b/src/heurams/interface/widgets/cloze_puzzle.py @@ -79,14 +79,14 @@ class ClozePuzzle(BasePuzzleWidget): self.hashmap[h] = i btnid = f"sel000-{h}" logger.debug(f"建立按钮 {btnid}") - self.btn_shortcuts[f'{c}'] = btnid - yield Button(f'[{c}] {i}', id=f"{btnid}") + self.btn_shortcuts[f"{c}"] = btnid + yield Button(f"[{c}] {i}", id=f"{btnid}") s.focus() yield Button("退格", id="delete") - self.btn_shortcuts[f'0'] = 'delete' - self.btn_shortcuts[f'backspace'] = 'delete' - self.btn_shortcuts[f'delete'] = 'delete' + self.btn_shortcuts[f"0"] = "delete" + self.btn_shortcuts[f"backspace"] = "delete" + self.btn_shortcuts[f"delete"] = "delete" def listprint(self, lst): s = "" @@ -128,10 +128,10 @@ class ClozePuzzle(BasePuzzleWidget): pass else: self.atom.minimize(rating) - + def on_key(self, event: Key) -> None: self.notify(event.key) if event.key in self.btn_shortcuts: btn_id = self.btn_shortcuts.get(event.key) - btn_id = '#' + btn_id + btn_id = "#" + btn_id self.query_one(btn_id, Button).press() diff --git a/src/heurams/interface/widgets/mcq_puzzle.py b/src/heurams/interface/widgets/mcq_puzzle.py index 0a08b5c..c04c74b 100644 --- a/src/heurams/interface/widgets/mcq_puzzle.py +++ b/src/heurams/interface/widgets/mcq_puzzle.py @@ -79,21 +79,21 @@ class MCQPuzzle(BasePuzzleWidget): c = 0 with ScrollableContainer(id="btn-container") as s: for i in current_options: - if i in [' ', '']: + if i in [" ", ""]: continue c += 1 h = str(hash(i)) self.hashmap[h] = i btnid = f"sel{str(self.cursor).zfill(3)}-{h}" logger.debug(f"建立按钮 {btnid}") - self.btn_shortcuts[f'{c}'] = f'{btnid}' - yield Button(f'[{c}] ' + i, id=f"{btnid}") + self.btn_shortcuts[f"{c}"] = f"{btnid}" + yield Button(f"[{c}] " + i, id=f"{btnid}") s.focus() yield Button("退格", id="delete") - self.btn_shortcuts['0'] = f'delete' - self.btn_shortcuts['delete'] = f'delete' - self.btn_shortcuts['backspace'] = f'delete' + self.btn_shortcuts["0"] = f"delete" + self.btn_shortcuts["delete"] = f"delete" + self.btn_shortcuts["backspace"] = f"delete" def update_display(self, error=0): # 更新预览标签 @@ -162,7 +162,7 @@ class MCQPuzzle(BasePuzzleWidget): if current_question_index < len(self.puzzle.options): current_options = self.puzzle.options[current_question_index] for option in current_options: - if option in ['', ' ']: + if option in ["", " "]: continue c += 1 button_id = f"sel{str(self.cursor).zfill(3)}-{hash(option)}" @@ -182,5 +182,5 @@ class MCQPuzzle(BasePuzzleWidget): self.notify(event.key) if event.key in self.btn_shortcuts: btn_id = self.btn_shortcuts.get(event.key) - btn_id = '#' + btn_id - self.query_one(btn_id, Button).press() \ No newline at end of file + btn_id = "#" + btn_id + self.query_one(btn_id, Button).press() diff --git a/src/heurams/interface/widgets/recognition.py b/src/heurams/interface/widgets/recognition.py index 5453954..d0a0c99 100644 --- a/src/heurams/interface/widgets/recognition.py +++ b/src/heurams/interface/widgets/recognition.py @@ -49,7 +49,7 @@ class Recognition(BasePuzzleWidget): def compose(self): from heurams.context import config_var - autovoice = config_var.get()["interface"]["widgets"]['recognition']["autovoice"] + autovoice = config_var.get()["interface"]["widgets"]["recognition"]["autovoice"] if autovoice: self.screen.action_play_voice() # type: ignore cfg: RecognitionConfig = self.atom.registry["nucleon"]["puzzles"][self.alia] diff --git a/src/heurams/kernel/particles/placeholders.py b/src/heurams/kernel/particles/placeholders.py index 3c21bc5..04c70ea 100644 --- a/src/heurams/kernel/particles/placeholders.py +++ b/src/heurams/kernel/particles/placeholders.py @@ -1,4 +1,3 @@ - from .atom import Atom from .electron import Electron from .nucleon import Nucleon diff --git a/src/heurams/kernel/puzzles/guess.py b/src/heurams/kernel/puzzles/guess.py index db88101..4927431 100644 --- a/src/heurams/kernel/puzzles/guess.py +++ b/src/heurams/kernel/puzzles/guess.py @@ -1,4 +1,3 @@ - from heurams.services.logger import get_logger from .base import BasePuzzle diff --git a/src/heurams/kernel/reactor/router.py b/src/heurams/kernel/reactor/router.py index 21776ef..021c199 100644 --- a/src/heurams/kernel/reactor/router.py +++ b/src/heurams/kernel/reactor/router.py @@ -136,7 +136,6 @@ class Router(Machine): def __repr__(self, style="pipe", ends="\n"): from tabulate import tabulate as tabu - lst = [ { "Type": "Router", diff --git a/src/heurams/services/attic.py b/src/heurams/services/attic.py index a0d7558..c846d8f 100644 --- a/src/heurams/services/attic.py +++ b/src/heurams/services/attic.py @@ -6,31 +6,37 @@ from pathlib import Path import atexit from heurams.services import timer from heurams.services.exceptions import WTFException + logger = get_logger(__name__) + def singleton(cls): instances = {} + def get_instance(ident, default): key = ident if key not in instances: instances[key] = cls(ident) instances[key].patch_dict(default) return instances[key] + return get_instance -atticdir = Path(config_var.get()['global']['paths']['misc']) / 'attics' + +atticdir = Path(config_var.get()["global"]["paths"]["misc"]) / "attics" atticdir.mkdir(parents=True, exist_ok=True) + @singleton class Attic: - def __init__(self, ident, default:dict={}): + def __init__(self, ident, default: dict = {}): self.ident = ident - self.ident = self.ident.replace('', str(timer.get_daystamp())) - self.ident = self.ident.replace('', str(timer.get_timestamp())) - if '<' in ident or '>' in ident: + self.ident = self.ident.replace("", str(timer.get_daystamp())) + self.ident = self.ident.replace("", str(timer.get_timestamp())) + if "<" in ident or ">" in ident: raise WTFException - #self.ident = get_md5(self.ident) - self.pklpath = atticdir / f'{self.ident}.pkl' + # self.ident = get_md5(self.ident) + self.pklpath = atticdir / f"{self.ident}.pkl" atexit.register(self.save) self.data = default if self.pklpath.exists(): @@ -45,9 +51,9 @@ class Attic: self.data.update({k: v for k, v in dct.items() if k not in self.data}) def save(self): - with open(atticdir / f'{self.ident}.pkl', 'wb') as f: + with open(atticdir / f"{self.ident}.pkl", "wb") as f: pkl.dump(self.data, f) def load(self): - with open(atticdir / f'{self.ident}.pkl', 'rb') as f: - self.data.update(dict(pkl.load(f))) \ No newline at end of file + with open(atticdir / f"{self.ident}.pkl", "rb") as f: + self.data.update(dict(pkl.load(f))) diff --git a/src/heurams/services/exceptions.py b/src/heurams/services/exceptions.py index f480c0f..665c728 100644 --- a/src/heurams/services/exceptions.py +++ b/src/heurams/services/exceptions.py @@ -1,4 +1,2 @@ - - class WTFException(Exception): pass diff --git a/src/heurams/services/hasher.py b/src/heurams/services/hasher.py index 6ab7746..d35f116 100644 --- a/src/heurams/services/hasher.py +++ b/src/heurams/services/hasher.py @@ -13,8 +13,8 @@ def get_md5(text): def hash(text): - #logger.debug(f"计算MD5-时间复合哈希, 输入`{text}`") - #result = hashlib.md5(f"{text}{random.randint(0,1000)}".encode("utf-8")).hexdigest() - #logger.debug("哈希结果: %s...", result[:8]) - #return result - return get_md5(text) \ No newline at end of file + # logger.debug(f"计算MD5-时间复合哈希, 输入`{text}`") + # result = hashlib.md5(f"{text}{random.randint(0,1000)}".encode("utf-8")).hexdigest() + # logger.debug("哈希结果: %s...", result[:8]) + # return result + return get_md5(text) diff --git a/src/heurams/unifront/session.py b/src/heurams/unifront/session.py index f5aab12..09cfc15 100644 --- a/src/heurams/unifront/session.py +++ b/src/heurams/unifront/session.py @@ -1,3 +1,5 @@ """会话模块""" + + class Session: - pass \ No newline at end of file + pass