void GraphDisplay::Set( const StageStats &ss, const PlayerStageStats &pss ) { float fTotalStepSeconds = ss.GetTotalPossibleStepsSeconds(); m_Values.resize( VALUE_RESOLUTION ); pss.GetLifeRecord( &m_Values[0], VALUE_RESOLUTION, ss.GetTotalPossibleStepsSeconds() ); for (auto &value: m_Values) { value = Rage::clamp( value, 0.f, 1.f ); } UpdateVerts(); // Show song boundaries float fSec = 0; auto &songs = ss.m_vpPossibleSongs; for (auto song = songs.begin(); song != songs.end(); ++song) { if( song == songs.end()-1 ) continue; fSec += (*song)->GetStepsSeconds(); Actor *p = m_sprSongBoundary->Copy(); m_vpSongBoundaries.push_back( p ); float fX = Rage::scale( fSec, 0.f, fTotalStepSeconds, m_quadVertices.left, m_quadVertices.right ); p->SetX( fX ); this->AddChild( p ); } if( !pss.m_bFailed ) { // Search for the min life record to show "Just Barely!" float fMinLifeSoFar = 1.0f; int iMinLifeSoFarAt = 0; for( int i = 0; i < VALUE_RESOLUTION; ++i ) { float fLife = m_Values[i]; if( fLife < fMinLifeSoFar ) { fMinLifeSoFar = fLife; iMinLifeSoFarAt = i; } } if( fMinLifeSoFar > 0.0f && fMinLifeSoFar < 0.1f ) { float fX = Rage::scale( float(iMinLifeSoFarAt), 0.0f, float(VALUE_RESOLUTION-1), m_quadVertices.left, m_quadVertices.right ); m_sprBarely->SetX( fX ); } else { m_sprBarely->SetVisible( false ); } this->AddChild( m_sprBarely ); } }
void StatsManager::GetFinalEvalStageStats( StageStats& statsOut ) const { statsOut.Init(); vector<StageStats> vssToCount; // Show stats only for the latest 3 normal songs + passed extra stages int PassedRegularSongsLeft = 3; for( int i = (int)m_vPlayedStageStats.size()-1; i >= 0; --i ) { const StageStats &ss = m_vPlayedStageStats[i]; if( !ss.OnePassed() ) continue; if( ss.m_Stage != Stage_Extra1 && ss.m_Stage != Stage_Extra2 ) { if( PassedRegularSongsLeft == 0 ) break; --PassedRegularSongsLeft; } vssToCount.push_back( ss ); } statsOut = AccumPlayedStageStats( vssToCount ); }
void StatsManager::GetFinalEvalStageStats( StageStats& statsOut ) const { statsOut.Init(); vector<StageStats> vssToCount; for (auto &stats: m_vPlayedStageStats) { vssToCount.push_back(stats); } statsOut = AccumPlayedStageStats( vssToCount ); }
void StatsManager::GetFinalEvalStageStats( StageStats& statsOut ) const { statsOut.Init(); vector<StageStats> vssToCount; for(size_t i= 0; i < m_vPlayedStageStats.size(); ++i) { vssToCount.push_back(m_vPlayedStageStats[i]); } statsOut = AccumPlayedStageStats( vssToCount ); }
static StageStats AccumPlayedStageStats( const vector<StageStats>& vss ) { StageStats ssreturn; if( !vss.empty() ) { ssreturn.m_playMode = vss[0].m_playMode; } for (auto &ss: vss) { ssreturn.AddStats( ss ); } unsigned uNumSongs = ssreturn.m_vpPlayedSongs.size(); if( uNumSongs == 0 ) return ssreturn; // don't divide by 0 below /* Scale radar percentages back down to roughly 0..1. Don't scale RadarCategory_TapsAndHolds * and the rest, which are counters. */ // FIXME: Weight each song by the number of stages it took to account for // long, marathon. FOREACH_EnabledPlayer( p ) { for( int r = 0; r < RadarCategory_TapsAndHolds; r++) { ssreturn.m_player[p].m_radarPossible[r] /= uNumSongs; ssreturn.m_player[p].m_radarActual[r] /= uNumSongs; } } FOREACH_EnabledMultiPlayer( p ) { for( int r = 0; r < RadarCategory_TapsAndHolds; r++) { ssreturn.m_multiPlayer[p].m_radarPossible[r] /= uNumSongs; ssreturn.m_multiPlayer[p].m_radarActual[r] /= uNumSongs; } } return ssreturn; }
/* This data is added to each player profile, and to the machine profile per-player. */ void AddPlayerStatsToProfile( Profile *pProfile, const StageStats &ss, PlayerNumber pn ) { ss.AssertValid( pn ); CHECKPOINT; StyleID sID; sID.FromStyle( ss.m_pStyle ); ASSERT( (int) ss.m_vpPlayedSongs.size() == ss.m_player[pn].m_iStepsPlayed ); for( int i=0; i<ss.m_player[pn].m_iStepsPlayed; i++ ) { Steps *pSteps = ss.m_player[pn].m_vpPossibleSteps[i]; pProfile->m_iNumSongsPlayedByPlayMode[ss.m_playMode]++; pProfile->m_iNumSongsPlayedByStyle[sID] ++; pProfile->m_iNumSongsPlayedByDifficulty[pSteps->GetDifficulty()] ++; int iMeter = clamp( pSteps->GetMeter(), 0, MAX_METER ); pProfile->m_iNumSongsPlayedByMeter[iMeter] ++; } pProfile->m_iTotalDancePoints += ss.m_player[pn].m_iActualDancePoints; if( ss.m_Stage == Stage_Extra1 || ss.m_Stage == Stage_Extra2 ) { if( ss.m_player[pn].m_bFailed ) ++pProfile->m_iNumExtraStagesFailed; else ++pProfile->m_iNumExtraStagesPassed; } // If you fail in a course, you passed all but the final song. // FIXME: Not true. If playing with 2 players, one player could have failed earlier. if( !ss.m_player[pn].m_bFailed ) { pProfile->m_iNumStagesPassedByPlayMode[ss.m_playMode] ++; pProfile->m_iNumStagesPassedByGrade[ss.m_player[pn].GetGrade()] ++; } }
void ComboGraph::Set( const StageStats &s, const PlayerStageStats &pss ) { using std::max; const float fFirstSecond = 0; const float fLastSecond = s.GetTotalPossibleStepsSeconds(); // Find the largest combo. int iMaxComboSize = 0; for( unsigned i = 0; i < pss.m_ComboList.size(); ++i ) iMaxComboSize = max( iMaxComboSize, pss.m_ComboList[i].GetStageCnt() ); for( unsigned i = 0; i < pss.m_ComboList.size(); ++i ) { const PlayerStageStats::Combo_t &combo = pss.m_ComboList[i]; if( combo.GetStageCnt() < MinComboSizeToShow ) continue; // too small const bool bIsMax = (combo.GetStageCnt() == iMaxComboSize); LOG->Trace( "combo %i is %f+%f of %f", i, combo.m_fStartSecond, combo.m_fSizeSeconds, fLastSecond ); Actor *pSprite = bIsMax? m_pMaxCombo->Copy() : m_pNormalCombo->Copy(); const float fStart = Rage::scale( combo.m_fStartSecond, fFirstSecond, fLastSecond, 0.0f, 1.0f ); const float fSize = Rage::scale( combo.m_fSizeSeconds, 0.f, fLastSecond-fFirstSecond, 0.0f, 1.0f ); pSprite->SetCropLeft ( Rage::scale( fSize, 0.0f, 1.0f, 0.5f, 0.0f ) ); pSprite->SetCropRight( Rage::scale( fSize, 0.0f, 1.0f, 0.5f, 0.0f ) ); pSprite->SetCropLeft( fStart ); pSprite->SetCropRight( 1 - (fSize + fStart) ); this->AddChild( pSprite ); } for( unsigned i = 0; i < pss.m_ComboList.size(); ++i ) { const PlayerStageStats::Combo_t &combo = pss.m_ComboList[i]; if( combo.GetStageCnt() < MinComboSizeToShow ) continue; // too small if( !iMaxComboSize ) continue; const bool bIsMax = (combo.GetStageCnt() == iMaxComboSize); if( !bIsMax ) continue; BitmapText *pText = m_pComboNumber->Copy(); const float fStart = Rage::scale( combo.m_fStartSecond, fFirstSecond, fLastSecond, 0.0f, 1.0f ); const float fSize = Rage::scale( combo.m_fSizeSeconds, 0.f, fLastSecond-fFirstSecond, 0.0f, 1.0f ); const float fCenterPercent = fStart + fSize/2; const float fCenterXPos = Rage::scale( fCenterPercent, 0.0f, 1.0f, -BODY_WIDTH/2.0f, BODY_WIDTH/2.0f ); pText->SetX( fCenterXPos ); pText->SetText( fmt::sprintf("%i",combo.GetStageCnt()) ); this->AddChild( pText ); } // Hide the templates. m_pNormalCombo->SetVisible( false ); m_pMaxCombo->SetVisible( false ); m_pComboNumber->SetVisible( false ); }