import type { UUID } from 'crypto'; import type { WorkoutExerciseCTO } from '../../../ctos/workout/WorkoutExerciseCTO.js'; import type { WorkoutMuscleGroupVolumeCTO } from '../../../ctos/workout/WorkoutMuscleGroupVolumeCTO.js'; import { type WorkoutMesocycle } from '../../../documents/workout/WorkoutMesocycle.js'; import type { WorkoutMicrocycle } from '../../../documents/workout/WorkoutMicrocycle.js'; import type { WorkoutSession } from '../../../documents/workout/WorkoutSession.js'; import type { WorkoutSessionExercise } from '../../../documents/workout/WorkoutSessionExercise.js'; import type { WorkoutSet } from '../../../documents/workout/WorkoutSet.js'; import type { DocumentOperations } from '../../Document.service.js'; import type { WorkoutDeloadRecommendation } from './WorkoutMesocycleService.types.js'; /** * A service for handling operations related to {@link WorkoutMesocycle}s. */ export default class WorkoutMesocycleService { #private; /** * Generates or updates the workout plan for a mesocycle. * * This method supports incremental generation by only creating new microcycles that don't * yet exist. It expects that the mesocycle's core parameters (planned session count, * microcycle count, microcycle length) and exercise ordering have not changed since * initial creation. If these parameters have changed, it is the responsibility of a * higher-level service to convert the mesocycle to free-form mode before calling this method. * * The method will clean up any incomplete microcycles (where the last session is not * complete) and regenerate from that point, unless the microcycle has already started * (first session complete), in which case it will throw an error. * * @param mesocycle The mesocycle configuration. * @param exerciseCTOs The exercise CTOs containing exercise, calibration, equipment, and historical data. * @param volumeCTOs Optional muscle group volume CTOs for historical volume landmark estimation. * @param existingMicrocycles Existing microcycle documents for this mesocycle. * @param existingSessions Existing session documents. * @param existingSessionExercises Existing session exercise documents. * @param existingSets Existing set documents. * @param startDate Optional start date for the first microcycle. Defaults to the current date when not provided. */ static generateOrUpdateMesocycle(mesocycle: WorkoutMesocycle, exerciseCTOs: WorkoutExerciseCTO[], volumeCTOs?: WorkoutMuscleGroupVolumeCTO[], existingMicrocycles?: WorkoutMicrocycle[], existingSessions?: WorkoutSession[], existingSessionExercises?: WorkoutSessionExercise[], existingSets?: WorkoutSet[], startDate?: Date): { mesocycleUpdate?: Partial; microcycles?: DocumentOperations; sessions?: DocumentOperations; sessionExercises?: DocumentOperations; sets?: DocumentOperations; }; /** * Returns the projected start date for a mesocycle. Uses * `mesocycle.startDate` if set (active/completed), otherwise falls back to * the earliest microcycle's start date (future/planned mesocycles). * * @param mesocycle The mesocycle to get the projected start date for. * @param microcycles The microcycles belonging to this mesocycle (pre-filtered). */ static getProjectedStartDate(mesocycle: WorkoutMesocycle, microcycles: WorkoutMicrocycle[]): Date | null; /** * Returns the projected end date of a mesocycle based on its microcycles. * If microcycles exist, uses the last microcycle's endDate. Otherwise, * calculates from the mesocycle's start date and planned parameters. * * @param mesocycle The mesocycle to calculate the end date for. * @param microcycles The microcycles belonging to this mesocycle (pre-filtered). */ static getProjectedEndDate(mesocycle: WorkoutMesocycle, microcycles: WorkoutMicrocycle[]): Date | null; /** * Shifts all dates in a mesocycle and its child documents by the given number of days. * Mutates the passed-in objects in place. * * @param mesocycle The mesocycle to shift. Its startDate is mutated directly. * @param microcycles The microcycles belonging to this mesocycle (pre-filtered). Mutated in place. * @param sessions The sessions belonging to these microcycles (pre-filtered). Mutated in place. * @param daysDelta The number of days to shift (positive = forward, negative = backward). */ static shiftMesocycleDates(mesocycle: WorkoutMesocycle, microcycles: WorkoutMicrocycle[], sessions: WorkoutSession[], daysDelta: number): void; /** * Detects whether any mesocycles in the provided list have overlapping date ranges. * Two mesocycles overlap if their projected date ranges intersect. * * @param mesocycles The mesocycles to check. * @param mesocycleToMicrocyclesMap A map from mesocycle ID to its microcycles. */ static detectMesocycleOverlap(mesocycles: WorkoutMesocycle[], mesocycleToMicrocyclesMap: Map): { hasOverlap: boolean; overlappingPairs: Array<[UUID, UUID]>; }; /** * Returns the earliest allowed start date for a new mesocycle. This is the later * of: the projected end of the last existing mesocycle, or today. * * @param existingMesocycles All existing mesocycles. * @param mesocycleToMicrocyclesMap A map from mesocycle ID to its microcycles. */ static getEarliestAllowedStartDate(existingMesocycles: WorkoutMesocycle[], mesocycleToMicrocyclesMap: Map): Date; /** * Evaluates whether the mesocycle should trigger an early deload based on * fatigue indicators from recent session data. * * Should be called after each session completion. Accepts the same document * inputs as {@link generateOrUpdateMesocycle} plus a current microcycle ID, * and uses {@link WorkoutMesocyclePlanContext} internally to derive all * needed data. */ static shouldTriggerEarlyDeload(mesocycle: WorkoutMesocycle, exerciseCTOs: WorkoutExerciseCTO[], currentMicrocycleId: UUID, existingMicrocycles: WorkoutMicrocycle[], existingSessions: WorkoutSession[], existingSessionExercises: WorkoutSessionExercise[], existingSets: WorkoutSet[]): WorkoutDeloadRecommendation; } //# sourceMappingURL=WorkoutMesocycle.service.d.ts.map