FFSM++  1.1.0
French Forest Sector Model ++
ModelData.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2015 by Laboratoire d'Economie Forestière *
3  * http://ffsm-project.org *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 3 of the License, or *
8  * (at your option) any later version, given the compliance with the *
9  * exceptions listed in the file COPYING that is distribued together *
10  * with this file. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program; if not, write to the *
19  * Free Software Foundation, Inc., *
20  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21  ***************************************************************************/
22 
23 #include <sys/types.h>
24 #include <dirent.h>
25 #include <errno.h>
26 #include <iostream>
27 
28 #include <vector>
29 #include <string>
30 #include <sstream>
31 #include <stdexcept>
32 #include <algorithm> //alghoritm used to reverse an array ( reverse(v.begin(), v.end()); )
33 #include <iomanip> // for unzip
34 #include <math.h>
35 #include <random> // for random temp directory to unzip
36 
37 // Qt headers..
38 #include <QFile>
39 #include <QFileInfo>
40 #include <QString>
41 #include <QStringList>
42 #include <QList>
43 
44 // Unzip headers..
45 #include "unzip.h"
46 
47 // RegMAS headers..
48 #include "ModelData.h"
49 //#include "InputDocument.h"
50 //#include "InputNode.h"
51 #include "MainWindow.h"
52 #include "Scheduler.h"
53 #include "ModelRegion.h"
54 #include "Pixel.h"
55 
56 typedef map<string, vector <double> > DataMap;
57 typedef pair<string, vector <double> > DataPair;
58 
59 
60 
62  MTHREAD = MTHREAD_h;
64  tempBool = true;
65  valueFoundBool = true;
66 }
67 
69 
70 }
71 
72 forType*
73 ModelData::getForType(string &forTypeId_h){
74  for(int i=0;i<forTypes.size();i++){
75  if(forTypes[i].forTypeId==forTypeId_h) return &forTypes[i];
76  }
77  msgOut(MSG_CRITICAL_ERROR,"forTypeId "+forTypeId_h+" not found. Aborting.");
78 }
79 
80 int
81 ModelData::getForTypeCounter(string& forTypeId_h, bool all){
82  vector <string> fTIds = getForTypeIds(all);
83  for(int i=0;i<fTIds.size();i++){
84  if(fTIds[i]==forTypeId_h) return i;
85  }
86  msgOut(MSG_CRITICAL_ERROR,"forTypeId "+forTypeId_h+" not found in "+((string) __func__ )+". Aborting.");
87 }
88 
89 string
90 ModelData::getForTypeParentId(const string &forTypeId_h){
91  for(int i=0;i<forTypes.size();i++){
92  if(forTypes[i].forTypeId==forTypeId_h) return forTypes[i].ereditatedFrom;
93  }
94  msgOut(MSG_CRITICAL_ERROR,"forTypeId "+forTypeId_h+" not found. Aborting.");
95 }
96 
97 vector<string>
98 ModelData::getForTypeChilds(const string &forTypeId_h){
99  vector<string> childs;
100  for(int i=0;i<forTypes.size();i++){
101  if(forTypes[i].ereditatedFrom==forTypeId_h) {
102  childs.push_back(forTypes[i].forTypeId);
103  }
104  }
105  return childs;
106 }
107 
108 vector<int>
109 ModelData::getForTypeChilds_pos(const string &forTypeId_h, bool all){
110  vector <int> childs;
111  vector <string> fTIds = getForTypeIds(all);
112  for(int i=0;i<fTIds.size();i++){
113  forType* ft = getForType(fTIds[i]);
114  if(ft->ereditatedFrom==forTypeId_h) {
115  childs.push_back(i);
116  }
117  }
118  return childs;
119 }
120 
121 vector<string>
123  vector<string> parents;
124  for(int i=0;i<forTypes.size();i++){
125  string parent = forTypes[i].ereditatedFrom;
126  if(!inVector(parent,parents) && parent != ""){
127  parents.push_back(parent);
128  }
129  }
130  return parents;
131 }
132 
133 
134 int
135 ModelData::getNForTypesChilds(const string& forTypeId_h){
136  int nChilds = 0;
137  for(int i=0;i<forTypes.size();i++){
138  if(forTypes[i].ereditatedFrom==forTypeId_h) {
139  nChilds ++;
140  }
141  }
142  return nChilds;
143 }
144 
145 vector<string>
147  vector<string> toReturn;
148  LLData table = getTable("scenarios");
149  for(int i=0;i<table.nrecords();i++){
150  string scenarioName = table.getData(i,"id");
151  toReturn.push_back(scenarioName);
152  }
153  return toReturn;
154 }
155 
156 int
158  vector<string> scenarios = getScenarios(); /// \todo Check that I can call this function all around the model and not only at the beginning
159  string currentScenario = MTHREAD->getScenarioName();
160  for(int i=0;i<scenarios.size();i++){
161  if (currentScenario == scenarios[i]){
162  return i;
163  }
164  }
165  msgOut(MSG_CRITICAL_ERROR, "function getScenarioIndex() didn't found the current scenarioName within those returned by getScenarios().");
166  return 0;
167 }
168 
169 void
171  LLData table = getTable("scenarios");
172  string choosenScenario = MTHREAD->getScenarioName();
173  for(int i=0;i<table.nrecords();i++){
174  string recordScenarioName = table.getData(i,"id");
175  if (recordScenarioName == choosenScenario){
176  scenario.id = recordScenarioName;
177  scenario.shortDesc = table.getData(i,"shortDesc");
178  scenario.longDesc = table.getData(i,"longDesc");
179  scenario.settingTable = table.getData(i,"settingTable");
180  scenario.forDataTable = table.getData(i,"forDataTable");
181  scenario.prodDataTable = table.getData(i,"prodDataTable");
182  scenario.forToProdTable = table.getData(i,"forToProdTable");
183  scenario.pathTable = table.getData(i,"pathTable");
184  scenario.settingFile = table.getData(i,"settingFile");
185  return;
186  }
187  }
188  msgOut(MSG_CRITICAL_ERROR, "Scenario not found!");
189 
190 
191 }
192 
193 void
195 
196  LLData table = getTable("settings");
197  int nheaders = table.nheaders();
198  for (int i=0; i< table.nrecords();i++){
199  BasicData SETT;
200  SETT.name = table.getData(i,"name");
201  string type = table.getData(i,"type");
202  SETT.type = getType(type);
203  string region_s= table.getData(i,"region");
204  SETT.regId = region_s==""?WORLD:s2i(table.getData(i,"region"));
205  SETT.comment = table.getData(i,"comment");
206  vector <string> values;
207  for (int z=0;z<nheaders-4;z++){ // don't consider name, type, comment and region headers
208  string toSearch = "value_"+i2s(z);
209  string value = table.getData(i,toSearch);
210  if (value != ""){
211  values.push_back(value);
212  }
213  }
214  SETT.values = values;
215  programSettingsVector.push_back(SETT);
216  }
217 
218  msgOut(MSG_INFO,"### USING SCENARIO: "+MTHREAD->getScenarioName()+" ###");
219 
220  setOutputDirectory(getStringSetting("outputDirname").c_str());
221 }
222 
223 void
225 
226  if(scenario.settingTable=="" && scenario.settingFile=="") {return;}
227  if(scenario.settingTable!="" && scenario.settingFile!="") {
228  msgOut(MSG_CRITICAL_ERROR,"Scenario-specific settings has been indicated to be loaded from BOTH from the spreadsheet and a file. Choose one of them.");
229  }
230  LLData table(MTHREAD,"settings");
231  if(scenario.settingTable!=""){
232  table = getTable(scenario.settingTable, MSG_CRITICAL_ERROR); //this scenario could not have an associated setting sheet
233  } else {
234  table = getTableFromFile("settings",scenario.settingFile);
235  }
236 
237 
238 
239  int nheaders = table.nheaders();
240  for(int i=0; i< table.nrecords(); i++){
241  string name = table.getData(i,"name");
242  string stype = table.getData(i,"type");
243  int type = getType(stype);
244  string region_s= table.getData(i,"region");
245  int regId = region_s==""?WORLD:s2i(table.getData(i,"region"));
246  string comment = table.getData(i,"comment");
247  vector <string> values;
248  for (int z=0;z<nheaders-4;z++){ // don't consider name, type and comment headers
249  string toSearch = "value_"+i2s(z);
250  string value = table.getData(i,toSearch);
251  if (value != ""){
252  values.push_back(value);
253  }
254  }
255  bool found = false;
256  for(uint i=0;i<programSettingsVector.size();i++){
257  if(programSettingsVector[i].name == name && programSettingsVector[i].regId == regId){
258  programSettingsVector[i].values = values;
259  programSettingsVector[i].type = type;
260  programSettingsVector[i].comment = comment;
261  found = true;
262  break;
263  }
264  }
265  if(!found){
266  BasicData SETT;
267  SETT.name = name;
268  SETT.type = type;
269  SETT.regId = regId;
270  SETT.comment = comment;
271  SETT.values = values;
272  programSettingsVector.push_back(SETT);
273  }
274 
275  }
276 
277  setOutputDirectory(getStringSetting("outputDirname").c_str());
278 }
279 
280 void
281 ModelData::addSetting(string name_h, vector <string> values_h, int type_h, string comment_h){
282 
283  for (uint i=0;i<programSettingsVector.size();i++){
284  if (programSettingsVector.at(i).name == name_h){
285  msgOut(MSG_ERROR, "I already have setting "+name_h+".. Nothing is added..");
286  return;
287  }
288  }
289  BasicData SETT;
290  SETT.name = name_h;
291  SETT.values = values_h;
292  SETT.type= type_h;
293  SETT.comment = comment_h;
294  programSettingsVector.push_back(SETT);
295 }
296 
297 void
298 ModelData::addSetting(string name_h, string value_h, int type_h, string comment_h){
299  vector <string> values;
300  values.push_back(value_h);
301  addSetting(name_h, values, type_h, comment_h);
302 }
303 
304 void
306  cached_initialYear = getIntSetting("initialYear");
307  diamClasses = getStringVectorSetting("dClasses");
308  priProducts = getStringVectorSetting("priProducts");
309  secProducts = getStringVectorSetting("secProducts");
311  allProducts.insert( allProducts.end(), secProducts.begin(), secProducts.end() );
312 }
313 
314 // ###############################################################################
315 
316 void
318  // first create regions and assign basic data...
319  LLData table = getTable("regions");
320  for (int i=0; i< table.nrecords();i++){
321  ModelRegion REGION(MTHREAD,
322  s2i(table.getData(i,"regId")),
323  table.getData(i,"regSName"),
324  table.getData(i,"regLName"),
325  s2i(table.getData(i,"regLevel")),
326  s2i(table.getData(i,"parRegId")),
327  s2b(table.getData(i,"isResidual")));
328  regionsVector.push_back(REGION);
329  }
330  // Now let's assign the parent/children pointers..
331  for (int i=0; i< regionsVector.size();i++){
332  // let's assign the parent:
333  regionsVector[i].setParent(this->getRegion(regionsVector[i].getParRegId()));
334  // let's assign the children:
335  vector<ModelRegion*> kids;
336  for (int y=0; y< regionsVector.size();y++){
337  if(regionsVector[y].getParRegId() == regionsVector[i].getRegId() ){
338  kids.push_back(&regionsVector[y]);
339  }
340  }
341  regionsVector[i].setChildren(kids);
342  }
343 }
344 
346 ModelData::getRegion(int regId_h){
347  for (int i=0; i< regionsVector.size();i++){
348  if(regionsVector[i].getRegId()==regId_h){
349  return &regionsVector[i];
350  }
351  }
352  msgOut(MSG_CRITICAL_ERROR, "Region id "+i2s(regId_h)+" not found, check your input data. Aborting simulation.");
353 }
354 
355 bool
356 ModelData::regionExist (const int & regId_h) const {
357  for (int i=0; i< regionsVector.size();i++){
358  if(regionsVector[i].getRegId()==regId_h){
359  return true;
360  }
361  }
362  return false;
363 }
364 
365 vector <int>
366 ModelData::getRegionIds(int level_h, bool excludeResidual){
367  vector <int> toReturn;
368  for(uint i=0;i<regionsVector.size();i++){
369  if(regionsVector[i].getRegLevel()==level_h){
370  if( (!excludeResidual) || (!regionsVector[i].getIsResidual())){
371  toReturn.push_back(regionsVector[i].getRegId());
372  }
373  }
374  }
375  return toReturn;
376 }
377 
378 vector <ModelRegion*>
379 ModelData::getAllRegions(bool excludeResidual){
380  vector <ModelRegion*> toReturn;
381  for(uint i=0;i<regionsVector.size();i++){
382  if( (!excludeResidual) || (!regionsVector[i].getIsResidual())){
383  toReturn.push_back(&regionsVector[i]);
384  }
385  }
386  return toReturn;
387 }
388 
389 vector < vector <int> >
390 ModelData::getRegionIds( bool excludeResidual){
391  vector < vector <int> > toReturn;
392  vector <int> l1regIds = MTHREAD->MD->getRegionIds(1, excludeResidual);
393  for(uint i=0;i<l1regIds.size();i++){
394  vector<int> l2ChildrenIds;
395  ModelRegion* l1Region = MTHREAD->MD->getRegion(l1regIds[i]);
396  vector<ModelRegion*> l2Childrens = l1Region->getChildren(excludeResidual);
397  for(uint j=0;j<l2Childrens.size();j++){
398  l2ChildrenIds.push_back(l2Childrens[j]->getRegId());
399  }
400  if(l2ChildrenIds.size()){
401  toReturn.push_back(l2ChildrenIds);
402  }
403  }
404  return toReturn;
405 }
406 
407 string
408 ModelData::regId2RegSName (const int & regId_h) const {
409  ModelRegion* reg = MTHREAD->MD->getRegion(regId_h);
410  return reg->getRegSName();
411 }
412 
413 int
414 ModelData::regSName2RegId (const string & regSName_h) const{
415  ModelRegion* reg;
416  for(uint i=0; i<3; i++){
417  vector <int> regIds = MTHREAD->MD->getRegionIds(i, false);
418  for(uint j=0;j<regIds.size();j++){
419  reg = MTHREAD->MD->getRegion(regIds[j]);
420  if(reg->getRegSName()==regSName_h) {return regIds[j];}
421  }
422  }
423  msgOut(MSG_CRITICAL_ERROR,"Regional short name not found.");
424 }
425 
426 
427 
428 
429 vector <string>
431  vector <string> toReturn;
432  for(uint i=0;i<forTypes.size();i++){
433  if(forTypes[i].memType!=1 || all) {
434  toReturn.push_back(forTypes[i].forTypeId);
435  }
436  }
437  return toReturn;
438 }
439 
440 const bool
441 ModelData::assessProdPossibility(const string &prod_h, const string &forType_h, const string &dClass_h){
442  bool ok=false;
443  for(uint i=0;i<forToProdVector.size();i++){
444  if( forToProdVector[i].product == prod_h
445  && forToProdVector[i].forType == forType_h
446  && forToProdVector[i].dClass == dClass_h
447  ){
448  return true;
449  }
450  }
451  return false;
452 }
453 
454 
455 const int
457  int maxMaxYears = 0;
458  for(uint i=0;i<forToProdVector.size();i++){
459  if(forToProdVector[i].maxYears > maxMaxYears){
460  maxMaxYears = forToProdVector[i].maxYears;
461  }
462  }
463  return maxMaxYears;
464 }
465 
466 
467 const int
468 ModelData::getMaxYearUsableDeathTimber(const string &prod_h, const string &forType_h, const string &dClass_h){
469  for(uint i=0;i<forToProdVector.size();i++){
470  if( forToProdVector[i].product == prod_h
471  && forToProdVector[i].forType == forType_h
472  && forToProdVector[i].dClass == dClass_h
473  ){
474  return forToProdVector[i].maxYears;
475  }
476  }
477  msgOut(MSG_CRITICAL_ERROR,"In getMaxYearUsableDeathTimber() I has been asked of a combination that I don't know how to handle.");
478 }
479 
480 void
482  msgOut(MSG_DEBUG,"Loading forest sector data..");
483  LLData table = getTable("forData");
484  int nheaders = table.nheaders();
485  for (int i=0; i< table.nrecords();i++){
486  vector <double> values;
487  for (int z=0;z<nheaders-4;z++){ // don't consider parName, region, forType and diamClass headers
488  string toSearch = "value_"+i2s(z);
489  string value = table.getData(i,toSearch);
490  if (value != ""){
491  values.push_back(s2d(value));
492  }
493  }
494  string keys = makeKeyForData(table.getData(i,"parName"), table.getData(i,"region"),table.getData(i,"forType"),table.getData(i,"freeDim"));
495  forDataMap.insert(std::pair<string, vector<double> >(keys, values));
496  }
497 }
498 
499 void
501 
502  if(scenario.forDataTable==""){return;}
504 
505  int nheaders = table.nheaders();
506  for(int i=0; i< table.nrecords(); i++){
507  bool found = false;
508  string key = makeKeyForData(table.getData(i,"parName"),table.getData(i,"region"),table.getData(i,"forType"),table.getData(i,"freeDim"));
509  vector <double> values;
510  for (int z=0;z<nheaders-4;z++){ // don't consider parName, region, forType and diamClass headers
511  string toSearch = "value_"+i2s(z);
512  string value = table.getData(i,toSearch);
513  if (value != ""){
514  values.push_back(s2d(value));
515  }
516  }
517  map <string, vector < double > >::iterator p;
518  p=forDataMap.find(key);
519  if(p != forDataMap.end()) {
520  // updating an existing record
521  p->second = values;
522  }
523  else {
524  // new one, adding it
525  forDataMap.insert(std::pair<string, vector<double> >(key, values));
526  }
527  }
528 }
529 
530 void
532 
533  msgOut(MSG_DEBUG,"Loading products data..");
534  LLData table = getTable("prodData");
535  int nheaders = table.nheaders();
536 
537  for (int i=0; i< table.nrecords();i++){
538 // prodData PDATA;
539 // PDATA.parName = table.getData(i,"parName");
540 // PDATA.region = s2i(table.getData(i,"region"));
541 // PDATA.prod = table.getData(i,"prod");
542 // PDATA.freeDim = table.getData(i,"freeDim");
543  vector <double> values;
544  for (int z=0;z<nheaders-4;z++){ // don't consider parName, region, prod and freeDim headers
545  string toSearch = "value_"+i2s(z);
546  string value = table.getData(i,toSearch);
547  if (value != ""){
548  values.push_back(s2d(value));
549  }
550  }
551 // PDATA.values = values;
552 // prodDataVector.push_back(PDATA);
553  string keys = makeKeyProdData(table.getData(i,"parName"), table.getData(i,"region"),table.getData(i,"prod"),table.getData(i,"freeDim"));
554  prodDataMap.insert(std::pair<string, vector<double> >(keys, values));
555  //giving a link to it to its own region:
556 // getRegion(PDATA.region)->addProdData(&PDATA);
557  }
558 }
559 
560 void
562 
563  if(scenario.prodDataTable==""){return;}
564  LLData table = getTable(scenario.prodDataTable, MSG_CRITICAL_ERROR); //this scenario could not have an associated setting sheet
565 
566  int nheaders = table.nheaders();
567  int debug = table.nrecords();
568  for(int i=0; i< table.nrecords(); i++){
569  //prodData PDATA;
570  bool found = false;
571  string key = makeKeyProdData(table.getData(i,"parName"),table.getData(i,"region"),table.getData(i,"prod"),table.getData(i,"freeDim"));
572 
573  //PDATA.parName = table.getData(i,"parName");
574  //PDATA.region = s2i(table.getData(i,"region"));
575  //PDATA.prod = table.getData(i,"prod");
576  //PDATA.freeDim = table.getData(i,"freeDim");
577  vector <double> values;
578  for (int z=0;z<nheaders-4;z++){// don't consider parName, region, prod and freeDim headers
579  string toSearch = "value_"+i2s(z);
580  string value = table.getData(i,toSearch);
581  if (value != ""){
582  values.push_back(s2d(value));
583  }
584  }
585  //PDATA.values = values;
586  //for(uint i=0;i<prodDataVector.size();i++){
587  // if(prodDataVector[i].parName == PDATA.parName
588  // && prodDataVector[i].region == PDATA.region
589  // && prodDataVector[i].prod == PDATA.prod
590  // && prodDataVector[i].freeDim == PDATA.freeDim){
591  // // existing prodData..
592  // prodDataVector[i].values = PDATA.values;
593  // found = true;
594  // break;
595  // }
596  //}
597  //if(!found){
598  // // new one, adding it
599  // prodDataVector.push_back(PDATA);
600  // //giving a link to it to its own region:
601  // getRegion(PDATA.region)->addProdData(&PDATA);
602  //}
603 
604  map <string, vector < double > >::iterator p;
605  p=prodDataMap.find(key);
606  if(p != prodDataMap.end()) {
607  // updating an existing record
608  p->second = values;
609  }
610  else {
611  // new one, adding it
612  prodDataMap.insert(std::pair<string, vector<double> >(key, values));
613  }
614  }
615 }
616 
617 void
619  msgOut(MSG_DEBUG,"Loading forest resource to primary products io matrix..");
620  LLData table = getTable("forToProd");
621  for (int i=0; i< table.nrecords();i++){
622  forToProd F2PDATA;
623  F2PDATA.product = table.getData(i,"product");
624  F2PDATA.forType = table.getData(i,"forType");
625  F2PDATA.dClass = table.getData(i,"dClass");
626  F2PDATA.maxYears = s2i(table.getData(i,"maxYears"));
627  forToProdVector.push_back(F2PDATA);
628  }
629 }
630 
631 void
633  if(scenario.forToProdTable==""){return;}
634  LLData table = getTable(scenario.forToProdTable, MSG_CRITICAL_ERROR); //this scenario could not have an associated setting sheet
635 
636  int nheaders = table.nheaders();
637  forToProdVector.clear();
638  for (int i=0; i< table.nrecords();i++){
639  forToProd F2PDATA;
640  F2PDATA.product = table.getData(i,"product");
641  F2PDATA.forType = table.getData(i,"forType");
642  F2PDATA.dClass = table.getData(i,"dClass");
643  forToProdVector.push_back(F2PDATA);
644  }
645 }
646 
647 void
649  LLData table = getTable("forTypes");
650  for (int i=0; i< table.nrecords();i++){
651  forType FTYPE;
652  FTYPE.forTypeId = table.getData(i,"forTypeId");
653  FTYPE.forLabel = table.getData(i,"forLabel");
654  FTYPE.memType = s2i(table.getData(i,"memType"));
655  FTYPE.forLayer = table.getData(i,"forLayer");
656  FTYPE.ereditatedFrom = table.getData(i,"ereditatedFrom");
657  if(FTYPE.memType == 3 && !getBoolSetting("useSpExplicitForestTypes")) continue;
658  forTypes.push_back(FTYPE);
659  }
660 }
661 
662 void
664 
665  msgOut(MSG_DEBUG,"Loading (but not yet applying) reclassification rules..");
666  LLData table = getTable("reclRules");
667  for (int i=0; i< table.nrecords();i++){
668  reclRule RL;
669  RL.regId = s2i(table.getData(i,"regID"));
670  RL.forTypeIn = table.getData(i,"forTypeIn");
671  RL.forTypeOut = table.getData(i,"forTypeOut");
672  RL.coeff = s2d(table.getData(i,"coeff"));
673  reclRules.push_back(RL);
674  }
675 }
676 
677 void
679 
680  if(!getBoolSetting("usePathogenModule")) return;
681  msgOut(MSG_DEBUG,"Loading pathogen rules..");
682  LLData table = getTable("pathRules");
683  int nheaders = table.nheaders();
684  for (int i=0; i< table.nrecords();i++){
685  pathRule PR;
686  PR.forType = table.getData(i,"forType");
687  PR.dClass = table.getData(i,"dClass");
688  PR.pathId = table.getData(i,"path_name");
689  PR.pres_min = s2d(table.getData(i,"pres_min"));
690 
691  vector <double> values;
692  for (int z=0;z<nheaders-4;z++){ // don't consider forType, dClass, path_name and pres_min headers
693  string toSearch = "year_"+i2s(z);
694  string value = table.getData(i,toSearch);
695  if (value != ""){
696  values.push_back(s2d(value));
697  }
698  }
699  PR.mortCoefficents = values;
700 
701  pathRules.push_back(PR);
702  }
703 }
704 
705 void
707 
708  if(scenario.pathTable==""){return;}
709  LLData table = getTable(scenario.pathTable, MSG_CRITICAL_ERROR); //this scenario could not have an associated setting sheet
710 
711  int nheaders = table.nheaders();
712  for (int i=0; i< table.nrecords();i++){
713  pathRule PR;
714  PR.forType = table.getData(i,"forType");
715  PR.dClass = table.getData(i,"dClass");
716  PR.pathId = table.getData(i,"path_name");
717  PR.pres_min = s2d(table.getData(i,"pres_min"));
718 
719  vector <double> values;
720  for (int z=0;z<nheaders-4;z++){ // don't consider forType, dClass, path_name and pres_min headers
721  string toSearch = "year_"+i2s(z);
722  string value = table.getData(i,toSearch);
723  if (value != ""){
724  values.push_back(s2d(value));
725  }
726  }
727  PR.mortCoefficents = values;
728 
729  bool found = false;
730  for(uint i=0;i<pathRules.size();i++){
731  if( pathRules[i].forType == PR.forType
732  && pathRules[i].dClass == PR.dClass
733  && pathRules[i].pathId == PR.pathId
734  ){
735  pathRules[i].pres_min = PR.pres_min;
736  pathRules[i].mortCoefficents = PR.mortCoefficents;
737  found = true;
738  break;
739  }
740  }
741  if(!found){
742  pathRules.push_back(PR);
743  }
744  } // end for each table record
745 }
746 
747 /// Cancel all reg1 level data and trasform them in reg2 level if not already existing
748 void
750 
751  if(!getBoolSetting("applyOverriding")) return;
752  msgOut(MSG_INFO, "Starting regional overriding analysis..");
753 
754  DataMap::iterator p;
755  string parName,prod,freeDim,forType,diamClass, key;
756  int regId;
757  DataMap toBeAdded;
758  vector <string> keysToRemove;
759 
760 
761  //apply override from level 0 to level 1 for forestry data
762  toBeAdded.clear();
763  keysToRemove.clear();
764  for(p=forDataMap.begin();p!=forDataMap.end();p++){
765  unpackKeyForData(p->first,parName,regId,forType,diamClass);
766  if(!regionExist(regId)){
767  msgOut(MSG_CRITICAL_ERROR,"Forest variable has a unknown region code If you want not to model a region, set residual=true.: "+parName+"\t"+i2s(regId));
768  continue;
769  }
770  if(getRegion(regId)->getRegLevel() == 0){
771  vector<ModelRegion*> childs = getRegion(regId)->getChildren(false);
772  for(uint j=0;j<childs.size();j++){
773  bool found = false;
774  key = makeKeyForData(parName,i2s(childs[j]->getRegId()),forType,diamClass);
775  if (!dataMapCheckExist(forDataMap,key,true)){
776  toBeAdded.insert(DataPair(key,p->second));
777  }
778  }
779  keysToRemove.push_back(p->first);
780  }
781  }
782  forDataMap.insert(toBeAdded.begin(),toBeAdded.end());
783  for(uint i=0;i<keysToRemove.size();i++){
784  DataMap::iterator rem = forDataMap.find(keysToRemove[i]);
785  if(rem != forDataMap.end()){
786  forDataMap.erase(rem);
787  }
788  }
789 
790 
791 
792 
793  //apply override from level 1 to level 2 for forestry data
794  toBeAdded.clear();
795  keysToRemove.clear();
796  for(p=forDataMap.begin();p!=forDataMap.end();p++){
797  unpackKeyForData(p->first,parName,regId,forType,diamClass);
798  if(!regionExist(regId)){
799  msgOut(MSG_CRITICAL_ERROR,"Forest variable has a unknown region code If you want not to model a region, set residual=true.: "+parName+"\t"+i2s(regId));
800  continue;
801  }
802  if(getRegion(regId)->getRegLevel() == 1){
803  vector<ModelRegion*> childs = getRegion(regId)->getChildren(false);
804  for(uint j=0;j<childs.size();j++){
805  bool found = false;
806  key = makeKeyForData(parName,i2s(childs[j]->getRegId()),forType,diamClass);
807  if (!dataMapCheckExist(forDataMap,key,true)){
808  toBeAdded.insert(DataPair(key,p->second));
809  }
810  }
811  keysToRemove.push_back(p->first);
812  }
813  }
814  forDataMap.insert(toBeAdded.begin(),toBeAdded.end());
815  for(uint i=0;i<keysToRemove.size();i++){
816  DataMap::iterator rem = forDataMap.find(keysToRemove[i]);
817  if(rem != forDataMap.end()){
818  forDataMap.erase(rem);
819  }
820  }
821 
822  //apply override from level 0 to level 1 for production data
823  toBeAdded.clear();
824  keysToRemove.clear();
825  for(p=prodDataMap.begin();p!=prodDataMap.end();p++){
826  unpackKeyProdData(p->first,parName,regId,prod,freeDim);
827  if(!regionExist(regId)){
828  msgOut(MSG_CRITICAL_ERROR,"Product variable has a unknown region code If you want not to model a region, set residual=true.: "+parName+"\t"+i2s(regId));
829  continue;
830  }
831  if(getRegion(regId)->getRegLevel() == 0){
832  vector<ModelRegion*> childs = getRegion(regId)->getChildren(false);
833  for(uint j=0;j<childs.size();j++){
834  bool found = false;
835  key = makeKeyProdData(parName,i2s(childs[j]->getRegId()),prod,freeDim);
836  if (!dataMapCheckExist(prodDataMap,key,true)){
837  toBeAdded.insert(DataPair(key,p->second));
838  }
839  }
840  //prodDataMap.erase(p);
841  //p--;
842  keysToRemove.push_back(p->first);
843  }
844  }
845  prodDataMap.insert(toBeAdded.begin(),toBeAdded.end());
846  for(uint i=0;i<keysToRemove.size();i++){
847  DataMap::iterator rem = prodDataMap.find(keysToRemove[i]);
848  if(rem != prodDataMap.end()){
849  prodDataMap.erase(rem);
850  }
851  }
852 
853 
854  //apply override from level 1 to level 2 for production data
855  toBeAdded.clear();
856  keysToRemove.clear();
857  for(p=prodDataMap.begin();p!=prodDataMap.end();p++){
858  string debug = p->first;
859  unpackKeyProdData(p->first,parName,regId,prod,freeDim);
860  if(!regionExist(regId)){
861  msgOut(MSG_CRITICAL_ERROR,"Product variable has a unknown region code If you want not to model a region, set residual=true.: "+parName+"\t"+i2s(regId));
862  continue;
863  }
864  if(getRegion(regId)->getRegLevel() == 1){
865  vector<ModelRegion*> childs = getRegion(regId)->getChildren(false);
866  for(uint j=0;j<childs.size();j++){
867  bool found = false;
868  key = makeKeyProdData(parName,i2s(childs[j]->getRegId()),prod,freeDim);
869  if (!dataMapCheckExist(prodDataMap,key,true)){
870  toBeAdded.insert(DataPair(key,p->second));
871  }
872  }
873  //prodDataMap.erase(p);
874  //p--;
875  keysToRemove.push_back(p->first);
876  }
877  }
878  prodDataMap.insert(toBeAdded.begin(),toBeAdded.end());
879  for(uint i=0;i<keysToRemove.size();i++){
880  DataMap::iterator rem = prodDataMap.find(keysToRemove[i]);
881  if(rem != prodDataMap.end()){
882  prodDataMap.erase(rem);
883  }
884  }
885 
886  //apply override from level 0 to level 1 for reclassification rules
887  for(uint i=0;i<reclRules.size();i++){
888  if(reclRules[i].regId == 0){
889  if(!regionExist(reclRules[i].regId)){
890  msgOut(MSG_CRITICAL_ERROR,"Reclassification rule has a unknown region code If you want not to model a region, set residual=true.: "+i2s(reclRules[i].regId));
891  continue;
892  }
893  for(uint j=0;j<getRegion(reclRules[i].regId)->getNChildren(false);j++){
894  vector<ModelRegion*> childs = getRegion(reclRules[i].regId)->getChildren(false);
895  bool found = 0;
896  for(uint z=0;z<reclRules.size();z++){
897  if( reclRules[z].regId == childs[j]->getRegId()
898  && reclRules[z].forTypeIn == reclRules[i].forTypeIn
899  && reclRules[z].forTypeOut == reclRules[i].forTypeOut
900  ){
901  found = true; // do nothing, this child has been already manually overritten
902  break;
903  }
904  }
905  if(!found){
906  reclRule RR;
907  RR.regId = childs[j]->getRegId();
908  RR.forTypeIn = reclRules[i].forTypeIn;
909  RR.forTypeOut = reclRules[i].forTypeOut;
910  RR.coeff = reclRules[i].coeff;
911  reclRules.push_back(RR);
912  }
913  }
914  reclRules.erase(reclRules.begin()+i);
915  i--;
916  }
917  }
918 
919  //apply override from level 1 to level 2 for reclassification rules
920  for(uint i=0;i<reclRules.size();i++){
921  if(!regionExist(reclRules[i].regId)){
922  msgOut(MSG_CRITICAL_ERROR,"Reclassification rule has a unknown region code. If you want not to model a region, set residual=true.: "+i2s(reclRules[i].regId));
923  continue;
924  }
925  if(getRegion(reclRules[i].regId)->getRegLevel() == 1){
926  for(uint j=0;j<getRegion(reclRules[i].regId)->getNChildren(false);j++){
927  vector<ModelRegion*> childs = getRegion(reclRules[i].regId)->getChildren(false);
928  bool found = 0;
929  for(uint z=0;z<reclRules.size();z++){
930  if( reclRules[z].regId == childs[j]->getRegId()
931  && reclRules[z].forTypeIn == reclRules[i].forTypeIn
932  && reclRules[z].forTypeOut == reclRules[i].forTypeOut
933  ){
934  found = true; // do nothing, this child has been already manually overritten
935  break;
936  }
937  }
938  if(!found){
939  reclRule RR;
940  RR.regId = childs[j]->getRegId();
941  RR.forTypeIn = reclRules[i].forTypeIn;
942  RR.forTypeOut = reclRules[i].forTypeOut;
943  RR.coeff = reclRules[i].coeff;
944  reclRules.push_back(RR);
945  }
946  }
947  reclRules.erase(reclRules.begin()+i);
948  i--;
949  }
950  }
951 }
952 
953 /**
954 The applyDebugMode flag all level2 regions not in the "debugRegions" option as "residual" (so they are in the map but not in the model code) and remove the primary and secondary products that are not included in the debugPriProducts and debugSecProducts options.
955 */
956 void
958  if(! getBoolSetting("debugFlag")) return;
959 
960  vector <int> debugRegions = getIntVectorSetting("debugRegions");
961  vector <string> debugPriProducts = getStringVectorSetting("debugPriProducts");
962  vector <string> debugSecProducts = getStringVectorSetting("debugSecProducts");
963 
964  for(uint i=0;i< regionsVector.size();i++){
965  if (regionsVector[i].getRegLevel()==2){
966  bool found= false;
967  for(uint j=0;j<debugRegions.size();j++){
968  if (debugRegions[j] == regionsVector[i].getRegId()){
969  found = true;
970  break;
971  }
972  }
973  if(!found){ // not in the list to keep
974  regionsVector[i].setIsResidual(true);
975  }
976  }
977  }
978 
979  for (uint i=0; i<programSettingsVector.size();i++){
980  if (programSettingsVector.at(i).name == "priProducts"){
981  programSettingsVector.at(i).values = debugPriProducts;
982  } else if (programSettingsVector.at(i).name == "secProducts"){
983  programSettingsVector.at(i).values = debugSecProducts;
984  }
985  }
986 
987 }
988 
989 void
990 ModelData::setOutputDirectory(const char* output_dirname_h){
991 
992  if (strlen(output_dirname_h)==0){
993  outputDirname=baseDirectory+"output/";
994  }
995  else {
996  outputDirname=output_dirname_h;
997  }
998  MTHREAD->setOutputDirName(outputDirname); //for the GUI
999 }
1000 
1001 /**
1002 Returns the value stored in the settings database.
1003 
1004 
1005 Regional overriding.
1006 
1007 Concerning the param regId_h:
1008 it expect either world (default), a L2 or L1 region.
1009 Settings in the memory are stored also with data in one or more of these levels (e.g. we may have a general WORLD value and then a more specific L2 value.
1010 The function is done such that if WORLD is used to query it, it returns only a world value, if L1 is used instead, it looks for this L1 value and then eventually
1011 (if nothing is found) for WORLD. Finally, if L2 is used, it query, in the order, for L2, L1 or world levels.
1012 
1013 */
1014 string
1015 ModelData::getBaseData (const string &name_h, int type_h, int position, int regId_h){
1016  // If the data is called with DATA_NOW we interpret the array of values as a temporal array and we return the value at the current time.
1017  if(position == DATA_NOW) {
1018  position = MTHREAD->SCD->getIteration();
1019  }
1020 
1021  vector <int> regIds;
1022 
1023  if(regId_h == WORLD){
1024  regIds.push_back(WORLD);
1025  } else if (getRegion(regId_h)->getRegLevel()==1){
1026  regIds.push_back(regId_h);
1027  regIds.push_back(WORLD);
1028  } else if (getRegion(regId_h)->getRegLevel()==2) {
1029  regIds.push_back(regId_h);
1030  regIds.push_back(getRegion(regId_h)->getParRegId());
1031  regIds.push_back(WORLD);
1032  } else {
1033  msgOut(MSG_CRITICAL_ERROR, "Error in getBaseData(). Data requested for a unknown region level.");
1034  }
1035 
1036 
1037  for (uint j=0; j<regIds.size();j++){
1038  int regId = regIds[j];
1039  for (uint i=0; i<programSettingsVector.size();i++){
1040  if (programSettingsVector.at(i).name == name_h & programSettingsVector.at(i).regId == regId){
1041  int type = programSettingsVector.at(i).type;
1042  if(type != type_h){msgOut(MSG_CRITICAL_ERROR, "mismatching type in calling getBaseData() for "+name_h);}
1043  if(programSettingsVector.at(i).values.size() > ((uint)position)) {
1044  return programSettingsVector.at(i).values.at(position);
1045  } else if (programSettingsVector.at(i).values.size() > 0 ){
1046  // returning the last available value...
1047  return programSettingsVector.at(i).values.at( programSettingsVector.at(i).values.size()-1 );
1048  }
1049  else {msgOut(MSG_CRITICAL_ERROR, "Error: "+name_h+" doesn't have any value, even on the first position(year)!"); }
1050  }
1051  }
1052  }
1053 
1054  msgOut(MSG_CRITICAL_ERROR, "Error calling getBaseData() for "+ name_h +". No setting option or macro data found with this name.");
1055 
1056 // switch(type_h){
1057 // case TYPE_BOOL:
1058 // return "0";
1059 // case TYPE_INT:
1060 // return "0";
1061 // case TYPE_DOUBLE:
1062 // return "0.0";
1063 // case TYPE_STRING:
1064 // return "";
1065 // default:
1066 // msgOut(MSG_CRITICAL_ERROR, "Error calling getBaseData() for "+ i2s(type_h) +". I don't know this type.");
1067 // }
1068  return "";
1069 }
1070 
1071 
1072 vector <string>
1073 ModelData::getVectorBaseData (const string &name_h, int type_h, int regId_h){
1074  vector <int> regIds;
1075  if(regId_h == WORLD){
1076  regIds.push_back(WORLD);
1077  } else if(getRegion(regId_h)->getRegLevel()==1){
1078  regIds.push_back(regId_h);
1079  regIds.push_back(WORLD);
1080  } else if (getRegion(regId_h)->getRegLevel()==2) {
1081  regIds.push_back(regId_h);
1082  regIds.push_back(getRegion(regId_h)->getParRegId());
1083  regIds.push_back(WORLD);
1084  } else {
1085  msgOut(MSG_CRITICAL_ERROR, "Error in getBaseData(). Data requested for a unknown region level.");
1086  }
1087 
1088  for (uint j=0; j<regIds.size();j++){
1089  int regId = regIds[j];
1090  for (uint i=0; i<programSettingsVector.size();i++){
1091  if (programSettingsVector.at(i).name == name_h & programSettingsVector.at(i).regId == regId){
1092  int type = programSettingsVector.at(i).type;
1093  if(type != type_h){msgOut(MSG_CRITICAL_ERROR, "mismatching type in calling getVectorBaseData() for "+name_h);}
1094  return programSettingsVector.at(i).values;
1095  }
1096  }
1097  }
1098  msgOut(MSG_CRITICAL_ERROR, "Error calling getVectorBaseData() for "+ name_h +". No setting option or macro data found with this name.");
1099  vector <string> toReturn;
1100  return toReturn;
1101 }
1102 
1103 // ------------- start getSetting() amd getMacro() functions ....... -----------------
1104 int
1105 ModelData::getIntSetting(const string &name_h, int position, int reg) const{
1106  return s2i( MTHREAD->MD->getBaseData(name_h,TYPE_INT,position, reg) );
1107 }
1108 double
1109 ModelData::getDoubleSetting(const string &name_h, int position, int reg) const{
1110  return s2d( MTHREAD->MD->getBaseData(name_h,TYPE_DOUBLE,position,reg) );
1111 }
1112 string
1113 ModelData::getStringSetting(const string &name_h, int position, int reg) const{
1114  return MTHREAD->MD->getBaseData(name_h,TYPE_STRING,position,reg);
1115 }
1116 bool
1117 ModelData::getBoolSetting(const string &name_h, int position, int reg) const{
1118  return s2b( MTHREAD->MD->getBaseData(name_h,TYPE_BOOL,position,reg) );
1119 }
1120 vector<int>
1121 ModelData::getIntVectorSetting(const string &name_h, int reg) const{
1122  return s2i(MTHREAD->MD->getVectorBaseData(name_h,TYPE_INT,reg));
1123 }
1124 vector<double>
1125 ModelData::getDoubleVectorSetting(const string &name_h, int reg) const{
1126  return s2d(MTHREAD->MD->getVectorBaseData(name_h,TYPE_DOUBLE,reg));
1127 }
1128 vector<string>
1129 ModelData::getStringVectorSetting(const string &name_h, int reg) const{
1130  return MTHREAD->MD->getVectorBaseData(name_h,TYPE_STRING,reg);
1131 }
1132 vector<bool>
1133 ModelData::getBoolVectorSetting(const string &name_h, int reg) const{
1134  return s2b(MTHREAD->MD->getVectorBaseData(name_h,TYPE_BOOL,reg));
1135 }
1136 
1137 // ------ END of getSetting() functions ---------------------
1138 
1139 //// Never used
1140 //void
1141 //ModelData::setBasicData(const string &name_h, int value, int position){
1142 // setBasicData(name_h, i2s(value), TYPE_INT, position);
1143 //}
1144 //void
1145 //ModelData::setBasicData(const string &name_h, double value, int position){
1146 // setBasicData(name_h, d2s(value), TYPE_DOUBLE, position);
1147 //}
1148 //void
1149 //ModelData::setBasicData(const string &name_h, string value, int position){
1150 // setBasicData(name_h, value, TYPE_STRING, position);
1151 //}
1152 //void
1153 //ModelData::setBasicData(const string &name_h, bool value, int position){
1154 // setBasicData(name_h, b2s(value), TYPE_BOOL, position);
1155 //}
1156 
1157 //void
1158 //ModelData::setBasicData(const string &name_h, string value, int type_h, int position){
1159 // for (uint i=0; i<programSettingsVector.size();i++){
1160 // if (programSettingsVector.at(i).name == name_h){
1161 // int type = programSettingsVector.at(i).type;
1162 // if(type != type_h){msgOut(MSG_CRITICAL_ERROR, "mismatching type in calling setBasicData() for "+name_h);}
1163 // if(programSettingsVector.at(i).values.size() > ((uint)position)) {
1164 // programSettingsVector.at(i).values.at(position)=value;
1165 // return;
1166 // }
1167 // else {msgOut(MSG_CRITICAL_ERROR, "out-of-bound error calling setBasicData() for "+name_h); }
1168 // }
1169 // }
1170 // msgOut(MSG_CRITICAL_ERROR, "Error calling setBasicData() for "+ name_h +". No setting option or macro data found with this name.");
1171 // return;
1172 //}
1173 
1174 std::string
1175 ModelData::getFilenameByType(std::string type_h){
1176  std::string directory;
1177  std::string filename;
1178  std::string filename_complete;
1179  for (uint i=0; i<iFilesVector.size(); i++){
1180  if (iFilesVector.at(i).type == type_h){
1181  directory=iFilesVector.at(i).directory;
1182  filename=iFilesVector.at(i).name;
1183  break;
1184  }
1185  }
1186  filename_complete = baseDirectory+directory+filename;
1187  return filename_complete;
1188 }
1189 
1190 vector <string>
1191 ModelData::getDiameterClasses(bool productionOnly){
1192  int i;
1193  if(productionOnly){
1194  i=1;
1195  } else {
1196  i=0;
1197  }
1198  vector <string> toReturn;
1199  for (i;i<diamClasses.size();i++){
1200  toReturn.push_back(diamClasses[i]);
1201  }
1202  return toReturn;
1203 }
1204 
1205 /**
1206 Basic function to retrieve products-related data.
1207 It addmits the following "filters":
1208 @type_h Name of the specific parameter requested
1209 @regId_h Look for level1 or level 2 region.
1210 @prodId_h Product. It accept three keywords, for summing up all products, primary products or secondary products, namelly PROD_ALL, PROD_PRI, PROD_SEC.
1211 @year Unless specified, get the value of the current year. If array is smaller (e.g. because it is time-independent), get the last value.
1212 @freeDim_h If specified, look exactly for it, otherwise simply doesn't filter for it.
1213 
1214 */
1215 const double
1216 ModelData::getProdData(const string &type_h, const int& regId_h, const string &prodId_h, const int& year, const string &freeDim_h) {
1217 
1218  double value=0;
1219  vector <int> regIds;
1220  string key;
1221  DataMap::const_iterator p;
1222 
1223  bool found = false;
1224  vector <string> products;
1225  bool exactMatch=true;
1226 
1227  if(prodId_h == PROD_PRI){
1228  products = priProducts;
1229  } else if (prodId_h == PROD_SEC){
1230  products = secProducts;
1231  } else if (prodId_h == PROD_ALL || prodId_h == ""){
1232  products = allProducts;
1233  products.push_back("");
1234  } else {
1235  products.push_back(prodId_h);
1236  }
1237  if(freeDim_h=="") exactMatch=false;
1238 
1239  // Make sure to set the new value to all l2 regions if requested for a reg1 level
1240  if(getRegion(regId_h)->getRegLevel()==2){
1241  regIds.push_back(regId_h);
1242  } else if (getRegion(regId_h)->getRegLevel()==1) {
1243  for(uint i=0;i<getRegion(regId_h)->getNChildren();i++){
1244  regIds.push_back(getRegion(regId_h)->getChildren()[i]->getRegId());
1245  }
1246  } else {
1247  msgOut(MSG_CRITICAL_ERROR, "Error in setProdData(). Setting a value for the whole World is not supported.");
1248  }
1249  int regIdsS = regIds.size();
1250 
1251 
1252  for(uint r=0;r<regIdsS;r++){
1253  for(uint i=0;i<products.size();i++){
1254  key = makeKeyProdData(type_h,i2s(regIds[r]),products[i],freeDim_h);
1255  if (!exactMatch && key.size () > 0) key.resize (key.size () - 1); // bug 20140402, removing the last #
1256  value += dataMapGetValue(prodDataMap,key,year,exactMatch);
1257  if(tempBool) found = true;
1258  }
1259  }
1260 
1261  if(!found){
1262  valueFoundBool = false;
1263  msgOut(errorLevel, "Error in getProdData: no combination found for "+type_h+", "+i2s(regId_h)+", "+prodId_h+", "+i2s(year)+", "+freeDim_h+". Returning 0, but double check that this is ok for your model.");
1264  }
1265  return value;
1266 
1267 
1268 }
1269 
1270 /**
1271 Basic function to retrieve forest-related data.
1272 It addmits the following "filters":
1273 @type_h Name of the specific parameter requested
1274 @regId_h Look for a level1 or level2 region
1275 @forType_h If specified, look exactly for the specified forest type, otherwise accept the keyword FT_ALL for summing all of them
1276 @freeDim_h Normally used for diameter class, but occasionally used for other uses (changed 20140514). It accepts three keywords, for summing up all diameters, production-ready diameters or sub-production ones, namelly DIAM_ALL, DIAM_PROD, DIAM_FIRST.\\
1277 If a diameter-independed variable is required, put it in the data with an empty diameter class and retrieve it here using DIAM_ALL.
1278 @year Unless specified, get the value of the current year. If array is smaller (e.g. because it is time-independent), get the last value.
1279 */
1280 const double
1281 ModelData::getForData(const string &type_h, const int& regId_h, const string &forType_h, const string &freeDim_h, const int& year){
1282  vector<int> regIds;
1283  vector <string> dClasses;
1284  vector <string> fTypes;
1285  string key;
1286  DataMap::const_iterator p;
1287  bool found = false;
1288  double value = 0;
1289 
1290  // creating the arrays to look up if keywords were specified..
1291  if (forType_h == FT_ALL){ // || forType_h == ""){
1292  fTypes = getForTypeIds();
1293  fTypes.push_back("");
1294  } else {
1295  fTypes.push_back(forType_h);
1296  }
1297  if(freeDim_h == DIAM_ALL){ // || freeDim_h == ""){
1298  dClasses = diamClasses;
1299  dClasses.push_back("");
1300  } else if (freeDim_h == DIAM_PROD){
1301  dClasses = getDiameterClasses(true);
1302  } else if (freeDim_h == DIAM_FIRST){
1303  dClasses.push_back(diamClasses.at(0));
1304  } else {
1305  dClasses.push_back(freeDim_h);
1306  }
1307  // Make sure to set the new value to all l2 regions if requested for a reg1 level
1308  if(getRegion(regId_h)->getRegLevel()==2){
1309  regIds.push_back(regId_h);
1310  } else if (getRegion(regId_h)->getRegLevel()==1) {
1311  for(uint i=0;i<getRegion(regId_h)->getNChildren();i++){
1312  regIds.push_back(getRegion(regId_h)->getChildren()[i]->getRegId());
1313  }
1314  } else {
1315  msgOut(MSG_CRITICAL_ERROR, "Error in getProdData(). Setting a value for the whole World is not supported.");
1316  }
1317  int regIdsS = regIds.size();
1318 
1319  // getting the actual data...
1320  for(uint r=0;r< regIds.size();r++){
1321  for(uint i=0;i<dClasses.size();i++){
1322  for (uint y=0;y<fTypes.size();y++){
1323  key = makeKeyForData(type_h,i2s(regIds[r]),fTypes[y],dClasses[i]);
1324  value += dataMapGetValue(forDataMap,key,year,true);
1325  if(tempBool) found = true;
1326  }
1327  }
1328  }
1329 
1330  if(!found){
1331  valueFoundBool = false;
1332  msgOut(errorLevel, "Error in getForData(): no combination found for "+type_h+", "+i2s(regId_h)+", "+forType_h+", "+i2s(year)+", "+freeDim_h+". Returning 0, but double check that this is ok for your model.");
1333  }
1334  return value;
1335 }
1336 
1337 
1338 /**
1339 Basic function to set products-related data.
1340 It can change an existing value or extend in time a serie, but it requires the keys (par. name/regId/prodId/freedim) to be already present in the data.
1341 @value_h New value to change with/add
1342 It addmits the following "filters":
1343 @type_h Name of the specific parameter requested
1344 @regId_h Set a specific level 2 region, or all its childred l2 region if a reg1 level is specified.
1345 @prodId_h Product. It accept three keywords, for changing/inserting the new value to all products, primary products or secondary products, namelly PROD_ALL, PROD_PRI, PROD_SEC.
1346 @year Unless specified, set the value of the current year. If array is smaller (e.g. because it is time-independent) fill all the values till the requested one.
1347 @create If true, allow creation of new data if not found. Default false (rise an error)
1348 @freeDim_h If specified, look exactly for it, otherwise simply doesn't filter for it.
1349 
1350 */
1351 void
1352 ModelData::setProdData(const double& value_h, const string &type_h, const int& regId_h, const string &prodId_h, const int& year, const bool& allowCreate, const string &freeDim_h){
1353 
1354  vector<int> regIds;
1355  string key;
1356  DataMap::const_iterator p;
1357  vector <string> products;
1358 
1359  if(prodId_h == PROD_PRI){
1360  products = priProducts;
1361  } else if (prodId_h == PROD_SEC){
1362  products = secProducts;
1363  } else if (prodId_h == PROD_ALL){
1364  products = allProducts;
1365  } else {
1366  products.push_back(prodId_h);
1367  }
1368 
1369  // Make sure to set the new value to all l2 regions if requested fora reg1 level
1370  if(getRegion(regId_h)->getRegLevel()==2){
1371  regIds.push_back(regId_h);
1372  } else if (getRegion(regId_h)->getRegLevel()==1) {
1373  for(uint i=0;i<getRegion(regId_h)->getNChildren();i++){
1374  regIds.push_back(getRegion(regId_h)->getChildren()[i]->getRegId());
1375  }
1376  } else {
1377  msgOut(MSG_CRITICAL_ERROR, "Error in setProdData(). Setting a value for the whole World is not supported.");
1378  }
1379 
1380  bool found = false;
1381  bool tempFound = false;
1382 
1383  for(uint r=0;r< regIds.size();r++){
1384  for(uint i=0;i<products.size();i++){
1385  key = makeKeyProdData(type_h,i2s(regIds[r]),products[i],freeDim_h);
1386  tempFound = dataMapSetValue(prodDataMap,key,value_h, year,true);
1387  if(tempFound) found = true;
1388  }
1389  }
1390 
1391  if(!found){
1392  if(!allowCreate){
1393  msgOut(MSG_CRITICAL_ERROR, "Error in setProdData: no combination found for "+type_h+", "+i2s(regId_h)+", "+prodId_h+", "+i2s(year)+", "+freeDim_h+". You can allow new variables to be created using the \"allowCreate\" flag.");
1394  } else {
1395  for(uint r=0;r< regIds.size();r++){
1396  for(uint i=0;i<products.size();i++){
1397  key = makeKeyProdData(type_h,i2s(regIds[r]),products[i],freeDim_h);
1398  vector <double> values;
1399  setTimedData(value_h,values,year,MSG_NO_MSG);
1400  prodDataMap.insert(DataPair(key,values));
1401  }
1402  }
1403  }
1404  }
1405 
1406 }
1407 
1408 
1409 
1410 
1411 void
1412 ModelData::setForData(const double& value_h, const string &type_h, const int& regId_h, const string &forType_h, const string &freeDim_h, const int& year, const bool& allowCreate){
1413 
1414  vector<int> regIds;
1415  vector <string> dClasses;
1416  vector <string> fTypes;
1417  string key;
1418  DataMap::const_iterator p;
1419  bool found = false;
1420  bool tempFound = false;
1421 
1422  if (forType_h == FT_ALL){
1423  fTypes = getForTypeIds();
1424  } else {
1425  fTypes.push_back(forType_h);
1426  }
1427 
1428  if(freeDim_h == DIAM_ALL){
1429  dClasses = diamClasses;
1430  } else if (freeDim_h == DIAM_PROD){
1431  dClasses = getDiameterClasses(true);
1432  } else if (freeDim_h == DIAM_FIRST){
1433  dClasses.push_back(diamClasses.at(0));
1434  } else {
1435  dClasses.push_back(freeDim_h);
1436  }
1437 
1438  // Make sure to set the new value to all l2 regions if requested for a reg1 level
1439  if(getRegion(regId_h)->getRegLevel()==2){
1440  regIds.push_back(regId_h);
1441  } else if (getRegion(regId_h)->getRegLevel()==1) {
1442  for(uint i=0;i<getRegion(regId_h)->getNChildren();i++){
1443  regIds.push_back(getRegion(regId_h)->getChildren()[i]->getRegId());
1444  }
1445  } else {
1446  msgOut(MSG_CRITICAL_ERROR, "Error in setProdData(). Setting a value for the whole World is not supported.");
1447  }
1448  int regIdsS = regIds.size();
1449 
1450  for(uint r=0;r< regIds.size();r++){
1451  for(uint i=0;i<dClasses.size();i++){
1452  for (uint y=0;y<fTypes.size();y++){
1453  key = makeKeyForData(type_h,i2s(regIds[r]),fTypes[y],dClasses[i]);
1454  tempFound = dataMapSetValue(forDataMap,key,value_h, year,true);
1455  if(tempFound) found = true;
1456  }
1457  }
1458  }
1459 
1460  if(!found){
1461  if(!allowCreate){
1462  msgOut(MSG_CRITICAL_ERROR, "Error in setForData: no combination found for "+type_h+", "+i2s(regId_h)+", "+forType_h+", "+i2s(year)+", "+freeDim_h+". You can allow new variables to be created using the \"allowCreate\" flag.");
1463  } else {
1464  for(uint r=0;r< regIds.size();r++){
1465  for(uint i=0;i<dClasses.size();i++){
1466  for (uint y=0;y<fTypes.size();y++){
1467  key = makeKeyForData(type_h,i2s(regIds[r]),fTypes[y],dClasses[i]);
1468  vector <double> values;
1469  setTimedData(value_h,values,year,MSG_NO_MSG);
1470  forDataMap.insert(DataPair(key,values));
1471  }
1472  }
1473  }
1474  }
1475  }
1476 }
1477 
1478 
1479 double
1480 ModelData::getTimedData(const vector<double> &dated_vector, const int& year_h) const{
1481 
1482  int position;
1483  if(year_h==DATA_NOW){
1484  position = MTHREAD->SCD->getYear()-cached_initialYear;
1485  } else {
1486  position = year_h-cached_initialYear;
1487  }
1488 
1489  if(dated_vector.size() > position) {
1490  return dated_vector[position];
1491  } else if (dated_vector.size() > 0 ){
1492  // returning the last available value...
1493  return dated_vector[dated_vector.size()-1];
1494  } else {
1495  msgOut(MSG_CRITICAL_ERROR, "Error in getTimedData: requested value doesn't have any value, even on the first position(year)!");
1496  }
1497  return 0;
1498 }
1499 
1500 void
1501 ModelData::setTimedData(const double& value_h, vector<double> &dated_vector, const int& year_h, const int& MSG_LEVEL){
1502 
1503  int position;
1504  if(year_h==DATA_NOW){
1505  position = MTHREAD->SCD->getYear()-cached_initialYear;
1506  } else {
1507  position = year_h-cached_initialYear;
1508  }
1509 
1510  int originalVectorSize = dated_vector.size();
1511  if(dated_vector.size() > position) {
1512  dated_vector[position]=value_h;
1513  } else {
1514  // extending the vector and filling it with the incoming value, but issuing a warning if done for more than one year
1515 
1516  for(uint i=0;i<position-originalVectorSize+1;i++){
1517  dated_vector.push_back(value_h);
1518  }
1519  if(position-originalVectorSize > 0 ){
1520  msgOut(MSG_LEVEL, "setTimedData: a dated vector has been filled several years ("+i2s(1+position-originalVectorSize)+") with incoming values to reach desidered position in time.");
1521  }
1522  }
1523 }
1524 
1525 
1526 void
1528  msgOut(MSG_INFO, "Loading input files (this can take a few minutes)...");
1529  //QString iFile("data/ffsmInput.ods");
1530  QString iFile(MTHREAD->getInputFileName().c_str());
1531  //cout << "PIPPO !!!!! " << MTHREAD->getInputFileName().c_str() << endl;
1532 
1533  //std::random_device rd;
1534  //std::mt19937 localgen(rd());
1535  std::mt19937 localgen(time(0));
1536  std::uniform_int_distribution<> dis(10, 1000000);
1537  int randomNumber = dis(localgen);
1538 
1539  QString oDir((MTHREAD->getBaseDirectory()+"tempInput-"+MTHREAD->getScenarioName()+i2s(randomNumber)).c_str());
1540  string forDataCachedFilename = MTHREAD->getBaseDirectory()+"cachedInput/forData.csv";
1541  string prodDataCachedFilename = MTHREAD->getBaseDirectory()+"cachedInput/prodData.csv";
1542 
1543  // removing output directory if exist..
1544  QDir oQtDir(oDir);
1545 
1546  if(oQtDir.exists()){
1547  bool deleted;
1548  deleted = delDir(oDir);
1549  if(deleted){msgOut(MSG_DEBUG,"Correctly deleted old temporary data");}
1550  else {msgOut(MSG_WARNING, "I could not delete old temporary data dir (hopefully we'll overrite the input files)");}
1551  }
1552 
1553  if (!QFile::exists(iFile))
1554  {
1555  cout << "File does not exist." << endl << endl;
1556  //return false;
1557  }
1558  UnZip::ErrorCode ec;
1559  UnZip uz;
1560  ec = uz.openArchive(iFile);
1561  if (ec != UnZip::Ok) {
1562  //cout << "Failed to open archive: " << uz.formatError(ec).toAscii().data() << endl << endl; // Qt4
1563  cout << "Failed to open archive: " << uz.formatError(ec).toLatin1().data() << endl << endl; // Qt5
1564  //return false;
1565  }
1566  ec = uz.extractAll(oDir);
1567  if (ec != UnZip::Ok){
1568  //cout << "Extraction failed: " << uz.formatError(ec).toAscii().data() << endl << endl; // Qt4
1569  cout << "Extraction failed: " << uz.formatError(ec).toLatin1().data() << endl << endl; // Qt5
1570  uz.closeArchive();
1571  //return false;
1572  }
1573 
1574  // loading input file into memory...
1575  string inputXMLFileName = MTHREAD->getBaseDirectory()+"tempInput-"+MTHREAD->getScenarioName()+i2s(randomNumber)+"/content.xml";
1576  //string inputXMLFileName = MTHREAD->getBaseDirectory()+"test/content.xml";
1577  //cout << "inputXMLFileName: " << inputXMLFileName << endl;
1578  //mainDocument = new InputDocument();
1579  mainDocument.setWorkingFile(inputXMLFileName);
1580  //InputNode documentContent = mainDocument.getNodeByName("office:document-content");
1581  //InputNode documentBody = mainDocument.getNodeByName("office:body");
1582  //InputNode mainNode = mainDocument.getNodeByName("spreadsheet");
1583  //InputNode pippo = mainDocument.getNodeByName("pippo-pippo");
1584  //InputNode table = mainDocument.getNodeByName("table");
1585  //cout << "Test result: " << table.getStringContent() << endl;
1586 
1587 
1588  vector <InputNode> tables = mainDocument.getNodesByName("table");
1589  for(uint i=0;i<tables.size();i++){
1590  string tableName = tables[i].getStringAttributeByName("name");
1591  //cout <<tableName<<endl;
1592  if( (tableName == "forData" || tableName == "prodData") && QFile::exists(forDataCachedFilename.c_str()) ) {
1593  msgOut(MSG_INFO,"Attenction, using cached data (csv) for "+tableName);
1594  string fileName = MTHREAD->getBaseDirectory()+"cachedInput/"+tableName+".csv";
1595  LLDataVector.push_back(MTHREAD->MD->getTableFromFile(tableName, fileName));
1596  continue;
1597  }
1598  LLData data(MTHREAD,tables[i].getStringAttributeByName("name"));
1599  vector <InputNode> rows = tables[i].getNodesByName("table-row",MSG_NO_MSG,true);
1600  if(rows.size()<2) continue; //empty table or only with headers
1601  // building headers..
1602  vector <InputNode> cells = rows[0].getNodesByName("table-cell",MSG_NO_MSG,true);
1603  for (uint y=0; y<cells.size(); y++){
1604  int repeated = 1;
1605  if( cells[y].hasAttributeByName("number-columns-repeated")){
1606  repeated = cells[y].getIntAttributeByName("number-columns-repeated");
1607  }
1608  for (int q=0;q<repeated;q++){
1609  if( !cells[y].hasChildNode("p") ){
1610  data.headers.push_back(""); // empty header
1611  } else {
1612  data.headers.push_back(cells[y].getNodeByName("p",MSG_NO_MSG,true).getStringContent());
1613  }
1614  }
1615  }
1616  // loading data...
1617  for (uint j=1; j<rows.size();j++){
1618  //cout << j << endl;
1619  vector <InputNode> cells = rows[j].getNodesByName("table-cell",MSG_NO_MSG,true);
1620  //vector <InputNode> cells = rows[j].getChildNodes();
1621  if (cells.size()<1) continue;
1622  vector<string> record;
1623  // checking the first cell is not a comment nor is empty..
1624  int childCount = cells[0].getChildNodesCount();
1625  if (childCount == 0 || !cells[0].hasChildNode("p")) continue; // empty line, first column empty!
1626  string fistCol = cells[0].getNodeByName("p",MSG_NO_MSG,true).getStringContent();
1627  unsigned int z;
1628  z = fistCol.find("#");
1629  if( z!=string::npos && z == 0) continue; // found "#" on fist position, it's a comment!
1630  for (uint y=0; y<cells.size(); y++){
1631  int repeated = 1;
1632  if( cells[y].hasAttributeByName("number-columns-repeated")){
1633  repeated = cells[y].getIntAttributeByName("number-columns-repeated");
1634  }
1635  for (int q=0;q<repeated;q++){
1636  if( !cells[y].hasChildNode("p") ){
1637  record.push_back(""); // empty header
1638  } else {
1639  // changed 20120625 as for float values the content of p is the visualised value, not the full memorised one.
1640  // this is strange because tought I already tested it.. but maybe is changed the format??
1641  if(cells[y].getStringAttributeByName("value-type")=="float"){
1642  record.push_back(cells[y].getStringAttributeByName("value"));
1643  } else {
1644  record.push_back(cells[y].getNodeByName("p",MSG_NO_MSG,true).getStringContent());
1645  }
1646  }
1647  }
1648  }
1649  data.records.push_back(record);
1650  }
1651  data.clean();
1652  LLDataVector.push_back(data);
1653  }
1654 
1655  //debug !!!
1656  /*for (uint i=0; i<LLDataVector.size();i++){
1657  cout << "***************** NEW TABLE: " << LLDataVector[i].tableName << endl;
1658  //cout << "***** Headers: "<< endl;
1659  int headerSize = LLDataVector[i].headers.size();
1660  bool ok = true;
1661  cout << "Header size: " << headerSize << endl;
1662  //for (uint j=0; j<LLDataVector[i].headers.size();j++){
1663  // cout << "["<<j<<"] " << LLDataVector[i].headers[j] << endl;
1664  //}
1665  //cout << "***** Records: " << endl;
1666  for (uint j=0; j<LLDataVector[i].records.size();j++){
1667  //cout << "** Record "<<j<<":"<<endl;
1668  if(LLDataVector[i].records[j].size() != headerSize){
1669  cout << "There is a problem on record " << j <<"!"<< endl;
1670  cout << "His size is: "<< LLDataVector[i].records[j].size() << endl;
1671  ok = false;
1672  }
1673  //for (uint y=0; y<LLDataVector[i].records[j].size();y++){
1674  // cout << "["<<y<<"] " << LLDataVector[i].records[j][y] << endl;
1675  //}
1676  }
1677  if(!ok) {cout <<"Problems with this table :-( !"<<endl;}
1678  }*/
1679 
1680 
1681 
1682  // deleting output directory if exist...
1683  if(oQtDir.exists()){
1684  bool deleted;
1685  deleted = delDir(oDir);
1686  if(deleted){msgOut(MSG_DEBUG,"Correctly deleted old temporary data");}
1687  else {msgOut(MSG_WARNING, "I could not delete old temporary data dir (hopefully we'll overrite the input files)");}
1688  }
1689 }
1690 
1691 
1692 /*
1693 void
1694 ModelData::loadDataFromCache(string tablename){
1695  msgOut(MSG_INFO,"Attenction, using cached data (csv) for "+tablename);
1696  string fileName = MTHREAD->getBaseDirectory()+"cachedInput/"+tablename+".csv";
1697  QFile file(fileName.c_str());
1698  if (!file.open(QFile::ReadOnly)) {
1699  msgOut(MSG_ERROR, "Cannot open file "+fileName+" for reading.");
1700  }
1701  QTextStream in(&file);
1702  LLData data(MTHREAD, tablename);
1703  int countRow = 0;
1704  while (!in.atEnd()) {
1705  QString line = in.readLine();
1706  QStringList fields = line.split(';');
1707  if (countRow==0){ // building headers
1708  for(uint i =0;i<fields.size();i++){
1709  data.headers.push_back(fields.at(i).toStdString());
1710  }
1711  } else {
1712  vector<string> record ; //= fields.toVector().toStdVector();
1713  unsigned int z = fields[0].toStdString().find("#");
1714  if( z!=string::npos && z == 0) continue; // found "#" on fist position, it's a comment!
1715  for(uint i =0;i<fields.size();i++){
1716  string field = fields.at(i).toStdString();
1717  replace(field.begin(), field.end(), ',', '.');
1718  record.push_back(field);
1719  }
1720  data.records.push_back(record);
1721  }
1722  countRow++;
1723  }
1724  data.clean();
1725  LLDataVector.push_back(data);
1726 
1727 }
1728 */
1729 
1730 LLData
1731 ModelData::getTableFromFile(string tablename, string filename_h){
1732  string fileName = MTHREAD->getBaseDirectory()+filename_h;
1733  QFile file(fileName.c_str());
1734  if (!file.open(QFile::ReadOnly)) {
1735  msgOut(MSG_ERROR, "Cannot open file "+fileName+" for reading.");
1736  }
1737  QTextStream in(&file);
1738  LLData data(MTHREAD, tablename);
1739  int countRow = 0;
1740  while (!in.atEnd()) {
1741  QString line = in.readLine();
1742  if(line=="") continue; //skipping completelly empty lines, even without separators
1743  QStringList fields = line.split(';');
1744  bool emptyLine = true;
1745  if (countRow==0){ // building headers
1746  for(uint i =0;i<fields.size();i++){
1747  data.headers.push_back(fields.at(i).toStdString());
1748  }
1749  } else {
1750  vector<string> record ; //= fields.toVector().toStdVector();
1751  unsigned int z = fields[0].toStdString().find("#");
1752  if( z!=string::npos && z == 0) continue; // found "#" on fist position, it's a comment!
1753  for(uint i =0;i<fields.size();i++){
1754  string field = fields.at(i).toStdString();
1755  replace(field.begin(), field.end(), ',', '.');
1756  record.push_back(field);
1757  if(field!="") emptyLine = false;
1758  }
1759  if(!emptyLine){data.records.push_back(record);};
1760  }
1761  countRow++;
1762  }
1763  data.clean();
1764  return data;
1765 }
1766 
1767 
1768 bool
1769 ModelData::delDir(QString dirname) {
1770  bool deleted = false;
1771  QDir dir(dirname);
1772  //msgOut(MSG_DEBUG, dir.absolutePath().toStdString());
1773  dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks);
1774  QFileInfoList list = dir.entryInfoList();
1775  deleted = dir.rmdir(dir.absolutePath());
1776  if (deleted) return true;
1777 
1778  for (int i = 0; i < list.size(); ++i) {
1779  QFileInfo fileInfo = list.at(i);
1780  if (fileInfo.isFile()){
1781  //msgOut(MSG_DEBUG, "A file, gonna remove it: "+fileInfo.absoluteFilePath().toStdString());
1782  QFile targetFile(fileInfo.absoluteFilePath());
1783  bool fileDeleted = targetFile.remove();
1784  if (!fileDeleted){
1785  msgOut(MSG_CRITICAL_ERROR, "We have a problem: can't delete file "+fileInfo.absoluteFilePath().toStdString());
1786  }
1787  }
1788  else if (fileInfo.isDir()){
1789  //msgOut(MSG_DEBUG, "A directory, gonna go inside it: "+fileInfo.absoluteFilePath().toStdString());
1790  delDir(fileInfo.absoluteFilePath());
1791  dir.rmdir(fileInfo.absoluteFilePath());
1792  }
1793  }
1794 
1795  deleted = dir.rmdir(dir.absolutePath());
1796  if (deleted) return true;
1797  return false;
1798 }
1799 
1800 LLData
1801 ModelData::getTable(string tableName_h, int debugLevel){
1802  LLData toReturn(MTHREAD,"");
1803  for(uint i=0;i<LLDataVector.size();i++){
1804  if (LLDataVector[i].getTableName() == tableName_h)return LLDataVector[i];
1805  }
1806  msgOut(debugLevel,"No table found with name "+tableName_h);
1807  return toReturn;
1808 }
1809 
1810 
1811 bool
1812 ModelData::dataMapCheckExist(const DataMap& map, const string& search_for, const bool& exactMatch) const {
1813  /*int dummyYear=MTHREAD->SCD->getYear();
1814  if(dataMapGetValue(map, search_for, dummyYear, exactMatch)==DATA_ERROR) {
1815  return false;
1816  } else {
1817  return true;
1818  }
1819  return false;
1820 }*/
1821  bool found = false;
1822  DataMap::const_iterator i;
1823  if(!exactMatch){
1824  i = map.lower_bound(search_for);
1825  for(;i != map.end();i++){
1826  const string& key = i->first;
1827  if (key.compare(0, search_for.size(), search_for) == 0) {// Really a prefix?
1828  return true;
1829  } else {
1830  return false;
1831  }
1832  }
1833  } else {
1834  i = map.find(search_for);
1835  if (i!=map.end()){
1836  return true;
1837  }
1838  }
1839  return false;
1840 }
1841 
1842 
1843 double
1844 ModelData::dataMapGetValue(const DataMap& map, const string& search_for, const int& year_h, const bool& exactMatch) {
1845  double toReturn = 0;
1846  tempBool = false;
1847  DataMap::const_iterator i;
1848  if(!exactMatch){
1849  i = map.lower_bound(search_for);
1850  for(;i != map.end();i++){
1851  const string& key = i->first;
1852  if (key.compare(0, search_for.size(), search_for) == 0) {// Really a prefix?
1853  tempBool = true;
1854  toReturn += getTimedData( i->second, year_h );
1855  } else {
1856  break;
1857  }
1858  }
1859  } else {
1860  i = map.find(search_for);
1861  if (i!=map.end()){
1862  tempBool = true;
1863  return getTimedData( i->second, year_h );
1864  }
1865  }
1866  return toReturn;
1867 }
1868 
1869 
1870 
1871 int
1872 ModelData::dataMapSetValue( DataMap& map, const string& search_for, const double& value_h, const int& year_h, const bool& exactMatch){
1873  bool found = false;
1874  DataMap::iterator i;
1875  if(!exactMatch){
1876  i = map.lower_bound(search_for);
1877  for(;i != map.end();i++){
1878  const string& key = i->first;
1879  if (key.compare(0, search_for.size(), search_for) == 0) {// Really a prefix?
1880  found = true;
1881  setTimedData(value_h, i->second, year_h);
1882  } else {
1883  break;
1884  }
1885  }
1886  } else {
1887  i = map.find(search_for);
1888  if (i!=map.end()){
1889  found = true;
1890  setTimedData(value_h, i->second, year_h, errorLevel);
1891  }
1892  }
1893  // removed 20120903 as the insertion of new values must be explicitly done, not in all cases we want a new insertion
1894  /*if(!found){
1895  vector < double> newValues;
1896  setTimedData(value_h, newValues, year_h, MSG_NO_MSG); // don't warning if we are making a multi-year value vector, as it is a new one
1897  map.insert(DataPair (search_for,newValues));
1898  }*/
1899  return found;
1900 }
1901 
1902 void
1903 ModelData::unpackKeyProdData(const string& key, string& parName, int& regId, string& prod, string& freeDim) const{
1904 
1905  int parNameDelimiter = key.find("#",0);
1906  int regIdDelimiter = key.find("#",parNameDelimiter+1);
1907  int prodDelimiter = key.find("#",regIdDelimiter+1);
1908  int freeDimDelimiter = key.find("#",prodDelimiter+1);
1909  if (freeDimDelimiter == string::npos){
1910  msgOut(MSG_CRITICAL_ERROR, "Error in unpacking a key in the map of production data.");
1911  }
1912  parName.assign(key,0,parNameDelimiter);
1913  string regIdString="";
1914  regIdString.assign(key,parNameDelimiter+1,regIdDelimiter-parNameDelimiter-1);
1915  regId = s2i(regIdString);
1916  prod.assign(key,regIdDelimiter+1,prodDelimiter-regIdDelimiter-1);
1917  freeDim.assign(key,prodDelimiter+1,freeDimDelimiter-prodDelimiter-1);
1918 
1919 }
1920 
1921 void
1922 ModelData::unpackKeyForData(const string& key, string& parName, int &regId, string& forType, string& diamClass) const{
1923  int parNameDelimiter = key.find("#",0);
1924  int regIdDelimiter = key.find("#",parNameDelimiter+1);
1925  int forTypeDelimiter = key.find("#",regIdDelimiter+1);
1926  int diamClassDelimiter = key.find("#",forTypeDelimiter+1);
1927  if (diamClassDelimiter == string::npos){
1928  msgOut(MSG_CRITICAL_ERROR, "Error in unpacking a key in the map of production data.");
1929  }
1930  parName.assign(key,0,parNameDelimiter);
1931  string regIdString="";
1932  regIdString.assign(key,parNameDelimiter+1,regIdDelimiter-parNameDelimiter-1);
1933  regId = s2i(regIdString);
1934  forType.assign(key,regIdDelimiter+1,forTypeDelimiter-regIdDelimiter-1);
1935  diamClass.assign(key,forTypeDelimiter+1,diamClassDelimiter-forTypeDelimiter-1);
1936 
1937 }
1938 
1939 
1940 /**
1941 calculating the discount factor
1942 
1943 Revenues at years n will be transforemed as average year rate as
1944 
1945 av.y.rev = rev(n)/ ( (1+ir)^(n-1)+(1+ir)^(n-2)+(1+ir)^(n-3)+...+(1+ir)^(n-n) )
1946 
1947 Objective is to have the present value of the final harvest (A) equal to the sum pf the present values of yearly activities (B):
1948 
1949 \image html diagram_calculateAnnualisedEquivalent.png "Comparing present values" width=10cm
1950 
1951 \f[ PV(A) = SUM(PV(B) \f]
1952 \f[ A/(1+r)^n = B/(1+r)^1 + B/(1+r)^2 + … + B/(1+r)^n \f]
1953 \f[ A/(1+r)^n = B * ( 1/(1+r)^1 + 1/(1+r)^2 + … + 1/(1+r)^n ) \f]
1954 \f[ A/(1+r)^n = B * ( (1+r)^(n-1) + (1+r)^(n-2) + … + (1+r)^(n-n) ) \f]
1955 \f[ B = A / ( (1+r)^(n-1) + (1+r)^(n-2) + … + (1+r)^(n-n) ) \f]
1956 
1957 20131204. Changed for the equivalent but simpler eai = rev(t)*i / ((1+i)^t-1)
1958 
1959 */
1960 double
1961 ModelData::calculateAnnualisedEquivalent(const double& amount_h, const int& years_h, const double& ir) const {
1962  // modified and tested 20120912. Before it was running this formula instead:
1963  // av.y.rev = rev(n)/ ( (1+ir)^1+(1+ir)^2+(1+ir)^3+...+(1+ir)^n )
1964  // the difference is that in this way the annual equivalent that is calulated doesn't need to be further discounted for yearly activites (e.g. agric)
1965 
1966  //loop(fy$(ord(fy)=1),
1967  // df(fy)= (1+ir)**(ord(fy));
1968  //);
1969  //loop(fy$(ord(fy)>1),
1970  // df(fy)=df(fy-1)+(1+ir)**(ord(fy));
1971  //);
1972  if(years_h<0) return 0.;
1973  if(years_h==0) return amount_h;
1974  //double ir = getDoubleSetting("ir",DATA_NOW);
1975  double eai = amount_h * ir / (pow(1.0+ir,years_h)-1.0);
1976 
1977  return eai;
1978 
1979  /*
1980  vector <double> df_by;
1981  for(int y=0;y<years_h;y++){
1982  double df;
1983  if(y==0){
1984  df = pow((1+ir),y);
1985  } else {
1986  df = df_by.at(y-1)+pow((1+ir),y);
1987  }
1988  if (y==years_h-1) {
1989  cout << eai << " " << amount_h/df << endl;
1990  return amount_h/df; // big bug 20120904
1991  }
1992  df_by.push_back(df);
1993  }
1994  exit(1);
1995  return 0; // never reached, just to avoid compilation warnings
1996  */
1997 }
1998 
1999 double
2000 ModelData::calculateAnnualisedEquivalent(const double& amount_h, const double& years_h, const double& ir) const{
2001  //ceil(x) DNLP returns the smallest integer number greater than or equal to x
2002  //loop( (u,i,lambda,essence),
2003  // cumTp(u,i,lambda,essence) = ceil(cumTp(u,i,lambda,essence));
2004  //);
2005  int ceiledYear = ceil(years_h);
2006  return calculateAnnualisedEquivalent(amount_h, ceiledYear, ir);
2007 }
2008 
2009 /** Get a list of files in a directory */
2010 int
2011 ModelData::getFilenamesByDir (const string & dir, vector<string> &files, const string & filter){
2012  DIR *dp;
2013  struct dirent *dirp;
2014  if((dp = opendir(dir.c_str())) == NULL) {
2015  msgOut(MSG_ERROR, "Error " + i2s(errno) + " opening the " + dir + " directory.");
2016  //cout << "Error(" << errno << ") opening " << dir << endl;
2017  return errno;
2018  }
2019  while ((dirp = readdir(dp)) != NULL) {
2020  string filename = dirp->d_name;
2021  if(
2022  (filter != "" && filename.substr(filename.find_last_of(".")) == filter) // there is a filter and the last bit of the filename match the filter
2023  || (filter == "" && filename.substr(filename.find_last_of(".") + 1) != "") // there isn't any filter but we don't want stuff like ".." or "."
2024  ) {
2025  files.push_back(string(dirp->d_name));
2026  }
2027  }
2028  closedir(dp);
2029  return 0;
2030 }
2031 
2032 
2033 vector<pathRule*>
2034 ModelData::getPathMortalityRule(const string& forType, const string& dC){
2035  vector<pathRule*> toReturn;
2036  for(uint i=0;i<pathRules.size();i++){
2037  if(pathRules[i].forType == forType && pathRules[i].dClass == dC){
2038  toReturn.push_back(&pathRules[i]);
2039  }
2040  }
2041  return toReturn;
2042 }
2043 
2044 /**
2045  * @brief ModelData::createCombinationsVector
2046  * Return a vector containing any possible combination of nItems items (including all subsets).
2047  *
2048  * For example with nItems = 3:
2049  * 0: []; 1: [0]; 2: [1]; 3: [0,1]; 4: [2]; 5: [0,2]; 6: [1,2]; 7: [0,1,2]
2050 
2051  * @param nItems number of items to create p
2052  * @return A vector with in each slot the items present in that specific combination subset.
2053  */
2054 vector < vector <int> >
2056  // Not confuse combination with permutation where order matter. Here it doesn't matter, as much as the algorithm is the same and returns
2057  // to as each position always the same subset
2058  vector < vector <int> > toReturn;
2059  int nCombs = pow(2,nItems);
2060  //int nCombs = nItems;
2061  for (uint i=0; i<nCombs; i++){
2062  vector<int> thisCombItems; //concernedPriProducts;
2063  for(uint j=0;j<nItems;j++){
2064  uint j2 = pow(2,j);
2065  if(i & j2){ // bit a bit operator, p217 C++ book
2066  thisCombItems.push_back(j);
2067  }
2068  }
2069  toReturn.push_back(thisCombItems);
2070  }
2071  return toReturn;
2072 }
2073 
2074 
2075 double
2076 ModelData::getAvailableDeathTimber(const vector<string> &primProd_h, int regId_h, int year_h){
2077  if (!getBoolSetting("useDeathTimber",DATA_NOW)) return 0;
2078  double toReturn = 0.0;
2079  vector <string> forTypesIds = getForTypeIds();
2080  for (uint i=0;i<forTypesIds.size();i++){
2081  string ft = forTypesIds[i];
2082  for(uint u=0;u<diamClasses.size();u++){
2083  string dc = diamClasses[u];
2084  bool possible = false;
2085  int maxYears = 0;
2086  for (int p=0; p<primProd_h.size();p++){
2087  string primProd = primProd_h[p];
2088  if(assessProdPossibility(primProd,ft, dc)){
2089  possible = true;
2090  maxYears=max(maxYears,getMaxYearUsableDeathTimber(primProd, ft, dc));
2091  }
2092  }
2093  if(possible){
2094  for(int y=year_h;y>year_h-maxYears;y--){
2095  iisskey key(y,regId_h,ft,dc);
2096  toReturn += findMap(deathTimberInventory,key,MSG_NO_MSG,0.0);
2097  }
2098  }
2099  }
2100  }
2101  return toReturn;
2102 }
2103 
2104 vector <int>
2105 ModelData::getAllocableProductIdsFromDeathTimber(const int &regId_h, const string &ft, const string &dc, const int &harvesting_year, int request_year){
2106  vector<int> allocableProductIds;
2107  if (!getBoolSetting("useDeathTimber",DATA_NOW)) return allocableProductIds;
2108  if (request_year == DATA_NOW) request_year = MTHREAD->SCD->getYear();
2109  for(uint p=0;p<priProducts.size();p++){
2110  string primProd = priProducts[p];
2111  if(assessProdPossibility(primProd,ft, dc)){
2112  int maxYears = getMaxYearUsableDeathTimber(primProd, ft, dc);
2113  if (request_year-harvesting_year < maxYears){
2114  allocableProductIds.push_back(p);
2115  }
2116  }
2117  }
2118  return allocableProductIds;
2119 }
2120 
2121 
2122 
2123 double
2124 ModelData::getAvailableAliveTimber(const vector<string> &primProd_h, int regId_h){
2125  double toReturn = 0.0;
2126  ModelRegion* REG = MTHREAD->MD->getRegion(regId_h);
2127  vector <Pixel*> regPx = REG->getMyPixels();
2128  vector <string> forTypesIds = getForTypeIds();
2129  for (uint i=0;i<forTypesIds.size();i++){
2130  string ft = forTypesIds[i];
2131  for(uint u=0;u<diamClasses.size();u++){
2132  string dc = diamClasses[u];
2133  bool possible = false;
2134  for (int p=0; p<primProd_h.size();p++){
2135  string primProd = primProd_h[p];
2136  if(assessProdPossibility(primProd,ft, dc)){
2137  possible = true;
2138  }
2139  }
2140  if(possible){
2141  for (uint p=0;p<regPx.size();p++){
2142  Pixel* px = regPx[p];
2143  toReturn += px->vol_l.at(i).at(u)*px->avalCoef.at(i);
2144  }
2145  }
2146  }
2147  }
2148  return toReturn;
2149 }
2150 
2151 // ========================== LLData =======================================
2152 
2153 LLData::LLData(ThreadManager* MTHREAD_h, string tableName_h){
2154  MTHREAD = MTHREAD_h;
2155  tableName = tableName_h;
2156 }
2157 
2159 
2160 }
2161 
2162 void
2164 
2165  //checking the size is correct...
2166  int hsize = headers.size();
2167  for (uint i=0;i<records.size();i++){
2168  if(records[i].size() != hsize){
2169  vector <string> record = records[i];
2170  msgOut(MSG_CRITICAL_ERROR,"Error in the input reading table "+tableName+". Record "+i2s(i)+" has "+i2s(records[i].size())+" fields instead of "+i2s(hsize)+".");
2171  }
2172  }
2173  //cleaning empty-header columns...
2174  for (int i=headers.size()-1;i>=0;i--){
2175  if(headers[i] == ""){
2176  headers.erase(headers.begin()+i);
2177  for (uint j=0;j<records.size();j++){
2178  records[j].erase(records[j].begin()+i);
2179  }
2180  }
2181  }
2182 
2183 }
2184 
2185 string
2186 LLData::getData(const int &pos_h, const string &header_h, const int &debugLevel) const{
2187 
2188  if (records.size()<= pos_h){
2189  msgOut(debugLevel, "Requested position "+i2s(pos_h)+" too high! Not enought records !!");
2190  return "";
2191  }
2192  int hsize = headers.size();
2193  for (uint i=0;i<hsize;i++){
2194  if(headers[i] == header_h) return records[pos_h][i];
2195  }
2196  msgOut(debugLevel, "Header string "+header_h+" not found!");
2197  return "";
2198 }
string comment
Definition: ModelData.h:273
Class to provide a simple integer-integer-string-string key in std maps.
Definition: BaseClass.h:213
string dClass
Definition: ModelData.h:283
Print an ERROR message, but don&#39;t stop the model.
Definition: BaseClass.h:61
The required data is for the current year.
Definition: BaseClass.h:73
vector< int > getAllocableProductIdsFromDeathTimber(const int &regId_h, const string &ft, const string &dc, const int &harvesting_year, int request_year=DATA_NOW)
Returns the ids of the primary products that is possible to obtain using the timber recorded death in...
Definition: ModelData.cpp:2105
int getType(const string &type_h) const
Return a type according to enum TYPE_* from a string (eg: "string" -> TYPE_STRING (2)) ...
Definition: BaseClass.cpp:310
int errorLevel
Definition: ModelData.h:244
InputNode mainDocument
For each agricultural soil type (as defined in the setting "agrLandTypes") this list define the objec...
Definition: ModelData.h:243
string forLabel
Definition: ModelData.h:295
int getIntSetting(const string &name_h, int position=0, int reg=WORLD) const
Definition: ModelData.cpp:1105
void setDefaultPathogenRules()
Definition: ModelData.cpp:678
bool tempBool
a temporary bool variable used for various functions
Definition: ModelData.h:239
vector< string > getForTypeParents()
Definition: ModelData.cpp:122
bool setWorkingFile(std::string filename_h)
Load the file on memory. Return false if no success.
Definition: InputNode.cpp:37
void setDefaultForData()
Definition: ModelData.cpp:481
bool getBoolSetting(const string &name_h, int position=0, int reg=WORLD) const
Definition: ModelData.cpp:1117
#define DIAM_FIRST
First diameter class (NOT used for production)
Definition: BaseClass.h:163
ErrorCode extractAll(const QString &dirname, ExtractionOptions options=ExtractPaths)
Definition: unzip.cpp:325
void setScenarioProdData()
Definition: ModelData.cpp:561
Do not actually output any message.
Definition: BaseClass.h:57
string pathId
Pathogen id (name)
Definition: ModelData.h:321
vector< vector< int > > createCombinationsVector(const int &nItems)
Return a vector containing any possible combination of nItems items (including any possible subset)...
Definition: ModelData.cpp:2055
ErrorCode
Definition: unzip.h:48
The required data is a string.
Definition: BaseClass.h:68
Forest types (struct)
Definition: ModelData.h:293
string i2s(const int &int_h) const
integer to string conversion
Definition: BaseClass.cpp:219
IO production matrix between the forest resources and the primary products (struct) ...
Definition: ModelData.h:306
ThreadManager * MTHREAD
Pointer to the Thread manager.
Definition: BaseClass.h:467
vector< reclRule > reclRules
Vector of reclassification rules.
Definition: ModelData.h:227
double getAvailableDeathTimber(const vector< string > &primProd_h, int regId_h, int year_h)
Returns the timber available for a given set of primary products as stored in the deathTimberInventor...
Definition: ModelData.cpp:2076
double calculateAnnualisedEquivalent(const double &amount_h, const int &years_h, const double &ir) const
Calculate the annual equivalent flow.
Definition: ModelData.cpp:1961
ModelData * MD
the model data object
Definition: ThreadManager.h:72
void closeArchive()
Definition: unzip.cpp:226
double pres_min
Minimum level of presence of the pathogen to be counted as present (tolerance threshold) ...
Definition: ModelData.h:322
int memType
Definition: ModelData.h:296
vector< string > headers
Definition: ModelData.h:344
void clean()
Definition: ModelData.cpp:2163
Request something that is not region-specific.
Definition: BaseClass.h:80
int nrecords()
Definition: ModelData.h:336
vector< LLData > LLDataVector
Vector of Low Level Data.
Definition: ModelData.h:223
The required data is a bool.
Definition: BaseClass.h:69
vector< double > avalCoef
Availability (of wood resources) coefficient. A [0,1] coefficient (new: by forest type) that reduces ...
Definition: Pixel.h:148
Basic data units (struct)
Definition: ModelData.h:267
string forTypeOut
Definition: ModelData.h:309
double getAvailableAliveTimber(const vector< string > &primProd_h, int regId_h)
Returns the timber available for a given set of primary products as stored in the px->vol_l vector...
Definition: ModelData.cpp:2124
#define PROD_SEC
Secondary products.
Definition: BaseClass.h:154
Scheduler * SCD
the scheduler object (simulation-loops scheduler)
Definition: ThreadManager.h:75
vector< vector< double > > vol_l
store the volumes of the previous year
Definition: Pixel.h:129
void msgOut(const int &msgCode_h, const string &msg_h, const bool &refreshGUI_h=true) const
Overloaded function to print the output log.
Definition: BaseClass.cpp:50
string id
Definition: ModelData.h:61
void setDefaultSettings()
Definition: ModelData.cpp:194
Thread manager. Responsable to manage the main thread and "speak" with the GUI.
Definition: ThreadManager.h:65
vector< string > getStringVectorSetting(const string &name_h, int reg=WORLD) const
Definition: ModelData.cpp:1129
vector< double > mortCoefficents
Mortality coefficients ordered by number of presence of the pathogen, e.g. first value is the mortali...
Definition: ModelData.h:323
double dataMapGetValue(const DataMap &map, const string &search_for, const int &year_h, const bool &exactMatch=true)
Definition: ModelData.cpp:1844
map< string, vector< double > > prodDataMap
Product data.
Definition: ModelData.h:218
string forDataTable
Definition: ModelData.h:65
void unpackKeyProdData(const string &key, string &parName, int &regId, string &prod, string &freeDim) const
Definition: ModelData.cpp:1903
void setScenarioForData()
Definition: ModelData.cpp:500
string longDesc
Definition: ModelData.h:63
bool dataMapCheckExist(const DataMap &map, const string &search_for, const bool &exactMatch=true) const
Definition: ModelData.cpp:1812
string forTypeIn
Definition: ModelData.h:308
vector< IFiles > iFilesVector
List of all input files. Simple (struct)
Definition: ModelData.h:221
vector< int > getForTypeChilds_pos(const string &forTypeId_h, bool all=false)
Definition: ModelData.cpp:109
string ereditatedFrom
Definition: ModelData.h:298
int dataMapSetValue(DataMap &map, const string &search_for, const double &value_h, const int &year_h, const bool &exactMatch=true)
Definition: ModelData.cpp:1872
int maxYears
The maximum year for a tree collapse that this product can be harvested from. E.g. a 0 value means it can be obtained only from live trees, a 5 years value mean it can be obtained from trees death no longer than 5 years ago.
Definition: ModelData.h:285
string getStringSetting(const string &name_h, int position=0, int reg=WORLD) const
Definition: ModelData.cpp:1113
vector< pathRule * > getPathMortalityRule(const string &forType, const string &dC)
Return the pathogen mortality rule(s) associated with a given ft and dc (plural as more than a single...
Definition: ModelData.cpp:2034
void addSetting(string name_h, vector< string > values_h, int type_h, string comment_h)
Definition: ModelData.cpp:281
const double getProdData(const string &type_h, const int &regId_h, const string &prodId_h, const int &year=DATA_NOW, const string &freeDim_h="")
Definition: ModelData.cpp:1216
void setOutputDirName(string outputDirname_h)
int getNForTypesChilds(const string &forTypeId_h)
Definition: ModelData.cpp:135
string forType
Definition: ModelData.h:319
vector< bool > getBoolVectorSetting(const string &name_h, int reg=WORLD) const
Definition: ModelData.cpp:1133
Print an error message and stop the model.
Definition: BaseClass.h:62
void loadInput()
Unzip the OpenOffice input file (NEW 2008.05.13)
Definition: ModelData.cpp:1527
#define DIAM_PROD
Diameter classes used for production (e.g. excluded the first one)
Definition: BaseClass.h:160
vector< string > getVectorBaseData(const string &name_h, int type_h, int regId_h=WORLD)
Definition: ModelData.cpp:1073
string prodDataTable
Definition: ModelData.h:66
string shortDesc
Definition: ModelData.h:62
const double getForData(const string &type_h, const int &regId_h, const string &forType_h, const string &freeDim_h, const int &year=DATA_NOW)
Definition: ModelData.cpp:1281
vector< double > getDoubleVectorSetting(const string &name_h, int reg=WORLD) const
Definition: ModelData.cpp:1125
void setProdData(const double &value_h, const string &type_h, const int &regId_h, const string &prodId_h, const int &year=DATA_NOW, const bool &allowCreate=false, const string &freeDim_h="")
Definition: ModelData.cpp:1352
vector< string > getDiameterClasses(bool productionOnly=false)
Definition: ModelData.cpp:1191
int getYear()
Definition: Scheduler.h:49
PKZip 2.0 file decompression. Compatibility with later versions is not ensured as they may use unsupp...
Definition: unzip.h:45
double getTimedData(const vector< double > &dated_vector, const int &year_h) const
Return the value for the specified year in a timelly ordered vector, taking the last value if this is...
Definition: ModelData.cpp:1480
Pixel-level class.
Definition: Pixel.h:47
string baseDirectory
Definition: ModelData.h:215
LLData getTable(string tableName_h, int debugLevel=MSG_CRITICAL_ERROR)
Definition: ModelData.cpp:1801
vector< string > priProducts
Definition: ModelData.h:235
void applyDebugMode()
Works only a specified subset of regions and products.
Definition: ModelData.cpp:957
int getNChildren(bool excludeResidual=true)
Definition: ModelRegion.cpp:69
void applyOverrides()
Cancel all reg1 level data and trasform them in reg2 level if not already existing.
Definition: ModelData.cpp:749
string getBaseData(const string &name_h, int type_h, int position=0, int regId_h=WORLD)
Definition: ModelData.cpp:1015
Print a debug message, normally filtered out.
Definition: BaseClass.h:58
bool inVector(const K &element, const vector< K > &v)
Definition: BaseClass.h:429
#define FT_ALL
All forest types.
Definition: BaseClass.h:166
The required data is a double.
Definition: BaseClass.h:67
string forTypeId
Definition: ModelData.h:294
Print a WARNING message.
Definition: BaseClass.h:60
string getForTypeParentId(const string &forTypeId_h)
Definition: ModelData.cpp:90
void setScenarioProductResourceMatrixLink()
Definition: ModelData.cpp:632
vector< pathRule > pathRules
Vector of pathogen rules.
Definition: ModelData.h:228
vector< string > getForTypeIds(bool all=false)
By default it doesn&#39;t return forTypes used only as input.
Definition: ModelData.cpp:430
string getFilenameByType(string type_h)
Definition: ModelData.cpp:1175
int regId
Definition: ModelData.h:272
string getScenarioName()
V findMap(const map< K, V > &mymap, const K &key, const int &error_level=MSG_CRITICAL_ERROR, const V &notFoundValue=numeric_limits< V >::min()) const
Lookup a map for a value. Return the value starting from the key.
Definition: BaseClass.h:286
vector< string > secProducts
Definition: ModelData.h:236
int nheaders()
Definition: ModelData.h:337
int regSName2RegId(const string &regSName_h) const
Definition: ModelData.cpp:414
QString formatError(UnZip::ErrorCode c) const
Definition: unzip.cpp:241
string forLayer
Definition: ModelData.h:297
void setTimedData(const double &value_h, vector< double > &dated_vector, const int &year_h, const int &MSG_LEVEL=MSG_WARNING)
Definition: ModelData.cpp:1501
LLData(ThreadManager *MTHREAD_h, string tableName_h)
Definition: ModelData.cpp:2153
int type
Definition: ModelData.h:271
string forToProdTable
Definition: ModelData.h:67
string outputDirname
Definition: ModelData.h:214
string makeKeyForData(const string &parName, const string &regId, const string &forType, const string &diamClass) const
Definition: ModelData.h:173
int getForTypeCounter(string &forTypeId_h, bool all=false)
By default it doesn&#39;t return forTypes used only as input.
Definition: ModelData.cpp:81
void cacheSettings()
Called after input reading, it fix frequently used data;.
Definition: ModelData.cpp:305
bool valueFoundBool
a bool used in getForData() and getProdData() to communicate they didn&#39;t found a variable ...
Definition: ModelData.h:240
vector< string > getScenarios()
Definition: ModelData.cpp:146
#define PROD_ALL
All primary and transformed products.
Definition: BaseClass.h:148
bool regionExist(const int &regId_h) const
Definition: ModelData.cpp:356
int getScenarioIndex()
Definition: ModelData.cpp:157
string settingTable
Definition: ModelData.h:64
void setReclassificationRules()
Definition: ModelData.cpp:663
string settingFile
Definition: ModelData.h:69
bool delDir(QString dirname)
Recursivelly delete a directory.
Definition: ModelData.cpp:1769
map< string, vector< double > > DataMap
Definition: ModelData.cpp:56
vector< int > getIntVectorSetting(const string &name_h, int reg=WORLD) const
Definition: ModelData.cpp:1121
int cached_initialYear
Definition: ModelData.h:234
string getInputFileName()
Definition: ThreadManager.h:99
vector< forToProd > forToProdVector
Vector of coefficients from forest resources to primary products.
Definition: ModelData.h:219
ModelData(ThreadManager *MTHREAD_h)
Definition: ModelData.cpp:61
vector< int > getRegionIds(int level_h, bool excludeResidual=true)
Definition: ModelData.cpp:366
string name
Definition: ModelData.h:268
int regId
Definition: ModelData.h:307
Pathogen rule (how pathogen presense influence mortality) for a given forest type and diameter class ...
Definition: ModelData.h:318
void setForestTypes()
Definition: ModelData.cpp:648
double getDoubleSetting(const string &name_h, int position=0, int reg=WORLD) const
Definition: ModelData.cpp:1109
vector< InputNode > getNodesByName(string nodeName_h, int debugLevel=MSG_WARNING, bool childFlag=false)
Definition: InputNode.cpp:155
#define PROD_PRI
Primary products.
Definition: BaseClass.h:151
int s2i(const string &string_h) const
string to integer conversion
Definition: BaseClass.cpp:149
string dClass
Definition: ModelData.h:320
double coeff
Definition: ModelData.h:310
vector< ModelRegion * > getChildren(bool excludeResidual=true)
Returns a pointer to the parent regions.
Definition: ModelRegion.cpp:55
The required data is an integer.
Definition: BaseClass.h:66
ErrorCode openArchive(const QString &filename)
Definition: unzip.cpp:190
string pathTable
Definition: ModelData.h:68
string getRegSName() const
Definition: ModelRegion.h:67
vector< string > allProducts
Definition: ModelData.h:237
void setForData(const double &value_h, const string &type_h, const int &regId_h, const string &forType_h, const string &freeDim_h, const int &year=DATA_NOW, const bool &allowCreate=false)
Definition: ModelData.cpp:1412
string getData(const int &pos_h, const string &header_h, const int &debugLevel=MSG_CRITICAL_ERROR) const
Definition: ModelData.cpp:2186
string forType
Definition: ModelData.h:282
vector< ModelRegion > regionsVector
Vector of modelled regions.
Definition: ModelData.h:224
int getIteration()
Definition: Scheduler.h:48
string getBaseDirectory()
Definition: ThreadManager.h:98
pair< string, vector< double > > DataPair
Definition: ModelData.cpp:57
string product
Definition: ModelData.h:281
vector< string > values
Values are stored as "string" because we don&#39;t yet know at this point if they are string...
Definition: ModelData.h:270
void setScenarioSettings()
Definition: ModelData.cpp:224
vector< Pixel * > getMyPixels()
Definition: ModelRegion.h:86
Print an INFO message.
Definition: BaseClass.h:59
bool s2b(const string &string_h) const
string to bool conversion
Definition: BaseClass.cpp:208
ModelRegion * getRegion(int regId_h)
Definition: ModelData.cpp:346
vector< BasicData > programSettingsVector
Setting data. Simple (struct)
Definition: ModelData.h:222
string makeKeyProdData(const string &parName, const string &regId, const string &prod, const string &freeDim="") const
Definition: ModelData.h:172
const int getMaxYearUsableDeathTimber()
Definition: ModelData.cpp:456
void unpackKeyForData(const string &key, string &parName, int &regId, string &forType, string &diamClass) const
Definition: ModelData.cpp:1922
#define DIAM_ALL
All diameter classes.
Definition: BaseClass.h:157
LLData getTableFromFile(string tablename, string filename_h)
Load and return a data table from a file (instead that from a spreadsheet sheet)
Definition: ModelData.cpp:1731
double s2d(const string &string_h) const
string to double conversion
Definition: BaseClass.cpp:171
void createRegions()
Definition: ModelData.cpp:317
vector< forType > forTypes
Vector of forest types.
Definition: ModelData.h:226
vector< string > getForTypeChilds(const string &forTypeId_h)
Definition: ModelData.cpp:98
void setDefaultProductResourceMatrixLink()
Definition: ModelData.cpp:618
int getFilenamesByDir(const string &dir, vector< string > &files, const string &filter="")
Return a list of files in a directory.
Definition: ModelData.cpp:2011
const bool assessProdPossibility(const string &prod_h, const string &forType_h, const string &dClass_h)
A simple function to assess if a specified product can be made by a certain forest type and diameter ...
Definition: ModelData.cpp:441
vector< ModelRegion * > getAllRegions(bool excludeResidual=true)
Definition: ModelData.cpp:379
void setScenarioPathogenRules()
Definition: ModelData.cpp:706
void setScenarioData()
Set the infos about this scenario (long description and overriding tables)
Definition: ModelData.cpp:170
void setDefaultProdData()
Definition: ModelData.cpp:531
IO production matrix between the forest resources and the primary products (struct) ...
Definition: ModelData.h:280
string regId2RegSName(const int &regId_h) const
Definition: ModelData.cpp:408
map< string, vector< double > > forDataMap
Forestry data.
Definition: ModelData.h:217
void setOutputDirectory(const char *output_dirname_h)
Definition: ModelData.cpp:990
vector< vector< string > > records
Definition: ModelData.h:345
vector< string > diamClasses
Diameter classes.
Definition: ModelData.h:233
map< iisskey, double > deathTimberInventory
Map that register the death of biomass still usable as timber by year, l2_region, forest type and dia...
Definition: ModelData.h:230
scenarioData scenario
Definition: ModelData.h:202
forType * getForType(int position)
Definition: ModelData.h:128
Low level data. XML input is reversed here after unzipping oocalc file and parsing content...
Definition: ModelData.h:329