规范代码

This commit is contained in:
2025-08-06 06:11:22 +08:00
parent 2cf2cdb33f
commit dd74dddf00
7 changed files with 344 additions and 261 deletions

169
main.py
View File

@@ -1,35 +1,43 @@
from textual.app import App, ComposeResult
from textual.widgets import Header, Footer, ListView, ProgressBar, DirectoryTree, ListItem, Label, Static, Button
from textual.widgets import (
Header,
Footer,
ListView,
ProgressBar,
DirectoryTree,
ListItem,
Label,
Static,
Button,
)
from textual.containers import Container, Horizontal, Center
from textual.screen import Screen
import pathlib
import threading
import edge_tts as tts
from playsound import playsound
import particles as pt
from reactor import Reactor, Apparatus
import auxiliary as aux
import compositions as compo
import builtins
# 保存原始的 open 函数
_original_open = builtins.open
# 定义新的 open 函数,默认使用 UTF-8
def _open(*args, **kwargs):
if 'encoding' not in kwargs:
kwargs['encoding'] = 'utf-8'
if "encoding" not in kwargs:
kwargs["encoding"] = "utf-8"
return _original_open(*args, **kwargs)
# 替换全局的 open
builtins.open = _open
ver = '0.3.0b'
ver = "0.3.0b"
config = aux.ConfigFile("config.toml")
class MemScreen(Screen):
BINDINGS = [
("d", "toggle_dark", "改变色调"),
@@ -49,38 +57,30 @@ class MemScreen(Screen):
("/", "press('q0')", None),
]
btn = dict()
def __init__(
self,
nucleon_file: pt.NucleonUnion,
electron_file: pt.ElectronUnion,
tasked_num
tasked_num,
):
super().__init__(name=None, id=None, classes=None)
self.reactor = Reactor(nucleon_file, electron_file, self, tasked_num)
self.stage = 1
self.stage += self.reactor.set_round_templated(self.stage)
##print(self.reactor.procession)
self.reactor.forward()
#self.compo:compo.Composition = compo.Placeholder(self)
self.compo = next(self.reactor.current_appar)
def compose(self) -> ComposeResult:
#print(self.compo)
yield Header(show_clock=True)
with Center():
yield Static(f"{len(self.reactor.procession) - self.reactor.index}/{len(self.reactor.procession)}")
#yield ProgressBar(total=len(self.reactor.procession) - 1, show_percentage=False, show_eta=False, id="progress")
yield Static(
f"{len(self.reactor.procession) - self.reactor.index}/{len(self.reactor.procession)}"
)
yield from self.compo.compose()
yield Footer()
"""
def _get_progress_text(self):
return f"{len(self.reactor.procession) - self.reactor.index}/{len(self.reactor.procession)}"
"""
def on_mount(self):
# 首次挂载时调用
pass
def on_button_pressed(self, event):
@@ -90,13 +90,12 @@ class MemScreen(Screen):
def _forward_judge(self, ret):
if ret == -1:
return
if ret == 0: # 成功
if ret == 0:
try:
self.compo = next(self.reactor.current_appar)
self.refresh_ui()
except StopIteration:
nxt = self.reactor.forward(1)
#print(2)
try:
self.compo = next(self.reactor.current_appar)
except:
@@ -106,13 +105,13 @@ class MemScreen(Screen):
if self.stage == 4:
if config.get("save"):
self.reactor.save()
self.compo = compo.Finished(self, None, pt.Atom.placeholder())
self.compo = compo.Finished(
self, None, pt.Atom.placeholder()
)
self.refresh_ui()
#self._show_finished_screen("今日目标已完成")
else:
self.reactor.set_round_templated(self.stage)
self.reactor.forward(1)
#self._update_ui()
self.stage += 1
self.compo = next(self.reactor.current_appar)
self.refresh_ui()
@@ -121,71 +120,47 @@ class MemScreen(Screen):
else:
self.refresh_ui()
return
if ret == 1: # 不允许前进
if ret == 1:
self.refresh_ui()
return
def refresh_ui(self):
self.call_later(self.recompose)
#self.call_later(lambda: self.query_one("#progress", expect_type=ProgressBar).advance(self.reactor.index))
##print(area.children)
#for child in list(area.children):
# child.remove() # 致敬传奇组件树 DOM
##print(1,list(self.compo.compose()))
#area.mount(*list(self.compo.compose()))
def report(self, quality):
assessment = self.reactor.report(self.reactor.current_atom, quality)
return assessment
"""if assessment == 1:
# 需要复习
feedback_label.update(f"评分为 {quality}, 已经加入至复习, 请重复记忆")
else:
ret = self.reactor.forward(1)
if ret == -1:
if self.reactor.round_set == 0:
if self.stage == 4:
# NOTE #
if config.get("save"):
self.reactor.save()
self._show_finished_screen("今日目标已完成")
else:
self.reactor.set_round_templated(self.stage)
self.reactor.forward(1)
self._update_ui()
self.stage += 1
return
#feedback_label.update("") # 清除反馈消息
self._update_ui()"""
#def action_press(self, btnid):
# self.on_button_pressed(btnid)
def action_play_voice(self):
def play():
cache_dir = pathlib.Path(f"./cache/voice/")
cache_dir.mkdir(parents = True, exist_ok = True)
cache = cache_dir / f"{self.reactor.current_atom[1].content.replace("/","")}.wav"
cache_dir.mkdir(parents=True, exist_ok=True)
cache = cache_dir / f"{self.reactor.current_atom[1].content.replace('/','')}.wav"
if not cache.exists():
communicate = tts.Communicate(self.reactor.current_atom[1].content.replace("/",""), "zh-CN-YunjianNeural")
communicate.save_sync(f"./cache/voice/{self.reactor.current_atom[1].content.replace("/","")}.wav")
communicate = tts.Communicate(
self.reactor.current_atom[1].content.replace("/", ""),
"zh-CN-YunjianNeural",
)
communicate.save_sync(
f"./cache/voice/{self.reactor.current_atom[1].content.replace('/','')}.wav"
)
playsound(str(cache))
threading.Thread(target=play).start()
def action_toggle_dark(self):
self.app.action_toggle_dark()
def action_pop_screen(self):
"""返回到上一个屏幕"""
self.app.pop_screen()
class PreparationScreen(Screen):
BINDINGS = [
("q", "go_back", "返回"),
("escape", "quit_app", "退出")
]
def __init__(self, nucleon_file: pt.NucleonUnion, electron_file: pt.ElectronUnion) -> None:
class PreparationScreen(Screen):
BINDINGS = [("q", "go_back", "返回"), ("escape", "quit_app", "退出")]
def __init__(
self, nucleon_file: pt.NucleonUnion, electron_file: pt.ElectronUnion
) -> None:
super().__init__(name=None, id=None, classes=None)
self.nucleon_file = nucleon_file
self.electron_file = electron_file
@@ -194,10 +169,19 @@ class PreparationScreen(Screen):
yield Header(show_clock=True)
with Container(id="learning_screen_container"):
yield Label(f"记忆项目: [b]{self.nucleon_file.name}[/b]\n")
yield Label(f"核子文件对象: ./nucleon/[b]{self.nucleon_file.name}[/b].toml")
yield Label(f"子文件对象: ./electron/[b]{self.electron_file.name}[/b].toml")
yield Label(
f"子文件对象: ./nucleon/[b]{self.nucleon_file.name}[/b].toml"
)
yield Label(
f"电子文件对象: ./electron/[b]{self.electron_file.name}[/b].toml"
)
yield Label(f"核子数量:{len(self.nucleon_file)}")
yield Button("开始记忆", id="start_memorizing_button", variant="primary", classes="start-button")
yield Button(
"开始记忆",
id="start_memorizing_button",
variant="primary",
classes="start-button",
)
yield Static(f"\n全文如下:\n")
yield Static(self._get_full_content(), classes="full")
yield Footer()
@@ -205,7 +189,7 @@ class PreparationScreen(Screen):
def _get_full_content(self):
content = ""
for i in self.nucleon_file.nucleons:
content += i['content']
content += i["content"]
return content
def action_go_back(self):
@@ -215,76 +199,79 @@ class PreparationScreen(Screen):
self.app.exit()
def on_button_pressed(self, event: Button.Pressed) -> None:
pass
if event.button.id == "start_memorizing_button":
#init_file(Path(self.atom_file).name)
newscr = MemScreen(self.nucleon_file, self.electron_file, config.get("tasked_number", 8))
self.app.push_screen(
newscr
newscr = MemScreen(
self.nucleon_file, self.electron_file, config.get("tasked_number", 8)
)
#if event.button.id == "edit_metadata_button":
# init_file(Path(self.atom_file).name)
# os.system("reset;nano ./data/" + str(Path(self.atom_file).name.replace(".txt", "_atoms.json")))
self.app.push_screen(newscr)
class FileSelectorScreen(Screen):
global ver
def compose(self) -> ComposeResult:
yield Header(show_clock=True)
yield Container(
Label(f'欢迎使用 "潜进" 辅助记忆软件, 版本 {ver}', classes="title-label"),
Label("选择要学习的文件:", classes="title-label"),
ListView(id="file-list", classes="file-list-view")
ListView(id="file-list", classes="file-list-view"),
)
yield Footer()
def on_mount(self) -> None:
file_list_widget = self.query_one("#file-list", ListView)
nucleon_path = pathlib.Path("./nucleon")
nucleon_files = sorted([f.name for f in nucleon_path.iterdir() if f.suffix == ".toml"])
nucleon_files = sorted(
[f.name for f in nucleon_path.iterdir() if f.suffix == ".toml"]
)
if nucleon_files:
for filename in nucleon_files:
file_list_widget.append(ListItem(Label(filename)))
else:
file_list_widget.append(ListItem(Static("在 ./nucleon/ 中未找到任何核子文件. 请放置文件后重启应用.")))
file_list_widget.append(
ListItem(Static("在 ./nucleon/ 中未找到任何核子文件. 请放置文件后重启应用."))
)
file_list_widget.disabled = True
def on_list_view_selected(self, event: ListView.Selected) -> None:
if not isinstance(event.item, ListItem):
self.notify("无法选择此项。", severity="error")
return
selected_label = event.item.query_one(Label)
if "未找到任何 .toml 文件" in str(selected_label.renderable):
self.notify("请先在 `./atoms/` 目录中放置 .toml 文件。", severity="warning")
return
selected_filename = str(selected_label.renderable)
nucleon_file = pt.NucleonUnion(pathlib.Path("./nucleon") / selected_filename)
nucleon_file = pt.NucleonUnion(
pathlib.Path("./nucleon") / selected_filename
)
electron_file_path = pathlib.Path("./electron") / selected_filename
if electron_file_path.exists():
pass
else:
electron_file_path.touch()
electron_file = pt.ElectronUnion(pathlib.Path("./electron") / selected_filename)
# self.notify(f"已选择: {selected_filename}", timeout=2)
electron_file = pt.ElectronUnion(
pathlib.Path("./electron") / selected_filename
)
self.app.push_screen(PreparationScreen(nucleon_file, electron_file))
def action_quit_app(self) -> None:
self.app.exit()
class AppLauncher(App):
CSS_PATH = "styles.tcss"
TITLE = '潜进 - 辅助记忆程序'
TITLE = "潜进 - 辅助记忆程序"
BINDINGS = [("escape", "quit", "退出"), ("d", "toggle_dark", "改变色调")]
SCREENS = {
"file_selection_screen": FileSelectorScreen,
}
def on_mount(self) -> None:
#self.action_toggle_dark()
self.push_screen("file_selection_screen")
if __name__ == "__main__":
app = AppLauncher()
app.run()
app.run()