Skip to content

Commit

Permalink
initial test of new save structure
Browse files Browse the repository at this point in the history
  • Loading branch information
MinaciousGrace committed Apr 20, 2017
1 parent 884b450 commit 82a0b9c
Show file tree
Hide file tree
Showing 2 changed files with 198 additions and 24 deletions.
199 changes: 175 additions & 24 deletions src/Profile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <algorithm>

const RString STATS_XML = "Stats.xml";
const RString ETT_XML = "ETT.xml";
const RString STATS_XML_GZ = "Stats.xml.gz";
/** @brief The filename for where one can edit their personal profile information. */
const RString EDITABLE_INI = "Editable.ini";
Expand Down Expand Up @@ -1325,7 +1326,8 @@ bool Profile::SaveAllToDir( const RString &sDir, bool bSignData ) const
// Save editable.ini
SaveEditableDataToDir( sDir );

bool bSaved = SaveStatsXmlToDir( sDir, bSignData );
//bool bSaved = SaveStatsXmlToDir( sDir, bSignData );
bool bSaved = SaveEttXmlToDir(sDir, bSignData);

SaveStatsWebPageToDir( sDir );

Expand Down Expand Up @@ -1376,6 +1378,16 @@ XNode *Profile::SaveStatsXmlCreateNode() const
return xml;
}

XNode *Profile::SaveEttXmlCreateNode() const
{
XNode *xml = new XNode("Stats");

xml->AppendChild(SaveGeneralDataCreateNode());
xml->AppendChild(SaveEttScoresCreateNode());

return xml;
}

bool Profile::SaveStatsXmlToDir( RString sDir, bool bSignData ) const
{
LOG->Trace( "SaveStatsXmlToDir: %s", sDir.c_str() );
Expand Down Expand Up @@ -1432,6 +1444,62 @@ bool Profile::SaveStatsXmlToDir( RString sDir, bool bSignData ) const
return true;
}

bool Profile::SaveEttXmlToDir(RString sDir, bool bSignData) const
{
LOG->Trace("SaveStatsXmlToDir: %s", sDir.c_str());
unique_ptr<XNode> xml(SaveEttXmlCreateNode());

sDir += PROFILEMAN->GetStatsPrefix();
// Save stats.xml
RString fn = sDir + (g_bProfileDataCompress ? STATS_XML_GZ : ETT_XML);

{
RString sError;
RageFile f;
if (!f.Open(fn, RageFile::WRITE))
{
LuaHelpers::ReportScriptErrorFmt("Couldn't open %s for writing: %s", fn.c_str(), f.GetError().c_str());
return false;
}

if (g_bProfileDataCompress)
{
RageFileObjGzip gzip(&f);
gzip.Start();
if (!XmlFileUtil::SaveToFile(xml.get(), gzip, "", false))
return false;

if (gzip.Finish() == -1)
return false;

/* After successfully saving STATS_XML_GZ, remove any stray STATS_XML. */
if (FILEMAN->IsAFile(sDir + STATS_XML))
FILEMAN->Remove(sDir + STATS_XML);
}
else
{
if (!XmlFileUtil::SaveToFile(xml.get(), f, "", false))
return false;

/* After successfully saving STATS_XML, remove any stray STATS_XML_GZ. */
if (FILEMAN->IsAFile(sDir + STATS_XML_GZ))
FILEMAN->Remove(sDir + STATS_XML_GZ);
}
}

if (bSignData)
{
RString sStatsXmlSigFile = fn + SIGNATURE_APPEND;
CryptManager::SignFileToFile(fn, sStatsXmlSigFile);

// Save the "don't share" file
RString sDontShareFile = sDir + DONT_SHARE_SIG;
CryptManager::SignFileToFile(sStatsXmlSigFile, sDontShareFile);
}

return true;
}

void Profile::SaveTypeToDir(const RString &dir) const
{
IniFile ini;
Expand Down Expand Up @@ -1948,45 +2016,90 @@ float Profile::CalculateCaloriesFromHeartRate(float HeartRate, float Duration)
/ 4.184f) * Duration;
}

XNode* Profile::SaveSongScoresCreateNode() const
XNode* Profile::SaveSongScoresCreateNode() const
{
CHECKPOINT_M("Getting the node to save song scores.");

const Profile* pProfile = this;
ASSERT(pProfile != NULL);

XNode* pNode = new XNode("SongScores");

FOREACHM_CONST(SongID, HighScoresForASong, m_SongHighScores, i)
{
const SongID &songID = i->first;
const HighScoresForASong &hsSong = i->second;

// skip songs that have never been played
if (pProfile->GetSongNumTimesPlayed(songID) == 0)
continue;

XNode* pSongNode = pNode->AppendChild(songID.CreateNode());

int jCheck2 = hsSong.m_StepsHighScores.size();
int jCheck1 = 0;
FOREACHM_CONST(StepsID, HighScoresForASteps, hsSong.m_StepsHighScores, j)
{
jCheck1++;
ASSERT(jCheck1 <= jCheck2);
const StepsID &stepsID = j->first;
const HighScoresForASteps &hsSteps = j->second;

const HighScoreList &hsl = hsSteps.hsl;

// skip steps that have never been played
if (hsl.GetNumTimesPlayed() == 0)
continue;

XNode* pStepsNode = pSongNode->AppendChild(stepsID.CreateNode());

pStepsNode->AppendChild(hsl.CreateNode());
}
}

return pNode;
}

XNode* Profile::SaveEttScoresCreateNode() const
{
CHECKPOINT_M("Getting the node to save song scores.");

const Profile* pProfile = this;
ASSERT( pProfile != NULL );

XNode* pNode = new XNode( "SongScores" );

FOREACHM_CONST( SongID, HighScoresForASong, m_SongHighScores, i )
FOREACHM_CONST( RString, HighScoreRateMap, HighScoresByChartKey, i )
{
const SongID &songID = i->first;
const HighScoresForASong &hsSong = i->second;
const RString &ck = i->first;
const HighScoreRateMap &hsrm = i->second;
XNode* pChartKey = new XNode("Chart");

// skip songs that have never been played
if( pProfile->GetSongNumTimesPlayed(songID) == 0 )
Song* psong = SONGMAN->GetSongByChartkey(ck);

// sometimes scores on invalid songs get loaded even though there is literally an isvalid check before any scores are loaded..??
if (!psong)
continue;

XNode* pSongNode = pNode->AppendChild( songID.CreateNode() );
pChartKey->AppendAttr("Key", ck);
pChartKey->AppendAttr("SongTitle", psong->GetDisplayMainTitle());

int jCheck2 = hsSong.m_StepsHighScores.size();
int jCheck1 = 0;
FOREACHM_CONST( StepsID, HighScoresForASteps, hsSong.m_StepsHighScores, j )
XNode* pScores = new XNode("RateScores");
FOREACHM_CONST( float, vector<HighScore>, hsrm, j )
{
jCheck1++;
ASSERT( jCheck1 <= jCheck2 );
const StepsID &stepsID = j->first;
const HighScoresForASteps &hsSteps = j->second;

const HighScoreList &hsl = hsSteps.hsl;

// skip steps that have never been played
if( hsl.GetNumTimesPlayed() == 0 )
continue;
const float &rate = j->first;
const vector<HighScore> &hsv = j->second;

XNode* pStepsNode = pSongNode->AppendChild( stepsID.CreateNode() );
XNode* pRateScores = new XNode(ssprintf("%f", rate));
FOREACH_CONST(HighScore, hsv, hs) {
const HighScore &chs = *hs;
pRateScores->AppendChild(chs.CreateNode());
}

pStepsNode->AppendChild( hsl.CreateNode() );
pScores->AppendChild(pRateScores);
}
pChartKey->AppendChild(pScores);
pNode->AppendChild(pChartKey);
}

return pNode;
Expand Down Expand Up @@ -2103,6 +2216,16 @@ void Profile::LoadSongScoresFromNode( const XNode* pSongScores )
}
}

// more future goalman stuff
void Profile::CreateGoal(RString ck) {
Goal goal;
goal.assigned = DateTime::GetNowDateTime();
goal.chartkey = ck;
//goal.rate = GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate;
goalmap[ck].emplace_back(goal);
LOG->Trace("New goal created %i goals", goalmap[ck].size());
}

/* This is really lame because for whatever reason getting the highscore object and passing them
to lua results in really weird and unpredictable errors that I can't figure out, so instead we pass
lua the keys and let the lua function get the highscore objects */
Expand Down Expand Up @@ -3417,6 +3540,19 @@ class LunaProfile : public Luna<Profile>
return 1;
}

static int GetGoalByKey(T* p, lua_State *L) {
RString ck = SArg(1);
auto it = p->goalmap.find(ck);
if (it == p->goalmap.end()) {
lua_pushnil(L);
}
else {
p->goalmap[SArg(1)].front().PushSelf(L);
}

return 1;
}

LunaProfile()
{
ADD_METHOD( AddScreenshot );
Expand Down Expand Up @@ -3498,10 +3634,25 @@ class LunaProfile : public Luna<Profile>
ADD_METHOD( RecalcTopSSR );
ADD_METHOD( GetPBHighScoreByKey );
ADD_METHOD( ValidateAllScores );
ADD_METHOD( GetGoalByKey);
}
};

LUA_REGISTER_CLASS( Profile )
class LunaGoal : public Luna<Goal>
{
public:
static int GetRate(T* p, lua_State *L) {
lua_pushnumber(L, p->rate);
return 1;
}

LunaGoal()
{
ADD_METHOD( GetRate );
}
};
LUA_REGISTER_CLASS(Goal)
// lua end


Expand Down
23 changes: 23 additions & 0 deletions src/Profile.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,21 @@ enum ProfileType
ProfileType_Invalid
};

// future goalman stuff - Mina
class Goal
{
public:
float rate = 1.f;
float percent = 93.f;
int priority = 1;
DateTime assigned;
DateTime achieved;
RString comment = "";
RString chartkey = "";

void PushSelf(lua_State *L);
};

/**
* @brief Player data that persists between sessions.
*
Expand Down Expand Up @@ -257,6 +272,10 @@ class Profile
// Vector for now, we can make this more efficient later
vector<RString> FavoritedCharts;

// more future goalman stuff
void CreateGoal(RString ck);
map<RString, vector<Goal>> goalmap;

/* store arbitrary data for the theme within a profile */
LuaTable m_UserTable;

Expand Down Expand Up @@ -337,6 +356,7 @@ class Profile
typedef map<float, vector<HighScore>> HighScoreRateMap;
map<RString, HighScoreRateMap> HighScoresByChartKey;


// Screenshot Data
vector<Screenshot> m_vScreenshots;
void AddScreenshot( const Screenshot &screenshot );
Expand Down Expand Up @@ -433,9 +453,12 @@ class Profile
void SaveTypeToDir(const RString &dir) const;
void SaveEditableDataToDir( const RString &sDir ) const;
bool SaveStatsXmlToDir( RString sDir, bool bSignData ) const;
bool SaveEttXmlToDir(RString sDir, bool bSignData) const;
XNode* SaveStatsXmlCreateNode() const;
XNode* SaveEttXmlCreateNode() const;
XNode* SaveGeneralDataCreateNode() const;
XNode* SaveSongScoresCreateNode() const;
XNode* SaveEttScoresCreateNode() const;
XNode* SaveCourseScoresCreateNode() const;
XNode* SaveCategoryScoresCreateNode() const;
XNode* SaveScreenshotDataCreateNode() const;
Expand Down

0 comments on commit 82a0b9c

Please sign in to comment.