From 6db1199db57d77baba92cf67afc8d006df1892c0 Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Tue, 13 May 2014 13:34:38 -0600 Subject: [PATCH] Added PROFILE:GetHighScoreListIfExists for limiting memory footprint on searches. Added PROFILE:GetAllUsedHighScoreNames to provide a non-brute force way for obtaining a list of names. Added HighScoreList:GetHighestScoreOfName so the C++ side could do the iteration. Added HighScoreList:GetRankOfName for the same reason. --- Docs/Luadoc/Lua.xml | 4 ++ Docs/Luadoc/LuaDocumentation.xml | 13 +++++ src/HighScore.cpp | 35 +++++++++++++ src/Profile.cpp | 84 ++++++++++++++++++++++++++++++++ src/Profile.h | 1 + 5 files changed, 137 insertions(+) diff --git a/Docs/Luadoc/Lua.xml b/Docs/Luadoc/Lua.xml index 82734843a4..3fade2e767 100644 --- a/Docs/Luadoc/Lua.xml +++ b/Docs/Luadoc/Lua.xml @@ -872,6 +872,8 @@ + + @@ -1133,6 +1135,7 @@ + @@ -1145,6 +1148,7 @@ + diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/Luadoc/LuaDocumentation.xml index b45c75352a..b67ea74b63 100644 --- a/Docs/Luadoc/LuaDocumentation.xml +++ b/Docs/Luadoc/LuaDocumentation.xml @@ -2592,6 +2592,12 @@ save yourself some time, copy this for undocumented things: Returns a table of the high scores. + + Returns the highest score for name in the list. Returns nil if there is no score for name in the list. + + + Returns the rank of the highest score for name in the list. Returns 0 if there is no score for name in the list. (returns 1 if name has the top score, 2 if name has the second place score, and so on) + @@ -3208,6 +3214,9 @@ save yourself some time, copy this for undocumented things: + + Returns a table of all high score names that have been used on this profile. + Returns the number of calories burned during the current day. @@ -3247,6 +3256,10 @@ save yourself some time, copy this for undocumented things: Gets the profile's HighScoreList for a specified Song and Steps. (Alternate arguments for Courses: Course c, Trail t) + + Gets the profile's HighScoreList for a specified Song and Steps. (Alternate arguments for Courses: Course c, Trail t)
+ If the profile does not have a HighScoreList for the Song and Steps, returns nil. Use this to avoid increasing the memory footprint of the profile when checking the score lists for every song and steps. +
Returns the last played Course for this profile. diff --git a/src/HighScore.cpp b/src/HighScore.cpp index 66644ecb06..3c5f682d8b 100644 --- a/src/HighScore.cpp +++ b/src/HighScore.cpp @@ -500,9 +500,44 @@ public: return 1; } + static int GetHighestScoreOfName( T* p, lua_State *L ) + { + RString name= SArg(1); + for(size_t i= 0; i < p->vHighScores.size(); ++i) + { + if(name == p->vHighScores[i].GetName()) + { + p->vHighScores[i].PushSelf(L); + return 1; + } + } + lua_pushnil(L); + return 1; + } + + static int GetRankOfName( T* p, lua_State *L ) + { + RString name= SArg(1); + size_t rank= 0; + for(size_t i= 0; i < p->vHighScores.size(); ++i) + { + if(name == p->vHighScores[i].GetName()) + { + // Indices from Lua are one-indexed. +1 to adjust. + rank= i+1; + break; + } + } + // The themer is expected to check for validity before using. + lua_pushnumber(L, rank); + return 1; + } + LunaHighScoreList() { ADD_METHOD( GetHighScores ); + ADD_METHOD( GetHighestScoreOfName ); + ADD_METHOD( GetRankOfName ); } }; diff --git a/src/Profile.cpp b/src/Profile.cpp index 25ca4123b7..0197deb233 100644 --- a/src/Profile.cpp +++ b/src/Profile.cpp @@ -744,6 +744,33 @@ void Profile::IncrementCoursePlayCount( const Course* pCourse, const Trail* pTra GetCourseHighScoreList(pCourse,pTrail).IncrementPlayCount( now ); } +void Profile::GetAllUsedHighScoreNames(std::set& names) +{ +#define GET_NAMES_FROM_MAP(main_member, main_key_type, main_value_type, sub_member, sub_key_type, sub_value_type) \ + for(std::map::iterator main_entry= \ + main_member.begin(); main_entry != main_member.end(); ++main_entry) \ + { \ + for(std::map::iterator sub_entry= \ + main_entry->second.sub_member.begin(); \ + sub_entry != main_entry->second.sub_member.end(); ++sub_entry) \ + { \ + for(vector::iterator high_score= \ + sub_entry->second.hsl.vHighScores.begin(); \ + high_score != sub_entry->second.hsl.vHighScores.end(); \ + ++high_score) \ + { \ + if(high_score->GetName().size() > 0) \ + { \ + names.insert(high_score->GetName()); \ + } \ + } \ + } \ + } + GET_NAMES_FROM_MAP(m_SongHighScores, SongID, HighScoresForASong, m_StepsHighScores, StepsID, HighScoresForASteps); + GET_NAMES_FROM_MAP(m_CourseHighScores, CourseID, HighScoresForACourse, m_TrailHighScores, TrailID, HighScoresForATrail); +#undef GET_NAMES_FROM_MAP +} + // Category high scores void Profile::AddCategoryHighScore( StepsType st, RankingCategory rc, HighScore hs, int &iIndexOut ) { @@ -2024,6 +2051,61 @@ public: return 1; } + static int GetHighScoreListIfExists( T* p, lua_State *L ) + { +#define GET_IF_EXISTS(arga_type, argb_type) \ + const arga_type *parga = Luna::check(L, 1); \ + const argb_type *pargb = Luna::check(L, 2); \ + arga_type##ID arga_id; \ + arga_id.From##arga_type(parga); \ + argb_type##ID argb_id; \ + argb_id.From##argb_type(pargb); \ + std::map::iterator \ + main_scores= p->m_##arga_type##HighScores.find(arga_id); \ + if(main_scores == p->m_##arga_type##HighScores.end()) \ + { \ + lua_pushnil(L); \ + return 1; \ + } \ + std::map::iterator \ + sub_scores= main_scores->second.m_##argb_type##HighScores.find(argb_id); \ + if(sub_scores == main_scores->second.m_##argb_type##HighScores.end()) \ + { \ + lua_pushnil(L); \ + return 1; \ + } \ + sub_scores->second.hsl.PushSelf(L); \ + return 1; + + if( LuaBinding::CheckLuaObjectType(L, 1, "Song") ) + { + GET_IF_EXISTS(Song, Steps); + } + else if( LuaBinding::CheckLuaObjectType(L, 1, "Course") ) + { + GET_IF_EXISTS(Course, Trail); + } + luaL_typerror( L, 1, "Song or Course" ); + return 0; +#undef GET_IF_EXISTS + } + + static int GetAllUsedHighScoreNames( T* p, lua_State *L ) + { + std::set names; + p->GetAllUsedHighScoreNames(names); + lua_createtable(L, names.size(), 0); + int next_name_index= 1; + for(std::set::iterator name= names.begin(); name != names.end(); + ++name) + { + lua_pushstring(L, name->c_str()); + lua_rawseti(L, -2, next_name_index); + ++next_name_index; + } + return 1; + } + static int GetCharacter( T* p, lua_State *L ) { p->GetCharacter()->PushSelf(L); return 1; } static int SetCharacter( T* p, lua_State *L ) { p->SetCharacter(SArg(1)); return 0; } static int GetWeightPounds( T* p, lua_State *L ) { lua_pushnumber(L, p->m_iWeightPounds ); return 1; } @@ -2117,6 +2199,8 @@ public: { ADD_METHOD( GetDisplayName ); ADD_METHOD( GetLastUsedHighScoreName ); + ADD_METHOD( GetAllUsedHighScoreNames ); + ADD_METHOD( GetHighScoreListIfExists ); ADD_METHOD( GetHighScoreList ); ADD_METHOD( GetCategoryHighScoreList ); ADD_METHOD( GetCharacter ); diff --git a/src/Profile.h b/src/Profile.h index 383d3d4c27..ca19b69415 100644 --- a/src/Profile.h +++ b/src/Profile.h @@ -262,6 +262,7 @@ public: DateTime GetCourseLastPlayedDateTime( const Course* pCourse ) const; void IncrementCoursePlayCount( const Course* pCourse, const Trail* pTrail ); + void GetAllUsedHighScoreNames(std::set& names); // Category high scores HighScoreList m_CategoryHighScores[NUM_StepsType][NUM_RankingCategory];