283 lines
7.7 KiB
C++
283 lines
7.7 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/>.
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
// includes
|
|
//-------------------------------------------------------------------------------------------------
|
|
|
|
#include "nel/misc/variable.h"
|
|
#include "nel/misc/path.h"
|
|
|
|
#include "game_share/persistent_data.h"
|
|
|
|
#include "character_scan_job.h"
|
|
#include "character.h"
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
// Variables
|
|
//-------------------------------------------------------------------------------------------------
|
|
|
|
extern NLMISC::CVariable<std::string> OutputDirectory;
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
// methods CCharacterScanJob
|
|
//-------------------------------------------------------------------------------------------------
|
|
|
|
CCharacterScanJob::CCharacterScanJob()
|
|
{
|
|
// start by initialising simple properties
|
|
_CharTblFile=NULL;
|
|
_NextFile=0;
|
|
_State=INIT;
|
|
|
|
// setup the special reserved table columns 'account' and 'accountSlot'
|
|
charTblAddCol("account");
|
|
charTblAddCol("accountSlot");
|
|
|
|
// open the output file for the character table
|
|
std::string filename= "char_tbl.csv";
|
|
_CharTblFile=fopen(filename.c_str(),"wb");
|
|
if (_CharTblFile==NULL)
|
|
{
|
|
nlwarning("Failed to open output file: %s",filename.c_str());
|
|
_State=ERROR;
|
|
}
|
|
}
|
|
|
|
CCharacterScanJob::~CCharacterScanJob()
|
|
{
|
|
if (_State!=ERROR)
|
|
_State=CLOSED;
|
|
|
|
if (_CharTblFile!=NULL)
|
|
fclose(_CharTblFile);
|
|
|
|
// flush the stats maps to their respective output files
|
|
for (TCharStatsMap::iterator it=_CharStatsMap.begin();it!=_CharStatsMap.end();++it)
|
|
{
|
|
// create the output file name and open the file for writing
|
|
std::string filename="char_stats_"+(*it).first+".csv";
|
|
FILE* f=fopen(filename.c_str(),"wb");
|
|
if (f==NULL)
|
|
{
|
|
nlwarning("Failed to open output file: %s",filename.c_str());
|
|
continue;
|
|
}
|
|
|
|
// dump data to the file
|
|
for (TCharStatsMapTbl::iterator it2=it->second.begin();it2!=it->second.end();++it2)
|
|
{
|
|
fprintf(f,"%s,%d,\n",it2->first.c_str(),it2->second);
|
|
}
|
|
|
|
// the writing is finished so close the file
|
|
fclose(f);
|
|
}
|
|
}
|
|
|
|
void CCharacterScanJob::update()
|
|
{
|
|
if (_NextFile>=_Files.size())
|
|
return;
|
|
|
|
// load the file into a pdr record
|
|
static CPersistentDataRecord pdr;
|
|
pdr.clear();
|
|
pdr.readFromFile(_Files[_NextFile].c_str());
|
|
++_NextFile;
|
|
|
|
// create a character representation and apply the pdr
|
|
CStatsScanCharacter c;
|
|
c.apply(pdr);
|
|
|
|
// iterate over the info extractors executing their core code
|
|
for (uint32 i=0;i<_InfoExtractors.size();++i)
|
|
{
|
|
_InfoExtractors[i]->execute(this,&c);
|
|
}
|
|
|
|
// flush the info collected by the info extractors to the output file
|
|
charTblFlushRow(123,456);
|
|
}
|
|
|
|
bool CCharacterScanJob::charTblAddCol(const std::string& name)
|
|
{
|
|
nlassert(_State==INIT);
|
|
|
|
// make sure the col doesn't already exist in the table
|
|
for (uint32 i=0;i<_TblCols.size();++i)
|
|
{
|
|
nlassert(_TblCols[i]!=name);
|
|
}
|
|
|
|
// add the colt ot he table
|
|
_TblCols.push_back(name);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CCharacterScanJob::addInfoExtractor(ICharInfoExtractor* infoExtractor)
|
|
{
|
|
// make sure this info extractor doesn't already exist
|
|
for (uint32 i=0;i<_InfoExtractors.size();++i)
|
|
{
|
|
if(_InfoExtractors[i]->toString()== infoExtractor->toString())
|
|
{
|
|
nlwarning("Attempt to add info extractor to the same job more than once: %s",infoExtractor->toString().c_str());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// append the new info extractor to the buffer
|
|
_InfoExtractors.push_back(infoExtractor);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CCharacterScanJob::addFilter(ICharFilter* filter)
|
|
{
|
|
// make sure this info extractor doesn't already exist
|
|
for (uint32 i=0;i<_Filters.size();++i)
|
|
{
|
|
if(_Filters[i]->toString()== filter->toString())
|
|
{
|
|
nlwarning("Attempt to add filter to the same job more than once: %s",filter->toString().c_str());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// append the new info extractor to the buffer
|
|
_Filters.push_back(filter);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CCharacterScanJob::addFiles(const CFileDescriptionContainer& fdc)
|
|
{
|
|
for (uint32 i=0;i<fdc.size();++i)
|
|
{
|
|
// generate a normalised a full file name with expanded path
|
|
std::string fullFileName= NLMISC::CPath::getFullPath(NLMISC::CFile::getPath(fdc[i].FileName))+NLMISC::CFile::getFilename(fdc[i].FileName);
|
|
|
|
// make sure the full file name doesn't already exist in the _Files vector
|
|
uint32 j;
|
|
for (j=0;j<_Files.size();++j)
|
|
{
|
|
if (fullFileName==_Files[j])
|
|
break;
|
|
}
|
|
if (j<_Files.size())
|
|
continue;
|
|
|
|
// add the full file name to the _Files vector
|
|
_Files.push_back(fullFileName);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CCharacterScanJob::setOutputPath(const std::string& path)
|
|
{
|
|
nlinfo("Setting output path to: %s",path.c_str());
|
|
_OutputPath= NLMISC::CPath::getFullPath(OutputDirectory)+path;
|
|
bool result= NLMISC::CFile::createDirectoryTree(_OutputPath);
|
|
if (result==false)
|
|
{
|
|
nlwarning("Failed to create directory tree: %s",path.c_str());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void CCharacterScanJob::charTblFlushRow(uint32 account,uint32 slot)
|
|
{
|
|
// setup the stuff for the ne
|
|
charTblSetEntry("account",NLMISC::toString(account));
|
|
charTblSetEntry("accountSlot",NLMISC::toString(slot));
|
|
|
|
nlassert(_State==WORK);
|
|
|
|
// build the row text from the _CurrentRowEntries entries and erase the entries as we go
|
|
std::string rowTxt;
|
|
for (uint32 i=0;i<_TblCols.size();++i)
|
|
{
|
|
if (!rowTxt.empty())
|
|
rowTxt+=',';
|
|
rowTxt+=_CurrentRowEntries[_TblCols[i]];
|
|
_CurrentRowEntries.erase(_TblCols[i]);
|
|
}
|
|
|
|
// get rid of any excess entries (spew warnings to compain about the problem)
|
|
while (!_CurrentRowEntries.empty())
|
|
{
|
|
nlwarning("Character Tbl entry found for unknown column: %s: %s",(*_CurrentRowEntries.begin()).first.c_str(),(*_CurrentRowEntries.begin()).second.c_str());
|
|
_CurrentRowEntries.erase(_CurrentRowEntries.begin());
|
|
}
|
|
|
|
// add the row text to the output file
|
|
fprintf(_CharTblFile,"%s\n",rowTxt.c_str());
|
|
fflush(_CharTblFile);
|
|
}
|
|
|
|
void CCharacterScanJob::charTblSetEntry(const std::string& colName,const std::string& value)
|
|
{
|
|
nlassert(_State==WORK);
|
|
|
|
// ensure we don't already have a value for this col
|
|
nlassert(_CurrentRowEntries.find(colName)==_CurrentRowEntries.end());
|
|
|
|
// det the value for the col
|
|
_CurrentRowEntries[colName]= value;
|
|
}
|
|
|
|
void CCharacterScanJob::freqTblAddEntry(const std::string& tblName, const std::string& key)
|
|
{
|
|
nlassert(_State==WORK);
|
|
|
|
// if the key doesn't exist in the given freq tbl then init the value to 1 else increment
|
|
if(_CharStatsMap[tblName].find(key)==_CharStatsMap[tblName].end())
|
|
_CharStatsMap[tblName][key]=1;
|
|
else
|
|
++_CharStatsMap[tblName][key];
|
|
}
|
|
|
|
bool CCharacterScanJob::finished()
|
|
{
|
|
return _NextFile>= _Files.size();
|
|
}
|
|
|
|
std::string CCharacterScanJob::getShortStatus()
|
|
{
|
|
return NLMISC::toString("CharacterFiles %d/%d",_NextFile,_Files.size());
|
|
}
|
|
|
|
std::string CCharacterScanJob::getStatus()
|
|
{
|
|
return getShortStatus();
|
|
}
|
|
|
|
void CCharacterScanJob::display(NLMISC::CLog* log)
|
|
{
|
|
log->displayNL("%s",getStatus().c_str());
|
|
for (uint32 i=0;i<_InfoExtractors.size();++i)
|
|
{
|
|
log->displayNL("- %s",_InfoExtractors[i]->toString().c_str());
|
|
}
|
|
}
|
|
|
|
|