protected override void PrepareNonCommonPar() { ParBase parFileName = GetUniquePar <ParBase>(DefPar.DefOutput.File); if (parFileName != null) // if null the programme is stopped after reading parameters (missing compulsory parameter) { fileName = Path.Combine(infoStore.runConfig.pathOutput, parFileName.xmlValue); if (!fileName.ToLower().EndsWith(".txt")) { fileName += ".txt"; } if (infoStore.runConfig.stdOutputFilenameSuffix != string.Empty) // e.g. uk_2017_std -> uk_2017_BTAoff { AdaptFileNameForNonStdExtensionSwitches(infoStore.runConfig.stdOutputFilenameSuffix); } if (infoStore.runConfig.outFileDate != string.Empty) // e.g. hu_2017_std.txt -> hu_2017_std_201805301954.txt { fileName = fileName.Insert(fileName.Length - 4, "_" + infoStore.runConfig.outFileDate); } // * * * T O D O * * * // check at this point if file is ready for writting, i.e. valid file-name, not used by another file, ... // to avoid running the whole thing and then cannot write (probably requires try-catch on attempt to open) // also if the file is available, lock it now? } // in future probably replaced by Scale function, but currently still needed, in particular for PET ParFormula parMultipleMonetaryBy = GetUniquePar <ParFormula>(DefPar.DefOutput.MultiplyMonetaryBy); if (parMultipleMonetaryBy != null) { multiplyMonetaryBy = parMultipleMonetaryBy.GetGlobalValue(); } PrepareVarILPar(); PrepareDefILPar(); PrepareUnitInfoPar(); append = GetParBoolValueOrDefault(DefFun.DefOutput, DefPar.DefOutput.Append); suppressVoidMessage = GetParBoolValueOrDefault(DefFun.DefOutput, DefPar.DefOutput.Suppress_Void_Message); nDecimals = (int)GetParNumberValueOrDefault(DefFun.DefOutput, DefPar.DefOutput.nDecimals); formatDecimals = "0."; for (int i = 0; i < nDecimals; i++) { formatDecimals += "#"; } parWho = GetUniquePar <ParCateg>(DefPar.Common.Who_Must_Be_Elig); parEligVar = GetUniquePar <ParVar>(DefPar.Common.Elig_Var); ParNumber parReplaceUnitLoopVoidBy = GetUniquePar <ParNumber>(DefPar.DefOutput.Replace_Void_By); if (parReplaceUnitLoopVoidBy != null) { doReplaceUnitLoopVoidBy = true; replaceUnitLoopVoidBy = parReplaceUnitLoopVoidBy.GetValue(); } }
internal override void CheckAndPrepare(FunBase fun) { parFormula = new ParFormula(infoStore, true) { xmlValue = xmlValue, description = this.description }; parFormula.CheckAndPrepare(fun); }
protected override void PrepareNonCommonPar() { parShare = GetUniquePar <ParFormula>(DefPar.Allocate.Share); parShareBetween = GetUniquePar <ParCond>(DefPar.Allocate.Share_Between); parShareProp = GetUniquePar <ParVarIL>(DefPar.Allocate.Share_Prop); shareAllIfNoElig = GetParBoolValueOrDefault(DefFun.Allocate, DefPar.Allocate.Share_All_IfNoElig); shareEquIfZero = GetParBoolValueOrDefault(DefFun.Allocate, DefPar.Allocate.Share_Equ_IfZero); ignoreNegProp = GetParBoolValueOrDefault(DefFun.Allocate, DefPar.Allocate.Ignore_Neg_Prop); }
internal static bool HandlesCheckAndPrepare(ParFormula pf) { // the standard ParFormula.CheckAndPrepare cannot handle the formula as it contains placeholders (IL_COMPONENT, etc.), therefore skip // to later CheckAndPrepare the adapted ParFormulas (see GetAdaptedParFormula below) return(pf.description.GetFunName().ToLower() == DefFun.IlArithOp.ToLower() && pf.description.GetParName().ToLower() == DefPar.IlArithOp.Formula.ToLower() && (pf.xmlValue.Contains(DefPar.IlArithOp.BASE_IL_COMPONENT.ToLower()) || pf.xmlValue.Contains(DefPar.IlArithOp.OUT_IL_COMPONENT.ToLower()) || pf.xmlValue.Contains(DefPar.IlArithOp.IL_COMPONENT.ToLower()))); }
// called by ParFormula to replace $Base by the actual content of this parameter internal string HandleBase(string formula, Description parDescription) { List <string> basePlaceHolders = new List <string>() { DefPar.Value.BENCALC_BASE, DefPar.Value.BENCALC_BASE_AMOUNT, DefPar.Value.BENCALC_BASE_IL, DefPar.Value.BENCALC_BASE_VAR }; string basePH = ContainsBase(); if (basePH == null) { return(formula); } ParFormula parBase = GetUniquePar <ParFormula>(DefPar.BenCalc.Base); if (parBase == null) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{parDescription.Get()}: missing parameter {DefPar.BenCalc.Base}" }); return(formula); } do { int index = formula.ToLower().IndexOf(basePH); formula = formula.Remove(index, basePH.Length); formula = formula.Insert(index, $"({parBase.xmlValue})"); basePH = ContainsBase(); } while (basePH != null); string ContainsBase() { foreach (string placeHolder in basePlaceHolders) { if (formula.ToLower().Contains(placeHolder)) { return(placeHolder); } } return(null); } return(formula); }
/// <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 override void PrepareNonCommonPar() { // get parameters ParIL parOperatorIL = GetUniquePar <ParIL>(DefPar.IlVarOp.Operator_IL); if (parOperatorIL == null) { return; // error is handled by global check } ParFormula parOperand = GetUniquePar <ParFormula>(DefPar.IlVarOp.Operand); bool useFactors = GetParBoolValueOrDefault(DefFun.IlVarOp, DefPar.IlVarOp.Operand_Factors); ParIL parOperandIL = GetUniquePar <ParIL>(DefPar.IlVarOp.Operand_IL); ParCateg parMulAdd = GetUniquePar <ParCateg>(DefPar.IlVarOp.Operation); if (parMulAdd != null) { mulAdd = parMulAdd.GetCateg(); } ParCateg parSelVar = GetUniquePar <ParCateg>(DefPar.IlVarOp.Sel_Var); if (parSelVar != null) { selVar = parSelVar.GetCateg(); } // assess what to do and check for insufficient or contradictory information if (parOperand != null) { //if (parOperand.IsGlobal()) opTask = OPERAND_TYPE.SCALAR; // out-commented to replace by the weaker condtion below, otherwise it produces an error with constants if (double.TryParse(parOperand.xmlValue, out double x)) { opTask = OPERAND_TYPE.SCALAR; } else { opTask = OPERAND_TYPE.FORMULA; formulaOperand = parOperand; } } else if (parOperandIL != null) { if (!CheckDoubleDef(OPERAND_TYPE.IL)) { return; } } if (useFactors) { if (!CheckDoubleDef(OPERAND_TYPE.FACTORS)) { return; } } if (mulAdd == DefPar.Value.ILVAROP_NEGTOZERO) { if (!CheckDoubleDef(OPERAND_TYPE.NEGTOZERO)) { return; } } if (opTask == OPERAND_TYPE.INVALID) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{description.Get()}: missing definition of operand" }); return; } if (opTask == OPERAND_TYPE.IL && parOperandIL.GetFlatContent().Count != parOperatorIL.GetFlatContent().Count) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{description.Get()}: incomelists {parOperatorIL.name} and {parOperandIL.name} do not have the same number of variables, operation is not possible" }); return; } // prepare information for run for (int i = 0; i < parOperatorIL.GetFlatContent().Count; ++i) { OpItem oi = new OpItem() { varOperator = parOperatorIL.GetFlatContent()[i].varSpec }; switch (opTask) { case OPERAND_TYPE.FACTORS: oi.numOperand = parOperatorIL.GetFlatContent()[i].addFactor; break; case OPERAND_TYPE.SCALAR: oi.numOperand = parOperand.GetGlobalValue(); break; case OPERAND_TYPE.IL: oi.varOperand = parOperandIL.GetFlatContent()[i].varSpec; break; } opItems.Add(oi); } bool CheckDoubleDef(OPERAND_TYPE ot) { if (opTask == OPERAND_TYPE.INVALID) { opTask = ot; return(true); } infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{description.Get()}: contradictory definition of operand" }); return(false); } }
protected void PrepareLimPar() { coParLowLim = GetUniquePar <ParFormula>(DefPar.Common.LowLim); coParUpLim = GetUniquePar <ParFormula>(DefPar.Common.UpLim); coParThres = GetUniquePar <ParFormula>(DefPar.Common.Threshold); ParCateg coParLimpriority = GetUniquePar <ParCateg>(DefPar.Common.Limpriority); // the following tries to optimise by getting the values here, if they are read-time-available (e.g. 600#y, GetSystemYear, ...) // and by checking for implausible values (e.g. upLim = 10, lowLim = 100) if already possible if (coParLowLim != null) { if (coParLowLim.IsGlobal(true)) { lowLim = coParLowLim.GetGlobalValue(); coParLowLim = null; } else { doRunTimeLimCheck = true; } } if (coParUpLim != null) { if (coParUpLim.IsGlobal(true)) { upLim = coParUpLim.GetGlobalValue(); coParUpLim = null; } else { doRunTimeLimCheck = true; } } bool checkThres = coParThres != null; if (coParThres != null) { if (coParThres.IsGlobal(true)) { thres = coParThres.GetGlobalValue(); coParThres = null; } else { doRunTimeThresCheck = true; } } if (coParLimpriority != null) { limPri = coParLimpriority.GetCateg(); } if (!doRunTimeLimCheck) // both limits available (might be double.MinValue and/or double.MaxValue, but does no harm here) { CheckLimits(ref lowLim, ref upLim); if (checkThres && !doRunTimeThresCheck) // threshold and both limits available { if (!CheckThreshold(thres, lowLim, upLim)) { thres = lowLim; } } } }
/// <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}" }); } }
protected override void PrepareNonCommonPar() { parFormula = GetUniquePar <ParFormula>(DefPar.IlArithOp.Formula); baseILSpecification = new ILSpecification() { ilName = GetUniquePar <ParIL>(DefPar.IlArithOp.Base_ILName).xmlValue }; if (!CheckPrePost(baseILSpecification, GetUniquePar <ParBase>(DefPar.IlArithOp.Base_Prefix), GetUniquePar <ParBase>(DefPar.IlArithOp.Base_Postfix))) { return; } coreVarNames = GetCoreVars(baseILSpecification); // assess the variables which need to be present in all decomposed ILs ilSpecifications = new List <ILSpecification>(); foreach (var pg in GetParGroups(DefPar.IlArithOp.ILName)) { List <ParBase> ilParList = pg.Value; ILSpecification ilSpecification = new ILSpecification() { ilName = GetUniqueGroupPar <ParIL>(DefPar.IlArithOp.ILName, ilParList).xmlValue, grpNo = pg.Key.ToString() }; if (!CheckPrePost(ilSpecification, GetUniqueGroupPar <ParBase>(DefPar.IlArithOp.Prefix, ilParList), GetUniqueGroupPar <ParBase>(DefPar.IlArithOp.Postfix, ilParList))) { return; } if (!CheckCoreVars(ilSpecification)) { return; } ilSpecifications.Add(ilSpecification); } outILSpecification = new ILSpecification() { ilName = GetUniquePar <ParBase>(DefPar.IlArithOp.Out_ILName).xmlValue }; bool outVarsMustExist = parFormula.xmlValue.Contains(DefPar.IlArithOp.OUT_IL_COMPONENT.ToLower()); bool outILExists = infoStore.operandAdmin.Exists(outILSpecification.ilName) && infoStore.operandAdmin.GetParType(outILSpecification.ilName) == DefPar.PAR_TYPE.IL; if (!CheckPrePost(outILSpecification, GetUniquePar <ParBase>(DefPar.IlArithOp.Out_Prefix), GetUniquePar <ParBase>(DefPar.IlArithOp.Out_Postfix), outILExists)) { return; } if (outVarsMustExist && !outILExists) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{description.Get()}: using {DefPar.IlArithOp.OUT_IL_COMPONENT} in {DefPar.IlArithOp.Formula} requires incomelist {outILSpecification.ilName} to exist" }); return; } if (outILExists) { if (!CheckCoreVars(outILSpecification)) { return; } } else { if (!RegisterOperands()) { return; } } PrepareFormulas(); }
protected override void PrepareNonCommonPar() { foreach (List <ParBase> compParList in GetParGroups(DefPar.BenCalc.Comp_X).Values) { Component component = new Component(); // condition component.pCond = GetUniqueGroupPar <ParCond>(DefPar.BenCalc.Comp_Cond, compParList); // amount (per elig/TU) component.pFormula = GetUniqueGroupPar <ParFormula>(DefPar.BenCalc.Comp_perTU, compParList); if (component.pFormula != null) { component.perElig = false; } else { component.pFormula = GetUniqueGroupPar <ParFormula>(DefPar.BenCalc.Comp_perElig, compParList); } // limits (see remark in _FunInSpineBase_Lim wrt not using a common implementation for limits) component.pLowLim = GetUniqueGroupPar <ParFormula>(DefPar.BenCalc.Comp_LowLim, compParList); component.pUpLim = GetUniqueGroupPar <ParFormula>(DefPar.BenCalc.Comp_UpLim, compParList); if (component.pLowLim != null) { if (component.pLowLim.IsGlobal(true)) { component.lowLim = component.pLowLim.GetGlobalValue(); component.pLowLim = null; } else { component.doRunTimeLimCheck = true; } } if (component.pUpLim != null) { if (component.pUpLim.IsGlobal(true)) { component.upLim = component.pUpLim.GetGlobalValue(); component.pUpLim = null; } else { component.doRunTimeLimCheck = true; } } if (!component.doRunTimeLimCheck) // both limits available (might be double.MinValue and/or double.MaxValue, but does no harm here) { CheckComponentLimits(ref component.lowLim, ref component.upLim); } components.Add(component); } withdraw_Base = GetUniquePar <ParFormula>(DefPar.BenCalc.Withdraw_Base); withdraw_Start = GetUniquePar <ParFormula>(DefPar.BenCalc.Withdraw_Start); withdraw_End = GetUniquePar <ParFormula>(DefPar.BenCalc.Withdraw_End); withdraw_Rate = GetUniquePar <ParFormula>(DefPar.BenCalc.Withdraw_Rate); if (withdraw_Base == null && (withdraw_Start != null || withdraw_End != null || withdraw_Rate != null)) // cannot have withdrawal without a base { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: Without a Withdraw_Base all other withdraw parameters will be ignored", runTimeErrorId = description.funID }); } else if (withdraw_End != null && withdraw_Rate != null) // Withdraw_End and Withdraw_Rate cannot co-exist { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: Withdraw_End and Withdraw_Rate cannot co-exist: Withdraw_Rate will be ignored", runTimeErrorId = description.funID }); } else if (withdraw_Base != null && withdraw_End == null && withdraw_Rate == null) // Withdraw_End and Withdraw_Rate cannot both be missing { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: Withdraw_End and Withdraw_Rate cannot both be missing: withdrawal will be ignored", runTimeErrorId = description.funID }); } }
protected override void PrepareNonCommonPar() { if (GetParGroups(DefPar.SchedCalc.Band_XXX).Count < 1) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{description.Get()}: SchedCalc must have at least one band" }); return; } foreach (KeyValuePair <int, List <ParBase> > bandParList in GetParGroups(DefPar.SchedCalc.Band_XXX)) { Band band = new Band(); // Prepare the Band Limits band.band = bandParList.Key; band.pLowLim = GetUniqueGroupPar <ParFormula>(DefPar.SchedCalc.Band_LowLim, bandParList.Value); if (band.pLowLim != null) // if there is a lowLim { if (band.pLowLim.IsGlobal(true)) { band.lowLim = band.pLowLim.GetGlobalValue(); band.pLowLim = null; } else { doRunTimeLimCheck = true; } } band.pUpLim = GetUniqueGroupPar <ParFormula>(DefPar.SchedCalc.Band_UpLim, bandParList.Value); if (band.pUpLim != null) // if there is a lowLim { if (band.pUpLim.IsGlobal(true)) { band.upLim = band.pUpLim.GetGlobalValue(); band.pUpLim = null; } else { doRunTimeLimCheck = true; } } // Prepare the Band Rate/Amount band.pRate = GetUniqueGroupPar <ParFormula>(DefPar.SchedCalc.Band_Rate, bandParList.Value); band.pAmount = GetUniqueGroupPar <ParFormula>(DefPar.SchedCalc.Band_Amount, bandParList.Value); if (band.pRate != null && band.pAmount != null) // Rate and Amount cannot co-exist { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{description.Get()}: Rate and Amount cannot co-exist in group {band.band}" }); } if (band.pRate == null && band.pAmount == null) // Rate and Amount cannot both be missing { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{description.Get()}: Rate and Amount cannot both be missing in group {band.band}" }); } if (band.pRate != null) { if (band.pRate.IsGlobal(true)) { band.rate = band.pRate.GetGlobalValue(); band.pRate = null; } else { doRunTimeRateCheck = true; } } if (band.pAmount != null) { if (band.pAmount.IsGlobal(true)) { band.amount = band.pAmount.GetGlobalValue(); band.pAmount = null; } else { doRunTimeRateCheck = true; } } bands.Add(band); } // check that all required limits exist for (int i = 1; i < bands.Count; i++) { // if both limits are missing then produce an error if (bands[i - 1].upLim == double.MaxValue && bands[i - 1].pUpLim == null && bands[i].lowLim == double.MinValue && bands[i].pLowLim == null) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{description.Get()}: Band {bands[i - 1].band}: insufficient definition of upper limit. Use parameters 'band_uplim' or 'band_lowlim'(+1)." }); } // if both limits are there, then produce an error else if ((bands[i - 1].upLim != double.MaxValue || bands[i - 1].pUpLim != null) && (bands[i].lowLim != double.MinValue || bands[i].pLowLim != null)) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{description.Get()}: Double definition of upper limit as 'Band_UpLim {bands[i - 1].band}' and 'Band_LowLim {bands[i].band}'." }); } // else, make sure that the upper limit always exist (copy from Group+1 lower limit if required) else if (bands[i - 1].upLim == double.MaxValue && bands[i - 1].pUpLim == null) { if (bands[i].pLowLim == null) { bands[i - 1].upLim = bands[i].lowLim; // copy the litteral limit if it exists } else { bands[i - 1].pUpLim = bands[i].pLowLim; // else copy the parameter to be run at run-time } } } // if possible, check that limits are also in order if (!doRunTimeLimCheck) { CheckGroupLimits(bands); } // prepare the other parameters basePar = GetUniquePar <ParFormula>(DefPar.SchedCalc.Base); if (basePar == null) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{description.Get()}: Missing required parameter Base" }); } ParBool doAverageRatesPar = GetUniquePar <ParBool>(DefPar.SchedCalc.Do_Average_Rates); doAverageRates = doAverageRatesPar != null && doAverageRatesPar.GetBoolValue(); ParBool simpleProgPar = GetUniquePar <ParBool>(DefPar.SchedCalc.Simple_Prog); simpleProg = simpleProgPar != null && simpleProgPar.GetBoolValue(); quotientPar = GetUniquePar <ParFormula>(DefPar.SchedCalc.Quotient); if (quotientPar != null) { if (quotientPar.IsGlobal(true)) { quotient = quotientPar.GetGlobalValue(); quotientPar = null; } } baseThresholdPar = GetUniquePar <ParFormula>(DefPar.SchedCalc.BaseThreshold); if (baseThresholdPar != null) { if (baseThresholdPar.IsGlobal(true)) { baseThreshold = baseThresholdPar.GetGlobalValue(); baseThresholdPar = null; } } ParNumber roundBasePar = GetUniquePar <ParNumber>(DefPar.SchedCalc.Round_Base); if (roundBasePar != null) { roundBase = roundBasePar.GetValue(); } }
protected override void PrepareNonCommonPar() { parFormula = GetUniquePar <ParFormula>(DefPar.ArithOp.Formula); }