{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://theamateur.co.uk/schemas/dpl/dpl.constraints-1.schema.json",
  "title": "DPL replan constraints",
  "description": "What the shoot can afford, read by `dpl replan <plan> <constraints.json>`. Any limit left out (or null) is not a constraint; an empty object means no constraints. Unknown members are refused. The first two limits (max_shots, max_setups) are the original ones; the rest came with replan v2 and change nothing about a document that does not use them.",
  "$comment": "The reader also accepts a bare `null` document as no constraints; a schema author should write an object. Minutes are the day as the profile's timing works it through: work plus spare time (what RDY-TIME holds against the day's window). `kit` replaces the plan's own kit for the replan. `people` counts characters that can be played (talent) and cameras that need hands (camera).",
  "type": "object",
  "properties": {
    "max_shots": {
      "description": "The most shots the cut may need.",
      "type": [
        "integer",
        "null"
      ]
    },
    "max_setups": {
      "description": "The most camera setups (shots sharing a setup count once; a shot with no setup is its own).",
      "type": [
        "integer",
        "null"
      ]
    },
    "max_minutes_per_day": {
      "description": "The most minutes any one shoot day may need, as the day is worked through with the profile's timing: its work plus its spare time (what RDY-TIME holds against the day's window). Needs a schedule.",
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1
    },
    "max_minutes_total": {
      "description": "The most minutes all the shoot days may need together (work plus spare time, day by day). Needs a schedule.",
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1
    },
    "max_locations": {
      "description": "The most places the shoot may go to (the locations the remaining scenes are set in).",
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1
    },
    "people": {
      "description": "People on hand by role: how many characters can be played (talent) and how many cameras can be held (camera). A role not listed is not limited.",
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/$defs/PeopleLimit"
      }
    },
    "kit": {
      "description": "The kit that is available. It replaces the plan's own kit: a shot that asks for a lens, support, frame rate or camera this kit lacks cannot be filmed and is given up. Short-form plans only.",
      "anyOf": [
        {
          "$ref": "#/$defs/Kit"
        },
        {
          "type": "null"
        }
      ]
    },
    "finish_by": {
      "description": "The clock time every shoot day must be finished by (\"17:30\"): the day's start plus its work and spare time. Needs a schedule.",
      "type": [
        "string",
        "null"
      ],
      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
    }
  },
  "additionalProperties": false,
  "$defs": {
    "CameraKind": {
      "type": "string",
      "description": "A phone has lens multipliers (0.5, 1, 3); a camera (mirrorless, DSLR, cinema) has lenses in millimetres.",
      "enum": [
        "phone",
        "camera"
      ]
    },
    "Kit": {
      "type": "object",
      "description": "What the crew has to shoot with.",
      "properties": {
        "cameras": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/KitCamera"
          }
        },
        "supports": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/Support"
          }
        },
        "sound": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/SoundGear"
          }
        },
        "lights": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/LightGear"
          }
        }
      },
      "additionalProperties": false
    },
    "KitCamera": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "kind": {
          "$ref": "#/$defs/CameraKind"
        },
        "description": {
          "description": "The device in words (\"iPhone 15\", \"Sony FX3\").",
          "type": [
            "string",
            "null"
          ]
        },
        "lens_multipliers": {
          "description": "For a phone: its lenses as multipliers of the main camera, for example [0.5, 1, 3].",
          "type": "array",
          "items": {
            "type": "number"
          }
        },
        "lenses": {
          "description": "For a camera: its lenses. A prime gives mm; a zoom gives min_mm and max_mm.",
          "type": "array",
          "items": {
            "$ref": "#/$defs/KitLens"
          }
        },
        "crop_factor": {
          "description": "For a camera: the sensor's crop factor against full frame (1 full frame, 1.5 APS-C, 2 Micro Four Thirds).",
          "type": [
            "number",
            "null"
          ]
        },
        "sensor": {
          "description": "For a camera: the sensor in words (\"full frame\", \"Super 35\").",
          "type": [
            "string",
            "null"
          ]
        },
        "frame_rates": {
          "description": "The frame rates it records, in frames per second.",
          "type": "array",
          "items": {
            "type": "number"
          }
        }
      },
      "required": [
        "id",
        "kind"
      ],
      "additionalProperties": false
    },
    "KitLens": {
      "type": "object",
      "properties": {
        "mm": {
          "description": "A prime lens's focal length in millimetres.",
          "type": [
            "number",
            "null"
          ]
        },
        "min_mm": {
          "description": "A zoom's shortest and longest focal length in millimetres.",
          "type": [
            "number",
            "null"
          ]
        },
        "max_mm": {
          "type": [
            "number",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "LightGear": {
      "type": "string",
      "enum": [
        "none",
        "practical",
        "led_panel",
        "reflector"
      ]
    },
    "LimitedRole": {
      "type": "string",
      "description": "The people a replan can hold the plan to: the ones who appear in the picture, and the ones who hold the camera.",
      "enum": [
        "talent",
        "camera"
      ]
    },
    "PeopleLimit": {
      "type": "object",
      "description": "How many people of a role are on hand: {\"role\": \"talent\", \"count\": 2}.",
      "properties": {
        "role": {
          "description": "Talent counts the characters the remaining shots show (one person plays one character). Camera counts the cameras that need hands: a shot on a tripod or clamp needs none.",
          "$ref": "#/$defs/LimitedRole"
        },
        "count": {
          "description": "How many people have the role. Zero is allowed: nobody to hold a camera means every held shot must go.",
          "type": "integer",
          "minimum": 0
        }
      },
      "required": [
        "role",
        "count"
      ],
      "additionalProperties": false
    },
    "SoundGear": {
      "type": "string",
      "enum": [
        "phone_mic",
        "lav",
        "shotgun",
        "recorder"
      ]
    },
    "Support": {
      "type": "string",
      "description": "Where the camera is carried. handheld, shoulder, gimbal and steadicam need an operator holding the camera.",
      "enum": [
        "handheld",
        "gimbal",
        "tripod",
        "clamp",
        "slider",
        "shoulder",
        "dolly",
        "jib",
        "crane",
        "steadicam",
        "drone"
      ]
    }
  }
}
