142 lines
4.0 KiB
Dart
142 lines
4.0 KiB
Dart
|
|
import 'package:json_annotation/json_annotation.dart';
|
||
|
|
|
||
|
|
part 'learning_session_model.g.dart';
|
||
|
|
|
||
|
|
/// 学习难度
|
||
|
|
enum StudyDifficulty {
|
||
|
|
@JsonValue('forgot')
|
||
|
|
forgot, // 完全忘记
|
||
|
|
@JsonValue('hard')
|
||
|
|
hard, // 困难
|
||
|
|
@JsonValue('good')
|
||
|
|
good, // 一般
|
||
|
|
@JsonValue('easy')
|
||
|
|
easy, // 容易
|
||
|
|
@JsonValue('perfect')
|
||
|
|
perfect, // 完美
|
||
|
|
}
|
||
|
|
|
||
|
|
/// 学习会话
|
||
|
|
@JsonSerializable()
|
||
|
|
class LearningSession {
|
||
|
|
@JsonKey(fromJson: _idFromJson)
|
||
|
|
final String id;
|
||
|
|
@JsonKey(name: 'user_id', fromJson: _userIdFromJson)
|
||
|
|
final String userId;
|
||
|
|
@JsonKey(name: 'book_id')
|
||
|
|
final String bookId;
|
||
|
|
@JsonKey(name: 'daily_goal')
|
||
|
|
final int dailyGoal;
|
||
|
|
@JsonKey(name: 'new_words_count')
|
||
|
|
final int newWordsCount;
|
||
|
|
@JsonKey(name: 'review_count')
|
||
|
|
final int reviewCount;
|
||
|
|
@JsonKey(name: 'mastered_count')
|
||
|
|
final int masteredCount;
|
||
|
|
@JsonKey(name: 'started_at')
|
||
|
|
final DateTime startedAt;
|
||
|
|
@JsonKey(name: 'completed_at')
|
||
|
|
final DateTime? completedAt;
|
||
|
|
|
||
|
|
const LearningSession({
|
||
|
|
required this.id,
|
||
|
|
required this.userId,
|
||
|
|
required this.bookId,
|
||
|
|
required this.dailyGoal,
|
||
|
|
this.newWordsCount = 0,
|
||
|
|
this.reviewCount = 0,
|
||
|
|
this.masteredCount = 0,
|
||
|
|
required this.startedAt,
|
||
|
|
this.completedAt,
|
||
|
|
});
|
||
|
|
|
||
|
|
factory LearningSession.fromJson(Map<String, dynamic> json) =>
|
||
|
|
_$LearningSessionFromJson(json);
|
||
|
|
Map<String, dynamic> toJson() => _$LearningSessionToJson(this);
|
||
|
|
|
||
|
|
static String _idFromJson(dynamic value) => value.toString();
|
||
|
|
static String _userIdFromJson(dynamic value) => value.toString();
|
||
|
|
}
|
||
|
|
|
||
|
|
/// 今日学习任务
|
||
|
|
@JsonSerializable()
|
||
|
|
class DailyLearningTasks {
|
||
|
|
@JsonKey(name: 'newWords')
|
||
|
|
final List<int> newWords; // 新单词ID列表
|
||
|
|
@JsonKey(name: 'reviewWords', fromJson: _reviewWordsFromJson)
|
||
|
|
final List<dynamic> reviewWords; // 复习单词进度列表
|
||
|
|
@JsonKey(name: 'masteredCount')
|
||
|
|
final int masteredCount; // 已掌握数量
|
||
|
|
@JsonKey(name: 'totalWords')
|
||
|
|
final int totalWords; // 总单词数
|
||
|
|
final double progress; // 整体进度百分比
|
||
|
|
|
||
|
|
const DailyLearningTasks({
|
||
|
|
required this.newWords,
|
||
|
|
required this.reviewWords,
|
||
|
|
required this.masteredCount,
|
||
|
|
required this.totalWords,
|
||
|
|
required this.progress,
|
||
|
|
});
|
||
|
|
|
||
|
|
factory DailyLearningTasks.fromJson(Map<String, dynamic> json) =>
|
||
|
|
_$DailyLearningTasksFromJson(json);
|
||
|
|
Map<String, dynamic> toJson() => _$DailyLearningTasksToJson(this);
|
||
|
|
|
||
|
|
/// 待学习总数
|
||
|
|
int get totalTasks => newWords.length + reviewWords.length;
|
||
|
|
|
||
|
|
/// 是否完成
|
||
|
|
bool get isCompleted => totalTasks == 0;
|
||
|
|
|
||
|
|
static List<dynamic> _reviewWordsFromJson(dynamic value) {
|
||
|
|
if (value == null) return [];
|
||
|
|
if (value is List) return value;
|
||
|
|
return [];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// 学习统计
|
||
|
|
@JsonSerializable()
|
||
|
|
class LearningStatistics {
|
||
|
|
final int todayNewWords; // 今日新学单词数
|
||
|
|
final int todayReview; // 今日复习单词数
|
||
|
|
final int todayMastered; // 今日掌握单词数
|
||
|
|
final int totalLearned; // 总学习单词数
|
||
|
|
final int totalMastered; // 总掌握单词数
|
||
|
|
final double avgProficiency; // 平均熟练度
|
||
|
|
final int streakDays; // 连续学习天数
|
||
|
|
|
||
|
|
const LearningStatistics({
|
||
|
|
required this.todayNewWords,
|
||
|
|
required this.todayReview,
|
||
|
|
required this.todayMastered,
|
||
|
|
required this.totalLearned,
|
||
|
|
required this.totalMastered,
|
||
|
|
required this.avgProficiency,
|
||
|
|
required this.streakDays,
|
||
|
|
});
|
||
|
|
|
||
|
|
factory LearningStatistics.fromJson(Map<String, dynamic> json) =>
|
||
|
|
_$LearningStatisticsFromJson(json);
|
||
|
|
Map<String, dynamic> toJson() => _$LearningStatisticsToJson(this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// 学习结果
|
||
|
|
@JsonSerializable()
|
||
|
|
class StudyResult {
|
||
|
|
final String wordId;
|
||
|
|
final StudyDifficulty difficulty;
|
||
|
|
final int studyTime; // 学习时长(毫秒)
|
||
|
|
|
||
|
|
const StudyResult({
|
||
|
|
required this.wordId,
|
||
|
|
required this.difficulty,
|
||
|
|
required this.studyTime,
|
||
|
|
});
|
||
|
|
|
||
|
|
factory StudyResult.fromJson(Map<String, dynamic> json) =>
|
||
|
|
_$StudyResultFromJson(json);
|
||
|
|
Map<String, dynamic> toJson() => _$StudyResultToJson(this);
|
||
|
|
}
|