69 lines
2.1 KiB
Dart
69 lines
2.1 KiB
Dart
import 'dart:math';
|
|
|
|
import 'question_source_preferences.dart';
|
|
import 'questions_db.dart';
|
|
|
|
/// Picks the next question source randomly matching configured mix percentages.
|
|
abstract final class QuestionSourceMix {
|
|
/// Source id selected using weighted random selection based on configured mix ratios.
|
|
static String pickNextSourceId({
|
|
required Map<String, int> effectiveMixPercent,
|
|
required Map<String, int> deliveredCounts,
|
|
Random? random,
|
|
}) {
|
|
if (effectiveMixPercent.isEmpty) {
|
|
return 'market_history';
|
|
}
|
|
|
|
final int totalWeight =
|
|
effectiveMixPercent.values.fold<int>(0, (int a, int b) => a + b);
|
|
if (totalWeight <= 0) {
|
|
return effectiveMixPercent.keys.first;
|
|
}
|
|
|
|
// If one source has 100% of the active weight, bypass the random roll completely.
|
|
for (final MapEntry<String, int> entry in effectiveMixPercent.entries) {
|
|
if (entry.value == totalWeight) {
|
|
return entry.key;
|
|
}
|
|
}
|
|
|
|
final Random rng = random ?? Random();
|
|
var roll = rng.nextInt(totalWeight);
|
|
for (final MapEntry<String, int> entry in effectiveMixPercent.entries) {
|
|
roll -= entry.value;
|
|
if (roll < 0) {
|
|
return entry.key;
|
|
}
|
|
}
|
|
return 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];
|
|
}
|
|
}
|