//Неглубокое копирование, все свойства копируются как ссылки, parent - приписываемый владелец значения public CalcValue LinkClone(CalcParamRun parent = null) { CalcValue cv = null; switch (Type) { case CalcValueType.Var: cv = new CalcValue(VarRun); break; case CalcValueType.Single: cv = new CalcValue(SingleValue); break; case CalcValueType.IntArray: cv = new CalcValue(IntArray); break; case CalcValueType.StringArray: cv = new CalcValue(StringArray); break; case CalcValueType.Void: cv = new CalcValue(); break; } if (cv != null) { cv.Error = Error; cv.ParentParam = parent; } return(cv); }
protected override CalcValue GetValue(CalcParamRun calcRun) { if (Grafic == null) { return(new CalcValue(new SingleValue(new Moment(0.0, new ErrorCalc("Не заполнены значения графика ", _calc.Code))))); } return(calcRun.ThreadCalc.Funs.GeneralFunction(Inputs, DataType.Real, calcRun, Grafic.CalculateMean, null)); }
//Произвести расчет public void Calculate() { if (RunParam == null) { RunParam = new CalcParamRun(this, null, Owner == null ? Project.RootParam : Owner.RunParam, null); } if (ReceiverSignal != null) { ReceiverSignal.Value = RunParam.CalcValue.SingleValue; } RunParam.JoinArchiveParam(FullCode); }
protected override CalcValue GetValue(CalcParamRun calcRun) { SingleValue sv = Signal == null || Signal.SourceSignal == null ? null : Signal.SourceSignal.Value; if (!_isHand && ConstValue != null) { sv = new SingleValue(ConstValue.Clone(calcRun.ThreadCalc.PeriodBegin)); } else if (sv == null || (sv.Type == SingleType.Moment && sv.Moment == null) || (sv.Type == SingleType.List && (sv.Moments == null || sv.Moments.Count == 0))) { sv = _isHand ? new SingleValue(ConstValue.Clone(calcRun.ThreadCalc.PeriodBegin)) : new SingleValue(new List <Moment>()); } return(new CalcValue(sv, Signal)); }
protected override CalcValue GetValue(CalcParamRun calcRun) { CalcParamRun cp = calcRun; while (!cp.Vars.ContainsKey(Code)) { cp = cp.Owner; } if (IsUse) { return(cp.Vars[Code].CalcValue); } return(new CalcValue(cp.Vars[Code])); }
protected override CalcValue GetValue(CalcParamRun calcRun) { switch (Fun.CodeType) { case FunCodeType.Scalar: return(_thread.Funs.GeneralFunction(Inputs, DataType, calcRun, Fun.ScalarDelegate, null)); case FunCodeType.List: return(_thread.Funs.GeneralFunction(Inputs, DataType, calcRun, null, Fun.ListDelegate)); case FunCodeType.Array: return(Fun.ArrayDelegate(Inputs, calcRun)); } return(null); }
public FunParams(CalcParamRun calc, List <MomentValue>[] listpar, int flags) { Flags = flags; CalcParamRun = calc; ListPar = listpar; Par = new MomentValue[listpar.Length]; Current = new bool[listpar.Length]; Number = new int[listpar.Length]; if ((flags & FunFlags.Filter) != 0) { Filter = new LinkedList <MomentValue>(); FilterNd = new SortedList <int, int>(); FilterErr = new SortedList <int, int>(); } Time = calc.ThreadCalc.PeriodBegin; }
protected override CalcValue GetValue(CalcParamRun calcRun) { CalcParamRun c = calcRun; var pr = calcRun.CalcParam.Project; if (IsMet) { c = MetOwner.ParentParam; while (c != null && !c.CalcParam.Methods.ContainsKey(Code)) { c = c.CalcValue.ParentParam; } } else { while (c.CalcParam != null && !c.CalcParam.Methods.ContainsKey(Code)) { c = c.Owner; } if (c.CalcParam == null) { c = pr.RootParam; } } CalcParamRun pp; if (c.Methods.ContainsKey(Code)) { pp = c.Methods[Code]; } else { var cp = c.CalcParam == null ? pr.CalcParamsCode[Code] : c.CalcParam.Methods[Code]; var cpr = new CalcParamRun(cp, Inputs, c, calcRun); pp = cpr; } //if (pp.CalcValue == null) return new CalcValue(); var cv = pp.CalcValue; if (cv.Error != null) { cv = cv.Clone(calcRun.CalcParam.FullCode); } MetOwner = null; return(cv.LinkClone(pp)); }
//Вычисление значения, свое для каждого типа выражения //На входе стек расчета и расчетный параметр, содержащий этот Expr public void ProcessCalcValue(Stack <CalcValue> stack, CalcParamRun calcRun) { Inputs = new CalcValue[ParamsCount]; for (int i = ParamsCount - 1; i >= 0; i--) { Inputs[i] = stack.Pop(); } var em = this as ExprCalc; if (em != null && em.IsMet) { em.MetOwner = stack.Pop(); } var cv = GetValue(calcRun); //if (cv.Type != CalcValueType.Void) stack.Push(cv); Inputs = null; }
public FilterIf(FilterIf parent, CalcValue condition, CalcParamRun calc, bool isPoints) { var funs = calc.ThreadCalc.Funs; IsPoints = isPoints; var par = new CalcValue[2]; par[0] = parent.True; par[1] = condition; True = funs.GeneralFunction(par, DataType.Boolean, calc, funs.andbb, null); var parn = new[] { condition }; par[1] = funs.GeneralFunction(parn, DataType.Boolean, calc, funs.notb, null); False = funs.GeneralFunction(par, DataType.Boolean, calc, funs.andbb, null); var b = new CalcValue(new SingleValue(new Moment(true))); parn = new[] { True, b }; True = funs.GeneralFunction(parn, DataType.Boolean, calc, null, funs.deleterepetitionsub); parn = new[] { False, b }; False = funs.GeneralFunction(parn, DataType.Boolean, calc, null, funs.deleterepetitionsub); }
//Вычисление значения, свое для каждого типа выражения protected virtual CalcValue GetValue(CalcParamRun calcRun) { return(null); }
//Вычисляет значение функции Пред f от параметров par private SingleValue CalcPrev(string f, CalcValue[] par, CalcParamRun calcRun) { string acode = par[0].SingleValue.LastMoment.String; string scode = acode.Split('.')[0]; var pr = _calc.Project; var cpr = calcRun; while (cpr != pr.RootParam && !cpr.CalcParam.Methods.ContainsKey(scode)) { cpr = cpr.Owner; } while (cpr != pr.RootParam) { while (cpr.Inputs.Count != 0) { cpr = cpr.Caller; } acode = cpr.CalcParam.Code + "." + acode; cpr = cpr.Owner; } if (!pr.ArchiveParams.ContainsKey(acode)) { var err = new ErrorCalc("Не найден архивный параметр " + acode, _calc.FullCode); return(new SingleValue(new Moment(par[1].SingleValue.DataType, err))); } var beg = pr.ThreadCalc.PeriodBegin; var p1 = par[1].SingleValue.LastMoment.Clone(beg); if (f == "prevabs") { var ap = pr.ArchiveParams[acode]; var m = ((ap.AbsoluteEnd == beg && ap.AbsoluteValue != null) ? ap.AbsoluteValue : p1).Clone(); if (par.Length == 2 || !par[2].SingleValue.LastMoment.Boolean) { m.Time = beg; } return(new SingleValue(m)); } var pp = pr.PrevParams[acode]; Moment mom = null; if (f == "prev") { mom = (pp.LastBase == null || pp.LastBase.DataType == DataType.Value) ? p1 : pp.LastBase; } if (f == "prevhour") { mom = (pp.LastHour == null || pp.LastHour.DataType == DataType.Value) ? p1 : pp.LastHour; } if (f == "prevday") { mom = (pp.LastDay == null || pp.LastDay.DataType == DataType.Value) ? p1 : pp.LastDay; } if (mom != null) { return(new SingleValue(mom.Clone(beg))); } if (f == "prevmom") { return(new SingleValue(pp.ManyMoments.Where(m => beg.Subtract(m.Time).TotalMinutes <= p1.Real).ToList())); } if (f == "prevperiod") { return(new SingleValue(pp.ManyBase.Where(m => beg.Subtract(m.Time).TotalMinutes <= p1.Real).ToList())); } if (f == "prevhourperiod") { return(new SingleValue(pp.ManyHour.Where(m => beg.Subtract(m.Time).TotalHours <= p1.Real).ToList())); } if (f == "prevdayperiod") { return(new SingleValue(pp.ManyDay.Where(m => beg.Subtract(m.Time).TotalDays <= p1.Real).ToList())); } return(null); }
protected override CalcValue GetValue(CalcParamRun calcRun) { switch (Code) { case "void": return(new CalcValue()); case "owner": var cv = calcRun.Owner.CalcValue; if (cv.ParentParam == null) { cv = cv.LinkClone(calcRun.Owner); } return(cv); case "caller": return(new CalcValue { ParentParam = calcRun.Caller }); case "getelement": if (Inputs[1].Type != CalcValueType.Single || Inputs[1].SingleValue.Type != SingleType.Moment) { return(new CalcValue(new SingleValue(new Moment(false, new ErrorCalc("Индекс массива должен быть отдельным значением", _calc.Code))))); } Moment m = Inputs[1].SingleValue.Moment; if (m.DataType.LessOrEquals(DataType.Integer)) { if (Inputs[0].IntArray == null || !Inputs[0].IntArray.ContainsKey(m.Integer)) { return(new CalcValue(new SingleValue(new Moment(false, new ErrorCalc("Несуществующий индекс массива (" + m.Integer + ")", _calc.Code))))); } return(Inputs[0].IntArray[m.Integer].CalcValue); } if (Inputs[0].StringArray == null || !Inputs[0].StringArray.ContainsKey(m.String)) { return(new CalcValue(new SingleValue(new Moment(false, new ErrorCalc("Несуществующий индекс массива (" + m.String + ")", _calc.Code))))); } return(Inputs[0].StringArray[m.String].CalcValue); case "signal": try { return(Inputs[0].Signal.Object.Signals[Inputs[1].SingleValue.LastMoment.String].CalcValue); } catch { return(new CalcValue(new SingleValue(new Moment(false, new ErrorCalc("Недопустимые параметры функции Сигнал", _calc.Code))))); } case "signalbool": case "signalint": case "signalreal": case "signalstring": string c = Inputs[0].SingleValue.LastMoment.String ?? ""; CalcUnit sig = null; if (_calc.Project.SignalsSources.ContainsKey(c)) { sig = _calc.Project.SignalsSources[c]; } if (_calc.Project.Objects.ContainsKey(c)) { sig = _calc.Project.Objects[c].DefaultSignal; } if (sig == null || !sig.DataType.LessOrEquals(Code.Substring(6).ToDataType())) { return(new CalcValue(new SingleValue(new Moment(false, new ErrorCalc("Строка задает несуществующий сигнал или сигнал недопустимого типа (" + c + ")", _calc.Code))))); } return(sig.CalcValue); case "takecode": case "takename": case "takeunits": case "taketask": case "takecomment": case "takecodesignal": case "takenamesignal": CalcParam cp = null; if (Inputs.Length == 0) { cp = _calc; } else if (Inputs[0].ParentParam != null) { cp = Inputs[0].ParentParam.CalcParam; } else if (Inputs[0].Signal != null) { var si = Inputs[0].Signal; return(new CalcValue(new SingleValue(new Moment(calcRun.ThreadCalc.PeriodBegin, Code == "takecode" ? si.CodeObject : Code == "takecodesignal" ? si.CodeSignal : Code == "takename" ? si.NameObject : Code == "takenamesignal" ? si.NameSignal : si.Units)))); } if (cp != null) { return(new CalcValue(new SingleValue(new Moment(calcRun.ThreadCalc.PeriodBegin, Code == "takecode" ? cp.Code : Code == "takename" ? cp.Name : Code == "taketask" ? cp.Task : Code == "takecomment" ? cp.Comment : cp.Units)))); } return(new CalcValue(new SingleValue(new Moment(false, new ErrorCalc("Параметр функции получения характеристики не задает расчетный параметр или сигнал", _calc.Code))))); case "prevabs": case "prevmom": case "prev": case "prevperiod": case "prevhour": case "prevhourperiod": case "prevday": case "prevdayperiod": return(new CalcValue(CalcPrev(Code, Inputs, calcRun))); } return(null); }
protected override CalcValue GetValue(CalcParamRun calcRun) { string s = Inputs.Length == 0 ? Code : Inputs[0].SingleValue.LastMoment.String + "." + Code; return(new CalcValue(new SingleValue(new Moment(calcRun.ThreadCalc.PeriodBegin, s)))); }
//calc - CalcParam с формулой для расчета, inputs - список входных значений //owner - владелец, caller - параметр, из которого вызывается public CalcParamRun(CalcParam calc, CalcValue[] inputs, CalcParamRun owner, CalcParamRun caller) { CalcParam = calc; Owner = owner; Caller = caller; if (inputs == null || inputs.Length == 0) { Owner.Methods.Add(calc.Code, this); if (calc.IsNotObject) { calc.RunParam = this; } } StackDepth = caller == null ? 1 : caller.StackDepth + 1; if (StackDepth > 500) { CalcValue = new CalcValue(new SingleValue(new Moment(DataType.Value, new ErrorCalc("Переполнение стека", CalcParam.FullCode)))); return; } foreach (var k in calc.Vars.Keys) { Vars.Add(k, new VarRun(calc.Vars[k])); } if (inputs != null) { for (int i = 0; i < inputs.Length; i++) { VarRun v = Vars[calc.Inputs[i]]; v.CalcValue = inputs[i]; Inputs.Add(v); } } ThreadCalc = CalcParam.Project.ThreadCalc; //Сразу производится расчет Calculate(); //Добавление ошибок расчета в проект if (CalcParam.Inputs.Count == 0) { var errors = CalcParam.Project.CalcErrors; if (CalcValue.Type != CalcValueType.Single) { if (CalcValue.Error != null) { errors.Add(CalcValue.Error); } } else { var sv = CalcValue.SingleValue; if (sv.Moment != null && sv.Moment.Error != null) { errors.Add(sv.Moment.Error); } if (sv.Moments != null) { foreach (var m in sv.Moments) { if (m.Error != null) { errors.Add(m.Error); break; } } } if (sv.Segments != null) { foreach (var seg in sv.Segments) { if (seg.Error != null) { errors.Add(seg.Error); break; } } } } } }
protected override CalcValue GetValue(CalcParamRun calcRun) { return(new CalcValue(new SingleValue(_moment.Clone(_thread.PeriodBegin)))); }
//Вычисление значения функций типа scalar и list public CalcValue GeneralFunction(CalcValue[] par, DataType dt, CalcParamRun calc, ScalarDelegate scalar, ListDelegate fun) { bool isScalar = scalar != null; int n = par.Count(); _calc = calc.CalcParam; Begin = calc.ThreadCalc.PeriodBegin; End = calc.ThreadCalc.PeriodEnd; _interpol = _calc.Interpolation; var sv = new SingleValue[n]; int ki = 0, ks = 0; for (int i = 0; i < n; i++) { var cvt = par[i].Type; if (ki == 0 && cvt == CalcValueType.IntArray) { ki = i; } if (ks == 0 && cvt == CalcValueType.StringArray) { ks = i; } if (cvt != CalcValueType.IntArray && cvt != CalcValueType.StringArray) { sv[i] = par[i].SingleValue; } } if (ki == 0 && ks == 0)//Нет массивов { if (isScalar) { return(new CalcValue(ScalarFunction(sv, dt, scalar))); } var ss = new SingleValue(); foreach (var s in sv) { ss.Error |= s.Error; } fun(sv, ss); if (ss.Type != SingleType.Segments && ss.Moment == null && ss.Moments == null) { ss.Moments = new List <Moment>(); } if (ss.Type == SingleType.Segments && ss.Segments == null) { ss.Segments = new List <Segment>(); } return(new CalcValue(ss)); } var cv = new CalcValue[n]; if (ki > 0)//Массивы с целыми индексами { var resi = new CalcValue(new SortedDictionary <int, VarRun>()); foreach (var key in par[ki].IntArray.Keys) { bool e = true; for (int i = 0; i < n; i++) { var p = par[i]; if (p.Type == CalcValueType.StringArray || (p.Type == CalcValueType.IntArray && !p.IntArray.ContainsKey(key))) { e = false; } else if (p.Type == CalcValueType.IntArray) { cv[i] = p.IntArray[key].CalcValue; } else { cv[i] = p; } } if (e) { var c = GeneralFunction(cv, dt, calc, scalar, fun); resi.Error |= c.Error; resi.IntArray.Add(key, new VarRun(c)); } } return(resi); } //Массивы со строковыми индексами var ress = new CalcValue(new SortedDictionary <int, VarRun>()); foreach (var key in par[ki].StringArray.Keys) { bool e = true; for (int i = 0; i < n; i++) { var p = par[i]; if (p.Type == CalcValueType.IntArray || (p.Type == CalcValueType.StringArray && !p.StringArray.ContainsKey(key))) { e = false; } else if (p.Type == CalcValueType.StringArray) { cv[i] = p.StringArray[key].CalcValue; } else { cv[i] = p; } } if (e) { var c = GeneralFunction(cv, dt, calc, scalar, fun); ress.Error |= c.Error; ress.StringArray.Add(key, new VarRun(c)); } } return(ress); }
public ParamVal(CalcParamRun calcRun, ErrMom err = null) { _val = calcRun.Value; CalcParam = calcRun.CalcParam; _error = err; }
//Расчет по всем формулам public void Calculate() { try { CalcErrors.Clear(); RootParam = new CalcParamRun(); int n = CalcParamsId.Count, i = 0; foreach (var c in CalcParamsId.Values) { if (c == null) { AddError("Список расчетных параметров загружен с ошибками, необходима повторная компиляция расчета"); } else { c.RunParam = null; foreach (var m in c.Methods.Values) { if (m == null) { AddError("Список расчетных параметров загружен с ошибками, необходима повторная компиляция расчета"); } else { m.RunParam = null; } } } } if (IsError) { return; } foreach (var c in CalcParamsId.Values) { if (c.IsNotObject) { c.Calculate(); foreach (var m in c.Methods.Values) { if (m.IsNotObject) { m.Calculate(); } } } if (IsError) { return; } if (n > 40 && ++i % (n / 20) == 0) { Procent = 80.0 * i / n; } } //Запись ошибок расчета в лог var count = CalcErrors.Count; if (count > 0) { string s = ""; int j = 0; while (j < 10 && j < count) { s += (s == "" ? "" : ", ") + CalcErrors[j++].Address; } string p = count % 10 == 1 ? "параметр" : (count % 10 == 2 || count % 10 == 3 || count % 10 == 4 ? "параметра" : "параметров"); AddWarning("При расчете произошли ошибки", null, count + " " + p + " с ошибками: " + s + (j < count ? " и др." : "")); } AddEvent("Объем используемой памяти", GC.GetTotalMemory(false).ToString()); } catch (OutOfMemoryException ex) { AddEvent("Объем используемой памяти", GC.GetTotalMemory(false).ToString()); AddError("Ошибка при расчете", ex); throw; } catch (Exception ex) { AddError("Ошибка при расчете", ex); } }
//Сохранение одного параметра или одной переменной, возвращает словарь ключи - коды переменных, значения - величичны //code - полный код для для записи в DebugParams //debugType - Параметр, Подпараметр, Объект, Переменная, Сигнал, paramId - id параметра или подпараметра, для остальных 0 //c - расчетный параметр, v - переменная, всегда одно из двух, level - уровень вложенности, //saveToRec - сохранять в рекордсет и переменные, если false, то сам параметр не сохраняется но могут сохраняться его подпараметры и переменные public Dictionary <string, string> SaveValues(string code, string debugType, int paramId, CalcParamRun c, VarRun v, int level, bool saveToRec = true) { if (level > 3) { return(null); } var dic = new Dictionary <string, string>(); CalcValue cv; string adderr = ""; if (v != null) { cv = v.CalcValue; } else { if (c == null || c.CalcValue == null) { return(null); } if (_thread.IsSaveProperties) { foreach (var met in c.Methods.Values) { bool e = met.CalcParam.IsNotObject; AddDic(dic, SaveValues(code + "." + met.CalcParam.Code, e ? "Подпараметр" : "Порождаемый", e ? met.CalcParam.Id : 0, met, null, level + 1), met.CalcParam.Code); if (met.CalcValue.Error != null && adderr.IsEmpty()) { adderr = "Ошибки в " + (e ? "" : "порожденных ") + "подпараметрах"; } } } if (_thread.IsSaveVariables) { foreach (var vr in c.Vars.Dic) { if (vr.Key != "calc" || (c.CalcValue.Type == CalcValueType.Single && c.CalcValue.SingleValue != vr.Value.CalcValue.SingleValue)) { AddDic(dic, SaveValues(code + "." + vr.Key, "Переменная", 0, null, vr.Value, level + 1), vr.Key); } } } cv = c.CalcValue; } if (cv != null) { switch (cv.Type) { case CalcValueType.Void: case CalcValueType.Single: if ((saveToRec && cv.SingleValue != null) || !adderr.IsEmpty()) { ValuesToRec(code, debugType, paramId, dic, cv.SingleValue ?? new SingleValue(), adderr); dic.Add("", SvToStr(cv.SingleValue)); } break; case CalcValueType.IntArray: foreach (var a in cv.IntArray) { AddDic(dic, SaveValues(code + "[" + a.Key + "]", "Переменная", 0, null, a.Value, level + 1), null); } break; case CalcValueType.StringArray: foreach (var a in cv.StringArray) { AddDic(dic, SaveValues(code + "[" + a.Key + "]", "Переменная", 0, null, a.Value, level + 1), null); } break; } if (cv.ParentParam != null && cv.ParentParam.Inputs.Count != 0) { if (c == cv.ParentParam) { ValuesToRec(code, debugType, paramId, dic, new SingleValue()); } else { AddDic(dic, SaveValues(code + ":" + cv.ParentParam.CalcParam.Code, debugType, paramId, cv.ParentParam, null, level, false), null); } } } return(dic); }