internal bool isMonetary = false; // should this varil be formatted like monetary internal override void CheckAndPrepare(FunBase fun) { GetFootnoteNumbers(xmlValue, out string potentialIL); if (infoStore.operandAdmin.Exists(potentialIL) && infoStore.operandAdmin.GetParType(potentialIL) == DefPar.PAR_TYPE.IL) { parIL = new ParIL(infoStore) { xmlValue = xmlValue, description = this.description }; parIL.CheckAndPrepare(fun); } else { parVal = new ParVar(infoStore) { xmlValue = xmlValue, description = this.description }; parVal.CheckAndPrepare(fun); } if (infoStore.operandAdmin.GetIsMonetary(GetName())) { isMonetary = true; } }
protected override void PrepareNonCommonPar() { path = GetParBaseValueOrDefault(DefFun.DefInput, DefPar.DefInput.path); // compulsory file = GetParBaseValueOrDefault(DefFun.DefInput, DefPar.DefInput.file); // compulsory ParVar parRowMergeVar = GetUniquePar <ParVar>(DefPar.DefInput.RowMergeVar); // compulsory if (parRowMergeVar != null) { rowMergeVar = new VarSpec() { name = parRowMergeVar.name } } ; ParVar parColMergeVar = GetUniquePar <ParVar>(DefPar.DefInput.ColMergeVar); if (parColMergeVar != null) { colMergeVar = new VarSpec() { name = parColMergeVar.name } } ; ParVar parInputVar = GetUniquePar <ParVar>(DefPar.DefInput.InputVar); if (parInputVar != null) { inputVar = new VarSpec() { name = parInputVar.name } } ; if ((colMergeVar != null && inputVar == null) || (colMergeVar == null && inputVar != null)) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{description.Get()}: if {DefPar.DefInput.ColMergeVar} is defined {DefPar.DefInput.InputVar} must be defined too, and vice-versa" }); } lookUpMode = colMergeVar != null; repByEMPath = GetParBaseValueOrDefault(DefFun.DefInput, DefPar.DefInput.RepByEMPath); ignoreNRows = (int)GetParNumberValueOrDefault(DefFun.DefInput, DefPar.DefInput.IgnoreNRows); ignoreNCols = (int)GetParNumberValueOrDefault(DefFun.DefInput, DefPar.DefInput.IgnoreNCols); doRanges = GetParBoolValueOrDefault(DefFun.DefInput, DefPar.DefInput.DoRanges); parDefaultIfNoMatch = GetUniquePar <ParNumber>(DefPar.DefInput.DefaultIfNoMatch); // * * * T O D O * * * // consider parameters that allow defining and initialising variables // currently all input-variables need to be defined with DefVar or, if they are defined in variables-file, initialised with SetDefault }
/// <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" }); } } }
protected void PrepareEligPar() { coParWho = GetUniquePar <ParCateg>(DefPar.Common.Who_Must_Be_Elig); coParEligVar = GetUniquePar <ParVar>(DefPar.Common.Elig_Var); }
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); } }
protected override void PrepareNonCommonPar() { aggs = GetNonUniquePar <ParVarIL>(DefPar.Totals.Agg); if (aggs.Count == 0) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{description.Get()}: missing required parameter AGG" }); return; } foreach (string t in new List <string> { DefPar.Totals.Varname_Sum, DefPar.Totals.Varname_Mean, DefPar.Totals.Varname_Median, DefPar.Totals.Varname_Decile, DefPar.Totals.Varname_Quintile, DefPar.Totals.Varname_Count, DefPar.Totals.Varname_PosCount, DefPar.Totals.Varname_NegCount, DefPar.Totals.Varname_Min, DefPar.Totals.Varname_Max }) { ParBase par = GetUniquePar <ParBase>(t); if (par == null) { continue; } actions.Add(t); foreach (ParVarIL agg in aggs) { string aggName = agg.GetName(); agg.CheckAndPrepare(this); int n = 1; if (t == DefPar.Totals.Varname_Decile) { n = 9; } if (t == DefPar.Totals.Varname_Quintile) { n = 4; } for (int i = 1; i <= n; ++i) { string counter = t == DefPar.Totals.Varname_Decile || t == DefPar.Totals.Varname_Quintile ? i.ToString() : string.Empty; string varName = $"{par.xmlValue}{counter}_{aggName}"; infoStore.operandAdmin.RegisterVar( // generate the variable that will take the total name: varName, creatorFun: DefFun.Totals, description: par.description, isMonetary: false, // not really clear, but adding over TU does not make sense isGlobal: true, // equal for each person isWriteable: false, // cannot be use as output-variable setInitialised: true); if (infoStore.operandAdmin.Exists(varName)) { totals.Add(t + (n > 1 ? i.ToString() : "") + aggName, new VarSpec() { name = varName }); } } } } // setup booleans hasMedian = actions.Contains(DefPar.Totals.Varname_Median); hasQuint = actions.Contains(DefPar.Totals.Varname_Quintile); hasDec = actions.Contains(DefPar.Totals.Varname_Decile); hasSum = actions.Contains(DefPar.Totals.Varname_Sum); hasMean = actions.Contains(DefPar.Totals.Varname_Mean); // check if there is a condition for inclusion ParCond inclCond = GetUniquePar <ParCond>(DefPar.Totals.Incl_Cond); if (inclCond != null) { ParCateg inclWho = GetUniquePar <ParCateg>(DefPar.Totals.Incl_Cond_Who); string inclWhoVal = (inclWho == null) ? DefPar.Value.WHO_ALL : inclWho.GetCateg(); include = new Tuple <ParCond, string>(inclCond, inclWhoVal); } // check if results should be weighted useWeights = GetParBoolValueOrDefault(DefFun.Totals, DefPar.Totals.Use_Weights); if (useWeights) // get the weight var, if null use dwt { ParVar dwtPar = GetUniquePar <ParVar>(DefPar.Totals.Weight_Var); dwtName = dwtPar != null ? dwtPar.name : DefVarName.DWT; infoStore.operandAdmin.CheckRegistration(dwtName, false, false, description); } // }
protected override void PrepareNonCommonPar() { if (!IsRunCondMet()) { return; } infoStore.applicableUprateFunctions.Add(description); // to allow for checking if there is no/more than one applicable Uprate // get the "function-internal" (rather outdated) factor definitions, i.e. those defined by parameters Factor_Name/Factor_Value Dictionary <string, double> internalFactorDefs = GetInternalFactorDefs(); // check if DBYearVar exists and handle accordingly ParVar parDBYearVarPar = GetUniquePar <ParVar>(DefPar.Uprate.DBYearVar); isDBYearVarUsed = parDBYearVarPar != null && parDBYearVarPar.name != DefPar.Value.NA; if (isDBYearVarUsed) { if (parDBYearVarPar.name.Trim() != string.Empty) { infoStore.operandAdmin.CheckRegistration(name: parDBYearVarPar.name.Trim(), isOutVar: false, warnIfNotInit: false, description: parDBYearVarPar.description); if (!infoStore.operandAdmin.GetVarExistsInPersonVarList(parDBYearVarPar.name)) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{parDBYearVarPar.description.Get()}: Parameter {DefPar.Uprate.DBYearVar} was used with value '{parDBYearVarPar.name}', but this variable is not defined" }); } else { DBYearVar = parDBYearVarPar.name; } } else { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{this.description.Get()}: Parameter {DefPar.Uprate.DBYearVar} was used and left empty" }); } } // (1) "NORMAL" VARIABLES: // an uprating-group consists of the variable to uprate (e.g. yem=$f_cpi) and optionally of a condition (e.g. Factor_Cond={dgn=0}) foreach (var group in GetParGroups(DefPar.Uprate.GROUP_MAIN).Values) { // optional condition parameter ParCond parCond = GetUniqueGroupPar <ParCond>(DefPar.Uprate.Factor_Condition, group); // compulsory var-name/factor-parameter (e.g. yem (in policy-column) / $f_cpi (in system-column)) // usually this will be one placeholder-parameter but it is possible that one condition applies to several variables List <ParBase> listParMain = GetPlaceholderGroupPar <ParBase>(group); if (listParMain.Count == 0) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{parCond.description.Get()}: loose condition {parCond.xmlValue}" }); continue; } foreach (ParBase parMain in listParMain) { string upVarName = parMain.description.GetParName(); // get the name of the variable to uprate (e.g. yem) // check for double uprating, but take care of conditions, e.g. twice yem-uprating without condition -> warning, yem-uprating different for men and women -> ok bool exists = ExistsUpVar(upVarName, out bool conditioned); if (exists && (!conditioned || parCond == null)) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{parMain.description.Get()}: double uprating of variable {upVarName}" }); } Dictionary <double, double> upFactors = GetFactors(internalFactorDefs, parMain); upVars.Add(new UpVar() { varSpec = new VarSpec() { name = upVarName }, factors = upFactors, parCondition = parCond }); // the main purpose of this registration is to ensure the variable exists (an error is issued if not) // in fact uprated variables are likely to be registered by usage (why uprate a variable that is not used?) // (it could still be that an uprated but otherwise unused variable should be in the output and would not if VarGroup is used) infoStore.operandAdmin.CheckRegistration(name: upVarName, isOutVar: false, warnIfNotInit: false, description: parMain.description); } } // check for double conditioned uprating foreach (UpVar condUpVar in from cuv in upVars where cuv.parCondition != null select cuv) { if ((from cuv in upVars where upVars.IndexOf(cuv) > upVars.IndexOf(condUpVar) && cuv.varSpec.name.ToLower() == condUpVar.varSpec.name.ToLower() && cuv.parCondition != null && cuv.parCondition.description.GetParGroup() == condUpVar.parCondition.description.GetParGroup() select cuv).Count() > 0) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{condUpVar.parCondition.description.Get()}: double uprating of variable {condUpVar.varSpec.name}" }); } } // (2) AGGREGATE VARIABLES: // the group consists of AggVar_Name (the agg-var to uprate) and a list of AggVar_Part (the vars summing up to the agg-var) // and optionally of AggVar_Tolerance (a tolerance for the check if part-vars actually sum up to agg-var) foreach (var group in GetParGroups(DefPar.Uprate.GROUP_AGG).Values) { ParVar parName = GetUniqueGroupPar <ParVar>(DefPar.Uprate.AggVar_Name, group); if (parName == null) { continue; // error is issued by general checking } if (ExistsUpVar(parName.name, out bool dummy)) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{parName.description.Get()}: double uprating of variable {parName.name} (aggregate and normally)" }); } ParNumber parTol = GetUniqueGroupPar <ParNumber>(DefPar.Uprate.AggVar_Tolerance, group); AggUpVar aggUpVar = new AggUpVar() { varSpec = new VarSpec() { name = parName.name } }; if (parTol != null) { aggUpVar.tolerance = parTol.GetValue(); } foreach (ParVar parPart in GetNonUniqueGroupPar <ParVar>(DefPar.Uprate.AggVar_Part, group)) { aggUpVar.parts.Add(new VarSpec() { name = parPart.name }); } if (aggUpVar.parts.Count > 0) { aggUpVars.Add(aggUpVar); } } // (3) VARIABLES DEFINED BY REGULAR EXPRESSION (e.g. for updating expenditure variables) foreach (var group in GetParGroups(DefPar.Uprate.GROUP_REGEXP).Values) { ParBase parDef = GetUniqueGroupPar <ParBase>(DefPar.Uprate.RegExp_Def, group); ParBase parFactor = GetUniqueGroupPar <ParBase>(DefPar.Uprate.RegExp_Factor, group); if (parDef == null || parFactor == null) { continue; } upRegExp.Add(parDef.xmlValue, GetFactors(internalFactorDefs, parFactor)); } // get default factor ... ParBase parDefFac = GetUniquePar <ParBase>(DefPar.Uprate.Def_Factor); if (parDefFac != null) { defaultFactor = GetFactors(internalFactorDefs, parDefFac); } // ... and the optional parameter WarnIfNoFactor warnIfNoFactor = GetParBoolValueOrDefault(DefFun.Uprate, DefPar.Uprate.WarnIfNoFactor); // ... and the optional parameter WarnIfNonMonetary warnIfNonMonetary = GetParBoolValueOrDefault(DefFun.Uprate, DefPar.Uprate.WarnIfNonMonetary); if (zeroFactorSysCollector.Count > 0) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: uprating-index for system year is 0 for {string.Join(", ", zeroFactorSysCollector)}, resulting in uprating concerned variables by 0." }); } if (zeroFactorDataCollector.Count > 0) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: uprating-index for data year is 0 for {string.Join(", ", zeroFactorDataCollector)}, resulting in setting concerned variables to NaN." }); } }
protected override void PrepareNonCommonPar() { ParVar fv = GetUniquePar <ParVar>(DefPar.AddHHMembers.FlagVar); if (fv != null) { flagVar = new VarSpec() { name = fv.name } } ; foreach (var g in GetParGroups(DefPar.AddHHMembers.GROUP_MAIN)) { var group = g.Value; int groupNo = g.Key; AddInstruction addInstruction = new AddInstruction(); // first find out whether we are adding children or partners or other persons ... ParCateg parWho = GetUniqueGroupPar <ParCateg>(DefPar.AddHHMembers.Add_Who, group); if (parWho == null) { continue; // compulsory parameter, error already issued } addInstruction.addWho = parWho.GetCateg(); // ... depending on that, check the add-condition ParCond parParent = GetUniqueGroupPar <ParCond>(DefPar.AddHHMembers.ParentCond, group); ParCond parPartner = GetUniqueGroupPar <ParCond>(DefPar.AddHHMembers.PartnerCond, group); ParCond parOther = GetUniqueGroupPar <ParCond>(DefPar.AddHHMembers.HHCond, group); string missing = string.Empty; string tooMuch = string.Empty; switch (addInstruction.addWho) { case DefPar.Value.ADDHHMEMBERS_CHILD: if (parParent != null) { addInstruction.cond = parParent; } else { missing = DefPar.AddHHMembers.ParentCond; } if (parPartner != null) { tooMuch = DefPar.AddHHMembers.PartnerCond + " "; } if (parOther != null) { tooMuch = DefPar.AddHHMembers.HHCond; } ParBool parIsPP = GetUniqueGroupPar <ParBool>(DefPar.AddHHMembers.IsPartnerParent, group); if (parIsPP != null) { addInstruction.isPartnerParent = parIsPP.GetBoolValue(); } break; case DefPar.Value.ADDHHMEMBERS_PARTNER: if (parParent != null) { tooMuch = DefPar.AddHHMembers.ParentCond + " "; } if (parPartner != null) { addInstruction.cond = parPartner; } else { missing = DefPar.AddHHMembers.PartnerCond; } if (parOther != null) { tooMuch = DefPar.AddHHMembers.HHCond; } break; case DefPar.Value.ADDHHMEMBERS_OTHER: if (parParent != null) { tooMuch = DefPar.AddHHMembers.ParentCond + " "; } if (parPartner != null) { tooMuch = DefPar.AddHHMembers.PartnerCond; } if (parOther != null) { addInstruction.cond = parOther; } else { missing = DefPar.AddHHMembers.HHCond; } break; default: continue; // error is caught by general error handling } if (missing != string.Empty) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{description.Get()} (group {groupNo}): {DefPar.AddHHMembers.Add_Who}={addInstruction.addWho} requires parameter {missing}" }); } if (tooMuch != string.Empty) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()} (group {groupNo}): {DefPar.AddHHMembers.Add_Who}={addInstruction.addWho} does not require {tooMuch}" }); } // here we are only gathering the variables that are to be set, but do not evaluate whether they exist // note: this function does not "register" variables, i.e. if a variable is not used anywhere else, it cannot be set foreach (ParFormula parVarDefinition in GetPlaceholderGroupPar <ParFormula>(group)) { string varName = parVarDefinition.description.GetParName(); if (addInstruction.prepVarDefinitions.ContainsKey(varName)) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{parVarDefinition.description.Get()}: double definition of variable {varName}" }); continue; } if (varName == DefVarName.IDHH || varName == DefVarName.IDPERSON || varName == DefVarName.DWT || varName == DefVarName.DCT) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{parVarDefinition.description.Get()}: variable {varName} is system-set and cannot be changed" }); continue; } addInstruction.prepVarDefinitions.Add(varName, parVarDefinition); } addInstructions.Add(addInstruction); } }