From 60f4d69592c440ab7bb67a04f4c07fc7279d2c20 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 May 2016 22:46:58 -0700 Subject: [PATCH] altoslib: Switch distance from m/ft to km/miles for large values This adds lots of infrastructure to deal with making the unit used depend on the value itself, and then uses it only for distances. Signed-off-by: Keith Packard --- .../AltosDroid/PreloadMapActivity.java | 2 +- altoslib/AltosDistance.java | 56 +++++- altoslib/AltosPyro.java | 2 +- altoslib/AltosUnits.java | 178 +++++++++++++----- altoslib/AltosUnitsRange.java | 46 +++++ altoslib/Makefile.am | 1 + altosui/AltosConfigPyroUI.java | 2 +- altosui/AltosConfigUI.java | 4 +- altosui/AltosPad.java | 52 +++-- altosuilib/AltosUIAxis.java | 2 +- altosuilib/AltosUIMapPreloadNew.java | 2 +- altosuilib/AltosUISeries.java | 4 +- 12 files changed, 269 insertions(+), 82 deletions(-) create mode 100644 altoslib/AltosUnitsRange.java diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java index 13a44e1f..0bf3aa10 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java @@ -234,7 +234,7 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe private double radius() { double r = value_distance(radius); if (AltosPreferences.imperial_units()) - r = AltosConvert.distance.inverse(r); + r = AltosConvert.miles_to_meters(r); else r = r * 1000; return r; diff --git a/altoslib/AltosDistance.java b/altoslib/AltosDistance.java index b68a4525..1ec39f8d 100644 --- a/altoslib/AltosDistance.java +++ b/altoslib/AltosDistance.java @@ -54,4 +54,58 @@ public class AltosDistance extends AltosUnits { return 1; return 0; } -} \ No newline at end of file + + public AltosDistance() { + range_metric = new AltosUnitsRange[2]; + + range_metric[0] = new AltosUnitsRange(0, "m", "meters") { + double value(double v) { + return v; + } + int show_fraction(int width) { + return width / 9; + } + int say_fraction() { + return 0; + } + }; + range_metric[1] = new AltosUnitsRange(2000, "km", "kilometers") { + double value(double v) { + return v / 1000; + } + int show_fraction(int width) { + return width / 5; + } + int say_fraction() { + return 1; + } + }; + + range_imperial = new AltosUnitsRange[2]; + + range_imperial[0] = new AltosUnitsRange(0, "ft", "feet") { + double value(double v) { + return AltosConvert.meters_to_feet(v); + } + int show_fraction(int width) { + return width / 9; + } + int say_fraction() { + return 0; + } + }; + + range_imperial[1] = new AltosUnitsRange(AltosConvert.feet_to_meters(5280), + "mi", "miles") { + double value(double v) { + return AltosConvert.meters_to_miles(v); + } + int show_fraction(int width) { + return width / 5; + } + int say_fraction() { + return 1; + } + }; + } +} diff --git a/altoslib/AltosPyro.java b/altoslib/AltosPyro.java index 28e65bc2..3afd03e0 100644 --- a/altoslib/AltosPyro.java +++ b/altoslib/AltosPyro.java @@ -138,7 +138,7 @@ public class AltosPyro { units = pyro_to_units.get(flag); if (units == null) return name; - return String.format ("%s (%s)", name, units.show_units()); + return String.format ("%s (%s)", name, units.parse_units()); } public static AltosUnits pyro_to_units(int flag) { diff --git a/altoslib/AltosUnits.java b/altoslib/AltosUnits.java index 13b9dbe6..bc53d4a0 100644 --- a/altoslib/AltosUnits.java +++ b/altoslib/AltosUnits.java @@ -21,6 +21,21 @@ import java.text.*; public abstract class AltosUnits { + AltosUnitsRange[] range_metric, range_imperial; + + private AltosUnitsRange range(double v, boolean imperial_units) { + AltosUnitsRange[] ranges = imperial_units ? range_imperial : range_metric; + + for (int i = ranges.length - 1; i > 0; i--) + if (v >= ranges[i].lower_limit) + return ranges[i]; + return ranges[0]; + } + + private AltosUnitsRange first_range(boolean imperial_units) { + return imperial_units ? range_imperial[0] : range_metric[0]; + } + public abstract double value(double v, boolean imperial_units); public abstract double inverse(double v, boolean imperial_units); @@ -31,89 +46,168 @@ public abstract class AltosUnits { public abstract int show_fraction(int width, boolean imperial_units); - public double parse_locale(String s, boolean imperial_units) throws ParseException { - double v = AltosParse.parse_double_locale(s); - return inverse(v, imperial_units); + private double value(double v) { + return value(v, AltosConvert.imperial_units); } - public double parse_net(String s, boolean imperial_units) throws ParseException { - double v = AltosParse.parse_double_net(s); - return inverse(v, imperial_units); + private double inverse(double v) { + return inverse(v, AltosConvert.imperial_units); } - public double parse_locale(String s) throws ParseException { - return parse_locale(s, AltosConvert.imperial_units); + private String show_units() { + return show_units(AltosConvert.imperial_units); } - public double parse_net(String s) throws ParseException { - return parse_net(s, AltosConvert.imperial_units); + private String say_units() { + return say_units(AltosConvert.imperial_units); } - public double value(double v) { - return value(v, AltosConvert.imperial_units); + private int show_fraction(int width) { + return show_fraction(width, AltosConvert.imperial_units); } - public double inverse(double v) { - return inverse(v, AltosConvert.imperial_units); + private int say_fraction(boolean imperial_units) { + return 0; } - public String show_units() { - return show_units(AltosConvert.imperial_units); + private String show_format(AltosUnitsRange range, int width) { + return String.format("%%%d.%df %s", width, range.show_fraction(width), range.show_units); } - public String say_units() { - return say_units(AltosConvert.imperial_units); + private String say_format(AltosUnitsRange range) { + return String.format("%%1.%df", range.say_fraction()); } - public int show_fraction(int width) { - return show_fraction(width, AltosConvert.imperial_units); + private String say_units_format(AltosUnitsRange range) { + return String.format("%%1.%df %s", range.say_fraction(), range.say_units); } - int say_fraction(boolean imperial_units) { - return 0; + public String show(int width, double v, boolean imperial_units) { + AltosUnitsRange range = range(v, imperial_units); + + return String.format(show_format(range, width), range.value(v)); + } + + public String say(double v, boolean imperial_units) { + AltosUnitsRange range = range(v, imperial_units); + + return String.format(say_format(range), range.value(v)); + } + + public String say_units(double v, boolean imperial_units) { + AltosUnitsRange range = range(v, imperial_units); + + return String.format(say_units_format(range), range.value(v)); + } + + public String show(int width, double v) { + return show(width, v, AltosConvert.imperial_units); + } + + public String say(double v) { + return say(v, AltosConvert.imperial_units); + } + + public String say_units(double v) { + return say_units(v, AltosConvert.imperial_units); + } + + /* Parsing functions. Use the first range of the type */ + public String parse_units(boolean imperial_units) { + return first_range(imperial_units).show_units; + } + + public String parse_units() { + return parse_units(AltosConvert.imperial_units); + } + + public double parse_value(double v, boolean imperial_units) { + return first_range(imperial_units).value(v); + } + + public double parse_value(double v) { + return parse_value(v, AltosConvert.imperial_units); } - private String show_format(int width, boolean imperial_units) { - return String.format("%%%d.%df %s", width, show_fraction(width, imperial_units), show_units(imperial_units)); + /* Graphing functions. Use the first range of the type */ + public String graph_units(boolean imperial_units) { + return first_range(imperial_units).show_units; } - private String say_format(boolean imperial_units) { - return String.format("%%1.%df", say_fraction(imperial_units)); + public String graph_units() { + return graph_units(AltosConvert.imperial_units); } - private String say_units_format(boolean imperial_units) { - return String.format("%%1.%df %s", say_fraction(imperial_units), say_units(imperial_units)); + public double graph_value(double v, boolean imperial_units) { + return first_range(imperial_units).value(v); + } + + public double graph_value(double v) { + return graph_value(v, AltosConvert.imperial_units); + } + + private String graph_format(AltosUnitsRange range, int width) { + return String.format(String.format("%%%d.%df", width, range.show_fraction(width)), 0.0); } public String graph_format(int width, boolean imperial_units) { - return String.format(String.format("%%%d.%df", width, show_fraction(width, imperial_units)), 0.0); + return graph_format(first_range(imperial_units), width); } public String graph_format(int width) { return graph_format(width, AltosConvert.imperial_units); } - public String show(int width, double v, boolean imperial_units) { - return String.format(show_format(width, imperial_units), value(v, imperial_units)); + /* Parsing functions. */ + public double parse_locale(String s, boolean imperial_units) throws ParseException { + double v = AltosParse.parse_double_locale(s); + return inverse(v, imperial_units); } - public String show(int width, double v) { - return show(width, v, AltosConvert.imperial_units); + public double parse_net(String s, boolean imperial_units) throws ParseException { + double v = AltosParse.parse_double_net(s); + return inverse(v, imperial_units); } - public String say(double v, boolean imperial_units) { - return String.format(say_format(imperial_units), value(v, imperial_units)); + public double parse_locale(String s) throws ParseException { + return parse_locale(s, AltosConvert.imperial_units); } - public String say(double v) { - return say(v, AltosConvert.imperial_units); + public double parse_net(String s) throws ParseException { + return parse_net(s, AltosConvert.imperial_units); } - public String say_units(double v, boolean imperial_units) { - return String.format(say_units_format(imperial_units), value(v, imperial_units)); - } + public AltosUnits() { + range_metric = new AltosUnitsRange[1]; - public String say_units(double v) { - return say_units(v, AltosConvert.imperial_units); + range_metric[0] = new AltosUnitsRange(this, false) { + double value(double v) { + return units.value(v, false); + } + + int show_fraction(int width) { + return units.show_fraction(width, false); + } + + int say_fraction() { + return units.say_fraction(false); + } + }; + + range_imperial = new AltosUnitsRange[1]; + + range_imperial[0] = new AltosUnitsRange(this, true) { + double value(double v) { + return units.value(v, true); + } + + int show_fraction(int width) { + return units.show_fraction(width, true); + } + + int say_fraction() { + return units.say_fraction(true); + } + }; } } diff --git a/altoslib/AltosUnitsRange.java b/altoslib/AltosUnitsRange.java new file mode 100644 index 00000000..9239481a --- /dev/null +++ b/altoslib/AltosUnitsRange.java @@ -0,0 +1,46 @@ +/* + * Copyright © 2016 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_10; + +import java.text.*; + +public abstract class AltosUnitsRange { + + AltosUnits units; + + double lower_limit; + String show_units; + String say_units; + + abstract double value(double v); + abstract int show_fraction(int width); + abstract int say_fraction(); + + AltosUnitsRange(AltosUnits units, boolean imperial_units) { + this.units = units; + this.show_units = units.show_units(imperial_units); + this.say_units = units.say_units(imperial_units); + } + + AltosUnitsRange(double lower_limit, String show_units, String say_units) { + this.units = null; + this.lower_limit = lower_limit; + this.show_units = show_units; + this.say_units = say_units; + } +} diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index dc9da8fd..f3219839 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -118,6 +118,7 @@ altoslib_JAVA = \ AltosIMU.java \ AltosMag.java \ AltosUnits.java \ + AltosUnitsRange.java \ AltosDistance.java \ AltosHeight.java \ AltosSpeed.java \ diff --git a/altosui/AltosConfigPyroUI.java b/altosui/AltosConfigPyroUI.java index e0915a17..125866c6 100644 --- a/altosui/AltosConfigPyroUI.java +++ b/altosui/AltosConfigPyroUI.java @@ -105,7 +105,7 @@ public class AltosConfigPyroUI double unit_value = new_value; AltosUnits units = AltosPyro.pyro_to_units(flag); if (units != null) - unit_value = units.value(new_value); + unit_value = units.parse_value(new_value); String format; if (scale >= 100) format = "%6.2f"; diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index 24167df3..09123f4f 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -976,7 +976,7 @@ public class AltosConfigUI } String get_main_deploy_label() { - return String.format("Main Deploy Altitude(%s):", AltosConvert.height.show_units()); + return String.format("Main Deploy Altitude(%s):", AltosConvert.height.parse_units()); } String[] main_deploy_values() { @@ -1243,7 +1243,7 @@ public class AltosConfigUI } String get_tracker_motion_label() { - return String.format("Logging Trigger Motion (%s):", AltosConvert.height.show_units()); + return String.format("Logging Trigger Motion (%s):", AltosConvert.height.parse_units()); } void set_tracker_tool_tip() { diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index 4f55636d..9a8c8087 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -101,7 +101,11 @@ public class AltosPad extends AltosUIFlightTab { class ReceiverBattery extends AltosUIVoltageIndicator { - public double voltage(AltosState state) { return AltosLib.MISSING; } + double last_voltage = AltosLib.MISSING; + + public double voltage(AltosState state) { + return last_voltage; + } public double good() { return AltosLib.ao_battery_good; } @@ -111,8 +115,10 @@ public class AltosPad extends AltosUIFlightTab { public double value(AltosState state, AltosListenerState listener_state, int i) { if (listener_state == null) - return AltosLib.MISSING; - return listener_state.battery; + last_voltage = AltosLib.MISSING; + else + last_voltage = listener_state.battery; + return last_voltage; } public ReceiverBattery (AltosUIFlightTab container, int y) { @@ -205,40 +211,26 @@ public class AltosPad extends AltosUIFlightTab { } } - class PadAlt extends AltosUIIndicator { + class PadAlt extends AltosUIUnitsIndicator { - double last_alt = AltosLib.MISSING - 1; + public double value(AltosState state, int i) { + if (report_pad(state)) + return state.pad_alt; + else + return state.gps.alt; + } public void show (AltosState state, AltosListenerState listener_state) { - double alt = AltosLib.MISSING; - String label = null; + String label = "Altitude"; - if (state != null) { - if (report_pad(state)) { - alt = state.pad_alt; - label = "Pad Altitude"; - } else { - alt = state.gps.alt; - label = "Altitude"; - } - } - if (alt != last_alt) { - if (alt != AltosLib.MISSING) { - show(AltosConvert.height.show(5, alt)); - set_label(label); - } else - hide(); - last_alt = alt; - } - } - - public void reset() { - super.reset(); - last_alt = AltosLib.MISSING - 1; + if (state != null && report_pad(state)) + label = "Pad Altitude"; + set_label(label); + super.show(state, listener_state); } public PadAlt (AltosUIFlightTab container, int y) { - super (container, y, "Pad Altitude", 1, false, 2); + super (container, y, AltosConvert.height, "Pad Altitude", 1, false, 2); } } public String getName() { return "Pad"; } diff --git a/altosuilib/AltosUIAxis.java b/altosuilib/AltosUIAxis.java index e307874a..24ea23d3 100644 --- a/altosuilib/AltosUIAxis.java +++ b/altosuilib/AltosUIAxis.java @@ -48,7 +48,7 @@ public class AltosUIAxis extends NumberAxis { public final static int axis_default = axis_include_zero; public void set_units() { - String u = units.show_units(); + String u = units.parse_units(); if (u != null) setLabel(String.format("%s (%s)", label, u)); else diff --git a/altosuilib/AltosUIMapPreloadNew.java b/altosuilib/AltosUIMapPreloadNew.java index 3269bbdd..cce07ab4 100644 --- a/altosuilib/AltosUIMapPreloadNew.java +++ b/altosuilib/AltosUIMapPreloadNew.java @@ -231,7 +231,7 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener Double r = (Double) radius.getSelectedItem(); if (AltosPreferences.imperial_units()) - r = AltosConvert.distance.inverse(r); + r = AltosConvert.miles_to_meters(r); else r = r * 1000; loading = true; diff --git a/altosuilib/AltosUISeries.java b/altosuilib/AltosUISeries.java index b16f046b..c9401be0 100644 --- a/altosuilib/AltosUISeries.java +++ b/altosuilib/AltosUISeries.java @@ -69,7 +69,7 @@ public class AltosUISeries extends XYSeries implements AltosUIGrapher { String example = units.graph_format(7); ttg = new StandardXYToolTipGenerator(String.format("{1}s: {2}%s ({0})", - units.show_units()), + units.graph_units()), new java.text.DecimalFormat(time_example), new java.text.DecimalFormat(example)); renderer.setBaseToolTipGenerator(ttg); @@ -85,7 +85,7 @@ public class AltosUISeries extends XYSeries implements AltosUIGrapher { public void add(AltosUIDataPoint dataPoint) { try { - super.add(dataPoint.x(), units.value(dataPoint.y(fetch))); + super.add(dataPoint.x(), units.graph_value(dataPoint.y(fetch))); } catch (AltosUIDataMissing dm) { } } -- 2.30.2