1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
|
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
#include <cstring>
#include <iomanip>
#include <cassert>
#include <cmath>
#include <cstdlib>
#include "CycleComputer.h"
using namespace std;
//
// Macro constants
//
#define FILE_NAME_SZ 256
#define INPUT_BUFFER_SZ 256
#define SCRIPT_COMMENT_CHAR '\''
#define SCRIPT_DELIM ": \t\n"
#define SCRIPT_TOK_RESET "RESET"
#define SCRIPT_TOK_SECOND "SECONDS"
#define SCRIPT_TOK_SHOW "SHOW"
#define SCRIPT_TOK_ROTATION "ROTATIONS"
#define SCRIPT_TOK_PAUSE "PAUSE"
// Display link separator statement
#define BREAK_STR cout << endl << "**********" << endl << endl
// Macro to create functions for fetching values from a user.
// nm - the function name
// type - the type for the function to get
// prompt - the prompt displayed to the user
//
#define GET_FUNC(nm, type, prompt) \
static type nm(void) \
{ \
type value; \
\
BREAK_STR; \
cout << "Enter " << prompt << ": "; \
\
cin >> value; \
\
return value; \
}
// Macro to display an error message for token processing
// ln - line number
// tok - token string
// msg - descriptive error message
//
#define ERROR(ln, tok, msg) \
{ \
cout << "*** Script error - tok: " << tok << endl; \
cout << "*** " msg " @ line #" << ln << endl; \
}
// Macro to test for a valid parameter for a token
// tok - token string
// param - parameter string
// ln - line number
//
#define VERIFY_PARAM_FOR_TOK( tok, param, ln ) \
if ( ! param ) \
{ \
ERROR( ln, tok, "Missing parameter" ); \
return; \
}
// Enum for menu options
enum MenuOption {
mnuMIN_ = 1,
mnuTickSingle_ = mnuMIN_,
mnuTickMultiple_,
mnuSetRotation_,
mnuResetTrip_,
mnuSetDiameter_,
mnuExeScript_,
mnuQuit_,
mnuMAX_ = mnuQuit_
};
// Macro expansions for functions to get values from the user
//
GET_FUNC(getDiameter, double, "tire diameter (inches)" )
GET_FUNC(getRotations, int, "tire rotations per second" )
GET_FUNC(getNumSeconds, int, "number of seconds" )
// Constants for time versions
//
#define SECS_PER_HOUR 3600
#define SECS_PER_MIN 60
// Function to take a large amount of seconds (eg. elapse time) and split it into
// its hours, minutes, and seconds components.
//
static void splitTime( long totalSeconds, long &hours, long &minutes, long &seconds )
{
hours = totalSeconds / SECS_PER_HOUR;
minutes = totalSeconds % SECS_PER_HOUR / SECS_PER_MIN;
seconds = totalSeconds % SECS_PER_HOUR % SECS_PER_MIN;
}
// Function to take a large amount of seconds (eg. elapse time) and display it
// as hours::minutes::seconds.
//
static void showTime( long totalSeconds )
{
long hours;
long minutes;
long seconds;
splitTime( totalSeconds, hours, minutes, seconds );
cout.fill('0');
cout << setw(2) << hours << ':'
<< setw(2) << minutes << ':'
<< setw(2) << seconds;
}
// Function to trucate a real number (value) to a specified
// number of places past the decimal (digits).
//
static double truncate( double value, int digits )
{
return int(value * pow(10.0, digits) ) / pow(10.0, digits);
}
// Function to display the menu and prompt the user for a menu choice.
// The user is re-prompted until a valid menu choice is entered.
// A valid menu choice number is returned.
//
static MenuOption getChoice(int numRotationsPerSecond)
{
// Display the menu
//
cout << endl
<< "Menu" << endl
<< "----" << endl
<< " 1. Tick second (single)" << endl
<< " 2. Tick second (multiple)" << endl
<< " 3. Set rotations per sec (current: " << numRotationsPerSecond << ')' << endl
<< " 4. Reset trip" << endl
<< " 5. Change diameter (causes a trip reset)" << endl
<< " 6. Execute script" << endl
<< " 7. Quit" << endl;
// Prompt until a value menu choice is entered
//
int choice;
while(true)
{
cout << "Choice: ";
cin >> choice;
if (choice >= mnuMIN_ && choice <= mnuMAX_ ) break;
cout << "*** Invalid entry!" << endl << endl;
}
return MenuOption(choice);
}
// Display the current state of the cycle computer
//
static void showState( CycleComputer *ccp, double diameter )
{
BREAK_STR;
// Display tire diameter
//
cout << " Tire diameter: "
<< truncate( diameter , 2 )
<< " inches"
<< endl;
// Display elapsed time
//
cout << " Elapsed time: ";
showTime( ccp->elapsedTime() );
// Display trip time
//
cout << endl
<< " Trip time: ";
showTime( ccp->tripTime() );
// Display velocity
//
cout << endl
<< " Distance: "
<< truncate( ccp->distanceTraveled(), 2 )
<< " miles"
<< endl;
// Display current velocity
//
cout << " Current velocity: "
<< truncate( ccp->velocity( CycleComputer::current_ ), 2 )
<< " mph"
<< endl;
// Display average velocity
//
cout << " Average velocity: "
<< truncate( ccp->velocity( CycleComputer::average_ ), 2 )
<< " mph"
<< endl;
// Display maximum velocity
//
cout << " Maximum velocity: "
<< truncate( ccp->velocity( CycleComputer::maximum_ ), 2 )
<< " mph"
<< endl;
}
| |