package tim.prune.data;
+import tim.prune.config.Config;
+
/**
* Represents a range of altitudes, taking units into account.
* Values assumed to be >= 0.
{
/** Range of altitudes in metres */
private IntegerRange _range = new IntegerRange();
- /** Empty flag */
- private boolean _empty;
+ /** Flag for whether previous value exists or not */
+ private boolean _gotPreviousValue;
/** Previous metric value */
- private int _prevValue;
+ private int _previousValue;
/** Total climb in metres */
- private double _climb;
+ private int _climb;
/** Total descent in metres */
- private double _descent;
+ private int _descent;
+ /** Flags for whether minimum or maximum has been found */
+ private boolean _gotPreviousMinimum = false, _gotPreviousMaximum = false;
+ /** Integer values of previous minimum and maximum, if any */
+ private int _previousExtreme = 0;
/**
public void clear()
{
_range.clear();
- _climb = 0.0;
- _descent = 0.0;
- _empty = true;
- _prevValue = 0;
+ _climb = _descent = 0;
+ _gotPreviousValue = false;
+ _previousValue = 0;
+ _gotPreviousMinimum = _gotPreviousMaximum = false;
+ _previousExtreme = 0;
}
*/
public void addValue(Altitude inAltitude)
{
+ final int wiggleLimit = Config.getConfigInt(Config.KEY_ALTITUDE_TOLERANCE) / 100;
+
if (inAltitude != null && inAltitude.isValid())
{
int altValue = (int) inAltitude.getMetricValue();
_range.addValue(altValue);
// Compare with previous value if any
- if (!_empty)
+ if (_gotPreviousValue)
{
- if (altValue > _prevValue)
- _climb += (altValue - _prevValue);
- else
- _descent += (_prevValue - altValue);
+ if (altValue != _previousValue)
+ {
+ // Got an altitude value which is different from the previous one
+ final boolean locallyUp = (altValue > _previousValue);
+ final boolean overallUp = _gotPreviousMinimum && _previousValue > _previousExtreme;
+ final boolean overallDn = _gotPreviousMaximum && _previousValue < _previousExtreme;
+ final boolean moreThanWiggle = Math.abs(altValue - _previousValue) > wiggleLimit;
+ // Do we know whether we're going up or down yet?
+ if (!_gotPreviousMinimum && !_gotPreviousMaximum)
+ {
+ // we don't know whether we're going up or down yet - check limit
+ if (moreThanWiggle)
+ {
+ if (locallyUp) {_gotPreviousMinimum = true;}
+ else {_gotPreviousMaximum = true;}
+ _previousExtreme = _previousValue;
+ _previousValue = altValue;
+ _gotPreviousValue = true;
+ }
+ }
+ else if (overallUp)
+ {
+ if (locallyUp) {
+ // we're still going up - do nothing
+ _previousValue = altValue;
+ }
+ else if (moreThanWiggle)
+ {
+ // we're going up but have dropped over a maximum
+ // Add the climb from _previousExtreme up to _previousValue
+ _climb += (_previousValue - _previousExtreme);
+ _previousExtreme = _previousValue;
+ _gotPreviousMinimum = false; _gotPreviousMaximum = true;
+ _previousValue = altValue;
+ _gotPreviousValue = true;
+ }
+ }
+ else if (overallDn)
+ {
+ if (locallyUp) {
+ if (moreThanWiggle)
+ {
+ // we're going down but have climbed up from a minimum
+ // Add the descent from _previousExtreme down to _previousValue
+ _descent += (_previousExtreme - _previousValue);
+ _previousExtreme = _previousValue;
+ _gotPreviousMinimum = true; _gotPreviousMaximum = false;
+ _previousValue = altValue;
+ _gotPreviousValue = true;
+ }
+ }
+ else {
+ // we're still going down - do nothing
+ _previousValue = altValue;
+ _gotPreviousValue = true;
+ }
+ }
+ // TODO: Behaviour when WIGGLE_LIMIT == 0 should be same as before, all differences cumulated
+ }
}
- _prevValue = altValue;
- _empty = false;
+ else
+ {
+ // we haven't got a previous value at all, so it's the start of a new segment
+ _previousValue = altValue;
+ _gotPreviousValue = true;
+ }
+
+// if (!_empty)
+// {
+// if (altValue > _previousValue)
+// _climb += (altValue - _previousValue);
+// else
+// _descent += (_previousValue - altValue);
+// }
+// _previousValue = altValue;
+// _empty = false;
}
}
*/
public void ignoreValue(Altitude inAltitude)
{
- // If we set the empty flag to true, that has the same effect as restarting a segment
- _empty = true;
- addValue(inAltitude);
+ // Process the previous value, if any, to update climb/descent as that's the end of the previous segment
+ if (_gotPreviousValue && _gotPreviousMinimum && _previousValue > _previousExtreme) {
+ _climb += (_previousValue - _previousExtreme);
+ }
+ else if (_gotPreviousValue && _gotPreviousMaximum && _previousValue < _previousExtreme) {
+ _descent += (_previousExtreme - _previousValue);
+ }
+ // Eliminate the counting values to start the new segment
+ _gotPreviousMinimum = _gotPreviousMaximum = false;
+ _gotPreviousValue = false;
+ // Now process this value if there is one
+ if (inAltitude != null && inAltitude.isValid())
+ {
+ final int altValue = (int) inAltitude.getMetricValue();
+ _range.addValue(altValue);
+ _previousValue = altValue;
+ _gotPreviousValue = true;
+ }
}
/**
*/
public boolean hasRange()
{
- return _range.getMaximum() > _range.getMinimum();
+ return _range.hasValues();
}
/**
* @param inUnit altitude units to use
- * @return minimum value, or -1 if none found
+ * @return minimum value
*/
public int getMinimum(Unit inUnit)
{
- if (_range.getMinimum() <= 0) return _range.getMinimum();
return (int) (_range.getMinimum() * inUnit.getMultFactorFromStd());
}
/**
* @param inUnit altitude units to use
- * @return maximum value, or -1 if none found
+ * @return maximum value
*/
public int getMaximum(Unit inUnit)
{
- if (_range.getMaximum() <= 0) return _range.getMaximum();
return (int) (_range.getMaximum() * inUnit.getMultFactorFromStd());
}
*/
public int getClimb(Unit inUnit)
{
- return (int) (_climb * inUnit.getMultFactorFromStd());
+ // May need to add climb from last segment
+ int lastSegmentClimb = 0;
+ if (_gotPreviousValue && _gotPreviousMinimum && _previousValue > _previousExtreme) {
+ lastSegmentClimb = _previousValue - _previousExtreme;
+ }
+ return (int) ((_climb + lastSegmentClimb) * inUnit.getMultFactorFromStd());
}
/**
*/
public int getDescent(Unit inUnit)
{
- return (int) (_descent * inUnit.getMultFactorFromStd());
+ // May need to add descent from last segment
+ int lastSegmentDescent = 0;
+ if (_gotPreviousValue && _gotPreviousMaximum && _previousValue < _previousExtreme) {
+ lastSegmentDescent = _previousExtreme - _previousValue;
+ }
+ return (int) ((_descent + lastSegmentDescent) * inUnit.getMultFactorFromStd());
+ }
+
+ /**
+ * @return overall height gain in metres
+ */
+ public double getMetricHeightDiff()
+ {
+ return getClimb(UnitSetLibrary.UNITS_METRES) - getDescent(UnitSetLibrary.UNITS_METRES);
}
}