2004-02-08 18:25:30 +00:00
|
|
|
#include "global.h"
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------
|
2004-02-09 06:26:13 +00:00
|
|
|
Class: Profile
|
2004-02-08 18:25:30 +00:00
|
|
|
|
|
|
|
|
Desc: See header.
|
|
|
|
|
|
|
|
|
|
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
|
|
|
|
|
Chris Danford
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
2004-02-09 06:26:13 +00:00
|
|
|
#include "Profile.h"
|
2004-02-08 18:25:30 +00:00
|
|
|
#include "RageUtil.h"
|
2004-02-09 06:26:13 +00:00
|
|
|
#include "PrefsManager.h"
|
2004-02-10 09:42:01 +00:00
|
|
|
#include "XmlFile.h"
|
|
|
|
|
#include "IniFile.h"
|
|
|
|
|
#include "GameManager.h"
|
|
|
|
|
#include "RageLog.h"
|
|
|
|
|
#include "RageFile.h"
|
|
|
|
|
#include "song.h"
|
|
|
|
|
#include "SongManager.h"
|
|
|
|
|
#include "Steps.h"
|
|
|
|
|
#include "Course.h"
|
2004-04-05 05:22:32 +00:00
|
|
|
#include <ctime>
|
2004-02-10 09:42:01 +00:00
|
|
|
#include "ThemeManager.h"
|
2004-02-15 04:47:32 +00:00
|
|
|
#include "CryptManager.h"
|
2004-02-16 02:57:55 +00:00
|
|
|
#include "ProfileHtml.h"
|
|
|
|
|
#include "ProfileManager.h"
|
2004-02-19 03:56:03 +00:00
|
|
|
#include "RageFileManager.h"
|
2004-03-11 06:31:30 +00:00
|
|
|
#include "ScoreKeeperMAX2.h"
|
2004-03-14 17:49:38 +00:00
|
|
|
#include "crypto/CryptRand.h"
|
2004-05-08 08:09:18 +00:00
|
|
|
#include "UnlockSystem.h"
|
2004-05-22 01:35:08 +00:00
|
|
|
#include "XmlFile.h"
|
2004-05-23 21:08:03 +00:00
|
|
|
#include "Foreach.h"
|
2004-02-09 06:26:13 +00:00
|
|
|
|
2004-02-10 09:42:01 +00:00
|
|
|
//
|
|
|
|
|
// Old file versions for backward compatibility
|
|
|
|
|
//
|
|
|
|
|
#define SM_300_STATISTICS_INI "statistics.ini"
|
|
|
|
|
|
|
|
|
|
#define SM_390A12_CATEGORY_SCORES_DAT "CategoryScores.dat"
|
|
|
|
|
#define SM_390A12_SONG_SCORES_DAT "SongScores.dat"
|
|
|
|
|
#define SM_390A12_COURSE_SCORES_DAT "CourseScores.dat"
|
2004-02-19 03:56:03 +00:00
|
|
|
#define SM_390A12_PROFILE_INI "Profile.ini"
|
2004-02-10 09:42:01 +00:00
|
|
|
const int SM_390A12_CATEGORY_RANKING_VERSION = 6;
|
|
|
|
|
const int SM_390A12_SONG_SCORES_VERSION = 9;
|
|
|
|
|
const int SM_390A12_COURSE_SCORES_VERSION = 8;
|
|
|
|
|
|
2004-04-18 05:46:43 +00:00
|
|
|
#define GUID_SIZE_BYTES 8
|
2004-02-10 09:42:01 +00:00
|
|
|
|
2004-05-08 10:12:10 +00:00
|
|
|
#define MAX_RECENT_SCORES_TO_SAVE 100
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-05-28 05:58:35 +00:00
|
|
|
#define MAX_EDITABLE_INI_SIZE_BYTES 2*1024 // 2KB
|
|
|
|
|
#define MAX_PLAYER_STATS_XML_SIZE_BYTES \
|
|
|
|
|
100 /* Songs */ \
|
|
|
|
|
* 3 /* Steps per Song */ \
|
|
|
|
|
* 10 /* HighScores per Steps */ \
|
|
|
|
|
* 1024 /* size in bytes of a HighScores XNode */
|
|
|
|
|
|
2004-02-22 07:07:03 +00:00
|
|
|
#if defined(WIN32)
|
|
|
|
|
#pragma warning (disable : 4706) // assignment within conditional expression
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define FOREACH_Node( Node, Var ) \
|
|
|
|
|
XNodes::const_iterator Var##Iter; \
|
|
|
|
|
const XNode *Var = NULL; \
|
|
|
|
|
for( Var##Iter = Node->childs.begin(); \
|
|
|
|
|
(Var##Iter != Node->childs.end() && (Var = *Var##Iter) ), Var##Iter != Node->childs.end(); \
|
|
|
|
|
++Var##Iter )
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
void Profile::InitEditableData()
|
|
|
|
|
{
|
|
|
|
|
m_sDisplayName = "";
|
2004-02-22 02:41:10 +00:00
|
|
|
m_sLastUsedHighScoreName = "";
|
2004-02-23 04:53:02 +00:00
|
|
|
m_iWeightPounds = 0;
|
2004-02-19 03:56:03 +00:00
|
|
|
}
|
2004-02-10 09:42:01 +00:00
|
|
|
|
|
|
|
|
void Profile::InitGeneralData()
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2004-03-14 17:49:38 +00:00
|
|
|
// Init m_iGuid.
|
|
|
|
|
// Does the RNG need to be inited and seeded every time?
|
|
|
|
|
random_init();
|
|
|
|
|
random_add_noise( "ai8049ujr3odusj" );
|
|
|
|
|
|
|
|
|
|
{
|
2004-04-18 05:46:43 +00:00
|
|
|
m_sGuid = "";
|
|
|
|
|
for( unsigned i=0; i<GUID_SIZE_BYTES; i++ )
|
2004-05-21 09:41:59 +00:00
|
|
|
m_sGuid += ssprintf( "%02x", random_byte() );
|
2004-03-14 17:49:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-02-10 09:42:01 +00:00
|
|
|
m_bUsingProfileDefaultModifiers = false;
|
|
|
|
|
m_sDefaultModifiers = "";
|
2004-03-12 08:31:40 +00:00
|
|
|
m_SortOrder = SORT_INVALID;
|
2004-03-25 09:54:28 +00:00
|
|
|
m_LastDifficulty = DIFFICULTY_INVALID;
|
|
|
|
|
m_LastCourseDifficulty = COURSE_DIFFICULTY_INVALID;
|
|
|
|
|
m_pLastSong = NULL;
|
2004-05-26 05:50:22 +00:00
|
|
|
m_pLastCourse = NULL;
|
2004-02-10 09:42:01 +00:00
|
|
|
m_iTotalPlays = 0;
|
|
|
|
|
m_iTotalPlaySeconds = 0;
|
|
|
|
|
m_iTotalGameplaySeconds = 0;
|
|
|
|
|
m_iCurrentCombo = 0;
|
2004-02-22 20:58:39 +00:00
|
|
|
m_fTotalCaloriesBurned = 0;
|
2004-02-22 08:16:49 +00:00
|
|
|
m_iTotalDancePoints = 0;
|
|
|
|
|
m_iNumExtraStagesPassed = 0;
|
|
|
|
|
m_iNumExtraStagesFailed = 0;
|
|
|
|
|
m_iNumToasties = 0;
|
|
|
|
|
m_UnlockedSongs.clear();
|
2004-04-18 05:46:43 +00:00
|
|
|
m_sLastPlayedMachineGuid = "";
|
2004-02-22 19:54:59 +00:00
|
|
|
m_iTotalTapsAndHolds = 0;
|
|
|
|
|
m_iTotalJumps = 0;
|
|
|
|
|
m_iTotalHolds = 0;
|
|
|
|
|
m_iTotalMines = 0;
|
|
|
|
|
m_iTotalHands = 0;
|
2004-02-10 09:42:01 +00:00
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
for( i=0; i<NUM_PLAY_MODES; i++ )
|
|
|
|
|
m_iNumSongsPlayedByPlayMode[i] = 0;
|
|
|
|
|
for( i=0; i<NUM_STYLES; i++ )
|
|
|
|
|
m_iNumSongsPlayedByStyle[i] = 0;
|
|
|
|
|
for( i=0; i<NUM_DIFFICULTIES; i++ )
|
|
|
|
|
m_iNumSongsPlayedByDifficulty[i] = 0;
|
|
|
|
|
for( i=0; i<MAX_METER+1; i++ )
|
|
|
|
|
m_iNumSongsPlayedByMeter[i] = 0;
|
2004-02-22 08:16:49 +00:00
|
|
|
ZERO( m_iNumSongsPassedByPlayMode );
|
|
|
|
|
ZERO( m_iNumSongsPassedByGrade );
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-10 09:42:01 +00:00
|
|
|
void Profile::InitSongScores()
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2004-04-18 18:42:42 +00:00
|
|
|
m_SongHighScores.clear();
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-10 09:42:01 +00:00
|
|
|
void Profile::InitCourseScores()
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2004-02-10 09:42:01 +00:00
|
|
|
m_CourseHighScores.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Profile::InitCategoryScores()
|
|
|
|
|
{
|
|
|
|
|
for( int st=0; st<NUM_STEPS_TYPES; st++ )
|
|
|
|
|
for( int rc=0; rc<NUM_RANKING_CATEGORIES; rc++ )
|
|
|
|
|
m_CategoryHighScores[st][rc].Init();
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
2004-02-08 18:25:30 +00:00
|
|
|
|
2004-02-17 01:16:57 +00:00
|
|
|
void Profile::InitScreenshotData()
|
|
|
|
|
{
|
|
|
|
|
m_vScreenshots.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-22 23:29:13 +00:00
|
|
|
void Profile::InitCalorieData()
|
|
|
|
|
{
|
|
|
|
|
m_mapDayToCaloriesBurned.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-07 04:34:49 +00:00
|
|
|
void Profile::InitAwards()
|
|
|
|
|
{
|
|
|
|
|
FOREACH_StepsType( st )
|
|
|
|
|
{
|
|
|
|
|
FOREACH_Difficulty( dc )
|
|
|
|
|
FOREACH_PerDifficultyAward( pda )
|
|
|
|
|
m_PerDifficultyAwards[st][dc][pda].Unset();
|
|
|
|
|
}
|
|
|
|
|
FOREACH_PeakComboAward( pca )
|
|
|
|
|
{
|
|
|
|
|
m_PeakComboAwards[pca].Unset();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-08 10:12:10 +00:00
|
|
|
void Profile::InitRecentSongScores()
|
2004-04-22 07:59:42 +00:00
|
|
|
{
|
2004-05-08 10:12:10 +00:00
|
|
|
m_vRecentStepsScores.clear();
|
2004-04-22 22:01:38 +00:00
|
|
|
}
|
|
|
|
|
|
2004-05-08 10:12:10 +00:00
|
|
|
void Profile::InitRecentCourseScores()
|
2004-04-22 22:01:38 +00:00
|
|
|
{
|
2004-05-08 10:12:10 +00:00
|
|
|
m_vRecentCourseScores.clear();
|
2004-04-22 07:59:42 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-16 05:35:06 +00:00
|
|
|
CString Profile::GetDisplayName() const
|
2004-02-08 18:25:30 +00:00
|
|
|
{
|
2004-02-19 03:56:03 +00:00
|
|
|
if( !m_sDisplayName.empty() )
|
|
|
|
|
return m_sDisplayName;
|
2004-02-08 18:25:30 +00:00
|
|
|
else if( !m_sLastUsedHighScoreName.empty() )
|
|
|
|
|
return m_sLastUsedHighScoreName;
|
|
|
|
|
else
|
2004-02-16 05:35:06 +00:00
|
|
|
return "NoName";
|
2004-02-08 18:25:30 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-22 20:58:39 +00:00
|
|
|
CString Profile::GetDisplayTotalCaloriesBurned() const
|
2004-02-08 18:25:30 +00:00
|
|
|
{
|
2004-02-23 04:53:02 +00:00
|
|
|
if( m_iWeightPounds == 0 ) // weight not entered
|
2004-02-08 18:25:30 +00:00
|
|
|
return "N/A";
|
|
|
|
|
else
|
2004-02-23 01:47:59 +00:00
|
|
|
return Commify((int)m_fTotalCaloriesBurned) + " Cal";
|
2004-02-08 18:25:30 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-22 08:16:49 +00:00
|
|
|
int Profile::GetTotalNumSongsPlayed() const
|
2004-02-08 18:25:30 +00:00
|
|
|
{
|
|
|
|
|
int iTotal = 0;
|
|
|
|
|
for( int i=0; i<NUM_PLAY_MODES; i++ )
|
|
|
|
|
iTotal += m_iNumSongsPlayedByPlayMode[i];
|
|
|
|
|
return iTotal;
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-22 08:16:49 +00:00
|
|
|
int Profile::GetTotalNumSongsPassed() const
|
|
|
|
|
{
|
|
|
|
|
int iTotal = 0;
|
|
|
|
|
for( int i=0; i<NUM_PLAY_MODES; i++ )
|
|
|
|
|
iTotal += m_iNumSongsPassedByPlayMode[i];
|
|
|
|
|
return iTotal;
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-08 08:09:18 +00:00
|
|
|
int Profile::GetPossibleSongDancePointsForStepsType( StepsType st ) const
|
2004-05-02 18:49:41 +00:00
|
|
|
{
|
|
|
|
|
int iTotal = 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
|
|
|
|
|
|
|
|
|
|
const RadarValues& fRadars = pSteps->GetRadarValues();
|
|
|
|
|
iTotal += ScoreKeeperMAX2::GetPossibleDancePoints( fRadars );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-08 08:09:18 +00:00
|
|
|
return iTotal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Profile::GetActualSongDancePointsForStepsType( StepsType st ) const
|
2004-03-11 06:31:30 +00:00
|
|
|
{
|
|
|
|
|
int iTotal = 0;
|
2004-03-12 05:24:32 +00:00
|
|
|
|
|
|
|
|
// add steps high scores
|
2004-03-11 06:31:30 +00:00
|
|
|
{
|
2004-04-18 18:42:42 +00:00
|
|
|
for( std::map<SongID,HighScoresForASong>::const_iterator i = m_SongHighScores.begin();
|
|
|
|
|
i != m_SongHighScores.end();
|
2004-05-21 05:40:52 +00:00
|
|
|
++i )
|
2004-03-11 06:31:30 +00:00
|
|
|
{
|
2004-05-21 05:40:52 +00:00
|
|
|
const SongID &id = i->first;
|
2004-04-18 18:42:42 +00:00
|
|
|
Song* pSong = id.ToSong();
|
|
|
|
|
|
|
|
|
|
// If the Song isn't loaded on the current machine, then we can't
|
|
|
|
|
// get radar values to compute dance points.
|
|
|
|
|
if( pSong == NULL )
|
|
|
|
|
continue;
|
|
|
|
|
|
2004-05-11 02:12:54 +00:00
|
|
|
if( pSong->m_SelectionDisplay == Song::SHOW_NEVER )
|
|
|
|
|
continue; // skip
|
|
|
|
|
|
2004-04-18 18:42:42 +00:00
|
|
|
const HighScoresForASong &hsfas = i->second;
|
|
|
|
|
|
|
|
|
|
for( std::map<StepsID,HighScoresForASteps>::const_iterator j = hsfas.m_StepsHighScores.begin();
|
|
|
|
|
j != hsfas.m_StepsHighScores.end();
|
2004-05-21 05:40:52 +00:00
|
|
|
++j )
|
2004-03-12 05:24:32 +00:00
|
|
|
{
|
2004-05-21 05:40:52 +00:00
|
|
|
const StepsID &id = j->first;
|
2004-04-18 18:42:42 +00:00
|
|
|
Steps* pSteps = id.ToSteps( pSong, true );
|
|
|
|
|
|
|
|
|
|
// If the Steps isn't loaded on the current machine, then we can't
|
|
|
|
|
// get radar values to compute dance points.
|
|
|
|
|
if( pSteps == NULL )
|
|
|
|
|
continue;
|
|
|
|
|
|
2004-05-02 18:49:41 +00:00
|
|
|
if( pSteps->m_StepsType != st )
|
|
|
|
|
continue;
|
|
|
|
|
|
2004-04-18 18:42:42 +00:00
|
|
|
const HighScoresForASteps& h = j->second;
|
|
|
|
|
const HighScoreList& hs = h.hs;
|
2004-05-02 18:49:41 +00:00
|
|
|
|
|
|
|
|
const RadarValues& fRadars = pSteps->GetRadarValues();
|
|
|
|
|
int iPossibleDP = ScoreKeeperMAX2::GetPossibleDancePoints( fRadars );
|
|
|
|
|
iTotal += (int)truncf( hs.GetTopScore().fPercentDP * iPossibleDP );
|
2004-03-12 05:24:32 +00:00
|
|
|
}
|
2004-03-11 06:31:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-08 08:09:18 +00:00
|
|
|
return iTotal;
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-08 08:20:16 +00:00
|
|
|
int Profile::GetPossibleCourseDancePointsForStepsType( StepsType st ) const
|
|
|
|
|
{
|
|
|
|
|
int iTotal = 0;
|
|
|
|
|
|
|
|
|
|
// add course high scores
|
|
|
|
|
{
|
|
|
|
|
vector<Course*> vCourses;
|
|
|
|
|
SONGMAN->GetAllCourses( vCourses, false );
|
|
|
|
|
for( unsigned i=0; i<vCourses.size(); i++ )
|
|
|
|
|
{
|
|
|
|
|
const Course* pCourse = vCourses[i];
|
|
|
|
|
|
|
|
|
|
// Don't count any course that has any entries that change over time.
|
|
|
|
|
if( !pCourse->AllSongsAreFixed() )
|
|
|
|
|
continue;
|
|
|
|
|
|
2004-05-20 22:27:45 +00:00
|
|
|
FOREACH_ShownCourseDifficulty( cd )
|
2004-05-08 08:20:16 +00:00
|
|
|
{
|
|
|
|
|
if( !pCourse->HasCourseDifficulty(st,cd) )
|
|
|
|
|
continue;
|
|
|
|
|
|
2004-05-24 06:07:59 +00:00
|
|
|
Trail* pTrail = pCourse->GetTrail(st,cd);
|
|
|
|
|
const RadarValues& fRadars = pTrail->GetRadarValues();
|
2004-05-08 08:20:16 +00:00
|
|
|
iTotal += ScoreKeeperMAX2::GetPossibleDancePoints( fRadars );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return iTotal;
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-08 08:09:18 +00:00
|
|
|
int Profile::GetActualCourseDancePointsForStepsType( StepsType st ) const
|
|
|
|
|
{
|
|
|
|
|
int iTotal = 0;
|
|
|
|
|
|
2004-03-12 05:24:32 +00:00
|
|
|
// add course high scores
|
|
|
|
|
{
|
2004-04-18 19:36:42 +00:00
|
|
|
for( std::map<CourseID,HighScoresForACourse>::const_iterator i = m_CourseHighScores.begin();
|
|
|
|
|
i != m_CourseHighScores.end();
|
|
|
|
|
i++ )
|
2004-03-12 05:24:32 +00:00
|
|
|
{
|
2004-04-18 19:36:42 +00:00
|
|
|
CourseID id = i->first;
|
|
|
|
|
const Course* pCourse = id.ToCourse();
|
|
|
|
|
|
|
|
|
|
// If the Course isn't loaded on the current machine, then we can't
|
|
|
|
|
// get radar values to compute dance points.
|
|
|
|
|
if( pCourse == NULL )
|
|
|
|
|
continue;
|
2004-03-20 19:24:38 +00:00
|
|
|
|
|
|
|
|
// Don't count any course that has any entries that change over time.
|
|
|
|
|
if( !pCourse->AllSongsAreFixed() )
|
|
|
|
|
continue;
|
|
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
const HighScoresForACourse &hsfac = i->second;
|
|
|
|
|
|
|
|
|
|
for( std::map<TrailID,HighScoresForATrail>::const_iterator j = hsfac.m_TrailHighScores.begin();
|
|
|
|
|
j != hsfac.m_TrailHighScores.end();
|
|
|
|
|
++j )
|
2004-03-12 05:24:32 +00:00
|
|
|
{
|
2004-05-23 21:08:03 +00:00
|
|
|
const TrailID &id = j->first;
|
|
|
|
|
Trail* pTrail = id.ToTrail( pCourse, true );
|
|
|
|
|
|
|
|
|
|
// If the Steps isn't loaded on the current machine, then we can't
|
|
|
|
|
// get radar values to compute dance points.
|
|
|
|
|
if( pTrail == NULL )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if( pTrail->m_StepsType != st )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
const HighScoresForATrail& h = j->second;
|
|
|
|
|
const HighScoreList& hs = h.hs;
|
|
|
|
|
|
|
|
|
|
const RadarValues& fRadars = pTrail->GetRadarValues();
|
2004-03-12 05:24:32 +00:00
|
|
|
int iPossibleDP = ScoreKeeperMAX2::GetPossibleDancePoints( fRadars );
|
|
|
|
|
iTotal += (int)truncf( hs.GetTopScore().fPercentDP * iPossibleDP );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-11 06:31:30 +00:00
|
|
|
return iTotal;
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-08 08:09:18 +00:00
|
|
|
float Profile::GetPercentCompleteForStepsType( StepsType st ) const
|
|
|
|
|
{
|
2004-05-20 19:14:51 +00:00
|
|
|
int iPossible =
|
2004-05-08 08:09:18 +00:00
|
|
|
GetPossibleSongDancePointsForStepsType( st ) +
|
|
|
|
|
GetPossibleCourseDancePointsForStepsType( st );
|
2004-05-20 19:14:51 +00:00
|
|
|
int iActual =
|
2004-05-08 08:09:18 +00:00
|
|
|
GetActualSongDancePointsForStepsType( st ) +
|
|
|
|
|
GetActualCourseDancePointsForStepsType( st );
|
|
|
|
|
|
2004-05-20 19:14:51 +00:00
|
|
|
return float(iActual) / iPossible;
|
2004-05-08 08:09:18 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-10 09:42:01 +00:00
|
|
|
CString Profile::GetProfileDisplayNameFromDir( CString sDir )
|
|
|
|
|
{
|
2004-02-22 03:44:04 +00:00
|
|
|
Profile profile;
|
|
|
|
|
profile.LoadEditableDataFromDir( sDir );
|
|
|
|
|
return profile.GetDisplayName();
|
2004-02-10 09:42:01 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-10 10:06:34 +00:00
|
|
|
int Profile::GetSongNumTimesPlayed( const Song* pSong ) const
|
2004-04-18 18:42:42 +00:00
|
|
|
{
|
|
|
|
|
SongID songID;
|
|
|
|
|
songID.FromSong( pSong );
|
|
|
|
|
return GetSongNumTimesPlayed( songID );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Profile::GetSongNumTimesPlayed( const SongID& songID ) const
|
2004-02-10 09:42:01 +00:00
|
|
|
{
|
2004-05-02 00:08:42 +00:00
|
|
|
const HighScoresForASong *hsSong = GetHighScoresForASong( songID );
|
|
|
|
|
if( hsSong == NULL )
|
|
|
|
|
return 0;
|
2004-04-18 18:42:42 +00:00
|
|
|
|
2004-05-02 00:08:42 +00:00
|
|
|
int iTotalNumTimesPlayed = 0;
|
|
|
|
|
for( std::map<StepsID,HighScoresForASteps>::const_iterator j = hsSong->m_StepsHighScores.begin();
|
|
|
|
|
j != hsSong->m_StepsHighScores.end();
|
2004-04-18 18:42:42 +00:00
|
|
|
j++ )
|
2004-02-10 09:42:01 +00:00
|
|
|
{
|
2004-04-18 18:42:42 +00:00
|
|
|
const HighScoresForASteps &hsSteps = j->second;
|
|
|
|
|
|
|
|
|
|
iTotalNumTimesPlayed += hsSteps.hs.iNumTimesPlayed;
|
2004-02-10 09:42:01 +00:00
|
|
|
}
|
|
|
|
|
return iTotalNumTimesPlayed;
|
|
|
|
|
}
|
2004-02-08 18:25:30 +00:00
|
|
|
|
2004-02-09 06:26:13 +00:00
|
|
|
//
|
|
|
|
|
// Steps high scores
|
|
|
|
|
//
|
2004-04-18 18:42:42 +00:00
|
|
|
void Profile::AddStepsHighScore( const Song* pSong, const Steps* pSteps, HighScore hs, int &iIndexOut )
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2004-05-28 04:46:43 +00:00
|
|
|
GetStepsHighScoreList(pSong,pSteps).AddHighScore( hs, iIndexOut, IsMachine() );
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
2004-04-18 18:42:42 +00:00
|
|
|
const HighScoreList& Profile::GetStepsHighScoreList( const Song* pSong, const Steps* pSteps ) const
|
2004-02-10 10:06:34 +00:00
|
|
|
{
|
2004-04-18 18:42:42 +00:00
|
|
|
return ((Profile*)this)->GetStepsHighScoreList(pSong,pSteps);
|
2004-02-10 10:06:34 +00:00
|
|
|
}
|
|
|
|
|
|
2004-04-18 18:42:42 +00:00
|
|
|
HighScoreList& Profile::GetStepsHighScoreList( const Song* pSong, const Steps* pSteps )
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2004-04-18 18:42:42 +00:00
|
|
|
SongID songID;
|
|
|
|
|
songID.FromSong( pSong );
|
|
|
|
|
|
|
|
|
|
StepsID stepsID;
|
|
|
|
|
stepsID.FromSteps( pSteps );
|
2004-04-26 00:06:42 +00:00
|
|
|
|
2004-04-18 18:42:42 +00:00
|
|
|
HighScoresForASong &hsSong = m_SongHighScores[songID]; // operator[] inserts into map
|
|
|
|
|
HighScoresForASteps &hsSteps = hsSong.m_StepsHighScores[stepsID]; // operator[] inserts into map
|
|
|
|
|
|
|
|
|
|
return hsSteps.hs;
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
2004-04-18 18:42:42 +00:00
|
|
|
int Profile::GetStepsNumTimesPlayed( const Song* pSong, const Steps* pSteps ) const
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2004-04-18 18:42:42 +00:00
|
|
|
return GetStepsHighScoreList(pSong,pSteps).iNumTimesPlayed;
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
2004-04-18 18:42:42 +00:00
|
|
|
void Profile::IncrementStepsPlayCount( const Song* pSong, const Steps* pSteps )
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2004-04-18 18:42:42 +00:00
|
|
|
GetStepsHighScoreList(pSong,pSteps).iNumTimesPlayed++;
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
2004-05-02 00:08:42 +00:00
|
|
|
void Profile::GetGrades( const Song* pSong, StepsType st, int iCounts[NUM_GRADES] ) const
|
|
|
|
|
{
|
|
|
|
|
SongID songID;
|
|
|
|
|
songID.FromSong( pSong );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memset( iCounts, 0, sizeof(int)*NUM_GRADES );
|
|
|
|
|
const HighScoresForASong *hsSong = GetHighScoresForASong( songID );
|
|
|
|
|
if( hsSong == NULL )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
FOREACH_Grade(g)
|
|
|
|
|
{
|
|
|
|
|
std::map<StepsID,HighScoresForASteps>::const_iterator it;
|
|
|
|
|
for( it = hsSong->m_StepsHighScores.begin(); it != hsSong->m_StepsHighScores.end(); ++it )
|
|
|
|
|
{
|
|
|
|
|
const StepsID &id = it->first;
|
|
|
|
|
if( !id.MatchesStepsType(st) )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
const HighScoresForASteps &hsSteps = it->second;
|
|
|
|
|
if( hsSteps.hs.GetTopScore().grade == g )
|
|
|
|
|
iCounts[g]++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-02-09 06:26:13 +00:00
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Course high scores
|
|
|
|
|
//
|
2004-05-23 21:08:03 +00:00
|
|
|
void Profile::AddCourseHighScore( const Course* pCourse, const Trail* pTrail, HighScore hs, int &iIndexOut )
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2004-05-28 04:46:43 +00:00
|
|
|
GetCourseHighScoreList(pCourse,pTrail).AddHighScore( hs, iIndexOut, IsMachine() );
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
const HighScoreList& Profile::GetCourseHighScoreList( const Course* pCourse, const Trail* pTrail ) const
|
2004-02-10 10:06:34 +00:00
|
|
|
{
|
2004-05-23 21:08:03 +00:00
|
|
|
return ((Profile *)this)->GetCourseHighScoreList( pCourse, pTrail );
|
2004-02-10 10:06:34 +00:00
|
|
|
}
|
|
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
HighScoreList& Profile::GetCourseHighScoreList( const Course* pCourse, const Trail* pTrail )
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2004-04-18 19:36:42 +00:00
|
|
|
CourseID courseID;
|
|
|
|
|
courseID.FromCourse( pCourse );
|
|
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
TrailID trailID;
|
|
|
|
|
trailID.FromTrail( pTrail );
|
|
|
|
|
|
|
|
|
|
HighScoresForACourse &hsCourse = m_CourseHighScores[courseID]; // operator[] inserts into map
|
|
|
|
|
HighScoresForATrail &hsTrail = hsCourse.m_TrailHighScores[trailID]; // operator[] inserts into map
|
|
|
|
|
|
|
|
|
|
return hsTrail.hs;
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Profile::GetCourseNumTimesPlayed( const Course* pCourse ) const
|
|
|
|
|
{
|
2004-04-18 19:36:42 +00:00
|
|
|
CourseID courseID;
|
|
|
|
|
courseID.FromCourse( pCourse );
|
|
|
|
|
|
|
|
|
|
return GetCourseNumTimesPlayed( courseID );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Profile::GetCourseNumTimesPlayed( const CourseID &courseID ) const
|
|
|
|
|
{
|
2004-05-23 21:08:03 +00:00
|
|
|
const HighScoresForACourse *hsCourse = GetHighScoresForACourse( courseID );
|
|
|
|
|
if( hsCourse == NULL )
|
2004-02-09 06:26:13 +00:00
|
|
|
return 0;
|
2004-05-23 21:08:03 +00:00
|
|
|
|
|
|
|
|
int iTotalNumTimesPlayed = 0;
|
|
|
|
|
for( std::map<TrailID,HighScoresForATrail>::const_iterator j = hsCourse->m_TrailHighScores.begin();
|
|
|
|
|
j != hsCourse->m_TrailHighScores.end();
|
|
|
|
|
j++ )
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2004-05-23 21:08:03 +00:00
|
|
|
const HighScoresForATrail &hsTrail = j->second;
|
|
|
|
|
|
|
|
|
|
iTotalNumTimesPlayed += hsTrail.hs.iNumTimesPlayed;
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
2004-05-23 21:08:03 +00:00
|
|
|
return iTotalNumTimesPlayed;
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
void Profile::IncrementCoursePlayCount( const Course* pCourse, const Trail* pTrail )
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2004-05-23 21:08:03 +00:00
|
|
|
GetCourseHighScoreList(pCourse,pTrail).iNumTimesPlayed++;
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Category high scores
|
|
|
|
|
//
|
|
|
|
|
void Profile::AddCategoryHighScore( StepsType st, RankingCategory rc, HighScore hs, int &iIndexOut )
|
|
|
|
|
{
|
2004-05-28 04:46:43 +00:00
|
|
|
m_CategoryHighScores[st][rc].AddHighScore( hs, iIndexOut, IsMachine() );
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-10 10:06:34 +00:00
|
|
|
const HighScoreList& Profile::GetCategoryHighScoreList( StepsType st, RankingCategory rc ) const
|
|
|
|
|
{
|
|
|
|
|
return ((Profile *)this)->m_CategoryHighScores[st][rc];
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-09 06:26:13 +00:00
|
|
|
HighScoreList& Profile::GetCategoryHighScoreList( StepsType st, RankingCategory rc )
|
|
|
|
|
{
|
|
|
|
|
return m_CategoryHighScores[st][rc];
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-10 09:42:01 +00:00
|
|
|
int Profile::GetCategoryNumTimesPlayed( StepsType st ) const
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
|
|
|
|
int iNumTimesPlayed = 0;
|
2004-02-10 09:42:01 +00:00
|
|
|
FOREACH_RankingCategory( rc )
|
2004-02-09 06:26:13 +00:00
|
|
|
iNumTimesPlayed += m_CategoryHighScores[st][rc].iNumTimesPlayed;
|
|
|
|
|
return iNumTimesPlayed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Profile::IncrementCategoryPlayCount( StepsType st, RankingCategory rc )
|
|
|
|
|
{
|
|
|
|
|
m_CategoryHighScores[st][rc].iNumTimesPlayed++;
|
|
|
|
|
}
|
2004-02-10 09:42:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Loading and saving
|
|
|
|
|
//
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
#define WARN LOG->Warn("Error parsing file at %s:%d",__FILE__,__LINE__);
|
|
|
|
|
#define WARN_AND_RETURN { WARN; return; }
|
|
|
|
|
#define WARN_AND_CONTINUE { WARN; continue; }
|
|
|
|
|
#define WARN_AND_BREAK { WARN; break; }
|
|
|
|
|
#define LOAD_NODE(X) { \
|
|
|
|
|
XNode* X = xml.GetChild(#X); \
|
|
|
|
|
if( X==NULL ) LOG->Warn("Failed to read section " #X); \
|
|
|
|
|
else Load##X##FromNode(X); }
|
|
|
|
|
int g_iOnceCtr;
|
|
|
|
|
#define FOR_ONCE for(g_iOnceCtr=0;g_iOnceCtr<1;g_iOnceCtr++)
|
|
|
|
|
|
|
|
|
|
|
2004-04-20 00:07:17 +00:00
|
|
|
bool Profile::LoadAllFromDir( CString sDir, bool bRequireSignature )
|
2004-02-15 04:47:32 +00:00
|
|
|
{
|
2004-02-19 03:56:03 +00:00
|
|
|
CHECKPOINT;
|
|
|
|
|
|
2004-02-15 04:47:32 +00:00
|
|
|
InitAll();
|
2004-02-19 03:56:03 +00:00
|
|
|
|
2004-02-22 02:41:10 +00:00
|
|
|
LoadEditableDataFromDir( sDir );
|
|
|
|
|
|
|
|
|
|
// Read stats.xml
|
2004-02-19 03:56:03 +00:00
|
|
|
FOR_ONCE
|
|
|
|
|
{
|
2004-02-22 02:41:10 +00:00
|
|
|
CString fn = sDir + STATS_XML;
|
2004-02-20 02:32:16 +00:00
|
|
|
if( !IsAFile(fn) )
|
|
|
|
|
break;
|
2004-02-19 03:56:03 +00:00
|
|
|
|
2004-02-22 02:41:10 +00:00
|
|
|
LOG->Trace( "Reading profile data '%s'", fn.c_str() );
|
2004-02-19 03:56:03 +00:00
|
|
|
|
|
|
|
|
//
|
2004-02-22 02:41:10 +00:00
|
|
|
// Don't unreasonably large stats.xml files.
|
2004-02-19 03:56:03 +00:00
|
|
|
//
|
2004-05-28 04:46:43 +00:00
|
|
|
if( !IsMachine() ) // only check stats coming from the player
|
2004-02-19 03:56:03 +00:00
|
|
|
{
|
2004-05-28 04:46:43 +00:00
|
|
|
int iBytes = FILEMAN->GetFileSizeInBytes( fn );
|
|
|
|
|
if( iBytes > MAX_PLAYER_STATS_XML_SIZE_BYTES )
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( "The file '%s' is unreasonably large. It won't be loaded.", fn.c_str() );
|
|
|
|
|
break;
|
|
|
|
|
}
|
2004-02-19 03:56:03 +00:00
|
|
|
}
|
|
|
|
|
|
2004-04-20 00:07:17 +00:00
|
|
|
if( bRequireSignature )
|
2004-02-19 03:56:03 +00:00
|
|
|
{
|
2004-02-22 02:41:10 +00:00
|
|
|
CString sStatsXmlSigFile = fn+SIGNATURE_APPEND;
|
|
|
|
|
CString sDontShareFile = sDir + DONT_SHARE_SIG;
|
2004-02-19 03:56:03 +00:00
|
|
|
|
2004-02-22 02:41:10 +00:00
|
|
|
// verify the stats.xml signature with the "don't share" file
|
|
|
|
|
if( !CryptManager::VerifyFileWithFile(sStatsXmlSigFile, sDontShareFile) )
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( "The don't share check for '%s' failed. Data will be ignored.", sStatsXmlSigFile.c_str() );
|
|
|
|
|
break;
|
|
|
|
|
}
|
2004-02-19 03:56:03 +00:00
|
|
|
|
2004-02-22 02:41:10 +00:00
|
|
|
// verify stats.xml
|
|
|
|
|
if( !CryptManager::VerifyFileWithFile(fn, sStatsXmlSigFile) )
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( "The signature check for '%s' failed. Data will be ignored.", fn.c_str() );
|
|
|
|
|
break;
|
|
|
|
|
}
|
2004-02-19 03:56:03 +00:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
XNode xml;
|
|
|
|
|
if( !xml.LoadFromFile( fn ) )
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( "Couldn't open file '%s' for reading.", fn.c_str() );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( xml.name != "Stats" )
|
|
|
|
|
WARN_AND_BREAK;
|
|
|
|
|
|
|
|
|
|
LOAD_NODE( GeneralData );
|
|
|
|
|
LOAD_NODE( SongScores );
|
|
|
|
|
LOAD_NODE( CourseScores );
|
|
|
|
|
LOAD_NODE( CategoryScores );
|
|
|
|
|
LOAD_NODE( ScreenshotData );
|
2004-02-22 23:29:13 +00:00
|
|
|
LOAD_NODE( CalorieData );
|
2004-03-07 04:34:49 +00:00
|
|
|
LOAD_NODE( Awards );
|
2004-05-08 10:12:10 +00:00
|
|
|
LOAD_NODE( RecentSongScores );
|
|
|
|
|
LOAD_NODE( RecentCourseScores );
|
2004-02-19 03:56:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true; // FIXME? Investigate what happens if we always return true.
|
2004-02-15 04:47:32 +00:00
|
|
|
}
|
|
|
|
|
|
2004-04-20 00:07:17 +00:00
|
|
|
bool Profile::SaveAllToDir( CString sDir, bool bSignData ) const
|
2004-02-15 04:47:32 +00:00
|
|
|
{
|
2004-04-18 05:46:43 +00:00
|
|
|
m_sLastPlayedMachineGuid = PROFILEMAN->GetMachineProfile()->m_sGuid;
|
2004-02-16 05:35:06 +00:00
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
// Save editable.xml
|
2004-02-22 02:41:10 +00:00
|
|
|
SaveEditableDataToDir( sDir );
|
2004-02-19 03:56:03 +00:00
|
|
|
|
|
|
|
|
// Save stats.xml
|
|
|
|
|
{
|
|
|
|
|
CString fn = sDir + STATS_XML;
|
|
|
|
|
|
|
|
|
|
XNode xml;
|
|
|
|
|
xml.name = "Stats";
|
|
|
|
|
xml.AppendChild( SaveGeneralDataCreateNode() );
|
|
|
|
|
xml.AppendChild( SaveSongScoresCreateNode() );
|
|
|
|
|
xml.AppendChild( SaveCourseScoresCreateNode() );
|
|
|
|
|
xml.AppendChild( SaveCategoryScoresCreateNode() );
|
|
|
|
|
xml.AppendChild( SaveScreenshotDataCreateNode() );
|
2004-02-22 23:29:13 +00:00
|
|
|
xml.AppendChild( SaveCalorieDataCreateNode() );
|
2004-03-07 04:34:49 +00:00
|
|
|
xml.AppendChild( SaveAwardsCreateNode() );
|
2004-05-08 10:12:10 +00:00
|
|
|
xml.AppendChild( SaveRecentSongScoresCreateNode() );
|
|
|
|
|
xml.AppendChild( SaveRecentCourseScoresCreateNode() );
|
2004-02-22 02:41:10 +00:00
|
|
|
bool bSaved = xml.SaveToFile(fn);
|
2004-04-22 08:03:02 +00:00
|
|
|
|
|
|
|
|
// Update file cache, or else IsAFile in CryptManager won't see this new file.
|
|
|
|
|
FILEMAN->FlushDirCache( sDir );
|
|
|
|
|
|
2004-04-20 00:07:17 +00:00
|
|
|
if( bSaved && bSignData )
|
2004-02-22 02:41:10 +00:00
|
|
|
{
|
|
|
|
|
CString sStatsXmlSigFile = fn+SIGNATURE_APPEND;
|
|
|
|
|
CryptManager::SignFileToFile(fn, sStatsXmlSigFile);
|
|
|
|
|
|
|
|
|
|
// Save the "don't share" file
|
|
|
|
|
CString sDontShareFile = sDir + DONT_SHARE_SIG;
|
|
|
|
|
CryptManager::SignFileToFile(sStatsXmlSigFile, sDontShareFile);
|
|
|
|
|
}
|
2004-02-19 03:56:03 +00:00
|
|
|
}
|
|
|
|
|
|
2004-05-28 04:46:43 +00:00
|
|
|
if( (IsMachine() && PREFSMAN->m_bWriteMachineStatsHtml) ||
|
|
|
|
|
(!IsMachine() && PREFSMAN->m_bWritePlayerStatsHtml) )
|
2004-05-21 01:52:45 +00:00
|
|
|
SaveStatsWebPageToDir( sDir );
|
2004-02-19 03:56:03 +00:00
|
|
|
|
2004-04-23 00:26:51 +00:00
|
|
|
//
|
2004-04-22 23:10:56 +00:00
|
|
|
// create edits dir
|
2004-04-23 00:26:51 +00:00
|
|
|
//
|
2004-04-22 23:10:56 +00:00
|
|
|
CString sEditsTempFile = sDir + EDITS_SUBDIR + "temp";
|
|
|
|
|
RageFile f;
|
|
|
|
|
f.Open( sDir + EDITS_SUBDIR + "temp", RageFile::WRITE );
|
|
|
|
|
f.Close();
|
|
|
|
|
|
2004-04-23 00:26:51 +00:00
|
|
|
FILEMAN->FlushDirCache( sDir + EDITS_SUBDIR );
|
|
|
|
|
|
2004-04-22 23:10:56 +00:00
|
|
|
FILEMAN->Remove( sEditsTempFile );
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
return true;
|
2004-02-15 04:47:32 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-22 02:41:10 +00:00
|
|
|
void Profile::SaveEditableDataToDir( CString sDir ) const
|
2004-02-10 09:42:01 +00:00
|
|
|
{
|
2004-02-22 02:41:10 +00:00
|
|
|
IniFile ini;
|
2004-02-10 09:42:01 +00:00
|
|
|
|
2004-02-22 02:41:10 +00:00
|
|
|
ini.SetValue( "Editable", "DisplayName", m_sDisplayName );
|
|
|
|
|
ini.SetValue( "Editable", "LastUsedHighScoreName", m_sLastUsedHighScoreName );
|
2004-02-23 04:53:02 +00:00
|
|
|
ini.SetValue( "Editable", "WeightPounds", m_iWeightPounds );
|
2004-02-22 02:41:10 +00:00
|
|
|
|
2004-05-23 02:27:51 +00:00
|
|
|
ini.WriteFile( sDir + EDITABLE_INI );
|
2004-02-19 03:56:03 +00:00
|
|
|
}
|
2004-02-10 09:42:01 +00:00
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
XNode* Profile::SaveGeneralDataCreateNode() const
|
|
|
|
|
{
|
|
|
|
|
XNode* pGeneralDataNode = new XNode;
|
|
|
|
|
pGeneralDataNode->name = "GeneralData";
|
2004-05-20 03:51:07 +00:00
|
|
|
|
2004-05-28 05:58:35 +00:00
|
|
|
// TRICKY: These are write-only elements that are never read again. This
|
|
|
|
|
// data is required by other apps (like internet ranking), but is
|
|
|
|
|
// redundant to the game app.
|
2004-05-20 03:51:07 +00:00
|
|
|
pGeneralDataNode->AppendChild( "DisplayName", GetDisplayName() );
|
2004-05-28 05:58:35 +00:00
|
|
|
pGeneralDataNode->AppendChild( "IsMachine", IsMachine() );
|
2004-05-20 03:51:07 +00:00
|
|
|
|
2004-04-18 05:46:43 +00:00
|
|
|
pGeneralDataNode->AppendChild( "Guid", m_sGuid );
|
2004-02-19 03:56:03 +00:00
|
|
|
pGeneralDataNode->AppendChild( "UsingProfileDefaultModifiers", m_bUsingProfileDefaultModifiers );
|
|
|
|
|
pGeneralDataNode->AppendChild( "DefaultModifiers", m_sDefaultModifiers );
|
2004-03-13 19:20:24 +00:00
|
|
|
pGeneralDataNode->AppendChild( "SortOrder", SortOrderToString(m_SortOrder) );
|
2004-03-25 09:54:28 +00:00
|
|
|
pGeneralDataNode->AppendChild( "LastDifficulty", DifficultyToString(m_LastDifficulty) );
|
|
|
|
|
pGeneralDataNode->AppendChild( "LastCourseDifficulty", CourseDifficultyToString(m_LastCourseDifficulty) );
|
|
|
|
|
if( m_pLastSong ) pGeneralDataNode->AppendChild( "LastSong", m_pLastSong->GetSongDir() );
|
2004-05-26 05:50:22 +00:00
|
|
|
if( m_pLastCourse ) pGeneralDataNode->AppendChild( "LastCourse",m_pLastCourse->m_sPath );
|
2004-02-19 03:56:03 +00:00
|
|
|
pGeneralDataNode->AppendChild( "TotalPlays", m_iTotalPlays );
|
|
|
|
|
pGeneralDataNode->AppendChild( "TotalPlaySeconds", m_iTotalPlaySeconds );
|
|
|
|
|
pGeneralDataNode->AppendChild( "TotalGameplaySeconds", m_iTotalGameplaySeconds );
|
|
|
|
|
pGeneralDataNode->AppendChild( "CurrentCombo", m_iCurrentCombo );
|
2004-02-22 20:58:39 +00:00
|
|
|
pGeneralDataNode->AppendChild( "TotalCaloriesBurned", m_fTotalCaloriesBurned );
|
2004-04-18 05:46:43 +00:00
|
|
|
pGeneralDataNode->AppendChild( "LastPlayedMachineGuid", m_sLastPlayedMachineGuid );
|
2004-02-22 08:16:49 +00:00
|
|
|
pGeneralDataNode->AppendChild( "TotalDancePoints", m_iTotalDancePoints );
|
|
|
|
|
pGeneralDataNode->AppendChild( "NumExtraStagesPassed", m_iNumExtraStagesPassed );
|
|
|
|
|
pGeneralDataNode->AppendChild( "NumExtraStagesFailed", m_iNumExtraStagesFailed );
|
|
|
|
|
pGeneralDataNode->AppendChild( "NumToasties", m_iNumToasties );
|
2004-02-22 19:54:59 +00:00
|
|
|
pGeneralDataNode->AppendChild( "TotalTapsAndHolds", m_iTotalTapsAndHolds );
|
2004-02-22 20:58:39 +00:00
|
|
|
pGeneralDataNode->AppendChild( "TotalJumps", m_iTotalJumps );
|
|
|
|
|
pGeneralDataNode->AppendChild( "TotalHolds", m_iTotalHolds );
|
|
|
|
|
pGeneralDataNode->AppendChild( "TotalMines", m_iTotalMines );
|
|
|
|
|
pGeneralDataNode->AppendChild( "TotalHands", m_iTotalHands );
|
2004-02-22 08:16:49 +00:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
XNode* pUnlockedSongs = pGeneralDataNode->AppendChild("UnlockedSongs");
|
|
|
|
|
for( set<int>::const_iterator it = m_UnlockedSongs.begin(); it != m_UnlockedSongs.end(); ++it )
|
2004-03-13 10:48:15 +00:00
|
|
|
pUnlockedSongs->AppendChild( ssprintf("Unlock%i", *it) );
|
2004-02-22 08:16:49 +00:00
|
|
|
}
|
2004-02-19 03:56:03 +00:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
XNode* pNumSongsPlayedByPlayMode = pGeneralDataNode->AppendChild("NumSongsPlayedByPlayMode");
|
|
|
|
|
FOREACH_PlayMode( pm )
|
2004-02-22 02:51:27 +00:00
|
|
|
{
|
|
|
|
|
/* Don't save unplayed PlayModes. */
|
|
|
|
|
if( !m_iNumSongsPlayedByPlayMode[pm] )
|
|
|
|
|
continue;
|
2004-02-19 03:56:03 +00:00
|
|
|
pNumSongsPlayedByPlayMode->AppendChild( PlayModeToString(pm), m_iNumSongsPlayedByPlayMode[pm] );
|
2004-02-22 02:51:27 +00:00
|
|
|
}
|
2004-02-19 03:56:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
XNode* pNumSongsPlayedByStyle = pGeneralDataNode->AppendChild("NumSongsPlayedByStyle");
|
|
|
|
|
for( int i=0; i<NUM_STYLES; i++ )
|
|
|
|
|
{
|
2004-02-22 02:51:27 +00:00
|
|
|
/* Don't save unplayed styles. */
|
|
|
|
|
if( !m_iNumSongsPlayedByStyle[i] )
|
|
|
|
|
continue;
|
2004-02-22 04:37:58 +00:00
|
|
|
|
|
|
|
|
XNode *pStyleNode = pNumSongsPlayedByStyle->AppendChild( "Style", m_iNumSongsPlayedByStyle[i] );
|
|
|
|
|
|
|
|
|
|
const StyleDef *pStyle = GAMEMAN->GetStyleDefForStyle((Style)i);
|
|
|
|
|
const GameDef *g = GAMEMAN->GetGameDefForGame( pStyle->m_Game );
|
|
|
|
|
ASSERT( g );
|
|
|
|
|
pStyleNode->AppendAttr( "Game", g->m_szName );
|
|
|
|
|
pStyleNode->AppendAttr( "Style", pStyle->m_szName );
|
2004-02-19 03:56:03 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
XNode* pNumSongsPlayedByDifficulty = pGeneralDataNode->AppendChild("NumSongsPlayedByDifficulty");
|
|
|
|
|
FOREACH_Difficulty( dc )
|
2004-02-22 04:20:20 +00:00
|
|
|
{
|
|
|
|
|
if( !m_iNumSongsPlayedByDifficulty[dc] )
|
|
|
|
|
continue;
|
2004-02-19 03:56:03 +00:00
|
|
|
pNumSongsPlayedByDifficulty->AppendChild( DifficultyToString(dc), m_iNumSongsPlayedByDifficulty[dc] );
|
2004-02-22 04:20:20 +00:00
|
|
|
}
|
2004-02-19 03:56:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
XNode* pNumSongsPlayedByMeter = pGeneralDataNode->AppendChild("NumSongsPlayedByMeter");
|
|
|
|
|
for( int i=0; i<MAX_METER+1; i++ )
|
2004-02-22 04:20:20 +00:00
|
|
|
{
|
|
|
|
|
if( !m_iNumSongsPlayedByMeter[i] )
|
|
|
|
|
continue;
|
2004-02-19 03:56:03 +00:00
|
|
|
pNumSongsPlayedByMeter->AppendChild( ssprintf("Meter%d",i), m_iNumSongsPlayedByMeter[i] );
|
2004-02-22 04:20:20 +00:00
|
|
|
}
|
2004-02-19 03:56:03 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-22 08:16:49 +00:00
|
|
|
{
|
|
|
|
|
XNode* pNumSongsPassedByGrade = pGeneralDataNode->AppendChild("NumSongsPassedByGrade");
|
|
|
|
|
FOREACH_Grade( g )
|
|
|
|
|
{
|
|
|
|
|
if( !m_iNumSongsPassedByGrade[g] )
|
|
|
|
|
continue;
|
|
|
|
|
pNumSongsPassedByGrade->AppendChild( GradeToString(g), m_iNumSongsPassedByGrade[g] );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
XNode* pNumSongsPassedByPlayMode = pGeneralDataNode->AppendChild("NumSongsPassedByPlayMode");
|
|
|
|
|
FOREACH_PlayMode( pm )
|
|
|
|
|
{
|
|
|
|
|
/* Don't save unplayed PlayModes. */
|
|
|
|
|
if( !m_iNumSongsPassedByPlayMode[pm] )
|
|
|
|
|
continue;
|
|
|
|
|
pNumSongsPassedByPlayMode->AppendChild( PlayModeToString(pm), m_iNumSongsPassedByPlayMode[pm] );
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-02-22 20:44:33 +00:00
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
return pGeneralDataNode;
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-22 02:41:10 +00:00
|
|
|
void Profile::LoadEditableDataFromDir( CString sDir )
|
2004-02-19 03:56:03 +00:00
|
|
|
{
|
2004-02-22 02:41:10 +00:00
|
|
|
CString fn = sDir + EDITABLE_INI;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Don't load unreasonably large editable.xml files.
|
|
|
|
|
//
|
|
|
|
|
int iBytes = FILEMAN->GetFileSizeInBytes( fn );
|
2004-04-23 00:26:51 +00:00
|
|
|
if( iBytes > MAX_EDITABLE_INI_SIZE_BYTES )
|
2004-02-22 02:41:10 +00:00
|
|
|
{
|
|
|
|
|
LOG->Warn( "The file '%s' is unreasonably large. It won't be loaded.", fn.c_str() );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
|
2004-02-22 02:41:10 +00:00
|
|
|
IniFile ini;
|
2004-05-23 02:27:51 +00:00
|
|
|
ini.ReadFile( fn );
|
2004-02-22 02:41:10 +00:00
|
|
|
|
|
|
|
|
ini.GetValue("Editable","DisplayName", m_sDisplayName);
|
|
|
|
|
ini.GetValue("Editable","LastUsedHighScoreName", m_sLastUsedHighScoreName);
|
2004-02-23 04:53:02 +00:00
|
|
|
ini.GetValue("Editable","WeightPounds", m_iWeightPounds);
|
2004-02-19 03:56:03 +00:00
|
|
|
|
|
|
|
|
// This is data that the user can change, so we have to validate it.
|
2004-02-22 02:49:13 +00:00
|
|
|
wstring wstr = CStringToWstring(m_sDisplayName);
|
|
|
|
|
if( wstr.size() > 12 )
|
|
|
|
|
wstr = wstr.substr(0, 12);
|
|
|
|
|
m_sDisplayName = WStringToCString(wstr);
|
2004-02-19 03:56:03 +00:00
|
|
|
// TODO: strip invalid chars?
|
2004-02-23 04:53:02 +00:00
|
|
|
if( m_iWeightPounds != 0 )
|
|
|
|
|
CLAMP( m_iWeightPounds, 50, 500 );
|
2004-02-10 09:42:01 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
void Profile::LoadGeneralDataFromNode( const XNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
ASSERT( pNode->name == "GeneralData" );
|
|
|
|
|
|
2004-03-13 22:18:09 +00:00
|
|
|
CString s;
|
|
|
|
|
|
2004-04-18 05:46:43 +00:00
|
|
|
pNode->GetChildValue( "Guid", m_sGuid );
|
2004-02-19 03:56:03 +00:00
|
|
|
pNode->GetChildValue( "UsingProfileDefaultModifiers", m_bUsingProfileDefaultModifiers );
|
|
|
|
|
pNode->GetChildValue( "DefaultModifiers", m_sDefaultModifiers );
|
2004-03-13 22:18:09 +00:00
|
|
|
pNode->GetChildValue( "SortOrder", s ); m_SortOrder = StringToSortOrder( s );
|
2004-03-25 09:54:28 +00:00
|
|
|
pNode->GetChildValue( "LastDifficulty", s ); m_LastDifficulty = StringToDifficulty( s );
|
|
|
|
|
pNode->GetChildValue( "LastCourseDifficulty", s ); m_LastCourseDifficulty = StringToCourseDifficulty( s );
|
|
|
|
|
pNode->GetChildValue( "LastSong", s ); m_pLastSong = SONGMAN->GetSongFromDir(s);
|
2004-05-26 05:50:22 +00:00
|
|
|
pNode->GetChildValue( "LastCourse", s ); m_pLastCourse = SONGMAN->GetCourseFromPath(s);
|
2004-02-19 03:56:03 +00:00
|
|
|
pNode->GetChildValue( "TotalPlays", m_iTotalPlays );
|
|
|
|
|
pNode->GetChildValue( "TotalPlaySeconds", m_iTotalPlaySeconds );
|
|
|
|
|
pNode->GetChildValue( "TotalGameplaySeconds", m_iTotalGameplaySeconds );
|
|
|
|
|
pNode->GetChildValue( "CurrentCombo", m_iCurrentCombo );
|
2004-02-22 20:58:39 +00:00
|
|
|
pNode->GetChildValue( "TotalCaloriesBurned", m_fTotalCaloriesBurned );
|
2004-04-18 05:46:43 +00:00
|
|
|
pNode->GetChildValue( "LastPlayedMachineGuid", m_sLastPlayedMachineGuid );
|
2004-02-22 08:16:49 +00:00
|
|
|
pNode->GetChildValue( "TotalDancePoints", m_iTotalDancePoints );
|
|
|
|
|
pNode->GetChildValue( "NumExtraStagesPassed", m_iNumExtraStagesPassed );
|
|
|
|
|
pNode->GetChildValue( "NumExtraStagesFailed", m_iNumExtraStagesFailed );
|
|
|
|
|
pNode->GetChildValue( "NumToasties", m_iNumToasties );
|
2004-02-22 19:54:59 +00:00
|
|
|
pNode->GetChildValue( "TotalTapsAndHolds", m_iTotalTapsAndHolds );
|
|
|
|
|
pNode->GetChildValue( "TotalJumps", m_iTotalJumps );
|
|
|
|
|
pNode->GetChildValue( "TotalHolds", m_iTotalHolds );
|
|
|
|
|
pNode->GetChildValue( "TotalMines", m_iTotalMines );
|
|
|
|
|
pNode->GetChildValue( "TotalHands", m_iTotalHands );
|
2004-02-22 08:16:49 +00:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
XNode* pUnlockedSongs = pNode->GetChild("UnlockedSongs");
|
|
|
|
|
if( pUnlockedSongs )
|
|
|
|
|
{
|
|
|
|
|
FOREACH_Node( pUnlockedSongs, song )
|
2004-03-13 10:48:15 +00:00
|
|
|
{
|
|
|
|
|
int iUnlock;
|
|
|
|
|
if( sscanf(song->name.c_str(),"Unlock%d",&iUnlock) == 1 )
|
|
|
|
|
m_UnlockedSongs.insert( iUnlock );
|
|
|
|
|
}
|
2004-02-22 08:16:49 +00:00
|
|
|
}
|
|
|
|
|
}
|
2004-02-19 03:56:03 +00:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
XNode* pNumSongsPlayedByPlayMode = pNode->GetChild("NumSongsPlayedByPlayMode");
|
|
|
|
|
if( pNumSongsPlayedByPlayMode )
|
|
|
|
|
FOREACH_PlayMode( pm )
|
|
|
|
|
pNumSongsPlayedByPlayMode->GetChildValue( PlayModeToString(pm), m_iNumSongsPlayedByPlayMode[pm] );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
XNode* pNumSongsPlayedByStyle = pNode->GetChild("NumSongsPlayedByStyle");
|
|
|
|
|
if( pNumSongsPlayedByStyle )
|
2004-02-22 07:07:03 +00:00
|
|
|
{
|
|
|
|
|
FOREACH_Node( pNumSongsPlayedByStyle, style )
|
2004-02-19 03:56:03 +00:00
|
|
|
{
|
2004-02-22 07:07:03 +00:00
|
|
|
if( style->name != "Style" )
|
2004-02-22 04:37:58 +00:00
|
|
|
continue;
|
|
|
|
|
|
2004-02-22 05:26:02 +00:00
|
|
|
CString sGame;
|
2004-02-22 07:07:03 +00:00
|
|
|
if( !style->GetAttrValue( "Game", sGame ) )
|
2004-02-22 04:37:58 +00:00
|
|
|
WARN_AND_CONTINUE;
|
2004-02-22 05:26:02 +00:00
|
|
|
Game g = GAMEMAN->StringToGameType( sGame );
|
2004-02-22 04:37:58 +00:00
|
|
|
if( g == GAME_INVALID )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
2004-02-22 05:26:02 +00:00
|
|
|
CString sStyle;
|
2004-02-22 07:07:03 +00:00
|
|
|
if( !style->GetAttrValue( "Style", sStyle ) )
|
2004-02-22 04:37:58 +00:00
|
|
|
WARN_AND_CONTINUE;
|
2004-02-22 05:26:02 +00:00
|
|
|
Style s = GAMEMAN->GameAndStringToStyle( g, sStyle );
|
2004-02-22 10:10:00 +00:00
|
|
|
if( s == STYLE_INVALID )
|
|
|
|
|
WARN_AND_CONTINUE;
|
2004-02-22 04:37:58 +00:00
|
|
|
|
2004-02-22 07:07:03 +00:00
|
|
|
style->GetValue( m_iNumSongsPlayedByStyle[s] );
|
2004-02-19 03:56:03 +00:00
|
|
|
}
|
2004-02-22 07:07:03 +00:00
|
|
|
}
|
2004-02-19 03:56:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
XNode* pNumSongsPlayedByDifficulty = pNode->GetChild("NumSongsPlayedByDifficulty");
|
|
|
|
|
if( pNumSongsPlayedByDifficulty )
|
|
|
|
|
FOREACH_Difficulty( dc )
|
|
|
|
|
pNumSongsPlayedByDifficulty->GetChildValue( DifficultyToString(dc), m_iNumSongsPlayedByDifficulty[dc] );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
XNode* pNumSongsPlayedByMeter = pNode->GetChild("NumSongsPlayedByMeter");
|
|
|
|
|
if( pNumSongsPlayedByMeter )
|
|
|
|
|
for( int i=0; i<MAX_METER+1; i++ )
|
|
|
|
|
pNumSongsPlayedByMeter->GetChildValue( ssprintf("Meter%d",i), m_iNumSongsPlayedByMeter[i] );
|
|
|
|
|
}
|
2004-02-22 08:16:49 +00:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
XNode* pNumSongsPassedByGrade = pNode->GetChild("NumSongsPassedByGrade");
|
|
|
|
|
if( pNumSongsPassedByGrade )
|
|
|
|
|
FOREACH_Grade( g )
|
|
|
|
|
pNumSongsPassedByGrade->GetChildValue( GradeToString(g), m_iNumSongsPassedByGrade[g] );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
XNode* pNumSongsPassedByPlayMode = pNode->GetChild("NumSongsPassedByPlayMode");
|
|
|
|
|
if( pNumSongsPassedByPlayMode )
|
|
|
|
|
FOREACH_PlayMode( pm )
|
|
|
|
|
pNumSongsPassedByPlayMode->GetChildValue( PlayModeToString(pm), m_iNumSongsPassedByPlayMode[pm] );
|
|
|
|
|
|
|
|
|
|
}
|
2004-02-22 20:44:33 +00:00
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-22 19:54:59 +00:00
|
|
|
void Profile::AddStepTotals( int iTotalTapsAndHolds, int iTotalJumps, int iTotalHolds, int iTotalMines, int iTotalHands )
|
2004-02-22 19:51:46 +00:00
|
|
|
{
|
2004-02-22 19:54:59 +00:00
|
|
|
m_iTotalTapsAndHolds += iTotalTapsAndHolds;
|
|
|
|
|
m_iTotalJumps += iTotalJumps;
|
|
|
|
|
m_iTotalHolds += iTotalHolds;
|
|
|
|
|
m_iTotalMines += iTotalMines;
|
|
|
|
|
m_iTotalHands += iTotalHands;
|
2004-02-22 19:51:46 +00:00
|
|
|
|
2004-02-23 04:53:02 +00:00
|
|
|
if( m_iWeightPounds != 0 )
|
2004-02-22 19:51:46 +00:00
|
|
|
{
|
|
|
|
|
float fCals =
|
2004-02-23 04:53:02 +00:00
|
|
|
SCALE( m_iWeightPounds, 100.f, 200.f, 0.029f, 0.052f ) * iTotalTapsAndHolds +
|
|
|
|
|
SCALE( m_iWeightPounds, 100.f, 200.f, 0.111f, 0.193f ) * iTotalJumps +
|
|
|
|
|
SCALE( m_iWeightPounds, 100.f, 200.f, 0.029f, 0.052f ) * iTotalHolds +
|
|
|
|
|
SCALE( m_iWeightPounds, 100.f, 200.f, 0.000f, 0.000f ) * iTotalMines +
|
|
|
|
|
SCALE( m_iWeightPounds, 100.f, 200.f, 0.222f, 0.386f ) * iTotalHands;
|
2004-02-22 20:58:39 +00:00
|
|
|
m_fTotalCaloriesBurned += fCals;
|
2004-02-22 23:29:13 +00:00
|
|
|
|
2004-02-23 01:44:04 +00:00
|
|
|
tm cur_tm = GetLocalTime();
|
|
|
|
|
Day day = { cur_tm.tm_yday, cur_tm.tm_year+1900 };
|
2004-02-22 23:29:13 +00:00
|
|
|
m_mapDayToCaloriesBurned[day] += fCals;
|
2004-02-22 19:51:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
2004-02-19 03:56:03 +00:00
|
|
|
|
|
|
|
|
XNode* Profile::SaveSongScoresCreateNode() const
|
2004-02-10 09:42:01 +00:00
|
|
|
{
|
|
|
|
|
CHECKPOINT;
|
|
|
|
|
|
2004-02-10 10:06:34 +00:00
|
|
|
const Profile* pProfile = this;
|
2004-02-10 09:42:01 +00:00
|
|
|
ASSERT( pProfile );
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
XNode* pNode = new XNode;
|
|
|
|
|
pNode->name = "SongScores";
|
2004-02-10 09:42:01 +00:00
|
|
|
|
2004-04-18 18:42:42 +00:00
|
|
|
for( std::map<SongID,HighScoresForASong>::const_iterator i = m_SongHighScores.begin();
|
|
|
|
|
i != m_SongHighScores.end();
|
|
|
|
|
i++ )
|
|
|
|
|
{
|
|
|
|
|
const SongID &songID = i->first;
|
|
|
|
|
const HighScoresForASong &hsSong = i->second;
|
2004-02-10 09:42:01 +00:00
|
|
|
|
|
|
|
|
// skip songs that have never been played
|
2004-04-18 18:42:42 +00:00
|
|
|
if( pProfile->GetSongNumTimesPlayed(songID) == 0 )
|
2004-02-10 09:42:01 +00:00
|
|
|
continue;
|
|
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
XNode* pSongNode = pNode->AppendChild( songID.CreateNode() );
|
2004-02-10 09:42:01 +00:00
|
|
|
|
2004-04-18 18:42:42 +00:00
|
|
|
for( std::map<StepsID,HighScoresForASteps>::const_iterator j = hsSong.m_StepsHighScores.begin();
|
|
|
|
|
j != hsSong.m_StepsHighScores.end();
|
|
|
|
|
j++ )
|
|
|
|
|
{
|
|
|
|
|
const StepsID &stepsID = j->first;
|
|
|
|
|
const HighScoresForASteps &hsSteps = j->second;
|
|
|
|
|
|
|
|
|
|
const HighScoreList &hsl = hsSteps.hs;
|
2004-02-10 09:42:01 +00:00
|
|
|
|
|
|
|
|
// skip steps that have never been played
|
2004-04-18 18:42:42 +00:00
|
|
|
if( hsl.iNumTimesPlayed == 0 )
|
2004-02-10 09:42:01 +00:00
|
|
|
continue;
|
|
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
XNode* pStepsNode = pSongNode->AppendChild( stepsID.CreateNode() );
|
2004-02-10 09:42:01 +00:00
|
|
|
|
|
|
|
|
pStepsNode->AppendChild( hsl.CreateNode() );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
return pNode;
|
2004-02-10 09:42:01 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
void Profile::LoadSongScoresFromNode( const XNode* pNode )
|
2004-02-10 09:42:01 +00:00
|
|
|
{
|
2004-05-23 21:08:03 +00:00
|
|
|
CHECKPOINT;
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
ASSERT( pNode->name == "SongScores" );
|
2004-02-10 09:42:01 +00:00
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
FOREACH_CONST( XNode*, pNode->childs, song )
|
2004-02-10 09:42:01 +00:00
|
|
|
{
|
|
|
|
|
if( (*song)->name != "Song" )
|
|
|
|
|
continue;
|
|
|
|
|
|
2004-04-18 18:42:42 +00:00
|
|
|
SongID songID;
|
|
|
|
|
songID.LoadFromNode( *song );
|
|
|
|
|
if( !songID.IsValid() )
|
2004-02-10 09:42:01 +00:00
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
FOREACH_CONST( XNode*, (*song)->childs, steps )
|
2004-02-10 09:42:01 +00:00
|
|
|
{
|
|
|
|
|
if( (*steps)->name != "Steps" )
|
|
|
|
|
continue;
|
|
|
|
|
|
2004-04-18 18:42:42 +00:00
|
|
|
StepsID stepsID;
|
|
|
|
|
stepsID.LoadFromNode( *steps );
|
|
|
|
|
if( !stepsID.IsValid() )
|
2004-02-10 09:42:01 +00:00
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
|
|
|
|
XNode *pHighScoreListNode = (*steps)->GetChild("HighScoreList");
|
|
|
|
|
if( pHighScoreListNode == NULL )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
2004-04-18 18:42:42 +00:00
|
|
|
HighScoreList &hsl = m_SongHighScores[songID].m_StepsHighScores[stepsID].hs;
|
2004-02-10 09:42:01 +00:00
|
|
|
hsl.LoadFromNode( pHighScoreListNode );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
XNode* Profile::SaveCourseScoresCreateNode() const
|
2004-02-10 09:42:01 +00:00
|
|
|
{
|
|
|
|
|
CHECKPOINT;
|
|
|
|
|
|
2004-02-10 10:06:34 +00:00
|
|
|
const Profile* pProfile = this;
|
2004-02-10 09:42:01 +00:00
|
|
|
ASSERT( pProfile );
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
XNode* pNode = new XNode;
|
|
|
|
|
pNode->name = "CourseScores";
|
2004-02-10 09:42:01 +00:00
|
|
|
|
|
|
|
|
|
2004-04-18 19:36:42 +00:00
|
|
|
for( std::map<CourseID,HighScoresForACourse>::const_iterator i = m_CourseHighScores.begin();
|
|
|
|
|
i != m_CourseHighScores.end();
|
|
|
|
|
i++ )
|
2004-02-10 09:42:01 +00:00
|
|
|
{
|
2004-05-23 21:08:03 +00:00
|
|
|
const CourseID &courseID = i->first;
|
2004-04-18 19:36:42 +00:00
|
|
|
const HighScoresForACourse &hsCourse = i->second;
|
2004-02-10 09:42:01 +00:00
|
|
|
|
|
|
|
|
// skip courses that have never been played
|
2004-05-23 21:08:03 +00:00
|
|
|
if( pProfile->GetCourseNumTimesPlayed(courseID) == 0 )
|
2004-02-10 09:42:01 +00:00
|
|
|
continue;
|
|
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
XNode* pCourseNode = pNode->AppendChild( courseID.CreateNode() );
|
2004-02-10 09:42:01 +00:00
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
for( std::map<TrailID,HighScoresForATrail>::const_iterator j = hsCourse.m_TrailHighScores.begin();
|
|
|
|
|
j != hsCourse.m_TrailHighScores.end();
|
|
|
|
|
j++ )
|
2004-02-10 09:42:01 +00:00
|
|
|
{
|
2004-05-23 21:08:03 +00:00
|
|
|
const TrailID &trailID = j->first;
|
|
|
|
|
const HighScoresForATrail &hsTrail = j->second;
|
2004-04-18 19:36:42 +00:00
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
const HighScoreList &hsl = hsTrail.hs;
|
2004-02-22 06:04:01 +00:00
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
// skip steps that have never been played
|
|
|
|
|
if( hsl.iNumTimesPlayed == 0 )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
XNode* pTrailNode = pCourseNode->AppendChild( trailID.CreateNode() );
|
2004-02-22 06:04:01 +00:00
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
pTrailNode->AppendChild( hsl.CreateNode() );
|
2004-02-10 09:42:01 +00:00
|
|
|
}
|
|
|
|
|
}
|
2004-02-19 03:56:03 +00:00
|
|
|
|
|
|
|
|
return pNode;
|
2004-02-10 09:42:01 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
void Profile::LoadCourseScoresFromNode( const XNode* pNode )
|
2004-02-10 09:42:01 +00:00
|
|
|
{
|
|
|
|
|
CHECKPOINT;
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
ASSERT( pNode->name == "CourseScores" );
|
2004-02-10 09:42:01 +00:00
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
FOREACH_CONST( XNode*, pNode->childs, course )
|
2004-02-10 09:42:01 +00:00
|
|
|
{
|
|
|
|
|
if( (*course)->name != "Course" )
|
|
|
|
|
continue;
|
2004-02-22 04:01:12 +00:00
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
CourseID courseID;
|
|
|
|
|
courseID.LoadFromNode( *course );
|
|
|
|
|
if( !courseID.IsValid() )
|
2004-02-22 04:01:12 +00:00
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
FOREACH_CONST( XNode*, (*course)->childs, trail )
|
2004-02-10 09:42:01 +00:00
|
|
|
{
|
2004-05-23 21:08:03 +00:00
|
|
|
if( (*trail)->name != "Trail" )
|
2004-02-10 09:42:01 +00:00
|
|
|
continue;
|
|
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
TrailID trailID;
|
|
|
|
|
trailID.LoadFromNode( *trail );
|
|
|
|
|
if( !trailID.IsValid() )
|
2004-02-22 04:01:12 +00:00
|
|
|
WARN_AND_CONTINUE;
|
2004-02-22 06:04:01 +00:00
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
XNode *pHighScoreListNode = (*trail)->GetChild("HighScoreList");
|
|
|
|
|
if( pHighScoreListNode == NULL )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
|
|
|
|
HighScoreList &hsl = m_CourseHighScores[courseID].m_TrailHighScores[trailID].hs;
|
|
|
|
|
hsl.LoadFromNode( pHighScoreListNode );
|
2004-02-10 09:42:01 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
XNode* Profile::SaveCategoryScoresCreateNode() const
|
2004-02-10 09:42:01 +00:00
|
|
|
{
|
|
|
|
|
CHECKPOINT;
|
|
|
|
|
|
2004-02-10 10:06:34 +00:00
|
|
|
const Profile* pProfile = this;
|
2004-02-10 09:42:01 +00:00
|
|
|
ASSERT( pProfile );
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
XNode* pNode = new XNode;
|
|
|
|
|
pNode->name = "CategoryScores";
|
2004-02-10 09:42:01 +00:00
|
|
|
|
|
|
|
|
FOREACH_StepsType( st )
|
|
|
|
|
{
|
|
|
|
|
// skip steps types that have never been played
|
|
|
|
|
if( pProfile->GetCategoryNumTimesPlayed( st ) == 0 )
|
|
|
|
|
continue;
|
|
|
|
|
|
2004-02-22 03:11:22 +00:00
|
|
|
XNode* pStepsTypeNode = pNode->AppendChild( "StepsType" );
|
|
|
|
|
pStepsTypeNode->AppendAttr( "Type", GameManager::NotesTypeToString(st) );
|
2004-02-10 09:42:01 +00:00
|
|
|
|
|
|
|
|
FOREACH_RankingCategory( rc )
|
|
|
|
|
{
|
|
|
|
|
// skip steps types/categories that have never been played
|
|
|
|
|
if( pProfile->GetCategoryHighScoreList(st,rc).iNumTimesPlayed == 0 )
|
|
|
|
|
continue;
|
|
|
|
|
|
2004-02-22 03:37:43 +00:00
|
|
|
XNode* pRankingCategoryNode = pStepsTypeNode->AppendChild( "RankingCategory" );
|
|
|
|
|
pRankingCategoryNode->AppendAttr( "Type", RankingCategoryToString(rc) );
|
2004-02-10 09:42:01 +00:00
|
|
|
|
2004-02-10 10:06:34 +00:00
|
|
|
const HighScoreList &hsl = pProfile->GetCategoryHighScoreList( (StepsType)st, (RankingCategory)rc );
|
2004-02-10 09:42:01 +00:00
|
|
|
|
|
|
|
|
pRankingCategoryNode->AppendChild( hsl.CreateNode() );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
return pNode;
|
2004-02-10 09:42:01 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
void Profile::LoadCategoryScoresFromNode( const XNode* pNode )
|
2004-02-10 09:42:01 +00:00
|
|
|
{
|
|
|
|
|
CHECKPOINT;
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
ASSERT( pNode->name == "CategoryScores" );
|
2004-02-15 04:47:32 +00:00
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
for( XNodes::const_iterator stepsType = pNode->childs.begin();
|
|
|
|
|
stepsType != pNode->childs.end();
|
2004-02-10 09:42:01 +00:00
|
|
|
stepsType++ )
|
|
|
|
|
{
|
|
|
|
|
if( (*stepsType)->name != "StepsType" )
|
|
|
|
|
continue;
|
|
|
|
|
|
2004-02-22 05:26:02 +00:00
|
|
|
CString str;
|
|
|
|
|
if( !(*stepsType)->GetAttrValue( "Type", str ) )
|
2004-02-22 03:11:22 +00:00
|
|
|
WARN_AND_CONTINUE;
|
2004-02-22 05:26:02 +00:00
|
|
|
StepsType st = GameManager::StringToNotesType( str );
|
2004-02-22 03:11:22 +00:00
|
|
|
if( st == STEPS_TYPE_INVALID )
|
|
|
|
|
WARN_AND_CONTINUE;
|
2004-02-10 09:42:01 +00:00
|
|
|
|
|
|
|
|
for( XNodes::iterator radarCategory = (*stepsType)->childs.begin();
|
|
|
|
|
radarCategory != (*stepsType)->childs.end();
|
|
|
|
|
radarCategory++ )
|
|
|
|
|
{
|
|
|
|
|
if( (*radarCategory)->name != "RankingCategory" )
|
|
|
|
|
continue;
|
|
|
|
|
|
2004-02-22 05:26:02 +00:00
|
|
|
if( !(*radarCategory)->GetAttrValue( "Type", str ) )
|
2004-02-22 03:37:43 +00:00
|
|
|
WARN_AND_CONTINUE;
|
2004-02-22 05:26:02 +00:00
|
|
|
RankingCategory rc = StringToRankingCategory( str );
|
2004-02-22 03:37:43 +00:00
|
|
|
if( rc == RANKING_INVALID )
|
|
|
|
|
WARN_AND_CONTINUE;
|
2004-02-10 09:42:01 +00:00
|
|
|
|
|
|
|
|
XNode *pHighScoreListNode = (*radarCategory)->GetChild("HighScoreList");
|
|
|
|
|
if( pHighScoreListNode == NULL )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
|
|
|
|
HighScoreList &hsl = this->GetCategoryHighScoreList( st, rc );
|
|
|
|
|
hsl.LoadFromNode( pHighScoreListNode );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-10 10:06:34 +00:00
|
|
|
void Profile::SaveStatsWebPageToDir( CString sDir ) const
|
2004-02-10 09:42:01 +00:00
|
|
|
{
|
2004-02-19 03:56:03 +00:00
|
|
|
ASSERT( PROFILEMAN );
|
|
|
|
|
|
2004-02-22 02:41:10 +00:00
|
|
|
SaveStatsWebPage(
|
|
|
|
|
sDir,
|
|
|
|
|
this,
|
|
|
|
|
PROFILEMAN->GetMachineProfile(),
|
2004-05-28 04:46:43 +00:00
|
|
|
IsMachine() ? HTML_TYPE_MACHINE : HTML_TYPE_PLAYER
|
2004-02-22 02:41:10 +00:00
|
|
|
);
|
2004-02-10 09:42:01 +00:00
|
|
|
}
|
2004-02-16 05:35:06 +00:00
|
|
|
|
|
|
|
|
void Profile::SaveMachinePublicKeyToDir( CString sDir ) const
|
|
|
|
|
{
|
2004-02-19 03:56:03 +00:00
|
|
|
if( PREFSMAN->m_bSignProfileData && IsAFile(CRYPTMAN->GetPublicKeyFileName()) )
|
2004-02-23 08:09:21 +00:00
|
|
|
FileCopy( CRYPTMAN->GetPublicKeyFileName(), sDir+PUBLIC_KEY_FILE );
|
2004-02-16 05:35:06 +00:00
|
|
|
}
|
2004-02-17 01:16:57 +00:00
|
|
|
|
|
|
|
|
void Profile::AddScreenshot( Screenshot screenshot )
|
|
|
|
|
{
|
|
|
|
|
m_vScreenshots.push_back( screenshot );
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
void Profile::LoadScreenshotDataFromNode( const XNode* pNode )
|
2004-02-17 01:16:57 +00:00
|
|
|
{
|
|
|
|
|
CHECKPOINT;
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
ASSERT( pNode->name == "ScreenshotData" );
|
|
|
|
|
for( XNodes::const_iterator screenshot = pNode->childs.begin();
|
|
|
|
|
screenshot != pNode->childs.end();
|
2004-02-17 01:16:57 +00:00
|
|
|
screenshot++ )
|
|
|
|
|
{
|
|
|
|
|
if( (*screenshot)->name != "Screenshot" )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
|
|
|
|
Screenshot ss;
|
|
|
|
|
|
|
|
|
|
if( !(*screenshot)->GetChildValue("FileName",ss.sFileName) )
|
2004-02-22 10:10:00 +00:00
|
|
|
WARN;
|
2004-02-17 01:16:57 +00:00
|
|
|
|
2004-02-22 02:41:10 +00:00
|
|
|
if( !(*screenshot)->GetChildValue("MD5",ss.sMD5) )
|
2004-02-22 10:10:00 +00:00
|
|
|
WARN;
|
2004-02-17 01:16:57 +00:00
|
|
|
|
2004-02-22 05:04:11 +00:00
|
|
|
if( !(*screenshot)->GetChildValue("Time",(int&)ss.time) ) // time_t is a signed long on Win32. Is this ok on other platforms?
|
2004-02-22 10:10:00 +00:00
|
|
|
WARN;
|
|
|
|
|
|
2004-04-18 05:46:43 +00:00
|
|
|
if( !(*screenshot)->GetChildValue("MachineGuid",ss.sMachineGuid) )
|
2004-02-22 10:10:00 +00:00
|
|
|
WARN;
|
2004-02-17 01:16:57 +00:00
|
|
|
|
|
|
|
|
m_vScreenshots.push_back( ss );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
XNode* Profile::SaveScreenshotDataCreateNode() const
|
2004-02-17 01:16:57 +00:00
|
|
|
{
|
|
|
|
|
CHECKPOINT;
|
|
|
|
|
|
|
|
|
|
const Profile* pProfile = this;
|
|
|
|
|
ASSERT( pProfile );
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
XNode* pNode = new XNode;
|
|
|
|
|
pNode->name = "ScreenshotData";
|
2004-02-17 01:16:57 +00:00
|
|
|
|
2004-02-17 07:07:13 +00:00
|
|
|
for( unsigned i=0; i<m_vScreenshots.size(); i++ )
|
2004-02-17 01:16:57 +00:00
|
|
|
{
|
|
|
|
|
const Screenshot &ss = m_vScreenshots[i];
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
XNode* pScreenshotNode = pNode->AppendChild( "Screenshot" );
|
2004-02-17 01:16:57 +00:00
|
|
|
|
|
|
|
|
pScreenshotNode->AppendChild( "FileName", ss.sFileName );
|
2004-02-22 20:58:39 +00:00
|
|
|
pScreenshotNode->AppendChild( "MD5", ss.sMD5 );
|
|
|
|
|
pScreenshotNode->AppendChild( "Time", (int) ss.time );
|
2004-04-18 05:46:43 +00:00
|
|
|
pScreenshotNode->AppendChild( "MachineGuid", ss.sMachineGuid );
|
2004-02-17 01:16:57 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
return pNode;
|
2004-02-17 01:16:57 +00:00
|
|
|
}
|
2004-02-22 23:29:13 +00:00
|
|
|
|
|
|
|
|
void Profile::LoadCalorieDataFromNode( const XNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
CHECKPOINT;
|
|
|
|
|
|
|
|
|
|
ASSERT( pNode->name == "CalorieData" );
|
|
|
|
|
for( XNodes::const_iterator pDay = pNode->childs.begin();
|
|
|
|
|
pDay != pNode->childs.end();
|
|
|
|
|
pDay++ )
|
|
|
|
|
{
|
|
|
|
|
if( (*pDay)->name != "Day" )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
|
|
|
|
Day day;
|
|
|
|
|
|
|
|
|
|
if( !(*pDay)->GetAttrValue("DayInYear",day.iDayInYear) )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
|
|
|
|
if( !(*pDay)->GetAttrValue("Year",day.iYear) )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
|
|
|
|
float fCaloriesBurned = 0;
|
|
|
|
|
|
|
|
|
|
if( !(*pDay)->GetChildValue("CaloriesBurned",fCaloriesBurned) )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
|
|
|
|
m_mapDayToCaloriesBurned[day] = fCaloriesBurned;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
XNode* Profile::SaveCalorieDataCreateNode() const
|
|
|
|
|
{
|
|
|
|
|
CHECKPOINT;
|
|
|
|
|
|
|
|
|
|
const Profile* pProfile = this;
|
|
|
|
|
ASSERT( pProfile );
|
|
|
|
|
|
|
|
|
|
XNode* pNode = new XNode;
|
|
|
|
|
pNode->name = "CalorieData";
|
|
|
|
|
|
|
|
|
|
for( map<Day,float>::const_iterator i = m_mapDayToCaloriesBurned.begin();
|
|
|
|
|
i != m_mapDayToCaloriesBurned.end();
|
|
|
|
|
i++ )
|
|
|
|
|
{
|
|
|
|
|
XNode* pDay = pNode->AppendChild( "Day" );
|
|
|
|
|
|
|
|
|
|
pDay->AppendAttr( "DayInYear", i->first.iDayInYear );
|
|
|
|
|
pDay->AppendAttr( "Year", i->first.iYear );
|
|
|
|
|
|
|
|
|
|
pDay->AppendChild( "CaloriesBurned", i->second );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return pNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float Profile::GetCaloriesBurnedForDay( Day day ) const
|
|
|
|
|
{
|
|
|
|
|
map<Day,float>::const_iterator i = m_mapDayToCaloriesBurned.find( day );
|
|
|
|
|
if( i == m_mapDayToCaloriesBurned.end() )
|
|
|
|
|
return 0;
|
|
|
|
|
else
|
|
|
|
|
return i->second;
|
|
|
|
|
}
|
2004-03-07 04:34:49 +00:00
|
|
|
|
|
|
|
|
XNode* Profile::AwardRecord::CreateNode() const
|
|
|
|
|
{
|
|
|
|
|
XNode* pNode = new XNode;
|
|
|
|
|
pNode->name = "AwardRecord";
|
|
|
|
|
|
2004-03-08 00:07:42 +00:00
|
|
|
pNode->AppendChild( "FirstTime", int(first) );
|
|
|
|
|
pNode->AppendChild( "LastTime", int(last) );
|
2004-03-07 04:34:49 +00:00
|
|
|
pNode->AppendChild( "Count", iCount );
|
|
|
|
|
|
|
|
|
|
return pNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Profile::AwardRecord::LoadFromNode( const XNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
Unset();
|
|
|
|
|
|
|
|
|
|
ASSERT( pNode->name == "AwardRecord" );
|
|
|
|
|
pNode->GetChildValue( "FirstTime", (int&)first ); // time_t is a signed long in Win32. Is this OK on other platforms?
|
|
|
|
|
pNode->GetChildValue( "LastTime", (int&)last );
|
|
|
|
|
pNode->GetChildValue( "Count", iCount );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Profile::LoadAwardsFromNode( const XNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
CHECKPOINT;
|
|
|
|
|
|
|
|
|
|
ASSERT( pNode->name == "Awards" );
|
|
|
|
|
for( XNodes::const_iterator pAward = pNode->childs.begin();
|
|
|
|
|
pAward != pNode->childs.end();
|
|
|
|
|
pAward++ )
|
|
|
|
|
{
|
|
|
|
|
if( (*pAward)->name == "PerDifficultyAward" )
|
|
|
|
|
{
|
|
|
|
|
CString sStepsType;
|
|
|
|
|
if( !(*pAward)->GetAttrValue( "StepsType", sStepsType ) )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
StepsType st = GameManager::StringToNotesType( sStepsType );
|
|
|
|
|
if( st == STEPS_TYPE_INVALID )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
|
|
|
|
CString sDifficulty;
|
|
|
|
|
if( !(*pAward)->GetAttrValue( "Difficulty", sDifficulty ) )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
Difficulty dc = StringToDifficulty( sDifficulty );
|
|
|
|
|
if( dc == DIFFICULTY_INVALID )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
|
|
|
|
CString sPerDifficultyAward;
|
|
|
|
|
if( !(*pAward)->GetAttrValue( "PerDifficultyAward", sPerDifficultyAward ) )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
PerDifficultyAward pda = StringToPerDifficultyAward( sPerDifficultyAward );
|
|
|
|
|
if( pda == PER_DIFFICULTY_AWARD_INVALID )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
|
|
|
|
AwardRecord &ar = m_PerDifficultyAwards[st][dc][pda];
|
|
|
|
|
|
|
|
|
|
XNode* pAwardRecord = (*pAward)->GetChild("AwardRecord");
|
|
|
|
|
if( pAwardRecord == NULL )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
|
|
|
|
ar.LoadFromNode( pAwardRecord );
|
|
|
|
|
}
|
|
|
|
|
else if( (*pAward)->name == "PeakComboAward" )
|
|
|
|
|
{
|
|
|
|
|
CString sPeakComboAward;
|
2004-03-14 19:26:03 +00:00
|
|
|
if( !(*pAward)->GetAttrValue( "PeakComboAward", sPeakComboAward ) )
|
2004-03-07 04:34:49 +00:00
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
PeakComboAward pca = StringToPeakComboAward( sPeakComboAward );
|
|
|
|
|
if( pca == PEAK_COMBO_AWARD_INVALID )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
|
|
|
|
AwardRecord &ar = m_PeakComboAwards[pca];
|
|
|
|
|
|
|
|
|
|
XNode* pAwardRecord = (*pAward)->GetChild("AwardRecord");
|
|
|
|
|
if( pAwardRecord == NULL )
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
|
|
|
|
|
ar.LoadFromNode( pAwardRecord );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
XNode* Profile::SaveAwardsCreateNode() const
|
|
|
|
|
{
|
|
|
|
|
CHECKPOINT;
|
|
|
|
|
|
|
|
|
|
const Profile* pProfile = this;
|
|
|
|
|
ASSERT( pProfile );
|
|
|
|
|
|
|
|
|
|
XNode* pNode = new XNode;
|
|
|
|
|
pNode->name = "Awards";
|
|
|
|
|
|
|
|
|
|
FOREACH_StepsType( st )
|
|
|
|
|
{
|
|
|
|
|
FOREACH_Difficulty( dc )
|
|
|
|
|
{
|
|
|
|
|
FOREACH_PerDifficultyAward( pda )
|
|
|
|
|
{
|
|
|
|
|
const AwardRecord &ar = m_PerDifficultyAwards[st][dc][pda];
|
|
|
|
|
if( !ar.IsSet() )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
XNode* pAward = pNode->AppendChild( "PerDifficultyAward" );
|
|
|
|
|
|
|
|
|
|
pAward->AppendAttr( "StepsType", GameManager::NotesTypeToString(st) );
|
|
|
|
|
pAward->AppendAttr( "Difficulty", DifficultyToString(dc) );
|
|
|
|
|
pAward->AppendAttr( "PerDifficultyAward", PerDifficultyAwardToString(pda) );
|
|
|
|
|
|
|
|
|
|
pAward->AppendChild( ar.CreateNode() );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FOREACH_PeakComboAward( pca )
|
|
|
|
|
{
|
|
|
|
|
const AwardRecord &ar = m_PeakComboAwards[pca];
|
|
|
|
|
if( !ar.IsSet() )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
XNode* pAward = pNode->AppendChild( "PeakComboAward" );
|
|
|
|
|
|
|
|
|
|
pAward->AppendAttr( "PeakComboAward", PeakComboAwardToString(pca) );
|
|
|
|
|
|
|
|
|
|
pAward->AppendChild( ar.CreateNode() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return pNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Profile::AddPerDifficultyAward( StepsType st, Difficulty dc, PerDifficultyAward pda )
|
|
|
|
|
{
|
|
|
|
|
m_PerDifficultyAwards[st][dc][pda].Set( time(NULL) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Profile::AddPeakComboAward( PeakComboAward pca )
|
|
|
|
|
{
|
|
|
|
|
m_PeakComboAwards[pca].Set( time(NULL) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Profile::HasPerDifficultyAward( StepsType st, Difficulty dc, PerDifficultyAward pda )
|
|
|
|
|
{
|
|
|
|
|
return m_PerDifficultyAwards[st][dc][pda].IsSet();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Profile::HasPeakComboAward( PeakComboAward pca )
|
|
|
|
|
{
|
|
|
|
|
return m_PeakComboAwards[pca].IsSet();
|
|
|
|
|
}
|
2004-04-22 07:59:42 +00:00
|
|
|
|
|
|
|
|
|
2004-04-22 22:01:38 +00:00
|
|
|
XNode* Profile::HighScoreForASongAndSteps::CreateNode() const
|
|
|
|
|
{
|
|
|
|
|
XNode* pNode = new XNode;
|
|
|
|
|
pNode->name = "HighScoreForASongAndSteps";
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-04-22 22:01:38 +00:00
|
|
|
pNode->AppendChild( songID.CreateNode() );
|
|
|
|
|
pNode->AppendChild( stepsID.CreateNode() );
|
|
|
|
|
pNode->AppendChild( hs.CreateNode() );
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-04-22 22:01:38 +00:00
|
|
|
return pNode;
|
|
|
|
|
}
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-04-22 22:01:38 +00:00
|
|
|
void Profile::HighScoreForASongAndSteps::LoadFromNode( const XNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
Unset();
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-04-22 22:01:38 +00:00
|
|
|
ASSERT( pNode->name == "HighScoreForASongAndSteps" );
|
|
|
|
|
XNode* p;
|
2004-04-26 23:10:16 +00:00
|
|
|
if( (p = pNode->GetChild("Song")) )
|
2004-04-22 22:01:38 +00:00
|
|
|
songID.LoadFromNode( p );
|
2004-04-26 23:10:16 +00:00
|
|
|
if( (p = pNode->GetChild("Steps")) )
|
2004-04-22 22:01:38 +00:00
|
|
|
stepsID.LoadFromNode( p );
|
2004-04-26 23:10:16 +00:00
|
|
|
if( (p = pNode->GetChild("HighScore")) )
|
2004-04-22 22:01:38 +00:00
|
|
|
hs.LoadFromNode( p );
|
|
|
|
|
}
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-05-08 10:12:10 +00:00
|
|
|
void Profile::LoadRecentSongScoresFromNode( const XNode* pNode )
|
2004-04-22 22:01:38 +00:00
|
|
|
{
|
|
|
|
|
CHECKPOINT;
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-05-08 10:12:10 +00:00
|
|
|
ASSERT( pNode->name == "RecentSongScores" );
|
2004-04-22 22:01:38 +00:00
|
|
|
for( XNodes::const_iterator p = pNode->childs.begin();
|
|
|
|
|
p != pNode->childs.end();
|
|
|
|
|
p++ )
|
|
|
|
|
{
|
|
|
|
|
if( (*p)->name == "HighScoreForASongAndSteps" )
|
|
|
|
|
{
|
|
|
|
|
HighScoreForASongAndSteps h;
|
|
|
|
|
h.LoadFromNode( *p );
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-05-08 10:12:10 +00:00
|
|
|
m_vRecentStepsScores.push_back( h );
|
2004-04-22 22:01:38 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-05-08 10:12:10 +00:00
|
|
|
XNode* Profile::SaveRecentSongScoresCreateNode() const
|
2004-04-22 22:01:38 +00:00
|
|
|
{
|
|
|
|
|
CHECKPOINT;
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-04-22 22:01:38 +00:00
|
|
|
const Profile* pProfile = this;
|
|
|
|
|
ASSERT( pProfile );
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-04-22 22:01:38 +00:00
|
|
|
XNode* pNode = new XNode;
|
2004-05-08 10:12:10 +00:00
|
|
|
pNode->name = "RecentSongScores";
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-05-08 10:12:10 +00:00
|
|
|
unsigned uNumToSave = min( m_vRecentStepsScores.size(), (unsigned)MAX_RECENT_SCORES_TO_SAVE );
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-04-22 22:01:38 +00:00
|
|
|
for( unsigned i=0; i<uNumToSave; i++ )
|
|
|
|
|
{
|
2004-05-08 10:12:10 +00:00
|
|
|
pNode->AppendChild( m_vRecentStepsScores[i].CreateNode() );
|
2004-04-22 22:01:38 +00:00
|
|
|
}
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-04-22 22:01:38 +00:00
|
|
|
return pNode;
|
|
|
|
|
}
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-05-08 10:12:10 +00:00
|
|
|
void Profile::AddStepsRecentScore( const Song* pSong, const Steps* pSteps, HighScore hs )
|
2004-04-22 22:01:38 +00:00
|
|
|
{
|
|
|
|
|
HighScoreForASongAndSteps h;
|
|
|
|
|
h.songID.FromSong( pSong );
|
|
|
|
|
h.stepsID.FromSteps( pSteps );
|
|
|
|
|
h.hs = hs;
|
2004-05-08 10:12:10 +00:00
|
|
|
m_vRecentStepsScores.push_back( h );
|
2004-04-22 22:01:38 +00:00
|
|
|
}
|
2004-04-22 07:59:42 +00:00
|
|
|
|
|
|
|
|
|
2004-04-22 22:01:38 +00:00
|
|
|
XNode* Profile::HighScoreForACourse::CreateNode() const
|
2004-04-22 07:59:42 +00:00
|
|
|
{
|
|
|
|
|
XNode* pNode = new XNode;
|
2004-04-22 22:01:38 +00:00
|
|
|
pNode->name = "HighScoreForACourse";
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-04-22 22:01:38 +00:00
|
|
|
pNode->AppendChild( courseID.CreateNode() );
|
2004-04-22 07:59:42 +00:00
|
|
|
pNode->AppendChild( hs.CreateNode() );
|
|
|
|
|
|
|
|
|
|
return pNode;
|
|
|
|
|
}
|
|
|
|
|
|
2004-04-22 22:01:38 +00:00
|
|
|
void Profile::HighScoreForACourse::LoadFromNode( const XNode* pNode )
|
2004-04-22 07:59:42 +00:00
|
|
|
{
|
|
|
|
|
Unset();
|
|
|
|
|
|
2004-04-22 22:01:38 +00:00
|
|
|
ASSERT( pNode->name == "HighScoreForACourse" );
|
2004-04-22 07:59:42 +00:00
|
|
|
XNode* p;
|
2004-04-26 23:10:16 +00:00
|
|
|
if( (p = pNode->GetChild("Course")) )
|
2004-04-22 22:01:38 +00:00
|
|
|
courseID.LoadFromNode( p );
|
2004-04-26 23:10:16 +00:00
|
|
|
if( (p = pNode->GetChild("HighScore")) )
|
2004-04-22 07:59:42 +00:00
|
|
|
hs.LoadFromNode( p );
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-08 10:12:10 +00:00
|
|
|
void Profile::LoadRecentCourseScoresFromNode( const XNode* pNode )
|
2004-04-22 07:59:42 +00:00
|
|
|
{
|
|
|
|
|
CHECKPOINT;
|
|
|
|
|
|
2004-05-08 10:12:10 +00:00
|
|
|
ASSERT( pNode->name == "RecentCourseScores" );
|
2004-04-22 07:59:42 +00:00
|
|
|
for( XNodes::const_iterator p = pNode->childs.begin();
|
|
|
|
|
p != pNode->childs.end();
|
|
|
|
|
p++ )
|
|
|
|
|
{
|
2004-04-22 22:01:38 +00:00
|
|
|
if( (*p)->name == "HighScoreForACourse" )
|
2004-04-22 07:59:42 +00:00
|
|
|
{
|
2004-04-22 22:01:38 +00:00
|
|
|
HighScoreForACourse h;
|
2004-04-22 07:59:42 +00:00
|
|
|
h.LoadFromNode( *p );
|
|
|
|
|
|
2004-05-08 10:12:10 +00:00
|
|
|
m_vRecentCourseScores.push_back( h );
|
2004-04-22 07:59:42 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
WARN_AND_CONTINUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-08 10:12:10 +00:00
|
|
|
XNode* Profile::SaveRecentCourseScoresCreateNode() const
|
2004-04-22 07:59:42 +00:00
|
|
|
{
|
|
|
|
|
CHECKPOINT;
|
|
|
|
|
|
|
|
|
|
const Profile* pProfile = this;
|
|
|
|
|
ASSERT( pProfile );
|
|
|
|
|
|
|
|
|
|
XNode* pNode = new XNode;
|
2004-05-08 10:12:10 +00:00
|
|
|
pNode->name = "RecentCourseScores";
|
2004-04-22 07:59:42 +00:00
|
|
|
|
2004-05-08 10:12:10 +00:00
|
|
|
unsigned uNumToSave = min( m_vRecentCourseScores.size(), (unsigned)MAX_RECENT_SCORES_TO_SAVE );
|
2004-04-22 07:59:42 +00:00
|
|
|
|
|
|
|
|
for( unsigned i=0; i<uNumToSave; i++ )
|
|
|
|
|
{
|
2004-05-08 10:12:10 +00:00
|
|
|
pNode->AppendChild( m_vRecentCourseScores[i].CreateNode() );
|
2004-04-22 07:59:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return pNode;
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-23 21:08:03 +00:00
|
|
|
void Profile::AddCourseRecentScore( const Course* pCourse, const Trail* pTrail, HighScore hs )
|
2004-04-22 07:59:42 +00:00
|
|
|
{
|
2004-04-22 22:01:38 +00:00
|
|
|
HighScoreForACourse h;
|
|
|
|
|
h.courseID.FromCourse( pCourse );
|
2004-05-23 21:08:03 +00:00
|
|
|
h.trailID.FromTrail( pTrail );
|
2004-04-22 07:59:42 +00:00
|
|
|
h.hs = hs;
|
2004-05-08 10:12:10 +00:00
|
|
|
m_vRecentCourseScores.push_back( h );
|
2004-04-22 07:59:42 +00:00
|
|
|
}
|
|
|
|
|
|
2004-05-02 00:08:42 +00:00
|
|
|
const Profile::HighScoresForASong *Profile::GetHighScoresForASong( const SongID& songID ) const
|
|
|
|
|
{
|
|
|
|
|
std::map<SongID,HighScoresForASong>::const_iterator it;
|
|
|
|
|
it = m_SongHighScores.find( songID );
|
|
|
|
|
if( it == m_SongHighScores.end() )
|
|
|
|
|
return NULL;
|
|
|
|
|
return &it->second;
|
|
|
|
|
}
|
2004-05-23 21:08:03 +00:00
|
|
|
|
|
|
|
|
const Profile::HighScoresForACourse *Profile::GetHighScoresForACourse( const CourseID& courseID ) const
|
|
|
|
|
{
|
|
|
|
|
std::map<CourseID,HighScoresForACourse>::const_iterator it;
|
|
|
|
|
it = m_CourseHighScores.find( courseID );
|
|
|
|
|
if( it == m_CourseHighScores.end() )
|
|
|
|
|
return NULL;
|
|
|
|
|
return &it->second;
|
|
|
|
|
}
|
2004-05-28 04:46:43 +00:00
|
|
|
|
|
|
|
|
bool Profile::IsMachine() const
|
|
|
|
|
{
|
|
|
|
|
// TODO: Think of a better way to handle this
|
|
|
|
|
return this == PROFILEMAN->GetMachineProfile();
|
|
|
|
|
}
|