122 lines
4.7 KiB
Go
122 lines
4.7 KiB
Go
package models
|
||
|
||
import (
|
||
"time"
|
||
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
// WrongQuestion 错题记录
|
||
type WrongQuestion struct {
|
||
ID int64 `gorm:"primarykey" json:"id"`
|
||
UserID int64 `gorm:"index;not null" json:"user_id"`
|
||
QuestionID int64 `gorm:"index;not null" json:"question_id"`
|
||
FirstWrongTime time.Time `json:"first_wrong_time"`
|
||
LastWrongTime time.Time `json:"last_wrong_time"`
|
||
TotalWrongCount int `gorm:"default:1" json:"total_wrong_count"`
|
||
MasteryLevel int `gorm:"default:0" json:"mastery_level"` // 0-100
|
||
ConsecutiveCorrect int `gorm:"default:0" json:"consecutive_correct"`
|
||
IsMastered bool `gorm:"default:false" json:"is_mastered"`
|
||
CreatedAt time.Time `json:"created_at"`
|
||
UpdatedAt time.Time `json:"updated_at"`
|
||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||
|
||
// 关联
|
||
PracticeQuestion *PracticeQuestion `gorm:"foreignKey:QuestionID;references:ID" json:"question,omitempty"`
|
||
History []WrongQuestionHistory `gorm:"foreignKey:WrongQuestionID" json:"history,omitempty"`
|
||
}
|
||
|
||
// WrongQuestionHistory 错误历史记录
|
||
type WrongQuestionHistory struct {
|
||
ID int64 `gorm:"primarykey" json:"id"`
|
||
WrongQuestionID int64 `gorm:"index;not null" json:"wrong_question_id"`
|
||
UserAnswer string `gorm:"type:jsonb;not null" json:"user_answer"` // JSON 存储
|
||
CorrectAnswer string `gorm:"type:jsonb;not null" json:"correct_answer"` // JSON 存储
|
||
AnsweredAt time.Time `gorm:"index" json:"answered_at"`
|
||
TimeSpent int `json:"time_spent"` // 答题用时(秒)
|
||
IsCorrect bool `json:"is_correct"`
|
||
}
|
||
|
||
// TableName 指定表名
|
||
func (WrongQuestion) TableName() string {
|
||
return "wrong_questions"
|
||
}
|
||
|
||
// TableName 指定表名
|
||
func (WrongQuestionHistory) TableName() string {
|
||
return "wrong_question_history"
|
||
}
|
||
|
||
// WrongQuestionDTO 错题数据传输对象
|
||
type WrongQuestionDTO struct {
|
||
ID int64 `json:"id"`
|
||
QuestionID int64 `json:"question_id"`
|
||
Question *PracticeQuestionDTO `json:"question"`
|
||
FirstWrongTime time.Time `json:"first_wrong_time"`
|
||
LastWrongTime time.Time `json:"last_wrong_time"`
|
||
TotalWrongCount int `json:"total_wrong_count"`
|
||
MasteryLevel int `json:"mastery_level"`
|
||
ConsecutiveCorrect int `json:"consecutive_correct"`
|
||
IsMastered bool `json:"is_mastered"`
|
||
RecentHistory []WrongQuestionHistoryDTO `json:"recent_history,omitempty"` // 最近3次历史
|
||
}
|
||
|
||
// WrongQuestionHistoryDTO 错误历史 DTO
|
||
type WrongQuestionHistoryDTO struct {
|
||
ID int64 `json:"id"`
|
||
UserAnswer interface{} `json:"user_answer"`
|
||
CorrectAnswer interface{} `json:"correct_answer"`
|
||
AnsweredAt time.Time `json:"answered_at"`
|
||
TimeSpent int `json:"time_spent"`
|
||
IsCorrect bool `json:"is_correct"`
|
||
}
|
||
|
||
// WrongQuestionStats 错题统计
|
||
type WrongQuestionStats struct {
|
||
TotalWrong int `json:"total_wrong"` // 总错题数
|
||
Mastered int `json:"mastered"` // 已掌握数
|
||
NotMastered int `json:"not_mastered"` // 未掌握数
|
||
NeedReview int `json:"need_review"` // 需要复习数
|
||
TypeStats map[string]int `json:"type_stats"` // 按题型统计
|
||
CategoryStats map[string]int `json:"category_stats"` // 按分类统计
|
||
MasteryLevelDist map[string]int `json:"mastery_level_dist"` // 掌握度分布
|
||
TrendData []TrendPoint `json:"trend_data"` // 错题趋势
|
||
}
|
||
|
||
// TrendPoint 趋势数据点
|
||
type TrendPoint struct {
|
||
Date string `json:"date"`
|
||
Count int `json:"count"`
|
||
}
|
||
|
||
// RecordWrongAnswer 记录错误答案
|
||
func (wq *WrongQuestion) RecordWrongAnswer() {
|
||
now := time.Now()
|
||
if wq.FirstWrongTime.IsZero() {
|
||
wq.FirstWrongTime = now
|
||
}
|
||
wq.LastWrongTime = now
|
||
wq.TotalWrongCount++
|
||
wq.ConsecutiveCorrect = 0 // 重置连续答对次数
|
||
wq.IsMastered = false // 重新标记为未掌握
|
||
wq.MasteryLevel = 0 // 重置掌握度
|
||
}
|
||
|
||
// RecordCorrectAnswer 记录正确答案
|
||
func (wq *WrongQuestion) RecordCorrectAnswer() {
|
||
wq.ConsecutiveCorrect++
|
||
|
||
// 根据连续答对次数更新掌握度(每答对一次增加16.67%)
|
||
// 连续答对6次即达到100%
|
||
wq.MasteryLevel = (wq.ConsecutiveCorrect * 100) / 6
|
||
if wq.MasteryLevel > 100 {
|
||
wq.MasteryLevel = 100
|
||
}
|
||
|
||
// 连续答对6次标记为已掌握
|
||
if wq.ConsecutiveCorrect >= 6 {
|
||
wq.IsMastered = true
|
||
wq.MasteryLevel = 100
|
||
}
|
||
}
|