/*******************************************************************************
* Gaggle is Copyright 2010 by Geeksville Industries LLC, a California limited liability corporation.
*
* Gaggle is distributed under a dual license. We've chosen this approach because within Gaggle we've used a number
* of components that Geeksville Industries LLC might reuse for commercial products. Gaggle can be distributed under
* either of the two licenses listed below.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Commercial Distribution License
* If you would like to distribute Gaggle (or portions thereof) under a license other than
* the "GNU General Public License, version 2", contact Geeksville Industries. Geeksville Industries reserves
* the right to release Gaggle source code under a commercial license of its choice.
*
* GNU Public License, version 2
* All other distribution of Gaggle must conform to the terms of the GNU Public License, version 2. The full
* text of this license is included in the Gaggle source, see assets/manual/gpl-2.0.txt.
******************************************************************************/
package com.geeksville.info;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
/**
* Convert units based on the user's preferences
*
* @author kevinh
*
*/
public class Units {
public static Units instance = new Units();
/**
* You must be careful to keep these enums in sync with the preferences
* arrays.xml
*
* @author kevinh
*
*/
public enum Speed {
/**
* mile per hour
*/
MilePerHr,
/**
* km per hour
*/
KmPerHr,
/**
* Meters per sec
*/
MPerSec,
/**
* Feet per minute
*/
FeetPerMin,
/**
* Knots per hr
*/
KtsPerHr,
}
private String getSpeedUnits(Speed s) {
final String[] speedUnits = { "mph", "kph", "m/s", "fpm",
"kts/hr" };
return speedUnits[s.ordinal()];
}
// FIXME - fill in missing #s
final double[] speedScaling = { 2.2369, 3.6, 1, 196.8503, 1.94384 };
public enum Distance {
Meters, Feet, KM, Miles, NauticalMiles
}
public enum CoordinateSet
{
DMS, DM, D
}
private String getDistanceUnits(Distance d) {
final String[] distanceUnits = { "m", "'", "km", "mi", "Nm" };
return distanceUnits[d.ordinal()];
}
final double[] distanceScaling = { 1.0, 3.2808399, 0.001, 0.000621371192,
0.000539956803 };
/**
* Convert mks units to whatever the selected units are
*
* @param d
* @param meters
* @return
*/
private <ScaleType extends Enum> double toSelectedUnits(ScaleType d,
double[] scaling, double meters) {
return meters * scaling[d.ordinal()];
}
/**
* Convert whatever the selected distance units to mks units
*
* @param d
* @param meters
* @return
*/
private <ScaleType extends Enum> double fromSelectedUnits(ScaleType d,
double[] scaling, double meters) {
return meters / scaling[d.ordinal()];
}
private Distance vdistance = Distance.Feet;
private Distance hdistance = Distance.KM;
private Speed hspeed = Speed.KmPerHr;
private Speed vspeed = Speed.MPerSec;
/**
* Pull our changes from the prefs (FIXME, is there something I can
* subscribe to for this?)
*
* @param c
*/
public void setFromPrefs(Context c) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
String defval = Distance.Feet.toString();
vdistance = Distance.valueOf(prefs.getString("altunits1_pref", defval));
hdistance = Distance.valueOf(prefs.getString("distunits1_pref",
Distance.Miles.toString()));
hspeed = Speed.valueOf(prefs.getString("speedunits1_pref",
Speed.MilePerHr.toString()));
vspeed = Speed.valueOf(prefs.getString("vspdunits1_pref",
Speed.FeetPerMin.toString()));
}
public String getAltitudeUnits() {
return getDistanceUnits(vdistance);
}
public String metersToAltitude(double alt) {
return String.format("%d", (int) toSelectedUnits(vdistance,
distanceScaling, alt));
}
/**
* Convert from the user's preferred altitude to meters
*
* @param alt
* @return
*/
public double altitudeToMeters(double alt) {
return fromSelectedUnits(vdistance, distanceScaling, alt);
}
public String getDistanceUnits() {
return getDistanceUnits(hdistance);
}
public String metersToDistance(double v) {
// FIXME - automatically switch to meters if less than some distance
v = toSelectedUnits(hdistance, distanceScaling, v);
// Only show fractions if we are close
return String.format(v < 10 ? "%.2f" : "%.0f", v);
}
public String getSpeedUnits() {
return getSpeedUnits(hspeed);
}
public String getVSpeedUnits() {
return getSpeedUnits(vspeed);
}
public String meterPerSecToSpeed(double v) {
return String.format("%.1f", toSelectedUnits(hspeed, speedScaling, v));
}
public String kilometerPerHourToSpeed(double v) {
double meters = v / speedScaling[Speed.KmPerHr.ordinal()];
return String.format("%.1f", toSelectedUnits(hspeed, speedScaling, meters));
}
public String meterPerSecToVSpeed(double v) {
return String.format("%.1f", toSelectedUnits(vspeed, speedScaling, v));
}
/**
* generate the user's preferred degrees, minutes, seconds string
*
* @param degs
* @return
*
* FIXME: Offer a few choices of how to format these strings. For
* now, deg & fractional min
*/
public String degreesToUserString(double degs, boolean isLatitude) {
// TODO Auto-generated method stub
return degreesToDegreeMinutesSeconds(degs, isLatitude);
}
/**
* Format as degrees, minutes, secs
*
* @param degIn
* @param isLatitude
* @return a string like 120deg
*/
private static String degreesToDegreeMinutesSeconds(double degIn, boolean isLatitude) {
boolean isPos = degIn >= 0;
char dirLetter = isLatitude ? (isPos ? 'N' : 'S') : (isPos ? 'E' : 'W');
degIn = Math.abs(degIn);
int degFloor = (int) degIn;
double minutes = 60 * (degIn - degFloor);
int minwhole = (int) minutes;
int seconds = (int) ((minutes - minwhole) * 60);
// 00b0 is unicode for the degree symbol
String s = String.format("%d\u00B0%02d'%02d\"%c", degFloor,
minwhole, seconds, dirLetter);
return s;
}
}