UNPKG

@toreda/time

Version:

Simple, small footprint library for common time operations and converting between units of time.

206 lines (205 loc) 7.35 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TimerActive = void 0; const strong_types_1 = require("@toreda/strong-types"); const defaults_1 = require("../defaults"); const group_1 = require("./callback/group"); const make_1 = require("../time/make"); const now_1 = require("../time/now"); /** * Active timer with internal timing clock. Takes a callback to invoke * every timer trigger. * * @category Timers */ class TimerActive { constructor(options) { this.lastIntervalEnd = (0, strong_types_1.floatMake)(0); this.running = (0, strong_types_1.boolMake)(false); this._handlersBound = (0, strong_types_1.boolMake)(false); const limitDuration = typeof (options === null || options === void 0 ? void 0 : options.limitDuration) === 'boolean' ? options === null || options === void 0 ? void 0 : options.limitDuration : false; this.limitDuration = (0, strong_types_1.boolMake)(limitDuration); this._checkIntervalMs = (0, make_1.timeMake)('ms', defaults_1.Defaults.Timer.CheckIntervalMs); this.timeStart = (0, make_1.timeMake)('s', 0); this.timeStop = (0, make_1.timeMake)('s', 0); const timeLimit = typeof (options === null || options === void 0 ? void 0 : options.timeLimit) === 'number' ? options === null || options === void 0 ? void 0 : options.timeLimit : 0; this.timeLimit = (0, make_1.timeMake)('s', timeLimit); this.paused = (0, strong_types_1.boolMake)(false); this.listeners = { start: new group_1.TimerCallbackGroup('start'), stop: new group_1.TimerCallbackGroup('stop'), pause: new group_1.TimerCallbackGroup('pause'), unpause: new group_1.TimerCallbackGroup('unpause'), done: new group_1.TimerCallbackGroup('done'), restart: new group_1.TimerCallbackGroup('restart'), reset: new group_1.TimerCallbackGroup('reset') }; } getListenerGroup(id) { if (typeof id !== 'string') { return null; } const group = this.listeners[id]; if (!group) { return null; } return group; } on(id, fn) { if (typeof fn !== 'function') { return false; } const group = this.getListenerGroup(id); if (!group) { return false; } group._always().push(fn); return true; } once(id, fn) { if (typeof fn !== 'function') { return false; } const group = this.getListenerGroup(id); if (!group) { return false; } group._once().push(fn); return true; } setTimeLimit(value) { if (value === undefined || value === null) { return false; } if (typeof value === 'number') { this.timeLimit.set(value); return true; } if (value.type === 'Time') { this.timeLimit.set(value.asSeconds()); return true; } return false; } bindHandlers() { if (this._handlersBound()) { return; } // Mark handlers as bound. this._handlersBound(true); this.start = this.start.bind(this); this.stop = this.stop.bind(this); this.reset = this.reset.bind(this); this.onUpdate = this.onUpdate.bind(this); } unpause() { return __awaiter(this, void 0, void 0, function* () { if (!this.running() || !this.paused()) { return false; } yield this.executeCallbacks('unpause'); this.paused(false); return true; }); } pause() { return __awaiter(this, void 0, void 0, function* () { if (!this.running() || this.paused()) { return false; } yield this.executeCallbacks('pause'); return this.paused(true); }); } /** * Start the timer. * @returns */ start() { return __awaiter(this, void 0, void 0, function* () { // Timer is already running. if (this.running()) { return false; } this.bindHandlers(); this.timeStart.setNow(); this._timerHandle = setTimeout(this.onUpdate, defaults_1.Defaults.Timer.CheckIntervalMs); yield this.executeCallbacks('start'); return this.running(true); }); } done() { return __awaiter(this, void 0, void 0, function* () { if (!this.running()) { return false; } yield this.executeCallbacks('done'); return this.stop(); }); } stop() { return __awaiter(this, void 0, void 0, function* () { // Time isn't running. Nothing to stop! if (!this.running()) { return false; } clearInterval(this._timerHandle); this.timeStop.setNow(); const timeSince = this.timeStart.since(this.timeStop()); const value = timeSince ? timeSince() : 0; this.listeners.stop.always(value); this.running(false); return true; }); } executeCallbacks(eventId) { return __awaiter(this, void 0, void 0, function* () { const group = this.listeners[eventId]; if (!group) { return; } const now = (0, now_1.timeNow)(); const timeSince = now.since(now()); const duration = timeSince ? timeSince() : 0; yield group.execute(duration); }); } reset() { this.stop(); this.lastIntervalEnd.reset(); this.listeners.done.reset(); this.listeners.pause.reset(); this.listeners.reset.reset(); this.listeners.restart.reset(); this.listeners.start.reset(); this.listeners.stop.reset(); this.listeners.unpause.reset(); this.running(false); this.paused(false); this.limitDuration.reset(); } onUpdate() { if (!this.running()) { return; } const now = (0, now_1.timeNow)(); // Fixed duration timers should stop when reaching their time limit. if (this.limitDuration()) { const duration = this.timeStart.since(now); if (duration && duration() >= this.timeLimit()) { this.done(); return; } } } } exports.TimerActive = TimerActive;