Files
abawo-bt-app/lib/model/gear_configurator.dart

92 lines
2.4 KiB
Dart

import 'package:abawo_bt_app/model/gear_ratio_codec.dart';
enum GearRetentionMode { keepHighest, keepAll }
class GearConfiguratorCalculation {
const GearConfiguratorCalculation({
required this.ratios,
required this.discardedBelowRange,
required this.discardedAboveRange,
required this.duplicateCount,
required this.truncatedCount,
});
final List<double> ratios;
final int discardedBelowRange;
final int discardedAboveRange;
final int duplicateCount;
final int truncatedCount;
}
GearConfiguratorCalculation calculateGearRatios({
required List<int> chainrings,
required List<int> sprockets,
required GearRetentionMode mode,
int maxRatios = 32,
}) {
final sortedChainrings = List<int>.from(chainrings)..sort();
final sortedSprockets = List<int>.from(sprockets)..sort((a, b) => b - a);
var discardedBelowRange = 0;
var discardedAboveRange = 0;
var duplicateCount = 0;
final encoded = <int>{};
final ratios = <double>[];
void addRatio(double ratio) {
if (ratio < gearRatioMin) {
discardedBelowRange++;
return;
}
if (ratio > gearRatioMax) {
discardedAboveRange++;
return;
}
final raw = encodeGearRatioByte(ratio);
if (!encoded.add(raw)) {
duplicateCount++;
return;
}
ratios.add(decodeGearRatioByte(raw));
}
switch (mode) {
case GearRetentionMode.keepAll:
for (final chainring in sortedChainrings) {
for (final sprocket in sortedSprockets) {
addRatio(chainring / sprocket);
}
}
break;
case GearRetentionMode.keepHighest:
var threshold = double.negativeInfinity;
for (final chainring in sortedChainrings) {
final beforeLength = ratios.length;
for (final sprocket in sortedSprockets) {
final ratio = chainring / sprocket;
if (ratio >= threshold) {
addRatio(ratio);
}
}
if (ratios.length > beforeLength) {
threshold = ratios.reduce((a, b) => a > b ? a : b);
}
}
break;
}
ratios.sort();
final truncatedCount =
ratios.length > maxRatios ? ratios.length - maxRatios : 0;
final limited = ratios.take(maxRatios).toList(growable: false);
return GearConfiguratorCalculation(
ratios: limited,
discardedBelowRange: discardedBelowRange,
discardedAboveRange: discardedAboveRange,
duplicateCount: duplicateCount,
truncatedCount: truncatedCount,
);
}