Track, nyomkövetés hozzáadása
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user