// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . // phrase_generator.cpp : Defines the entry point for the console application. // //-b -p r:\code\ryzom\data_leveldesign -o r:/code/ryzom/data_leveldesign/leveldesign/game_element/sphrase/magic/ magic_bricks.csv -d -m // -p r:\code\ryzom\data_leveldesign -o r:/code/ryzom/data_leveldesign/leveldesign/game_element/sphrase/magic/ magic_bricks.csv -d -m #include "stdafx.h" // Misc #include #include "nel/misc/path.h" #include "nel/misc/file.h" #include "nel/misc/smart_ptr.h" #include "nel/misc/command.h" #include "nel/misc/common.h" #include "nel/misc/path.h" #include #include #include "nel/misc/algo.h" #include "nel/misc/words_dictionary.h" // Georges #include "nel/georges/u_form.h" #include "nel/georges/u_form_elm.h" #include "nel/georges/u_form_dfn.h" #include "nel/georges/u_form_loader.h" #include "nel/georges/u_type.h" // Georges, bypassing interface #include "georges/stdgeorges.h" #include "georges/form.h" // Game share //#include "game_share/xml.h" // Unicode language file // C #include #include #include #include // stl #include #include "skill_tree.h" using namespace NLMISC; using namespace NLGEORGES; using namespace std; typedef vector vs; typedef map< string, string > mss; typedef map< string, vs > msvs; bool GenerateBrickProgression = false; bool ProduceDocFromExistingPhrases = false; bool MultipleDocFiles = false; bool Hypertext = true; string PhrasePath = "r:/code/ryzom/data_leveldesign/leveldesign/game_element/sphrase/"; uint NbSheetsGenTries = 0; uint NbSheetsWritten = 0; uint NbSheetsRead = 0; uint NbSheetsRejected = 0; bool UseBricks; const string brSheetType = "sbrick"; const string phSheetType = "sphrase"; const string PHRASE_MAGIC_PREFIX = "abm_"; // action bricks magic (bm for brick filter) struct CBrickInfo { CBrickInfo( const string& ls="", const string& t="", const vs& props=vs() ) : LearnSkills(ls), Text(t), Props(props) {} string LearnSkills; string Text; // UTF-8 vs Props; }; vs OptionBricks, CounterpartBricks, AllBricks, PhrasesWithInvalidCost, InvalidPhrases; set UsedCounterpartBricks, UsedCounterpartBrickFamiliesInPhrase; map SabrinaCosts; map PhraseSabrinaCosts; map PhraseCastable; map BrickInfo; mss TextToBrick; multimap< uint, pair > Progression; // phrase code, min. skill mss PhraseNames, PhraseTitles; vector ValidPhrases; set UsedBricks, GeneratedPhrases; map GrammarMandatParamBrickFamilies, GrammarOptionCreditBrickFamilies; UFormLoader *FormLoader; vector PhraseDocFiles( 26 ); string DocFileName,DocFileNameRoot; msvs Phrases; map SkillNameToMaxSkill; map PhraseCodeToLink; CWordsDictionary Dico; CStaticSkillsTree SkillsTree; /* * */ string inputSheetPath; bool inputSheetPathLoaded = false; map inputSheetPathContent; // short filename without ext, full filename with path //----------------------------------------------- // getBrickTypeLetterRPos // //----------------------------------------------- uint getBrickTypeLetterRPos( string& brick ) { /* uint i =0; while( i=0 && (isdigit(brick[i]) || brick[i]=='_') ) i--; return (brick.size() - i + 1); } // getBrickTypeLetterRPos // //----------------------------------------------- // loadSheetPath // // from georges2csv //----------------------------------------------- void loadSheetPath() { if (inputSheetPathLoaded) return; NLMISC::createDebug(); NLMISC::WarningLog->addNegativeFilter( "CPath::insertFileInMap" ); CPath::addSearchPath(inputSheetPath, true, false); // for Georges to work properly vector files; CPath::getPathContent (inputSheetPath, true, false, true, files); uint i; for (i=0; i& v, CLog *log=DebugLog ) { if ( ! title.empty() ) log->displayRaw( "%s: ", title.c_str() ); vector::const_iterator ist; for ( ist=v.begin(); ist!=v.end(); ++ist ) log->displayRaw( "%s ", (*ist).c_str() ); log->displayRawNL( "" ); } /* * */ class CStrIComparator : public binary_function { public: bool operator() ( const string& s1, const string& s2 ) const { return (nlstricmp( s1, s2 ) == 0); } }; /* * */ uint getIndexFromString( const string& s, const vector& v, bool displayWarning=true ) { if ( v.empty() ) { nlwarning( "Can't find '%s' in empty array", s.c_str() ); return ~0; } else { vector::const_iterator ist = find_if( v.begin(), v.end(), bind2nd(CStrIComparator(), s) ); if ( ist == v.end() ) { if ( displayWarning ) { nlwarning( "Can't find '%s' in:", s.c_str() ); displayList( "", v, WarningLog ); } return ~0; } else return ist - v.begin(); } } //----------------------------------------------- // Erase every carriage returns of the string // //----------------------------------------------- void eraseCarriageReturns( string& s ) { const char CR = '\n'; string::size_type p = s.find( CR ); while ( (p=s.find( CR )) != string::npos ) s.erase( p, 1 ); } // // First param: vector of indices of columns matching wantedColumnNames // Second param: vector of fields matching wantedColumnNames typedef void (*TDeliveryCallback) ( mss& ); //----------------------------------------------- // loadCSVFile // //----------------------------------------------- void loadCSVFile( const char *filename, TDeliveryCallback deliveryCallback ) { char lineBuffer[2048]; FILE *file; const char *SEPARATOR = ";"; vector args; vector::iterator iarg; if ( (file = nlfopen( filename, "r" )) == NULL ) { nlwarning( "Can't find file %s", filename ); } else { // Read first line as header with column names lineBuffer[0] = '\0'; fgets( lineBuffer, 2048, file ); explode( lineBuffer, SEPARATOR, args ); // Store column names (and get rid of carriage returns!) vector < string > columnNames; mss valuesByName; for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) { eraseCarriageReturns( *iarg ); columnNames.push_back( *iarg ); valuesByName.insert( make_pair( *iarg, string("") ) ); } // for each line, deliver the value of the fields while ( ! feof(file) ) { // Get from file lineBuffer[0] = '\0'; fgets( lineBuffer, 2048, file ); explode( lineBuffer, SEPARATOR, args ); // Set values (and get rid of carriage returns!) for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) { eraseCarriageReturns( *iarg ); valuesByName[columnNames[iarg-args.begin()]] = *iarg; } // Deliver the wanted fields deliveryCallback( valuesByName ); } } } // loadCSVFile // //set Skills; //----------------------------------------------- // brickDeliveryCallback // // Fetch brick code and sabrina cost // - AllBricks // - BrickInfo // - OptionBricks // - CounterpartBricks // - SabrinaCosts //----------------------------------------------- void brickDeliveryCallback( mss& values ) { string s = values["Brick_id"]; if ( s.empty() ) { s = values["FILE"]; if ( s.empty() ) s = values["fileName"]; } string brick = CFile::getFilenameWithoutExtension( s ); strupr( brick ); if ( brick.empty() ) { nlwarning(" can't get root filename of %s",s.c_str()); return; } string sc = values["Basics.SabrinaCost"]; string ls = values["Basics.LearnRequiresOneOfSkills"]; string txt = values["name"]; // TODO: only for combat string fmn = values["familyName"]; string propIdent = "Basics.Property"; if ( UseBricks ) { AllBricks.push_back( brick ); string name = (txt.empty()) ? fmn : txt; vs props; // Find all Basics.Property N (assumes they are subsequent) mss::const_iterator imv = values.find( propIdent + " 0" ); for ( ; imv!=values.end(); ++imv ) { const string& colName = (*imv).first; const string& v = (*imv).second; if ( colName.find( propIdent ) != string::npos ) { if ( v != "NULL" && !v.empty() ) props.push_back( v ); } else break; } BrickInfo.insert( make_pair( brick, CBrickInfo( ls, name, props ) ) ); } // Store brick in right container string::size_type p = brick.size() - getBrickTypeLetterRPos(brick); if ( ((sint)p) >= 0 ) { switch ( brick[p] ) { case 'O': OptionBricks.push_back( brick ); break; case 'C': CounterpartBricks.push_back( brick ); break; } } else { nlwarning( "Invalid brick code: %s", brick.c_str() ); return; } // Store cost sint sabrinaCost; if ( sc.empty() ) { nldebug( "No sabrina cost for %s, assuming cost 0", brick.c_str() ); sabrinaCost = 0; } else { sabrinaCost = atoi( sc.c_str() ); } SabrinaCosts.insert( make_pair( brick, sabrinaCost ) ); /* // Quick hack to generate skill codes string skill = brick.substr( 1, p-1 ); if ( ! skill.empty() ) Skills.insert( skill );*/ } // brickDeliveryCallback // //----------------------------------------------- // loadBricks // //----------------------------------------------- void loadBricks( const char* filename ) { loadCSVFile( filename, brickDeliveryCallback ); if ( ProduceDocFromExistingPhrases ) nlinfo( "Loaded %u option bricks, %u counterpart bricks, %u sabrina costs", OptionBricks.size(), CounterpartBricks.size(), SabrinaCosts.size() ); else if ( UseBricks ) nlinfo( "Loaded %u bricks", AllBricks.size() ); /*set::const_iterator iss; for ( iss=Skills.begin(); iss!=Skills.end(); ++iss ) { const string& skill = (*iss); InfoLog->displayRawNL( " ", skill.c_str(), skill.c_str() ); }*/ } // loadBricks // /* * */ string getRootBrickForOptionOrCredit( const string& ob ) { // Extract brick code radix string::size_type p = ob.size() - getBrickTypeLetterRPos(const_cast(ob)); if ( (ob.size() <= getBrickTypeLetterRPos(const_cast(ob))) || ((ob[p] != 'O') && (ob[p] != 'C')) ) nlerror( "%s is not an option or credit brick", ob.c_str() ); string radix = ob.substr( 0, p ); // Append root brick suffix return radix + "PA01"; } /* * */ string getBrickFamily( const string& b ) { if ( b.size() >= getBrickTypeLetterRPos(const_cast(b))+2 ) { string::size_type p = b.size() - getBrickTypeLetterRPos(const_cast(b)); return b.substr( 0, p+2 ); } return string(); } /* * */ bool isFromBrickFamily( const string& brick, const string& fam ) { return nlstricmp( brick.substr( 0, fam.size() ), fam ) == 0; } /* * */ string getFirstBrickOfFamily( const string& family ) { vs::const_iterator ib; for ( ib=AllBricks.begin(); ib!=AllBricks.end(); ++ib ) { const string& brick = *ib; if ( isFromBrickFamily( brick, family ) ) return brick; } return string(); } /* * */ vs getAllBricksOfFamily( const string& family ) { vs res; vs::const_iterator ib; for ( ib=AllBricks.begin(); ib!=AllBricks.end(); ++ib ) { const string& brick = *ib; if ( isFromBrickFamily( brick, family ) ) res.push_back( brick ); } return res; } /* * */ uint getCompatibleCounterpartBrickForCost( uint phraseCost, vs& phrase ) { //nlinfo( "Searching credit for cost %u", phraseCost ); // Get the lowest matching counterpart brick uint minHigherCounterpartValue = ~0, maxLowerCounterpartValue = 0, counterpartValue; vs::const_iterator icb, iPerfectMatch = CounterpartBricks.end(), iMinCb = CounterpartBricks.end(), iMaxCb = CounterpartBricks.end(); for ( icb=CounterpartBricks.begin(); icb!=CounterpartBricks.end(); ++icb) { const string& cb = *icb; // Skip if family already used in current phrase if ( UsedCounterpartBrickFamiliesInPhrase.find( getBrickFamily( cb ) ) != UsedCounterpartBrickFamiliesInPhrase.end() ) continue; counterpartValue = abs( SabrinaCosts[cb] ); //nldebug( "Trying with credit %u", counterpartValue ); if ( counterpartValue == phraseCost ) { // Perfect match, check if not already taken if ( UsedCounterpartBricks.insert( cb ).second ) { UsedCounterpartBrickFamiliesInPhrase.insert( getBrickFamily( cb ) ); phrase.push_back( cb ); return counterpartValue; } else { // If already taken, we will come back to it later iPerfectMatch = icb; } } else if ( counterpartValue > phraseCost ) { // Higher => get the minimum if ( counterpartValue < minHigherCounterpartValue ) { minHigherCounterpartValue = counterpartValue; iMinCb = icb; } } else // counterpartValue < phraseCost : store the max { if ( counterpartValue >= maxLowerCounterpartValue ) { maxLowerCounterpartValue = counterpartValue; iMaxCb = icb; } } } if ( iPerfectMatch != CounterpartBricks.end() ) { // We skipped a perfect match in order to try to get a new value. But none found. Now get back to the last value. phrase.push_back( *iPerfectMatch ); UsedCounterpartBrickFamiliesInPhrase.insert( getBrickFamily( *iPerfectMatch ) ); return abs( SabrinaCosts[*iPerfectMatch] ); } else if ( iMinCb == CounterpartBricks.end() ) { if ( iMaxCb == CounterpartBricks.end() ) { nlerror( "No matching counterpart" ); return ~0; } else { // No phrase possible with only one (more) counterpart, try with the max and more (recurse) UsedCounterpartBricks.insert( *iMaxCb ); UsedCounterpartBrickFamiliesInPhrase.insert( getBrickFamily( *iMaxCb ) ); phrase.push_back( *iMaxCb ); return maxLowerCounterpartValue + getCompatibleCounterpartBrickForCost( phraseCost - maxLowerCounterpartValue, phrase ); } } else { // Phrase possible with one (more) counterpart UsedCounterpartBricks.insert( *iMinCb ); UsedCounterpartBrickFamiliesInPhrase.insert( getBrickFamily( *iMinCb ) ); phrase.push_back( *iMinCb ); return minHigherCounterpartValue; } } /* * */ void getCompatibleCounterpartBricks( vs& phrase ) { // Calculate the cost of the phrase sint phraseCost = 0; string phraseStr; vs::const_iterator ip; for ( ip=phrase.begin(); ip!=phrase.end(); ++ip ) { const string& brick = *ip; sint sabrinaCost; map::const_iterator isc = SabrinaCosts.find( brick ); if ( isc != SabrinaCosts.end() ) sabrinaCost = (*isc).second; else sabrinaCost = 0; phraseCost += sabrinaCost; phraseStr += brick + " "; } // Find matching counterpart(s), only 1 per family UsedCounterpartBrickFamiliesInPhrase.clear(); uint counterpartValue = getCompatibleCounterpartBrickForCost( phraseCost, phrase ); displayList( toString( "+%3u -%3u", phraseCost, counterpartValue ), phrase ); } /* * */ /*void getCompatiblePhraseByCounterpart( const string& counterpartBrick, vs& phrase ) { sint sabrinaCost = SabrinaCosts[counterpartBrick]; // Assuming root brick cost is zero! vs::const_iterator iob; for ( iob=OptionBricks.begin(); iob!=OptionBricks.end(); ++iob ) { // TODO: Find the highest cost that is lower or equal than the counterpart value const string& ob = *iob; if ( SabrinaCosts[ob] <= SabrinaCosts[counterpartBrick] ) break; // currently, take the first found } if ( iob != OptionBricks.end() ) { string rb = getRootBrickForOptionOrCredit( *iob ); phrase.push_back( rb ); phrase.push_back( *iob ); phrase.push_back( counterpartBrick ); nldebug( "%s %s %s: +%u -%u", rb.c_str(), (*iob).c_str(), counterpartBrick.c_str(), SabrinaCosts[rb]+SabrinaCosts[*iob], SabrinaCosts[counterpartBrick] ); } else nlwarning( "No matching phrase for counterpart %s", counterpartBrick.c_str() ); }*/ /* * Clear the form to reuse it (and all contents below node) */ void clearSheet( CForm *form, UFormElm* node ) { ((CFormElm*)node)->clean(); form->clean(); } /* * */ inline void explodeBrickAndParameters( const string& brickAndParams, vs& bricks ) { explode( brickAndParams, " ", bricks ); } /* * */ string getBrickType( const string& brick ) { if ( brick.size() < 4 ) return "INVALID TYPE in " + brick; else { switch ( brick[brick.size()-getBrickTypeLetterRPos(const_cast(brick))] ) { case 'P': return "Root"; break; case 'E': return "Effect"; break; case 'O': return "Option"; break; case 'M': return "Modifier"; break; case 'C': return "Credit"; break; default: return "INVALID TYPE in " + brick; } } } //----------------------------------------------- // printBrickInfo // //----------------------------------------------- void printBrickInfo( FILE *htmlfile, const string& brick, const string& grammarError, sint& sabrinaCost, uint& minSkillValue, string& minSkill ) { minSkill.clear(); string b = brick; strupr( b ); string brickType = getBrickType( b ); sint sc = (brickType=="Credit") ? -abs( SabrinaCosts[b] ) : SabrinaCosts[b]; CBrickInfo& bInfo = BrickInfo[b]; fprintf( htmlfile, "
  • %s %s %s
    \n", brickType.c_str(), b.c_str(), bInfo.Text.c_str() ); if ( ! grammarError.empty() ) { fprintf( htmlfile, "%s
    \n", grammarError.c_str() ); } else { fprintf( htmlfile, "Sabrina Cost: %d
    \n", sc ); if( !bInfo.LearnSkills.empty() ) { fprintf( htmlfile, "Skills required: %s
    \n", bInfo.LearnSkills.c_str() ); } if( bInfo.Props.size() ) { fprintf( htmlfile, "Properties:" ); for ( vs::const_iterator ip = bInfo.Props.begin(); ip!=bInfo.Props.end(); ++ip ) { fprintf( htmlfile, " %s", (*ip) ); } } } fprintf( htmlfile, "
  • \n" ); // Calculate sabrina cost & skill value sabrinaCost = sc; if ( bInfo.LearnSkills.empty() ) minSkillValue = 0; else { minSkillValue = ~0; vector skillsAndValues; explode( bInfo.LearnSkills, ":", skillsAndValues, true ); vector skillValues( skillsAndValues.size(), ~0 ); vector::iterator isv; for ( isv=skillsAndValues.begin(); isv!=skillsAndValues.end(); ++isv ) { const string& sav = *isv; string::size_type p = sav.find( ' ' ); if ( (p == string::npos) || (sav.size() == p+1) ) nlwarning( "Invalid LearnRequiresOneOfSkills value '%s'", sav.c_str() ); else { uint sv = atoi( sav.substr( p+1 ).c_str() ); skillValues[isv-skillsAndValues.begin()] = sv; if ( sv < minSkillValue ) minSkillValue = sv; } } for ( isv=skillsAndValues.begin(); isv!=skillsAndValues.end(); ++isv ) { if ( skillValues[isv-skillsAndValues.begin()] == minSkillValue ) { string& sav = *isv; if ( (! sav.empty()) && (sav[0] != 'S') ) sav = 'S' + sav; if ( minSkill.find( sav ) == string::npos ) { if ( ! minSkill.empty() ) minSkill += ", "; minSkill += sav; } } } } } // printBrickInfo // //----------------------------------------------- // loadBrickGrammar // //----------------------------------------------- void loadBrickGrammar() { uint nbRootBricks = 0; vs::const_iterator ib; for ( ib=AllBricks.begin(); ib!=AllBricks.end(); ++ib ) { string brick = *ib; strupr( brick ); if ( brick.size() >= 4 ) { char brickType = brick[brick.size()-getBrickTypeLetterRPos(brick)]; /*// As the root bricks may be absent from the table, deduce them (obsolete) if ( brickType == 'O' ) { string rootBrick = getRootBrickForOptionOrCredit( brick ); if ( GrammarOptionCreditBrickFamilies.find( rootBrick ) == GrammarOptionCreditBrickFamilies.end() ) { brick = rootBrick; brickType = 'P'; } else { continue; } }*/ // If not skipped by previous 'continue' if ( (brickType == 'P') || (brickType == 'E') || (brickType == 'O' ) ) // root, effect, option { NLMISC::CSmartPtr form = (CForm*)FormLoader->loadForm( (strlwr(static_cast(brick))+"."+brSheetType).c_str() ); if ( ! form ) { nlwarning( "Can't load sheet %s", ((strlwr(static_cast(brick)))+"."+phSheetType).c_str() ); continue; } for ( uint i=0; i!=12; ++i ) { string value; form->getRootNode().getValueByName( value, toString( "Mandatory.f%u", i ).c_str() ); if ( (! value.empty()) && (value != "Unknown") ) { GrammarMandatParamBrickFamilies[brick].push_back( value ); } } if ( brickType == 'O' ) { for ( uint i=0; i!=4; ++i ) { string value; form->getRootNode().getValueByName( value, toString( "Parameter.f%u", i ).c_str() ); if ( (! value.empty()) && (value != "Unknown") ) { GrammarMandatParamBrickFamilies[brick].push_back( value ); } } } if ( brickType == 'P' ) // root { ++nbRootBricks; for ( uint i=0; i!=32; ++i ) { string value; form->getRootNode().getValueByName( value, toString( "Optional.f%u", i ).c_str() ); if ( (! value.empty()) && (value != "Unknown") ) { GrammarOptionCreditBrickFamilies[brick].push_back( value ); } } for ( uint i=0; i!=12; ++i ) { string value; form->getRootNode().getValueByName( value, toString( "Credit.f%u", i ).c_str() ); if ( (! value.empty()) && (value != "Unknown") ) { GrammarOptionCreditBrickFamilies[brick].push_back( value ); } } } } } else { nlwarning( "Invalid brick code %s", brick.c_str() ); } } nlinfo( "%u bricks have mandatory/parameter grammar rules", GrammarMandatParamBrickFamilies.size() ); nlinfo( "%u bricks have option/credit grammar rules", GrammarOptionCreditBrickFamilies.size() ); nlinfo( "Found or deduced %u root bricks", nbRootBricks ); } // loadBrickGrammar // //----------------------------------------------- // loadPhraseTitles // //----------------------------------------------- void loadPhraseTitles() { STRING_MANAGER::TWorksheet worksheet; STRING_MANAGER::loadExcelSheet( "r:/code/ryzom/translation/translated/sphrase_words_en.txt", worksheet ); uint cp, cn; if ( worksheet.findCol( ucstring("sphrase ID"), cp ) && worksheet.findCol( ucstring("name"), cn ) ) { for ( std::vector::iterator ip = worksheet.begin(); ip!=worksheet.end(); ++ip ) { if ( ip == worksheet.begin() ) // skip first row continue; STRING_MANAGER::TWorksheet::TRow& row = *ip; PhraseTitles.insert( make_pair( strlwr(row[cp].toString()), row[cn].toUtf8() ) ); } } else nlwarning( "sphrase ID or name not found" ); nlinfo( "Loaded %u phrase titles", PhraseTitles.size() ); } // loadPhraseTitles // //----------------------------------------------- // loadBrickTitles // //----------------------------------------------- void loadBrickTitles() { STRING_MANAGER::TWorksheet worksheet; STRING_MANAGER::loadExcelSheet( "r:/code/ryzom/translation/translated/sbrick_words_en.txt", worksheet ); uint cp, cn, nbTitles = 0; if ( worksheet.findCol( ucstring("sbrick ID"), cp ) && worksheet.findCol( ucstring("name"), cn ) ) { for ( std::vector::iterator ip = worksheet.begin(); ip!=worksheet.end(); ++ip ) { if ( ip == worksheet.begin() ) // skip first row continue; STRING_MANAGER::TWorksheet::TRow& row = *ip; BrickInfo[strupr(row[cp].toString())].Text = row[cn].toUtf8();; ++nbTitles; } } else nlwarning( "sbrick ID or name not found" ); nlinfo( "Loaded %u brick titles", nbTitles ); } // loadBrickTitles // /* * */ void getChildrenBricks( const string& brick, vs& chFamilies ) { chFamilies = GrammarMandatParamBrickFamilies[brick]; } /* * */ void addError( string& errorStr, string& newError, uint& nbGrammarErrors ) { if ( ! errorStr.empty() ) errorStr += "
    "; errorStr += newError; ++nbGrammarErrors; } /* * */ void checkOptionOrCreditCompatibility( string& errorStr, const string& currentBrick, const string& rootBrick, uint& nbGrammarErrors ) { string brick = currentBrick; strupr( brick ); if ( brick.size() >= 4 && brick[1]!='C' && brick[1]!='H') // C & H for craft and harvest { char brickType = brick[brick.size()-getBrickTypeLetterRPos(brick)]; if ( (brickType == 'O') || (brickType == 'C') ) { string rootBrick = getRootBrickForOptionOrCredit( brick ); const vs& compatibleOptionOrCredits = GrammarOptionCreditBrickFamilies[rootBrick]; vs::const_iterator ic; for ( ic=compatibleOptionOrCredits.begin(); ic!=compatibleOptionOrCredits.end(); ++ic ) { if ( isFromBrickFamily( brick, (*ic) ) ) break; } if ( ic == compatibleOptionOrCredits.end() ) { addError( errorStr, toString( "This family is not compatible with options/credits of root %s", rootBrick.c_str() ), nbGrammarErrors ); } } } } /* * Preconditions: * - grammarErrors.size() == phrase.size() * - r < phrase.size() * * Note: does not check that all bricks should have a different family */ void checkGrammar( const vs& phrase, uint& r, vs& grammarErrors, uint& nbGrammarErrors, const string& rootBrick, bool readNext=true ) { uint origR = r; string grammarBrick = phrase[origR]; strupr( grammarBrick ); // Check option/credit checkOptionOrCreditCompatibility( grammarErrors[r], phrase[r], rootBrick, nbGrammarErrors ); // Check mandatory/parameter vs chFamilies; getChildrenBricks( grammarBrick, chFamilies ); ++r; for ( vs::const_iterator icf=chFamilies.begin(); icf!=chFamilies.end(); ++icf ) { // Detect incomplete phrase if ( r >= phrase.size() ) { addError( grammarErrors[origR], "Missing mandatory/parameter " + (*icf) + " at the end", nbGrammarErrors ); break; } // Detect wrong brick family if ( isFromBrickFamily( phrase[r], (*icf) ) ) { // Check grammar using child as root checkGrammar( phrase, r, grammarErrors, nbGrammarErrors, phrase[r], false ); } else { addError( grammarErrors[r], "Error: " + (*icf) + " expected (mandatory/parameter of " + grammarBrick + ")", nbGrammarErrors ); ++r; } } // Next if ( readNext && (r < phrase.size()) ) { checkGrammar( phrase, r, grammarErrors, nbGrammarErrors, rootBrick ); } } /* * */ char getDocFileLetter( const string& sheetName ) { // skip abm_mt_, abm_ml_... char letter = 'a'; uint nbUnderscoresToSkip = 2, nbUnderscoresFound = 0; for ( uint c=0; c!=sheetName.size(); ++c ) { if ( nbUnderscoresFound == nbUnderscoresToSkip ) { letter = sheetName[c]; break; } if ( sheetName[c] == '_' ) ++nbUnderscoresFound; } return tolower( letter ); } //----------------------------------------------- // testPhraseGrammarAndProduceDoc // //----------------------------------------------- bool testPhraseGrammarAndProduceDoc( const string& sheetName, const vs& phrase ) { string filename = strlwr( sheetName ) + "." + phSheetType; string phraseStatus; bool isPhraseCorrect = true; const char *rejectedstr = "(grammatically invalid)"; // Check grammar for this phrase vs grammarErrors( phrase.size() ); uint nbGrammarErrors = 0, r = 0; checkGrammar( phrase, r, grammarErrors, nbGrammarErrors, phrase[0] ); if ( nbGrammarErrors != 0 ) { InvalidPhrases.push_back( sheetName ); isPhraseCorrect = false; phraseStatus = rejectedstr; } // Look-up phrase title string phraseTitle = PhraseTitles[sheetName]; // Output phrase description char letter = 'a'; if ( (! MultipleDocFiles) && (sheetName.size() > 3) ) { letter = tolower( sheetName[3] ); } else { letter = getDocFileLetter( sheetName ); } if ( letter < 'a' ) letter = 'a'; else if ( letter > 'z' ) letter = 'z'; FILE *htmlFile = PhraseDocFiles[letter - 'a']; sint sabrinaCost; fprintf( htmlFile, "

    %s %s %s

      \n", sheetName.c_str(), filename.c_str(), phraseTitle.c_str(), phraseStatus.c_str() ); vector minBrickSkills( phrase.size() ); vector minBrickSkillValues( phrase.size(), 0 ); string brickMinSkill, maxSkill; sint posCost = 0, negCost = 0, totalCost; uint maxSkillValue = 0, brickMinSkillValue; for ( uint i=0; i!=phrase.size(); ++i ) { printBrickInfo( htmlFile, phrase[i], grammarErrors[i], sabrinaCost, brickMinSkillValue, brickMinSkill ); if ( sabrinaCost > 0 ) posCost += sabrinaCost; else negCost += sabrinaCost; minBrickSkillValues[i] = brickMinSkillValue; minBrickSkills[i] = brickMinSkill; if ( brickMinSkillValue > maxSkillValue ) maxSkillValue = brickMinSkillValue; } for ( uint i=0; i!=phrase.size(); ++i ) { if ( minBrickSkillValues[i] == maxSkillValue ) { if ( maxSkill.find( minBrickSkills[i] ) == string::npos ) { if ( ! maxSkill.empty() ) maxSkill += "; "; maxSkill += minBrickSkills[i]; } } } if ( phrase.size() > 1 ) { string effectOrOptionBrick = phrase[1]; strupr( effectOrOptionBrick ); if ( ! PhraseNames.insert( make_pair( sheetName, BrickInfo[effectOrOptionBrick].Text ) ).second ) nlwarning( "Found duplicate phrase %s", sheetName.c_str() ); } Progression.insert( make_pair( maxSkillValue, make_pair( sheetName, maxSkill ) ) ); totalCost = posCost + negCost; PhraseSabrinaCosts.insert( make_pair(sheetName,totalCost) ); char *redbegin = "", *redend = ""; if ( totalCost > 0 ) { map::const_iterator itCastable = PhraseCastable.find(sheetName); if( itCastable != PhraseCastable.end() ) { if( (*itCastable).second ) { redbegin = ""; redend = ""; PhrasesWithInvalidCost.push_back( sheetName ); isPhraseCorrect = false; } } } fprintf( htmlFile, "
    • %sTotal sabrina cost: +%d %d = %d%s
    • \n", redbegin, posCost, negCost, totalCost, redend ); fprintf( htmlFile, "
    • Minimum skill value required: %d
    • \n", maxSkillValue ); fprintf( htmlFile, "

    \n" ); if ( ! isPhraseCorrect ) { ++NbSheetsRejected; } return isPhraseCorrect; } // testPhraseGrammarAndProduceDoc // /* * */ inline bool isSeparator( char c ) { return (c == ' ') || (c == '\t'); } //----------------------------------------------- // produceDocFromExistingPhrases // // - Phrases //----------------------------------------------- void produceDocFromExistingPhrases() { vs files; CPath::getPathContent( PhrasePath, true, false, true, files ); NbSheetsRead = 0; for ( vs::const_iterator ip=files.begin(); ip!=files.end(); ++ip ) { if ( CFile::getExtension( *ip ) == phSheetType ) { // Read george sheet NLMISC::CSmartPtr form = (UForm*)FormLoader->loadForm( (*ip).c_str() ); if ( ! form ) nlerror( "Can't load sheet %s", (*ip).c_str() ); // Get the bricks of the phrase vs phrase; for ( uint i=0; i!=100; ++i ) { string value; form->getRootNode().getValueByName( value, toString( "brick %u", i ).c_str() ); if ( !value.empty() ) { strupr( value ); phrase.push_back( CFile::getFilenameWithoutExtension( value ) ); } } Phrases.insert( make_pair(CFile::getFilenameWithoutExtension( *ip ), phrase) ); // look if phrase is castable bool castable; form->getRootNode().getValueByName( castable, "castable"); PhraseCastable.insert( make_pair(CFile::getFilenameWithoutExtension( *ip ), castable) ); // Test grammar and produce doc testPhraseGrammarAndProduceDoc( CFile::getFilenameWithoutExtension( *ip ), phrase ); ++NbSheetsRead; } } nlinfo( "Total: %u phrases", NbSheetsRead ); } // produceDocFromExistingPhrases // /* * */ string getLink( const string& phrase ) { string res; if ( MultipleDocFiles && (! phrase.empty()) ) { res += DocFileName + "_" + getDocFileLetter( phrase ) + ".html"; } else { res += DocFileName + ".html"; } res += "#" + phrase; //nlinfo( "%s", res.c_str() ); return res; } /* * */ void usage(char *argv0, FILE *out) { fprintf(out, "\n"); fprintf(out, "Syntax: %s [-p ] [-o ] [-b] [-d] [-m] [-n]\n", argv0); fprintf(out, "-o: output phrase path (or input if -d is set)\n"); fprintf(out, "-b: produce doc about brick learning infos\n"); fprintf(out, "-d: browse existing phrases in (and subdirs) and produce doc\n"); fprintf(out, "-m: multiple doc html files, alphabetically (use with -g,-c,-d with numerous phrases)\n"); fprintf(out, "-n: no hypertext (don't produce links phrases)\n"); fprintf(out, "\n"); } //----------------------------------------------- // makeIndexFile // //----------------------------------------------- void makeIndexFile() { FILE * indexFile = nlfopen( "_" + DocFileNameRoot + "_INDEX.html", "wt" ); if( indexFile ) { fprintf( indexFile, ("\n\nSummary of " + DocFileNameRoot + "\n\n").c_str() ); DocFileName = DocFileNameRoot + "_actions"; if ( MultipleDocFiles ) { // One HTML file per alphabet letter for ( uint l=0; l!=26; ++l ) { string filename = toString( "%s_%c.html", DocFileName.c_str(), 'a'+l ); PhraseDocFiles[l] = nlfopen( filename, "wt" ); fprintf( PhraseDocFiles[l], ("\n\n" + DocFileName + toString( " - %c", (char)('A'+l) ) + "\n\n").c_str() ); fprintf( indexFile, ("" + (char)('A'+l) + " ").c_str() ); } } else { // One single HTML file fprintf( indexFile, ("Go to action details").c_str() ); PhraseDocFiles[0] = nlfopen( DocFileName + ".html", "wt" ); fprintf( PhraseDocFiles[0], ("\n\n" + DocFileName + "\n\n").c_str() ); for ( uint l=1; l!=26; ++l ) { PhraseDocFiles[l] = PhraseDocFiles[0]; } } fprintf( indexFile, ("
    Go to action by skill value\n").c_str() ); fprintf( indexFile, ("
    Go to action by skill value (detail)\n").c_str() ); fprintf( indexFile, ("
    Go to action by skill
    \n").c_str() ); if( GenerateBrickProgression ) { fprintf( indexFile, ("

    Go to brick list
    \n").c_str() ); } produceDocFromExistingPhrases(); for ( map< uint, pair >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip ) { const string& phraseCode = (*ip).second.first; string link = Hypertext ? toString( "%s", getLink(phraseCode).c_str(), phraseCode.c_str() ) : "" + phraseCode + ""; PhraseCodeToLink.insert( make_pair(phraseCode,link) ); } // Summary (errors in phrases) fprintf( indexFile, "
    \n" ); fprintf( indexFile, ("Summary of " + DocFileName + "
    \n").c_str() ); if ( NbSheetsGenTries != 0 ) fprintf( indexFile, "

    %u valid sheets written on %u

    \n", NbSheetsWritten, NbSheetsGenTries ); if ( NbSheetsRead != 0 ) fprintf( indexFile, "

    %u sheets read

    \n", NbSheetsRead ); fprintf( indexFile, "

    %u invalid sheets rejected", NbSheetsRejected ); if ( ! PhrasesWithInvalidCost.empty() ) { fprintf( indexFile, "

    Phrases with invalid sabrina cost:
    \n" ); for ( vs::const_iterator iip=PhrasesWithInvalidCost.begin(); iip!=PhrasesWithInvalidCost.end(); ++iip ) { string link = Hypertext ? toString( "%s", getLink(*iip).c_str(), (*iip).c_str() ) : "" + (*iip) + ""; fprintf( indexFile, "%s
    \n", link.c_str() ); } fprintf( indexFile, "

    \n" ); } else { fprintf( indexFile, "

    All phrases have valid sabrina cost.

    \n" ); } if ( ! InvalidPhrases.empty() ) { fprintf( indexFile, "

    Grammatically invalid phrases:
    \n" ); for ( vs::const_iterator iip=InvalidPhrases.begin(); iip!=InvalidPhrases.end(); ++iip ) { string link = Hypertext ? toString( "%s", getLink(*iip).c_str(), (*iip).c_str() ) : "" + (*iip) + ""; fprintf( indexFile, "%s
    \n", link.c_str() ); } fprintf( indexFile, "

    \n" ); } else { fprintf( indexFile, "

    All phrases are grammatically valid.

    \n" ); } fprintf( indexFile, "\n" ); fclose( indexFile ); if ( MultipleDocFiles ) { for ( uint l=0; l!=26; ++l ) { fprintf( PhraseDocFiles[l], "\n" ); fclose( PhraseDocFiles[l] ); } } else { fprintf( PhraseDocFiles[0], "\n" ); fclose( PhraseDocFiles[0] ); } } } // makeIndexFile // //----------------------------------------------- // makeActionsBySkillGroupFile // //----------------------------------------------- void makeActionsBySkillGroupFile() { // progression by skill FILE * actionsBySkillGroupFile = nlfopen( DocFileName + "__by_skill.html", "wt" ); if( actionsBySkillGroupFile ) { fprintf( actionsBySkillGroupFile, ("\n\nProgression of " + DocFileName + "\n\n").c_str() ); fprintf( actionsBySkillGroupFile, "
    \n" ); fprintf( actionsBySkillGroupFile, "

    ACTIONS BY SKILL GROUP:
    \n\n" ); map > phrasesBySkill; for ( map< uint, pair >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip ) { const string& phraseCode = (*ip).second.first; string skillName = (*ip).second.second.substr(0,(*ip).second.second.find(" ")); string skillValueStr = (*ip).second.second.substr((*ip).second.second.find(" ")+1,(*ip).second.second.size()-(*ip).second.second.find(" ")-1); uint skillValue = atoi(skillValueStr.c_str()); map >::iterator it = phrasesBySkill.find(skillName); if( it != phrasesBySkill.end() ) { (*it).second.insert(make_pair(skillValue,phraseCode)); } else { multimap m; m.insert(make_pair(skillValue,phraseCode)); phrasesBySkill.insert( make_pair(skillName,m) ); } } map >::iterator itPhrasesBySkill; for( itPhrasesBySkill = phrasesBySkill.begin(); itPhrasesBySkill != phrasesBySkill.end(); ++itPhrasesBySkill ) { CVectorSString dicoResult; Dico.lookup( (*itPhrasesBySkill).first, dicoResult, true ); if( !dicoResult.empty() ) fprintf( actionsBySkillGroupFile, "\n", (*itPhrasesBySkill).first.c_str(),dicoResult[0].c_str()); else fprintf( actionsBySkillGroupFile, "\n", (*itPhrasesBySkill).first.c_str(),(*itPhrasesBySkill).first.c_str()); } for( itPhrasesBySkill = phrasesBySkill.begin(); itPhrasesBySkill != phrasesBySkill.end(); ++itPhrasesBySkill ) { CVectorSString dicoResult; Dico.lookup( (*itPhrasesBySkill).first, dicoResult, true ); if( !dicoResult.empty() ) fprintf( actionsBySkillGroupFile, "\n", (*itPhrasesBySkill).first.c_str(), dicoResult[0].c_str() ); else fprintf( actionsBySkillGroupFile, "\n", (*itPhrasesBySkill).first.c_str(),(*itPhrasesBySkill).first.c_str() ); multimap::iterator it; for( it = (*itPhrasesBySkill).second.begin(); it != (*itPhrasesBySkill).second.end(); ++it ) { fprintf( actionsBySkillGroupFile, "\n", (*it).first, PhraseCodeToLink[(*it).second].c_str(), PhraseTitles[(*it).second].c_str()); } } fprintf( actionsBySkillGroupFile, "
    %s
    %s
    %s
    %s
    %d%s%s

    \n" ); fprintf( actionsBySkillGroupFile, "\n" ); fclose( actionsBySkillGroupFile ); } } // makeActionsBySkillGroupFile // //----------------------------------------------- // makeActionsBySkillValueFile // //----------------------------------------------- void makeActionsBySkillValueFile() { FILE * actionsBySkillValueFile = fopen( (DocFileName + "__by_skill_value.html").c_str(), "wt" ); if( actionsBySkillValueFile ) { fprintf( actionsBySkillValueFile, ("\n\nProgression of " + DocFileName + "\n\n").c_str() ); // Progression (phrases sorted by skill value) fprintf( actionsBySkillValueFile, "
    \n" ); fprintf( actionsBySkillValueFile, "

    ACTIONS BY SKILL VALUE: [detail]\n

    \n",(DocFileName + "__by_skill_value_detail.html").c_str() ); fprintf( actionsBySkillValueFile, "\n"); map phraseCodeToLink; for ( map< uint, pair >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip ) { const string& phraseCode = (*ip).second.first; fprintf( actionsBySkillValueFile, "\n", PhraseCodeToLink[phraseCode].c_str(), /*newbrickTitle.c_str(),*/ PhraseTitles[phraseCode].c_str(), (*ip).second.second.c_str() ); } fprintf( actionsBySkillValueFile, "
    FileNameSkill needed
    %s%s%s

    \n" ); fprintf( actionsBySkillValueFile, "\n" ); fclose( actionsBySkillValueFile ); } } // makeActionsBySkillValueFile // //----------------------------------------------- // makeActionsBySkillValueDetailFile // //----------------------------------------------- void makeActionsBySkillValueDetailFile() { FILE * actionsBySkillValueDetailFile = nlfopen( DocFileName + "__by_skill_value_detail.html", "wt" ); if( actionsBySkillValueDetailFile ) { fprintf( actionsBySkillValueDetailFile, ("\n\nProgression of " + DocFileName + "\n\n").c_str() ); // Progression summary (phrases sorted by skill value) fprintf( actionsBySkillValueDetailFile, "
    \n" ); fprintf( actionsBySkillValueDetailFile, "

    ACTIONS BY SKILL VALUE:
    \n

    \n" ); fprintf( actionsBySkillValueDetailFile, "\n"); set effects; map > effectAndModifiers; for ( map< uint, pair >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip ) { const string& phraseCode = (*ip).second.first; fprintf( actionsBySkillValueDetailFile, "",PhraseCodeToLink[phraseCode].c_str(), PhraseTitles[phraseCode].c_str(), (*ip).second.second.c_str(),PhraseSabrinaCosts[phraseCode]); msvs::iterator itPhrases = Phrases.find( phraseCode ); if( itPhrases != Phrases.end() ) { string effect; uint modifierCount = 0; uint creditCount = 0; for( uint i = 0; i<(*itPhrases).second.size(); ++i ) { string brick = (*itPhrases).second[i]; string color; switch ( brick[brick.size()-getBrickTypeLetterRPos(brick)] ) { case 'P': color = "Black"; break; case 'E': { color = "Brown"; effects.insert(brick); if( effectAndModifiers.find(brick) == effectAndModifiers.end() ) { set s; effectAndModifiers.insert( make_pair(brick,s) ); } effect = brick; } break; case 'O': color = "Green"; break; case 'M': { color = "Blue"; effectAndModifiers[effect].insert(brick); modifierCount++; } break; case 'C': color = "Red"; creditCount++; break; default: color = "Black"; } string text = BrickInfo[brick].Text; if( text.empty() ) { text = strlwr(brick); nlwarning("%s not found in BrickInfo",brick.c_str()); } else { if(text.find("$|sap")!=-1) { text = text.substr(0,text.size()-5); string str = brick.substr(brick.size()-5,5); text += toString(atoi(str.c_str())); } } fprintf( actionsBySkillValueDetailFile, "",color.c_str(),text.c_str()); } } else { nlerror("not found : %s",phraseCode.c_str()); } fprintf( actionsBySkillValueDetailFile, "\n"); } fprintf( actionsBySkillValueDetailFile, "
    FileNameSkill needed
    Sabrina costBricks ...
    %s%s%s%d%s

    \n" ); fprintf( actionsBySkillValueDetailFile, "\n" ); fclose( actionsBySkillValueDetailFile ); } } // makeActionsBySkillValueDetailFile // //----------------------------------------------- // validateBrick // //----------------------------------------------- bool validateBrick( const string& brk ) { if(brk[1]=='C') return true; if(brk[1]=='F') return true; if(brk[1]=='H') return true; if(brk[1]=='M') return true; if(brk[1]=='S') return true; return false; } // validateBrick // //----------------------------------------------- // makeSkillTreeFile // //----------------------------------------------- void makeSkillTreeFile( char filter, string skillFamily, bool withTraduction ) { vector > skillsArray; skillsArray.resize(6); // 6 tranches de skill uint i; for( i = 0; i maxLine ) { maxLine = skillsArray[i].size(); } } string filename = skillFamily + "_skill_tree.html"; string filenameWithTraduction = skillFamily + "_skill_tree_detailed.html"; FILE * skillTreeFile; if( withTraduction ) skillTreeFile = nlfopen( filenameWithTraduction, "wt" ); else skillTreeFile = nlfopen( filename, "wt" ); fprintf( skillTreeFile,"\n"); fprintf( skillTreeFile,"\n"); fprintf( skillTreeFile,"SKILL TREE ( %s )\n",skillFamily.c_str()); fprintf( skillTreeFile,"\n"); if( withTraduction ) fprintf( skillTreeFile,"SKILL TREE ( %s )\n",skillFamily.c_str()); else fprintf( skillTreeFile,"SKILL TREE ( %s ) [display traduction]
    \n",skillFamily.c_str(),filenameWithTraduction.c_str()); fprintf( skillTreeFile,"
    \n"); fprintf( skillTreeFile,"\n"); uint j; // print line by line for( j=0; j"); // for each column for( i=0; i::iterator itSkillcode; for( itSkillcode = skillsArray[i].begin(), p=0; itSkillcode != skillsArray[i].end() && p%s : ???",(*itSkillcode).first.c_str()); else fprintf( skillTreeFile,"",dicoResult[0].c_str()); } else fprintf( skillTreeFile,"",(*itSkillcode).first.c_str()); } else fprintf( skillTreeFile,""); } fprintf( skillTreeFile,"\n"); } fprintf( skillTreeFile, "
    0 to 2020 to 5050 to 100100 to 150150 to 200200 to 250
    %s%s

    \n" ); fprintf( skillTreeFile, "\n" ); fclose( skillTreeFile ); } // makeSkillTreeFile // //----------------------------------------------- // MAIN // //----------------------------------------------- int main(int argc, char* argv[]) { // parse command line const char *inputFilename = NULL; for ( uint i=1; (sint)i!=argc; i++ ) { const char *arg = argv[i]; if ( arg[0] == '-' ) { switch ( arg[1] ) { case 'p': ++i; if ( (sint)i == argc ) { fprintf( stderr, "Missing after -p option\n" ); usage( argv[0], stderr ); exit( 0 ); } inputSheetPath = argv[i]; break; case 'o': ++i; if ( (sint)i == argc ) { fprintf( stderr, "Missing after -o option\n" ); usage( argv[0], stderr ); exit( 0 ); } PhrasePath = argv[i]; if ( PhrasePath[PhrasePath.size()-1] != '/' ) PhrasePath += '/'; break; case 'b' : GenerateBrickProgression = true; break; case 'd': ProduceDocFromExistingPhrases = true; break; case 'm': MultipleDocFiles = true; break; case 'n': Hypertext = false; break; } } else { if ( CFile::getExtension(arg) == "csv" ) { inputFilename = arg; } else nlerror( "Unrecognized extension in %s", arg ); } } Dico.init(); loadSheetPath(); FormLoader = UFormLoader::createLoader(); CSheetId::init(); CSheetId skillTreeSheet("skills.skill_tree"); CSmartPtr skillTreeForm = FormLoader->loadForm( "skills.skill_tree" ); SkillsTree.readGeorges( skillTreeForm, skillTreeSheet ); makeSkillTreeFile('C',"craft", false); makeSkillTreeFile('F',"fight", false); makeSkillTreeFile('H',"forage", false); makeSkillTreeFile('M',"magic", false); makeSkillTreeFile('C',"craft", true); makeSkillTreeFile('F',"fight", true); makeSkillTreeFile('H',"forage", true); makeSkillTreeFile('M',"magic", true); // Load bricks from the csv UseBricks = ProduceDocFromExistingPhrases; if ( UseBricks ) { if ( ! inputFilename ) { usage( argv[0], stderr ); exit( 0 ); } loadBricks( inputFilename ); } // Phrases if ( ProduceDocFromExistingPhrases ) { loadBrickGrammar(); loadBrickTitles(); loadPhraseTitles(); DocFileNameRoot = toString( "%s", CFile::getFilenameWithoutExtension( inputFilename ).c_str() ); // index makeIndexFile(); // progression by skill makeActionsBySkillGroupFile(); // Progression (phrases sorted by skill value) makeActionsBySkillValueFile(); // Progression (phrases sorted by skill value + detail) makeActionsBySkillValueDetailFile(); } if( GenerateBrickProgression ) { map > > levelToBrick; map phraseToSkill; for ( map< uint, pair >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip ) { const string& phraseCode = (*ip).second.first; string skillTmp = (*ip).second.second.c_str(); phraseToSkill.insert( make_pair(phraseCode,skillTmp) ); if(skillTmp.empty()==false) { // get skill string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); // get level string levelStr; if( skillTmp.find(";") != -1 ) { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); } else { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); } if(levelStr.find(".")!=-1) levelStr = levelStr.substr(0,levelStr.size()-1); uint level = atoi(levelStr.c_str()); map > >::iterator itLvl = levelToBrick.find(level); if( itLvl == levelToBrick.end() ) { set s; map > mp; mp.insert(make_pair(skill,s)); levelToBrick.insert(make_pair(level,mp)); } else { if( (*itLvl).second.find(skill) == (*itLvl).second.end() ) { set s; (*itLvl).second.insert( make_pair(skill,s) ); } } msvs::iterator itPhrases = Phrases.find( phraseCode ); if( itPhrases != Phrases.end() ) { string effect; for( uint i = 0; i<(*itPhrases).second.size(); ++i ) { string brick = (*itPhrases).second[i]; if( levelToBrick[level][skill].find(brick) == levelToBrick[level][skill].end() ) { levelToBrick[level][skill].insert(brick); } } } } } // get family & color map brickToColor; map brickToFamily; map::iterator itBInf; for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) { string brk = (*itBInf).first; if(!validateBrick(brk)) continue; string color; string family; if( brk[brk.size()-getBrickTypeLetterRPos(brk)] =='M' ) { color = "Blue"; family = "Modifier"; } if( brk[brk.size()-getBrickTypeLetterRPos(brk)] =='C' ) { color = "Red"; family = "Credit"; } if( brk[brk.size()-getBrickTypeLetterRPos(brk)] =='O' ) { color = "Green"; family = "Option"; } if( brk[brk.size()-getBrickTypeLetterRPos(brk)] =='P' ) { color = "Black"; family = "Root"; } if( brk[brk.size()-getBrickTypeLetterRPos(brk)] =='E' ) { color = "Brown"; family = "Effect"; } brickToColor.insert(make_pair(brk,color)); brickToFamily.insert(make_pair(brk,family)); } // get phrases where the brick can be found map > brickToPhrases; msvs::iterator itPhrases; for( itPhrases=Phrases.begin(); itPhrases!=Phrases.end(); ++itPhrases ) { for( uint i = 0; i<(*itPhrases).second.size(); ++i ) { string brick = (*itPhrases).second[i]; if( brickToPhrases.find(brick)==brickToPhrases.end() ) { map m; m.insert(make_pair((*itPhrases).first,phraseToSkill[(*itPhrases).first])); brickToPhrases.insert(make_pair(brick,m)); } else { brickToPhrases[brick].insert(make_pair((*itPhrases).first,phraseToSkill[(*itPhrases).first])); } } } // get skill when a brick is learnt map brickToLearnSkill; map >::iterator itLearn; for( itLearn=brickToPhrases.begin(); itLearn!=brickToPhrases.end(); ++itLearn ) { string minSkill; uint minLevel = 250; mss::iterator itPh; for( itPh=(*itLearn).second.begin(); itPh!=(*itLearn).second.end(); ++itPh ) { string skillTmp = (*itPh).second; string levelStr; if( skillTmp.find(";") != -1 ) { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); } else { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); } uint level = atoi(levelStr.c_str()); if( level\n"); fprintf( brickPhraseDocFile_m,"\n"); fprintf( brickPhraseDocFile_m,"Brick phrases\n"); fprintf( brickPhraseDocFile_m,"\n"); fprintf( brickPhraseDocFile_m,"
    \n"); filename = DocFileNameRoot + "_c.html"; FILE * brickPhraseDocFile_c = nlfopen( filename, "wt" ); fprintf( brickPhraseDocFile_c,"\n"); fprintf( brickPhraseDocFile_c,"\n"); fprintf( brickPhraseDocFile_c,"Brick phrases\n"); fprintf( brickPhraseDocFile_c,"\n"); fprintf( brickPhraseDocFile_c,"
    \n"); filename = DocFileNameRoot + "_o.html"; FILE * brickPhraseDocFile_o = nlfopen( filename, "wt" ); fprintf( brickPhraseDocFile_o,"\n"); fprintf( brickPhraseDocFile_o,"\n"); fprintf( brickPhraseDocFile_o,"Brick phrases\n"); fprintf( brickPhraseDocFile_o,"\n"); fprintf( brickPhraseDocFile_o,"
    \n"); filename = DocFileNameRoot + "_p.html"; FILE * brickPhraseDocFile_p = nlfopen( filename, "wt" ); fprintf( brickPhraseDocFile_p,"\n"); fprintf( brickPhraseDocFile_p,"\n"); fprintf( brickPhraseDocFile_p,"Brick phrases\n"); fprintf( brickPhraseDocFile_p,"\n"); fprintf( brickPhraseDocFile_p,"
    \n"); filename = DocFileNameRoot + "_e.html"; FILE * brickPhraseDocFile_e = nlfopen( filename, "wt" ); fprintf( brickPhraseDocFile_e,"\n"); fprintf( brickPhraseDocFile_e,"\n"); fprintf( brickPhraseDocFile_e,"Brick phrases\n"); fprintf( brickPhraseDocFile_e,"\n"); fprintf( brickPhraseDocFile_e,"
    \n"); for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) { string brk = (*itBInf).first; if(!validateBrick(brk)) continue; string code = strlwr(brk.c_str()); if(brickToFamily[brk]=="Modifier") fprintf( brickPhraseDocFile_m,"\n",brk.c_str(),code.c_str()); if(brickToFamily[brk]=="Credit") fprintf( brickPhraseDocFile_c,"\n",brk.c_str(),code.c_str()); if(brickToFamily[brk]=="Option") fprintf( brickPhraseDocFile_o,"\n",brk.c_str(),code.c_str()); if(brickToFamily[brk]=="Effect") fprintf( brickPhraseDocFile_e,"\n",brk.c_str(),code.c_str()); if(brickToFamily[brk]=="Root") fprintf( brickPhraseDocFile_p,"\n",brk.c_str(),code.c_str()); map >::iterator itPhrases = brickToPhrases.find(brk); if( itPhrases != brickToPhrases.end() ) { map::iterator itPh; for( itPh=(*itPhrases).second.begin(); itPh!=(*itPhrases).second.end(); ++itPh ) { if(brickToFamily[brk]=="Modifier") fprintf( brickPhraseDocFile_m,"\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); if(brickToFamily[brk]=="Credit") fprintf( brickPhraseDocFile_c,"\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); if(brickToFamily[brk]=="Option") fprintf( brickPhraseDocFile_o,"\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); if(brickToFamily[brk]=="Effect") fprintf( brickPhraseDocFile_e,"\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); if(brickToFamily[brk]=="Root") fprintf( brickPhraseDocFile_p,"\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); } } } fprintf( brickPhraseDocFile_m, "
    %s
    %s
    %s
    %s
    %s
    %s
    %s
    %s
    %s
    %s

    \n" ); fprintf( brickPhraseDocFile_m, "\n" ); fclose( brickPhraseDocFile_m ); fprintf( brickPhraseDocFile_c, "

    \n" ); fprintf( brickPhraseDocFile_c, "\n" ); fclose( brickPhraseDocFile_c ); fprintf( brickPhraseDocFile_o, "

    \n" ); fprintf( brickPhraseDocFile_o, "\n" ); fclose( brickPhraseDocFile_o ); fprintf( brickPhraseDocFile_e, "

    \n" ); fprintf( brickPhraseDocFile_e, "\n" ); fclose( brickPhraseDocFile_e ); fprintf( brickPhraseDocFile_p, "

    \n" ); fprintf( brickPhraseDocFile_p, "\n" ); fclose( brickPhraseDocFile_p ); // CODE // write header and title bar filename = DocFileNameRoot + ".html"; FILE * brickDocFile = nlfopen( filename, "wt" ); fprintf( brickDocFile,"\n"); fprintf( brickDocFile,"\n"); fprintf( brickDocFile,"Bricks infos\n"); fprintf( brickDocFile,"\n"); fprintf( brickDocFile,"
    \n"); fprintf( brickDocFile,"\n"); fprintf( brickDocFile,"\n"); fprintf( brickDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickDocFile,"\n"); fprintf( brickDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickDocFile,"\n"); fprintf( brickDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickDocFile,"\n"); fprintf( brickDocFile,"\n"); // write infos for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) { string brk = (*itBInf).first; if(!validateBrick(brk)) continue; string skillTmp = (*itBInf).second.LearnSkills; string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); CVectorSString dicoResult; Dico.lookup( skill, dicoResult, true ); if(dicoResult.empty()) continue; // color string color = brickToColor[brk]; // code string code = strlwr(brk.c_str()); fprintf( brickDocFile, "\n",color.c_str(),code.c_str()); // name string name = (*itBInf).second.Text; fprintf( brickDocFile, "\n",name.c_str()); // family string family = brickToFamily[brk]; fprintf( brickDocFile, "\n",color.c_str(),family.c_str()); // required skill name fprintf( brickDocFile, "\n",dicoResult[0].c_str()); // required skill value string levelStr; if( skillTmp.find(";") != -1 ) { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); } else { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); } fprintf( brickDocFile, "\n",levelStr.c_str()); // learn skill name string learnSkillTmp = brickToLearnSkill[brk]; skill = learnSkillTmp.substr(0,learnSkillTmp.find_first_of(" ")); fprintf( brickDocFile, "\n",skill.c_str()); // learn skill value if( learnSkillTmp.find(";") != -1 ) { sint idx = learnSkillTmp.find_first_of(" "); levelStr = learnSkillTmp.substr(idx+1,learnSkillTmp.find_first_of(";")-idx-1); } else { sint idx = learnSkillTmp.find_first_of(" "); levelStr = learnSkillTmp.substr(idx+1,learnSkillTmp.size()-idx); } fprintf( brickDocFile, "\n",levelStr.c_str()); // phrase list fprintf( brickDocFile, "\n"); } fprintf( brickDocFile, "
    *Code*NameFamilyRequired Skill NameRequired Skill ValueLearn Skill NameLearn Skill ValueFound In Phrases
    %s%s%s%s%s%s%s"); map >::iterator itPhrases = brickToPhrases.find(brk); if( itPhrases != brickToPhrases.end() ) { map::iterator itPh; uint i; for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i ) { if( MultipleDocFiles ) fprintf( brickDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); else fprintf( brickDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str()); } if( i==2 ) { char type = family[0]; fprintf( brickDocFile,"[...]",DocFileNameRoot.c_str(),type,brk.c_str()); } } fprintf( brickDocFile, "

    \n" ); fprintf( brickDocFile, "\n" ); fclose( brickDocFile ); // NAME // write header and title bar filename = DocFileNameRoot + "_name.html"; FILE * brickNameDocFile = nlfopen( filename, "wt" ); fprintf( brickNameDocFile,"\n"); fprintf( brickNameDocFile,"\n"); fprintf( brickNameDocFile,"Bricks infos\n"); fprintf( brickNameDocFile,"\n"); fprintf( brickNameDocFile,"
    \n"); fprintf( brickNameDocFile,"\n"); fprintf( brickNameDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickNameDocFile,"\n"); fprintf( brickNameDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickNameDocFile,"\n"); fprintf( brickNameDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickNameDocFile,"\n"); fprintf( brickNameDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickNameDocFile,"\n"); fprintf( brickNameDocFile,"\n"); map nameToCode; for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) { string brk = (*itBInf).first; if(!validateBrick(brk)) continue; // code string code = strlwr(brk.c_str()); // name string name = (*itBInf).second.Text; if( !name.empty()) nameToCode.insert( make_pair(name,brk) ); } mss::iterator itNTC; for( itNTC=nameToCode.begin(); itNTC!=nameToCode.end(); ++itNTC ) { itBInf=BrickInfo.find((*itNTC).second); string brk = (*itBInf).first; if(!validateBrick(brk)) continue; string skillTmp = (*itBInf).second.LearnSkills; string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); CVectorSString dicoResult; Dico.lookup( skill, dicoResult, true ); if(dicoResult.empty()) continue; // color string color = brickToColor[brk]; // code string code = strlwr(brk.c_str()); fprintf( brickNameDocFile, "\n",color.c_str(),code.c_str()); // name string name = (*itBInf).second.Text; fprintf( brickNameDocFile, "\n",name.c_str()); // family string family = brickToFamily[brk]; fprintf( brickNameDocFile, "\n",color.c_str(),family.c_str()); // required skill name fprintf( brickNameDocFile, "\n",dicoResult[0].c_str()); // required skill value string levelStr; if( skillTmp.find(";") != -1 ) { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); } else { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); } fprintf( brickNameDocFile, "\n",levelStr.c_str()); // learn skill name skillTmp = brickToLearnSkill[brk]; skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); fprintf( brickNameDocFile, "\n",skill.c_str()); // learn skill value if( skillTmp.find(";") != -1 ) { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); } else { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); } fprintf( brickNameDocFile, "\n",levelStr.c_str()); // phrase list fprintf( brickNameDocFile, "\n"); } fprintf( brickNameDocFile, "
    Code*Name*FamilyRequired Skill NameRequired Skill ValueLearn Skill NameLearn Skill ValueFound In Phrases
    %s%s%s%s%s%s%s"); map >::iterator itPhrases = brickToPhrases.find(brk); if( itPhrases != brickToPhrases.end() ) { map::iterator itPh; uint i; for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i ) { if( MultipleDocFiles ) fprintf( brickNameDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); else fprintf( brickNameDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str()); } if( i==2 ) { char type = family[0]; fprintf( brickNameDocFile,"[...]",DocFileNameRoot.c_str(),type,brk.c_str()); } } fprintf( brickNameDocFile, "

    \n" ); fprintf( brickNameDocFile, "\n" ); fclose( brickNameDocFile ); // FAMILY // write header and title bar filename = DocFileNameRoot + "_family.html"; FILE * brickFamilyDocFile = nlfopen( filename, "wt" ); fprintf( brickFamilyDocFile,"\n"); fprintf( brickFamilyDocFile,"\n"); fprintf( brickFamilyDocFile,"Bricks infos\n"); fprintf( brickFamilyDocFile,"\n"); fprintf( brickFamilyDocFile,"
    \n"); fprintf( brickFamilyDocFile,"\n"); fprintf( brickFamilyDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickFamilyDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickFamilyDocFile,"\n"); fprintf( brickFamilyDocFile,"\n"); fprintf( brickFamilyDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickFamilyDocFile,"\n"); fprintf( brickFamilyDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickFamilyDocFile,"\n"); fprintf( brickFamilyDocFile,"\n"); // write infos multimap familyToCode; for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) { string brk = (*itBInf).first; if(!validateBrick(brk)) continue; // family string family = brickToFamily[brk]; familyToCode.insert( make_pair(family,brk) ); } multimap::iterator itFTC; for( itFTC=familyToCode.begin(); itFTC!=familyToCode.end(); ++itFTC ) { itBInf=BrickInfo.find((*itFTC).second); string brk = (*itBInf).first; if(!validateBrick(brk)) continue; string skillTmp = (*itBInf).second.LearnSkills; string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); CVectorSString dicoResult; Dico.lookup( skill, dicoResult, true ); if(dicoResult.empty()) continue; // color string color = brickToColor[brk]; // code string code = strlwr(brk.c_str()); fprintf( brickFamilyDocFile, "\n",color.c_str(),code.c_str()); // name string name = (*itBInf).second.Text; fprintf( brickFamilyDocFile, "\n",name.c_str()); // family string family = brickToFamily[brk]; fprintf( brickFamilyDocFile, "\n",color.c_str(),family.c_str()); // required skill name fprintf( brickFamilyDocFile, "\n",dicoResult[0].c_str()); // required skill value string levelStr; if( skillTmp.find(";") != -1 ) { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); } else { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); } fprintf( brickFamilyDocFile, "\n",levelStr.c_str()); // learn skill name skillTmp = brickToLearnSkill[brk]; skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); fprintf( brickFamilyDocFile, "\n",skill.c_str()); // learn skill value if( skillTmp.find(";") != -1 ) { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); } else { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); } fprintf( brickFamilyDocFile, "\n",levelStr.c_str()); // phrase list fprintf( brickFamilyDocFile, "\n"); } fprintf( brickFamilyDocFile, "
    CodeName*Family*Required Skill NameRequired Skill ValueLearn Skill NameLearn Skill ValueFound In Phrases
    %s%s%s%s%s%s%s"); map >::iterator itPhrases = brickToPhrases.find(brk); if( itPhrases != brickToPhrases.end() ) { map::iterator itPh; uint i; for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i ) { if( MultipleDocFiles ) fprintf( brickFamilyDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); else fprintf( brickFamilyDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str()); } if( i==2 ) { char type = family[0]; fprintf( brickFamilyDocFile,"[...]",DocFileNameRoot.c_str(),type,brk.c_str()); } } fprintf( brickFamilyDocFile, "

    \n" ); fprintf( brickFamilyDocFile, "\n" ); fclose( brickFamilyDocFile ); // REQUIRED SKILL VALUE // write header and title bar filename = DocFileNameRoot + "_required_skill_value.html"; FILE * brickRequiredDocFile = nlfopen( filename, "wt" ); fprintf( brickRequiredDocFile,"\n"); fprintf( brickRequiredDocFile,"\n"); fprintf( brickRequiredDocFile,"Bricks infos\n"); fprintf( brickRequiredDocFile,"\n"); fprintf( brickRequiredDocFile,"
    \n"); fprintf( brickRequiredDocFile,"\n"); fprintf( brickRequiredDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickRequiredDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickRequiredDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickRequiredDocFile,"\n"); fprintf( brickRequiredDocFile,"\n"); fprintf( brickRequiredDocFile,"\n"); fprintf( brickRequiredDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickRequiredDocFile,"\n"); fprintf( brickRequiredDocFile,"\n"); // write infos multimap requiredSkillValueToCode; for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) { string brk = (*itBInf).first; if(!validateBrick(brk)) continue; // required skill value string skillTmp = (*itBInf).second.LearnSkills; string levelStr; if( skillTmp.find(";") != -1 ) { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); } else { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); } uint level = atoi(levelStr.c_str()); requiredSkillValueToCode.insert( make_pair(level,brk) ); } multimap::iterator itRTC; for( itRTC=requiredSkillValueToCode.begin(); itRTC!=requiredSkillValueToCode.end(); ++itRTC ) { itBInf=BrickInfo.find((*itRTC).second); string brk = (*itBInf).first; if(!validateBrick(brk)) continue; string skillTmp = (*itBInf).second.LearnSkills; string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); CVectorSString dicoResult; Dico.lookup( skill, dicoResult, true ); if(dicoResult.empty()) continue; // color string color = brickToColor[brk]; // code string code = strlwr(brk.c_str()); fprintf( brickRequiredDocFile, "\n",color.c_str(),code.c_str()); // name string name = (*itBInf).second.Text; fprintf( brickRequiredDocFile, "\n",name.c_str()); // family string family = brickToFamily[brk]; fprintf( brickRequiredDocFile, "\n",color.c_str(),family.c_str()); // required skill name fprintf( brickRequiredDocFile, "\n",dicoResult[0].c_str()); // required skill value string levelStr; if( skillTmp.find(";") != -1 ) { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); } else { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); } fprintf( brickRequiredDocFile, "\n",levelStr.c_str()); // learn skill name skillTmp = brickToLearnSkill[brk]; skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); fprintf( brickRequiredDocFile, "\n",skill.c_str()); // learn skill value if( skillTmp.find(";") != -1 ) { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); } else { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); } fprintf( brickRequiredDocFile, "\n",levelStr.c_str()); // phrase list fprintf( brickRequiredDocFile, "\n"); } fprintf( brickRequiredDocFile, "
    CodeNameFamilyRequired Skill Name*Required Skill Value*Learn Skill NameLearn Skill ValueFound In Phrases
    %s%s%s%s%s%s%s"); map >::iterator itPhrases = brickToPhrases.find(brk); if( itPhrases != brickToPhrases.end() ) { map::iterator itPh; uint i; for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i ) { if( MultipleDocFiles ) fprintf( brickRequiredDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); else fprintf( brickRequiredDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str()); } if( i==2 ) { char type = family[0]; fprintf( brickRequiredDocFile,"[...]",DocFileNameRoot.c_str(),type,brk.c_str()); } } fprintf( brickRequiredDocFile, "

    \n" ); fprintf( brickRequiredDocFile, "\n" ); fclose( brickRequiredDocFile ); // LEARN SKILL VALUE // write header and title bar filename = DocFileNameRoot + "_learn_skill_value.html"; FILE * brickLearnDocFile = nlfopen( filename, "wt" ); fprintf( brickLearnDocFile,"\n"); fprintf( brickLearnDocFile,"\n"); fprintf( brickLearnDocFile,"Bricks infos\n"); fprintf( brickLearnDocFile,"\n"); fprintf( brickLearnDocFile,"
    \n"); fprintf( brickLearnDocFile,"\n"); fprintf( brickLearnDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickLearnDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickLearnDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickLearnDocFile,"\n"); fprintf( brickLearnDocFile,"\n",DocFileNameRoot.c_str()); fprintf( brickLearnDocFile,"\n"); fprintf( brickLearnDocFile,"\n"); fprintf( brickLearnDocFile,"\n"); fprintf( brickLearnDocFile,"\n"); // write infos multimap learnSkillValueToCode; for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) { string brk = (*itBInf).first; if(!validateBrick(brk)) continue; // learn skill value string skillTmp = brickToLearnSkill[brk]; string levelStr; if( skillTmp.find(";") != -1 ) { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); } else { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); } uint level = atoi(levelStr.c_str()); learnSkillValueToCode.insert( make_pair(level,brk) ); } multimap::iterator itLTC; for( itLTC=learnSkillValueToCode.begin(); itLTC!=learnSkillValueToCode.end(); ++itLTC ) { itBInf=BrickInfo.find((*itLTC).second); string brk = (*itBInf).first; if(!validateBrick(brk)) continue; string skillTmp = (*itBInf).second.LearnSkills; string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); CVectorSString dicoResult; Dico.lookup( skill, dicoResult, true ); if(dicoResult.empty()) continue; // color string color = brickToColor[brk]; // code string code = strlwr(brk.c_str()); fprintf( brickLearnDocFile, "\n",color.c_str(),code.c_str()); // name string name = (*itBInf).second.Text; fprintf( brickLearnDocFile, "\n",name.c_str()); // family string family = brickToFamily[brk]; fprintf( brickLearnDocFile, "\n",color.c_str(),family.c_str()); // required skill name fprintf( brickLearnDocFile, "\n",dicoResult[0].c_str()); // required skill value string levelStr; if( skillTmp.find(";") != -1 ) { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); } else { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); } fprintf( brickLearnDocFile, "\n",levelStr.c_str()); // learn skill name skillTmp = brickToLearnSkill[brk]; skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); fprintf( brickLearnDocFile, "\n",skill.c_str()); // learn skill value if( skillTmp.find(";") != -1 ) { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); } else { sint idx = skillTmp.find_first_of(" "); levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); } fprintf( brickLearnDocFile, "\n",levelStr.c_str()); // phrase list fprintf( brickLearnDocFile, "\n"); } fprintf( brickLearnDocFile, "
    CodeNameFamilyRequired Skill NameRequired Skill ValueLearn Skill Name*Learn Skill Value*Found In Phrases
    %s%s%s%s%s%s%s"); map >::iterator itPhrases = brickToPhrases.find(brk); if( itPhrases != brickToPhrases.end() ) { map::iterator itPh; uint i; for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i ) { if( MultipleDocFiles ) fprintf( brickLearnDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); else fprintf( brickLearnDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str()); } if( i==2 ) { char type = family[0]; fprintf( brickLearnDocFile,"[...]",DocFileNameRoot.c_str(),type,brk.c_str()); } } fprintf( brickLearnDocFile, "

    \n" ); fprintf( brickLearnDocFile, "\n" ); fclose( brickLearnDocFile ); } return 0; } // main //