package org.opensatnav.services;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collection;
import org.opensatnav.TripStatisticsController;
import android.location.Location;
import android.text.format.Formatter;
public class TripStatistics {
public static final int METRIC = 0;
public static final int ENGLISH = 1;
private int pointsReceivedCount;
private long tripStartTimeMilisec;
private long lastPointTimeMilisec;
private float tripDistanceMeters;
// Previous Point
private Location lastLocatPoint = null;
private Collection<TripStatisticsListener> listeners = null;
private DecimalFormat formatter;
public TripStatistics() {
initializeStats();
}
public TripStatistics(TripStatisticsListener firstListener) {
this();
// Tried to do this from where the service is started, but
// onCreate() doesn't run until after some time later.
addTripStatsListener(firstListener);
}
private void initializeStats() {
pointsReceivedCount = 0;
tripStartTimeMilisec = -1;
lastPointTimeMilisec = -1;
tripDistanceMeters = 0;
formatter = new DecimalFormat();
}
public void addTripStatsListener(TripStatisticsListener listener) {
if( listeners == null ) {
listeners = new ArrayList<TripStatisticsListener>();
}
listeners.add(listener);
listener.tripStatisticsChanged(this);
}
public void removeTripStatsListener(TripStatisticsListener listener) {
if( listeners.contains(listener) ) {
listeners.remove(listener);
}
}
public void removeAllTripStatsListeners() {
listeners = null;
}
public void addNewLocationPoint(Location newLocatPoint) {
pointsReceivedCount++;
if( tripStartTimeMilisec == -1 ) {
tripStartTimeMilisec = newLocatPoint.getTime();
}
lastPointTimeMilisec = newLocatPoint.getTime();
if( lastLocatPoint != null ) {
tripDistanceMeters += newLocatPoint.distanceTo(lastLocatPoint);
}
lastLocatPoint = newLocatPoint;
if( pointsReceivedCount > 1 ) {
callAllListeners(); // Can't deliver with just one point.
}
}
private void callAllListeners() {
if( listeners != null ) {
for( TripStatisticsListener l : listeners) {
l.tripStatisticsChanged(this);
}
}
}
/** Returns the aver trip speed in m/s */
public float getAverageTripSpeed() {
if( pointsReceivedCount == 0 ) {
return 0f;
} else {
return getTripDistance() / (getTripTime() / 1000);
}
}
/** Return total trip time in milisec */
public long getTripTime() {
if( pointsReceivedCount == 0 ) {
return 0;
} else {
return lastPointTimeMilisec - tripStartTimeMilisec;
}
}
/** Returns total trip distance in meters */
public float getTripDistance() {
if( pointsReceivedCount == 0 ) {
return 0;
} else {
return tripDistanceMeters;
}
}
/* Note: the instantenous speed is newPoint.getSpeed() */
public float getInstantSpeed() {
if( pointsReceivedCount == 0 ) {
return 0;
} else {
return lastLocatPoint.getSpeed();
}
}
public void resetStatistics() {
initializeStats();
callAllListeners();
}
public String getAverageTripSpeedString(int unitSystem) {
return getSpeedString(getAverageTripSpeed(),unitSystem);
}
public String getInstantSpeedString(int unitSystem) {
return getSpeedString(getInstantSpeed(),unitSystem);
}
private String getSpeedString(float speed, int unitSystem) {
if( unitSystem == METRIC ) {
formatter.applyLocalizedPattern("###.##");
return formatter.format(speed * 3600f / 1000f) + " km/h";
} else {
return "not implemented"; // TODO do it
}
}
public String getTripTimeString(int unitSystem) {
int tripTimeSec = Math.round(getTripTime() / 1000f);
formatter.applyLocalizedPattern("#0");
int hr = tripTimeSec / 3600;
String hrStr = formatter.format(hr);
formatter.applyLocalizedPattern("00");
int min = (tripTimeSec - hr * 3600) / 60;
String minStr = formatter.format(min);
int sec = tripTimeSec % 60;
String secStr = formatter.format(sec);
return hrStr + ":" + minStr + ":" + secStr;
}
public String getTripDistanceString(int unitSystem) {
String dist = "";
if( unitSystem == METRIC ) {
int distMeters = Math.round(getTripDistance());
int km = distMeters / 1000;
int m = distMeters % 1000;
if( km > 0 ) {
dist = km + " km ";
}
dist += m + " m";
} else {
dist = "not implemented"; // TODO do it
}
return dist;
}
public static class TripStatisticsStrings {
public String averSpeed;
public String instSpeed;
public String tripDistance;
public String tripDuration;
}
}