package uk.ac.imperial.lsds.seep.gc14.operator;
import static uk.ac.imperial.lsds.seep.gc14.util.StaticSensorNetworkStructure.maxIndexHouseholds;
import static uk.ac.imperial.lsds.seep.gc14.util.StaticSensorNetworkStructure.maxIndexPlugs;
import static uk.ac.imperial.lsds.seep.gc14.util.StaticSensorNetworkStructure.numberHouses;
import static uk.ac.imperial.lsds.seep.gc14.util.StaticSensorNetworkStructure.numberPlugs;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import uk.ac.imperial.lsds.seep.comm.serialization.DataTuple;
import uk.ac.imperial.lsds.seep.gc14.util.StaticSensorNetworkStructure;
import uk.ac.imperial.lsds.seep.operator.StatefulOperator;
import uk.ac.imperial.lsds.seep.state.StateWrapper;
public class Q2OutliersPart1 implements StatefulOperator {
private static final long serialVersionUID = 1L;
static final int windowOneHourInSec = 3600;
static final int windowOneDayInSec = 86400;
Map<Integer,Deque<Float>> valuesOneHourPerPlug = new HashMap<Integer,Deque<Float>>();
Map<Integer,Deque<Float>> valuesOneDayPerPlug = new HashMap<Integer,Deque<Float>>();
Map<Integer,Deque<Integer>> timestampsOneHourPerPlug = new HashMap<Integer,Deque<Integer>>();
Map<Integer,Deque<Integer>> timestampsOneDayPerPlug = new HashMap<Integer,Deque<Integer>>();
Map<Integer,List<Float>> valuesSortedByValueOneHourPerPlug = new HashMap<Integer,List<Float>>();
Map<Integer,List<Float>> valuesSortedByValueOneDayPerPlug = new HashMap<Integer,List<Float>>();
int[][][] plugPointer = new int[numberHouses][maxIndexHouseholds][maxIndexPlugs];
@Override
public void setUp() {
plugPointer = StaticSensorNetworkStructure.getInstance().getPlugPointer(numberHouses,
maxIndexHouseholds, maxIndexPlugs);
for (int i = 0; i < numberPlugs; i++) {
valuesOneHourPerPlug.put(i, new LinkedList<Float>());
valuesOneDayPerPlug.put(i, new LinkedList<Float>());
timestampsOneHourPerPlug.put(i, new LinkedList<Integer>());
timestampsOneDayPerPlug.put(i, new LinkedList<Integer>());
valuesSortedByValueOneHourPerPlug.put(i, new ArrayList<Float>());
valuesSortedByValueOneDayPerPlug.put(i, new ArrayList<Float>());
}
}
/** State mngt methods **/
@Override
public StateWrapper getState() {
// TODO Auto-generated method stub
return null;
}
@Override
public void replaceState(StateWrapper arg0) {
// TODO Auto-generated method stub
}
@Override
public void processData(DataTuple data) {
// System.out.println("Data: "+data);
/*
* ignore heart beats
*/
if (data.getLong("id") == -1)
return;
/*
* ignore work measurements for the time being
*/
if (data.getInt("property") != 1)
return;
int timestamp = data.getInt("timestamp");
// System.out.println("ts0: "+timestamp);
int house = data.getInt("house_id");
int household = data.getInt("household_id");
int plug = data.getInt("plug_id");
float value = data.getFloat("value");
int ppointer = plugPointer[house][household][plug];
/*
* Update hour window with new measurement
* and send update to aggregator if needed
*/
// System.out.println("ts1: "+timestamp);
handleWindow(data, ppointer, timestamp, value, windowOneHourInSec, valuesOneHourPerPlug, timestampsOneHourPerPlug, valuesSortedByValueOneHourPerPlug);
/*
* Update day window with new measurement
* and send update to aggregator if needed
*/
handleWindow(data, ppointer, timestamp, value, windowOneDayInSec, valuesOneDayPerPlug, timestampsOneDayPerPlug, valuesSortedByValueOneDayPerPlug);
}
private void handleWindow( DataTuple data, int ppointer, int timestamp, float value, int window,
Map<Integer,Deque<Float>> valuesPerPlug,
Map<Integer,Deque<Integer>> timestampsPerPlug,
Map<Integer,List<Float>> valuesSortedByValuePerPlug) {
// System.out.println("ts2: "+timestamp);
/*
* Enqueue new event
*/
valuesPerPlug.get(ppointer).addLast(value);
timestampsPerPlug.get(ppointer).addLast(timestamp);
/*
* Insert into sorted values
*/
if (valuesSortedByValuePerPlug.get(ppointer).isEmpty()) {
valuesSortedByValuePerPlug.get(ppointer).add(value);
}
else {
List<Float> valuesSortedByValue = valuesSortedByValuePerPlug.get(ppointer);
// not exact median, but lower value of the two values around the median if list contains even number of entries
int middle = (int)(valuesSortedByValue.size()/2f);
float currentMedian = valuesSortedByValue.get(middle);
if (currentMedian < value) {
// new sorted list
valuesSortedByValue = QUtils.insertIntoSortedFloatList(valuesSortedByValue, value, middle, valuesSortedByValue.size()-1);
// store new sorted list
valuesSortedByValuePerPlug.put(ppointer, valuesSortedByValue);
}
else {
// new sorted list
valuesSortedByValue = QUtils.insertIntoSortedFloatList(valuesSortedByValue, value, 0, middle);
// store new sorted list
valuesSortedByValuePerPlug.put(ppointer, valuesSortedByValue);
}
}
/*
* Dequeue events
*/
int tsToRemove = timestampsPerPlug.get(ppointer).getFirst();
tsToRemove = timestampsPerPlug.get(ppointer).getFirst();
List<Float> removedValues = new ArrayList<Float>();
while (tsToRemove < (timestamp - window)) {
timestampsPerPlug.get(ppointer).removeFirst();
float removedValue = valuesPerPlug.get(ppointer).removeFirst();
removedValues.add(removedValue);
valuesSortedByValuePerPlug.get(ppointer).remove(removedValue);
tsToRemove = timestampsPerPlug.get(ppointer).getFirst();
}
// if(in>0){
// System.out.println("has to remove: "+in);
// System.out.println("gonna remove: "+removedValues.size());
// }
/*
* Send update
*/
if (removedValues.remove(value))
value = -1;
if (!(value == -1 && removedValues.isEmpty())) {
float plugMedian = QUtils.medianOfSortedList(valuesSortedByValuePerPlug.get(ppointer));
float[] primitiveArray = QUtils.toPrimitiveArray(removedValues);
// if(removedValues.size() != primitiveArray.length){
// System.out.println("removedValues: "+removedValues.size());
// System.out.println("primitiveArray: "+primitiveArray.length);
// }
DataTuple output = data.setValues(timestamp, ppointer, window, plugMedian, value, primitiveArray);
api.send(output);
}
}
@Override
public void processData(List<DataTuple> dataList) { }
}