package pl.llp.aircasting.model;
import com.google.common.base.Optional;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import static pl.llp.aircasting.model.internal.MeasurementLevel.*;
public class MeasurementStream implements Serializable
{
@Expose @SerializedName("measurements")
private transient List<Measurement> measurements = new CopyOnWriteArrayList<Measurement>();
private long id;
private long sessionId;
@Expose @SerializedName("sensor_name") private String sensorName;
@Expose @SerializedName("sensor_package_name") private String packageName;
@Expose @SerializedName("measurement_type") private String measurementType;
@Expose @SerializedName("measurement_short_type") private String shortType;
@Expose @SerializedName("unit_name") private String unit;
@Expose @SerializedName("unit_symbol") private String symbol;
private Double sum = 0.0;
@Expose @SerializedName("average_value") Double avg;
private Double peak;
@Expose @SerializedName("threshold_very_high") private int thresholdVeryHigh;
@Expose @SerializedName("threshold_very_low") private int thresholdVeryLow;
@Expose @SerializedName("threshold_low") private int thresholdLow;
@Expose @SerializedName("threshold_medium") private int thresholdMedium;
@Expose @SerializedName("threshold_high") private int thresholdHigh;
@Expose @SerializedName("min_latitude") private Double minLatitude;
@Expose @SerializedName("max_latitude") private Double maxLatitude;
@Expose @SerializedName("min_longitude") private Double minLongitude;
@Expose @SerializedName("max_longitude") private Double maxLongitude;
@Expose @SerializedName("deleted") private boolean markedForRemoval;
private transient boolean submittedForRemoval;
private transient Visibility visibility = Visibility.VISIBLE;
private transient String address = "none";
public MeasurementStream() {
}
public MeasurementStream(Sensor sensor)
{
this(sensor.getPackageName(),
sensor.getSensorName(),
sensor.getMeasurementType(),
sensor.getShortType(),
sensor.getUnit(),
sensor.getSymbol(),
sensor.getThreshold(VERY_LOW),
sensor.getThreshold(MID),
sensor.getThreshold(LOW),
sensor.getThreshold(HIGH),
sensor.getThreshold(VERY_HIGH),
"none");
}
public MeasurementStream(
String packageName, String sensorName, String type, String shortType, String unit, String symbol,
int thresholdVeryLow, int thresholdLow, int thresholdMedium, int thresholdHigh, int thresholdVeryHigh)
{
this(packageName, sensorName, type, shortType, unit, symbol,
thresholdVeryLow, thresholdLow, thresholdMedium, thresholdHigh, thresholdVeryHigh, "none");
}
public MeasurementStream(String packageName, String sensorName, String type, String shortType, String unit, String symbol,
int thresholdVeryLow, int thresholdLow,
int thresholdMedium,
int thresholdHigh, int thresholdVeryHigh, String address
) {
this.packageName = packageName;
this.sensorName = sensorName;
this.measurementType = type;
this.shortType = shortType;
this.unit = unit;
this.symbol = symbol;
this.thresholdVeryLow = thresholdVeryLow;
this.thresholdLow = thresholdLow;
this.thresholdMedium = thresholdMedium;
this.thresholdHigh = thresholdHigh;
this.thresholdVeryHigh = thresholdVeryHigh;
this.address = address;
}
public List<Measurement> getMeasurements() {
return measurements;
}
public List<Measurement> getLastMeasurements(int amount) {
int size = measurements.size();
if(size > amount)
return measurements.subList(size - amount, size);
else
return measurements;
}
public void add(Measurement measurement) {
if(peak == null)
peak = Double.NEGATIVE_INFINITY;
measurements.add(measurement);
double value = measurement.getValue();
sum += value;
if (value > peak) {
peak = value;
}
Optional<Double> average = Optional.fromNullable(avg);
avg = average.or(0.0) + (value - average.or(0.0))/(measurements.size());
if(minLatitude == null) minLatitude = Double.POSITIVE_INFINITY;
if(minLongitude == null) minLongitude = Double.POSITIVE_INFINITY;
if(maxLatitude == null) maxLatitude = Double.NEGATIVE_INFINITY;
if(maxLongitude == null) maxLongitude = Double.NEGATIVE_INFINITY;
maxLatitude = Math.max(maxLatitude, measurement.getLatitude());
minLatitude = Math.min(minLatitude, measurement.getLatitude());
maxLongitude = Math.max(maxLongitude, measurement.getLatitude());
minLongitude = Math.min(minLongitude, measurement.getLatitude());
}
public String getSensorName() {
return sensorName;
}
public String getMeasurementType() {
return measurementType;
}
public String getShortType() {
return shortType;
}
public String getUnit() {
return unit;
}
public String getSymbol() {
return symbol;
}
private double calculatePeak() {
double newPeak = Integer.MIN_VALUE;
for (Measurement measurement : measurements) {
if (measurement.getValue() > newPeak) {
newPeak = measurement.getValue();
}
}
return newPeak;
}
public double getPeak() {
if (peak == null) {
peak = calculatePeak();
}
return peak;
}
public double getAvg() {
if (avg == null)
{
avg = calculateAvg();
}
return avg;
}
private double calculateAvg() {
double sum = getSum();
return sum / (measurements.isEmpty() ? 1 : measurements.size());
}
public void setPeak(double peak) {
this.peak = peak;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MeasurementStream stream = (MeasurementStream) o;
if (measurementType != null ? !measurementType.equals(stream.measurementType) : stream.measurementType != null)
return false;
if (sensorName != null ? !sensorName.equals(stream.sensorName) : stream.sensorName != null) return false;
if (symbol != null ? !symbol.equals(stream.symbol) : stream.symbol != null) return false;
if (unit != null ? !unit.equals(stream.unit) : stream.unit != null) return false;
return true;
}
@Override
public int hashCode() {
int result = sensorName != null ? sensorName.hashCode() : 0;
result = 31 * result + (measurementType != null ? measurementType.hashCode() : 0);
result = 31 * result + (unit != null ? unit.hashCode() : 0);
result = 31 * result + (symbol != null ? symbol.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "MeasurementStream{" +
"measurements=" + measurements +
", sensorName='" + sensorName + '\'' +
", measurementType='" + measurementType + '\'' +
", unit='" + unit + '\'' +
", symbol='" + symbol + '\'' +
", sum=" + sum +
", peak=" + peak +
'}';
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getSessionId() {
return sessionId;
}
public void setSessionId(long sessionId) {
this.sessionId = sessionId;
}
public void setMeasurements(List<Measurement> measurements) {
this.measurements = measurements;
sum = 0.0;
for (Measurement measurement : measurements) {
sum += measurement.getValue();
}
avg = null;
}
public Double getSum() {
return sum;
}
public void setAvg(double avg) {
this.avg = avg;
}
public int getThresholdVeryHigh() {
return thresholdVeryHigh;
}
public int getThresholdVeryLow() {
return thresholdVeryLow;
}
public int getThresholdLow() {
return thresholdLow;
}
public int getThresholdMedium() {
return thresholdMedium;
}
public int getThresholdHigh() {
return thresholdHigh;
}
public boolean isEmpty() {
return measurements.isEmpty();
}
public String getPackageName()
{
return packageName;
}
public boolean isMarkedForRemoval()
{
return markedForRemoval;
}
public void setMarkedForRemoval(boolean markedForRemoval)
{
this.markedForRemoval = markedForRemoval;
}
public boolean isSubmittedForRemoval()
{
return submittedForRemoval;
}
public void setSubmittedForRemoval(boolean submittedForRemoval)
{
this.submittedForRemoval = submittedForRemoval;
}
public boolean isVisible()
{
boolean deleted = Visibility.INVISIBLE_DELETED.equals(visibility);
boolean disconnected = Visibility.INVISIBLE_DISCONNECTED.equals(visibility);
return !(deleted || disconnected);
}
public void markAs(Visibility state)
{
setVisibility(state);
}
public void setVisibility(Visibility visibility)
{
this.visibility = visibility;
}
public String getAddress()
{
return address;
}
public enum Visibility
{
VISIBLE,
INVISIBLE_DELETED,
INVISIBLE_DISCONNECTED,
VISIBLE_RECONNECTED;
}
}