/* Scanning the files ... this is the business!! */ void scanFiles(const CSString &filespec) { std::vector<std::string> filenames; buildFileVector(filenames, filespec); // if there s no file, nothing to do if (filenames.empty()) return; // display the table header line fprintf(Outf,"FILE"); for (unsigned i=0;i<fields.size();i++) fprintf(Outf,"%s%s",SEPARATOR, fields[i]._name.c_str()); fprintf(Outf,"\n"); UFormLoader *formLoader = NULL; NLMISC::TTime last = NLMISC::CTime::getLocalTime (); NLMISC::TTime start = NLMISC::CTime::getLocalTime (); NLMISC::CSmartPtr<UForm> form; for (uint j = 0; j < filenames.size(); j++) { if (NLMISC::CTime::getLocalTime () > last + 5000) { last = NLMISC::CTime::getLocalTime (); if (j>0) { nlinfo ("%.0f%% completed (%d/%d), %d seconds remaining", (float)j*100.0/filenames.size(),j,filenames.size(), (filenames.size()-j)*(last-start)/j/1000); } } //std::string p = NLMISC::CPath::lookup (filenames[j], false, false); std::string p = filenames[j]; if (p.empty()) continue; // create the georges loader if necessary if (formLoader == NULL) { WarningLog->addNegativeFilter("CFormLoader: Can't open the form file"); formLoader = UFormLoader::createLoader (); } // Load the form with given sheet id // form = formLoader->loadForm (sheetIds[j].toString().c_str ()); form = formLoader->loadForm (filenames[j].c_str ()); if (form) { // the form was found so read the true values from George // std::string s; fprintf(Outf,"%s",CFile::getFilenameWithoutExtension(filenames[j]).c_str()); for (unsigned i=0;i<fields.size();i++) { UFormElm::TWhereIsValue where; UFormElm *fieldForm=NULL; std::string valueString; form->getRootNode ().getNodeByName(&fieldForm, fields[i]._name.c_str()); if (fieldForm) { if (fieldForm->isArray()) // if its an array { uint arraySize=0,arrayIndex=0; fieldForm->getArraySize(arraySize); while (arrayIndex<arraySize) { if (fieldForm->getArrayValue(valueString,arrayIndex,fields[i]._evaluated, &where)) ;//addQuotesRoundString (valueString); else setErrorString (valueString, fields[i]._evaluated, where); arrayIndex++; if (arrayIndex<arraySize) // another value in the array.. valueString+=ARRAY_SEPARATOR; } } else { if (form->getRootNode ().getValueByName(valueString,fields[i]._name.c_str(),fields[i]._evaluated,&where)) //fieldForm->getValue(valueString,fields[i]._evaluated)) ;//addQuotesRoundString (valueString); else setErrorString (valueString, fields[i]._evaluated, where); } } // else // node not found. // { // setErrorString (valueString, fields[i]._evaluated, where); // } replaceTrueAndFalseTagToCsv(valueString); fprintf(Outf,"%s%s", SEPARATOR, valueString.c_str()); // UFormElm::TWhereIsValue where; // // bool result=form->getRootNode ().getValueByName(s,fields[i]._name.c_str(),fields[i]._evaluated,&where); // if (!result) // { // if (fields[i]._evaluated) // { // s="ERR"; // } // else // { // switch(where) // { // case UFormElm::ValueForm: s="ValueForm"; break; // case UFormElm::ValueParentForm: s="ValueParentForm"; break; // case UFormElm::ValueDefaultDfn: s="ValueDefaultDfn"; break; // case UFormElm::ValueDefaultType: s="ValueDefaultType"; break; // default: s="ERR"; // } // // } // // } // else // { // // add quotes round strings // std::string hold=s; // s.erase(); // s='\"'; // for (unsigned i=0;i<hold.size();i++) // { // if (hold[i]=='\"') // s+="\"\""; // else // s+=hold[i]; // } // s+='\"'; // } // fprintf(Outf,"%s%s", SEPARATOR, s); } fprintf(Outf,"\n"); } } // free the georges loader if necessary if (formLoader != NULL) { UFormLoader::releaseLoader (formLoader); WarningLog->removeFilter ("CFormLoader: Can't open the form file"); } // housekeeping // sheetIds.clear (); filenames.clear (); fields.clear(); }
/* * CSV -> Georges */ void convertCsvFile( const string &file, bool generate, const string& sheetType ) { const uint BUFFER_SIZE = 16*1024; char lineBuffer[BUFFER_SIZE]; FILE *s; vector<string> fields; vector<string> args; if ((s = fopen(file.c_str(), "r")) == NULL) { fprintf(stderr, "Can't find file %s to convert\n", file.c_str()); return; } loadSheetPath(); UFormLoader *formLoader = UFormLoader::createLoader (); NLMISC::CSmartPtr<CForm> form; NLMISC::CSmartPtr<UFormDfn> formDfn; fgets(lineBuffer, BUFFER_SIZE, s); explode(std::string(lineBuffer), std::string(SEPARATOR), fields); vector<bool> activeFields( fields.size(), true ); // Load DFN (generation only) set<CDfnField> dfnFields; if ( generate ) { formDfn = formLoader->loadFormDfn( (sheetType + ".dfn").c_str() ); if ( ! formDfn ) nlerror( "Can't find DFN for %s", sheetType.c_str() ); fillFromDFN( formLoader, dfnFields, formDfn, "", sheetType ); // Display missing fields and check fields against DFN uint i; for ( i=1; i!=fields.size(); ++i ) { eraseCarriageReturnsAndMakeBlankNonAsciiChars( fields[i] ); if ( fields[i].empty() ) { nlinfo( "Skipping field #%u (empty)", i ); activeFields[i] = false; } else if ( nlstricmp( fields[i], "parent" ) == 0 ) { strlwr( fields[i] ); // non-const version } else { set<CDfnField>::iterator ist = dfnFields.find( CDfnField(fields[i]) ); if ( ist == dfnFields.end() ) { nlinfo( "Skipping field #%u (%s, not found in %s DFN)", i, fields[i].c_str(), sheetType.c_str() ); activeFields[i] = false; } } } for ( i=1; i!=fields.size(); ++i ) { if ( activeFields[i] ) nlinfo( "Selected field: %s", fields[i].c_str() ); } } string addExtension = "." + sheetType; uint dirmapLetterIndex = ~0; bool dirmapLetterBackward = false; vector<string> dirmapDirs; string dirmapSheetCode; bool WriteEmptyProperties = false, WriteSheetsToDisk = true; bool ForceInsertParents = false; if ( generate ) { // Get the directory mapping try { CConfigFile dirmapcfg; dirmapcfg.load( sheetType + "_dirmap.cfg" ); if ( OutputPath.empty() ) { CConfigFile::CVar *path = dirmapcfg.getVarPtr( "OutputPath" ); if ( path ) OutputPath = path->asString(); if ( ! OutputPath.empty() ) { if ( OutputPath[OutputPath.size()-1] != '/' ) OutputPath += '/'; else if ( ! CFile::isDirectory( OutputPath ) ) nlwarning( "Output path does not exist" ); } } CConfigFile::CVar *letterIndex1 = dirmapcfg.getVarPtr( "LetterIndex" ); if ( letterIndex1 && letterIndex1->asInt() > 0 ) { dirmapLetterIndex = letterIndex1->asInt() - 1; CConfigFile::CVar *letterWay = dirmapcfg.getVarPtr( "LetterWay" ); dirmapLetterBackward = (letterWay && (letterWay->asInt() == 1)); CConfigFile::CVar dirs = dirmapcfg.getVar( "Directories" ); for ( uint idm=0; idm!=dirs.size(); ++idm ) { dirmapDirs.push_back( dirs.asString( idm ) ); nlinfo( "Directory: %s", dirmapDirs.back().c_str() ); if ( ! CFile::isExists( OutputPath + dirmapDirs.back() ) ) { CFile::createDirectory( OutputPath + dirmapDirs.back() ); } else { if ( ! CFile::isDirectory( OutputPath + dirmapDirs.back() ) ) { nlwarning( "Already existing but not a directory!" ); } } } nlinfo( "Mapping letter #%u (%s) of sheet name to directory", dirmapLetterIndex + 1, dirmapLetterBackward?"backward":"forward" ); } CConfigFile::CVar *sheetCode = dirmapcfg.getVarPtr( "AddSheetCode" ); if ( sheetCode ) dirmapSheetCode = sheetCode->asString(); nlinfo( "Sheet code: %s", dirmapSheetCode.c_str() ); if ( ! dirmapLetterBackward ) dirmapLetterIndex += dirmapSheetCode.size(); CConfigFile::CVar *wep = dirmapcfg.getVarPtr( "WriteEmptyProperties" ); if ( wep ) WriteEmptyProperties = (wep->asInt() == 1); nlinfo( "Write empty properties mode: %s", WriteEmptyProperties ? "ON" : "OFF" ); CConfigFile::CVar *wstd = dirmapcfg.getVarPtr( "WriteSheetsToDisk" ); if ( wstd ) WriteSheetsToDisk = (wstd->asInt() == 1); nlinfo( "Write sheets to disk mode: %s", WriteSheetsToDisk ? "ON" : "OFF" ); CConfigFile::CVar *fiparents = dirmapcfg.getVarPtr( "ForceInsertParents" ); if ( fiparents ) ForceInsertParents = (fiparents->asInt() == 1); nlinfo( "Force insert parents mode: %s", ForceInsertParents ? "ON" : "OFF" ); } catch ( EConfigFile& e ) { nlwarning( "Problem in directory mapping: %s", e.what() ); } nlinfo( "Using output path: %s", OutputPath.c_str() ); nlinfo( "Press a key to generate *.%s", sheetType.c_str() ); getchar(); nlinfo( "Generating...." ); } else nlinfo("Updating modifications (only modified fields are updated)"); set<string> newSheets; uint nbNewSheets = 0, nbModifiedSheets = 0, nbUnchangedSheets = 0, nbWritten = 0; while (!feof(s)) { lineBuffer[0] = '\0'; fgets(lineBuffer, BUFFER_SIZE, s); explode(std::string(lineBuffer), std::string(SEPARATOR), args); if (args.size() < 1) continue; eraseCarriageReturnsAndMakeBlankNonAsciiChars( args[0] ); replaceTrueAndFalseTagFromCsv(args); // Skip empty lines if ( args[0].empty() || (args[0] == string(".")+sheetType) ) continue; //nldebug( "%s: %u", args[0].c_str(), args.size() ); string filebase = dirmapSheetCode+args[0]; /*+"."+sheetType;*/ if (filebase.find("."+sheetType) == string::npos) { filebase += "." + sheetType; } strlwr (filebase); string filename, dirbase; bool isNewSheet=true; // Locate existing sheet // map<string, string>::iterator it = inputSheetPathContent.find( CFile::getFilenameWithoutExtension( filebase ) ); map<string, string>::iterator it = inputSheetPathContent.find( CFile::getFilename( filebase ) ); if (it == inputSheetPathContent.end()) { // Not found if ( ! generate ) { if ( ! filebase.empty() ) { nlwarning( "Sheet %s not found", filebase.c_str( )); continue; } } else { // Load template sheet filename = strlwr( static_cast<const string&>(filebase) ); form = (CForm*)formLoader->loadForm( (string("_empty.") + sheetType).c_str() ); if (form == NULL) { nlerror( "Can't load sheet _empty.%s", sheetType.c_str() ); } // Deduce directory from sheet name if ( dirmapLetterIndex != ~0 ) { if ( dirmapLetterIndex < filebase.size() ) { uint letterIndex; char c; if ( dirmapLetterBackward ) letterIndex = filebase.size() - 1 - (CFile::getExtension( filebase ).size()+1) - dirmapLetterIndex; else letterIndex = dirmapLetterIndex; c = tolower( filebase[letterIndex] ); vector<string>::const_iterator idm; for ( idm=dirmapDirs.begin(); idm!=dirmapDirs.end(); ++idm ) { if ( (! (*idm).empty()) && (tolower((*idm)[0]) == c) ) { dirbase = (*idm) + "/"; break; } } if ( idm==dirmapDirs.end() ) { nlinfo( "Directory mapping not found for %s (index %u)", filebase.c_str(), letterIndex ); dirbase = ""; // put into root } } else { nlerror( "Can't map directory with letter #%u, greater than size of %s + code", dirmapLetterIndex, filebase.c_str() ); } } nlinfo( "New sheet: %s", filebase.c_str() ); ++nbNewSheets; if ( ! newSheets.insert( filebase ).second ) nlwarning( "Found duplicate sheet: %s", filebase.c_str() ); isNewSheet = true; } } else // an existing sheet was found { // Load sheet (skip if failed) dirbase = ""; filename = (*it).second; // whole path form = (CForm*)formLoader->loadForm( filename.c_str() ); if (form == NULL) { nlwarning( "Can't load sheet %s", filename.c_str() ); continue; } isNewSheet = false; } const UFormElm &rootForm=form->getRootNode(); bool displayed = false; bool isModified = false; uint i; for ( i=1; i<args.size () && i<fields.size (); ++i ) { const string &var = fields[i]; string &val = args[i]; eraseCarriageReturnsAndMakeBlankNonAsciiChars( val ); // Skip column with inactive field (empty or not in DFN) if ( (! activeFields[i]) ) continue; // Skip setting of empty cell except if required if ( (! WriteEmptyProperties) && val.empty() ) continue; // Special case for parent sheet if (var == "parent") // already case-lowered { vector<string> parentVals; explode( val, std::string(ARRAY_SEPARATOR), parentVals ); if ( (parentVals.size() == 1) && (parentVals[0].empty()) ) parentVals.clear(); if ( (isNewSheet || ForceInsertParents) && (! parentVals.empty()) ) { // This is slow. Opti: insertParent() should have an option to do it without loading the form // parent have same type that this object (postulat). uint nbinsertedparents=0; for ( uint p=0; p!=parentVals.size(); ++p ) { string localExtension=(parentVals[p].find(addExtension)==string::npos)?addExtension:""; string parentName=parentVals[p]+localExtension; CSmartPtr<CForm> parentForm = (CForm*)formLoader->loadForm(CFile::getFilename(parentName.c_str()).c_str()); if ( ! parentForm ) { nlwarning( "Can't load parent form %s", parentName.c_str() ); } else { form->insertParent( p, parentName.c_str(), parentForm ); isModified=true; displayed = true; nbinsertedparents++; } } nlinfo( "Inserted %u parent(s)", nbinsertedparents ); } // NOTE: Changing the parent is not currently implemented! continue; } const UFormElm *fieldForm=NULL; if (rootForm.getNodeByName(&fieldForm, var.c_str())) { UFormDfn *dfnForm=const_cast<UFormElm&>(rootForm).getStructDfn(); nlassert(dfnForm); vector<string> memberVals; explode( val, std::string(ARRAY_SEPARATOR), memberVals ); uint32 memberIndex=0; while (memberIndex<memberVals.size()) { const uint currentMemberIndex=memberIndex; std::string memberVal=memberVals[memberIndex]; memberIndex++; if (!memberVal.empty()) { if (memberVal[0] == '"') memberVal.erase(0, 1); if (memberVal.size()>0 && memberVal[memberVal.size()-1] == '"') memberVal.resize(memberVal.size()-1); if (memberVal == "ValueForm" || memberVal == "ValueParentForm" || memberVal == "ValueDefaultDfn" || memberVal == "ValueDefaultType" || memberVal == "ERR") continue; } // nlassert(fieldDfn); // virtual bool getEntryFilenameExt (uint entry, std::string &name) const = 0; // virtual bool getEntryFilename (uint entry, std::string &name) const = 0; if (dfnForm) { string fileName; string fileNameExt; bool toto=false; static string filenameTyp("filename.typ"); string extension; uint fieldIndex; if (dfnForm->getEntryIndexByName (fieldIndex, var)) // field exists. { dfnForm->getEntryFilename(fieldIndex,fileName); if (fileName==filenameTyp) { dfnForm->getEntryFilenameExt(fieldIndex,fileNameExt); if ( !fileNameExt.empty() && fileNameExt!="*.*") { string::size_type index=fileNameExt.find("."); if (index==string::npos) // not found. { extension=fileNameExt; } else { extension=fileNameExt.substr(index+1); } if (memberVal.find(extension)==string::npos) // extension not found. { memberVal=NLMISC::toString("%s.%s",memberVal.c_str(),extension.c_str()); } } } } } if (dfnForm->isAnArrayEntryByName(var)) { if ( !isNewSheet && fieldForm!=NULL) { uint arraySize; const UFormElm *arrayNode = NULL; if (fieldForm->isArray() && fieldForm->getArraySize(arraySize) && arraySize == memberVals.size()) { string test; if ( fieldForm->getArrayValue(test, currentMemberIndex) && test==memberVal ) { continue; } } } //nldebug( "%s: %s '%s'", args[0].c_str(), var.c_str(), memberVal.c_str() ); // need to put the value at the correct index. const std::string fieldName=NLMISC::toString("%s[%d]", var.c_str(), currentMemberIndex).c_str(); const_cast<UFormElm&>(rootForm).setValueByName(memberVal.c_str(), fieldName.c_str()); isModified=true; displayed = true; } else { if (!isNewSheet) { string test; if ( rootForm.getValueByName(test,var.c_str()) && test==memberVal ) { continue; } } //nldebug( "%s: %s '%s'", args[0].c_str(), var.c_str(), memberVal.c_str() ); const_cast<UFormElm&>(rootForm).setValueByName(memberVal.c_str(), var.c_str()); isModified=true; displayed = true; } if (!isNewSheet) { isModified = true; if (!displayed) nlinfo("in %s:", filename.c_str()); displayed = true; nlinfo("%s = %s", var.c_str(), memberVal.c_str()); } } } else // field Node not found :\ (bad) { } } if ( ! isNewSheet ) { if ( isModified ) ++nbModifiedSheets; else ++nbUnchangedSheets; } // Write sheet if ( isNewSheet || displayed ) { if ( WriteSheetsToDisk ) { ++nbWritten; string path = isNewSheet ? OutputPath : ""; string ext = (filename.find( addExtension ) == string::npos) ? addExtension : ""; string absoluteFileName=path + dirbase + filename + ext; // nlinfo("opening: %s", absoluteFileName.c_str() ); COFile output(absoluteFileName); if (!output.isOpen()) { nlinfo("creating path: %s", (path + dirbase).c_str() ); NLMISC::CFile::createDirectory(path + dirbase); } // nlinfo("opening2: %s", absoluteFileName.c_str() ); output.open (absoluteFileName); if (!output.isOpen()) { nlinfo("ERROR! cannot create file path: %s", absoluteFileName.c_str() ); } else { form->write(output, true); output.close(); if (!CPath::exists(filename + ext)) CPath::addSearchFile(absoluteFileName); } } clearSheet( form, &form->getRootNode() ); } } nlinfo( "%u sheets processed (%u new, %u modified, %u unchanged - %u written)", nbNewSheets+nbModifiedSheets+nbUnchangedSheets, nbNewSheets, nbModifiedSheets, nbUnchangedSheets, nbWritten ); UFormLoader::releaseLoader (formLoader); }
//----------------------------------------------- // readGeorges for CStaticSkillsTree // //----------------------------------------------- void CStaticSkillsTree::readGeorges( const NLMISC::CSmartPtr<NLGEORGES::UForm> &form, const NLMISC::CSheetId &sheetId ) { if( form ) { UFormElm& root = form->getRootNode(); UFormElm *arraySkillElt = NULL; if( root.getNodeByName( &arraySkillElt, "SkillData" ) ) { if( arraySkillElt ) { uint NbSkills; nlverify( arraySkillElt->getArraySize( NbSkills ) ); nlassertex( NbSkills == SKILLS::NUM_SKILLS, ("(%u != %u) Please synchronise game_share/skill.* with leveldesign/game_element/xp_table/skills.skill_tree (use skill_extractor.exe)", NbSkills, SKILLS::NUM_SKILLS)); SkillsTree.resize( NbSkills ); for( uint i = 0; i < NbSkills; ++i ) { UFormElm* SkillElt = NULL; if( ! ( arraySkillElt->getArrayNode( &SkillElt, i ) && SkillElt ) ) { nlwarning("<CStaticSkillsTree::readGeorges> can't get array node of SkillElt in sheet %s", sheetId.toString().c_str() ); } else { // Skill string SkillName; SkillElt->getValueByName( SkillName, "Skill" ); SKILLS::ESkills skill = SKILLS::toSkill( SkillName ); nlassert( skill != SKILLS::unknown ); if (skill == SKILLS::unknown) { continue; } SkillsTree[ skill ].Skill = skill; if( ! SkillElt->getValueByName( SkillsTree[ skill ].SkillCode, "SkillCode" ) ) { nlwarning("<CStaticSkillsTree::readGeorges> can't get node SkillCode in sheet %s", sheetId.toString().c_str() ); } // Skill Code if( ! SkillElt->getValueByName( SkillsTree[ skill ].SkillCode, "SkillCode" ) ) { nlwarning("<CStaticSkillsTree::readGeorges> can't get node SkillCode in sheet %s", sheetId.toString().c_str() ); } // Max skill value if( ! SkillElt->getValueByName( SkillsTree[ skill ].MaxSkillValue, "MaxSkillValue" ) ) { nlwarning("<CStaticSkillsTree::readGeorges> can't get node MaxSkillValue in sheet %s", sheetId.toString().c_str() ); } // Type of stage if( ! SkillElt->getValueByName( SkillsTree[ skill ].StageType, "Type of Stage" ) ) { nlwarning("<CStaticSkillsTree::readGeorges> can't get node 'Type of Stage' in sheet %s", sheetId.toString().c_str() ); } // ParentSkill if( ! SkillElt->getValueByName( SkillName, "ParentSkill" ) ) { nlwarning("<CStaticSkillsTree::readGeorges> can't get node ParentSkills in sheet %s", sheetId.toString().c_str() ); } else { SkillsTree[ skill ].ParentSkill = SKILLS::toSkill( SkillName ); } // ChildSkills UFormElm *arrayChildSkillElt = NULL; if( SkillElt->getNodeByName( &arrayChildSkillElt, "ChildSkills" ) ) { if( arrayChildSkillElt ) { uint NbChildSkills; nlverify( arrayChildSkillElt->getArraySize( NbChildSkills ) ); SkillsTree[ skill ].ChildSkills.resize( NbChildSkills ); for( uint i = 0; i < NbChildSkills; ++i ) { string childSkillName; arrayChildSkillElt->getArrayValue( childSkillName, i ); SKILLS::ESkills childSkill = SKILLS::toSkill( childSkillName ); nlassert( childSkill != SKILLS::unknown ); if (skill == SKILLS::unknown) { continue; } SkillsTree[ skill ].ChildSkills[ i ] = childSkill; } } } } } } } } }