You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
7.8 KiB
289 lines
7.8 KiB
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 = [];
|
|
|
|
function activeData(id) {
|
|
const workout = workouts.find(w2 => w2.id === id);
|
|
if (workout == null) {
|
|
return {
|
|
active: false,
|
|
};
|
|
}
|
|
|
|
return {
|
|
active: true,
|
|
state: workout.state,
|
|
}
|
|
}
|
|
|
|
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,
|
|
...activeData(w.id),
|
|
})));
|
|
}
|
|
|
|
try {
|
|
const dbWorkouts = await repo.listWorkouts();
|
|
return res.status(200).json(dbWorkouts.map(w => ({
|
|
...w,
|
|
...activeData(w.id),
|
|
})));
|
|
} 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,
|
|
...activeData(w.id),
|
|
});
|
|
}
|
|
|
|
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,
|
|
...activeData(workout.id),
|
|
});
|
|
} 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,
|
|
...activeData(w.id),
|
|
});
|
|
} 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,
|
|
...activeData(workout.id),
|
|
});
|
|
} 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,
|
|
...activeData(workout.id),
|
|
});
|
|
} 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,
|
|
...activeData(workout.id),
|
|
});
|
|
} 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,
|
|
...activeData(workout.id),
|
|
});
|
|
} 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({
|
|
id: workout.id,
|
|
bike: workout.bike,
|
|
program: workout.program,
|
|
date: workout.date,
|
|
...activeData(workout.id),
|
|
});
|
|
} catch (err) {
|
|
return res.status(500).json({code: 500, message: err.message || err})
|
|
}
|
|
});
|
|
|
|
router.ws("/:id/subscribe", (ws, req) => {
|
|
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) => {
|
|
list = list.map(v => {delete v.id; delete v.workoutId; return v});
|
|
|
|
for (let i = 0; i < list.length; i += 240) {
|
|
ws.send(JSON.stringify({workoutStatusBackfill: list.slice(i, i+240)}));
|
|
}
|
|
}).catch(err => {
|
|
ws.send(JSON.stringify({error: `could not list measurements: ${err.message || err}`}));
|
|
ws.close();
|
|
});
|
|
|
|
const onWorkoutStatus = (workoutStatus) => {
|
|
workoutStatus = {...workoutStatus};
|
|
delete workoutStatus.id;
|
|
|
|
ws.send(JSON.stringify({workoutStatus}))
|
|
}
|
|
workout.events.on("workoutStatus", onWorkoutStatus);
|
|
|
|
const onState = (state) => {
|
|
ws.send(JSON.stringify({state}))
|
|
}
|
|
workout.events.on("state", onState);
|
|
|
|
|
|
ws.onclose = () => {
|
|
workout.events.removeListener("workoutStatus", onWorkoutStatus);
|
|
workout.events.removeListener("state", onState);
|
|
ws.removeAllListeners();
|
|
};
|
|
|
|
ws.send(JSON.stringify({
|
|
state: workout.state,
|
|
workout: {
|
|
id: workout.id,
|
|
bike: workout.bike,
|
|
program: workout.program,
|
|
date: workout.date,
|
|
},
|
|
}));
|
|
})
|
|
|
|
return router;
|
|
}
|