131 lines
3.7 KiB
Dart
131 lines
3.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:motorcycle_dash/features/replay/replay_screen.dart';
|
|
import 'package:motorcycle_dash/database/database.dart';
|
|
|
|
void main() {
|
|
group('Forensic Replay Apex Grading (MOB-13)', () {
|
|
test('CornerAnalysis initializes and grades cornering efficiency accurately', () {
|
|
final cornerA = CornerAnalysis(
|
|
id: 1,
|
|
direction: 'Left',
|
|
entrySpeed: 52.0,
|
|
apexSpeed: 48.0,
|
|
exitSpeed: 54.0,
|
|
apexLeanAngle: 42.0,
|
|
grade: 'A+',
|
|
startIndex: 10,
|
|
apexIndex: 25,
|
|
endIndex: 40,
|
|
);
|
|
|
|
expect(cornerA.id, 1);
|
|
expect(cornerA.direction, 'Left');
|
|
expect(cornerA.entrySpeed, 52.0);
|
|
expect(cornerA.apexSpeed, 48.0);
|
|
expect(cornerA.exitSpeed, 54.0);
|
|
expect(cornerA.speedDelta, 2.0);
|
|
expect(cornerA.apexLeanAngle, 42.0);
|
|
expect(cornerA.grade, 'A+');
|
|
expect(cornerA.getGradeColor(), const Color(0xFF10B981)); // Emerald
|
|
|
|
final cornerB = CornerAnalysis(
|
|
id: 2,
|
|
direction: 'Right',
|
|
entrySpeed: 45.0,
|
|
apexSpeed: 40.0,
|
|
exitSpeed: 44.0,
|
|
apexLeanAngle: 24.0,
|
|
grade: 'B',
|
|
startIndex: 50,
|
|
apexIndex: 65,
|
|
endIndex: 80,
|
|
);
|
|
|
|
expect(cornerB.grade, 'B');
|
|
expect(cornerB.getGradeColor(), Colors.cyanAccent);
|
|
|
|
final cornerC = CornerAnalysis(
|
|
id: 3,
|
|
direction: 'Left',
|
|
entrySpeed: 40.0,
|
|
apexSpeed: 30.0,
|
|
exitSpeed: 32.0,
|
|
apexLeanAngle: 18.0,
|
|
grade: 'C',
|
|
startIndex: 90,
|
|
apexIndex: 105,
|
|
endIndex: 120,
|
|
);
|
|
|
|
expect(cornerC.grade, 'C');
|
|
expect(cornerC.getGradeColor(), Colors.amberAccent);
|
|
|
|
final cornerD = CornerAnalysis(
|
|
id: 4,
|
|
direction: 'Right',
|
|
entrySpeed: 55.0,
|
|
apexSpeed: 25.0,
|
|
exitSpeed: 28.0,
|
|
apexLeanAngle: 22.0,
|
|
grade: 'D',
|
|
startIndex: 130,
|
|
apexIndex: 145,
|
|
endIndex: 160,
|
|
);
|
|
|
|
expect(cornerD.grade, 'D');
|
|
expect(cornerD.getGradeColor(), const Color(0xFFFF334B)); // Red
|
|
});
|
|
|
|
test('Telemetry sample sequence with curves generates correct corner breakdown and heatmap tiers', () {
|
|
final now = DateTime.now();
|
|
final samples = <TelemetrySample>[];
|
|
|
|
// 1. Straight section (lean <= 20)
|
|
for (int i = 0; i < 10; i++) {
|
|
samples.add(TelemetrySample(
|
|
id: i,
|
|
rideId: 1,
|
|
timestamp: now.add(Duration(milliseconds: i * 50)),
|
|
latitude: 35.0 + (i * 0.0001),
|
|
longitude: -84.0 + (i * 0.0001),
|
|
speed: 50.0,
|
|
leanAngle: 5.0, // Straight/mild -> Yellow
|
|
));
|
|
}
|
|
|
|
// 2. Corner 1: Left turn reaching 38 degrees (Apex > 35 -> Red tier)
|
|
for (int i = 10; i < 25; i++) {
|
|
final lean = -15.0 - (i - 10) * 1.5; // reaches -37.5°
|
|
samples.add(TelemetrySample(
|
|
id: i,
|
|
rideId: 1,
|
|
timestamp: now.add(Duration(milliseconds: i * 50)),
|
|
latitude: 35.0 + (i * 0.0001),
|
|
longitude: -84.0 + (i * 0.0001),
|
|
speed: 42.0,
|
|
leanAngle: lean,
|
|
));
|
|
}
|
|
|
|
// 3. Straight recovery
|
|
for (int i = 25; i < 35; i++) {
|
|
samples.add(TelemetrySample(
|
|
id: i,
|
|
rideId: 1,
|
|
timestamp: now.add(Duration(milliseconds: i * 50)),
|
|
latitude: 35.0 + (i * 0.0001),
|
|
longitude: -84.0 + (i * 0.0001),
|
|
speed: 48.0,
|
|
leanAngle: 4.0,
|
|
));
|
|
}
|
|
|
|
expect(samples.length, 35);
|
|
final hasApexSample = samples.any((s) => (s.leanAngle ?? 0.0).abs() > 35.0);
|
|
expect(hasApexSample, isTrue);
|
|
});
|
|
});
|
|
}
|