diff options
Diffstat (limited to 'src/org/traccar/reports/ReportUtils.java')
-rw-r--r-- | src/org/traccar/reports/ReportUtils.java | 189 |
1 files changed, 187 insertions, 2 deletions
diff --git a/src/org/traccar/reports/ReportUtils.java b/src/org/traccar/reports/ReportUtils.java index 84d3b3a77..ead50571a 100644 --- a/src/org/traccar/reports/ReportUtils.java +++ b/src/org/traccar/reports/ReportUtils.java @@ -1,6 +1,6 @@ /* - * Copyright 2016 Anton Tananaev (anton@traccar.org) - * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org) + * Copyright 2016 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,10 @@ import org.jxls.transform.poi.PoiTransformer; import org.jxls.util.TransformerFactory; import org.traccar.Context; import org.traccar.model.Position; +import org.traccar.reports.model.BaseReport; +import org.traccar.reports.model.StopReport; +import org.traccar.reports.model.TripReport; +import org.traccar.reports.model.TripsConfig; import java.io.IOException; import java.io.InputStream; @@ -123,4 +127,185 @@ public final class ReportUtils { transformer.write(); } + public static TripsConfig initTripsConfig() { + return new TripsConfig( + Context.getConfig().getLong("report.trip.minimalTripDuration", 300) * 1000, + Context.getConfig().getLong("report.trip.minimalTripDistance", 500), + Context.getConfig().getLong("report.trip.minimalParkingDuration", 300) * 1000, + Context.getConfig().getBoolean("report.trip.greedyParking")); + } + + private static TripReport calculateTrip( + ArrayList<Position> positions, int startIndex, int endIndex, boolean ignoreOdometer) { + Position startTrip = positions.get(startIndex); + Position endTrip = positions.get(endIndex); + + double speedMax = 0.0; + double speedSum = 0.0; + for (int i = startIndex; i <= endIndex; i++) { + double speed = positions.get(i).getSpeed(); + speedSum += speed; + if (speed > speedMax) { + speedMax = speed; + } + } + + TripReport trip = new TripReport(); + + long tripDuration = endTrip.getFixTime().getTime() - startTrip.getFixTime().getTime(); + long deviceId = startTrip.getDeviceId(); + trip.setDeviceId(deviceId); + trip.setDeviceName(Context.getIdentityManager().getDeviceById(deviceId).getName()); + + trip.setStartPositionId(startTrip.getId()); + trip.setStartLat(startTrip.getLatitude()); + trip.setStartLon(startTrip.getLongitude()); + trip.setStartTime(startTrip.getFixTime()); + trip.setStartAddress(startTrip.getAddress()); + + trip.setEndPositionId(endTrip.getId()); + trip.setEndLat(endTrip.getLatitude()); + trip.setEndLon(endTrip.getLongitude()); + trip.setEndTime(endTrip.getFixTime()); + trip.setEndAddress(endTrip.getAddress()); + + trip.setDistance(calculateDistance(startTrip, endTrip, !ignoreOdometer)); + trip.setDuration(tripDuration); + trip.setAverageSpeed(speedSum / (endIndex - startIndex)); + trip.setMaxSpeed(speedMax); + trip.setSpentFuel(calculateFuel(startTrip, endTrip)); + + return trip; + } + + private static StopReport calculateStop(ArrayList<Position> positions, int startIndex, int endIndex) { + Position startStop = positions.get(startIndex); + Position endStop = positions.get(endIndex); + + StopReport stop = new StopReport(); + + long deviceId = startStop.getDeviceId(); + stop.setDeviceId(deviceId); + stop.setDeviceName(Context.getIdentityManager().getDeviceById(deviceId).getName()); + + stop.setPositionId(startStop.getId()); + stop.setLatitude(startStop.getLatitude()); + stop.setLongitude(startStop.getLongitude()); + stop.setStartTime(startStop.getFixTime()); + stop.setAddress(startStop.getAddress()); + stop.setEndTime(endStop.getFixTime()); + + long stopDuration = endStop.getFixTime().getTime() - startStop.getFixTime().getTime(); + stop.setDuration(stopDuration); + stop.setSpentFuel(calculateFuel(startStop, endStop)); + + long engineHours = 0; + for (int i = startIndex + 1; i <= endIndex; i++) { + if (positions.get(i).getBoolean(Position.KEY_IGNITION) + && positions.get(i - 1).getBoolean(Position.KEY_IGNITION)) { + engineHours += positions.get(i).getFixTime().getTime() - positions.get(i - 1).getFixTime().getTime(); + } + } + stop.setEngineHours(engineHours); + + return stop; + + } + + public static Collection<BaseReport> detectTripsAndStops(TripsConfig tripsConfig, boolean ignoreOdometer, + double speedThreshold, Collection<Position> positionCollection, boolean trips) { + + Collection<BaseReport> result = new ArrayList<>(); + + ArrayList<Position> positions = new ArrayList<>(positionCollection); + if (positions != null && !positions.isEmpty()) { + int previousStartParkingIndex = 0; + int startParkingIndex = -1; + int previousEndParkingIndex = 0; + int endParkingIndex = 0; + + boolean isMoving = false; + boolean isLast = false; + boolean skipped = false; + boolean tripFiltered = false; + + for (int i = 0; i < positions.size(); i++) { + isMoving = positions.get(i).getSpeed() > speedThreshold; + isLast = i == positions.size() - 1; + + if ((isMoving || isLast) && startParkingIndex != -1) { + if (!skipped || previousEndParkingIndex == 0) { + previousEndParkingIndex = endParkingIndex; + } + endParkingIndex = i; + } + if (!isMoving && startParkingIndex == -1) { + if (tripsConfig.getGreedyParking()) { + long tripDuration = positions.get(i).getFixTime().getTime() + - positions.get(endParkingIndex).getFixTime().getTime(); + double tripDistance = ReportUtils.calculateDistance(positions.get(endParkingIndex), + positions.get(i), false); + tripFiltered = tripDuration < tripsConfig.getMinimalTripDuration() + && tripDistance < tripsConfig.getMinimalTripDistance(); + if (tripFiltered) { + startParkingIndex = previousStartParkingIndex; + endParkingIndex = previousEndParkingIndex; + tripFiltered = false; + } else { + previousStartParkingIndex = i; + startParkingIndex = i; + } + } else { + long tripDuration = positions.get(i).getFixTime().getTime() + - positions.get(previousEndParkingIndex).getFixTime().getTime(); + double tripDistance = ReportUtils.calculateDistance(positions.get(previousEndParkingIndex), + positions.get(i), false); + tripFiltered = tripDuration < tripsConfig.getMinimalTripDuration() + && tripDistance < tripsConfig.getMinimalTripDistance(); + startParkingIndex = i; + } + } + if (startParkingIndex != -1 && (endParkingIndex > startParkingIndex || isLast)) { + long parkingDuration = positions.get(endParkingIndex).getFixTime().getTime() + - positions.get(startParkingIndex).getFixTime().getTime(); + if ((parkingDuration >= tripsConfig.getMinimalParkingDuration() || isLast) + && previousEndParkingIndex < startParkingIndex) { + if (!tripFiltered) { + if (trips) { + result.add(calculateTrip( + positions, previousEndParkingIndex, startParkingIndex, ignoreOdometer)); + } else { + if (result.isEmpty() && previousEndParkingIndex > previousStartParkingIndex) { + long previousParkingDuration = positions.get(previousEndParkingIndex) + .getFixTime().getTime() - positions.get(previousStartParkingIndex) + .getFixTime().getTime(); + if (previousParkingDuration >= tripsConfig.getMinimalParkingDuration()) { + result.add(calculateStop(positions, previousStartParkingIndex, + previousEndParkingIndex)); + } + } + result.add(calculateStop(positions, startParkingIndex, endParkingIndex)); + } + } + previousEndParkingIndex = endParkingIndex; + skipped = false; + } else { + skipped = true; + } + startParkingIndex = -1; + } + } + if (result.isEmpty() && !trips) { + int end = isMoving && !tripsConfig.getGreedyParking() + ? Math.max(endParkingIndex, previousEndParkingIndex) : positions.size() - 1; + long parkingDuration = positions.get(end).getFixTime().getTime() + - positions.get(previousStartParkingIndex).getFixTime().getTime(); + if (parkingDuration >= tripsConfig.getMinimalParkingDuration()) { + result.add(calculateStop(positions, previousStartParkingIndex, end)); + } + } + } + + return result; + } } |