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

113 lines
3.8 KiB
Dart

import 'models.dart';
/// Combines strict local matching with an advisory semantic AI result.
///
/// Progress is deliberately permissive: a strict local match can continue if
/// AI is unavailable or disagrees. Mastery evidence is conservative: a free
/// scene produces independent evidence only when local and AI agree and the
/// learner received no answer-level help.
DialogueTurnDecision resolveDialogueTurnDecision({
required LocalDialogueVerdict local,
required DialogueAiIntervention? ai,
required bool aiWasAttempted,
required bool isFreeScene,
required DialogueSupportLevel supportLevel,
}) {
if (local == LocalDialogueVerdict.rejected) {
return const DialogueTurnDecision(
canAdvance: false,
evidenceOutcome: EvidenceKind.languageError,
validationSource: DialogueValidationSource.local,
supportLevel: DialogueSupportLevel.none,
feedback: '请输入一个有效的英文回答。',
);
}
final aiAccepted =
ai?.accepted == true &&
ai?.goalSatisfied == true &&
ai?.verdict == DialogueAiVerdict.accepted;
final assisted = switch (supportLevel) {
DialogueSupportLevel.hint ||
DialogueSupportLevel.translation ||
DialogueSupportLevel.correction ||
DialogueSupportLevel.skipped => true,
_ => false,
};
if (local == LocalDialogueVerdict.accepted && aiAccepted) {
return DialogueTurnDecision(
canAdvance: true,
evidenceOutcome: !isFreeScene
? (assisted ? EvidenceKind.assisted : EvidenceKind.pending)
: (assisted
? EvidenceKind.assisted
: EvidenceKind.independentSuccess),
validationSource: DialogueValidationSource.localAndAi,
supportLevel: supportLevel,
feedback: ai?.explanation,
);
}
if (aiAccepted) {
return DialogueTurnDecision(
canAdvance: true,
evidenceOutcome: assisted ? EvidenceKind.assisted : EvidenceKind.pending,
validationSource: DialogueValidationSource.ai,
supportLevel: supportLevel == DialogueSupportLevel.none
? DialogueSupportLevel.validationOnly
: supportLevel,
feedback: ai?.explanation,
);
}
if (local == LocalDialogueVerdict.accepted) {
final aiExplicitlyRejected =
ai?.verdict == DialogueAiVerdict.correctable ||
ai?.verdict == DialogueAiVerdict.offTopic;
if (aiExplicitlyRejected) {
return DialogueTurnDecision(
canAdvance: false,
evidenceOutcome: assisted
? EvidenceKind.assisted
: EvidenceKind.pending,
validationSource: DialogueValidationSource.disagreement,
supportLevel: supportLevel,
feedback: ai?.explanation,
suggestion: ai?.suggestion,
);
}
final source = aiWasAttempted
? (ai == null
? DialogueValidationSource.unavailable
: DialogueValidationSource.disagreement)
: DialogueValidationSource.local;
return DialogueTurnDecision(
canAdvance: true,
evidenceOutcome: assisted
? EvidenceKind.assisted
: aiWasAttempted
? EvidenceKind.pending
: isFreeScene
? EvidenceKind.independentSuccess
: EvidenceKind.pending,
validationSource: source,
supportLevel: supportLevel,
feedback: ai?.explanation,
);
}
return DialogueTurnDecision(
canAdvance: false,
evidenceOutcome: assisted ? EvidenceKind.assisted : EvidenceKind.pending,
validationSource: aiWasAttempted
? (ai == null
? DialogueValidationSource.unavailable
: DialogueValidationSource.localAndAi)
: DialogueValidationSource.local,
supportLevel: supportLevel,
feedback: ai?.explanation ?? '暂时无法确认这句是否完成本轮任务,请换一种说法。',
suggestion: ai?.suggestion,
);
}