120 lines
2.2 KiB
Go
120 lines
2.2 KiB
Go
package engine
|
||
|
||
import (
|
||
"math"
|
||
"time"
|
||
)
|
||
|
||
// 记忆引擎 - 基于艾宾浩斯遗忘曲线
|
||
type MemoryEngine struct {
|
||
// 基础间隔(小时)
|
||
baseInterval float64
|
||
// 最大间隔(天)
|
||
maxInterval float64
|
||
}
|
||
|
||
// 记忆级别
|
||
const (
|
||
Level0 = iota // 完全忘记
|
||
Level1
|
||
Level2
|
||
Level3
|
||
Level4
|
||
Level5 // 永久记住
|
||
)
|
||
|
||
func NewMemoryEngine() *MemoryEngine {
|
||
return &MemoryEngine{
|
||
baseInterval: 1, // 1小时
|
||
maxInterval: 30 * 24, // 30天
|
||
}
|
||
}
|
||
|
||
// CalculateNextReview 计算下次复习时间
|
||
// correct: 回答是否正确
|
||
// currentLevel: 当前掌握程度 0-5
|
||
func (e *MemoryEngine) CalculateNextReview(correct bool, currentLevel int) time.Duration {
|
||
var interval float64
|
||
|
||
if !correct {
|
||
// 回答错误,重置到Level1,1小时后复习
|
||
interval = e.baseInterval
|
||
} else {
|
||
// 根据当前级别计算间隔
|
||
switch currentLevel {
|
||
case 0:
|
||
interval = 1 // 1小时后
|
||
case 1:
|
||
interval = 12 // 12小时后
|
||
case 2:
|
||
interval = 24 // 1天后
|
||
case 3:
|
||
interval = 72 // 3天后
|
||
case 4:
|
||
interval = 168 // 7天后
|
||
case 5:
|
||
interval = 360 // 15天后
|
||
default:
|
||
interval = e.baseInterval
|
||
}
|
||
|
||
// 增加难度系数
|
||
interval = interval * 1.2
|
||
}
|
||
|
||
// 限制最大间隔
|
||
interval = math.Min(interval, e.maxInterval)
|
||
|
||
return time.Duration(interval) * time.Hour
|
||
}
|
||
|
||
// GetMasteryLevel 计算掌握程度
|
||
// correctCount: 正确次数
|
||
// totalCount: 总次数
|
||
func (e *MemoryEngine) GetMasteryLevel(correctCount, totalCount int) int {
|
||
if totalCount == 0 {
|
||
return 0
|
||
}
|
||
|
||
// 正确率
|
||
rate := float64(correctCount) / float64(totalCount)
|
||
|
||
// 根据正确率和次数计算级别
|
||
if totalCount < 3 {
|
||
if rate >= 0.8 {
|
||
return 1
|
||
}
|
||
return 0
|
||
}
|
||
|
||
if rate >= 0.9 {
|
||
return 5
|
||
} else if rate >= 0.8 {
|
||
return 4
|
||
} else if rate >= 0.7 {
|
||
return 3
|
||
} else if rate >= 0.5 {
|
||
return 2
|
||
} else {
|
||
return 1
|
||
}
|
||
}
|
||
|
||
// IsDueForReview 是否应该复习
|
||
func (e *MemoryEngine) IsDueForReview(lastReview *time.Time, nextReview *time.Time) bool {
|
||
now := time.Now()
|
||
|
||
// 没有复习记录,需要复习
|
||
if lastReview == nil {
|
||
return true
|
||
}
|
||
|
||
// 有计划复习时间
|
||
if nextReview != nil {
|
||
return now.After(*nextReview)
|
||
}
|
||
|
||
// 默认:超过1天没复习需要复习
|
||
return now.Sub(*lastReview) > 24*time.Hour
|
||
}
|