Files
English/kouyu_english/lib/core/review_feedback.dart
T

100 lines
3.8 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'models.dart';
class ReviewCheckResult {
const ReviewCheckResult({required this.complete, required this.message});
final bool complete;
final String message;
}
/// Checks only the minimum information a learner needs to produce in an A0
/// review. It intentionally accepts common contractions and variable slot
/// values instead of comparing an answer with one fixed sentence.
class ReviewFeedback {
const ReviewFeedback._();
static String _normalize(String input) => input
.toLowerCase()
.replaceAll('', "'")
.replaceAll('', "'")
.replaceAll(RegExp(r'\s+'), ' ')
.trim();
static ReviewCheckResult check(ReviewItem item, String input) {
final text = _normalize(input);
final tokens = RegExp(
r"[a-z]+(?:'[a-z]+)?",
).allMatches(text).map((match) => match.group(0)!).toSet();
bool has(String token) => tokens.contains(_normalize(token));
bool phrase(String value) => text.contains(_normalize(value));
bool hasAny(Iterable<String> values) => values.any(has);
final introduction =
phrase("i'm") || phrase('i am') || phrase('my name is');
final itIs = phrase("it's") || phrase('it is');
final numberWords = RegExp(
r'\b(zero|one|two|three|four|five|six|seven|eight|nine|ten)\b',
).allMatches(text).length;
final complete = switch (item.id) {
'A0-P01' => introduction && tokens.length >= 2,
'A0-P02' => (phrase("what's your name") || phrase('what is your name')),
'A0-P03' => phrase('nice to meet you'),
'A0-P04' => phrase('how do you spell'),
'A0-P05' => phrase('how are you'),
'A0-P06' => introduction && hasAny(['good', 'okay', 'tired']),
'A0-P07' =>
phrase("what's your phone number") ||
phrase('what is your phone number'),
'A0-P08' =>
(phrase('my number is') || numberWords >= 3) && numberWords >= 3,
'A0-P09' => phrase("what's this") || phrase('what is this'),
'A0-P10' => itIs && hasAny(['book', 'pen', 'bag', 'key']),
'A0-P11' => phrase('where are you from'),
'A0-P12' => introduction && has('from') && tokens.length >= 3,
'A0-P13' => phrase('this is my') && tokens.length >= 4,
'A0-P14' => phrase('what day is it'),
'A0-P15' =>
itIs &&
hasAny([
'monday',
'tuesday',
'wednesday',
'thursday',
'friday',
'saturday',
'sunday',
]),
'A0-P16' => phrase('what time is it'),
'A0-P17' =>
itIs &&
(has('clock') ||
has("o'clock") ||
has('oclock') ||
phrase("o'clock")),
'A0-P18' => introduction && has('like') && tokens.length >= 3,
'A0-P19' => phrase('do you like'),
'A0-P20' =>
phrase('please say that again') || phrase('please speak slowly'),
_ when item.id.startsWith('A0-W') =>
tokens.contains(_normalize(item.target)) || phrase(item.target),
_ => tokens.length >= 2,
};
return ReviewCheckResult(
complete: complete,
message: complete ? '表达已完成,可以进入下一次复习安排。' : _hint(item.id),
);
}
static String _hint(String id) => switch (id) {
'A0-P01' => '用 Im / I am 或 My name is 介绍一个名字。',
'A0-P02' => '试着问:Whats your name?',
'A0-P04' => '问对方怎样拼写:How do you spell …?',
'A0-P08' => '说出至少三个英文数字,也可用 My number is … 开头。',
'A0-P10' => '用 Its / It is 加上一个物品。',
'A0-P12' => '用 Im from … 说出一个地点。',
'A0-P17' => '用 Its … oclock 说整点时间。',
'A0-P18' => '用 I like … 说一项喜好。',
_ => '再补充本次目标中的关键英文词或句型。',
};
}