Update: TTS settings modal and settings types

This commit is contained in:
likingcode
2026-03-18 15:18:47 +08:00
parent 71232cf489
commit 4ea96243c2
13 changed files with 1393 additions and 149 deletions

View File

@@ -1,23 +1,58 @@
import type { StudyProgress, DifficultyRating } from '../types/vocabulary';
interface SRSConfig {
initialEase: number;
minEase: number;
maxInterval: number;
learningStepInterval: number;
}
const DEFAULT_CONFIG: SRSConfig = {
initialEase: 2.5,
minEase: 1.3,
maxInterval: 365, // 最大间隔 365 天
learningStepInterval: 10, // 学习步骤间隔(分钟)
};
/**
* 改进的 SM-2 算法实现
* 基于 Anki 和 SuperMemo 的研究
*/
export function calculateNextReview(
progress: StudyProgress,
rating: DifficultyRating
rating: DifficultyRating,
config: SRSConfig = DEFAULT_CONFIG
): StudyProgress {
const newProgress = { ...progress };
const { minEase, maxInterval } = config;
// 如果是新单词repetitions === 0使用学习步骤
if (progress.repetitions === 0 && rating === 'again') {
// 标记为"再次",保持在第一步
newProgress.interval = 0;
newProgress.easeFactor = Math.max(minEase, progress.easeFactor - 0.2);
newProgress.nextReviewDate = new Date(Date.now() + DEFAULT_CONFIG.learningStepInterval * 60 * 1000);
newProgress.lastStudiedDate = new Date();
return newProgress;
}
switch (rating) {
case 'again':
// 完全重置,但保留一些学习历史
newProgress.interval = 1;
newProgress.repetitions = 0;
newProgress.easeFactor = Math.max(1.3, progress.easeFactor - 0.2);
newProgress.easeFactor = Math.max(minEase, progress.easeFactor - 0.2);
break;
case 'hard':
newProgress.interval = Math.round(progress.interval * 1.2);
// 困难:间隔增长较慢
newProgress.interval = Math.max(1, Math.round(progress.interval * 1.2));
newProgress.repetitions += 1;
newProgress.easeFactor = Math.max(1.3, progress.easeFactor - 0.15);
newProgress.easeFactor = Math.max(minEase, progress.easeFactor - 0.15);
break;
case 'good':
// 良好:标准 SM-2 算法
if (progress.repetitions === 0) {
newProgress.interval = 1;
} else if (progress.repetitions === 1) {
@@ -27,7 +62,9 @@ export function calculateNextReview(
}
newProgress.repetitions += 1;
break;
case 'easy':
// 简单:间隔增长更快
if (progress.repetitions === 0) {
newProgress.interval = 4;
} else {
@@ -38,9 +75,52 @@ export function calculateNextReview(
break;
}
// 限制最大间隔
newProgress.interval = Math.min(newProgress.interval, maxInterval);
// 确保 easeFactor 在合理范围内
newProgress.easeFactor = Math.max(minEase, Math.min(newProgress.easeFactor, 3.0));
// 计算下次复习日期
const now = new Date();
newProgress.nextReviewDate = new Date(now.getTime() + newProgress.interval * 24 * 60 * 60 * 1000);
newProgress.lastStudiedDate = now;
return newProgress;
}
/**
* 计算单词的掌握程度 (0-100%)
*/
export function calculateMastery(progress: StudyProgress): number {
if (progress.repetitions === 0) return 0;
const baseScore = Math.min(progress.repetitions * 20, 80);
const intervalBonus = Math.min(progress.interval / 30 * 20, 20);
return Math.min(100, Math.round(baseScore + intervalBonus));
}
/**
* 获取复习优先级分数(越高越优先)
*/
export function getReviewPriority(progress: StudyProgress): number {
const now = new Date();
const nextReview = new Date(progress.nextReviewDate);
const overdue = now.getTime() - nextReview.getTime();
// 逾期的单词优先级更高
if (overdue > 0) {
return 1000 + Math.min(overdue / (1000 * 60 * 60), 1000); // 每小时增加 1 点优先级
}
// 即将到期的单词
const timeUntilDue = nextReview.getTime() - now.getTime();
const hoursUntilDue = timeUntilDue / (1000 * 60 * 60);
if (hoursUntilDue < 24) {
return 500 + (24 - hoursUntilDue) * 20;
}
return hoursUntilDue;
}