Files
itgmania212121/stepmania/src/HighScore.cpp
T

278 lines
7.9 KiB
C++
Raw Normal View History

2004-02-10 09:42:01 +00:00
#include "global.h"
#include "HighScore.h"
#include "PrefsManager.h"
#include "GameConstantsAndTypes.h"
2004-03-08 02:50:46 +00:00
#include "ThemeManager.h"
2004-05-22 01:35:08 +00:00
#include "XmlFile.h"
2005-01-07 09:09:23 +00:00
#include "Foreach.h"
2004-03-08 02:50:46 +00:00
#define EMPTY_NAME THEME->GetMetric ("HighScore","EmptyName")
2004-02-10 09:42:01 +00:00
bool HighScore::operator>=( const HighScore& other ) const
{
/* Make sure we treat AAAA as higher than AAA, even though the score
* is the same.
*
* XXX: Isn't it possible to beat the grade but not beat the score, since
* grading and scores are on completely different systems? Should we be
* checking for these completely separately? */
if( PREFSMAN->m_bPercentageScoring )
{
if( fPercentDP == other.fPercentDP )
return grade >= other.grade;
else
return fPercentDP >= other.fPercentDP;
}
else
{
if( iScore == other.iScore )
return grade >= other.grade;
else
return iScore >= other.iScore;
}
}
XNode* HighScore::CreateNode() const
{
XNode* pNode = new XNode;
2005-01-07 14:28:00 +00:00
pNode->m_sName = "HighScore";
2004-02-10 09:42:01 +00:00
2004-02-11 03:46:54 +00:00
// TRICKY: Don't write "name to fill in" markers.
2004-08-06 21:01:28 +00:00
pNode->AppendChild( "Name", IsRankingToFillIn(sName) ? CString("") : sName );
2004-05-20 03:50:42 +00:00
pNode->AppendChild( "Grade", GradeToString(grade) );
2004-02-10 09:42:01 +00:00
pNode->AppendChild( "Score", iScore );
pNode->AppendChild( "PercentDP", fPercentDP );
pNode->AppendChild( "SurviveSeconds", fSurviveSeconds );
pNode->AppendChild( "Modifiers", sModifiers );
2004-07-19 08:05:14 +00:00
pNode->AppendChild( "DateTime", dateTime );
2004-04-22 22:56:38 +00:00
pNode->AppendChild( "PlayerGuid", sPlayerGuid );
2004-04-18 19:49:45 +00:00
pNode->AppendChild( "MachineGuid", sMachineGuid );
pNode->AppendChild( "ProductID", iProductID );
XNode* pTapNoteScores = pNode->AppendChild( "TapNoteScores" );
FOREACH_TapNoteScore( tns )
if( tns != TNS_NONE ) // HACK: don't save meaningless "none" count
pTapNoteScores->AppendChild( TapNoteScoreToString(tns), iTapNoteScores[tns] );
XNode* pHoldNoteScores = pNode->AppendChild( "HoldNoteScores" );
FOREACH_HoldNoteScore( hns )
if( hns != HNS_NONE ) // HACK: don't save meaningless "none" count
pHoldNoteScores->AppendChild( HoldNoteScoreToString(hns), iHoldNoteScores[hns] );
2004-07-19 08:05:14 +00:00
pNode->AppendChild( radarValues.CreateNode() );
2004-02-10 09:42:01 +00:00
return pNode;
}
2004-02-19 03:19:41 +00:00
void HighScore::LoadFromNode( const XNode* pNode )
2004-02-10 09:42:01 +00:00
{
2005-01-07 14:28:00 +00:00
ASSERT( pNode->m_sName == "HighScore" );
CString s;
pNode->GetChildValue( "Name", sName );
pNode->GetChildValue( "Grade", s );
/* Pre-a19 compatibility; remove eventually */
if( IsAnInt(s) )
grade = (Grade) atoi( s );
else
grade = StringToGrade( s );
pNode->GetChildValue( "Score", iScore );
pNode->GetChildValue( "PercentDP", fPercentDP );
pNode->GetChildValue( "SurviveSeconds", fSurviveSeconds );
pNode->GetChildValue( "Modifiers", sModifiers );
2004-07-19 08:05:14 +00:00
pNode->GetChildValue( "DateTime", dateTime );
pNode->GetChildValue( "PlayerGuid", sPlayerGuid );
pNode->GetChildValue( "MachineGuid", sMachineGuid );
pNode->GetChildValue( "ProductID", iProductID );
2004-07-23 02:27:07 +00:00
const XNode* pTapNoteScores = pNode->GetChild( "TapNoteScores" );
if( pTapNoteScores )
FOREACH_TapNoteScore( tns )
pTapNoteScores->GetChildValue( TapNoteScoreToString(tns), iTapNoteScores[tns] );
2004-07-23 02:27:07 +00:00
const XNode* pHoldNoteScores = pNode->GetChild( "HoldNoteScores" );
if( pHoldNoteScores )
FOREACH_HoldNoteScore( hns )
pHoldNoteScores->GetChildValue( HoldNoteScoreToString(hns), iHoldNoteScores[hns] );
2004-07-23 02:27:07 +00:00
const XNode* pRadarValues = pNode->GetChild( "RadarValues" );
2004-07-11 07:21:33 +00:00
if( pRadarValues )
radarValues.LoadFromNode( pRadarValues );
/* Validate input. */
grade = clamp( grade, GRADE_TIER01, GRADE_FAILED );
2004-02-10 09:42:01 +00:00
}
2004-03-08 02:50:46 +00:00
CString HighScore::GetDisplayName() const
{
if( sName.empty() )
return EMPTY_NAME;
else
return sName;
}
2004-02-10 09:42:01 +00:00
void HighScoreList::Init()
{
iNumTimesPlayed = 0;
vHighScores.clear();
}
void HighScoreList::AddHighScore( HighScore hs, int &iIndexOut, bool bIsMachine )
2004-02-10 09:42:01 +00:00
{
int i;
for( i=0; i<(int)vHighScores.size(); i++ )
{
if( hs >= vHighScores[i] )
break;
}
const int iMaxScores = bIsMachine ?
PREFSMAN->m_iMaxHighScoresPerListForMachine :
PREFSMAN->m_iMaxHighScoresPerListForPlayer;
if( i < iMaxScores )
2004-02-10 09:42:01 +00:00
{
vHighScores.insert( vHighScores.begin()+i, hs );
iIndexOut = i;
2005-04-25 09:03:24 +00:00
// Delete extra machine high scores in RemoveAllButOneOfEachNameAndClampSize
// and not here so that we don't end up with less than iMaxScores after
// removing HighScores with duplicate names.
//
if( !bIsMachine )
ClampSize( bIsMachine );
2004-02-10 09:42:01 +00:00
}
}
2004-04-26 00:06:42 +00:00
2005-04-25 22:44:32 +00:00
void HighScoreList::IncrementPlayCount( DateTime dtLastPlayed )
{
dtLastPlayed = dtLastPlayed;
iNumTimesPlayed++;
}
2004-02-10 09:42:01 +00:00
const HighScore& HighScoreList::GetTopScore() const
{
if( vHighScores.empty() )
{
static HighScore hs;
hs = HighScore();
return hs;
}
else
{
return vHighScores[0];
}
}
XNode* HighScoreList::CreateNode() const
{
XNode* pNode = new XNode;
2005-01-07 14:28:00 +00:00
pNode->m_sName = "HighScoreList";
2004-02-10 09:42:01 +00:00
pNode->AppendChild( "NumTimesPlayed", iNumTimesPlayed );
2005-05-01 09:14:11 +00:00
pNode->AppendChild( "LastPlayed", dtLastPlayed );
2004-02-10 09:42:01 +00:00
2004-02-10 10:15:27 +00:00
for( unsigned i=0; i<vHighScores.size(); i++ )
2004-02-10 09:42:01 +00:00
{
const HighScore &hs = vHighScores[i];
pNode->AppendChild( hs.CreateNode() );
}
return pNode;
}
2005-01-07 09:09:23 +00:00
void HighScoreList::LoadFromNode( const XNode* pHighScoreList )
2004-02-10 09:42:01 +00:00
{
Init();
2005-01-07 14:28:00 +00:00
ASSERT( pHighScoreList->m_sName == "HighScoreList" );
2005-01-07 09:09:23 +00:00
FOREACH_CONST_Child( pHighScoreList, p )
2004-02-10 09:42:01 +00:00
{
2005-01-07 14:28:00 +00:00
if( p->m_sName == "NumTimesPlayed" )
2004-02-10 09:42:01 +00:00
{
2005-01-07 09:09:23 +00:00
p->GetValue( iNumTimesPlayed );
2004-02-10 09:42:01 +00:00
}
2005-04-25 22:44:32 +00:00
else if( p->m_sName == "LastPlayed" )
{
p->GetValue( dtLastPlayed );
}
2005-01-07 14:28:00 +00:00
else if( p->m_sName == "HighScore" )
2004-02-10 09:42:01 +00:00
{
vHighScores.resize( vHighScores.size()+1 );
2005-01-07 09:09:23 +00:00
vHighScores.back().LoadFromNode( p );
2004-02-10 09:42:01 +00:00
// ignore all high scores that are 0
if( vHighScores.back().iScore == 0 )
vHighScores.pop_back();
}
}
}
2005-04-25 09:03:24 +00:00
void HighScoreList::RemoveAllButOneOfEachName()
{
FOREACH( HighScore, vHighScores, i )
{
for( vector<HighScore>::iterator j = i+1; j != vHighScores.end(); j++ )
{
if( i->sName == j->sName )
{
j--;
vHighScores.erase( j+1 );
}
}
}
}
void HighScoreList::ClampSize( bool bIsMachine )
{
const int iMaxScores = bIsMachine ?
PREFSMAN->m_iMaxHighScoresPerListForMachine :
PREFSMAN->m_iMaxHighScoresPerListForPlayer;
if( vHighScores.size() > unsigned(iMaxScores) )
vHighScores.erase( vHighScores.begin()+iMaxScores, vHighScores.end() );
}
2004-06-12 07:01:07 +00:00
XNode* Screenshot::CreateNode() const
{
XNode* pNode = new XNode;
2005-01-07 14:28:00 +00:00
pNode->m_sName = "Screenshot";
2004-06-12 07:01:07 +00:00
// TRICKY: Don't write "name to fill in" markers.
pNode->AppendChild( "FileName", sFileName );
pNode->AppendChild( "MD5", sMD5 );
pNode->AppendChild( highScore.CreateNode() );
return pNode;
}
void Screenshot::LoadFromNode( const XNode* pNode )
{
2005-01-07 14:28:00 +00:00
ASSERT( pNode->m_sName == "Screenshot" );
2004-06-12 07:01:07 +00:00
pNode->GetChildValue( "FileName", sFileName );
pNode->GetChildValue( "MD5", sMD5 );
2004-07-23 02:27:07 +00:00
const XNode* pHighScore = pNode->GetChild( "HighScore" );
2004-06-12 07:01:07 +00:00
if( pHighScore )
highScore.LoadFromNode( pHighScore );
}
2004-05-31 22:42:12 +00:00
/*
* (c) 2004 Chris Danford
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/