예제 #1
0
        protected override void PrepareNonCommonPar()
        {
            ParBase parFileName = GetUniquePar <ParBase>(DefPar.DefOutput.File);

            if (parFileName != null) // if null the programme is stopped after reading parameters (missing compulsory parameter)
            {
                fileName = Path.Combine(infoStore.runConfig.pathOutput, parFileName.xmlValue);
                if (!fileName.ToLower().EndsWith(".txt"))
                {
                    fileName += ".txt";
                }

                if (infoStore.runConfig.stdOutputFilenameSuffix != string.Empty) // e.g. uk_2017_std -> uk_2017_BTAoff
                {
                    AdaptFileNameForNonStdExtensionSwitches(infoStore.runConfig.stdOutputFilenameSuffix);
                }

                if (infoStore.runConfig.outFileDate != string.Empty) // e.g. hu_2017_std.txt -> hu_2017_std_201805301954.txt
                {
                    fileName = fileName.Insert(fileName.Length - 4, "_" + infoStore.runConfig.outFileDate);
                }

                // * * *   T O D O   * * *
                // check at this point if file is ready for writting, i.e. valid file-name, not used by another file, ...
                // to avoid running the whole thing and then cannot write (probably requires try-catch on attempt to open)
                // also if the file is available, lock it now?
            }

            // in future probably replaced by Scale function, but currently still needed, in particular for PET
            ParFormula parMultipleMonetaryBy = GetUniquePar <ParFormula>(DefPar.DefOutput.MultiplyMonetaryBy);

            if (parMultipleMonetaryBy != null)
            {
                multiplyMonetaryBy = parMultipleMonetaryBy.GetGlobalValue();
            }

            PrepareVarILPar();
            PrepareDefILPar();
            PrepareUnitInfoPar();
            append = GetParBoolValueOrDefault(DefFun.DefOutput, DefPar.DefOutput.Append);
            suppressVoidMessage = GetParBoolValueOrDefault(DefFun.DefOutput, DefPar.DefOutput.Suppress_Void_Message);

            nDecimals      = (int)GetParNumberValueOrDefault(DefFun.DefOutput, DefPar.DefOutput.nDecimals);
            formatDecimals = "0."; for (int i = 0; i < nDecimals; i++)
            {
                formatDecimals += "#";
            }

            parWho     = GetUniquePar <ParCateg>(DefPar.Common.Who_Must_Be_Elig);
            parEligVar = GetUniquePar <ParVar>(DefPar.Common.Elig_Var);

            ParNumber parReplaceUnitLoopVoidBy = GetUniquePar <ParNumber>(DefPar.DefOutput.Replace_Void_By);

            if (parReplaceUnitLoopVoidBy != null)
            {
                doReplaceUnitLoopVoidBy = true;
                replaceUnitLoopVoidBy   = parReplaceUnitLoopVoidBy.GetValue();
            }
        }
예제 #2
0
 internal override void CheckAndPrepare(FunBase fun)
 {
     parFormula = new ParFormula(infoStore, true)
     {
         xmlValue = xmlValue, description = this.description
     };
     parFormula.CheckAndPrepare(fun);
 }
예제 #3
0
 protected override void PrepareNonCommonPar()
 {
     parShare         = GetUniquePar <ParFormula>(DefPar.Allocate.Share);
     parShareBetween  = GetUniquePar <ParCond>(DefPar.Allocate.Share_Between);
     parShareProp     = GetUniquePar <ParVarIL>(DefPar.Allocate.Share_Prop);
     shareAllIfNoElig = GetParBoolValueOrDefault(DefFun.Allocate, DefPar.Allocate.Share_All_IfNoElig);
     shareEquIfZero   = GetParBoolValueOrDefault(DefFun.Allocate, DefPar.Allocate.Share_Equ_IfZero);
     ignoreNegProp    = GetParBoolValueOrDefault(DefFun.Allocate, DefPar.Allocate.Ignore_Neg_Prop);
 }
예제 #4
0
 internal static bool HandlesCheckAndPrepare(ParFormula pf)
 { // the standard ParFormula.CheckAndPrepare cannot handle the formula as it contains placeholders (IL_COMPONENT, etc.), therefore skip
   // to later CheckAndPrepare the adapted ParFormulas (see GetAdaptedParFormula below)
     return(pf.description.GetFunName().ToLower() == DefFun.IlArithOp.ToLower() &&
            pf.description.GetParName().ToLower() == DefPar.IlArithOp.Formula.ToLower() &&
            (pf.xmlValue.Contains(DefPar.IlArithOp.BASE_IL_COMPONENT.ToLower()) ||
             pf.xmlValue.Contains(DefPar.IlArithOp.OUT_IL_COMPONENT.ToLower()) ||
             pf.xmlValue.Contains(DefPar.IlArithOp.IL_COMPONENT.ToLower())));
 }
        // called by ParFormula to replace $Base by the actual content of this parameter
        internal string HandleBase(string formula, Description parDescription)
        {
            List <string> basePlaceHolders = new List <string>()
            {
                DefPar.Value.BENCALC_BASE, DefPar.Value.BENCALC_BASE_AMOUNT,
                DefPar.Value.BENCALC_BASE_IL, DefPar.Value.BENCALC_BASE_VAR
            };
            string basePH = ContainsBase();

            if (basePH == null)
            {
                return(formula);
            }

            ParFormula parBase = GetUniquePar <ParFormula>(DefPar.BenCalc.Base);

            if (parBase == null)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false, message = $"{parDescription.Get()}: missing parameter {DefPar.BenCalc.Base}"
                });
                return(formula);
            }

            do
            {
                int index = formula.ToLower().IndexOf(basePH);
                formula = formula.Remove(index, basePH.Length);
                formula = formula.Insert(index, $"({parBase.xmlValue})");
                basePH  = ContainsBase();
            } while (basePH != null);

            string ContainsBase()
            {
                foreach (string placeHolder in basePlaceHolders)
                {
                    if (formula.ToLower().Contains(placeHolder))
                    {
                        return(placeHolder);
                    }
                }
                return(null);
            }

            return(formula);
        }
예제 #6
0
        /// <summary>
        /// try to identify parameters and, if valid, generate the respective ParXXX and put into respective lists (see above)
        /// </summary>
        private void ClassifyParameters(Dictionary <string, ExeXml.Par> xmlParList, DefinitionAdmin.Fun funDef)
        {
            int dummyGroupNumber = -9999; // this is for placeholder-parameters, see below

            foreach (var xmlPar in xmlParList)
            {
                Description parDescription = new Description(description, xmlPar.Value, xmlPar.Key);
                string      xmlParName     = xmlPar.Value.Name;

                // first check if it is an 'ordinary' parameter ...
                DefinitionAdmin.Par parDef = funDef.GetParDef(xmlParName);
                if (parDef != null)
                {
                    string officialParName = funDef.GetOfficalParName(xmlParName); // is (in contrast to xmlParName) case-sensitive and
                                                                                   // corresponds to constants as defined in Common-library
                                                                                   // generate parameter ...
                    ParBase par = GeneratePar(xmlPar, parDef, parDescription);
                    // ... and put it into the list it belongs too ...
                    if (parDef.isFootnote) // ... footnote-list
                    {
                        if (GetGroupNumber(xmlPar.Value, parDescription, out int dummy))
                        {
                            if (!footnotePar.ContainsKey(xmlPar.Value.Group))
                            {
                                footnotePar.Add(xmlPar.Value.Group, new Dictionary <string, ParBase>());
                            }
                            if (!footnotePar[xmlPar.Value.Group].ContainsKey(officialParName))
                            {
                                footnotePar[xmlPar.Value.Group].Add(officialParName, par);
                            }
                            else
                            {
                                ReportDoubleDef(parDescription);
                            }
                        }
                    }
                    else if (parDef.maxCount == 1) // ... unique-parameter-list
                    {
                        if (!uniquePar.ContainsKey(officialParName))
                        {
                            uniquePar.Add(officialParName, par);
                            if (infoStore.runConfig.warnAboutUselessGroups && !string.IsNullOrEmpty(xmlPar.Value.Group))
                            {
                                ReportUselessGroup(parDescription);
                            }
                        }
                        else
                        {
                            ReportDoubleDef(parDescription);
                        }
                    }
                    else // ... non-unique-parameter-list
                    {
                        if (!nonUniquePar.ContainsKey(officialParName))
                        {
                            nonUniquePar.Add(officialParName, new List <ParBase>());
                        }
                        nonUniquePar[officialParName].Add(par);
                        if (infoStore.runConfig.warnAboutUselessGroups && !string.IsNullOrEmpty(xmlPar.Value.Group))
                        {
                            ReportUselessGroup(parDescription);
                        }
                    }
                    continue;
                }
                // ... if not successuful, check if it is a group parameter ...
                parDef = funDef.GetGroupParDef(xmlParName, out string groupName);
                if (parDef != null)
                {
                    if (GetGroupNumber(xmlPar.Value, parDescription, out int groupNo))
                    {
                        // generate parameter ...
                        ParBase par = GeneratePar(xmlPar, parDef, parDescription);
                        // ... and put it into group-parameter-list
                        if (!groupPar.ContainsKey(groupName))
                        {
                            groupPar.Add(groupName, new SortedList <int, List <ParBase> >());
                        }
                        if (!groupPar[groupName].ContainsKey(groupNo))
                        {
                            groupPar[groupName].Add(groupNo, new List <ParBase>());
                        }
                        if (parDef.maxCount > 1 || GetUniqueGroupPar <ParBase>(xmlPar.Value.Name, groupPar[groupName][groupNo]) == null)
                        {
                            groupPar[groupName][groupNo].Add(par);
                        }
                        else
                        {
                            ReportDoubleDef(parDescription);
                        }
                    }
                    continue;
                }
                // ... if still not successful, it could still be placehoder parameter ...
                if (funDef.AllowsForPlaceholders())
                {
                    parDef = funDef.GetPlaceholderDef(out string phGroupName);
                    ParBase par = GeneratePar(xmlPar, parDef, parDescription, true);
                    if (phGroupName == null) // non-group placeholder, as e.g. in SetDefault, DefIL
                    {
                        if (!placeholderPar.TryAdd(xmlParName, par))
                        {
                            infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                            {
                                isWarning = true, message = $" {parDescription.Get()}: {xmlParName} double definition (is ignored)"
                            });
                        }
                    }
                    else // group placeholder, as e.g. in DefVar (PH, IsGlobal, IsMonetary), Uprate (PH, FactorCond)
                    {
                        GetGroupNumber(xmlPar.Value, parDescription, // note that this returns a dummy-group if the user didn't indicate one
                                       out int groupNo, true); // as placeholders only actually need a group if they are "further specified" (e.g. uprating-factors: factor_condition)
                        if (!groupPar.ContainsKey(phGroupName))
                        {
                            groupPar.Add(phGroupName, new SortedList <int, List <ParBase> >());
                        }
                        if (!groupPar[phGroupName].ContainsKey(groupNo))
                        {
                            groupPar[phGroupName].Add(groupNo, new List <ParBase>());
                        }
                        groupPar[phGroupName][groupNo].Add(par);
                    }
                    continue;
                }
                // ... now we give up
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = true, message = $" {parDescription.Get()}: unknown parameter"
                });
            }

            if (infoStore.runConfig.warnAboutUselessGroups)
            {
                foreach (var groupType in groupPar)
                {
                    if (groupType.Key.ToLower() == DefPar.SchedCalc.Band_XXX.ToLower())
                    {
                        continue;
                    }
                    foreach (var group in groupType.Value)
                    {
                        if (group.Key >= 0 && group.Value.Count == 1)
                        {
                            ReportUselessGroup(group.Value[0].description);
                        }
                    }
                }
            }

            // internal function for generating parameters
            ParBase GeneratePar(KeyValuePair <string, ExeXml.Par> xmlPar, DefinitionAdmin.Par parDef,
                                Description parDescription, bool isPlaceholder = false)
            {
                ParBase par;

                switch (parDef.valueType)
                {
                case DefPar.PAR_TYPE.FORMULA: par = new ParFormula(infoStore); break;

                case DefPar.PAR_TYPE.CONDITION: par = new ParCond(infoStore); break;

                case DefPar.PAR_TYPE.BOOLEAN: par = new ParBool(infoStore); break;

                case DefPar.PAR_TYPE.NUMBER: par = new ParNumber(infoStore); break;

                case DefPar.PAR_TYPE.TEXT: par = new ParBase(infoStore); break;

                case DefPar.PAR_TYPE.VAR: par = new ParVar(infoStore); break;

                case DefPar.PAR_TYPE.OUTVAR: par = new ParOutVar(infoStore); break;

                case DefPar.PAR_TYPE.IL: par = new ParIL(infoStore); break;

                case DefPar.PAR_TYPE.TU: par = new ParTU(infoStore); break;

                case DefPar.PAR_TYPE.VARorIL: par = new ParVarIL(infoStore); break;

                case DefPar.PAR_TYPE.CATEG: par = new ParCateg(infoStore, parDef.categValues); break;

                case DefPar.PAR_TYPE.PLACEHOLDER: par = new ParBase(infoStore); break;

                default: throw new Exception($"Not yet properly implemented parameter value type {parDef.valueType}");
                }
                par.description = parDescription;
                par.xmlValue    = xmlPar.Value.val;
                par.description.isPlaceholder = isPlaceholder;
                return(par);
            }

            bool GetGroupNumber(ExeXml.Par p, Description parDescription, out int groupNumber, bool allowDummy = false)
            {
                groupNumber = dummyGroupNumber++;  // placeholders (e.g.uprating factors) only actually need a group
                if (string.IsNullOrEmpty(p.Group)) // if they are "further specified" (e.g.factor_condition)
                {
                    if (allowDummy)
                    {
                        return(true);
                    }
                    infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                    {
                        isWarning = false, message = $" {parDescription.Get()}: missing group"
                    });
                    return(false);
                }
                if (int.TryParse(p.Group, out groupNumber))
                {
                    return(true);
                }
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false, message = $" {parDescription.Get()}: invalid group {p.Group} (must be an integer number)"
                });
                return(false);
            }

            void ReportDoubleDef(Description parDescription)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false, message = $" {parDescription.Get()}: defined more than once"
                });
            }

            void ReportUselessGroup(Description parDescription)
            {
                if (parDescription.GetFunName() != DefFun.Store)    // add a special exception for Store, as it has its own reporting
                {
                    infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                    {
                        isWarning = true, message = $" {parDescription.Get()}: group has no use"
                    });
                }
            }
        }
예제 #7
0
        protected override void PrepareNonCommonPar()
        {
            // get parameters
            ParIL parOperatorIL = GetUniquePar <ParIL>(DefPar.IlVarOp.Operator_IL); if (parOperatorIL == null)
            {
                return;                                                                                               // error is handled by global check
            }
            ParFormula parOperand   = GetUniquePar <ParFormula>(DefPar.IlVarOp.Operand);
            bool       useFactors   = GetParBoolValueOrDefault(DefFun.IlVarOp, DefPar.IlVarOp.Operand_Factors);
            ParIL      parOperandIL = GetUniquePar <ParIL>(DefPar.IlVarOp.Operand_IL);
            ParCateg   parMulAdd    = GetUniquePar <ParCateg>(DefPar.IlVarOp.Operation); if (parMulAdd != null)
            {
                mulAdd = parMulAdd.GetCateg();
            }
            ParCateg parSelVar = GetUniquePar <ParCateg>(DefPar.IlVarOp.Sel_Var); if (parSelVar != null)

            {
                selVar = parSelVar.GetCateg();
            }

            // assess what to do and check for insufficient or contradictory information
            if (parOperand != null)
            {
                //if (parOperand.IsGlobal()) opTask = OPERAND_TYPE.SCALAR; // out-commented to replace by the weaker condtion below, otherwise it produces an error with constants
                if (double.TryParse(parOperand.xmlValue, out double x))
                {
                    opTask = OPERAND_TYPE.SCALAR;
                }
                else
                {
                    opTask = OPERAND_TYPE.FORMULA; formulaOperand = parOperand;
                }
            }
            else if (parOperandIL != null)
            {
                if (!CheckDoubleDef(OPERAND_TYPE.IL))
                {
                    return;
                }
            }
            if (useFactors)
            {
                if (!CheckDoubleDef(OPERAND_TYPE.FACTORS))
                {
                    return;
                }
            }
            if (mulAdd == DefPar.Value.ILVAROP_NEGTOZERO)
            {
                if (!CheckDoubleDef(OPERAND_TYPE.NEGTOZERO))
                {
                    return;
                }
            }
            if (opTask == OPERAND_TYPE.INVALID)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false,
                    message   = $"{description.Get()}: missing definition of operand"
                });
                return;
            }
            if (opTask == OPERAND_TYPE.IL && parOperandIL.GetFlatContent().Count != parOperatorIL.GetFlatContent().Count)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false,
                    message   = $"{description.Get()}: incomelists {parOperatorIL.name} and {parOperandIL.name} do not have the same number of variables, operation is not possible"
                });
                return;
            }

            // prepare information for run
            for (int i = 0; i < parOperatorIL.GetFlatContent().Count; ++i)
            {
                OpItem oi = new OpItem()
                {
                    varOperator = parOperatorIL.GetFlatContent()[i].varSpec
                };
                switch (opTask)
                {
                case OPERAND_TYPE.FACTORS: oi.numOperand = parOperatorIL.GetFlatContent()[i].addFactor; break;

                case OPERAND_TYPE.SCALAR: oi.numOperand = parOperand.GetGlobalValue(); break;

                case OPERAND_TYPE.IL: oi.varOperand = parOperandIL.GetFlatContent()[i].varSpec; break;
                }
                opItems.Add(oi);
            }


            bool CheckDoubleDef(OPERAND_TYPE ot)
            {
                if (opTask == OPERAND_TYPE.INVALID)
                {
                    opTask = ot; return(true);
                }
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false,
                    message   = $"{description.Get()}: contradictory definition of operand"
                });
                return(false);
            }
        }
        protected void PrepareLimPar()
        {
            coParLowLim = GetUniquePar <ParFormula>(DefPar.Common.LowLim);
            coParUpLim  = GetUniquePar <ParFormula>(DefPar.Common.UpLim);
            coParThres  = GetUniquePar <ParFormula>(DefPar.Common.Threshold);
            ParCateg coParLimpriority = GetUniquePar <ParCateg>(DefPar.Common.Limpriority);

            // the following tries to optimise by getting the values here, if they are read-time-available (e.g. 600#y, GetSystemYear, ...)
            // and by checking for implausible values (e.g. upLim = 10, lowLim = 100) if already possible
            if (coParLowLim != null)
            {
                if (coParLowLim.IsGlobal(true))
                {
                    lowLim = coParLowLim.GetGlobalValue(); coParLowLim = null;
                }
                else
                {
                    doRunTimeLimCheck = true;
                }
            }
            if (coParUpLim != null)
            {
                if (coParUpLim.IsGlobal(true))
                {
                    upLim = coParUpLim.GetGlobalValue(); coParUpLim = null;
                }
                else
                {
                    doRunTimeLimCheck = true;
                }
            }
            bool checkThres = coParThres != null;

            if (coParThres != null)
            {
                if (coParThres.IsGlobal(true))
                {
                    thres = coParThres.GetGlobalValue(); coParThres = null;
                }
                else
                {
                    doRunTimeThresCheck = true;
                }
            }
            if (coParLimpriority != null)
            {
                limPri = coParLimpriority.GetCateg();
            }

            if (!doRunTimeLimCheck) // both limits available (might be double.MinValue and/or double.MaxValue, but does no harm here)
            {
                CheckLimits(ref lowLim, ref upLim);

                if (checkThres && !doRunTimeThresCheck) // threshold and both limits available
                {
                    if (!CheckThreshold(thres, lowLim, upLim))
                    {
                        thres = lowLim;
                    }
                }
            }
        }
예제 #9
0
        /// <summary>
        /// checks if the standard footnote-parameters, i.e. #_LowLim, #_UpLim, #_Level, are applied on the parameter
        /// if so, stores them in lowLim, upLim and alternativeTU (see above)
        /// also provides the "cleaned" value (e.g. yem#1 -> yem)
        /// note that the footnote-parameters are assessed via the (mother)function (parameter fun)
        /// also note that the only other (not here handled) footnote-parameters are 'amount', which is handled by ParFormula
        /// and query parameters which will not issue a "missing" (see below) but let the query check if it can use the footnote
        /// </summary>
        protected void ExtractStandardFootnotes(string value, out string cleanedValue, FunBase fun)
        {
            List <string> numbers = GetFootnoteNumbers(value, out cleanedValue); // it's unlikely, but yem#1#3 is possible (see GetFootnoteNumbers)

            if (numbers.Count == 0)
            {
                return;                     // no footnotes
            }
            // limits (see remark in _FunInSpineBase_Lim wrt not using a common implementation for limits)
            pLowLim = fun.GetFootnotePar <ParFormula>(DefPar.Footnote.LowLim, numbers);
            if (pLowLim != null)
            {
                if (pLowLim.IsGlobal(true))
                {
                    lowLim = pLowLim.GetGlobalValue(); pLowLim = null;
                }
                else
                {
                    doRunTimeLimCheck = true;
                }
            }

            pUpLim = fun.GetFootnotePar <ParFormula>(DefPar.Footnote.UpLim, numbers);
            if (pUpLim != null)
            {
                if (pUpLim.IsGlobal(true))
                {
                    upLim = pUpLim.GetGlobalValue(); pUpLim = null;
                }
                else
                {
                    doRunTimeLimCheck = true;
                }
            }

            ParCateg pLimpriority = fun.GetFootnotePar <ParCateg>(DefPar.Footnote.LimPriority, numbers);

            if (pLimpriority != null)
            {
                limPri = pLimpriority.GetCateg();
            }

            if (!doRunTimeLimCheck) // both limits available (might be double.MinValue and/or double.MaxValue, but does no harm here)
            {
                CheckLimits(ref lowLim, ref upLim);
            }

            // alternative TU
            ParBase parAltTU = fun.GetFootnotePar <ParBase>(DefPar.Footnote.Level, numbers);

            if (parAltTU != null)
            {
                alternativeTU = parAltTU.xmlValue;
            }

            // if none of the standard footnotes is defined in the function #x points to nowhere ...
            if (GetType() == typeof(ParQuery)) // ... except for queries, which may have own footnotes
            {
                return;                        // (this is slightly negligent, as it accepts e.g. IsMarried#1 without respective footnote-parameter)
            }
            if (pLowLim == null && lowLim == double.MinValue &&
                pUpLim == null && upLim == double.MaxValue &&
                parAltTU == null)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = true, message = $"{description.Get()}: missing footnote parameter for {value}"
                });
            }
        }
예제 #10
0
        protected override void PrepareNonCommonPar()
        {
            parFormula = GetUniquePar <ParFormula>(DefPar.IlArithOp.Formula);

            baseILSpecification = new ILSpecification()
            {
                ilName = GetUniquePar <ParIL>(DefPar.IlArithOp.Base_ILName).xmlValue
            };
            if (!CheckPrePost(baseILSpecification, GetUniquePar <ParBase>(DefPar.IlArithOp.Base_Prefix),
                              GetUniquePar <ParBase>(DefPar.IlArithOp.Base_Postfix)))
            {
                return;
            }

            coreVarNames = GetCoreVars(baseILSpecification); // assess the variables which need to be present in all decomposed ILs

            ilSpecifications = new List <ILSpecification>();
            foreach (var pg in GetParGroups(DefPar.IlArithOp.ILName))
            {
                List <ParBase>  ilParList       = pg.Value;
                ILSpecification ilSpecification = new ILSpecification()
                {
                    ilName = GetUniqueGroupPar <ParIL>(DefPar.IlArithOp.ILName, ilParList).xmlValue, grpNo = pg.Key.ToString()
                };
                if (!CheckPrePost(ilSpecification, GetUniqueGroupPar <ParBase>(DefPar.IlArithOp.Prefix, ilParList),
                                  GetUniqueGroupPar <ParBase>(DefPar.IlArithOp.Postfix, ilParList)))
                {
                    return;
                }
                if (!CheckCoreVars(ilSpecification))
                {
                    return;
                }
                ilSpecifications.Add(ilSpecification);
            }

            outILSpecification = new ILSpecification()
            {
                ilName = GetUniquePar <ParBase>(DefPar.IlArithOp.Out_ILName).xmlValue
            };
            bool outVarsMustExist = parFormula.xmlValue.Contains(DefPar.IlArithOp.OUT_IL_COMPONENT.ToLower());
            bool outILExists      = infoStore.operandAdmin.Exists(outILSpecification.ilName) && infoStore.operandAdmin.GetParType(outILSpecification.ilName) == DefPar.PAR_TYPE.IL;

            if (!CheckPrePost(outILSpecification, GetUniquePar <ParBase>(DefPar.IlArithOp.Out_Prefix),
                              GetUniquePar <ParBase>(DefPar.IlArithOp.Out_Postfix), outILExists))
            {
                return;
            }

            if (outVarsMustExist && !outILExists)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false,
                    message   = $"{description.Get()}: using {DefPar.IlArithOp.OUT_IL_COMPONENT} in {DefPar.IlArithOp.Formula} requires incomelist {outILSpecification.ilName} to exist"
                });
                return;
            }

            if (outILExists)
            {
                if (!CheckCoreVars(outILSpecification))
                {
                    return;
                }
            }
            else
            {
                if (!RegisterOperands())
                {
                    return;
                }
            }

            PrepareFormulas();
        }
        protected override void PrepareNonCommonPar()
        {
            foreach (List <ParBase> compParList in GetParGroups(DefPar.BenCalc.Comp_X).Values)
            {
                Component component = new Component();

                // condition
                component.pCond = GetUniqueGroupPar <ParCond>(DefPar.BenCalc.Comp_Cond, compParList);

                // amount (per elig/TU)
                component.pFormula = GetUniqueGroupPar <ParFormula>(DefPar.BenCalc.Comp_perTU, compParList);
                if (component.pFormula != null)
                {
                    component.perElig = false;
                }
                else
                {
                    component.pFormula = GetUniqueGroupPar <ParFormula>(DefPar.BenCalc.Comp_perElig, compParList);
                }

                // limits (see remark in _FunInSpineBase_Lim wrt not using a common implementation for limits)
                component.pLowLim = GetUniqueGroupPar <ParFormula>(DefPar.BenCalc.Comp_LowLim, compParList);
                component.pUpLim  = GetUniqueGroupPar <ParFormula>(DefPar.BenCalc.Comp_UpLim, compParList);
                if (component.pLowLim != null)
                {
                    if (component.pLowLim.IsGlobal(true))
                    {
                        component.lowLim = component.pLowLim.GetGlobalValue(); component.pLowLim = null;
                    }
                    else
                    {
                        component.doRunTimeLimCheck = true;
                    }
                }
                if (component.pUpLim != null)
                {
                    if (component.pUpLim.IsGlobal(true))
                    {
                        component.upLim = component.pUpLim.GetGlobalValue(); component.pUpLim = null;
                    }
                    else
                    {
                        component.doRunTimeLimCheck = true;
                    }
                }
                if (!component.doRunTimeLimCheck) // both limits available (might be double.MinValue and/or double.MaxValue, but does no harm here)
                {
                    CheckComponentLimits(ref component.lowLim, ref component.upLim);
                }

                components.Add(component);
            }

            withdraw_Base  = GetUniquePar <ParFormula>(DefPar.BenCalc.Withdraw_Base);
            withdraw_Start = GetUniquePar <ParFormula>(DefPar.BenCalc.Withdraw_Start);
            withdraw_End   = GetUniquePar <ParFormula>(DefPar.BenCalc.Withdraw_End);
            withdraw_Rate  = GetUniquePar <ParFormula>(DefPar.BenCalc.Withdraw_Rate);

            if (withdraw_Base == null && (withdraw_Start != null || withdraw_End != null || withdraw_Rate != null)) // cannot have withdrawal without a base
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = true, message = $"{description.Get()}: Without a Withdraw_Base all other withdraw parameters will be ignored", runTimeErrorId = description.funID
                });
            }
            else if (withdraw_End != null && withdraw_Rate != null)  // Withdraw_End and Withdraw_Rate cannot co-exist
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = true, message = $"{description.Get()}: Withdraw_End and Withdraw_Rate cannot co-exist: Withdraw_Rate will be ignored", runTimeErrorId = description.funID
                });
            }
            else if (withdraw_Base != null && withdraw_End == null && withdraw_Rate == null)  // Withdraw_End and Withdraw_Rate cannot both be missing
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = true, message = $"{description.Get()}: Withdraw_End and Withdraw_Rate cannot both be missing: withdrawal will be ignored", runTimeErrorId = description.funID
                });
            }
        }
        protected override void PrepareNonCommonPar()
        {
            if (GetParGroups(DefPar.SchedCalc.Band_XXX).Count < 1)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false, message = $"{description.Get()}: SchedCalc must have at least one band"
                });
                return;
            }
            foreach (KeyValuePair <int, List <ParBase> > bandParList in GetParGroups(DefPar.SchedCalc.Band_XXX))
            {
                Band band = new Band();
                // Prepare the Band Limits
                band.band    = bandParList.Key;
                band.pLowLim = GetUniqueGroupPar <ParFormula>(DefPar.SchedCalc.Band_LowLim, bandParList.Value);
                if (band.pLowLim != null)   // if there is a lowLim
                {
                    if (band.pLowLim.IsGlobal(true))
                    {
                        band.lowLim = band.pLowLim.GetGlobalValue(); band.pLowLim = null;
                    }
                    else
                    {
                        doRunTimeLimCheck = true;
                    }
                }
                band.pUpLim = GetUniqueGroupPar <ParFormula>(DefPar.SchedCalc.Band_UpLim, bandParList.Value);
                if (band.pUpLim != null)   // if there is a lowLim
                {
                    if (band.pUpLim.IsGlobal(true))
                    {
                        band.upLim = band.pUpLim.GetGlobalValue(); band.pUpLim = null;
                    }
                    else
                    {
                        doRunTimeLimCheck = true;
                    }
                }
                // Prepare the Band Rate/Amount
                band.pRate   = GetUniqueGroupPar <ParFormula>(DefPar.SchedCalc.Band_Rate, bandParList.Value);
                band.pAmount = GetUniqueGroupPar <ParFormula>(DefPar.SchedCalc.Band_Amount, bandParList.Value);
                if (band.pRate != null && band.pAmount != null) // Rate and Amount cannot co-exist
                {
                    infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                    {
                        isWarning = false, message = $"{description.Get()}: Rate and Amount cannot co-exist in group {band.band}"
                    });
                }
                if (band.pRate == null && band.pAmount == null) // Rate and Amount cannot both be missing
                {
                    infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                    {
                        isWarning = false, message = $"{description.Get()}: Rate and Amount cannot both be missing in group {band.band}"
                    });
                }
                if (band.pRate != null)
                {
                    if (band.pRate.IsGlobal(true))
                    {
                        band.rate = band.pRate.GetGlobalValue(); band.pRate = null;
                    }
                    else
                    {
                        doRunTimeRateCheck = true;
                    }
                }
                if (band.pAmount != null)
                {
                    if (band.pAmount.IsGlobal(true))
                    {
                        band.amount = band.pAmount.GetGlobalValue(); band.pAmount = null;
                    }
                    else
                    {
                        doRunTimeRateCheck = true;
                    }
                }
                bands.Add(band);
            }

            // check that all required limits exist
            for (int i = 1; i < bands.Count; i++)
            {
                // if both limits are missing then produce an error
                if (bands[i - 1].upLim == double.MaxValue && bands[i - 1].pUpLim == null && bands[i].lowLim == double.MinValue && bands[i].pLowLim == null)
                {
                    infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                    {
                        isWarning = false, message = $"{description.Get()}: Band {bands[i - 1].band}: insufficient definition of upper limit. Use parameters 'band_uplim' or 'band_lowlim'(+1)."
                    });
                }
                // if both limits are there, then produce an error
                else if ((bands[i - 1].upLim != double.MaxValue || bands[i - 1].pUpLim != null) && (bands[i].lowLim != double.MinValue || bands[i].pLowLim != null))
                {
                    infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                    {
                        isWarning = false, message = $"{description.Get()}: Double definition of upper limit as 'Band_UpLim {bands[i - 1].band}' and 'Band_LowLim {bands[i].band}'."
                    });
                }
                // else, make sure that the upper limit always exist (copy from Group+1 lower limit if required)
                else if (bands[i - 1].upLim == double.MaxValue && bands[i - 1].pUpLim == null)
                {
                    if (bands[i].pLowLim == null)
                    {
                        bands[i - 1].upLim = bands[i].lowLim;                           // copy the litteral limit if it exists
                    }
                    else
                    {
                        bands[i - 1].pUpLim = bands[i].pLowLim;                         // else copy the parameter to be run at run-time
                    }
                }
            }

            // if possible, check that limits are also in order
            if (!doRunTimeLimCheck)
            {
                CheckGroupLimits(bands);
            }

            // prepare the other parameters
            basePar = GetUniquePar <ParFormula>(DefPar.SchedCalc.Base);
            if (basePar == null)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false, message = $"{description.Get()}: Missing required parameter Base"
                });
            }

            ParBool doAverageRatesPar = GetUniquePar <ParBool>(DefPar.SchedCalc.Do_Average_Rates);

            doAverageRates = doAverageRatesPar != null && doAverageRatesPar.GetBoolValue();
            ParBool simpleProgPar = GetUniquePar <ParBool>(DefPar.SchedCalc.Simple_Prog);

            simpleProg = simpleProgPar != null && simpleProgPar.GetBoolValue();

            quotientPar = GetUniquePar <ParFormula>(DefPar.SchedCalc.Quotient);
            if (quotientPar != null)
            {
                if (quotientPar.IsGlobal(true))
                {
                    quotient = quotientPar.GetGlobalValue(); quotientPar = null;
                }
            }

            baseThresholdPar = GetUniquePar <ParFormula>(DefPar.SchedCalc.BaseThreshold);
            if (baseThresholdPar != null)
            {
                if (baseThresholdPar.IsGlobal(true))
                {
                    baseThreshold = baseThresholdPar.GetGlobalValue(); baseThresholdPar = null;
                }
            }

            ParNumber roundBasePar = GetUniquePar <ParNumber>(DefPar.SchedCalc.Round_Base);

            if (roundBasePar != null)
            {
                roundBase = roundBasePar.GetValue();
            }
        }
예제 #13
0
 protected override void PrepareNonCommonPar()
 {
     parFormula = GetUniquePar <ParFormula>(DefPar.ArithOp.Formula);
 }