const express = require("express"); const Workout = require("../systems/workout"); /** * @param {import("../repositories/sqlite3")} repo */ module.exports = function workoutRouter(repo) { const router = express.Router({caseSensitive: false}); /** @type {Workout[]} */ let workouts = []; router.get("/", async(req, res) => { if (req.query.active === "true") { return res.status(200).json(workouts.map(w => ({ id: w.id, bike: w.bike, program: w.program, date: w.date, active: true, }))); } try { const dbWorkouts = await repo.listWorkouts(); return res.status(200).json(dbWorkouts.map(w => ({ ...w, active: workouts.find(w2 => w2.id === w.id) != null, }))); } catch (err) { return res.status(400).json({code: 400, message: err.message || err}) } }); router.get("/:id", async(req, res) => { let workout = workouts.find(w => w.id == req.params.id); if (workout != null) { return res.status(200).json({id: workout.id, bike: workout.bike, program: workout.program, date: workout.date, active: true}) } try { workout = await repo.findWorkout(req.params.id); if (workout == null) { return res.status(404).json({code: 404, message: "workout not found"}) } return res.status(200).json({active: false, ...workout}); } catch (err) { return res.status(500).json({code: 500, message: err.message || err}) } }); router.get("/:id/measurements/", async(req, res) => { try { const measurements = await repo.listMeasurements(req.params.id); if (measurements == null) { return res.status(404).json({code: 404, message: "measurements not found"}) } return res.status(200).json(measurements); } catch (err) { return res.status(500).json({code: 500, message: err.message || err}) } }); router.post("/", async(req, res) => { try { const {bikeId, programId} = req.body; const workout = await Workout.create(repo, bikeId, programId); workouts.push(workout); return res.status(200).json({id: workout.id, bike: workout.bike, program: workout.program, date: workout.date}); } catch (err) { return res.status(400).json({code: 400, message: err.message || err}); } }); router.post("/:id/continue", async(req, res) => { let workout = workouts.find(w => w.id == req.params.id); if (workout != null) { return res.status(400).json({code: 400, message: "Workout already active."}) } try { workout = await Workout.continue(repo, req.params.id); workouts.push(workout); return res.status(200).json({id: workout.id, bike: workout.bike, program: workout.program, date: workout.date}); } catch (err) { return res.status(400).json({code: 400, message: err.message || err}) } }); router.post("/:id/connect", async(req, res) => { const workout = workouts.find(w => w.id == req.params.id); if (workout == null) { return res.status(404).json({code: 404, message: "Workout not found or inactive."}) } try { await workout.connect(); return res.status(200).json({id: workout.id, bike: workout.bike, program: workout.program, date: workout.date}); } catch(err) { return res.status(500).json({code: 500, message: err.message || err}); } }); router.post("/:id/start", async(req, res) => { const workout = workouts.find(w => w.id == req.params.id); if (workout == null) { return res.status(404).json({code: 404, message: "Workout not found or inactive."}) } try { await workout.start(); return res.status(200).json({id: workout.id, bike: workout.bike, program: workout.program, date: workout.date}); } catch(err) { return res.status(500).json({code: 500, message: err.message || err}); } }); router.post("/:id/pause", async(req, res) => { const workout = workouts.find(w => w.id == req.params.id); if (workout == null) { return res.status(404).json({code: 404, message: "Workout not found or inactive."}) } try { await workout.pause(); return res.status(200).json({id: workout.id, bike: workout.bike, program: workout.program, date: workout.date}); } catch(err) { return res.status(500).json({code: 500, message: err.message || err}); } }); router.post("/:id/stop", async(req, res) => { const workout = workouts.find(w => w.id == req.params.id); if (workout == null) { return res.status(404).json({code: 404, message: "Workout not found or inactive."}) } try { if (workout.driver != null) { await workout.stop(); } workouts = workouts.filter(w => w !== workout); await workout.destroy(); return res.status(200).json({id: workout.id, bike: workout.bike, program: workout.program, date: workout.date}); } catch(err) { return res.status(500).json({code: 500, message: err.message || err}); } }); router.delete("/:id", async(req, res) => { let workout = workouts.find(w => w.id == req.params.id); if (workout != null) { return res.status(400).json({code: 400, message: "Workout already active."}) } try { workout = await repo.findWorkout(req.params.id); if (workout == null) { return res.status(404).json({code: 404, message: "workout not found"}) } await repo.deleteWorkout(workout); return res.status(200).json(workout); } catch (err) { return res.status(500).json({code: 500, message: err.message || err}) } }); router.ws("/:id/subscribe", (ws, req) => { console.log("HELLO!") const workout = workouts.find(w => w.id === req.params.id); if (workout == null) { ws.send(JSON.stringify({error: "workout not found"})); ws.close(); } workout.listMeasurements().then((list) => { ws.send(JSON.stringify({workoutStatusBackfill: list})); }).catch(err => { ws.send(JSON.stringify({error: `could not list measurements: ${err.message || err}`})); ws.close(); }); const handler = (workotuStatus) => { workotuStatus = {...workotuStatus}; delete workotuStatus.id; ws.send(JSON.stringify({workotuStatus})) } workout.events.on("workoutStatus", handler); ws.onclose = () => { workout.events.removeListener("workoutStatus", handler); ws.removeAllListeners(); }; ws.send(JSON.stringify({ workout: { id: workout.id, bike: workout.bike, program: workout.program, date: workout.date, }, })); }) return router; }