cyberhybridhub/server/lib/pipeline/branch_decision.dart

73 lines
2.0 KiB
Dart

/// Outcome of evaluating a user's numeric answer against pipeline rules.
enum BranchOutcome {
/// Answer matched the expected value (within tolerance when applicable).
match,
/// Answer was on the positive side of the scale (e.g. preference toward +10).
preferHigh,
/// Answer was on the negative side of the scale.
preferLow,
/// Numeric answer was close but not exact.
close,
/// Answer was far from the target.
miss,
}
class BranchDecision {
const BranchDecision._();
/// Exact match for discrete choices encoded as integers.
static BranchOutcome discreteChoice({
required num userResponse,
required num correctAnswer,
}) {
if (userResponse.round() == correctAnswer.round()) {
return BranchOutcome.match;
}
return userResponse.sign >= 0 ? BranchOutcome.preferHigh : BranchOutcome.preferLow;
}
/// Compares a population or temperature estimate with tolerance.
static BranchOutcome numericEstimate({
required num userResponse,
required num correctAnswer,
int tolerance = 2,
}) {
final int delta = (userResponse.round() - correctAnswer.round()).abs();
if (delta == 0) {
return BranchOutcome.match;
}
if (delta <= tolerance) {
return BranchOutcome.close;
}
return BranchOutcome.miss;
}
/// Yes/no questions encoded as +10 (yes) vs -10 (no) on the slider.
static BranchOutcome yesNo({
required num userResponse,
required num correctAnswer,
}) {
final bool userYes = userResponse > 0;
final bool correctYes = correctAnswer > 0;
if (userYes == correctYes) {
return BranchOutcome.match;
}
return BranchOutcome.miss;
}
/// Interprets slider position as a preference (geography vs weather track).
static BranchOutcome trackPreference(num userResponse) {
if (userResponse >= 3) {
return BranchOutcome.preferHigh;
}
if (userResponse <= -3) {
return BranchOutcome.preferLow;
}
return BranchOutcome.close;
}
}