コード例 #1
0
        public Polskaya(PolskaParams polskaParams,
                        IDBInterfaceAdapter nameInterface,
                        IFormulaArchivesPrecalculator formulaArchivesPrecalculator,
                        Dictionary <string, Variable> variablesDict)
        {
            _polskaParams = polskaParams;

            NameInterface = nameInterface;

            _operationStack = new List <PolskayaVariable>(MemoryAllockStep_bytes);
            OutString       = new List <PolskayaVariable>();
            Expression      = new StringBuilder();
            _variablesDict  = variablesDict;

            #region Ф-ии

            CreateFunction(new MinFunction());
            CreateFunction(new MaxFunction());
            CreateFunction(new SinFunction());
            CreateFunction(new CosFunction());
            CreateFunction(new PowFunction());
            CreateFunction(new ExpFunction());
            CreateFunction(new LogFunction());
            CreateFunction(new IfFunction());
            CreateFunction(new MacroIfFunction());
            CreateFunction(new RoundFunction());
            CreateFunction(new ValueStatusCodeContains());
            CreateFunction(new ValueStatusCodeContainsAllAlarmStatuses());

            #endregion

            // Добавляем возможность использовать пользовательский функции
            CreateFunction(new GetHalfHourIndex());
            CreateFunction(new UserDefinedSQLFunction(nameInterface));
            CreateFunction(new UserDefinedCSharpFunction());
            CreateFunction(new GetHalfHourDateTime());

            CreateFunction(new AbsFunction());

            #region Добавление ф-ий которые требуют предварительной подгрузки данных

            _precalculatedFunctionDict = new Dictionary <string, PrecalculatedFunctionVariable>();
            foreach (var precalculatedFormulasFunction in Enum.GetNames(typeof(EnumFormulasFunction))
                     .Select(s => (EnumFormulasFunction)Enum.Parse(typeof(EnumFormulasFunction), s)).Select(
                         formulasFunction =>
                         formulasFunction.CreatePrecalculatedFormulasFunctionDescription(formulaArchivesPrecalculator)))
            {
                _precalculatedFunctionDict[precalculatedFormulasFunction.Id] = precalculatedFormulasFunction;
            }

            _precalculatedFunctionBooleanDict = new Dictionary <string, Function>();
            var f = new IfEnabledFunction();
            _precalculatedFunctionBooleanDict[f.id] = f;



            #endregion
        }
コード例 #2
0
        /// <summary>
        /// Проверка формулы
        /// </summary>
        /// <param name="formulaParams">формула</param>
        /// <param name="dataSourceType">Источник данных</param>
        public void CheckFormula(IFormulaParam formulaParams)
        {
            _recursionCallStack.Clear();
            int?tpId = null;

            if (formulaParams.tP_CH_ID != null)
            {
                tpId = formulaParams.tP_CH_ID.TP_ID;
            }
            var formula = GetFormulaByID(formulaParams.FormulaID);

            var polskaParams = new PolskaParams(formula.F_ID, _formulasTable, formulaParams.StartDateTime, formulaParams.FinishDateTime.GetValueOrDefault(),
                                                enumTimeDiscreteType.DBHalfHours, 1, null);

            var parser = ComposeExpressionPolskaya(formula, polskaParams, 0, 1, 1, false);

            parser.EvaluateStringValue(0);
        }
コード例 #3
0
        /// <summary>
        /// Делаем расчет по формуле
        /// </summary>
        /// <param name="formulaId">Идентификатор формулы</param>
        /// <param name="inDataTI">Данные по ТИ</param>
        /// <param name="inDataIntegrals">Интегральные данные</param>
        /// <param name="inDataTP">Данные по ТП</param>
        /// <param name="inDataSection">Данные по сечению</param>
        /// <param name="indxStart">Начальный индекс, с которого формула активна</param>
        /// <param name="indxEnd">Конечный индекс</param>
        /// <param name="unitDigitCoeff">Коэфф. дорасчета ед. измерения</param>
        /// <param name="formulaTPType">Тип формулы ТП</param>
        /// <param name="formulasTable">Табличный тип формулы (обычная или ТП)</param>
        /// <param name="tpId">Идентификатор ТП к которой привязана формула</param>
        /// <param name="rangeInSectionForEntirePeriod">Используется ли формула в сечении, где действует ограничение на период действия ТП</param>
        /// <param name="rangeIndexesInSectionList">Индексы с которого действуют ТП в сечении</param>
        /// <param name="hiHiSetpoint">Верхняя уставка, по которой проверяем формулу</param>
        /// <param name="loLoSetpoint">Нижняя уставка, по которой проверяем формулу</param>
        /// <param name="inFormulaConstants">Данные по константам, используемым в формуле</param>
        /// <param name="formulasDisabledPeriods">Индексы получасовок между которыми формула не считается</param>
        /// <returns></returns>
        public List <TVALUES_DB> InterpretFormula(string formulaId
                                                  , bool isSumm
                                                  , int indxStart, int indxEnd, double unitDigitCoeff, enumClientFormulaTPType formulaTPType,
                                                  enumFormulasTable formulasTable, bool rangeInSectionForEntirePeriod = true,
                                                  IEnumerable <IPeriodIndexesTpInSection> rangeIndexesInSectionList   = null, double?hiHiSetpoint = null, double?loLoSetpoint = null,
                                                  IEnumerable <IFormulasDisabledPeriod> formulasDisabledPeriods       = null,
                                                  string measureUnitUn = null, PeriodFactory manualEnteredHalfHourIndexes = null)
        {
            var isCalculateBetweenIndexes = !InterpretatorParams.TechProfilePeriod.HasValue && (indxStart > 0 || indxEnd < (InterpretatorParams.NumbersHalfHours - 1));

            var isExistDisablePeriod = formulasDisabledPeriods != null && formulasDisabledPeriods.ToList().Count > 0;

            _recursionCallStack.Clear();

            double?coeff;

            if (string.IsNullOrEmpty(measureUnitUn))
            {
                if (unitDigitCoeff > 1)
                {
                    coeff = 1 / unitDigitCoeff;
                    if (InterpretatorParams.TypeInformation == enumTypeInformation.Power)
                    {
                        coeff *= 2;
                    }
                }
                else if (InterpretatorParams.TypeInformation == enumTypeInformation.Power)
                {
                    coeff = 2;
                }
                else
                {
                    coeff = null;
                }
            }
            else
            {
                coeff = null;
            }

            _formulasTable = formulasTable;

            var formula = GetFormulaByID(formulaId);

            var polskaParams = new PolskaParams(formula.F_ID, _formulasTable,
                                                InterpretatorParams.StartDateTime, InterpretatorParams.EndDateTime, InterpretatorParams.DiscreteType, InterpretatorParams.NumbersHalfHours, formula.UnitDigit, InterpretatorParams.TechProfilePeriod.HasValue);

            var parser = ComposeExpressionPolskaya(formula, polskaParams, indxStart, indxEnd, InterpretatorParams.NumbersHalfHours, isCalculateBetweenIndexes);

            parser.Compile();

            //var result = new List<TVALUES_DB>();

            using (var accamulator = new FormulaAccamulator(InterpretatorParams.IntervalTimeList, isSumm, formula.UnitDigit))
            {
                //Считаем всегда по получасовкам
                for (var halfHourIndex = 0; halfHourIndex < InterpretatorParams.NumbersHalfHours; halfHourIndex++)
                {
                    // рассчет по формуле
                    if (!isCalculateBetweenIndexes || halfHourIndex >= indxStart && halfHourIndex <= indxEnd)
                    {
                        #region Ограничиваем диапазоном в сечении

                        if (!rangeInSectionForEntirePeriod)
                        {
                            if (!rangeIndexesInSectionList.Any(range => range.StartIndex <= halfHourIndex && (range.FinishIndex ?? InterpretatorParams.NumbersHalfHours - 1) >= halfHourIndex))
                            {
                                accamulator.Accamulate(0, VALUES_FLAG_DB.TpNotInSectionRange, enumClientFormulaTPType.TpNotInSectionRange);
                                continue;
                            }
                        }

                        #endregion

                        #region Ограничиваем когда формула заблокирована напряму таблицей Info_Formula_DisabledPeriod

                        if (isExistDisablePeriod)
                        {
                            if (formulasDisabledPeriods.Any(range => halfHourIndex >= range.StartIndx && halfHourIndex <= range.FinishIndx))
                            {
                                accamulator.Accamulate(0, VALUES_FLAG_DB.FormulaNotInRange);
                                //result.Add(new Formula_VALUES_DB(VALUES_FLAG_DB.FormulaNotInRange, 0));
                                continue;
                            }
                        }

                        #endregion

                        #region Ограничиваем периодами, когда данные были введены вручную (считать не нужно)

                        if (manualEnteredHalfHourIndexes != null && manualEnteredHalfHourIndexes.HavePeriod(halfHourIndex))
                        {
                            //result.Add(new Formula_VALUES_DB(VALUES_FLAG_DB.None, 0));
                            accamulator.Accamulate(0, VALUES_FLAG_DB.None);
                            continue;
                        }

                        #endregion

                        var val = parser.EvaluateStringValue(halfHourIndex);

                        #region Обрабатываем уставки

                        if (hiHiSetpoint.HasValue && val.F_VALUE >= hiHiSetpoint)
                        {
                            val.F_FLAG |= VALUES_FLAG_DB.HiHiSetpointExcess;
                        }
                        if (loLoSetpoint.HasValue && val.F_VALUE <= loLoSetpoint)
                        {
                            val.F_FLAG |= VALUES_FLAG_DB.LoLoSetpointExcess;
                        }

                        #endregion

                        //Учитываем что это мощность или размерность (кило, мега и т.д.)
                        if (coeff.HasValue)
                        {
                            val.F_VALUE *= coeff.Value;
                        }

                        val.FormulaTPType = formulaTPType;

                        accamulator.Accamulate(val.F_VALUE, val.F_FLAG, formulaTPType);
                        //result.Add(val.F_VALUE, val.F_FLAG);
                    }
                    else
                    {
                        accamulator.Accamulate(0, VALUES_FLAG_DB.FormulaNotInRange, enumClientFormulaTPType.NotInRange);
                        //Ограничения по времени действия формулы
                        //result.Add(new Formula_VALUES_DB(VALUES_FLAG_DB.FormulaNotInRange, 0, enumClientFormulaTPType.NotInRange));
                    }
                }

                return(accamulator.Result);
            }

            //return result;
        }
コード例 #4
0
        private Polskaya ComposeExpressionPolskaya(FORMULA f, PolskaParams polskaParams
                                                   , int indxStart, int indxEnd, int numbersHalfHours, bool isCalculateBetweenIndexes = true)
        {
            var parser = new Polskaya(polskaParams, _nameInterface, _formulaArchivesPrecalculator, _variablesDict);

            if (_recursionCallStack.Contains(f.F_ID))
            {
                throw new FormulaParseException("Обнаружена рекурсия формулы\n[" + GetOperNameFromDB(f.F_ID, F_OPERATOR.F_OPERAND_TYPE.Formula, null) + "]");
            }
            _recursionCallStack.Add(f.F_ID);

            foreach (F_OPERATOR operators in f.F_OPERATORS)
            {
                switch (operators.OPER_TYPE)
                {
                case F_OPERATOR.F_OPERAND_TYPE.Section:
                case F_OPERATOR.F_OPERAND_TYPE.TP_channel:
                case F_OPERATOR.F_OPERAND_TYPE.ContrTI_Chanel:
                case F_OPERATOR.F_OPERAND_TYPE.Integral_Channel:
                case F_OPERATOR.F_OPERAND_TYPE.TI_channel:
                case F_OPERATOR.F_OPERAND_TYPE.FormulaConstant:
                case F_OPERATOR.F_OPERAND_TYPE.UANode:

                    if (!parser.ContainsVariable(operators.Name))
                    {
                        Variable var;
                        if (Archives == null)
                        {
                            // режим поиска параметров и проверки правильности
                            var = new Variable(operators.Name, indxStart, indxEnd, isCalculateBetweenIndexes: isCalculateBetweenIndexes);
                        }
                        else
                        {
                            IGetAchives data = Archives.GetArchiveByOperandType(operators);
                            if (data == null && !Archives.IsArchTech)
                            {
                                if (operators.OPER_TYPE == F_OPERATOR.F_OPERAND_TYPE.TP_channel)
                                {
                                    throw new FormulaParseException("Расчет формулы невозможен. Не найдено значение для ТП \"" +
                                                                    GetOperNameFromDB(operators.OPER_ID, operators.OPER_TYPE, operators.TI_CHANNEL) + "\"\nНе описан канал или не найдена для него формула.");
                                }

                                throw new FormulaParseException("Расчет формулы невозможен. Отсутствуют значения для \"" +
                                                                GetOperNameFromDB(operators.OPER_ID, operators.OPER_TYPE, operators.TI_CHANNEL) + "\"\n из формулы <" + GetOperNameFromDB(f.F_ID, F_OPERATOR.F_OPERAND_TYPE.Formula, null) + ">");
                            }

                            var = new Variable(operators.Name, indxStart, indxEnd, data, operators.TI_CHANNEL, isCalculateBetweenIndexes);
                        }

                        parser.CreateVariable(var);
                    }

                    parser.Expression.Append(operators.PRE_OPERANDS ?? "").Append(operators.Name).Append(operators.AFTER_OPERANDS ?? "");
                    break;

                case F_OPERATOR.F_OPERAND_TYPE.Formula:
                    parser.Expression.Append(operators.PRE_OPERANDS ?? "").Append(operators.Name).Append(operators.AFTER_OPERANDS ?? "");
                    if (!parser.ContainsVariable(operators.Name))
                    {
                        var innerFId = GetFormulaByID(operators.OPER_ID);
                        if (innerFId != null)
                        {
                            var p = new PolskaParams(innerFId.F_ID, _formulasTable, polskaParams.StartDateTime, polskaParams.EndDateTime, polskaParams.DiscreteType,
                                                     numbersHalfHours, innerFId.UnitDigit);
                            var formulaExpression = ComposeExpressionPolskaya(innerFId, p, indxStart, indxEnd, numbersHalfHours, isCalculateBetweenIndexes);

                            //Время дейстаия внутренней формулы берем из основной
                            var var = new Variable(operators.Name, indxStart, indxEnd, formulaExpression, isCalculateBetweenIndexes);
                            parser.CreateVariable(var);
                        }
                        else
                        {
                            parser.CreateVariable(new Variable(operators.Name, -1, -1));
                        }
                    }
                    break;

                case F_OPERATOR.F_OPERAND_TYPE.Constanta:
                    parser.Expression.Append(operators.PRE_OPERANDS).Append(operators.AFTER_OPERANDS ?? "");
                    break;

                case F_OPERATOR.F_OPERAND_TYPE.None:
                    if (string.IsNullOrEmpty(operators.PRE_OPERANDS) && string.IsNullOrEmpty(operators.AFTER_OPERANDS))
                    {
                        throw new FormulaParseException("Формула не описана!");
                    }
                    parser.Expression.Append(operators.PRE_OPERANDS ?? "").Append(operators.AFTER_OPERANDS ?? "");
                    break;

                default:
                    throw new FormulaParseException("Неизвестный тип оператора!");
                }
            }

            _recursionCallStack.Remove(f.F_ID);

            return(parser);
        }