Beispiel #1
0
        private void ReadInfo(ExeXml.Fun fun, string funId, out Dictionary <string, Tuple <string, string> > changes,
                              out ExeXml.Par parRunCond, out List <ExeXml.Par> parDatabaseName)
        {
            parRunCond = null; parDatabaseName = new List <ExeXml.Par>();
            changes    = new Dictionary <string, Tuple <string, string> >(); // key: group, value.item1: fun/pol-ident, value.item2: on/off
            foreach (var par in fun.pars.Values)
            {
                if (par.Name.ToLower() == DefPar.Common.Run_Cond.ToLower()) // Run_Cond = { xxx }
                {
                    parRunCond = par;
                }
                else if (par.Name.ToLower() == DefQuery.Par.DataBasename.ToLower())  // #_DatabaseName is the only footnote-parameter possible
                {
                    parDatabaseName.Add(par);                                        // for global conditions (i.e. the Run_Cond)
                }
                else if (par.Name.ToLower() == DefPar.ChangeSwitch.PolFun.ToLower()) // PolFun = Guid / PolFun = policy-name
                {
                    AddToChangeList(changes, par.Group, par.val, false, funId);
                }
                else if (par.Name.ToLower() == DefPar.ChangeSwitch.Switch_NewVal.ToLower()) // SwitchNewVal = on/off
                {
                    AddToChangeList(changes, par.Group, par.val, true, funId);
                }
                else
                {
                    infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                    {
                        isWarning = false,
                        message   = $"Change switch ({funId}): unknown parameter {par.Name}"
                    });
                }
            }

            if (parRunCond == null)
            {
                return;
            }

            // make sure that footnote-parameters (i.e. #_DatabasName) do not get into conflict with existing footnote-parameters (i.e. same group)
            List <int> replaceGroups = new List <int>();

            foreach (ExeXml.Par parDB in parDatabaseName)
            {
                if (!int.TryParse(parDB.Group, out int g))
                {
                    continue;                                        // ignore this rather unlikely case (just keep the strange group)
                }
                parDB.Group = GetNewGroup(g).ToString(); replaceGroups.Add(g);
            }
            replaceGroups.Sort(); replaceGroups.Reverse(); // avoid replacing ...#1...#12... with ...#9901...#99012...
            foreach (int group in replaceGroups)           // and hope there is no #9
            {
                parRunCond.val = parRunCond.val.Replace($"#{group}", $"#{GetNewGroup(group)}");
            }

            int GetNewGroup(int group)
            {
                return(group + 9900);
            }
        }
 private ExeXml.Fun CloneFun(ExeXml.Fun fun)
 {
     ExeXml.Fun clone = new ExeXml.Fun {
         Name = fun.Name, on = fun.on, order = fun.order
     };
     foreach (ExeXml.Par par in fun.pars.Values)
     {
         ExeXml.Par clonePar = new ExeXml.Par()
         {
             Name = par.Name, Group = par.Group, order = par.order, val = par.val
         };
         clone.pars.Add(Guid.NewGuid().ToString(), clonePar);
     }
     return(clone);
 }
        private bool FindFun(string funID, Dictionary <string, ExeXml.Pol> pols, Description description,
                             out ExeXml.Fun foundFun, out ExeXml.Pol parentPol)
        {
            foreach (ExeXml.Pol pol in pols.Values)
            {
                if (pol.funs.ContainsKey(funID))
                {
                    foundFun = pol.funs[funID]; parentPol = pol; return(true);
                }
            }

            infoStore.communicator.ReportError(new Communicator.ErrorInfo()
            {
                isWarning = false,
                message   = $"{description.Get()}: unknown function-id {funID}"
            });
            foundFun = null; parentPol = null; return(false);
        }
        private void IntegratePar(ExeXml.Fun addOnPar, Description funDescription)
        {
            string insertFunID = null;
            Dictionary <string, ExeXml.Par> parToAdd = new Dictionary <string, ExeXml.Par>();

            // interpret the parameters of the AddOn_Par function
            foreach (var p in addOnPar.pars)
            {
                if (p.Value.val == DefPar.Value.NA)
                {
                    continue;
                }
                if (p.Value.Name.ToLower() == DefPar.AddOn_Par.Insert_Func.ToLower())
                {
                    insertFunID = p.Value.val;
                }
                else
                {
                    parToAdd.Add(p.Key, p.Value);  // any other parameter is an add-on-parameter (i.e. should be added to the insert-function)
                }
            }
            // check for the only compulsory parameter
            if (insertFunID == null)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false,
                    message   = $"{funDescription.Get()}: parameter {DefPar.AddOn_Par.Insert_Func} not defined"
                });
                return;
            }

            // find the insert-function in the country file
            if (!FindFun(insertFunID, infoStore.country.cao.pols, funDescription, out ExeXml.Fun insertFun, out ExeXml.Pol dummy))
            {
                return;
            }
            // add the parameters to the insert-function (note: order of parameters is irrelevant for the executable)
            insertFun.pars.AddRange(parToAdd);
        }
Beispiel #5
0
        // implementation of new function ChangeSwitch, which partly replaces run-time changes of ChangeParam (see ApplyChangeParam)
        // parameters provided:
        // - optional parameter RunCond (if present: run-time switch-change, if not present: read-time switch-change)
        // - parameters for switching on/off policies/functions:
        //   parameter-group: PolFun: id/name of policy/function
        //                    SwitchNewVal: on/off
        // examples: Run_Cond = { $ScenarioX = 1 }, PolFun (Group 1) = bsa_cy, NewSwitch (Group 1) = off,
        //                                          PolFun (Group 2) = A18317A2-25AC-4E58-AFA2-92E80623550F, NewSwitch (Group 2) = on
        //           (in an AddOn:) Run_Cond = { $Sum_xyz > 100 }, PolFun (Group 1) = tco_cy, NewSwitch (Group 1) = off,
        //                                                         PolFun (Group 2) = tin_cy#1, NewSwitch (Group 2) = off
        // (note: symbolic IDs are already replaced at this stage(by add-on integration))
        private void ApplyChangeSwitch()
        {
            foreach (var cs in GetSpecificFuns(DefFun.ChangeSwitch))
            {
                ExeXml.Fun fun = cs.Value; string funId = cs.Key;

                // gather the information by reading parameters: there may be a Run_Cond (optional),
                // the other parameters are a list of switch changes, defined by the parameters PolFun (=id) and SwitchNewVal (=on/off)
                ReadInfo(fun, funId, out Dictionary <string, Tuple <string, string> > changes,
                         out ExeXml.Par parRunCond, out List <ExeXml.Par> parDatabaseName);

                // gather the functions which are affected by the switch-changes (i.e. all functions of a policy or a specific function)
                // and check for unknown ids or invalid switches
                CheckInfo(funId, changes, out Dictionary <ExeXml.Fun, bool> switchInfo);

                // apply the switch changes, taking run-cond into account
                ApplyInfo(switchInfo, parRunCond, parDatabaseName);

                // finally, switch ChangeSwitch-function off: thus DropOff will delete it
                fun.on = false;
            }
        }
Beispiel #6
0
        // important note on new handling of ChangeParam:
        // - ChangeParam will only allow for read-time changes and does not allow for changing switches anymore
        // - a new function ChangeSwitch will allow for changing switches of policies/functions at run- or read-time
        //
        // justification:
        // - the only reason for run-time parameter changes are loops:
        //   as far as I can see this option is only used by MTR and LMA to switch policies/functions on/off
        // - other applications just 'misuse' Param_CondVal (AT, BE), i.e. they do not provide a RunCond and thus c(sh)ould use Param_NewVal
        //   (e.g. AT switches stuff off for SORESI, in a ChangeParam located in a policy that is only on for SORESI)
        //
        // actual reason for the abolishment:
        // full application of run-time parameter changes is very complex (close to impossible, consider e.g. formula-interpretation ...)


        // changes to old ChangeParam:
        // - parameter Param_CondVal is abolished (i.e. no run-time changes anymore - but see ApplyChangeSwitch),
        //   respectively renamed to Param_NewVal where the change actually concerns a read-time-change
        // - parameter RunCond is abolished, respectively replaced by
        // - parameter Database (non-unique): usage like in Uprate/SetDefault, except not provided means apply for any dataset here
        // examples: Database = sk_2019, Param_Id = 9ac9d5e6-bbfe-4e5c-a87e-940b33a5457e, Param_NewVal = adp*0.5 (e.g. if adp exists only in this data)
        //           (in an AddOn:) Param_Id = yem_sk_#2.1, Param_NewVal = { dag <= 6 }
        // (note: symbolic IDs are already replaced at this stage (by add-on integration))
        private void ApplyChangeParam()
        {
            foreach (var cp in GetSpecificFuns(DefFun.ChangeParam))
            {
                ExeXml.Fun cpFun = cp.Value; string cpFunId = cp.Key;

                // gather the information (consisting of whether the function applies to the current dataset and the list of changes)
                Dictionary <string, Tuple <string, string> > changeList = new Dictionary <string, Tuple <string, string> >();
                List <string> applyDatasets = new List <string>();
                foreach (ExeXml.Par par in cpFun.pars.Values)
                {
                    if (par.Name.ToLower() == DefPar.ChangeParam.Dataset.ToLower())
                    {
                        applyDatasets.Add(par.val);
                    }
                    else if (par.Name.ToLower() == DefPar.ChangeParam.Param_Id.ToLower())
                    {
                        AddToChangeList(changeList, par.Group, par.val, false, cpFunId);
                    }
                    else if (par.Name.ToLower() == DefPar.ChangeParam.Param_NewVal.ToLower())
                    {
                        AddToChangeList(changeList, par.Group, par.val, true, cpFunId);
                    }
                    else
                    {
                        infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                        {
                            isWarning = false,
                            message   = $"Change param ({cpFunId}): unknown parameter {par.Name}"
                        });
                    }
                }

                // check if the ChangeParam applies to the currently used dataset
                bool applies = applyDatasets.Count == 0; // if there is no Dataset parameter the change applies (see explanation above)
                foreach (string dataName in applyDatasets)
                {
                    if (infoStore.IsUsedDatabase(dataName))
                    {
                        applies = true; break;
                    }
                }

                if (applies)
                {
                    // check if the IDs exist and (if yes) apply the changes
                    foreach (var change in changeList) // remark: if there are many changes, it may be more efficient to
                    {                                  // loop only once over all pars, but I assume that's not very likely
                        string group = change.Key, changeId = change.Value.Item1, changeNewVal = change.Value.Item2;
                        if (changeId == null || changeNewVal == null)
                        {
                            infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                            {
                                isWarning = false,
                                message   = $"Change param ({cpFunId}): insufficient definition of group {group}"
                            });
                            continue;
                        }

                        bool found = false;
                        foreach (var pol in infoStore.country.cao.pols.Values)
                        {
                            foreach (var fun in pol.funs.Values)
                            {
                                if (fun.pars.ContainsKey(changeId))
                                {
                                    fun.pars[changeId].val = changeNewVal; found = true; break;
                                }
                                if (found)
                                {
                                    break;
                                }
                            }
                            if (found)
                            {
                                break;
                            }
                        }

                        if (!found)
                        {
                            infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                            {
                                isWarning = false,
                                message   = $"Change param ({cpFunId}): parameter id {changeId} not found"
                            });
                        }
                    }
                }

                // finally, switch ChangeParam-function off: thus DropOff will delete it
                cpFun.on = false;
            }
        }
 internal Description(Description parDesc, string _queryName)
 {
     pol = parDesc.pol; fun = parDesc.fun; funID = parDesc.funID; par = parDesc.par; parID = parDesc.parID; queryName = _queryName;
 }
 internal Description(Description funDesc, ExeXml.Par _par, string _parID = null)
 {
     pol = funDesc.pol; fun = funDesc.fun; funID = funDesc.funID; par = _par; parID = _parID;
 }
        internal bool isPlaceholder = false; // is relevant for e.g. FunDefVar and FunDefUprate (see FunBase.GetPlaceholderGroupPar)

        internal Description(ExeXml.Pol _pol, ExeXml.Fun _fun, string _funID = null)
        {
            pol = _pol; fun = _fun; funID = _funID;
        }
Beispiel #10
0
        private void CheckAndPrepare()
        {
            Dictionary <double, ExeXml.Fun> allFun = new Dictionary <double, ExeXml.Fun>(); // key: order - necessary to do TakePar in spine-order, see below

            // 1st STEP: IDENTIFY FUNCTIONS
            foreach (var pol in infoStore.country.cao.pols) // policies are only function-containers, not relevant for the run
            {                                               // (except from perhaps error-reporting)
                foreach (var f in pol.Value.funs)
                {
                    ExeXml.Fun  xmlFun = f.Value; string funID = f.Key;
                    Description funDescription = new Description(pol.Value, xmlFun, funID); string funName = xmlFun.Name.ToLower();
                    double      order = GetOrder(pol.Value.order, xmlFun.order); bool recognised = true;

                    if (funName == DefFun.ArithOp.ToLower())
                    {
                        infoStore.spine.Add(order, new FunArithOp(infoStore));
                    }
                    else if (funName == DefFun.Elig.ToLower())
                    {
                        infoStore.spine.Add(order, new FunElig(infoStore));
                    }
                    else if (funName == DefFun.BenCalc.ToLower())
                    {
                        infoStore.spine.Add(order, new FunBenCalc(infoStore));
                    }
                    else if (funName == DefFun.SchedCalc.ToLower())
                    {
                        infoStore.spine.Add(order, new FunSchedCalc(infoStore));
                    }
                    else if (funName == DefFun.Min.ToLower())
                    {
                        infoStore.spine.Add(order, new FunMin(infoStore));
                    }
                    else if (funName == DefFun.Max.ToLower())
                    {
                        infoStore.spine.Add(order, new FunMax(infoStore));
                    }
                    else if (funName == DefFun.Allocate.ToLower())
                    {
                        infoStore.spine.Add(order, new FunAllocate(infoStore));
                    }
                    else if (funName == DefFun.DefVar.ToLower())
                    {
                        infoStore.spine.Add(order, new FunDefVar(infoStore, false));
                    }
                    else if (funName == DefFun.DefConst.ToLower())
                    {
                        infoStore.spine.Add(order, new FunDefVar(infoStore, true));
                    }
                    else if (funName == DefFun.DefIl.ToLower())
                    {
                        infoStore.spine.Add(order, new FunDefIL(infoStore));
                    }
                    else if (funName == DefFun.Store.ToLower())
                    {
                        infoStore.spine.Add(order, new FunStore(infoStore));
                    }
                    else if (funName == DefFun.Restore.ToLower())
                    {
                        infoStore.spine.Add(order, new FunRestore(infoStore));
                    }
                    else if (funName == DefFun.IlVarOp.ToLower())
                    {
                        infoStore.spine.Add(order, new FunILVarOp(infoStore));
                    }
                    else if (funName == DefFun.RandSeed.ToLower())
                    {
                        infoStore.spine.Add(order, new FunRandSeed(infoStore));
                    }
                    else if (funName == DefFun.CallProgramme.ToLower())
                    {
                        infoStore.spine.Add(order, new FunCallProgramme(infoStore));
                    }
                    else if (funName == DefFun.DefInput.ToLower())
                    {
                        infoStore.spine.Add(order, new FunDefInput(infoStore));
                    }
                    else if (funName == DefFun.DefTu.ToLower())
                    {
                        infoStore.spine.Add(order, new FunDefTU(infoStore));
                    }
                    else if (funName == DefFun.UpdateTu.ToLower())
                    {
                        infoStore.spine.Add(order, new FunUpdateTU(infoStore));
                    }
                    else if (funName == DefFun.Uprate.ToLower())
                    {
                        infoStore.spine.Add(order, new FunUprate(infoStore));
                    }
                    else if (funName == DefFun.SetDefault.ToLower())
                    {
                        infoStore.spine.Add(order, new FunSetDefault(infoStore));
                    }
                    else if (funName == DefFun.DefOutput.ToLower())
                    {
                        infoStore.spine.Add(order, new FunDefOutput(infoStore));
                    }
                    else if (funName == DefFun.Loop.ToLower())
                    {
                        infoStore.spine.Add(order, new FunLoop(infoStore));
                    }
                    else if (funName == DefFun.UnitLoop.ToLower())
                    {
                        infoStore.spine.Add(order, new FunUnitLoop(infoStore));
                    }
                    else if (funName == DefFun.Totals.ToLower())
                    {
                        infoStore.spine.Add(order, new FunTotals(infoStore));
                    }
                    else if (funName == DefFun.Scale.ToLower())
                    {
                        infoStore.spine.Add(order, new FunScale(infoStore));
                    }
                    else if (funName == DefFun.DropUnit.ToLower())
                    {
                        infoStore.spine.Add(order, new FunDropKeepUnit(infoStore, false));
                    }
                    else if (funName == DefFun.KeepUnit.ToLower())
                    {
                        infoStore.spine.Add(order, new FunDropKeepUnit(infoStore, true));
                    }
                    else if (funName == DefFun.AddHHMembers.ToLower())
                    {
                        infoStore.spine.Add(order, new FunAddHHMembers(infoStore));
                    }
                    else if (funName == DefFun.IlArithOp.ToLower())
                    {
                        infoStore.spine.Add(order, new FunIlArithOp(infoStore));
                    }
                    else
                    {
                        infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                        {
                            isWarning = true, message = $"Unkown function is ignored: {funDescription.Get()}"
                        });
                        recognised = false;
                    }

                    // identification of parameters is moved below, to be done in spine-order (this is at the stage of moving only necessary for FunScale)
                    //if (recognised) infoStore.spine[order].TakePar(funDescription, xmlFun.pars);
                    if (recognised)
                    {
                        infoStore.spine[order].description = funDescription; allFun.Add(order, f.Value);
                    }
                }
            }

            // 2nd STEP: IDENTIFY (KNOWN) PARAMETERS AND CHECK FOR COMPLETENESS
            foreach (var f in infoStore.spine)
            {
                f.Value.TakePar(f.Value.description, allFun[f.Key].pars);
            }

            // 3rd STEP: PUT TUs, VARIABLES, QUERIES, LOOPS, etc. (i.e. stuff that's used by other parameters) INTO RESPECTIVE INDICES
            foreach (FunBase fun in infoStore.spine.Values)
            {
                fun.ProvideIndexInfo();
            }

            // 4th STEP: ANALYSE PARAMETER-VALUES
            foreach (FunBase fun in infoStore.spine.Values)
            {
                if (fun.description.GetFunName().ToLower() != DefFun.DefTu.ToLower()) // for DefTU this function is called by ParTU, i.e.
                {
                    fun.CheckAndPrepare();                                            // on first usage (see ParTU for futher explanation)
                }
            }
        }
        private void HandleExtensionSwitches(List <ExeXml.AddOn> addOns)
        {
            // first overwrite the default switch settings in the country file, if the user changed them (via config-settings sent by the run-tool)
            TakeExtensionSwitches(infoStore.runConfig.extensionSwitches);

            // then overwrite with any instructions from extensions, the means the priority of switches to be on or off is as follows:
            // highest: add-ons (via AddOn_ExtensionSwitch), next: user settings (via run-tool), lowest: default settings (via set-switches-dialog)
            TakeAddOnExtensionSwitches(addOns);

            // take care of a "feature" that is mainly there for compatibility with the version before March 2020, where the switches of functions within extension-policies were visible instead of set to switch
            // namly that such functions can be permanantly off instead of switchable
            List <ExeXml.Fun> permanentOffFunctions = TakeCareOfPermanentOffFunctions();

            // lists for taking into account that pol/fun/par can be switched by more than one extension and that 'on' always wins
            List <string> onIds = new List <string>();
            Dictionary <string, ExeXml.Fun> parsToRemove = new Dictionary <string, ExeXml.Fun>();

            foreach (var extension in infoStore.country.extensions.Values)
            {
                foreach (var extPol in extension.polIds)
                {
                    string polId     = extPol.Key;
                    bool   isBasePol = extPol.Value == true; // true: a base-policy, that is switched off if the extension is on

                    if (!infoStore.country.cao.pols.ContainsKey(polId))
                    {
                        continue;
                    }
                    ExeXml.Pol pol = infoStore.country.cao.pols[polId];

                    bool?switchOn = null;
                    if (extension.on == true)
                    {
                        switchOn = isBasePol ? false : true;                       // extension-switch is on: added-as-on ✔: on; added-as-off ✘: off
                    }
                    else if (!isBasePol)
                    {
                        switchOn = false;                  // extension-switch is off or n/a: added-as-on ✔: off; added-as-off ✘: do not touch
                    }
                    if (switchOn == true)
                    {
                        pol.on = true;
                    }
                    if (switchOn == false && !onIds.Contains(polId))
                    {
                        pol.on = false;
                    }

                    // add the policy and all its functions and parameters, which do not have an own setting, to the switched-on (i.e. winning) elements
                    if (switchOn == true)
                    {
                        onIds.AddUnique(polId);
                        foreach (var f in pol.funs)
                        {
                            if (!extension.funIds.ContainsKey(f.Key))
                            {
                                string funId = f.Key; ExeXml.Fun fun = f.Value;
                                fun.on = true; onIds.AddUnique(funId);
                                foreach (var parId in fun.pars.Keys)
                                {
                                    if (!extension.parIds.ContainsKey(parId))
                                    {
                                        if (parsToRemove.ContainsKey(parId))
                                        {
                                            parsToRemove.Remove(parId);
                                        }
                                        onIds.AddUnique(parId);
                                    }
                                }
                            }
                        }
                    }
                }
                foreach (var extFun in extension.funIds)
                {
                    string funId     = extFun.Key;
                    bool   isBaseFun = extFun.Value == true; // true: a base-function, that is switched off if the extension is on

                    ExeXml.Fun fun = null;
                    foreach (var pol in infoStore.country.cao.pols)
                    {
                        var funs = from f in pol.Value.funs where f.Key == funId select f; if (!funs.Any())
                        {
                            continue;
                        }
                        fun = funs.First().Value;
                        if (fun.pars.Count == 0)
                        {
                            fun = null;                      // this takes care of functions which are set to n/a including all their parameters for this system, i.e. ignores them
                        }
                        break;
                    }
                    if (fun == null)
                    {
                        continue;
                    }

                    // see explanation above, however note: if parent-policy is switched off, all included functions are off as well
                    // if parent-policy is switched on, included functions can still be switched off
                    bool?switchOn = null;
                    if (extension.on == true)
                    {
                        switchOn = isBaseFun ? false : true;                       // extension-switch is on: added-as-on ✔: on; added-as-off ✘: off
                    }
                    else if (!isBaseFun)
                    {
                        switchOn = false;                  // extension-switch is off or n/a: added-as-on ✔: off; added-as-off ✘: do not touch
                    }
                    if (switchOn == true)
                    {
                        fun.on = true;
                    }
                    if (switchOn == false && !onIds.Contains(funId))
                    {
                        fun.on = false;
                    }

                    // add the function and all its parameters, which do not have an own setting, to the switched-on (i.e. winning) elements
                    if (switchOn == true)
                    {
                        onIds.AddUnique(funId);
                        foreach (var parId in fun.pars.Keys)
                        {
                            if (!extension.parIds.ContainsKey(parId))
                            {
                                if (parsToRemove.ContainsKey(parId))
                                {
                                    parsToRemove.Remove(parId);
                                }
                                onIds.AddUnique(parId);
                            }
                        }
                    }
                }
                foreach (var extPar in extension.parIds)
                {
                    string parId = extPar.Key; bool isBasePar = extPar.Value == true;

                    // other than for pol/fun we do not need the par, but its id and the parent-fun, because we need to delete the parameter in case
                    ExeXml.Fun parentFun = null;
                    foreach (var pol in infoStore.country.cao.pols)
                    {
                        foreach (var fun in pol.Value.funs)
                        {
                            if ((from p in fun.Value.pars where p.Key == parId select p).Any())
                            {
                                parentFun = fun.Value; break;
                            }
                        }
                        if (parentFun != null)
                        {
                            break;
                        }
                    }
                    if (parentFun == null)
                    {
                        continue;
                    }

                    bool?keepPar = null;
                    if (extension.on == true)
                    {
                        keepPar = isBasePar ? false : true;                       // extension-switch is on: added-as-on ✔: keep par, added-as-off ✘: remove par
                    }
                    else if (!isBasePar)
                    {
                        keepPar = false;                  // extension-switch is off or n/a: added-as-on ✔: remove par, added-as-off ✘: do not touch
                    }
                    if (keepPar == true && parsToRemove.ContainsKey(parId))
                    {
                        parsToRemove.Remove(parId);
                    }
                    if (keepPar == false && !onIds.Contains(parId))
                    {
                        parsToRemove.TryAdd(parId, parentFun);
                    }
                    if (keepPar == true)
                    {
                        onIds.AddUnique(parId);
                    }
                }
            }
            foreach (var ptr in parsToRemove)
            {
                ptr.Value.pars.Remove(ptr.Key);                               // remove the respective parameters only after taking all extensions into account
            }
            foreach (ExeXml.Fun pof in permanentOffFunctions)
            {
                pof.on = false;
            }
        }
        internal void IntegratePol(ExeXml.AddOn addOn, ExeXml.Fun addOnPol, Description funDescription)
        {
            string polName     = null; // the name of the policy to add
            string linkPolName = null; // the name of the policy after or before which to add the policy
            bool   before      = true;

            // interpret the parameters of the AddOn_Pol function
            foreach (var par in addOnPol.pars.Values)
            {
                if (par.val == DefPar.Value.NA)
                {
                    continue;
                }
                Description parDescription = new Description(funDescription, par);
                if (par.Name.ToLower() == DefPar.AddOn_Pol.Pol_Name.ToLower())
                {
                    polName = par.val;
                }
                else if (par.Name.ToLower() == DefPar.AddOn_Pol.Insert_Before_Pol.ToLower())
                {
                    linkPolName = par.val;
                }
                else if (par.Name.ToLower() == DefPar.AddOn_Pol.Insert_After_Pol.ToLower())
                {
                    linkPolName = par.val; before = false;
                }
                else if (par.Name.ToLower() == DefPar.AddOn_Pol.Allow_Duplicates.ToLower())
                {
                }                                                                               // do nothing, just allow duplicates always
                else
                {
                    infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                    {
                        isWarning = true, message = $"{parDescription.Get()}: unknown parameter: {par.Name}"
                    });
                }
            }

            // check for compulsory parameters
            if (polName == null)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false,
                    message   = $"{funDescription.Get()}: parameter {DefPar.AddOn_Pol.Pol_Name} not defined"
                });
                return;
            }
            if (linkPolName == null)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false,
                    message   = $"{funDescription.Get()}: neither {DefPar.AddOn_Pol.Insert_Before_Pol} nor {DefPar.AddOn_Pol.Insert_After_Pol} defined"
                });
                return;
            }

            // integrate the policy ...
            // ... in the country file, find the policy after or before which to integrate the policy
            if (!FindPol(addOn, linkPolName, infoStore.country.cao.pols, out ExeXml.Pol linkPol, out string dummy))
            {
                return;
            }
            // ... in the add-on file, find the policy to add
            if (!FindPol(addOn, polName, addOn.cao.pols, out ExeXml.Pol pol, out string polID))
            {
                return;
            }
            // ... check if policy was added before, if yes, make a clone with different ids
            if (infoStore.country.cao.pols.ContainsKey(polID))
            {
                polID = Guid.NewGuid().ToString(); pol = ClonePol(pol);
            }
            // ... find an appropriate order
            pol.order = MakeOrder(linkPol.order, (from p in infoStore.country.cao.pols.Values select p.order).ToList(), before);
            // ... add the policy
            infoStore.country.cao.pols.Add(polID, pol);
        }
        private void IntegrateFun(ExeXml.AddOn addOn, ExeXml.Fun addOnFun, Description funDescription)
        {
            string funID     = null; // the id of the function to add
            string linkFunID = null; // the id of the function after or before which to add the function
            bool   before    = true;

            // interpret the parameters of the AddOn_Func function
            foreach (var par in addOnFun.pars.Values)
            {
                if (par.val == DefPar.Value.NA)
                {
                    continue;
                }
                Description parDescription = new Description(funDescription, par);
                if (par.Name.ToLower() == DefPar.AddOn_Func.Id_Func.ToLower())
                {
                    funID = par.val;
                }
                else if (par.Name.ToLower() == DefPar.AddOn_Func.Insert_Before_Func.ToLower())
                {
                    linkFunID = par.val;
                }
                else if (par.Name.ToLower() == DefPar.AddOn_Func.Insert_After_Func.ToLower())
                {
                    linkFunID = par.val; before = false;
                }
                else
                {
                    infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                    {
                        isWarning = true, message = $"{parDescription.Get()}: unknown parameter: {par.Name}"
                    });
                }
            }

            // check for compulsory parameters
            if (funID == null)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false,
                    message   = $"{funDescription.Get()}: parameter {DefPar.AddOn_Func.Id_Func} not defined"
                });
                return;
            }
            if (linkFunID == null)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false,
                    message   = $"{funDescription.Get()}: neither {DefPar.AddOn_Func.Insert_Before_Func} nor {DefPar.AddOn_Func.Insert_After_Func} defined"
                });
                return;
            }

            // integrate the function ...
            // ... in the country file, find the function after or before which to integrate the function
            if (!FindFun(linkFunID, infoStore.country.cao.pols, funDescription, out ExeXml.Fun linkFun, out ExeXml.Pol parentPol))
            {
                return;
            }
            // ... in the add-on file, find the function to add
            if (!FindFun(funID, addOn.cao.pols, funDescription, out ExeXml.Fun fun, out ExeXml.Pol dummy))
            {
                return;
            }
            // ... check if function was added before, if yes, make a clone with different ids
            if (!parentPol.funs.ContainsKey(funID))
            {
                funID = Guid.NewGuid().ToString(); fun = CloneFun(fun);
            }
            // ... find an appropriate order
            fun.order = MakeOrder(linkFun.order, (from f in parentPol.funs.Values select f.order).ToList(), before);
            // ... add the function
            parentPol.funs.Add(funID, fun);
        }
Beispiel #14
0
        private void ApplyInfo(Dictionary <ExeXml.Fun, bool> switchInfo, ExeXml.Par switchFunRunCond, List <ExeXml.Par> switchFunDatabaseName)
        {
            foreach (var si in switchInfo)
            {
                ExeXml.Fun fun = si.Key; bool on = si.Value;

                // read-time change - simply change the switch as required
                if (switchFunRunCond == null)
                {
                    fun.on = on; continue;
                }

                // run-time change: implement switch by editing or adding the function's RunCond
                var hasRunCond = from p in fun.pars.Values
                                 where p.Name.ToLower() == DefPar.Common.Run_Cond.ToLower()
                                 select p;
                // function does not yet have a RunCond: add a copy of the ChangeSwitch-RunCond
                if (hasRunCond == null || hasRunCond.Count() == 0)
                {
                    if (fun.Name.ToLower() != DefFun.DefTu.ToLower() && // DefTU and DefIL do not accept a RunCond (does not make sense)
                        fun.Name.ToLower() != DefFun.DefIl.ToLower())   // and it does no harm if these definitions exist
                    {
                        ExeXml.Par newRunCond = new ExeXml.Par()
                        {
                            Name = DefPar.Common.Run_Cond
                        };
                        // function is currently on, switch off if RunCon is fulfilled
                        // i.e. run as long as ChangeSwitch-RunCond is not fulfilled
                        if (fun.on)
                        {
                            newRunCond.val = $"!({switchFunRunCond.val})";
                        }
                        // function is currently off, switch on if RunCond is fulfilled
                        // needs to be switched on, otherwise it is dropped by DropOff
                        // but do not run until ChangeSwitch-RunCond is fulfilled
                        else
                        {
                            fun.on = true; newRunCond.val = switchFunRunCond.val;
                        }
                        fun.pars.Add(Guid.NewGuid().ToString(), newRunCond);
                    }
                }
                // function has a RunCond: merge with the ChangeSwitch-RunCond
                else
                {
                    ExeXml.Par runCond = hasRunCond.First();
                    // function is currently on, switch off if RunCon is fulfilled
                    // run if current RunCond is fulfilled and as long as ChangeSwitch-RunCond is not fulfilled
                    if (fun.on)
                    {
                        runCond.val = $"!({switchFunRunCond.val}) & ({runCond.val})";
                    }
                    // function is currently off, switch on if RunCond is fulfilled
                    // needs to be switched on, otherwise it is dropped by DropOff
                    // but do not run until ChangeSwitch-RunCond is fulfilled, but still also fulfill current RunCond
                    else
                    {
                        fun.on = true; runCond.val = $"({switchFunRunCond.val}) & ({runCond.val})";
                    }
                }
                // transfer a possible #_DatabaseName-footnote from the switch-function to the function it is applied on
                foreach (ExeXml.Par dbName in switchFunDatabaseName)
                {
                    fun.pars.Add(Guid.NewGuid().ToString(), dbName);
                }
            }
        }
Beispiel #15
0
        private bool HandleBreak()
        {
            // CHECK IF THERE IS ANY BREAK FUNCTION ...
            string breakFunId = null; ExeXml.Fun breakFun = null; double breakFunOrder = double.MaxValue; Description funDesc = null;

            foreach (var pol in infoStore.country.cao.pols)
            {
                if (!pol.Value.on)
                {
                    continue;
                }
                foreach (var fun in pol.Value.funs)
                {
                    if (fun.Value.on && fun.Value.Name.ToLower() == DefFun.Break.ToLower())
                    {
                        double o = GetOrder(pol.Value.order, fun.Value.order);
                        if (o < breakFunOrder) // only consider 1stBreak in spine (if there are foolishly more)
                        {
                            breakFunId    = fun.Key; breakFun = fun.Value;
                            breakFunOrder = o; funDesc = new Description(pol.Value, breakFun, breakFunId);
                        }
                    }
                }
            }
            if (breakFun == null)
            {
                return(true);
            }

            // ... IF SO, CHECK PARAMETERS
            bool produceOutput = true, produceTUinfo = false; string outputFileName = string.Empty;

            foreach (var p in breakFun.pars)
            {
                string parID = p.Key; ExeXml.Par par = p.Value;
                if (par.val.ToLower() == DefPar.Value.NA)
                {
                    continue;
                }
                Description parDesc = new Description(funDesc, par, parID);

                if (par.Name.ToLower() == DefPar.Break.ProduceOutput.ToLower() || par.Name.ToLower() == DefPar.Break.ProduceTUinfo.ToLower())
                {
                    bool produceX = false;
                    if (par.val.ToLower() == DefPar.Value.YES)
                    {
                        produceX = true;
                    }
                    else if (par.val.ToLower() == DefPar.Value.NO)
                    {
                        produceX = false;
                    }
                    else
                    {
                        IssueErr(parDesc, "invalid value (must be yes or no)");
                    }
                    if (par.Name.ToLower() == DefPar.Break.ProduceOutput.ToLower())
                    {
                        produceOutput = produceX;
                    }
                    else
                    {
                        produceTUinfo = produceX;
                    }
                }
                else if (par.Name.ToLower() == DefPar.Break.OutputFileName.ToLower())
                {
                    outputFileName = par.val;
                }
                else
                {
                    IssueErr(parDesc, "unknown parameter");
                }
            }

            if (produceOutput == false && produceTUinfo == true)
            {
                IssueErr(funDesc, "TUinfo can only be produced if output is produced (parameter is ignored)", true);
            }

            if (infoStore.communicator.errorCount > 0)
            {
                return(false);
            }

            // IMPLEMENT THE BREAK
            // - main task: switch off everything after the Break function
            // - and, if necessary, search for DefOutput that can provide the output-filename (if not set by parameter OutputFileName)
            // - and, if necessary, find all TU names
            double        outputFunOrder = produceOutput && outputFileName == string.Empty ? double.MaxValue : -1; // the default for OutputFileName should be the first "normal" outputfile
            List <string> tuNames = new List <string>(); string indTUName = string.Empty;

            foreach (var pol in infoStore.country.cao.pols.Values)
            {
                if (!pol.on)
                {
                    continue;
                }
                foreach (var fun in pol.funs.Values)
                {
                    if (!fun.on)
                    {
                        continue;
                    }
                    double funOrder = GetOrder(pol.order, fun.order);
                    if (funOrder > breakFunOrder)
                    {
                        fun.on = false;                           // switch off everything after the Break function
                    }
                    if (fun.Name.ToLower() == DefFun.DefOutput.ToLower() &&
                        funOrder < outputFunOrder && funOrder > breakFunOrder) // get the File paramter of the first DefOutput after the Break
                    {
                        var fn = from p in fun.pars.Values where p.Name.ToLower() == DefPar.DefOutput.File.ToLower() select p.val;
                        if (fn.Count() > 0)
                        {
                            outputFileName = fn.First(); outputFunOrder = funOrder;
                        }
                    }

                    // if necessary, find at least one individual TU for output function, or all (active) TUs if TUinfo should be produced
                    if (!fun.on || !produceOutput || fun.Name.ToLower() != DefFun.DefTu.ToLower())
                    {
                        continue;
                    }

                    var tuNamePar = from p in fun.pars.Values where p.Name.ToLower() == DefPar.DefTu.Name.ToLower() select p.val;
                    var tuTypePar = from p in fun.pars.Values where p.Name.ToLower() == DefPar.DefTu.Type.ToLower() select p.val;
                    if (tuNamePar.Count() == 0 || tuTypePar.Count() == 0)
                    {
                        continue;
                    }
                    if (produceTUinfo)
                    {
                        tuNames.Add(tuNamePar.First());
                    }
                    if (indTUName == string.Empty && tuTypePar.First().ToUpper() == DefPar.Value.TUTYPE_IND)
                    {
                        indTUName = tuNamePar.First();
                    }
                }
            }

            // if necessary produce DefOutput function in redefining the Break function, which is not required anymore
            if (produceOutput == false)
            {
                breakFun.on = false; return(true);
            }
            if (outputFileName == string.Empty)
            {
                IssueErr(funDesc, "no name for the output file found"); return(false);
            }
            if (indTUName == string.Empty)
            {
                IssueErr(funDesc, "no DefTU with Type=IND found (required as DefOutput's TAX_UNIT)"); return(false);
            }

            int iGroup = 0, order = 0;

            breakFun.Name = DefFun.DefOutput; breakFun.pars.Clear();
            breakFun.pars.Add(Guid.NewGuid().ToString(), new ExeXml.Par()
            {
                Name = DefPar.DefOutput.File, val = outputFileName, order = (++order).ToString()
            });
            breakFun.pars.Add(Guid.NewGuid().ToString(), new ExeXml.Par()
            {
                Name = DefPar.DefOutput.VarGroup, val = "*", order = (++order).ToString()
            });
            breakFun.pars.Add(Guid.NewGuid().ToString(), new ExeXml.Par()
            {
                Name = DefPar.DefOutput.ILGroup, val = "*", order = (++order).ToString()
            });
            breakFun.pars.Add(Guid.NewGuid().ToString(), new ExeXml.Par()
            {
                Name = DefPar.Common.TAX_UNIT, val = indTUName, order = (++order).ToString()
            });

            foreach (string tuName in tuNames)
            {
                string sGroup = (++iGroup).ToString();
                breakFun.pars.Add(Guid.NewGuid().ToString(), new ExeXml.Par()
                {
                    Name = DefPar.DefOutput.UnitInfo_TU, val = tuName, Group = sGroup, order = (++order).ToString()
                });
                foreach (string uiId in new List <string> {
                    DefPar.Value.UNITINFO_HEADID, DefPar.Value.UNITINFO_ISPARTNER, DefPar.Value.UNITINFO_ISDEPCHILD,
                    DefPar.Value.UNITINFO_ISOWNCHILD, DefPar.Value.UNITINFO_ISOWNDEPCHILD, DefPar.Value.UNITINFO_ISDEPPARENT,
                    DefPar.Value.UNITINFO_ISDEPRELATIVE, DefPar.Value.UNITINFO_ISLONEPARENT
                })
                {
                    breakFun.pars.Add(Guid.NewGuid().ToString(), new ExeXml.Par()
                    {
                        Name = DefPar.DefOutput.UnitInfo_Id, val = uiId, Group = sGroup, order = (++order).ToString()
                    });
                }
            }

            void IssueErr(Description d, string m, bool isW = false)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = isW, message = $"{d.Get()}: {m}"
                });
            }

            return(true);
        }