init
This commit is contained in:
713
client/lib/features/vocabulary/models/learning_stats_model.dart
Normal file
713
client/lib/features/vocabulary/models/learning_stats_model.dart
Normal file
@@ -0,0 +1,713 @@
|
||||
/// 学习统计数据
|
||||
class LearningStats {
|
||||
/// 用户ID
|
||||
final String userId;
|
||||
|
||||
/// 总学习天数
|
||||
final int totalStudyDays;
|
||||
|
||||
/// 连续学习天数
|
||||
final int currentStreak;
|
||||
|
||||
/// 最长连续学习天数
|
||||
final int maxStreak;
|
||||
|
||||
/// 总学习单词数
|
||||
final int totalWordsLearned;
|
||||
|
||||
/// 总复习单词数
|
||||
final int totalWordsReviewed;
|
||||
|
||||
/// 总学习时间(分钟)
|
||||
final int totalStudyTimeMinutes;
|
||||
|
||||
/// 平均每日学习单词数
|
||||
final double averageDailyWords;
|
||||
|
||||
/// 平均每日学习时间(分钟)
|
||||
final double averageDailyMinutes;
|
||||
|
||||
/// 学习准确率
|
||||
final double accuracyRate;
|
||||
|
||||
/// 完成的词汇书数量
|
||||
final int completedBooks;
|
||||
|
||||
/// 当前学习的词汇书数量
|
||||
final int currentBooks;
|
||||
|
||||
/// 掌握的单词数
|
||||
final int masteredWords;
|
||||
|
||||
/// 学习中的单词数
|
||||
final int learningWords;
|
||||
|
||||
/// 需要复习的单词数
|
||||
final int reviewWords;
|
||||
|
||||
/// 本周学习统计
|
||||
final WeeklyStats weeklyStats;
|
||||
|
||||
/// 本月学习统计
|
||||
final MonthlyStats monthlyStats;
|
||||
|
||||
/// 学习等级
|
||||
final int level;
|
||||
|
||||
/// 当前等级经验值
|
||||
final int currentExp;
|
||||
|
||||
/// 升级所需经验值
|
||||
final int nextLevelExp;
|
||||
|
||||
/// 最后学习时间
|
||||
final DateTime? lastStudyTime;
|
||||
|
||||
/// 创建时间
|
||||
final DateTime createdAt;
|
||||
|
||||
/// 更新时间
|
||||
final DateTime updatedAt;
|
||||
|
||||
/// 每日学习记录
|
||||
final List<DailyStudyRecord> dailyRecords;
|
||||
|
||||
/// 学习成就
|
||||
final List<Achievement> achievements;
|
||||
|
||||
/// 排行榜信息
|
||||
final Leaderboard? leaderboard;
|
||||
|
||||
const LearningStats({
|
||||
required this.userId,
|
||||
required this.totalStudyDays,
|
||||
required this.currentStreak,
|
||||
required this.maxStreak,
|
||||
required this.totalWordsLearned,
|
||||
required this.totalWordsReviewed,
|
||||
required this.totalStudyTimeMinutes,
|
||||
required this.averageDailyWords,
|
||||
required this.averageDailyMinutes,
|
||||
required this.accuracyRate,
|
||||
required this.completedBooks,
|
||||
required this.currentBooks,
|
||||
required this.masteredWords,
|
||||
required this.learningWords,
|
||||
required this.reviewWords,
|
||||
required this.weeklyStats,
|
||||
required this.monthlyStats,
|
||||
required this.level,
|
||||
required this.currentExp,
|
||||
required this.nextLevelExp,
|
||||
this.lastStudyTime,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
required this.dailyRecords,
|
||||
required this.achievements,
|
||||
this.leaderboard,
|
||||
});
|
||||
|
||||
factory LearningStats.fromJson(Map<String, dynamic> json) {
|
||||
return LearningStats(
|
||||
userId: json['userId'] as String,
|
||||
totalStudyDays: json['totalStudyDays'] as int,
|
||||
currentStreak: json['currentStreak'] as int,
|
||||
maxStreak: json['maxStreak'] as int,
|
||||
totalWordsLearned: json['totalWordsLearned'] as int,
|
||||
totalWordsReviewed: json['totalWordsReviewed'] as int,
|
||||
totalStudyTimeMinutes: json['totalStudyTimeMinutes'] as int,
|
||||
averageDailyWords: (json['averageDailyWords'] as num).toDouble(),
|
||||
averageDailyMinutes: (json['averageDailyMinutes'] as num).toDouble(),
|
||||
accuracyRate: (json['accuracyRate'] as num).toDouble(),
|
||||
completedBooks: json['completedBooks'] as int,
|
||||
currentBooks: json['currentBooks'] as int,
|
||||
masteredWords: json['masteredWords'] as int,
|
||||
learningWords: json['learningWords'] as int,
|
||||
reviewWords: json['reviewWords'] as int,
|
||||
weeklyStats: WeeklyStats.fromJson(json['weeklyStats'] as Map<String, dynamic>),
|
||||
monthlyStats: MonthlyStats.fromJson(json['monthlyStats'] as Map<String, dynamic>),
|
||||
level: json['level'] as int,
|
||||
currentExp: json['currentExp'] as int,
|
||||
nextLevelExp: json['nextLevelExp'] as int,
|
||||
lastStudyTime: json['lastStudyTime'] != null
|
||||
? DateTime.parse(json['lastStudyTime'] as String)
|
||||
: null,
|
||||
createdAt: DateTime.parse(json['createdAt'] as String),
|
||||
updatedAt: DateTime.parse(json['updatedAt'] as String),
|
||||
dailyRecords: (json['dailyRecords'] as List<dynamic>?)
|
||||
?.map((e) => DailyStudyRecord.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ?? [],
|
||||
achievements: (json['achievements'] as List<dynamic>?)
|
||||
?.map((e) => Achievement.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ?? [],
|
||||
leaderboard: json['leaderboard'] != null
|
||||
? Leaderboard.fromJson(json['leaderboard'] as Map<String, dynamic>)
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'userId': userId,
|
||||
'totalStudyDays': totalStudyDays,
|
||||
'currentStreak': currentStreak,
|
||||
'maxStreak': maxStreak,
|
||||
'totalWordsLearned': totalWordsLearned,
|
||||
'totalWordsReviewed': totalWordsReviewed,
|
||||
'totalStudyTimeMinutes': totalStudyTimeMinutes,
|
||||
'averageDailyWords': averageDailyWords,
|
||||
'averageDailyMinutes': averageDailyMinutes,
|
||||
'accuracyRate': accuracyRate,
|
||||
'completedBooks': completedBooks,
|
||||
'currentBooks': currentBooks,
|
||||
'masteredWords': masteredWords,
|
||||
'learningWords': learningWords,
|
||||
'reviewWords': reviewWords,
|
||||
'weeklyStats': weeklyStats.toJson(),
|
||||
'monthlyStats': monthlyStats.toJson(),
|
||||
'level': level,
|
||||
'currentExp': currentExp,
|
||||
'nextLevelExp': nextLevelExp,
|
||||
'lastStudyTime': lastStudyTime?.toIso8601String(),
|
||||
'createdAt': createdAt.toIso8601String(),
|
||||
'updatedAt': updatedAt.toIso8601String(),
|
||||
'dailyRecords': dailyRecords.map((e) => e.toJson()).toList(),
|
||||
'achievements': achievements.map((e) => e.toJson()).toList(),
|
||||
'leaderboard': leaderboard?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
LearningStats copyWith({
|
||||
String? userId,
|
||||
int? totalStudyDays,
|
||||
int? currentStreak,
|
||||
int? maxStreak,
|
||||
int? totalWordsLearned,
|
||||
int? totalWordsReviewed,
|
||||
int? totalStudyTimeMinutes,
|
||||
double? averageDailyWords,
|
||||
double? averageDailyMinutes,
|
||||
double? accuracyRate,
|
||||
int? completedBooks,
|
||||
int? currentBooks,
|
||||
int? masteredWords,
|
||||
int? learningWords,
|
||||
int? reviewWords,
|
||||
WeeklyStats? weeklyStats,
|
||||
MonthlyStats? monthlyStats,
|
||||
int? level,
|
||||
int? currentExp,
|
||||
int? nextLevelExp,
|
||||
DateTime? lastStudyTime,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
List<DailyStudyRecord>? dailyRecords,
|
||||
List<Achievement>? achievements,
|
||||
Leaderboard? leaderboard,
|
||||
}) {
|
||||
return LearningStats(
|
||||
userId: userId ?? this.userId,
|
||||
totalStudyDays: totalStudyDays ?? this.totalStudyDays,
|
||||
currentStreak: currentStreak ?? this.currentStreak,
|
||||
maxStreak: maxStreak ?? this.maxStreak,
|
||||
totalWordsLearned: totalWordsLearned ?? this.totalWordsLearned,
|
||||
totalWordsReviewed: totalWordsReviewed ?? this.totalWordsReviewed,
|
||||
totalStudyTimeMinutes: totalStudyTimeMinutes ?? this.totalStudyTimeMinutes,
|
||||
averageDailyWords: averageDailyWords ?? this.averageDailyWords,
|
||||
averageDailyMinutes: averageDailyMinutes ?? this.averageDailyMinutes,
|
||||
accuracyRate: accuracyRate ?? this.accuracyRate,
|
||||
completedBooks: completedBooks ?? this.completedBooks,
|
||||
currentBooks: currentBooks ?? this.currentBooks,
|
||||
masteredWords: masteredWords ?? this.masteredWords,
|
||||
learningWords: learningWords ?? this.learningWords,
|
||||
reviewWords: reviewWords ?? this.reviewWords,
|
||||
weeklyStats: weeklyStats ?? this.weeklyStats,
|
||||
monthlyStats: monthlyStats ?? this.monthlyStats,
|
||||
level: level ?? this.level,
|
||||
currentExp: currentExp ?? this.currentExp,
|
||||
nextLevelExp: nextLevelExp ?? this.nextLevelExp,
|
||||
lastStudyTime: lastStudyTime ?? this.lastStudyTime,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
dailyRecords: dailyRecords ?? this.dailyRecords,
|
||||
achievements: achievements ?? this.achievements,
|
||||
leaderboard: leaderboard ?? this.leaderboard,
|
||||
);
|
||||
}
|
||||
|
||||
/// 获取学习进度百分比
|
||||
double get progressPercentage {
|
||||
if (nextLevelExp == 0) return 0.0;
|
||||
return currentExp / nextLevelExp;
|
||||
}
|
||||
|
||||
/// 获取总学习时间(小时)
|
||||
double get totalStudyHours {
|
||||
return totalStudyTimeMinutes / 60.0;
|
||||
}
|
||||
|
||||
/// 获取平均每日学习时间(小时)
|
||||
double get averageDailyHours {
|
||||
return averageDailyMinutes / 60.0;
|
||||
}
|
||||
}
|
||||
|
||||
/// 周学习统计
|
||||
class WeeklyStats {
|
||||
/// 本周学习天数
|
||||
final int studyDays;
|
||||
|
||||
/// 本周学习单词数
|
||||
final int wordsLearned;
|
||||
|
||||
/// 本周复习单词数
|
||||
final int wordsReviewed;
|
||||
|
||||
/// 本周学习时间(分钟)
|
||||
final int studyTimeMinutes;
|
||||
|
||||
/// 本周准确率
|
||||
final double accuracyRate;
|
||||
|
||||
/// 每日学习记录
|
||||
final List<DailyStudyRecord> dailyRecords;
|
||||
|
||||
const WeeklyStats({
|
||||
required this.studyDays,
|
||||
required this.wordsLearned,
|
||||
required this.wordsReviewed,
|
||||
required this.studyTimeMinutes,
|
||||
required this.accuracyRate,
|
||||
required this.dailyRecords,
|
||||
});
|
||||
|
||||
factory WeeklyStats.fromJson(Map<String, dynamic> json) {
|
||||
return WeeklyStats(
|
||||
studyDays: json['studyDays'] as int,
|
||||
wordsLearned: json['wordsLearned'] as int,
|
||||
wordsReviewed: json['wordsReviewed'] as int,
|
||||
studyTimeMinutes: json['studyTimeMinutes'] as int,
|
||||
accuracyRate: (json['accuracyRate'] as num).toDouble(),
|
||||
dailyRecords: (json['dailyRecords'] as List<dynamic>?)
|
||||
?.map((e) => DailyStudyRecord.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ?? [],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'studyDays': studyDays,
|
||||
'wordsLearned': wordsLearned,
|
||||
'wordsReviewed': wordsReviewed,
|
||||
'studyTimeMinutes': studyTimeMinutes,
|
||||
'accuracyRate': accuracyRate,
|
||||
'dailyRecords': dailyRecords.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
|
||||
/// 获取本周学习时间(小时)
|
||||
double get studyHours {
|
||||
return studyTimeMinutes / 60.0;
|
||||
}
|
||||
}
|
||||
|
||||
/// 月学习统计
|
||||
class MonthlyStats {
|
||||
/// 本月学习天数
|
||||
final int studyDays;
|
||||
|
||||
/// 本月学习单词数
|
||||
final int wordsLearned;
|
||||
|
||||
/// 本月复习单词数
|
||||
final int wordsReviewed;
|
||||
|
||||
/// 本月学习时间(分钟)
|
||||
final int studyTimeMinutes;
|
||||
|
||||
/// 本月准确率
|
||||
final double accuracyRate;
|
||||
|
||||
/// 本月完成的词汇书数
|
||||
final int completedBooks;
|
||||
|
||||
/// 周统计记录
|
||||
final List<WeeklyStats> weeklyRecords;
|
||||
|
||||
const MonthlyStats({
|
||||
required this.studyDays,
|
||||
required this.wordsLearned,
|
||||
required this.wordsReviewed,
|
||||
required this.studyTimeMinutes,
|
||||
required this.accuracyRate,
|
||||
required this.completedBooks,
|
||||
required this.weeklyRecords,
|
||||
});
|
||||
|
||||
factory MonthlyStats.fromJson(Map<String, dynamic> json) {
|
||||
return MonthlyStats(
|
||||
studyDays: json['studyDays'] as int,
|
||||
wordsLearned: json['wordsLearned'] as int,
|
||||
wordsReviewed: json['wordsReviewed'] as int,
|
||||
studyTimeMinutes: json['studyTimeMinutes'] as int,
|
||||
accuracyRate: (json['accuracyRate'] as num).toDouble(),
|
||||
completedBooks: json['completedBooks'] as int,
|
||||
weeklyRecords: (json['weeklyRecords'] as List<dynamic>?)
|
||||
?.map((e) => WeeklyStats.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ?? [],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'studyDays': studyDays,
|
||||
'wordsLearned': wordsLearned,
|
||||
'wordsReviewed': wordsReviewed,
|
||||
'studyTimeMinutes': studyTimeMinutes,
|
||||
'accuracyRate': accuracyRate,
|
||||
'completedBooks': completedBooks,
|
||||
'weeklyRecords': weeklyRecords.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
|
||||
/// 获取本月学习时间(小时)
|
||||
double get studyHours {
|
||||
return studyTimeMinutes / 60.0;
|
||||
}
|
||||
}
|
||||
|
||||
/// 每日学习记录
|
||||
class DailyStudyRecord {
|
||||
/// 日期
|
||||
final DateTime date;
|
||||
|
||||
/// 学习单词数
|
||||
final int wordsLearned;
|
||||
|
||||
/// 复习单词数
|
||||
final int wordsReviewed;
|
||||
|
||||
/// 学习时间(分钟)
|
||||
final int studyTimeMinutes;
|
||||
|
||||
/// 准确率
|
||||
final double accuracyRate;
|
||||
|
||||
/// 完成的测试数
|
||||
final int testsCompleted;
|
||||
|
||||
/// 获得的经验值
|
||||
final int expGained;
|
||||
|
||||
/// 学习的词汇书ID列表
|
||||
final List<String> vocabularyBookIds;
|
||||
|
||||
const DailyStudyRecord({
|
||||
required this.date,
|
||||
required this.wordsLearned,
|
||||
required this.wordsReviewed,
|
||||
required this.studyTimeMinutes,
|
||||
required this.accuracyRate,
|
||||
required this.testsCompleted,
|
||||
required this.expGained,
|
||||
required this.vocabularyBookIds,
|
||||
});
|
||||
|
||||
factory DailyStudyRecord.fromJson(Map<String, dynamic> json) {
|
||||
// 支持两种命名格式:驼峰命名和蛇形命名
|
||||
return DailyStudyRecord(
|
||||
date: DateTime.parse(json['date'] as String),
|
||||
wordsLearned: (json['wordsLearned'] ?? json['words_learned'] ?? json['new_words_learned'] ?? 0) as int,
|
||||
wordsReviewed: (json['wordsReviewed'] ?? json['words_reviewed'] ?? 0) as int,
|
||||
studyTimeMinutes: (json['studyTimeMinutes'] ?? json['total_study_time_seconds'] != null
|
||||
? (json['total_study_time_seconds'] as int) ~/ 60
|
||||
: 0) as int,
|
||||
accuracyRate: ((json['accuracyRate'] ?? json['average_accuracy'] ?? 0) as num).toDouble(),
|
||||
testsCompleted: (json['testsCompleted'] ?? json['session_count'] ?? 0) as int,
|
||||
expGained: (json['expGained'] ?? json['experience_gained'] ?? 0) as int,
|
||||
vocabularyBookIds: (json['vocabularyBookIds'] as List<dynamic>?)
|
||||
?.map((e) => e as String)
|
||||
.toList() ?? [],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'date': date.toIso8601String(),
|
||||
'wordsLearned': wordsLearned,
|
||||
'wordsReviewed': wordsReviewed,
|
||||
'studyTimeMinutes': studyTimeMinutes,
|
||||
'accuracyRate': accuracyRate,
|
||||
'testsCompleted': testsCompleted,
|
||||
'expGained': expGained,
|
||||
'vocabularyBookIds': vocabularyBookIds,
|
||||
};
|
||||
}
|
||||
|
||||
/// 获取学习时间(小时)
|
||||
double get studyHours {
|
||||
return studyTimeMinutes / 60.0;
|
||||
}
|
||||
}
|
||||
|
||||
/// 学习成就
|
||||
class Achievement {
|
||||
/// 成就ID
|
||||
final String id;
|
||||
|
||||
/// 成就名称
|
||||
final String name;
|
||||
|
||||
/// 成就描述
|
||||
final String description;
|
||||
|
||||
/// 成就图标
|
||||
final String icon;
|
||||
|
||||
/// 成就类型
|
||||
final AchievementType type;
|
||||
|
||||
/// 是否已解锁
|
||||
final bool isUnlocked;
|
||||
|
||||
/// 解锁时间
|
||||
final DateTime? unlockedAt;
|
||||
|
||||
/// 进度值
|
||||
final int progress;
|
||||
|
||||
/// 目标值
|
||||
final int target;
|
||||
|
||||
/// 奖励经验值
|
||||
final int rewardExp;
|
||||
|
||||
const Achievement({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.description,
|
||||
required this.icon,
|
||||
required this.type,
|
||||
required this.isUnlocked,
|
||||
this.unlockedAt,
|
||||
required this.progress,
|
||||
required this.target,
|
||||
required this.rewardExp,
|
||||
});
|
||||
|
||||
factory Achievement.fromJson(Map<String, dynamic> json) {
|
||||
return Achievement(
|
||||
id: json['id'] as String,
|
||||
name: json['name'] as String,
|
||||
description: json['description'] as String,
|
||||
icon: json['icon'] as String,
|
||||
type: AchievementType.values.firstWhere(
|
||||
(e) => e.name == json['type'],
|
||||
orElse: () => AchievementType.special,
|
||||
),
|
||||
isUnlocked: json['isUnlocked'] as bool,
|
||||
unlockedAt: json['unlockedAt'] != null
|
||||
? DateTime.parse(json['unlockedAt'] as String)
|
||||
: null,
|
||||
progress: json['progress'] as int,
|
||||
target: json['target'] as int,
|
||||
rewardExp: json['rewardExp'] as int,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'description': description,
|
||||
'icon': icon,
|
||||
'type': type.name,
|
||||
'isUnlocked': isUnlocked,
|
||||
'unlockedAt': unlockedAt?.toIso8601String(),
|
||||
'progress': progress,
|
||||
'target': target,
|
||||
'rewardExp': rewardExp,
|
||||
};
|
||||
}
|
||||
|
||||
/// 复制并修改部分属性
|
||||
Achievement copyWith({
|
||||
String? id,
|
||||
String? name,
|
||||
String? description,
|
||||
String? icon,
|
||||
AchievementType? type,
|
||||
bool? isUnlocked,
|
||||
DateTime? unlockedAt,
|
||||
int? progress,
|
||||
int? target,
|
||||
int? rewardExp,
|
||||
}) {
|
||||
return Achievement(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
description: description ?? this.description,
|
||||
icon: icon ?? this.icon,
|
||||
type: type ?? this.type,
|
||||
isUnlocked: isUnlocked ?? this.isUnlocked,
|
||||
unlockedAt: unlockedAt ?? this.unlockedAt,
|
||||
progress: progress ?? this.progress,
|
||||
target: target ?? this.target,
|
||||
rewardExp: rewardExp ?? this.rewardExp,
|
||||
);
|
||||
}
|
||||
|
||||
/// 获取进度百分比
|
||||
double get progressPercentage {
|
||||
if (target == 0) return 0.0;
|
||||
return (progress / target).clamp(0.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
/// 成就类型
|
||||
enum AchievementType {
|
||||
/// 学习天数
|
||||
studyDays,
|
||||
/// 学习单词数
|
||||
wordsLearned,
|
||||
/// 连续学习
|
||||
streak,
|
||||
/// 完成词汇书
|
||||
booksCompleted,
|
||||
/// 测试成绩
|
||||
testScore,
|
||||
/// 学习时间
|
||||
studyTime,
|
||||
/// 特殊成就
|
||||
special,
|
||||
}
|
||||
|
||||
/// 学习排行榜
|
||||
class Leaderboard {
|
||||
/// 排行榜类型
|
||||
final LeaderboardType type;
|
||||
|
||||
/// 时间范围
|
||||
final LeaderboardPeriod period;
|
||||
|
||||
/// 排行榜条目
|
||||
final List<LeaderboardEntry> entries;
|
||||
|
||||
/// 用户排名
|
||||
final int? userRank;
|
||||
|
||||
/// 更新时间
|
||||
final DateTime updatedAt;
|
||||
|
||||
const Leaderboard({
|
||||
required this.type,
|
||||
required this.period,
|
||||
required this.entries,
|
||||
this.userRank,
|
||||
required this.updatedAt,
|
||||
});
|
||||
|
||||
factory Leaderboard.fromJson(Map<String, dynamic> json) {
|
||||
return Leaderboard(
|
||||
type: LeaderboardType.values.firstWhere(
|
||||
(e) => e.name == json['type'],
|
||||
orElse: () => LeaderboardType.wordsLearned,
|
||||
),
|
||||
period: LeaderboardPeriod.values.firstWhere(
|
||||
(e) => e.name == json['period'],
|
||||
orElse: () => LeaderboardPeriod.weekly,
|
||||
),
|
||||
entries: (json['entries'] as List<dynamic>?)
|
||||
?.map((e) => LeaderboardEntry.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ?? [],
|
||||
userRank: json['userRank'] as int?,
|
||||
updatedAt: DateTime.parse(json['updatedAt'] as String),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'type': type.name,
|
||||
'period': period.name,
|
||||
'entries': entries.map((e) => e.toJson()).toList(),
|
||||
'userRank': userRank,
|
||||
'updatedAt': updatedAt.toIso8601String(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// 排行榜条目
|
||||
class LeaderboardEntry {
|
||||
/// 排名
|
||||
final int rank;
|
||||
|
||||
/// 用户ID
|
||||
final String userId;
|
||||
|
||||
/// 用户名
|
||||
final String username;
|
||||
|
||||
/// 用户头像
|
||||
final String? avatar;
|
||||
|
||||
/// 分数
|
||||
final int score;
|
||||
|
||||
/// 等级
|
||||
final int level;
|
||||
|
||||
const LeaderboardEntry({
|
||||
required this.rank,
|
||||
required this.userId,
|
||||
required this.username,
|
||||
this.avatar,
|
||||
required this.score,
|
||||
required this.level,
|
||||
});
|
||||
|
||||
factory LeaderboardEntry.fromJson(Map<String, dynamic> json) {
|
||||
return LeaderboardEntry(
|
||||
rank: json['rank'] as int,
|
||||
userId: json['userId'] as String,
|
||||
username: json['username'] as String,
|
||||
avatar: json['avatar'] as String?,
|
||||
score: json['score'] as int,
|
||||
level: json['level'] as int,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'rank': rank,
|
||||
'userId': userId,
|
||||
'username': username,
|
||||
'avatar': avatar,
|
||||
'score': score,
|
||||
'level': level,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// 排行榜类型
|
||||
enum LeaderboardType {
|
||||
/// 学习单词数
|
||||
wordsLearned,
|
||||
/// 连续学习天数
|
||||
streak,
|
||||
/// 学习时间
|
||||
studyTime,
|
||||
/// 测试分数
|
||||
testScore,
|
||||
}
|
||||
|
||||
/// 排行榜时间范围
|
||||
enum LeaderboardPeriod {
|
||||
/// 每日
|
||||
daily,
|
||||
/// 每周
|
||||
weekly,
|
||||
/// 每月
|
||||
monthly,
|
||||
/// 全部时间
|
||||
allTime,
|
||||
}
|
||||
Reference in New Issue
Block a user