private static void GetUpIndInfo(Dictionary <string, Dictionary <string, string> > upInds, Dictionary <string, Dictionary <string, string> > upIndYears, ExeXml.Country country) { foreach (Dictionary <string, string> ui in upIndYears.Values) // loop over <UPIND_YEARs> { if (ui.ContainsKey(TAGS.YEAR)) { string upIndId = ui.GetOrEmpty(TAGS.UPIND_ID); string sVal = ui.GetOrEmpty(TAGS.VALUE); if (upIndId == string.Empty || sVal == string.Empty || !double.TryParse(EM_Helpers.AdaptDecimalSign(sVal), out double val)) { continue; } string facName = null; // get the name of the factor from <UPINDs> if (upInds.ContainsKey(upIndId) && upInds[upIndId].ContainsKey(TAGS.NAME)) { facName = upInds[upIndId][TAGS.NAME]; } // Store all uprate indices if (!country.upFacs.ContainsKey(facName)) // If uprating factor name does not exist, create a new entry { country.upFacs.Add(facName, new ExeXml.UpIndDict()); } country.upFacs[facName].SetYear(ui[TAGS.YEAR], val); } } }
public static double ReadExRate(string path, string country, string sysName, // in future perhaps 'year' string exRateDate, // supposed to be TAGS.EXRATE_AVERAGE or TAGS.EXRATE_1stSEMESTER or Communicator communicator) // TAGS.EXRATE_2ndSEMESTER or TAGS.EXRATE_DEFAULT { try { if (!File.Exists(path)) { return(-1); } using (StreamReader sr = new StreamReader(path, Encoding.UTF8)) using (XmlReader reader = XmlReader.Create(sr)) { // find the appropriate exchangerate for the system to run foreach (var rate in XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.EXRATE, hasId: false, uniqueProperties: false).Values) { if (rate.GetOrEmpty(TAGS.EXRATE_COUNTRY).ToLower() != country.ToLower()) { continue; } foreach (var prop in rate) // in future this could perhaps be 'if (rate.GetOrEmpty(TAGS.YEAR) == year)' { if (prop.Key.StartsWith(TAGS.SYS_NAME) && // (non-unique tags are stored as SysName1,SysName2,... in the Dictionary) prop.Value.ToLower() == sysName.ToLower()) { if (exRateDate == TAGS.EXRATE_DEFAULT) // if the user didn't define a concrete date (e.g. June30) use <Default>xxx</Default> { exRateDate = rate.GetOrEmpty(TAGS.EXRATE_DEFAULT).Replace(" ", ""); // e.g. June 30 -> June30 (the former is the content of <Default>xxx</Default>, the latter the tag-name) } string sRate = EM_Helpers.AdaptDecimalSign(rate.GetOrEmpty(exRateDate)); if (double.TryParse(sRate, out double exRate)) { return(exRate); } ReportError(communicator, path, $"Exchange rate for {sysName} invalid" + (sRate != string.Empty ? $": {sRate}" : string.Empty)); return(-1); } } } } return(-1); // note: -1 is also what's used in the file to indicate n/a (thus easier for the caller to just check for -1) // also note: not finding must not be reported here, as the rate may not be required (actually quite likely that data/param/output are in same currency) } catch (Exception exception) { throw new Exception($"Failure reading file {path}{Environment.NewLine}{exception.Message}"); } }
private double GetAddMod(ParBase par) { string addMode = par.xmlValue.Trim(); // i.e. '+' or '-' or '+0.5' or ... if (addMode == "+" || addMode == "-") { addMode += "1"; } if (!double.TryParse(EM_Helpers.AdaptDecimalSign(addMode), out double am)) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{par.description.Get()}: invalid incomelist add-mode: {addMode}" }); } return(am); }
// used in GetPolInfo and GetFunInfo to assess the <Order> private static double GetOrder(Dictionary <string, string> props, out string error) { double order = -1.0; error = null; if (!props.ContainsKey(TAGS.ORDER)) { error = GenErr("not found"); } else if (!double.TryParse(EM_Helpers.AdaptDecimalSign(props[TAGS.ORDER]), out order)) { error = GenErr($"invalid: {props[TAGS.ORDER]}"); } return(order); string GenErr(string what) { return($"{props.GetOrEmpty(TAGS.POL_ID)}{props.GetOrEmpty(TAGS.FUN_ID)}: <{TAGS.ORDER}> {what}"); } }
private static bool GetIndTaxInfo(Dictionary <string, Dictionary <string, string> > indTaxes, Dictionary <string, Dictionary <string, string> > indTaxYears, ExeXml.Country country) { if (string.IsNullOrEmpty(country.data.indirectTaxTableYear)) { return(true); } string relevantYear = country.data.indirectTaxTableYear.Trim().ToLower(); foreach (Dictionary <string, string> it in indTaxYears.Values) // loop over <INDTAX_YEARs> { if (it.GetOrEmpty(TAGS.YEAR) != relevantYear) { continue; } string indTaxId = it.GetOrEmpty(TAGS.INDTAX_ID); string sVal = it.GetOrEmpty(TAGS.VALUE).Trim(); if (indTaxId == string.Empty || sVal == string.Empty || sVal == DefPar.Value.NA) { continue; } double pct = sVal.EndsWith("%") ? 0.01 : 1; if (!double.TryParse(EM_Helpers.AdaptDecimalSign(sVal.Replace("%", "")), out double val)) { continue; } string indTaxName = null; // get the name of the factor from <INDTAXs> if (indTaxes.ContainsKey(indTaxId) && indTaxes[indTaxId].ContainsKey(TAGS.NAME)) { indTaxName = indTaxes[indTaxId][TAGS.NAME]; } country.indTaxes.AddOrReplace(indTaxName, val * pct); } return(country.indTaxes.Count > 0); }
private string constName = null; // only relevant if value is a constant, e.g. #_amount = $Const_A, Factor_Value = $Const_B internal override void CheckAndPrepare(FunBase fun) { double periodFactor = HandlePeriodFactor(out string xmlCleaned); // if TryParse works: a simple number ... if (double.TryParse(EM_Helpers.AdaptDecimalSign(xmlCleaned), out value)) { value *= periodFactor; return; } // ... if not: possibly a constant if (infoStore.operandAdmin.Exists(xmlValue) && infoStore.operandAdmin.GetIsGlobal(xmlValue)) { constName = xmlValue; // note: not necessary to us xmlCleaned, as a constant cannot have a period } else { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{description.Get()}: {xmlValue} is not a valid number" }); } }
public static ExeXml.UpIndDict ReadHICP(string path, string country, string sysYear, string dataYear, Communicator communicator) { try { ExeXml.UpIndDict HICP = new ExeXml.UpIndDict(); if (!File.Exists(path)) { return(HICP); } using (StreamReader sr = new StreamReader(path, Encoding.UTF8)) using (XmlReader reader = XmlReader.Create(sr)) { // find the appropriate HICP for the respective data- and system-year foreach (var rate in XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.HICP, hasId: false).Values) { if (rate.GetOrEmpty(TAGS.EXRATE_COUNTRY).ToLower() != country.ToLower()) { continue; } string year = rate.GetOrEmpty(TAGS.YEAR); string shicp = EM_Helpers.AdaptDecimalSign(rate.GetOrEmpty(TAGS.VALUE)); if (double.TryParse(shicp, out double hicp)) { HICP.SetYear(year, hicp); } } } return(HICP); // note: not finding must not be reported here, as the HICP may not be required } catch (Exception exception) { throw new Exception($"Failure reading file {path}{Environment.NewLine}{exception.Message}"); } }
/// <summary> /// read data from file and create the complete list of variables for each person (HH.personVarList), /// i.e. also for non-data variables (simulated, created by DefVar, loop-counters, ...) /// note that HHAdmin and OperandAmin need to "talk" a bit here: /// e.g. OperandAdmin tells HHAdmin what to read (incl. vars that may be provided by SetDefault); HHAdmin reports back what he read /// </summary> internal void GenerateData() { string path = GetDataPath(infoStore); try // note: maybe the extra try/catch is disputable (i.e. one could rely on general try/catch as all other functions instead) { // but IO-problems seem more likely and serious and this may help to better locate the error IEnumerable <string> inputLines = null; if (!string.IsNullOrEmpty(infoStore.runConfig.inputPassword)) { byte[] allBytes = File.ReadAllBytes(path); allBytes = EM_Crypt.EM_Crypt.SimpleDecryptWithPassword(allBytes, infoStore.runConfig.inputPassword); if (allBytes == null) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"Wrong decryption password!" }); return; } inputLines = System.Text.Encoding.Default.GetString(allBytes).Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); } else { inputLines = File.ReadLines(path); } // first split header line to get the column-indices of the variables to read Dictionary <string, int> varColumn = new Dictionary <string, int>(); Dictionary <string, int> stringVarColumn = new Dictionary <string, int>(); // check if all variables exist List <string> missing = new List <string>(); string missingStringVar = string.Empty; foreach (var readVar in infoStore.operandAdmin.GetVarsToRead()) // the numeric (i.e. usual) variables { if (infoStore.allDataVariables.Contains(readVar)) // data contains the variable { varColumn.Add(readVar, infoStore.allDataVariables.IndexOf(readVar)); infoStore.operandAdmin.SetProvidedBySetDefault(readVar, false); // "inform" any possible SetDefault that } // it does not have to provide a value else // data does not contain the variable { if (!infoStore.operandAdmin.IsProvidedByDefault(readVar, infoStore.country.data.useCommonDefault)) { missing.Add(readVar); } // else will be initialised by SetDefault } } foreach (string stringVar in infoStore.operandAdmin.indexStringVars.Keys) // possible (rather unusual) string variables { if (infoStore.allDataVariables.Contains(stringVar)) { stringVarColumn.Add(stringVar, infoStore.allDataVariables.IndexOf(stringVar)); } else { missingStringVar += stringVar + ", "; } } if (missingStringVar != string.Empty) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{path}: String-variable(s) {missingStringVar.TrimEnd(new char[] { ',', ' ' })} not found (thus cannot be outputted)" }); } // get non-data variables from the OperandAdmin, i.e. simulated vars, vars generated by DefVar, by default, loop-counters, ... // as they also need to be added to the persons' variables list, see below List <string> nonDataVars = infoStore.operandAdmin.GetPersonVarsNotRead(); if (missing.Count > 0) { string sMissing = string.Empty; foreach (string m in missing) { nonDataVars.Add(m); sMissing += m + ", "; } infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{path}: Variable(s) {sMissing.TrimEnd(new char[] { ',', ' ' })} not found (zero is used as default)" }); } // assess the column-index of the idHH variable string IDHH = DefVarName.IDHH; int indexIDHH; if (varColumn.ContainsKey(IDHH)) { indexIDHH = indexIDHH = varColumn[IDHH]; } else { throw new Exception($"Variable {IDHH} not found"); } double?firstHH = infoStore.runConfig.firstHH, lastHH = infoStore.runConfig.lastHH; double nHHOnly = infoStore.runConfig.nHHOnly, nHHRead = 0; // generate the (complete) variables-list for each person in each HH hhs = new List <HH>(); Dictionary <string, HH> indexReadHH = new Dictionary <string, HH>(); foreach (string inputLine in inputLines.Skip(1)) { if (inputLine == string.Empty) { continue; } string[] splitInputLine = inputLine.Split('\t'); HH currentHH; if (!indexReadHH.ContainsKey(splitInputLine[indexIDHH])) { currentHH = new HH(infoStore); if (firstHH != null && double.TryParse(splitInputLine[indexIDHH], out double fhhid) && fhhid < firstHH) { continue; } if (lastHH != null && double.TryParse(splitInputLine[indexIDHH], out double lhhid) && lhhid > lastHH) { break; } if (++nHHRead > nHHOnly) { break; } hhs.Add(currentHH); indexReadHH.Add(splitInputLine[indexIDHH], currentHH); } else { currentHH = indexReadHH[splitInputLine[indexIDHH]]; } // first get (numeric) data variables for the person ... List <double> onePersonsVariables = new List <double>(varColumn.Count); foreach (var vc in varColumn.Values) { if (!double.TryParse(EM_Helpers.AdaptDecimalSign(splitInputLine[vc]), out double number)) { throw new Exception($"Variable {(from v in varColumn where v.Value == vc select v.Key).FirstOrDefault()}: failed converting '{splitInputLine[vc]}' to number"); } onePersonsVariables.Add(number); } // ... then add 0 for each non-data variable ... for (int ndv = 0; ndv < nonDataVars.Count; ++ndv) { onePersonsVariables.Add(0); } // ... finally get (rather unusual) non-numeric data variables List <string> onePersonsStringVariables = new List <string>(stringVarColumn.Count); foreach (var svc in stringVarColumn.Values) { onePersonsStringVariables.Add(splitInputLine[svc]); } currentHH.personVarList.Add(onePersonsVariables); currentHH.personStringVarList.Add(onePersonsStringVariables); } if (hhs.Count == 0) { throw new Exception("No housholds could be read"); } // "inform" the OperandAdmin about the final variable-index in the HH.personVarList int c = 0; Dictionary <string, int> varIndex = new Dictionary <string, int>(), stringVarIndex = new Dictionary <string, int>(); foreach (var vi in varColumn) { varIndex.Add(vi.Key, c++); } foreach (string v in nonDataVars) { varIndex.Add(v, c++); } c = 0; foreach (var vi in stringVarColumn) { stringVarIndex.Add(vi.Key, c++); } infoStore.operandAdmin.SetVarIndex(varIndex, stringVarIndex); // each HH has a dummy individual TU (for usage by spine-functions which do not have a TAX_UNIT parameter // (see CreateDummyTU-function for further comments) infoStore.indexTUs.Add(DUMMY_INDIVIDUAL_TU, null); foreach (HH hh in hhs) { CreateDummyTU(hh); } #if OLD_EXE_COMPARISON SimulateOldExeRand(); #endif } catch (Exception exception) { throw new Exception($"Failed reading file {path}{Environment.NewLine}{exception.Message}"); } }
private bool Read_LookUpMode(string fullPath, out Dictionary <double, List <double> > rows, out List <double> cols) { rows = new Dictionary <double, List <double> >(); cols = new List <double>(); try { var inputLines = File.ReadLines(fullPath).Skip(ignoreNRows); foreach (string cv in inputLines.First().Split('\t').Skip(ignoreNCols + 1)) // first column must contain row-identifiers { if (!double.TryParse(EM_Helpers.AdaptDecimalSign(cv), out double colValue)) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: {cv} is not a valid number - input is canceled" }); return(false); } if (cols.Contains(colValue)) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: colum identifier is not unique ({colValue}) - input is canceled" }); return(false); } cols.Add(colValue); } if (cols.Count == 0) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: data contains no columns - input is canceled" }); return(false); } string idErr1 = Guid.NewGuid().ToString(); foreach (string inputLine in inputLines.Skip(1)) { if (inputLine == string.Empty) { continue; } var splitInputLine = inputLine.Split('\t').Skip(ignoreNCols); if (splitInputLine.Count() < cols.Count + 1) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, runTimeErrorId = idErr1, message = $"{description.Get()}: too short line is ignored: ({(inputLine.Length > 20 ? inputLine.Substring(0, 20) : inputLine)})" }); continue; } double rowIdentifier = 0; List <double> rowValues = new List <double>(); for (int c = 0; c < splitInputLine.Count(); ++c) { if (!double.TryParse(EM_Helpers.AdaptDecimalSign(splitInputLine.ElementAt(c)), out double value)) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: {splitInputLine.ElementAt(c)} is not a valid number - input is canceled" }); return(false); } if (c == 0) { rowIdentifier = value; } else { rowValues.Add(value); } } if (rows.ContainsKey(rowIdentifier)) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: row identifier is not unique ({rowIdentifier}) - input is canceled" }); return(false); } rows.Add(rowIdentifier, rowValues); } if (rows.Count == 0) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: data contains no rows - input is canceled" }); return(false); } if (lookUpMode) { if (!CheckAsc(cols, "column ranges") || !CheckAsc(rows.Keys.ToList(), "row ranges")) { return(false); } } return(true); bool CheckAsc(List <double> vals, string what) { double prev = double.MinValue; foreach (double c in vals) { if (c < prev) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: {what} are not ascending ({prev} > {c}) - input is canceled" }); return(false); } prev = c; } return(true); } } catch (Exception exception) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: {exception.Message} - input is canceled" }); return(false); } }
private bool Read_InputMode(string fullPath, out Dictionary <double, List <double> > inputContent, out Dictionary <int, int> indexMatches) { inputContent = new Dictionary <double, List <double> >(); indexMatches = new Dictionary <int, int>(); try { var inputLines = File.ReadLines(fullPath).Skip(ignoreNRows); List <string> headers = new List <string>(); foreach (string v in inputLines.First().ToLower().Split('\t').Skip(ignoreNCols)) { headers.Add(v.Trim()); } int indexMergeVar = -1; Dictionary <int, int> tempIndexMatches = new Dictionary <int, int>(); for (int iInputCol = 0; iInputCol < headers.Count; ++iInputCol) { string varName = headers[iInputCol]; if (infoStore.operandAdmin.Exists(varName)) { int iData = infoStore.operandAdmin.GetIndexInPersonVarList(varName); if (iData >= 0) { if (iData == rowMergeVar.index) { indexMergeVar = iInputCol; } else { tempIndexMatches.Add(iData, iInputCol); } continue; } } infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: {varName} is not the name of an existing variable ({varName} is not inputted)" }); } if (indexMergeVar == -1) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: merge-variable {rowMergeVar.name} not found in input data - input is canceled" }); return(false); } if (tempIndexMatches.Count == 0) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: no (valid) variables for input found - input is canceled" }); return(false); } string idErr1 = Guid.NewGuid().ToString(), idErr2 = Guid.NewGuid().ToString(), idErr3 = Guid.NewGuid().ToString(), idErr4 = Guid.NewGuid().ToString(); foreach (string inputLine in inputLines.Skip(1)) { if (inputLine == string.Empty) { continue; } var splitInputLine = inputLine.Split('\t').Skip(ignoreNCols); if (splitInputLine.Count() < headers.Count) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, runTimeErrorId = idErr1, message = $"{description.Get()}: too short line is ignored: ({(inputLine.Length > 20 ? inputLine.Substring(0, 20) : inputLine)})" }); continue; } string strValMergeVar = splitInputLine.ElementAt(indexMergeVar); if (!double.TryParse(EM_Helpers.AdaptDecimalSign(strValMergeVar), out double valMergeVar)) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, runTimeErrorId = idErr2, message = $"{description.Get()}: value of {rowMergeVar.name} {strValMergeVar} is not a valid number - line is ignored" }); continue; } if (inputContent.ContainsKey(valMergeVar)) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, runTimeErrorId = idErr3, message = $"{description.Get()}: {rowMergeVar.name} is not unique ({valMergeVar}) - only first value is taken into account" }); continue; } List <double> valOtherVar = new List <double>(tempIndexMatches.Count); foreach (int im in tempIndexMatches.Values) { if (!double.TryParse(EM_Helpers.AdaptDecimalSign(splitInputLine.ElementAt(im)), out double number)) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, runTimeErrorId = idErr4, message = $"{description.Get()}: {splitInputLine.ElementAt(im)} is not a valid number - 0 is used as default" }); number = 0; } valOtherVar.Add(number); } inputContent.Add(valMergeVar, valOtherVar); } // example: input-row: inputVar1, mergeVar, inputVar2, ... // tempIndexMatches = {27, 0}, {88, 2} // the first value is a phantasie-value for the index in the data-array // indexMatches = {27, 0}, {88, 1} foreach (var im in tempIndexMatches) { indexMatches.Add(im.Key, im.Value > indexMergeVar ? im.Value - 1 : im.Value); } return(true); } catch (Exception exception) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{description.Get()}: {exception.Message} - input is canceled" }); return(false); } }
private Dictionary <double, double> GetFactors(Dictionary <string, double> internalFactorDefs, ParBase parFac) { Dictionary <double, double> allFactors = new Dictionary <double, double>(); string upFactorS = parFac.xmlValue; // xmlValue contains the uprating instruction, // which may be a number (e.g. 1.4) or the name of a factor (e.g. $f_cpi) if (!double.TryParse(EM_Helpers.AdaptDecimalSign(upFactorS), out double upFactor)) // first try if a number ... { if (internalFactorDefs.ContainsKey(upFactorS)) // ... then try if a factor defined by Factor_Name/Factor_Value { allFactors.Add(UpVar.ALLYEARS, internalFactorDefs[upFactorS]); } else if (infoStore.country.upFacs.ContainsKey(upFactorS)) // ... then try if a factor-name defined in dialog { if (infoStore.country.upFacs[upFactorS].Get(infoStore.country.sys.year, out double sysInd)) { if (sysInd == 0 && !zeroFactorSysCollector.Contains(upFactorS)) { zeroFactorSysCollector.Add(upFactorS); } if (isDBYearVarUsed) { // Calculate the uprating factors foreach (KeyValuePair <string, double> facs in infoStore.country.upFacs[upFactorS].GetAll()) { if (double.TryParse(facs.Key, out double yr)) { if (facs.Value == 0 && !zeroFactorDataCollector.Contains(facs.Key)) { zeroFactorDataCollector.Add(facs.Key); } allFactors.Add(yr, sysInd / facs.Value); } else { // This should only happen if a year cannot be parsed - This should NEVER happen! infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{parFac.description.Get()}: invalid year '{facs.Key}' found in uprating factors!" }); return(allFactors); } } } else { if (infoStore.country.upFacs[upFactorS].Get(infoStore.country.data.year, out double dbInd)) { if (dbInd == 0 && !zeroFactorDataCollector.Contains(upFactorS)) { zeroFactorDataCollector.Add(upFactorS); } allFactors.Add(UpVar.ALLYEARS, sysInd / dbInd); } else { // Or keep 1 and return warning if any indices are missing string dataInfo = string.IsNullOrEmpty(infoStore.country.data.year) ? $": income-year is missing for '{infoStore.country.data.Name}'" : $" for data year '{infoStore.country.data.year}'"; infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{parFac.description.Get()}: insufficient definition of uprating-factor '{parFac.xmlValue}'{dataInfo} (1 is used as default)" }); } } } else { // Or keep 1 and return warning if any indices are missing infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{parFac.description.Get()}: insufficient definition of uprating-factor '{parFac.xmlValue}' for system year '{infoStore.country.sys.year}' (1 is used as default)" }); } } else { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"{parFac.description.Get()}: unknown factor {parFac.xmlValue}" }); } } else { allFactors.Add(UpVar.ALLYEARS, upFactor); } return(allFactors); }