From df9ed04fd39ce1d5d92d7dd11d5eaeedbac0c58b Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Sun, 9 Aug 2009 20:11:23 +0000 Subject: [PATCH] CustomDifficulty fixup fix stats.xml not saving experimental recentscores.xml saving --- .../Themes/default/Scripts/Utilities.lua | 10 ++ stepmania/src/CourseUtil.cpp | 2 +- stepmania/src/Difficulty.cpp | 19 +-- stepmania/src/DifficultyList.cpp | 2 +- stepmania/src/EditMenu.cpp | 4 +- stepmania/src/HighScore.cpp | 9 +- stepmania/src/HighScore.h | 2 + stepmania/src/LuaManager.h | 3 - stepmania/src/Profile.cpp | 78 ++---------- stepmania/src/Profile.h | 33 ------ stepmania/src/ProfileManager.cpp | 14 --- stepmania/src/ScreenEvaluation.cpp | 2 +- stepmania/src/ScreenGameplay.cpp | 2 +- stepmania/src/ScreenGameplayLesson.cpp | 2 +- stepmania/src/ScreenNetSelectMusic.cpp | 4 +- stepmania/src/StageStats.cpp | 96 +++++++++------ stepmania/src/StageStats.h | 2 +- stepmania/src/StatsManager.cpp | 112 +++++++++++++++--- stepmania/src/StepsDisplay.cpp | 71 +++++------ stepmania/src/StepsDisplay.h | 8 +- 20 files changed, 222 insertions(+), 253 deletions(-) diff --git a/stepmania/Themes/default/Scripts/Utilities.lua b/stepmania/Themes/default/Scripts/Utilities.lua index 0d1ee6165d..57f8b47b1e 100644 --- a/stepmania/Themes/default/Scripts/Utilities.lua +++ b/stepmania/Themes/default/Scripts/Utilities.lua @@ -115,6 +115,16 @@ function GetSongBackground() return THEME:GetPathG("Common","fallback background") end +function StepsOrTrailToCustomDifficulty( stepsOrTrail ) + if lua.CheckType("Steps", stepsOrTrail) then + return StepsToCustomDifficulty( stepsOrTrail ); + end + if lua.CheckType("Trail", stepsOrTrail) then + return TrailToCustomDifficulty( stepsOrTrail ); + end +end + + -- (c) 2005 Glenn Maynard, Chris Danford -- All rights reserved. -- diff --git a/stepmania/src/CourseUtil.cpp b/stepmania/src/CourseUtil.cpp index 23f52bb562..418a6e71b7 100644 --- a/stepmania/src/CourseUtil.cpp +++ b/stepmania/src/CourseUtil.cpp @@ -419,7 +419,7 @@ void EditCourseUtil::UpdateAndSetTrail() StepsType st = GAMESTATE->m_pCurStyle->m_StepsType; Trail *pTrail = NULL; if( GAMESTATE->m_pCurCourse ) - GAMESTATE->m_pCurCourse->GetTrailForceRegenCache( st ); + pTrail = GAMESTATE->m_pCurCourse->GetTrailForceRegenCache( st ); GAMESTATE->m_pCurTrail[PLAYER_1].Set( pTrail ); } diff --git a/stepmania/src/Difficulty.cpp b/stepmania/src/Difficulty.cpp index de1a9913bc..723339e2eb 100644 --- a/stepmania/src/Difficulty.cpp +++ b/stepmania/src/Difficulty.cpp @@ -148,24 +148,9 @@ RString TrailToCustomDifficulty( const Trail *pTrail ) #include "LuaBinding.h" -static int StepsOrTrailToCustomDifficulty( lua_State *L ) -{ - Steps *pSteps = Luna::check(L, 1); - if( pSteps ) - { - lua_pushstring(L, StepsToCustomDifficulty( pSteps )); - return 1; - } - Trail *pTrail = Luna::check(L, 1); - if( pTrail ) - { - lua_pushstring(L, TrailToCustomDifficulty( pTrail )); - return 1; - } - return 0; -} +LuaFunction( StepsToCustomDifficulty, StepsToCustomDifficulty(Luna::check(L, 1)) ); +LuaFunction( TrailToCustomDifficulty, TrailToCustomDifficulty(Luna::check(L, 1)) ); -LuaFunction2( StepsOrTrailToCustomDifficulty ); /* * (c) 2001-2004 Chris Danford diff --git a/stepmania/src/DifficultyList.cpp b/stepmania/src/DifficultyList.cpp index 092c007e31..5fa3e23d63 100644 --- a/stepmania/src/DifficultyList.cpp +++ b/stepmania/src/DifficultyList.cpp @@ -259,7 +259,7 @@ void StepsDisplayList::SetFromGameState() FOREACH_CONST( Difficulty, difficulties, d ) { m_Rows[i].m_dc = *d; - m_Lines[i].m_Meter.SetFromStepsTypeAndMeterAndDifficulty( StepsType_Invalid, 0, *d ); + m_Lines[i].m_Meter.SetFromStepsTypeAndMeterAndDifficultyAndCourseType( GAMESTATE->m_pCurStyle->m_StepsType, 0, *d, CourseType_Invalid ); ++i; } } diff --git a/stepmania/src/EditMenu.cpp b/stepmania/src/EditMenu.cpp index efb131f940..dddf1bbdf6 100644 --- a/stepmania/src/EditMenu.cpp +++ b/stepmania/src/EditMenu.cpp @@ -483,7 +483,7 @@ void EditMenu::OnRowValueChanged( EditMenuRow row ) if( GetSelectedSteps() ) m_StepsDisplay.SetFromSteps( GetSelectedSteps() ); else - m_StepsDisplay.SetFromStepsTypeAndMeterAndDifficulty( GetSelectedSourceStepsType(), 0, GetSelectedDifficulty() ); + m_StepsDisplay.SetFromStepsTypeAndMeterAndDifficultyAndCourseType( GetSelectedSourceStepsType(), 0, GetSelectedDifficulty(), CourseType_Invalid ); // fall through case ROW_SOURCE_STEPS_TYPE: m_textLabel[ROW_SOURCE_STEPS_TYPE].SetVisible( GetSelectedSteps() ? false : true ); @@ -535,7 +535,7 @@ void EditMenu::OnRowValueChanged( EditMenuRow row ) else if( GetSelectedSourceSteps() ) m_StepsDisplaySource.SetFromSteps( GetSelectedSourceSteps() ); else - m_StepsDisplaySource.SetFromStepsTypeAndMeterAndDifficulty( GetSelectedSourceStepsType(), 0, GetSelectedSourceDifficulty() ); + m_StepsDisplaySource.SetFromStepsTypeAndMeterAndDifficultyAndCourseType( GetSelectedSourceStepsType(), 0, GetSelectedSourceDifficulty(), CourseType_Invalid ); m_StepsDisplaySource.SetVisible( !(bHideMeter || GetSelectedSteps()) ); m_Actions.clear(); diff --git a/stepmania/src/HighScore.cpp b/stepmania/src/HighScore.cpp index 1d45c3d8b6..2c4e822206 100644 --- a/stepmania/src/HighScore.cpp +++ b/stepmania/src/HighScore.cpp @@ -8,7 +8,7 @@ #include "Foreach.h" #include "RadarValues.h" -#define EMPTY_NAME THEME->GetMetric ("HighScore","EmptyName") +ThemeMetric EMPTY_NAME("HighScore","EmptyName"); struct HighScoreImpl @@ -27,6 +27,7 @@ struct HighScoreImpl int iHoldNoteScores[NUM_HoldNoteScore]; RadarValues radarValues; float fLifeRemainingSeconds; + bool bDisqualified; HighScoreImpl(); XNode *CreateNode() const; @@ -55,6 +56,7 @@ bool HighScoreImpl::operator==( const HighScoreImpl& other ) const COMPARE( iHoldNoteScores[hns] ); COMPARE( radarValues ); COMPARE( fLifeRemainingSeconds ); + COMPARE( bDisqualified ); #undef COMPARE return true; @@ -76,6 +78,7 @@ HighScoreImpl::HighScoreImpl() ZERO( iHoldNoteScores ); radarValues.MakeUnknown(); fLifeRemainingSeconds = 0; + bDisqualified = false; } XNode *HighScoreImpl::CreateNode() const @@ -105,6 +108,7 @@ XNode *HighScoreImpl::CreateNode() const pHoldNoteScores->AppendChild( HoldNoteScoreToString(hns), iHoldNoteScores[hns] ); pNode->AppendChild( radarValues.CreateNode(bWriteSimpleValues, bWriteComplexValues) ); pNode->AppendChild( "LifeRemainingSeconds", fLifeRemainingSeconds ); + pNode->AppendChild( "Disqualified", bDisqualified); return pNode; } @@ -138,6 +142,7 @@ void HighScoreImpl::LoadFromNode( const XNode *pNode ) if( pRadarValues ) radarValues.LoadFromNode( pRadarValues ); pNode->GetChildValue( "LifeRemainingSeconds", fLifeRemainingSeconds ); + pNode->GetChildValue( "Disqualified", bDisqualified); /* Validate input. */ grade = clamp( grade, Grade_Tier01, Grade_Failed ); @@ -170,6 +175,7 @@ int HighScore::GetTapNoteScore( TapNoteScore tns ) const { return m_Impl->iTapNo int HighScore::GetHoldNoteScore( HoldNoteScore hns ) const { return m_Impl->iHoldNoteScores[hns]; } const RadarValues &HighScore::GetRadarValues() const { return m_Impl->radarValues; } float HighScore::GetLifeRemainingSeconds() const { return m_Impl->fLifeRemainingSeconds; } +bool HighScore::GetDisqualified() const { return m_Impl->bDisqualified; } void HighScore::SetName( const RString &sName ) { m_Impl->sName = sName; } void HighScore::SetGrade( Grade g ) { m_Impl->grade = g; } @@ -185,6 +191,7 @@ void HighScore::SetTapNoteScore( TapNoteScore tns, int i ) { m_Impl->iTapNoteSco void HighScore::SetHoldNoteScore( HoldNoteScore hns, int i ) { m_Impl->iHoldNoteScores[hns] = i; } void HighScore::SetRadarValues( const RadarValues &rv ) { m_Impl->radarValues = rv; } void HighScore::SetLifeRemainingSeconds( float f ) { m_Impl->fLifeRemainingSeconds = f; } +void HighScore::SetDisqualified( bool b ) { m_Impl->bDisqualified = b; } /* We normally don't give direct access to the members. We need this one * for NameToFillIn; use a special accessor so it's easy to find where this diff --git a/stepmania/src/HighScore.h b/stepmania/src/HighScore.h index 78d963ae2d..0a5dc6dc76 100644 --- a/stepmania/src/HighScore.h +++ b/stepmania/src/HighScore.h @@ -32,6 +32,7 @@ struct HighScore int GetHoldNoteScore( HoldNoteScore tns ) const; const RadarValues &GetRadarValues() const; float GetLifeRemainingSeconds() const; + bool GetDisqualified() const; void SetName( const RString &sName ); void SetGrade( Grade g ); @@ -47,6 +48,7 @@ struct HighScore void SetHoldNoteScore( HoldNoteScore tns, int i ); void SetRadarValues( const RadarValues &rv ); void SetLifeRemainingSeconds( float f ); + void SetDisqualified( bool b ); RString *GetNameMutable(); const RString *GetNameMutable() const { return const_cast (const_cast(this)->GetNameMutable()); } diff --git a/stepmania/src/LuaManager.h b/stepmania/src/LuaManager.h index 62919b5d98..4446efc0e4 100644 --- a/stepmania/src/LuaManager.h +++ b/stepmania/src/LuaManager.h @@ -214,9 +214,6 @@ int LuaFunc_##func( lua_State *L ) { \ void LuaFunc_Register_##func( lua_State *L ) { lua_register( L, #func, LuaFunc_##func ); } \ REGISTER_WITH_LUA_FUNCTION( LuaFunc_Register_##func ); -#define LuaFunction2( func ) \ -void LuaFunc_Register_##func( lua_State *L ) { lua_register( L, #func, func ); } \ -REGISTER_WITH_LUA_FUNCTION( LuaFunc_Register_##func ); #endif diff --git a/stepmania/src/Profile.cpp b/stepmania/src/Profile.cpp index 99652b31b8..bfd523d140 100644 --- a/stepmania/src/Profile.cpp +++ b/stepmania/src/Profile.cpp @@ -34,7 +34,6 @@ const RString PUBLIC_KEY_FILE = "public.key"; const RString SCREENSHOTS_SUBDIR = "Screenshots/"; const RString EDIT_STEPS_SUBDIR = "Edits/"; const RString EDIT_COURSES_SUBDIR = "EditCourses/"; -const RString UPLOAD_SUBDIR = "Upload/"; ThemeMetric SHOW_COIN_DATA( "Profile", "ShowCoinData" ); static Preference g_bProfileDataCompress( "ProfileDataCompress", false ); @@ -978,6 +977,9 @@ bool Profile::SaveStatsXmlToDir( RString sDir, bool bSignData ) const { RageFileObjGzip gzip( &f ); gzip.Start(); + if( !XmlFileUtil::SaveToFile( xml.get(), gzip, "", false ) ) + return false; + if( gzip.Finish() == -1 ) return false; @@ -987,6 +989,9 @@ bool Profile::SaveStatsXmlToDir( RString sDir, bool bSignData ) const } else { + if( !XmlFileUtil::SaveToFile( xml.get(), f, "", false ) ) + return false; + /* After successfully saving STATS_XML, remove any stray STATS_XML_GZ. */ if( FILEMAN->IsAFile(sDir + STATS_XML_GZ) ) FILEMAN->Remove( sDir + STATS_XML_GZ ); @@ -1717,75 +1722,6 @@ float Profile::GetCaloriesBurnedForDay( DateTime day ) const return i->second.fCals; } -static void SaveRecentScore( XNode* xml ) -{ - RString sDate = DateTime::GetNowDate().GetString(); - sDate.Replace(":","-"); - - RString sFileNameNoExtension = Profile::MakeUniqueFileNameNoExtension(UPLOAD_SUBDIR, sDate ); - RString fn = UPLOAD_SUBDIR + sFileNameNoExtension + ".xml"; - - RString sStatsXmlSigFile = fn+SIGNATURE_APPEND; - CryptManager::SignFileToFile(fn, sStatsXmlSigFile); -} - - -XNode* Profile::HighScoreForASongAndSteps::CreateNode() const -{ - XNode* pNode = new XNode( "HighScoreForASongAndSteps" ); - - pNode->AppendChild( songID.CreateNode() ); - pNode->AppendChild( stepsID.CreateNode() ); - pNode->AppendChild( hs.CreateNode() ); - - return pNode; -} - -void Profile::SaveStepsRecentScore( const Song* pSong, const Steps* pSteps, HighScore hs ) -{ - ASSERT( pSong ); - ASSERT( pSteps ); - HighScoreForASongAndSteps h; - h.songID.FromSong( pSong ); - ASSERT( h.songID.IsValid() ); - h.stepsID.FromSteps( pSteps ); - ASSERT( h.stepsID.IsValid() ); - h.hs = hs; - - auto_ptr xml( new XNode("Stats") ); - xml->AppendChild( "MachineGuid", PROFILEMAN->GetMachineProfile()->m_sGuid ); - XNode *recent = xml->AppendChild( new XNode("RecentSongScores") ); - recent->AppendChild( h.CreateNode() ); - - SaveRecentScore( xml.get() ); -} - - -XNode* Profile::HighScoreForACourseAndTrail::CreateNode() const -{ - XNode* pNode = new XNode( "HighScoreForACourseAndTrail" ); - - pNode->AppendChild( courseID.CreateNode() ); - pNode->AppendChild( trailID.CreateNode() ); - pNode->AppendChild( hs.CreateNode() ); - - return pNode; -} - -void Profile::SaveCourseRecentScore( const Course* pCourse, const Trail* pTrail, HighScore hs ) -{ - HighScoreForACourseAndTrail h; - h.courseID.FromCourse( pCourse ); - h.trailID.FromTrail( pTrail ); - h.hs = hs; - - auto_ptr xml( new XNode("Stats") ); - xml->AppendChild( "MachineGuid", PROFILEMAN->GetMachineProfile()->m_sGuid ); - XNode *recent = xml->AppendChild( new XNode("RecentCourseScores") ); - recent->AppendChild( h.CreateNode() ); - - SaveRecentScore( xml.get() ); -} const Profile::HighScoresForASong *Profile::GetHighScoresForASong( const SongID& songID ) const { @@ -1882,7 +1818,7 @@ RString Profile::MakeUniqueFileNameNoExtension( RString sDir, RString sFileNameB FILEMAN->FlushDirCache( sDir ); vector files; - GetDirListing( sDir + "sFileNameBeginning*", files, false, false ); + GetDirListing( sDir + sFileNameBeginning+"*", files, false, false ); sort( files.begin(), files.end() ); int iIndex = 0; diff --git a/stepmania/src/Profile.h b/stepmania/src/Profile.h index 1a92d4b90a..5dbad7e899 100644 --- a/stepmania/src/Profile.h +++ b/stepmania/src/Profile.h @@ -234,39 +234,6 @@ public: float GetCaloriesBurnedForDay( DateTime day ) const; - // - // RecentSongScores - // - struct HighScoreForASongAndSteps - { - StepsID stepsID; - SongID songID; - HighScore hs; - - HighScoreForASongAndSteps() { Unset(); } - void Unset() { stepsID.Unset(); songID.Unset(); hs.Unset(); } - - XNode* CreateNode() const; - }; - void SaveStepsRecentScore( const Song* pSong, const Steps* pSteps, HighScore hs ); - - - // - // RecentCourseScores - // - struct HighScoreForACourseAndTrail - { - CourseID courseID; - TrailID trailID; - HighScore hs; - - HighScoreForACourseAndTrail() { Unset(); } - void Unset() { courseID.Unset(); hs.Unset(); } - - XNode* CreateNode() const; - }; - void SaveCourseRecentScore( const Course* pCourse, const Trail* pTrail, HighScore hs ); - // // Init'ing // diff --git a/stepmania/src/ProfileManager.cpp b/stepmania/src/ProfileManager.cpp index 65b1d74536..52a177480e 100644 --- a/stepmania/src/ProfileManager.cpp +++ b/stepmania/src/ProfileManager.cpp @@ -667,13 +667,6 @@ void ProfileManager::AddStepsScore( const Song* pSong, const Steps* pSteps, Play if( !pSteps->IsAPlayerEdit() ) GetMachineProfile()->AddStepsHighScore( pSong, pSteps, hs, iMachineIndexOut ); } - - // - // save recent score - // - if( IsPersistentProfile(pn) ) - GetProfile(pn)->SaveStepsRecentScore( pSong, pSteps, hs ); - GetMachineProfile()->SaveStepsRecentScore( pSong, pSteps, hs ); } void ProfileManager::IncrementStepsPlayCount( const Song* pSong, const Steps* pSteps, PlayerNumber pn ) @@ -717,13 +710,6 @@ void ProfileManager::AddCourseScore( const Course* pCourse, const Trail* pTrail, GetProfile(pn)->AddCourseHighScore( pCourse, pTrail, hs, iPersonalIndexOut ); if( hs.GetPercentDP() >= PREFSMAN->m_fMinPercentageForMachineCourseHighScore ) GetMachineProfile()->AddCourseHighScore( pCourse, pTrail, hs, iMachineIndexOut ); - - // - // save recent score - // - if( IsPersistentProfile(pn) ) - GetProfile(pn)->SaveCourseRecentScore( pCourse, pTrail, hs ); - GetMachineProfile()->SaveCourseRecentScore( pCourse, pTrail, hs ); } void ProfileManager::IncrementCoursePlayCount( const Course* pCourse, const Trail* pTrail, PlayerNumber pn ) diff --git a/stepmania/src/ScreenEvaluation.cpp b/stepmania/src/ScreenEvaluation.cpp index 7dca69ea20..79689d8da4 100644 --- a/stepmania/src/ScreenEvaluation.cpp +++ b/stepmania/src/ScreenEvaluation.cpp @@ -237,7 +237,7 @@ void ScreenEvaluation::Init() // update persistent statistics // if( SUMMARY ) - m_pStageStats->CommitScores( true ); + m_pStageStats->FinalizeScores( true ); // Run this here, so STATSMAN->m_CurStageStats is available to overlays. ScreenWithMenuElements::Init(); diff --git a/stepmania/src/ScreenGameplay.cpp b/stepmania/src/ScreenGameplay.cpp index d04ab2dcf6..8ac68ad7dd 100644 --- a/stepmania/src/ScreenGameplay.cpp +++ b/stepmania/src/ScreenGameplay.cpp @@ -2446,7 +2446,7 @@ void ScreenGameplay::StageFinished( bool bBackedOut ) FOREACH_HumanPlayer( pn ) STATSMAN->m_CurStageStats.m_player[pn].CalcAwards( pn, STATSMAN->m_CurStageStats.m_bGaveUp, STATSMAN->m_CurStageStats.m_bUsedAutoplay ); - STATSMAN->m_CurStageStats.CommitScores( false ); + STATSMAN->m_CurStageStats.FinalizeScores( false ); GAMESTATE->CommitStageStats(); diff --git a/stepmania/src/ScreenGameplayLesson.cpp b/stepmania/src/ScreenGameplayLesson.cpp index 778fc1226e..8a77beaea1 100644 --- a/stepmania/src/ScreenGameplayLesson.cpp +++ b/stepmania/src/ScreenGameplayLesson.cpp @@ -107,7 +107,7 @@ void ScreenGameplayLesson::HandleScreenMessage( const ScreenMessage SM ) // Commit scores here since we don't go through an eval screen. // Only commit if we've cleared. Don't commit if we've failed all 3 tries. - STATSMAN->m_CurStageStats.CommitScores( false ); + STATSMAN->m_CurStageStats.FinalizeScores( false ); } else if( bAnyTriesLeft ) { diff --git a/stepmania/src/ScreenNetSelectMusic.cpp b/stepmania/src/ScreenNetSelectMusic.cpp index 4df39fbd06..d008b9550f 100644 --- a/stepmania/src/ScreenNetSelectMusic.cpp +++ b/stepmania/src/ScreenNetSelectMusic.cpp @@ -488,7 +488,7 @@ void ScreenNetSelectMusic::UpdateDifficulties( PlayerNumber pn ) { if ( GAMESTATE->m_pCurSong == NULL ) { - m_StepsDisplays[pn].SetFromStepsTypeAndMeterAndDifficulty( StepsType_Invalid, 0, Difficulty_Beginner ); + m_StepsDisplays[pn].SetFromStepsTypeAndMeterAndDifficultyAndCourseType( StepsType_Invalid, 0, Difficulty_Beginner, CourseType_Invalid ); m_DifficultyIcon[pn].SetFromSteps( pn, NULL ); //It will blank it out return; } @@ -510,7 +510,7 @@ void ScreenNetSelectMusic::UpdateDifficulties( PlayerNumber pn ) if ( ( m_DC[pn] < NUM_Difficulty ) && ( m_DC[pn] >= Difficulty_Beginner ) ) m_StepsDisplays[pn].SetFromSteps( pSteps ); else - m_StepsDisplays[pn].SetFromStepsTypeAndMeterAndDifficulty( StepsType_Invalid, 0, Difficulty_Beginner ); + m_StepsDisplays[pn].SetFromStepsTypeAndMeterAndDifficultyAndCourseType( StepsType_Invalid, 0, Difficulty_Beginner, CourseType_Invalid ); } void ScreenNetSelectMusic::MusicChanged() diff --git a/stepmania/src/StageStats.cpp b/stepmania/src/StageStats.cpp index 37025fd0a6..f81fa293dc 100644 --- a/stepmania/src/StageStats.cpp +++ b/stepmania/src/StageStats.cpp @@ -129,7 +129,42 @@ float StageStats::GetTotalPossibleStepsSeconds() const return fSecs / m_fMusicRate; } -void StageStats::CommitScores( bool bSummary ) +static HighScore FillInHighScore( const PlayerStageStats &pss, const PlayerState &ps, RString sRankingToFillInMarker, RString sPlayerGuid ) +{ + HighScore hs; + hs.SetName( sRankingToFillInMarker ); + hs.SetGrade( pss.GetGrade() ); + hs.SetScore( pss.m_iScore ); + hs.SetPercentDP( pss.GetPercentDancePoints() ); + hs.SetAliveSeconds( pss.m_fAliveSeconds ); + + vector asModifiers; + { + RString sPlayerOptions = ps.m_PlayerOptions.GetStage().GetString(); + if( !sPlayerOptions.empty() ) + asModifiers.push_back( sPlayerOptions ); + RString sSongOptions = GAMESTATE->m_SongOptions.GetStage().GetString(); + if( !sSongOptions.empty() ) + asModifiers.push_back( sSongOptions ); + } + hs.SetModifiers( join(", ", asModifiers) ); + + hs.SetDateTime( DateTime::GetNowDateTime() ); + hs.SetPlayerGuid( sPlayerGuid ); + hs.SetMachineGuid( PROFILEMAN->GetMachineProfile()->m_sGuid ); + hs.SetProductID( PREFSMAN->m_iProductID ); + FOREACH_ENUM( TapNoteScore, tns ) + hs.SetTapNoteScore( tns, pss.m_iTapNoteScores[tns] ); + FOREACH_ENUM( HoldNoteScore, hns ) + hs.SetHoldNoteScore( hns, pss.m_iHoldNoteScores[hns] ); + hs.SetRadarValues( pss.m_radarActual ); + hs.SetLifeRemainingSeconds( pss.m_fLifeRemainingSeconds ); + hs.SetDisqualified( pss.IsDisqualified() ); + + return hs; +} + +void StageStats::FinalizeScores( bool bSummary ) { switch( GAMESTATE->m_PlayMode ) { @@ -153,44 +188,23 @@ void StageStats::CommitScores( bool bSummary ) LOG->Trace( "saving stats and high scores" ); + // + // generate a HighScore for each player + // + // whether or not to save scores when the stage was failed + // depends on if this is a course or not ... it's handled + // below in the switch FOREACH_HumanPlayer( p ) { - // don't save scores if the player is disqualified - if( this->m_player[p].IsDisqualified() ) + RString sPlayerGuid = PROFILEMAN->IsPersistentProfile(p) ? PROFILEMAN->GetProfile(p)->m_sGuid : RString(""); + m_player[p].m_HighScore = FillInHighScore( m_player[p], *GAMESTATE->m_pPlayerState[p], RANKING_TO_FILL_IN_MARKER[p], sPlayerGuid ); + } + FOREACH_MultiPlayer( mp ) + { + if( !GAMESTATE->IsMultiPlayerEnabled(mp) ) continue; - - // whether or not to save scores when the stage was failed - // depends on if this is a course or not ... it's handled - // below in the switch - - HighScore &hs = m_player[p].m_HighScore; - hs.SetName( RANKING_TO_FILL_IN_MARKER[p] ); - hs.SetGrade( m_player[p].GetGrade() ); - hs.SetScore( m_player[p].m_iScore ); - hs.SetPercentDP( m_player[p].GetPercentDancePoints() ); - hs.SetAliveSeconds( m_player[p].m_fAliveSeconds ); - - vector asModifiers; - { - RString sPlayerOptions = GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.GetStage().GetString(); - if( !sPlayerOptions.empty() ) - asModifiers.push_back( sPlayerOptions ); - RString sSongOptions = GAMESTATE->m_SongOptions.GetStage().GetString(); - if( !sSongOptions.empty() ) - asModifiers.push_back( sSongOptions ); - } - hs.SetModifiers( join(", ", asModifiers) ); - - hs.SetDateTime( DateTime::GetNowDateTime() ); - hs.SetPlayerGuid( PROFILEMAN->IsPersistentProfile(p) ? PROFILEMAN->GetProfile(p)->m_sGuid : RString("") ); - hs.SetMachineGuid( PROFILEMAN->GetMachineProfile()->m_sGuid ); - hs.SetProductID( PREFSMAN->m_iProductID ); - FOREACH_ENUM( TapNoteScore, tns ) - hs.SetTapNoteScore( tns, m_player[p].m_iTapNoteScores[tns] ); - FOREACH_ENUM( HoldNoteScore, hns ) - hs.SetHoldNoteScore( hns, m_player[p].m_iHoldNoteScores[hns] ); - hs.SetRadarValues( m_player[p].m_radarActual ); - hs.SetLifeRemainingSeconds( m_player[p].m_fLifeRemainingSeconds ); + RString sPlayerGuid = "????"; // FIXME + m_multiPlayer[mp].m_HighScore = FillInHighScore( m_multiPlayer[mp], *GAMESTATE->m_pMultiPlayerState[mp], "", sPlayerGuid ); } FOREACH_HumanPlayer( p ) @@ -201,6 +215,10 @@ void StageStats::CommitScores( bool bSummary ) const Song* pSong = GAMESTATE->m_pCurSong; const Steps* pSteps = GAMESTATE->m_pCurSteps[p]; + // Don't save DQ'd scores + if( hs.GetDisqualified() ) + continue; + if( bSummary ) { // don't save scores if any stage was failed @@ -217,6 +235,8 @@ void StageStats::CommitScores( bool bSummary ) } else if( GAMESTATE->IsCourseMode() ) { + // Save this stage to recent scores + Course* pCourse = GAMESTATE->m_pCurCourse; ASSERT( pCourse ); Trail* pTrail = GAMESTATE->m_pCurTrail[p]; @@ -231,8 +251,6 @@ void StageStats::CommitScores( bool bSummary ) } } - LOG->Trace( "done saving stats and high scores" ); - // If both players get a machine high score in the same HighScoreList, // then one player's score may have bumped the other player. Look in // the HighScoreList and re-get the high score index. @@ -272,7 +290,7 @@ void StageStats::CommitScores( bool bSummary ) m_player[p].m_iMachineHighScoreIndex = iter - pHSL->vHighScores.begin(); } - + LOG->Trace( "done saving stats and high scores" ); } bool StageStats::PlayerHasHighScore( PlayerNumber pn ) const diff --git a/stepmania/src/StageStats.h b/stepmania/src/StageStats.h index e6f21852c8..57cc33573e 100644 --- a/stepmania/src/StageStats.h +++ b/stepmania/src/StageStats.h @@ -49,7 +49,7 @@ public: PlayerStageStats m_player[NUM_PLAYERS]; PlayerStageStats m_multiPlayer[NUM_MultiPlayer]; - void CommitScores( bool bSummary ); + void FinalizeScores( bool bSummary ); // finalize by filling in the HighScore structures for all players bool PlayerHasHighScore( PlayerNumber pn ) const; int GetMinimumMissCombo() const; diff --git a/stepmania/src/StatsManager.cpp b/stepmania/src/StatsManager.cpp index 05784a9774..65f29a2684 100644 --- a/stepmania/src/StatsManager.cpp +++ b/stepmania/src/StatsManager.cpp @@ -8,6 +8,10 @@ #include "Steps.h" #include "StyleUtil.h" #include "LuaManager.h" +#include "Profile.h" +#include "XmlFile.h" +#include "CryptManager.h" +#include "XmlFileUtil.h" StatsManager* STATSMAN = NULL; // global object accessable from anywhere in the program @@ -156,12 +160,47 @@ void AddPlayerStatsToProfile( Profile *pProfile, const StageStats &ss, PlayerNum } } +XNode* MakeRecentScoreNode( const StageStats &ss, Trail *pTrail, const PlayerStageStats &pss, MultiPlayer mp ) +{ + XNode* pNode = NULL; + if( GAMESTATE->IsCourseMode() ) + { + pNode = new XNode( "HighScoreForACourseAndTrail" ); + + CourseID courseID; + courseID.FromCourse(GAMESTATE->m_pCurCourse ); + pNode->AppendChild( courseID.CreateNode() ); + + TrailID trailID; + trailID.FromTrail( pTrail ); + pNode->AppendChild( trailID.CreateNode() ); + + } + else + { + XNode* pNode = new XNode( "HighScoreForASongAndSteps" ); + + SongID songID; + songID.FromSong( ss.m_vpPossibleSongs[0] ); + pNode->AppendChild( songID.CreateNode() ); + + StepsID stepsID; + stepsID.FromSteps( pss.m_vpPossibleSteps[0] ); + pNode->AppendChild( stepsID.CreateNode() ); + } + + XNode* pHighScore = pss.m_HighScore.CreateNode(); + pHighScore->AppendChild("Pad", mp); + RString sStageGuid = ssprintf("%08x-0000-1000-0000-53FA337761C6", GAMESTATE->m_iStageSeed); + pHighScore->AppendChild("StageGuid", sStageGuid); + + pNode->AppendChild( pHighScore ); + + return pNode; +} void StatsManager::CommitStatsToProfiles( const StageStats *pSS ) { - if( GAMESTATE->m_bMultiplayer ) - return; - // // Add step totals. Use radarActual, since the player might have failed part way // through the song, in which case we don't want to give credit for the rest of the @@ -188,24 +227,63 @@ void StatsManager::CommitStatsToProfiles( const StageStats *pSS ) pMachineProfile->m_iNumTotalSongsPlayed += pSS->m_vpPlayedSongs.size(); CHECKPOINT; - FOREACH_HumanPlayer( pn ) + if( !GAMESTATE->m_bMultiplayer ) // FIXME { - CHECKPOINT; - - Profile* pPlayerProfile = PROFILEMAN->GetProfile( pn ); - if( pPlayerProfile ) + FOREACH_HumanPlayer( pn ) { - pPlayerProfile->m_iTotalGameplaySeconds += iGameplaySeconds; - pPlayerProfile->m_iNumTotalSongsPlayed += pSS->m_vpPlayedSongs.size(); + CHECKPOINT; + + Profile* pPlayerProfile = PROFILEMAN->GetProfile( pn ); + if( pPlayerProfile ) + { + pPlayerProfile->m_iTotalGameplaySeconds += iGameplaySeconds; + pPlayerProfile->m_iNumTotalSongsPlayed += pSS->m_vpPlayedSongs.size(); + } + + AddPlayerStatsToProfile( pMachineProfile, *pSS, pn ); + + if( pPlayerProfile ) + AddPlayerStatsToProfile( pPlayerProfile, *pSS, pn ); + + CHECKPOINT; } - - AddPlayerStatsToProfile( pMachineProfile, *pSS, pn ); - - if( pPlayerProfile ) - AddPlayerStatsToProfile( pPlayerProfile, *pSS, pn ); - - CHECKPOINT; } + + // Save recent scores + { + auto_ptr xml( new XNode("Stats") ); + xml->AppendChild( "MachineGuid", PROFILEMAN->GetMachineProfile()->m_sGuid ); + + XNode *recent = NULL; + if( GAMESTATE->IsCourseMode() ) + recent = xml->AppendChild( new XNode("RecentCourseScores") ); + else + recent = xml->AppendChild( new XNode("RecentSongScores") ); + + FOREACH_HumanPlayer( p ) + recent->AppendChild( MakeRecentScoreNode( *pSS, GAMESTATE->m_pCurTrail[p], pSS->m_player[p], MultiPlayer_Invalid ) ); + + FOREACH_EnabledMultiPlayer( mp ) + recent->AppendChild( MakeRecentScoreNode( *pSS, GAMESTATE->m_pCurTrail[GAMESTATE->m_MasterPlayerNumber], pSS->m_multiPlayer[mp], mp ) ); + + + RString sDate = DateTime::GetNowDate().GetString(); + sDate.Replace(":","-"); + + const RString UPLOAD_DIR = "Save/Upload/"; + RString sFileNameNoExtension = Profile::MakeUniqueFileNameNoExtension(UPLOAD_DIR, sDate + " " ); + RString fn = UPLOAD_DIR + sFileNameNoExtension + ".xml"; + + bool bSaved = XmlFileUtil::SaveToFile( xml.get(), fn, "", false ); + + if( bSaved ) + { + RString sStatsXmlSigFile = fn + SIGNATURE_APPEND; + CryptManager::SignFileToFile(fn, sStatsXmlSigFile); + } + } + + FileCopy( "Data/TempTestGroups.xml", "Save/Upload/data.xml" ); } void StatsManager::UnjoinPlayer( PlayerNumber pn ) diff --git a/stepmania/src/StepsDisplay.cpp b/stepmania/src/StepsDisplay.cpp index d5a041fb06..e7f667c1cb 100644 --- a/stepmania/src/StepsDisplay.cpp +++ b/stepmania/src/StepsDisplay.cpp @@ -125,7 +125,7 @@ void StepsDisplay::SetFromGameState( PlayerNumber pn ) if( pTrail ) SetFromTrail( pTrail ); else - SetFromStepsTypeAndMeterAndCourseDifficulty( StepsType_Invalid, 0, GAMESTATE->m_PreferredCourseDifficulty[pn] ); + SetFromStepsTypeAndMeterAndDifficultyAndCourseType( StepsType_Invalid, 0, GAMESTATE->m_PreferredCourseDifficulty[pn], pTrail->m_CourseType ); } else { @@ -133,7 +133,7 @@ void StepsDisplay::SetFromGameState( PlayerNumber pn ) if( pSteps ) SetFromSteps( pSteps ); else - SetFromStepsTypeAndMeterAndDifficulty( StepsType_Invalid, 0, GAMESTATE->m_PreferredDifficulty[pn] ); + SetFromStepsTypeAndMeterAndDifficultyAndCourseType( StepsType_Invalid, 0, GAMESTATE->m_PreferredDifficulty[pn], CourseType_Invalid ); } } @@ -145,7 +145,7 @@ void StepsDisplay::SetFromSteps( const Steps* pSteps ) return; } - SetParams params = { pSteps, NULL, pSteps->GetMeter(), pSteps->m_StepsType, pSteps->GetDifficulty(), false, pSteps->GetDescription() }; + SetParams params = { pSteps, NULL, pSteps->GetMeter(), pSteps->m_StepsType, pSteps->GetDifficulty(), CourseType_Invalid }; SetInternal( params ); } @@ -157,50 +157,50 @@ void StepsDisplay::SetFromTrail( const Trail* pTrail ) return; } - SetParams params = { NULL, pTrail, pTrail->GetMeter(), pTrail->m_StepsType, pTrail->m_CourseDifficulty, true, RString() }; + SetParams params = { NULL, pTrail, pTrail->GetMeter(), pTrail->m_StepsType, pTrail->m_CourseDifficulty, pTrail->m_CourseType }; SetInternal( params ); } void StepsDisplay::Unset() { - SetParams params = { NULL, NULL, 0, StepsType_Invalid, Difficulty_Invalid, false, RString() }; - SetInternal( params ); + this->SetVisible( false ); } -void StepsDisplay::SetFromStepsTypeAndMeterAndDifficulty( StepsType st, int iMeter, Difficulty dc ) +void StepsDisplay::SetFromStepsTypeAndMeterAndDifficultyAndCourseType( StepsType st, int iMeter, Difficulty dc, CourseType ct ) { - SetParams params = { NULL, NULL, iMeter, st, dc, false, RString() }; - SetInternal( params ); -} - -void StepsDisplay::SetFromStepsTypeAndMeterAndCourseDifficulty( StepsType st, int iMeter, CourseDifficulty cd ) -{ - SetParams params = { NULL, NULL, 0, st, cd, true, RString() }; + SetParams params = { NULL, NULL, iMeter, st, dc, ct }; SetInternal( params ); } void StepsDisplay::SetInternal( const SetParams ¶ms ) { + this->SetVisible( true ); + Message msg( "Set" ); + + RString sCustomDifficulty; + if( params.pSteps ) + sCustomDifficulty = StepsToCustomDifficulty(params.pSteps); + else if( params.pTrail ) + sCustomDifficulty = TrailToCustomDifficulty(params.pTrail); + else + sCustomDifficulty = GetCustomDifficulty( params.st, params.dc, params.ct ); + msg.SetParam( "CustomDifficulty", sCustomDifficulty ); + + RString sDisplayDescription; + if( params.pSteps && params.pSteps->IsAnEdit() ) + sDisplayDescription = params.pSteps->GetDescription(); + else + sDisplayDescription = CustomDifficultyToLocalizedString( sCustomDifficulty ); + msg.SetParam( "DisplayDescription", sDisplayDescription ); + if( params.pSteps ) msg.SetParam( "Steps", LuaReference::CreateFromPush(*(Steps*)params.pSteps) ); if( params.pTrail ) msg.SetParam( "Trail", LuaReference::CreateFromPush(*(Trail*)params.pTrail) ); msg.SetParam( "Meter", params.iMeter ); msg.SetParam( "StepsType", params.st ); - msg.SetParam( "Difficulty", params.dc ); - msg.SetParam( "IsCourseDifficulty", params.bIsCourseDifficulty ); - msg.SetParam( "Description", params.sDescription ); - RString sCustomDifficulty; - if( params.st != StepsType_Invalid ) - { - if( params.pSteps ) - sCustomDifficulty = StepsToCustomDifficulty(params.pSteps); - if( params.pTrail ) - sCustomDifficulty = TrailToCustomDifficulty(params.pTrail); - msg.SetParam( "CustomDifficulty", sCustomDifficulty ); - } - + m_sprFrame->HandleMessage( msg ); if( m_bShowTicks ) @@ -231,20 +231,7 @@ void StepsDisplay::SetInternal( const SetParams ¶ms ) if( m_bShowDescription ) { - RString s; - if( params.bIsCourseDifficulty ) - { - s = CourseDifficultyToLocalizedString(params.dc); - } - else - { - if( params.pSteps && params.pSteps->IsAnEdit() ) - s = params.sDescription; - else if( !sCustomDifficulty.empty() ) - s = CustomDifficultyToLocalizedString( sCustomDifficulty ); - } - - m_textDescription.SetText( s ); + m_textDescription.SetText( sDisplayDescription ); } if( m_bShowAutogen ) @@ -273,7 +260,6 @@ class LunaStepsDisplay: public Luna { public: static int Load( T* p, lua_State *L ) { p->Load( SArg(1), NULL ); return 0; } - static int SetFromStepsTypeAndMeterAndDifficulty( T* p, lua_State *L ) { p->SetFromStepsTypeAndMeterAndDifficulty( Enum::Check(L, 1), IArg(2), Enum::Check(L, 3) ); return 0; } static int SetFromSteps( T* p, lua_State *L ) { if( lua_isnil(L,1) ) @@ -310,7 +296,6 @@ public: LunaStepsDisplay() { ADD_METHOD( Load ); - ADD_METHOD( SetFromStepsTypeAndMeterAndDifficulty ); ADD_METHOD( SetFromSteps ); ADD_METHOD( SetFromTrail ); ADD_METHOD( SetFromGameState ); diff --git a/stepmania/src/StepsDisplay.h b/stepmania/src/StepsDisplay.h index 6adcf0f8e6..9f2c0e04bf 100644 --- a/stepmania/src/StepsDisplay.h +++ b/stepmania/src/StepsDisplay.h @@ -27,8 +27,7 @@ public: virtual StepsDisplay *Copy() const; void SetFromGameState( PlayerNumber pn ); - void SetFromStepsTypeAndMeterAndDifficulty( StepsType st, int iMeter, Difficulty dc ); - void SetFromStepsTypeAndMeterAndCourseDifficulty( StepsType st, int iMeter, CourseDifficulty cd ); + void SetFromStepsTypeAndMeterAndDifficultyAndCourseType( StepsType st, int iMeter, Difficulty dc, CourseType ct ); void SetFromSteps( const Steps* pSteps ); void SetFromTrail( const Trail* pTrail ); void Unset(); @@ -42,10 +41,9 @@ private: const Steps *pSteps; const Trail *pTrail; int iMeter; - StepsType st; + StepsType st; // pass because there may be a StepType icons Difficulty dc; - bool bIsCourseDifficulty; - RString sDescription; + CourseType ct; }; void SetInternal( const SetParams ¶ms );