diff --git a/Dice.hpp b/Dice.hpp index e1f29e8..999d687 100644 --- a/Dice.hpp +++ b/Dice.hpp @@ -29,7 +29,7 @@ #include //Use this for anything besides Linux. It replaces random_device //I know this doesn't work correctly with mingw on Windows, not sure about msbuild or mac so I don't take the chance -#ifndef linux +#ifndef __linux #include #endif //ifndef linux @@ -37,23 +37,24 @@ namespace mee{ +template class Dice{ private: - uint64_t face; //Holds the currently rolled number - uint64_t sides; //Holds the number of sides the dice has + T face; //Holds the currently rolled number + T sides; //Holds the number of sides the dice has std::default_random_engine generator; //The number generator that all the numbers come from - std::uniform_int_distribution dist; //A distribution to make sure the numbers come out relatively evenly + std::uniform_int_distribution dist; //A distribution to make sure the numbers come out relatively evenly public: - #ifdef linux - Dice(uint64_t sides = 6) : face(1), sides(sides), generator(std::random_device{}()), dist(1, sides) { } + #ifdef __linux + Dice(T sides = 6) : face(1), sides(sides), generator(std::random_device{}()), dist(1, sides) { } #else - Dice(uint64_t sides = 6) : face(1), sides(sides), generator(time(0)), dist(1, sides) { } + Dice(T sides = 6) : face(1), sides(sides), generator(time(0)), dist(1, sides) { } #endif //ifdef linux //Setup ways to get information from the class - uint64_t getFace() const { return face; } - uint64_t getSides() const { return sides; } + T getFace() const { return face; } + T getSides() const { return sides; } //Used to simulate rolling the dice. Returns the new number - uint64_t roll() { + T roll() { face = dist(generator); return face; } diff --git a/Stopwatch.hpp b/Stopwatch.hpp index b1b6745..aceb2a8 100644 --- a/Stopwatch.hpp +++ b/Stopwatch.hpp @@ -26,15 +26,22 @@ #include +#include +#include namespace mee{ class Stopwatch{ +public: + //Create an error class + class stopBeforeStart{}; //Used in stop() to check if you are trying to stop the stopwatch before starting it + class timeBeforeStart{}; //Used in getTime() to check if you are trying to get a time before you start it + class invalidTimeResolution{}; //Used to detect invalid time resolution in the getStr function private: std::chrono::high_resolution_clock::time_point startTime; //The time the start function was called std::chrono::high_resolution_clock::time_point endTime; //The time the stop function was called bool hasStarted; //A flag to show that start() has been called bool hasStopped; //A flag to show that stop() has been called - enum TIME_RESOLUTION {HOUR, MINUTE, SECOND, MILLISECOND, MICROSECOND, NANOSECOND, DEFAULT}; + enum TIME_RESOLUTION {NANOSECOND, MICROSECOND, MILLISECOND, SECOND, MINUTE, HOUR, DEFAULT}; //Return the duration in the default time period for the high_resolution_clock double getTime(TIME_RESOLUTION timeResolution){ double timePassed = 0; //Holds the amount of time that has passed @@ -43,9 +50,9 @@ private: if(!hasStopped){ endTime = std::chrono::high_resolution_clock::now(); } - //If the timer hasn't been started return a -1 as an error + //If the timer hasn't been started throw an exception if(!hasStarted){ - return -1; + throw timeBeforeStart(); } //Decide what resolution to make the duration if(timeResolution == HOUR){ @@ -98,11 +105,16 @@ public: //Set the stop time and flag void stop(){ //Put this first to ensure the time recorded is as close to the call time as possible - endTime = std::chrono::high_resolution_clock::now(); + std::chrono::high_resolution_clock::time_point tempTime = std::chrono::high_resolution_clock::now(); //Make sure the stopwatch has started before you say it has stopped if(hasStarted){ + endTime = tempTime; //Set the end time appropriately hasStopped = true; //Show that the stop function has been called } + //If the stopwatch hadn't been started throw an exception + else{ + throw stopBeforeStart(); + } } //Return the duration in nanoseconds double getNano(){ @@ -132,6 +144,37 @@ public: double getTime(){ return getTime(DEFAULT); } + //Returns a string with the time at best resolution + std::string getStr(){ + //Setup the variables + double tempTime = getTime(NANOSECOND); //Holds the + std::stringstream timeStr; + + //Decide what time resolution would be best. Looking for the format of XXX.XXX + int timeRes = NANOSECOND; + for(timeRes = MICROSECOND;(timeRes < DEFAULT) && (tempTime >= 1000);++timeRes){ + tempTime = getTime(static_cast(timeRes)); + } + --timeRes; //Take this variable back down to the right place. It has to go one too far to trigger the loop stop + + //Put the number in the string + timeStr << std::fixed << std::setprecision(3) << tempTime << ' '; + + //From the timeRes variable decide what word should go on the end of the string + switch(timeRes){ + case HOUR: timeStr << "hours"; break; + case MINUTE: timeStr << "minutes"; break; + case SECOND: timeStr << "seconds"; break; + case MILLISECOND: timeStr << "milliseconds"; break; + case MICROSECOND: timeStr << "microseconds"; break; + case NANOSECOND: timeStr << "nanoseconds"; break; + case DEFAULT: timeStr << "time"; break; + default: throw invalidTimeResolution(); //This should never be hit with this code, but it's good to have all the bases covered + } + + //Return the string + return timeStr.str(); + } //This function resets all the variables so that it can be run again void reset(){ hasStarted = hasStopped = false; //Set the flags as though nothing has happened diff --git a/testDice.cpp b/testDice.cpp index 15fd2d2..1bf794e 100644 --- a/testDice.cpp +++ b/testDice.cpp @@ -22,6 +22,7 @@ #include #include +#include #include "Dice.hpp" const int LENGTH_OF_TEST = 100; //How many times the dice will get rolled * the number of sides @@ -30,7 +31,7 @@ const int LENGTH_OF_TEST = 100; //How many times the dice will get rolled * the int main(){ //Check the default constructor std::cout << "Checking the default constructor of the Dice class:\n"; - mee::Dice die1; + mee::Dice die1; if(die1.getSides() == 6){ std::cout << "Default constructor passes the test\n"; } @@ -40,7 +41,7 @@ int main(){ //Check the constructor with a high side number std::cout << "\nChecking a constructor with a high number of sides\n"; - mee::Dice die2(50); + mee::Dice die2(50); if(die2.getSides() == 50){ std::cout << "Parameterized constructor passed the test\n"; } diff --git a/testStopwatch.cpp b/testStopwatch.cpp new file mode 100644 index 0000000..20f2e25 --- /dev/null +++ b/testStopwatch.cpp @@ -0,0 +1,88 @@ +//myClasses/testStopwatch.cpp +//Matthew Ellison +// Created: 02-12-19 +//Modified: 02-12-19 +//This file is a simple test for the Stopwatch class + + +#include +#include "Stopwatch.hpp" + +int main(){ + mee::Stopwatch timer; + //Try to stop the timer without starting it + std::cout << "Testing the stopBeforeStart error" << std::endl; + try{ + timer.stop(); + std::cout << "Test failed" << std::endl; + } + catch(mee::Stopwatch::invalidTimeResolution){ + std::cout << "There was an invalid time resolution" << std::endl; + std::cout << "Test failed" << std::endl; + } + catch(mee::Stopwatch::timeBeforeStart){ + std::cout << "Tried to get time before the stopwatch was started" << std::endl; + std::cout << "Test failed" << std::endl; + } + catch(mee::Stopwatch::stopBeforeStart){ + std::cout << "Tried to stop the stopwatch before it was started" << std::endl; + std::cout << "Test successful" << std::endl; + } + + //Try to get the time on it without starting it + std::cout << "Testing the timeBeforeStart error" << std::endl; + try{ + std::cout << timer.getStr() << std::endl; + std::cout << "Test failed" << std::endl; + } + catch(mee::Stopwatch::invalidTimeResolution){ + std::cout << "There was an invalid time resolution" << std::endl; + std::cout << "Test failed" << std::endl; + } + catch(mee::Stopwatch::timeBeforeStart){ + std::cout << "Tried to get time before the stopwatch was started" << std::endl; + std::cout << "Test successful" << std::endl; + } + catch(mee::Stopwatch::stopBeforeStart){ + std::cout << "Tried to stop the stopwatch before it was started" << std::endl; + std::cout << "Test failed" << std::endl; + } + + //Use it correctly + std::cout << "Using the class correctly" << std::endl; + try{ + timer.start(); + for(int cnt = 0;cnt < 1000000;++cnt){ + int num = cnt; + } + timer.stop(); + std::cout << "It took " << timer.getStr() << " to complete this loop" << std::endl; + std::cout << "Test successful" << std::endl; + } + catch(mee::Stopwatch::invalidTimeResolution){ + std::cout << "There was an invalid time resolution" << std::endl; + std::cout << "Test failed" << std::endl; + } + catch(mee::Stopwatch::timeBeforeStart){ + std::cout << "Tried to get time before the stopwatch was started" << std::endl; + std::cout << "Test failed" << std::endl; + } + catch(mee::Stopwatch::stopBeforeStart){ + std::cout << "Tried to stop the stopwatch before it was started" << std::endl; + std::cout << "Test failed" << std::endl; + } + + return 0; +} + +/* Results: +Testing the stopBeforeStart error +Tried to stop the stopwatch before it was started +Test successful +Testing the timeBeforeStart error +Tried to get time before the stopwatch was started +Test successful +Using the class correctly +It took 1.855 milliseconds to complete this loop +Test successful +*/