using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using CategoryTheory;
using DiagramUI;
using DiagramUI.Interfaces;
using DiagramUI.Labels;
using DataPerformer.Interfaces;
using DataPerformer.Abstract;
using DataPerformer.Helpers;
namespace DataPerformer.Advanced.Accumulators
{
/// <summary>
/// Base class for all accumulatotrs
/// </summary>
public class AccumulatorBase : AbstractDataTransformer,
ISerializable, ITimeMeasureProvider, IBlocking, IPostSetArrow
{
#region Fields
/// <summary>
/// Time measure
/// </summary>
protected IMeasure timeMeasure;
/// <summary>
/// Time
/// </summary>
protected double time;
/// <summary>
/// Type of variable
/// </summary>
static private readonly Double a = 0;
/// <summary>
/// Array of arguments
/// </summary>
protected double[] arg;
/// <summary>
/// Table of time functions
/// </summary>
Dictionary<IMeasure, TimeFunction> functions = new Dictionary<IMeasure, TimeFunction>();
/// <summary>
/// Dependent daca consumers
/// </summary>
private IList dep;
/// <summary>
/// Updatable objects
/// </summary>
private List<IUpdatableObject> upd = new List<IUpdatableObject>();
/// <summary>
/// Consumers
/// </summary>
private List<IDataConsumer> consumers = new List<IDataConsumer>();
/// <summary>
/// Dynamical
/// </summary>
private List<IDynamical> dyn = new List<IDynamical>();
private List<IStep> steps = new List<IStep>();
/// <summary>
/// Degree of interpolation
/// </summary>
private int degree = 1;
/// <summary>
/// The "is active" sign
/// </summary>
private bool isActive = true;
/// <summary>
/// Block
/// </summary>
private bool block = false;
/// <summary>
/// Processor
/// </summary>
private IDifferentialEquationProcessor processor;
/// <summary>
/// Step
/// </summary>
protected double step;
/// <summary>
/// Runtime wrapper
/// </summary>
protected RuntimeWrapper rtw;
/// <summary>
/// Bloked sign
/// </summary>
protected bool blocked = false;
#endregion
#region Ctor
/// <summary>
/// Default constructor
/// </summary>
protected AccumulatorBase()
{
rtw = new RuntimeWrapper(this);
processor = new InternalRungeProcessor(this);
timeMeasure = new MeasureDerivation(a, new Func<object>(GetTime), new ConstantMeasure(1), "Time");
}
/// <summary>
/// Deserialization constructor
/// </summary>
/// <param name="info">Serialization info</param>
/// <param name="context">Streaming context</param>
protected AccumulatorBase(SerializationInfo info, StreamingContext context)
: this()
{
try
{
Degree = (int)info.GetValue("Degree", typeof(int));
isActive = (bool)info.GetValue("IsActive", typeof(bool));
}
catch (Exception ex)
{
ex.Log();
}
}
#endregion
#region IPostSetArrow Members
void IPostSetArrow.PostSetArrow()
{
Post();
}
#endregion
#region ISerializable Members
/// <summary>
/// ISerializable interface implementation
/// </summary>
/// <param name="info">Serialization info</param>
/// <param name="context">Streaming context</param>
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Degree", degree, typeof(int));
info.AddValue("IsActive", isActive, typeof(bool));
}
#endregion
#region ITimeMeasureProvider Members
IMeasure ITimeMeasureProvider.TimeMeasure
{
get { return timeMeasure; }
}
double ITimeMeasureProvider.Time
{
get
{
return time;
}
set
{
time = value;
}
}
double ITimeMeasureProvider.Step
{
get
{
return step;
}
set
{
step = value;
}
}
#endregion
#region IBlocking Members
bool IBlocking.Blocked
{
get
{
return blocked;
}
set
{
blocked = value;
}
}
#endregion
#region Specific Members
#region Overriden Members
/// <summary>
/// Updates measurements data
/// </summary>
public override void UpdateMeasurements()
{
Update();
}
#endregion
#region Public
/// <summary>
/// Approximation degree
/// </summary>
public int Degree
{
get
{
return degree;
}
set
{
degree = value;
SetDegree();
}
}
/// <summary>
/// The "is active" sign
/// </summary>
public bool IsActive
{
get
{
return isActive;
}
set
{
isActive = value;
}
}
#endregion
#region Protected
/// <summary>
/// Post operation
/// This funtion is called afrer editing of propreties
/// </summary>
protected virtual void Post()
{
//TimeMeasurePerformer.SetProvider(this);
//measurementsOut.Clear();
functions.Clear();
List<IMeasure> measures = new List<IMeasure>();
for (int i = 0; i < measurements.Count; i++)
{
Perform(measurements[i], measures);
}
dep = this.GetDependentObjects();
consumers.Clear();
upd.Clear();
dyn.Clear();
steps.Clear();
foreach (object o in dep)
{
Add(o);
}
mea = measures.ToArray();
Degree = degree;
}
#endregion
#region Private
private void SetDegree()
{
foreach (TimeFunction f in functions.Values)
{
f.Degree = degree;
}
}
private object GetTime()
{
return time;
}
void Add(object o)
{
if (o == null)
{
return;
}
if (o is IDataConsumer)
{
IDataConsumer c = o as IDataConsumer;
if (!consumers.Contains(c))
{
consumers.Add(c);
}
}
if (o is IUpdatableObject)
{
IUpdatableObject u = o as IUpdatableObject;
if (!upd.Contains(u))
{
upd.Add(u);
}
}
if (o is IDynamical)
{
IDynamical d = o as IDynamical;
if (!dyn.Contains(d))
{
dyn.Add(d);
}
}
if (o is IStep)
{
IStep s = o as IStep;
s.Step = 0;
if (!steps.Contains(s))
{
steps.Add(s);
}
}
if (o is IChildrenObject)
{
IChildrenObject ch = o as IChildrenObject;
IAssociatedObject[] objs = ch.Children;
foreach (object obj in objs)
{
Add(obj);
}
}
if (o is MeasurementsWrapper)
{
MeasurementsWrapper mw = o as MeasurementsWrapper;
int n = mw.Count;
for (int i = 0; i < n; i++)
{
Add(mw[i]);
}
}
}
private void Perform(IMeasurements m, List<IMeasure> measures)
{
string s = "";
if (m is IAssociatedObject)
{
IAssociatedObject ao = m as IAssociatedObject;
s = this.GetRelativeName(ao);
s = s.Replace("/", "_");
}
for (int i = 0; i < m.Count; i++)
{
Perform(m[i], s, measures);
}
}
private void Perform(IMeasure m, string str, List<IMeasure> measures)
{
string s = str + "_" + m.Name;
TimeFunction func = new TimeFunction(arg.Length, m.Type);
functions[m] = func;
IMeasure mea = new Measure(func, FuncMeasure.createParameter(func), s);
measures.Add(mea);
}
private void Update()
{
if (blocked)
{
return;
}
this.ForEach<IStack>(delegate(IStack s)
{
s.Push();
});
ITimeMeasureProvider old = processor.TimeProvider;
processor.TimeProvider = this;
if (!IsActive)
{
return;
}
if (block)
{
//return;
}
block = true;
using (TimeProviderBackup tb = new TimeProviderBackup(this, this, processor, 0))
{
IDataConsumer th = this;
double last;
if (arg == null)
{
return;
}
if (IsUpdated)
{
return;
}
double st = arg[0];
last = st;
foreach (IStep s in steps)
{
s.Step = -1;
}
//IDifferentialEquationProcessor processor = DifferentialEquationProcessor.Processor;
if (processor != null)
{
INamedComponent nc = Object as INamedComponent;
rtw.Runtime.StartAll(arg[0]);
// processor.Set(this.GetDesktop());
}
for (int i = 0; i < arg.Length; i++)
{
if (i == 0)
{
start(arg[0]);
}
foreach (IUpdatableObject u in upd)
{
u.UpdateObject();
}
time = arg[i];
if (i > 0 & processor != null)
{
processor.Step(last, time);
}
foreach (IDynamical d in dyn)
{
d.Time = time;
}
foreach (IStep s in steps)
{
s.Step = i;
}
th.UpdateChildrenData();
foreach (IMeasure m in functions.Keys)
{
object o = m.Parameter();
TimeFunction f = functions[m];
f.Set(i, time, o);
}
this.FullReset();
last = time;
}
}
this.ForEach<IStack>((IStack s) =>
{
s.Pop();
});
processor.TimeProvider = old;
block = false;
}
private int Step
{
set
{
foreach (object o in dep)
{
if (o is IStep)
{
IStep s = o as IStep;
s.Step = value;
}
}
}
}
private void start(double time)
{
foreach (object o in dep)
{
if (o is IStarted)
{
IStarted s = o as IStarted;
s.Start(time);
}
}
}
#endregion
#endregion
#region Additional classes
#region Functional Measure
class FuncMeasure
{
TimeFunction func;
private FuncMeasure(TimeFunction func)
{
this.func = func;
}
private object calc()
{
return func;
}
internal static Func<object> createParameter(TimeFunction f)
{
FuncMeasure fm = new FuncMeasure(f);
return fm.calc;
}
}
#endregion
#region Internal Runge Processor
class InternalRungeProcessor : RungeProcessor
{
#region Fields
AccumulatorBase accumulator;
#endregion
internal InternalRungeProcessor(AccumulatorBase accumulator)
{
this.accumulator = accumulator;
}
public override void UpdateMeasurements()
{
if (Dim > 0)
{
try
{
foreach (IMeasurements m in measurements)
{
if (m == accumulator)
{
continue;
}
m.UpdateMeasurements();
}
foreach (INormalizable n in norm)
{
n.Normalize();
}
}
catch (Exception e)
{
e.Log();
this.Throw(e);
}
}
}
}
#endregion
#endregion
}
}