132 lines
3.5 KiB
Dart
132 lines
3.5 KiB
Dart
import 'package:aves/model/activity/activity_entry.dart';
|
|
import 'package:aves/model/activity/activity_track.dart';
|
|
import 'package:latlong2/latlong.dart' show Distance, LengthUnit;
|
|
|
|
class ActivityFormatters {
|
|
static final Distance _distance = Distance();
|
|
|
|
static String distance(double? meters) {
|
|
if (meters == null) return '-';
|
|
return '${(meters / 1000).toStringAsFixed(2)} km';
|
|
}
|
|
|
|
static String distanceDelta(double? computed, double? file) {
|
|
if (computed == null || file == null) return '-';
|
|
|
|
final delta = computed - file;
|
|
final sign = delta >= 0 ? '+' : '';
|
|
|
|
return '$sign${(delta / 1000).toStringAsFixed(2)} km';
|
|
}
|
|
|
|
static String elevation(double? meters) {
|
|
if (meters == null) return '-';
|
|
return '${meters.round()} m';
|
|
}
|
|
|
|
static String entryElevation(double? meters) {
|
|
if (meters == null) return 'D+ -';
|
|
return 'D+ ${meters.round()} m';
|
|
}
|
|
|
|
static String elevationDelta(double? computed, double? file) {
|
|
if (computed == null || file == null) return '-';
|
|
|
|
final delta = computed - file;
|
|
final sign = delta >= 0 ? '+' : '';
|
|
|
|
return '$sign${delta.round()} m';
|
|
}
|
|
|
|
static String entryDate(ActivityEntry entry) {
|
|
final millis = entry.startTimeMillis;
|
|
if (millis == null) return 'Data -';
|
|
|
|
final date = DateTime.fromMillisecondsSinceEpoch(millis).toLocal();
|
|
|
|
final day = date.day.toString().padLeft(2, '0');
|
|
final month = date.month.toString().padLeft(2, '0');
|
|
final year = date.year.toString().padLeft(4, '0');
|
|
final hour = date.hour.toString().padLeft(2, '0');
|
|
final minute = date.minute.toString().padLeft(2, '0');
|
|
|
|
return '$day/$month/$year $hour:$minute';
|
|
}
|
|
|
|
static String entryDuration(int? millis) {
|
|
if (millis == null) return '-';
|
|
|
|
final duration = Duration(milliseconds: millis);
|
|
|
|
final hours = duration.inHours;
|
|
final minutes = duration.inMinutes.remainder(60);
|
|
final seconds = duration.inSeconds.remainder(60);
|
|
|
|
if (hours > 0) {
|
|
return '${hours}h ${minutes}m';
|
|
}
|
|
|
|
if (minutes > 0) {
|
|
return '${minutes}m ${seconds}s';
|
|
}
|
|
|
|
return '${seconds}s';
|
|
}
|
|
|
|
static double? computeDistanceFromTrack(ActivityTrack activity) {
|
|
final points = activity.validPoints;
|
|
if (points.length < 2) return null;
|
|
|
|
double total = 0;
|
|
|
|
for (int i = 1; i < points.length; i++) {
|
|
final segment = _distance.as(
|
|
LengthUnit.Meter,
|
|
points[i - 1],
|
|
points[i],
|
|
);
|
|
|
|
if (!segment.isFinite || segment <= 0) continue;
|
|
if (segment > 500) continue;
|
|
|
|
total += segment;
|
|
}
|
|
|
|
return total > 0 ? total : null;
|
|
}
|
|
|
|
static double? readDiagnosticDouble(String? diagnostics, String key) {
|
|
if (diagnostics == null || diagnostics.isEmpty) return null;
|
|
|
|
for (final line in diagnostics.split('\n')) {
|
|
final index = line.indexOf('=');
|
|
if (index <= 0) continue;
|
|
|
|
final currentKey = line.substring(0, index).trim();
|
|
if (currentKey != key) continue;
|
|
|
|
final value = line.substring(index + 1).trim();
|
|
if (value == 'null' || value.isEmpty) return null;
|
|
|
|
return double.tryParse(value.replaceAll(',', '.'));
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
static String normalizePath(String path) {
|
|
final trimmed = path.trim();
|
|
return trimmed.endsWith('/') ? trimmed : '$trimmed/';
|
|
}
|
|
|
|
static bool isExpectedActivityRoot(
|
|
String? selectedPath,
|
|
String expectedPath,
|
|
) {
|
|
if (selectedPath == null || selectedPath.trim().isEmpty) {
|
|
return false;
|
|
}
|
|
|
|
return normalizePath(selectedPath) == normalizePath(expectedPath);
|
|
}
|
|
}
|