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.

141 lines
3.2 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. const EventEmitter = require("events");
  2. const createDriver = require("../drivers");
  3. class Workout {
  4. /**
  5. * @param {import("../repositories/sqlite3")} repo
  6. * @param {number} id
  7. * @param {{
  8. * id: string,
  9. * name: string,
  10. * driver: string,
  11. * connect: string,
  12. * maxLevel: number,
  13. * }} bike
  14. * @param {{
  15. * id: number,
  16. * name: string,
  17. * cpm: number,
  18. * warmupMin: number,
  19. * warmupCpm: number,
  20. * }} program
  21. * @param {Date} date
  22. */
  23. constructor(repo, id, bike, program, date) {
  24. this.repo = repo;
  25. this.id = id;
  26. this.bike = bike;
  27. this.program = program;
  28. this.date = date;
  29. this.driver = null;
  30. this.offsetSeconds = 0;
  31. this.offsets = {};
  32. this.events = new EventEmitter();
  33. }
  34. async connect() {
  35. this.driver = createDriver(this.bike.driver, this.bike.connect);
  36. this.driver.events.on("workoutStatus", ws => this.handleworkoutStatus(ws));
  37. return this.driver.connect();
  38. }
  39. start() {
  40. return this.driver.start();
  41. }
  42. pause() {
  43. return this.driver.pause();
  44. }
  45. stop() {
  46. return this.driver.stop();
  47. }
  48. destroy() {
  49. this.events.emit("destroy");
  50. this.events.removeAllListeners();
  51. if (this.driver != null) {
  52. this.driver.destroy();
  53. this.driver = null;
  54. }
  55. }
  56. listMeasurements() {
  57. return this.repo.listMeasurements(this.id);
  58. }
  59. handleworkoutStatus(ws) {
  60. if (this.offsetSeconds > 0) {
  61. const seconds = (ws.minutes * 60) + ws.seconds + this.offsetSeconds;
  62. ws.minutes = Math.floor(seconds / 60);
  63. ws.seconds = seconds % 60;
  64. for (const key in this.offsets) {
  65. if (!this.offsets.hasOwnProperty(key)) {
  66. continue;
  67. }
  68. ws[key] += this.offsets[key];
  69. }
  70. }
  71. this.repo.insertMeasurement({...ws, workoutId: this.id});
  72. this.events.emit("workoutStatus", {...ws});
  73. }
  74. /**
  75. * @param {import("../repositories/sqlite3")} repo
  76. * @param {number} bikeId
  77. * @param {number} programId
  78. */
  79. static async create(repo, bikeId, programId) {
  80. const bike = await repo.findBike(bikeId);
  81. if (bike == null) {
  82. throw new Error("bike not found");
  83. }
  84. const program = await repo.findProgram(programId);
  85. if (program == null) {
  86. throw new Error("program not found");
  87. }
  88. const date = new Date();
  89. const id = await repo.insertWorkout({
  90. bikeId: bike.id,
  91. programId: program.id,
  92. date: date,
  93. });
  94. return new Workout(repo, id, bike, program, date);
  95. }
  96. /**
  97. * @param {import("../repositories/sqlite3")} repo
  98. * @param {number} id
  99. */
  100. static async continue(repo, id) {
  101. const data = await repo.findWorkout(id);
  102. const bike = await repo.findBike(data.bikeId);
  103. const program = await repo.findWorkout(data.workoutId);
  104. const workout = new Workout(repo, id, bike, program, new Date(data.date));
  105. const list = await repo.listMeasurements(id);
  106. if (list.length > 0) {
  107. const last = list[list.length - 1];
  108. workout.offsetSeconds = (last.minutes * 60 + last.seconds);
  109. workout.offsets = {
  110. distance: last.distance,
  111. calories: last.calories,
  112. }
  113. }
  114. return workout;
  115. }
  116. }
  117. module.exports = Workout;