100 lines
3.5 KiB
C#
100 lines
3.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace BCG
|
|
{
|
|
public class DerivativeStream : ViewStream
|
|
{
|
|
|
|
private IBlueTableSchema mySchema;
|
|
private string myDerivandColumn;
|
|
private string myOutputColumn;
|
|
private string myKeyColumn;
|
|
private DateTime myLastPacketArrival = DateTime.MinValue;
|
|
private ViewStream myDataSource;
|
|
|
|
private IDictionary<string, double> myPreviousValues;
|
|
|
|
|
|
public DerivativeStream(ViewStream input, string keyColumn, string columnToDifferentiate, string outputColName)
|
|
{
|
|
myDerivandColumn = columnToDifferentiate;
|
|
myOutputColumn = outputColName;
|
|
myKeyColumn = keyColumn;
|
|
myDataSource = input;
|
|
}
|
|
|
|
protected override void myOnFirstSubscriber()
|
|
{
|
|
myDataSource.onChange += myDataSource_onChange;
|
|
}
|
|
|
|
protected override void myOnLastSubscriber()
|
|
{
|
|
myDataSource.onChange -= myDataSource_onChange;
|
|
}
|
|
|
|
|
|
void myDataSource_onChange(object newValue)
|
|
{
|
|
DataPacket dp = (DataPacket)newValue;
|
|
if (myLastPacketArrival == DateTime.MinValue)
|
|
mySchema = myBuildOutputSchema(dp.schema);
|
|
else
|
|
{
|
|
DateTime now = DateTime.Now;
|
|
BlueTable thisVersion = new BlueTable(mySchema);
|
|
double timeScale = 1.0 / (now - myLastPacketArrival).TotalSeconds;
|
|
foreach (IBlueRow r in dp.newRows)
|
|
thisVersion.addRow(myMakeRow(r, timeScale));
|
|
|
|
if (myLastValue == null)
|
|
myFireEvent(new DataPacket(thisVersion, new BlueTable(mySchema), new BlueTable(mySchema)));
|
|
else
|
|
{
|
|
IBlueRowCollection deleted, added;
|
|
BlueDataUtility.computeDifferences(thisVersion, ((DataPacket)myLastValue).newRows, out deleted, out added);
|
|
myFireEvent(new DataPacket(thisVersion, added, deleted));
|
|
}
|
|
}
|
|
myStoreNewPacketInfo(dp);
|
|
}
|
|
|
|
protected IBlueRow myMakeRow(IBlueRow r, double timeScale)
|
|
{
|
|
object[] outValues = new object[mySchema.columnInfo.Length];
|
|
r.Values.CopyTo(outValues, 0);
|
|
|
|
object derivand = r[myDerivandColumn];
|
|
double lastValue = default(double);
|
|
if (myPreviousValues.TryGetValue(r[myKeyColumn].ToString(), out lastValue) && derivand != null && derivand != DBNull.Value)
|
|
outValues[mySchema.columnInfo.Length - 1] = (Convert.ToDouble(derivand) - lastValue) * timeScale;
|
|
else
|
|
outValues[mySchema.columnInfo.Length - 1] = 0.0;
|
|
return new BlueRow(mySchema, outValues);
|
|
|
|
}
|
|
|
|
protected IBlueTableSchema myBuildOutputSchema(IBlueTableSchema inSchema)
|
|
{
|
|
ColumnInfo[] cols = new ColumnInfo[inSchema.columnInfo.Length + 1];
|
|
inSchema.columnInfo.CopyTo(cols, 0);
|
|
cols[cols.Length - 1] = new ColumnInfo(myOutputColumn, cols.Length - 1, typeof(double));
|
|
return new BlueTableSchema("derviative of " + inSchema.tableName, cols);
|
|
}
|
|
protected void myStoreNewPacketInfo(DataPacket dp)
|
|
{
|
|
myPreviousValues = new Dictionary<string, double>();
|
|
myLastPacketArrival = DateTime.Now;
|
|
foreach (IBlueRow row in dp.newRows)
|
|
{
|
|
object derivand = row[myDerivandColumn];
|
|
if (derivand != null && derivand != DBNull.Value)
|
|
myPreviousValues[row[myKeyColumn].ToString()] = Convert.ToDouble(derivand);
|
|
}
|
|
}
|
|
}
|
|
}
|