Skip to content

feat: Bug Fixes & Performance Optimization#67

Merged
OctagonalStar merged 4 commits intoOctagonalStar:mainfrom
JYinherit:main
Feb 28, 2026
Merged

feat: Bug Fixes & Performance Optimization#67
OctagonalStar merged 4 commits intoOctagonalStar:mainfrom
JYinherit:main

Conversation

@JYinherit
Copy link
Contributor

[Arabic Learning] Bug Fixes & Performance Optimization

📅 版本信息

  • 平台: Android (v8aRelease)
  • 存储方式: IndexDB

🐛 描述问题与复现步骤

1. 规律学习重复推送同一个单词

  • 问题描述: 在“学习推送单词”模块中,由于随机数生成逻辑使用的是固定长度的 for 循环和随机种子组合,系统不会在当次批次内校验历史抽取记录,导致同一个单词可能在单次学习会话中被连续推送多次。
  • 复现步骤:
    1. 打开应用,进入学习功能页面。
    2. 点击“学习推送单词”按钮。
    3. 观察连续出来的学习卡片,会频繁出现重复的一模一样的阿拉伯语单词。

2. 新安装无复习任务时 FSRS 设置菜单丢失

  • 问题描述: 当应用初次安装且用户词库中尚无标记为“待复习”的词汇时,直接点击主界面的“复习”按钮会弹出“目前没有要复习的单词”提示并阻断流程。这导致新用户完全无法进入底层的 FSRS (Spaced Repetition System) 配置页面去开启算法或调整复习权重。
  • 复现步骤:
    1. 清除应用数据或全新安装启动。
    2. 在主页直接点击“复习”按钮。
    3. 观察到弹窗拦截,且无法找到其他入口进入 FSRS 设置面板。

3. 同形异义单词重复录入被错误合并(去重逻辑缺陷)

  • 问题描述: 原有的词库数据解析器 dataFormater 使用了全等的阿拉伯语拼写匹配。这会导致拥有相同辅音字母但元音符号 (harakat) 不同的同形异音异义词被错误地判断为“已存在”,从而被底层抛弃。若采用去除音标的“纯净版”对比,又会导致拼写完全相同但中文释义绝然不同的多音多义词被强制合并,使用户在特定课程下永远刷不出对应的生词。
  • 复现步骤:
    1. 准备两份自建词库 JSON 文件。
    2. 文件 A 包含 كَلِمَة (带有元音符号)。文件 B 包含 كلمة (不带符号) 或是 كُتِبَ (同形异音异义)。
    3. 依次导入文件 A 和 B。
    4. 检查全局词库总数,发现 B 中的特异词汇并没有被录入进新字典课程下,发生了数据丢失。

🛠️ 修改方案与实现逻辑

🟢 修复:学习推送批次去重

将 LearningPage 中负责抽取单词的固定大小 for 循环,重构为了由 Set<WordItem> 驱动的 while 循环逻辑。
利用 Set 数据结构天生的唯一性,强制系统不断抽取随机词直至填满用户设定的每日推送配额 (pushAmount)。这从数据结构层面上彻底根除了单批次推送池内出现重复词的可能性

🟢 修复:桥接无数据时的 FSRS 菜单

修改了主界面复习按钮的响应拦截阀。在拦截条件中追加了 || !context.read<Global>().globalFSRS.config.enabled
现在,如果系统检测到复习功能本身处于彻底的禁用/未激活状态,无论待复习卡片数为多少,点击“复习”都将作为安全通道,直接带用户进入 ForeFSRSSettingPage 开启及配置算法。

🟢 新功能/修复:基于 Jaccard 重叠率的同义词交叉校验与 O(1) 性能跃迁

重构了 global.dart 中底层词典数据化模型 dataFormater 的去重与映射逻辑。

  • 实现逻辑(语义防误伤):

    1. 在 utili.dart 中为核心 String 类注入了轻量级、不依赖第三方 NLP 的 Jaccard 字符交集相似度算法 .hasSimilarMeaning()
    2. 系统在导入阶段不仅生成“纯净版阿拉伯语”,同步维护与之对应的中文 chineseList
    3. 当遭遇“纯净发音”完全一致的单词冲撞时,触发 .hasSimilarMeaning() 比对双方的中文释义:清洗掉标点后把两组释义打碎为单汉字集合,计算 intersection / minLength
    4. 如果语义雷同(重合度 > 40% 或极短词包含核心字),视为用户重复导入同义词,安全剥离并在新类目下挂载现有 Index,不增加总库体积
    5. 如果语义毫无交集,认定为多音/多义衍生词(如主动语态“他写了”与被动“被写了”),直接放行,完整录入为全新卡片。
  • 实现逻辑(万级词库导入性能拔高):
    为了承载可能高达数万词的巨型词典交叉比对带来的 CPU 峰值压力,废弃了原有的 rawWordListpureWordList 线性数组。
    使用 Map<String, int> 字典哈希表重新构建了索引链。这使得引擎对全局单词库的存在性嗅探和下标获取的时间复杂度由沉重的 O(N) 跌至完美的 O(1),彻底消灭了导入海量 JSON 词库时可能发生的 UI 线程阻塞与卡顿。

Signed-off-by: JYinherit <jyinherit@qq.com>
@OctagonalStar OctagonalStar self-requested a review February 28, 2026 01:27
@OctagonalStar
Copy link
Owner

📅 版本信息

  • 平台: Android (v8aRelease)
  • 存储方式: IndexDB

你是怎么在Android上用上IndexDB的?(doge

JYinherit and others added 3 commits February 28, 2026 13:32
Co-authored-by: OctagonalStar <76486554+OctagonalStar@users.noreply.github.com>
Signed-off-by: JYinherit <138550825+JYinherit@users.noreply.github.com>
Signed-off-by: JYinherit <jyinherit@qq.com>
@JYinherit
Copy link
Contributor Author

问题描述:在没有词库(或第一次开启没触发过学习)的情况下,不仅 getLeastDueCard() 从空数组取数会报 RangeError 崩溃,而且LearningPage 会拦截你,只要 FSRS已开启 且 待复习数量为0,它就不让你进入复习界面
解决方案:getLeastDueCard() 遇到空卡片记录会安全返回跳过
每日推送随机抽词前加入了空词库检测
无论 FSRS 状态如何,去除了点击“复习”按钮时“目前没有要复习的单词”的阻隔,永远可以进入 FSRS 管理页
当待复习单词等于0时,进入 FSRS 后不再自动闪退,而是保持在带有右上角齿轮⚙️的界面
在 ForeFSRSSettingPage 的底部新增了一个红色的【重置并停用 FSRS】按钮(带有二次确认弹窗)

@OctagonalStar OctagonalStar merged commit 13b15f1 into OctagonalStar:main Feb 28, 2026
3 checks passed
OctagonalStar added a commit that referenced this pull request Mar 1, 2026
Signed-off-by: OctagonalStar <76486554+OctagonalStar@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants