autogen Oni courses by artist, sorted by song difficulty

This commit is contained in:
Glenn Maynard
2004-05-25 02:17:17 +00:00
parent d904805150
commit dbe044d039
3 changed files with 132 additions and 7 deletions
+86 -5
View File
@@ -272,6 +272,7 @@ void Course::Init()
m_bRepeat = false;
m_bRandomize = false;
m_iLives = -1;
m_bSortByMeter = false;
ZERO( m_iCustomMeter );
m_entries.clear();
m_sPath = m_sName = m_sTranslitName = m_sBannerPath = m_sCDTitlePath = "";
@@ -432,6 +433,47 @@ void Course::AutogenNonstopFromGroup( CString sGroupName, Difficulty diff )
m_entries.pop_back();
}
void Course::AutogenOniFromArtist( CString sArtistName, vector<Song*> aSongs, Difficulty dc )
{
m_bIsAutogen = true;
m_bRepeat = false;
m_bRandomize = true;
m_bSortByMeter = true;
m_iLives = 4;
m_iCustomMeter[0] = m_iCustomMeter[1] = -1;
ASSERT( sArtistName != "" );
ASSERT( aSongs.size() > 0 );
/* "Artist Oni" is a little repetitive; "by Artist" stands out less, and lowercasing
* "by" puts more emphasis on the artist's name. It also sorts them together. */
m_sName = "by " + sArtistName;
// m_sBannerPath = ""; // XXX
/* Shuffle the list to determine which songs we'll use. Shuffle it deterministically,
* so we always get the same set of songs unless the song set changes. */
{
RandomGen rng( GetHashForString( sArtistName ) + aSongs.size() );
random_shuffle( aSongs.begin(), aSongs.end(), rng );
}
/* Only use up to four songs. */
if( aSongs.size() > 4 )
aSongs.erase( aSongs.begin()+4, aSongs.end() );
CourseEntry e;
e.type = COURSE_ENTRY_FIXED;
e.difficulty = dc;
for( unsigned i = 0; i < aSongs.size(); ++i )
{
e.pSong = aSongs[i];
m_entries.push_back( e );
}
}
/*
* Difficult courses do the following:
*
@@ -501,6 +543,13 @@ static vector<Song*> GetFilteredBestSongs( StepsType st )
return ret;
}
struct SortTrailEntry
{
TrailEntry entry;
int SortMeter;
bool operator< ( const SortTrailEntry &rhs ) const { return SortMeter < rhs.SortMeter; }
};
/* This is called by many simple functions, like Course::GetTotalSeconds, and may
* be called on all songs to sort. It can take time to execute, so we cache the
* results. */
@@ -516,7 +565,44 @@ Trail* Course::GetTrail( StepsType st, CourseDifficulty cd ) const
return &it->second;
}
//
// Construct a new Trail, add it to the cache, then return it.
//
Trail trail;
GetTrailUnsorted( st, cd, trail );
if( this->m_bSortByMeter )
{
/* Sort according to COURSE_DIFFICULTY_REGULAR, since the order of songs
* must not change across difficulties. */
Trail SortTrail;
if( cd == COURSE_DIFFICULTY_REGULAR )
SortTrail = trail;
else
GetTrailUnsorted( st, COURSE_DIFFICULTY_REGULAR, SortTrail );
ASSERT_M( trail.m_vEntries.size() == SortTrail.m_vEntries.size(), ssprintf("%i %i", trail.m_vEntries.size(), SortTrail.m_vEntries.size()) );
vector<SortTrailEntry> entries;
for( unsigned i = 0; i < trail.m_vEntries.size(); ++i )
{
SortTrailEntry ste;
ste.entry = trail.m_vEntries[i];
ste.SortMeter = SortTrail.m_vEntries[i].pSteps->GetMeter();
entries.push_back( ste );
}
stable_sort( entries.begin(), entries.end() );
for( unsigned i = 0; i < trail.m_vEntries.size(); ++i )
trail.m_vEntries[i] = entries[i].entry;
}
/* Cache results. */
m_TrailCache[params] = trail;
return &m_TrailCache[params];
}
void Course::GetTrailUnsorted( StepsType st, CourseDifficulty cd, Trail &trail ) const
{
//
// Construct a new Trail, add it to the cache, then return it.
//
@@ -544,7 +630,6 @@ Trail* Course::GetTrail( StepsType st, CourseDifficulty cd ) const
int CurSong = 0; /* Current offset into AllSongsShuffled */
Trail trail;
trail.m_StepsType = st;
trail.m_CourseDifficulty = cd;
@@ -680,10 +765,6 @@ Trail* Course::GetTrail( StepsType st, CourseDifficulty cd ) const
te.iHighMeter = high_meter;
trail.m_vEntries.push_back( te );
}
/* Cache results. */
m_TrailCache[params] = trail;
return &m_TrailCache[params];
}
bool Course::HasMods() const
+5 -2
View File
@@ -95,6 +95,7 @@ public:
bool m_bRandomize; // play the songs in a random order
int m_iLives; // -1 means use bar life meter
int m_iCustomMeter[NUM_COURSE_DIFFICULTIES]; // -1 = no meter specified
bool m_bSortByMeter;
vector<CourseEntry> m_entries;
@@ -122,8 +123,9 @@ public:
void LoadFromCRSFile( CString sPath );
void Init();
void Save();
void AutogenEndlessFromGroup( CString sGroupName, Difficulty diff );
void AutogenNonstopFromGroup( CString sGroupName, Difficulty diff );
void AutogenEndlessFromGroup( CString sGroupName, Difficulty dc );
void AutogenNonstopFromGroup( CString sGroupName, Difficulty dc );
void AutogenOniFromArtist( CString sArtistName, vector<Song*> aSongs, Difficulty dc );
// sorting values
int m_SortOrder_TotalDifficulty;
@@ -136,6 +138,7 @@ public:
void ClearCache();
private:
void GetTrailUnsorted( StepsType st, CourseDifficulty cd, Trail &trail ) const;
void GetMeterRange( int stage, int& iMeterLowOut, int& iMeterHighOut, CourseDifficulty cd ) const;
typedef pair<StepsType,CourseDifficulty> TrailParams;
+41
View File
@@ -589,6 +589,47 @@ void SongManager::InitAutogenCourses()
pCourse = new Course;
pCourse->AutogenEndlessFromGroup( "", DIFFICULTY_MEDIUM );
m_pCourses.push_back( pCourse );
/* Generate Oni courses from artists. Only create courses if we have at least
* four songs from an artist; create 3- and 4-song courses. */
vector<Song *> aSongs;
{
vector<Song*> apSongs = this->GetAllSongs();
SongUtil::SortSongPointerArrayByArtist( apSongs );
CString sCurArtist = "";
int iCurArtistCount = 0;
unsigned i = 0;
do {
CString sArtist = i >= apSongs.size()? "": apSongs[i]->GetTranslitArtist();
if( i < apSongs.size() && !sCurArtist.CompareNoCase(sArtist) )
{
aSongs.push_back( apSongs[i] );
++iCurArtistCount;
continue;
}
/* Different artist, or we're at the end. If we have enough entries for
* the last artist, add it. Skip blanks and "Unknown artist". */
if( iCurArtistCount >= 3 && sCurArtist != "" &&
sCurArtist.CompareNoCase("Unknown artist") )
{
pCourse = new Course;
pCourse->AutogenOniFromArtist( sCurArtist, aSongs, DIFFICULTY_HARD );
m_pCourses.push_back( pCourse );
}
aSongs.clear();
if( i < apSongs.size() )
{
sCurArtist = sArtist;
iCurArtistCount = 1;
aSongs.push_back( apSongs[i] );
}
} while( i++ < apSongs.size() );
}
}