From d1a3f1fbdeefeaf719ae2d2e4ec58e1c5b2efc5c Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Tue, 17 Feb 2004 01:16:57 +0000 Subject: [PATCH] add grade counts, screenshots to stats.html --- stepmania/src/CryptManager.cpp | 50 ++++++++++++++++++ stepmania/src/CryptManager.h | 3 ++ stepmania/src/Profile.cpp | 84 ++++++++++++++++++++++++++++++ stepmania/src/Profile.h | 18 +++++++ stepmania/src/ScreenEvaluation.cpp | 19 ++++++- stepmania/src/ScreenEvaluation.h | 3 ++ stepmania/src/Song.cpp | 26 ++++----- stepmania/src/StepMania.cpp | 16 +++--- stepmania/src/StepMania.h | 4 +- 9 files changed, 202 insertions(+), 21 deletions(-) diff --git a/stepmania/src/CryptManager.cpp b/stepmania/src/CryptManager.cpp index 9aaf2de837..0aab8adf81 100644 --- a/stepmania/src/CryptManager.cpp +++ b/stepmania/src/CryptManager.cpp @@ -110,6 +110,56 @@ bool CryptManager::VerifyFile( CString sPath ) return verifierFilter->GetLastResult(); } +CString CryptManager::GetFileSignature( CString sPath ) +{ + CString sPrivFilename = PRIVATE_KEY_PATH; + CString sMessageFilename = sPath; + + if( !IsAFile(sPrivFilename) ) + return ""; + + if( !IsAFile(sMessageFilename) ) + return ""; + + // CAREFUL: These classes can throw all kinds of exceptions. Should this + // be wrapped in a try catch? + + RageFileSource privFile(sPrivFilename, true, new HexDecoder); + RSASSA_PKCS1v15_SHA_Signer priv(privFile); + AutoSeededRandomPool rng; + CString sSignature; + RageFileSource f(sMessageFilename, true, new SignerFilter(rng, priv, new HexEncoder(new StringSink(sSignature)))); + return sSignature; +} + +bool CryptManager::VerifyFile( CString sPath, CString sSignature ) +{ + CString sPubFilename = PUBLIC_KEY_PATH; + CString sMessageFilename = sPath; + + if( !IsAFile(sPubFilename) ) + return false; + + // CAREFUL: These classes can throw all kinds of exceptions. Should this + // be wrapped in a try catch? + + RageFileSource pubFile(sPubFilename, true, new HexDecoder); + RSASSA_PKCS1v15_SHA_Verifier pub(pubFile); + + StringSource signatureFile(sSignature, true); + if (signatureFile.MaxRetrievable() != pub.SignatureLength()) + return false; + SecByteBlock signature(pub.SignatureLength()); + signatureFile.Get(signature, signature.size()); + + VerifierFilter *verifierFilter = new VerifierFilter(pub); + verifierFilter->Put(signature, pub.SignatureLength()); + RageFileSource f(sMessageFilename, true, verifierFilter); + + return verifierFilter->GetLastResult(); +} + + void CryptManager::DigestFile(const char *filename) { // MD5 md5; diff --git a/stepmania/src/CryptManager.h b/stepmania/src/CryptManager.h index bc6709dfc8..c04896ab0c 100644 --- a/stepmania/src/CryptManager.h +++ b/stepmania/src/CryptManager.h @@ -12,6 +12,9 @@ public: static void SignFile( CString sPath ); static bool VerifyFile( CString sPath ); + static CString GetFileSignature( CString sPath ); + static bool VerifyFile( CString sPath, CString sSignature ); + static void DigestFile(const char *filename); static CString GetPublicKeyFileName(); diff --git a/stepmania/src/Profile.cpp b/stepmania/src/Profile.cpp index 8d76abbfd4..b75d210875 100644 --- a/stepmania/src/Profile.cpp +++ b/stepmania/src/Profile.cpp @@ -48,6 +48,7 @@ const int SM_390A12_COURSE_SCORES_VERSION = 8; #define CATEGORY_SCORES_XML "CategoryScores.xml" #define SONG_SCORES_XML "SongScores.xml" #define COURSE_SCORES_XML "CourseScores.xml" +#define SCREENSHOT_DATA_XML "ScreenshotData.xml" #define DEFAULT_PROFILE_NAME "" @@ -96,6 +97,11 @@ void Profile::InitCategoryScores() m_CategoryHighScores[st][rc].Init(); } +void Profile::InitScreenshotData() +{ + m_vScreenshots.clear(); +} + CString Profile::GetDisplayName() const { if( !m_sName.empty() ) @@ -283,6 +289,7 @@ bool Profile::LoadAllFromDir( CString sDir ) LoadSongScoresFromDir( sDir ); LoadCourseScoresFromDir( sDir ); LoadCategoryScoresFromDir( sDir ); + LoadScreenshotDataFromDir( sDir ); return bResult; } @@ -300,6 +307,7 @@ bool Profile::SaveAllToDir( CString sDir ) const DeleteCourseScoresFromDirSM390a12( sDir ); SaveCategoryScoresToDir( sDir ); DeleteCategoryScoresFromDirSM390a12( sDir ); + SaveScreenshotDataToDir( sDir ); SaveStatsWebPageToDir( sDir ); SaveMachinePublicKeyToDir( sDir ); return bResult; @@ -1007,3 +1015,79 @@ void Profile::SaveMachinePublicKeyToDir( CString sDir ) const { FileCopy( CRYPTMAN->GetPublicKeyFileName(), "public.key.rsa" ); } + +void Profile::AddScreenshot( Screenshot screenshot ) +{ + m_vScreenshots.push_back( screenshot ); +} + +void Profile::LoadScreenshotDataFromDir( CString sDir ) +{ + CHECKPOINT; + + CString fn = sDir + SCREENSHOT_DATA_XML; + + CRYPT_VERIFY_FILE; + + XNode xml; + if( !xml.LoadFromFile( fn ) ) + { + LOG->Warn( "Couldn't open file \"%s\" for writing.", fn.c_str() ); + return; + } + + if( xml.name != "ScreenshotData" ) + WARN_AND_RETURN; + + for( XNodes::iterator screenshot = xml.childs.begin(); + screenshot != xml.childs.end(); + screenshot++ ) + { + if( (*screenshot)->name != "Screenshot" ) + WARN_AND_CONTINUE; + + Screenshot ss; + + if( !(*screenshot)->GetChildValue("FileName",ss.sFileName) ) + WARN_AND_CONTINUE; + + if( !(*screenshot)->GetChildValue("Signature",ss.sSignature) ) + WARN_AND_CONTINUE; + + XNode *pHighScoreNode = (*screenshot)->GetChild("HighScore"); + if( pHighScoreNode == NULL ) + WARN_AND_CONTINUE; + + HighScore &hs = ss.highScore; + hs.LoadFromNode( pHighScoreNode ); + + m_vScreenshots.push_back( ss ); + } +} + +void Profile::SaveScreenshotDataToDir( CString sDir ) const +{ + CHECKPOINT; + + const Profile* pProfile = this; + ASSERT( pProfile ); + + CString fn = sDir + SCREENSHOT_DATA_XML; + + XNode xml; + xml.name = "ScreenshotData"; + + for( int i=0; iAppendChild( "FileName", ss.sFileName ); + pScreenshotNode->AppendChild( "Signature", ss.sSignature ); + pScreenshotNode->AppendChild( ss.highScore.CreateNode() ); + } + + xml.SaveToFile( fn ); + CRYPT_WRITE_SIG; +} diff --git a/stepmania/src/Profile.h b/stepmania/src/Profile.h index 67900aba6c..48bd766441 100644 --- a/stepmania/src/Profile.h +++ b/stepmania/src/Profile.h @@ -106,6 +106,19 @@ public: void IncrementCategoryPlayCount( StepsType st, RankingCategory rc ); + // + // Screenshot Data + // + struct Screenshot + { + CString sFileName; // no directory part - just the file name + CString sSignature; // sFile signed with the machine's private key + HighScore highScore; // high score that the screenshot is taken of + }; + vector m_vScreenshots; + void AddScreenshot( Screenshot screenshot ); + + // // Init'ing // @@ -115,11 +128,13 @@ public: InitSongScores(); InitCourseScores(); InitCategoryScores(); + InitScreenshotData(); } void InitGeneralData(); void InitSongScores(); void InitCourseScores(); void InitCategoryScores(); + void InitScreenshotData(); // // Loading and saving @@ -145,6 +160,9 @@ public: void SaveCategoryScoresToDir( CString sDir ) const; void DeleteCategoryScoresFromDirSM390a12( CString sDir ) const; + void LoadScreenshotDataFromDir( CString sDir ); + void SaveScreenshotDataToDir( CString sDir ) const; + void SaveStatsWebPageToDir( CString sDir ) const; void SaveMachinePublicKeyToDir( CString sDir ) const; diff --git a/stepmania/src/ScreenEvaluation.cpp b/stepmania/src/ScreenEvaluation.cpp index 6e17529b1f..119c7fa35d 100644 --- a/stepmania/src/ScreenEvaluation.cpp +++ b/stepmania/src/ScreenEvaluation.cpp @@ -36,6 +36,7 @@ #include "CodeDetector.h" #include "RageDisplay.h" #include "StepMania.h" +#include "CryptManager.h" const int NUM_SCORE_DIGITS = 9; @@ -100,6 +101,8 @@ ScreenEvaluation::ScreenEvaluation( CString sClassName ) : Screen(sClassName) if( PREFSMAN->m_bScreenTestMode ) { + PROFILEMAN->LoadProfileFromMemoryCard(PLAYER_1); + GAMESTATE->m_PlayMode = PLAY_MODE_RAVE; GAMESTATE->m_CurStyle = STYLE_DANCE_VERSUS; GAMESTATE->m_bSideIsJoined[PLAYER_1] = true; @@ -903,7 +906,7 @@ void ScreenEvaluation::CommitScores( const StageStats &stageStats, int iPersonal // depends on if this is a course or not ... it's handled // below in the switch - HighScore hs; + HighScore &hs = m_HighScore[p]; hs.grade = stageStats.GetGrade( (PlayerNumber)p ); hs.iScore = stageStats.iScore[p]; hs.fPercentDP = stageStats.GetPercentDancePoints( (PlayerNumber)p ); @@ -1301,7 +1304,19 @@ void ScreenEvaluation::Input( const DeviceInput& DeviceI, const InputEventType t /* StyleI won't be valid if it's a menu button that's pressed. * There's got to be a better way of doing this. -Chris */ CString sDir = PROFILEMAN->GetProfileDir((ProfileSlot)pn) + "Screenshots/"; - SaveScreenshot( sDir, true, true ); + CString sFileName = SaveScreenshot( sDir, true, true ); + CString sPath = sDir+sFileName; + + if( !sFileName.empty() ) + { + Profile* pProfile = PROFILEMAN->GetProfile(pn); + Profile::Screenshot screenshot; + screenshot.sFileName = sFileName; + screenshot.sSignature = CRYPTMAN->GetFileSignature( sPath ); + screenshot.highScore = m_HighScore[pn]; + pProfile->AddScreenshot( screenshot ); + } + m_bSavedScreenshot[pn] = true; return; // handled } diff --git a/stepmania/src/ScreenEvaluation.h b/stepmania/src/ScreenEvaluation.h index e45a41ec09..aea434c6e9 100644 --- a/stepmania/src/ScreenEvaluation.h +++ b/stepmania/src/ScreenEvaluation.h @@ -28,6 +28,7 @@ #include "BGAnimation.h" #include "ActorUtil.h" #include "ConditionalBGA.h" +#include "HighScore.h" const int MAX_SONGS_TO_SHOW = 5; // In summary, we show last 3 stages, plus extra stages if passed const int NUM_JUDGE_LINES = 9; // marvelous, perfect, great, good, boo, miss, ok, max_combo, error @@ -145,6 +146,8 @@ protected: bool m_bPassFailTriggered; // has the pass / fail sound been played yet? RageTimer m_timerSoundSequences; // timer used for triggering sounds. vector m_SoundSequences; // a sequence of sounds to be played (although they're stored in no particular order!) + + HighScore m_HighScore[NUM_PLAYERS]; bool m_bSavedScreenshot[NUM_PLAYERS]; }; diff --git a/stepmania/src/Song.cpp b/stepmania/src/Song.cpp index c047c5734b..07435084b2 100644 --- a/stepmania/src/Song.cpp +++ b/stepmania/src/Song.cpp @@ -342,20 +342,22 @@ void Song::RevertFromDisk() PREFSMAN->m_bFastLoad = OldVal; - for( int p = 0; p < NUM_PLAYERS; ++p ) { - CHECKPOINT; - if( GAMESTATE->m_pCurSong == this ) - GAMESTATE->m_pCurNotes[p] = OldCurNotes[p].GetSteps( this ); - CHECKPOINT; - if( g_CurStageStats.pSong == this ) - g_CurStageStats.pSteps[p] = OldCurStageStats[p].GetSteps( this ); - CHECKPOINT; - for( unsigned i = 0; i < g_vPlayedStageStats.size(); ++i ) + for( int p = 0; p < NUM_PLAYERS; ++p ) { - CHECKPOINT_M(ssprintf("%i", i)); - if( g_vPlayedStageStats[i].pSong == this ) - g_vPlayedStageStats[i].pSteps[p] = OldPlayedStageStats[p][i].GetSteps( this ); + CHECKPOINT; + if( GAMESTATE->m_pCurSong == this ) + GAMESTATE->m_pCurNotes[p] = OldCurNotes[p].GetSteps( this ); + CHECKPOINT; + if( g_CurStageStats.pSong == this ) + g_CurStageStats.pSteps[p] = OldCurStageStats[p].GetSteps( this ); + CHECKPOINT; + for( unsigned i = 0; i < g_vPlayedStageStats.size(); ++i ) + { + CHECKPOINT_M(ssprintf("%i", i)); + if( g_vPlayedStageStats[i].pSong == this ) + g_vPlayedStageStats[i].pSteps[p] = OldPlayedStageStats[p][i].GetSteps( this ); + } } } } diff --git a/stepmania/src/StepMania.cpp b/stepmania/src/StepMania.cpp index 231dbe3074..4159932f1d 100644 --- a/stepmania/src/StepMania.cpp +++ b/stepmania/src/StepMania.cpp @@ -1096,7 +1096,7 @@ int main(int argc, char* argv[]) return 0; } -bool SaveScreenshot( CString sDir, bool bSaveCompressed, bool bMakeSignature ) +CString SaveScreenshot( CString sDir, bool bSaveCompressed, bool bMakeSignature ) { // // Find a file name for the screenshot @@ -1125,12 +1125,13 @@ bool SaveScreenshot( CString sDir, bool bSaveCompressed, bool bMakeSignature ) // // Save the screenshot // - CString sScreenshotPath = ssprintf( sDir+"screen%04d.%s",fileno,bSaveCompressed ? "jpg" : "bmp" ); - bool bResult = DISPLAY->SaveScreenshot( sScreenshotPath, bSaveCompressed ? RageDisplay::jpg : RageDisplay::bmp ); + CString sFileName = ssprintf( "screen%04d.%s",fileno,bSaveCompressed ? "jpg" : "bmp" ); + CString sPath = sDir+sFileName; + bool bResult = DISPLAY->SaveScreenshot( sPath, bSaveCompressed ? RageDisplay::jpg : RageDisplay::bmp ); if( !bResult ) { SOUND->PlayOnce( THEME->GetPathToS("Common invalid") ); - return false; + return ""; } SOUND->PlayOnce( THEME->GetPathToS("Common screenshot") ); @@ -1141,9 +1142,9 @@ bool SaveScreenshot( CString sDir, bool bSaveCompressed, bool bMakeSignature ) FlushDirCache(); if( bMakeSignature ) - CryptManager::SignFile( sScreenshotPath ); + CryptManager::SignFile( sPath ); - return false; + return sFileName; } /* Returns true if the key has been handled and should be discarded, false if @@ -1197,6 +1198,9 @@ bool HandleGlobalInputs( DeviceInput DeviceI, InputEventType type, GameInput Gam // so we don't have to play through a whole song to get new output. BOOKKEEPER->WriteToDisk(); PROFILEMAN->SaveMachineProfile(); + for( int p=0; pIsUsingProfile((PlayerNumber)p) ) + PROFILEMAN->SaveProfile( (PlayerNumber)p ); /* If we're in screen test mode, reload the screen. */ if( PREFSMAN->m_bScreenTestMode ) diff --git a/stepmania/src/StepMania.h b/stepmania/src/StepMania.h index 8e0cd7adc0..a44175ae05 100644 --- a/stepmania/src/StepMania.h +++ b/stepmania/src/StepMania.h @@ -20,7 +20,9 @@ void ResetGame( bool ReturnToFirstScreen=true ); void ReadGamePrefsFromDisk( bool bSwitchToLastPlayedGame=true ); void SaveGamePrefsToDisk(); void ChangeCurrentGame( Game g ); -bool SaveScreenshot( CString sDir, bool bSaveCompressed, bool bMakeSignature ); + +// If successful, return filename of screenshot in sDir, else return "" +CString SaveScreenshot( CString sDir, bool bSaveCompressed, bool bMakeSignature ); #if defined(_WINDOWS) #include "windows.h"