update Course stats file format
This commit is contained in:
+95
-487
@@ -33,6 +33,7 @@
|
|||||||
#include "UnlockSystem.h"
|
#include "UnlockSystem.h"
|
||||||
#include "CatalogXml.h"
|
#include "CatalogXml.h"
|
||||||
#include "XmlFile.h"
|
#include "XmlFile.h"
|
||||||
|
#include "Foreach.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Old file versions for backward compatibility
|
// Old file versions for backward compatibility
|
||||||
@@ -338,11 +339,27 @@ int Profile::GetActualCourseDancePointsForStepsType( StepsType st ) const
|
|||||||
if( !pCourse->AllSongsAreFixed() )
|
if( !pCourse->AllSongsAreFixed() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const HighScoresForACourse& h = i->second;
|
const HighScoresForACourse &hsfac = i->second;
|
||||||
FOREACH_ShownCourseDifficulty( cd )
|
|
||||||
|
for( std::map<TrailID,HighScoresForATrail>::const_iterator j = hsfac.m_TrailHighScores.begin();
|
||||||
|
j != hsfac.m_TrailHighScores.end();
|
||||||
|
++j )
|
||||||
{
|
{
|
||||||
const HighScoreList& hs = h.hs[st][cd];
|
const TrailID &id = j->first;
|
||||||
const RadarValues& fRadars = pCourse->GetTrail(st,cd)->GetRadarValues();
|
Trail* pTrail = id.ToTrail( pCourse, true );
|
||||||
|
|
||||||
|
// If the Steps isn't loaded on the current machine, then we can't
|
||||||
|
// get radar values to compute dance points.
|
||||||
|
if( pTrail == NULL )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( pTrail->m_StepsType != st )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const HighScoresForATrail& h = j->second;
|
||||||
|
const HighScoreList& hs = h.hs;
|
||||||
|
|
||||||
|
const RadarValues& fRadars = pTrail->GetRadarValues();
|
||||||
int iPossibleDP = ScoreKeeperMAX2::GetPossibleDancePoints( fRadars );
|
int iPossibleDP = ScoreKeeperMAX2::GetPossibleDancePoints( fRadars );
|
||||||
iTotal += (int)truncf( hs.GetTopScore().fPercentDP * iPossibleDP );
|
iTotal += (int)truncf( hs.GetTopScore().fPercentDP * iPossibleDP );
|
||||||
}
|
}
|
||||||
@@ -463,33 +480,28 @@ void Profile::GetGrades( const Song* pSong, StepsType st, int iCounts[NUM_GRADES
|
|||||||
//
|
//
|
||||||
// Course high scores
|
// Course high scores
|
||||||
//
|
//
|
||||||
void Profile::AddCourseHighScore( const Course* pCourse, StepsType st, CourseDifficulty cd, HighScore hs, int &iIndexOut )
|
void Profile::AddCourseHighScore( const Course* pCourse, const Trail* pTrail, HighScore hs, int &iIndexOut )
|
||||||
|
{
|
||||||
|
GetCourseHighScoreList(pCourse,pTrail).AddHighScore( hs, iIndexOut );
|
||||||
|
}
|
||||||
|
|
||||||
|
const HighScoreList& Profile::GetCourseHighScoreList( const Course* pCourse, const Trail* pTrail ) const
|
||||||
|
{
|
||||||
|
return ((Profile *)this)->GetCourseHighScoreList( pCourse, pTrail );
|
||||||
|
}
|
||||||
|
|
||||||
|
HighScoreList& Profile::GetCourseHighScoreList( const Course* pCourse, const Trail* pTrail )
|
||||||
{
|
{
|
||||||
CourseID courseID;
|
CourseID courseID;
|
||||||
courseID.FromCourse( pCourse );
|
courseID.FromCourse( pCourse );
|
||||||
|
|
||||||
std::map<CourseID,HighScoresForACourse>::iterator iter = m_CourseHighScores.find( courseID );
|
TrailID trailID;
|
||||||
if( iter == m_CourseHighScores.end() )
|
trailID.FromTrail( pTrail );
|
||||||
m_CourseHighScores[courseID].hs[st][cd].AddHighScore( hs, iIndexOut ); // operator[] inserts into map
|
|
||||||
else
|
|
||||||
iter->second.hs[st][cd].AddHighScore( hs, iIndexOut );
|
|
||||||
}
|
|
||||||
|
|
||||||
const HighScoreList& Profile::GetCourseHighScoreList( const Course* pCourse, StepsType st, CourseDifficulty cd ) const
|
HighScoresForACourse &hsCourse = m_CourseHighScores[courseID]; // operator[] inserts into map
|
||||||
{
|
HighScoresForATrail &hsTrail = hsCourse.m_TrailHighScores[trailID]; // operator[] inserts into map
|
||||||
return ((Profile *)this)->GetCourseHighScoreList( pCourse, st, cd );
|
|
||||||
}
|
|
||||||
|
|
||||||
HighScoreList& Profile::GetCourseHighScoreList( const Course* pCourse, StepsType st, CourseDifficulty cd )
|
return hsTrail.hs;
|
||||||
{
|
|
||||||
CourseID courseID;
|
|
||||||
courseID.FromCourse( pCourse );
|
|
||||||
|
|
||||||
std::map<CourseID,HighScoresForACourse>::iterator iter = m_CourseHighScores.find( courseID );
|
|
||||||
if( iter == m_CourseHighScores.end() )
|
|
||||||
return m_CourseHighScores[courseID].hs[st][cd]; // operator[] inserts into map
|
|
||||||
else
|
|
||||||
return iter->second.hs[st][cd];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Profile::GetCourseNumTimesPlayed( const Course* pCourse ) const
|
int Profile::GetCourseNumTimesPlayed( const Course* pCourse ) const
|
||||||
@@ -502,24 +514,25 @@ int Profile::GetCourseNumTimesPlayed( const Course* pCourse ) const
|
|||||||
|
|
||||||
int Profile::GetCourseNumTimesPlayed( const CourseID &courseID ) const
|
int Profile::GetCourseNumTimesPlayed( const CourseID &courseID ) const
|
||||||
{
|
{
|
||||||
std::map<CourseID,HighScoresForACourse>::const_iterator iter = m_CourseHighScores.find( courseID );
|
const HighScoresForACourse *hsCourse = GetHighScoresForACourse( courseID );
|
||||||
if( iter == m_CourseHighScores.end() )
|
if( hsCourse == NULL )
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
else
|
int iTotalNumTimesPlayed = 0;
|
||||||
|
for( std::map<TrailID,HighScoresForATrail>::const_iterator j = hsCourse->m_TrailHighScores.begin();
|
||||||
|
j != hsCourse->m_TrailHighScores.end();
|
||||||
|
j++ )
|
||||||
{
|
{
|
||||||
int iTotalNumTimesPlayed = 0;
|
const HighScoresForATrail &hsTrail = j->second;
|
||||||
for( unsigned st = 0; st < NUM_STEPS_TYPES; ++st )
|
|
||||||
FOREACH_CourseDifficulty( cd )
|
iTotalNumTimesPlayed += hsTrail.hs.iNumTimesPlayed;
|
||||||
iTotalNumTimesPlayed += iter->second.hs[st][cd].iNumTimesPlayed;
|
|
||||||
return iTotalNumTimesPlayed;
|
|
||||||
}
|
}
|
||||||
|
return iTotalNumTimesPlayed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Profile::IncrementCoursePlayCount( const Course* pCourse, StepsType st, CourseDifficulty cd )
|
void Profile::IncrementCoursePlayCount( const Course* pCourse, const Trail* pTrail )
|
||||||
{
|
{
|
||||||
GetCourseHighScoreList(pCourse,st,cd).iNumTimesPlayed++;
|
GetCourseHighScoreList(pCourse,pTrail).iNumTimesPlayed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -576,18 +589,8 @@ bool Profile::LoadAllFromDir( CString sDir, bool bRequireSignature )
|
|||||||
|
|
||||||
InitAll();
|
InitAll();
|
||||||
|
|
||||||
// Only try to load old score formats if we're allowing unsigned data.
|
|
||||||
if( !PREFSMAN->m_bSignProfileData )
|
|
||||||
{
|
|
||||||
LoadProfileDataFromDirSM390a12( sDir );
|
|
||||||
LoadSongScoresFromDirSM390a12( sDir );
|
|
||||||
LoadCourseScoresFromDirSM390a12( sDir );
|
|
||||||
LoadCategoryScoresFromDirSM390a12( sDir );
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadEditableDataFromDir( sDir );
|
LoadEditableDataFromDir( sDir );
|
||||||
|
|
||||||
|
|
||||||
// Read stats.xml
|
// Read stats.xml
|
||||||
FOR_ONCE
|
FOR_ONCE
|
||||||
{
|
{
|
||||||
@@ -690,17 +693,6 @@ bool Profile::SaveAllToDir( CString sDir, bool bSignData ) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Delete old files after saving new ones so we don't try to load old
|
|
||||||
// files the next time and make duplicate records.
|
|
||||||
if( !PREFSMAN->m_bSignProfileData ) // we tried to read the older formats
|
|
||||||
{
|
|
||||||
DeleteProfileDataFromDirSM390a12( sDir );
|
|
||||||
DeleteSongScoresFromDirSM390a12( sDir );
|
|
||||||
DeleteCourseScoresFromDirSM390a12( sDir );
|
|
||||||
DeleteCategoryScoresFromDirSM390a12( sDir );
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool bThisIsMachineProfile = (this == PROFILEMAN->GetMachineProfile()); // XXX
|
const bool bThisIsMachineProfile = (this == PROFILEMAN->GetMachineProfile()); // XXX
|
||||||
if( (bThisIsMachineProfile && PREFSMAN->m_bWriteMachineStatsHtml) ||
|
if( (bThisIsMachineProfile && PREFSMAN->m_bWriteMachineStatsHtml) ||
|
||||||
(!bThisIsMachineProfile && PREFSMAN->m_bWriteProfileStatsHtml) )
|
(!bThisIsMachineProfile && PREFSMAN->m_bWriteProfileStatsHtml) )
|
||||||
@@ -721,43 +713,6 @@ bool Profile::SaveAllToDir( CString sDir, bool bSignData ) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Profile::LoadProfileDataFromDirSM390a12( CString sDir )
|
|
||||||
{
|
|
||||||
CString fn = sDir + SM_390A12_PROFILE_INI;
|
|
||||||
InitEditableData();
|
|
||||||
InitGeneralData();
|
|
||||||
|
|
||||||
//
|
|
||||||
// read ini
|
|
||||||
//
|
|
||||||
IniFile ini;
|
|
||||||
if( !ini.ReadFile( fn ) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
ini.GetValue( "Profile", "DisplayName", m_sDisplayName );
|
|
||||||
ini.GetValue( "Profile", "LastUsedHighScoreName", m_sLastUsedHighScoreName );
|
|
||||||
ini.GetValue( "Profile", "UsingProfileDefaultModifiers", m_bUsingProfileDefaultModifiers );
|
|
||||||
ini.GetValue( "Profile", "DefaultModifiers", m_sDefaultModifiers );
|
|
||||||
ini.GetValue( "Profile", "TotalPlays", m_iTotalPlays );
|
|
||||||
ini.GetValue( "Profile", "TotalPlaySeconds", m_iTotalPlaySeconds );
|
|
||||||
ini.GetValue( "Profile", "TotalGameplaySeconds", m_iTotalGameplaySeconds );
|
|
||||||
ini.GetValue( "Profile", "CurrentCombo", m_iCurrentCombo );
|
|
||||||
ini.GetValue( "Profile", "WeightPounds", m_iWeightPounds );
|
|
||||||
ini.GetValue( "Profile", "CaloriesBurned", m_fTotalCaloriesBurned );
|
|
||||||
ini.GetValue( "Profile", "LastPlayedMachineGuid", m_sLastPlayedMachineGuid );
|
|
||||||
|
|
||||||
unsigned i;
|
|
||||||
for( i=0; i<NUM_PLAY_MODES; i++ )
|
|
||||||
ini.GetValue( "Profile", "NumSongsPlayedByPlayMode"+Capitalize(PlayModeToString((PlayMode)i)), m_iNumSongsPlayedByPlayMode[i] );
|
|
||||||
for( i=0; i<NUM_STYLES; i++ )
|
|
||||||
ini.GetValue( "Profile", "NumSongsPlayedByStyle"+Capitalize(GAMEMAN->GetGameDefForGame(GAMEMAN->GetStyleDefForStyle((Style)i)->m_Game)->m_szName)+Capitalize(GAMEMAN->GetStyleDefForStyle((Style)i)->m_szName), m_iNumSongsPlayedByStyle[i] );
|
|
||||||
for( i=0; i<NUM_DIFFICULTIES; i++ )
|
|
||||||
ini.GetValue( "Profile", "NumSongsPlayedByDifficulty"+Capitalize(DifficultyToString((Difficulty)i)), m_iNumSongsPlayedByDifficulty[i] );
|
|
||||||
for( i=0; i<MAX_METER+1; i++ )
|
|
||||||
ini.GetValue( "Profile", "NumSongsPlayedByMeter"+ssprintf("%d",i), m_iNumSongsPlayedByMeter[i] );
|
|
||||||
}
|
|
||||||
|
|
||||||
void Profile::SaveEditableDataToDir( CString sDir ) const
|
void Profile::SaveEditableDataToDir( CString sDir ) const
|
||||||
{
|
{
|
||||||
IniFile ini;
|
IniFile ini;
|
||||||
@@ -1066,8 +1021,7 @@ XNode* Profile::SaveSongScoresCreateNode() const
|
|||||||
if( pProfile->GetSongNumTimesPlayed(songID) == 0 )
|
if( pProfile->GetSongNumTimesPlayed(songID) == 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
XNode* pSongNode = pNode->AppendChild( songID.CreateNode() );
|
||||||
LPXNode pSongNode = pNode->AppendChild( songID.CreateNode() );
|
|
||||||
|
|
||||||
for( std::map<StepsID,HighScoresForASteps>::const_iterator j = hsSong.m_StepsHighScores.begin();
|
for( std::map<StepsID,HighScoresForASteps>::const_iterator j = hsSong.m_StepsHighScores.begin();
|
||||||
j != hsSong.m_StepsHighScores.end();
|
j != hsSong.m_StepsHighScores.end();
|
||||||
@@ -1082,7 +1036,7 @@ XNode* Profile::SaveSongScoresCreateNode() const
|
|||||||
if( hsl.iNumTimesPlayed == 0 )
|
if( hsl.iNumTimesPlayed == 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
LPXNode pStepsNode = pSongNode->AppendChild( stepsID.CreateNode() );
|
XNode* pStepsNode = pSongNode->AppendChild( stepsID.CreateNode() );
|
||||||
|
|
||||||
pStepsNode->AppendChild( hsl.CreateNode() );
|
pStepsNode->AppendChild( hsl.CreateNode() );
|
||||||
}
|
}
|
||||||
@@ -1093,11 +1047,11 @@ XNode* Profile::SaveSongScoresCreateNode() const
|
|||||||
|
|
||||||
void Profile::LoadSongScoresFromNode( const XNode* pNode )
|
void Profile::LoadSongScoresFromNode( const XNode* pNode )
|
||||||
{
|
{
|
||||||
|
CHECKPOINT;
|
||||||
|
|
||||||
ASSERT( pNode->name == "SongScores" );
|
ASSERT( pNode->name == "SongScores" );
|
||||||
|
|
||||||
for( XNodes::const_iterator song = pNode->childs.begin();
|
FOREACH_CONST( XNode*, pNode->childs, song )
|
||||||
song != pNode->childs.end();
|
|
||||||
song++ )
|
|
||||||
{
|
{
|
||||||
if( (*song)->name != "Song" )
|
if( (*song)->name != "Song" )
|
||||||
continue;
|
continue;
|
||||||
@@ -1107,9 +1061,7 @@ void Profile::LoadSongScoresFromNode( const XNode* pNode )
|
|||||||
if( !songID.IsValid() )
|
if( !songID.IsValid() )
|
||||||
WARN_AND_CONTINUE;
|
WARN_AND_CONTINUE;
|
||||||
|
|
||||||
for( XNodes::iterator steps = (*song)->childs.begin();
|
FOREACH_CONST( XNode*, (*song)->childs, steps )
|
||||||
steps != (*song)->childs.end();
|
|
||||||
steps++ )
|
|
||||||
{
|
{
|
||||||
if( (*steps)->name != "Steps" )
|
if( (*steps)->name != "Steps" )
|
||||||
continue;
|
continue;
|
||||||
@@ -1129,309 +1081,6 @@ void Profile::LoadSongScoresFromNode( const XNode* pNode )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Grade ConvertA12Grade( Grade g )
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Map
|
|
||||||
* GRADE_NO_DATA=0, GRADE_E, GRADE_D, GRADE_C, GRADE_B, GRADE_A,
|
|
||||||
* GRADE_AA,GRADE_AAA,GRADE_AAAA, NUM_GRADES
|
|
||||||
*
|
|
||||||
* to GRADE_TIER_1 (AAAA) ... GRADE_TIER_7 (D), GRADE_FAILED (E), GRADE_NO_DATA.
|
|
||||||
*/
|
|
||||||
switch( g )
|
|
||||||
{
|
|
||||||
case 0: return GRADE_NO_DATA;
|
|
||||||
case 1: return GRADE_FAILED; /* E */
|
|
||||||
case 2: return GRADE_TIER_7; /* D */
|
|
||||||
case 3: return GRADE_TIER_6; /* C */
|
|
||||||
case 4: return GRADE_TIER_5; /* B */
|
|
||||||
case 5: return GRADE_TIER_4; /* A */
|
|
||||||
case 6: return GRADE_TIER_3; /* AA */
|
|
||||||
case 7: return GRADE_TIER_2; /* AAA */
|
|
||||||
case 8: return GRADE_TIER_1; /* AAAA */
|
|
||||||
default: return GRADE_NO_DATA;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Profile::LoadSongScoresFromDirSM390a12( CString sDir )
|
|
||||||
{
|
|
||||||
Profile* pProfile = this;
|
|
||||||
ASSERT( pProfile );
|
|
||||||
|
|
||||||
CString fn = sDir + SM_390A12_SONG_SCORES_DAT;
|
|
||||||
if( !IsAFile(fn) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
RageFile f;
|
|
||||||
if( !f.Open(fn, RageFile::READ) )
|
|
||||||
{
|
|
||||||
LOG->Warn( "Couldn't open file \"%s\": %s", fn.c_str(), f.GetError().c_str() );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int version;
|
|
||||||
if( !FileRead(f, version) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
if( version != SM_390A12_SONG_SCORES_VERSION )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
int iNumSongs;
|
|
||||||
if( !FileRead(f, iNumSongs) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
for( int s=0; s<iNumSongs; s++ )
|
|
||||||
{
|
|
||||||
CString sSongDir;
|
|
||||||
if( !FileRead(f, sSongDir) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
Song* pSong = SONGMAN->GetSongFromDir( sSongDir );
|
|
||||||
|
|
||||||
int iNumNotes;
|
|
||||||
if( !FileRead(f, iNumNotes) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
for( int n=0; n<iNumNotes; n++ )
|
|
||||||
{
|
|
||||||
StepsType st;
|
|
||||||
if( !FileRead(f, (int&)st) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
Difficulty dc;
|
|
||||||
if( !FileRead(f, (int&)dc) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
CString sDescription;
|
|
||||||
if( !FileRead(f, sDescription) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
// Even if pSong or pSteps is null, we still have to skip over that data.
|
|
||||||
|
|
||||||
Steps* pSteps = NULL;
|
|
||||||
if( pSong )
|
|
||||||
{
|
|
||||||
if( dc==DIFFICULTY_INVALID )
|
|
||||||
pSteps = pSong->GetStepsByDescription( st, sDescription );
|
|
||||||
else
|
|
||||||
pSteps = pSong->GetStepsByDifficulty( st, dc );
|
|
||||||
}
|
|
||||||
|
|
||||||
int iNumTimesPlayed;
|
|
||||||
if( !FileRead(f, iNumTimesPlayed) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
HighScoreList &hsl = pProfile->GetStepsHighScoreList(pSong,pSteps);
|
|
||||||
|
|
||||||
if( pSteps )
|
|
||||||
hsl.iNumTimesPlayed = iNumTimesPlayed;
|
|
||||||
|
|
||||||
int iNumHighScores;
|
|
||||||
if( !FileRead(f, iNumHighScores) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
if( pSteps )
|
|
||||||
hsl.vHighScores.resize( iNumHighScores );
|
|
||||||
|
|
||||||
int l;
|
|
||||||
for( l=0; l<iNumHighScores; l++ )
|
|
||||||
{
|
|
||||||
CString sName;
|
|
||||||
if( !FileRead(f, sName) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
Grade grade;
|
|
||||||
if( !FileRead(f, (int&)grade) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
grade = ConvertA12Grade( grade );
|
|
||||||
|
|
||||||
int iScore;
|
|
||||||
if( !FileRead(f, iScore) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
float fPercentDP;
|
|
||||||
if( !FileRead(f, fPercentDP) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
if( grade == NUM_GRADES || grade == GRADE_NO_DATA )
|
|
||||||
continue; // ignore this high score
|
|
||||||
if( pSteps == NULL )
|
|
||||||
continue; // ignore this high score
|
|
||||||
|
|
||||||
hsl.vHighScores[l].sName = sName;
|
|
||||||
hsl.vHighScores[l].grade = grade;
|
|
||||||
hsl.vHighScores[l].iScore = iScore;
|
|
||||||
hsl.vHighScores[l].fPercentDP = fPercentDP;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore all high scores that are 0
|
|
||||||
for( l=0; l<iNumHighScores; l++ )
|
|
||||||
{
|
|
||||||
if( pSteps && hsl.vHighScores[l].iScore <= 0 )
|
|
||||||
{
|
|
||||||
hsl.vHighScores.resize(l);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Profile::LoadCategoryScoresFromDirSM390a12( CString sDir )
|
|
||||||
{
|
|
||||||
CHECKPOINT;
|
|
||||||
|
|
||||||
Profile* pProfile = this;
|
|
||||||
ASSERT( pProfile );
|
|
||||||
|
|
||||||
CString fn = sDir + SM_390A12_CATEGORY_SCORES_DAT;
|
|
||||||
if( !IsAFile(fn) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
RageFile f;
|
|
||||||
if( !f.Open(fn, RageFile::READ) )
|
|
||||||
{
|
|
||||||
LOG->Warn( "Couldn't open file \"%s\": %s", fn.c_str(), f.GetError().c_str() );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int version;
|
|
||||||
if( !FileRead(f, version) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
if( version != SM_390A12_CATEGORY_RANKING_VERSION )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
/* NUM_STEPS_TYPES changed after A12. Only read up to the last unchanged type. We
|
|
||||||
* can probably drop all of this compatibility code before the final release, anyway ... */
|
|
||||||
for( int st=0; st<=STEPS_TYPE_DS3DDX_SINGLE; st++ )
|
|
||||||
{
|
|
||||||
for( int rc=0; rc<NUM_RANKING_CATEGORIES; rc++ )
|
|
||||||
{
|
|
||||||
int iNumHighScores;
|
|
||||||
if( !FileRead(f, iNumHighScores) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
HighScoreList &hsl = pProfile->GetCategoryHighScoreList( (StepsType)st, (RankingCategory)rc );
|
|
||||||
hsl.vHighScores.resize( iNumHighScores );
|
|
||||||
|
|
||||||
for( int l=0; l<iNumHighScores; l++ )
|
|
||||||
{
|
|
||||||
CString sName;
|
|
||||||
if( !FileRead(f, sName) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
int iScore;
|
|
||||||
if( !FileRead(f, iScore) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
float fPercentDP;
|
|
||||||
if( !FileRead(f, fPercentDP) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
hsl.vHighScores[l].sName = sName;
|
|
||||||
hsl.vHighScores[l].iScore = iScore;
|
|
||||||
hsl.vHighScores[l].fPercentDP = fPercentDP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Profile::LoadCourseScoresFromDirSM390a12( CString sDir )
|
|
||||||
{
|
|
||||||
CHECKPOINT;
|
|
||||||
|
|
||||||
Profile* pProfile = this;
|
|
||||||
ASSERT( pProfile );
|
|
||||||
|
|
||||||
CString fn = sDir + SM_390A12_COURSE_SCORES_DAT;
|
|
||||||
if( !IsAFile(fn) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
RageFile f;
|
|
||||||
if( !f.Open(fn, RageFile::READ) )
|
|
||||||
{
|
|
||||||
LOG->Warn( "Couldn't open file \"%s\": %s", fn.c_str(), f.GetError().c_str() );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int version;
|
|
||||||
if( !FileRead(f, version) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
if( version != SM_390A12_COURSE_SCORES_VERSION )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
int iNumCourses;
|
|
||||||
if( !FileRead(f, iNumCourses) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
for( int c=0; c<iNumCourses; c++ )
|
|
||||||
{
|
|
||||||
CString sPath;
|
|
||||||
if( !FileRead(f, sPath) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
Course* pCourse = SONGMAN->GetCourseFromPath( sPath );
|
|
||||||
if( pCourse == NULL )
|
|
||||||
pCourse = SONGMAN->GetCourseFromName( sPath );
|
|
||||||
|
|
||||||
// even if we don't find the Course*, we still have to read past the input
|
|
||||||
|
|
||||||
int NumStepsTypesPlayed = 0;
|
|
||||||
if( !FileRead(f, NumStepsTypesPlayed) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
while( NumStepsTypesPlayed-- )
|
|
||||||
{
|
|
||||||
int st;
|
|
||||||
if( !FileRead(f, st) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
int iNumTimesPlayed;
|
|
||||||
if( !FileRead(f, iNumTimesPlayed) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
HighScoreList &hsl = pProfile->GetCourseHighScoreList( pCourse, (StepsType)st, COURSE_DIFFICULTY_REGULAR );
|
|
||||||
|
|
||||||
if( pCourse )
|
|
||||||
hsl.iNumTimesPlayed = iNumTimesPlayed;
|
|
||||||
|
|
||||||
int iNumHighScores;
|
|
||||||
if( !FileRead(f, iNumHighScores) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
if( pCourse )
|
|
||||||
hsl.vHighScores.resize(iNumHighScores);
|
|
||||||
|
|
||||||
for( int l=0; l<iNumHighScores; l++ )
|
|
||||||
{
|
|
||||||
CString sName;
|
|
||||||
if( !FileRead(f, sName) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
int iScore;
|
|
||||||
if( !FileRead(f, iScore) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
float fPercentDP;
|
|
||||||
if( !FileRead(f, fPercentDP) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
float fSurviveSeconds;
|
|
||||||
if( !FileRead(f, fSurviveSeconds) )
|
|
||||||
WARN_AND_RETURN;
|
|
||||||
|
|
||||||
if( pCourse && st < NUM_STEPS_TYPES )
|
|
||||||
{
|
|
||||||
hsl.vHighScores[l].sName = sName;
|
|
||||||
hsl.vHighScores[l].iScore = iScore;
|
|
||||||
hsl.vHighScores[l].fPercentDP = fPercentDP;
|
|
||||||
hsl.vHighScores[l].fSurviveSeconds = fSurviveSeconds;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
XNode* Profile::SaveCourseScoresCreateNode() const
|
XNode* Profile::SaveCourseScoresCreateNode() const
|
||||||
{
|
{
|
||||||
@@ -1448,39 +1097,31 @@ XNode* Profile::SaveCourseScoresCreateNode() const
|
|||||||
i != m_CourseHighScores.end();
|
i != m_CourseHighScores.end();
|
||||||
i++ )
|
i++ )
|
||||||
{
|
{
|
||||||
const CourseID &id = i->first;
|
const CourseID &courseID = i->first;
|
||||||
const HighScoresForACourse &hsCourse = i->second;
|
const HighScoresForACourse &hsCourse = i->second;
|
||||||
|
|
||||||
// skip courses that have never been played
|
// skip courses that have never been played
|
||||||
if( pProfile->GetCourseNumTimesPlayed(id) == 0 )
|
if( pProfile->GetCourseNumTimesPlayed(courseID) == 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
XNode* pCourseNode = pNode->AppendChild( id.CreateNode() );
|
XNode* pCourseNode = pNode->AppendChild( courseID.CreateNode() );
|
||||||
|
|
||||||
for( StepsType st=(StepsType)0; st<NUM_STEPS_TYPES; ((int&)st)++ )
|
for( std::map<TrailID,HighScoresForATrail>::const_iterator j = hsCourse.m_TrailHighScores.begin();
|
||||||
|
j != hsCourse.m_TrailHighScores.end();
|
||||||
|
j++ )
|
||||||
{
|
{
|
||||||
// TRICKY: Only append this node if one we have at least one child.
|
const TrailID &trailID = j->first;
|
||||||
// There's no point to saving a bunch of empty StepsType nodes.
|
const HighScoresForATrail &hsTrail = j->second;
|
||||||
LPXNode pStepsTypeNode = new XNode;
|
|
||||||
pStepsTypeNode->name = "StepsType";
|
|
||||||
pStepsTypeNode->AppendAttr( "Type", GameManager::NotesTypeToString(st) );
|
|
||||||
|
|
||||||
FOREACH_CourseDifficulty( cd )
|
const HighScoreList &hsl = hsTrail.hs;
|
||||||
{
|
|
||||||
const HighScoreList &hsl = hsCourse.hs[st][cd];
|
|
||||||
|
|
||||||
// skip course/steps types that have never been played
|
// skip steps that have never been played
|
||||||
if( hsl.iNumTimesPlayed == 0 )
|
if( hsl.iNumTimesPlayed == 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
LPXNode pCourseDifficultyNode = pStepsTypeNode->AppendChild( "CourseDifficulty" );
|
XNode* pTrailNode = pCourseNode->AppendChild( trailID.CreateNode() );
|
||||||
pCourseDifficultyNode->AppendAttr( "Type", CourseDifficultyToString(cd) );
|
|
||||||
|
|
||||||
pCourseDifficultyNode->AppendChild( hsl.CreateNode() );
|
pTrailNode->AppendChild( hsl.CreateNode() );
|
||||||
}
|
|
||||||
|
|
||||||
if( !pStepsTypeNode->childs.empty() )
|
|
||||||
pCourseNode->AppendChild( pStepsTypeNode );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1493,51 +1134,32 @@ void Profile::LoadCourseScoresFromNode( const XNode* pNode )
|
|||||||
|
|
||||||
ASSERT( pNode->name == "CourseScores" );
|
ASSERT( pNode->name == "CourseScores" );
|
||||||
|
|
||||||
for( XNodes::const_iterator course = pNode->childs.begin();
|
FOREACH_CONST( XNode*, pNode->childs, course )
|
||||||
course != pNode->childs.end();
|
|
||||||
course++ )
|
|
||||||
{
|
{
|
||||||
if( (*course)->name != "Course" )
|
if( (*course)->name != "Course" )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CourseID id;
|
CourseID courseID;
|
||||||
id.LoadFromNode( *course );
|
courseID.LoadFromNode( *course );
|
||||||
if( !id.IsValid() )
|
if( !courseID.IsValid() )
|
||||||
WARN_AND_CONTINUE;
|
WARN_AND_CONTINUE;
|
||||||
|
|
||||||
for( XNodes::iterator stepsType = (*course)->childs.begin();
|
FOREACH_CONST( XNode*, (*course)->childs, trail )
|
||||||
stepsType != (*course)->childs.end();
|
|
||||||
stepsType++ )
|
|
||||||
{
|
{
|
||||||
if( (*stepsType)->name != "StepsType" )
|
if( (*trail)->name != "Trail" )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CString str;
|
TrailID trailID;
|
||||||
if( !(*stepsType)->GetAttrValue( "Type", str ) )
|
trailID.LoadFromNode( *trail );
|
||||||
WARN_AND_CONTINUE;
|
if( !trailID.IsValid() )
|
||||||
StepsType st = GameManager::StringToNotesType( str );
|
|
||||||
if( st == STEPS_TYPE_INVALID )
|
|
||||||
WARN_AND_CONTINUE;
|
WARN_AND_CONTINUE;
|
||||||
|
|
||||||
for( XNodes::iterator courseDifficulty = (*stepsType)->childs.begin();
|
XNode *pHighScoreListNode = (*trail)->GetChild("HighScoreList");
|
||||||
courseDifficulty != (*stepsType)->childs.end();
|
if( pHighScoreListNode == NULL )
|
||||||
courseDifficulty++ )
|
WARN_AND_CONTINUE;
|
||||||
{
|
|
||||||
|
|
||||||
const LPXAttr TypeAttr = (*courseDifficulty)->GetAttr( "Type" );
|
HighScoreList &hsl = m_CourseHighScores[courseID].m_TrailHighScores[trailID].hs;
|
||||||
if( TypeAttr == NULL )
|
hsl.LoadFromNode( pHighScoreListNode );
|
||||||
WARN_AND_CONTINUE;
|
|
||||||
CourseDifficulty cd = StringToCourseDifficulty( TypeAttr->value );
|
|
||||||
if( cd == COURSE_DIFFICULTY_INVALID )
|
|
||||||
WARN_AND_CONTINUE;
|
|
||||||
|
|
||||||
XNode *pHighScoreListNode = (*courseDifficulty)->GetChild("HighScoreList");
|
|
||||||
if( pHighScoreListNode == NULL )
|
|
||||||
WARN_AND_CONTINUE;
|
|
||||||
|
|
||||||
HighScoreList &hsl = m_CourseHighScores[id].hs[st][cd];
|
|
||||||
hsl.LoadFromNode( pHighScoreListNode );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1622,30 +1244,6 @@ void Profile::LoadCategoryScoresFromNode( const XNode* pNode )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Profile::DeleteProfileDataFromDirSM390a12( CString sDir ) const
|
|
||||||
{
|
|
||||||
CString fn = sDir + SM_390A12_PROFILE_INI;
|
|
||||||
FILEMAN->Remove( fn );
|
|
||||||
}
|
|
||||||
|
|
||||||
void Profile::DeleteSongScoresFromDirSM390a12( CString sDir ) const
|
|
||||||
{
|
|
||||||
CString fn = sDir + SM_390A12_SONG_SCORES_DAT;
|
|
||||||
FILEMAN->Remove( fn );
|
|
||||||
}
|
|
||||||
|
|
||||||
void Profile::DeleteCourseScoresFromDirSM390a12( CString sDir ) const
|
|
||||||
{
|
|
||||||
CString fn = sDir + SM_390A12_COURSE_SCORES_DAT;
|
|
||||||
FILEMAN->Remove( fn );
|
|
||||||
}
|
|
||||||
|
|
||||||
void Profile::DeleteCategoryScoresFromDirSM390a12( CString sDir ) const
|
|
||||||
{
|
|
||||||
CString fn = sDir + SM_390A12_CATEGORY_SCORES_DAT;
|
|
||||||
FILEMAN->Remove( fn );
|
|
||||||
}
|
|
||||||
|
|
||||||
void Profile::SaveStatsWebPageToDir( CString sDir ) const
|
void Profile::SaveStatsWebPageToDir( CString sDir ) const
|
||||||
{
|
{
|
||||||
ASSERT( PROFILEMAN );
|
ASSERT( PROFILEMAN );
|
||||||
@@ -2084,10 +1682,11 @@ XNode* Profile::SaveRecentCourseScoresCreateNode() const
|
|||||||
return pNode;
|
return pNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Profile::AddCourseRecentScore( const Course* pCourse, StepsType st, CourseDifficulty cd, HighScore hs )
|
void Profile::AddCourseRecentScore( const Course* pCourse, const Trail* pTrail, HighScore hs )
|
||||||
{
|
{
|
||||||
HighScoreForACourse h;
|
HighScoreForACourse h;
|
||||||
h.courseID.FromCourse( pCourse );
|
h.courseID.FromCourse( pCourse );
|
||||||
|
h.trailID.FromTrail( pTrail );
|
||||||
h.hs = hs;
|
h.hs = hs;
|
||||||
m_vRecentCourseScores.push_back( h );
|
m_vRecentCourseScores.push_back( h );
|
||||||
}
|
}
|
||||||
@@ -2100,3 +1699,12 @@ const Profile::HighScoresForASong *Profile::GetHighScoresForASong( const SongID&
|
|||||||
return NULL;
|
return NULL;
|
||||||
return &it->second;
|
return &it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Profile::HighScoresForACourse *Profile::GetHighScoresForACourse( const CourseID& courseID ) const
|
||||||
|
{
|
||||||
|
std::map<CourseID,HighScoresForACourse>::const_iterator it;
|
||||||
|
it = m_CourseHighScores.find( courseID );
|
||||||
|
if( it == m_CourseHighScores.end() )
|
||||||
|
return NULL;
|
||||||
|
return &it->second;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user