From b3f1702e4e7e57e52402be69c10a84e5caa85f82 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 10 Sep 2011 22:03:12 +0200 Subject: Factor distance parser into its own class and static method Also, match against one regexp to increase efficiency. Named constants have been used instead of hardcoded ones to convert various lengths to kilometers. --- src/cgeo/geocaching/cgBase.java | 34 ++++++---------- src/cgeo/geocaching/cgeopoint.java | 44 +++------------------ src/cgeo/geocaching/cgeowaypointadd.java | 44 +++------------------ src/cgeo/geocaching/geopoint/DistanceParser.java | 47 +++++++++++++++++++++++ src/cgeo/geocaching/geopoint/Geopoint.java | 1 - src/cgeo/geocaching/mapcommon/cgOverlayScale.java | 2 +- 6 files changed, 70 insertions(+), 102 deletions(-) create mode 100644 src/cgeo/geocaching/geopoint/DistanceParser.java (limited to 'src') diff --git a/src/cgeo/geocaching/cgBase.java b/src/cgeo/geocaching/cgBase.java index 775b267..72743b9 100644 --- a/src/cgeo/geocaching/cgBase.java +++ b/src/cgeo/geocaching/cgBase.java @@ -71,6 +71,7 @@ import android.util.Log; import android.widget.EditText; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.files.LocParser; +import cgeo.geocaching.geopoint.DistanceParser; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.utils.CollectionUtils; @@ -172,7 +173,9 @@ public class cgBase { private static final Pattern patternViewstateFieldCount = Pattern.compile("id=\"__VIEWSTATEFIELDCOUNT\"[^(value)]+value=\"(\\d+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); private static final Pattern patternViewstates = Pattern.compile("id=\"__VIEWSTATE(\\d*)\"[^(value)]+value=\"([^\"]+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); private static final Pattern patternIsPremium = Pattern.compile(" 0) { - trackable.distance = parseDistance(matcherDistance.group(1)); + try { + trackable.distance = DistanceParser.parseDistance(matcherDistance.group(1), settings.units); + } catch (NumberFormatException e) { + trackable.distance = null; + throw e; + } } } catch (Exception e) { // failed to parse trackable distance @@ -2407,24 +2415,6 @@ public class cgBase { return text.trim(); } - public static Double parseDistance(String dst) { - Double distance = null; - - final Pattern pattern = Pattern.compile("([0-9\\.,]+)[ ]*(km|mi)", Pattern.CASE_INSENSITIVE); - final Matcher matcher = pattern.matcher(dst); - while (matcher.find()) { - if (matcher.groupCount() > 1) { - if (matcher.group(2).equalsIgnoreCase("km")) { - distance = Double.valueOf(matcher.group(1)); - } else { - distance = Double.valueOf(matcher.group(1)) / kmInMiles; - } - } - } - - return distance; - } - public static double getDistance(final Geopoint coords1, final Geopoint coords2) { if (coords1 == null || coords2 == null) { return 0; @@ -2455,7 +2445,7 @@ public class cgBase { } if (settings.units == cgSettings.unitsImperial) { - distance *= kmInMiles; + distance /= miles2km; if (distance > 100) { return String.format(Locale.getDefault(), "%.0f", Double.valueOf(Math.round(distance))) + " mi"; } else if (distance > 0.5) { @@ -2491,7 +2481,7 @@ public class cgBase { String unit = "km/h"; if (this.settings.units == cgSettings.unitsImperial) { - kph *= kmInMiles; + kph /= miles2km; unit = "mph"; } diff --git a/src/cgeo/geocaching/cgeopoint.java b/src/cgeo/geocaching/cgeopoint.java index 240636e..bb817b5 100644 --- a/src/cgeo/geocaching/cgeopoint.java +++ b/src/cgeo/geocaching/cgeopoint.java @@ -2,8 +2,6 @@ package cgeo.geocaching; import java.util.List; import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; @@ -32,6 +30,7 @@ import android.widget.ListView; import android.widget.TextView; import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; +import cgeo.geocaching.geopoint.DistanceParser; import cgeo.geocaching.geopoint.Geopoint; public class cgeopoint extends AbstractActivity { @@ -519,43 +518,10 @@ public class cgeopoint extends AbstractActivity { return null; } - Double distance = null; // km - - final Pattern patternA = Pattern.compile("^([0-9\\.\\,]+)[ ]*m$", Pattern.CASE_INSENSITIVE); // m - final Pattern patternB = Pattern.compile("^([0-9\\.\\,]+)[ ]*km$", Pattern.CASE_INSENSITIVE); // km - final Pattern patternC = Pattern.compile("^([0-9\\.\\,]+)[ ]*ft$", Pattern.CASE_INSENSITIVE); // ft - 0.3048m - final Pattern patternD = Pattern.compile("^([0-9\\.\\,]+)[ ]*yd$", Pattern.CASE_INSENSITIVE); // yd - 0.9144m - final Pattern patternE = Pattern.compile("^([0-9\\.\\,]+)[ ]*mi$", Pattern.CASE_INSENSITIVE); // mi - 1609.344m - - Matcher matcherA = patternA.matcher(distanceText); - Matcher matcherB = patternB.matcher(distanceText); - Matcher matcherC = patternC.matcher(distanceText); - Matcher matcherD = patternD.matcher(distanceText); - Matcher matcherE = patternE.matcher(distanceText); - - if (matcherA.find() && matcherA.groupCount() > 0) { - distance = (new Double(matcherA.group(1))) * 0.001; - } else if (matcherB.find() && matcherB.groupCount() > 0) { - distance = new Double(matcherB.group(1)); - } else if (matcherC.find() && matcherC.groupCount() > 0) { - distance = (new Double(matcherC.group(1))) * 0.0003048; - } else if (matcherD.find() && matcherD.groupCount() > 0) { - distance = (new Double(matcherD.group(1))) * 0.0009144; - } else if (matcherE.find() && matcherE.groupCount() > 0) { - distance = (new Double(matcherE.group(1))) * 1.609344; - } else { - try { - if (settings.units == cgSettings.unitsImperial) { - distance = (new Double(distanceText)) * 0.0003048; // considering it feet - } else { - distance = (new Double(distanceText)) * 0.001; // considering it meters - } - } catch (Exception e) { - // probably not a number - } - } - - if (distance == null) { + double distance; + try { + distance = DistanceParser.parseDistance(distanceText, settings.units); + } catch (NumberFormatException e) { showToast(res.getString(R.string.err_parse_dist)); return null; } diff --git a/src/cgeo/geocaching/cgeowaypointadd.java b/src/cgeo/geocaching/cgeowaypointadd.java index 9cac3a5..eefe2fd 100644 --- a/src/cgeo/geocaching/cgeowaypointadd.java +++ b/src/cgeo/geocaching/cgeowaypointadd.java @@ -3,8 +3,6 @@ package cgeo.geocaching; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; @@ -21,6 +19,7 @@ import android.widget.Button; import android.widget.EditText; import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.activity.ActivityMixin; +import cgeo.geocaching.geopoint.DistanceParser; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.GeopointFormatter; @@ -298,43 +297,10 @@ public class cgeowaypointadd extends AbstractActivity { return; } - Double distance = null; // km - - final Pattern patternA = Pattern.compile("^([0-9\\.\\,]+)[ ]*m$", Pattern.CASE_INSENSITIVE); // m - final Pattern patternB = Pattern.compile("^([0-9\\.\\,]+)[ ]*km$", Pattern.CASE_INSENSITIVE); // km - final Pattern patternC = Pattern.compile("^([0-9\\.\\,]+)[ ]*ft$", Pattern.CASE_INSENSITIVE); // ft - 0.3048m - final Pattern patternD = Pattern.compile("^([0-9\\.\\,]+)[ ]*yd$", Pattern.CASE_INSENSITIVE); // yd - 0.9144m - final Pattern patternE = Pattern.compile("^([0-9\\.\\,]+)[ ]*mi$", Pattern.CASE_INSENSITIVE); // mi - 1609.344m - - Matcher matcherA = patternA.matcher(distanceText); - Matcher matcherB = patternB.matcher(distanceText); - Matcher matcherC = patternC.matcher(distanceText); - Matcher matcherD = patternD.matcher(distanceText); - Matcher matcherE = patternE.matcher(distanceText); - - if (matcherA.find() && matcherA.groupCount() > 0) { - distance = (new Double(matcherA.group(1))) * 0.001; - } else if (matcherB.find() && matcherB.groupCount() > 0) { - distance = new Double(matcherB.group(1)); - } else if (matcherC.find() && matcherC.groupCount() > 0) { - distance = (new Double(matcherC.group(1))) * 0.0003048; - } else if (matcherD.find() && matcherD.groupCount() > 0) { - distance = (new Double(matcherD.group(1))) * 0.0009144; - } else if (matcherE.find() && matcherE.groupCount() > 0) { - distance = (new Double(matcherE.group(1))) * 1.609344; - } else { - try { - if (settings.units == cgSettings.unitsImperial) { - distance = (new Double(distanceText)) * 1.609344; // considering it miles - } else { - distance = (new Double(distanceText)) * 0.001; // considering it meters - } - } catch (Exception e) { - // probably not a number - } - } - - if (distance == null) { + double distance; + try { + distance = DistanceParser.parseDistance(distanceText, settings.units); + } catch (NumberFormatException e) { showToast(res.getString(R.string.err_parse_dist)); return; } diff --git a/src/cgeo/geocaching/geopoint/DistanceParser.java b/src/cgeo/geocaching/geopoint/DistanceParser.java new file mode 100644 index 0000000..3578902 --- /dev/null +++ b/src/cgeo/geocaching/geopoint/DistanceParser.java @@ -0,0 +1,47 @@ +package cgeo.geocaching.geopoint; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import cgeo.geocaching.cgBase; +import cgeo.geocaching.cgSettings; + +public final class DistanceParser { + + private static final Pattern pattern = Pattern.compile("^([0-9\\.\\,]+)[ ]*(m|km|ft|yd|mi|)?$", Pattern.CASE_INSENSITIVE); + + /** + * Parse a distance string composed by a number and an optional suffix + * (such as "1.2km"). + * + * @param distanceText the string to analyze + * @return the distance in kilometers + * + * @throws NumberFormatException if the given number is invalid + */ + public static double parseDistance(String distanceText, final int defaultUnit) { + final Matcher matcher = pattern.matcher(distanceText); + + if (!matcher.find()) { + throw new NumberFormatException(distanceText); + } + + final double value = Double.parseDouble(matcher.group(1)); + final String unit = matcher.group(2).toLowerCase(); + + if (unit.equals("m") || (unit.length() == 0 && defaultUnit == cgSettings.unitsMetric)) { + return value / 1000; + } + if (unit.equals("km")) { + return value; + } + if (unit.equals("yd")) { + return value * cgBase.yards2km; + } + if (unit.equals("mi")) { + return value * cgBase.miles2km; + } + return value * cgBase.feet2km; + } + +} diff --git a/src/cgeo/geocaching/geopoint/Geopoint.java b/src/cgeo/geocaching/geopoint/Geopoint.java index 4cea883..8f3d521 100644 --- a/src/cgeo/geocaching/geopoint/Geopoint.java +++ b/src/cgeo/geocaching/geopoint/Geopoint.java @@ -7,7 +7,6 @@ import android.location.Location; */ public final class Geopoint { - public static final double kmInMiles = 1 / 1.609344; public static final double deg2rad = Math.PI / 180; public static final double rad2deg = 180 / Math.PI; public static final float erad = 6371.0f; diff --git a/src/cgeo/geocaching/mapcommon/cgOverlayScale.java b/src/cgeo/geocaching/mapcommon/cgOverlayScale.java index fcd5bf5..e4db67c 100644 --- a/src/cgeo/geocaching/mapcommon/cgOverlayScale.java +++ b/src/cgeo/geocaching/mapcommon/cgOverlayScale.java @@ -64,7 +64,7 @@ public class cgOverlayScale implements OverlayBase { distanceRound = 0d; if(settings.units == cgSettings.unitsImperial) { - distance *= cgBase.kmInMiles; + distance /= cgBase.miles2km; if (distance > 100) { // 100+ mi > 1xx mi distanceRound = Math.floor(distance / 100) * 100; -- cgit v1.1