diff --git a/stepmania/Themes/default/metrics.ini b/stepmania/Themes/default/metrics.ini index d43c1c4694..b4d150804a 100644 --- a/stepmania/Themes/default/metrics.ini +++ b/stepmania/Themes/default/metrics.ini @@ -3368,8 +3368,10 @@ TimerSeconds=-1 StepsTypesToHide=dance-couple,dance-solo,pump-halfdouble ShowCategories=1 CoursesToShow=Courses/DDRMAX/NaokiStandard.crs,Courses/DDRMAX/ParanoiaBrothers.crs,Courses/Samples/PlayersBest1-4.crs -ShowAllStepsScores=0 -ShowAllCourseScores=0 +ShowStepsScores=0 +ShowCourseScores=0 +ShowOnlyMostRecentScores=0 +NumMostRecentScoresToShow=10 DifficultiesToShow=easy,medium,hard,challenge SecondsPerPage=5 PageFadeSeconds=1.0 diff --git a/stepmania/src/CourseUtil.cpp b/stepmania/src/CourseUtil.cpp index 3f69d74b60..39192ea918 100644 --- a/stepmania/src/CourseUtil.cpp +++ b/stepmania/src/CourseUtil.cpp @@ -7,6 +7,7 @@ #include "XmlFile.h" #include "GameState.h" #include "Style.h" +#include "Foreach.h" // @@ -92,23 +93,23 @@ static bool CompareCoursePointersByRanking(const Course* pCourse1, const Course* return iNum1 < iNum2; } -void CourseUtil::SortCoursePointerArrayByDifficulty( vector &apCourses ) +void CourseUtil::SortCoursePointerArrayByDifficulty( vector &vpCoursesInOut ) { - sort( apCourses.begin(), apCourses.end(), CompareCoursePointersByDifficulty ); + sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), CompareCoursePointersByDifficulty ); } -void CourseUtil::SortCoursePointerArrayByRanking( vector &apCourses ) +void CourseUtil::SortCoursePointerArrayByRanking( vector &vpCoursesInOut ) { - for(unsigned i=0; iUpdateCourseStats( GAMESTATE->GetCurrentStyle()->m_StepsType ); - sort( apCourses.begin(), apCourses.end(), CompareCoursePointersByRanking ); + for(unsigned i=0; iUpdateCourseStats( GAMESTATE->GetCurrentStyle()->m_StepsType ); + sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), CompareCoursePointersByRanking ); } -void CourseUtil::SortCoursePointerArrayByTotalDifficulty( vector &apCourses ) +void CourseUtil::SortCoursePointerArrayByTotalDifficulty( vector &vpCoursesInOut ) { - for(unsigned i=0; iUpdateCourseStats( GAMESTATE->GetCurrentStyle()->m_StepsType ); - sort( apCourses.begin(), apCourses.end(), CompareCoursePointersByTotalDifficulty ); + for(unsigned i=0; iUpdateCourseStats( GAMESTATE->GetCurrentStyle()->m_StepsType ); + sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), CompareCoursePointersByTotalDifficulty ); } static bool CompareCoursePointersByType(const Course* pCourse1, const Course* pCourse2) @@ -116,17 +117,17 @@ static bool CompareCoursePointersByType(const Course* pCourse1, const Course* pC return pCourse1->GetPlayMode() < pCourse2->GetPlayMode(); } -void CourseUtil::SortCoursePointerArrayByType( vector &apCourses ) +void CourseUtil::SortCoursePointerArrayByType( vector &vpCoursesInOut ) { - stable_sort( apCourses.begin(), apCourses.end(), CompareCoursePointersByType ); + stable_sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), CompareCoursePointersByType ); } -void CourseUtil::MoveRandomToEnd( vector &apCourses ) +void CourseUtil::MoveRandomToEnd( vector &vpCoursesInOut ) { - stable_sort( apCourses.begin(), apCourses.end(), CompareRandom ); + stable_sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), CompareRandom ); } -static map course_sort_val; +static map course_sort_val; bool CompareCoursePointersBySortValueAscending(const Course *pSong1, const Course *pSong2) { @@ -143,44 +144,65 @@ bool CompareCoursePointersByTitle( const Course *pCourse1, const Course *pCourse return CompareCoursePointersByName( pCourse1, pCourse2 ); } -void CourseUtil::SortCoursePointerArrayByTitle( vector &apCourses ) +void CourseUtil::SortCoursePointerArrayByTitle( vector &vpCoursesInOut ) { - sort( apCourses.begin(), apCourses.end(), CompareCoursePointersByTitle ); + sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), CompareCoursePointersByTitle ); } -void CourseUtil::SortCoursePointerArrayByAvgDifficulty( vector &apCourses ) +void CourseUtil::SortCoursePointerArrayByAvgDifficulty( vector &vpCoursesInOut ) { RageTimer foo; course_sort_val.clear(); - for(unsigned i = 0; i < apCourses.size(); ++i) + for(unsigned i = 0; i < vpCoursesInOut.size(); ++i) { - const Trail* pTrail = apCourses[i]->GetTrail( GAMESTATE->GetCurrentStyle()->m_StepsType ); - course_sort_val[apCourses[i]] = pTrail != NULL? (float) pTrail->GetMeter(): 0.0f; + const Trail* pTrail = vpCoursesInOut[i]->GetTrail( GAMESTATE->GetCurrentStyle()->m_StepsType ); + course_sort_val[vpCoursesInOut[i]] = pTrail != NULL? (float) pTrail->GetMeter(): 0.0f; } - sort( apCourses.begin(), apCourses.end(), CompareCoursePointersByTitle ); - stable_sort( apCourses.begin(), apCourses.end(), CompareCoursePointersBySortValueAscending ); + sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), CompareCoursePointersByTitle ); + stable_sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), CompareCoursePointersBySortValueAscending ); - stable_sort( apCourses.begin(), apCourses.end(), MovePlayersBestToEnd ); + stable_sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), MovePlayersBestToEnd ); } -void CourseUtil::SortCoursePointerArrayByNumPlays( vector &arrayCoursePointers, ProfileSlot slot, bool bDescending ) +void CourseUtil::SortCoursePointerArrayByNumPlays( vector &vpCoursesInOut, ProfileSlot slot, bool bDescending ) { Profile* pProfile = PROFILEMAN->GetProfile(slot); if( pProfile == NULL ) return; // nothing to do since we don't have data - SortCoursePointerArrayByNumPlays( arrayCoursePointers, pProfile, bDescending ); + SortCoursePointerArrayByNumPlays( vpCoursesInOut, pProfile, bDescending ); } -void CourseUtil::SortCoursePointerArrayByNumPlays( vector &arrayCoursePointers, const Profile* pProfile, bool bDescending ) +void CourseUtil::SortCoursePointerArrayByNumPlays( vector &vpCoursesInOut, const Profile* pProfile, bool bDescending ) { ASSERT( pProfile ); - for(unsigned i = 0; i < arrayCoursePointers.size(); ++i) - course_sort_val[arrayCoursePointers[i]] = (float) pProfile->GetCourseNumTimesPlayed(arrayCoursePointers[i]); - stable_sort( arrayCoursePointers.begin(), arrayCoursePointers.end(), bDescending ? CompareCoursePointersBySortValueDescending : CompareCoursePointersBySortValueAscending ); + for(unsigned i = 0; i < vpCoursesInOut.size(); ++i) + course_sort_val[vpCoursesInOut[i]] = (float) pProfile->GetCourseNumTimesPlayed(vpCoursesInOut[i]); + stable_sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), bDescending ? CompareCoursePointersBySortValueDescending : CompareCoursePointersBySortValueAscending ); course_sort_val.clear(); } +void CourseUtil::SortByMostRecentlyPlayedForMachine( vector &vpCoursesInOut ) +{ + Profile *pProfile = PROFILEMAN->GetMachineProfile(); + + FOREACH_CONST( Course*, vpCoursesInOut, c ) + { + int iNumTimesPlayed = pProfile->GetCourseNumTimesPlayed( *c ); + CString val = iNumTimesPlayed ? pProfile->GetCourseLastPlayedDateTime(*c).GetString() : "9999999999999"; + course_sort_val[*c] = val; + } + + stable_sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), CompareCoursePointersBySortValueAscending ); + course_sort_val.clear(); +} + + + +////////////////////////////////// +// CourseID +////////////////////////////////// + void CourseID::FromCourse( const Course *p ) { if( p ) diff --git a/stepmania/src/CourseUtil.h b/stepmania/src/CourseUtil.h index 2b58b7c3cb..34f75a1f5b 100644 --- a/stepmania/src/CourseUtil.h +++ b/stepmania/src/CourseUtil.h @@ -11,16 +11,17 @@ struct XNode; namespace CourseUtil { - void SortCoursePointerArrayByDifficulty( vector &apCourses ); - void SortCoursePointerArrayByType( vector &apCourses ); - void SortCoursePointerArrayByTitle( vector &apCourses ); - void SortCoursePointerArrayByAvgDifficulty( vector &apCourses ); - void SortCoursePointerArrayByTotalDifficulty( vector &apCourses ); - void SortCoursePointerArrayByRanking( vector &apCourses ); - void SortCoursePointerArrayByNumPlays( vector &arrayCoursePointers, ProfileSlot slot, bool bDescending ); - void SortCoursePointerArrayByNumPlays( vector &arrayCoursePointers, const Profile* pProfile, bool bDescending ); + void SortCoursePointerArrayByDifficulty( vector &vpCoursesInOut ); + void SortCoursePointerArrayByType( vector &vpCoursesInOut ); + void SortCoursePointerArrayByTitle( vector &vpCoursesInOut ); + void SortCoursePointerArrayByAvgDifficulty( vector &vpCoursesInOut ); + void SortCoursePointerArrayByTotalDifficulty( vector &vpCoursesInOut ); + void SortCoursePointerArrayByRanking( vector &vpCoursesInOut ); + void SortCoursePointerArrayByNumPlays( vector &vpCoursesInOut, ProfileSlot slot, bool bDescending ); + void SortCoursePointerArrayByNumPlays( vector &vpCoursesInOut, const Profile* pProfile, bool bDescending ); + void SortByMostRecentlyPlayedForMachine( vector &vpCoursesInOut ); - void MoveRandomToEnd( vector &apCourses ); + void MoveRandomToEnd( vector &vpCoursesInOut ); }; class CourseID diff --git a/stepmania/src/HighScore.cpp b/stepmania/src/HighScore.cpp index 54cfe298af..e578cd2416 100644 --- a/stepmania/src/HighScore.cpp +++ b/stepmania/src/HighScore.cpp @@ -139,6 +139,12 @@ void HighScoreList::AddHighScore( HighScore hs, int &iIndexOut, bool bIsMachine } } +void HighScoreList::IncrementPlayCount( DateTime dtLastPlayed ) +{ + dtLastPlayed = dtLastPlayed; + iNumTimesPlayed++; +} + const HighScore& HighScoreList::GetTopScore() const { if( vHighScores.empty() ) @@ -180,6 +186,10 @@ void HighScoreList::LoadFromNode( const XNode* pHighScoreList ) { p->GetValue( iNumTimesPlayed ); } + else if( p->m_sName == "LastPlayed" ) + { + p->GetValue( dtLastPlayed ); + } else if( p->m_sName == "HighScore" ) { vHighScores.resize( vHighScores.size()+1 ); diff --git a/stepmania/src/HighScore.h b/stepmania/src/HighScore.h index af515fd338..b9d64284cc 100644 --- a/stepmania/src/HighScore.h +++ b/stepmania/src/HighScore.h @@ -75,26 +75,37 @@ struct HighScore struct HighScoreList { - int iNumTimesPlayed; - vector vHighScores; - - +public: HighScoreList() { iNumTimesPlayed = 0; } - void Init(); + + int GetNumTimesPlayed() const + { + return iNumTimesPlayed; + } + DateTime GetLastPlayed() const + { + ASSERT( iNumTimesPlayed > 0 ); // don't call this unless the song has been played + return dtLastPlayed; + } + const HighScore& GetTopScore() const; void AddHighScore( HighScore hs, int &iIndexOut, bool bIsMachine ); - - const HighScore& GetTopScore() const; + void IncrementPlayCount( DateTime dtLastPlayed ); + void RemoveAllButOneOfEachName(); + void ClampSize( bool bIsMachine ); XNode* CreateNode() const; void LoadFromNode( const XNode* pNode ); - void RemoveAllButOneOfEachName(); - void ClampSize( bool bIsMachine ); + vector vHighScores; +private: + int iNumTimesPlayed; + DateTime dtLastPlayed; // meaningless if iNumTimesPlayed == 0 + }; struct Screenshot diff --git a/stepmania/src/Profile.cpp b/stepmania/src/Profile.cpp index 8c2d853385..f8c518c751 100644 --- a/stepmania/src/Profile.cpp +++ b/stepmania/src/Profile.cpp @@ -475,7 +475,7 @@ int Profile::GetSongNumTimesPlayed( const SongID& songID ) const { const HighScoresForASteps &hsSteps = j->second; - iTotalNumTimesPlayed += hsSteps.hsl.iNumTimesPlayed; + iTotalNumTimesPlayed += hsSteps.hsl.GetNumTimesPlayed(); } return iTotalNumTimesPlayed; } @@ -541,12 +541,35 @@ HighScoreList& Profile::GetStepsHighScoreList( const Song* pSong, const Steps* p int Profile::GetStepsNumTimesPlayed( const Song* pSong, const Steps* pSteps ) const { - return GetStepsHighScoreList(pSong,pSteps).iNumTimesPlayed; + return GetStepsHighScoreList(pSong,pSteps).GetNumTimesPlayed(); +} + +DateTime Profile::GetSongLastPlayedDateTime( const Song* pSong ) const +{ + SongID id; + id.FromSong( pSong ); + std::map::const_iterator iter = m_SongHighScores.find( id ); + + // don't call this unless has been played once + ASSERT( iter != m_SongHighScores.end() ); + ASSERT( !iter->second.m_StepsHighScores.empty() ); + + DateTime dtLatest; // starts out zeroed + FOREACHM_CONST( StepsID, HighScoresForASteps, iter->second.m_StepsHighScores, i ) + { + const HighScoreList &hsl = i->second.hsl; + if( hsl.GetNumTimesPlayed() == 0 ) + continue; + if( dtLatest < hsl.GetLastPlayed() ) + dtLatest = hsl.GetLastPlayed(); + } + return dtLatest; } void Profile::IncrementStepsPlayCount( const Song* pSong, const Steps* pSteps ) { - GetStepsHighScoreList(pSong,pSteps).iNumTimesPlayed++; + DateTime now = DateTime::GetNowDate(); + GetStepsHighScoreList(pSong,pSteps).IncrementPlayCount( now ); } void Profile::GetGrades( const Song* pSong, StepsType st, int iCounts[NUM_GRADES] ) const @@ -624,14 +647,37 @@ int Profile::GetCourseNumTimesPlayed( const CourseID &courseID ) const { const HighScoresForATrail &hsTrail = j->second; - iTotalNumTimesPlayed += hsTrail.hsl.iNumTimesPlayed; + iTotalNumTimesPlayed += hsTrail.hsl.GetNumTimesPlayed(); } return iTotalNumTimesPlayed; } +DateTime Profile::GetCourseLastPlayedDateTime( const Course* pCourse ) const +{ + CourseID id; + id.FromCourse( pCourse ); + std::map::const_iterator iter = m_CourseHighScores.find( id ); + + // don't call this unless has been played once + ASSERT( iter != m_CourseHighScores.end() ); + ASSERT( !iter->second.m_TrailHighScores.empty() ); + + DateTime dtLatest; // starts out zeroed + FOREACHM_CONST( TrailID, HighScoresForATrail, iter->second.m_TrailHighScores, i ) + { + const HighScoreList &hsl = i->second.hsl; + if( hsl.GetNumTimesPlayed() == 0 ) + continue; + if( dtLatest < hsl.GetLastPlayed() ) + dtLatest = hsl.GetLastPlayed(); + } + return dtLatest; +} + void Profile::IncrementCoursePlayCount( const Course* pCourse, const Trail* pTrail ) { - GetCourseHighScoreList(pCourse,pTrail).iNumTimesPlayed++; + DateTime now = DateTime::GetNowDate(); + GetCourseHighScoreList(pCourse,pTrail).IncrementPlayCount( now ); } // @@ -656,13 +702,14 @@ int Profile::GetCategoryNumTimesPlayed( StepsType st ) const { int iNumTimesPlayed = 0; FOREACH_RankingCategory( rc ) - iNumTimesPlayed += m_CategoryHighScores[st][rc].iNumTimesPlayed; + iNumTimesPlayed += m_CategoryHighScores[st][rc].GetNumTimesPlayed(); return iNumTimesPlayed; } void Profile::IncrementCategoryPlayCount( StepsType st, RankingCategory rc ) { - m_CategoryHighScores[st][rc].iNumTimesPlayed++; + DateTime now = DateTime::GetNowDate(); + m_CategoryHighScores[st][rc].IncrementPlayCount( now ); } @@ -1204,7 +1251,7 @@ XNode* Profile::SaveSongScoresCreateNode() const const HighScoreList &hsl = hsSteps.hsl; // skip steps that have never been played - if( hsl.iNumTimesPlayed == 0 ) + if( hsl.GetNumTimesPlayed() == 0 ) continue; XNode* pStepsNode = pSongNode->AppendChild( stepsID.CreateNode() ); @@ -1287,7 +1334,7 @@ XNode* Profile::SaveCourseScoresCreateNode() const const HighScoreList &hsl = hsTrail.hsl; // skip steps that have never been played - if( hsl.iNumTimesPlayed == 0 ) + if( hsl.GetNumTimesPlayed() == 0 ) continue; XNode* pTrailNode = pCourseNode->AppendChild( trailID.CreateNode() ); @@ -1357,7 +1404,7 @@ XNode* Profile::SaveCategoryScoresCreateNode() const FOREACH_RankingCategory( rc ) { // skip steps types/categories that have never been played - if( pProfile->GetCategoryHighScoreList(st,rc).iNumTimesPlayed == 0 ) + if( pProfile->GetCategoryHighScoreList(st,rc).GetNumTimesPlayed() == 0 ) continue; XNode* pRankingCategoryNode = pStepsTypeNode->AppendChild( "RankingCategory" ); diff --git a/stepmania/src/Profile.h b/stepmania/src/Profile.h index b5694e3019..82d217ca8e 100644 --- a/stepmania/src/Profile.h +++ b/stepmania/src/Profile.h @@ -77,8 +77,6 @@ public: float GetCoursesPercentComplete( StepsType st, CourseDifficulty cd ) const; float GetSongsAndCoursesPercentCompleteAllDifficulties( StepsType st ) const; static CString GetProfileDisplayNameFromDir( CString sDir ); - int GetSongNumTimesPlayed( const Song* pSong ) const; - int GetSongNumTimesPlayed( const SongID& songID ) const; bool GetDefaultModifiers( const Game* pGameType, CString &sModifiersOut ) const; void SetDefaultModifiers( const Game* pGameType, const CString &sModifiers ); bool IsCodeUnlocked( int iCode ) const; @@ -157,7 +155,9 @@ public: int GetStepsNumTimesPlayed( const Song* pSong, const Steps* pSteps ) const; void IncrementStepsPlayCount( const Song* pSong, const Steps* pSteps ); void GetGrades( const Song* pSong, StepsType st, int iCounts[NUM_GRADES] ) const; - + int GetSongNumTimesPlayed( const Song* pSong ) const; + int GetSongNumTimesPlayed( const SongID& songID ) const; + DateTime GetSongLastPlayedDateTime( const Song* pSong ) const; // // Course high scores @@ -179,6 +179,7 @@ public: const HighScoreList& GetCourseHighScoreList( const Course* pCourse, const Trail* pTrail ) const; int GetCourseNumTimesPlayed( const Course* pCourse ) const; int GetCourseNumTimesPlayed( const CourseID& courseID ) const; + DateTime GetCourseLastPlayedDateTime( const Course* pCourse ) const; void IncrementCoursePlayCount( const Course* pCourse, const Trail* pTrail ); diff --git a/stepmania/src/ScreenRanking.cpp b/stepmania/src/ScreenRanking.cpp index 243809543a..d68c36ff24 100644 --- a/stepmania/src/ScreenRanking.cpp +++ b/stepmania/src/ScreenRanking.cpp @@ -48,7 +48,7 @@ AutoScreenMessage( SM_ShowNextPage ) AutoScreenMessage( SM_HidePage ) -static void GetAllSongsToShow( vector &vpOut ) +static void GetAllSongsToShow( vector &vpOut, bool bShowOnlyMostRecentScores, int iNumMostRecentScoresToShow ) { vpOut.clear(); FOREACH_CONST( Song*, SONGMAN->GetAllSongs(), s ) @@ -59,12 +59,18 @@ static void GetAllSongsToShow( vector &vpOut ) continue; // skip vpOut.push_back( *s ); } + + if( bShowOnlyMostRecentScores ) + { + SongUtil::SortByMostRecentlyPlayedForMachine( vpOut ); + if( vpOut.size() > iNumMostRecentScoresToShow ) + vpOut.erase( vpOut.begin()+iNumMostRecentScoresToShow, vpOut.end() ); + } } -static void GetAllCoursesToShow( vector &vpOut ) +static void GetAllCoursesToShow( vector &vpOut, bool bShowOnlyMostRecentScores, int iNumMostRecentScoresToShow ) { vpOut.clear(); - vector vpCourses; SONGMAN->GetAllCourses( vpCourses, false ); @@ -76,6 +82,12 @@ static void GetAllCoursesToShow( vector &vpOut ) continue; // skip vpOut.push_back( *c ); } + if( bShowOnlyMostRecentScores ) + { + CourseUtil::SortByMostRecentlyPlayedForMachine( vpOut ); + if( vpOut.size() > iNumMostRecentScoresToShow ) + vpOut.erase( vpOut.begin()+iNumMostRecentScoresToShow, vpOut.end() ); + } } @@ -87,8 +99,10 @@ ScreenRanking::ScreenRanking( CString sClassName ) : ScreenAttract( sClassName ) DIFFICULTIES_TO_SHOW (m_sName,"DifficultiesToShow"), SHOW_CATEGORIES (m_sName,"ShowCategories"), - SHOW_ALL_STEPS_SCORES (m_sName,"ShowAllStepsScores"), - SHOW_ALL_COURSE_SCORES (m_sName,"ShowAllCourseScores"), + SHOW_STEPS_SCORES (m_sName,"ShowStepsScores"), + SHOW_COURSE_SCORES (m_sName,"ShowCourseScores"), + SHOW_ONLY_MOST_RECENT_SCORES (m_sName,"ShowOnlyMostRecentScores"), + NUM_MOST_RECENT_SCORES_TO_SHOW (m_sName,"NumMostRecentScoresToShow"), SECONDS_PER_PAGE (m_sName,"SecondsPerPage"), PAGE_FADE_SECONDS (m_sName,"PageFadeSeconds"), NO_SCORE_NAME (m_sName,"NoScoreName"), @@ -208,7 +222,7 @@ void ScreenRanking::Init() pts.type = PAGE_TYPE_CATEGORY; pts.colorIndex = i; pts.category = (RankingCategory)c; - pts.nt = STEPS_TYPES_TO_SHOW.GetValue()[i]; + pts.st = STEPS_TYPES_TO_SHOW.GetValue()[i]; m_vPagesToShow.push_back( pts ); } } @@ -224,12 +238,12 @@ void ScreenRanking::Init() PageToShow pts; pts.type = PAGE_TYPE_TRAIL; pts.colorIndex = i; - pts.nt = STEPS_TYPES_TO_SHOW.GetValue()[i]; + pts.st = STEPS_TYPES_TO_SHOW.GetValue()[i]; pts.pCourse = SONGMAN->GetCourseFromPath( asCoursePaths[c] ); if( pts.pCourse == NULL ) continue; - pts.pTrail = pts.pCourse->GetTrail( pts.nt ); + pts.pTrail = pts.pCourse->GetTrail( pts.st ); if( pts.pTrail == NULL ) continue; @@ -263,14 +277,14 @@ void ScreenRanking::Init() } - ASSERT( !SHOW_ALL_STEPS_SCORES || !SHOW_ALL_COURSE_SCORES ); // Can't do both on the same screen + ASSERT( !SHOW_STEPS_SCORES || !SHOW_COURSE_SCORES ); // Can't do both on the same screen - if( SHOW_ALL_STEPS_SCORES ) + if( SHOW_STEPS_SCORES ) { m_vScoreRowItem.clear(); vector vpSongs; - GetAllSongsToShow( vpSongs ); + GetAllSongsToShow( vpSongs, SHOW_ONLY_MOST_RECENT_SCORES, NUM_MOST_RECENT_SCORES_TO_SHOW ); m_vScoreRowItem.resize( vpSongs.size() ); FOREACH_CONST( Song*, vpSongs, s ) { @@ -309,16 +323,16 @@ void ScreenRanking::Init() PageToShow pts; pts.type = PAGE_TYPE_ALL_STEPS; pts.colorIndex = i; - pts.nt = STEPS_TYPES_TO_SHOW.GetValue()[i]; + pts.st = STEPS_TYPES_TO_SHOW.GetValue()[i]; m_vPagesToShow.push_back( pts ); } } } - if( SHOW_ALL_COURSE_SCORES ) + if( SHOW_COURSE_SCORES ) { vector vpCourses; - GetAllCoursesToShow( vpCourses ); + GetAllCoursesToShow( vpCourses, SHOW_ONLY_MOST_RECENT_SCORES, NUM_MOST_RECENT_SCORES_TO_SHOW ); LOG->Trace("rankings: adding %u courses", vpCourses.size()); m_vScoreRowItem.resize( vpCourses.size() ); FOREACH_CONST( Course*, vpCourses, c ) @@ -360,7 +374,7 @@ void ScreenRanking::Init() PageToShow pts; pts.type = PAGE_TYPE_ALL_COURSES; pts.colorIndex = i; - pts.nt = STEPS_TYPES_TO_SHOW.GetValue()[i]; + pts.st = STEPS_TYPES_TO_SHOW.GetValue()[i]; m_vPagesToShow.push_back( pts ); } } @@ -721,11 +735,11 @@ float ScreenRanking::SetPage( PageToShow pts ) case PAGE_TYPE_CATEGORY: { m_textCategory.SetText( ssprintf("Type %c", 'A'+pts.category) ); - m_textStepsType.SetText( GameManager::StepsTypeToThemedString(pts.nt) ); + m_textStepsType.SetText( GameManager::StepsTypeToThemedString(pts.st) ); for( int l=0; lGetMachineProfile()->GetCategoryHighScoreList(pts.nt,pts.category); + HighScoreList& hsl = PROFILEMAN->GetMachineProfile()->GetCategoryHighScoreList(pts.st,pts.category); HighScore hs; bool bRecentHighScore = false; if( l < (int)hsl.vHighScores.size() ) @@ -761,7 +775,7 @@ float ScreenRanking::SetPage( PageToShow pts ) { m_textCourseTitle.SetText( pts.pCourse->GetFullDisplayTitle() ); m_Banner.LoadFromCourse( pts.pCourse ); - m_textStepsType.SetText( GameManager::StepsTypeToThemedString(pts.nt) ); + m_textStepsType.SetText( GameManager::StepsTypeToThemedString(pts.st) ); const HighScoreList &hsl = PROFILEMAN->GetMachineProfile()->GetCourseHighScoreList( pts.pCourse, pts.pTrail ); for( int l=0; lGetStepsByDifficulty( pts.nt, *iter, false ); + const Steps* pSteps = pSong->GetStepsByDifficulty( pts.st, *iter, false ); BitmapText* pTextStepsScore = &item.m_textScore[*iter]; if( pSteps == NULL ) @@ -853,7 +867,7 @@ float ScreenRanking::SetPage( PageToShow pts ) return m_ListScoreRowItems.GetSecondsForCompleteScrollThrough(); case PAGE_TYPE_ALL_COURSES: { - m_textStepsType.SetText( GameManager::StepsTypeToThemedString(pts.nt) ); + m_textStepsType.SetText( GameManager::StepsTypeToThemedString(pts.st) ); for( unsigned c=0; cGetTrail( pts.nt, cd ); + Trail *pTrail = pCourse->GetTrail( pts.st, cd ); pTextStepsScore->SetHidden( pTrail==NULL ); if( pTrail == NULL ) continue; diff --git a/stepmania/src/ScreenRanking.h b/stepmania/src/ScreenRanking.h index d23108f45f..53305b754b 100644 --- a/stepmania/src/ScreenRanking.h +++ b/stepmania/src/ScreenRanking.h @@ -58,7 +58,7 @@ protected: PageType type; int colorIndex; - StepsType nt; + StepsType st; RankingCategory category; Course* pCourse; Trail* pTrail; @@ -105,8 +105,10 @@ protected: ThemeMetricDifficultiesToShow DIFFICULTIES_TO_SHOW; ThemeMetric SHOW_CATEGORIES; - ThemeMetric SHOW_ALL_STEPS_SCORES; - ThemeMetric SHOW_ALL_COURSE_SCORES; + ThemeMetric SHOW_STEPS_SCORES; + ThemeMetric SHOW_COURSE_SCORES; + ThemeMetric SHOW_ONLY_MOST_RECENT_SCORES; + ThemeMetric NUM_MOST_RECENT_SCORES_TO_SHOW; ThemeMetric SECONDS_PER_PAGE; ThemeMetric PAGE_FADE_SECONDS; ThemeMetric NO_SCORE_NAME; diff --git a/stepmania/src/SongManager.cpp b/stepmania/src/SongManager.cpp index 5241b9af64..cc6f7c0b92 100644 --- a/stepmania/src/SongManager.cpp +++ b/stepmania/src/SongManager.cpp @@ -44,7 +44,7 @@ static const ThemeMetric NUM_GROUP_COLORS ("SongManager","NumGroupColors") #define GROUP_COLOR( i ) THEME->GetMetricC("SongManager",ssprintf("GroupColor%d",i+1)) static const ThemeMetric BEGINNER_COLOR ("SongManager","BeginnerColor"); static const ThemeMetric EASY_COLOR ("SongManager","EasyColor"); -static const ThemeMetric MEDIUM_COLOR ("SongManager","MediumColor"); +static const ThemeMetric MEDIUM_COLOR ("SongManager","MediumColor"); static const ThemeMetric HARD_COLOR ("SongManager","HardColor"); static const ThemeMetric CHALLENGE_COLOR ("SongManager","ChallengeColor"); static const ThemeMetric EDIT_COLOR ("SongManager","EditColor"); diff --git a/stepmania/src/SongUtil.cpp b/stepmania/src/SongUtil.cpp index 9f2e2dcff8..da391f5485 100644 --- a/stepmania/src/SongUtil.cpp +++ b/stepmania/src/SongUtil.cpp @@ -9,6 +9,7 @@ #include "SongManager.h" #include "XmlFile.h" #include "PrefsManager.h" +#include "Foreach.h" ///////////////////////////////////// @@ -69,9 +70,9 @@ bool CompareSongPointersByTitle(const Song *pSong1, const Song *pSong2) return pSong1->GetSongFilePath().CompareNoCase(pSong2->GetSongFilePath()) < 0; } -void SongUtil::SortSongPointerArrayByTitle( vector &arraySongPointers ) +void SongUtil::SortSongPointerArrayByTitle( vector &vpSongsInOut ) { - sort( arraySongPointers.begin(), arraySongPointers.end(), CompareSongPointersByTitle ); + sort( vpSongsInOut.begin(), vpSongsInOut.end(), CompareSongPointersByTitle ); } bool CompareSongPointersByBPM(const Song *pSong1, const Song *pSong2) @@ -88,9 +89,9 @@ bool CompareSongPointersByBPM(const Song *pSong1, const Song *pSong2) return CompareCStringsAsc( pSong1->GetSongFilePath(), pSong2->GetSongFilePath() ); } -void SongUtil::SortSongPointerArrayByBPM( vector &arraySongPointers ) +void SongUtil::SortSongPointerArrayByBPM( vector &vpSongsInOut ) { - sort( arraySongPointers.begin(), arraySongPointers.end(), CompareSongPointersByBPM ); + sort( vpSongsInOut.begin(), vpSongsInOut.end(), CompareSongPointersByBPM ); } void AppendOctal( int n, int digits, CString &out ) @@ -106,17 +107,17 @@ void AppendOctal( int n, int digits, CString &out ) bool CompDescending( const pair &a, const pair &b ) { return a.second > b.second; } -void SongUtil::SortSongPointerArrayByGrade( vector &arraySongPointers ) +void SongUtil::SortSongPointerArrayByGrade( vector &vpSongsInOut ) { /* Optimize by pre-writing a string to compare, since doing GetNumNotesWithGrade * inside the sort is too slow. */ typedef pair< Song *, CString > val; vector vals; - vals.reserve( arraySongPointers.size() ); + vals.reserve( vpSongsInOut.size() ); - for( unsigned i = 0; i < arraySongPointers.size(); ++i ) + for( unsigned i = 0; i < vpSongsInOut.size(); ++i ) { - Song *pSong = arraySongPointers[i]; + Song *pSong = vpSongsInOut[i]; int iCounts[NUM_GRADES]; PROFILEMAN->GetMachineProfile()->GetGrades( pSong, GAMESTATE->GetCurrentStyle()->m_StepsType, iCounts ); @@ -130,25 +131,25 @@ void SongUtil::SortSongPointerArrayByGrade( vector &arraySongPointers ) sort( vals.begin(), vals.end(), CompDescending ); - for( unsigned i = 0; i < arraySongPointers.size(); ++i ) - arraySongPointers[i] = vals[i].first; + for( unsigned i = 0; i < vpSongsInOut.size(); ++i ) + vpSongsInOut[i] = vals[i].first; } -void SongUtil::SortSongPointerArrayByArtist( vector &arraySongPointers ) +void SongUtil::SortSongPointerArrayByArtist( vector &vpSongsInOut ) { - for( unsigned i = 0; i < arraySongPointers.size(); ++i ) - song_sort_val[arraySongPointers[i]] = MakeSortString( arraySongPointers[i]->GetTranslitArtist() ); - stable_sort( arraySongPointers.begin(), arraySongPointers.end(), CompareSongPointersBySortValueAscending ); + for( unsigned i = 0; i < vpSongsInOut.size(); ++i ) + song_sort_val[vpSongsInOut[i]] = MakeSortString( vpSongsInOut[i]->GetTranslitArtist() ); + stable_sort( vpSongsInOut.begin(), vpSongsInOut.end(), CompareSongPointersBySortValueAscending ); } /* This is for internal use, not display; sorting by Unicode codepoints isn't very * interesting for display. */ -void SongUtil::SortSongPointerArrayByDisplayArtist( vector &arraySongPointers ) +void SongUtil::SortSongPointerArrayByDisplayArtist( vector &vpSongsInOut ) { - for( unsigned i = 0; i < arraySongPointers.size(); ++i ) - song_sort_val[arraySongPointers[i]] = MakeSortString( arraySongPointers[i]->GetDisplayArtist() ); - stable_sort( arraySongPointers.begin(), arraySongPointers.end(), CompareSongPointersBySortValueAscending ); + for( unsigned i = 0; i < vpSongsInOut.size(); ++i ) + song_sort_val[vpSongsInOut[i]] = MakeSortString( vpSongsInOut[i]->GetDisplayArtist() ); + stable_sort( vpSongsInOut.begin(), vpSongsInOut.end(), CompareSongPointersBySortValueAscending ); } static int CompareSongPointersByGenre(const Song *pSong1, const Song *pSong2) @@ -156,9 +157,9 @@ static int CompareSongPointersByGenre(const Song *pSong1, const Song *pSong2) return pSong1->m_sGenre < pSong2->m_sGenre; } -void SongUtil::SortSongPointerArrayByGenre( vector &arraySongPointers ) +void SongUtil::SortSongPointerArrayByGenre( vector &vpSongsInOut ) { - stable_sort( arraySongPointers.begin(), arraySongPointers.end(), CompareSongPointersByGenre ); + stable_sort( vpSongsInOut.begin(), vpSongsInOut.end(), CompareSongPointersByGenre ); } static int CompareSongPointersByGroup(const Song *pSong1, const Song *pSong2) @@ -166,10 +167,10 @@ static int CompareSongPointersByGroup(const Song *pSong1, const Song *pSong2) return pSong1->m_sGroupName < pSong2->m_sGroupName; } -void SongUtil::SortSongPointerArrayByGroupAndDifficulty( vector &arraySongPointers ) +void SongUtil::SortSongPointerArrayByGroupAndDifficulty( vector &vpSongsInOut ) { - SortSongPointerArrayByMeter( arraySongPointers, DIFFICULTY_EASY ); - stable_sort( arraySongPointers.begin(), arraySongPointers.end(), CompareSongPointersByGroup ); + SortSongPointerArrayByMeter( vpSongsInOut, DIFFICULTY_EASY ); + stable_sort( vpSongsInOut.begin(), vpSongsInOut.end(), CompareSongPointersByGroup ); } int CompareSongPointersByGroupAndTitle(const Song *pSong1, const Song *pSong2) @@ -186,25 +187,25 @@ int CompareSongPointersByGroupAndTitle(const Song *pSong1, const Song *pSong2) return CompareSongPointersByTitle( pSong1, pSong2 ); } -void SongUtil::SortSongPointerArrayByGroupAndTitle( vector &arraySongPointers ) +void SongUtil::SortSongPointerArrayByGroupAndTitle( vector &vpSongsInOut ) { - sort( arraySongPointers.begin(), arraySongPointers.end(), CompareSongPointersByGroupAndTitle ); + sort( vpSongsInOut.begin(), vpSongsInOut.end(), CompareSongPointersByGroupAndTitle ); } -void SongUtil::SortSongPointerArrayByNumPlays( vector &arraySongPointers, ProfileSlot slot, bool bDescending ) +void SongUtil::SortSongPointerArrayByNumPlays( vector &vpSongsInOut, ProfileSlot slot, bool bDescending ) { Profile* pProfile = PROFILEMAN->GetProfile(slot); if( pProfile == NULL ) return; // nothing to do since we don't have data - SortSongPointerArrayByNumPlays( arraySongPointers, pProfile, bDescending ); + SortSongPointerArrayByNumPlays( vpSongsInOut, pProfile, bDescending ); } -void SongUtil::SortSongPointerArrayByNumPlays( vector &arraySongPointers, const Profile* pProfile, bool bDescending ) +void SongUtil::SortSongPointerArrayByNumPlays( vector &vpSongsInOut, const Profile* pProfile, bool bDescending ) { ASSERT( pProfile ); - for(unsigned i = 0; i < arraySongPointers.size(); ++i) - song_sort_val[arraySongPointers[i]] = ssprintf("%9i", pProfile->GetSongNumTimesPlayed(arraySongPointers[i])); - stable_sort( arraySongPointers.begin(), arraySongPointers.end(), bDescending ? CompareSongPointersBySortValueDescending : CompareSongPointersBySortValueAscending ); + for(unsigned i = 0; i < vpSongsInOut.size(); ++i) + song_sort_val[vpSongsInOut[i]] = ssprintf("%9i", pProfile->GetSongNumTimesPlayed(vpSongsInOut[i])); + stable_sort( vpSongsInOut.begin(), vpSongsInOut.end(), bDescending ? CompareSongPointersBySortValueDescending : CompareSongPointersBySortValueAscending ); song_sort_val.clear(); } @@ -309,35 +310,35 @@ CString SongUtil::GetSectionNameFromSongAndSort( const Song* pSong, SortOrder so } } -void SongUtil::SortSongPointerArrayBySectionName( vector &arraySongPointers, SortOrder so ) +void SongUtil::SortSongPointerArrayBySectionName( vector &vpSongsInOut, SortOrder so ) { - for(unsigned i = 0; i < arraySongPointers.size(); ++i) + for(unsigned i = 0; i < vpSongsInOut.size(); ++i) { - CString val = GetSectionNameFromSongAndSort( arraySongPointers[i], so ); + CString val = GetSectionNameFromSongAndSort( vpSongsInOut[i], so ); /* Make sure NUM comes first and OTHER comes last. */ if( val == "NUM" ) val = "0"; else if( val == "OTHER" ) val = "2"; else val = "1" + MakeSortString(val); - song_sort_val[arraySongPointers[i]] = val; + song_sort_val[vpSongsInOut[i]] = val; } - stable_sort( arraySongPointers.begin(), arraySongPointers.end(), CompareSongPointersBySortValueAscending ); + stable_sort( vpSongsInOut.begin(), vpSongsInOut.end(), CompareSongPointersBySortValueAscending ); song_sort_val.clear(); } -void SongUtil::SortSongPointerArrayByMeter( vector &arraySongPointers, Difficulty dc ) +void SongUtil::SortSongPointerArrayByMeter( vector &vpSongsInOut, Difficulty dc ) { song_sort_val.clear(); - for(unsigned i = 0; i < arraySongPointers.size(); ++i) + for(unsigned i = 0; i < vpSongsInOut.size(); ++i) { - const Steps* pSteps = arraySongPointers[i]->GetClosestNotes( GAMESTATE->GetCurrentStyle()->m_StepsType, dc ); - CString &s = song_sort_val[arraySongPointers[i]]; + const Steps* pSteps = vpSongsInOut[i]->GetClosestNotes( GAMESTATE->GetCurrentStyle()->m_StepsType, dc ); + CString &s = song_sort_val[vpSongsInOut[i]]; s = ssprintf("%03d", pSteps ? pSteps->GetMeter() : 0); /* Hack: always put tutorial songs first. */ - s += ssprintf( "%c", arraySongPointers[i]->IsTutorial()? '0':'1' ); + s += ssprintf( "%c", vpSongsInOut[i]->IsTutorial()? '0':'1' ); /* * pSteps may not be exactly the difficulty we want; for example, we may @@ -354,7 +355,22 @@ void SongUtil::SortSongPointerArrayByMeter( vector &arraySongPointers, Di if( PREFSMAN->m_bSubSortByNumSteps ) s += ssprintf("%06.0f",pSteps ? pSteps->GetRadarValues()[RADAR_NUM_TAPS_AND_HOLDS] : 0); } - stable_sort( arraySongPointers.begin(), arraySongPointers.end(), CompareSongPointersBySortValueAscending ); + stable_sort( vpSongsInOut.begin(), vpSongsInOut.end(), CompareSongPointersBySortValueAscending ); +} + +void SongUtil::SortByMostRecentlyPlayedForMachine( vector &vpSongsInOut ) +{ + Profile *pProfile = PROFILEMAN->GetMachineProfile(); + + FOREACH_CONST( Song*, vpSongsInOut, s ) + { + int iNumTimesPlayed = pProfile->GetSongNumTimesPlayed( *s ); + CString val = iNumTimesPlayed ? pProfile->GetSongLastPlayedDateTime(*s).GetString() : "9999999999999"; + song_sort_val[*s] = val; + } + + stable_sort( vpSongsInOut.begin(), vpSongsInOut.end(), CompareSongPointersBySortValueAscending ); + song_sort_val.clear(); } ////////////////////////////////// diff --git a/stepmania/src/SongUtil.h b/stepmania/src/SongUtil.h index b6b96f43e4..ee07521041 100644 --- a/stepmania/src/SongUtil.h +++ b/stepmania/src/SongUtil.h @@ -13,19 +13,20 @@ struct XNode; namespace SongUtil { CString MakeSortString( CString s ); - void SortSongPointerArrayByTitle( vector &arraySongPointers ); - void SortSongPointerArrayByBPM( vector &arraySongPointers ); - void SortSongPointerArrayByGrade( vector &arraySongPointers ); - void SortSongPointerArrayByArtist( vector &arraySongPointers ); - void SortSongPointerArrayByDisplayArtist( vector &arraySongPointers ); - void SortSongPointerArrayByGenre( vector &arraySongPointers ); - void SortSongPointerArrayByGroupAndDifficulty( vector &arraySongPointers ); - void SortSongPointerArrayByGroupAndTitle( vector &arraySongPointers ); - void SortSongPointerArrayByNumPlays( vector &arraySongPointers, ProfileSlot slot, bool bDescending ); - void SortSongPointerArrayByNumPlays( vector &arraySongPointers, const Profile* pProfile, bool bDescending ); - void SortSongPointerArrayByMeter( vector &arraySongPointers, Difficulty dc ); + void SortSongPointerArrayByTitle( vector &vpSongsInOut ); + void SortSongPointerArrayByBPM( vector &vpSongsInOut ); + void SortSongPointerArrayByGrade( vector &vpSongsInOut ); + void SortSongPointerArrayByArtist( vector &vpSongsInOut ); + void SortSongPointerArrayByDisplayArtist( vector &vpSongsInOut ); + void SortSongPointerArrayByGenre( vector &vpSongsInOut ); + void SortSongPointerArrayByGroupAndDifficulty( vector &vpSongsInOut ); + void SortSongPointerArrayByGroupAndTitle( vector &vpSongsInOut ); + void SortSongPointerArrayByNumPlays( vector &vpSongsInOut, ProfileSlot slot, bool bDescending ); + void SortSongPointerArrayByNumPlays( vector &vpSongsInOut, const Profile* pProfile, bool bDescending ); + void SortSongPointerArrayByMeter( vector &vpSongsInOut, Difficulty dc ); CString GetSectionNameFromSongAndSort( const Song* pSong, SortOrder so ); - void SortSongPointerArrayBySectionName( vector &arraySongPointers, SortOrder so ); + void SortSongPointerArrayBySectionName( vector &vpSongsInOut, SortOrder so ); + void SortByMostRecentlyPlayedForMachine( vector &vpSongsInOut ); } class SongID diff --git a/stepmania/src/StepsUtil.h b/stepmania/src/StepsUtil.h index 07bd8bc60b..29f6af872b 100644 --- a/stepmania/src/StepsUtil.h +++ b/stepmania/src/StepsUtil.h @@ -14,14 +14,14 @@ namespace StepsUtil bool CompareNotesPointersByRadarValues(const Steps* pSteps1, const Steps* pSteps2); bool CompareNotesPointersByMeter(const Steps *pSteps1, const Steps* pSteps2); bool CompareNotesPointersByDifficulty(const Steps *pSteps1, const Steps *pSteps2); - void SortNotesArrayByDifficulty( vector &arrayNotess ); + void SortNotesArrayByDifficulty( vector &vpStepsInOut ); bool CompareStepsPointersByTypeAndDifficulty(const Steps *pStep1, const Steps *pStep2); - void SortStepsByTypeAndDifficulty( vector &arraySongPointers ); - void SortStepsPointerArrayByNumPlays( vector &vStepsPointers, ProfileSlot slot, bool bDescending ); - void SortStepsPointerArrayByNumPlays( vector &vStepsPointers, const Profile* pProfile, bool bDescending ); + void SortStepsByTypeAndDifficulty( vector &vpStepsInOut ); + void SortStepsPointerArrayByNumPlays( vector &vpStepsInOut, ProfileSlot slot, bool bDescending ); + void SortStepsPointerArrayByNumPlays( vector &vpStepsInOut, const Profile* pProfile, bool bDescending ); bool CompareStepsPointersByDescription(const Steps *pStep1, const Steps *pStep2); - void SortStepsByDescription( vector &vStepsPointers ); - void RemoveLockedSteps( const Song *pSong, vector &arrayNotess ); + void SortStepsByDescription( vector &vpStepsInOut ); + void RemoveLockedSteps( const Song *pSong, vector &vpStepsInOut ); }; class StepsID