package storm.applications.bolt;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static storm.applications.constants.VoIPSTREAMConstants.*;
import storm.applications.model.cdr.CallDetailRecord;
/**
*
* @author Maycon Viana Bordin <mayconbordin@gmail.com>
*/
public class ScoreBolt extends AbstractScoreBolt {
private static final Logger LOG = LoggerFactory.getLogger(ScoreBolt.class);
private double[] weights;
public ScoreBolt() {
super(null);
}
@Override
public void initialize() {
super.initialize();
// parameters
double fofirWeight = config.getDouble(Conf.FOFIR_WEIGHT);
double urlWeight = config.getDouble(Conf.URL_WEIGHT);
double acdWeight = config.getDouble(Conf.ACD_WEIGHT);
weights = new double[3];
weights[0] = fofirWeight;
weights[1] = urlWeight;
weights[2] = acdWeight;
}
@Override
public void execute(Tuple input) {
CallDetailRecord cdr = (CallDetailRecord) input.getValueByField(Field.RECORD);
Source src = parseComponentId(input.getSourceComponent());
String caller = cdr.getCallingNumber();
long timestamp = cdr.getAnswerTime().getMillis()/1000;
double score = input.getDouble(2);
String key = String.format("%s:%d", caller, timestamp);
if (map.containsKey(key)) {
Entry e = map.get(key);
if (e.isFull()) {
double mainScore = sum(e.getValues(), weights);
LOG.debug(String.format("Score=%f; Scores=%s", mainScore, Arrays.toString(e.getValues())));
collector.emit(new Values(caller, timestamp, mainScore, cdr));
} else {
e.set(src, score);
}
} else {
Entry e = new Entry(cdr);
e.set(src, score);
map.put(key, e);
}
}
/**
* Computes weighted sum of a given sequence.
* @param data data array
* @param weights weights
* @return weighted sum of the data
*/
private static double sum(double[] data, double[] weights) {
double sum = 0.0;
for (int i=0; i<data.length; i++) {
sum += (data[i] * weights[i]);
}
return sum;
}
@Override
protected Source[] getFields() {
return new Source[]{Source.FOFIR, Source.URL, Source.ACD};
}
}