示例#1
0
 internal override void CheckAndPrepare(FunBase fun, List <string> footnoteNumbers)
 {
     foreach (string dVar in new List <string>()
     {
         DefVarName.DDI, DefVarName.DDILV
     })
     {
         if (infoStore.operandAdmin.Exists(dVar))
         {
             continue;
         }
         if (dVar == DefVarName.DDI)
         {
             autoReg = true;
         }
         infoStore.operandAdmin.CheckRegistration(name: dVar,
                                                  isOutVar: false,
                                                  warnIfNotInit: true,
                                                  description: description);
         infoStore.operandAdmin.SetProvidedBySetDefault(dVar);
     }
 }
        private string constName = null; // only relevant if value is a constant, e.g. #_amount = $Const_A, Factor_Value = $Const_B

        internal override void CheckAndPrepare(FunBase fun)
        {
            double periodFactor = HandlePeriodFactor(out string xmlCleaned);

            // if TryParse works: a simple number ...
            if (double.TryParse(EM_Helpers.AdaptDecimalSign(xmlCleaned), out value))
            {
                value *= periodFactor; return;
            }

            // ... if not: possibly a constant
            if (infoStore.operandAdmin.Exists(xmlValue) && infoStore.operandAdmin.GetIsGlobal(xmlValue))
            {
                constName = xmlValue; // note: not necessary to us xmlCleaned, as a constant cannot have a period
            }
            else
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false, message = $"{description.Get()}: {xmlValue} is not a valid number"
                });
            }
        }
示例#3
0
        internal override void CheckAndPrepare(FunBase fun)
        {
            if (infoStore.indexTUs.ContainsKey(xmlValue))
            {
                name = xmlValue;

                // in contrast to other functions FunDefTU's CheckAndPrepare must be called on "first usage" instead of once it is defined
                // otherwise one would get "not-yet-calculated"-waringings for variables, which are not
                // available at the point of TU-definition, but are available at the point of first usage
                if (!infoStore.indexTUs[xmlValue].isPrepared)
                {
                    infoStore.indexTUs[xmlValue].CheckAndPrepare();
                }
                infoStore.indexTUs[xmlValue].isPrepared = true; // to avoid that CheckAndPrepare is called for further usages
            }
            else
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false, message = $"{description.Get()}: unknown tax unit {xmlValue}"
                });
            }
        }
示例#4
0
        // currently only used by IsNtoMchild, but still make it general as future queries may make use of it
        protected void PrepareNMPar(FunBase fun, List <string> footnoteNumbers)
        {
            parN = fun.GetFootnotePar <ParNumber>(DefQuery.Par.N, footnoteNumbers);
            if (parN == null)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false, message = $"{description.Get()}: compulsory query-parameter {DefQuery.Par.N} missing"
                });
            }

            parM = fun.GetFootnotePar <ParNumber>(DefQuery.Par.M, footnoteNumbers);
            if (parM == null)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false, message = $"{description.Get()}: compulsory query-parameter {DefQuery.Par.M} missing"
                });
            }

            // note: getting the numbers and not just the parameters at this stage may be more efficient, but would make using
            // constants more difficult (actually happens) and a future change to ParFormula (for more flexibility) impossible
        }
 internal override void CheckAndPrepare(FunBase fun, List <string> footnoteNumbers)
 {
 }
 internal override void CheckAndPrepare(FunBase fun, List <string> footnoteNumbers)
 {
     PrepareIncomeInfoPar(fun, footnoteNumbers);
 }
示例#7
0
        internal void PrepareSpine(ref bool runSequential)
        {
            string  BEFORE = "BEFORE", AFTER = "AFTER", IN = "IN", spineState = BEFORE;
            FunBase causeForSequential = null, prevFun = null;

            if (!runSequential)
            {
                foreach (FunBase fun in infoStore.spine.Values)
                {
                    switch (DefinitionAdmin.GetFunDefinition(fun.description.GetFunName()).runMode)
                    {
                    case DefFun.RUN_MODE.NOT_APPLICABLE: continue;

                    case DefFun.RUN_MODE.IN_SPINE:
                        if (spineState == AFTER)
                        {
                            runSequential = true; causeForSequential = prevFun;
                        }
                        else
                        {
                            spineState = IN; runInSpine.Add(fun);
                        }
                        break;

                    case DefFun.RUN_MODE.OUTSIDE_SPINE:
                        if (spineState == IN)
                        {
                            spineState = AFTER;
                        }
                        if (spineState == AFTER)
                        {
                            runAfterSpine.Add(fun as FunOutOfSpineBase);
                        }
                        else
                        {
                            runBeforeSpine.Add(fun as FunOutOfSpineBase);
                        }
                        break;
                    }
                    if (runSequential)
                    {
                        break;
                    }
                    prevFun = fun;
                }
            }
            if (runSequential)
            {
                runBeforeSpine.Clear(); runAfterSpine.Clear(); runInSpine.Clear();
                foreach (FunBase fun in infoStore.spine.Values)
                {
                    if (DefinitionAdmin.GetFunDefinition(fun.description.GetFunName()).runMode != DefFun.RUN_MODE.NOT_APPLICABLE)
                    {
                        runInSpine.Add(fun);
                    }
                }
                string cause = causeForSequential == null ? "Forcing sequential" : $"{causeForSequential.description.Get()}: usage inside spine";
                infoStore.communicator.ReportProgress(new Communicator.ProgressInfo()
                {
                    message = cause + " causes (slightly) slower run"
                });
            }

            // organise loop-handling (if there is/are any)
            foreach (FunBase fun in infoStore.spine.Values)
            {
                if (fun is FunLoop)
                {
                    FunLoop funLoop = fun as FunLoop;
                    if (!funLoop.GetRange(runInSpine) || IsLoopIntersection(funLoop))
                    {
                        continue;
                    }

                    // put loops into Dictionaries that allow LoopyGetNextFun to recognise that it needs to "talk" to the loops (when it hits start or end)
                    // if there are several loops with the same last function (nested loops) they are sorted reversly
                    // by their first function, in order to "ask" the inner loop first, if there should be a jump back
                    if (!loopEnds.ContainsKey(funLoop.indexLastFun))
                    {
                        loopEnds.Add(funLoop.indexLastFun, new SortedList <double, FunLoop>());
                    }
                    double iSort = funLoop.indexFirstFun; // if loops have the same start and end, make the first declared the outer
                    while (loopEnds[funLoop.indexLastFun].ContainsKey(iSort * (-1)))
                    {
                        iSort += 0.001;
                    }
                    loopEnds[funLoop.indexLastFun].Add(iSort * (-1), funLoop);

                    // similar holds for loops with the same start, they need to be sorted reversly by their last function
                    // in order to ask the outer loop first, if there should be a jump over
                    if (!loopStarts.ContainsKey(funLoop.indexFirstFun))
                    {
                        loopStarts.Add(funLoop.indexFirstFun, new SortedList <double, FunLoop>());
                    }
                    iSort = funLoop.indexLastFun; // see above, wrt to loops with same start and end
                    while (loopStarts[funLoop.indexFirstFun].ContainsKey(iSort * (-1)))
                    {
                        iSort -= 0.001;
                    }
                    loopStarts[funLoop.indexFirstFun].Add(iSort * (-1), funLoop);
                }
            }
        }
示例#8
0
 internal override void CheckAndPrepare(FunBase fun, List <string> footnoteNumbers)
 {
     isParent.CheckAndPrepare(fun, footnoteNumbers);
     isWithPartner.CheckAndPrepare(fun, footnoteNumbers);
 }
示例#9
0
 /// <summary> check and prepare the query's parameters </summary>
 internal abstract void CheckAndPrepare(FunBase fun,
                                        List <string> footnoteNumbers); // usually that's one footnote number (e.g. IsDepChild#2 -> 2)
示例#10
0
        private bool RunSequential(SpineAdmin spineManager)
        {
            int curFunIndex = 0;

            Dictionary <FunBase, List <FunUnitLoop> > unitLoopRanges = spineManager.GetUnitLoopRangesForSequentialRun();

            while (true) // loop over functions
            {
                FunBase fun = spineManager.GetNextFun(ref curFunIndex); if (fun == null)
                {
                    break;
                }

                DefFun.RUN_MODE runMode = // find out if the function expects to be run within HH-loop or not
                                          DefinitionAdmin.GetFunDefinition(fun.description.GetFunName()).runMode;
                if (runMode != DefFun.RUN_MODE.IN_SPINE)
                {
                    (fun as FunOutOfSpineBase).Run(); // concerns functions usually running pre- or post-spine (DefOutput, Totals, etc.)
                }
                else
                {
                    // concerns functions usually running in spine (BenCalc, Elig, etc.)
                    FunInSpineBase spineFun = fun as FunInSpineBase;
                    if (infoStore.runConfig.forceSequentialRun)
                    {
                        // run in a single thread
                        foreach (HH hh in infoStore.hhAdmin.hhs)
                        {
                            foreach (List <Person> tu in hh.GetTUs(spineFun.GetTUName()))
                            {
                                SpineFunRun(spineFun, hh, tu);
                            }
                        }
                    }
                    else
                    {
                        // run in multiple threads
                        Parallel.ForEach <HH>(infoStore.hhAdmin.hhs, hh => {
                            foreach (List <Person> tu in hh.GetTUs(spineFun.GetTUName()))
                            {
                                SpineFunRun(spineFun, hh, tu);
                            }
                        });
                    }
                }
                if (!infoStore.communicator.ReportProgress(
                        new Communicator.ProgressInfo()
                {
                    message = $"Done with function {fun.description.Get(true)}"
                }))
                {
                    return(false);
                }
            }
            return(true);

            void SpineFunRun(FunInSpineBase spineFun, HH hh, List <Person> tu)
            {
                bool run = false;

                if (unitLoopRanges.ContainsKey(spineFun))                // there are UnitLoops in the spine
                {                                                        // note that a function may be enclosed by more than one UnitLoop (see NRR add-on)
                    foreach (FunUnitLoop ul in unitLoopRanges[spineFun]) // if any of the UnitLoops allows running - run
                    {
                        if (!ul.IsFinished(hh))
                        {
                            run = true;
                        }
                    }
                }
                else
                {
                    run = true;  // the usual case - no UnitLoops
                }
                if (run)
                {
                    spineFun.Run(hh, tu);
                }
            }
        }
示例#11
0
        internal override void CheckAndPrepare(FunBase fun)
        {
            ExtractStandardFootnotes(xmlValue, out string queryName, fun); // it is not impossible that #_Low/UpLim are applied on queries
                                                                           // and #_Level may make good sense
            DefinitionAdmin.GetQueryDefinition(queryName, out DefinitionAdmin.Query queryDef, out string queryMainName);
            switch (queryMainName)                                         // a query may have aliases, therefore GetQueryDefinition returns the "main"-name
            {
            case DefQuery.GetSystemYear: query = new QueryGetSystemYear(infoStore); break;

            case DefQuery.GetDataIncomeYear: query = new QueryGetDataIncomeYear(infoStore); break;

            case DefQuery.GetExchangeRate: query = new QueryGetExchangeRate(infoStore); break;

            case DefQuery.GetPartnerIncome: query = new QueryGetPartnerIncome(infoStore); break;

            case DefQuery.GetMotherIncome: query = new QueryGetMotherIncome(infoStore); break;

            case DefQuery.GetFatherIncome: query = new QueryGetFatherIncome(infoStore); break;

            case DefQuery.GetCoupleIncome: query = new QueryGetCoupleIncome(infoStore); break;

            case DefQuery.GetParentsIncome: query = new QueryGetParentsIncome(infoStore); break;

            case DefQuery.GetOwnChildrenIncome: query = new QueryGetOwnChildrenIncome(infoStore); break;

            case DefQuery.HasMaxValInTu: query = new QueryHasMaxValInTu(infoStore); break;

            case DefQuery.HasMinValInTu: query = new QueryHasMinValInTu(infoStore); break;

            case DefQuery.IsHeadOfTu: query = new QueryIsHead(infoStore); break;

            case DefQuery.IsMarried: query = new QueryIsMarried(infoStore); break;

            case DefQuery.IsCohabiting: query = new QueryIsCohabiting(infoStore); break;

            case DefQuery.IsWithPartner: query = new QueryIsWithPartner(infoStore); break;

            case DefQuery.IsUsedDatabase: query = new QueryIsUsedDatabase(infoStore); break;

            case DefQuery.IsNtoMchild: query = new QueryIsNtoMChild(infoStore); break;

            case DefQuery.IsParent: query = new QueryIsParent(infoStore); break;

            case DefQuery.IsParentOfDepChild: query = new QueryIsParentOfDepChild(infoStore); break;

            case DefQuery.IsInEducation: query = new QueryIsInEducation(infoStore); break;

            case DefQuery.IsDisabled: query = new QueryIsDisabled(infoStore); break;

            case DefQuery.IsPartner: query = new QueryIsPartner(infoStore); break;

            case DefQuery.IsDepChild: query = new QueryIsDepChild(infoStore); break;

            case DefQuery.IsOwnChild: query = new QueryIsOwnChild(infoStore); break;

            case DefQuery.IsOwnDepChild: query = new QueryIsOwnDepChild(infoStore); break;

            case DefQuery.IsLooseDepChild: query = new QueryIsLooseDepChild(infoStore); break;

            case DefQuery.IsDepParent: query = new QueryIsDepParent(infoStore); break;

            case DefQuery.IsDepRelative: query = new QueryIsDepRelative(infoStore); break;

            case DefQuery.IsLoneParentOfDepChild: query = new QueryIsLoneParentOfDepChild(infoStore); break;

            case DefQuery.IsCivilServant: query = new QueryIsCivilServant(infoStore); break;

            case DefQuery.IsBlueColl: query = new QueryIsBlueColl(infoStore); break;

            case DefQuery.IsOutputCurrencyEuro: query = new QueryIsOutputCurrencyEuro(infoStore); break;

            case DefQuery.IsParamCurrencyEuro: query = new QueryIsParamCurrencyEuro(infoStore); break;

            case DefQuery.IsLoneParent: query = new QueryIsLoneParent(infoStore); break;

            case DefQuery.nChildrenOfCouple: query = new QueryNChildrenOfCouple(infoStore); break;

            case DefQuery.nDepChildrenOfCouple: query = new QueryNDepChildrenOfCouple(infoStore); break;

            case DefQuery.nAdultsInTu: query = new QueryNAdultsInTu(infoStore); break;

            case DefQuery.nDepChildrenInTu: query = new QueryNDepChildrenInTu(infoStore); break;

            case DefQuery.nLooseDepChildrenInTu: query = new QueryNLooseDepChildrenInTu(infoStore); break;

            case DefQuery.nDepParentsInTu: query = new QueryNDepParentsInTu(infoStore); break;

            case DefQuery.nDepRelativesInTu: query = new QueryNDepRelativesInTu(infoStore); break;

            case DefQuery.nDepParentsAndRelativesInTu: query = new QueryNDepParentsAndRelativesInTu(infoStore); break;

            case DefQuery.nPersInUnit: query = new QueryNPersInUnit(infoStore); break;

            case DefQuery.rand: query = new QueryRand(infoStore); break;

            default:     // the query must be defined in DefQuery, otherwise there wouldn't be a ParQuery-parameter, but it seems to be not implemented)
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false, message = $"{description.Get()}: usage of not implemented query {queryName}"
                });
                return;
            }

            isGlobal          = queryDef.isGlobal;
            query.description = new Description(description, queryName);
            query.CheckAndPrepare(fun, GetFootnoteNumbers(xmlValue, out string dummy));
        }
示例#12
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}"
                });
            }
        }
示例#13
0
        internal string alternativeTU  = null; // #_Level

        internal virtual void CheckAndPrepare(FunBase fun)
        {
        }
        internal override void CheckAndPrepare(FunBase fun)
        {
            if (FunIlArithOp.HandlesCheckAndPrepare(this))
            {
                return;                                            // IlArithOp has a special handling for the Formula parameter (see FunIlArithOp.cs)
            }
            if (xmlValue.Contains("}#"))
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = true, runTimeErrorId = description.funID, message = $"{description.Get()}: Footnotes should not be placed outside curly brackets! Please make sure that all footnotes are directly applied to a single operand."
                });
            }
            // for optimisation reasons handle #Amount and periods (#y, #w, ...) before parsing the formula:
            // alternatively one could allow for PAR_TYPE.NUMBER in the switch below, which would create a ParNumber that takes care
            // but then e.g. 1200#y*3 would, for each HH, ask for parNumber.GetValue()*3, while with this "preparsing" we just have 300
            string preParsedFormula = PreParse(xmlValue, fun);

            // parse the main formula
            try { parsedExpression = calc.CompileExpression(preParsedFormula); }
            catch (Exception e)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false, message = $"{description.Get()}: {e.Message}"
                }); return;
            }

            foreach (string op in calc.Variables.Keys)     // parse the formula ...
            {
                ParBase_FormulaComponent opPar = null;     // ... and prepare the operands

                GetFootnoteNumbers(op, out string opName); // temporarily remove potential footnotes to get the pure operand (e.g. yem#1->yem)

                // handle "partner:yem" or "head:yem"
                if (opName.Contains(":"))
                {
                    // this is not allowed outside DefTU!
                    if (description.fun.Name != DefFun.DefTu)
                    {
                        infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                        {
                            isWarning = false, message = $"{description.Get()}: invalid use of target outside of a DefTU '{opName}'."
                        });
                    }
                    opName = opName.Substring(opName.IndexOf(":") + 1);
                }

                if (infoStore.operandAdmin.Exists(opName))
                {
                    switch (infoStore.operandAdmin.GetParType(opName))
                    {
                    //case DefPar.PAR_TYPE.NUMBER: opPar = new ParNumber(infoStore); break; // see PreParse above
                    case DefPar.PAR_TYPE.VAR: opPar = new ParVar(infoStore); break;

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

                    case DefPar.PAR_TYPE.QUERY: opPar = new ParQuery(infoStore); break;
                    }
                }
                else
                {
                    opPar = new ParVar(infoStore);  // if not yet in the operand-list, the only (not faulty) option is a data-variable
                }
                opPar.description = description;
                opPar.xmlValue    = op;
                opPar.CheckAndPrepare(fun);
                operands.Add(op, opPar);
            }
        }