MobilApp/lib/models/track.dart

161 lines
5.1 KiB
Dart
Raw Normal View History

2026-05-10 02:31:27 +02:00
import 'dart:math' as math;
// ─── TrackPoint ───────────────────────────────────────────────────────────────
class TrackPoint {
final int? id;
final int trackId;
final double latitude;
final double longitude;
final double? altitude;
final double? accuracy;
final double? speed; // m/s
final double? heading;
final DateTime timestamp;
const TrackPoint({
this.id,
required this.trackId,
required this.latitude,
required this.longitude,
this.altitude,
this.accuracy,
this.speed,
this.heading,
required this.timestamp,
});
Map<String, dynamic> toMap() => {
if (id != null) 'id': id,
'track_id': trackId,
'latitude': latitude,
'longitude': longitude,
'altitude': altitude,
'accuracy': accuracy,
'speed': speed,
'heading': heading,
'timestamp': timestamp.toIso8601String(),
};
factory TrackPoint.fromMap(Map<String, dynamic> m) => TrackPoint(
id: m['id'] as int?,
trackId: m['track_id'] as int,
latitude: m['latitude'] as double,
longitude: m['longitude'] as double,
altitude: m['altitude'] as double?,
accuracy: m['accuracy'] as double?,
speed: m['speed'] as double?,
heading: m['heading'] as double?,
timestamp: DateTime.parse(m['timestamp'] as String),
);
}
// ─── Track státusz ────────────────────────────────────────────────────────────
enum TrackStatus { recording, paused, finished }
// ─── Track ───────────────────────────────────────────────────────────────────
class Track {
final int? id;
final String name;
final DateTime startTime;
final DateTime? endTime;
final TrackStatus status;
final String source; // pl. "Telefon GPS", "BLE GNSS"
// Statisztikák — ezeket a DB is tárolja a gyors listázáshoz
final double distanceMeters;
final int pointCount;
const Track({
this.id,
required this.name,
required this.startTime,
this.endTime,
this.status = TrackStatus.recording,
this.source = 'Telefon GPS',
this.distanceMeters = 0,
this.pointCount = 0,
});
Track copyWith({
int? id,
String? name,
DateTime? startTime,
DateTime? endTime,
TrackStatus? status,
String? source,
double? distanceMeters,
int? pointCount,
}) =>
Track(
id: id ?? this.id,
name: name ?? this.name,
startTime: startTime ?? this.startTime,
endTime: endTime ?? this.endTime,
status: status ?? this.status,
source: source ?? this.source,
distanceMeters: distanceMeters ?? this.distanceMeters,
pointCount: pointCount ?? this.pointCount,
);
/// Formázott időtartam (óó:pp:mm)
String get durationFormatted {
final end = endTime ?? DateTime.now();
final d = end.difference(startTime);
final h = d.inHours.toString().padLeft(2, '0');
final m = (d.inMinutes % 60).toString().padLeft(2, '0');
final s = (d.inSeconds % 60).toString().padLeft(2, '0');
return '$h:$m:$s';
}
/// Formázott távolság
String get distanceFormatted {
if (distanceMeters < 1000) {
return '${distanceMeters.toStringAsFixed(0)} m';
}
return '${(distanceMeters / 1000).toStringAsFixed(2)} km';
}
Map<String, dynamic> toMap() => {
if (id != null) 'id': id,
'name': name,
'start_time': startTime.toIso8601String(),
'end_time': endTime?.toIso8601String(),
'status': status.name,
'source': source,
'distance_meters': distanceMeters,
'point_count': pointCount,
};
factory Track.fromMap(Map<String, dynamic> m) => Track(
id: m['id'] as int?,
name: m['name'] as String,
startTime: DateTime.parse(m['start_time'] as String),
endTime: m['end_time'] != null
? DateTime.parse(m['end_time'] as String)
: null,
status: TrackStatus.values.byName(m['status'] as String),
source: m['source'] as String? ?? 'Telefon GPS',
distanceMeters: (m['distance_meters'] as num?)?.toDouble() ?? 0,
pointCount: m['point_count'] as int? ?? 0,
);
}
// ─── Segédszámítás: Haversine távolság ───────────────────────────────────────
double haversineMeters(double lat1, double lon1, double lat2, double lon2) {
const r = 6371000.0;
final dLat = _toRad(lat2 - lat1);
final dLon = _toRad(lon2 - lon1);
final a = math.sin(dLat / 2) * math.sin(dLat / 2) +
math.cos(_toRad(lat1)) *
math.cos(_toRad(lat2)) *
math.sin(dLon / 2) *
math.sin(dLon / 2);
return r * 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a));
}
double _toRad(double deg) => deg * math.pi / 180;