{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://liftdiff.com/schema/history-v1.json",
  "title": "LiftDiff History Document",
  "description": "LiftDiff training history. Exercises are referenced by name, not by internal ID. This is the only import format, and it is identical to what the app exports.",
  "type": "object",
  "required": [
    "schema",
    "workouts"
  ],
  "properties": {
    "schema": {
      "const": "liftdiff.history/v1"
    },
    "exportedAt": {
      "type": "string",
      "format": "date-time"
    },
    "workouts": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/workout"
      }
    }
  },
  "$defs": {
    "workout": {
      "type": "object",
      "required": [
        "startedAt",
        "exercises"
      ],
      "properties": {
        "title": {
          "type": "string",
          "maxLength": 120
        },
        "startedAt": {
          "type": "string",
          "description": "ISO8601. A time without seconds, or a bare date, is also accepted."
        },
        "finishedAt": {
          "type": [
            "string",
            "null"
          ]
        },
        "note": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 2000,
          "description": "A note about the whole session. Notes about a single exercise do not belong here."
        },
        "exercises": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/exercise"
          }
        }
      }
    },
    "exercise": {
      "type": "object",
      "required": [
        "exercise",
        "sets"
      ],
      "properties": {
        "exercise": {
          "type": "string",
          "maxLength": 120,
          "description": "Exercise name. Spelling variations are resolved against the catalog on import."
        },
        "note": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 2000,
          "description": "A note about this exercise on this day."
        },
        "restSeconds": {
          "type": "integer",
          "minimum": 0,
          "maximum": 900
        },
        "superset": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Exercises sharing the same integer form a superset. Use null when it stands alone."
        },
        "targetRIR": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0,
          "maximum": 10
        },
        "sets": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/set"
          }
        }
      }
    },
    "set": {
      "type": "object",
      "description": "A set with no weight, reps, seconds or distanceKm is discarded.",
      "properties": {
        "kind": {
          "enum": [
            "normal",
            "warmup",
            "drop",
            "failure"
          ],
          "default": "normal"
        },
        "weight": {
          "type": [
            "number",
            "string",
            "null"
          ],
          "description": "Kilograms. If you only have pounds, put them in weightLb and they will be converted."
        },
        "weightLb": {
          "type": [
            "number",
            "string",
            "null"
          ]
        },
        "reps": {
          "type": [
            "integer",
            "string",
            "null"
          ]
        },
        "rpe": {
          "type": [
            "number",
            "null"
          ],
          "minimum": 0,
          "maximum": 10,
          "description": "When rir is absent and rpe is present, RIR = 10 - RPE is used."
        },
        "rir": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0,
          "maximum": 10,
          "description": "Takes precedence when both rpe and rir are present."
        },
        "seconds": {
          "type": [
            "integer",
            "null"
          ]
        },
        "distanceKm": {
          "type": [
            "number",
            "string",
            "null"
          ]
        }
      }
    }
  }
}
