package com.github.pfichtner.jrunalyser.base.data.stat; import static com.github.pfichtner.jrunalyser.base.data.stat.Predicates.LinkedWayPoints.hasLink; import static com.github.pfichtner.jrunalyser.base.util.Validator.validateWaypoints; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Iterables.filter; import java.io.Serializable; import java.util.List; import java.util.concurrent.TimeUnit; import com.github.pfichtner.jrunalyser.base.data.DefaultDuration; import com.github.pfichtner.jrunalyser.base.data.Distance; import com.github.pfichtner.jrunalyser.base.data.DistanceUnit; import com.github.pfichtner.jrunalyser.base.data.Duration; import com.github.pfichtner.jrunalyser.base.data.LinkedTrackPoint; import com.github.pfichtner.jrunalyser.base.data.Speed; import com.github.pfichtner.jrunalyser.base.data.WayPoint; import com.github.pfichtner.jrunalyser.base.data.segment.Segment; import com.github.pfichtner.jrunalyser.base.data.track.Track; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; public class DefaultStatistics implements Statistics, Serializable { private static final long serialVersionUID = 5608387056728759224L; private final WayPoint minElevation; private final WayPoint maxElevation; private final int ascent; private final int descent; private final LinkedTrackPoint minSpeed; private final LinkedTrackPoint maxSpeed; private final Speed avgSpeed; private final Distance distance; private final Duration duration; private DefaultStatistics(Statistics stats) { this.minElevation = stats.getMinElevation(); this.maxElevation = stats.getMaxElevation(); this.ascent = stats.getAscent(); this.descent = stats.getDescent(); this.minSpeed = stats.getMinSpeed(); this.maxSpeed = stats.getMaxSpeed(); this.avgSpeed = stats.getAvgSpeed(); this.distance = stats.getDistance(); this.duration = stats.getDuration(); } public static Statistics copyOf(Statistics stats) { return stats == null ? NULL : new DefaultStatistics(stats); } public static Statistics ofTrack(Track track) { List<Statistics> statistics = Lists.newArrayList(); for (Segment segment : track.getSegments()) { statistics.add(ofSegment(segment)); } return DefaultStatistics.copyOf(CombinedStatistics.of(statistics)); } public static Statistics ofSegment(Segment segment) { return new DefaultStatistics(segment.getTrackpoints()); } public static Statistics ofWaypoints(List<? extends LinkedTrackPoint> wps) { return new DefaultStatistics(wps); } private DefaultStatistics(List<? extends LinkedTrackPoint> wps) { List<? extends LinkedTrackPoint> wayPoints = checkNotNull(wps); checkArgument(!wps.isEmpty(), "Waypoints are empty"); assert validateWaypoints(wayPoints) != null; Iterable<? extends LinkedTrackPoint> linkedTps = filter(wayPoints, hasLink()); this.minElevation = StatCalculators.minEle().calculate(wayPoints); this.maxElevation = StatCalculators.maxEle().calculate(wayPoints); this.ascent = StatCalculators.ascent().calculate(linkedTps).intValue(); this.descent = StatCalculators.descent().calculate(linkedTps) .intValue(); // ---------------------------------------------------------- this.minSpeed = StatCalculators.minSpeed().calculate(linkedTps); this.maxSpeed = StatCalculators.maxSpeed().calculate(linkedTps); this.avgSpeed = StatCalculators.avgSpeed(DistanceUnit.METERS, TimeUnit.SECONDS).calculate(linkedTps); this.distance = StatCalculators.distance(DistanceUnit.METERS) .calculate(linkedTps); // ---------------------------------------------------------- this.duration = wayPoints.isEmpty() ? null : calcDuration(wayPoints); } private static Duration calcDuration( List<? extends LinkedTrackPoint> wayPoints) { long startTime = wayPoints.get(0).getTime().longValue(); LinkedTrackPoint last = Iterables.getLast(wayPoints); long endTime = last.getLink() == null ? last.getTime().longValue() : last.getLink().getNext().getTime().longValue(); return DefaultDuration.of(endTime - startTime, TimeUnit.MILLISECONDS) .convertTo(TimeUnit.SECONDS); } public Distance getDistance() { return this.distance; } public Duration getDuration() { return this.duration; } public WayPoint getMinElevation() { return this.minElevation; } public WayPoint getMaxElevation() { return this.maxElevation; } public int getAscent() { return this.ascent; } public int getDescent() { return this.descent; } public LinkedTrackPoint getMinSpeed() { return this.minSpeed; } public LinkedTrackPoint getMaxSpeed() { return this.maxSpeed; } @Override public Speed getAvgSpeed() { return this.avgSpeed; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + this.ascent; result = prime * result + ((this.avgSpeed == null) ? 0 : this.avgSpeed.hashCode()); result = prime * result + this.descent; result = prime * result + ((this.distance == null) ? 0 : this.distance.hashCode()); result = prime * result + ((this.duration == null) ? 0 : this.duration.hashCode()); result = prime * result + ((this.maxElevation == null) ? 0 : this.maxElevation .hashCode()); result = prime * result + ((this.maxSpeed == null) ? 0 : this.maxSpeed.hashCode()); result = prime * result + ((this.minElevation == null) ? 0 : this.minElevation .hashCode()); result = prime * result + ((this.minSpeed == null) ? 0 : this.minSpeed.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; DefaultStatistics other = (DefaultStatistics) obj; if (this.ascent != other.ascent) return false; if (this.avgSpeed == null) { if (other.avgSpeed != null) return false; } else if (!this.avgSpeed.equals(other.avgSpeed)) return false; if (this.descent != other.descent) return false; if (this.distance == null) { if (other.distance != null) return false; } else if (!this.distance.equals(other.distance)) return false; if (this.duration == null) { if (other.duration != null) return false; } else if (!this.duration.equals(other.duration)) return false; if (this.maxElevation == null) { if (other.maxElevation != null) return false; } else if (!this.maxElevation.equals(other.maxElevation)) return false; if (this.maxSpeed == null) { if (other.maxSpeed != null) return false; } else if (!this.maxSpeed.equals(other.maxSpeed)) return false; if (this.minElevation == null) { if (other.minElevation != null) return false; } else if (!this.minElevation.equals(other.minElevation)) return false; if (this.minSpeed == null) { if (other.minSpeed != null) return false; } else if (!this.minSpeed.equals(other.minSpeed)) return false; return true; } }