package com.github.pfichtner.jrunalyser.base.data;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;
import com.google.common.math.LongMath;
import com.google.common.primitives.Doubles;
public class DefaultSpeed implements Speed, Serializable {
private static final long serialVersionUID = 1609904844575774284L;
private static final long fix = TimeUnit.MILLISECONDS.convert(1,
TimeUnit.DAYS);
private final double dPerT;
private final DistanceUnit distanceUnit;
private final TimeUnit timeUnit;
public DefaultSpeed(Distance distance, Duration duration) {
this(distance.getValue(distance.getDistanceUnit())
/ duration.getValue(duration.getTimeUnit()), distance
.getDistanceUnit(), duration.getTimeUnit());
}
public DefaultSpeed(double dPerT, DistanceUnit distanceUnit,
TimeUnit timeUnit) {
this.dPerT = dPerT;
this.distanceUnit = distanceUnit;
this.timeUnit = timeUnit;
}
public DefaultSpeed convert(DistanceUnit distanceUnit, TimeUnit timeUnit) {
return convert(distanceUnit, 1, timeUnit);
}
private DefaultSpeed convert(DistanceUnit distanceUnit, int time,
TimeUnit timeUnit) {
if (distanceUnit == this.distanceUnit && timeUnit == this.timeUnit) {
return this;
}
long longTime = LongMath.checkedMultiply(time, fix);
return new DefaultSpeed(distanceUnit.convert(
this.dPerT * this.timeUnit.convert(longTime, timeUnit),
this.distanceUnit) / fix, distanceUnit, timeUnit);
}
@Override
public Pace toPace(TimeUnit timeUnit, DistanceUnit distanceUnit) {
return new DefaultPace(1 / getValue(distanceUnit, timeUnit), timeUnit,
distanceUnit);
}
@Override
public DistanceUnit getDistanceUnit() {
return this.distanceUnit;
}
@Override
public TimeUnit getTimeUnit() {
return this.timeUnit;
}
@Override
public double getValue(DistanceUnit distanceUnit, TimeUnit timeUnit) {
return convert(distanceUnit, timeUnit).dPerT;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(this.dPerT);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime
* result
+ ((this.distanceUnit == null) ? 0 : this.distanceUnit
.hashCode());
result = prime * result
+ ((this.timeUnit == null) ? 0 : this.timeUnit.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;
DefaultSpeed other = (DefaultSpeed) obj;
if (Double.doubleToLongBits(this.dPerT) != Double
.doubleToLongBits(other.dPerT))
return false;
if (this.distanceUnit != other.distanceUnit)
return false;
if (this.timeUnit != other.timeUnit)
return false;
return true;
}
@Override
public String toString() {
return this.dPerT + " " + this.distanceUnit + " per " + this.timeUnit;
}
public int compareTo(Speed o) {
return Doubles.compare(getValue(this.distanceUnit, this.timeUnit),
o.getValue(this.distanceUnit, this.timeUnit));
}
}