package storm.applications.bolt;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import storm.applications.constants.TrafficMonitoringConstants.Field;
import storm.applications.model.gis.Road;
/**
* Copyright 2013 Xdata@SIAT
* email: gh.chen@siat.ac.cn
*/
public class SpeedCalculatorBolt extends AbstractBolt {
private Map<Integer, Road> roads;
@Override
public void initialize() {
roads = new HashMap<>();
}
@Override
public void execute(Tuple input) {
int roadID = input.getIntegerByField(Field.ROAD_ID);
int speed = input.getIntegerByField(Field.SPEED);
int averageSpeed = 0;
int count = 0;
if (!roads.containsKey(roadID)) {
Road road = new Road(roadID);
road.addRoadSpeed(speed);
road.setCount(1);
road.setAverageSpeed(speed);
roads.put(roadID, road);
averageSpeed = speed;
count = 1;
} else {
Road road = roads.get(roadID);
int sum = 0;
if (road.getRoadSpeedSize() < 2) {
road.incrementCount();
road.addRoadSpeed(speed);
for (int it : road.getRoadSpeed()) {
sum += it;
}
averageSpeed = (int)((double)sum/(double)road.getRoadSpeedSize());
road.setAverageSpeed(averageSpeed);
count = road.getRoadSpeedSize();
} else {
double avgLast = roads.get(roadID).getAverageSpeed();
double temp = 0;
for (int it : road.getRoadSpeed()) {
sum += it;
temp += Math.pow((it-avgLast), 2);
}
int avgCurrent = (int) ((sum + speed)/((double)road.getRoadSpeedSize() + 1));
temp = (temp + Math.pow((speed - avgLast), 2)) / (road.getRoadSpeedSize());
double stdDev = Math.sqrt(temp);
if (Math.abs(speed - avgCurrent) <= (2 * stdDev)) {
road.incrementCount();
road.addRoadSpeed(speed);
road.setAverageSpeed(avgCurrent);
averageSpeed = avgCurrent;
count = road.getRoadSpeedSize();
}
}
}
collector.emit(input, new Values(new Date(), roadID, averageSpeed, count));
collector.ack(input);
}
@Override
public Fields getDefaultFields() {
return new Fields(Field.NOW_DATE, Field.ROAD_ID, Field.AVG_SPEED, Field.COUNT);
}
}