cyberhybridhub/server/lib/question_source_mix.dart
nathanAndrinoid 4459852f83
Some checks failed
Admin portal tests / test (push) Has been cancelled
spelling
2026-06-05 03:22:35 +00:00

71 lines
2.2 KiB
Dart

import 'question_source_preferences.dart';
import 'questions_db.dart';
/// Picks the next question source to match configured mix percentages over time.
abstract final class QuestionSourceMix {
/// Source id with the largest deficit vs configured effective mix (sequential balance).
static String pickNextSourceId({
required Map<String, int> effectiveMixPercent,
required Map<String, int> deliveredCounts,
}) {
if (effectiveMixPercent.isEmpty) {
return 'market_history';
}
final int totalDelivered =
deliveredCounts.values.fold<int>(0, (int a, int b) => a + b);
if (totalDelivered == 0) {
return effectiveMixPercent.entries
.reduce(
(
MapEntry<String, int> a,
MapEntry<String, int> b,
) =>
a.value >= b.value ? a : b,
)
.key;
}
String? pick;
var maxDeficit = double.negativeInfinity;
for (final MapEntry<String, int> entry in effectiveMixPercent.entries) {
final double target = entry.value / 100.0;
final double actual =
(deliveredCounts[entry.key] ?? 0) / totalDelivered;
final double deficit = target - actual;
if (deficit > maxDeficit) {
maxDeficit = deficit;
pick = entry.key;
}
}
return pick ?? effectiveMixPercent.keys.first;
}
static Map<String, int> effectiveMixFromResolved(
List<ResolvedQuestionSourcePreference> prefs,
) {
return QuestionSourcePreferences.effectiveMix(prefs);
}
/// Orders unanswered rows so [preferredSourceId] is shown first (stable FIFO within source).
static List<Map<String, dynamic>> orderUnansweredByPreferredSource(
List<Map<String, dynamic>> rows, {
required String preferredSourceId,
}) {
if (rows.length <= 1) {
return rows;
}
final List<Map<String, dynamic>> preferred = <Map<String, dynamic>>[];
final List<Map<String, dynamic>> rest = <Map<String, dynamic>>[];
for (final Map<String, dynamic> row in rows) {
if (QuestionsDb.resolveSourceId(row) == preferredSourceId) {
preferred.add(row);
} else {
rest.add(row);
}
}
return <Map<String, dynamic>>[...preferred, ...rest];
}
}