void StepsUtil::SortStepsPointerArrayByNumPlays( vector<Steps*> &vStepsPointers, const Profile* pProfile, bool bDecending ) { // ugly... vector<Song*> vpSongs = SONGMAN->GetAllSongs(); vector<Steps*> vpAllSteps; map<Steps*,Song*> mapStepsToSong; { for( unsigned i=0; i<vpSongs.size(); i++ ) { Song* pSong = vpSongs[i]; vector<Steps*> vpSteps = pSong->GetAllSteps(); for( unsigned j=0; j<vpSteps.size(); j++ ) { Steps* pSteps = vpSteps[j]; if( pSteps->IsAutogen() ) continue; // skip vpAllSteps.push_back( pSteps ); mapStepsToSong[pSteps] = pSong; } } } ASSERT( pProfile != NULL ); for(unsigned i = 0; i < vStepsPointers.size(); ++i) { Steps* pSteps = vStepsPointers[i]; Song* pSong = mapStepsToSong[pSteps]; steps_sort_val[vStepsPointers[i]] = ssprintf("%9i", pProfile->GetStepsNumTimesPlayed(pSong,pSteps)); } stable_sort( vStepsPointers.begin(), vStepsPointers.end(), bDecending ? CompareStepsPointersBySortValueDescending : CompareStepsPointersBySortValueAscending ); steps_sort_val.clear(); }
float Profile::GetSongsPossible( StepsType st, Difficulty dc ) const { int iTotalSteps = 0; // add steps high scores const vector<Song*> vSongs = SONGMAN->GetAllSongs(); for( unsigned i=0; i<vSongs.size(); i++ ) { Song* pSong = vSongs[i]; if( pSong->m_SelectionDisplay == Song::SHOW_NEVER ) continue; // skip vector<Steps*> vSteps = pSong->GetAllSteps(); for( unsigned j=0; j<vSteps.size(); j++ ) { Steps* pSteps = vSteps[j]; if( pSteps->m_StepsType != st ) continue; // skip if( pSteps->GetDifficulty() != dc ) continue; // skip iTotalSteps++; } } return (float) iTotalSteps; }
bool NotesWriterSM::Write(CString sPath, const Song &out, bool bSavingCache) { /* Flush dir cache when writing steps, so the old size isn't cached. */ FILEMAN->FlushDirCache( Dirname(sPath) ); unsigned i; int flags = RageFile::WRITE; /* If we're not saving cache, we're saving real data, so enable SLOW_FLUSH * to prevent data loss. If we're saving cache, this will slow things down * too much. */ if( !bSavingCache ) flags |= RageFile::SLOW_FLUSH; RageFile f; if( !f.Open( sPath, flags ) ) { LOG->Warn( "Error opening song file '%s' for writing: %s", sPath.c_str(), f.GetError().c_str() ); return false; } WriteGlobalTags( f, out ); if( bSavingCache ) { f.PutLine( ssprintf( "// cache tags:" ) ); f.PutLine( ssprintf( "#FIRSTBEAT:%.3f;", out.m_fFirstBeat ) ); f.PutLine( ssprintf( "#LASTBEAT:%.3f;", out.m_fLastBeat ) ); f.PutLine( ssprintf( "#SONGFILENAME:%s;", out.m_sSongFileName.c_str() ) ); f.PutLine( ssprintf( "#HASMUSIC:%i;", out.m_bHasMusic ) ); f.PutLine( ssprintf( "#HASBANNER:%i;", out.m_bHasBanner ) ); f.PutLine( ssprintf( "#MUSICLENGTH:%.3f;", out.m_fMusicLengthSeconds ) ); f.PutLine( ssprintf( "// end cache tags" ) ); } // // Save all Steps for this file // const vector<Steps*>& vpSteps = out.GetAllSteps(); for( i=0; i<vpSteps.size(); i++ ) { const Steps* pSteps = vpSteps[i]; if( pSteps->IsAutogen() ) continue; /* don't write autogen notes */ /* Only save steps that weren't loaded from a profile. */ if( pSteps->WasLoadedFromProfile() ) continue; WriteSMNotesTag( *pSteps, f, bSavingCache ); } return true; }
bool NotesWriterDWI::Write( RString sPath, const Song &out ) { RageFile f; if( !f.Open( sPath, RageFile::WRITE ) ) { LOG->UserLog( "Song file", sPath, "couldn't be opened for writing: %s", f.GetError().c_str() ); return false; } /* Write transliterations, if we have them, since DWI doesn't support UTF-8. */ f.PutLine( ssprintf("#TITLE:%s;", DwiEscape(out.GetTranslitFullTitle()).c_str()) ); f.PutLine( ssprintf("#ARTIST:%s;", DwiEscape(out.GetTranslitArtist()).c_str()) ); ASSERT( out.m_Timing.m_BPMSegments[0].m_iStartRow == 0 ); f.PutLine( ssprintf("#FILE:%s;", DwiEscape(out.m_sMusicFile).c_str()) ); f.PutLine( ssprintf("#BPM:%.3f;", out.m_Timing.m_BPMSegments[0].GetBPM()) ); f.PutLine( ssprintf("#GAP:%ld;", -lrintf( out.m_Timing.m_fBeat0OffsetInSeconds*1000 )) ); f.PutLine( ssprintf("#SAMPLESTART:%.3f;", out.m_fMusicSampleStartSeconds) ); f.PutLine( ssprintf("#SAMPLELENGTH:%.3f;", out.m_fMusicSampleLengthSeconds) ); if( out.m_sCDTitleFile.size() ) f.PutLine( ssprintf("#CDTITLE:%s;", DwiEscape(out.m_sCDTitleFile).c_str()) ); switch( out.m_DisplayBPMType ) { case Song::DISPLAY_ACTUAL: // write nothing break; case Song::DISPLAY_SPECIFIED: if( out.m_fSpecifiedBPMMin == out.m_fSpecifiedBPMMax ) f.PutLine( ssprintf("#DISPLAYBPM:%i;\n", (int) out.m_fSpecifiedBPMMin) ); else f.PutLine( ssprintf("#DISPLAYBPM:%i..%i;\n", (int) out.m_fSpecifiedBPMMin, (int) out.m_fSpecifiedBPMMax) ); break; case Song::DISPLAY_RANDOM: f.PutLine( "#DISPLAYBPM:*" ); break; } if( !out.m_Timing.m_StopSegments.empty() ) { f.Write( "#FREEZE:" ); for( unsigned i=0; i<out.m_Timing.m_StopSegments.size(); i++ ) { const StopSegment &fs = out.m_Timing.m_StopSegments[i]; f.Write( ssprintf("%.3f=%.3f", fs.m_iStartRow * 4.0f / ROWS_PER_BEAT, roundf(fs.m_fStopSeconds*1000)) ); if( i != out.m_Timing.m_StopSegments.size()-1 ) f.Write( "," ); } f.PutLine( ";" ); } if( out.m_Timing.m_BPMSegments.size() > 1) { f.Write( "#CHANGEBPM:" ); for( unsigned i=1; i<out.m_Timing.m_BPMSegments.size(); i++ ) { const BPMSegment &bs = out.m_Timing.m_BPMSegments[i]; f.Write( ssprintf("%.3f=%.3f", bs.m_iStartRow * 4.0f / ROWS_PER_BEAT, bs.GetBPM() ) ); if( i != out.m_Timing.m_BPMSegments.size()-1 ) f.Write( "," ); } f.PutLine( ";" ); } const vector<Steps*>& vpSteps = out.GetAllSteps(); for( unsigned i=0; i<vpSteps.size(); i++ ) { const Steps* pSteps = vpSteps[i]; if( pSteps->IsAutogen() ) continue; // don't save autogen notes if( !WriteDWINotesTag( f, *pSteps )) continue; WriteDWINotesField( f, *pSteps, 0 ); if( pSteps->m_StepsType==StepsType_dance_double || pSteps->m_StepsType==StepsType_dance_couple ) { f.PutLine( ":" ); WriteDWINotesField( f, *pSteps, 4 ); } f.PutLine( ";" ); } return true; }