init
This commit is contained in:
150
lib/util/loco_info_util.dart
Normal file
150
lib/util/loco_info_util.dart
Normal file
@@ -0,0 +1,150 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class LocoInfoUtil {
|
||||
static final List<LocoInfo> _locoData = [];
|
||||
static bool _initialized = false;
|
||||
|
||||
static Future<void> initialize() async {
|
||||
if (_initialized) return;
|
||||
|
||||
try {
|
||||
final csvData = await rootBundle.loadString('assets/loco_info.csv');
|
||||
final lines = csvData.split('\n');
|
||||
|
||||
for (final line in lines) {
|
||||
if (line.trim().isEmpty) continue;
|
||||
|
||||
final fields = _parseCsvLine(line);
|
||||
if (fields.length >= 4) {
|
||||
try {
|
||||
final model = fields[0];
|
||||
final start = int.parse(fields[1]);
|
||||
final end = int.parse(fields[2]);
|
||||
final owner = fields[3];
|
||||
final alias = fields.length > 4 ? fields[4] : '';
|
||||
final manufacturer = fields.length > 5 ? fields[5] : '';
|
||||
|
||||
_locoData.add(LocoInfo(
|
||||
model: model,
|
||||
start: start,
|
||||
end: end,
|
||||
owner: owner,
|
||||
alias: alias,
|
||||
manufacturer: manufacturer,
|
||||
));
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
_initialized = true;
|
||||
} catch (e) {
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
static List<String> _parseCsvLine(String line) {
|
||||
final fields = <String>[];
|
||||
final buffer = StringBuffer();
|
||||
bool inQuotes = false;
|
||||
|
||||
for (int i = 0; i < line.length; i++) {
|
||||
final char = line[i];
|
||||
|
||||
if (char == '"') {
|
||||
inQuotes = !inQuotes;
|
||||
} else if (char == ',' && !inQuotes) {
|
||||
fields.add(buffer.toString().trim());
|
||||
buffer.clear();
|
||||
} else {
|
||||
buffer.write(char);
|
||||
}
|
||||
}
|
||||
|
||||
fields.add(buffer.toString().trim());
|
||||
return fields;
|
||||
}
|
||||
|
||||
static LocoInfo? findLocoInfo(String model, String number) {
|
||||
if (!_initialized || model.isEmpty || number.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
final cleanNumber = number.trim().replaceAll('-', '').replaceAll(' ', '');
|
||||
final num = cleanNumber.length > 4
|
||||
? int.parse(cleanNumber.substring(cleanNumber.length - 4))
|
||||
: int.parse(cleanNumber);
|
||||
|
||||
for (final info in _locoData) {
|
||||
if (info.model == model && num >= info.start && num <= info.end) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static String? getLocoInfoDisplay(String model, String number) {
|
||||
if (_locoData.isEmpty) return null;
|
||||
|
||||
final modelTrimmed = model.trim();
|
||||
final numberTrimmed = number.trim();
|
||||
|
||||
if (modelTrimmed.isEmpty ||
|
||||
numberTrimmed.isEmpty ||
|
||||
numberTrimmed == "<NUL>") {
|
||||
return null;
|
||||
}
|
||||
|
||||
final cleanNumber = numberTrimmed.replaceAll('-', '').replaceAll(' ', '');
|
||||
final numberSuffix = cleanNumber.length >= 4
|
||||
? cleanNumber.substring(cleanNumber.length - 4)
|
||||
: cleanNumber.padLeft(4, '0');
|
||||
|
||||
final numberInt = int.tryParse(numberSuffix);
|
||||
if (numberInt == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (final info in _locoData) {
|
||||
if (info.model == modelTrimmed &&
|
||||
numberInt >= info.start &&
|
||||
numberInt <= info.end) {
|
||||
final buffer = StringBuffer();
|
||||
buffer.write(info.owner);
|
||||
|
||||
if (info.alias.isNotEmpty) {
|
||||
buffer.write(' - ${info.alias}');
|
||||
}
|
||||
|
||||
if (info.manufacturer.isNotEmpty) {
|
||||
buffer.write(' - ${info.manufacturer}');
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class LocoInfo {
|
||||
final String model;
|
||||
final int start;
|
||||
final int end;
|
||||
final String owner;
|
||||
final String alias;
|
||||
final String manufacturer;
|
||||
|
||||
LocoInfo({
|
||||
required this.model,
|
||||
required this.start,
|
||||
required this.end,
|
||||
required this.owner,
|
||||
required this.alias,
|
||||
required this.manufacturer,
|
||||
});
|
||||
}
|
||||
54
lib/util/loco_type_util.dart
Normal file
54
lib/util/loco_type_util.dart
Normal file
@@ -0,0 +1,54 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class LocoTypeUtil {
|
||||
static final LocoTypeUtil _instance = LocoTypeUtil._internal();
|
||||
factory LocoTypeUtil() => _instance;
|
||||
LocoTypeUtil._internal() {
|
||||
_syncInitialize();
|
||||
}
|
||||
|
||||
final Map<String, String> _locoTypeMap = {};
|
||||
bool _isInitialized = false;
|
||||
|
||||
void _syncInitialize() {
|
||||
try {
|
||||
rootBundle.loadString('assets/loco_type_info.csv').then((csvData) {
|
||||
final lines = const LineSplitter().convert(csvData);
|
||||
for (final line in lines) {
|
||||
final trimmedLine = line.trim();
|
||||
if (trimmedLine.isEmpty) continue;
|
||||
final parts = trimmedLine.split(',');
|
||||
if (parts.length >= 2) {
|
||||
final code = parts[0].trim();
|
||||
final type = parts[1].trim();
|
||||
_locoTypeMap[code] = type;
|
||||
}
|
||||
}
|
||||
_isInitialized = true;
|
||||
});
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
@deprecated
|
||||
Future<void> initialize() async {}
|
||||
|
||||
String? getLocoTypeByCode(String code) {
|
||||
return _locoTypeMap[code];
|
||||
}
|
||||
|
||||
String? getLocoTypeByLocoNumber(String locoNumber) {
|
||||
if (locoNumber.length < 3) return null;
|
||||
final prefix = locoNumber.substring(0, 3);
|
||||
return getLocoTypeByCode(prefix);
|
||||
}
|
||||
|
||||
Map<String, String> getAllMappings() {
|
||||
return Map.from(_locoTypeMap);
|
||||
}
|
||||
|
||||
bool get isInitialized => _isInitialized;
|
||||
|
||||
int get mappingCount => _locoTypeMap.length;
|
||||
}
|
||||
68
lib/util/train_type_util.dart
Normal file
68
lib/util/train_type_util.dart
Normal file
@@ -0,0 +1,68 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class TrainTypeUtil {
|
||||
static final List<_TrainTypePattern> _patterns = [];
|
||||
static bool _initialized = false;
|
||||
|
||||
static Future<void> initialize() async {
|
||||
if (_initialized) return;
|
||||
|
||||
try {
|
||||
final csvData =
|
||||
await rootBundle.loadString('assets/train_number_info.csv');
|
||||
final lines = csvData.split('\n');
|
||||
|
||||
for (final line in lines) {
|
||||
if (line.trim().isEmpty) continue;
|
||||
|
||||
final firstQuoteEnd = line.indexOf('"', 1);
|
||||
if (firstQuoteEnd > 0 && firstQuoteEnd < line.length - 1) {
|
||||
final regex = line.substring(1, firstQuoteEnd);
|
||||
final remainingPart = line.substring(firstQuoteEnd + 1).trim();
|
||||
|
||||
if (remainingPart.startsWith(',"') && remainingPart.endsWith('"')) {
|
||||
final type = remainingPart.substring(2, remainingPart.length - 1);
|
||||
try {
|
||||
_patterns.add(_TrainTypePattern(RegExp(regex), type));
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
_initialized = true;
|
||||
} catch (e) {
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
static String? getTrainType(String lbjClass, String train) {
|
||||
if (!_initialized) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final lbjClassTrimmed = lbjClass.trim();
|
||||
final trainTrimmed = train.trim();
|
||||
|
||||
if (trainTrimmed.isEmpty || trainTrimmed == "<NUL>") {
|
||||
return null;
|
||||
}
|
||||
|
||||
final actualTrain =
|
||||
lbjClassTrimmed == "NA" ? trainTrimmed : lbjClassTrimmed + trainTrimmed;
|
||||
|
||||
for (final pattern in _patterns) {
|
||||
if (pattern.regex.hasMatch(actualTrain)) {
|
||||
return pattern.type;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class _TrainTypePattern {
|
||||
final RegExp regex;
|
||||
final String type;
|
||||
|
||||
_TrainTypePattern(this.regex, this.type);
|
||||
}
|
||||
Reference in New Issue
Block a user