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.

This commit is contained in:
Kyzentun
2014-05-13 13:34:38 -06:00
parent 80c741f175
commit 6db1199db5
5 changed files with 137 additions and 0 deletions
+4
View File
@@ -872,6 +872,8 @@
</Class>
<Class name='HighScoreList'>
<Function name='GetHighScores'/>
<Function name='GetHighestScoreOfName'/>
<Function name='GetRankOfName'/>
</Class>
<Class base='ActorFrame' name='HoldJudgment'>
<Function name='LoadFromMultiPlayer'/>
@@ -1133,6 +1135,7 @@
<Function name='SetPreferenceToDefault'/>
</Class>
<Class name='Profile'>
<Function name='GetAllUsedHighScoreNames'/>
<Function name='GetCaloriesBurnedToday'/>
<Function name='GetCharacter'/>
<Function name='GetCoursesActual'/>
@@ -1145,6 +1148,7 @@
<Function name='GetGoalSeconds'/>
<Function name='GetGoalType'/>
<Function name='GetHighScoreList'/>
<Function name='GetHighScoreListIfExists'/>
<Function name='GetLastPlayedCourse'/>
<Function name='GetLastPlayedSong'/>
<Function name='GetLastUsedHighScoreName'/>
+13
View File
@@ -2592,6 +2592,12 @@ save yourself some time, copy this for undocumented things:
<Function name='GetHighScores' return='{HighScore}' arguments=''>
Returns a table of the high scores.
</Function>
<Function name='GetHighestScoreOfName' return='HighScore' arguments='string name'>
Returns the highest score for name in the list. Returns nil if there is no score for name in the list.
</Function>
<Function name='GetRankOfName' return='int' arguments='string name'>
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)
</Function>
</Class>
<Class name='HoldJudgment'>
<Function name='LoadFromMultiPlayer' return='void' arguments='MultiPlayer mp'>
@@ -3208,6 +3214,9 @@ save yourself some time, copy this for undocumented things:
</Function>
</Class>
<Class name='Profile'>
<Function name='GetAllUsedHighScoreNames' return= '{string}' arguments='void'>
Returns a table of all high score names that have been used on this profile.
</Function>
<Function name='GetCaloriesBurnedToday' return='float' arguments=''>
Returns the number of calories burned during the current day.
</Function>
@@ -3247,6 +3256,10 @@ save yourself some time, copy this for undocumented things:
<Function name='GetHighScoreList' return='HighScoreList' arguments='Song s, Steps st'>
Gets the profile's HighScoreList for a specified Song and Steps. (Alternate arguments for Courses: <code>Course c, Trail t</code>)
</Function>
<Function name='GetHighScoreListIfExists' return='HighScoreList' arguments='Song s, Steps st'>
Gets the profile's HighScoreList for a specified Song and Steps. (Alternate arguments for Courses: <code>Course c, Trail t</code>)<br />
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.
</Function>
<Function name='GetLastPlayedCourse' return='Course' arguments=''>
Returns the last played Course for this profile.
</Function>
+35
View File
@@ -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 );
}
};
+84
View File
@@ -744,6 +744,33 @@ void Profile::IncrementCoursePlayCount( const Course* pCourse, const Trail* pTra
GetCourseHighScoreList(pCourse,pTrail).IncrementPlayCount( now );
}
void Profile::GetAllUsedHighScoreNames(std::set<RString>& 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<main_key_type, main_value_type>::iterator main_entry= \
main_member.begin(); main_entry != main_member.end(); ++main_entry) \
{ \
for(std::map<sub_key_type, sub_value_type>::iterator sub_entry= \
main_entry->second.sub_member.begin(); \
sub_entry != main_entry->second.sub_member.end(); ++sub_entry) \
{ \
for(vector<HighScore>::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<arga_type>::check(L, 1); \
const argb_type *pargb = Luna<argb_type>::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<arga_type##ID, Profile::HighScoresForA##arga_type>::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<argb_type##ID, Profile::HighScoresForA##argb_type>::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<RString> names;
p->GetAllUsedHighScoreNames(names);
lua_createtable(L, names.size(), 0);
int next_name_index= 1;
for(std::set<RString>::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 );
+1
View File
@@ -262,6 +262,7 @@ public:
DateTime GetCourseLastPlayedDateTime( const Course* pCourse ) const;
void IncrementCoursePlayCount( const Course* pCourse, const Trail* pTrail );
void GetAllUsedHighScoreNames(std::set<RString>& names);
// Category high scores
HighScoreList m_CategoryHighScores[NUM_StepsType][NUM_RankingCategory];