Begin adding the work data visualizer
This commit is contained in:
parent
7e78ed323d
commit
5bc49b4cff
9 changed files with 294 additions and 13 deletions
136
lib/data.dart
136
lib/data.dart
|
@ -1,15 +1,14 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:math' as math;
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:libac_dart/utils/TimeUtils.dart';
|
||||
import 'package:libac_dart/nbt/Stream.dart';
|
||||
import 'package:timetrack/consts.dart';
|
||||
|
||||
class SessionData {
|
||||
static int StartTime = 0;
|
||||
|
||||
static get StartTimeAsDateTime =>
|
||||
DateTime.fromMillisecondsSinceEpoch(StartTime * 1000);
|
||||
static DateTime StartTime = DateTime(0);
|
||||
|
||||
static bool IsOnTheClock = false;
|
||||
|
||||
|
@ -19,12 +18,121 @@ class SessionData {
|
|||
static Trip? currentTrip;
|
||||
static List<Position> positions = [];
|
||||
static late StreamSubscription<Position> _listener;
|
||||
static Callbacks Calls = Callbacks();
|
||||
|
||||
/// This flag is usually set when data is loaded from a saved state. Or when accessed using the Web version of the app.
|
||||
static bool IsReadOnly = false;
|
||||
|
||||
static double GetTotalBasePay() {
|
||||
double total = 0;
|
||||
for (var trip in Trips) {
|
||||
total += trip.BasePay;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
static double GetTotalTips() {
|
||||
double total = 0;
|
||||
for (var trip in Trips) {
|
||||
for (var drop in trip.deliveries) {
|
||||
total += drop.TipAmount;
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
static double GetTotalPay() {
|
||||
return GetTotalBasePay() + GetTotalTips();
|
||||
}
|
||||
|
||||
static double GetTotalMiles() {
|
||||
double total = 0;
|
||||
total = _totalMilesTraveled(
|
||||
positions,
|
||||
minDistanceMeters: 5,
|
||||
maxDistanceMeters: 512,
|
||||
);
|
||||
return total;
|
||||
}
|
||||
|
||||
static String GetTotalMilesAsString() {
|
||||
double miles = GetTotalMiles();
|
||||
if (miles == 0) return "0.0";
|
||||
List<String> split = miles.toString().split(".");
|
||||
StringBuilder out = StringBuilder();
|
||||
|
||||
out.append(split[0]);
|
||||
out.append(".");
|
||||
out.append(split[1].substring(0, 4));
|
||||
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
//** Begin AI Generated code */
|
||||
/// Converts meters → miles.
|
||||
static const _metersPerMile = 1609.344;
|
||||
|
||||
/// Radius of the earth in meters (WGS‑84 mean radius).
|
||||
static const _earthRadiusM = 6371000.0;
|
||||
static double _haversineMeters(
|
||||
double lat1,
|
||||
double lon1,
|
||||
double lat2,
|
||||
double lon2,
|
||||
) {
|
||||
final dLat = _deg2rad(lat2 - lat1);
|
||||
final dLon = _deg2rad(lon2 - lon1);
|
||||
|
||||
final a =
|
||||
math.sin(dLat / 2) * math.sin(dLat / 2) +
|
||||
math.cos(_deg2rad(lat1)) *
|
||||
math.cos(_deg2rad(lat2)) *
|
||||
math.sin(dLon / 2) *
|
||||
math.sin(dLon / 2);
|
||||
|
||||
return _earthRadiusM * 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a));
|
||||
}
|
||||
|
||||
static double _deg2rad(double deg) => deg * math.pi / 180.0;
|
||||
|
||||
/// Returns total miles traveled after basic GPS‑noise cleanup.
|
||||
///
|
||||
/// * [minDistanceMeters] – drop segments shorter than this (jitter).
|
||||
/// * [maxDistanceMeters] – drop segments longer than this (impossible jump).
|
||||
static double _totalMilesTraveled(
|
||||
List<Position> positions, {
|
||||
double minDistanceMeters = 5,
|
||||
double? maxDistanceMeters,
|
||||
}) {
|
||||
if (positions.length < 2) return 0;
|
||||
|
||||
var meters = 0.0;
|
||||
|
||||
for (var i = 1; i < positions.length; i++) {
|
||||
final p1 = positions[i - 1];
|
||||
final p2 = positions[i];
|
||||
|
||||
final d = _haversineMeters(
|
||||
p1.latitude,
|
||||
p1.longitude,
|
||||
p2.latitude,
|
||||
p2.longitude,
|
||||
);
|
||||
|
||||
if (d < minDistanceMeters) continue; // too small → jitter
|
||||
if (maxDistanceMeters != null && d > maxDistanceMeters)
|
||||
continue; // glitch
|
||||
|
||||
meters += d;
|
||||
}
|
||||
return meters / _metersPerMile;
|
||||
}
|
||||
//** End AI Generated code */
|
||||
|
||||
static Future<void> Login() async {
|
||||
StartTime = TimeUtils.getUnixTimestamp();
|
||||
StartTime = DateTime.now();
|
||||
IsOnTheClock = true;
|
||||
|
||||
bool hasGPS;
|
||||
|
@ -60,6 +168,8 @@ class SessionData {
|
|||
return;
|
||||
}
|
||||
positions.add(pos);
|
||||
|
||||
SessionData.Calls.dispatch();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -226,3 +336,17 @@ class Trip {
|
|||
return trip;
|
||||
}
|
||||
}
|
||||
|
||||
class Callbacks {
|
||||
VoidCallback? HomeCallback;
|
||||
VoidCallback? MapCallback;
|
||||
VoidCallback? UpdateSettingsCallback;
|
||||
VoidCallback? WorkDataCallback;
|
||||
|
||||
void dispatch() {
|
||||
if (HomeCallback != null) HomeCallback!();
|
||||
if (MapCallback != null) MapCallback!();
|
||||
if (UpdateSettingsCallback != null) UpdateSettingsCallback!();
|
||||
if (WorkDataCallback != null) WorkDataCallback!();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue