Files
peakup/peakup-backend/src/main/resources/weekplan-import.schema.json
2026-03-26 13:44:21 +01:00

147 lines
5.0 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "weekplan-import",
"title": "WeekPlanImportRequest",
"description": "AI-generated week plan import format for peakUp",
"type": "object",
"required": ["year", "calendarWeek", "workouts"],
"additionalProperties": false,
"properties": {
"year": {
"type": "integer",
"minimum": 2000,
"maximum": 2100,
"description": "ISO week-based year"
},
"calendarWeek": {
"type": "integer",
"minimum": 1,
"maximum": 53,
"description": "ISO calendar week number (1–53)"
},
"weekLabel": {
"type": "string",
"description": "Short label for the week, e.g. 'Race Prep Week 3'"
},
"weekDescription": {
"type": "string",
"description": "Longer description of the week's focus and goals"
},
"workouts": {
"type": "array",
"minItems": 1,
"description": "Planned workouts. Omit rest days — do not add empty entries.",
"items": { "$ref": "#/$defs/WorkoutImportItem" }
}
},
"$defs": {
"WorkoutImportItem": {
"type": "object",
"required": ["title", "day", "type"],
"additionalProperties": false,
"properties": {
"title": {
"type": "string",
"description": "Short name of the workout, e.g. 'Zone 2 Ride'"
},
"day": {
"type": "string",
"enum": ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"],
"description": "Day of the week (lowercase)"
},
"time": {
"type": "string",
"pattern": "^\\d{2}:\\d{2}$",
"description": "Start time in HH:mm format (24h), e.g. '07:30'. Optional — omit if no fixed start time."
},
"type": {
"type": "string",
"enum": ["BIKE", "RUN", "SWIM", "STRENGTH", "OTHER"],
"description": "Sport type"
},
"estimatedTimeSeconds": {
"type": "integer",
"minimum": 1,
"description": "Total workout duration in seconds. Must equal the sum of all step durations when steps are provided."
},
"estimatedTss": {
"type": "integer",
"minimum": 1,
"description": "Estimated Training Stress Score. Formula: IF² × (estimatedTimeSeconds / 3600) × 100, where IF = avg intensity / threshold."
},
"description": {
"type": "string",
"description": "Optional longer description / coaching notes for the workout"
},
"statusNote": {
"type": "string",
"description": "Optional pre-populated status note"
},
"steps": {
"type": "array",
"description": "Ordered workout steps. If omitted the workout has no structured intervals.",
"items": { "$ref": "#/$defs/StepImportItem" }
}
}
},
"StepImportItem": {
"type": "object",
"required": ["label", "stepType", "durationSeconds", "description", "intensityReference"],
"additionalProperties": false,
"if": {
"properties": { "stepType": { "const": "RAMP" } },
"required": ["stepType"]
},
"then": {
"required": ["targetValuePctStart", "targetValuePctEnd"]
},
"else": {
"required": ["targetValuePct"]
},
"properties": {
"label": {
"type": "string",
"description": "Short name, e.g. 'Warm Up', '4×8 min threshold', 'Recovery'"
},
"stepType": {
"type": "string",
"enum": ["WARM_UP", "WORK", "RAMP", "RECOVERY", "REST", "COOL_DOWN"],
"description": "Step category. RAMP = progressive intensity change (requires targetValuePctStart + targetValuePctEnd)."
},
"durationSeconds": {
"type": "integer",
"minimum": 1,
"description": "Duration of this step in seconds"
},
"description": {
"type": "string",
"description": "Optional coaching cue for this step, e.g. 'Keep cadence above 90 rpm'"
},
"intensityReference": {
"type": "string",
"enum": ["FTP", "LTHR", "THRESHOLD_PACE", "MAX_HR"],
"description": "Reference metric for target intensity. FTP = cycling power, LTHR = lactate-threshold HR, THRESHOLD_PACE = run threshold pace, MAX_HR = maximum HR."
},
"targetValuePct": {
"type": "integer",
"minimum": 0,
"maximum": 200,
"description": "Target intensity as % of intensityReference. Use for all stepTypes except RAMP."
},
"targetValuePctStart": {
"type": "integer",
"minimum": 0,
"maximum": 200,
"description": "Ramp start intensity (% of intensityReference). RAMP steps only."
},
"targetValuePctEnd": {
"type": "integer",
"minimum": 0,
"maximum": 200,
"description": "Ramp end intensity (% of intensityReference). RAMP steps only."
}
}
}
}
}