// HRateMon.cpp : implementation of the CHeartRateMonitor class
//
#include "stdafx.h"
#include "HRateMon.h"
#include <stdlib.h>
// List of predefined constants
#define ID_HEART_RATE_METER 0x12345
// Structure for heart rate definition
typedef struct tagHeartRate
{
INT nFromAge;
INT nToAge;
INT nMinValue;
INT nThresholdValue;
INT nMaxValue;
}HEARTRATE, * LPHEARTRATE, **LPPHEARTRATE;
/////////////////////////////////////////////////////////////////////////////
// CHeartRateMonitor message handlers
BEGIN_MESSAGE_MAP(CHeartRateMonitor, CCardioMonitor)
//{{AFX_MSG_MAP(CTimeMonitor)
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CHeartRateMonitor::CHeartRateMonitor( CCardioSubject * pCardioSubject ) : CCardioMonitor( pCardioSubject )
{
// Step 1 - Initialize class members
m_nAge = m_pCardioSubject->GetAge();
m_csProgram = m_pCardioSubject->GetProgram();
m_nLevel = m_pCardioSubject->GetLevel();
// Step 2 - Based on Age and Program initialize min, threshold and max heartrate value
InitializeHeartRate();
}
CHeartRateMonitor::~CHeartRateMonitor()
{
}
BOOL CHeartRateMonitor::Update( CSubject * pSubject )
{
// Step 1 - Make sure the right subject updates the heartrate meter
if( m_pCardioSubject != pSubject )
{
return FALSE;
}
// Step 2 - Set heart rate if the program changes
CString csProgram = m_pCardioSubject->GetProgram();
if( csProgram != m_csProgram )
{
m_csProgram = csProgram;
InitializeHeartRate();
}
else
{
m_csProgram = csProgram;
}
// Step 3 - Get age and level
m_nAge = m_pCardioSubject->GetAge();
m_nLevel = m_pCardioSubject->GetLevel();
// Step 4 - Get heart rate, if the meter is running
if( m_bStarted == TRUE )
{
LONG lHeartRate = GetHeartRate();
CHAR szText[ 512 ];
INT nPercent = ( INT )( ( ( double ) ( lHeartRate - m_nMinValue ) ) /
( double ) ( m_nMaxValue - m_nMinValue ) * 100 );
// Step 5 - Beep to indicate very low or high heart rate
if( lHeartRate < m_nMinValue )
{
MessageBeep( 0xFFFFFFFF );
nPercent = 0;
}
if( lHeartRate > m_nMaxValue )
{
MessageBeep( 0xFFFFFFFF );
nPercent = 100;
}
memset( szText, 0, sizeof( szText ) );
sprintf( szText, "Heart Rate = %ld (%d%%)", lHeartRate, nPercent );
m_HeartRateMeter.SetText( szText );
m_HeartRateMeter.SetPos( nPercent );
}
// Step 6 - Update the window with the new information
Invalidate();
return TRUE;
}
BOOL CHeartRateMonitor::Create( const RECT & rRect, CWnd * pParentWnd, UINT nID )
{
// Step 1 - Adjust Rectangle
CRect WndRect = CRect( rRect.left, rRect.top, rRect.left + 490, rRect.top + 120 );
CRect ClientRect;
// Step 2 - Create window
CWnd::Create( NULL, NULL, WS_VISIBLE | WS_BORDER | WS_CHILD | WS_TABSTOP,
WndRect, pParentWnd, nID );
// Step 3 - Create heart rate meter
GetClientRect( ClientRect );
CRect HeartRateMeterRect = CRect( ClientRect.left + 20, ClientRect.top + 60, ClientRect.right - 20, ClientRect.top + 80 );
m_HeartRateMeter.Create( NULL, "0", WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP,
HeartRateMeterRect, ( CWnd * ) this, ID_HEART_RATE_METER );
// Step 4 - Set default display
CHAR szText[ 512 ];
memset( szText, 0, sizeof( szText ) );
sprintf( szText, "Heart Rate = 0 (0%%)" );
m_HeartRateMeter.SetText( szText );
return TRUE;
}
void CHeartRateMonitor::OnPaint()
{
CRect ClientRect;
CRect DrawRect;
CRect TitleRect;
CHAR szTitle[ 512 ];
CHAR szHeartRateValue[ 512 ];
CPaintDC dc(this);
// Step 1 - Set background color and mode
GetClientRect( ClientRect );
dc.FillSolidRect( ClientRect, RGB( 255, 255, 0 ) );
TitleRect = CRect( ClientRect.left, ClientRect.top, ClientRect.right, ClientRect.top + 30 );
dc.FillSolidRect( TitleRect, RGB( 0, 128, 128 ) );
dc.SetBkMode( TRANSPARENT );
// Step 2 - Set the title color and text
dc.SetTextColor( RGB( 255, 255, 255 ) );
DrawRect = CRect( ClientRect.left, ClientRect.top + 5, ClientRect.right, ClientRect.top + 45 );
memset( szTitle, 0, sizeof( szTitle ) );
sprintf( szTitle, "HeartRate Monitor : Program - %s and Level - %d", m_csProgram, m_nLevel );
dc.DrawText( szTitle, strlen( szTitle ), DrawRect, DT_CENTER | DT_WORDBREAK );
// Step 3 - Set the min, threshold and max values
dc.SetTextColor( RGB( 0, 0, 0 ) );
DrawRect = CRect( ClientRect.left, ClientRect.top + 85, ClientRect.right, ClientRect.top + 125 );
memset( szHeartRateValue, 0, sizeof( szHeartRateValue ) );
sprintf( szHeartRateValue, " Min - %.3d Threshold - %.3d Max - %.3d",
m_nMinValue, m_nThresholdValue, m_nMaxValue );
dc.DrawText( szHeartRateValue, strlen( szHeartRateValue ), DrawRect, DT_LEFT | DT_WORDBREAK );
}
LONG CHeartRateMonitor::GetHeartRate()
{
// Step 1 - Generate random no. to get the heartrate
LONG lHeartRate = m_nMinValue + ( rand() % ( m_nMaxValue - m_nMinValue ) );
// Step 2 - Adjust the heart rate, to simulate the extreme conditions
// when heart rate falls in that area
if( lHeartRate - m_nMinValue < 5 )
{
lHeartRate -= rand() % 5;
}
if( m_nMaxValue - lHeartRate < 5 )
{
lHeartRate += rand() % 5;
}
return lHeartRate;
}
VOID CHeartRateMonitor::Stop()
{
// Step 1 - Set default display
CHAR szText[ 512 ];
memset( szText, 0, sizeof( szText ) );
sprintf( szText, "Heart Rate = 0 (0%%)" );
m_HeartRateMeter.SetText( szText );
m_HeartRateMeter.SetPos( 0 );
// Step 2 - Set m_bStarted to FALSE
m_bStarted = FALSE;
}
BOOL CHeartRateMonitor::InitializeHeartRate()
{
// Assign some arbitary heart rate
static HEARTRATE sbFatburn[ 7 ] =
{
{ 10, 20, 105, 110, 115 },
{ 21, 30, 110, 115, 120 },
{ 31, 40, 115, 120, 125 },
{ 41, 50, 120, 125, 130 },
{ 51, 60, 115, 120, 125 },
{ 61, 70, 110, 115, 120 },
{ 71, 100, 105, 110, 115 }
};
static HEARTRATE sbCardio[ 7 ] =
{
{ 10, 20, 115, 120, 125 },
{ 21, 30, 120, 125, 130 },
{ 31, 40, 125, 130, 135 },
{ 41, 50, 130, 135, 140 },
{ 51, 60, 125, 130, 135 },
{ 61, 70, 120, 125, 130 },
{ 71, 100, 115, 120, 125 }
};
INT nIndex = 0;
// Step 1 - Assign min, max and threshold heart rates based on
// the program
if( m_csProgram.CompareNoCase( "Fatburn" ) == 0 )
{
for( nIndex = 0; nIndex < 7; nIndex++ )
{
if( m_nAge >= sbFatburn[ nIndex ].nFromAge &&
m_nAge <= sbFatburn[ nIndex ].nToAge )
{
m_nMinValue = sbFatburn[ nIndex ].nMinValue;
m_nThresholdValue = sbFatburn[ nIndex ].nThresholdValue;
m_nMaxValue = sbFatburn[ nIndex ].nMaxValue;
break;
}
}
}
else
{
for( nIndex = 0; nIndex < 7; nIndex++ )
{
if( m_nAge >= sbCardio[ nIndex ].nFromAge &&
m_nAge <= sbCardio[ nIndex ].nToAge )
{
m_nMinValue = sbCardio[ nIndex ].nMinValue;
m_nThresholdValue = sbCardio[ nIndex ].nThresholdValue;
m_nMaxValue = sbCardio[ nIndex ].nMaxValue;
break;
}
}
}
return TRUE;
}