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.

219 lines
6.7 KiB

5 years ago
5 years ago
  1. const express = require("express");
  2. const Workout = require("../systems/workout");
  3. /**
  4. * @param {import("../repositories/sqlite3")} repo
  5. */
  6. module.exports = function workoutRouter(repo) {
  7. const router = express.Router({caseSensitive: false});
  8. /** @type {Workout[]} */
  9. let workouts = [];
  10. router.get("/", async(req, res) => {
  11. if (req.query.active === "true") {
  12. return res.status(200).json(workouts.map(w => ({
  13. id: w.id,
  14. bike: w.bike,
  15. program: w.program,
  16. date: w.date,
  17. active: true,
  18. })));
  19. }
  20. try {
  21. const dbWorkouts = await repo.listWorkouts();
  22. return res.status(200).json(dbWorkouts.map(w => ({
  23. ...w,
  24. active: workouts.find(w2 => w2.id === w.id) != null,
  25. })));
  26. } catch (err) {
  27. return res.status(400).json({code: 400, message: err.message || err})
  28. }
  29. });
  30. router.get("/:id", async(req, res) => {
  31. let workout = workouts.find(w => w.id == req.params.id);
  32. if (workout != null) {
  33. return res.status(200).json({id: workout.id, bike: workout.bike, program: workout.program, date: workout.date, active: true})
  34. }
  35. try {
  36. workout = await repo.findWorkout(req.params.id);
  37. if (workout == null) {
  38. return res.status(404).json({code: 404, message: "workout not found"})
  39. }
  40. return res.status(200).json({active: false, ...workout});
  41. } catch (err) {
  42. return res.status(500).json({code: 500, message: err.message || err})
  43. }
  44. });
  45. router.get("/:id/measurements/", async(req, res) => {
  46. try {
  47. const measurements = await repo.listMeasurements(req.params.id);
  48. if (measurements == null) {
  49. return res.status(404).json({code: 404, message: "measurements not found"})
  50. }
  51. return res.status(200).json(measurements);
  52. } catch (err) {
  53. return res.status(500).json({code: 500, message: err.message || err})
  54. }
  55. });
  56. router.post("/", async(req, res) => {
  57. try {
  58. const {bikeId, programId} = req.body;
  59. const workout = await Workout.create(repo, bikeId, programId);
  60. workouts.push(workout);
  61. return res.status(200).json({id: workout.id, bike: workout.bike, program: workout.program, date: workout.date});
  62. } catch (err) {
  63. return res.status(400).json({code: 400, message: err.message || err});
  64. }
  65. });
  66. router.post("/:id/continue", async(req, res) => {
  67. let workout = workouts.find(w => w.id == req.params.id);
  68. if (workout != null) {
  69. return res.status(400).json({code: 400, message: "Workout already active."})
  70. }
  71. try {
  72. workout = await Workout.continue(repo, req.params.id);
  73. workouts.push(workout);
  74. return res.status(200).json({id: workout.id, bike: workout.bike, program: workout.program, date: workout.date});
  75. } catch (err) {
  76. return res.status(400).json({code: 400, message: err.message || err})
  77. }
  78. });
  79. router.post("/:id/connect", async(req, res) => {
  80. const workout = workouts.find(w => w.id == req.params.id);
  81. if (workout == null) {
  82. return res.status(404).json({code: 404, message: "Workout not found or inactive."})
  83. }
  84. try {
  85. await workout.connect();
  86. return res.status(200).json({id: workout.id, bike: workout.bike, program: workout.program, date: workout.date});
  87. } catch(err) {
  88. return res.status(500).json({code: 500, message: err.message || err});
  89. }
  90. });
  91. router.post("/:id/start", async(req, res) => {
  92. const workout = workouts.find(w => w.id == req.params.id);
  93. if (workout == null) {
  94. return res.status(404).json({code: 404, message: "Workout not found or inactive."})
  95. }
  96. try {
  97. await workout.start();
  98. return res.status(200).json({id: workout.id, bike: workout.bike, program: workout.program, date: workout.date});
  99. } catch(err) {
  100. return res.status(500).json({code: 500, message: err.message || err});
  101. }
  102. });
  103. router.post("/:id/pause", async(req, res) => {
  104. const workout = workouts.find(w => w.id == req.params.id);
  105. if (workout == null) {
  106. return res.status(404).json({code: 404, message: "Workout not found or inactive."})
  107. }
  108. try {
  109. await workout.pause();
  110. return res.status(200).json({id: workout.id, bike: workout.bike, program: workout.program, date: workout.date});
  111. } catch(err) {
  112. return res.status(500).json({code: 500, message: err.message || err});
  113. }
  114. });
  115. router.post("/:id/stop", async(req, res) => {
  116. const workout = workouts.find(w => w.id == req.params.id);
  117. if (workout == null) {
  118. return res.status(404).json({code: 404, message: "Workout not found or inactive."})
  119. }
  120. try {
  121. if (workout.driver != null) {
  122. await workout.stop();
  123. }
  124. workouts = workouts.filter(w => w !== workout);
  125. await workout.destroy();
  126. return res.status(200).json({id: workout.id, bike: workout.bike, program: workout.program, date: workout.date});
  127. } catch(err) {
  128. return res.status(500).json({code: 500, message: err.message || err});
  129. }
  130. });
  131. router.delete("/:id", async(req, res) => {
  132. let workout = workouts.find(w => w.id == req.params.id);
  133. if (workout != null) {
  134. return res.status(400).json({code: 400, message: "Workout already active."})
  135. }
  136. try {
  137. workout = await repo.findWorkout(req.params.id);
  138. if (workout == null) {
  139. return res.status(404).json({code: 404, message: "workout not found"})
  140. }
  141. await repo.deleteWorkout(workout);
  142. return res.status(200).json(workout);
  143. } catch (err) {
  144. return res.status(500).json({code: 500, message: err.message || err})
  145. }
  146. });
  147. router.ws("/:id/subscribe", (ws, req) => {
  148. console.log("HELLO!")
  149. const workout = workouts.find(w => w.id === req.params.id);
  150. if (workout == null) {
  151. ws.send(JSON.stringify({error: "workout not found"}));
  152. ws.close();
  153. }
  154. workout.listMeasurements().then((list) => {
  155. for (let i = 0; i < list.length; i += 240) {
  156. ws.send(JSON.stringify({workoutStatusBackfill: list.slice(i, i+240)}));
  157. }
  158. }).catch(err => {
  159. ws.send(JSON.stringify({error: `could not list measurements: ${err.message || err}`}));
  160. ws.close();
  161. });
  162. const handler = (workotuStatus) => {
  163. workotuStatus = {...workotuStatus};
  164. delete workotuStatus.id;
  165. ws.send(JSON.stringify({workotuStatus}))
  166. }
  167. workout.events.on("workoutStatus", handler);
  168. ws.onclose = () => {
  169. workout.events.removeListener("workoutStatus", handler);
  170. ws.removeAllListeners();
  171. };
  172. ws.send(JSON.stringify({
  173. workout: {
  174. id: workout.id,
  175. bike: workout.bike,
  176. program: workout.program,
  177. date: workout.date,
  178. },
  179. }));
  180. })
  181. return router;
  182. }