diff --git a/stepmania/src/CatalogXml.cpp b/stepmania/src/CatalogXml.cpp index 5aa54dd23c..50e1278fcc 100644 --- a/stepmania/src/CatalogXml.cpp +++ b/stepmania/src/CatalogXml.cpp @@ -10,12 +10,14 @@ #include "StepsUtil.h" #include "CourseUtil.h" #include "TrailUtil.h" +#include "GameState.h" +#include +#include "Foreach.h" -const CString CATALOG_XML = "Catalog.xml"; -void SaveCatalogXml( CString sDir ) +void SaveCatalogXml() { - CString fn = sDir + CATALOG_XML; + CString fn = CATALOG_XML_FILE; LOG->Trace( "Writing %s ...", fn.c_str() ); @@ -87,6 +89,29 @@ void SaveCatalogXml( CString sDir ) } } + { + XNode* pNode = xml.AppendChild( "DifficultiesToShow" ); + + set vDiffs; + GAMESTATE->GetDifficultiesToShow( vDiffs ); + for( set::const_iterator iter = vDiffs.begin(); iter != vDiffs.end(); iter++ ) + { + pNode->AppendChild( "Difficulty", DifficultyToString(*iter) ); + } + } + + { + XNode* pNode = xml.AppendChild( "CourseDifficultiesToShow" ); + + set vDiffs; + GAMESTATE->GetCourseDifficultiesToShow( vDiffs ); + for( set::const_iterator iter = vDiffs.begin(); iter != vDiffs.end(); iter++ ) + { + pNode->AppendChild( "CourseDifficulty", DifficultyToString(*iter) ); + } + } + + xml.SaveToFile(fn); LOG->Trace( "Done." ); diff --git a/stepmania/src/CatalogXml.h b/stepmania/src/CatalogXml.h index f000c0933d..e8dc9a972d 100644 --- a/stepmania/src/CatalogXml.h +++ b/stepmania/src/CatalogXml.h @@ -3,7 +3,12 @@ #ifndef CATALOG_XML_H #define CATALOG_XML_H -void SaveCatalogXml( CString sDir ); +#include "GameConstantsAndTypes.h" + +const CString CATALOG_XML = "Catalog.xml"; +const CString CATALOG_XML_FILE = DATA_DIR + "Catalog.xml"; + +void SaveCatalogXml(); #endif diff --git a/stepmania/src/GameConstantsAndTypes.h b/stepmania/src/GameConstantsAndTypes.h index 301c33d4eb..b1be05e6b9 100644 --- a/stepmania/src/GameConstantsAndTypes.h +++ b/stepmania/src/GameConstantsAndTypes.h @@ -297,7 +297,7 @@ const int ITEM_NONE = -1; #define BG_ANIMS_DIR CString("BGAnimations/") #define VISUALIZATIONS_DIR CString("Visualizations/") #define RANDOMMOVIES_DIR CString("RandomMovies/") - +#define DATA_DIR CString("Data/") // diff --git a/stepmania/src/GameState.cpp b/stepmania/src/GameState.cpp index 00b44a54f0..b7c3c4e8cf 100644 --- a/stepmania/src/GameState.cpp +++ b/stepmania/src/GameState.cpp @@ -1674,34 +1674,52 @@ bool GameState::ChangePreferredDifficulty( PlayerNumber pn, Difficulty dc ) return true; } -bool GameState::ChangePreferredDifficulty( PlayerNumber pn, int dir ) +void GameState::GetDifficultiesToShow( set &ret ) { - // FIXME: This clamps to between the min and the max difficulty, but - // it really should round to the nearest difficulty that's in - // DIFFICULTIES_TO_SHOW. - CStringArray asDiff; - split( DIFFICULTIES_TO_SHOW, ",", asDiff ); - Difficulty mind = (Difficulty)(NUM_DIFFICULTIES-1); - Difficulty maxd = (Difficulty)0; - for( unsigned i=0; i cache; + if( RageTimer::GetTimeSinceStart() < fExpiration ) { - Difficulty d = StringToDifficulty( asDiff[i] ); - if( d == DIFFICULTY_INVALID ) - continue; - - mind = min( mind, d ); - maxd = max( maxd, d ); + ret = cache; + return; } - Difficulty diff = (Difficulty)(m_PreferredDifficulty[pn]+dir); + CStringArray asDiff; + split( DIFFICULTIES_TO_SHOW, ",", asDiff ); + ASSERT( asDiff.size() > 0 ); - if( diff < mind || diff > maxd ) - return false; + cache.clear(); + for( unsigned i = 0; i < asDiff.size(); ++i ) + { + Difficulty d = StringToDifficulty(asDiff[i]); + if( d == DIFFICULTY_INVALID ) + RageException::Throw( "Unknown difficulty \"%s\" in CourseDifficultiesToShow", asDiff[i].c_str() ); + cache.insert( d ); + } - return ChangePreferredDifficulty( pn, diff ); + fExpiration = RageTimer::GetTimeSinceStart()+1; + ret = cache; } -static void GetCourseDifficultiesToShow( set &ret ) +bool GameState::ChangePreferredDifficulty( PlayerNumber pn, int dir ) +{ + set asDiff; + GetDifficultiesToShow( asDiff ); + + Difficulty d = m_PreferredDifficulty[pn]; + while( 1 ) + { + d = (Difficulty)(d+dir); + if( d < 0 || d >= NUM_DIFFICULTIES ) + return false; + if( asDiff.find(d) == asDiff.end() ) + continue; /* not available */ + } + + return ChangePreferredDifficulty( pn, d ); +} + +void GameState::GetCourseDifficultiesToShow( set &ret ) { static float fExpiration = -999; static set cache; @@ -1719,7 +1737,7 @@ static void GetCourseDifficultiesToShow( set &ret ) for( unsigned i = 0; i < asDiff.size(); ++i ) { CourseDifficulty cd = StringToCourseDifficulty(asDiff[i]); - if( cd == NUM_DIFFICULTIES ) + if( cd == DIFFICULTY_INVALID ) RageException::Throw( "Unknown difficulty \"%s\" in CourseDifficultiesToShow", asDiff[i].c_str() ); cache.insert( cd ); } diff --git a/stepmania/src/GameState.h b/stepmania/src/GameState.h index ead504cde6..779a41b5b4 100644 --- a/stepmania/src/GameState.h +++ b/stepmania/src/GameState.h @@ -13,6 +13,7 @@ #include #include +#include class Song; class Steps; @@ -288,6 +289,12 @@ public: // int m_iNumTimesThroughAttract; // negative means play regardless of m_iAttractSoundFrequency setting bool IsTimeToPlayAttractSounds(); + + // + // DifficultiesToShow stuff + // + void GetDifficultiesToShow( set &AddTo ); + void GetCourseDifficultiesToShow( set &AddTo ); }; diff --git a/stepmania/src/Makefile.am b/stepmania/src/Makefile.am index 63a2db8543..09b5d64d66 100644 --- a/stepmania/src/Makefile.am +++ b/stepmania/src/Makefile.am @@ -64,7 +64,7 @@ NoteFieldPositioning.cpp NoteFieldPositioning.h NoteTypes.cpp NoteTypes.h NotesL NotesLoaderBMS.cpp NotesLoaderBMS.h NotesLoaderDWI.cpp NotesLoaderDWI.h NotesLoaderKSF.cpp NotesLoaderKSF.h \ NotesLoaderSM.cpp NotesLoaderSM.h NotesWriterDWI.cpp NotesWriterDWI.h NotesWriterSM.cpp NotesWriterSM.h \ PlayerAI.cpp PlayerAI.h PlayerNumber.cpp PlayerNumber.h PlayerOptions.cpp PlayerOptions.h Profile.cpp Profile.h \ -ProfileHtml.cpp ProfileHtml.h RandomSample.cpp RandomSample.h ScoreKeeper.h ScoreKeeperMAX2.cpp ScoreKeeperMAX2.h \ +RandomSample.cpp RandomSample.h ScoreKeeper.h ScoreKeeperMAX2.cpp ScoreKeeperMAX2.h \ ScoreKeeperRave.cpp ScoreKeeperRave.h Song.cpp song.h SongCacheIndex.cpp SongCacheIndex.h \ SongOptions.cpp SongOptions.h SongUtil.cpp SongUtil.h StageStats.cpp StageStats.h Steps.cpp Steps.h \ StepsUtil.cpp StepsUtil.h Style.cpp Style.h \ diff --git a/stepmania/src/Profile.cpp b/stepmania/src/Profile.cpp index e0a671f41b..9f2b175ff9 100644 --- a/stepmania/src/Profile.cpp +++ b/stepmania/src/Profile.cpp @@ -14,7 +14,6 @@ #include #include "ThemeManager.h" #include "CryptManager.h" -#include "ProfileHtml.h" #include "ProfileManager.h" #include "RageFileManager.h" #include "ScoreKeeperMAX2.h" @@ -22,11 +21,13 @@ #include "UnlockSystem.h" #include "XmlFile.h" #include "Foreach.h" +#include "CatalogXml.h" // // Old file versions for backward compatibility // -#define SM_300_STATISTICS_INI "statistics.ini" +const CString STYLE_XSL = "Style.xsl"; +const CString STYLE_CSS = "Style.css"; #define GUID_SIZE_BYTES 8 @@ -678,7 +679,10 @@ bool Profile::SaveAllToDir( CString sDir, bool bSignData ) const xml.AppendChild( SaveAwardsCreateNode() ); xml.AppendChild( SaveRecentSongScoresCreateNode() ); xml.AppendChild( SaveRecentCourseScoresCreateNode() ); - bool bSaved = xml.SaveToFile(fn); + + DISP_OPT opts = optDefault; + opts.stylesheet = STYLE_XSL; + bool bSaved = xml.SaveToFile(fn, &opts); // Update file cache, or else IsAFile in CryptManager won't see this new file. FILEMAN->FlushDirCache( sDir ); @@ -1257,12 +1261,9 @@ void Profile::SaveStatsWebPageToDir( CString sDir ) const { ASSERT( PROFILEMAN ); - SaveStatsWebPage( - sDir, - this, - PROFILEMAN->GetMachineProfile(), - IsMachine() ? HTML_TYPE_MACHINE : HTML_TYPE_PLAYER - ); + FileCopy( THEME->GetPathO("Profile",STYLE_XSL), sDir+STYLE_XSL ); + FileCopy( THEME->GetPathO("Profile",STYLE_CSS), sDir+STYLE_CSS ); + FileCopy( CATALOG_XML_FILE, sDir+CATALOG_XML ); } void Profile::SaveMachinePublicKeyToDir( CString sDir ) const diff --git a/stepmania/src/ProfileHtml.cpp b/stepmania/src/ProfileHtml.cpp deleted file mode 100644 index fcd390b50a..0000000000 --- a/stepmania/src/ProfileHtml.cpp +++ /dev/null @@ -1,1527 +0,0 @@ -#include "global.h" -#include "ProfileHtml.h" -#include "ThemeManager.h" -#include "RageFile.h" -#include "RageLog.h" -#include "SongManager.h" -#include "song.h" -#include "Steps.h" -#include -#include "GameManager.h" -#include "Course.h" -#include "Bookkeeper.h" -#include "PrefsManager.h" -#include "CryptManager.h" -#include "UnlockSystem.h" -#include "RageUtil.h" -#include "SongUtil.h" -#include "StepsUtil.h" -#include "CourseUtil.h" -#include "GameState.h" - - -const CString STATS_HTML = "Stats.html"; -const CString STYLE_CSS = "Style.css"; - -#define TITLE THEME->GetMetric("ProfileHtml","Title") -#define FOOTER THEME->GetMetric("ProfileHtml","Footer") -#define VERIFICATION_TEXT THEME->GetMetric("ProfileHtml","VerificationText") -#define SHOW_PLAY_MODE(pm) THEME->GetMetricB("ProfileHtml","ShowPlayMode"+PlayModeToString(pm)) -#define SHOW_RADAR_CATEGORY(rc) THEME->GetMetricB("ProfileHtml","ShowRadarCategory"+RadarCategoryToString(rc)) -#define SHOW_DIFFICULTY(dc) THEME->GetMetricB("ProfileHtml","ShowDifficulty"+DifficultyToString(dc)) -#define STYLES_TO_SHOW THEME->GetMetric ("ProfileHtml","StylesToShow") -#define STEPS_TYPES_TO_SHOW THEME->GetMetric ("ProfileHtml","StepsTypesToShow") -#define SHOW_HIGH_SCORE_SCORE THEME->GetMetricB("ProfileHtml","ShowHighScoreScore") -#define SHOW_HIGH_SCORE_GRADE THEME->GetMetricB("ProfileHtml","ShowHighScoreGrade") -#define SHOW_HIGH_SCORE_PERCENT THEME->GetMetricB("ProfileHtml","ShowHighScorePercent") - -#define NEWLINE "\r\n" - -CString HighScoreToString( const HighScore& hs ) -{ - CStringArray asTokens; - asTokens.push_back( hs.sName.empty() ? "????" : hs.sName ); - if( SHOW_HIGH_SCORE_GRADE ) - asTokens.push_back( GradeToThemedString(hs.grade) ); - if( SHOW_HIGH_SCORE_SCORE ) - asTokens.push_back( ssprintf("%i", hs.iScore) ); - if( SHOW_HIGH_SCORE_PERCENT ) - asTokens.push_back( ssprintf("%05.2f%%", hs.fPercentDP*100) ); - - return join(", ",asTokens); -} - -void TranslatedWrite( RageFile &f, CString s ) -{ - s.Replace("\n",NEWLINE); - f.Write( s ); -} - -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); TranslatedWrite(f,ssprintf("
\n" "%s\n" "
\n", g_Level, g_Level, sID.c_str(), sName.c_str(), g_Level, sID.c_str(), bExpanded?"":" CLASS='hiddentext'") ); } -inline void PRINT_OPEN(RageFile &f,CString sName,bool bExpanded=false) { PRINT_OPEN(f,sName,bExpanded,MakeUniqueId()); } -inline void PRINT_CLOSE(RageFile &f) { TranslatedWrite(f, "
\n" "
\n" ); g_Level--; ASSERT(g_Level>=0); } - - -struct Table -{ - Table() {} - - struct Line - { - Line() {} - 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 = Commify(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); } - Line(int r,CString n,CString v) { sRank = ssprintf("%d",r); sName = n; sValue = v; } - Line(int r,CString n,CString sn,CString v) { sRank = ssprintf("%d",r); sName = n; sSubName = sn; sValue = v; } - Line(int r,CString n,CString sn,CString ssn,CString v) { sRank = ssprintf("%d",r); sName = n; sSubName = sn; sSubSubName = ssn; sValue = v; } - - CString sRank; - CString sName; - CString sSubName; - CString sSubSubName; - CString sValue; - }; - - int iNumCols; - vector vLines; -}; - -#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 ); } - -inline void PrintTable(RageFile &f,Table &table) -{ - const vector &vLines = table.vLines; - int &iNumCols = table.iNumCols; - - ASSERT( iNumCols > 0 ); - - if( vLines.empty() ) - return; - - bool bPrintRank = !vLines.empty() && !vLines[0].sRank.empty(); - bool bPrintInstructions = !vLines.empty() && vLines[0].sRank.empty() && vLines[0].sSubName.empty() && vLines[0].sSubSubName.empty() && vLines[0].sValue.empty(); - - int iMaxItemsPerCol = (vLines.size()+iNumCols-1) / iNumCols; - iNumCols = (vLines.size()+iMaxItemsPerCol-1) / iMaxItemsPerCol; // round up - TranslatedWrite(f,ssprintf("\n",bPrintInstructions?"instructions":"group")); - if( iNumCols == 0 ) - { - TranslatedWrite(f,"\n"); - } - for( int col=0; col\n"); - - int iStartItem = col*iMaxItemsPerCol; - - TranslatedWrite(f,"
empty
\n"); - for( int i=iStartItem; i"); - - const Table::Line& line = (i<(int)vLines.size()) ? vLines[i] : Table::Line(); - if( bPrintRank ) - { - TranslatedWrite(f,""); - TranslatedWrite(f,""); - } - if( bPrintRank ) - { - TranslatedWrite(f,""); - } - else if( line.sValue.empty() ) - { - TranslatedWrite(f,""); - } - else - { - TranslatedWrite(f,""); - } - - if( !line.sSubSubName.empty() ) - { - TranslatedWrite(f,""); - TranslatedWrite(f,""); - } - - if( !line.sValue.empty() ) - { - TranslatedWrite(f,""); - TranslatedWrite(f,""); - } - else - { - TranslatedWrite(f,""); - TranslatedWrite(f,""); - } - - TranslatedWrite(f, "\n" ); - - TranslatedWrite(f,"\n"); - } - TranslatedWrite(f,"
"); - TranslatedWrite(f, line.sRank ); - TranslatedWrite(f," "); - TranslatedWrite(f,"

"); - TranslatedWrite(f, line.sName ); - TranslatedWrite(f,"

"); - if( !line.sSubName.empty() ) - { - TranslatedWrite(f,"

"); - TranslatedWrite(f, line.sSubName ); - TranslatedWrite(f,"

"); - } - TranslatedWrite(f,"
"); - TranslatedWrite(f, line.sName ); - TranslatedWrite(f,""); - TranslatedWrite(f, line.sName ); - TranslatedWrite(f," "); - TranslatedWrite(f,"

"); - TranslatedWrite(f, line.sSubSubName ); - TranslatedWrite(f,"

"); - TranslatedWrite(f,"
 "); - TranslatedWrite(f, line.sValue ); - TranslatedWrite(f,"  
\n"); - - TranslatedWrite(f,"\n"); - } - TranslatedWrite(f,"\n\n"); -} - -void PrintEmptyTable( RageFile &f ) -{ - BEGIN_TABLE(1); - TABLE_LINE1("empty"); - END_TABLE; -} - -#define STRING_AS_LINK(s) CString(""+s+"") - -void PrintInstructions( RageFile &f, const Profile *pProfile, CString sTitle ) -{ - PRINT_OPEN(f,sTitle); - { - PRINT_OPEN(f,"Overview",true); - { - BEGIN_TABLE(1); - TABLE_LINE1("

This directory contains all your game profile data. Please read these instructions before modifying or moving any files on your memory card. Modifying files may result in irreversible loss of your data.

\n"); - END_TABLE; - } - PRINT_CLOSE(f); - - PRINT_OPEN(f,"Description of Files"); - { - BEGIN_TABLE(1); - TABLE_LINE2(STRING_AS_LINK(EDITS_SUBDIR), CString("Place edit step files in this directory. See the Edits section below for more details.")); - TABLE_LINE2(STRING_AS_LINK(SCREENSHOTS_SUBDIR), CString("All screenshots that you take are saved in this directory.")); - TABLE_LINE2(DONT_SHARE_SIG, CString("This is a secret file that you should never share with anyone else. See the Sharing Your Data section below for more details.")); - TABLE_LINE2(STRING_AS_LINK(EDITABLE_INI), CString("Holds preferences that you can edit offline using your home computer. This file is not digitally signed.")); - TABLE_LINE2(STATS_HTML, CString("You're looking at this file now. It contains a formatted view of all your saved data, plus some data from the last machine you played on.")); - TABLE_LINE2(STATS_HTML+SIGNATURE_APPEND, CString("The signature file for "+STATS_HTML+".")); - TABLE_LINE2(STRING_AS_LINK(STATS_XML), CString("This is the primary data file. It contains all the score data and statistics, and is read by the game when you join.")); - TABLE_LINE2(STATS_XML+SIGNATURE_APPEND, CString("The signature file for "+STATS_XML+".")); - TABLE_LINE2(STYLE_CSS, CString("Contains style data used by "+STATS_HTML+".")); - END_TABLE; - } - PRINT_CLOSE(f); - - PRINT_OPEN(f,"Digital Signatures"); - { - BEGIN_TABLE(1); - TABLE_LINE1("

Some files on your memory card have a corresponding digital signature. Digital signatures are used to verify that your files haven't been modified outside of the game. This prevents cheaters from changing their score data and then passing it off as real.

\n"); - TABLE_LINE1("

Before the game reads your memory card data, it verifies that your data and digital signatures match. If the data and signatures don't match, then your data has been modified outside of the game. When the game detects this condition, it will completely ignore your tampered data. It is very important that you -do not- modify any file that has a digital signature because this will cause your data to be permanently unusable.

\n"); - TABLE_LINE1("

If someone else shares their profile data with you, you can verify their score data using digital signatures. To verify their data, you'll need 3 things:

\n"); - TABLE_LINE1("

- the "+STATS_XML+" data file

\n"); - TABLE_LINE1("

- the digital signature file "+STATS_XML+SIGNATURE_APPEND+"

\n"); - TABLE_LINE1("

- a small utility that will check data against a signature

\n"); - END_TABLE; - } - PRINT_CLOSE(f); - - PRINT_OPEN(f,"About Editable Preferences"); - { - BEGIN_TABLE(1); - TABLE_LINE1("

The file "+STRING_AS_LINK(EDITABLE_INI)+" contains settings that you can modify using your home computer. If you're using a Windows PC, you can click here to open the file for editing. This file is not digitally signed and the game will import any changes you make to this file.

\n"); - END_TABLE; - } - PRINT_CLOSE(f); - - PRINT_OPEN(f,"About Screenshots"); - { - BEGIN_TABLE(1); - TABLE_LINE1("

The "+STRING_AS_LINK(SCREENSHOTS_SUBDIR)+" directory contains all screenshots that you've captured while playing the game. See the Screenshots section later on this page to see thumbnails and more information captured at the time of the screenshot. The Screenshots section also lists an MD5 hash of the screenshot file. You can use the MD5 has to verify that the screenshot has not been modified since it was first saved.

\n"); - TABLE_LINE1("

If your memory card is full, you may delete files from this directory or the move files to another disk. If you move a screenshot to another disk, you can still verify the screenshot file using the MD5 hash.

\n"); - END_TABLE; - } - PRINT_CLOSE(f); - - PRINT_OPEN(f,"About Edits"); - { - BEGIN_TABLE(1); - TABLE_LINE1("

The "+STRING_AS_LINK(EDITS_SUBDIR)+" directory contains edit step files that you've created yourself or downloaded from the internet. See here for more information about edit files.

\n"); - END_TABLE; - } - PRINT_CLOSE(f); - - PRINT_OPEN(f,"Sharing Your Data"); - { - BEGIN_TABLE(1); - TABLE_LINE1("

You can share your score data with other players or submit it to a web site for an internet ranking contest. When sharing your data though, do -not- share the file "+DONT_SHARE_SIG+". "+DONT_SHARE_SIG+" is private digital signature required by the game before loading memory card data. Without "+DONT_SHARE_SIG+", the person you're sharing data with can verify that your data is original, but can't load your data using their memory card or pass your scores off as their own.

\n"); - TABLE_LINE1("

If you do share your "+DONT_SHARE_SIG+" with someone, then they can completely replicate your memory card and pass your scores off as their own.

\n"); - END_TABLE; - } - PRINT_CLOSE(f); - - PRINT_OPEN(f,"Backing Up/Moving Your Data"); - { - BEGIN_TABLE(1); - TABLE_LINE1("

To make a backup of your data, copy the entire "+PREFSMAN->m_sMemoryCardProfileSubdir+"/ directory on the root of your memory card to your local hard drive.

\n"); - TABLE_LINE1("

To move your data from the current memory card to a new memory card, move the entire "+PREFSMAN->m_sMemoryCardProfileSubdir+"/ directory on your current memory card to the root directory on the new memory card.

\n"); - END_TABLE; - } - PRINT_CLOSE(f); - } - PRINT_CLOSE(f); -} - -void PrintStatistics( RageFile &f, const Profile *pProfile, CString sTitle, vector &vpSongs, vector &vpAllSteps, vector &vStepsTypesToShow, map mapStepsToSong, vector vpCourses ) -{ - /* We don't convert these to Style, because Style is game-specific and these strings - * affect all styles with the same name. */ - set StylesToShow; - { - CString sStyles = STYLES_TO_SHOW; - vector vStyles; - split( sStyles, ",", vStyles, true ); - for( unsigned i = 0; i < vStyles.size(); ++i ) - { - vStyles[i].MakeLower(); - StylesToShow.insert(vStyles[i]); - } - } - - PRINT_OPEN(f,sTitle,true); - { - PRINT_OPEN(f,"General Info",true); - { - BEGIN_TABLE(2); - TABLE_LINE2( "DisplayName", pProfile->m_sDisplayName.empty() ? CString("(empty)") : pProfile->m_sDisplayName ); - TABLE_LINE2( "ID", pProfile->m_sGuid ); - TABLE_LINE2( "LastUsedHighScoreName", pProfile->m_sLastUsedHighScoreName ); - TABLE_LINE2( "LastPlayedMachineID", pProfile->m_sLastPlayedMachineGuid ); - TABLE_LINE2( "UsingProfileDefaultModifiers", pProfile->m_bUsingProfileDefaultModifiers ); - PlayerOptions po; - po.FromString( pProfile->m_sDefaultModifiers ); - TABLE_LINE2( "DefaultModifiers", po.GetThemedString() ); - TABLE_LINE2( "TotalPlays", pProfile->m_iTotalPlays ); - TABLE_LINE2( "TotalPlay", SecondsToHHMMSS( (float) pProfile->m_iTotalPlaySeconds) ); - TABLE_LINE2( "TotalGameplay", SecondsToHHMMSS( (float) pProfile->m_iTotalGameplaySeconds) ); - TABLE_LINE2( "CurrentCombo", pProfile->m_iCurrentCombo ); - TABLE_LINE2( "TotalCaloriesBurned", pProfile->GetDisplayTotalCaloriesBurned() ); - TABLE_LINE2( "TotalTapsAndHolds", pProfile->m_iTotalTapsAndHolds ); - TABLE_LINE2( "TotalJumps", pProfile->m_iTotalJumps ); - TABLE_LINE2( "TotalHolds", pProfile->m_iTotalHolds ); - TABLE_LINE2( "TotalMines", pProfile->m_iTotalMines ); - TABLE_LINE2( "TotalHands", pProfile->m_iTotalHands ); - END_TABLE; - } - PRINT_CLOSE(f); - - - PRINT_OPEN(f,"Num Songs Played by PlayMode"); - { - BEGIN_TABLE(4); - FOREACH_PlayMode( pm ) - { - if( !SHOW_PLAY_MODE(pm) ) - continue; // skip - TABLE_LINE2( PlayModeToThemedString(pm), pProfile->m_iNumSongsPlayedByPlayMode[pm] ); - } - END_TABLE; - } - PRINT_CLOSE(f); - - - PRINT_OPEN(f,"Num Songs Played by Style"); - { - BEGIN_TABLE(4); - - for( map::const_iterator iter = pProfile->m_iNumSongsPlayedByStyle.begin(); - iter != pProfile->m_iNumSongsPlayedByStyle.end(); - iter++ ) - { - const Style* pStyle = iter->first; - int iNumTimesPlayed = iter->second; - StepsType st = pStyle->m_StepsType; - // only show if this style plays a StepsType that we're showing - if( find(vStepsTypesToShow.begin(),vStepsTypesToShow.end(),st) == vStepsTypesToShow.end() ) - continue; // skip - if( StylesToShow.find(pStyle->m_szName) == StylesToShow.end() ) - continue; - TABLE_LINE2( GAMEMAN->StyleToThemedString(pStyle), iNumTimesPlayed ); - } - END_TABLE; - } - PRINT_CLOSE(f); - - - PRINT_OPEN(f,"Num Songs Played by Difficulty"); - { - BEGIN_TABLE(4); - FOREACH_Difficulty( dc ) - { - if( !SHOW_DIFFICULTY(dc) ) - continue; - TABLE_LINE2( DifficultyToThemedString(dc), pProfile->m_iNumSongsPlayedByDifficulty[dc] ); - } - END_TABLE; - } - PRINT_CLOSE(f); - - PRINT_OPEN(f,"Num Songs Played by Meter"); - { - 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); - - PRINT_OPEN(f,"Grade Count"); - { - int iGradeCount[NUM_GRADES]; - ZERO( iGradeCount ); - - for( unsigned i=0; i vpSteps = pSong->GetAllSteps(); - - for( unsigned j=0; jGetStepsHighScoreList(pSong,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; gm_iNumGradeTiersUsed; g++ ) - TABLE_LINE2( GradeToThemedString((Grade)g), iGradeCount[g] ); - TABLE_LINE2( GradeToThemedString(GRADE_FAILED), iGradeCount[GRADE_FAILED] ); - END_TABLE; - } - PRINT_CLOSE(f); - - } - PRINT_CLOSE(f); -} - -void PrintPopularity( RageFile &f, const Profile *pProfile, CString sTitle, vector &vpSongs, vector &vpAllSteps, vector &vStepsTypesToShow, map mapStepsToSong, vector vpCourses ) -{ - PRINT_OPEN(f, sTitle ); - if( vpSongs.size() ) - { - SongUtil::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; - - unsigned uMaxToShow = min( vpSongs.size(), (unsigned)100 ); - - // compute total plays - int iTotalPlays = 0; - for( unsigned i=0; iGetSongNumTimesPlayed( vpSongs[i] ); - - - { - PRINT_OPEN(f, "Most Popular Songs" ); - { - BEGIN_TABLE(1); - unsigned i; - for( i=0; iGetSongNumTimesPlayed(pSong); - if( iNumTimesPlayed == 0 || iNumTimesPlayed < iPopularNumPlaysThreshold ) // not popular - break; // done searching - TABLE_LINE4(i+1, pSong->GetDisplayMainTitle(), pSong->GetDisplaySubTitle(), PrettyPercent(iNumTimesPlayed,iTotalPlays) ); - } - if( i == 0 ) - TABLE_LINE1("empty"); - END_TABLE; - } - PRINT_CLOSE(f); - } - - { - SongUtil::SortSongPointerArrayByNumPlays( vpSongs, pProfile, false ); - PRINT_OPEN(f, "Least Popular Songs" ); - { - BEGIN_TABLE(1); - unsigned i; - for( i=0; iGetSongNumTimesPlayed(pSong); - if( iNumTimesPlayed >= iPopularNumPlaysThreshold ) // not unpopular - break; // done searching - TABLE_LINE4(i+1, pSong->GetDisplayMainTitle(), pSong->GetDisplaySubTitle(), PrettyPercent(iNumTimesPlayed,iTotalPlays) ); - } - if( i == 0 ) - TABLE_LINE1("empty"); - END_TABLE; - } - PRINT_CLOSE(f); - } - - { - unsigned uNumToShow = min( vpAllSteps.size(), (unsigned)100 ); - - StepsUtil::SortStepsPointerArrayByNumPlays( vpAllSteps, pProfile, true ); - PRINT_OPEN(f, "Most Popular Steps" ); - { - BEGIN_TABLE(1); - unsigned i; - for( i=0; iGetStepsNumTimesPlayed(pSong,pSteps); - if( iNumTimesPlayed==0 ) - continue; // skip - CString s; - s += GAMEMAN->NotesTypeToThemedString(pSteps->m_StepsType); - s += " "; - s += DifficultyToThemedString(pSteps->GetDifficulty()); - TABLE_LINE5(i+1, pSong->GetDisplayMainTitle(), pSong->GetDisplaySubTitle(), s, PrettyPercent(iNumTimesPlayed,iTotalPlays) ); - } - if( i == 0 ) - TABLE_LINE1("empty"); - END_TABLE; - } - PRINT_CLOSE(f); - } - - { - unsigned uNumToShow = min( vpCourses.size(), (unsigned)100 ); - - CourseUtil::SortCoursePointerArrayByNumPlays( vpCourses, pProfile, true ); - PRINT_OPEN(f, "Most Popular Courses" ); - { - BEGIN_TABLE(2); - unsigned i; - for( i=0; iGetCourseNumTimesPlayed(pCourse); - TABLE_LINE3(i+1, pCourse->m_sName, PrettyPercent(iNumTimesPlayed,iTotalPlays) ); - } - if( i == 0 ) - TABLE_LINE1("empty"); - END_TABLE; - } - PRINT_CLOSE(f); - } - } - PRINT_CLOSE(f); -} - - -// return true if anything was printed -typedef bool (*FnPrintSong)(RageFile &f, const Profile *pProfile, Song* pSong ); -typedef bool (*FnPrintGroup)(RageFile &f, const Profile *pProfile, CString sGroup ); -typedef bool (*FnPrintStepsType)(RageFile &f, const Profile *pProfile, StepsType st ); -typedef bool (*FnPrintCourse)(RageFile &f, const Profile *pProfile, Course* pCourse ); - - -bool PrintSongsInGroup( RageFile &f, const Profile *pProfile, CString sGroup, FnPrintSong pFn ) -{ - vector vpSongs; - SONGMAN->GetSongs( vpSongs, sGroup ); - - if( vpSongs.empty() ) - return false; - - PRINT_OPEN(f, sGroup ); - { - bool bPrintedAny = false; - for( unsigned i=0; iGetGroupNames( asGroups ); - - if( asGroups.empty() ) - return false; - - PRINT_OPEN(f, sTitle ); - { - bool bPrintedAny = false; - - for( unsigned g=0; g vpCourses; - SONGMAN->GetAllCourses( vpCourses, true ); - - if( vpCourses.empty() ) - return false; - - PRINT_OPEN(f, sTitle ); - { - bool bPrintedAny = false; - - for( unsigned c=0; c vStepsTypesToShow, FnPrintStepsType pFn ) -{ - PRINT_OPEN(f, sTitle ); - { - for( unsigned s=0; sNeverDisplayed() || UNLOCKMAN->SongIsLocked(pSong) ) - return false; // skip - int iNumTimesPlayed = pProfile->GetSongNumTimesPlayed(pSong); - if( iNumTimesPlayed == 0 ) - return false; // skip - - vector vpSteps = pSong->GetAllSteps(); - - bool bPrintedOpen = false; - - { - // - // Print Steps list - // - for( unsigned j=0; jIsAutogen() ) - continue; // skip autogen - if( pProfile->GetStepsNumTimesPlayed(pSong,pSteps)==0 ) - continue; // skip - const HighScoreList &hsl = pProfile->GetStepsHighScoreList( pSong,pSteps ); - if( hsl.vHighScores.empty() ) - continue; - - if( !bPrintedOpen ) - { - PRINT_OPEN(f, pSong->GetFullDisplayTitle() ); - bPrintedOpen = true; - } - - CString s = - GAMEMAN->NotesTypeToThemedString(pSteps->m_StepsType) + - " - " + - DifficultyToThemedString(pSteps->GetDifficulty()); - PRINT_OPEN(f, s, true); - { - PrintHighScoreListTable( f, hsl ); - } - PRINT_CLOSE(f); - } - } - if( bPrintedOpen ) - PRINT_CLOSE(f); - - return bPrintedOpen; -} - -bool PrintHighScoresForCourse( RageFile &f, const Profile *pProfile, Course* pCourse ) -{ - bool bPrintedAny = false; - - FOREACH_StepsType( st ) - { - FOREACH_ShownCourseDifficulty( cd ) - { - Trail *pTrail = pCourse->GetTrail( st, cd ); - if( pTrail == NULL ) - continue; - - const HighScoreList &hsl = pProfile->GetCourseHighScoreList( pCourse, pTrail ); - if( hsl.vHighScores.empty() ) - continue; - - bPrintedAny = true; - - PRINT_OPEN(f, GAMEMAN->NotesTypeToThemedString(st)+" - "+CourseDifficultyToThemedString(cd) ); - { - PrintHighScoreListTable( f, hsl ); - } - PRINT_CLOSE(f); - } - } - - return bPrintedAny; -} - -bool PrintHighScoresForGroup(RageFile &f, const Profile *pProfile, CString sGroup ) -{ - return PrintSongsInGroup( f, pProfile, sGroup, PrintHighScoresForSong ); -} - -void PrintSongHighScores( RageFile &f, const Profile *pProfile, CString sTitle, vector &vpSongs, vector &vpAllSteps, vector &vStepsTypesToShow, map mapStepsToSong, vector vpCourses ) -{ - PrintGroups( f, pProfile, sTitle, PrintHighScoresForGroup ); -} - -void PrintCourseHighScores( RageFile &f, const Profile *pProfile, CString sTitle, vector &vpSongs, vector &vpAllSteps, vector &vStepsTypesToShow, map mapStepsToSong, vector vpCourses ) -{ - PrintCourses( f, pProfile, sTitle, PrintHighScoresForCourse ); -} - -bool PrintPercentCompleteForStepsType( RageFile &f, const Profile *pProfile, StepsType st ) -{ - unsigned i; - const vector &vpSongs = SONGMAN->GetAllSongs(); - vector vpCourses; - SONGMAN->GetAllCourses( vpCourses, true ); - - PRINT_OPEN(f, GAMEMAN->NotesTypeToThemedString(st) ); - { - FOREACH_Difficulty( dc ) - { - if( dc == DIFFICULTY_EDIT ) - continue; // skip - if( !SHOW_DIFFICULTY(dc) ) - continue; - BEGIN_TABLE(1); - { - const int iActualSong = pProfile->GetActualSongDancePoints(st,dc); - const int iPossibleSong = pProfile->GetPossibleSongDancePoints(st,dc); - const float fPercent = float(iActualSong) / (iPossibleSong); - CString sDifficulty = DifficultyToThemedString(dc); - TABLE_LINE2( sDifficulty+" Percent Complete", ssprintf("%06.3f%%", fPercent*100) ); - TABLE_LINE2( sDifficulty+" Actual Song Points", iActualSong ); - TABLE_LINE2( sDifficulty+" Possible Song Points", iPossibleSong ); - } - END_TABLE; - } - - PRINT_OPEN(f, "Songs" ); - { - TranslatedWrite(f, "\n" ); - - // table header row - TranslatedWrite(f, "" ); - FOREACH_Difficulty( dc ) - { - if( dc == DIFFICULTY_EDIT ) - continue; // skip - if( !SHOW_DIFFICULTY(dc) ) - continue; - TranslatedWrite(f, ssprintf("", DifficultyToThemedString(dc).c_str()) ); - } - TranslatedWrite(f, "\n" ); - - // table body rows - for( i=0; im_SelectionDisplay == Song::SHOW_NEVER ) - continue; // skip - if( UNLOCKMAN->SongIsLocked(pSong) ) - continue; - - TranslatedWrite(f, "" ); - - TranslatedWrite(f, "" ); - - FOREACH_Difficulty( dc ) - { - if( dc == DIFFICULTY_EDIT ) - continue; // skip - if( !SHOW_DIFFICULTY(dc) ) - continue; - Steps* pSteps = pSong->GetStepsByDifficulty( st, dc, false ); - if( pSteps && !pSteps->IsAutogen() ) - { - TranslatedWrite(f,""); - } - else - { - TranslatedWrite(f, "" ); - } - } - - TranslatedWrite(f, "\n" ); - } - - TranslatedWrite(f, "
 %s
" ); - TranslatedWrite(f, ssprintf("

%s

", pSong->GetDisplayMainTitle().c_str()) ); - TranslatedWrite(f, ssprintf("

%s

", pSong->GetDisplaySubTitle().c_str()) ); - TranslatedWrite(f, "
"); - TranslatedWrite(f, ssprintf("(%d)",pSteps->GetMeter()) ); - HighScore hs = pProfile->GetStepsHighScoreList( pSong,pSteps ).GetTopScore(); - Grade grade = hs.grade; - if( grade != GRADE_NO_DATA ) - { - TranslatedWrite(f, ssprintf(" %s %05.2f%%",GradeToThemedString(grade).c_str(), hs.fPercentDP*100) ); - } - TranslatedWrite(f," 
\n" ); - } - PRINT_CLOSE(f); - - FOREACH_ShownCourseDifficulty( cd ) - { - BEGIN_TABLE(1); - { - const int iActualCourse = pProfile->GetActualCourseDancePoints(st,cd); - const int iPossibleCourse = pProfile->GetPossibleCourseDancePoints(st,cd); - const float fPercent = float(iActualCourse) / (iPossibleCourse); - TABLE_LINE2( CourseDifficultyToThemedString(cd)+" Percent Complete", ssprintf("%06.3f%%", fPercent*100) ); - TABLE_LINE2( CourseDifficultyToThemedString(cd)+" Actual Course Points", iActualCourse ); - TABLE_LINE2( CourseDifficultyToThemedString(cd)+" Possible Course Points", iPossibleCourse ); - } - END_TABLE; - } - - PRINT_OPEN(f, "Courses" ); - { - TranslatedWrite(f, "\n" ); - - // table header row - TranslatedWrite(f, "" ); - FOREACH_ShownCourseDifficulty( cd ) - { - TranslatedWrite(f, ssprintf("", CourseDifficultyToThemedString(cd).c_str()) ); - } - TranslatedWrite(f, "\n" ); - - // table body rows - for( i=0; iAllSongsAreFixed() ) - continue; - - TranslatedWrite(f, "" ); - - TranslatedWrite(f, "" ); - - FOREACH_ShownCourseDifficulty( cd ) - { - Trail *pTrail = pCourse->GetTrail( st, cd ); - if( pTrail ) - { - TranslatedWrite(f,""); - } - else - { - TranslatedWrite(f, "" ); - } - } - - TranslatedWrite(f, "\n" ); - } - - TranslatedWrite(f, "
 %s
" ); - TranslatedWrite(f, ssprintf("

%s

", pCourse->m_sName.c_str()) ); - TranslatedWrite(f, "
"); - int iMeter = pTrail->GetMeter(); - TranslatedWrite(f, ssprintf("(%d)",iMeter) ); - HighScore hs = pProfile->GetCourseHighScoreList(pCourse,pTrail).GetTopScore(); - Grade grade = hs.grade; - if( grade != GRADE_NO_DATA ) - { - TranslatedWrite(f, ssprintf(" %s %05.2f%%",GradeToThemedString(grade).c_str(), hs.fPercentDP*100) ); - } - TranslatedWrite(f," 
\n" ); - } - PRINT_CLOSE(f); - } - PRINT_CLOSE(f); - - return true; -} - -void PrintPercentComplete( RageFile &f, const Profile *pProfile, CString sTitle, vector &vpSongs, vector &vpAllSteps, vector &vStepsTypesToShow, map mapStepsToSong, vector vpCourses ) -{ - PrintStepsTypes( f, pProfile, sTitle, vStepsTypesToShow, PrintPercentCompleteForStepsType ); -} - -bool PrintRecentScores( RageFile &f, const Profile *pProfile, CString sTitle, vector &vpSongs, vector &vpAllSteps, vector &vStepsTypesToShow, map mapStepsToSong, vector vpCourses ) -{ - PRINT_OPEN(f, sTitle ); - { - PRINT_OPEN(f, "Songs" ); - { - for( unsigned i=0; im_vRecentStepsScores.size(); i++ ) - { - const Profile::HighScoreForASongAndSteps hsfas = pProfile->m_vRecentStepsScores[i]; - - BEGIN_TABLE(1); - TABLE_LINE2( "Song", hsfas.songID.ToString() ); - TABLE_LINE2( "Steps", hsfas.stepsID.ToString() ); - TABLE_LINE2( "Results", HighScoreToString(hsfas.hs) ); - END_TABLE; - } - if( pProfile->m_vRecentStepsScores.empty() ) - PrintEmptyTable(f); - } - PRINT_CLOSE(f); - - PRINT_OPEN(f, "Courses" ); - { - for( unsigned i=0; im_vRecentCourseScores.size(); i++ ) - { - const Profile::HighScoreForACourse hsfac = pProfile->m_vRecentCourseScores[i]; - - BEGIN_TABLE(1); - TABLE_LINE2( "Course", hsfac.courseID.ToString() ); - TABLE_LINE2( "Results", HighScoreToString(hsfac.hs) ); - END_TABLE; - } - if( pProfile->m_vRecentCourseScores.empty() ) - PrintEmptyTable(f); - } - PRINT_CLOSE(f); - } - PRINT_CLOSE(f); - - return true; -} - -/* (experimental) Short-term internal cache timer. */ -struct CacheTimer -{ - float fExpiration, fDuration; - CacheTimer( float duration = 1 ) { fExpiration = -999; fDuration = duration; } - - /* Return true if the timer has expired (fDuration has elapsed since the last - * true IsExpired call) or if this is the first call. */ - bool IsExpired() - { - float fNow = RageTimer::GetTimeSinceStart(); - if( fNow < fExpiration ) - return false; - fExpiration = fNow + fDuration; - return true; - } -}; - -bool PrintCatalogForSong( RageFile &f, const Profile *pProfile, Song* pSong ) -{ - if( pSong->NeverDisplayed() || UNLOCKMAN->SongIsLocked(pSong) ) - return false; // skip - - vector vpSteps = pSong->GetAllSteps(); - - static bool bShowRadarCategory[NUM_RADAR_CATEGORIES]; - static CString sThemedRadarCategory[NUM_RADAR_CATEGORIES]; - - static CacheTimer timer; - if( timer.IsExpired() ) - { - FOREACH_RadarCategory(rc) - { - bShowRadarCategory[rc] = SHOW_RADAR_CATEGORY(rc); - sThemedRadarCategory[rc] = RadarCategoryToThemedString(rc); - } - } - - PRINT_OPEN(f, pSong->GetFullDisplayTitle() ); - { - BEGIN_TABLE(2); - TABLE_LINE2( "Artist", pSong->GetDisplayArtist() ); - TABLE_LINE2( "GroupName", pSong->m_sGroupName ); - DisplayBpms bpms; - pSong->GetDisplayBpms( bpms ); - CString sBPM = (bpms.BpmIsConstant()) ? ssprintf("%.1f",bpms.GetMin()) : ssprintf("%.1f - %.1f",bpms.GetMin(),bpms.GetMax()); - TABLE_LINE2( "BPM", sBPM ); - TABLE_LINE2( "Credit", pSong->m_sCredit ); - TABLE_LINE2( "MusicLength", SecondsToMMSSMsMs(pSong->m_fMusicLengthSeconds) ); - TABLE_LINE2( "Lyrics", pSong->HasLyrics() ); - TABLE_LINE2( "NumTimesPlayed", pProfile->GetSongNumTimesPlayed(pSong) ); - END_TABLE; - - // - // Print Steps list - // - for( unsigned j=0; jIsAutogen() ) - continue; // skip autogen - CString s = - GAMEMAN->NotesTypeToThemedString(pSteps->m_StepsType) + - " - " + - DifficultyToThemedString(pSteps->GetDifficulty()); - PRINT_OPEN(f, s, true); // use poister value as the hash - { - BEGIN_TABLE(3); - TABLE_LINE2( "Meter", pSteps->GetMeter() ); - TABLE_LINE2( "Description", pSteps->GetDescription() ); - TABLE_LINE2( "NumTimesPlayed", pProfile->GetStepsNumTimesPlayed(pSong,pSteps) ); - END_TABLE; - - BEGIN_TABLE(2); - - FOREACH_RadarCategory( cat ) - { - if( !bShowRadarCategory[cat] ) - continue; // skip - - const CString &sCat = sThemedRadarCategory[cat]; - float fVal = pSteps->GetRadarValues()[cat]; - CString sVal = ssprintf( "%05.2f", fVal ); - TABLE_LINE2( sCat, sVal ); - } - END_TABLE; - } - PRINT_CLOSE(f); - } - } - PRINT_CLOSE(f); - - return true; -} - -bool PrintCatalogForGroup( RageFile &f, const Profile *pProfile, CString sGroup ) -{ - return PrintSongsInGroup( f, pProfile, sGroup, PrintCatalogForSong ); -} - -void PrintCatalogList( RageFile &f, const Profile *pProfile, CString sTitle, vector &vpSongs, vector &vpAllSteps, vector &vStepsTypesToShow, map mapStepsToSong, vector vpCourses ) -{ - PrintGroups( f, pProfile, sTitle, PrintCatalogForGroup ); -} - -void PrintBookkeeping( RageFile &f, const Profile *pProfile, CString sTitle, vector &vpSongs, vector &vpAllSteps, vector &vStepsTypesToShow, map mapStepsToSong, vector 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; iGetCoinsLastWeeks( coins ); - PRINT_OPEN(f, ssprintf("Coins for Last %d Weeks",NUM_LAST_WEEKS), true ); - { - BEGIN_TABLE(4); - for( int i=0; iGetCoinsByDayOfWeek( coins ); - PRINT_OPEN(f, "Coins by Day of Week", true ); - { - BEGIN_TABLE(4); - for( int i=0; iGetCoinsByHour( coins ); - PRINT_OPEN(f, ssprintf("Coins for Last %d Hours",HOURS_IN_DAY), true ); - { - BEGIN_TABLE(4); - for( int i=0; i", sImagePath.c_str(), sImagePath.c_str() ); - - - TranslatedWrite(f,"\n"); - TranslatedWrite(f,"\n"); - TranslatedWrite(f,"\n"); - TranslatedWrite(f,"\n"); - - TranslatedWrite(f,"
"+sImgHtml+"\n"); - - BEGIN_TABLE(1); - - TABLE_LINE2( "File", ss.sFileName ); - TABLE_LINE2( "MD5", ss.sMD5 ); - TABLE_LINE2( "Results", HighScoreToString(ss.highScore) ); - - END_TABLE; - - TranslatedWrite(f,"
\n"); -} - -void PrintScreenshots( RageFile &f, const Profile *pProfile, CString sTitle, CString sProfileDir ) -{ - PRINT_OPEN(f, sTitle ); - { - CString sCurrentMonth; - bool bFirstMonth = true; - - for( int i = (int)pProfile->m_vScreenshots.size()-1; i >= 0; i-- ) - { - Screenshot ss = pProfile->m_vScreenshots[i]; - tm new_time; - localtime_r( &ss.highScore.time, &new_time ); - int iYear = new_time.tm_year+1900; - int iMonth = new_time.tm_mon+1; - CString sNewMonth = ssprintf("%02d/%d", iMonth, iYear ); - - if( sNewMonth != sCurrentMonth ) - { - if( !bFirstMonth ) - PRINT_CLOSE(f); - PRINT_OPEN(f, sNewMonth, bFirstMonth); - } - PrintScreenshot( f, ss ); - - sCurrentMonth = sNewMonth; - bFirstMonth = false; - } - - if( pProfile->m_vScreenshots.empty() ) - { - PrintEmptyTable(f); - } - else - { - PRINT_CLOSE(f); - } - } - PRINT_CLOSE(f); -} - -void PrintCaloriesBurned( RageFile &f, const Profile *pProfile, CString sTitle, CString sProfileDir ) -{ - PRINT_OPEN(f, sTitle ); - { - PRINT_OPEN(f, "Totals", true); - { - BEGIN_TABLE(1); - - TABLE_LINE2("All Time", pProfile->GetDisplayTotalCaloriesBurned() ); - TABLE_LINE2("Per Song", ssprintf("%.2f",pProfile->m_fTotalCaloriesBurned/pProfile->GetTotalNumSongsPlayed()) ); - TABLE_LINE2("Per Second of Gameplay", ssprintf("%.2f",pProfile->m_fTotalCaloriesBurned/(float)pProfile->m_iTotalGameplaySeconds) ); - - END_TABLE; - } - PRINT_CLOSE(f); - - PRINT_OPEN(f, "By Week", false); - { - BEGIN_TABLE(4); - - // row for each week - tm when = GetLocalTime(); - when = GetNextSunday( when ); - when = AddDays( when, -DAYS_IN_WEEK ); - { - for( int w=0; wGetCaloriesBurnedForDay( day ); - fWeekCals += fDayCals; - when = AddDays( when, +1 ); - } - - TABLE_LINE2(LastWeekToString(w), Commify((int)fWeekCals) ); - - when = AddDays( when, -DAYS_IN_WEEK*2 ); - } - } - - END_TABLE; - } - PRINT_CLOSE(f); - - PRINT_OPEN(f, "By Day of Week", false); - { - float fCaloriesByDay[DAYS_IN_WEEK]; - ZERO( fCaloriesByDay ); - - // row for each week - tm when = GetLocalTime(); - when = GetNextSunday( when ); - when = AddDays( when, -DAYS_IN_WEEK ); - for( int w=0; wGetCaloriesBurnedForDay( day ); - fCaloriesByDay[d] += fDayCals; - when = AddDays( when, +1 ); - } - - when = AddDays( when, -DAYS_IN_WEEK*2 ); - } - - BEGIN_TABLE(2); - - for( int d=0; dTrace( "Writing %s ...", fn.c_str() ); - - // - // Open file - // - RageFile f; - if( !f.Open( fn, RageFile::WRITE ) ) - { - LOG->Warn( "Couldn't open file \"%s\": %s", fn.c_str(), f.GetError().c_str() ); - return; - } - - // - // Gather data - // - vector vpSongs = SONGMAN->GetAllSongs(); - vector vpAllSteps; - map mapStepsToSong; - for( unsigned i=0; i vpSteps = pSong->GetAllSteps(); - for( unsigned j=0; jIsAutogen() ) - continue; // skip - vpAllSteps.push_back( pSteps ); - mapStepsToSong[pSteps] = pSong; - } - } - vector vpCourses; - SONGMAN->GetAllCourses( vpCourses, false ); - - // - // Calculate which StepTypes to show - // - vector vStepsTypesToShow; - { - CString sShow = STEPS_TYPES_TO_SHOW; - vector vTypes; - split( sShow, ",", vTypes, true ); - for( unsigned i = 0; i < vTypes.size(); ++i ) - { - StepsType st = GAMEMAN->StringToNotesType( vTypes[i] ); - if( st == STEPS_TYPE_INVALID ) - { - LOG->Warn( "ProfileHtml::StepsTypesToShow: unknown steps type \"%s\"", vTypes[i].c_str() ); - continue; - } - - vStepsTypesToShow.push_back( st ); - } - } - - for( unsigned i = 0; i < vStepsTypesToShow.size(); ++i ) - { - StepsType st = vStepsTypesToShow[i]; - - // don't show if there are no Steps of this StepsType - bool bOneSongHasStepsForThisStepsType = false; - for( unsigned j=0; j vpSteps; - pSong->GetSteps( vpSteps, st, DIFFICULTY_INVALID, -1, -1, "", false ); - if( !vpSteps.empty() ) - { - bOneSongHasStepsForThisStepsType = true; - break; - } - } - if( !bOneSongHasStepsForThisStepsType ) - { - vStepsTypesToShow.erase( vStepsTypesToShow.begin()+i ); - --i; - continue; - } - } - - // - // Print HTML headers - // - { - TranslatedWrite(f, ssprintf("\ -\n\ -\n\ -\n\ -%s\n\ -\n\ -\n\ -\n\ -\n\ -", -TITLE.c_str(), STYLE_CSS.c_str() ) ); - } - - CString sName = pProfile->GetDisplayName(); - time_t ltime = time( NULL ); - CString sTime = ctime( <ime ); - - CString sNameCell; - switch( htmlType ) - { - case HTML_TYPE_PLAYER: - sNameCell = ssprintf( - "%s
\n" - "%s\n", - sName.c_str(), sTime.c_str() ); - break; - case HTML_TYPE_MACHINE: - sNameCell = ssprintf( - "Machine: %s
\n" - "%s\n", - sName.c_str(), sTime.c_str() ); - break; - default: - ASSERT(0); - } - - TranslatedWrite(f, ssprintf( - "\n

%s

%s
\n", - TITLE.c_str(), sNameCell.c_str() ) ); - - switch( htmlType ) - { - case HTML_TYPE_PLAYER: - PrintInstructions( f, pProfile, "Instructions" ); - PrintStatistics( f, pProfile, "My Statistics", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - PrintPopularity( f, pProfile, "My Popularity", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - PrintSongHighScores( f, pProfile, "My Song High Scores", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - PrintCourseHighScores( f, pProfile, "My Course High Scores", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - PrintScreenshots( f, pProfile, "My Screenshots", sDir ); - PrintCaloriesBurned( f, pProfile, "My Calories Burned", sDir ); - PrintPercentComplete( f, pProfile, "My Percent Complete", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - PrintRecentScores( f, pProfile, "My Recent Scores", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - PrintPopularity( f, pProfile, "Last Machine's Popularity", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - PrintSongHighScores( f, pProfile, "Last Machine's Song High Scores", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - PrintCourseHighScores( f, pProfile, "Last Machine's Course High Scores",vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - break; - case HTML_TYPE_MACHINE: - PrintStatistics( f, pProfile, "Statistics", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - PrintPopularity( f, pProfile, "Popularity", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - PrintSongHighScores( f, pProfile, "Song High Scores", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - PrintCourseHighScores( f, pProfile, "Course High Scores", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - PrintScreenshots( f, pProfile, "Screenshots", sDir ); - PrintCaloriesBurned( f, pProfile, "Calories Burned", sDir ); - PrintPercentComplete( f, pProfile, "Percent Complete", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - PrintRecentScores( f, pProfile, "Most Scores", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - PrintCatalogList( f, pProfile, "Song Information", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - PrintBookkeeping( f, pProfile, "Bookkeeping", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses ); - break; - default: - ASSERT(0); - } - - TranslatedWrite(f, ssprintf("\n", FOOTER.c_str()) ); - - TranslatedWrite(f, "\n" ); - TranslatedWrite(f, "\n" ); - f.Close(); - - // Don't sign Stats.html. The html data is redundant to the xml data, and - // signing is slow. - //if( PREFSMAN->m_bSignProfileData ) - // CryptManager::SignFileToFile(fn); - - // - // 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." ); - -} - -/* - * (c) 2004 Chris Danford - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/stepmania/src/ProfileHtml.h b/stepmania/src/ProfileHtml.h deleted file mode 100644 index 0bffc676af..0000000000 --- a/stepmania/src/ProfileHtml.h +++ /dev/null @@ -1,42 +0,0 @@ -/* ProfileHtml - Helpers for generating an HTML web page based on Profile data. */ - -#ifndef ProfileHtml_H -#define ProfileHtml_H - -#include "Profile.h" - -enum HtmlType { HTML_TYPE_MACHINE, HTML_TYPE_PLAYER }; - -void SaveStatsWebPage( - CString sDir, - const Profile *pProfile, - const Profile *pMachineProfile, - HtmlType htmlType - ); - -#endif - -/* - * (c) 2004 Chris Danford - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/stepmania/src/SongManager.cpp b/stepmania/src/SongManager.cpp index d221d53f1b..a41c4808de 100644 --- a/stepmania/src/SongManager.cpp +++ b/stepmania/src/SongManager.cpp @@ -33,7 +33,6 @@ SongManager* SONGMAN = NULL; // global and accessable from anywhere in our progr #define SONGS_DIR "Songs/" #define COURSES_DIR "Courses/" -#define DATA_DIR "Data/" #define MAX_EDITS_PER_PROFILE 200 @@ -93,7 +92,7 @@ void SongManager::InitAll( LoadingWindow *ld ) * even visible, we should be fixing it, not showing a progress display. */ if( ld ) ld->SetText( "Saving Catalog.xml ..." ); - SaveCatalogXml( DATA_DIR ); + SaveCatalogXml(); } void SongManager::Reload( LoadingWindow *ld ) diff --git a/stepmania/src/StepMania.dsp b/stepmania/src/StepMania.dsp index 6a88984fcd..7a33b0fd9f 100644 --- a/stepmania/src/StepMania.dsp +++ b/stepmania/src/StepMania.dsp @@ -1,5 +1,5 @@ # Microsoft Developer Studio Project File - Name="StepMania" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# Microsoft Developer Studio Generated Build File, Format Version 60000 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Application" 0x0101 @@ -59,10 +59,10 @@ LINK32=link.exe # SUBTRACT LINK32 /verbose /profile /pdb:none /incremental:no /nodefaultlib # Begin Special Build Tool IntDir=.\../Debug6 -TargetDir=\temp\stepmania\Program +TargetDir=\stepmania\stepmania\Program TargetName=StepMania-debug SOURCE="$(InputPath)" -PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ +PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi # End Special Build Tool @@ -96,10 +96,10 @@ LINK32=link.exe # SUBTRACT LINK32 /verbose /pdb:none /debug # Begin Special Build Tool IntDir=.\../Release6 -TargetDir=\temp\stepmania\Program +TargetDir=\stepmania\stepmania\Program TargetName=StepMania SOURCE="$(InputPath)" -PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ +PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi # End Special Build Tool @@ -884,14 +884,6 @@ SOURCE=.\Profile.h # End Source File # Begin Source File -SOURCE=.\ProfileHtml.cpp -# End Source File -# Begin Source File - -SOURCE=.\ProfileHtml.h -# End Source File -# Begin Source File - SOURCE=.\RandomSample.cpp # End Source File # Begin Source File diff --git a/stepmania/src/StepMania.vcproj b/stepmania/src/StepMania.vcproj index 3871e6c599..03077f5a71 100644 --- a/stepmania/src/StepMania.vcproj +++ b/stepmania/src/StepMania.vcproj @@ -794,12 +794,6 @@ cl /Zl /nologo /c verstub.cpp /Fo"$(IntDir)"\ - - - - diff --git a/stepmania/src/XmlFile.cpp b/stepmania/src/XmlFile.cpp index 0a2943f758..897de4a3c7 100644 --- a/stepmania/src/XmlFile.cpp +++ b/stepmania/src/XmlFile.cpp @@ -1230,6 +1230,9 @@ bool XNode::SaveToFile( CString sFile, LPDISP_OPT opt ) LOG->Warn("Couldn't open %s for writing: %s", sFile.c_str(), f.GetError().c_str() ); return false; } + f.PutLine( "" ); + if( !opt->stylesheet.empty() ) + f.PutLine( "stylesheet + "\"?>" ); if( !this->GetXML(f, opt) ) return false; if( f.Flush() == -1 ) diff --git a/stepmania/src/XmlFile.h b/stepmania/src/XmlFile.h index 3077244627..3f99c6bf90 100644 --- a/stepmania/src/XmlFile.h +++ b/stepmania/src/XmlFile.h @@ -91,6 +91,7 @@ struct DISP_OPT bool newline; // newline when new tag bool reference_value; // do convert from entity to reference ( < -> < ) LPXENTITYS entitys; // entity table for entity encode + CString stylesheet; // empty string = none int tab_base; // internal usage DISP_OPT() { newline = true; reference_value = true; entitys = &entityDefault; tab_base = 0; }