@slime/stopwatch
Advanced tools
Sorry, the diff of this file is not supported yet
+19
| <!DOCTYPE html> | ||
| <html xmlns="http://www.w3.org/1999/xhtml"> | ||
| <head> | ||
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> | ||
| <link rel="stylesheet" type="text/css" | ||
| href="style.css"/> | ||
| </head> | ||
| <body> | ||
| <h1 id="stop-watch" style="font-family:'Digit';font-weight:normal;font-size:20px">00:00:00</h1> | ||
| <button id="start"> start </button> | ||
| <button id="stop"> stop </button> | ||
| <button id="reset"> reset </button> | ||
| <script src="./index.js"></script> | ||
| </body> | ||
| </html> |
+92
| class StopWatch{ | ||
| constructor() { | ||
| this.prevTimeElapsed = 0; | ||
| this.start = null; | ||
| this.resume = false; | ||
| } | ||
| startTimer(){ | ||
| if(this.start == null || this.resume){ | ||
| this.start = Date.now(); | ||
| this.resume = false; | ||
| } | ||
| } | ||
| stopTimer(){ | ||
| if(this.resume == false){ | ||
| this.resume = true; | ||
| this.prevTimeElapsed = this.prevTimeElapsed + (Date.now() - this.start); | ||
| } | ||
| } | ||
| reset(){ | ||
| this.start = null; | ||
| this.prevTimeElapsed = 0; | ||
| } | ||
| get getTimeElapsedInMs(){ | ||
| if(this.start == null){ // if stopwatch hasn't started yet or is reset | ||
| return 0; | ||
| }else if(this.resume){ // if stop watch is currently stopped | ||
| return this.prevTimeElapsed; | ||
| }else{ // get time whilst stopwatch is not stopped | ||
| return this.prevTimeElapsed + (Date.now() - this.start); | ||
| } | ||
| } | ||
| get getSecondsElapsedIn60Seconds(){ | ||
| return Math.floor(this.getTimeElapsedInMs / 1000 % 60); | ||
| } | ||
| get getTimeElapsedInMinutes(){ | ||
| return Math.floor(this.getTimeElapsedInMs / 1000 / 60); | ||
| } | ||
| get getCurrentMillaSecondElapsedAsFraction(){ | ||
| return this.getTimeElapsedInMs % 1000 / 1000; | ||
| } | ||
| get getTimeElapsedInStopWatchFormatString(){ | ||
| // console.log("mins"); | ||
| // console.log(this.getTimeElapsedInMinutes); | ||
| let minsNumberAsString = String(this.getTimeElapsedInMinutes); | ||
| let minsAs2Digits = minsNumberAsString.length > 1 ? minsNumberAsString : "0" + minsNumberAsString; | ||
| let secondsNumberAsString = String(this.getSecondsElapsedIn60Seconds); | ||
| let secondsAs2Digits = secondsNumberAsString.length > 1 ? secondsNumberAsString : "0" + secondsNumberAsString; | ||
| let millaSecondAs2DigitNumberAsString = "0" + String(Math.floor(this.getCurrentMillaSecondElapsedAsFraction * 10)); | ||
| return `${minsAs2Digits}:${secondsAs2Digits}:${millaSecondAs2DigitNumberAsString}`; | ||
| } | ||
| } | ||
| let stopWatch = new StopWatch(); | ||
| let digitsH1 = document.getElementById("stop-watch"); | ||
| let startBtn = document.getElementById("start"); | ||
| let stopBtn = document.getElementById("stop"); | ||
| let resetBtn = document.getElementById("reset"); | ||
| function loop(){ | ||
| digitsH1.innerHTML = stopWatch.getTimeElapsedInStopWatchFormatString; | ||
| window.requestAnimationFrame(loop); | ||
| } | ||
| window.requestAnimationFrame(loop); | ||
| startBtn.addEventListener("click", () => { | ||
| stopWatch.startTimer(); | ||
| }); | ||
| stopBtn.addEventListener("click", () => { | ||
| stopWatch.stopTimer(); | ||
| }); | ||
| resetBtn.addEventListener("click", () => { | ||
| stopWatch.reset(); | ||
| }); | ||
| /* #### Generated By: http://www.cufonfonts.com #### */ | ||
| @font-face { | ||
| font-family: 'Digit'; | ||
| font-style: normal; | ||
| font-weight: normal; | ||
| src: local('Digit'), url('Digit.woff') format('woff'); | ||
| } |
+59
-48
@@ -1,64 +0,75 @@ | ||
| class StopWatch{ | ||
| constructor() { | ||
| this.prevTimeElapsed = 0; | ||
| this.start = null; | ||
| this.resume = false; | ||
| } | ||
| class StopWatch { | ||
| constructor() { | ||
| this.prevTimeElapsed = 0; | ||
| this.start = null; | ||
| this.resume = false; | ||
| } | ||
| startTimer(){ | ||
| if(this.start == null || this.resume){ | ||
| this.start = Date.now(); | ||
| this.resume = false; | ||
| } | ||
| startTimer() { | ||
| if (this.start == null || this.resume) { | ||
| this.start = Date.now(); | ||
| this.resume = false; | ||
| } | ||
| } | ||
| stopTimer(){ | ||
| if(this.resume == false){ | ||
| this.resume = true; | ||
| this.prevTimeElapsed = this.prevTimeElapsed + (Date.now() - this.start); | ||
| } | ||
| stopTimer() { | ||
| if (this.start && this.resume == false) { | ||
| this.resume = true; | ||
| this.prevTimeElapsed = this.prevTimeElapsed + (Date.now() - this.start); | ||
| } | ||
| } | ||
| reset(){ | ||
| this.start = null; | ||
| this.prevTimeElapsed = 0; | ||
| } | ||
| reset() { | ||
| this.start = null; | ||
| this.prevTimeElapsed = 0; | ||
| } | ||
| get getTimeElapsedInMs(){ | ||
| if(this.start == null){ // if stopwatch hasn't started yet or is reset | ||
| return 0; | ||
| }else if(this.resume){ // if stop watch is currently stopped | ||
| return this.prevTimeElapsed; | ||
| }else{ // get time whilst stopwatch is not stopped | ||
| return this.prevTimeElapsed + (Date.now() - this.start); | ||
| } | ||
| get getTimeElapsedInMs() { | ||
| if (this.start == null) { | ||
| // if stopwatch hasn't started yet or is reset | ||
| return 0; | ||
| } else if (this.resume) { | ||
| // if stop watch is currently stopped | ||
| return this.prevTimeElapsed; | ||
| } else { | ||
| // get time whilst stopwatch is not stopped | ||
| return this.prevTimeElapsed + (Date.now() - this.start); | ||
| } | ||
| } | ||
| get getSecondsElapsedIn60Seconds(){ | ||
| return Math.floor(this.getTimeElapsedInMs / 1000 % 60); | ||
| } | ||
| get getSecondsElapsedIn60Seconds() { | ||
| return Math.floor((this.getTimeElapsedInMs / 1000) % 60); | ||
| } | ||
| get getTimeElapsedInMinutes(){ | ||
| return Math.floor(this.getTimeElapsedInMs / 1000 / 60); | ||
| } | ||
| get getTimeElapsedInMinutes() { | ||
| return Math.floor(this.getTimeElapsedInMs / 1000 / 60); | ||
| } | ||
| get getCurrentMillaSecondElapsedAsFraction(){ | ||
| return this.getTimeElapsedInMs % 1000 / 1000; | ||
| } | ||
| get getCurrentMillaSecondElapsedAsFraction() { | ||
| return (this.getTimeElapsedInMs % 1000) / 1000; | ||
| } | ||
| get getTimeElapsedInStopWatchFormatString(){ | ||
| // console.log("mins"); | ||
| // console.log(this.getTimeElapsedInMinutes); | ||
| let minsNumberAsString = String(this.getTimeElapsedInMinutes); | ||
| let minsAs2Digits = minsNumberAsString.length > 1 ? minsNumberAsString : "0" + minsNumberAsString; | ||
| get getTimeElapsedInStopWatchFormatString() { | ||
| // console.log("mins"); | ||
| // console.log(this.getTimeElapsedInMinutes); | ||
| let minsNumberAsString = String(this.getTimeElapsedInMinutes); | ||
| let minsAs2Digits = | ||
| minsNumberAsString.length > 1 | ||
| ? minsNumberAsString | ||
| : "0" + minsNumberAsString; | ||
| let secondsNumberAsString = String(this.getSecondsElapsedIn60Seconds); | ||
| let secondsAs2Digits = secondsNumberAsString.length > 1 ? secondsNumberAsString : "0" + secondsNumberAsString; | ||
| let secondsNumberAsString = String(this.getSecondsElapsedIn60Seconds); | ||
| let secondsAs2Digits = | ||
| secondsNumberAsString.length > 1 | ||
| ? secondsNumberAsString | ||
| : "0" + secondsNumberAsString; | ||
| let millaSecondAs2DigitNumberAsString = "0" + String(Math.floor(this.getCurrentMillaSecondElapsedAsFraction * 10)); | ||
| let millaSecondAs2DigitNumberAsString = | ||
| "0" + | ||
| String(Math.floor(this.getCurrentMillaSecondElapsedAsFraction * 10)); | ||
| return `${minsAs2Digits}:${secondsAs2Digits}:${millaSecondAs2DigitNumberAsString}`; | ||
| } | ||
| return `${minsAs2Digits}:${secondsAs2Digits}:${millaSecondAs2DigitNumberAsString}`; | ||
| } | ||
| } | ||
| module.exports = StopWatch; | ||
| module.exports = StopWatch; |
+2
-2
| { | ||
| "name": "@slime/stopwatch", | ||
| "version": "1.2.2", | ||
| "description": "a class for handling and printing elapsed time in ms, under the hood is just comparing timestamps with Date.now().", | ||
| "version": "1.3.0", | ||
| "description": "a stopwatch class utility for starting, pausing, resetting and getting elapsed time in milliseconds (ms), under the hood is just comparing timestamps with Date.now().", | ||
| "main": "dist/index.js", | ||
@@ -6,0 +6,0 @@ "types": "dist/types/index.d.ts", |
+17
-15
| # StopWatch | ||
|  | ||
|  | ||
| simple class utility for tracking amount of time elapsed in milliseconds (ms). | ||
| simple class utility for tracking amount of time elapsed in milliseconds (ms), by comparing time stamps | ||
| version 1.1.0: added typescript type definitions for StopWatch class | ||
| version 1.3.0: fixed bug where when initially calling .stopTimer() before subsequent calls to .startTimer() when the StopWatch object is first instantiated, it will cause the incorrect time elapsed to be returned | ||
| - version 1.1.0: added typescript type definitions for StopWatch class | ||
| - version 1.2.1: fixed bug where when stop, and resume again, the logic to calculate new time elapsed (while taking into account previous time elapsed) was wrong | ||
| ## how to use StopWatch class via NPM/node.js | ||
| ## how to use StopWatch class via NPM/node.js | ||
| installation from terminal/CMD line | ||
| ``` | ||
| npm i @slime/stopwatch | ||
| ``` | ||
| usage: | ||
| first instantiate a new StopWatch object instance from the StopWatch class | ||
| ``` | ||
| const StopWatch = require("@slime/stopwatch"); | ||
| let stopWatch = new StopWatch(); | ||
| const StopWatch = require("@slime/stopwatch"); | ||
| let stopWatch = new StopWatch(); | ||
| ``` | ||
@@ -26,3 +27,3 @@ | ||
| ``` | ||
| stopWatch.startTimer(); | ||
| stopWatch.startTimer(); | ||
| stopWatch.stopTimer(); | ||
@@ -41,8 +42,10 @@ stopWatch.startTimer(); | ||
| ## demo usage | ||
| start timer and show time elapsed after 1.5 seconds | ||
| ``` | ||
| const StopWatch = require("@slime/stopwatch"); | ||
| let stopWatch = new StopWatch(); | ||
| const StopWatch = require("@slime/stopwatch"); | ||
| let stopWatch = new StopWatch(); | ||
| console.log(stopWatch.getTimeElapsedInMs); | ||
| console.log(stopWatch.getTimeElapsedInStopWatchFormatString); | ||
| console.log(stopWatch.getTimeElapsedInStopWatchFormatString); | ||
| stopWatch.startTimer(); | ||
@@ -52,5 +55,4 @@ setTimeout(()=>{ | ||
| console.log(stopWatch.getTimeElapsedInMs); | ||
| console.log(stopWatch.getTimeElapsedInStopWatchFormatString); | ||
| }, 1500); | ||
| console.log(stopWatch.getTimeElapsedInStopWatchFormatString); | ||
| }, 1500); | ||
| ``` | ||
+77
-61
@@ -1,5 +0,4 @@ | ||
| // hello world test | ||
| test('adds 1 + 2 to equal 3', () => { | ||
| expect(1 + 2).toBe(3); | ||
| test("adds 1 + 2 to equal 3", () => { | ||
| expect(1 + 2).toBe(3); | ||
| }); | ||
@@ -10,71 +9,88 @@ | ||
| test('on object initialisation time elapsed in ms(millaseconds) to be equal to 0', () => { | ||
| const sw = new StopWatch(); | ||
| expect(sw.getTimeElapsedInMs).toBe(0); | ||
| test("on object initialisation time elapsed in ms(millaseconds) to be equal to 0", () => { | ||
| const sw = new StopWatch(); | ||
| expect(sw.getTimeElapsedInMs).toBe(0); | ||
| }); | ||
| test('on object initialisation before starting timer, stop watch format string to be \ | ||
| equal to 00:00:00 and to be same after calling reset()', () => { | ||
| const sw = new StopWatch(); | ||
| expect(sw.getTimeElapsedInStopWatchFormatString).toBe("00:00:00"); | ||
| sw.reset(); | ||
| expect(sw.getTimeElapsedInStopWatchFormatString).toBe("00:00:00"); | ||
| test("on object initialisation when calling .stopTimer() before .startTimer(), subsequent checks/gets of time elapsed after then \ | ||
| calling .startTimer() work as expected", () => { | ||
| const sw = new StopWatch(); | ||
| sw.stopTimer(); | ||
| sw.startTimer(); | ||
| expect(sw.getTimeElapsedInMs).toBeLessThanOrEqual(10); | ||
| }); | ||
| test('on timer start, after 1 second elapsed result to be equal or greater than 1000ms', done => { | ||
| const tollerenceInMs = 10; | ||
| const oneSecondInMs = 1000; | ||
| const sw = new StopWatch(); | ||
| sw.startTimer(); | ||
| setTimeout(() => { | ||
| sw.stopTimer(); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, oneSecondInMs, tollerenceInMs); | ||
| done(); | ||
| },oneSecondInMs); | ||
| test("on object initialisation before starting timer, stop watch format string to be \ | ||
| equal to 00:00:00 and to be same after calling reset()", () => { | ||
| const sw = new StopWatch(); | ||
| expect(sw.getTimeElapsedInStopWatchFormatString).toBe("00:00:00"); | ||
| sw.reset(); | ||
| expect(sw.getTimeElapsedInStopWatchFormatString).toBe("00:00:00"); | ||
| }); | ||
| test('start, stop, resume, reset, start: stopwatch timer', async () => { | ||
| jest.setTimeout(15000); | ||
| // will need to use await sleep()'s | ||
| const tollerenceInMs = 10; | ||
| const sw = new StopWatch(); | ||
| sw.startTimer(); | ||
| await sleep(970); | ||
| test("on timer start, after 1 second elapsed result to be equal or greater than 1000ms", (done) => { | ||
| const tollerenceInMs = 10; | ||
| const oneSecondInMs = 1000; | ||
| const sw = new StopWatch(); | ||
| sw.startTimer(); | ||
| setTimeout(() => { | ||
| sw.stopTimer(); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 970, tollerenceInMs); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed( | ||
| sw, | ||
| oneSecondInMs, | ||
| tollerenceInMs | ||
| ); | ||
| done(); | ||
| }, oneSecondInMs); | ||
| }); | ||
| sw.startTimer(); | ||
| await sleep(30); | ||
| sw.stopTimer(); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 1000, tollerenceInMs); | ||
| test("start, stop, resume, reset, start: stopwatch timer", async () => { | ||
| jest.setTimeout(15000); | ||
| await sleep(1000); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 1000, tollerenceInMs); | ||
| sw.startTimer(); | ||
| await sleep(1000); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 2000, tollerenceInMs); | ||
| await sleep(2000); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 4000, tollerenceInMs); | ||
| sw.stopTimer(); | ||
| await sleep(1000); | ||
| sw.stopTimer(); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 4000, tollerenceInMs); | ||
| sw.startTimer(); | ||
| await sleep(1000); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 5000, tollerenceInMs); | ||
| sw.reset(); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 0, tollerenceInMs); | ||
| sw.startTimer(); | ||
| await sleep(1000); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 1000, tollerenceInMs); | ||
| // will need to use await sleep()'s | ||
| const tollerenceInMs = 15; | ||
| const sw = new StopWatch(); | ||
| sw.startTimer(); | ||
| await sleep(970); | ||
| sw.stopTimer(); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 970, tollerenceInMs); | ||
| sw.startTimer(); | ||
| await sleep(30); | ||
| sw.stopTimer(); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 1000, tollerenceInMs); | ||
| await sleep(1000); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 1000, tollerenceInMs); | ||
| sw.startTimer(); | ||
| await sleep(1000); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 2000, tollerenceInMs); | ||
| await sleep(2000); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 4000, tollerenceInMs); | ||
| sw.stopTimer(); | ||
| await sleep(1000); | ||
| sw.stopTimer(); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 4000, tollerenceInMs); | ||
| sw.startTimer(); | ||
| await sleep(1000); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 5000, tollerenceInMs); | ||
| sw.reset(); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 0, tollerenceInMs); | ||
| sw.startTimer(); | ||
| await sleep(1000); | ||
| testTimerDisplaysCorrectTimeAfterMsElapsed(sw, 1000, tollerenceInMs); | ||
| }); | ||
| function testTimerDisplaysCorrectTimeAfterMsElapsed(stopWatchObject, ms, msTollerence){ | ||
| const re = new RegExp(`00:0${Math.floor(ms / 1000)}:0[0-9]`); | ||
| expect(stopWatchObject.getTimeElapsedInMs).toBeGreaterThanOrEqual(ms); | ||
| expect(stopWatchObject.getTimeElapsedInMs).toBeLessThanOrEqual(ms + msTollerence); | ||
| expect(stopWatchObject.getTimeElapsedInStopWatchFormatString).toMatch(re); | ||
| function testTimerDisplaysCorrectTimeAfterMsElapsed( | ||
| stopWatchObject, | ||
| ms, | ||
| msTollerence | ||
| ) { | ||
| const re = new RegExp(`00:0${Math.floor(ms / 1000)}:0[0-9]`); | ||
| expect(stopWatchObject.getTimeElapsedInMs).toBeGreaterThanOrEqual(ms); | ||
| expect(stopWatchObject.getTimeElapsedInMs).toBeLessThanOrEqual( | ||
| ms + msTollerence | ||
| ); | ||
| expect(stopWatchObject.getTimeElapsedInStopWatchFormatString).toMatch(re); | ||
| } | ||
26987
36.45%14
40%365
40.38%56
3.7%