add popularity lists to stats.html
This commit is contained in:
@@ -1018,16 +1018,20 @@ int Course::GetNumTimesPlayed( MemoryCard card ) const
|
|||||||
|
|
||||||
static map<const Course*, int> course_sort_val;
|
static map<const Course*, int> course_sort_val;
|
||||||
|
|
||||||
bool CompareCoursePointersBySortVal(const Course *pSong1, const Course *pSong2)
|
bool CompareCoursePointersBySortValueAscending(const Course *pSong1, const Course *pSong2)
|
||||||
{
|
{
|
||||||
return course_sort_val[pSong1] < course_sort_val[pSong2];
|
return course_sort_val[pSong1] < course_sort_val[pSong2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CompareCoursePointersBySortValueDescending(const Course *pSong1, const Course *pSong2)
|
||||||
|
{
|
||||||
|
return course_sort_val[pSong1] > course_sort_val[pSong2];
|
||||||
|
}
|
||||||
|
|
||||||
void SortCoursePointerArrayByMostPlayed( vector<Course*> &arrayCoursePointers, MemoryCard card )
|
void SortCoursePointerArrayByMostPlayed( vector<Course*> &arrayCoursePointers, MemoryCard card )
|
||||||
{
|
{
|
||||||
for(unsigned i = 0; i < arrayCoursePointers.size(); ++i)
|
for(unsigned i = 0; i < arrayCoursePointers.size(); ++i)
|
||||||
course_sort_val[arrayCoursePointers[i]] = arrayCoursePointers[i]->GetNumTimesPlayed( card );
|
course_sort_val[arrayCoursePointers[i]] = arrayCoursePointers[i]->GetNumTimesPlayed( card );
|
||||||
stable_sort( arrayCoursePointers.begin(), arrayCoursePointers.end(), CompareCoursePointersBySortVal );
|
stable_sort( arrayCoursePointers.begin(), arrayCoursePointers.end(), CompareCoursePointersBySortValueDescending );
|
||||||
reverse( arrayCoursePointers.begin(), arrayCoursePointers.end() );
|
|
||||||
course_sort_val.clear();
|
course_sort_val.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -362,26 +362,7 @@ void MusicWheel::GetSongList(vector<Song*> &arraySongs, SongSortOrder so, CStrin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern map<const Song*, CString> song_sort_val;
|
|
||||||
bool CompareSongPointersBySortVal(const Song *pSong1, const Song *pSong2);
|
|
||||||
|
|
||||||
void MusicWheel::SortSongPointerArrayBySectionName( vector<Song*> &arraySongPointers, SongSortOrder so )
|
|
||||||
{
|
|
||||||
for(unsigned i = 0; i < arraySongPointers.size(); ++i)
|
|
||||||
{
|
|
||||||
CString val = MusicWheel::GetSectionNameFromSongAndSort( arraySongPointers[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" + val;
|
|
||||||
|
|
||||||
song_sort_val[arraySongPointers[i]] = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
stable_sort( arraySongPointers.begin(), arraySongPointers.end(), CompareSongPointersBySortVal );
|
|
||||||
song_sort_val.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MusicWheel::BuildWheelItemDatas( vector<WheelItemData> &arrayWheelItemDatas, SongSortOrder so )
|
void MusicWheel::BuildWheelItemDatas( vector<WheelItemData> &arrayWheelItemDatas, SongSortOrder so )
|
||||||
@@ -1408,93 +1389,6 @@ void MusicWheel::TweenOffScreen(bool changing_sort)
|
|||||||
m_fTimeLeftInState = GetTweenTimeLeft() + 0.100f;
|
m_fTimeLeftInState = GetTweenTimeLeft() + 0.100f;
|
||||||
}
|
}
|
||||||
|
|
||||||
CString MusicWheel::GetSectionNameFromSongAndSort( const Song* pSong, SongSortOrder so )
|
|
||||||
{
|
|
||||||
if( pSong == NULL )
|
|
||||||
return "";
|
|
||||||
|
|
||||||
switch( so )
|
|
||||||
{
|
|
||||||
case SORT_PREFERRED:
|
|
||||||
return "";
|
|
||||||
case SORT_GROUP:
|
|
||||||
return pSong->m_sGroupName;
|
|
||||||
case SORT_TITLE:
|
|
||||||
case SORT_ARTIST:
|
|
||||||
{
|
|
||||||
CString s;
|
|
||||||
switch( so )
|
|
||||||
{
|
|
||||||
case SORT_TITLE: s = pSong->GetTranslitMainTitle(); break;
|
|
||||||
case SORT_ARTIST: s = pSong->GetTranslitArtist(); break;
|
|
||||||
default: ASSERT(0);
|
|
||||||
}
|
|
||||||
s = MakeSortString(s); // resulting string will be uppercase
|
|
||||||
|
|
||||||
if( s.empty() )
|
|
||||||
return "";
|
|
||||||
else if( s[0] >= '0' && s[0] <= '9' )
|
|
||||||
return "NUM";
|
|
||||||
else if( s[0] < 'A' || s[0] > 'Z')
|
|
||||||
return "OTHER";
|
|
||||||
else
|
|
||||||
return s.Left(1);
|
|
||||||
}
|
|
||||||
case SORT_BPM:
|
|
||||||
{
|
|
||||||
const int iBPMGroupSize = 20;
|
|
||||||
float fMinBPM, fMaxBPM;
|
|
||||||
pSong->GetDisplayBPM( fMinBPM, fMaxBPM );
|
|
||||||
int iMaxBPM = (int)fMaxBPM;
|
|
||||||
iMaxBPM += iBPMGroupSize - (iMaxBPM%iBPMGroupSize) - 1;
|
|
||||||
return ssprintf("%03d-%03d",iMaxBPM-(iBPMGroupSize-1), iMaxBPM);
|
|
||||||
}
|
|
||||||
case SORT_MOST_PLAYED:
|
|
||||||
return "";
|
|
||||||
case SORT_GRADE:
|
|
||||||
{
|
|
||||||
for( int i=NUM_GRADES; i>GRADE_NO_DATA; i-- )
|
|
||||||
{
|
|
||||||
Grade g = (Grade)i;
|
|
||||||
int iCount = pSong->GetNumNotesWithGrade( g );
|
|
||||||
if( iCount > 0 )
|
|
||||||
return ssprintf( "%4s x %d", GradeToString(g).c_str(), iCount );
|
|
||||||
}
|
|
||||||
return "NO DATA";
|
|
||||||
}
|
|
||||||
case SORT_EASY_METER:
|
|
||||||
{
|
|
||||||
Steps* pNotes = pSong->GetStepsByDifficulty(GAMESTATE->GetCurrentStyleDef()->m_StepsType,DIFFICULTY_EASY);
|
|
||||||
if( pNotes )
|
|
||||||
return ssprintf("%02d", pNotes->GetMeter() );
|
|
||||||
return "N/A";
|
|
||||||
}
|
|
||||||
case SORT_MEDIUM_METER:
|
|
||||||
{
|
|
||||||
Steps* pNotes = pSong->GetStepsByDifficulty(GAMESTATE->GetCurrentStyleDef()->m_StepsType,DIFFICULTY_MEDIUM);
|
|
||||||
if( pNotes )
|
|
||||||
return ssprintf("%02d", pNotes->GetMeter() );
|
|
||||||
return "N/A";
|
|
||||||
}
|
|
||||||
case SORT_HARD_METER:
|
|
||||||
{
|
|
||||||
Steps* pNotes = pSong->GetStepsByDifficulty(GAMESTATE->GetCurrentStyleDef()->m_StepsType,DIFFICULTY_HARD);
|
|
||||||
if( pNotes )
|
|
||||||
return ssprintf("%02d", pNotes->GetMeter() );
|
|
||||||
return "N/A";
|
|
||||||
}
|
|
||||||
case SORT_MENU:
|
|
||||||
return "";
|
|
||||||
case SORT_ALL_COURSES:
|
|
||||||
case SORT_NONSTOP_COURSES:
|
|
||||||
case SORT_ONI_COURSES:
|
|
||||||
case SORT_ENDLESS_COURSES:
|
|
||||||
default:
|
|
||||||
ASSERT(0);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MusicWheel::Move(int n)
|
void MusicWheel::Move(int n)
|
||||||
{
|
{
|
||||||
if(n == m_Moving)
|
if(n == m_Moving)
|
||||||
|
|||||||
@@ -125,8 +125,6 @@ protected:
|
|||||||
RageSound m_soundStart;
|
RageSound m_soundStart;
|
||||||
RageSound m_soundLocked;
|
RageSound m_soundLocked;
|
||||||
|
|
||||||
static CString GetSectionNameFromSongAndSort( const Song* pSong, SongSortOrder so );
|
|
||||||
static void SortSongPointerArrayBySectionName( vector<Song*> &arraySongPointers, SongSortOrder so );
|
|
||||||
bool WheelItemIsVisible(int n);
|
bool WheelItemIsVisible(int n);
|
||||||
void UpdateScrollbar();
|
void UpdateScrollbar();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -871,68 +871,39 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, MemoryCard mc )
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make local song list
|
// Gather data
|
||||||
//
|
//
|
||||||
vector<Song*> vpSongs = SONGMAN->GetAllSongs();
|
vector<Song*> vpSongs = SONGMAN->GetAllSongs();
|
||||||
SortSongPointerArrayByGroupAndTitle( vpSongs );
|
vector<Steps*> vpAllSteps;
|
||||||
|
map<Steps*,Song*> mapStepsToSong;
|
||||||
|
{
|
||||||
|
for( unsigned i=0; i<vpSongs.size(); i++ )
|
||||||
|
{
|
||||||
|
Song* pSong = vpSongs[i];
|
||||||
|
vector<Steps*> vpSteps = pSong->GetAllSteps();
|
||||||
|
for( unsigned j=0; j<vpSteps.size(); j++ )
|
||||||
|
{
|
||||||
|
Steps* pSteps = vpSteps[j];
|
||||||
|
if( pSteps->IsAutogen() )
|
||||||
|
continue; // skip
|
||||||
|
vpAllSteps.push_back( pSteps );
|
||||||
|
mapStepsToSong[pSteps] = pSong;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vector<Course*> vpCourses;
|
||||||
|
SONGMAN->GetAllCourses( vpCourses, false );
|
||||||
|
|
||||||
//
|
//
|
||||||
// print HTML headers
|
// Calculate which StepTypes to show
|
||||||
//
|
//
|
||||||
f.PutLine( "<html>" );
|
vector<StepsType> vStepsTypesToShow;
|
||||||
f.PutLine( "<head>" );
|
{
|
||||||
f.PutLine( "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">" );
|
|
||||||
f.PutLine( ssprintf("<title>%s</title>", PRODUCT_NAME_VER) );
|
|
||||||
f.PutLine( "<link rel='stylesheet' type='text/css' href='style.css'>" );
|
|
||||||
f.PutLine( "</head>" );
|
|
||||||
f.PutLine( "<body>" );
|
|
||||||
|
|
||||||
#define PRINT_LINK(szName,szLink) f.Write( ssprintf("<p><a href='%s'>%s</a></p>\n",szLink,szName) )
|
|
||||||
#define PRINT_LINE_S(szName,sVal) f.Write( ssprintf("<p>%s = <b>%s</b></p>\n",szName,sVal.c_str()) )
|
|
||||||
#define PRINT_LINE_B(szName,bVal) f.Write( ssprintf("<p>%s = <b>%s</b></p>\n",szName,(bVal)?"yes":"no") )
|
|
||||||
#define PRINT_LINE_I(szName,iVal) f.Write( ssprintf("<p>%s = <b>%d</b></p>\n",szName,iVal) )
|
|
||||||
//
|
|
||||||
// Print table of contents
|
|
||||||
//
|
|
||||||
f.PutLine( "<h2><a name='Table of Contents'>Table of Contents</a></h2>\n" );
|
|
||||||
f.PutLine( "<div class='section1'>\n" );
|
|
||||||
f.PutLine( "<h3>Sections</h3>\n" );
|
|
||||||
PRINT_LINK( "My Statistics", "#My Statistics" );
|
|
||||||
PRINT_LINK( "Difficulty Table", "#Difficulty Table" );
|
|
||||||
PRINT_LINK( "Song/Steps List", "#Song/Steps List" );
|
|
||||||
f.PutLine( "</div>\n" );
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Print My Statistics
|
|
||||||
//
|
|
||||||
f.PutLine( "<h2><a name='My Statistics'>My Statistics</a> <a href='#Table of Contents'>(top)</a></h2>\n" );
|
|
||||||
f.PutLine( "<div class='section1'>\n" );
|
|
||||||
CString sName = pProfile->m_sLastUsedHighScoreName.empty() ?
|
|
||||||
pProfile->m_sName :
|
|
||||||
pProfile->m_sLastUsedHighScoreName;
|
|
||||||
f.PutLine( ssprintf("<h3>%s</h3>\n",sName.c_str()) );
|
|
||||||
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 );
|
|
||||||
f.PutLine( "</div>\n" );
|
|
||||||
|
|
||||||
//
|
|
||||||
// Print Difficulty tables
|
|
||||||
//
|
|
||||||
f.PutLine( "<h2><a name='Difficulty Table'>Difficulty Table</a> <a href='#Table of Contents'>(top)</a></h2>\n" );
|
|
||||||
for( StepsType st=(StepsType)0; st<NUM_STEPS_TYPES; st=(StepsType)(st+1) )
|
for( StepsType st=(StepsType)0; st<NUM_STEPS_TYPES; st=(StepsType)(st+1) )
|
||||||
{
|
{
|
||||||
unsigned i;
|
// don't show if there are no Steps of this StepsType
|
||||||
|
|
||||||
// don't print this table if there are no songs that have this StepsType
|
|
||||||
bool bOneSongHasStepsForThisStepsType = false;
|
bool bOneSongHasStepsForThisStepsType = false;
|
||||||
for( i=0; i<vpSongs.size(); i++ )
|
for( unsigned i=0; i<vpSongs.size(); i++ )
|
||||||
{
|
{
|
||||||
Song* pSong = vpSongs[i];
|
Song* pSong = vpSongs[i];
|
||||||
vector<Steps*> vpSteps;
|
vector<Steps*> vpSteps;
|
||||||
@@ -944,11 +915,143 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, MemoryCard mc )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !bOneSongHasStepsForThisStepsType )
|
if( bOneSongHasStepsForThisStepsType )
|
||||||
continue; // don't print this table
|
vStepsTypesToShow.push_back( st );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
f.PutLine( "<div class='section1'>\n" );
|
//
|
||||||
f.PutLine( ssprintf("<h3>%s</h3>\n", GAMEMAN->NotesTypeToString(st).c_str()) );
|
// print HTML headers
|
||||||
|
//
|
||||||
|
{
|
||||||
|
f.PutLine( "<html>" );
|
||||||
|
f.PutLine( "<head>" );
|
||||||
|
f.PutLine( "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">" );
|
||||||
|
f.PutLine( ssprintf("<title>%s</title>", PRODUCT_NAME_VER) );
|
||||||
|
f.PutLine( "<link rel='stylesheet' type='text/css' href='style.css'>" );
|
||||||
|
f.PutLine( "</head>" );
|
||||||
|
f.PutLine( "<body>" );
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PRINT_SECTION_START(szName) f.Write( ssprintf("<h2><a name='%s'>"szName"</a> <a href='#Table of Contents'>(top)</a></h2>\n", szName) )
|
||||||
|
#define PRINT_SECTION_END f.Write( "\n" )
|
||||||
|
#define PRINT_DIV_START(szName) f.Write( ssprintf("<div class='section1'>\n" "<h3>%s</h3>\n", szName) )
|
||||||
|
#define PRINT_DIV_START_ANCHOR(uAnchor,szName) f.Write( ssprintf("<div class='section1'>\n" "<h3><a name='%u'>%s</a></h3>\n", uAnchor, szName) )
|
||||||
|
#define PRINT_DIV_END f.Write( "</div>\n" )
|
||||||
|
#define PRINT_DIV2_START(szName) f.Write( ssprintf("<div class='section2'>\n" "<h3>%s</h3>\n", szName) )
|
||||||
|
#define PRINT_DIV2_START_ANCHOR(uAnchor,szName) f.Write( ssprintf("<div class='section2'>\n" "<h3><a name='%u'>%s</a></h3>\n", uAnchor, szName) )
|
||||||
|
#define PRINT_DIV2_END f.Write( "</div>\n" )
|
||||||
|
#define PRINT_LINK(szName,szLink) f.Write( ssprintf("<p><a href='%s'>%s</a></p>\n",szLink,szName) )
|
||||||
|
#define PRINT_LINE_S(szName,sVal) f.Write( ssprintf("<p>%s = <b>%s</b></p>\n",szName,sVal.c_str()) )
|
||||||
|
#define PRINT_LINE_B(szName,bVal) f.Write( ssprintf("<p>%s = <b>%s</b></p>\n",szName,(bVal)?"yes":"no") )
|
||||||
|
#define PRINT_LINE_I(szName,iVal) f.Write( ssprintf("<p>%s = <b>%d</b></p>\n",szName,iVal) )
|
||||||
|
#define PRINT_LINE_RANK(iRank,sName,iVal) f.Write( ssprintf("<p><b>%d</b> - %s (%d)</p>\n",iRank,sName.c_str(),iVal) )
|
||||||
|
|
||||||
|
//
|
||||||
|
// Print table of contents
|
||||||
|
//
|
||||||
|
{
|
||||||
|
PRINT_SECTION_START( "Table of Contents" );
|
||||||
|
PRINT_DIV_START("Sections");
|
||||||
|
PRINT_LINK( "My Statistics", "#My Statistics" );
|
||||||
|
PRINT_LINK( "Popularity Lists", "#Popularity Lists" );
|
||||||
|
PRINT_LINK( "Difficulty Table", "#Difficulty Table" );
|
||||||
|
PRINT_LINK( "Song/Steps List", "#Song/Steps List" );
|
||||||
|
PRINT_DIV_END;
|
||||||
|
PRINT_SECTION_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Print My Statistics
|
||||||
|
//
|
||||||
|
{
|
||||||
|
PRINT_SECTION_START( "My Statistics" );
|
||||||
|
CString sName = pProfile->m_sLastUsedHighScoreName.empty() ?
|
||||||
|
pProfile->m_sName :
|
||||||
|
pProfile->m_sLastUsedHighScoreName;
|
||||||
|
PRINT_DIV_START( sName.c_str() );
|
||||||
|
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;
|
||||||
|
PRINT_SECTION_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Print Popularity Lists
|
||||||
|
//
|
||||||
|
{
|
||||||
|
PRINT_SECTION_START( "Popularity Lists" );
|
||||||
|
|
||||||
|
// Songs by popularity
|
||||||
|
{
|
||||||
|
unsigned uNumToShow = min( vpSongs.size(), (unsigned)100 );
|
||||||
|
|
||||||
|
SortSongPointerArrayByMostPlayed( vpSongs, mc );
|
||||||
|
PRINT_DIV_START( "Songs by Popularity" );
|
||||||
|
for( unsigned i=0; i<uNumToShow; i++ )
|
||||||
|
{
|
||||||
|
Song* pSong = vpSongs[i];
|
||||||
|
PRINT_LINE_RANK( i+1, pSong->GetFullDisplayTitle(), pSong->GetNumTimesPlayed(mc) );
|
||||||
|
}
|
||||||
|
PRINT_DIV_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Steps by popularity
|
||||||
|
{
|
||||||
|
unsigned uNumToShow = min( vpAllSteps.size(), (unsigned)100 );
|
||||||
|
|
||||||
|
SortStepsPointerArrayByMostPlayed( vpAllSteps, mc );
|
||||||
|
PRINT_DIV_START( "Steps by Popularity" );
|
||||||
|
for( unsigned i=0; i<uNumToShow; i++ )
|
||||||
|
{
|
||||||
|
Steps* pSteps = vpAllSteps[i];
|
||||||
|
Song* pSong = mapStepsToSong[pSteps];
|
||||||
|
CString s;
|
||||||
|
s += pSong->GetFullDisplayTitle();
|
||||||
|
s += " - ";
|
||||||
|
s += GAMEMAN->NotesTypeToString(pSteps->m_StepsType);
|
||||||
|
s += " ";
|
||||||
|
s += DifficultyToString(pSteps->GetDifficulty());
|
||||||
|
PRINT_LINE_RANK( i+1, s, pSteps->GetNumTimesPlayed(mc) );
|
||||||
|
}
|
||||||
|
PRINT_DIV_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Course by popularity
|
||||||
|
{
|
||||||
|
unsigned uNumToShow = min( vpCourses.size(), (unsigned)100 );
|
||||||
|
|
||||||
|
SortCoursePointerArrayByMostPlayed( vpCourses, mc );
|
||||||
|
PRINT_DIV_START( "Courses by Popularity" );
|
||||||
|
for( unsigned i=0; i<uNumToShow; i++ )
|
||||||
|
{
|
||||||
|
Course* pCourse = vpCourses[i];
|
||||||
|
PRINT_LINE_RANK( i+1, pCourse->m_sName, pCourse->GetNumTimesPlayed(mc) );
|
||||||
|
}
|
||||||
|
PRINT_DIV_END;
|
||||||
|
}
|
||||||
|
PRINT_SECTION_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Print Difficulty tables
|
||||||
|
//
|
||||||
|
{
|
||||||
|
SortSongPointerArrayByGroupAndTitle( vpSongs );
|
||||||
|
|
||||||
|
PRINT_SECTION_START( "Difficulty Table" );
|
||||||
|
for( unsigned s=0; s<vStepsTypesToShow.size(); s++ )
|
||||||
|
{
|
||||||
|
StepsType st = vStepsTypesToShow[s];
|
||||||
|
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
PRINT_DIV_START( GAMEMAN->NotesTypeToString(st).c_str() );
|
||||||
f.PutLine( "<table border='1' cellpadding='2' cellspacing='0'>\n" );
|
f.PutLine( "<table border='1' cellpadding='2' cellspacing='0'>\n" );
|
||||||
|
|
||||||
// table header row
|
// table header row
|
||||||
@@ -986,14 +1089,16 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, MemoryCard mc )
|
|||||||
}
|
}
|
||||||
|
|
||||||
f.PutLine( "</table>\n" );
|
f.PutLine( "</table>\n" );
|
||||||
f.PutLine( "</div>\n" );
|
PRINT_DIV_END;
|
||||||
|
}
|
||||||
|
PRINT_SECTION_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Print song list
|
// Print song list
|
||||||
//
|
//
|
||||||
f.PutLine( "<h2><a name='Song/Steps List'>Song/Steps List</a> <a href='#Table of Contents'>(top)</a></h2>\n" );
|
{
|
||||||
|
PRINT_SECTION_START( "Song/Steps List" );
|
||||||
for( unsigned i=0; i<vpSongs.size(); i++ )
|
for( unsigned i=0; i<vpSongs.size(); i++ )
|
||||||
{
|
{
|
||||||
Song* pSong = vpSongs[i];
|
Song* pSong = vpSongs[i];
|
||||||
@@ -1006,10 +1111,7 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, MemoryCard mc )
|
|||||||
* the directory cache expires before we get here.) */
|
* 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 print the song banner anyway since this is going on the memory card. -Chris */
|
||||||
//CString sImagePath = pSong->HasBanner() ? pSong->GetBannerPath() : (pSong->HasBackground() ? pSong->GetBackgroundPath() : "" );
|
//CString sImagePath = pSong->HasBanner() ? pSong->GetBannerPath() : (pSong->HasBackground() ? pSong->GetBackgroundPath() : "" );
|
||||||
f.PutLine( "<div class='section1'>\n" );
|
PRINT_DIV_START_ANCHOR( /*Song primary key*/pSong, pSong->GetFullDisplayTitle().c_str() );
|
||||||
f.PutLine( ssprintf("<h3><a name='%u'>%s</a></h3>\n",
|
|
||||||
pSong, // use pointer value as the hash
|
|
||||||
pSong->GetFullDisplayTitle().c_str()) );
|
|
||||||
PRINT_LINE_S( "Artist", pSong->GetDisplayArtist() );
|
PRINT_LINE_S( "Artist", pSong->GetDisplayArtist() );
|
||||||
PRINT_LINE_S( "GroupName", pSong->m_sGroupName );
|
PRINT_LINE_S( "GroupName", pSong->m_sGroupName );
|
||||||
float fMinBPM, fMaxBPM;
|
float fMinBPM, fMaxBPM;
|
||||||
@@ -1020,7 +1122,7 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, MemoryCard mc )
|
|||||||
PRINT_LINE_S( "Credit", pSong->m_sCredit );
|
PRINT_LINE_S( "Credit", pSong->m_sCredit );
|
||||||
PRINT_LINE_S( "MusicLength", SecondsToTime(pSong->m_fMusicLengthSeconds) );
|
PRINT_LINE_S( "MusicLength", SecondsToTime(pSong->m_fMusicLengthSeconds) );
|
||||||
PRINT_LINE_B( "Lyrics", !pSong->m_sLyricsFile.empty() );
|
PRINT_LINE_B( "Lyrics", !pSong->m_sLyricsFile.empty() );
|
||||||
f.PutLine( "</div>\n" );
|
PRINT_DIV_END;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Print Steps list
|
// Print Steps list
|
||||||
@@ -1031,14 +1133,17 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, MemoryCard mc )
|
|||||||
if( pSteps->IsAutogen() )
|
if( pSteps->IsAutogen() )
|
||||||
continue; // skip autogen
|
continue; // skip autogen
|
||||||
f.PutLine( "<div class='section2'>\n" );
|
f.PutLine( "<div class='section2'>\n" );
|
||||||
f.PutLine( ssprintf("<h4><a name='%u'>%s - %s</a></h4>\n",
|
CString s =
|
||||||
pSteps, // use pointer value as the hash
|
GAMEMAN->NotesTypeToString(pSteps->m_StepsType) +
|
||||||
GAMEMAN->NotesTypeToString(pSteps->m_StepsType).c_str(),
|
" - " +
|
||||||
DifficultyToString(pSteps->GetDifficulty()).c_str()) );
|
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[mc].iNumTimesPlayed );
|
PRINT_LINE_I( "NumTimesPlayed", pSteps->m_MemCardDatas[mc].iNumTimesPlayed );
|
||||||
f.PutLine( "</div>\n" );
|
f.PutLine( "</div>\n" );
|
||||||
|
PRINT_DIV2_END;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
PRINT_SECTION_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
f.PutLine( "</body>" );
|
f.PutLine( "</body>" );
|
||||||
|
|||||||
+112
-3
@@ -1468,17 +1468,126 @@ void SortSongPointerArrayByGroupAndTitle( vector<Song*> &arraySongPointers )
|
|||||||
* it. (This could be generalized with a template.) */
|
* it. (This could be generalized with a template.) */
|
||||||
map<const Song*, CString> song_sort_val;
|
map<const Song*, CString> song_sort_val;
|
||||||
|
|
||||||
bool CompareSongPointersBySortVal(const Song *pSong1, const Song *pSong2)
|
bool CompareSongPointersBySortValueAscending(const Song *pSong1, const Song *pSong2)
|
||||||
{
|
{
|
||||||
return song_sort_val[pSong1] < song_sort_val[pSong2];
|
return song_sort_val[pSong1] < song_sort_val[pSong2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CompareSongPointersBySortValueDescending(const Song *pSong1, const Song *pSong2)
|
||||||
|
{
|
||||||
|
return song_sort_val[pSong1] > song_sort_val[pSong2];
|
||||||
|
}
|
||||||
|
|
||||||
void SortSongPointerArrayByMostPlayed( vector<Song*> &arraySongPointers, MemoryCard card )
|
void SortSongPointerArrayByMostPlayed( vector<Song*> &arraySongPointers, MemoryCard card )
|
||||||
{
|
{
|
||||||
for(unsigned i = 0; i < arraySongPointers.size(); ++i)
|
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", arraySongPointers[i]->GetNumTimesPlayed(card));
|
||||||
stable_sort( arraySongPointers.begin(), arraySongPointers.end(), CompareSongPointersBySortVal );
|
stable_sort( arraySongPointers.begin(), arraySongPointers.end(), CompareSongPointersBySortValueDescending );
|
||||||
reverse( arraySongPointers.begin(), arraySongPointers.end() );
|
song_sort_val.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
CString GetSectionNameFromSongAndSort( const Song* pSong, SongSortOrder so )
|
||||||
|
{
|
||||||
|
if( pSong == NULL )
|
||||||
|
return "";
|
||||||
|
|
||||||
|
switch( so )
|
||||||
|
{
|
||||||
|
case SORT_PREFERRED:
|
||||||
|
return "";
|
||||||
|
case SORT_GROUP:
|
||||||
|
return pSong->m_sGroupName;
|
||||||
|
case SORT_TITLE:
|
||||||
|
case SORT_ARTIST:
|
||||||
|
{
|
||||||
|
CString s;
|
||||||
|
switch( so )
|
||||||
|
{
|
||||||
|
case SORT_TITLE: s = pSong->GetTranslitMainTitle(); break;
|
||||||
|
case SORT_ARTIST: s = pSong->GetTranslitArtist(); break;
|
||||||
|
default: ASSERT(0);
|
||||||
|
}
|
||||||
|
s = MakeSortString(s); // resulting string will be uppercase
|
||||||
|
|
||||||
|
if( s.empty() )
|
||||||
|
return "";
|
||||||
|
else if( s[0] >= '0' && s[0] <= '9' )
|
||||||
|
return "NUM";
|
||||||
|
else if( s[0] < 'A' || s[0] > 'Z')
|
||||||
|
return "OTHER";
|
||||||
|
else
|
||||||
|
return s.Left(1);
|
||||||
|
}
|
||||||
|
case SORT_BPM:
|
||||||
|
{
|
||||||
|
const int iBPMGroupSize = 20;
|
||||||
|
float fMinBPM, fMaxBPM;
|
||||||
|
pSong->GetDisplayBPM( fMinBPM, fMaxBPM );
|
||||||
|
int iMaxBPM = (int)fMaxBPM;
|
||||||
|
iMaxBPM += iBPMGroupSize - (iMaxBPM%iBPMGroupSize) - 1;
|
||||||
|
return ssprintf("%03d-%03d",iMaxBPM-(iBPMGroupSize-1), iMaxBPM);
|
||||||
|
}
|
||||||
|
case SORT_MOST_PLAYED:
|
||||||
|
return "";
|
||||||
|
case SORT_GRADE:
|
||||||
|
{
|
||||||
|
for( int i=NUM_GRADES; i>GRADE_NO_DATA; i-- )
|
||||||
|
{
|
||||||
|
Grade g = (Grade)i;
|
||||||
|
int iCount = pSong->GetNumNotesWithGrade( g );
|
||||||
|
if( iCount > 0 )
|
||||||
|
return ssprintf( "%4s x %d", GradeToString(g).c_str(), iCount );
|
||||||
|
}
|
||||||
|
return "NO DATA";
|
||||||
|
}
|
||||||
|
case SORT_EASY_METER:
|
||||||
|
{
|
||||||
|
Steps* pNotes = pSong->GetStepsByDifficulty(GAMESTATE->GetCurrentStyleDef()->m_StepsType,DIFFICULTY_EASY);
|
||||||
|
if( pNotes )
|
||||||
|
return ssprintf("%02d", pNotes->GetMeter() );
|
||||||
|
return "N/A";
|
||||||
|
}
|
||||||
|
case SORT_MEDIUM_METER:
|
||||||
|
{
|
||||||
|
Steps* pNotes = pSong->GetStepsByDifficulty(GAMESTATE->GetCurrentStyleDef()->m_StepsType,DIFFICULTY_MEDIUM);
|
||||||
|
if( pNotes )
|
||||||
|
return ssprintf("%02d", pNotes->GetMeter() );
|
||||||
|
return "N/A";
|
||||||
|
}
|
||||||
|
case SORT_HARD_METER:
|
||||||
|
{
|
||||||
|
Steps* pNotes = pSong->GetStepsByDifficulty(GAMESTATE->GetCurrentStyleDef()->m_StepsType,DIFFICULTY_HARD);
|
||||||
|
if( pNotes )
|
||||||
|
return ssprintf("%02d", pNotes->GetMeter() );
|
||||||
|
return "N/A";
|
||||||
|
}
|
||||||
|
case SORT_MENU:
|
||||||
|
return "";
|
||||||
|
case SORT_ALL_COURSES:
|
||||||
|
case SORT_NONSTOP_COURSES:
|
||||||
|
case SORT_ONI_COURSES:
|
||||||
|
case SORT_ENDLESS_COURSES:
|
||||||
|
default:
|
||||||
|
ASSERT(0);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SortSongPointerArrayBySectionName( vector<Song*> &arraySongPointers, SongSortOrder so )
|
||||||
|
{
|
||||||
|
for(unsigned i = 0; i < arraySongPointers.size(); ++i)
|
||||||
|
{
|
||||||
|
CString val = GetSectionNameFromSongAndSort( arraySongPointers[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" + val;
|
||||||
|
|
||||||
|
song_sort_val[arraySongPointers[i]] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
stable_sort( arraySongPointers.begin(), arraySongPointers.end(), CompareSongPointersBySortValueAscending );
|
||||||
song_sort_val.clear();
|
song_sort_val.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -280,6 +280,25 @@ void Steps::SetRadarValue(int r, float val)
|
|||||||
//
|
//
|
||||||
// Sorting stuff
|
// Sorting stuff
|
||||||
//
|
//
|
||||||
|
map<const Steps*, CString> steps_sort_val;
|
||||||
|
|
||||||
|
bool CompareStepsPointersBySortValueAscending(const Steps *pSteps1, const Steps *pSteps2)
|
||||||
|
{
|
||||||
|
return steps_sort_val[pSteps1] < steps_sort_val[pSteps2];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CompareStepsPointersBySortValueDescending(const Steps *pSteps1, const Steps *pSteps2)
|
||||||
|
{
|
||||||
|
return steps_sort_val[pSteps1] > steps_sort_val[pSteps2];
|
||||||
|
}
|
||||||
|
|
||||||
|
void SortStepsPointerArrayByMostPlayed( vector<Steps*> &vStepsPointers, MemoryCard card )
|
||||||
|
{
|
||||||
|
for(unsigned i = 0; i < vStepsPointers.size(); ++i)
|
||||||
|
steps_sort_val[vStepsPointers[i]] = ssprintf("%9i", vStepsPointers[i]->GetNumTimesPlayed(card));
|
||||||
|
stable_sort( vStepsPointers.begin(), vStepsPointers.end(), CompareStepsPointersBySortValueDescending );
|
||||||
|
steps_sort_val.clear();
|
||||||
|
}
|
||||||
|
|
||||||
bool CompareNotesPointersByRadarValues(const Steps* pNotes1, const Steps* pNotes2)
|
bool CompareNotesPointersByRadarValues(const Steps* pNotes1, const Steps* pNotes2)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -137,5 +137,6 @@ bool CompareNotesPointersByDifficulty(const Steps *pNotes1, const Steps *pNotes2
|
|||||||
void SortNotesArrayByDifficulty( vector<Steps*> &arrayNotess );
|
void SortNotesArrayByDifficulty( vector<Steps*> &arrayNotess );
|
||||||
bool CompareStepsPointersByTypeAndDifficulty(const Steps *pStep1, const Steps *pStep2);
|
bool CompareStepsPointersByTypeAndDifficulty(const Steps *pStep1, const Steps *pStep2);
|
||||||
void SortStepsByTypeAndDifficulty( vector<Steps*> &arraySongPointers );
|
void SortStepsByTypeAndDifficulty( vector<Steps*> &arraySongPointers );
|
||||||
|
void SortStepsPointerArrayByMostPlayed( vector<Steps*> &vStepsPointers, MemoryCard card );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -273,6 +273,8 @@ void SortSongPointerArrayByGroupAndDifficulty( vector<Song*> &arraySongPointers
|
|||||||
void SortSongPointerArrayByGroupAndTitle( vector<Song*> &arraySongPointers );
|
void SortSongPointerArrayByGroupAndTitle( vector<Song*> &arraySongPointers );
|
||||||
void SortSongPointerArrayByMostPlayed( vector<Song*> &arraySongPointers, MemoryCard card );
|
void SortSongPointerArrayByMostPlayed( vector<Song*> &arraySongPointers, MemoryCard card );
|
||||||
void SortSongPointerArrayByMeter( vector<Song*> &arraySongPointers, Difficulty dc );
|
void SortSongPointerArrayByMeter( vector<Song*> &arraySongPointers, Difficulty dc );
|
||||||
|
CString GetSectionNameFromSongAndSort( const Song* pSong, SongSortOrder so );
|
||||||
|
void SortSongPointerArrayBySectionName( vector<Song*> &arraySongPointers, SongSortOrder so );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user