Files
Bus-Infotainment--IBus-/lib/tfl_datasets.dart
2024-05-01 12:29:59 +01:00

295 lines
7.9 KiB
Dart

import 'dart:typed_data';
import 'package:bus_infotainment/audio_cache.dart';
import 'package:bus_infotainment/backend/live_information.dart';
import 'package:bus_infotainment/backend/modules/info_module.dart';
import 'package:bus_infotainment/utils/NameBeautify.dart';
import 'package:bus_infotainment/utils/OrdinanceSurveyUtils.dart';
import 'package:fast_csv/csv_converter.dart';
import 'package:vector_math/vector_math.dart';
class BusSequences extends InfoModule {
Map<String, BusRoute> routes = {};
Map<String, BusDestination> destinations = {};
BusSequences.fromCSV(String destinationsCSV, String busSequencesCSV) {
// Init the bus destinations
List<List<String>> destinationRows = CsvConverter().convert(destinationsCSV);
destinationRows.removeAt(0);
print("Destination rows: ${destinationRows.length}");
for (int i = 0; i < destinationRows.length; i++) {
try {
List<dynamic> entries = destinationRows[i];
// print("Parsing destination row $i: $entries");
String routeNumber = entries[0].toString();
BusRoute route = routes.containsKey(routeNumber) ? routes[routeNumber]! : BusRoute(routeNumber: routeNumber);
String blind = entries[1].toString();
double lat = double.parse(entries[2].toString());
double long = double.parse(entries[3].toString());
Vector2 grid = OSGrid.toNorthingEasting(lat, long);
BusDestination destination = BusDestination();
destination.destination = blind;
destination.easting = grid.x;
destination.northing = grid.y;
route.destinations.add(destination);
routes[routeNumber] = route;
destinations[blind] = destination;
} catch (e) {}
}
print("Loaded ${destinations.length} destinations");
// Init the bus routes
List<List<dynamic>> busSequenceRows = CsvConverter().convert(busSequencesCSV);
busSequenceRows.removeAt(0);
for (int i = 0; i < busSequenceRows.length; i++) {
try
{
List<dynamic> entries = busSequenceRows[i];
// print("Parsing bus sequence row $i: $entries");
String routeNumber = entries[0].toString();
BusRoute route = routes.containsKey(routeNumber) ? routes[routeNumber]! : BusRoute(routeNumber: routeNumber);
int routeVariant = int.parse(entries[1]);
BusRouteStop stop = BusRouteStop();
stop.stopName = entries[6].toString();
stop.stopCode = entries[4].toString();
stop.easting = int.parse(entries[7]);
stop.northing = int.parse(entries[8]);
stop.heading = int.parse(entries[9] != "" ? entries[9] : "-1");
BusRouteVariant variant = route.routeVariants.containsKey(routeVariant) ? route.routeVariants[routeVariant]! : BusRouteVariant(routeVariant: routeVariant, busRoute: route);
variant.busStops.add(stop);
route.routeVariants[routeVariant] = variant;
routes[routeNumber] = route;
}
catch (e) {
print("Error parsing bus sequence: $e");
}
}
print("Loaded ${routes.length} routes");
}
}
class BusRoute {
String routeNumber = "";
List<BusDestination> destinations = [];
AnnouncementCache? announcementCache;
Map<int, BusRouteVariant> routeVariants = {};
BusRoute({
this.routeNumber = "-1",
this.announcementCache,
});
}
class BusRouteVariant {
int routeVariant = -1;
List<BusRouteStop> busStops = [];
late BusRoute busRoute;
BusRouteVariant({
this.routeVariant = -1,
required this.busRoute,
});
BusDestination? _destination;
BusDestination? get destination {
if (_destination == null) {
// Get the nearest destination
BusDestination? nearestDestinationA;
double nearestDistanceA = double.infinity;
Vector2 stopLocation = Vector2(busStops.last.northing.toDouble(), busStops.last.easting.toDouble());
for (BusDestination destination in busRoute.destinations) {
Vector2 destinationLocation = Vector2(destination.northing.toDouble(), destination.easting.toDouble());
double distance = stopLocation.distanceTo(destinationLocation);
if (distance < nearestDistanceA) {
nearestDestinationA = destination;
nearestDistanceA = distance;
}
}
// get the nearest destination from global pool of destinations
BusDestination? nearestDestinationB;
double nearestDistanceB = double.infinity;
for (BusDestination destination in LiveInformation().busSequences.destinations.values) {
Vector2 destinationLocation = Vector2(destination.northing.toDouble(), destination.easting.toDouble());
double distance = stopLocation.distanceTo(destinationLocation);
if (distance < nearestDistanceB) {
nearestDestinationB = destination;
nearestDistanceB = distance;
}
}
print("Nearest destination A: $nearestDestinationA, distance: $nearestDistanceA");
print("Nearest destination B: $nearestDestinationB, distance: $nearestDistanceB");
// Choose the nearest destination
if (nearestDistanceA < nearestDistanceB) {
_destination = nearestDestinationA;
} else {
_destination = nearestDestinationB;
}
}
return _destination;
}
@override
String toString() {
return 'BusRouteVariant{routeVariant: $routeVariant, busRoute: ${busRoute.routeNumber}, busStops: ${busStops.length}, destinations: ${busRoute.destinations.length}}';
}
}
class BusRouteStop {
String stopName = "";
int easting = -1;
int northing = -1;
int heading = -1;
String stopCode = "";
String get formattedStopName {
return NameBeautify.beautifyStopName(stopName);
}
String getAudioFileName() {
// Convert the stop name to all caps
String stopName = this.stopName.toUpperCase();
stopName = NameBeautify.beautifyStopName(stopName);
// replace & with N
stopName = stopName.replaceAll('&', 'N');
stopName = stopName.replaceAll('/', '');
stopName = stopName.replaceAll('\'', '');
stopName = stopName.replaceAll(' ', ' ');
// Replace space with underscore
stopName = stopName.replaceAll(' ', '_');
// convert to all caps
stopName = stopName.toUpperCase();
stopName = "S_${stopName}_001.mp3";
return stopName;
}
}
class BusDestination {
String destination = "";
double easting = -1;
double northing = -1;
Future<Uint8List> getAudioBytes() async {
// Convert the stop name to all caps
String name = destination.toUpperCase();
name = NameBeautify.beautifyStopName(name);
// replace & with N
name = name.replaceAll('&', 'N');
name = name.replaceAll('/', '');
name = name.replaceAll('\'', '');
name = name.replaceAll(' ', ' ');
// Replace space with underscore
name = name.replaceAll(' ', '_');
// convert to all caps
name = name.toUpperCase();
String audioNameA = "D_${name}_001.mp3";
String audioNameB = "S_${name}_001.mp3";
String audioNameC = "A_${name}_001.mp3";
print("Audio name A: $audioNameA");
print("Audio name B: $audioNameB");
print("Audio name C: $audioNameC");
await LiveInformation().announcementModule.announcementCache.loadAnnouncementsFromBytes(await LiveInformation().announcementModule.getBundleBytes(), [audioNameA, audioNameB, audioNameC]);
Uint8List? audioBytesA = LiveInformation().announcementModule.announcementCache[audioNameA];
Uint8List? audioBytesB = LiveInformation().announcementModule.announcementCache[audioNameB];
Uint8List? audioBytesC = LiveInformation().announcementModule.announcementCache[audioNameC];
if (audioBytesA != null) return audioBytesA;
if (audioBytesB != null) return audioBytesB;
if (audioBytesC != null) return audioBytesC;
print("No audio bytes found for $name");
return Uint8List(0);
}
}