com.espertech.esper.view.stat.WeightedAverageView Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of esper Show documentation
Show all versions of esper Show documentation
Complex event processing and event series analysis component
/**************************************************************************************
* Copyright (C) 2006-2015 EsperTech Inc. All rights reserved. *
* http://www.espertech.com/esper *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
**************************************************************************************/
package com.espertech.esper.view.stat;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.EventType;
import com.espertech.esper.collection.SingleEventIterator;
import com.espertech.esper.core.context.util.AgentInstanceViewFactoryChainContext;
import com.espertech.esper.core.service.StatementContext;
import com.espertech.esper.epl.expression.core.ExprEvaluator;
import com.espertech.esper.epl.expression.core.ExprNode;
import com.espertech.esper.metrics.instrumentation.InstrumentationHelper;
import com.espertech.esper.view.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* View for computing a weighted average. The view uses 2 fields within the parent view to compute the weighted average.
* The X field and weight field. In a price-volume example it calculates the volume-weighted average price
* as (sum(price * volume) / sum(volume)).
* Example: weighted_avg("price", "volume")
*/
public class WeightedAverageView extends ViewSupport implements CloneableView, DerivedValueView
{
private final WeightedAverageViewFactory viewFactory;
private final AgentInstanceViewFactoryChainContext agentInstanceContext;
private final ExprEvaluator fieldNameXEvaluator;
private final ExprEvaluator fieldNameWeightEvaluator;
private EventBean[] eventsPerStream = new EventBean[1];
protected double sumXtimesW = Double.NaN;
protected double sumW = Double.NaN;
protected double currentValue = Double.NaN;
protected Object[] lastValuesEventNew;
private EventBean lastNewEvent;
/**
* Constructor requires the name of the field to use in the parent view to compute the weighted average on,
* as well as the name of the field in the parent view to get the weight from.
* compute the average for.
*/
public WeightedAverageView(WeightedAverageViewFactory viewFactory, AgentInstanceViewFactoryChainContext agentInstanceContext)
{
this.viewFactory = viewFactory;
this.fieldNameXEvaluator = viewFactory.fieldNameX.getExprEvaluator();
this.fieldNameWeightEvaluator = viewFactory.fieldNameWeight.getExprEvaluator();
this.agentInstanceContext = agentInstanceContext;
}
public View cloneView()
{
return viewFactory.makeView(agentInstanceContext);
}
/**
* Returns the expression supplying the X values.
* @return expression supplying X data points
*/
public final ExprNode getFieldNameX()
{
return viewFactory.fieldNameX;
}
/**
* Returns the expression supplying the weight values.
* @return expression supplying weight
*/
public final ExprNode getFieldNameWeight()
{
return viewFactory.fieldNameWeight;
}
public void update(EventBean[] newData, EventBean[] oldData)
{
if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qViewProcessIRStream(this, WeightedAverageViewFactory.NAME, newData, oldData);}
double oldValue = currentValue;
// If we have child views, keep a reference to the old values, so we can update them as old data event.
EventBean oldDataMap = null;
if (lastNewEvent == null)
{
if (this.hasViews())
{
Map oldDataValues = new HashMap();
oldDataValues.put(ViewFieldEnum.WEIGHTED_AVERAGE__AVERAGE.getName(), oldValue);
addProperties(oldDataValues);
oldDataMap = agentInstanceContext.getStatementContext().getEventAdapterService().adapterForTypedMap(oldDataValues, viewFactory.eventType);
}
}
// add data points to the bean
if (newData != null)
{
for (int i = 0; i < newData.length; i++)
{
eventsPerStream[0] = newData[i];
Number pointnum = (Number) fieldNameXEvaluator.evaluate(eventsPerStream, true, agentInstanceContext);
Number weightnum = (Number) fieldNameWeightEvaluator.evaluate(eventsPerStream, true, agentInstanceContext);
if (pointnum != null && weightnum != null) {
double point = pointnum.doubleValue();
double weight = weightnum.doubleValue();
if (Double.valueOf(sumXtimesW).isNaN())
{
sumXtimesW = point * weight;
sumW = weight;
}
else
{
sumXtimesW += point * weight;
sumW += weight;
}
}
}
if ((viewFactory.additionalProps != null) && (newData.length != 0)) {
if (lastValuesEventNew == null) {
lastValuesEventNew = new Object[viewFactory.additionalProps.getAdditionalExpr().length];
}
for (int val = 0; val < viewFactory.additionalProps.getAdditionalExpr().length; val++) {
lastValuesEventNew[val] = viewFactory.additionalProps.getAdditionalExpr()[val].evaluate(eventsPerStream, true, agentInstanceContext);
}
}
}
// remove data points from the bean
if (oldData != null)
{
for (int i = 0; i < oldData.length; i++)
{
eventsPerStream[0] = oldData[i];
Number pointnum = (Number) fieldNameXEvaluator.evaluate(eventsPerStream, true, agentInstanceContext);
Number weightnum = (Number) fieldNameWeightEvaluator.evaluate(eventsPerStream, true, agentInstanceContext);
if (pointnum != null && weightnum != null) {
double point = pointnum.doubleValue();
double weight = weightnum.doubleValue();
sumXtimesW -= point * weight;
sumW -= weight;
}
}
}
if (sumW != 0)
{
currentValue = sumXtimesW / sumW;
}
else
{
currentValue = Double.NaN;
}
// If there are child view, fireStatementStopped update method
if (this.hasViews())
{
Map newDataMap = new HashMap();
newDataMap.put(ViewFieldEnum.WEIGHTED_AVERAGE__AVERAGE.getName(), currentValue);
addProperties(newDataMap);
EventBean newDataEvent = agentInstanceContext.getStatementContext().getEventAdapterService().adapterForTypedMap(newDataMap, viewFactory.eventType);
EventBean[] newEvents = new EventBean[] {newDataEvent};
EventBean[] oldEvents;
if (lastNewEvent == null) {
oldEvents = new EventBean[] {oldDataMap};
}
else {
oldEvents = new EventBean[] {lastNewEvent};
}
if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qViewIndicate(this, WeightedAverageViewFactory.NAME, newEvents, oldEvents);}
updateChildren(newEvents, oldEvents);
if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aViewIndicate();}
lastNewEvent = newDataEvent;
}
if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aViewProcessIRStream();}
}
private void addProperties(Map newDataMap)
{
if (viewFactory.additionalProps == null) {
return;
}
viewFactory.additionalProps.addProperties(newDataMap, lastValuesEventNew);
}
public final EventType getEventType()
{
return viewFactory.eventType;
}
public final Iterator iterator()
{
Map newDataMap = new HashMap();
newDataMap.put(ViewFieldEnum.WEIGHTED_AVERAGE__AVERAGE.getName(), currentValue);
addProperties(newDataMap);
return new SingleEventIterator(agentInstanceContext.getStatementContext().getEventAdapterService().adapterForTypedMap(newDataMap, viewFactory.eventType));
}
public final String toString()
{
return this.getClass().getName() +
" fieldName=" + viewFactory.fieldNameX +
" fieldNameWeight=" + viewFactory.fieldNameWeight;
}
/**
* Creates the event type for this view.
* @param statementContext is the event adapter service
* @return event type of view
*/
public static EventType createEventType(StatementContext statementContext, StatViewAdditionalProps additionalProps, int streamNum)
{
Map schemaMap = new HashMap();
schemaMap.put(ViewFieldEnum.WEIGHTED_AVERAGE__AVERAGE.getName(), Double.class);
StatViewAdditionalProps.addCheckDupProperties(schemaMap, additionalProps, ViewFieldEnum.WEIGHTED_AVERAGE__AVERAGE);
String outputEventTypeName = statementContext.getStatementId() + "_wavgview_" + streamNum;
return statementContext.getEventAdapterService().createAnonymousMapType(outputEventTypeName, schemaMap, false);
}
public double getSumXtimesW() {
return sumXtimesW;
}
public void setSumXtimesW(double sumXtimesW) {
this.sumXtimesW = sumXtimesW;
}
public double getSumW() {
return sumW;
}
public void setSumW(double sumW) {
this.sumW = sumW;
}
public double getCurrentValue() {
return currentValue;
}
public void setCurrentValue(double currentValue) {
this.currentValue = currentValue;
}
public Object[] getLastValuesEventNew() {
return lastValuesEventNew;
}
public void setLastValuesEventNew(Object[] lastValuesEventNew) {
this.lastValuesEventNew = lastValuesEventNew;
}
public ViewFactory getViewFactory() {
return viewFactory;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy