const EventEmitter = require("events"); const createDriver = require("../drivers"); class Workout { /** * @param {import("../repositories/sqlite3")} repo * @param {number} id * @param {{ * id: string, * name: string, * driver: string, * connect: string, * maxLevel: number, * }} bike * @param {{ * id: number, * name: string, * cpm: number, * warmupMin: number, * warmupCpm: number, * }} program * @param {Date} date */ constructor(repo, id, bike, program, date) { this.repo = repo; this.id = id; this.bike = bike; this.program = program; this.date = date; this.driver = null; this.offsetSeconds = 0; this.offsets = {}; this.events = new EventEmitter(); } async connect() { this.driver = createDriver(this.bike.driver, this.bike.connect); this.driver.events.on("workoutStatus", ws => this.handleworkoutStatus(ws)); return this.driver.connect(); } start() { return this.driver.start(); } pause() { return this.driver.pause(); } stop() { return this.driver.stop(); } destroy() { this.events.emit("destroy"); this.events.removeAllListeners(); if (this.driver != null) { this.driver.destroy(); this.driver = null; } } listMeasurements() { return this.repo.listMeasurements(this.id); } handleworkoutStatus(ws) { if (this.offsetSeconds > 0) { const seconds = (ws.minutes * 60) + ws.seconds + this.offsetSeconds; ws.minutes = Math.floor(seconds / 60); ws.seconds = seconds % 60; for (const key in this.offsets) { if (!this.offsets.hasOwnProperty(key)) { continue; } ws[key] += this.offsets[key]; } } this.repo.insertMeasurement({...ws, workoutId: this.id}); this.events.emit("workoutStatus", {...ws}); } /** * @param {import("../repositories/sqlite3")} repo * @param {number} bikeId * @param {number} programId */ static async create(repo, bikeId, programId) { const bike = await repo.findBike(bikeId); if (bike == null) { throw new Error("bike not found"); } const program = await repo.findProgram(programId); if (program == null) { throw new Error("program not found"); } const date = new Date(); const id = await repo.insertWorkout({ bikeId: bike.id, programId: program.id, date: date, }); return new Workout(repo, id, bike, program, date); } /** * @param {import("../repositories/sqlite3")} repo * @param {number} id */ static async continue(repo, id) { const data = await repo.findWorkout(id); const bike = await repo.findBike(data.bikeId); const program = await repo.findWorkout(data.workoutId); const workout = new Workout(repo, id, bike, program, new Date(data.date)); const list = await repo.listMeasurements(id); if (list.length > 0) { const last = list[list.length - 1]; workout.offsetSeconds = (last.minutes * 60 + last.seconds); workout.offsets = { distance: last.distance, calories: last.calories, } } return workout; } } module.exports = Workout;