First attempt to reduce load time of player deck selection screens.

This change makes use of caching the DeckStats and DeckStatsWrappers into singleton caches that
get flushed when you quit the game.  The initial load time will be significant as lazy loading has not
been coded yet for the ai decks.

TODO: lazy load the player and ai decks as they appear on the screen.  Currently, each screen loads
all decks.
This commit is contained in:
techdragon.nguyen@gmail.com
2011-01-27 16:13:40 +00:00
parent e87f5edaf5
commit ce7745bfa6
10 changed files with 213 additions and 101 deletions

View File

@@ -19,11 +19,17 @@ public:
vector<DeckMetaData *> playerDeckOrderList;
vector<DeckMetaData *> aiDeckOrderList;
map<string, StatsWrapper *> playerDeckStatsMap;
map<string, StatsWrapper *> aiDeckStatsMap;
void updateMetaDataList(vector<DeckMetaData *>* refList, bool isAI);
vector<DeckMetaData *> * getPlayerDeckOrderList();
vector<DeckMetaData *> * getAIDeckOrderList();
DeckMetaData * getDeckMetaDataById( int deckId, bool isAI );
StatsWrapper * getExtendedStatsForDeckId( int deckId, MTGAllCards *collection, bool isAI );
StatsWrapper * getExtendedDeckStats( DeckMetaData *selectedDeck, MTGAllCards *collection, bool isAI );
static DeckManager * GetInstance();
static void EndInstance();
@@ -31,10 +37,7 @@ public:
//since the eventual move of all deck meta data should be managed by this class
static int getDifficultyRating(Player *statsPlayer, Player *player);
~DeckManager()
{
instanceFlag = false;
}
~DeckManager();
};

View File

@@ -15,9 +15,10 @@ class GameObserver;
class DeckStat
{
public:
DeckStat(int _nbgames = 0, int _victories = 0);
int nbgames;
int victories;
DeckStat(int _nbgames = 0, int _victories = 0);
int percentVictories();
};
@@ -26,8 +27,12 @@ class DeckStats
protected:
static DeckStats * mInstance;
public:
map<string, DeckStat *> stats;
//map<string, DeckStat *> stats; // current set of statistics
string currentDeck;
map<string, map<string,DeckStat*> > masterDeckStats;
static DeckStats * GetInstance();
static void EndInstance();
void saveStats(Player * player, Player * opponent, GameObserver * game);
void save(const char * filename);
void save(Player * player);

View File

@@ -604,8 +604,7 @@ Spell * ActionStack::addSpell(MTGCardInstance * _source, TargetChooser * tc, Man
}
Spell * spell = NEW Spell(mCount, _source, tc, mana, payResult);
addAction(spell);
if (!game->players[0]->isAI() && _source->controller() == game->players[0] && 0
== options[Options::INTERRUPTMYSPELLS].number)
if (!game->players[0]->isAI() && _source->controller() == game->players[0] && 0 == options[Options::INTERRUPTMYSPELLS].number)
interruptDecision[0] = DONT_INTERRUPT;
return spell;
}

View File

@@ -1,60 +1,132 @@
#include "PrecompiledHeader.h"
#include "DeckManager.h"
#include "Player.h"
#include <JRenderer.h>
void DeckManager::updateMetaDataList(vector<DeckMetaData *> * refList, bool isAI)
{
if (refList)
{
vector<DeckMetaData *> * inputList = isAI ? &aiDeckOrderList : &playerDeckOrderList;
inputList->clear();
inputList->assign(refList->begin(), refList -> end());
}
}
vector<DeckMetaData *> * DeckManager::getPlayerDeckOrderList()
{
return &playerDeckOrderList;
}
vector<DeckMetaData *> * DeckManager::getAIDeckOrderList()
{
return &aiDeckOrderList;
}
DeckManager * DeckManager::mInstance = NULL;
bool DeckManager::instanceFlag = false;
void DeckManager::EndInstance()
{
if (mInstance)
{
mInstance->aiDeckOrderList.clear();
mInstance->playerDeckOrderList.clear();
SAFE_DELETE( mInstance );
}
}
DeckManager* DeckManager::GetInstance()
{
if (!instanceFlag)
{
mInstance = NEW DeckManager();
instanceFlag = true;
}
return mInstance;
}
// p1 is assumed to be the player you want stats for
// p2 is the opponent
int DeckManager::getDifficultyRating(Player *statsPlayer, Player *player)
{
DeckMetaDataList * metas = DeckMetaDataList::decksMetaData;
DeckMetaData *meta = metas->get(player->deckFile, statsPlayer);
return meta->getDifficulty();
}
#include "PrecompiledHeader.h"
#include "DeckManager.h"
#include "Player.h"
#include <JRenderer.h>
void DeckManager::updateMetaDataList(vector<DeckMetaData *> * refList, bool isAI)
{
if (refList)
{
vector<DeckMetaData *> * inputList = isAI ? &aiDeckOrderList : &playerDeckOrderList;
inputList->clear();
inputList->assign(refList->begin(), refList -> end());
}
}
vector<DeckMetaData *> * DeckManager::getPlayerDeckOrderList()
{
return &playerDeckOrderList;
}
vector<DeckMetaData *> * DeckManager::getAIDeckOrderList()
{
return &aiDeckOrderList;
}
DeckMetaData * DeckManager::getDeckMetaDataById( int deckId, bool isAI )
{
DeckMetaData* currentDeck = NULL;
vector<DeckMetaData *>::iterator currentPos, end;
if ( isAI )
{
currentPos = aiDeckOrderList.begin();
end = aiDeckOrderList.end();
}
else
{
currentPos = playerDeckOrderList.begin();
end = playerDeckOrderList.end();
}
for (; currentPos != end; ++currentPos)
{
currentDeck = *currentPos;
if (currentDeck->getDeckId() == deckId )
return currentDeck;
}
return NULL;
}
StatsWrapper * DeckManager::getExtendedStatsForDeckId( int deckId, MTGAllCards *collection, bool isAI )
{
DeckMetaData *selectedDeck = getDeckMetaDataById( deckId, isAI );
return getExtendedDeckStats( selectedDeck, collection, isAI);
}
StatsWrapper * DeckManager::getExtendedDeckStats( DeckMetaData *selectedDeck, MTGAllCards *collection, bool isAI )
{
StatsWrapper * stats = NULL;
map<string, StatsWrapper *> *statsMap = NULL;
string deckName = selectedDeck->getFilename();
int deckId = selectedDeck->getDeckId();
if (isAI)
statsMap = &aiDeckStatsMap;
else
statsMap = &playerDeckStatsMap;
if (statsMap->empty() || (statsMap->find(deckName) == statsMap->end()))
{
stats = NEW StatsWrapper(deckId);
stats->updateStats( deckName, collection);
statsMap->insert( make_pair( deckName, stats));
}
stats = statsMap->find(deckName) ->second;
return stats;
}
DeckManager * DeckManager::mInstance = NULL;
bool DeckManager::instanceFlag = false;
void DeckManager::EndInstance()
{
if (mInstance)
{
mInstance->aiDeckOrderList.clear();
mInstance->playerDeckOrderList.clear();
map<string, StatsWrapper *>::iterator it;
for (it = mInstance->aiDeckStatsMap.begin(); it != mInstance->aiDeckStatsMap.end(); it++){
SAFE_DELETE(it->second);
}
for (it = mInstance->playerDeckStatsMap.begin(); it != mInstance->playerDeckStatsMap.end(); it++){
SAFE_DELETE(it->second);
}
mInstance->aiDeckStatsMap.clear();
mInstance->playerDeckStatsMap.clear();
SAFE_DELETE( mInstance );
}
}
DeckManager* DeckManager::GetInstance()
{
if (!instanceFlag)
{
mInstance = NEW DeckManager();
instanceFlag = true;
}
return mInstance;
}
// p1 is assumed to be the player you want stats for
// p2 is the opponent
int DeckManager::getDifficultyRating(Player *statsPlayer, Player *player)
{
DeckMetaDataList * metas = DeckMetaDataList::decksMetaData;
DeckMetaData *meta = metas->get(player->deckFile, statsPlayer);
return meta->getDifficulty();
}
DeckManager::~DeckManager()
{
instanceFlag = false;
}

View File

@@ -23,30 +23,44 @@ DeckStats * DeckStats::GetInstance()
if (!mInstance)
{
mInstance = NEW DeckStats();
}
return mInstance;
}
void DeckStats::cleanStats()
{
map<string, DeckStat *>::iterator it;
/* map<string, DeckStat *>::iterator it;
for (it = stats.begin(); it != stats.end(); it++)
{
SAFE_DELETE(it->second);
}
stats.clear();
*/
}
DeckStats::~DeckStats()
{
cleanStats();
map<string, map<string,DeckStat*> > ::iterator it;
for (it = masterDeckStats.begin(); it != masterDeckStats.end(); ++it)
{
string key = it->first;
map<string, DeckStat *> innerMap = masterDeckStats[key];
map<string, DeckStat *>::iterator it2;
for (it2 = innerMap.begin(); it2 != innerMap.end(); it2++)
{
SAFE_DELETE(it2->second);
}
innerMap.clear();
}
masterDeckStats.clear();
}
DeckStat* DeckStats::getDeckStat(string opponentsFile)
{
map<string, DeckStat *> stats = masterDeckStats[currentDeck];
map<string, DeckStat *>::iterator it = stats.find(opponentsFile);
if (it == stats.end())
{
@@ -61,6 +75,7 @@ DeckStat* DeckStats::getDeckStat(string opponentsFile)
int DeckStats::nbGames()
{
int nbgames = 0;
map<string, DeckStat *> stats = masterDeckStats[currentDeck];
map<string, DeckStat *>::iterator it;
for (it = stats.begin(); it != stats.end(); it++)
{
@@ -72,6 +87,7 @@ int DeckStats::nbGames()
int DeckStats::percentVictories(string opponentsFile)
{
map<string, DeckStat *> stats = masterDeckStats[currentDeck];
map<string, DeckStat *>::iterator it = stats.find(opponentsFile);
if (it == stats.end())
{
@@ -87,6 +103,7 @@ int DeckStats::percentVictories()
{
int victories = 0;
int nbgames = 0;
map<string, DeckStat *> stats = masterDeckStats[currentDeck];
map<string, DeckStat *>::iterator it;
for (it = stats.begin(); it != stats.end(); it++)
{
@@ -110,7 +127,12 @@ void DeckStats::load(Player * player)
void DeckStats::load(const char * filename)
{
cleanStats();
currentDeck = filename;
if ( masterDeckStats.find(filename) != masterDeckStats.end() )
{
return;
}
wagic::ifstream file(filename);
std::string s;
@@ -123,11 +145,12 @@ void DeckStats::load(const char * filename)
int games = atoi(s.c_str());
std::getline(file, s);
int victories = atoi(s.c_str());
map<string, DeckStat *>::iterator it = stats.find(deckfile);
if (it == stats.end())
if ( masterDeckStats[filename].find(deckfile) != masterDeckStats[filename].end())
{
stats[deckfile] = NEW DeckStat(games, victories);
SAFE_DELETE( masterDeckStats[filename][deckfile] );
}
DeckStat * newDeckStat = NEW DeckStat(games, victories);
(masterDeckStats[filename])[deckfile] = newDeckStat;
}
file.close();
}
@@ -146,6 +169,7 @@ void DeckStats::save(const char * filename)
char writer[512];
if (file)
{
map<string, DeckStat *> stats = masterDeckStats[currentDeck];
map<string, DeckStat *>::iterator it;
for (it = stats.begin(); it != stats.end(); it++)
{
@@ -173,10 +197,11 @@ void DeckStats::saveStats(Player *player, Player *opponent, GameObserver * game)
victory = 0;
}
load(player);
map<string, DeckStat *>::iterator it = stats.find(opponent->deckFileSmall);
if (it == stats.end())
map<string, DeckStat *> *stats = &masterDeckStats[currentDeck];
map<string, DeckStat *>::iterator it = stats->find(opponent->deckFileSmall);
if (it == stats->end())
{
stats[opponent->deckFileSmall] = NEW DeckStat(1, victory);
stats->insert( make_pair( opponent->deckFileSmall, NEW DeckStat(1, victory) ));
}
else
{
@@ -186,6 +211,12 @@ void DeckStats::saveStats(Player *player, Player *opponent, GameObserver * game)
save(player);
}
void DeckStats::EndInstance()
{
SAFE_DELETE( mInstance );
}
// StatsWrapper
float noLandsProbInTurn[Constants::STATS_FOR_TURNS] = {0.0f};
@@ -256,10 +287,13 @@ void StatsWrapper::initStatistics(string deckstats)
found = 0;
char buffer[512];
char smallDeckName[512];
sprintf(buffer, "%s/deck%i.txt", RESPATH"/ai/baka", nbDecks + 1);
ostringstream oss;
oss << "deck" << (nbDecks + 1);
string bakaDir = JGE_GET_RES("/ai/baka");
string deckFilename = oss.str();
sprintf(buffer, "%s/%s.txt", bakaDir.c_str(), deckFilename.c_str());
if (fileExists(buffer))
{
MTGDeck * mtgd = NEW MTGDeck(buffer, NULL, 1);
found = 1;
nbDecks++;
@@ -268,11 +302,10 @@ void StatsWrapper::initStatistics(string deckstats)
if ((deckStat != NULL) && (deckStat->nbgames > 0))
{
aiDeckNames.push_back(string(mtgd->meta_name));
aiDeckNames.push_back(deckFilename);
aiDeckStats.push_back(deckStat);
}
delete mtgd;
}
}
else

View File

@@ -22,6 +22,7 @@
#include "GameStateStory.h"
#include "DeckStats.h"
#include "DeckMetaData.h"
#include "DeckManager.h"
#include "Translate.h"
#include "WFilter.h"
@@ -273,7 +274,9 @@ void GameApp::Destroy()
collection->destroyAllCards();
SAFE_DELETE(collection);
}
delete (DeckStats::GetInstance());
DeckManager::EndInstance();
DeckStats::EndInstance();
SAFE_DELETE(Subtypes::subtypesList);
SAFE_DELETE(DeckMetaDataList::decksMetaData);

View File

@@ -1453,8 +1453,12 @@ void GameStateDeckViewer::Render()
int GameStateDeckViewer::loadDeck(int deckid)
{
if (!stw) stw = new StatsWrapper(deckid);
if (!stw)
{
DeckManager *deckManager = DeckManager::GetInstance();
stw = deckManager->getExtendedStatsForDeckId( deckid, mParent->collection, false );
}
stw->currentPage = 0;
stw->pageCount = 9;
stw->needUpdate = true;

View File

@@ -83,7 +83,6 @@ GameStateDuel::GameStateDuel(GameApp* parent) :
GameStateDuel::~GameStateDuel()
{
End();
}
void GameStateDuel::Start()
@@ -156,7 +155,6 @@ void GameStateDuel::Start()
{
mPlayers[i] = NULL;
}
}
void GameStateDuel::loadPlayer(int playerId, int decknb, int isAI)
@@ -231,15 +229,14 @@ void GameStateDuel::End()
DebugTrace("Ending GameStateDuel");
JRenderer::GetInstance()->EnableVSync(false);
DeckManager::EndInstance();
if (!premadeDeck && mPlayers[0] && mPlayers[1]) // save the stats for the game
mPlayers[0]->End();
else if ( !mPlayers[1] && mPlayers[0] )
// clean up player object
SAFE_DELETE( mPlayers[0] );
GameObserver::EndInstance(); // this will delete both player objects if a game has been played
GameObserver::EndInstance(); // this will delete both player objects
game = NULL;
premadeDeck = false;
@@ -248,7 +245,6 @@ void GameStateDuel::End()
mPlayers[i] = NULL;
deck[i] = NULL;
}
SAFE_DELETE(credits);
SAFE_DELETE(rules);

View File

@@ -76,9 +76,11 @@ void SimplePopup::drawBoundingBox( float x, float y, float width, float height )
void SimplePopup::Update(DeckMetaData* selectedDeck)
{
mDeckInformation = selectedDeck;
SAFE_DELETE(mStatsWrapper);
mStatsWrapper = NEW StatsWrapper(mDeckInformation->getDeckId());
mStatsWrapper->updateStats(mDeckInformation->getFilename(), mCollection);
// get the information from the cache, if it doesn't exist create an entry
DeckManager *deckManager = DeckManager::GetInstance();
mStatsWrapper = deckManager->getExtendedDeckStats( mDeckInformation, mCollection, (mDeckInformation->getFilename().find("baka") != string::npos) );
}
@@ -184,6 +186,5 @@ SimplePopup::~SimplePopup(void)
{
mTextFont = NULL;
mDeckInformation = NULL;
SAFE_DELETE(mStatsWrapper);
}

View File

@@ -1022,10 +1022,6 @@
RelativePath=".\include\DamagerDamaged.h"
>
</File>
<File
RelativePath=".\include\DebugRoutines.h"
>
</File>
<File
RelativePath=".\include\DeckDataWrapper.h"
>