init
This commit is contained in:
398
client/lib/features/vocabulary/models/study_session_model.dart
Normal file
398
client/lib/features/vocabulary/models/study_session_model.dart
Normal file
@@ -0,0 +1,398 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'word_model.dart';
|
||||
|
||||
part 'study_session_model.g.dart';
|
||||
|
||||
/// 学习模式
|
||||
enum StudyMode {
|
||||
@JsonValue('new_words')
|
||||
newWords, // 学习新单词
|
||||
@JsonValue('review')
|
||||
review, // 复习单词
|
||||
@JsonValue('mixed')
|
||||
mixed, // 混合模式
|
||||
@JsonValue('test')
|
||||
test, // 测试模式
|
||||
@JsonValue('quick_review')
|
||||
quickReview, // 快速复习
|
||||
}
|
||||
|
||||
/// 练习类型
|
||||
enum ExerciseType {
|
||||
@JsonValue('word_meaning')
|
||||
wordMeaning, // 单词释义
|
||||
@JsonValue('meaning_word')
|
||||
meaningWord, // 释义选单词
|
||||
@JsonValue('spelling')
|
||||
spelling, // 拼写练习
|
||||
@JsonValue('listening')
|
||||
listening, // 听力练习
|
||||
@JsonValue('sentence_completion')
|
||||
sentenceCompletion, // 句子填空
|
||||
@JsonValue('synonym_antonym')
|
||||
synonymAntonym, // 同义词反义词
|
||||
@JsonValue('image_word')
|
||||
imageWord, // 图片识词
|
||||
}
|
||||
|
||||
/// 答题结果
|
||||
enum AnswerResult {
|
||||
@JsonValue('correct')
|
||||
correct,
|
||||
@JsonValue('wrong')
|
||||
wrong,
|
||||
@JsonValue('skipped')
|
||||
skipped,
|
||||
}
|
||||
|
||||
/// 学习会话
|
||||
@JsonSerializable()
|
||||
class StudySession {
|
||||
/// 会话ID
|
||||
final String id;
|
||||
|
||||
/// 用户ID
|
||||
final String userId;
|
||||
|
||||
/// 词汇书ID
|
||||
final String? vocabularyBookId;
|
||||
|
||||
/// 学习模式
|
||||
final StudyMode mode;
|
||||
|
||||
/// 目标单词数
|
||||
final int targetWordCount;
|
||||
|
||||
/// 实际学习单词数
|
||||
final int actualWordCount;
|
||||
|
||||
/// 正确答题数
|
||||
final int correctAnswers;
|
||||
|
||||
/// 错误答题数
|
||||
final int wrongAnswers;
|
||||
|
||||
/// 跳过答题数
|
||||
final int skippedAnswers;
|
||||
|
||||
/// 学习时长(秒)
|
||||
final int durationSeconds;
|
||||
|
||||
/// 准确率
|
||||
final double accuracy;
|
||||
|
||||
/// 获得经验值
|
||||
final int experienceGained;
|
||||
|
||||
/// 获得积分
|
||||
final int pointsGained;
|
||||
|
||||
/// 是否完成
|
||||
final bool isCompleted;
|
||||
|
||||
/// 开始时间
|
||||
final DateTime startedAt;
|
||||
|
||||
/// 结束时间
|
||||
final DateTime? endedAt;
|
||||
|
||||
/// 创建时间
|
||||
final DateTime createdAt;
|
||||
|
||||
const StudySession({
|
||||
required this.id,
|
||||
required this.userId,
|
||||
this.vocabularyBookId,
|
||||
required this.mode,
|
||||
required this.targetWordCount,
|
||||
this.actualWordCount = 0,
|
||||
this.correctAnswers = 0,
|
||||
this.wrongAnswers = 0,
|
||||
this.skippedAnswers = 0,
|
||||
this.durationSeconds = 0,
|
||||
this.accuracy = 0.0,
|
||||
this.experienceGained = 0,
|
||||
this.pointsGained = 0,
|
||||
this.isCompleted = false,
|
||||
required this.startedAt,
|
||||
this.endedAt,
|
||||
required this.createdAt,
|
||||
});
|
||||
|
||||
factory StudySession.fromJson(Map<String, dynamic> json) => _$StudySessionFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$StudySessionToJson(this);
|
||||
|
||||
StudySession copyWith({
|
||||
String? id,
|
||||
String? userId,
|
||||
String? vocabularyBookId,
|
||||
StudyMode? mode,
|
||||
int? targetWordCount,
|
||||
int? actualWordCount,
|
||||
int? correctAnswers,
|
||||
int? wrongAnswers,
|
||||
int? skippedAnswers,
|
||||
int? durationSeconds,
|
||||
double? accuracy,
|
||||
int? experienceGained,
|
||||
int? pointsGained,
|
||||
bool? isCompleted,
|
||||
DateTime? startedAt,
|
||||
DateTime? endedAt,
|
||||
DateTime? createdAt,
|
||||
}) {
|
||||
return StudySession(
|
||||
id: id ?? this.id,
|
||||
userId: userId ?? this.userId,
|
||||
vocabularyBookId: vocabularyBookId ?? this.vocabularyBookId,
|
||||
mode: mode ?? this.mode,
|
||||
targetWordCount: targetWordCount ?? this.targetWordCount,
|
||||
actualWordCount: actualWordCount ?? this.actualWordCount,
|
||||
correctAnswers: correctAnswers ?? this.correctAnswers,
|
||||
wrongAnswers: wrongAnswers ?? this.wrongAnswers,
|
||||
skippedAnswers: skippedAnswers ?? this.skippedAnswers,
|
||||
durationSeconds: durationSeconds ?? this.durationSeconds,
|
||||
accuracy: accuracy ?? this.accuracy,
|
||||
experienceGained: experienceGained ?? this.experienceGained,
|
||||
pointsGained: pointsGained ?? this.pointsGained,
|
||||
isCompleted: isCompleted ?? this.isCompleted,
|
||||
startedAt: startedAt ?? this.startedAt,
|
||||
endedAt: endedAt ?? this.endedAt,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
);
|
||||
}
|
||||
|
||||
/// 总答题数
|
||||
int get totalAnswers => correctAnswers + wrongAnswers + skippedAnswers;
|
||||
|
||||
/// 计算准确率
|
||||
double calculateAccuracy() {
|
||||
if (totalAnswers == 0) return 0.0;
|
||||
return correctAnswers / totalAnswers;
|
||||
}
|
||||
|
||||
/// 学习时长(分钟)
|
||||
double get durationMinutes => durationSeconds / 60.0;
|
||||
}
|
||||
|
||||
/// 单词练习记录
|
||||
@JsonSerializable()
|
||||
class WordExerciseRecord {
|
||||
/// 记录ID
|
||||
final String id;
|
||||
|
||||
/// 学习会话ID
|
||||
final String sessionId;
|
||||
|
||||
/// 单词ID
|
||||
final String wordId;
|
||||
|
||||
/// 练习类型
|
||||
final ExerciseType exerciseType;
|
||||
|
||||
/// 用户答案
|
||||
final String userAnswer;
|
||||
|
||||
/// 正确答案
|
||||
final String correctAnswer;
|
||||
|
||||
/// 答题结果
|
||||
final AnswerResult result;
|
||||
|
||||
/// 答题时间(秒)
|
||||
final int responseTimeSeconds;
|
||||
|
||||
/// 提示次数
|
||||
final int hintCount;
|
||||
|
||||
/// 单词信息
|
||||
final Word? word;
|
||||
|
||||
/// 答题时间
|
||||
final DateTime answeredAt;
|
||||
|
||||
const WordExerciseRecord({
|
||||
required this.id,
|
||||
required this.sessionId,
|
||||
required this.wordId,
|
||||
required this.exerciseType,
|
||||
required this.userAnswer,
|
||||
required this.correctAnswer,
|
||||
required this.result,
|
||||
required this.responseTimeSeconds,
|
||||
this.hintCount = 0,
|
||||
this.word,
|
||||
required this.answeredAt,
|
||||
});
|
||||
|
||||
factory WordExerciseRecord.fromJson(Map<String, dynamic> json) => _$WordExerciseRecordFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$WordExerciseRecordToJson(this);
|
||||
|
||||
WordExerciseRecord copyWith({
|
||||
String? id,
|
||||
String? sessionId,
|
||||
String? wordId,
|
||||
ExerciseType? exerciseType,
|
||||
String? userAnswer,
|
||||
String? correctAnswer,
|
||||
AnswerResult? result,
|
||||
int? responseTimeSeconds,
|
||||
int? hintCount,
|
||||
Word? word,
|
||||
DateTime? answeredAt,
|
||||
}) {
|
||||
return WordExerciseRecord(
|
||||
id: id ?? this.id,
|
||||
sessionId: sessionId ?? this.sessionId,
|
||||
wordId: wordId ?? this.wordId,
|
||||
exerciseType: exerciseType ?? this.exerciseType,
|
||||
userAnswer: userAnswer ?? this.userAnswer,
|
||||
correctAnswer: correctAnswer ?? this.correctAnswer,
|
||||
result: result ?? this.result,
|
||||
responseTimeSeconds: responseTimeSeconds ?? this.responseTimeSeconds,
|
||||
hintCount: hintCount ?? this.hintCount,
|
||||
word: word ?? this.word,
|
||||
answeredAt: answeredAt ?? this.answeredAt,
|
||||
);
|
||||
}
|
||||
|
||||
/// 是否正确
|
||||
bool get isCorrect => result == AnswerResult.correct;
|
||||
|
||||
/// 是否错误
|
||||
bool get isWrong => result == AnswerResult.wrong;
|
||||
|
||||
/// 是否跳过
|
||||
bool get isSkipped => result == AnswerResult.skipped;
|
||||
|
||||
/// 答题时间(分钟)
|
||||
double get responseTimeMinutes => responseTimeSeconds / 60.0;
|
||||
}
|
||||
|
||||
/// 学习统计
|
||||
@JsonSerializable()
|
||||
class StudyStatistics {
|
||||
/// 统计ID
|
||||
final String id;
|
||||
|
||||
/// 用户ID
|
||||
@JsonKey(name: 'user_id')
|
||||
final String userId;
|
||||
|
||||
/// 统计日期
|
||||
final DateTime date;
|
||||
|
||||
/// 学习会话数
|
||||
@JsonKey(name: 'session_count')
|
||||
final int sessionCount;
|
||||
|
||||
/// 学习单词数
|
||||
@JsonKey(name: 'words_studied')
|
||||
final int wordsStudied;
|
||||
|
||||
/// 新学单词数
|
||||
@JsonKey(name: 'new_words_learned')
|
||||
final int newWordsLearned;
|
||||
|
||||
/// 复习单词数
|
||||
@JsonKey(name: 'words_reviewed')
|
||||
final int wordsReviewed;
|
||||
|
||||
/// 掌握单词数
|
||||
@JsonKey(name: 'words_mastered')
|
||||
final int wordsMastered;
|
||||
|
||||
/// 学习时长(秒)
|
||||
@JsonKey(name: 'total_study_time_seconds')
|
||||
final int totalStudyTimeSeconds;
|
||||
|
||||
/// 正确答题数
|
||||
@JsonKey(name: 'correct_answers')
|
||||
final int correctAnswers;
|
||||
|
||||
/// 错误答题数
|
||||
@JsonKey(name: 'wrong_answers')
|
||||
final int wrongAnswers;
|
||||
|
||||
/// 平均准确率
|
||||
@JsonKey(name: 'average_accuracy')
|
||||
final double averageAccuracy;
|
||||
|
||||
/// 获得经验值
|
||||
@JsonKey(name: 'experience_gained')
|
||||
final int experienceGained;
|
||||
|
||||
/// 获得积分
|
||||
@JsonKey(name: 'points_gained')
|
||||
final int pointsGained;
|
||||
|
||||
/// 连续学习天数
|
||||
@JsonKey(name: 'streak_days')
|
||||
final int streakDays;
|
||||
|
||||
const StudyStatistics({
|
||||
required this.id,
|
||||
required this.userId,
|
||||
required this.date,
|
||||
this.sessionCount = 0,
|
||||
this.wordsStudied = 0,
|
||||
this.newWordsLearned = 0,
|
||||
this.wordsReviewed = 0,
|
||||
this.wordsMastered = 0,
|
||||
this.totalStudyTimeSeconds = 0,
|
||||
this.correctAnswers = 0,
|
||||
this.wrongAnswers = 0,
|
||||
this.averageAccuracy = 0.0,
|
||||
this.experienceGained = 0,
|
||||
this.pointsGained = 0,
|
||||
this.streakDays = 0,
|
||||
});
|
||||
|
||||
factory StudyStatistics.fromJson(Map<String, dynamic> json) => _$StudyStatisticsFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$StudyStatisticsToJson(this);
|
||||
|
||||
StudyStatistics copyWith({
|
||||
String? id,
|
||||
String? userId,
|
||||
DateTime? date,
|
||||
int? sessionCount,
|
||||
int? wordsStudied,
|
||||
int? newWordsLearned,
|
||||
int? wordsReviewed,
|
||||
int? wordsMastered,
|
||||
int? totalStudyTimeSeconds,
|
||||
int? correctAnswers,
|
||||
int? wrongAnswers,
|
||||
double? averageAccuracy,
|
||||
int? experienceGained,
|
||||
int? pointsGained,
|
||||
int? streakDays,
|
||||
}) {
|
||||
return StudyStatistics(
|
||||
id: id ?? this.id,
|
||||
userId: userId ?? this.userId,
|
||||
date: date ?? this.date,
|
||||
sessionCount: sessionCount ?? this.sessionCount,
|
||||
wordsStudied: wordsStudied ?? this.wordsStudied,
|
||||
newWordsLearned: newWordsLearned ?? this.newWordsLearned,
|
||||
wordsReviewed: wordsReviewed ?? this.wordsReviewed,
|
||||
wordsMastered: wordsMastered ?? this.wordsMastered,
|
||||
totalStudyTimeSeconds: totalStudyTimeSeconds ?? this.totalStudyTimeSeconds,
|
||||
correctAnswers: correctAnswers ?? this.correctAnswers,
|
||||
wrongAnswers: wrongAnswers ?? this.wrongAnswers,
|
||||
averageAccuracy: averageAccuracy ?? this.averageAccuracy,
|
||||
experienceGained: experienceGained ?? this.experienceGained,
|
||||
pointsGained: pointsGained ?? this.pointsGained,
|
||||
streakDays: streakDays ?? this.streakDays,
|
||||
);
|
||||
}
|
||||
|
||||
/// 总答题数
|
||||
int get totalAnswers => correctAnswers + wrongAnswers;
|
||||
|
||||
/// 学习时长(分钟)
|
||||
double get totalStudyTimeMinutes => totalStudyTimeSeconds / 60.0;
|
||||
|
||||
/// 学习时长(小时)
|
||||
double get totalStudyTimeHours => totalStudyTimeSeconds / 3600.0;
|
||||
}
|
||||
Reference in New Issue
Block a user