Skip to content

Commit 0545deb

Browse files
committed
feat: add selfEvaluation solution in review part
Signed-off-by: OctagonalStar <76486554+OctagonalStar@users.noreply.github.com>
1 parent c670a9a commit 0545deb

5 files changed

Lines changed: 265 additions & 210 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- 给部分文本框添加了动画
1212
- 添加了听力题型 [#51](https://github.com/OctagonalStar/arabic_learning/issues/51)
1313
- 为每次学习添加了是否计算复习的提示 [#52](https://github.com/OctagonalStar/arabic_learning/issues/52)
14+
- 在复习部分添加了自我评级方案 [#52](https://github.com/OctagonalStar/arabic_learning/issues/52)
1415

1516
### Improvement
1617

lib/funcs/fsrs_func.dart

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ class FSRSConfig {
123123
final int easyDuration;
124124
final int goodDuration;
125125
final bool preferSimilar;
126+
final bool selfEvaluate;
126127

127128
const FSRSConfig({
128129
bool? enabled,
@@ -132,15 +133,17 @@ class FSRSConfig {
132133
double? desiredRetention,
133134
int? easyDuration,
134135
int? goodDuration,
135-
bool? preferSimilar
136+
bool? preferSimilar,
137+
bool? selfEvaluate
136138
}) :
137139
enabled = enabled??false,
138140
cards = cards??const [],
139141
reviewLogs = reviewLogs??const [],
140142
desiredRetention = desiredRetention??0.9,
141143
easyDuration = easyDuration??3000,
142144
goodDuration = goodDuration??6000,
143-
preferSimilar = preferSimilar??false;
145+
preferSimilar = preferSimilar??false,
146+
selfEvaluate = selfEvaluate??false;
144147

145148
Map<String, dynamic> toMap(){
146149
return {
@@ -151,7 +154,8 @@ class FSRSConfig {
151154
"desiredRetention": desiredRetention,
152155
"easyDuration": easyDuration,
153156
"goodDuration": goodDuration,
154-
"preferSimilar": preferSimilar
157+
"preferSimilar": preferSimilar,
158+
"selfEvaluate": selfEvaluate
155159
};
156160
}
157161

@@ -163,7 +167,8 @@ class FSRSConfig {
163167
double? desiredRetention,
164168
int? easyDuration,
165169
int? goodDuration,
166-
bool? preferSimilar
170+
bool? preferSimilar,
171+
bool? selfEvaluate
167172
}) {
168173
return FSRSConfig(
169174
enabled: enabled??this.enabled,
@@ -173,7 +178,8 @@ class FSRSConfig {
173178
desiredRetention: desiredRetention??this.desiredRetention,
174179
easyDuration: easyDuration??this.easyDuration,
175180
goodDuration: goodDuration??this.goodDuration,
176-
preferSimilar: preferSimilar??this.preferSimilar
181+
preferSimilar: preferSimilar??this.preferSimilar,
182+
selfEvaluate: selfEvaluate??this.selfEvaluate
177183
);
178184
}
179185

@@ -187,7 +193,8 @@ class FSRSConfig {
187193
desiredRetention: configData["desiredRetention"],
188194
easyDuration: configData["easyDuration"],
189195
goodDuration: configData["goodDuration"],
190-
preferSimilar: configData["preferSimilar"]
196+
preferSimilar: configData["preferSimilar"],
197+
selfEvaluate: configData["selfEvaluate"]
191198
);
192199
}
193200
return FSRSConfig(enabled: false);

lib/funcs/ui.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,7 @@ class ChoiceQuestions extends StatefulWidget {
716716
final List<String> choices;
717717
final bool? Function(int) onSelected;
718718
final String? hint;
719+
final Widget? midWidget;
719720
final Widget? bottomWidget;
720721
final Function? onDisAllowMutipleSelect;
721722
final bool allowMutipleSelect;
@@ -728,6 +729,7 @@ class ChoiceQuestions extends StatefulWidget {
728729
required this.allowAudio,
729730
required this.onSelected,
730731
this.hint,
732+
this.midWidget,
731733
this.bottomWidget,
732734
this.onDisAllowMutipleSelect,
733735
this.bottonLayout = -1,
@@ -758,7 +760,7 @@ class _ChoiceQuestions extends State<ChoiceQuestions> {
758760
children: [
759761
if(widget.hint!=null) TextContainer(text: widget.hint!, animated: true),
760762
Expanded(
761-
child: StatefulBuilder(
763+
child: widget.midWidget ?? StatefulBuilder(
762764
builder: (context, setLocalState) {
763765
return ElevatedButton.icon(
764766
icon: Icon(widget.allowAudio ? (playing ? Icons.multitrack_audio : Icons.volume_up) : Icons.short_text, size: 24.0),

lib/sub_pages_builder/learning_pages/fsrs_pages.dart

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:math';
22

33
import 'package:arabic_learning/vars/config_structure.dart';
44
import 'package:flutter/material.dart';
5+
import 'package:fsrs/fsrs.dart' show Rating;
56
import 'package:provider/provider.dart';
67

78
import 'package:arabic_learning/vars/statics_var.dart';
@@ -143,6 +144,37 @@ class ForeFSRSSettingPage extends StatelessWidget {
143144
),
144145
margin: EdgeInsets.all(8.0),
145146
padding: EdgeInsets.all(8.0),
147+
child: Column(
148+
crossAxisAlignment: CrossAxisAlignment.start,
149+
children: [
150+
Row(
151+
children: [
152+
Expanded(child: Text("使用自我评级", style: Theme.of(context).textTheme.bodyLarge)),
153+
Switch(
154+
value: fsrs.config.selfEvaluate,
155+
onChanged: (value){
156+
setState(() {
157+
fsrs.config = fsrs.config.copyWith(
158+
selfEvaluate: value
159+
);
160+
});
161+
}
162+
)
163+
],
164+
),
165+
Text("自我评级 开启时会向你展示遮挡了中文的单词卡片,由你自行选择你是 记得很清楚/还记得/回忆困难/忘了"),
166+
Text("在此模式下,计时仅作展示,不作为评分依据"),
167+
Text("适合清楚自己的实力的人启用")
168+
],
169+
),
170+
),
171+
if(!fsrs.config.selfEvaluate) Container(
172+
decoration: BoxDecoration(
173+
borderRadius: StaticsVar.br,
174+
color: Theme.of(context).colorScheme.onPrimary
175+
),
176+
margin: EdgeInsets.all(8.0),
177+
padding: EdgeInsets.all(8.0),
146178
child: Column(
147179
crossAxisAlignment: CrossAxisAlignment.start,
148180
children: [
@@ -162,7 +194,8 @@ class ForeFSRSSettingPage extends StatelessWidget {
162194
],
163195
),
164196
Text("偏好易混词 开启时选择题的选项更多地按照词根寻找相似的单词进行测试"),
165-
Text("关闭时选择题的选项更多地考察同课程的单词")
197+
Text("关闭时选择题的选项更多地考察同课程的单词"),
198+
Text("该选型仅在自我评级关闭时生效")
166199
],
167200
),
168201
),
@@ -225,7 +258,7 @@ class MainFSRSPage extends StatelessWidget {
225258
return Center(
226259
child: Column(
227260
children: [
228-
TextContainer(text: "你有${fsrs.getWillDueCount().toString()}个单词即将逾期!\n上滑页面开始复习",size: Size(mediaQuery.size.width * 0.8, mediaQuery.size.height * 0.4),textAlign: TextAlign.center),
261+
TextContainer(text: "你有${fsrs.getWillDueCount().toString()}个单词需要复习!\n上滑页面开始复习",size: Size(mediaQuery.size.width * 0.8, mediaQuery.size.height * 0.4),textAlign: TextAlign.center),
229262
Icon(Icons.arrow_upward, size: 48.0, color: Colors.grey)
230263
],
231264
),
@@ -269,20 +302,27 @@ class _FSRSReviewCardPage extends State<FSRSReviewCardPage> {
269302
context.read<Global>().uiLogger.info("构建 FSRSReviewCardPage");
270303
MediaQueryData mediaQuery = MediaQuery.of(context);
271304
final List<WordItem> wordData = context.read<Global>().wordData.words;
305+
late final int correct;
272306

273307
// 防止重建后选项丢失
274308
if(options == null){
275-
List<WordItem> optionWords = getRandomWords(4, context.read<Global>().wordData, include: wordData[widget.wordID], preferClass: !widget.fsrs.config.preferSimilar, rnd: widget.rnd);
276-
options ??= List.generate(4, (int index) => optionWords[index].chinese, growable: false);
309+
if(widget.fsrs.config.selfEvaluate) {
310+
options = const ["记得很清楚", "还记得", "回忆困难", "忘了"];
311+
correct = -1;
312+
} else {
313+
List<WordItem> optionWords = getRandomWords(4, context.read<Global>().wordData, include: wordData[widget.wordID], preferClass: !widget.fsrs.config.preferSimilar, rnd: widget.rnd);
314+
options = List.generate(4, (int index) => optionWords[index].chinese, growable: false);
315+
correct = options!.indexOf(context.read<Global>().wordData.words[widget.wordID].chinese);
316+
}
277317
}
278318

279-
final int correct = options!.indexOf(context.read<Global>().wordData.words[widget.wordID].chinese);
280319
return Material(
281320
child: ChoiceQuestions(
282-
mainWord: wordData[widget.wordID].arabic,
321+
mainWord: widget.fsrs.config.selfEvaluate ? "[selfEvaluate]" : wordData[widget.wordID].arabic,
322+
midWidget: widget.fsrs.config.selfEvaluate ? WordCard(word: wordData[widget.wordID]) : null,
283323
choices: options!,
284324
allowAudio: true,
285-
allowAnitmation: true,
325+
allowAnitmation: !widget.fsrs.config.selfEvaluate,
286326
allowMutipleSelect: false,
287327
hint: "单词ID: ${widget.wordID}${choosed ? " 用时: ${end.difference(start).inMilliseconds}毫秒" : ""}",
288328
onDisAllowMutipleSelect: (value) {
@@ -295,13 +335,18 @@ class _FSRSReviewCardPage extends State<FSRSReviewCardPage> {
295335
choosed = true;
296336
end = DateTime.now();
297337
});
298-
if(correct == value) {
299-
widget.fsrs.reviewCard(widget.wordID, end.difference(start).inMilliseconds, true);
300-
context.read<Global>().updateLearningStreak();
338+
context.read<Global>().updateLearningStreak();
339+
if(widget.fsrs.config.selfEvaluate) {
340+
widget.fsrs.reviewCard(widget.wordID, end.difference(start).inMilliseconds, true, forceRate: (const [Rating.easy, Rating.good, Rating.hard, Rating.again]).elementAt(value));
301341
return true;
302342
} else {
303-
widget.fsrs.reviewCard(widget.wordID, end.difference(start).inMilliseconds, false);
304-
return false;
343+
if(correct == value) {
344+
widget.fsrs.reviewCard(widget.wordID, end.difference(start).inMilliseconds, true);
345+
return true;
346+
} else {
347+
widget.fsrs.reviewCard(widget.wordID, end.difference(start).inMilliseconds, false);
348+
return false;
349+
}
305350
}
306351
},
307352
bottomWidget: TweenAnimationBuilder<double>(
@@ -315,7 +360,7 @@ class _FSRSReviewCardPage extends State<FSRSReviewCardPage> {
315360
return Row(
316361
mainAxisAlignment: MainAxisAlignment.center,
317362
children: [
318-
ElevatedButton.icon(
363+
if(!widget.fsrs.config.selfEvaluate) ElevatedButton.icon(
319364
style: ElevatedButton.styleFrom(
320365
fixedSize: Size(mediaQuery.size.width * 0.9 - mediaQuery.size.width * 0.5 * value, mediaQuery.size.height * 0.1),
321366
shape: RoundedRectangleBorder(borderRadius: StaticsVar.br)
@@ -329,10 +374,10 @@ class _FSRSReviewCardPage extends State<FSRSReviewCardPage> {
329374
icon: Icon(Icons.tips_and_updates),
330375
label: Text(value == 0.0 ? "忘了?" : "详解"),
331376
),
332-
SizedBox(width: mediaQuery.size.width*0.02*value),
377+
if(!widget.fsrs.config.selfEvaluate) SizedBox(width: mediaQuery.size.width*0.02*value),
333378
if(value > 0.3) ElevatedButton.icon(
334379
style: ElevatedButton.styleFrom(
335-
fixedSize: Size(mediaQuery.size.width * 0.5 * value, mediaQuery.size.height * 0.1),
380+
fixedSize: Size(mediaQuery.size.width * (widget.fsrs.config.selfEvaluate ? 1 : 0.5) * value, mediaQuery.size.height * 0.1),
336381
shape: RoundedRectangleBorder(borderRadius: StaticsVar.br)
337382
),
338383
onPressed: () {

0 commit comments

Comments
 (0)