302 lines
8.3 KiB
Dart
302 lines
8.3 KiB
Dart
import 'dart:convert';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:lbjconsole/util/train_type_util.dart';
|
|
import 'package:lbjconsole/util/loco_info_util.dart';
|
|
|
|
class TrainRecord {
|
|
final String uniqueId;
|
|
final DateTime timestamp;
|
|
final DateTime receivedTimestamp;
|
|
final String train;
|
|
final int direction;
|
|
final String speed;
|
|
final String position;
|
|
final String time;
|
|
final String loco;
|
|
final String locoType;
|
|
final String lbjClass;
|
|
final String route;
|
|
final String positionInfo;
|
|
final double rssi;
|
|
|
|
TrainRecord({
|
|
required this.uniqueId,
|
|
required this.timestamp,
|
|
required this.receivedTimestamp,
|
|
required this.train,
|
|
required this.direction,
|
|
required this.speed,
|
|
required this.position,
|
|
required this.time,
|
|
required this.loco,
|
|
required this.locoType,
|
|
required this.lbjClass,
|
|
required this.route,
|
|
required this.positionInfo,
|
|
required this.rssi,
|
|
});
|
|
|
|
factory TrainRecord.fromJson(Map<String, dynamic> json) {
|
|
return TrainRecord(
|
|
uniqueId: json['uniqueId'] ?? json['unique_id'] ?? '',
|
|
timestamp: DateTime.fromMillisecondsSinceEpoch(json['timestamp'] ?? 0),
|
|
receivedTimestamp: DateTime.fromMillisecondsSinceEpoch(
|
|
json['receivedTimestamp'] ?? json['received_timestamp'] ?? 0),
|
|
train: json['train'] ?? '',
|
|
direction: json['direction'] ?? json['dir'] ?? 0,
|
|
speed: json['speed'] ?? '',
|
|
position: json['position'] ?? json['pos'] ?? '',
|
|
time: json['time'] ?? '',
|
|
loco: json['loco'] ?? '',
|
|
locoType: json['locoType'] ?? json['loco_type'] ?? '',
|
|
lbjClass: json['lbjClass'] ?? json['lbj_class'] ?? '',
|
|
route: json['route'] ?? '',
|
|
positionInfo: json['positionInfo'] ?? json['position_info'] ?? '',
|
|
rssi: (json['rssi'] ?? 0.0).toDouble(),
|
|
);
|
|
}
|
|
|
|
factory TrainRecord.fromJsonString(String jsonString) {
|
|
final json = jsonDecode(jsonString);
|
|
return TrainRecord.fromJson(json);
|
|
}
|
|
|
|
Map<String, dynamic> toJson() {
|
|
return {
|
|
'uniqueId': uniqueId,
|
|
'timestamp': timestamp.millisecondsSinceEpoch,
|
|
'receivedTimestamp': receivedTimestamp.millisecondsSinceEpoch,
|
|
'train': train,
|
|
'direction': direction,
|
|
'speed': speed,
|
|
'position': position,
|
|
'time': time,
|
|
'loco': loco,
|
|
'loco_type': locoType,
|
|
'lbj_class': lbjClass,
|
|
'route': route,
|
|
'position_info': positionInfo,
|
|
'rssi': rssi,
|
|
};
|
|
}
|
|
|
|
Map<String, dynamic> toDatabaseJson() {
|
|
return {
|
|
'uniqueId': uniqueId,
|
|
'timestamp': timestamp.millisecondsSinceEpoch,
|
|
'receivedTimestamp': receivedTimestamp.millisecondsSinceEpoch,
|
|
'train': train,
|
|
'direction': direction,
|
|
'speed': speed,
|
|
'position': position,
|
|
'time': time,
|
|
'loco': loco,
|
|
'locoType': locoType,
|
|
'lbjClass': lbjClass,
|
|
'route': route,
|
|
'positionInfo': positionInfo,
|
|
'rssi': rssi,
|
|
};
|
|
}
|
|
|
|
factory TrainRecord.fromDatabaseJson(Map<String, dynamic> json) {
|
|
return TrainRecord(
|
|
uniqueId: json['uniqueId']?.toString() ?? '',
|
|
timestamp:
|
|
DateTime.fromMillisecondsSinceEpoch(json['timestamp'] as int? ?? 0),
|
|
receivedTimestamp: DateTime.fromMillisecondsSinceEpoch(
|
|
json['receivedTimestamp'] as int? ?? 0),
|
|
train: json['train']?.toString() ?? '',
|
|
direction: json['direction'] as int? ?? 0,
|
|
speed: json['speed']?.toString() ?? '',
|
|
position: json['position']?.toString() ?? '',
|
|
time: json['time']?.toString() ?? '',
|
|
loco: json['loco']?.toString() ?? '',
|
|
locoType: json['locoType']?.toString() ?? '',
|
|
lbjClass: json['lbjClass']?.toString() ?? '',
|
|
route: json['route']?.toString() ?? '',
|
|
positionInfo: json['positionInfo']?.toString() ?? '',
|
|
rssi: (json['rssi'] as num?)?.toDouble() ?? 0.0,
|
|
);
|
|
}
|
|
|
|
String get directionText {
|
|
switch (direction) {
|
|
case 0:
|
|
return '上行';
|
|
case 1:
|
|
return '下行';
|
|
default:
|
|
return '未知';
|
|
}
|
|
}
|
|
|
|
String get locoTypeText {
|
|
if (locoType.isEmpty) return '未知';
|
|
return locoType;
|
|
}
|
|
|
|
String get trainType {
|
|
final lbjClassValue = lbjClass.isEmpty ? "NA" : lbjClass;
|
|
return TrainTypeUtil.getTrainType(lbjClassValue, train) ?? '未知';
|
|
}
|
|
|
|
String? get locoInfo {
|
|
return LocoInfoUtil.getLocoInfoDisplay(locoType, train);
|
|
}
|
|
|
|
String get fullTrainNumber {
|
|
final lbjClassValue = lbjClass.trim();
|
|
final trainValue = train.trim();
|
|
|
|
if (trainValue == "<NUL>" || trainValue.contains("-----")) {
|
|
return "";
|
|
}
|
|
|
|
if (lbjClassValue.isEmpty || lbjClassValue == "NA") {
|
|
return trainValue;
|
|
} else {
|
|
return "$lbjClassValue$trainValue";
|
|
}
|
|
}
|
|
|
|
String get lbjClassText {
|
|
if (lbjClass.isEmpty) return '未知';
|
|
return lbjClass;
|
|
}
|
|
|
|
double get speedValue {
|
|
try {
|
|
return double.parse(speed.replaceAll(RegExp(r'[^\d.]'), ''));
|
|
} catch (e) {
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
String get speedUnit {
|
|
if (speed.contains('km/h')) return 'km/h';
|
|
if (speed.contains('m/s')) return 'm/s';
|
|
return '';
|
|
}
|
|
|
|
String get formattedTime {
|
|
return '${timestamp.hour.toString().padLeft(2, '0')}:${timestamp.minute.toString().padLeft(2, '0')}:${timestamp.second.toString().padLeft(2, '0')}';
|
|
}
|
|
|
|
String get formattedDate {
|
|
return '${timestamp.year}-${timestamp.month.toString().padLeft(2, '0')}-${timestamp.day.toString().padLeft(2, '0')}';
|
|
}
|
|
|
|
String get relativeTime {
|
|
final now = DateTime.now();
|
|
final difference = now.difference(timestamp);
|
|
|
|
if (difference.inMinutes < 1) {
|
|
return '刚刚';
|
|
} else if (difference.inHours < 1) {
|
|
return '${difference.inMinutes}分钟前';
|
|
} else if (difference.inDays < 1) {
|
|
return '${difference.inHours}小时前';
|
|
} else if (difference.inDays < 7) {
|
|
return '${difference.inDays}天前';
|
|
} else {
|
|
return formattedDate;
|
|
}
|
|
}
|
|
|
|
String get rssiDescription {
|
|
if (rssi > -50) return '强';
|
|
if (rssi > -70) return '中';
|
|
if (rssi > -90) return '弱';
|
|
return '无信号';
|
|
}
|
|
|
|
Color get rssiColor {
|
|
if (rssi > -50) return Colors.green;
|
|
if (rssi > -70) return Colors.orange;
|
|
if (rssi > -90) return Colors.red;
|
|
return Colors.grey;
|
|
}
|
|
|
|
Map<String, dynamic> toMap() {
|
|
return {
|
|
'uniqueId': uniqueId,
|
|
'timestamp': timestamp.millisecondsSinceEpoch,
|
|
'receivedTimestamp': receivedTimestamp.millisecondsSinceEpoch,
|
|
'train': train,
|
|
'direction': direction,
|
|
'speed': speed,
|
|
'position': position,
|
|
'time': time,
|
|
'loco': loco,
|
|
'locoType': locoType,
|
|
'lbjClass': lbjClass,
|
|
'route': route,
|
|
'positionInfo': positionInfo,
|
|
'rssi': rssi,
|
|
};
|
|
}
|
|
|
|
Map<String, double> getCoordinates() {
|
|
final parts = position.split(',');
|
|
if (parts.length >= 2) {
|
|
try {
|
|
final lat = double.parse(parts[0].trim());
|
|
final lng = double.parse(parts[1].trim());
|
|
return {'lat': lat, 'lng': lng};
|
|
} catch (e) {
|
|
return {'lat': 0.0, 'lng': 0.0};
|
|
}
|
|
}
|
|
return {'lat': 0.0, 'lng': 0.0};
|
|
}
|
|
|
|
TrainRecord copyWith({
|
|
String? uniqueId,
|
|
DateTime? timestamp,
|
|
DateTime? receivedTimestamp,
|
|
String? train,
|
|
int? direction,
|
|
String? speed,
|
|
String? position,
|
|
String? time,
|
|
String? loco,
|
|
String? locoType,
|
|
String? lbjClass,
|
|
String? route,
|
|
String? positionInfo,
|
|
double? rssi,
|
|
}) {
|
|
return TrainRecord(
|
|
uniqueId: uniqueId ?? this.uniqueId,
|
|
timestamp: timestamp ?? this.timestamp,
|
|
receivedTimestamp: receivedTimestamp ?? this.receivedTimestamp,
|
|
train: train ?? this.train,
|
|
direction: direction ?? this.direction,
|
|
speed: speed ?? this.speed,
|
|
position: position ?? this.position,
|
|
time: time ?? this.time,
|
|
loco: loco ?? this.loco,
|
|
locoType: locoType ?? this.locoType,
|
|
lbjClass: lbjClass ?? this.lbjClass,
|
|
route: route ?? this.route,
|
|
positionInfo: positionInfo ?? this.positionInfo,
|
|
rssi: rssi ?? this.rssi,
|
|
);
|
|
}
|
|
|
|
@override
|
|
String toString() {
|
|
return 'TrainRecord(uniqueId: $uniqueId, train: $train, direction: $direction, speed: $speed, position: $position)';
|
|
}
|
|
|
|
@override
|
|
bool operator ==(Object other) {
|
|
if (identical(this, other)) return true;
|
|
return other is TrainRecord && other.uniqueId == uniqueId;
|
|
}
|
|
|
|
@override
|
|
int get hashCode => uniqueId.hashCode;
|
|
}
|