fix: 稳定性修复

This commit is contained in:
2026-05-04 13:13:05 +08:00
parent 2ee7ff6b0e
commit 37a05874b2
13 changed files with 11612 additions and 27 deletions

View File

@@ -1,4 +1,4 @@
zmq_debug = false zmq_debug = true
_zmq_debug_desc = "[调试] ZeroMQ 调试服务器, 这会在 zmq_debug_port 上打开一个服务器\n调试工具可远程在 HeurAMS 内执行任意 python 代码, 无必要请关闭" _zmq_debug_desc = "[调试] ZeroMQ 调试服务器, 这会在 zmq_debug_port 上打开一个服务器\n调试工具可远程在 HeurAMS 内执行任意 python 代码, 无必要请关闭"
zmq_debug_port = 5555 zmq_debug_port = 5555
_zmq_debug_port_desc = "[调试] ZeroMQ 调试服务器端口" _zmq_debug_port_desc = "[调试] ZeroMQ 调试服务器端口"

View File

@@ -1,2 +1,2 @@
min_denominator = "2" min_denominator = " 1"
_min_denominator_desc = "设空比例系数的倒数" _min_denominator_desc = "设空比例系数的倒数"

View File

@@ -1,6 +1,6 @@
algorithm = "NSP-0" algorithm = "NSP-0"
_algorithm_desc = "记忆调度算法" _algorithm_desc = "记忆调度算法"
scheduled_num = 420 scheduled_num = 35
_scheduled_num_desc = "单次记忆单元数量" _scheduled_num_desc = "单次记忆单元数量"
[_algorithm_candidate] [_algorithm_candidate]

View File

@@ -1 +1,164 @@
[] [
{
"repo_path": "cngk-t",
"ident": "庄宗受而藏之于庙. 其后用兵, 则遣从事以一少牢告庙, 请其矢, 盛以锦囊, 负而前驱, 及凯旋而纳之",
"added": 1777679860,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "方其系燕父子以组, 函梁君臣之首, 入于太庙, 还矢先王, 而告以成功, 其意气之盛, 可谓壮哉!",
"added": 1777684719,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "洎牧以谗诛, 邯郸为郡, 惜其用武而不终也.",
"added": 1777748505,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "苟以天下之大, 下而从六国破亡之故事, 是又在六国下矣.",
"added": 1777749120,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "故木受绳则直, 金就砺则利, 君子博学而日参省乎己, 则知明而行无过矣.",
"added": 1777749248,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "假舆马者, 非利足也, 而致千里; 假舟楫者, 非能水也, 而绝江河.",
"added": 1777749385,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "向使三国各爱其地, 齐人勿附于秦, 刺客不行, 良将犹在,",
"added": 1777749648,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "则胜负之数, 存亡之理, 当与秦相较, 或未易量.",
"added": 1777749737,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "呜呼! 以赂秦之地封天下之谋臣, 以事秦之心礼天下之奇才, 并力西向,",
"added": 1777749774,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "积土成山, 风雨兴焉; 积水成渊, 蛟龙生焉; 积善成德, 而神明自得, 圣心备焉.",
"added": 1777750294,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "锲而舍之, 朽木不折; 锲而不舍, 金石可镂.",
"added": 1777750446,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "寻寻觅觅, 冷冷清清, 凄凄惨惨戚戚. 乍暖还寒时候, 最难将息. 三杯两盏淡酒, 怎敌他、晚来风急! 雁过也, 正伤心, 却是旧时相识.",
"added": 1777750594,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "满地黄花堆积, 憔悴损, 如今有谁堪摘? 守着窗儿, 独自怎生得黑? 梧桐更兼细雨, 到黄昏、点点滴滴. 这次第, 怎一个愁字了得!",
"added": 1777750678,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "夫六国与秦皆诸侯, 其势弱于秦, 而犹有可以不赂而胜之之势.",
"added": 1777750884,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "登高而招, 臂非加长也, 而见者远; 顺风而呼, 声非加疾也, 而闻者彰.",
"added": 1777750964,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "故不积跬步, 无以至千里; 不积小流, 无以成江海.",
"added": 1777751066,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "且燕赵处秦革灭殆尽之际, 可谓智力孤危, 战败而亡, 诚不得已.",
"added": 1777751570,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "货恶其弃于地也, 不必藏于己; 力恶其不出于身也, 不必为己.",
"added": 1777846911,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "是故谋闭不兴, 盗窃乱贼而不作.",
"added": 1777846943,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "花径不曾缘客扫, 蓬门今始为君开.",
"added": 1777846974,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "盘飧市远无兼味, 樽酒家贫只旧醅.",
"added": 1777847000,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "五花马、千金裘, 呼儿将出换美酒, 与尔同销万古愁!",
"added": 1777847065,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "屈平疾王听之不聪也, 谗谄之蔽明也, 邪曲之害公也, 方正之不容也, 故忧愁幽思而作《离骚》.",
"added": 1777847121,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "夫天者, 人之始也; 父母者, 人之本也.",
"added": 1777847174,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "人穷则反本, 故劳苦倦极, 未尝不呼天也; 疾痛惨怛, 未尝不呼父母也.",
"added": 1777847195,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "信而见疑, 忠而被谤, 能无怨乎?",
"added": 1777847267,
"tags": []
},
{
"repo_path": "cngk-t",
"ident": "屈平正道直行, 竭忠尽智以事其君, 谗人间之, 可谓穷矣.",
"added": 1777847825,
"tags": []
}
]

File diff suppressed because it is too large Load Diff

View File

@@ -13,3 +13,13 @@ NavigatorScreen {
border: thick $background 80%; border: thick $background 80%;
background: $surface; background: $surface;
} }
.favorite-item {
height: auto;
}
.favorite-item-btn {
dock: right;
width: 8;
padding: 0;
}

View File

@@ -2,3 +2,7 @@
height: auto; height: auto;
width: auto; width: auto;
} }
.hori {
height: auto;
}

View File

@@ -60,12 +60,12 @@ API 版本代号: `{version.codename.capitalize()}`
一个基于启发式算法与认知科学理论的辅助记忆调度器, 旨在帮助用户更高效地进行记忆工作与学习规划. 一个基于启发式算法与认知科学理论的辅助记忆调度器, 旨在帮助用户更高效地进行记忆工作与学习规划.
一个开放, 优雅, 易于扩展的间隔重复调度器实验平台, 旨在帮助研究者更高效地进行前沿记忆算法的研究. 一个开放, 优雅, 易于扩展的间隔重复调度器实验平台, 旨在帮助研究者更高效地进行前沿记忆算法的研究.
以 AGPL-3.0 开放源代码, 这直接意味着任何个体直接基于此代码对外或内部提供的应用和服务, 无论本地或网络, 必须向所有用户公开完整修改后的源代码, 且继续沿用 AGPL-3.0 协议. 您正使用的 TUI 用户界面是 python 版本程序库自带的基本用户界面, 以作为第一个全功能前端实现与程序库测试套件, 位于程序库下 interface 目录.
您正使用的 TUI 用户界面是 python 版本程序库自带的基本用户界面, 以作为第一个全功能前端实现与程序库测试套件, 位于程序库根目录中的 interface 文件夹.
您可在项目主页 https://ams.pluv27.top 获取用户指南, 开发文档与软件更新. 您可在项目主页 https://ams.pluv27.top 获取用户指南, 开发文档与软件更新.
以 GNU Affero 通用公共许可证 (第3版) 开放源代码.
如果您觉得这个软件有用, 可以考虑参与贡献, 或在它的源代码仓库给它添加一个星标 :) 如果您觉得这个软件有用, 可以考虑参与贡献, 或在它的源代码仓库给它添加一个星标 :)
您的慷慨支持, 我们必当涌泉相报. 您的慷慨支持, 我们必当涌泉相报.

View File

@@ -7,7 +7,7 @@ from typing import List, Optional
from textual import events, on from textual import events, on
from textual.app import ComposeResult from textual.app import ComposeResult
from textual.containers import ScrollableContainer from textual.containers import ScrollableContainer, Horizontal
from textual.screen import Screen from textual.screen import Screen
from textual.widgets import ( from textual.widgets import (
Button, Button,
@@ -104,23 +104,20 @@ class FavoriteManagerScreen(Screen):
# 尝试获取仓库信息 # 尝试获取仓库信息
repo_info = self._get_repo_info(fav.repo_path, fav) repo_info = self._get_repo_info(fav.repo_path, fav)
title = repo_info.get("title", fav.repo_path) if repo_info else fav.repo_path title = repo_info.get("title", fav.repo_path) if repo_info else fav.repo_path
content_preview = repo_info.get("content_preview", "") if repo_info else ""
added_time = self._format_time(fav.added) added_time = self._format_time(fav.added)
# 构建显示文本 # 构建显示文本
display_text = f"[b]{title}[/b] ({fav.ident})\n" display_text = f"{fav.ident}\n"
if content_preview: display_text += f" [d]添加于: {added_time}\n 来自 {title}[/d]"
display_text += f"{content_preview}\n"
display_text += f"添加于: {added_time}"
if fav.tags: if fav.tags:
display_text += f" 标签: {', '.join(fav.tags)}" display_text += f"{', '.join(fav.tags)}"
# 创建安全的按钮 ID # 创建安全的按钮 ID
button_key = self._encode_favorite_key(fav.repo_path, fav.ident) button_key = self._encode_favorite_key(fav.repo_path, fav.ident)
# 创建列表项,包含移除按钮 # 创建列表项,包含移除按钮
container = ScrollableContainer( container = Horizontal(
Markdown(display_text, classes="favorite-content"), Label(display_text, classes="favorite-content"),
Button("移除", id=f"remove-{button_key}", variant="error"), Button("移除", id=f"remove-{button_key}", variant="error", flat=True, classes="favorite-item-btn"),
classes="favorite-item", classes="favorite-item",
) )
return ListItem(container) return ListItem(container)

View File

@@ -24,12 +24,13 @@ logger = get_logger(__name__)
class MemScreen(Screen): class MemScreen(Screen):
BINDINGS = [ BINDINGS = [
("q", "go_back", "返回"), ("q", "go_back_notif", "返回"),
("p", "prev", "查看上一个"), ("p", "prev", "查看上一个"),
("d", "toggle_dark", ""), ("d", "toggle_dark", ""),
("v", "play_voice", "朗读"), ("v", "play_voice", "朗读"),
("*", "toggle_favorite", "收藏"), ("*", "toggle_favorite", "收藏"),
("r", "resume_mark"), ("r", "resume_mark"),
("Q", "go_back"),
("n", "block_prompt"), ("n", "block_prompt"),
("s", "block_prompt"), ("s", "block_prompt"),
("z", "block_prompt"), ("z", "block_prompt"),
@@ -220,6 +221,8 @@ class MemScreen(Screen):
self.update_state() # 刷新状态 self.update_state() # 刷新状态
self.expander = self.procession.get_expander() self.expander = self.procession.get_expander()
def action_go_back_notif(self):
self.notify("确定吗? 按下大写 Q 以返回")
def action_go_back(self): def action_go_back(self):
self.app.pop_screen() self.app.pop_screen()

View File

@@ -2,7 +2,7 @@ import copy
import random import random
from typing import TypedDict from typing import TypedDict
from textual.containers import ScrollableContainer from textual.containers import ScrollableContainer, Horizontal
from textual.widget import Widget from textual.widget import Widget
from textual.widgets import Button, Label, Markdown from textual.widgets import Button, Label, Markdown
from textual.events import Key from textual.events import Key
@@ -71,6 +71,7 @@ class ClozePuzzle(BasePuzzleWidget):
# 渲染当前问题的选项 # 渲染当前问题的选项
with ScrollableContainer(id="btn-container") as s: with ScrollableContainer(id="btn-container") as s:
c = 0 c = 0
btns = []
for i in self.ans: for i in self.ans:
h = str(hash(i)) h = str(hash(i))
if hash(i) in self.hashmap.keys(): if hash(i) in self.hashmap.keys():
@@ -80,7 +81,12 @@ class ClozePuzzle(BasePuzzleWidget):
btnid = f"sel000-{h}" btnid = f"sel000-{h}"
logger.debug(f"建立按钮 {btnid}") logger.debug(f"建立按钮 {btnid}")
self.btn_shortcuts[f"{c}"] = btnid self.btn_shortcuts[f"{c}"] = btnid
yield Button(f"[{c}] {i}", id=f"{btnid}") btns.append(Button(f"{i}", id=f"{btnid}", classes='cloze-option-btn'))
for i in range((len(btns)+1)//2):
if 2 * i + 1 + 1 <= len(btns):
yield Horizontal(btns[i], btns[len(btns) - 1 - i], classes='hori')
else:
yield btns[i]
s.focus() s.focus()
yield Button("退格", id="delete") yield Button("退格", id="delete")
@@ -130,7 +136,7 @@ class ClozePuzzle(BasePuzzleWidget):
self.atom.minimize(rating) self.atom.minimize(rating)
def on_key(self, event: Key) -> None: def on_key(self, event: Key) -> None:
self.notify(event.key) #self.notify(event.key)
if event.key in self.btn_shortcuts: if event.key in self.btn_shortcuts:
btn_id = self.btn_shortcuts.get(event.key) btn_id = self.btn_shortcuts.get(event.key)
btn_id = "#" + btn_id btn_id = "#" + btn_id

View File

@@ -54,9 +54,10 @@ class NSP0Algorithm(BaseAlgorithm):
logger.debug("feedback 为 -1, 跳过更新") logger.debug("feedback 为 -1, 跳过更新")
return return
algodata[cls.algo_name]["interval"] = 1 if feedback <= 3 else float("inf") algodata[cls.algo_name]["interval"] = 1 if feedback <= 3 else float("inf")
algodata[cls.algo_name]["important"] = ( if not algodata[cls.algo_name]["important"]:
1 if feedback <= 3 else algodata[cls.algo_name]["important"] algodata[cls.algo_name]["important"] = (
) 1 if feedback <= 3 else algodata[cls.algo_name]["important"]
)
algodata[cls.algo_name]["last_date"] = timer.get_daystamp() algodata[cls.algo_name]["last_date"] = timer.get_daystamp()
algodata[cls.algo_name]["next_date"] = ( algodata[cls.algo_name]["next_date"] = (
timer.get_daystamp() + algodata[cls.algo_name]["interval"] timer.get_daystamp() + algodata[cls.algo_name]["interval"]