113 lines
3.8 KiB
Dart
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,
|
|
);
|
|
}
|