2756 lines
85 KiB
C++
2756 lines
85 KiB
C++
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
|
// 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 <http://www.gnu.org/licenses/>.
|
|
|
|
// 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 <nel/misc/types_nl.h>
|
|
#include "nel/misc/path.h"
|
|
#include "nel/misc/file.h"
|
|
#include "nel/misc/smart_ptr.h"
|
|
#include "nel/misc/command.h"
|
|
#include "nel/misc/path.h"
|
|
#include <nel/misc/sstring.h>
|
|
#include <nel/misc/diff_tool.h>
|
|
#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 <time.h>
|
|
#include <stdio.h>
|
|
#include <conio.h>
|
|
#include <fstream>
|
|
// stl
|
|
#include <map>
|
|
|
|
#include "skill_tree.h"
|
|
|
|
using namespace NLMISC;
|
|
using namespace NLGEORGES;
|
|
using namespace std;
|
|
|
|
|
|
typedef vector<string> 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<string> UsedCounterpartBricks, UsedCounterpartBrickFamiliesInPhrase;
|
|
map<string, sint> SabrinaCosts;
|
|
map<string, sint> PhraseSabrinaCosts;
|
|
map<string, bool> PhraseCastable;
|
|
map<string, CBrickInfo> BrickInfo;
|
|
mss TextToBrick;
|
|
multimap< uint, pair<string, string> > Progression; // phrase code, min. skill
|
|
mss PhraseNames, PhraseTitles;
|
|
vector<vs> ValidPhrases;
|
|
set<string> UsedBricks, GeneratedPhrases;
|
|
map<string, vs> GrammarMandatParamBrickFamilies, GrammarOptionCreditBrickFamilies;
|
|
UFormLoader *FormLoader;
|
|
vector<FILE*> PhraseDocFiles( 26 );
|
|
string DocFileName,DocFileNameRoot;
|
|
msvs Phrases;
|
|
map<string,uint> SkillNameToMaxSkill;
|
|
map<string,string> PhraseCodeToLink;
|
|
CWordsDictionary Dico;
|
|
CStaticSkillsTree SkillsTree;
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
string inputSheetPath;
|
|
bool inputSheetPathLoaded = false;
|
|
map<string, string> inputSheetPathContent; // short filename without ext, full filename with path
|
|
|
|
|
|
//-----------------------------------------------
|
|
// getBrickTypeLetterRPos
|
|
//
|
|
//-----------------------------------------------
|
|
uint getBrickTypeLetterRPos( string& brick )
|
|
{
|
|
/*
|
|
uint i =0;
|
|
while( i<brick.size() && !isdigit(brick[i]) )
|
|
i++;
|
|
|
|
nlassert(i<brick.size());
|
|
|
|
return (brick.size() - i + 2);
|
|
*/
|
|
|
|
uint i =brick.size()-1;
|
|
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<string> files;
|
|
CPath::getPathContent (inputSheetPath, true, false, true, files);
|
|
|
|
uint i;
|
|
for (i=0; i<files.size(); ++i)
|
|
{
|
|
string filename = files[i];
|
|
string filebase = CFile::getFilenameWithoutExtension(filename);
|
|
if( CFile::getExtension(filename)!="saibrick" && CFile::getExtension(filename)!="saiphrase" )
|
|
{
|
|
inputSheetPathContent[filebase] = filename;
|
|
}
|
|
}
|
|
|
|
inputSheetPathLoaded = true;
|
|
|
|
} // loadSheetPath //
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
void displayList( const string& title, const vector<string>& v, CLog *log=DebugLog )
|
|
{
|
|
if ( ! title.empty() )
|
|
log->displayRaw( "%s: ", title.c_str() );
|
|
vector<string>::const_iterator ist;
|
|
for ( ist=v.begin(); ist!=v.end(); ++ist )
|
|
log->displayRaw( "%s ", (*ist).c_str() );
|
|
log->displayRawNL( "" );
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
class CStrIComparator : public binary_function<string, string, bool>
|
|
{
|
|
public:
|
|
bool operator() ( const string& s1, const string& s2 ) const
|
|
{
|
|
return (nlstricmp( s1, s2 ) == 0);
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
uint getIndexFromString( const string& s, const vector<string>& v, bool displayWarning=true )
|
|
{
|
|
if ( v.empty() )
|
|
{
|
|
nlwarning( "Can't find '%s' in empty array", s.c_str() );
|
|
return ~0;
|
|
}
|
|
else
|
|
{
|
|
vector<string>::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<string> args;
|
|
vector<string>::iterator iarg;
|
|
|
|
if ( (file = fopen( 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<string> 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("<brickDeliveryCallback> 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<string>::const_iterator iss;
|
|
for ( iss=Skills.begin(); iss!=Skills.end(); ++iss )
|
|
{
|
|
const string& skill = (*iss);
|
|
InfoLog->displayRawNL( " <DEFINITION Label=\"S%s\" Value=\"S%s\"/>", 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<string&>(ob));
|
|
if ( (ob.size() <= getBrickTypeLetterRPos(const_cast<string&>(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<string&>(b))+2 )
|
|
{
|
|
string::size_type p = b.size() - getBrickTypeLetterRPos(const_cast<string&>(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<string, sint>::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<string&>(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, "<LI><B>%s %s</B> %s<BR>\n", brickType.c_str(), b.c_str(), bInfo.Text.c_str() );
|
|
if ( ! grammarError.empty() )
|
|
{
|
|
fprintf( htmlfile, "<FONT COLOR=\"RED\">%s</FONT><BR>\n", grammarError.c_str() );
|
|
}
|
|
else
|
|
{
|
|
fprintf( htmlfile, "Sabrina Cost: %d <BR>\n", sc );
|
|
if( !bInfo.LearnSkills.empty() )
|
|
{
|
|
fprintf( htmlfile, "Skills required: %s<BR>\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, "</LI>\n" );
|
|
|
|
// Calculate sabrina cost & skill value
|
|
sabrinaCost = sc;
|
|
if ( bInfo.LearnSkills.empty() )
|
|
minSkillValue = 0;
|
|
else
|
|
{
|
|
minSkillValue = ~0;
|
|
vector<string> skillsAndValues;
|
|
explode( bInfo.LearnSkills, ":", skillsAndValues, true );
|
|
vector<uint> skillValues( skillsAndValues.size(), ~0 );
|
|
vector<string>::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<CForm> form = (CForm*)FormLoader->loadForm( (strlwr(static_cast<const string&>(brick))+"."+brSheetType).c_str() );
|
|
if ( ! form )
|
|
{
|
|
nlwarning( "Can't load sheet %s", ((strlwr(static_cast<const string&>(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<STRING_MANAGER::TWorksheet::TRow>::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<STRING_MANAGER::TWorksheet::TRow>::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 += "<BR>";
|
|
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, "<A NAME=\"%s\"></A><P><B>%s</B> %s %s<BR><UL>\n", sheetName.c_str(), filename.c_str(), phraseTitle.c_str(), phraseStatus.c_str() );
|
|
vector<string> minBrickSkills( phrase.size() );
|
|
vector<uint> 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<string,bool>::const_iterator itCastable = PhraseCastable.find(sheetName);
|
|
if( itCastable != PhraseCastable.end() )
|
|
{
|
|
if( (*itCastable).second )
|
|
{
|
|
redbegin = "<FONT COLOR=\"RED\">";
|
|
redend = "</FONT>";
|
|
PhrasesWithInvalidCost.push_back( sheetName );
|
|
isPhraseCorrect = false;
|
|
}
|
|
}
|
|
}
|
|
fprintf( htmlFile, "<LI>%s<B>Total sabrina cost: </B>+%d %d = %d%s</LI>\n", redbegin, posCost, negCost, totalCost, redend );
|
|
fprintf( htmlFile, "<LI><B>Minimum skill value required: %d</B></LI>\n", maxSkillValue );
|
|
fprintf( htmlFile, "</UL></P>\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<UForm> 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 <sheet path>] <bricksFilename> [-o <phrasePath>] [-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 <phrasePath> (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 = fopen( ("_" + DocFileNameRoot + "_INDEX.html").c_str(), "wt" );
|
|
if( indexFile )
|
|
{
|
|
fprintf( indexFile, ("<html><head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n<title>Summary of " + DocFileNameRoot + "</title>\n</head><body>\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] = fopen( filename.c_str(), "wt" );
|
|
fprintf( PhraseDocFiles[l], ("<html><head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n<title>" + DocFileName + toString( " - %c", (char)('A'+l) ) + "</title>\n</head><body>\n").c_str() );
|
|
fprintf( indexFile, ("<A HREF=\"" + filename + "\">" + (char)('A'+l) + "</A> ").c_str() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// One single HTML file
|
|
fprintf( indexFile, ("<A HREF=\"" + DocFileName + ".html\">Go to action details</A>").c_str() );
|
|
PhraseDocFiles[0] = fopen( (DocFileName + ".html").c_str(), "wt" );
|
|
fprintf( PhraseDocFiles[0], ("<html><head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n<title>" + DocFileName + "</title>\n</head><body>\n").c_str() );
|
|
for ( uint l=1; l!=26; ++l )
|
|
{
|
|
PhraseDocFiles[l] = PhraseDocFiles[0];
|
|
}
|
|
}
|
|
fprintf( indexFile, ("<BR><A HREF=\"" + DocFileName + "__by_skill_value.html" + "\">Go to action by skill value</A>\n").c_str() );
|
|
fprintf( indexFile, ("<BR><A HREF=\"" + DocFileName + "__by_skill_value_detail.html" + "\">Go to action by skill value (detail)</A>\n").c_str() );
|
|
fprintf( indexFile, ("<BR><A HREF=\"" + DocFileName + "__by_skill.html" + "\">Go to action by skill</A><BR>\n").c_str() );
|
|
|
|
if( GenerateBrickProgression )
|
|
{
|
|
fprintf( indexFile, ("<BR><BR><A HREF=\"" + DocFileNameRoot + ".html" + "\">Go to brick list</A><BR>\n").c_str() );
|
|
}
|
|
|
|
produceDocFromExistingPhrases();
|
|
|
|
for ( map< uint, pair<string, string> >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip )
|
|
{
|
|
const string& phraseCode = (*ip).second.first;
|
|
string link = Hypertext ? toString( "<A HREF=\"%s\">%s</A>", getLink(phraseCode).c_str(), phraseCode.c_str() ) : "<B>" + phraseCode + "</B>";
|
|
PhraseCodeToLink.insert( make_pair(phraseCode,link) );
|
|
}
|
|
|
|
// Summary (errors in phrases)
|
|
fprintf( indexFile, "<BR><A NAME=\"summary\"></A>\n" );
|
|
fprintf( indexFile, ("<FONT SIZE=\"20\">Summary of " + DocFileName + "</FONT><BR>\n").c_str() );
|
|
if ( NbSheetsGenTries != 0 )
|
|
fprintf( indexFile, "<P>%u valid sheets written on %u</P>\n", NbSheetsWritten, NbSheetsGenTries );
|
|
if ( NbSheetsRead != 0 )
|
|
fprintf( indexFile, "<P>%u sheets read</P>\n", NbSheetsRead );
|
|
fprintf( indexFile, "<P>%u invalid sheets rejected", NbSheetsRejected );
|
|
if ( ! PhrasesWithInvalidCost.empty() )
|
|
{
|
|
fprintf( indexFile, "<P><B>Phrases with invalid sabrina cost:</B><BR>\n" );
|
|
for ( vs::const_iterator iip=PhrasesWithInvalidCost.begin(); iip!=PhrasesWithInvalidCost.end(); ++iip )
|
|
{
|
|
string link = Hypertext ? toString( "<A HREF=\"%s\">%s</A>", getLink(*iip).c_str(), (*iip).c_str() ) : "<B>" + (*iip) + "</B>";
|
|
fprintf( indexFile, "%s<BR>\n", link.c_str() );
|
|
}
|
|
fprintf( indexFile, "</P>\n" );
|
|
}
|
|
else
|
|
{
|
|
fprintf( indexFile, "<P><B>All phrases have valid sabrina cost.</B></P>\n" );
|
|
}
|
|
if ( ! InvalidPhrases.empty() )
|
|
{
|
|
fprintf( indexFile, "<P><B>Grammatically invalid phrases:</B><BR>\n" );
|
|
for ( vs::const_iterator iip=InvalidPhrases.begin(); iip!=InvalidPhrases.end(); ++iip )
|
|
{
|
|
string link = Hypertext ? toString( "<A HREF=\"%s\">%s</A>", getLink(*iip).c_str(), (*iip).c_str() ) : "<B>" + (*iip) + "</B>";
|
|
fprintf( indexFile, "%s<BR>\n", link.c_str() );
|
|
}
|
|
fprintf( indexFile, "</P>\n" );
|
|
}
|
|
else
|
|
{
|
|
fprintf( indexFile, "<P><B>All phrases are grammatically valid.</B></P>\n" );
|
|
}
|
|
fprintf( indexFile, "</body></html>\n" );
|
|
fclose( indexFile );
|
|
|
|
if ( MultipleDocFiles )
|
|
{
|
|
for ( uint l=0; l!=26; ++l )
|
|
{
|
|
fprintf( PhraseDocFiles[l], "</body></html>\n" );
|
|
fclose( PhraseDocFiles[l] );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf( PhraseDocFiles[0], "</body></html>\n" );
|
|
fclose( PhraseDocFiles[0] );
|
|
}
|
|
}
|
|
|
|
} // makeIndexFile //
|
|
|
|
|
|
//-----------------------------------------------
|
|
// makeActionsBySkillGroupFile
|
|
//
|
|
//-----------------------------------------------
|
|
void makeActionsBySkillGroupFile()
|
|
{
|
|
// progression by skill
|
|
FILE * actionsBySkillGroupFile = fopen( (DocFileName + "__by_skill.html").c_str(), "wt" );
|
|
if( actionsBySkillGroupFile )
|
|
{
|
|
fprintf( actionsBySkillGroupFile, ("<html><head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n<title>Progression of " + DocFileName + "</title>\n</head><body>\n").c_str() );
|
|
fprintf( actionsBySkillGroupFile, "<BR><A NAME=\"by_skill_group\"></A>\n" );
|
|
fprintf( actionsBySkillGroupFile, "<P><B>ACTIONS BY SKILL GROUP:</B><BR>\n<table cellpadding=\"0\" cellspacing=\"1\" border=\"0\" style=\"text-align: left;\"><tbody>\n" );
|
|
map<string, multimap<uint,string> > phrasesBySkill;
|
|
for ( map< uint, pair<string, string> >::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<string, multimap<uint,string> >::iterator it = phrasesBySkill.find(skillName);
|
|
if( it != phrasesBySkill.end() )
|
|
{
|
|
(*it).second.insert(make_pair(skillValue,phraseCode));
|
|
}
|
|
else
|
|
{
|
|
multimap<uint,string> m;
|
|
m.insert(make_pair(skillValue,phraseCode));
|
|
phrasesBySkill.insert( make_pair(skillName,m) );
|
|
}
|
|
}
|
|
|
|
map<string, multimap<uint,string> >::iterator itPhrasesBySkill;
|
|
for( itPhrasesBySkill = phrasesBySkill.begin(); itPhrasesBySkill != phrasesBySkill.end(); ++itPhrasesBySkill )
|
|
{
|
|
CVectorSString dicoResult;
|
|
Dico.lookup( (*itPhrasesBySkill).first, dicoResult, true );
|
|
if( !dicoResult.empty() )
|
|
fprintf( actionsBySkillGroupFile, "<tr><td><A HREF=\"#%s\">%s</A></td></tr>\n", (*itPhrasesBySkill).first.c_str(),dicoResult[0].c_str());
|
|
else
|
|
fprintf( actionsBySkillGroupFile, "<tr><td><A HREF=\"#%s\">%s</A></td></tr>\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, "<tr><td><A NAME=\"%s\"><B>%s</B></A><BR></td></tr>\n", (*itPhrasesBySkill).first.c_str(), dicoResult[0].c_str() );
|
|
else
|
|
fprintf( actionsBySkillGroupFile, "<tr><td><A NAME=\"%s\"><B>%s</B></A><BR></td></tr>\n", (*itPhrasesBySkill).first.c_str(),(*itPhrasesBySkill).first.c_str() );
|
|
|
|
multimap<uint,string>::iterator it;
|
|
for( it = (*itPhrasesBySkill).second.begin(); it != (*itPhrasesBySkill).second.end(); ++it )
|
|
{
|
|
fprintf( actionsBySkillGroupFile, "<tr><td>%d</td><td>%s</td><td>%s<BR></td></tr>\n", (*it).first, PhraseCodeToLink[(*it).second].c_str(), PhraseTitles[(*it).second].c_str());
|
|
}
|
|
}
|
|
fprintf( actionsBySkillGroupFile, "</tbody><table></P>\n" );
|
|
fprintf( actionsBySkillGroupFile, "</body></html>\n" );
|
|
fclose( actionsBySkillGroupFile );
|
|
}
|
|
|
|
} // makeActionsBySkillGroupFile //
|
|
|
|
|
|
|
|
//-----------------------------------------------
|
|
// makeActionsBySkillValueFile
|
|
//
|
|
//-----------------------------------------------
|
|
void makeActionsBySkillValueFile()
|
|
{
|
|
FILE * actionsBySkillValueFile = fopen( (DocFileName + "__by_skill_value.html").c_str(), "wt" );
|
|
if( actionsBySkillValueFile )
|
|
{
|
|
fprintf( actionsBySkillValueFile, ("<html><head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n<title>Progression of " + DocFileName + "</title>\n</head><body>\n").c_str() );
|
|
|
|
// Progression (phrases sorted by skill value)
|
|
fprintf( actionsBySkillValueFile, "<BR><A NAME=\"by_skill_value\"></A>\n" );
|
|
fprintf( actionsBySkillValueFile, "<P><B>ACTIONS BY SKILL VALUE: <A HREF=\"%s\">[detail]</A></B>\n<table cellpadding=\"0\" cellspacing=\"1\" border=\"0\" style=\"text-align: left;\"><tbody>\n",(DocFileName + "__by_skill_value_detail.html").c_str() );
|
|
fprintf( actionsBySkillValueFile, "<tr><td><B>File</B></td><td><B>Name</B></td><td><B>Skill needed</B><BR></td></tr>\n");
|
|
map<string,string> phraseCodeToLink;
|
|
for ( map< uint, pair<string, string> >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip )
|
|
{
|
|
const string& phraseCode = (*ip).second.first;
|
|
fprintf( actionsBySkillValueFile, "<tr><td><font size=2>%s</font></td><td><font size=2>%s</font></td><td><B><font size=2>%s</font></B><BR></td></tr>\n", PhraseCodeToLink[phraseCode].c_str(), /*newbrickTitle.c_str(),*/ PhraseTitles[phraseCode].c_str(), (*ip).second.second.c_str() );
|
|
}
|
|
fprintf( actionsBySkillValueFile, "</tbody><table></P>\n" );
|
|
fprintf( actionsBySkillValueFile, "</body></html>\n" );
|
|
fclose( actionsBySkillValueFile );
|
|
}
|
|
|
|
} // makeActionsBySkillValueFile //
|
|
|
|
|
|
//-----------------------------------------------
|
|
// makeActionsBySkillValueDetailFile
|
|
//
|
|
//-----------------------------------------------
|
|
void makeActionsBySkillValueDetailFile()
|
|
{
|
|
FILE * actionsBySkillValueDetailFile = fopen( (DocFileName + "__by_skill_value_detail.html").c_str(), "wt" );
|
|
if( actionsBySkillValueDetailFile )
|
|
{
|
|
fprintf( actionsBySkillValueDetailFile, ("<html><head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n<title>Progression of " + DocFileName + "</title>\n</head><body>\n").c_str() );
|
|
|
|
// Progression summary (phrases sorted by skill value)
|
|
fprintf( actionsBySkillValueDetailFile, "<BR><A NAME=\"progression\"></A>\n" );
|
|
fprintf( actionsBySkillValueDetailFile, "<P><B>ACTIONS BY SKILL VALUE:</B><BR>\n<table cellpadding=\"0\" cellspacing=\"1\" border=\"0\" style=\"text-align: left;\"><tbody>\n" );
|
|
fprintf( actionsBySkillValueDetailFile, "<tr><td><B>File</B></td><td><B>Name</B></td><td><B>Skill needed</B><BR></td><td><B>Sabrina cost</B></td><td><B>Bricks ...</B></td></tr>\n");
|
|
|
|
set<string> effects;
|
|
map<string,set<string> > effectAndModifiers;
|
|
for ( map< uint, pair<string, string> >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip )
|
|
{
|
|
const string& phraseCode = (*ip).second.first;
|
|
fprintf( actionsBySkillValueDetailFile, "<tr><td><font size=2>%s</font></td><td><font size=2>%s</font></td><td><B><font size=2>%s</font></B></td><td><font size=2>%d</font></td>",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<string> 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, "<td><FONT COLOR=\"%s\" SIZE=2>%s</FONT></td>",color.c_str(),text.c_str());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nlerror("not found : %s",phraseCode.c_str());
|
|
}
|
|
fprintf( actionsBySkillValueDetailFile, "</tr>\n");
|
|
}
|
|
fprintf( actionsBySkillValueDetailFile, "</tbody><table></P>\n" );
|
|
fprintf( actionsBySkillValueDetailFile, "</body></html>\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<map<string,uint16> > skillsArray;
|
|
skillsArray.resize(6); // 6 tranches de skill
|
|
uint i;
|
|
for( i = 0; i<SkillsTree.SkillsTree.size(); ++i )
|
|
{
|
|
string skillCode = SkillsTree.SkillsTree[i].SkillCode;
|
|
if( skillCode[1] == filter )
|
|
{
|
|
uint sIdx = skillCode.length()-2; // -1 for 'S', -1 for 0
|
|
skillsArray[sIdx].insert( make_pair(skillCode,SkillsTree.SkillsTree[i].MaxSkillValue) );
|
|
}
|
|
}
|
|
|
|
uint16 maxLine = 0;
|
|
for( i=0; i<skillsArray.size(); ++i )
|
|
{
|
|
if( skillsArray[i].size() > maxLine )
|
|
{
|
|
maxLine = skillsArray[i].size();
|
|
}
|
|
}
|
|
|
|
string filename = skillFamily + "_skill_tree.html";
|
|
string filenameWithTraduction = skillFamily + "_skill_tree_detailed.html";
|
|
FILE * skillTreeFile;
|
|
if( withTraduction )
|
|
skillTreeFile = fopen( filenameWithTraduction.c_str(), "wt" );
|
|
else
|
|
skillTreeFile = fopen( filename.c_str(), "wt" );
|
|
fprintf( skillTreeFile,"<html><head>\n");
|
|
fprintf( skillTreeFile,"<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n");
|
|
fprintf( skillTreeFile,"<title>SKILL TREE ( %s )</title>\n",skillFamily.c_str());
|
|
fprintf( skillTreeFile,"</head><body>\n");
|
|
if( withTraduction )
|
|
fprintf( skillTreeFile,"<b>SKILL TREE ( %s )</b>\n",skillFamily.c_str());
|
|
else
|
|
fprintf( skillTreeFile,"<b>SKILL TREE ( %s )</b> [<A HREF=\"%s\">display traduction</A>]<BR>\n",skillFamily.c_str(),filenameWithTraduction.c_str());
|
|
fprintf( skillTreeFile,"<table cellpadding=\"2\" cellspacing=\"2\" border=\"0\" style=\"text-align: left;\"><tbody>\n");
|
|
fprintf( skillTreeFile,"<tr><td><b>0 to 20</b></td><td><b>20 to 50</b></td><td><b>50 to 100</b></td><td><b>100 to 150</b></td><td><b>150 to 200</b></td><td><b>200 to 250</b></td></tr>\n");
|
|
|
|
uint j;
|
|
// print line by line
|
|
for( j=0; j<maxLine; ++j )
|
|
{
|
|
fprintf( skillTreeFile,"<tr>");
|
|
// for each column
|
|
for( i=0; i<skillsArray.size(); ++i )
|
|
{
|
|
uint p;
|
|
map<string,uint16>::iterator itSkillcode;
|
|
for( itSkillcode = skillsArray[i].begin(), p=0; itSkillcode != skillsArray[i].end() && p<j; ++itSkillcode,++p );
|
|
if( itSkillcode != skillsArray[i].end() )
|
|
{
|
|
if( withTraduction )
|
|
{
|
|
CVectorSString dicoResult;
|
|
Dico.lookup( (*itSkillcode).first, dicoResult, true );
|
|
if(dicoResult.empty())
|
|
fprintf( skillTreeFile,"<td>%s : ???</td>",(*itSkillcode).first.c_str());
|
|
else
|
|
fprintf( skillTreeFile,"<td>%s</td>",dicoResult[0].c_str());
|
|
}
|
|
else
|
|
fprintf( skillTreeFile,"<td>%s</td>",(*itSkillcode).first.c_str());
|
|
}
|
|
else
|
|
fprintf( skillTreeFile,"<td></td>");
|
|
}
|
|
fprintf( skillTreeFile,"</tr>\n");
|
|
}
|
|
|
|
fprintf( skillTreeFile, "</tbody><table></P>\n" );
|
|
fprintf( skillTreeFile, "</body></html>\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 <sheet path> after -p option\n" );
|
|
usage( argv[0], stderr );
|
|
exit( 0 );
|
|
}
|
|
inputSheetPath = argv[i];
|
|
break;
|
|
case 'o':
|
|
++i;
|
|
if ( (sint)i == argc )
|
|
{
|
|
fprintf( stderr, "Missing <phrasePath> 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<UForm> 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<uint,map<string,set<string> > > levelToBrick;
|
|
|
|
map<string,string> phraseToSkill;
|
|
|
|
for ( map< uint, pair<string, string> >::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<uint,map<string,set<string> > >::iterator itLvl = levelToBrick.find(level);
|
|
if( itLvl == levelToBrick.end() )
|
|
{
|
|
set<string> s;
|
|
map<string,set<string> > mp;
|
|
mp.insert(make_pair(skill,s));
|
|
levelToBrick.insert(make_pair(level,mp));
|
|
}
|
|
else
|
|
{
|
|
if( (*itLvl).second.find(skill) == (*itLvl).second.end() )
|
|
{
|
|
set<string> 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<string,string> brickToColor;
|
|
map<string,string> brickToFamily;
|
|
map<string, CBrickInfo>::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<string,map<string,string> > 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<string,string> 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<string,string> brickToLearnSkill;
|
|
map<string,map<string,string> >::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<minLevel || minSkill.empty() )
|
|
{
|
|
minSkill = skillTmp;
|
|
minLevel = level;
|
|
}
|
|
}
|
|
|
|
brickToLearnSkill.insert(make_pair((*itLearn).first,minSkill));
|
|
}
|
|
|
|
// PHRASES
|
|
|
|
// write header and title bar
|
|
string filename;
|
|
filename = DocFileNameRoot + "_m.html";
|
|
FILE * brickPhraseDocFile_m = fopen( filename.c_str(), "wt" );
|
|
fprintf( brickPhraseDocFile_m,"<html><head>\n");
|
|
fprintf( brickPhraseDocFile_m,"<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n");
|
|
fprintf( brickPhraseDocFile_m,"<title>Brick phrases</title>\n");
|
|
fprintf( brickPhraseDocFile_m,"</head><body>\n");
|
|
fprintf( brickPhraseDocFile_m,"<table cellpadding=\"0\" cellspacing=\"1\" border=\"0\" style=\"text-align: left;\"><tbody>\n");
|
|
|
|
filename = DocFileNameRoot + "_c.html";
|
|
FILE * brickPhraseDocFile_c = fopen( filename.c_str(), "wt" );
|
|
fprintf( brickPhraseDocFile_c,"<html><head>\n");
|
|
fprintf( brickPhraseDocFile_c,"<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n");
|
|
fprintf( brickPhraseDocFile_c,"<title>Brick phrases</title>\n");
|
|
fprintf( brickPhraseDocFile_c,"</head><body>\n");
|
|
fprintf( brickPhraseDocFile_c,"<table cellpadding=\"0\" cellspacing=\"1\" border=\"0\" style=\"text-align: left;\"><tbody>\n");
|
|
|
|
filename = DocFileNameRoot + "_o.html";
|
|
FILE * brickPhraseDocFile_o = fopen( filename.c_str(), "wt" );
|
|
fprintf( brickPhraseDocFile_o,"<html><head>\n");
|
|
fprintf( brickPhraseDocFile_o,"<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n");
|
|
fprintf( brickPhraseDocFile_o,"<title>Brick phrases</title>\n");
|
|
fprintf( brickPhraseDocFile_o,"</head><body>\n");
|
|
fprintf( brickPhraseDocFile_o,"<table cellpadding=\"0\" cellspacing=\"1\" border=\"0\" style=\"text-align: left;\"><tbody>\n");
|
|
|
|
filename = DocFileNameRoot + "_p.html";
|
|
FILE * brickPhraseDocFile_p = fopen( filename.c_str(), "wt" );
|
|
fprintf( brickPhraseDocFile_p,"<html><head>\n");
|
|
fprintf( brickPhraseDocFile_p,"<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n");
|
|
fprintf( brickPhraseDocFile_p,"<title>Brick phrases</title>\n");
|
|
fprintf( brickPhraseDocFile_p,"</head><body>\n");
|
|
fprintf( brickPhraseDocFile_p,"<table cellpadding=\"0\" cellspacing=\"1\" border=\"0\" style=\"text-align: left;\"><tbody>\n");
|
|
|
|
filename = DocFileNameRoot + "_e.html";
|
|
FILE * brickPhraseDocFile_e = fopen( filename.c_str(), "wt" );
|
|
fprintf( brickPhraseDocFile_e,"<html><head>\n");
|
|
fprintf( brickPhraseDocFile_e,"<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n");
|
|
fprintf( brickPhraseDocFile_e,"<title>Brick phrases</title>\n");
|
|
fprintf( brickPhraseDocFile_e,"</head><body>\n");
|
|
fprintf( brickPhraseDocFile_e,"<table cellpadding=\"0\" cellspacing=\"1\" border=\"0\" style=\"text-align: left;\"><tbody>\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,"<tr><td><A NAME=\"%s\"><FONT COLOR=\"Blue\">%s</FONT></A></td><td></td></tr>\n",brk.c_str(),code.c_str());
|
|
if(brickToFamily[brk]=="Credit")
|
|
fprintf( brickPhraseDocFile_c,"<tr><td><A NAME=\"%s\"><FONT COLOR=\"Red\">%s</FONT></A></td><td></td></tr>\n",brk.c_str(),code.c_str());
|
|
if(brickToFamily[brk]=="Option")
|
|
fprintf( brickPhraseDocFile_o,"<tr><td><A NAME=\"%s\"><FONT COLOR=\"Green\">%s</FONT></A></td><td></td></tr>\n",brk.c_str(),code.c_str());
|
|
if(brickToFamily[brk]=="Effect")
|
|
fprintf( brickPhraseDocFile_e,"<tr><td><A NAME=\"%s\"><FONT COLOR=\"Brown\">%s</FONT></A></td><td></td></tr>\n",brk.c_str(),code.c_str());
|
|
if(brickToFamily[brk]=="Root")
|
|
fprintf( brickPhraseDocFile_p,"<tr><td><A NAME=\"%s\"><FONT COLOR=\"Black\">%s</FONT></A></td><td></td></tr>\n",brk.c_str(),code.c_str());
|
|
|
|
map<string,map<string,string> >::iterator itPhrases = brickToPhrases.find(brk);
|
|
if( itPhrases != brickToPhrases.end() )
|
|
{
|
|
map<string,string>::iterator itPh;
|
|
for( itPh=(*itPhrases).second.begin(); itPh!=(*itPhrases).second.end(); ++itPh )
|
|
{
|
|
if(brickToFamily[brk]=="Modifier")
|
|
fprintf( brickPhraseDocFile_m,"<tr><td></td><td><A HREF=\"%s_%c.html#%s\">%s</A></td></tr>\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str());
|
|
if(brickToFamily[brk]=="Credit")
|
|
fprintf( brickPhraseDocFile_c,"<tr><td></td><td><A HREF=\"%s_%c.html#%s\">%s</A></td></tr>\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str());
|
|
if(brickToFamily[brk]=="Option")
|
|
fprintf( brickPhraseDocFile_o,"<tr><td></td><td><A HREF=\"%s_%c.html#%s\">%s</A></td></tr>\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str());
|
|
if(brickToFamily[brk]=="Effect")
|
|
fprintf( brickPhraseDocFile_e,"<tr><td></td><td><A HREF=\"%s_%c.html#%s\">%s</A></td></tr>\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str());
|
|
if(brickToFamily[brk]=="Root")
|
|
fprintf( brickPhraseDocFile_p,"<tr><td></td><td><A HREF=\"%s_%c.html#%s\">%s</A></td></tr>\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str());
|
|
}
|
|
}
|
|
}
|
|
fprintf( brickPhraseDocFile_m, "</tbody><table></P>\n" );
|
|
fprintf( brickPhraseDocFile_m, "</body></html>\n" );
|
|
fclose( brickPhraseDocFile_m );
|
|
|
|
fprintf( brickPhraseDocFile_c, "</tbody><table></P>\n" );
|
|
fprintf( brickPhraseDocFile_c, "</body></html>\n" );
|
|
fclose( brickPhraseDocFile_c );
|
|
|
|
fprintf( brickPhraseDocFile_o, "</tbody><table></P>\n" );
|
|
fprintf( brickPhraseDocFile_o, "</body></html>\n" );
|
|
fclose( brickPhraseDocFile_o );
|
|
|
|
fprintf( brickPhraseDocFile_e, "</tbody><table></P>\n" );
|
|
fprintf( brickPhraseDocFile_e, "</body></html>\n" );
|
|
fclose( brickPhraseDocFile_e );
|
|
|
|
fprintf( brickPhraseDocFile_p, "</tbody><table></P>\n" );
|
|
fprintf( brickPhraseDocFile_p, "</body></html>\n" );
|
|
fclose( brickPhraseDocFile_p );
|
|
|
|
|
|
// CODE
|
|
|
|
// write header and title bar
|
|
filename = DocFileNameRoot + ".html";
|
|
FILE * brickDocFile = fopen( filename.c_str(), "wt" );
|
|
fprintf( brickDocFile,"<html><head>\n");
|
|
fprintf( brickDocFile,"<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n");
|
|
fprintf( brickDocFile,"<title>Bricks infos</title>\n");
|
|
fprintf( brickDocFile,"</head><body>\n");
|
|
fprintf( brickDocFile,"<table cellpadding=\"1\" cellspacing=\"1\" border=\"0\"><tbody>\n");
|
|
fprintf( brickDocFile,"<tr>\n");
|
|
fprintf( brickDocFile,"<td><b>*Code*</b></td>\n");
|
|
fprintf( brickDocFile,"<td><b><a href=\"%s_name.html\">Name</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickDocFile,"<td><b><a href=\"%s_family.html\">Family</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickDocFile,"<td><b>Required Skill Name</b></td>\n");
|
|
fprintf( brickDocFile,"<td><b><a href=\"%s_required_skill_value.html\">Required Skill Value</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickDocFile,"<td><b>Learn Skill Name</b></td>\n");
|
|
fprintf( brickDocFile,"<td><b><a href=\"%s_learn_skill_value.html\">Learn Skill Value</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickDocFile,"<td><b>Found In Phrases</b></td>\n");
|
|
fprintf( brickDocFile,"</tr>\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, "<tr><td><FONT COLOR=\"%s\">%s</FONT></td>\n",color.c_str(),code.c_str());
|
|
|
|
// name
|
|
string name = (*itBInf).second.Text;
|
|
fprintf( brickDocFile, "<td>%s</td>\n",name.c_str());
|
|
|
|
// family
|
|
string family = brickToFamily[brk];
|
|
fprintf( brickDocFile, "<td><FONT COLOR=\"%s\">%s</FONT></td>\n",color.c_str(),family.c_str());
|
|
|
|
// required skill name
|
|
fprintf( brickDocFile, "<td>%s</td>\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, "<td>%s</td>\n",levelStr.c_str());
|
|
|
|
// learn skill name
|
|
string learnSkillTmp = brickToLearnSkill[brk];
|
|
skill = learnSkillTmp.substr(0,learnSkillTmp.find_first_of(" "));
|
|
fprintf( brickDocFile, "<td>%s</td>\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, "<td>%s</td>\n",levelStr.c_str());
|
|
|
|
|
|
// phrase list
|
|
fprintf( brickDocFile, "<td>");
|
|
map<string,map<string,string> >::iterator itPhrases = brickToPhrases.find(brk);
|
|
if( itPhrases != brickToPhrases.end() )
|
|
{
|
|
map<string,string>::iterator itPh;
|
|
uint i;
|
|
for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i )
|
|
{
|
|
if( MultipleDocFiles )
|
|
fprintf( brickDocFile,"<A HREF=\"%s_%c.html#%s\">%s</A>,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str());
|
|
else
|
|
fprintf( brickDocFile,"<A HREF=\"%s.html#%s\">%s</A>,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str());
|
|
}
|
|
if( i==2 )
|
|
{
|
|
char type = family[0];
|
|
fprintf( brickDocFile,"[<A HREF=\"%s_%c.html#%s\">...</A>]",DocFileNameRoot.c_str(),type,brk.c_str());
|
|
}
|
|
}
|
|
|
|
fprintf( brickDocFile, "</td></tr>\n");
|
|
}
|
|
fprintf( brickDocFile, "</tbody><table></P>\n" );
|
|
fprintf( brickDocFile, "</body></html>\n" );
|
|
fclose( brickDocFile );
|
|
|
|
|
|
|
|
// NAME
|
|
|
|
// write header and title bar
|
|
filename = DocFileNameRoot + "_name.html";
|
|
FILE * brickNameDocFile = fopen( filename.c_str(), "wt" );
|
|
fprintf( brickNameDocFile,"<html><head>\n");
|
|
fprintf( brickNameDocFile,"<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n");
|
|
fprintf( brickNameDocFile,"<title>Bricks infos</title>\n");
|
|
fprintf( brickNameDocFile,"</head><body>\n");
|
|
fprintf( brickNameDocFile,"<table cellpadding=\"1\" cellspacing=\"1\" border=\"0\"><tbody>\n");
|
|
fprintf( brickNameDocFile,"<tr>\n");
|
|
fprintf( brickNameDocFile,"<td><b><a href=\"%s.html\">Code</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickNameDocFile,"<td><b>*Name*</b></td>\n");
|
|
fprintf( brickNameDocFile,"<td><b><a href=\"%s_family.html\">Family</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickNameDocFile,"<td><b>Required Skill Name</b></td>\n");
|
|
fprintf( brickNameDocFile,"<td><b><a href=\"%s_required_skill_value.html\">Required Skill Value</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickNameDocFile,"<td><b>Learn Skill Name</b></td>\n");
|
|
fprintf( brickNameDocFile,"<td><b><a href=\"%s_learn_skill_value.html\">Learn Skill Value</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickNameDocFile,"<td><b>Found In Phrases</b></td>\n");
|
|
fprintf( brickNameDocFile,"</tr>\n");
|
|
|
|
map<string,string> 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, "<tr><td><FONT COLOR=\"%s\">%s</FONT></td>\n",color.c_str(),code.c_str());
|
|
|
|
// name
|
|
string name = (*itBInf).second.Text;
|
|
fprintf( brickNameDocFile, "<td>%s</td>\n",name.c_str());
|
|
|
|
// family
|
|
string family = brickToFamily[brk];
|
|
fprintf( brickNameDocFile, "<td><FONT COLOR=\"%s\">%s</FONT></td>\n",color.c_str(),family.c_str());
|
|
|
|
// required skill name
|
|
fprintf( brickNameDocFile, "<td>%s</td>\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, "<td>%s</td>\n",levelStr.c_str());
|
|
|
|
// learn skill name
|
|
skillTmp = brickToLearnSkill[brk];
|
|
skill = skillTmp.substr(0,skillTmp.find_first_of(" "));
|
|
fprintf( brickNameDocFile, "<td>%s</td>\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, "<td>%s</td>\n",levelStr.c_str());
|
|
|
|
|
|
// phrase list
|
|
fprintf( brickNameDocFile, "<td>");
|
|
map<string,map<string,string> >::iterator itPhrases = brickToPhrases.find(brk);
|
|
if( itPhrases != brickToPhrases.end() )
|
|
{
|
|
map<string,string>::iterator itPh;
|
|
uint i;
|
|
for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i )
|
|
{
|
|
if( MultipleDocFiles )
|
|
fprintf( brickNameDocFile,"<A HREF=\"%s_%c.html#%s\">%s</A>,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str());
|
|
else
|
|
fprintf( brickNameDocFile,"<A HREF=\"%s.html#%s\">%s</A>,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str());
|
|
}
|
|
if( i==2 )
|
|
{
|
|
char type = family[0];
|
|
fprintf( brickNameDocFile,"[<A HREF=\"%s_%c.html#%s\">...</A>]",DocFileNameRoot.c_str(),type,brk.c_str());
|
|
}
|
|
}
|
|
|
|
fprintf( brickNameDocFile, "</td></tr>\n");
|
|
|
|
}
|
|
|
|
fprintf( brickNameDocFile, "</tbody><table></P>\n" );
|
|
fprintf( brickNameDocFile, "</body></html>\n" );
|
|
fclose( brickNameDocFile );
|
|
|
|
|
|
|
|
|
|
// FAMILY
|
|
|
|
// write header and title bar
|
|
filename = DocFileNameRoot + "_family.html";
|
|
FILE * brickFamilyDocFile = fopen( filename.c_str(), "wt" );
|
|
fprintf( brickFamilyDocFile,"<html><head>\n");
|
|
fprintf( brickFamilyDocFile,"<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n");
|
|
fprintf( brickFamilyDocFile,"<title>Bricks infos</title>\n");
|
|
fprintf( brickFamilyDocFile,"</head><body>\n");
|
|
fprintf( brickFamilyDocFile,"<table cellpadding=\"1\" cellspacing=\"1\" border=\"0\"><tbody>\n");
|
|
fprintf( brickFamilyDocFile,"<tr>\n");
|
|
fprintf( brickFamilyDocFile,"<td><b><a href=\"%s.html\">Code</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickFamilyDocFile,"<td><b><a href=\"%s_name.html\">Name</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickFamilyDocFile,"<td><b>*Family*</b></td>\n");
|
|
fprintf( brickFamilyDocFile,"<td><b>Required Skill Name</b></td>\n");
|
|
fprintf( brickFamilyDocFile,"<td><b><a href=\"%s_required_skill_value.html\">Required Skill Value</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickFamilyDocFile,"<td><b>Learn Skill Name</b></td>\n");
|
|
fprintf( brickFamilyDocFile,"<td><b><a href=\"%s_learn_skill_value.html\">Learn Skill Value</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickFamilyDocFile,"<td><b>Found In Phrases</b></td>\n");
|
|
fprintf( brickFamilyDocFile,"</tr>\n");
|
|
|
|
|
|
// write infos
|
|
multimap<string,string> 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<string,string>::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, "<tr><td><FONT COLOR=\"%s\">%s</FONT></td>\n",color.c_str(),code.c_str());
|
|
|
|
// name
|
|
string name = (*itBInf).second.Text;
|
|
fprintf( brickFamilyDocFile, "<td>%s</td>\n",name.c_str());
|
|
|
|
// family
|
|
string family = brickToFamily[brk];
|
|
fprintf( brickFamilyDocFile, "<td><FONT COLOR=\"%s\">%s</FONT></td>\n",color.c_str(),family.c_str());
|
|
|
|
// required skill name
|
|
fprintf( brickFamilyDocFile, "<td>%s</td>\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, "<td>%s</td>\n",levelStr.c_str());
|
|
|
|
// learn skill name
|
|
skillTmp = brickToLearnSkill[brk];
|
|
skill = skillTmp.substr(0,skillTmp.find_first_of(" "));
|
|
fprintf( brickFamilyDocFile, "<td>%s</td>\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, "<td>%s</td>\n",levelStr.c_str());
|
|
|
|
|
|
// phrase list
|
|
fprintf( brickFamilyDocFile, "<td>");
|
|
map<string,map<string,string> >::iterator itPhrases = brickToPhrases.find(brk);
|
|
if( itPhrases != brickToPhrases.end() )
|
|
{
|
|
map<string,string>::iterator itPh;
|
|
uint i;
|
|
for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i )
|
|
{
|
|
if( MultipleDocFiles )
|
|
fprintf( brickFamilyDocFile,"<A HREF=\"%s_%c.html#%s\">%s</A>,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str());
|
|
else
|
|
fprintf( brickFamilyDocFile,"<A HREF=\"%s.html#%s\">%s</A>,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str());
|
|
}
|
|
if( i==2 )
|
|
{
|
|
char type = family[0];
|
|
fprintf( brickFamilyDocFile,"[<A HREF=\"%s_%c.html#%s\">...</A>]",DocFileNameRoot.c_str(),type,brk.c_str());
|
|
}
|
|
}
|
|
|
|
fprintf( brickFamilyDocFile, "</td></tr>\n");
|
|
}
|
|
fprintf( brickFamilyDocFile, "</tbody><table></P>\n" );
|
|
fprintf( brickFamilyDocFile, "</body></html>\n" );
|
|
fclose( brickFamilyDocFile );
|
|
|
|
|
|
|
|
|
|
// REQUIRED SKILL VALUE
|
|
|
|
// write header and title bar
|
|
filename = DocFileNameRoot + "_required_skill_value.html";
|
|
FILE * brickRequiredDocFile = fopen( filename.c_str(), "wt" );
|
|
fprintf( brickRequiredDocFile,"<html><head>\n");
|
|
fprintf( brickRequiredDocFile,"<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n");
|
|
fprintf( brickRequiredDocFile,"<title>Bricks infos</title>\n");
|
|
fprintf( brickRequiredDocFile,"</head><body>\n");
|
|
fprintf( brickRequiredDocFile,"<table cellpadding=\"1\" cellspacing=\"1\" border=\"0\"><tbody>\n");
|
|
fprintf( brickRequiredDocFile,"<tr>\n");
|
|
fprintf( brickRequiredDocFile,"<td><b><a href=\"%s.html\">Code</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickRequiredDocFile,"<td><b><a href=\"%s_name.html\">Name</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickRequiredDocFile,"<td><b><a href=\"%s_family.html\">Family</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickRequiredDocFile,"<td><b>Required Skill Name</b></td>\n");
|
|
fprintf( brickRequiredDocFile,"<td><b>*Required Skill Value*</b></td>\n");
|
|
fprintf( brickRequiredDocFile,"<td><b>Learn Skill Name</b></td>\n");
|
|
fprintf( brickRequiredDocFile,"<td><b><a href=\"%s_learn_skill_value.html\">Learn Skill Value</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickRequiredDocFile,"<td><b>Found In Phrases</b></td>\n");
|
|
fprintf( brickRequiredDocFile,"</tr>\n");
|
|
|
|
|
|
// write infos
|
|
multimap<uint,string> 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<uint,string>::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, "<tr><td><FONT COLOR=\"%s\">%s</FONT></td>\n",color.c_str(),code.c_str());
|
|
|
|
// name
|
|
string name = (*itBInf).second.Text;
|
|
fprintf( brickRequiredDocFile, "<td>%s</td>\n",name.c_str());
|
|
|
|
// family
|
|
string family = brickToFamily[brk];
|
|
fprintf( brickRequiredDocFile, "<td><FONT COLOR=\"%s\">%s</FONT></td>\n",color.c_str(),family.c_str());
|
|
|
|
// required skill name
|
|
fprintf( brickRequiredDocFile, "<td>%s</td>\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, "<td>%s</td>\n",levelStr.c_str());
|
|
|
|
// learn skill name
|
|
skillTmp = brickToLearnSkill[brk];
|
|
skill = skillTmp.substr(0,skillTmp.find_first_of(" "));
|
|
fprintf( brickRequiredDocFile, "<td>%s</td>\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, "<td>%s</td>\n",levelStr.c_str());
|
|
|
|
|
|
// phrase list
|
|
fprintf( brickRequiredDocFile, "<td>");
|
|
map<string,map<string,string> >::iterator itPhrases = brickToPhrases.find(brk);
|
|
if( itPhrases != brickToPhrases.end() )
|
|
{
|
|
map<string,string>::iterator itPh;
|
|
uint i;
|
|
for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i )
|
|
{
|
|
if( MultipleDocFiles )
|
|
fprintf( brickRequiredDocFile,"<A HREF=\"%s_%c.html#%s\">%s</A>,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str());
|
|
else
|
|
fprintf( brickRequiredDocFile,"<A HREF=\"%s.html#%s\">%s</A>,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str());
|
|
}
|
|
if( i==2 )
|
|
{
|
|
char type = family[0];
|
|
fprintf( brickRequiredDocFile,"[<A HREF=\"%s_%c.html#%s\">...</A>]",DocFileNameRoot.c_str(),type,brk.c_str());
|
|
}
|
|
}
|
|
|
|
fprintf( brickRequiredDocFile, "</td></tr>\n");
|
|
}
|
|
fprintf( brickRequiredDocFile, "</tbody><table></P>\n" );
|
|
fprintf( brickRequiredDocFile, "</body></html>\n" );
|
|
fclose( brickRequiredDocFile );
|
|
|
|
|
|
|
|
// LEARN SKILL VALUE
|
|
|
|
// write header and title bar
|
|
filename = DocFileNameRoot + "_learn_skill_value.html";
|
|
FILE * brickLearnDocFile = fopen( filename.c_str(), "wt" );
|
|
fprintf( brickLearnDocFile,"<html><head>\n");
|
|
fprintf( brickLearnDocFile,"<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n");
|
|
fprintf( brickLearnDocFile,"<title>Bricks infos</title>\n");
|
|
fprintf( brickLearnDocFile,"</head><body>\n");
|
|
fprintf( brickLearnDocFile,"<table cellpadding=\"1\" cellspacing=\"1\" border=\"0\"><tbody>\n");
|
|
fprintf( brickLearnDocFile,"<tr>\n");
|
|
fprintf( brickLearnDocFile,"<td><b><a href=\"%s.html\">Code</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickLearnDocFile,"<td><b><a href=\"%s_name.html\">Name</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickLearnDocFile,"<td><b><a href=\"%s_family.html\">Family</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickLearnDocFile,"<td><b>Required Skill Name</b></td>\n");
|
|
fprintf( brickLearnDocFile,"<td><b><a href=\"%s_required_skill_value.html\">Required Skill Value</a></b></td>\n",DocFileNameRoot.c_str());
|
|
fprintf( brickLearnDocFile,"<td><b>Learn Skill Name</b></td>\n");
|
|
fprintf( brickLearnDocFile,"<td><b>*Learn Skill Value*</b></td>\n");
|
|
fprintf( brickLearnDocFile,"<td><b>Found In Phrases</b></td>\n");
|
|
fprintf( brickLearnDocFile,"</tr>\n");
|
|
|
|
|
|
// write infos
|
|
multimap<uint,string> 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<uint,string>::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, "<tr><td><FONT COLOR=\"%s\">%s</FONT></td>\n",color.c_str(),code.c_str());
|
|
|
|
// name
|
|
string name = (*itBInf).second.Text;
|
|
fprintf( brickLearnDocFile, "<td>%s</td>\n",name.c_str());
|
|
|
|
// family
|
|
string family = brickToFamily[brk];
|
|
fprintf( brickLearnDocFile, "<td><FONT COLOR=\"%s\">%s</FONT></td>\n",color.c_str(),family.c_str());
|
|
|
|
// required skill name
|
|
fprintf( brickLearnDocFile, "<td>%s</td>\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, "<td>%s</td>\n",levelStr.c_str());
|
|
|
|
// learn skill name
|
|
skillTmp = brickToLearnSkill[brk];
|
|
skill = skillTmp.substr(0,skillTmp.find_first_of(" "));
|
|
fprintf( brickLearnDocFile, "<td>%s</td>\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, "<td>%s</td>\n",levelStr.c_str());
|
|
|
|
|
|
// phrase list
|
|
fprintf( brickLearnDocFile, "<td>");
|
|
map<string,map<string,string> >::iterator itPhrases = brickToPhrases.find(brk);
|
|
if( itPhrases != brickToPhrases.end() )
|
|
{
|
|
map<string,string>::iterator itPh;
|
|
uint i;
|
|
for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i )
|
|
{
|
|
if( MultipleDocFiles )
|
|
fprintf( brickLearnDocFile,"<A HREF=\"%s_%c.html#%s\">%s</A>,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str());
|
|
else
|
|
fprintf( brickLearnDocFile,"<A HREF=\"%s.html#%s\">%s</A>,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str());
|
|
}
|
|
if( i==2 )
|
|
{
|
|
char type = family[0];
|
|
fprintf( brickLearnDocFile,"[<A HREF=\"%s_%c.html#%s\">...</A>]",DocFileNameRoot.c_str(),type,brk.c_str());
|
|
}
|
|
}
|
|
|
|
fprintf( brickLearnDocFile, "</td></tr>\n");
|
|
}
|
|
fprintf( brickLearnDocFile, "</tbody><table></P>\n" );
|
|
fprintf( brickLearnDocFile, "</body></html>\n" );
|
|
fclose( brickLearnDocFile );
|
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
|
} // main //
|
|
|
|
|
|
|
|
|