79 lines
2.4 KiB
Dart
79 lines
2.4 KiB
Dart
/// 「学习」首页需要的一份排程摘要。
|
|
///
|
|
/// 目前由 [StudyPlan.sample] 提供示例数据;接上新内核后,这里应改为由排程
|
|
/// 返回的真实数据(到期条目数、新识记额度、历史平均速度等),UI 不需要改。
|
|
class StudyPlan {
|
|
const StudyPlan({
|
|
required this.deckName,
|
|
required this.algorithm,
|
|
required this.totalItems,
|
|
required this.activatedItems,
|
|
required this.dueItems,
|
|
required this.newItems,
|
|
required this.secondsPerItem,
|
|
});
|
|
|
|
/// 当前单元集名称。
|
|
final String deckName;
|
|
|
|
/// 该单元集使用的调度算法标识,如 `NSP-0`、`SM-2`。
|
|
final String algorithm;
|
|
|
|
/// 单元集条目总数。
|
|
final int totalItems;
|
|
|
|
/// 已激活(学过至少一次)的条目数。
|
|
final int activatedItems;
|
|
|
|
/// 今天到期、需要复习的条目数。
|
|
final int dueItems;
|
|
|
|
/// 今天还可以引入的新识记条目数。
|
|
final int newItems;
|
|
|
|
/// 单个条目完成一轮多谜题测验的平均耗时(秒)。
|
|
///
|
|
/// 用于把「今天要学多少」翻译成用户能感知的时间承诺。实测速度应当来自
|
|
/// 内核,这里先用经验值。
|
|
final int secondsPerItem;
|
|
|
|
/// 今天总共要处理的条目数。
|
|
int get itemCount => dueItems + newItems;
|
|
|
|
/// 今天是否无事可做。
|
|
bool get isEmpty => itemCount == 0;
|
|
|
|
/// 单元集整体完成度,0..1。
|
|
double get progress => totalItems == 0 ? 0 : activatedItems / totalItems;
|
|
|
|
/// 完成度百分比,保留一位小数。
|
|
String get progressPercent => '${(progress * 100).toStringAsFixed(1)}%';
|
|
|
|
/// 预计用时(分钟,向上取整)。条目数为 0 时返回 0。
|
|
int get estimatedMinutes => _minutes(itemCount, secondsPerItem);
|
|
|
|
/// 预计用时的展示文案。
|
|
String get estimatedLabel => isEmpty
|
|
? '今天没有到期的内容'
|
|
: '预计用时 $estimatedMinutes 分钟';
|
|
|
|
/// 示例数据:高考必背古诗文,NSP-0 调度。
|
|
static const StudyPlan sample = StudyPlan(
|
|
deckName: '高考必背古诗文',
|
|
algorithm: 'NSP-0',
|
|
totalItems: 950,
|
|
activatedItems: 295,
|
|
dueItems: 18,
|
|
newItems: 35,
|
|
secondsPerItem: 13,
|
|
);
|
|
|
|
static int _minutes(int itemCount, int secondsPerItem) {
|
|
if (itemCount <= 0 || secondsPerItem <= 0) {
|
|
return 0;
|
|
}
|
|
final int totalSeconds = itemCount * secondsPerItem;
|
|
return (totalSeconds + 59) ~/ 60;
|
|
}
|
|
}
|