diff --git a/InvalidResult.ts b/InvalidResult.ts new file mode 100644 index 0000000..62f626d --- /dev/null +++ b/InvalidResult.ts @@ -0,0 +1,33 @@ +//typescriptClasses/InvalidResult.ts +//Matthew Ellison +// Created: 10-18-20 +//Modified: 10-18-20 +//This file contains a class that is used to time the execution time of other programs +/* +Copyright (C) 2020 Matthew Ellison + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + + +export class InvalidResult{ + private message: string; + public constructor(message: string){ + this.message = message; + + } + public getMessage(): string{ + return this.message; + } +} diff --git a/Stopwatch.ts b/Stopwatch.ts new file mode 100644 index 0000000..967af2c --- /dev/null +++ b/Stopwatch.ts @@ -0,0 +1,143 @@ +//typescriptClasses/Stopwatch.ts +//Matthew Ellison +// Created: 10-18-20 +//Modified: 10-18-20 +//This file contains a class that is used to time the execution time of other programs +/* +Copyright (C) 2020 Matthew Ellison + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + + +import {InvalidResult} from "./InvalidResult"; +import {performance} from "perf_hooks"; + + +//An enum that helps keep track of how many times the time has been reduced in the getStr function +enum TIME_RESOLUTION{ NANOSECOND, MICROSECOND, MILLISECOND, SECOND, MINUTE, HOUR, ERROR }; + +export class Stopwatch{ + private startTime: number; + private stopTime: number; + //Constructor makes sure all values are set to defaults + public constructor(){ + //Make sure both values are null so it is easier to detect incorrect function calling order + this.startTime = null; + this.stopTime = null; + } + //Returns a long with the elapsed time in milliseconds. Used by other functions to get the time before converting it to the correct resolution + private getTime(): number{ + if(this.startTime == null){ + return 0; + } + else if(this.stopTime == null){ + return performance.now() - this.startTime; + } + else{ + return this.stopTime - this.startTime; + } + } + //Simultates starting a stopwatch by saving the time + public start(): void{ + //Make sure the stop time is reset + this.stopTime = null; + //Get the time as close to returning from the function as possible + this.startTime = performance.now(); + } + //Simulates stopping a stopwatch by saving the time + public stop(): void{ + //Set the stopTime as close to call time as possible + this.stopTime = performance.now(); + //If the startTime has not been set then reset stopTime + if(this.startTime == null){ + this.stopTime = null; + } + } + //Resets all variables in the stopwatch + public reset(): void{ + //Make sure all variables are reset correctly + this.startTime = null; + this.stopTime = null; + } + //Returns the time in nanoseconds + public getNano(): number{ + return this.getTime() * 1000000; + } + //Returns the time in microseconds + public getMicro(): number{ + return this.getTime() * 1000; + } + //Returns the time in milliseconds + public getMilli(): number{ + return this.getTime(); + } + //Returns the time in seconds + public getSecond(): number{ + return this.getTime() / 1000; + } + //Returns the time in minutes + public getMinute(): number{ + return this.getTime() / 60000; + } + //Returns the time in hours + public getHour(): number{ + return this.getTime() / 3600000; + } + //Returns the time as a string at the 'best' resolution. (Goal is xxx.xxx) + public getStr(): string{ + //Get the current duraction from time + return Stopwatch.getStr(this.getNano()); + } + + public static getStr(nanoseconds: number): string{ + let duration: number = nanoseconds; + //Reduce the num,ber to the appropriate number of digits. (xxx.x). + //This loop works down to seconds + let resolution: TIME_RESOLUTION; + for(resolution = TIME_RESOLUTION.NANOSECOND;(resolution < TIME_RESOLUTION.SECOND) && (duration >= 1000);++resolution){ + duration /= 1000; + } + //Check if the duration needs reduced to minutes + if((duration >= 120) && (resolution == TIME_RESOLUTION.SECOND)){ + //Reduce to minutes + duration /= 60; + ++resolution; + + //Check if the duration needs reduced to hours + if(duration >= 60){ + //Reduce to hours + duration /= 60; + ++resolution; + } + } + + //Turn the number into a string + let time: string = duration.toFixed(3); + + //Tack on the appropriate suffix for resolution + switch(resolution){ + case TIME_RESOLUTION.NANOSECOND: time += " nanoseconds"; break; + case TIME_RESOLUTION.MICROSECOND: time += " microseconds"; break; + case TIME_RESOLUTION.MILLISECOND: time += " milliseconds"; break; + case TIME_RESOLUTION.SECOND: time += " seconds"; break; + case TIME_RESOLUTION.MINUTE: time += " minutes"; break; + case TIME_RESOLUTION.HOUR: time += " hours"; break; + case TIME_RESOLUTION.ERROR: + default: throw new InvalidResult("timeResolution was invalid"); + } + //Return the string + return time; + } +} diff --git a/TestStopwatch.ts b/TestStopwatch.ts new file mode 100644 index 0000000..f138c17 --- /dev/null +++ b/TestStopwatch.ts @@ -0,0 +1,99 @@ +//typescriptClasses/TestStopwatch.ts +//Matthew Ellison +// Created: 10-18-20 +//Modified: 10-18-20 +//This file contains a class that is used to time the execution time of other programs +/* +Copyright (C) 2020 Matthew Ellison + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + + +import assert = require("assert"); +import {Stopwatch} from "./Stopwatch"; + + +let NUM_TO_RUN = 100000; + +function testStartStop(): void{ + let timer: Stopwatch = new Stopwatch(); + timer.start(); + timer.stop(); + //If it gets to here without throwing an exception everything went well + console.log("start/stop passed"); +} +function testConversion(): void{ + let timer: Stopwatch = new Stopwatch(); + let sum: number = 0; + //Start the timer + timer.start(); + //Do something to run some time + for(let cnt: number = 0;cnt < NUM_TO_RUN;++cnt){ + sum += cnt; + } + //Stop the timer + timer.stop(); + //Assert something so the sum isn't ignored during compile + assert.notStrictEqual(sum, 0, "You really messed up"); + //Check that the different resolutions work out correctly + let nano: number = timer.getNano(); + assert.strictEqual(timer.getMicro(), nano / 1000, "Micro resolution test failed"); + assert.strictEqual(timer.getMilli(), nano / 1000000, "Milli resolution test failed"); + assert.strictEqual(timer.getSecond(), nano / 1000000000, "Minute resolution test failed"); + assert.strictEqual(timer.getMinute(), nano / 60000000000, "Minute resolution test failed"); + assert.strictEqual(timer.getHour(), nano / 3600000000000, "Hour resolution test failed"); + console.log("conversion passed"); +} +function testStringConversion(): void{ + //Test nanoseconds + let results: string = Stopwatch.getStr(1.0); + assert.strictEqual(results, "1.000 nanoseconds", "String conversion to nanoseconds failed"); + //Test microseconds + results = Stopwatch.getStr(1.0e3); + assert.strictEqual(results, "1.000 microseconds", "String conversion to microseconds failed"); + //Test milliseconds + results = Stopwatch.getStr(1.0e6); + assert.strictEqual(results, "1.000 milliseconds", "String conversion to milliseconds failed"); + //Test seconds + results = Stopwatch.getStr(1.0e9); + assert.strictEqual(results, "1.000 seconds", "String conversion to seconds failed"); + //Test mintues + results = Stopwatch.getStr(1.0e12); + assert.strictEqual(results, "16.667 minutes", "String conversion to minutes failed"); + //Rest hours + results = Stopwatch.getStr(1.0e13); + assert.strictEqual(results, "2.778 hours", "String conversion to hours failed"); + console.log("string conversion passed"); +} + +//Run the functions +try{ + testStartStop(); +} +catch(error){ + console.error("start/stop test failed!"); +} +try{ + testConversion(); +} +catch(error){ + console.error("conversion test failed!"); +} +try{ + testStringConversion(); +} +catch(error){ + console.error("string conversion test failed!"); +}