From d7f0e6c2bc63611963d2a1af83b152ae51ed87fd Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Mon, 9 Feb 2004 06:26:13 +0000 Subject: [PATCH] move all high score data into Profile --- stepmania/src/Course.cpp | 50 +- stepmania/src/Course.h | 53 -- stepmania/src/GameState.cpp | 131 +++-- stepmania/src/MusicWheelItem.cpp | 5 +- stepmania/src/PaneDisplay.cpp | 31 +- stepmania/src/Profile.cpp | 170 +++++- stepmania/src/Profile.h | 84 +++ stepmania/src/ProfileManager.cpp | 555 +++++++++++-------- stepmania/src/ProfileManager.h | 63 ++- stepmania/src/ScreenEvaluation.cpp | 28 +- stepmania/src/ScreenGameplay.cpp | 13 +- stepmania/src/ScreenNameEntryTraditional.cpp | 8 +- stepmania/src/ScreenRanking.cpp | 40 +- stepmania/src/ScreenSelectCourse.cpp | 17 +- stepmania/src/ScreenSelectMusic.cpp | 24 +- stepmania/src/Song.cpp | 40 +- stepmania/src/Steps.cpp | 55 +- stepmania/src/Steps.h | 52 -- stepmania/src/song.h | 4 +- 19 files changed, 796 insertions(+), 627 deletions(-) diff --git a/stepmania/src/Course.cpp b/stepmania/src/Course.cpp index 6317cf36a4..d8154d3a81 100644 --- a/stepmania/src/Course.cpp +++ b/stepmania/src/Course.cpp @@ -439,23 +439,6 @@ void Course::AutogenNonstopFromGroup( CString sGroupName, vector &apSongs m_entries.pop_back(); } -void Course::MemCardData::AddHighScore( HighScore hs, int &iIndexOut ) -{ - int i; - for( i=0; i<(int)vHighScores.size(); i++ ) - { - if( hs >= vHighScores[i] ) - break; - } - if( i < NUM_RANKING_LINES ) - { - vHighScores.insert( vHighScores.begin()+i, hs ); - iIndexOut = i; - if( vHighScores.size() > unsigned(NUM_RANKING_LINES) ) - vHighScores.erase( vHighScores.begin()+NUM_RANKING_LINES, vHighScores.end() ); - } -} - /* * Difficult courses do the following: * @@ -1029,24 +1012,6 @@ bool Course::IsRanking() const return false; } -void Course::AddHighScore( StepsType st, PlayerNumber pn, MemCardData::HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut ) -{ - hs.sName = RANKING_TO_FILL_IN_MARKER[pn]; - if( PROFILEMAN->IsUsingProfile(pn) ) - m_MemCardDatas[st][pn].AddHighScore( hs, iPersonalIndexOut ); - else - iPersonalIndexOut = -1; - m_MemCardDatas[st][PROFILE_SLOT_MACHINE].AddHighScore( hs, iMachineIndexOut ); -} - -int Course::GetNumTimesPlayed( ProfileSlot card ) const -{ - int iTotalNumTimesPlayed = 0; - for( unsigned i = 0; i < NUM_STEPS_TYPES; ++i ) - iTotalNumTimesPlayed += GetNumTimesPlayed( (StepsType) i, card ); - return iTotalNumTimesPlayed; -} - static map course_sort_val; bool CompareCoursePointersBySortValueAscending(const Course *pSong1, const Course *pSong2) @@ -1077,18 +1042,15 @@ void SortCoursePointerArrayByAvgDifficulty( vector &apCourses ) } -void SortCoursePointerArrayByMostPlayed( vector &arrayCoursePointers, ProfileSlot card ) +void SortCoursePointerArrayByMostPlayed( vector &arrayCoursePointers, ProfileSlot slot ) { + Profile* pProfile = PROFILEMAN->GetProfile(slot); + if( pProfile == NULL ) + return; // nothing to do since we don't have data + for(unsigned i = 0; i < arrayCoursePointers.size(); ++i) - course_sort_val[arrayCoursePointers[i]] = (float) arrayCoursePointers[i]->GetNumTimesPlayed( card ); + course_sort_val[arrayCoursePointers[i]] = (float) pProfile->GetCourseNumTimesPlayed(arrayCoursePointers[i]); stable_sort( arrayCoursePointers.begin(), arrayCoursePointers.end(), CompareCoursePointersBySortValueDescending ); course_sort_val.clear(); } -bool Course::MemCardData::HighScore::operator>=( const HighScore& other ) const -{ - if( PREFSMAN->m_bPercentageScoring ) - return fPercentDP >= other.fPercentDP; - else - return iScore >= other.iScore; -} diff --git a/stepmania/src/Course.h b/stepmania/src/Course.h index 9632753333..5cba8c5ba6 100644 --- a/stepmania/src/Course.h +++ b/stepmania/src/Course.h @@ -139,59 +139,6 @@ public: void AutogenNonstopFromGroup( CString sGroupName, vector &apSongsInGroup ); - struct MemCardData - { - MemCardData() - { - iNumTimesPlayed = 0; - } - - int iNumTimesPlayed; - - struct HighScore - { - CString sName; - int iScore; - float fPercentDP; - float fSurviveTime; - - HighScore() - { - iScore = 0; - fPercentDP = 0; - fSurviveTime = 0; - } - - bool operator>=( const HighScore& other ) const; - }; - vector vHighScores; - - void AddHighScore( HighScore hs, int &iIndexOut ); - - HighScore GetTopScore() - { - if( vHighScores.empty() ) - return HighScore(); - else - return vHighScores[0]; - } - - } m_MemCardDatas[NUM_STEPS_TYPES][NUM_PROFILE_SLOTS]; - - void AddHighScore( StepsType st, PlayerNumber pn, MemCardData::HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut ); - - MemCardData::HighScore GetTopScore( StepsType st, ProfileSlot slot ) - { - return m_MemCardDatas[st][slot].GetTopScore(); - } - - int GetNumTimesPlayed( StepsType st, ProfileSlot slot ) const - { - return m_MemCardDatas[st][slot].iNumTimesPlayed; - } - - int GetNumTimesPlayed( ProfileSlot slot ) const; - // sorting values int SortOrder_TotalDifficulty; int SortOrder_Ranking; diff --git a/stepmania/src/GameState.cpp b/stepmania/src/GameState.cpp index 1e5cea2861..066ec73594 100644 --- a/stepmania/src/GameState.cpp +++ b/stepmania/src/GameState.cpp @@ -1132,48 +1132,56 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector &asFeatsO Steps* pSteps = vSongAndSteps[i].pSteps; // Find Machine Records - vector &vMachineHighScores = pSteps->m_MemCardDatas[PROFILE_SLOT_MACHINE].vHighScores; - for( j=0; jGetMachineProfile()->GetStepsHighScoreList(pSteps); + for( j=0; jGetTranslitMainTitle().c_str(), DifficultyToString(pSteps->GetDifficulty()).c_str() ); - feat.pStringToFill = &vMachineHighScores[j].sName; - feat.grade = vMachineHighScores[j].grade; - feat.fPercentDP = vMachineHighScores[j].fPercentDP; - feat.iScore = vMachineHighScores[j].iScore; + if( hs.sName != RANKING_TO_FILL_IN_MARKER[pn] ) + continue; - if( pSong->HasBanner() ) - feat.Banner = pSong->GetBannerPath(); + RankingFeats feat; + feat.Type = RankingFeats::SONG; + feat.Feat = ssprintf("MR #%d in %s %s", j+1, pSong->GetTranslitMainTitle().c_str(), DifficultyToString(pSteps->GetDifficulty()).c_str() ); + feat.pStringToFill = &hs.sName; + feat.grade = hs.grade; + feat.fPercentDP = hs.fPercentDP; + feat.iScore = hs.iScore; - asFeatsOut.push_back( feat ); + if( pSong->HasBanner() ) + feat.Banner = pSong->GetBannerPath(); + + asFeatsOut.push_back( feat ); + } } // Find Personal Records - vector &vPersonalHighScores = pSteps->m_MemCardDatas[pn].vHighScores; - for( j=0; jGetProfile(pn)->GetStepsHighScoreList(pSteps); + for( j=0; jGetTranslitMainTitle().c_str(), DifficultyToString(pSteps->GetDifficulty()).c_str() ); - feat.pStringToFill = &vPersonalHighScores[j].sName; - feat.grade = vPersonalHighScores[j].grade; - feat.fPercentDP = vMachineHighScores[j].fPercentDP; - feat.iScore = vMachineHighScores[j].iScore; + if( hs.sName != RANKING_TO_FILL_IN_MARKER[pn] ) + continue; - // XXX: temporary hack - if( pSong->HasBackground() ) - feat.Banner = pSong->GetBackgroundPath(); - // if( pSong->HasBanner() ) - // feat.Banner = pSong->GetBannerPath(); + RankingFeats feat; + feat.Type = RankingFeats::SONG; + feat.Feat = ssprintf("PR #%d in %s %s", j+1, pSong->GetTranslitMainTitle().c_str(), DifficultyToString(pSteps->GetDifficulty()).c_str() ); + feat.pStringToFill = &hs.sName; + feat.grade = hs.grade; + feat.fPercentDP = hs.fPercentDP; + feat.iScore = hs.iScore; - asFeatsOut.push_back( feat ); + // XXX: temporary hack + if( pSong->HasBackground() ) + feat.Banner = pSong->GetBackgroundPath(); + // if( pSong->HasBanner() ) + // feat.Banner = pSong->GetBannerPath(); + + asFeatsOut.push_back( feat ); + } } } @@ -1183,42 +1191,46 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector &asFeatsO GetFinalEvalStatsAndSongs( stats, vSongs ); - // Find Machine Records + // Find Machine Category Records for( i=0; i &vHighScores = PROFILEMAN->m_CategoryDatas[PROFILE_SLOT_MACHINE][nt][i].vHighScores; - for( unsigned j=0; jGetMachineProfile()->GetCategoryHighScoreList( nt, rc ); + for( unsigned j=0; j &vHighScores = PROFILEMAN->m_CategoryDatas[pn][nt][i].vHighScores; - for( unsigned j=0; jGetProfile(pn)->GetCategoryHighScoreList( nt, rc ); + for( unsigned j=0; j &asFeatsO // Find Machine Records { - vector &vHighScores = pCourse->m_MemCardDatas[nt][PROFILE_SLOT_MACHINE].vHighScores; - for( unsigned i=0; iGetMachineProfile(); + HighScoreList &hsl = pProfile->GetCourseHighScoreList( pCourse, nt ); + for( unsigned i=0; im_sName.c_str() ); - feat.pStringToFill = &vHighScores[i].sName; + feat.pStringToFill = &hs.sName; feat.grade = GRADE_NO_DATA; - feat.iScore = vHighScores[i].iScore; - feat.fPercentDP = vHighScores[i].fPercentDP; + feat.iScore = hs.iScore; + feat.fPercentDP = hs.fPercentDP; if( pCourse->HasBanner() ) feat.Banner = pCourse->m_sBannerPath; asFeatsOut.push_back( feat ); @@ -1258,20 +1272,23 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector &asFeatsO } // Find Personal Records - vector &vHighScores = pCourse->m_MemCardDatas[nt][pn].vHighScores; + if( PROFILEMAN->IsUsingProfile( pn ) ) { - for( unsigned i=0; iGetProfile( pn ); + HighScoreList &hsl = pProfile->GetCourseHighScoreList( pCourse, nt ); + for( unsigned i=0; im_sName.c_str() ); - feat.pStringToFill = &vHighScores[i].sName; + feat.pStringToFill = &hs.sName; feat.grade = GRADE_NO_DATA; - feat.iScore = vHighScores[i].iScore; - feat.fPercentDP = vHighScores[i].fPercentDP; + feat.iScore = hs.iScore; + feat.fPercentDP = hs.fPercentDP; if( pCourse->HasBanner() ) feat.Banner = pCourse->m_sBannerPath; asFeatsOut.push_back( feat ); diff --git a/stepmania/src/MusicWheelItem.cpp b/stepmania/src/MusicWheelItem.cpp index 8e58ba5f2e..ca942e8e0e 100644 --- a/stepmania/src/MusicWheelItem.cpp +++ b/stepmania/src/MusicWheelItem.cpp @@ -186,7 +186,6 @@ void MusicWheelItem::LoadFromWheelItemData( WheelItemData* pWID ) ASSERT( 0 ); // invalid type } } -Steps::MemCardData::HighScore GetHighScoreForDifficulty( const Song *s, const StyleDef *st, ProfileSlot card, Difficulty dc ); void MusicWheelItem::RefreshGrades() { @@ -207,9 +206,9 @@ void MusicWheelItem::RefreshGrades() dc = GAMESTATE->m_PreferredDifficulty[p]; Grade grade; if( PROFILEMAN->IsUsingProfile((PlayerNumber)p) ) - grade = GetHighScoreForDifficulty( data->m_pSong, GAMESTATE->GetCurrentStyleDef(), (ProfileSlot)p, dc ).grade; + grade = PROFILEMAN->GetHighScoreForDifficulty( data->m_pSong, GAMESTATE->GetCurrentStyleDef(), (ProfileSlot)p, dc ).grade; else - grade = GetHighScoreForDifficulty( data->m_pSong, GAMESTATE->GetCurrentStyleDef(), PROFILE_SLOT_MACHINE, dc ).grade; + grade = PROFILEMAN->GetHighScoreForDifficulty( data->m_pSong, GAMESTATE->GetCurrentStyleDef(), PROFILE_SLOT_MACHINE, dc ).grade; m_GradeDisplay[p].SetGrade( (PlayerNumber)p, grade ); } diff --git a/stepmania/src/PaneDisplay.cpp b/stepmania/src/PaneDisplay.cpp index 6ab9c72fa3..e50e367c0b 100644 --- a/stepmania/src/PaneDisplay.cpp +++ b/stepmania/src/PaneDisplay.cpp @@ -170,6 +170,11 @@ void PaneDisplay::SetContent( PaneContents c ) } } + const Song *pSong = GAMESTATE->m_pCurSong; + const Steps *pSteps = GAMESTATE->m_pCurNotes[m_PlayerNumber]; + StepsType st = GAMESTATE->GetCurrentStyleDef()->m_StepsType; + const Course *pCourse = GAMESTATE->m_pCurCourse; + float val = 0; CString str; switch( c ) @@ -190,21 +195,21 @@ void PaneDisplay::SetContent( PaneContents c ) case SONG_DIFFICULTY_RADAR_FREEZE: val = fRadarValues[RADAR_FREEZE]; break; case SONG_DIFFICULTY_RADAR_CHAOS: val = fRadarValues[RADAR_CHAOS]; break; case SONG_PROFILE_HIGH_SCORE: - val = 100.0f * GAMESTATE->m_pCurNotes[m_PlayerNumber]->GetTopScore( PlayerMemCard(m_PlayerNumber) ).fPercentDP; + val = 100.0f * PROFILEMAN->GetProfile(m_PlayerNumber)->GetStepsHighScoreList(pSteps).GetTopScore().fPercentDP; break; case SONG_PROFILE_NUM_PLAYS: - val = (float) GAMESTATE->m_pCurNotes[m_PlayerNumber]->GetNumTimesPlayed( PlayerMemCard(m_PlayerNumber) ); + val = (float) PROFILEMAN->GetProfile(m_PlayerNumber)->GetStepsNumTimesPlayed(pSteps); break; case SONG_MACHINE_HIGH_NAME: /* set val for color */ case SONG_MACHINE_HIGH_SCORE: - val = 100.0f * GAMESTATE->m_pCurNotes[m_PlayerNumber]->GetTopScore( PROFILE_SLOT_MACHINE ).fPercentDP; + val = 100.0f * PROFILEMAN->GetProfile(m_PlayerNumber)->GetStepsHighScoreList(pSteps).GetTopScore().fPercentDP; break; case SONG_MACHINE_RANK: { const vector best = SONGMAN->GetBestSongs( PROFILE_SLOT_MACHINE ); - val = (float) FindIndex( best.begin(), best.end(), GAMESTATE->m_pCurSong ); + val = (float) FindIndex( best.begin(), best.end(), pSong ); val += 1; break; } @@ -212,38 +217,38 @@ void PaneDisplay::SetContent( PaneContents c ) case SONG_PROFILE_RANK: { const vector best = SONGMAN->GetBestSongs( PlayerMemCard(m_PlayerNumber) ); - val = (float) FindIndex( best.begin(), best.end(), GAMESTATE->m_pCurSong ); + val = (float) FindIndex( best.begin(), best.end(), pSong ); val += 1; break; } case COURSE_MACHINE_HIGH_NAME: /* set val for color */ case COURSE_MACHINE_HIGH_SCORE: - val = 100.0f * GAMESTATE->m_pCurCourse->GetTopScore( GAMESTATE->GetCurrentStyleDef()->m_StepsType, PROFILE_SLOT_MACHINE ).fPercentDP; + val = 100.0f * PROFILEMAN->GetMachineProfile()->GetCourseHighScoreList(pCourse,st).GetTopScore().fPercentDP; break; case COURSE_MACHINE_NUM_PLAYS: - val = (float) GAMESTATE->m_pCurCourse->GetNumTimesPlayed( PROFILE_SLOT_MACHINE ); + val = (float) PROFILEMAN->GetMachineProfile()->GetCourseNumTimesPlayed( pCourse ); break; case COURSE_MACHINE_RANK: { const vector best = SONGMAN->GetBestCourses( PROFILE_SLOT_MACHINE ); - val = (float) FindIndex( best.begin(), best.end(), GAMESTATE->m_pCurCourse ); + val = (float) FindIndex( best.begin(), best.end(), pCourse ); val += 1; } break; case COURSE_PROFILE_HIGH_SCORE: - val = 100.0f * GAMESTATE->m_pCurCourse->GetTopScore( GAMESTATE->GetCurrentStyleDef()->m_StepsType, PlayerMemCard(m_PlayerNumber) ).fPercentDP; + val = 100.0f * PROFILEMAN->GetProfile(m_PlayerNumber)->GetCourseHighScoreList(pCourse,st).GetTopScore().fPercentDP; break; case COURSE_PROFILE_NUM_PLAYS: - val = (float) GAMESTATE->m_pCurCourse->GetNumTimesPlayed( PlayerMemCard(m_PlayerNumber) ); + val = (float) PROFILEMAN->GetProfile(m_PlayerNumber)->GetCourseNumTimesPlayed( pCourse ); break; case COURSE_PROFILE_RANK: const vector best = SONGMAN->GetBestCourses( PlayerMemCard(m_PlayerNumber) ); - val = (float) FindIndex( best.begin(), best.end(), GAMESTATE->m_pCurCourse ); + val = (float) FindIndex( best.begin(), best.end(), pCourse ); val += 1; break; }; @@ -265,10 +270,10 @@ void PaneDisplay::SetContent( PaneContents c ) switch( c ) { case SONG_MACHINE_HIGH_NAME: - str = GAMESTATE->m_pCurNotes[m_PlayerNumber]->GetTopScore( PROFILE_SLOT_MACHINE ).sName; + str = PROFILEMAN->GetMachineProfile()->GetStepsHighScoreList(pSteps).GetTopScore().sName; break; case COURSE_MACHINE_HIGH_NAME: - str = GAMESTATE->m_pCurCourse->GetTopScore( GAMESTATE->GetCurrentStyleDef()->m_StepsType, PROFILE_SLOT_MACHINE ).sName; + str = PROFILEMAN->GetMachineProfile()->GetCourseHighScoreList(pCourse, st).GetTopScore().sName; break; case SONG_MACHINE_HIGH_SCORE: diff --git a/stepmania/src/Profile.cpp b/stepmania/src/Profile.cpp index fec4a0c871..22d2d633d9 100644 --- a/stepmania/src/Profile.cpp +++ b/stepmania/src/Profile.cpp @@ -1,7 +1,7 @@ #include "global.h" /* ----------------------------------------------------------------------------- - Class: ProfileManager + Class: Profile Desc: See header. @@ -10,8 +10,64 @@ ----------------------------------------------------------------------------- */ -#include "ProfileManager.h" +#include "Profile.h" #include "RageUtil.h" +#include "PrefsManager.h" + +bool HighScore::operator>=( const HighScore& other ) const +{ + /* Make sure we treat AAAA as higher than AAA, even though the score + * is the same. + * + * XXX: Isn't it possible to beat the grade but not beat the score, since + * grading and scores are on completely different systems? Should we be + * checking for these completely separately? */ + if( PREFSMAN->m_bPercentageScoring ) + { + if( fPercentDP == other.fPercentDP ) + return grade >= other.grade; + else + return fPercentDP >= other.fPercentDP; + } + else + { + if( iScore == other.iScore ) + return grade >= other.grade; + else + return iScore >= other.iScore; + } +} + +void HighScoreList::AddHighScore( HighScore hs, int &iIndexOut ) +{ + int i; + for( i=0; i<(int)vHighScores.size(); i++ ) + { + if( hs >= vHighScores[i] ) + break; + } + if( i < NUM_RANKING_LINES ) + { + vHighScores.insert( vHighScores.begin()+i, hs ); + iIndexOut = i; + if( vHighScores.size() > unsigned(NUM_RANKING_LINES) ) + vHighScores.erase( vHighScores.begin()+NUM_RANKING_LINES, vHighScores.end() ); + } +} + +const HighScore& HighScoreList::GetTopScore() const +{ + if( vHighScores.empty() ) + { + static HighScore hs; + hs = HighScore(); + return hs; + } + else + { + return vHighScores[0]; + } +} CString Profile::GetDisplayName() { @@ -40,3 +96,113 @@ int Profile::GetTotalNumSongsPlayed() } +// +// Steps high scores +// +void Profile::AddStepsHighScore( const Steps* pSteps, HighScore hs, int &iIndexOut ) +{ + std::map::iterator iter = m_StepsHighScores.find( pSteps ); + if( iter == m_StepsHighScores.end() ) + m_StepsHighScores[pSteps].hs.AddHighScore( hs, iIndexOut ); // operator[] inserts into map + else + iter->second.hs.AddHighScore( hs, iIndexOut ); +} + +HighScoreList& Profile::GetStepsHighScoreList( const Steps* pSteps ) +{ + std::map::iterator iter = m_StepsHighScores.find( pSteps ); + if( iter == m_StepsHighScores.end() ) + return m_StepsHighScores[pSteps].hs; // operator[] inserts into map + else + return iter->second.hs; +} + +int Profile::GetStepsNumTimesPlayed( const Steps* pSteps ) const +{ + std::map::const_iterator iter = m_StepsHighScores.find( pSteps ); + if( iter == m_StepsHighScores.end() ) + { + return 0; + } + else + { + int iTotalNumTimesPlayed = 0; + for( unsigned st = 0; st < NUM_STEPS_TYPES; ++st ) + iTotalNumTimesPlayed += iter->second.hs.iNumTimesPlayed; + return iTotalNumTimesPlayed; + } +} + +void Profile::IncrementStepsPlayCount( const Steps* pSteps ) +{ + GetStepsHighScoreList(pSteps).iNumTimesPlayed++; +} + + +// +// Course high scores +// +void Profile::AddCourseHighScore( const Course* pCourse, StepsType st, HighScore hs, int &iIndexOut ) +{ + std::map::iterator iter = m_CourseHighScores.find( pCourse ); + if( iter == m_CourseHighScores.end() ) + m_CourseHighScores[pCourse].hs[st].AddHighScore( hs, iIndexOut ); // operator[] inserts into map + else + iter->second.hs[st].AddHighScore( hs, iIndexOut ); +} + +HighScoreList& Profile::GetCourseHighScoreList( const Course* pCourse, StepsType st ) +{ + std::map::iterator iter = m_CourseHighScores.find( pCourse ); + if( iter == m_CourseHighScores.end() ) + return m_CourseHighScores[pCourse].hs[st]; // operator[] inserts into map + else + return iter->second.hs[st]; +} + +int Profile::GetCourseNumTimesPlayed( const Course* pCourse ) const +{ + std::map::const_iterator iter = m_CourseHighScores.find( pCourse ); + if( iter == m_CourseHighScores.end() ) + { + return 0; + } + else + { + int iTotalNumTimesPlayed = 0; + for( unsigned st = 0; st < NUM_STEPS_TYPES; ++st ) + iTotalNumTimesPlayed += iter->second.hs[st].iNumTimesPlayed; + return iTotalNumTimesPlayed; + } +} + +void Profile::IncrementCoursePlayCount( const Course* pCourse, StepsType st ) +{ + GetCourseHighScoreList(pCourse,st).iNumTimesPlayed++; +} + +// +// Category high scores +// +void Profile::AddCategoryHighScore( StepsType st, RankingCategory rc, HighScore hs, int &iIndexOut ) +{ + m_CategoryHighScores[st][rc].AddHighScore( hs, iIndexOut ); +} + +HighScoreList& Profile::GetCategoryHighScoreList( StepsType st, RankingCategory rc ) +{ + return m_CategoryHighScores[st][rc]; +} + +int Profile::GetCategoryNumTimesPlayed( RankingCategory rc ) const +{ + int iNumTimesPlayed = 0; + for( int st=0; st + +class Steps; +class Course; + +struct HighScore +{ + CString sName; + Grade grade; + int iScore; + float fPercentDP; + float fSurviveTime; + + HighScore() + { + grade = GRADE_NO_DATA; + iScore = 0; + fPercentDP = 0; + fSurviveTime = 0; + } + + bool operator>=( const HighScore& other ) const; +}; + +struct HighScoreList +{ + int iNumTimesPlayed; + vector vHighScores; + + + HighScoreList() + { + iNumTimesPlayed = 0; + } + + void AddHighScore( HighScore hs, int &iIndexOut ); + + const HighScore& GetTopScore() const; +}; + struct Profile { @@ -62,6 +103,49 @@ struct Profile int m_iNumSongsPlayedByStyle[NUM_STYLES]; int m_iNumSongsPlayedByDifficulty[NUM_DIFFICULTIES]; int m_iNumSongsPlayedByMeter[MAX_METER+1]; + + + // + // Steps high scores + // + struct HighScoresForASteps + { + HighScoreList hs; + }; + std::map m_StepsHighScores; + + void AddStepsHighScore( const Steps* pSteps, HighScore hs, int &iIndexOut ); + HighScoreList& GetStepsHighScoreList( const Steps* pSteps ); + int GetStepsNumTimesPlayed( const Steps* pSteps ) const; + void IncrementStepsPlayCount( const Steps* pSteps ); + + + // + // Course high scores + // + // struct was a typedef'd array of HighScores, but VC6 freaks out + // in processing the templates for map::operator[]. + struct HighScoresForACourse + { + HighScoreList hs[NUM_STEPS_TYPES]; + }; + std::map m_CourseHighScores; + + void AddCourseHighScore( const Course* pCourse, StepsType st, HighScore hs, int &iIndexOut ); + HighScoreList& GetCourseHighScoreList( const Course* pCourse, StepsType st ); + int GetCourseNumTimesPlayed( const Course* pCourse ) const; + void IncrementCoursePlayCount( const Course* pCourse, StepsType st ); + + + // + // Category high scores + // + HighScoreList m_CategoryHighScores[NUM_STEPS_TYPES][NUM_RANKING_CATEGORIES]; + + void AddCategoryHighScore( StepsType st, RankingCategory rc, HighScore hs, int &iIndexOut ); + HighScoreList& GetCategoryHighScoreList( StepsType st, RankingCategory rc ); + int GetCategoryNumTimesPlayed( RankingCategory rc ) const; + void IncrementCategoryPlayCount( StepsType st, RankingCategory rc ); }; diff --git a/stepmania/src/ProfileManager.cpp b/stepmania/src/ProfileManager.cpp index 3aea0bb72a..612d8e6eb6 100644 --- a/stepmania/src/ProfileManager.cpp +++ b/stepmania/src/ProfileManager.cpp @@ -59,7 +59,7 @@ const int COURSE_SCORES_VERSION = 8; static const char *MEM_CARD_DIR[NUM_PLAYERS] = { - /* @ is important; see RageFileManager LoadedDriver::GetPath */ + /* @ is importast; see RageFileManager LoadedDriver::GetPath */ "@mc1/", "@mc2/", }; @@ -160,14 +160,14 @@ bool ProfileManager::LoadProfileFromMemoryCard( PlayerNumber pn ) { UnloadProfile( pn ); #ifndef _XBOX - // mount card + // moust card if( MEMCARDMAN->GetCardState(pn) == MEMORY_CARD_STATE_READY ) { FILEMAN->Mount( "dir", MEMCARDMAN->GetOsMountDir(pn), MEM_CARD_DIR[pn] ); CString sDir = MEM_CARD_DIR[pn]; - DEBUG_ASSERT( FILEMAN->IsMounted(sDir) ); // should be called only if we've already mounted + DEBUG_ASSERT( FILEMAN->IsMounted(sDir) ); // should be called only if we've already mousted // tack on a subdirectory so that we don't write everything to the root sDir += PREFSMAN->m_sMemoryCardProfileSubdir; @@ -191,7 +191,7 @@ bool ProfileManager::CreateMemoryCardProfile( PlayerNumber pn ) { CString sDir = MEM_CARD_DIR[pn]; - DEBUG_ASSERT( FILEMAN->IsMounted(sDir) ); // should be called only if we've already mounted + DEBUG_ASSERT( FILEMAN->IsMounted(sDir) ); // should be called only if we've already mousted // tack on a subdirectory so that we don't write everything to the root sDir += PREFSMAN->m_sMemoryCardProfileSubdir; @@ -393,28 +393,14 @@ void ProfileManager::SaveMachineScoresToDisk() SaveStatsWebPageToDir( MACHINE_PROFILE_DIR, PROFILE_SLOT_MACHINE ); } -void ProfileManager::CategoryData::AddHighScore( HighScore hs, int &iIndexOut ) -{ - int i; - for( i=0; i<(int)vHighScores.size(); i++ ) - { - if( hs >= vHighScores[i] ) - break; - } - if( i < NUM_RANKING_LINES ) - { - vHighScores.insert( vHighScores.begin()+i, hs ); - iIndexOut = i; - if( int(vHighScores.size()) > NUM_RANKING_LINES ) - vHighScores.erase( vHighScores.begin()+NUM_RANKING_LINES, vHighScores.end() ); - } -} - #define WARN_AND_RETURN { LOG->Warn("Error parsing file '%s' at %s:%d",fn.c_str(),__FILE__,__LINE__); return; } void ProfileManager::ReadSongScoresFromDir( CString sDir, ProfileSlot slot ) { + Profile* pProfile = GetProfile( slot ); + ASSERT( pProfile ); + CString fn = sDir + SONG_SCORES_FILE; RageFile f; @@ -448,8 +434,8 @@ void ProfileManager::ReadSongScoresFromDir( CString sDir, ProfileSlot slot ) for( int n=0; nGetStepsByDescription( nt, sDescription ); + pNotes = pSong->GetStepsByDescription( st, sDescription ); else - pNotes = pSong->GetStepsByDifficulty( nt, dc ); + pNotes = pSong->GetStepsByDifficulty( st, dc ); } int iNumTimesPlayed; if( !FileRead(f, iNumTimesPlayed) ) WARN_AND_RETURN; + HighScoreList &hsl = pProfile->GetStepsHighScoreList(pNotes); + if( pNotes ) - pNotes->m_MemCardDatas[slot].iNumTimesPlayed = iNumTimesPlayed; + hsl.iNumTimesPlayed = iNumTimesPlayed; int iNumHighScores; if( !FileRead(f, iNumHighScores) ) WARN_AND_RETURN; if( pNotes ) - pNotes->m_MemCardDatas[slot].vHighScores.resize( iNumHighScores ); + hsl.vHighScores.resize( iNumHighScores ); int l; for( l=0; lm_MemCardDatas[slot].vHighScores[l].sName = sName; - pNotes->m_MemCardDatas[slot].vHighScores[l].grade = grade; - pNotes->m_MemCardDatas[slot].vHighScores[l].iScore = iScore; - pNotes->m_MemCardDatas[slot].vHighScores[l].fPercentDP = fPercentDP; + 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; lm_MemCardDatas[slot].vHighScores[l].iScore <= 0 ) + if( pNotes && hsl.vHighScores[l].iScore <= 0 ) { - pNotes->m_MemCardDatas[slot].vHighScores.resize(l); + hsl.vHighScores.resize(l); break; } } @@ -530,6 +518,9 @@ void ProfileManager::ReadSongScoresFromDir( CString sDir, ProfileSlot slot ) void ProfileManager::ReadCategoryScoresFromDir( CString sDir, ProfileSlot slot ) { + Profile* pProfile = GetProfile( slot ); + ASSERT( pProfile ); + CString fn = sDir + CATEGORY_SCORES_FILE; RageFile f; @@ -553,7 +544,8 @@ void ProfileManager::ReadCategoryScoresFromDir( CString sDir, ProfileSlot slot ) if( !FileRead(f, iNumHighScores) ) WARN_AND_RETURN; - m_CategoryDatas[slot][st][rc].vHighScores.resize( iNumHighScores ); + HighScoreList &hsl = pProfile->GetCategoryHighScoreList( (StepsType)st, (RankingCategory)rc ); + hsl.vHighScores.resize( iNumHighScores ); for( int l=0; lGetCourseHighScoreList( pCourse, (StepsType)st ); + if( pCourse ) - pCourse->m_MemCardDatas[st][slot].iNumTimesPlayed = iNumTimesPlayed; + hsl.iNumTimesPlayed = iNumTimesPlayed; int iNumHighScores; if( !FileRead(f, iNumHighScores) ) WARN_AND_RETURN; if( pCourse ) - pCourse->m_MemCardDatas[st][slot].vHighScores.resize(iNumHighScores); + hsl.vHighScores.resize(iNumHighScores); for( int l=0; lm_MemCardDatas[st][slot].vHighScores[l].sName = sName; - pCourse->m_MemCardDatas[st][slot].vHighScores[l].iScore = iScore; - pCourse->m_MemCardDatas[st][slot].vHighScores[l].fPercentDP = fPercentDP; - pCourse->m_MemCardDatas[st][slot].vHighScores[l].fSurviveTime = fSurviveTime; + hsl.vHighScores[l].sName = sName; + hsl.vHighScores[l].iScore = iScore; + hsl.vHighScores[l].fPercentDP = fPercentDP; + hsl.vHighScores[l].fSurviveTime = fSurviveTime; } } } @@ -667,7 +664,7 @@ void ProfileManager::ReadCourseScoresFromDir( CString sDir, ProfileSlot slot ) void ProfileManager::InitMachineScoresFromDisk() { // read old style notes scores - ReadSM300NoteScores(); +// ReadSM300NoteScores(); // category ranking ReadCategoryScoresFromDir( MACHINE_PROFILE_DIR, PROFILE_SLOT_MACHINE ); @@ -681,6 +678,7 @@ void ProfileManager::InitMachineScoresFromDisk() } } +/* void ProfileManager::ReadSM300NoteScores() { if( !DoesFileExist(SM_300_STATISTICS_FILE) ) @@ -713,18 +711,18 @@ void ProfileManager::ReadSM300NoteScores() CString sSongDir = FixSlashes( szSongDir ); - // Search for the corresponding Song pointer. + // Search for the corresponding Song poister. Song* pSong = SONGMAN->GetSongFromDir( sSongDir ); if( pSong == NULL ) // didn't find a match - continue; // skip this entry + continue; // skip this estry StepsType st = GAMEMAN->StringToNotesType( szStepsType ); Difficulty dc = StringToDifficulty( szStepsDescription ); - // Search for the corresponding Notes pointer. + // Search for the corresponding Notes poister. Steps* pNotes = pSong->GetStepsByDifficulty( st, dc ); if( pNotes == NULL ) // didn't find a match - continue; // skip this entry + continue; // skip this estry // Parse the Notes statistics. @@ -748,10 +746,13 @@ void ProfileManager::ReadSM300NoteScores() } } } - +*/ void ProfileManager::SaveCategoryScoresToDir( CString sDir, ProfileSlot slot ) { + Profile* pProfile = GetProfile( slot ); + ASSERT( pProfile ); + CString fn = sDir + CATEGORY_SCORES_FILE; LOG->Trace("SongManager::SaveCategoryRankingsToFile"); @@ -769,17 +770,19 @@ void ProfileManager::SaveCategoryScoresToDir( CString sDir, ProfileSlot slot ) { for( int rc=0; rcGetCategoryHighScoreList( (StepsType)st, (RankingCategory)rc ); - for( unsigned l=0; lTrace("SongManager::SaveCourseScoresToFile"); @@ -815,40 +821,47 @@ void ProfileManager::SaveCourseScoresToDir( CString sDir, ProfileSlot slot ) else FileWrite( f, pCourse->m_sPath ); - int NumStepsPlayed = 0; + int NumStepsTypesPlayed = 0; int st; for( st=0; stm_MemCardDatas[st][slot].iNumTimesPlayed ) - ++NumStepsPlayed; - FileWrite( f, NumStepsPlayed ); + { + HighScoreList &hsl = pProfile->GetCourseHighScoreList( pCourse, (StepsType)st ); + if( hsl.iNumTimesPlayed ) + ++NumStepsTypesPlayed; + } + FileWrite( f, NumStepsTypesPlayed ); for( st=0; stm_MemCardDatas[st][slot].iNumTimesPlayed ) + HighScoreList &hsl = pProfile->GetCourseHighScoreList( pCourse, (StepsType)st ); + if( hsl.iNumTimesPlayed == 0 ) continue; - --NumStepsPlayed; + --NumStepsTypesPlayed; FileWrite( f, st ); - FileWrite( f, pCourse->m_MemCardDatas[st][slot].iNumTimesPlayed ); - FileWrite( f, pCourse->m_MemCardDatas[st][slot].vHighScores.size() ); - for( unsigned l=0; lm_MemCardDatas[st][slot].vHighScores.size(); l++ ) + FileWrite( f, hsl.iNumTimesPlayed ); + FileWrite( f, hsl.vHighScores.size() ); + for( unsigned l=0; lm_MemCardDatas[st][slot].vHighScores[l].sName) ) - pCourse->m_MemCardDatas[st][slot].vHighScores[l].sName = ""; + if( IsRankingToFillIn(hsl.vHighScores[l].sName) ) + hsl.vHighScores[l].sName = ""; - FileWrite( f, pCourse->m_MemCardDatas[st][slot].vHighScores[l].sName ); - FileWrite( f, pCourse->m_MemCardDatas[st][slot].vHighScores[l].iScore ); - FileWrite( f, pCourse->m_MemCardDatas[st][slot].vHighScores[l].fPercentDP ); - FileWrite( f, pCourse->m_MemCardDatas[st][slot].vHighScores[l].fSurviveTime ); + FileWrite( f, hsl.vHighScores[l].sName ); + FileWrite( f, hsl.vHighScores[l].iScore ); + FileWrite( f, hsl.vHighScores[l].fPercentDP ); + FileWrite( f, hsl.vHighScores[l].fSurviveTime ); } } - ASSERT( !NumStepsPlayed ); + ASSERT( !NumStepsTypesPlayed ); } } void ProfileManager::SaveSongScoresToDir( CString sDir, ProfileSlot slot ) { + Profile* pProfile = GetProfile( slot ); + ASSERT( pProfile ); + CString fn = sDir + SONG_SCORES_FILE; LOG->Trace("SongManager::SaveSongScoresToFile %s", fn.c_str()); @@ -874,43 +887,43 @@ void ProfileManager::SaveSongScoresToDir( CString sDir, ProfileSlot slot ) /* If the song has never been played, don't write anything. This keeps * us from saving a dozen copies of each song for all autogen difficulties, * since most people only use a couple game modes. */ - vector vNotes; + vector vNotesToWrite; for( unsigned i=0; im_apNotes.size(); ++i ) { Steps* pNotes = pSong->m_apNotes[i]; - if( pNotes->m_MemCardDatas[slot].iNumTimesPlayed == 0 && pNotes->m_MemCardDatas[slot].vHighScores.empty() ) + HighScoreList &hsl = pProfile->GetStepsHighScoreList( pNotes ); + if( hsl.iNumTimesPlayed == 0 && hsl.vHighScores.empty() ) continue; - vNotes.push_back( pNotes ); + vNotesToWrite.push_back( pNotes ); } FileWrite( f, pSong->GetSongDir() ); - FileWrite( f, vNotes.size() ); + FileWrite( f, vNotesToWrite.size() ); - if( vNotes.size() == 0 ) - continue; // skip - - for( unsigned n=0; nGetStepsHighScoreList( pNotes ); FileWrite( f, pNotes->m_StepsType ); FileWrite( f, pNotes->GetDifficulty() ); FileWrite( f, pNotes->GetDescription() ); - FileWrite( f, pNotes->m_MemCardDatas[slot].iNumTimesPlayed ); + FileWrite( f, hsl.iNumTimesPlayed ); - FileWrite( f, pNotes->m_MemCardDatas[slot].vHighScores.size() ); + FileWrite( f, hsl.vHighScores.size() ); - for( int l=0; l<(int)pNotes->m_MemCardDatas[slot].vHighScores.size(); l++ ) + for( int l=0; l<(int)hsl.vHighScores.size(); l++ ) { // tricky: wipe out "name to fill in" markers - if( IsRankingToFillIn(pNotes->m_MemCardDatas[slot].vHighScores[l].sName) ) - pNotes->m_MemCardDatas[slot].vHighScores[l].sName = ""; + if( IsRankingToFillIn(hsl.vHighScores[l].sName) ) + hsl.vHighScores[l].sName = ""; - FileWrite( f, pNotes->m_MemCardDatas[slot].vHighScores[l].sName ); - FileWrite( f, pNotes->m_MemCardDatas[slot].vHighScores[l].grade ); - FileWrite( f, pNotes->m_MemCardDatas[slot].vHighScores[l].iScore ); - FileWrite( f, pNotes->m_MemCardDatas[slot].vHighScores[l].fPercentDP ); + FileWrite( f, hsl.vHighScores[l].sName ); + FileWrite( f, hsl.vHighScores[l].grade ); + FileWrite( f, hsl.vHighScores[l].iScore ); + FileWrite( f, hsl.vHighScores[l].fPercentDP ); } } } @@ -998,35 +1011,35 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, ProfileSlot slot ) } // - // print HTML headers + // prist HTML headers // { f.PutLine( "" ); f.PutLine( "" ); - f.PutLine( "" ); + f.PutLine( "" ); f.PutLine( ssprintf("%s", STATS_TITLE.c_str() ) ); f.PutLine( ssprintf("",STYLE_CSS_FILE) ); f.PutLine( "" ); f.PutLine( "" ); } -#define PRINT_SECTION_START(szName) f.Write( ssprintf("

"szName" (top)

\n", szName) ) -#define PRINT_SECTION_END f.Write( "\n" ) -#define PRINT_DIV_START(szName) f.Write( ssprintf("
\n" "

%s

\n", szName) ) -#define PRINT_DIV_START_ANCHOR(uAnchor,szName) f.Write( ssprintf("
\n" "

%s

\n", (unsigned)uAnchor, szName) ) -#define PRINT_DIV_END f.Write( "
\n" ) -#define PRINT_DIV2_START(szName) f.Write( ssprintf("
\n" "

%s

\n", szName) ) -#define PRINT_DIV2_START_ANCHOR(uAnchor,szName) f.Write( ssprintf("
\n" "

%s

\n", (unsigned)uAnchor, szName) ) -#define PRINT_DIV2_END f.Write( "
\n" ) -#define PRINT_LINK(szName,szLink) f.Write( ssprintf("

%s

\n",szLink,szName) ) -#define PRINT_LINE_S(szName,sVal) f.Write( ssprintf("

%s = %s

\n",szName,sVal.c_str()) ) -#define PRINT_LINE_B(szName,bVal) f.Write( ssprintf("

%s = %s

\n",szName,(bVal)?"yes":"no") ) -#define PRINT_LINE_I(szName,iVal) f.Write( ssprintf("

%s = %d

\n",szName,iVal) ) -#define PRINT_LINE_RANK(iRank,sName,iVal) f.Write( ssprintf("

%d - %s (%d)

\n",iRank,sName.c_str(),iVal) ) -#define PRINT_LINE_RANK_LINK(iRank,sName,szLink,iVal) f.Write( ssprintf("

%d - %s (%d)

\n",iRank,szLink,sName.c_str(),iVal) ) +#define PRIst_SECTION_START(szName) f.Write( ssprintf("

"szName" (top)

\n", szName) ) +#define PRIst_SECTION_END f.Write( "\n" ) +#define PRIst_DIV_START(szName) f.Write( ssprintf("
\n" "

%s

\n", szName) ) +#define PRIst_DIV_START_ANCHOR(uAnchor,szName) f.Write( ssprintf("
\n" "

%s

\n", (unsigned)uAnchor, szName) ) +#define PRIst_DIV_END f.Write( "
\n" ) +#define PRIst_DIV2_START(szName) f.Write( ssprintf("
\n" "

%s

\n", szName) ) +#define PRIst_DIV2_START_ANCHOR(uAnchor,szName) f.Write( ssprintf("
\n" "

%s

\n", (unsigned)uAnchor, szName) ) +#define PRIst_DIV2_END f.Write( "
\n" ) +#define PRIst_LINK(szName,szLink) f.Write( ssprintf("

%s

\n",szLink,szName) ) +#define PRIst_LINE_S(szName,sVal) f.Write( ssprintf("

%s = %s

\n",szName,sVal.c_str()) ) +#define PRIst_LINE_B(szName,bVal) f.Write( ssprintf("

%s = %s

\n",szName,(bVal)?"yes":"no") ) +#define PRIst_LINE_I(szName,iVal) f.Write( ssprintf("

%s = %d

\n",szName,iVal) ) +#define PRIst_LINE_RANK(iRank,sName,iVal) f.Write( ssprintf("

%d - %s (%d)

\n",iRank,sName.c_str(),iVal) ) +#define PRIst_LINE_RANK_LINK(iRank,sName,szLink,iVal) f.Write( ssprintf("

%d - %s (%d)

\n",iRank,szLink,sName.c_str(),iVal) ) // - // Print table of contents + // Prist table of costests // { CString sName = @@ -1037,48 +1050,48 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, ProfileSlot slot ) CString sTime = ctime( <ime ); f.Write( ssprintf("

%s for %s - %s

\n",STATS_TITLE.c_str(), sName.c_str(), sTime.c_str()) ); - PRINT_DIV_START("Table of Contents"); - PRINT_LINK( "Statistics", "#Statistics" ); - PRINT_LINK( "Popularity Lists", "#Popularity Lists" ); - PRINT_LINK( "Difficulty Table", "#Difficulty Table" ); - PRINT_LINK( "High Scores Table", "#High Scores Table" ); - PRINT_LINK( "Song/Steps List", "#Song/Steps List" ); - PRINT_LINK( "Bookkeeping", "#Bookkeeping" ); - PRINT_DIV_END; + PRIst_DIV_START("Table of Costests"); + PRIst_LINK( "Statistics", "#Statistics" ); + PRIst_LINK( "Popularity Lists", "#Popularity Lists" ); + PRIst_LINK( "Difficulty Table", "#Difficulty Table" ); + PRIst_LINK( "High Scores Table", "#High Scores Table" ); + PRIst_LINK( "Song/Steps List", "#Song/Steps List" ); + PRIst_LINK( "Bookkeeping", "#Bookkeeping" ); + PRIst_DIV_END; } // - // Print Statistics + // Prist Statistics // LOG->Trace( "Writing stats ..." ); { - PRINT_SECTION_START( "Statistics" ); + PRIst_SECTION_START( "Statistics" ); // Memory card stats { - PRINT_DIV_START( "This Profile" ); - PRINT_LINE_S( "Name", pProfile->m_sName ); - PRINT_LINE_S( "LastUsedHighScoreName", pProfile->m_sLastUsedHighScoreName ); - PRINT_LINE_B( "UsingProfileDefaultModifiers", pProfile->m_bUsingProfileDefaultModifiers ); - PRINT_LINE_S( "DefaultModifiers", pProfile->m_sDefaultModifiers ); - PRINT_LINE_I( "TotalPlays", pProfile->m_iTotalPlays ); - PRINT_LINE_I( "TotalPlaySeconds", pProfile->m_iTotalPlaySeconds ); - PRINT_LINE_I( "TotalGameplaySeconds", pProfile->m_iTotalGameplaySeconds ); - PRINT_LINE_I( "CurrentCombo", pProfile->m_iCurrentCombo ); - PRINT_DIV_END; + PRIst_DIV_START( "This Profile" ); + PRIst_LINE_S( "Name", pProfile->m_sName ); + PRIst_LINE_S( "LastUsedHighScoreName", pProfile->m_sLastUsedHighScoreName ); + PRIst_LINE_B( "UsingProfileDefaultModifiers", pProfile->m_bUsingProfileDefaultModifiers ); + PRIst_LINE_S( "DefaultModifiers", pProfile->m_sDefaultModifiers ); + PRIst_LINE_I( "TotalPlays", pProfile->m_iTotalPlays ); + PRIst_LINE_I( "TotalPlaySeconds", pProfile->m_iTotalPlaySeconds ); + PRIst_LINE_I( "TotalGameplaySeconds", pProfile->m_iTotalGameplaySeconds ); + PRIst_LINE_I( "CurrentCombo", pProfile->m_iCurrentCombo ); + PRIst_DIV_END; } // Num Songs Played by PlayMode { - PRINT_DIV_START( "Num Songs Played by PlayMode" ); + PRIst_DIV_START( "Num Songs Played by PlayMode" ); for( int i=0; im_iNumSongsPlayedByPlayMode[i] ); - PRINT_DIV_END; + PRIst_LINE_I( PlayModeToString((PlayMode)i).c_str(), pProfile->m_iNumSongsPlayedByPlayMode[i] ); + PRIst_DIV_END; } // Num Songs Played by Style { - PRINT_DIV_START( "Num Songs Played by Style" ); + PRIst_DIV_START( "Num Songs Played by Style" ); for( int i=0; im_szName, pProfile->m_iNumSongsPlayedByStyle[i] ); + PRIst_LINE_I( pStyleDef->m_szName, pProfile->m_iNumSongsPlayedByStyle[i] ); } - PRINT_DIV_END; + PRIst_DIV_END; } // Num Songs Played by Difficulty { - PRINT_DIV_START( "Num Songs Played by Difficulty" ); + PRIst_DIV_START( "Num Songs Played by Difficulty" ); for( int i=0; im_iNumSongsPlayedByDifficulty[i] ); - PRINT_DIV_END; + PRIst_LINE_I( DifficultyToString((Difficulty)i).c_str(), pProfile->m_iNumSongsPlayedByDifficulty[i] ); + PRIst_DIV_END; } // Num Songs Played by Meter { - PRINT_DIV_START( "Num Songs Played by Meter" ); + PRIst_DIV_START( "Num Songs Played by Meter" ); for( int i=MAX_METER; i>=MIN_METER; i-- ) - PRINT_LINE_I( ssprintf("%d",i).c_str(), pProfile->m_iNumSongsPlayedByMeter[i] ); - PRINT_DIV_END; + PRIst_LINE_I( ssprintf("%d",i).c_str(), pProfile->m_iNumSongsPlayedByMeter[i] ); + PRIst_DIV_END; } - PRINT_SECTION_END; + PRIst_SECTION_END; } // - // Print Popularity Lists + // Prist Popularity Lists // { - PRINT_SECTION_START( "Popularity Lists" ); + PRIst_SECTION_START( "Popularity Lists" ); // Songs by popularity { unsigned uNumToShow = min( vpSongs.size(), (unsigned)100 ); SortSongPointerArrayByMostPlayed( vpSongs, slot ); - PRINT_DIV_START( "Songs by Popularity" ); + PRIst_DIV_START( "Songs by Popularity" ); for( unsigned i=0; iGetFullDisplayTitle(), ssprintf("#%u",(unsigned)pSong).c_str(), pSong->GetNumTimesPlayed(slot) ); + PRIst_LINE_RANK_LINK( i+1, pSong->GetFullDisplayTitle(), ssprintf("#%u",(unsigned)pSong).c_str(), PROFILEMAN->GetSongNumTimesPlayed(pSong,slot) ); } - PRINT_DIV_END; + PRIst_DIV_END; } // Steps by popularity @@ -1138,7 +1151,7 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, ProfileSlot slot ) unsigned uNumToShow = min( vpAllSteps.size(), (unsigned)100 ); SortStepsPointerArrayByMostPlayed( vpAllSteps, slot ); - PRINT_DIV_START( "Steps by Popularity" ); + PRIst_DIV_START( "Steps by Popularity" ); for( unsigned i=0; iNotesTypeToString(pSteps->m_StepsType); s += " "; s += DifficultyToString(pSteps->GetDifficulty()); - PRINT_LINE_RANK_LINK( i+1, s, ssprintf("#%u",(unsigned)pSteps).c_str(), pSteps->GetNumTimesPlayed(slot) ); + PRIst_LINE_RANK_LINK( i+1, s, ssprintf("#%u",(unsigned)pSteps).c_str(), pProfile->GetStepsNumTimesPlayed(pSteps) ); } - PRINT_DIV_END; + PRIst_DIV_END; } // Course by popularity @@ -1159,32 +1172,32 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, ProfileSlot slot ) unsigned uNumToShow = min( vpCourses.size(), (unsigned)100 ); SortCoursePointerArrayByMostPlayed( vpCourses, slot ); - PRINT_DIV_START( "Courses by Popularity" ); + PRIst_DIV_START( "Courses by Popularity" ); for( unsigned i=0; im_sName, ssprintf("#%u",(unsigned)pCourse).c_str(), pCourse->GetNumTimesPlayed(slot) ); + PRIst_LINE_RANK_LINK( i+1, pCourse->m_sName, ssprintf("#%u",(unsigned)pCourse).c_str(), pProfile->GetCourseNumTimesPlayed(pCourse) ); } - PRINT_DIV_END; + PRIst_DIV_END; } - PRINT_SECTION_END; + PRIst_SECTION_END; } // - // Print High score tables + // Prist High score tables // { SortSongPointerArrayByGroupAndTitle( vpSongs ); - PRINT_SECTION_START( "High Scores Table" ); + PRIst_SECTION_START( "High Scores Table" ); for( unsigned s=0; sNotesTypeToString(st).c_str() ); + PRIst_DIV_START( GAMEMAN->NotesTypeToString(st).c_str() ); f.PutLine( "\n" ); // table header row @@ -1204,7 +1217,7 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, ProfileSlot slot ) f.PutLine( "" ); f.Write( ssprintf("", - (unsigned)pSong, // use pointer value as the hash + (unsigned)pSong, // use poister value as the hash pSong->GetFullDisplayTitle().c_str()) ); for( Difficulty dc=(Difficulty)0; dcGetStepsByDifficulty( st, dc, false ); if( pSteps ) { + HighScoreList &hsl = pProfile->GetStepsHighScoreList( pSteps ); CString sHighScore; - if( !pSteps->m_MemCardDatas[slot].vHighScores.empty() ) + if( !hsl.vHighScores.empty() ) { - sHighScore += pSteps->m_MemCardDatas[slot].vHighScores[0].sName; + sHighScore += hsl.vHighScores[0].sName; sHighScore += "
"; - sHighScore += GradeToString( pSteps->m_MemCardDatas[slot].vHighScores[0].grade ); + sHighScore += GradeToString( hsl.vHighScores[0].grade ); sHighScore += "
"; - sHighScore += ssprintf("%d",pSteps->m_MemCardDatas[slot].vHighScores[0].iScore); + sHighScore += ssprintf("%d",hsl.vHighScores[0].iScore); } f.PutLine( ssprintf("
", - (unsigned)pSteps, // use pointer value as the hash + (unsigned)pSteps, // use poister value as the hash sHighScore.c_str()) ); } else @@ -1235,25 +1249,25 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, ProfileSlot slot ) } f.PutLine( "
%s

%s

\n" ); - PRINT_DIV_END; + PRIst_DIV_END; } - PRINT_SECTION_END; + PRIst_SECTION_END; } // - // Print Difficulty tables + // Prist Difficulty tables // { SortSongPointerArrayByGroupAndTitle( vpSongs ); - PRINT_SECTION_START( "Difficulty Table" ); + PRIst_SECTION_START( "Difficulty Table" ); for( unsigned s=0; sNotesTypeToString(st).c_str() ); + PRIst_DIV_START( GAMEMAN->NotesTypeToString(st).c_str() ); f.PutLine( "\n" ); // table header row @@ -1273,7 +1287,7 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, ProfileSlot slot ) f.PutLine( "" ); f.Write( ssprintf("", - (unsigned)pSong, // use pointer value as the hash + (unsigned)pSong, // use poister value as the hash pSong->GetFullDisplayTitle().c_str()) ); for( Difficulty dc=(Difficulty)0; dc

%d

", - (unsigned)pSteps, // use pointer value as the hash + (unsigned)pSteps, // use poister value as the hash pSteps->GetMeter()) ); } else @@ -1295,137 +1309,137 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, ProfileSlot slot ) } f.PutLine( "
%s
\n" ); - PRINT_DIV_END; + PRIst_DIV_END; } - PRINT_SECTION_END; + PRIst_SECTION_END; } // - // Print song list + // Prist song list // LOG->Trace( "Writing song list ..." ); { - PRINT_SECTION_START( "Song/Steps List" ); + PRIst_SECTION_START( "Song/Steps List" ); for( unsigned i=0; i vpSteps = pSong->GetAllSteps(); - /* XXX: We can't call pSong->HasBanner on every song; it'll effectively re-traverse the entire + /* XXX: We can't call pSong->HasBanner on every song; it'll effectively re-traverse the estire * song directory tree checking if each banner file really exists. * * (Note for testing this: remember that we'll cache directories for a time; this is only slow if * the directory cache expires before we get here.) */ - /* Don't print the song banner anyway since this is going on the memory card. -Chris */ + /* Don't prist the song banner anyway since this is going on the memory card. -Chris */ //CString sImagePath = pSong->HasBanner() ? pSong->GetBannerPath() : (pSong->HasBackground() ? pSong->GetBackgroundPath() : "" ); - PRINT_DIV_START_ANCHOR( /*Song primary key*/pSong, pSong->GetFullDisplayTitle().c_str() ); - PRINT_LINE_S( "Artist", pSong->GetDisplayArtist() ); - PRINT_LINE_S( "GroupName", pSong->m_sGroupName ); + PRIst_DIV_START_ANCHOR( /*Song primary key*/pSong, pSong->GetFullDisplayTitle().c_str() ); + PRIst_LINE_S( "Artist", pSong->GetDisplayArtist() ); + PRIst_LINE_S( "GroupName", pSong->m_sGroupName ); float fMinBPM, fMaxBPM; pSong->GetDisplayBPM( fMinBPM, fMaxBPM ); CString sBPM = (fMinBPM==fMaxBPM) ? ssprintf("%.1f",fMinBPM) : ssprintf("%.1f - %.1f",fMinBPM,fMaxBPM); - PRINT_LINE_S( "BPM", sBPM ); - PRINT_LINE_I( "NumTimesPlayed", pSong->GetNumTimesPlayed(slot) ); - PRINT_LINE_S( "Credit", pSong->m_sCredit ); - PRINT_LINE_S( "MusicLength", SecondsToTime(pSong->m_fMusicLengthSeconds) ); - PRINT_LINE_B( "Lyrics", !pSong->m_sLyricsFile.empty() ); - PRINT_DIV_END; + PRIst_LINE_S( "BPM", sBPM ); + PRIst_LINE_I( "NumTimesPlayed", PROFILEMAN->GetSongNumTimesPlayed(pSong,slot) ); + PRIst_LINE_S( "Credit", pSong->m_sCredit ); + PRIst_LINE_S( "MusicLength", SecondsToTime(pSong->m_fMusicLengthSeconds) ); + PRIst_LINE_B( "Lyrics", !pSong->m_sLyricsFile.empty() ); + PRIst_DIV_END; // - // Print Steps list + // Prist Steps list // for( unsigned j=0; jIsAutogen() ) continue; // skip autogen + HighScoreList &hsl = pProfile->GetStepsHighScoreList( pSteps ); CString s = GAMEMAN->NotesTypeToString(pSteps->m_StepsType) + " - " + DifficultyToString(pSteps->GetDifficulty()); - PRINT_DIV2_START_ANCHOR( /*Steps primary key*/pSteps, s.c_str() ); // use pointer value as the hash - PRINT_LINE_I( "NumTimesPlayed", pSteps->m_MemCardDatas[slot].iNumTimesPlayed ); + PRIst_DIV2_START_ANCHOR( /*Steps primary key*/pSteps, s.c_str() ); // use poister value as the hash + PRIst_LINE_I( "NumTimesPlayed", hsl.iNumTimesPlayed ); - vector& vHighScores = pSteps->m_MemCardDatas[slot].vHighScores; - for( unsigned i=0; i\n" ); - PRINT_DIV2_END; + PRIst_DIV2_END; } } - PRINT_SECTION_END; + PRIst_SECTION_END; } // - // Print Bookkeeping + // Prist Bookkeeping // { - PRINT_SECTION_START( "Bookkeeping" ); + PRIst_SECTION_START( "Bookkeeping" ); // GetCoinsLastDays { int coins[NUM_LAST_DAYS]; BOOKKEEPER->GetCoinsLastDays( coins ); - PRINT_DIV_START( ssprintf("Coins for Last %d Days",NUM_LAST_DAYS).c_str() ); + PRIst_DIV_START( ssprintf("Coins for Last %d Days",NUM_LAST_DAYS).c_str() ); for( int i=0; iGetCoinsLastWeeks( coins ); - PRINT_DIV_START( ssprintf("Coins for Last %d Weeks",NUM_LAST_WEEKS).c_str() ); + PRIst_DIV_START( ssprintf("Coins for Last %d Weeks",NUM_LAST_WEEKS).c_str() ); for( int i=0; iGetCoinsByDayOfWeek( coins ); - PRINT_DIV_START( "Coins by Day of Week" ); + PRIst_DIV_START( "Coins by Day of Week" ); for( int i=0; iGetCoinsByHour( coins ); - PRINT_DIV_START( ssprintf("Coins for Last %d Hours",HOURS_PER_DAY).c_str() ); + PRIst_DIV_START( ssprintf("Coins for Last %d Hours",HOURS_PER_DAY).c_str() ); for( int i=0; i" ); f.PutLine( "" ); @@ -1439,14 +1453,6 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, ProfileSlot slot ) } -bool ProfileManager::CategoryData::HighScore::operator>=( const HighScore& other ) const -{ - if( PREFSMAN->m_bPercentageScoring ) - return fPercentDP >= other.fPercentDP; - else - return iScore >= other.iScore; -} - bool ProfileManager::ProfileWasLoadedFromMemoryCard( PlayerNumber pn ) { return GetProfile(pn) && m_bWasLoadedFromMemoryCard[pn]; @@ -1466,3 +1472,112 @@ CString ProfileManager::GetProfileDir( ProfileSlot slot ) } } +Profile* ProfileManager::GetProfile( ProfileSlot slot ) +{ + switch( slot ) + { + case PROFILE_SLOT_PLAYER_1: + case PROFILE_SLOT_PLAYER_2: + if( m_sProfileDir[slot].empty() ) + return NULL; + else + return &m_Profile[slot]; + case PROFILE_SLOT_MACHINE: + return &m_MachineProfile; + default: + ASSERT(0); + } +} + + +// +// Song stats +// +int ProfileManager::GetSongNumTimesPlayed( Song* pSong, ProfileSlot card ) const +{ + int iTotalNumTimesPlayed = 0; + vector vpSteps; + pSong->GetSteps( vpSteps ); + for( unsigned i=0; iGetMachineProfile()->GetStepsHighScoreList(pSteps).iNumTimesPlayed; + } + + return iTotalNumTimesPlayed; +} + +void ProfileManager::AddStepsHighScore( const Steps* pSteps, PlayerNumber pn, HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut ) +{ + hs.sName = RANKING_TO_FILL_IN_MARKER[pn]; + if( PROFILEMAN->IsUsingProfile(pn) ) + PROFILEMAN->GetProfile(pn)->AddStepsHighScore( pSteps, hs, iPersonalIndexOut ); + else + iPersonalIndexOut = -1; + PROFILEMAN->GetMachineProfile()->AddStepsHighScore( pSteps, hs, iMachineIndexOut ); +} + +void ProfileManager::IncrementStepsPlayCount( const Steps* pSteps, PlayerNumber pn ) +{ + if( PROFILEMAN->IsUsingProfile(pn) ) + PROFILEMAN->GetProfile(pn)->IncrementStepsPlayCount( pSteps ); + PROFILEMAN->GetMachineProfile()->IncrementStepsPlayCount( pSteps ); +} + +HighScore ProfileManager::GetHighScoreForDifficulty( const Song *s, const StyleDef *st, ProfileSlot slot, Difficulty dc ) +{ + // return max grade of notes in difficulty class + vector aNotes; + s->GetSteps( aNotes, st->m_StepsType ); + SortNotesArrayByDifficulty( aNotes ); + + Steps* pSteps = s->GetStepsByDifficulty( st->m_StepsType, dc ); + + if( PROFILEMAN->IsUsingProfile(slot) ) + return PROFILEMAN->GetProfile(slot)->GetStepsHighScoreList(pSteps).GetTopScore(); + else + return HighScore(); +} + + +// +// Course stats +// +void ProfileManager::AddCourseHighScore( const Course* pCourse, StepsType st, PlayerNumber pn, HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut ) +{ + hs.sName = RANKING_TO_FILL_IN_MARKER[pn]; + if( PROFILEMAN->IsUsingProfile(pn) ) + PROFILEMAN->GetProfile(pn)->AddCourseHighScore( pCourse, st, hs, iPersonalIndexOut ); + else + iPersonalIndexOut = -1; + PROFILEMAN->GetMachineProfile()->AddCourseHighScore( pCourse, st, hs, iMachineIndexOut ); +} + +void ProfileManager::IncrementCoursePlayCount( const Course* pCourse, StepsType st, PlayerNumber pn ) +{ + if( PROFILEMAN->IsUsingProfile(pn) ) + PROFILEMAN->GetProfile(pn)->IncrementCoursePlayCount( pCourse, st ); + PROFILEMAN->GetMachineProfile()->IncrementCoursePlayCount( pCourse, st ); +} + + +// +// Category stats +// +void ProfileManager::AddCategoryHighScore( StepsType st, RankingCategory rc, PlayerNumber pn, HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut ) +{ + hs.sName = RANKING_TO_FILL_IN_MARKER[pn]; + if( PROFILEMAN->IsUsingProfile(pn) ) + PROFILEMAN->GetProfile(pn)->AddCategoryHighScore( st, rc, hs, iPersonalIndexOut ); + else + iPersonalIndexOut = -1; + PROFILEMAN->GetMachineProfile()->AddCategoryHighScore( st, rc, hs, iMachineIndexOut ); +} + +void ProfileManager::IncrementCategoryPlayCount( StepsType st, RankingCategory rc, PlayerNumber pn ) +{ + if( PROFILEMAN->IsUsingProfile(pn) ) + PROFILEMAN->GetProfile(pn)->IncrementCategoryPlayCount( st, rc ); + PROFILEMAN->GetMachineProfile()->IncrementCategoryPlayCount( st, rc ); +} + diff --git a/stepmania/src/ProfileManager.h b/stepmania/src/ProfileManager.h index 3fedebc598..f00c8051ce 100644 --- a/stepmania/src/ProfileManager.h +++ b/stepmania/src/ProfileManager.h @@ -17,6 +17,9 @@ #include "Style.h" #include "Profile.h" +class Song; +class StyleDef; + class ProfileManager { public: @@ -38,7 +41,22 @@ public: void SaveMachineProfile(); bool IsUsingProfile( PlayerNumber pn ) { return !m_sProfileDir[pn].empty(); } + bool IsUsingProfile( ProfileSlot slot ) + { + switch( slot ) + { + case PROFILE_SLOT_PLAYER_1: + case PROFILE_SLOT_PLAYER_2: + return !m_sProfileDir[slot].empty(); + case PROFILE_SLOT_MACHINE: + return true; + default: + ASSERT(0); + return false; + } + } Profile* GetProfile( PlayerNumber pn ); + Profile* GetProfile( ProfileSlot slot ); CString GetProfileDir( ProfileSlot slot ); Profile* GetMachineProfile() { return &m_MachineProfile; } @@ -53,36 +71,29 @@ public: void InitMachineScoresFromDisk(); void SaveMachineScoresToDisk(); - struct CategoryData - { - struct HighScore - { - CString sName; - int iScore; - float fPercentDP; + // + // Song stats + // + int GetSongNumTimesPlayed( Song* pSong, ProfileSlot card ) const; + bool IsSongNew( Song* pSong ) const { return GetSongNumTimesPlayed(pSong,PROFILE_SLOT_MACHINE)==0; } + void AddStepsHighScore( const Steps* pSteps, PlayerNumber pn, HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut ); + void IncrementStepsPlayCount( const Steps* pSteps, PlayerNumber pn ); + HighScore GetHighScoreForDifficulty( const Song *s, const StyleDef *st, ProfileSlot slot, Difficulty dc ); - HighScore() - { - iScore = 0; - fPercentDP = 0; - } + // + // Course stats + // + void AddCourseHighScore( const Course* pCourse, StepsType st, PlayerNumber pn, HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut ); + void IncrementCoursePlayCount( const Course* pCourse, StepsType st, PlayerNumber pn ); - bool operator>=( const HighScore& other ) const; - }; - vector vHighScores; + // + // Category stats + // + void AddCategoryHighScore( StepsType nt, RankingCategory rc, PlayerNumber pn, HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut ); + void IncrementCategoryPlayCount( StepsType nt, RankingCategory rc, PlayerNumber pn ); - void AddHighScore( HighScore hs, int &iIndexOut ); - } m_CategoryDatas[NUM_PROFILE_SLOTS][NUM_STEPS_TYPES][NUM_RANKING_CATEGORIES]; - - void AddHighScore( StepsType nt, RankingCategory rc, PlayerNumber pn, CategoryData::HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut ) - { - hs.sName = RANKING_TO_FILL_IN_MARKER[pn]; - m_CategoryDatas[pn][nt][rc].AddHighScore( hs, iPersonalIndexOut ); - m_CategoryDatas[PROFILE_SLOT_MACHINE][nt][rc].AddHighScore( hs, iMachineIndexOut ); - } - - void ReadSM300NoteScores(); +// void ReadSM300NoteScores(); void ReadSongScoresFromDir( CString sDir, ProfileSlot slot ); void ReadCourseScoresFromDir( CString sDir, ProfileSlot slot ); void ReadCategoryScoresFromDir( CString sDir, ProfileSlot slot ); diff --git a/stepmania/src/ScreenEvaluation.cpp b/stepmania/src/ScreenEvaluation.cpp index 946e6c9517..84c2f7a677 100644 --- a/stepmania/src/ScreenEvaluation.cpp +++ b/stepmania/src/ScreenEvaluation.cpp @@ -866,6 +866,14 @@ void ScreenEvaluation::CommitScores( const StageStats &stageStats, int iPersonal // depends on if this is a course or not ... it's handled // below in the switch + HighScore hs; + hs.grade = stageStats.GetGrade( (PlayerNumber)p ); + hs.iScore = stageStats.iScore[p]; + hs.fPercentDP = stageStats.GetPercentDancePoints( (PlayerNumber)p ); + hs.fSurviveTime = stageStats.fAliveSeconds[p]; + + StepsType nt = GAMESTATE->GetCurrentStyleDef()->m_StepsType; + switch( m_Type ) { case stage: @@ -876,12 +884,8 @@ void ScreenEvaluation::CommitScores( const StageStats &stageStats, int iPersonal ASSERT( GAMESTATE->m_pCurNotes[p] ); - Steps::MemCardData::HighScore hs; - hs.grade = stageStats.GetGrade( (PlayerNumber)p ); - hs.iScore = stageStats.iScore[p] + stageStats.iBonus[p]; - hs.fPercentDP = stageStats.GetPercentDancePoints( (PlayerNumber)p ); if( hs.fPercentDP > PREFSMAN->m_fMinPercentageForHighScore ) - GAMESTATE->m_pCurNotes[p]->AddHighScore( (PlayerNumber)p, hs, iPersonalHighScoreIndex[p], iMachineHighScoreIndex[p] ); + PROFILEMAN->AddStepsHighScore( GAMESTATE->m_pCurNotes[p], (PlayerNumber)p, hs, iPersonalHighScoreIndex[p], iMachineHighScoreIndex[p] ); } break; @@ -891,16 +895,11 @@ void ScreenEvaluation::CommitScores( const StageStats &stageStats, int iPersonal if( stageStats.bFailed[p] ) continue; - StepsType nt = GAMESTATE->GetCurrentStyleDef()->m_StepsType; - float fAverageMeter = stageStats.iMeter[p] / (float)PREFSMAN->m_iNumArcadeStages; rc[p] = AverageMeterToRankingCategory( fAverageMeter ); - ProfileManager::CategoryData::HighScore hs; - hs.iScore = stageStats.iScore[p]; - hs.fPercentDP = stageStats.GetPercentDancePoints( (PlayerNumber)p ); if( hs.fPercentDP > PREFSMAN->m_fMinPercentageForHighScore ) - PROFILEMAN->AddHighScore( nt, rc[p], (PlayerNumber)p, hs, iPersonalHighScoreIndex[p], iMachineHighScoreIndex[p] ); + PROFILEMAN->AddCategoryHighScore( nt, rc[p], (PlayerNumber)p, hs, iPersonalHighScoreIndex[p], iMachineHighScoreIndex[p] ); } break; @@ -914,13 +913,8 @@ void ScreenEvaluation::CommitScores( const StageStats &stageStats, int iPersonal if( stageStats.bFailed[p] && pCourse->IsNonstop() ) continue; - StepsType nt = GAMESTATE->GetCurrentStyleDef()->m_StepsType; - Course::MemCardData::HighScore hs; - hs.iScore = stageStats.iScore[p]; - hs.fPercentDP = stageStats.GetPercentDancePoints( (PlayerNumber)p ); - hs.fSurviveTime = stageStats.fAliveSeconds[p]; if( hs.fPercentDP > PREFSMAN->m_fMinPercentageForHighScore ) - pCourse->AddHighScore( nt, (PlayerNumber)p, hs, iPersonalHighScoreIndex[p], iMachineHighScoreIndex[p] ); + PROFILEMAN->AddCourseHighScore( pCourse, nt, (PlayerNumber)p, hs, iPersonalHighScoreIndex[p], iMachineHighScoreIndex[p] ); } } break; diff --git a/stepmania/src/ScreenGameplay.cpp b/stepmania/src/ScreenGameplay.cpp index b699e27fb9..6828636f35 100644 --- a/stepmania/src/ScreenGameplay.cpp +++ b/stepmania/src/ScreenGameplay.cpp @@ -173,10 +173,9 @@ ScreenGameplay::ScreenGameplay( CString sName, bool bDemonstration ) : Screen("S const StepsType st = GAMESTATE->GetCurrentStyleDef()->m_StepsType; /* Increment the play count. */ if( !m_bDemonstration ) - { - for( int mc = 0; mc < NUM_PROFILE_SLOTS; ++mc ) - ++GAMESTATE->m_pCurCourse->m_MemCardDatas[st][mc].iNumTimesPlayed; - } + for( p=0; pIsPlayerEnabled(p) ) + PROFILEMAN->IncrementCoursePlayCount( GAMESTATE->m_pCurCourse, st, (PlayerNumber)p ); for( int p=0; pm_pCurNotes[p]->m_MemCardDatas[mc].iNumTimesPlayed; - } - + PROFILEMAN->IncrementStepsPlayCount( GAMESTATE->m_pCurNotes[p], (PlayerNumber)p ); m_textPlayerOptions[p].SetText( GAMESTATE->m_PlayerOptions[p].GetString() ); diff --git a/stepmania/src/ScreenNameEntryTraditional.cpp b/stepmania/src/ScreenNameEntryTraditional.cpp index c39183cbc4..61bb4b1705 100644 --- a/stepmania/src/ScreenNameEntryTraditional.cpp +++ b/stepmania/src/ScreenNameEntryTraditional.cpp @@ -81,18 +81,18 @@ ScreenNameEntryTraditional::ScreenNameEntryTraditional( CString sClassName ) : S st.iPossibleDancePoints[i] = 1000; st.iActualDancePoints[i] = 985; - Steps::MemCardData::HighScore hs; + HighScore hs; hs.grade = GRADE_TIER_3; hs.iScore = 42; int a, b; - GAMESTATE->m_pCurNotes[i]->AddHighScore( (PlayerNumber)i, hs, a, b ); + PROFILEMAN->AddStepsHighScore( GAMESTATE->m_pCurNotes[i], (PlayerNumber)i, hs, a, b ); if( i == 0 ) { - ProfileManager::CategoryData::HighScore hs; + HighScore hs; hs.iScore = 1234567; StepsType nt = GAMESTATE->GetCurrentStyleDef()->m_StepsType; - PROFILEMAN->AddHighScore( nt, RANKING_A, (PlayerNumber)i, hs, a, b ); + PROFILEMAN->AddCategoryHighScore( nt, RANKING_A, (PlayerNumber)i, hs, a, b ); } } diff --git a/stepmania/src/ScreenRanking.cpp b/stepmania/src/ScreenRanking.cpp index 06cd0f8e40..c6300992c1 100644 --- a/stepmania/src/ScreenRanking.cpp +++ b/stepmania/src/ScreenRanking.cpp @@ -671,12 +671,13 @@ float ScreenRanking::SetPage( PageToShow pts ) for( int l=0; lGetMachineProfile()->GetCategoryHighScoreList(pts.nt,pts.category); + HighScore hs; bool bRecentHighScore = false; - if( l < (int)PROFILEMAN->m_CategoryDatas[PROFILE_SLOT_MACHINE][pts.nt][pts.category].vHighScores.size() ) + if( l < (int)hsl.vHighScores.size() ) { - hs = PROFILEMAN->m_CategoryDatas[PROFILE_SLOT_MACHINE][pts.nt][pts.category].vHighScores[l]; - CString *psName = &PROFILEMAN->m_CategoryDatas[PROFILE_SLOT_MACHINE][pts.nt][pts.category].vHighScores[l].sName; + hs = hsl.vHighScores[l]; + CString *psName = &hsl.vHighScores[l].sName; bRecentHighScore = find( GAMESTATE->m_vpsNamesThatWereFilled.begin(), GAMESTATE->m_vpsNamesThatWereFilled.end(), psName ) != GAMESTATE->m_vpsNamesThatWereFilled.end(); } else @@ -710,20 +711,22 @@ float ScreenRanking::SetPage( PageToShow pts ) m_Banner.LoadFromCourse( pts.pCourse ); m_textStepsType.SetText( GameManager::NotesTypeToString(pts.nt) ); + const HighScoreList &hsl = PROFILEMAN->GetMachineProfile()->GetCourseHighScoreList( pts.pCourse, pts.nt ); for( int l=0; lm_MemCardDatas[pts.nt][PROFILE_SLOT_MACHINE].vHighScores.size() ) + if( l < (int)hsl.vHighScores.size() ) { - hs = pts.pCourse->m_MemCardDatas[pts.nt][PROFILE_SLOT_MACHINE].vHighScores[l]; - CString *psName = &pts.pCourse->m_MemCardDatas[pts.nt][PROFILE_SLOT_MACHINE].vHighScores[l].sName; + hs = hsl.vHighScores[l]; + const CString *psName = &hsl.vHighScores[l].sName; bRecentHighScore = find( GAMESTATE->m_vpsNamesThatWereFilled.begin(), GAMESTATE->m_vpsNamesThatWereFilled.end(), psName ) != GAMESTATE->m_vpsNamesThatWereFilled.end(); } else { hs.sName = NO_SCORE_NAME; } + if( hs.sName.empty() ) hs.sName = EMPTY_SCORE_NAME; @@ -778,12 +781,13 @@ float ScreenRanking::SetPage( PageToShow pts ) } else { - Steps::MemCardData::HighScore hs; + HighScoreList &hsl = PROFILEMAN->GetMachineProfile()->GetStepsHighScoreList(pSteps); + HighScore hs = hsl.GetTopScore(); bool bRecentHighScore = false; - if( !pSteps->m_MemCardDatas[PROFILE_SLOT_MACHINE].vHighScores.empty() ) + if( !hsl.vHighScores.empty() ) { - hs = pSteps->m_MemCardDatas[PROFILE_SLOT_MACHINE].vHighScores[0]; - const CString *psName = &pSteps->m_MemCardDatas[PROFILE_SLOT_MACHINE].vHighScores[0].sName; + hs = hsl.GetTopScore(); + const CString *psName = &hsl.GetTopScore().sName; bRecentHighScore = find( GAMESTATE->m_vpsNamesThatWereFilled.begin(), GAMESTATE->m_vpsNamesThatWereFilled.end(), psName ) != GAMESTATE->m_vpsNamesThatWereFilled.end(); } else @@ -812,16 +816,20 @@ float ScreenRanking::SetPage( PageToShow pts ) const Course* pCourse = pCourseScoreRowItem->m_pCourse; pCourseScoreRowItem->m_textSongTitle.SetText( pCourse->m_sName ); + const HighScoreList &hsl = PROFILEMAN->GetMachineProfile()->GetCourseHighScoreList( pCourse, pts.nt ); for( int d=0; dm_textStepsScore[d]; - Course::MemCardData::HighScore hs; + HighScore hs; bool bRecentHighScore = false; - if( !pCourse->m_MemCardDatas[pts.nt][PROFILE_SLOT_MACHINE].vHighScores.empty() ) + if( !hsl.vHighScores.empty() ) { - hs = pCourse->m_MemCardDatas[pts.nt][PROFILE_SLOT_MACHINE].vHighScores[0]; - const CString *psName = &pCourse->m_MemCardDatas[pts.nt][PROFILE_SLOT_MACHINE].vHighScores[0].sName; + hs = hsl.vHighScores[0]; + const CString *psName = &hsl.GetTopScore().sName; bRecentHighScore = find( GAMESTATE->m_vpsNamesThatWereFilled.begin(), GAMESTATE->m_vpsNamesThatWereFilled.end(), psName ) != GAMESTATE->m_vpsNamesThatWereFilled.end(); } else diff --git a/stepmania/src/ScreenSelectCourse.cpp b/stepmania/src/ScreenSelectCourse.cpp index 2d80149e8e..aebce0055b 100644 --- a/stepmania/src/ScreenSelectCourse.cpp +++ b/stepmania/src/ScreenSelectCourse.cpp @@ -416,21 +416,23 @@ void ScreenSelectCourse::AfterCourseChange() { const StepsType &st = GAMESTATE->GetCurrentStyleDef()->m_StepsType; - int mc = PROFILE_SLOT_MACHINE; + Profile* pProfile; if( PROFILEMAN->IsUsingProfile( (PlayerNumber)p ) ) - mc = p; + pProfile = PROFILEMAN->GetProfile((PlayerNumber)p); + else + pProfile = PROFILEMAN->GetMachineProfile(); + /* Courses are scored by survive time, dance points, * percent, and normal score. Every last mother will * have an opinion on which should be used here for * each of oni, endless, nonstop -- * should this choice be an option or a metric? */ + const HighScoreList& hsl = pProfile->GetCourseHighScoreList( pCourse, st ); if ( pCourse->IsOni() || pCourse->IsEndless() ) { /* use survive time */ - float fSurviveTime = 0.0f; - if( !pCourse->m_MemCardDatas[st][mc].vHighScores.empty() ) - fSurviveTime = pCourse->m_MemCardDatas[st][mc].vHighScores[0].fSurviveTime; + float fSurviveTime = hsl.GetTopScore().fSurviveTime; CString s = SecondsToTime(fSurviveTime); /* dim the inital unsignificant digits */ @@ -452,10 +454,7 @@ void ScreenSelectCourse::AfterCourseChange() else /* pCourse->IsNonStop() */ { /* use score */ - int iScore = 0; - if( !pCourse->m_MemCardDatas[st][mc].vHighScores.empty() ) - iScore = pCourse->m_MemCardDatas[st][mc].vHighScores[0].iScore; - + int iScore = hsl.GetTopScore().iScore; m_HighScore[p].SetText( ssprintf("%*i", NUM_SCORE_DIGITS, iScore) ); } diff --git a/stepmania/src/ScreenSelectMusic.cpp b/stepmania/src/ScreenSelectMusic.cpp index be41c56323..999e6d6e78 100644 --- a/stepmania/src/ScreenSelectMusic.cpp +++ b/stepmania/src/ScreenSelectMusic.cpp @@ -1008,7 +1008,7 @@ void ScreenSelectMusic::MenuStart( PlayerNumber pn ) switch( m_MusicWheel.GetSelectedType() ) { case TYPE_SONG: { - const bool bIsNew = m_MusicWheel.GetSelectedSong()->IsNew(); + const bool bIsNew = PROFILEMAN->IsSongNew( m_MusicWheel.GetSelectedSong() ); bool bIsHard = false; for( int p=0; pm_pCurNotes[pn] = pNotes; + GAMESTATE->m_pCurNotes[pn] = pSteps; // m_BPMDisplay.SetZoomY( 0 ); // m_BPMDisplay.BeginTweening( 0.2f ); // m_BPMDisplay.SetZoomY( 1.2f ); - if( pNotes ) + if( pSteps ) { int iScore = 0; if( PROFILEMAN->IsUsingProfile(pn) ) - { - if( !pNotes->m_MemCardDatas[pn].vHighScores.empty() ) - iScore = pNotes->m_MemCardDatas[pn].vHighScores[0].iScore; - } + iScore = PROFILEMAN->GetProfile(pn)->GetStepsHighScoreList(pSteps).GetTopScore().iScore; else - { - if( !pNotes->m_MemCardDatas[PROFILE_SLOT_MACHINE].vHighScores.empty() ) - iScore = pNotes->m_MemCardDatas[PROFILE_SLOT_MACHINE].vHighScores[0].iScore; - } + iScore = PROFILEMAN->GetMachineProfile()->GetStepsHighScoreList(pSteps).GetTopScore().iScore; m_textHighScore[pn].SetText( ssprintf("%*i", NUM_SCORE_DIGITS, iScore) ); } else @@ -1161,8 +1155,8 @@ void ScreenSelectMusic::AfterNotesChange( PlayerNumber pn ) m_textHighScore[pn].SetText( ssprintf("%*i", NUM_SCORE_DIGITS, 0) ); } - m_DifficultyIcon[pn].SetFromNotes( pn, pNotes ); - if( pNotes && pNotes->IsAutogen() ) + m_DifficultyIcon[pn].SetFromNotes( pn, pSteps ); + if( pSteps && pSteps->IsAutogen() ) { m_AutoGenIcon[pn].SetEffectDiffuseShift(); } @@ -1174,7 +1168,7 @@ void ScreenSelectMusic::AfterNotesChange( PlayerNumber pn ) m_DifficultyMeter[pn].SetFromGameState( pn ); if( SHOW_DIFFICULTY_LIST ) m_DifficultyList.SetFromGameState(); - m_GrooveRadar.SetFromNotes( pn, pNotes ); + m_GrooveRadar.SetFromNotes( pn, pSteps ); m_MusicWheel.NotesChanged( pn ); if( SHOW_PANES ) m_PaneDisplay[pn].SetFromGameState(); diff --git a/stepmania/src/Song.cpp b/stepmania/src/Song.cpp index 8f858d3fab..905b8f4987 100644 --- a/stepmania/src/Song.cpp +++ b/stepmania/src/Song.cpp @@ -34,6 +34,7 @@ #include "RageFileManager.h" #include "NoteDataUtil.h" #include "SDL_utils.h" +#include "ProfileManager.h" #include "NotesLoaderSM.h" #include "NotesLoaderDWI.h" @@ -860,7 +861,8 @@ void Song::GetSteps( vector& arrayAddTo, StepsType nt, Difficulty dc, in if( !Max ) break; - if( m_apNotes[i]->m_StepsType != nt ) continue; + if( nt != STEPS_TYPE_INVALID && m_apNotes[i]->m_StepsType != nt ) + continue; if( dc != DIFFICULTY_INVALID && dc != m_apNotes[i]->GetDifficulty() ) continue; if( iMeterLow != -1 && iMeterLow > m_apNotes[i]->GetMeter() ) @@ -1114,28 +1116,6 @@ void Song::RemoveAutoGenNotes() } } - -Steps::MemCardData::HighScore GetHighScoreForDifficulty( const Song *s, const StyleDef *st, ProfileSlot card, Difficulty dc ) -{ - // return max grade of notes in difficulty class - vector aNotes; - s->GetSteps( aNotes, st->m_StepsType ); - SortNotesArrayByDifficulty( aNotes ); - - - Steps* pSteps = s->GetStepsByDifficulty( st->m_StepsType, dc ); - if( pSteps ) - return pSteps->GetTopScore(card); - else - return Steps::MemCardData::HighScore(); -} - - -bool Song::IsNew() const -{ - return GetNumTimesPlayed(PROFILE_SLOT_MACHINE) == 0; -} - bool Song::IsEasy( StepsType nt ) const { const Steps* pHardNotes = GetStepsByDifficulty( nt, DIFFICULTY_HARD ); @@ -1387,10 +1367,10 @@ bool CompareSongPointersBySortValueDescending(const Song *pSong1, const Song *pS return song_sort_val[pSong1] > song_sort_val[pSong2]; } -void SortSongPointerArrayByMostPlayed( vector &arraySongPointers, ProfileSlot card ) +void SortSongPointerArrayByMostPlayed( vector &arraySongPointers, ProfileSlot slot ) { for(unsigned i = 0; i < arraySongPointers.size(); ++i) - song_sort_val[arraySongPointers[i]] = ssprintf("%9i", arraySongPointers[i]->GetNumTimesPlayed(card)); + song_sort_val[arraySongPointers[i]] = ssprintf("%9i", PROFILEMAN->GetSongNumTimesPlayed(arraySongPointers[i],slot)); stable_sort( arraySongPointers.begin(), arraySongPointers.end(), CompareSongPointersBySortValueDescending ); song_sort_val.clear(); } @@ -1553,14 +1533,6 @@ bool Song::HasBackground() const {return m_sBackgroundFile != "" && IsAFile(G bool Song::HasCDTitle() const {return m_sCDTitleFile != "" && IsAFile(GetCDTitlePath()); } bool Song::HasBGChanges() const {return !m_BackgroundChanges.empty(); } -int Song::GetNumTimesPlayed( ProfileSlot card ) const -{ - int iTotalNumTimesPlayed = 0; - for( unsigned i=0; iGetNumTimesPlayed( card ); - - return iTotalNumTimesPlayed; -} /* Note that supplying a path relative to the top-level directory is only for compatibility * with DWI. We prefer paths relative to the song directory. */ @@ -1673,7 +1645,7 @@ int Song::GetNumNotesWithGrade( Grade g ) const { Steps* pSteps = vNotes[j]; - if( pSteps->GetTopScore(PROFILE_SLOT_MACHINE).grade == g ) + if( PROFILEMAN->GetMachineProfile()->GetStepsHighScoreList(pSteps).GetTopScore().grade == g ) iCount++; } return iCount; diff --git a/stepmania/src/Steps.cpp b/stepmania/src/Steps.cpp index 80458b4e26..f7ecc86379 100644 --- a/stepmania/src/Steps.cpp +++ b/stepmania/src/Steps.cpp @@ -327,10 +327,13 @@ bool CompareStepsPointersBySortValueDescending(const Steps *pSteps1, const Steps return steps_sort_val[pSteps1] > steps_sort_val[pSteps2]; } -void SortStepsPointerArrayByMostPlayed( vector &vStepsPointers, ProfileSlot card ) +void SortStepsPointerArrayByMostPlayed( vector &vStepsPointers, ProfileSlot slot ) { + Profile* pProfile = PROFILEMAN->GetProfile(slot); + ASSERT( pProfile ); // we shouldn't be requesting this sort unless there's a Profile in this slot + for(unsigned i = 0; i < vStepsPointers.size(); ++i) - steps_sort_val[vStepsPointers[i]] = ssprintf("%9i", vStepsPointers[i]->GetNumTimesPlayed(card)); + steps_sort_val[vStepsPointers[i]] = ssprintf("%9i", pProfile->GetStepsNumTimesPlayed(vStepsPointers[i])); stable_sort( vStepsPointers.begin(), vStepsPointers.end(), CompareStepsPointersBySortValueDescending ); steps_sort_val.clear(); } @@ -382,51 +385,3 @@ void SortStepsByTypeAndDifficulty( vector &arraySongPointers ) } -bool Steps::MemCardData::HighScore::operator>=( const Steps::MemCardData::HighScore& other ) const -{ - if( PREFSMAN->m_bPercentageScoring ) - return fPercentDP >= other.fPercentDP; - else - return iScore >= other.iScore; - /* Make sure we treat AAAA as higher than AAA, even though the score - * is the same. - * - * XXX: Isn't it possible to beat the grade but not beat the score, since - * grading and scores are on completely different systems? Should we be - * checking for these completely separately? */ - // if( vsScore > this->fScore ) - // return true; - // if( vsScore < this->fScore ) - // return false; - // return vsGrade > this->grade; -} - -void Steps::MemCardData::AddHighScore( Steps::MemCardData::HighScore hs, int &iIndexOut ) -{ - int i; - - for( i=0; i<(int)vHighScores.size(); i++ ) - { - if( hs >= vHighScores[i] ) // tie goes to new score - break; - } - - if( i < NUM_RANKING_LINES ) - { - vHighScores.insert( vHighScores.begin()+i, hs ); - iIndexOut = i; - if( (int)vHighScores.size() > NUM_RANKING_LINES ) - vHighScores.erase( vHighScores.begin()+NUM_RANKING_LINES, vHighScores.end() ); - } -} - -void Steps::AddHighScore( PlayerNumber pn, MemCardData::HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut ) -{ - hs.sName = RANKING_TO_FILL_IN_MARKER[pn]; - if( PROFILEMAN->IsUsingProfile(pn) ) - m_MemCardDatas[pn].AddHighScore( hs, iPersonalIndexOut ); - else - iPersonalIndexOut = -1; - m_MemCardDatas[PROFILE_SLOT_MACHINE].AddHighScore( hs, iMachineIndexOut ); -} - diff --git a/stepmania/src/Steps.h b/stepmania/src/Steps.h index ab843a3abd..7c520e847f 100644 --- a/stepmania/src/Steps.h +++ b/stepmania/src/Steps.h @@ -55,58 +55,6 @@ public: void SetSMNoteData( const CString ¬es_comp, const CString &attacks_comp ); void GetSMNoteData( CString ¬es_comp_out, CString &attacks_comp_out ) const; - - struct MemCardData - { - MemCardData() - { - iNumTimesPlayed = 0; - } - - int iNumTimesPlayed; - - struct HighScore - { - CString sName; - Grade grade; - int iScore; - float fPercentDP; - - HighScore() - { - grade = GRADE_NO_DATA; - iScore = 0; - fPercentDP = 0; - } - - bool operator>=( const HighScore& other ) const; - }; - vector vHighScores; - - void AddHighScore( MemCardData::HighScore hs, int &iIndexOut ); - - HighScore GetTopScore() - { - if( vHighScores.empty() ) - return HighScore(); - else - return vHighScores[0]; - } - - } m_MemCardDatas[NUM_PROFILE_SLOTS]; - - void AddHighScore( PlayerNumber pn, MemCardData::HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut ); - - MemCardData::HighScore GetTopScore( ProfileSlot slot ) - { - return m_MemCardDatas[slot].GetTopScore(); - } - - int GetNumTimesPlayed( ProfileSlot slot ) - { - return m_MemCardDatas[slot].iNumTimesPlayed; - } - void TidyUpData(); protected: diff --git a/stepmania/src/song.h b/stepmania/src/song.h index a57e43839d..0f04aa8c49 100644 --- a/stepmania/src/song.h +++ b/stepmania/src/song.h @@ -182,14 +182,12 @@ public: bool SongHasNotesType( StepsType nt ) const; bool SongHasNotesTypeAndDifficulty( StepsType nt, Difficulty dc ) const; const vector& GetAllSteps() const { return m_apNotes; } - void GetSteps( vector& arrayAddTo, StepsType nt, Difficulty dc = DIFFICULTY_INVALID, int iMeterLow = -1, int iMeterHigh = -1, const CString &sDescription = "", bool bIncludeAutoGen = true, int Max = -1 ) const; + void GetSteps( vector& arrayAddTo, StepsType nt = STEPS_TYPE_INVALID, Difficulty dc = DIFFICULTY_INVALID, int iMeterLow = -1, int iMeterHigh = -1, const CString &sDescription = "", bool bIncludeAutoGen = true, int Max = -1 ) const; Steps* GetStepsByDifficulty( StepsType nt, Difficulty dc, bool bIncludeAutoGen = true ) const; Steps* GetStepsByMeter( StepsType nt, int iMeterLow, int iMeterHigh, bool bIncludeAutoGen = true ) const; Steps* GetStepsByDescription( StepsType nt, CString sDescription, bool bIncludeAutoGen = true ) const; Steps* GetClosestNotes( StepsType nt, Difficulty dc, bool bIncludeAutoGen = true ) const; void GetEdits( vector& arrayAddTo, StepsType nt, bool bIncludeAutoGen = true ) const; - int GetNumTimesPlayed( ProfileSlot slot ) const; - bool IsNew() const; bool IsEasy( StepsType nt ) const; bool HasEdits( StepsType nt ) const; bool NormallyDisplayed() const;