void RPModel::readXML(string fileName) { using tinyxml2::XMLDocument; using tinyxml2::XMLElement; using KBase::KException; // read XML file with tinyXML2 then do equivalent of // initScen and configScen XMLDocument d1; try { d1.LoadFile(fileName.c_str()); auto eid = d1.ErrorID(); if (0 != eid) { cout << "ErrorID: " << eid << endl; throw KException(d1.GetErrorStr1()); } else { // missing data causes the missing XMLElement* to come back as nullptr, // so we get a segmentation violation, which is not catchable. XMLElement* scenEl = d1.FirstChildElement( "Scenario" ); XMLElement* scenNameEl = scenEl->FirstChildElement( "name" ); assert (nullptr != scenNameEl); try { const char * sName = scenNameEl->GetText(); printf( "Name of scenario: %s\n", sName ); } catch (...) { throw (KException("Error reading file header")); } XMLElement* scenDescEl = scenEl->FirstChildElement( "desc" ); assert (nullptr != scenDescEl); const char* sn2 = scenDescEl->GetText(); assert (nullptr != sn2); // get some top level values from the corresponding Elements (no Attributes) XMLElement* gbEl = scenEl->FirstChildElement( "govBudget" ); assert (nullptr != gbEl); double gb = 1000.0; // impossible value gbEl->QueryDoubleText(&gb); assert (0.0 < gb); assert (gb <= 100.0); govBudget = ((unsigned int) (0.5 + gb)); XMLElement* obEl = scenEl->FirstChildElement( "outOfBudgetFactor" ); assert (nullptr != obEl); double obf = 1000.0; // impossible value obEl->QueryDoubleText(&obf); assert (0.0 < obf); assert (obf < 1.0); obFactor = obf; XMLElement* pdEl = scenEl->FirstChildElement( "orderFactor" ); assert (nullptr != pdEl); double pdf = 1000.0; // impossible value pdEl->QueryDoubleText(&pdf); assert (0.0 < pdf); assert (pdf < 1.0); pDecline = pdf; // TODO: read these two parameters from XML KBase::VotingRule vrScen = KBase::VotingRule::Proportional; RfrmPri::RPActor::PropModel pmScen = RfrmPri::RPActor::PropModel::ExpUtil; // read all the categories unsigned int nc = 0; try { XMLElement* catsEl = scenEl->FirstChildElement( "Categories" ); assert (nullptr != catsEl); XMLElement* cEl = catsEl->FirstChildElement( "category" ); assert (nullptr != cEl); // has to be at least one while (nullptr != cEl) { nc++; cEl = cEl->NextSiblingElement( "category" ); } printf("Found %i categories \n", nc); numCat = nc; } catch (...) { throw (KException("Error reading Categories data")); } // In this case, the number of items should equal to the number of categories, // so we can setup the matrix with the following size. govCost = KMatrix(1, numCat); // read all the items unsigned int ni = 0; try { XMLElement* itemsEl = scenEl->FirstChildElement( "Items" ); assert (nullptr != itemsEl); XMLElement* iEl = itemsEl->FirstChildElement( "Item" ); assert (nullptr != iEl); // has to be at least one while (nullptr != iEl) { double gci=0.0; XMLElement* gcEl = iEl->FirstChildElement("cost"); gcEl->QueryDoubleText(&gci); assert (0.0 < gci); govCost(0, ni) = gci; ni++; iEl = iEl->NextSiblingElement( "Item" ); } printf("Found %i items \n", ni); assert (ni == nc); // for this problem, number of items and categories are equal numItm = ni; } catch (...) { throw (KException("Error reading Items data")); } // We now know numItm and obFactor, so we can fill in prob vector. prob = vector<double>(); double pj = 1.0; printf("pDecline factor: %.3f \n", pDecline); printf("obFactor: %.3f \n", obFactor); // rate of decline has little effect on the results. for (unsigned int j = 0; j < numItm; j++) { prob.push_back(pj); pj = pj * pDecline; } // read all the actors unsigned int na = 0; try { XMLElement* actorsEl = scenEl->FirstChildElement( "Actors" ); assert (nullptr != actorsEl); XMLElement* aEl = actorsEl->FirstChildElement( "Actor" ); assert (nullptr != aEl); // has to be at least one while (nullptr != aEl) { const char* aName = aEl->FirstChildElement( "name" )->GetText(); const char* aDesc = aEl->FirstChildElement( "description" )->GetText(); double cap = 0.0; // another impossible value aEl->FirstChildElement( "capability" )->QueryDoubleText(&cap); assert(0.0 < cap); auto ri = new RPActor(aName, aDesc, this); ri->sCap = cap; ri->riVals = vector<double>(); ri->idNum = na; ri->vr = vrScen; ri->pMod = pmScen; XMLElement* ivsEl = aEl->FirstChildElement("ItemValues"); unsigned int numIVS = 0; XMLElement* ivEl = ivsEl->FirstChildElement("iVal"); assert (nullptr != ivEl); while (nullptr != ivEl) { numIVS++; double iv = -1.0; // impossible value ivEl->QueryDoubleText(&iv); assert (0 <= iv); ri->riVals.push_back(iv); ivEl = ivEl->NextSiblingElement("iVal"); } assert(ni == numIVS); // must have a value for each item addActor(ri); // move to the next, if any na++; aEl = aEl->NextSiblingElement( "Actor" ); } printf("Found %i actors \n", na); assert (minNumActor <= na); assert (na <= maxNumActor); } catch (...) { throw (KException("Error reading Actors data")); } } } catch (const KException& ke) { cout << "Caught KException in readXML: "<< ke.msg <<endl<<flush; } catch (...) { cout << "Caught unidentified exception in readXML"<<endl<<flush; } return; }
// -------------------------------------------- // JAH 20160728 modified to return a KTable object instead of the SQL string KTable * SMPModel::createSQL(unsigned int n) { string sql = ""; string name = ""; unsigned int grpID = 0; // check total number of table exceeds assert(n < Model::NumTables + NumTables); if (n < Model::NumTables) { return Model::createSQL(n); } else { switch (n-Model::NumTables) { case 0: // coordinates of each actor's position sql = "create table if not exists VectorPosition (" \ "ScenarioId VARCHAR(32) NOT NULL DEFAULT 'None', "\ "Turn_t INTEGER NOT NULL DEFAULT 0, "\ "Act_i INTEGER NOT NULL DEFAULT 0, "\ "Dim_k INTEGER NOT NULL DEFAULT 0, "\ "Pos_Coord FLOAT NOT NULL DEFAULT 0,"\ "Idl_Coord FLOAT NOT NULL DEFAULT 0, " \ "Mover_BargnId INTEGER NULL DEFAULT 0" \ ");"; name = "VectorPosition"; grpID = 4;// JAH 20161010 put in group 4 all by itself break; case 1: // salience to each actor of each dimension sql = "create table if not exists SpatialSalience (" \ "ScenarioId VARCHAR(32) NOT NULL DEFAULT 'None', "\ "Turn_t INTEGER NOT NULL DEFAULT 0, "\ "Act_i INTEGER NOT NULL DEFAULT 0, "\ "Dim_k INTEGER NOT NULL DEFAULT 0, "\ "Sal FLOAT NOT NULL DEFAULT 0.0"\ ");"; name = "SpatialSalience"; grpID = 0; break; case 2: // scalar capability of each actor sql = "create table if not exists SpatialCapability (" \ "ScenarioId VARCHAR(32) NOT NULL DEFAULT 'None', "\ "Turn_t INTEGER NOT NULL DEFAULT 0, "\ "Act_i INTEGER NOT NULL DEFAULT 0, "\ "Cap FLOAT NOT NULL DEFAULT 0.0"\ ");"; name = "SpatialCapability"; grpID = 0; break; case 3: // names of dimensions, so the GUI can use it JAH 20160727 { char *sqlBuff = newChars(500); sprintf(sqlBuff, "create table if not exists DimensionDescription (" \ "ScenarioId VARCHAR(32) NOT NULL DEFAULT 'None', "\ "Dim_k INTEGER NOT NULL DEFAULT 0, "\ "\"Desc\" VARCHAR(%u) NOT NULL DEFAULT 'NoDesc' "\ ");", maxDimDescLen); sql = std::string(sqlBuff); delete sqlBuff; sqlBuff = nullptr; name = "DimensionDescription"; grpID = 0; } break; case 4: // affinities of actors, so the GUI can use it { sql = "create table if not exists Accommodation (" \ "ScenarioId VARCHAR(32) NOT NULL DEFAULT 'None', "\ "Act_i INTEGER NOT NULL DEFAULT 0, "\ "Act_j INTEGER NOT NULL DEFAULT 0, "\ "Affinity FLOAT NOT NULL DEFAULT 0.0"\ ");"; name = "Accommodation"; grpID = 0; break; } default: throw(KException("SMPModel::createSQL unrecognized table number")); } } assert(grpID<(Model::NumSQLLogGrps+NumSQLLogGrps)); auto tab = new KTable(n,name,sql,grpID); return tab; }