Archived
0
0

style: 代码格式化

This commit is contained in:
2025-12-13 21:47:37 +08:00
parent a0b327cdbb
commit baa7ac8ee9
64 changed files with 755 additions and 573 deletions

View File

@@ -14,6 +14,7 @@ from textual.screen import Screen
import heurams.services.version as version
from heurams.context import *
class AboutScreen(Screen):
def compose(self) -> ComposeResult:

View File

@@ -21,6 +21,7 @@ from .about import AboutScreen
import pathlib
class DashboardScreen(Screen):
def compose(self) -> ComposeResult:
@@ -31,7 +32,9 @@ class DashboardScreen(Screen):
Label(f'时区修正: UTC+{config_var.get()["timezone_offset"] / 3600}'),
Label("选择待学习或待修改的记忆单元集:", classes="title-label"),
ListView(id="union-list", classes="union-list-view"),
Label(f'"潜进" 开放源代码软件项目 | 版本 {version.ver} {version.codename.capitalize()} | Wang Zhiyu 2025'),
Label(
f'"潜进" 开放源代码软件项目 | 版本 {version.ver} {version.codename.capitalize()} | Wang Zhiyu 2025'
),
)
yield Footer()
@@ -46,17 +49,20 @@ class DashboardScreen(Screen):
res[0] = f"{filename}\0"
from heurams.kernel.particles.loader import load_electron
import heurams.kernel.particles as pt
electron_file_path = (pathlib.Path(config_var.get()["paths"]["electron_dir"]) / (filestem + ".json"))
if electron_file_path.exists(): # 未找到则创建电子文件 (json)
electron_file_path = pathlib.Path(config_var.get()["paths"]["electron_dir"]) / (
filestem + ".json"
)
if electron_file_path.exists(): # 未找到则创建电子文件 (json)
pass
else:
electron_file_path.touch()
with open(electron_file_path, 'w') as f:
with open(electron_file_path, "w") as f:
f.write("{}")
electron_dict = load_electron(path=electron_file_path) # TODO: 取消硬编码扩展名
electron_dict = load_electron(path=electron_file_path) # TODO: 取消硬编码扩展名
is_due = 0
is_activated = 0
nextdate = 0x3f3f3f3f
nextdate = 0x3F3F3F3F
for i in electron_dict.values():
i: pt.Electron
if i.is_due():
@@ -78,12 +84,18 @@ class DashboardScreen(Screen):
if len(probe["nucleon"]):
for file in probe["nucleon"]:
text = self.item_desc_generator(file)
union_list_widget.append(ListItem(
Label(text[0] + '\n' + text[1]),
))
union_list_widget.append(
ListItem(
Label(text[0] + "\n" + text[1]),
)
)
else:
union_list_widget.append(
ListItem(Static("在 ./nucleon/ 中未找到任何内容源数据文件.\n请放置文件后重启应用.\n或者新建空的单元集."))
ListItem(
Static(
"在 ./nucleon/ 中未找到任何内容源数据文件.\n请放置文件后重启应用.\n或者新建空的单元集."
)
)
)
union_list_widget.disabled = True
@@ -95,27 +107,36 @@ class DashboardScreen(Screen):
if "未找到任何 .toml 文件" in str(selected_label.renderable):
return
selected_filename = pathlib.Path(str(selected_label.renderable)
.partition('\0')[0] # 文件名末尾截断, 保留文件名
.replace('*', "")) # 去除markdown加粗
selected_filename = pathlib.Path(
str(selected_label.renderable)
.partition("\0")[0] # 文件名末尾截断, 保留文件名
.replace("*", "")
) # 去除markdown加粗
nucleon_file_path = pathlib.Path(config_var.get()["paths"]["nucleon_dir"]) / selected_filename
electron_file_path = pathlib.Path(config_var.get()["paths"]["electron_dir"]) / (str(selected_filename.stem) + ".json")
nucleon_file_path = (
pathlib.Path(config_var.get()["paths"]["nucleon_dir"]) / selected_filename
)
electron_file_path = pathlib.Path(config_var.get()["paths"]["electron_dir"]) / (
str(selected_filename.stem) + ".json"
)
self.app.push_screen(PreparationScreen(nucleon_file_path, electron_file_path))
def on_button_pressed(self, event) -> None:
if event.button.id == "new_nucleon_button":
# 切换到创建单元
from .nucreator import NucleonCreatorScreen
newscr = NucleonCreatorScreen()
self.app.push_screen(newscr)
elif event.button.id == "precache_all_button":
# 切换到缓存管理器
from .precache import PrecachingScreen
precache_screen = PrecachingScreen()
self.app.push_screen(precache_screen)
elif event.button.id == "about_button":
from .about import AboutScreen
about_screen = AboutScreen()
self.app.push_screen(about_screen)

View File

@@ -12,10 +12,12 @@ import heurams.kernel.particles as pt
import heurams.kernel.puzzles as pz
from .. import shim
class AtomState(Enum):
FAILED = auto()
NORMAL = auto()
class MemScreen(Screen):
BINDINGS = [
("q", "pop_screen", "返回"),
@@ -27,15 +29,21 @@ class MemScreen(Screen):
if config_var.get()["quick_pass"]:
BINDINGS.append(("k", "quick_pass", "跳过"))
rating = reactive(-1)
def __init__(self, atoms: list, name: str | None = None, id: str | None = None, classes: str | None = None) -> None:
def __init__(
self,
atoms: list,
name: str | None = None,
id: str | None = None,
classes: str | None = None,
) -> None:
super().__init__(name, id, classes)
self.atoms = atoms
self.phaser = Phaser(atoms)
#print(self.phaser.state)
self.procession: Procession = self.phaser.current_procession() # type: ignore
#print(self.phaser.state)
#self.procession.forward(1)
# print(self.phaser.state)
self.procession: Procession = self.phaser.current_procession() # type: ignore
# print(self.phaser.state)
# self.procession.forward(1)
def on_mount(self):
self.load_puzzle()
@@ -45,22 +53,26 @@ class MemScreen(Screen):
try:
print(self.phaser.state)
self.fission = Fission(self.procession.current_atom, self.phaser.state)
#print(1)
# print(1)
puzzle_info = next(self.fission.generate())
print(puzzle_info)
return shim.puzzle2widget[puzzle_info["puzzle"]](atom = self.procession.current_atom, alia = puzzle_info["alia"])
return shim.puzzle2widget[puzzle_info["puzzle"]](
atom=self.procession.current_atom, alia=puzzle_info["alia"]
)
except (KeyError, StopIteration, AttributeError) as e:
print(f"调度展开出错: {e}")
return Static("无法生成谜题")
#print(shim.puzzle2widget[puzzle_info["puzzle"]])
# print(shim.puzzle2widget[puzzle_info["puzzle"]])
def compose(self) -> ComposeResult:
yield Header(show_clock=True)
with Center():
yield Static(f"当前进度: {self.procession.process()}/{self.procession.total_length()}")
#self.mount(self.current_widget()) # type: ignore
yield Static(
f"当前进度: {self.procession.process()}/{self.procession.total_length()}"
)
# self.mount(self.current_widget()) # type: ignore
yield Container(id="puzzle-container")
#yield Button("重新学习此单元", id="re-recognize", variant="warning")
# yield Button("重新学习此单元", id="re-recognize", variant="warning")
yield Footer()
def load_puzzle(self):

View File

@@ -14,6 +14,7 @@ from textual.screen import Screen
from heurams.services.version import ver
class NucleonCreatorScreen(Screen):
BINDINGS = [("q", "go_back", "返回")]
@@ -23,18 +24,20 @@ class NucleonCreatorScreen(Screen):
def search_templates(self):
from pathlib import Path
from heurams.context import config_var
template_dir = Path(config_var.get()['paths']['template_dir'])
template_dir = Path(config_var.get()["paths"]["template_dir"])
templates = list()
for i in template_dir.iterdir():
if i.name.endswith('.toml'):
if i.name.endswith(".toml"):
try:
import toml
with open(i, 'r') as f:
with open(i, "r") as f:
dic = toml.load(f)
desc = dic['__metadata__.attribution']['desc']
templates.append(desc + ' (' + i.name + ')')
desc = dic["__metadata__.attribution"]["desc"]
templates.append(desc + " (" + i.name + ")")
except Exception as e:
templates.append(f'无描述模板 ({i.name})')
templates.append(f"无描述模板 ({i.name})")
print(e)
print(templates)
return templates
@@ -43,10 +46,14 @@ class NucleonCreatorScreen(Screen):
yield Header(show_clock=True)
with Container(id="vice_container"):
yield Label(f"[b]空白单元集创建向导\n")
yield Markdown("> 提示: 你可能注意到当选中文本框时底栏和操作按键绑定将被覆盖 \n只需选中(使用鼠标或 Tab)选择框即可恢复底栏功能")
yield Markdown(
"> 提示: 你可能注意到当选中文本框时底栏和操作按键绑定将被覆盖 \n只需选中(使用鼠标或 Tab)选择框即可恢复底栏功能"
)
yield Markdown("1. 键入单元集名称")
yield Input(placeholder="单元集名称")
yield Markdown("> 单元集名称不应与现有单元集重复. \n> 新的单元集文件将创建在 ./nucleon/你输入的名称.toml")
yield Markdown(
"> 单元集名称不应与现有单元集重复. \n> 新的单元集文件将创建在 ./nucleon/你输入的名称.toml"
)
yield Label(f"\n")
yield Markdown("2. 选择单元集模板")
LINES = self.search_templates()
@@ -79,5 +86,5 @@ class NucleonCreatorScreen(Screen):
def on_button_pressed(self, event) -> None:
event.stop()
if event.button.id == 'submit_button':
if event.button.id == "submit_button":
pass

View File

@@ -21,17 +21,19 @@ import heurams.services.hasher as hasher
from heurams.context import *
from textual.worker import Worker, get_current_worker
class PrecachingScreen(Screen):
"""预缓存音频文件屏幕
缓存记忆单元音频文件, 全部(默认) 或部分记忆单元(可选参数传入)
Args:
nucleons (list): 可选列表, 仅包含 Nucleon 对象
desc (list): 可选字符串, 包含对此次调用的文字描述
"""
BINDINGS = [("q", "go_back", "返回")]
def __init__(self, nucleons: list = [], desc: str = ""):
super().__init__(name=None, id=None, classes=None)
self.nucleons = nucleons
@@ -47,23 +49,23 @@ class PrecachingScreen(Screen):
for i in nucleons:
i: pt.Nucleon
i.do_eval()
#print("完成 EVAL")
# print("完成 EVAL")
def compose(self) -> ComposeResult:
yield Header(show_clock=True)
with Container(id="precache_container"):
yield Label("[b]音频预缓存[/b]", classes="title-label")
if self.nucleons:
yield Static(f"目标单元归属: [b]{self.desc}[/b]", classes="target-info")
yield Static(f"单元数量: {len(self.nucleons)}", classes="target-info")
else:
yield Static("目标: 所有单元", classes="target-info")
yield Static(id="status", classes="status-info")
yield Static(id="current_item", classes="current-item")
yield ProgressBar(total=100, show_eta=False, id="progress_bar")
with Horizontal(classes="button-group"):
if not self.is_precaching:
yield Button("开始预缓存", id="start_precache", variant="primary")
@@ -71,9 +73,9 @@ class PrecachingScreen(Screen):
yield Button("取消预缓存", id="cancel_precache", variant="error")
yield Button("清空缓存", id="clear_cache", variant="warning")
yield Button("返回", id="go_back", variant="default")
yield Static("若您离开此界面, 未完成的缓存进程会自动停止.")
yield Static("缓存程序支持 \"断点续传\".")
yield Static('缓存程序支持 "断点续传".')
yield Footer()
@@ -86,10 +88,10 @@ class PrecachingScreen(Screen):
status_widget = self.query_one("#status", Static)
item_widget = self.query_one("#current_item", Static)
progress_bar = self.query_one("#progress_bar", ProgressBar)
status_widget.update(f"状态: {status}")
item_widget.update(f"当前项目: {current_item}" if current_item else "")
if progress is not None:
progress_bar.progress = progress
progress_bar.advance(0) # 刷新显示
@@ -97,12 +99,14 @@ class PrecachingScreen(Screen):
def precache_by_text(self, text: str):
"""预缓存单段文本的音频"""
from heurams.context import rootdir, workdir, config_var
cache_dir = pathlib.Path(config_var.get()["paths"]["cache_dir"])
cache_dir.mkdir(parents=True, exist_ok=True)
cache_file = cache_dir / f"{hasher.get_md5(text)}.wav"
if not cache_file.exists():
try: # TODO: 调用模块消除tts耦合
try: # TODO: 调用模块消除tts耦合
import edge_tts as tts
communicate = tts.Communicate(text, "zh-CN-XiaoxiaoNeural")
communicate.save_sync(str(cache_file))
return 1
@@ -110,34 +114,30 @@ class PrecachingScreen(Screen):
print(f"预缓存失败 '{text}': {e}")
return 0
return 1
def precache_by_nucleon(self, nucleon: pt.Nucleon):
"""依据 Nucleon 缓存"""
#print(nucleon.metadata['formation']['tts_text'])
ret = self.precache_by_text(nucleon.metadata['formation']['tts_text'])
# print(nucleon.metadata['formation']['tts_text'])
ret = self.precache_by_text(nucleon.metadata["formation"]["tts_text"])
return ret
#print(f"TTS 缓存: {nucleon.metadata['formation']['tts_text']}")
# print(f"TTS 缓存: {nucleon.metadata['formation']['tts_text']}")
def precache_by_list(self, nucleons: list):
"""依据 Nucleons 列表缓存"""
for idx, nucleon in enumerate(nucleons):
#print(f"PROC: {nucleon}")
# print(f"PROC: {nucleon}")
worker = get_current_worker()
if worker and worker.is_cancelled: # 函数在worker中执行且已被取消
if worker and worker.is_cancelled: # 函数在worker中执行且已被取消
return False
text = nucleon.metadata['formation']['tts_text']
#self.current_item = text[:30] + "..." if len(text) > 50 else text
#print(text)
text = nucleon.metadata["formation"]["tts_text"]
# self.current_item = text[:30] + "..." if len(text) > 50 else text
# print(text)
self.processed += 1
#print(self.processed)
#print(self.total)
# print(self.processed)
# print(self.total)
progress = int((self.processed / self.total) * 100) if self.total > 0 else 0
#print(progress)
self.update_status(
f"正处理 ({idx + 1}/{len(nucleons)})",
text,
progress
)
# print(progress)
self.update_status(f"正处理 ({idx + 1}/{len(nucleons)})", text, progress)
ret = self.precache_by_nucleon(nucleon)
if not ret:
self.update_status(
@@ -145,6 +145,7 @@ class PrecachingScreen(Screen):
f"处理失败, 跳过: {self.current_item}",
)
import time
time.sleep(1)
if self.cancel_flag:
worker.cancel()
@@ -153,9 +154,9 @@ class PrecachingScreen(Screen):
return True
def precache_by_nucleons(self):
#print("开始缓存")
# print("开始缓存")
ret = self.precache_by_list(self.nucleons)
#print(f"返回 {ret}")
# print(f"返回 {ret}")
return ret
def precache_by_filepath(self, path: pathlib.Path):
@@ -165,13 +166,15 @@ class PrecachingScreen(Screen):
lst.append(i[0])
return self.precache_by_list(lst)
def precache_all_files(self):
"""预缓存所有文件"""
from heurams.context import rootdir, workdir, config_var
nucleon_path = pathlib.Path(config_var.get()["paths"]["nucleon_dir"])
nucleon_files = [f for f in nucleon_path.iterdir() if f.suffix == ".toml"] # TODO: 解耦合
nucleon_files = [
f for f in nucleon_path.iterdir() if f.suffix == ".toml"
] # TODO: 解耦合
# 计算总项目数
self.total = 0
nu = list()
@@ -186,16 +189,26 @@ class PrecachingScreen(Screen):
i: pt.Nucleon
i.do_eval()
return self.precache_by_list(nu)
def on_button_pressed(self, event: Button.Pressed) -> None:
event.stop()
if event.button.id == "start_precache" and not self.is_precaching:
# 开始预缓存
if self.nucleons:
self.precache_worker = self.run_worker(self.precache_by_nucleons, thread=True, exclusive=True, exit_on_error=True)
self.precache_worker = self.run_worker(
self.precache_by_nucleons,
thread=True,
exclusive=True,
exit_on_error=True,
)
else:
self.precache_worker = self.run_worker(self.precache_all_files, thread=True, exclusive=True, exit_on_error=True)
self.precache_worker = self.run_worker(
self.precache_all_files,
thread=True,
exclusive=True,
exit_on_error=True,
)
elif event.button.id == "cancel_precache" and self.is_precaching:
# 取消预缓存
if self.precache_worker:
@@ -204,20 +217,23 @@ class PrecachingScreen(Screen):
self.processed = 0
self.progress = 0
self.update_status("已取消", "预缓存操作被用户取消", 0)
elif event.button.id == "clear_cache":
# 清空缓存
try:
import shutil
from heurams.context import rootdir, workdir, config_var
shutil.rmtree(f"{config_var.get()["paths"]["cache_dir"]}", ignore_errors=True)
shutil.rmtree(
f"{config_var.get()["paths"]["cache_dir"]}", ignore_errors=True
)
self.update_status("已清空", "音频缓存已清空", 0)
except Exception as e:
self.update_status("错误", f"清空缓存失败: {e}")
self.cancel_flag = 1
self.processed = 0
self.progress = 0
elif event.button.id == "go_back":
self.action_go_back()

View File

@@ -15,15 +15,11 @@ import heurams.kernel.particles as pt
import heurams.services.hasher as hasher
from heurams.context import *
class PreparationScreen(Screen):
BINDINGS = [
("q", "go_back", "返回"),
("p", "precache", "预缓存音频")
]
def __init__(
self, nucleon_file: pathlib.Path, electron_file: pathlib.Path
) -> None:
class PreparationScreen(Screen):
BINDINGS = [("q", "go_back", "返回"), ("p", "precache", "预缓存音频")]
def __init__(self, nucleon_file: pathlib.Path, electron_file: pathlib.Path) -> None:
super().__init__(name=None, id=None, classes=None)
self.nucleon_file = nucleon_file
self.electron_file = electron_file
@@ -39,10 +35,10 @@ class PreparationScreen(Screen):
yield Label(f"\n单元数量: {len(self.nucleons_with_orbital)}\n")
yield Button(
"开始记忆",
id="start_memorizing_button",
variant="primary",
classes="start-button",
"开始记忆",
id="start_memorizing_button",
variant="primary",
classes="start-button",
)
yield Button(
"预缓存音频",
@@ -68,6 +64,7 @@ class PreparationScreen(Screen):
def action_precache(self):
from ..screens.precache import PrecachingScreen
lst = list()
for i in self.nucleons_with_orbital:
lst.append(i[0])
@@ -97,8 +94,8 @@ class PreparationScreen(Screen):
atom.link("orbital_path", None)
atoms.append(atom)
from .memorizor import MemScreen
memscreen = MemScreen(atoms)
self.app.push_screen(memscreen)
elif event.button.id == "precache_button":
self.action_precache()