better calories tracking
This commit is contained in:
@@ -28,35 +28,6 @@ static const CString COINS_DAT = "Data/Coins.dat";
|
||||
|
||||
const int COINS_DAT_VERSION = 1;
|
||||
|
||||
tm AddDays( tm start, int iDaysToMove )
|
||||
{
|
||||
start.tm_mday += iDaysToMove;
|
||||
time_t seconds = mktime( &start );
|
||||
ASSERT( seconds != (time_t)-1 );
|
||||
tm time;
|
||||
localtime_r( &seconds, &time );
|
||||
return time;
|
||||
}
|
||||
|
||||
tm GetYesterday( tm start )
|
||||
{
|
||||
return AddDays( start, -1 );
|
||||
}
|
||||
|
||||
int GetDayOfWeek( tm time )
|
||||
{
|
||||
int iDayOfWeek = time.tm_wday;
|
||||
ASSERT( iDayOfWeek < DAYS_IN_WEEK );
|
||||
return iDayOfWeek;
|
||||
}
|
||||
|
||||
tm GetNextSunday( tm start )
|
||||
{
|
||||
return AddDays( start, DAYS_IN_WEEK-GetDayOfWeek(start) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
Bookkeeper::Bookkeeper()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
+76
-20
@@ -95,7 +95,6 @@ void Profile::InitGeneralData()
|
||||
m_iNumSongsPlayedByMeter[i] = 0;
|
||||
ZERO( m_iNumSongsPassedByPlayMode );
|
||||
ZERO( m_iNumSongsPassedByGrade );
|
||||
ZERO( m_iCaloriesByDayForLastYear );
|
||||
}
|
||||
|
||||
void Profile::InitSongScores()
|
||||
@@ -120,6 +119,11 @@ void Profile::InitScreenshotData()
|
||||
m_vScreenshots.clear();
|
||||
}
|
||||
|
||||
void Profile::InitCalorieData()
|
||||
{
|
||||
m_mapDayToCaloriesBurned.clear();
|
||||
}
|
||||
|
||||
CString Profile::GetDisplayName() const
|
||||
{
|
||||
if( !m_sDisplayName.empty() )
|
||||
@@ -135,7 +139,7 @@ CString Profile::GetDisplayTotalCaloriesBurned() const
|
||||
if( m_fWeightPounds == 0 ) // weight not entered
|
||||
return "N/A";
|
||||
else
|
||||
return ssprintf("%0.3fCal",m_fTotalCaloriesBurned);
|
||||
return ssprintf("%0.3f Cal",m_fTotalCaloriesBurned);
|
||||
}
|
||||
|
||||
int Profile::GetTotalNumSongsPlayed() const
|
||||
@@ -385,6 +389,7 @@ bool Profile::LoadAllFromDir( CString sDir )
|
||||
LOAD_NODE( CourseScores );
|
||||
LOAD_NODE( CategoryScores );
|
||||
LOAD_NODE( ScreenshotData );
|
||||
LOAD_NODE( CalorieData );
|
||||
}
|
||||
|
||||
return true; // FIXME? Investigate what happens if we always return true.
|
||||
@@ -408,6 +413,7 @@ bool Profile::SaveAllToDir( CString sDir ) const
|
||||
xml.AppendChild( SaveCourseScoresCreateNode() );
|
||||
xml.AppendChild( SaveCategoryScoresCreateNode() );
|
||||
xml.AppendChild( SaveScreenshotDataCreateNode() );
|
||||
xml.AppendChild( SaveCalorieDataCreateNode() );
|
||||
bool bSaved = xml.SaveToFile(fn);
|
||||
if( bSaved && PREFSMAN->m_bSignProfileData )
|
||||
{
|
||||
@@ -585,17 +591,6 @@ XNode* Profile::SaveGeneralDataCreateNode() const
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
XNode* pCaloriesByDayForLastYear = pGeneralDataNode->AppendChild("CaloriesByDayForLastYear");
|
||||
for( int i=0; i<DAYS_IN_YEAR; i++ )
|
||||
{
|
||||
/* Don't save empty. */
|
||||
if( m_iCaloriesByDayForLastYear[i]==0 )
|
||||
continue;
|
||||
pCaloriesByDayForLastYear->AppendChild( DayInYearToString(i), m_iCaloriesByDayForLastYear[i] );
|
||||
}
|
||||
}
|
||||
|
||||
return pGeneralDataNode;
|
||||
}
|
||||
|
||||
@@ -727,13 +722,6 @@ void Profile::LoadGeneralDataFromNode( const XNode* pNode )
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
XNode* pCaloriesByDayForLastYear = pNode->GetChild("CaloriesByDayForLastYear");
|
||||
if( pCaloriesByDayForLastYear )
|
||||
for( int i=0; i<DAYS_IN_YEAR; i++ )
|
||||
pCaloriesByDayForLastYear->GetChildValue( DayInYearToString(i), m_iCaloriesByDayForLastYear[i] );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Profile::AddStepTotals( int iTotalTapsAndHolds, int iTotalJumps, int iTotalHolds, int iTotalMines, int iTotalHands )
|
||||
@@ -753,6 +741,11 @@ void Profile::AddStepTotals( int iTotalTapsAndHolds, int iTotalJumps, int iTotal
|
||||
SCALE( m_fWeightPounds, 100.f, 200.f, 0.000f, 0.000f ) * iTotalMines +
|
||||
SCALE( m_fWeightPounds, 100.f, 200.f, 0.222f, 0.386f ) * iTotalHands;
|
||||
m_fTotalCaloriesBurned += fCals;
|
||||
|
||||
time_t cur_time = time(NULL);
|
||||
tm *cur_tm = localtime( &cur_time );
|
||||
Day day = { cur_tm->tm_yday, cur_tm->tm_year+1900 };
|
||||
m_mapDayToCaloriesBurned[day] += fCals;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1451,3 +1444,66 @@ XNode* Profile::SaveScreenshotDataCreateNode() const
|
||||
|
||||
return pNode;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
+33
-3
@@ -72,6 +72,8 @@ public:
|
||||
int GetTotalNumSongsPassed() const;
|
||||
static CString GetProfileDisplayNameFromDir( CString sDir );
|
||||
int GetSongNumTimesPlayed( const Song* pSong ) const;
|
||||
|
||||
void AddStepTotals( int iNumTapsAndHolds, int iNumJumps, int iNumHolds, int iNumMines, int iNumHands );
|
||||
|
||||
//
|
||||
// Editable data
|
||||
@@ -107,9 +109,6 @@ public:
|
||||
int m_iNumSongsPlayedByMeter[MAX_METER+1];
|
||||
int m_iNumSongsPassedByPlayMode[NUM_PLAY_MODES];
|
||||
int m_iNumSongsPassedByGrade[NUM_GRADES];
|
||||
int m_iCaloriesByDayForLastYear[DAYS_IN_YEAR];
|
||||
|
||||
void AddStepTotals( int iNumTapsAndHolds, int iNumJumps, int iNumHolds, int iNumMines, int iNumHands );
|
||||
|
||||
//
|
||||
// Steps high scores
|
||||
@@ -171,6 +170,33 @@ public:
|
||||
void AddScreenshot( Screenshot screenshot );
|
||||
int GetNextScreenshotIndex() { return m_vScreenshots.size(); }
|
||||
|
||||
|
||||
//
|
||||
// Calorie Data
|
||||
//
|
||||
// Why track calories in a map, and not in a static sized array like
|
||||
// Bookkeeping? The machine's clock is not guaranteed to be set correctly.
|
||||
// If calorie array is in a static sized array, playing on a machine with
|
||||
// a mis-set clock could wipe out all your past data. With this scheme,
|
||||
// the worst that could happen is that playing on a mis-set machine will
|
||||
// insert some garbage entries into the map.
|
||||
struct Day
|
||||
{
|
||||
int iDayInYear; // 0-365
|
||||
int iYear; // e.g. 2004
|
||||
bool operator==( const Day& other ) const { return iDayInYear==other.iDayInYear && iYear==other.iYear; }
|
||||
bool operator<( const Day& other ) const
|
||||
{
|
||||
if(iYear<other.iYear)
|
||||
return true;
|
||||
if( iYear>other.iYear)
|
||||
return false;
|
||||
else
|
||||
return iDayInYear<other.iDayInYear;
|
||||
}
|
||||
};
|
||||
map<Day,float> m_mapDayToCaloriesBurned;
|
||||
float GetCaloriesBurnedForDay( Day day ) const;
|
||||
|
||||
//
|
||||
// Init'ing
|
||||
@@ -183,6 +209,7 @@ public:
|
||||
InitCourseScores();
|
||||
InitCategoryScores();
|
||||
InitScreenshotData();
|
||||
InitCalorieData();
|
||||
}
|
||||
void InitEditableData();
|
||||
void InitGeneralData();
|
||||
@@ -190,6 +217,7 @@ public:
|
||||
void InitCourseScores();
|
||||
void InitCategoryScores();
|
||||
void InitScreenshotData();
|
||||
void InitCalorieData();
|
||||
|
||||
//
|
||||
// Loading and saving
|
||||
@@ -208,6 +236,7 @@ public:
|
||||
void LoadCourseScoresFromNode( const XNode* pNode );
|
||||
void LoadCategoryScoresFromNode( const XNode* pNode );
|
||||
void LoadScreenshotDataFromNode( const XNode* pNode );
|
||||
void LoadCalorieDataFromNode( const XNode* pNode );
|
||||
|
||||
void SaveEditableDataToDir( CString sDir ) const;
|
||||
XNode* SaveGeneralDataCreateNode() const;
|
||||
@@ -215,6 +244,7 @@ public:
|
||||
XNode* SaveCourseScoresCreateNode() const;
|
||||
XNode* SaveCategoryScoresCreateNode() const;
|
||||
XNode* SaveScreenshotDataCreateNode() const;
|
||||
XNode* SaveCalorieDataCreateNode() const;
|
||||
|
||||
void DeleteProfileDataFromDirSM390a12( CString sDir ) const;
|
||||
void DeleteSongScoresFromDirSM390a12( CString sDir ) const;
|
||||
|
||||
@@ -363,6 +363,7 @@ void PrintStatistics( RageFile &f, const Profile *pProfile, CString sTitle, vect
|
||||
END_TABLE;
|
||||
}
|
||||
PRINT_CLOSE(f);
|
||||
|
||||
}
|
||||
PRINT_CLOSE(f);
|
||||
}
|
||||
@@ -855,13 +856,7 @@ void PrintBookkeeping( RageFile &f, const Profile *pProfile, CString sTitle, vec
|
||||
BEGIN_TABLE(4);
|
||||
for( int i=0; i<NUM_LAST_WEEKS; i++ )
|
||||
{
|
||||
CString sWeek;
|
||||
switch( i )
|
||||
{
|
||||
case 0: sWeek = "This week"; break;
|
||||
case 1: sWeek = "Last week"; break;
|
||||
default: sWeek = ssprintf("%d weeks ago",i); break;
|
||||
}
|
||||
CString sWeek = LastWeekToString( i );
|
||||
TABLE_LINE2( sWeek, coins[i] );
|
||||
}
|
||||
END_TABLE;
|
||||
@@ -972,6 +967,51 @@ void PrintScreenshots( RageFile &f, const Profile *pProfile, CString sTitle, CSt
|
||||
PRINT_CLOSE(f);
|
||||
}
|
||||
|
||||
void PrintCaloriesBurned( RageFile &f, const Profile *pProfile, CString sTitle, CString sProfileDir )
|
||||
{
|
||||
PRINT_OPEN(f, sTitle );
|
||||
{
|
||||
f.Write("<table>\n");
|
||||
|
||||
// header row
|
||||
f.Write("<tr>");
|
||||
f.Write("<td></td>");
|
||||
{
|
||||
for( int i=0; i<DAYS_IN_WEEK; i++ )
|
||||
f.Write("<td>"+DayOfWeekToString(i)+"</td>");
|
||||
}
|
||||
f.Write("<td>Total</td>");
|
||||
f.Write("</tr>");
|
||||
|
||||
// row for each week
|
||||
time_t now = time( NULL );
|
||||
tm when = *localtime( &now );
|
||||
when = GetNextSunday( when );
|
||||
when = AddDays( when, -DAYS_IN_WEEK );
|
||||
{
|
||||
for( int i=0; i<NUM_LAST_WEEKS; i++ )
|
||||
{
|
||||
float fWeekCals = 0;
|
||||
f.Write("<tr>");
|
||||
f.Write("<td>"+LastWeekToString(i)+"</td>");
|
||||
for( int i=0; i<DAYS_IN_WEEK; i++ )
|
||||
{
|
||||
Profile::Day day = { when.tm_yday, when.tm_year+1900 };
|
||||
float fDayCals = pProfile->GetCaloriesBurnedForDay( day );
|
||||
fWeekCals += fDayCals;
|
||||
f.Write("<td>"+ssprintf("%0.3f",fDayCals)+"</td>");
|
||||
when = AddDays( when, +1 );
|
||||
}
|
||||
f.Write("<td>"+ssprintf("%0.3f",fWeekCals)+"</td>");
|
||||
f.Write("</tr>");
|
||||
when = AddDays( when, -DAYS_IN_WEEK*2 );
|
||||
}
|
||||
}
|
||||
f.Write("</table>\n");
|
||||
}
|
||||
PRINT_CLOSE(f);
|
||||
}
|
||||
|
||||
|
||||
void SaveStatsWebPage(
|
||||
CString sDir,
|
||||
@@ -1124,6 +1164,7 @@ TITLE.c_str(), STYLE_CSS.c_str() ) );
|
||||
PrintSongHighScores( f, pProfile, "My Song High Scores", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
||||
PrintCourseHighScores( f, pProfile, "My Course High Scores", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
||||
PrintScreenshots( f, pProfile, "My Screenshots", sDir );
|
||||
PrintCaloriesBurned( f, pProfile, "My Calories Burned", sDir );
|
||||
PrintGradeTable( f, pProfile, "My Grade Table", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
||||
PrintPopularity( f, pProfile, "Last Machine Popularity", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
||||
PrintSongHighScores( f, pProfile, "Last Machine High Scores", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
||||
@@ -1134,6 +1175,7 @@ TITLE.c_str(), STYLE_CSS.c_str() ) );
|
||||
PrintSongHighScores( f, pProfile, "Song High Scores", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
||||
PrintCourseHighScores( f, pProfile, "Course High Scores", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
||||
PrintScreenshots( f, pProfile, "Screenshots", sDir );
|
||||
PrintCaloriesBurned( f, pProfile, "Calories Burned", sDir );
|
||||
PrintGradeTable( f, pProfile, "Grade Table", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
||||
PrintInventoryList( f, pProfile, "Song Information", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
||||
PrintBookkeeping( f, pProfile, "Bookkeeping", vpSongs, vpAllSteps, vStepsTypesToShow, mapStepsToSong, vpCourses );
|
||||
|
||||
@@ -63,3 +63,74 @@ CString HourInDayToString( int iHourInDayIndex )
|
||||
return ssprintf("%02d:00", iHourInDayIndex);
|
||||
}
|
||||
|
||||
static const CString MONTH_TO_NAME[MONTHS_IN_YEAR] =
|
||||
{
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December",
|
||||
};
|
||||
|
||||
CString MonthToString( int iMonthIndex )
|
||||
{
|
||||
return MONTH_TO_NAME[iMonthIndex];
|
||||
}
|
||||
|
||||
CString LastWeekToString( int iLastWeekIndex )
|
||||
{
|
||||
switch( iLastWeekIndex )
|
||||
{
|
||||
case 0: return "This week"; break;
|
||||
case 1: return "Last week"; break;
|
||||
default: return ssprintf("%d weeks ago",iLastWeekIndex); break;
|
||||
}
|
||||
}
|
||||
|
||||
tm AddDays( tm start, int iDaysToMove )
|
||||
{
|
||||
start.tm_mday += iDaysToMove;
|
||||
time_t seconds = mktime( &start );
|
||||
ASSERT( seconds != (time_t)-1 );
|
||||
tm time;
|
||||
localtime_r( &seconds, &time );
|
||||
return time;
|
||||
}
|
||||
|
||||
tm GetYesterday( tm start )
|
||||
{
|
||||
return AddDays( start, -1 );
|
||||
}
|
||||
|
||||
int GetDayOfWeek( tm time )
|
||||
{
|
||||
int iDayOfWeek = time.tm_wday;
|
||||
ASSERT( iDayOfWeek < DAYS_IN_WEEK );
|
||||
return iDayOfWeek;
|
||||
}
|
||||
|
||||
tm GetNextSunday( tm start )
|
||||
{
|
||||
return AddDays( start, DAYS_IN_WEEK-GetDayOfWeek(start) );
|
||||
}
|
||||
|
||||
|
||||
tm GetDayInYearAndYear( int iDayInYearIndex, int iYear )
|
||||
{
|
||||
time_t now = time( NULL );
|
||||
tm when = *localtime( &now );
|
||||
|
||||
when.tm_mday = iDayInYearIndex;
|
||||
when.tm_year = iYear - 1900;
|
||||
time_t then = mktime( &when );
|
||||
|
||||
when = *localtime( &then );
|
||||
return when;
|
||||
}
|
||||
|
||||
@@ -11,17 +11,29 @@
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "time.h"
|
||||
|
||||
|
||||
const int NUM_LAST_DAYS = 7;
|
||||
const int NUM_LAST_WEEKS = 52;
|
||||
const int DAYS_IN_YEAR = 365;
|
||||
const int HOURS_IN_DAY = 24;
|
||||
const int DAYS_IN_WEEK = 7;
|
||||
const int MONTHS_IN_YEAR = 12;
|
||||
|
||||
CString DayInYearToString( int iDayInYearIndex );
|
||||
CString LastDayToString( int iLastDayIndex );
|
||||
CString DayOfWeekToString( int iDayOfWeekIndex );
|
||||
CString HourInDayToString( int iHourIndex );
|
||||
CString MonthToString( int iMonthIndex );
|
||||
CString LastWeekToString( int iLastWeekIndex );
|
||||
|
||||
tm AddDays( tm start, int iDaysToMove );
|
||||
tm GetYesterday( tm start );
|
||||
int GetDayOfWeek( tm time );
|
||||
tm GetNextSunday( tm start );
|
||||
|
||||
tm GetDayInYearAndYear( int iDayInYearIndex, int iYear );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1043,6 +1043,9 @@ LPXAttr _tagXMLNode::AppendAttr( LPCTSTR name /*= NULL*/, LPCTSTR value /*= NULL
|
||||
return AppendAttr( CreateAttr( name, value ) );
|
||||
}
|
||||
|
||||
LPXAttr _tagXMLNode::AppendAttr( LPCTSTR name, float value ){ return AppendAttr(name,ssprintf("%f",value)); }
|
||||
LPXAttr _tagXMLNode::AppendAttr( LPCTSTR name, int value ) { return AppendAttr(name,ssprintf("%d",value)); }
|
||||
|
||||
//========================================================
|
||||
// Name : DetachChild
|
||||
// Desc : no delete object, just detach in list
|
||||
|
||||
@@ -186,6 +186,8 @@ typedef struct _tagXMLNode
|
||||
XAttrs::iterator GetAttrIterator( LPXAttr node );
|
||||
LPXAttr CreateAttr( LPCTSTR anem = NULL, LPCTSTR value = NULL );
|
||||
LPXAttr AppendAttr( LPCTSTR name = NULL, LPCTSTR value = NULL );
|
||||
LPXAttr AppendAttr( LPCTSTR name, float value );
|
||||
LPXAttr AppendAttr( LPCTSTR name, int value );
|
||||
LPXAttr AppendAttr( LPXAttr attr );
|
||||
bool RemoveAttr( LPXAttr attr );
|
||||
LPXAttr DetachAttr( LPXAttr attr );
|
||||
|
||||
Reference in New Issue
Block a user