This commit is contained in:
2025-08-02 17:48:42 +08:00
parent 4d6d1f1b60
commit 445e15646b
11 changed files with 122 additions and 55 deletions

View File

@@ -30,4 +30,4 @@ def get_daystamp() -> int:
#print(f"TIME OVERRIDEED TO {time_override}") #print(f"TIME OVERRIDEED TO {time_override}")
return int(time_override) return int(time_override)
return int(time.time() // (24 * 3600)) return int(time.time() // (24 * 3600))

View File

@@ -4,10 +4,11 @@ from textual.widgets import Header, Footer, ListView, ListItem, Label, Static, B
from textual.containers import Container, Horizontal from textual.containers import Container, Horizontal
from textual.screen import Screen from textual.screen import Screen
import pathlib import pathlib
from typing import Tuple, Dict
import particles as pt import particles as pt
class Composition(): class Composition():
def __init__(self, screen: Screen, atom): def __init__(self, screen: Screen, atom: Tuple[pt.Electron, pt.Nucleon, Dict]):
self.screen = screen self.screen = screen
self.atom = atom self.atom = atom
def compose(self): def compose(self):
@@ -17,16 +18,55 @@ class Composition():
print(event.button.id) print(event.button.id)
self.screen.query_one("#testlabel", Label).update("hi") self.screen.query_one("#testlabel", Label).update("hi")
class Placeholder(Composition):
def __init__(self, screen: Screen):
self.screen = screen
def compose(self):
yield Label("示例标签", id="testlabel")
yield Button("示例按钮", id="testbtn")
def handler(self, event):
print(event.button.id)
self.screen.query_one("#testlabel", Label).update("hi")
class Recognition(Composition): class Recognition(Composition):
def __init__(self, screen: Screen, atom): def __init__(self, screen: Screen, atom: Tuple[pt.Electron, pt.Nucleon, Dict]):
pass super().__init__(screen, atom)
def compose(self):
yield Label(self.atom[1]["content"], id="sentence")
for i in self.atom[2]["testdata"]["additional_inf"]:
yield Label("[" + self.atom[2]["keydata"][i] + "] " + str(self.atom[1][i]), id=f"label_{i}")
yield Button("我已知晓", id="ok")
def handler(self, event):
if event.button.id == "ok":
return 1
class FillBlank(Composition):
def __init__(self, screen: Screen, atom: Tuple[pt.Electron, pt.Nucleon, Dict]):
super().__init__(screen, atom)
def compose(self):
yield Label(self.atom[1]["content"], id="sentence")
for i in self.atom[2]["testdata"]["additional_inf"]:
yield Label(f"{self.atom[2]["keydata"][i]}: {self.atom[1][i]}", id=f"label_{i}")
yield Button("我已知晓", id="ok")
def handler(self, event):
if event.button.id == "ok":
return 1
registry = {
"sample": Composition,
"recognition": Recognition,
"fill_blank_test": FillBlank,
"draw_card_test": Composition,
}
# TEST # TEST
class TestScreen(Screen): class TestScreen(Screen):
def __init__(self): def __init__(self):
super().__init__(name=None, id=None, classes=None) super().__init__(name=None, id=None, classes=None)
self.comp = Composition(self, pt.Atom.advanced_placeholder()) self.comp = Recognition(self, pt.Atom.advanced_placeholder())
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
yield Header(show_clock=True) yield Header(show_clock=True)
yield from self.comp.compose() yield from self.comp.compose()

51
main.py
View File

@@ -1,5 +1,5 @@
from textual.app import App, ComposeResult from textual.app import App, ComposeResult
from textual.widgets import Header, Footer, ListView, ListItem, Label, Static, Button from textual.widgets import Header, Footer, ListView, DirectoryTree, ListItem, Label, Static, Button
from textual.containers import Container, Horizontal from textual.containers import Container, Horizontal
from textual.screen import Screen from textual.screen import Screen
import pathlib import pathlib
@@ -9,8 +9,9 @@ from playsound import playsound
from textual.logging import TextualHandler from textual.logging import TextualHandler
import particles as pt import particles as pt
from reactor import Reactor from reactor import Reactor, Apparatus
import auxiliary as aux import auxiliary as aux
import compositions as compo
ver = '0.3.0' ver = '0.3.0'
@@ -42,57 +43,32 @@ class MemScreen(Screen):
tasked_num tasked_num
): ):
super().__init__(name=None, id=None, classes=None) super().__init__(name=None, id=None, classes=None)
self.reactor = Reactor(nucleon_file, electron_file, tasked_num) self.reactor = Reactor(nucleon_file, electron_file, self, tasked_num)
self.stage = 1 self.stage = 1
self.stage += self.reactor.set_round_templated(self.stage) self.stage += self.reactor.set_round_templated(self.stage)
#print(self.reactor.procession) #print(self.reactor.procession)
self.reactor.forward() self.reactor.forward()
self.compo:compo.Composition = compo.Placeholder(self)
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
self.compo = next(self.reactor.current_appar)
yield Header(show_clock=True) yield Header(show_clock=True)
with Container(id="main_container"): with Container(id="main_container"):
yield Label(self.reactor.round_title, id="round_title") yield from self.compo.compose()
yield Label("记住了吗?", id="question")
yield Static(self.reactor.current_atom[1].content, id="sentence")
yield Static("", id="feedback") # 用于显示反馈
yield Label(self._get_progress_text(), id="progress")
with Container(id="button_container"):
if 1:
self.btn['5'] = Button("完美回想", variant="success", id="q5", classes="choice")
self.btn['4'] = Button("犹豫后正确", variant="success", id="q4", classes="choice")
self.btn['3'] = Button("困难地正确", variant="warning", id="q3", classes="choice")
self.btn['2'] = Button("错误但熟悉", variant="warning", id="q2", classes="choice")
self.btn['1'] = Button("错误且不熟", variant="error", id="q1", classes="choice")
self.btn['0'] = Button("完全空白", variant="error", id="q0", classes="choice")
yield Horizontal(self.btn['5'], self.btn['4'])
yield Horizontal(self.btn['3'], self.btn['2'])
yield Horizontal(self.btn['1'], self.btn['0'])
yield Footer() yield Footer()
"""
def _get_progress_text(self): def _get_progress_text(self):
return f"{len(self.reactor.procession) - self.reactor.index}/{len(self.reactor.procession)}" return f"{len(self.reactor.procession) - self.reactor.index}/{len(self.reactor.procession)}"
"""
def on_mount(self): def on_mount(self):
# 首次挂载时调用 # 首次挂载时调用
self._update_ui() pass
def _update_ui(self):
self.query_one("#round_title", Label).update(self.reactor.round_title)
self.query_one("#sentence", Static).update(self.reactor.current_atom[1].content)
self.query_one("#progress", Label).update(self._get_progress_text())
self.query_one("#feedback", Static).update("") # 清除任何之前的反馈消息
def _show_finished_screen(self, message):
self.query_one("#question", Label).update(message)
self.query_one("#sentence", Static).update("已经完成记忆任务")
self.query_one("#round_title").display = False
self.query_one("#progress").display = False
for i in range(6):
self.query_one(f"#q{i}", Button).display = False
def on_button_pressed(self, event): def on_button_pressed(self, event):
feedback_label = self.query_one("#feedback", Static) self.compo.handler(event)
"""feedback_label = self.query_one("#feedback", Static)
if type(event) == str: if type(event) == str:
btnid = event btnid = event
else: else:
@@ -119,7 +95,8 @@ class MemScreen(Screen):
self.stage += 1 self.stage += 1
return return
#feedback_label.update("") # 清除反馈消息 #feedback_label.update("") # 清除反馈消息
self._update_ui() self._update_ui()"""
def action_press(self, btnid): def action_press(self, btnid):
self.on_button_pressed(btnid) self.on_button_pressed(btnid)

View File

@@ -258,7 +258,7 @@ class Atom():
"keyword_note": "关键词翻译", "keyword_note": "关键词翻译",
"translation": "语句翻译"}, "translation": "语句翻译"},
"testdata":{ "testdata":{
"additional_inf": ["translation", "note"], "additional_inf": ["translation", "note", "keyword_note"],
"fill_blank_test": ["translation"], "fill_blank_test": ["translation"],
"draw_card_test": ["keyword_note"] "draw_card_test": ["keyword_note"]
}, },

View File

@@ -0,0 +1,44 @@
import random
class Puzzle():
pass
class BlankPuzzle(Puzzle):
"""填空题谜题生成器
Args:
text: 原始字符串(需要 "/" 分割句子, 末尾应有 "/")
min_denominator: 最小概率倒数(如占所有可生成填空数的 1/7 中的 7, 若期望值小于 1, 则取 1)
"""
def __init__(self, text, min_denominator):
self.text = text
self.min_denominator = min_denominator
self.wording = "填空题 - 尚未刷新谜题"
self.answer = ["填空题 - 尚未刷新谜题"]
def refresh(self): # 刷新谜题
placeholder = "___SLASH___"
tmp_text = self.text.replace("/", placeholder)
words = tmp_text.split(placeholder)
if not words:
return ""
words = [word for word in words if word]
num_blanks = min(max(1, len(words) // self.min_denominator), len(words))
indices_to_blank = random.sample(range(len(words)), num_blanks)
indices_to_blank.sort()
blanked_words = list(words)
answer = list()
for index in indices_to_blank:
blanked_words[index] = "__" * len(words[index])
answer.append(words[index])
result = []
for word in blanked_words:
result.append(word)
self.answer = answer
self.wording = "".join(result)
def __str__(self):
return f"{self.wording}\n{str(self.answer)}"
class SelectionPuzzle(Puzzle):
"选择题谜题生成器"

View File

@@ -2,30 +2,35 @@ import typing
import particles as pt import particles as pt
import pathlib import pathlib
import auxiliary as aux import auxiliary as aux
import compositions import compositions as comps
import random
class Apparatus(): class Apparatus():
"""反应器对象, 处理一个原子的记忆工作, 并反馈到布局""" """反应器对象, 决策一个原子的不同记忆方式, 并反馈到布局"""
def __init__(self, atom): def __init__(self, screen, atom):
self.electron: pt.Electron = atom[0] self.electron: pt.Electron = atom[0]
self.nucleon: pt.Nucleon = atom[1] self.nucleon: pt.Nucleon = atom[1]
self.positron: dict = atom[2] self.positron: dict = atom[2]
self.testdata = self.positron["testdata"] self.testdata = self.positron["testdata"]
self.procession: typing.List[comps.Composition] = list()
def iterator(self):
pass
def composer(self):
if self.positron["is_new_activation"] == 1: if self.positron["is_new_activation"] == 1:
self.positron["is_new_activation"] = 0 self.positron["is_new_activation"] = 0
self.procession.append(comps.registry["recognition"](screen, atom))
return
for i in self.positron["testdata"].keys():
if i == "additional_inf":
continue
self.procession.append(comps.registry[i](screen, atom))
# self.procession.reverse()
random.shuffle(self.procession)
def updater(self): def iterator(self):
pass yield from self.procession
class Reactor(): class Reactor():
"""反应堆对象, 处理和分配一次文件记忆流程的资源与策略""" """反应堆对象, 处理和分配一次文件记忆流程的资源与策略"""
def __init__(self, nucleon_file: pt.NucleonUnion, electron_file: pt.ElectronUnion, tasked_num): def __init__(self, nucleon_file: pt.NucleonUnion, electron_file: pt.ElectronUnion, screen, tasked_num):
# 导入原子对象 # 导入原子对象
self.reported = set() self.reported = set()
self.nucleon_file = nucleon_file self.nucleon_file = nucleon_file
@@ -34,7 +39,7 @@ class Reactor():
self.atoms_new = list() self.atoms_new = list()
self.atoms_review = list() self.atoms_review = list()
counter = self.tasked_num counter = self.tasked_num
self.screen = screen
self.electron_dict = electron_file.electrons_dict self.electron_dict = electron_file.electrons_dict
def electron_dict_get_fallback(key) -> pt.Electron: def electron_dict_get_fallback(key) -> pt.Electron:
@@ -113,6 +118,7 @@ class Reactor():
return -1 # 此轮已完成 return -1 # 此轮已完成
self.index += step self.index += step
self.current_atom = self.procession[self.index] self.current_atom = self.procession[self.index]
self.current_appar = Apparatus(self.screen, self.current_atom).iterator()
return 0 return 0
def save(self): def save(self):