fix: 输入校验忽略多个连续空格与大小写;统一中英文引号与空白规范化
This commit is contained in:
@@ -1081,8 +1081,17 @@ const a0SegmentGrammarNotes = <String, String>{
|
||||
String grammarNoteForSegment(String segmentId, String lessonId) =>
|
||||
a0SegmentGrammarNotes[segmentId] ?? grammarNoteForLesson(lessonId);
|
||||
|
||||
String _normalizeDialogueInput(String response) => response
|
||||
.toLowerCase()
|
||||
.replaceAll('\u2019', "'")
|
||||
.replaceAll('\u2018', "'")
|
||||
.replaceAll('’', "'")
|
||||
.replaceAll('‘', "'")
|
||||
.replaceAll(RegExp(r'\s+'), ' ')
|
||||
.trim();
|
||||
|
||||
bool matchesSegmentDialogue(String segmentId, int stage, String response) {
|
||||
final text = response.toLowerCase().replaceAll('’', "'");
|
||||
final text = _normalizeDialogueInput(response);
|
||||
final segment = a0LessonSegments.values
|
||||
.expand((segments) => segments)
|
||||
.where((item) => item.id == segmentId)
|
||||
@@ -1091,7 +1100,7 @@ bool matchesSegmentDialogue(String segmentId, int stage, String response) {
|
||||
return false;
|
||||
}
|
||||
bool hasAny(Iterable<String> terms) =>
|
||||
terms.any((term) => text.contains(term));
|
||||
terms.any((term) => text.contains(_normalizeDialogueInput(term)));
|
||||
// A phone-number report needs both the reporting frame and at least one
|
||||
// spoken digit. Other segment turns need one reviewed, task-specific term.
|
||||
if (segmentId == 'a0-04-c' && stage == 0) {
|
||||
@@ -1102,7 +1111,7 @@ bool matchesSegmentDialogue(String segmentId, int stage, String response) {
|
||||
}
|
||||
|
||||
bool matchesSegmentIndependent(String segmentId, String response) {
|
||||
final text = response.toLowerCase().replaceAll('’', "'");
|
||||
final text = _normalizeDialogueInput(response);
|
||||
final segment = a0LessonSegments.values
|
||||
.expand((segments) => segments)
|
||||
.where((item) => item.id == segmentId)
|
||||
@@ -1110,17 +1119,18 @@ bool matchesSegmentIndependent(String segmentId, String response) {
|
||||
if (segment == null) return true;
|
||||
if (segmentId == 'a0-04-a' || segmentId == 'a0-04-b') {
|
||||
final count = segment.independentRequiredTerms
|
||||
.where((term) => text.contains(term))
|
||||
.where((term) => text.contains(_normalizeDialogueInput(term)))
|
||||
.length;
|
||||
return count >= 3;
|
||||
}
|
||||
if (segmentId == 'a0-04-c') {
|
||||
return segment.independentRequiredTerms
|
||||
.where((term) => text.contains(term))
|
||||
.where((term) => text.contains(_normalizeDialogueInput(term)))
|
||||
.length >=
|
||||
3;
|
||||
}
|
||||
return segment.independentRequiredTerms.any((term) => text.contains(term));
|
||||
return segment.independentRequiredTerms
|
||||
.any((term) => text.contains(_normalizeDialogueInput(term)));
|
||||
}
|
||||
|
||||
class LessonDialogue {
|
||||
@@ -1156,7 +1166,8 @@ bool _containsTerm(String text, String term) {
|
||||
return term.split(' + ').every((part) => _containsTerm(text, part.trim()));
|
||||
}
|
||||
if (term.startsWith('#')) return _matchesStructure(text, term);
|
||||
final escaped = RegExp.escape(term.toLowerCase());
|
||||
final normTerm = _normalizeDialogueInput(term);
|
||||
final escaped = RegExp.escape(normTerm);
|
||||
return RegExp('(?<![a-z])$escaped(?![a-z])').hasMatch(text);
|
||||
}
|
||||
|
||||
@@ -1178,9 +1189,6 @@ bool _matchesStructure(String text, String token) => switch (token) {
|
||||
_ => false,
|
||||
};
|
||||
|
||||
String _normalizeDialogueInput(String response) =>
|
||||
response.toLowerCase().replaceAll('\u2019', "'").replaceAll('\u2018', "'");
|
||||
|
||||
/// Whole-lesson and free-scene dialogues validate the same way segment
|
||||
/// dialogues do: the turn has to contain the language the turn is teaching.
|
||||
bool matchesDialogueStage(LessonDialogue script, int stage, String response) {
|
||||
|
||||
Reference in New Issue
Block a user