2004-02-16 02:57:55 +00:00
|
|
|
#include "global.h"
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
|
Class: ProfileHtml
|
|
|
|
|
|
|
|
|
|
Desc: See header.
|
|
|
|
|
|
|
|
|
|
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
|
|
|
|
|
Chris Danford
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "ProfileHtml.h"
|
|
|
|
|
#include "ThemeManager.h"
|
|
|
|
|
#include "RageFile.h"
|
|
|
|
|
#include "RageLog.h"
|
|
|
|
|
#include "SongManager.h"
|
|
|
|
|
#include "song.h"
|
|
|
|
|
#include "Steps.h"
|
|
|
|
|
#include <time.h>
|
|
|
|
|
#include "GameManager.h"
|
|
|
|
|
#include "Course.h"
|
|
|
|
|
#include "Bookkeeper.h"
|
2004-02-16 09:23:34 +00:00
|
|
|
#include "PrefsManager.h"
|
2004-02-16 02:57:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
#define STATS_HTML "stats.html"
|
|
|
|
|
#define STYLE_CSS "style.css"
|
|
|
|
|
|
2004-02-16 09:23:34 +00:00
|
|
|
#define TITLE THEME->GetMetric("ProfileHtml","Title")
|
|
|
|
|
#define FOOTER THEME->GetMetric("ProfileHtml","Footer")
|
|
|
|
|
#define VERIFICATION_TEXT THEME->GetMetric("ProfileHtml","VerificationText")
|
2004-02-16 02:57:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
static int g_Level = 1;
|
|
|
|
|
|
|
|
|
|
inline CString MakeUniqueId() { CString s="id"+ssprintf("%d%d%d",rand(),rand(),rand()); return s; }
|
|
|
|
|
inline void PRINT_OPEN(RageFile &f,CString sName,bool bExpanded,CString sID){ g_Level++; ASSERT(g_Level>0 && g_Level<6); f.Write( ssprintf("<div class='section%d'>\n" "<h%d onClick='expandIt(%s); return false' CLASS='outline'>%s</h%d>\n" "<DIV ID='%s' CLASS='%s'>\n", g_Level, g_Level, sID.c_str(), sName.c_str(), g_Level, sID.c_str(), bExpanded?"visibletext":"hiddentext") ); }
|
|
|
|
|
inline void PRINT_OPEN(RageFile &f,CString sName,bool bExpanded=false) { PRINT_OPEN(f,sName,bExpanded,MakeUniqueId()); }
|
|
|
|
|
inline void PRINT_CLOSE(RageFile &f) { f.Write( "</div>\n" "</div>\n" ); g_Level--; ASSERT(g_Level>=0); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Table
|
|
|
|
|
{
|
|
|
|
|
Table() {}
|
|
|
|
|
|
|
|
|
|
struct Line
|
|
|
|
|
{
|
|
|
|
|
Line() {}
|
2004-02-16 09:23:34 +00:00
|
|
|
Line(CString n) { sName = n; }
|
|
|
|
|
Line(CString n,CString v) { sName = n; sValue = v; }
|
|
|
|
|
Line(CString n,bool v) { sName = n; sValue = ssprintf("%s",v?"yes":"no"); }
|
|
|
|
|
Line(CString n,int v) { sName = n; sValue = ssprintf("%d",v); }
|
|
|
|
|
Line(int r,CString n,int v) { sRank = ssprintf("%d",r); sName = n; sValue = ssprintf("%d",v); }
|
|
|
|
|
Line(int r,CString n,CString sn,int v) { sRank = ssprintf("%d",r); sName = n; sSubName = sn; sValue = ssprintf("%d",v); }
|
|
|
|
|
Line(int r,CString n,CString sn,CString ssn,int v) { sRank = ssprintf("%d",r); sName = n; sSubName = sn; sSubSubName = ssn; sValue = ssprintf("%d",v); }
|
2004-02-16 02:57:55 +00:00
|
|
|
|
|
|
|
|
CString sRank;
|
|
|
|
|
CString sName;
|
2004-02-16 09:23:34 +00:00
|
|
|
CString sSubName;
|
|
|
|
|
CString sSubSubName;
|
2004-02-16 02:57:55 +00:00
|
|
|
CString sValue;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int iNumCols;
|
|
|
|
|
vector<Line> vLines;
|
|
|
|
|
};
|
|
|
|
|
|
2004-02-16 09:23:34 +00:00
|
|
|
#define BEGIN_TABLE(cols) { Table table; table.iNumCols=cols;
|
|
|
|
|
#define TABLE_LINE1(p1) table.vLines.push_back( Table::Line(p1) );
|
|
|
|
|
#define TABLE_LINE2(p1,p2) table.vLines.push_back( Table::Line(p1,p2) );
|
|
|
|
|
#define TABLE_LINE3(p1,p2,p3) table.vLines.push_back( Table::Line(p1,p2,p3) );
|
|
|
|
|
#define TABLE_LINE4(p1,p2,p3,p4) table.vLines.push_back( Table::Line(p1,p2,p3,p4) );
|
|
|
|
|
#define TABLE_LINE5(p1,p2,p3,p4,p5) table.vLines.push_back( Table::Line(p1,p2,p3,p4,p5) );
|
|
|
|
|
#define END_TABLE PrintTable( f, table ); }
|
2004-02-16 02:57:55 +00:00
|
|
|
|
|
|
|
|
inline void PrintTable(RageFile &f,Table &table)
|
|
|
|
|
{
|
|
|
|
|
const vector<Table::Line> &vLines = table.vLines;
|
|
|
|
|
int &iNumCols = table.iNumCols;
|
|
|
|
|
|
|
|
|
|
ASSERT( iNumCols > 0 );
|
|
|
|
|
|
|
|
|
|
if( vLines.empty() )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
bool bPrintRank = !vLines.empty() && !vLines[0].sRank.empty();
|
|
|
|
|
|
|
|
|
|
int iMaxItemsPerCol = (vLines.size()+iNumCols-1) / iNumCols;
|
|
|
|
|
iNumCols = (vLines.size()+iMaxItemsPerCol-1) / iMaxItemsPerCol; // round up
|
|
|
|
|
f.Write("<table class='group'><tr>\n");
|
|
|
|
|
for( int col=0; col<iNumCols; col++ )
|
|
|
|
|
{
|
|
|
|
|
f.Write("<td>\n");
|
|
|
|
|
|
|
|
|
|
int iStartItem = col*iMaxItemsPerCol;
|
|
|
|
|
|
|
|
|
|
f.Write("<table class='column'>\n");
|
|
|
|
|
for( int i=iStartItem; i<iStartItem+iMaxItemsPerCol; i++ )
|
|
|
|
|
{
|
|
|
|
|
f.Write("<tr>");
|
|
|
|
|
|
2004-02-16 07:25:59 +00:00
|
|
|
const Table::Line& line = (i<(int)vLines.size()) ? vLines[i] : Table::Line();
|
2004-02-16 02:57:55 +00:00
|
|
|
if( bPrintRank )
|
|
|
|
|
{
|
|
|
|
|
f.Write("<td class='rank'>");
|
|
|
|
|
f.Write( line.sRank );
|
|
|
|
|
f.Write("</td>");
|
|
|
|
|
f.Write("<td> </td>");
|
|
|
|
|
}
|
2004-02-16 09:23:34 +00:00
|
|
|
if( bPrintRank )
|
|
|
|
|
{
|
|
|
|
|
f.Write("<td>");
|
|
|
|
|
f.Write("<p class='songtitle'>");
|
|
|
|
|
f.Write( line.sName );
|
|
|
|
|
f.Write("</p>");
|
|
|
|
|
f.Write("<p class='songsubtitle'>");
|
|
|
|
|
f.Write( line.sSubName );
|
|
|
|
|
f.Write("</p>");
|
|
|
|
|
f.Write("</td>");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
f.Write("<td class='name'>");
|
|
|
|
|
f.Write( line.sName );
|
|
|
|
|
f.Write("</td>");
|
|
|
|
|
}
|
|
|
|
|
if( !line.sValue.empty() )
|
|
|
|
|
{
|
|
|
|
|
f.Write("<td> </td>");
|
|
|
|
|
f.Write("<td class='value'>");
|
|
|
|
|
f.Write( line.sValue );
|
|
|
|
|
f.Write("</td>");
|
|
|
|
|
}
|
2004-02-16 02:57:55 +00:00
|
|
|
f.Write( "\n" );
|
|
|
|
|
|
|
|
|
|
f.Write("</tr>");
|
|
|
|
|
}
|
|
|
|
|
f.Write("</table>\n");
|
|
|
|
|
|
|
|
|
|
f.Write("</td>\n");
|
|
|
|
|
}
|
|
|
|
|
f.Write("</tr></table>\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrintStatistics( RageFile &f, const Profile *pProfile, CString sTitle, vector<Song*> &vpSongs, vector<Steps*> &vpAllSteps, vector<StepsType> &vStepsTypesToShow, map<Steps*,Song*> mapStepsToSong, vector<Course*> vpCourses )
|
|
|
|
|
{
|
2004-02-16 09:23:34 +00:00
|
|
|
PRINT_OPEN(f,sTitle,true);
|
2004-02-16 02:57:55 +00:00
|
|
|
{
|
2004-02-16 09:23:34 +00:00
|
|
|
PRINT_OPEN(f,"General Info",true);
|
2004-02-16 02:57:55 +00:00
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(2);
|
|
|
|
|
TABLE_LINE2( "Name", pProfile->m_sName );
|
|
|
|
|
TABLE_LINE2( "LastUsedHighScoreName", pProfile->m_sLastUsedHighScoreName );
|
|
|
|
|
TABLE_LINE2( "UsingProfileDefaultModifiers", pProfile->m_bUsingProfileDefaultModifiers );
|
|
|
|
|
TABLE_LINE2( "DefaultModifiers", pProfile->m_sDefaultModifiers );
|
|
|
|
|
TABLE_LINE2( "TotalPlays", pProfile->m_iTotalPlays );
|
|
|
|
|
TABLE_LINE2( "TotalPlaySeconds", pProfile->m_iTotalPlaySeconds );
|
|
|
|
|
TABLE_LINE2( "TotalGameplaySeconds", pProfile->m_iTotalGameplaySeconds );
|
|
|
|
|
TABLE_LINE2( "CurrentCombo", pProfile->m_iCurrentCombo );
|
2004-02-16 05:35:06 +00:00
|
|
|
TABLE_LINE2( "CaloriesBurned", pProfile->m_fCaloriesBurned );
|
|
|
|
|
TABLE_LINE2( "LastMachinePlayed", pProfile->m_sLastMachinePlayed );
|
2004-02-16 02:57:55 +00:00
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
|
|
|
|
|
|
2004-02-16 09:23:34 +00:00
|
|
|
PRINT_OPEN(f,"Num Songs Played by PlayMode");
|
2004-02-16 02:57:55 +00:00
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(4);
|
|
|
|
|
FOREACH_PlayMode( pm )
|
|
|
|
|
TABLE_LINE2( PlayModeToString(pm), pProfile->m_iNumSongsPlayedByPlayMode[pm] );
|
|
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
|
|
|
|
|
|
2004-02-16 09:23:34 +00:00
|
|
|
PRINT_OPEN(f,"Num Songs Played by Style");
|
2004-02-16 02:57:55 +00:00
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(4);
|
|
|
|
|
for( int i=0; i<NUM_STYLES; i++ )
|
|
|
|
|
{
|
|
|
|
|
Style style = (Style)i;
|
|
|
|
|
const StyleDef* pStyleDef = GAMEMAN->GetStyleDefForStyle(style);
|
|
|
|
|
StepsType st = pStyleDef->m_StepsType;
|
|
|
|
|
if( !pStyleDef->m_bUsedForGameplay )
|
|
|
|
|
continue; // skip
|
|
|
|
|
// only show if this style plays a StepsType that we're showing
|
|
|
|
|
if( find(vStepsTypesToShow.begin(),vStepsTypesToShow.end(),st) == vStepsTypesToShow.end() )
|
|
|
|
|
continue; // skip
|
|
|
|
|
TABLE_LINE2( pStyleDef->m_szName, pProfile->m_iNumSongsPlayedByStyle[i] );
|
|
|
|
|
}
|
|
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
|
|
|
|
|
|
2004-02-16 09:23:34 +00:00
|
|
|
PRINT_OPEN(f,"Num Songs Played by Difficulty");
|
2004-02-16 02:57:55 +00:00
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(4);
|
|
|
|
|
FOREACH_Difficulty( dc )
|
|
|
|
|
TABLE_LINE2( DifficultyToString(dc), pProfile->m_iNumSongsPlayedByDifficulty[dc] );
|
|
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
|
2004-02-16 09:23:34 +00:00
|
|
|
PRINT_OPEN(f,"Num Songs Played by Meter");
|
2004-02-16 02:57:55 +00:00
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(4);
|
|
|
|
|
for( int i=MIN_METER; i<=MAX_METER; i++ )
|
|
|
|
|
TABLE_LINE2( ssprintf("Meter %d",i), pProfile->m_iNumSongsPlayedByMeter[i] );
|
|
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
2004-02-16 09:23:34 +00:00
|
|
|
|
|
|
|
|
PRINT_OPEN(f,"Grade Count");
|
|
|
|
|
{
|
|
|
|
|
int iGradeCount[NUM_GRADES];
|
|
|
|
|
ZERO( iGradeCount );
|
|
|
|
|
|
|
|
|
|
for( int i=0; i<vpAllSteps.size(); i++ )
|
|
|
|
|
{
|
|
|
|
|
Steps* pSteps = vpAllSteps[i];
|
|
|
|
|
const HighScoreList &hsl = pProfile->GetStepsHighScoreList(pSteps);
|
|
|
|
|
if( hsl.vHighScores.empty() )
|
|
|
|
|
continue; // no data, skip this one
|
|
|
|
|
Grade g = hsl.GetTopScore().grade;
|
|
|
|
|
ASSERT( g != GRADE_NO_DATA );
|
|
|
|
|
ASSERT( g < NUM_GRADES );
|
|
|
|
|
ASSERT( g >= 0 );
|
|
|
|
|
iGradeCount[g] ++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BEGIN_TABLE(6);
|
|
|
|
|
for( int g=0; g<PREFSMAN->m_iNumGradeTiersUsed; g++ )
|
|
|
|
|
TABLE_LINE2( GradeToThemedString((Grade)g), iGradeCount[g] );
|
|
|
|
|
TABLE_LINE2( GradeToThemedString(GRADE_FAILED), iGradeCount[GRADE_FAILED] );
|
|
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
2004-02-16 02:57:55 +00:00
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrintPopularity( RageFile &f, const Profile *pProfile, CString sTitle, vector<Song*> &vpSongs, vector<Steps*> &vpAllSteps, vector<StepsType> &vStepsTypesToShow, map<Steps*,Song*> mapStepsToSong, vector<Course*> vpCourses )
|
|
|
|
|
{
|
|
|
|
|
PRINT_OPEN(f, sTitle );
|
|
|
|
|
{
|
2004-02-16 05:35:06 +00:00
|
|
|
SortSongPointerArrayByNumPlays( vpSongs, pProfile, true );
|
|
|
|
|
Song* pSongPopularThreshold = vpSongs[ vpSongs.size()*2/3 ];
|
|
|
|
|
int iPopularNumPlaysThreshold = pProfile->GetSongNumTimesPlayed(pSongPopularThreshold);
|
|
|
|
|
|
|
|
|
|
// unplayed songs are always considered unpopular
|
|
|
|
|
if( iPopularNumPlaysThreshold == 0 )
|
|
|
|
|
iPopularNumPlaysThreshold = 1;
|
2004-02-16 02:57:55 +00:00
|
|
|
|
2004-02-16 05:35:06 +00:00
|
|
|
unsigned uMaxToShow = min( vpSongs.size(), (unsigned)100 );
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
PRINT_OPEN(f, "Most Popular Songs" );
|
2004-02-16 02:57:55 +00:00
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(1);
|
2004-02-16 05:35:06 +00:00
|
|
|
for( unsigned i=0; i<uMaxToShow; i++ )
|
2004-02-16 02:57:55 +00:00
|
|
|
{
|
|
|
|
|
Song* pSong = vpSongs[i];
|
2004-02-16 05:35:06 +00:00
|
|
|
int iNumTimesPlayed = pProfile->GetSongNumTimesPlayed(pSong);
|
|
|
|
|
if( iNumTimesPlayed == 0 || iNumTimesPlayed < iPopularNumPlaysThreshold ) // not popular
|
|
|
|
|
break; // done searching
|
2004-02-16 09:23:34 +00:00
|
|
|
TABLE_LINE4(i+1, pSong->GetDisplayMainTitle(), pSong->GetDisplaySubTitle(), iNumTimesPlayed );
|
2004-02-16 05:35:06 +00:00
|
|
|
}
|
|
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
SortSongPointerArrayByNumPlays( vpSongs, pProfile, false );
|
|
|
|
|
PRINT_OPEN(f, "Least Popular Songs" );
|
|
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(1);
|
|
|
|
|
for( unsigned i=0; i<uMaxToShow; i++ )
|
|
|
|
|
{
|
|
|
|
|
Song* pSong = vpSongs[i];
|
|
|
|
|
int iNumTimesPlayed = pProfile->GetSongNumTimesPlayed(pSong);
|
|
|
|
|
if( iNumTimesPlayed >= iPopularNumPlaysThreshold ) // not unpopular
|
|
|
|
|
break; // done searching
|
2004-02-16 09:23:34 +00:00
|
|
|
TABLE_LINE4(i+1, pSong->GetDisplayMainTitle(), pSong->GetDisplaySubTitle(), iNumTimesPlayed );
|
2004-02-16 02:57:55 +00:00
|
|
|
}
|
|
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
unsigned uNumToShow = min( vpAllSteps.size(), (unsigned)100 );
|
|
|
|
|
|
2004-02-16 05:35:06 +00:00
|
|
|
SortStepsPointerArrayByNumPlays( vpAllSteps, pProfile, true );
|
|
|
|
|
PRINT_OPEN(f, "Most Popular Steps" );
|
2004-02-16 02:57:55 +00:00
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(1);
|
|
|
|
|
for( unsigned i=0; i<uNumToShow; i++ )
|
|
|
|
|
{
|
|
|
|
|
Steps* pSteps = vpAllSteps[i];
|
2004-02-16 05:35:06 +00:00
|
|
|
if( pProfile->GetStepsNumTimesPlayed(pSteps)==0 )
|
|
|
|
|
continue; // skip
|
2004-02-16 02:57:55 +00:00
|
|
|
Song* pSong = mapStepsToSong[pSteps];
|
|
|
|
|
CString s;
|
|
|
|
|
s += GAMEMAN->NotesTypeToString(pSteps->m_StepsType);
|
|
|
|
|
s += " ";
|
|
|
|
|
s += DifficultyToString(pSteps->GetDifficulty());
|
2004-02-16 09:23:34 +00:00
|
|
|
TABLE_LINE5(i+1, pSong->GetDisplayMainTitle(), pSong->GetDisplaySubTitle(), s, pProfile->GetStepsNumTimesPlayed(pSteps) );
|
2004-02-16 02:57:55 +00:00
|
|
|
}
|
|
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
unsigned uNumToShow = min( vpCourses.size(), (unsigned)100 );
|
|
|
|
|
|
2004-02-16 05:35:06 +00:00
|
|
|
SortCoursePointerArrayByNumPlays( vpCourses, pProfile, true );
|
|
|
|
|
PRINT_OPEN(f, "Most Popular Courses" );
|
2004-02-16 02:57:55 +00:00
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(2);
|
|
|
|
|
for( unsigned i=0; i<uNumToShow; i++ )
|
|
|
|
|
{
|
|
|
|
|
Course* pCourse = vpCourses[i];
|
|
|
|
|
TABLE_LINE3(i+1, pCourse->m_sName, pProfile->GetCourseNumTimesPlayed(pCourse) );
|
|
|
|
|
}
|
|
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef void (*FnPrintSong)(RageFile &f, const Profile *pProfile, Song* pSong );
|
|
|
|
|
typedef void (*FnPrintGroup)(RageFile &f, const Profile *pProfile, CString sGroup );
|
|
|
|
|
typedef void (*FnPrintStepsType)(RageFile &f, const Profile *pProfile, StepsType st );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrintSongsInGroup( RageFile &f, const Profile *pProfile, CString sGroup, FnPrintSong pFn )
|
|
|
|
|
{
|
|
|
|
|
PRINT_OPEN(f, sGroup );
|
|
|
|
|
{
|
|
|
|
|
vector<Song*> vpSongs;
|
|
|
|
|
SONGMAN->GetSongs( vpSongs, sGroup );
|
|
|
|
|
|
|
|
|
|
for( unsigned i=0; i<vpSongs.size(); i++ )
|
|
|
|
|
{
|
|
|
|
|
Song* pSong = vpSongs[i];
|
|
|
|
|
|
|
|
|
|
pFn( f, pProfile, pSong );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrintGroups( RageFile &f, const Profile *pProfile, CString sTitle, FnPrintGroup pFn )
|
|
|
|
|
{
|
|
|
|
|
CStringArray asGroups;
|
|
|
|
|
SONGMAN->GetGroupNames( asGroups );
|
|
|
|
|
|
|
|
|
|
PRINT_OPEN(f, sTitle );
|
|
|
|
|
{
|
2004-02-16 07:25:59 +00:00
|
|
|
for( unsigned g=0; g<asGroups.size(); g++ )
|
2004-02-16 02:57:55 +00:00
|
|
|
{
|
|
|
|
|
CString sGroup = asGroups[g];
|
|
|
|
|
|
|
|
|
|
pFn( f, pProfile, sGroup );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrintStepsTypes( RageFile &f, const Profile *pProfile, CString sTitle, vector<StepsType> vStepsTypesToShow, FnPrintStepsType pFn )
|
|
|
|
|
{
|
|
|
|
|
PRINT_OPEN(f, sTitle );
|
|
|
|
|
{
|
|
|
|
|
for( unsigned s=0; s<vStepsTypesToShow.size(); s++ )
|
|
|
|
|
{
|
|
|
|
|
StepsType st = vStepsTypesToShow[s];
|
|
|
|
|
|
|
|
|
|
pFn( f, pProfile, st );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrintHighScoresForSong( RageFile &f, const Profile *pProfile, Song* pSong )
|
|
|
|
|
{
|
2004-02-16 05:35:06 +00:00
|
|
|
int iNumTimesPlayed = pProfile->GetSongNumTimesPlayed(pSong);
|
|
|
|
|
if( iNumTimesPlayed == 0 )
|
|
|
|
|
return; // skip
|
|
|
|
|
|
2004-02-16 02:57:55 +00:00
|
|
|
vector<Steps*> vpSteps = pSong->GetAllSteps();
|
|
|
|
|
|
|
|
|
|
PRINT_OPEN(f, pSong->GetFullDisplayTitle() );
|
|
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(2);
|
2004-02-16 05:35:06 +00:00
|
|
|
TABLE_LINE2( "NumTimesPlayed", iNumTimesPlayed );
|
2004-02-16 02:57:55 +00:00
|
|
|
END_TABLE;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Print Steps list
|
|
|
|
|
//
|
|
|
|
|
for( unsigned j=0; j<vpSteps.size(); j++ )
|
|
|
|
|
{
|
|
|
|
|
Steps* pSteps = vpSteps[j];
|
|
|
|
|
if( pSteps->IsAutogen() )
|
|
|
|
|
continue; // skip autogen
|
2004-02-16 05:35:06 +00:00
|
|
|
if( pProfile->GetStepsNumTimesPlayed(pSteps)==0 )
|
|
|
|
|
continue; // skip
|
|
|
|
|
|
2004-02-16 02:57:55 +00:00
|
|
|
const HighScoreList &hsl = pProfile->GetStepsHighScoreList( pSteps );
|
|
|
|
|
CString s =
|
|
|
|
|
GAMEMAN->NotesTypeToString(pSteps->m_StepsType) +
|
|
|
|
|
" - " +
|
|
|
|
|
DifficultyToString(pSteps->GetDifficulty());
|
|
|
|
|
PRINT_OPEN(f, s, true);
|
|
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(2);
|
|
|
|
|
TABLE_LINE2( "NumTimesPlayed", hsl.iNumTimesPlayed );
|
|
|
|
|
END_TABLE;
|
|
|
|
|
|
|
|
|
|
BEGIN_TABLE(2);
|
|
|
|
|
for( unsigned i=0; i<hsl.vHighScores.size(); i++ )
|
|
|
|
|
{
|
|
|
|
|
const HighScore &hs = hsl.vHighScores[i];
|
|
|
|
|
CString sName = ssprintf("#%d",i+1);
|
|
|
|
|
CString sHSName = hs.sName.empty() ? "????" : hs.sName;
|
|
|
|
|
CString sValue = ssprintf("%s, %s, %i, %.2f%%", sHSName.c_str(), GradeToString(hs.grade).c_str(), hs.iScore, hs.fPercentDP*100);
|
|
|
|
|
TABLE_LINE2( sName.c_str(), sValue );
|
|
|
|
|
}
|
|
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrintHighScoresForGroup(RageFile &f, const Profile *pProfile, CString sGroup )
|
|
|
|
|
{
|
|
|
|
|
PrintSongsInGroup( f, pProfile, sGroup, PrintHighScoresForSong );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrintHighScores( RageFile &f, const Profile *pProfile, CString sTitle, vector<Song*> &vpSongs, vector<Steps*> &vpAllSteps, vector<StepsType> &vStepsTypesToShow, map<Steps*,Song*> mapStepsToSong, vector<Course*> vpCourses )
|
|
|
|
|
{
|
|
|
|
|
PrintGroups( f, pProfile, sTitle, PrintHighScoresForGroup );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrintDifficultyTableForStepsType( RageFile &f, const Profile *pProfile, StepsType st )
|
|
|
|
|
{
|
|
|
|
|
unsigned i;
|
|
|
|
|
const vector<Song*> &vpSongs = SONGMAN->GetAllSongs();
|
|
|
|
|
|
|
|
|
|
PRINT_OPEN(f, GAMEMAN->NotesTypeToString(st).c_str() );
|
|
|
|
|
{
|
|
|
|
|
f.PutLine( "<table class='difficulty'>\n" );
|
|
|
|
|
|
|
|
|
|
// table header row
|
|
|
|
|
f.Write( "<tr><td> </td>" );
|
|
|
|
|
FOREACH_Difficulty( dc )
|
|
|
|
|
{
|
|
|
|
|
if( dc == DIFFICULTY_EDIT )
|
|
|
|
|
continue; // skip
|
|
|
|
|
f.PutLine( ssprintf("<td>%s</td>", Capitalize(DifficultyToString(dc).Left(3)).c_str()) );
|
|
|
|
|
}
|
|
|
|
|
f.PutLine( "</tr>" );
|
|
|
|
|
|
|
|
|
|
// table body rows
|
|
|
|
|
for( i=0; i<vpSongs.size(); i++ )
|
|
|
|
|
{
|
|
|
|
|
Song* pSong = vpSongs[i];
|
|
|
|
|
|
|
|
|
|
f.PutLine( "<tr>" );
|
|
|
|
|
|
|
|
|
|
f.Write( "<td>" );
|
|
|
|
|
f.Write( ssprintf("<p class='songtitle'>%s</p>", pSong->GetDisplayMainTitle().c_str()) );
|
|
|
|
|
f.Write( ssprintf("<p class='songsubtitle'>%s</p>", pSong->GetDisplaySubTitle().c_str()) );
|
|
|
|
|
f.Write( "</td>" );
|
|
|
|
|
|
|
|
|
|
FOREACH_Difficulty( dc )
|
|
|
|
|
{
|
|
|
|
|
if( dc == DIFFICULTY_EDIT )
|
|
|
|
|
continue; // skip
|
|
|
|
|
|
|
|
|
|
Steps* pSteps = pSong->GetStepsByDifficulty( st, dc, false );
|
|
|
|
|
if( pSteps )
|
|
|
|
|
f.PutLine( ssprintf("<td><p class='meter'>%d</p></td>",pSteps->GetMeter()) );
|
|
|
|
|
else
|
|
|
|
|
f.PutLine( "<td> </td>" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f.Write( "</tr>" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f.PutLine( "</table>\n" );
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrintDifficultyTable( RageFile &f, const Profile *pProfile, CString sTitle, vector<Song*> &vpSongs, vector<Steps*> &vpAllSteps, vector<StepsType> &vStepsTypesToShow, map<Steps*,Song*> mapStepsToSong, vector<Course*> vpCourses )
|
|
|
|
|
{
|
|
|
|
|
PrintStepsTypes( f, pProfile, sTitle, vStepsTypesToShow, PrintDifficultyTableForStepsType );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrintInventoryForSong( RageFile &f, const Profile *pProfile, Song* pSong )
|
|
|
|
|
{
|
|
|
|
|
vector<Steps*> vpSteps = pSong->GetAllSteps();
|
|
|
|
|
|
|
|
|
|
PRINT_OPEN(f, pSong->GetFullDisplayTitle().c_str() );
|
|
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(2);
|
|
|
|
|
TABLE_LINE2( "Artist", pSong->GetDisplayArtist() );
|
|
|
|
|
TABLE_LINE2( "GroupName", pSong->m_sGroupName );
|
|
|
|
|
float fMinBPM, fMaxBPM;
|
|
|
|
|
pSong->GetDisplayBPM( fMinBPM, fMaxBPM );
|
|
|
|
|
CString sBPM = (fMinBPM==fMaxBPM) ? ssprintf("%.1f",fMinBPM) : ssprintf("%.1f - %.1f",fMinBPM,fMaxBPM);
|
|
|
|
|
TABLE_LINE2( "BPM", sBPM );
|
|
|
|
|
TABLE_LINE2( "Credit", pSong->m_sCredit );
|
|
|
|
|
TABLE_LINE2( "MusicLength", SecondsToTime(pSong->m_fMusicLengthSeconds) );
|
|
|
|
|
TABLE_LINE2( "Lyrics", !pSong->m_sLyricsFile.empty() );
|
|
|
|
|
END_TABLE;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Print Steps list
|
|
|
|
|
//
|
|
|
|
|
for( unsigned j=0; j<vpSteps.size(); j++ )
|
|
|
|
|
{
|
|
|
|
|
Steps* pSteps = vpSteps[j];
|
|
|
|
|
if( pSteps->IsAutogen() )
|
|
|
|
|
continue; // skip autogen
|
|
|
|
|
CString s =
|
|
|
|
|
GAMEMAN->NotesTypeToString(pSteps->m_StepsType) +
|
|
|
|
|
" - " +
|
|
|
|
|
DifficultyToString(pSteps->GetDifficulty());
|
|
|
|
|
PRINT_OPEN(f, s, true); // use poister value as the hash
|
|
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(2);
|
|
|
|
|
TABLE_LINE2( "Description", pSteps->GetDescription() );
|
|
|
|
|
TABLE_LINE2( "Meter", pSteps->GetMeter() );
|
|
|
|
|
END_TABLE;
|
|
|
|
|
|
|
|
|
|
BEGIN_TABLE(2);
|
|
|
|
|
FOREACH_RadarCategory( cat )
|
|
|
|
|
{
|
|
|
|
|
CString sCat = RadarCategoryToString(cat);
|
|
|
|
|
float fVal = pSteps->GetRadarValues()[cat];
|
|
|
|
|
CString sVal = ssprintf( "%.2f", fVal );
|
|
|
|
|
TABLE_LINE2( sCat, sVal );
|
|
|
|
|
}
|
|
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrintInventoryForGroup( RageFile &f, const Profile *pProfile, CString sGroup )
|
|
|
|
|
{
|
|
|
|
|
PrintSongsInGroup( f, pProfile, sGroup, PrintInventoryForSong );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrintInventoryList( RageFile &f, const Profile *pProfile, CString sTitle, vector<Song*> &vpSongs, vector<Steps*> &vpAllSteps, vector<StepsType> &vStepsTypesToShow, map<Steps*,Song*> mapStepsToSong, vector<Course*> vpCourses )
|
|
|
|
|
{
|
|
|
|
|
PrintGroups( f, pProfile, sTitle, PrintInventoryForGroup );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrintBookkeeping( RageFile &f, const Profile *pProfile, CString sTitle, vector<Song*> &vpSongs, vector<Steps*> &vpAllSteps, vector<StepsType> &vStepsTypesToShow, map<Steps*,Song*> mapStepsToSong, vector<Course*> vpCourses)
|
|
|
|
|
{
|
|
|
|
|
PRINT_OPEN(f, sTitle );
|
|
|
|
|
{
|
|
|
|
|
// GetCoinsLastDays
|
|
|
|
|
{
|
|
|
|
|
int coins[NUM_LAST_DAYS];
|
|
|
|
|
BOOKKEEPER->GetCoinsLastDays( coins );
|
|
|
|
|
PRINT_OPEN(f, ssprintf("Coins for Last %d Days",NUM_LAST_DAYS), true );
|
|
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(4);
|
|
|
|
|
for( int i=0; i<NUM_LAST_DAYS; i++ )
|
|
|
|
|
{
|
|
|
|
|
CString sDay = (i==0) ? "Today" : ssprintf("%d day(s) ago",i);
|
|
|
|
|
TABLE_LINE2( sDay, coins[i] );
|
|
|
|
|
}
|
|
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetCoinsLastWeeks
|
|
|
|
|
{
|
|
|
|
|
int coins[NUM_LAST_WEEKS];
|
|
|
|
|
BOOKKEEPER->GetCoinsLastWeeks( coins );
|
|
|
|
|
PRINT_OPEN(f, ssprintf("Coins for Last %d Weeks",NUM_LAST_WEEKS), true );
|
|
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(4);
|
|
|
|
|
for( int i=0; i<NUM_LAST_WEEKS; i++ )
|
|
|
|
|
{
|
|
|
|
|
CString sWeek;
|
|
|
|
|
switch( i )
|
|
|
|
|
{
|
|
|
|
|
case 0: sWeek = "This week"; break;
|
|
|
|
|
case 1: sWeek = "Last week"; break;
|
|
|
|
|
default: sWeek = ssprintf("%d weeks ago",i); break;
|
|
|
|
|
}
|
|
|
|
|
TABLE_LINE2( sWeek, coins[i] );
|
|
|
|
|
}
|
|
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetCoinsByDayOfWeek
|
|
|
|
|
{
|
|
|
|
|
int coins[DAYS_IN_WEEK];
|
|
|
|
|
BOOKKEEPER->GetCoinsByDayOfWeek( coins );
|
|
|
|
|
PRINT_OPEN(f, "Coins by Day of Week", true );
|
|
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(4);
|
|
|
|
|
for( int i=0; i<DAYS_IN_WEEK; i++ )
|
|
|
|
|
{
|
|
|
|
|
CString sDay = DAY_OF_WEEK_TO_NAME[i];
|
|
|
|
|
TABLE_LINE2( sDay, coins[i] );
|
|
|
|
|
}
|
|
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetCoinsByHour
|
|
|
|
|
{
|
|
|
|
|
int coins[HOURS_PER_DAY];
|
|
|
|
|
BOOKKEEPER->GetCoinsByHour( coins );
|
|
|
|
|
PRINT_OPEN(f, ssprintf("Coins for Last %d Hours",HOURS_PER_DAY), true );
|
|
|
|
|
{
|
|
|
|
|
BEGIN_TABLE(4);
|
|
|
|
|
for( int i=0; i<HOURS_PER_DAY; i++ )
|
|
|
|
|
{
|
|
|
|
|
CString sHour = ssprintf("hour %d",i);
|
|
|
|
|
TABLE_LINE2( sHour, coins[i] );
|
|
|
|
|
}
|
|
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-16 09:23:34 +00:00
|
|
|
void PrintScreenshots( RageFile &f, const Profile *pProfile, CString sTitle, CString sProfileDir )
|
|
|
|
|
{
|
|
|
|
|
PRINT_OPEN(f, sTitle );
|
|
|
|
|
{
|
|
|
|
|
CStringArray asFiles;
|
|
|
|
|
GetDirListing( sProfileDir+"Screenshots/*.jpg", asFiles );
|
|
|
|
|
|
|
|
|
|
BEGIN_TABLE(2);
|
|
|
|
|
for( int i=0; i<asFiles.size(); i++ )
|
|
|
|
|
{
|
|
|
|
|
CString sFile = "Screenshots/"+asFiles[i];
|
|
|
|
|
|
|
|
|
|
CString sImgTag = ssprintf("<a href='%s' target='_new'><img class='screenshot' src='%s' width='160' height='120'></a>", sFile.c_str(), sFile.c_str() );
|
|
|
|
|
|
|
|
|
|
TABLE_LINE1( sImgTag );
|
|
|
|
|
}
|
|
|
|
|
END_TABLE;
|
|
|
|
|
}
|
|
|
|
|
PRINT_CLOSE(f);
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-16 02:57:55 +00:00
|
|
|
enum SaveType { SAVE_TYPE_PLAYER, SAVE_TYPE_MACHINE };
|
|
|
|
|
|
|
|
|
|
void SaveStatsWebPageToDir( CString sDir, SaveType saveType, const Profile *pProfile, const Profile *pProfileMachine )
|
|
|
|
|
{
|
|
|
|
|
CString fn = sDir + STATS_HTML;
|
|
|
|
|
|
|
|
|
|
LOG->Trace( "Writing %s ...", fn.c_str() );
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Open file
|
|
|
|
|
//
|
|
|
|
|
RageFile f;
|
|
|
|
|
if( !f.Open( fn, RageFile::WRITE ) )
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( "Couldn't open file '%s'", fn.c_str() );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Gather data
|
|
|
|
|
//
|
|
|
|
|
vector<Song*> vpSongs = SONGMAN->GetAllSongs();
|
|
|
|
|
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 );
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Calculate which StepTypes to show
|
|
|
|
|
//
|
|
|
|
|
vector<StepsType> vStepsTypesToShow;
|
|
|
|
|
{
|
|
|
|
|
for( StepsType st=(StepsType)0; st<NUM_STEPS_TYPES; st=(StepsType)(st+1) )
|
|
|
|
|
{
|
|
|
|
|
// don't show if there are no Steps of this StepsType
|
|
|
|
|
bool bOneSongHasStepsForThisStepsType = false;
|
|
|
|
|
for( unsigned i=0; i<vpSongs.size(); i++ )
|
|
|
|
|
{
|
|
|
|
|
Song* pSong = vpSongs[i];
|
|
|
|
|
vector<Steps*> vpSteps;
|
|
|
|
|
pSong->GetSteps( vpSteps, st, DIFFICULTY_INVALID, -1, -1, "", false );
|
|
|
|
|
if( !vpSteps.empty() )
|
|
|
|
|
{
|
|
|
|
|
bOneSongHasStepsForThisStepsType = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( bOneSongHasStepsForThisStepsType )
|
|
|
|
|
vStepsTypesToShow.push_back( st );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Print HTML headers
|
|
|
|
|
//
|
|
|
|
|
{
|
|
|
|
|
f.PutLine( ssprintf("\
|
|
|
|
|
<html>\n\
|
|
|
|
|
<head>\n\
|
|
|
|
|
<META HTTP-EQUIV=\"Content-Type\" Content=\"text/html; charset=UTF-8\">\n\
|
|
|
|
|
<title>%s</title>\n\
|
|
|
|
|
<SCRIPT LANGUAGE=\"JavaScript\" TYPE=\"text/javascript\">\n\
|
|
|
|
|
<!-- // hide from old browsers\n\
|
|
|
|
|
\n\
|
|
|
|
|
// hide text from MSIE browsers\n\
|
|
|
|
|
\n\
|
|
|
|
|
with (document)\n\
|
|
|
|
|
{\n\
|
|
|
|
|
write(\"<STYLE TYPE='text/css'>\");\n\
|
|
|
|
|
if (navigator.appName == 'Microsoft Internet Explorer')\n\
|
|
|
|
|
{\n\
|
|
|
|
|
write(\".hiddentext {display:none} .visibletext {display:block} .outline {cursor:hand; text-decoration:underline}\");\n\
|
|
|
|
|
}\n\
|
|
|
|
|
write(\"</STYLE>\");\n\
|
|
|
|
|
}\n\
|
|
|
|
|
\n\
|
|
|
|
|
// show text on click for MSIE browsers\n\
|
|
|
|
|
\n\
|
|
|
|
|
function expandIt(whichEl)\n\
|
|
|
|
|
{\n\
|
|
|
|
|
if (navigator.appName == 'Microsoft Internet Explorer')\n\
|
|
|
|
|
{\n\
|
|
|
|
|
whichEl.style.display = (whichEl.style.display == \"block\" ) ? \"none\" : \"block\";\n\
|
|
|
|
|
}\n\
|
|
|
|
|
else return;\n\
|
|
|
|
|
}\n\
|
|
|
|
|
// end hiding from old browsers -->\n\
|
|
|
|
|
</SCRIPT>\n\
|
|
|
|
|
<link rel='stylesheet' type='text/css' href='%s'>\n\
|
|
|
|
|
</head>\n\
|
|
|
|
|
<body>",
|
2004-02-16 09:23:34 +00:00
|
|
|
TITLE.c_str(), STYLE_CSS ) );
|
2004-02-16 02:57:55 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-16 05:35:06 +00:00
|
|
|
CString sType;
|
|
|
|
|
switch( saveType )
|
|
|
|
|
{
|
|
|
|
|
case SAVE_TYPE_PLAYER: sType = "Player: "; break;
|
|
|
|
|
case SAVE_TYPE_MACHINE: sType = "Machine: "; break;
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-16 02:57:55 +00:00
|
|
|
CString sName =
|
|
|
|
|
pProfile->m_sLastUsedHighScoreName.empty() ?
|
|
|
|
|
pProfile->m_sName :
|
|
|
|
|
pProfile->m_sLastUsedHighScoreName;
|
|
|
|
|
time_t ltime = time( NULL );
|
|
|
|
|
CString sTime = ctime( <ime );
|
|
|
|
|
|
|
|
|
|
f.Write( ssprintf(
|
2004-02-16 05:35:06 +00:00
|
|
|
"<table border='0' cellpadding='0' cellspacing='0' width='100%%' cellspacing='5'><tr><td><h1>%s</h1></td><td>%s %s<br>%s</td></tr></table>\n",
|
2004-02-16 09:23:34 +00:00
|
|
|
TITLE.c_str(), sType.c_str(), sName.c_str(), sTime.c_str() ) );
|
2004-02-16 02:57:55 +00:00
|
|
|
|
2004-02-16 05:35:06 +00:00
|
|
|
CString sPlayerName = pProfile->GetDisplayName();
|
|
|
|
|
CString sMachineName = pProfileMachine->GetDisplayName();
|
2004-02-16 02:57:55 +00:00
|
|
|
|
|
|
|
|
switch( saveType )
|
|
|
|
|
{
|
|
|
|
|
case SAVE_TYPE_PLAYER:
|
2004-02-16 05:35:06 +00:00
|
|
|
PrintStatistics( f, pProfile, sPlayerName+"'s Statistics", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
|
|
|
|
PrintPopularity( f, pProfile, sPlayerName+"'s Popularity", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
|
|
|
|
PrintHighScores( f, pProfile, sPlayerName+"'s High Scores", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
2004-02-16 09:23:34 +00:00
|
|
|
PrintScreenshots( f, pProfile, sPlayerName+"'s Screenshots", sDir );
|
2004-02-16 05:35:06 +00:00
|
|
|
PrintPopularity( f, pProfileMachine, sMachineName+"'s Popularity", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
|
|
|
|
PrintHighScores( f, pProfileMachine, sMachineName+"'s High Scores", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
2004-02-16 02:57:55 +00:00
|
|
|
break;
|
|
|
|
|
case SAVE_TYPE_MACHINE:
|
|
|
|
|
PrintStatistics( f, pProfile, "Statistics", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
|
|
|
|
PrintPopularity( f, pProfile, "Popularity", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
|
|
|
|
PrintHighScores( f, pProfile, "High Scores", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
|
|
|
|
PrintDifficultyTable( f, pProfile, "Difficulty Table", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
|
|
|
|
PrintInventoryList( f, pProfile, "Song Information", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
|
|
|
|
PrintBookkeeping( f, pProfile, "Bookkeeping", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-16 09:23:34 +00:00
|
|
|
f.PutLine( ssprintf("<p class='footer'>%s</p>\n", FOOTER.c_str()) );
|
2004-02-16 05:35:06 +00:00
|
|
|
|
2004-02-16 02:57:55 +00:00
|
|
|
f.PutLine( "</body>" );
|
|
|
|
|
f.PutLine( "</html>" );
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Copy CSS file from theme. If the copy fails, oh well...
|
|
|
|
|
//
|
|
|
|
|
CString sStyleFile = THEME->GetPathToO("ProfileManager style.css");
|
|
|
|
|
FileCopy( sStyleFile, sDir+STYLE_CSS );
|
|
|
|
|
LOG->Trace( "Done." );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SavePlayerHtmlToDir( CString sDir, const Profile* pProfilePlayer, const Profile* pProfileMachine )
|
|
|
|
|
{
|
|
|
|
|
SaveStatsWebPageToDir( sDir, SAVE_TYPE_PLAYER, pProfilePlayer, pProfileMachine );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SaveMachineHtmlToDir( CString sDir, const Profile* pProfileMachine )
|
|
|
|
|
{
|
|
|
|
|
SaveStatsWebPageToDir( sDir, SAVE_TYPE_MACHINE, pProfileMachine, pProfileMachine );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|