{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "definitions": {
        "pipetteName": {
            "description": "Name of a pipette. Does not contain info about specific model/version. Should match keys in pipetteNameSpecs.json file",
            "type": "string",
            "enum": [
                "p10_single",
                "p10_multi",
                "p50_single",
                "p50_multi",
                "p300_single",
                "p300_multi",
                "p1000_single",
                "p1000_multi"
            ]
        },
        "pipette-model": {
            "description": "DEPRECATED. Exists to support backwards compatibility",
            "type": "string",
            "$comment": "TODO: Ian 2018-11-06 remove this def and every usage of it",
            "enum": [
                "p10_single_v1",
                "p10_multi_v1",
                "p50_single_v1",
                "p50_multi_v1",
                "p300_single_v1",
                "p300_multi_v1",
                "p1000_single_v1",
                "p1000_multi_v1",
                "p10_single_v1.3",
                "p10_multi_v1.3",
                "p50_single_v1.3",
                "p50_multi_v1.3",
                "p300_single_v1.3",
                "p300_multi_v1.3",
                "p1000_single_v1.3",
                "p1000_multi_v1.3"
            ]
        },
        "mm-offset": {
            "description": "Millimeters for pipette location offsets",
            "type": "number"
        },
        "flow-rate-for-pipettes": {
            "description": "Flow rate in mm/sec for each pipette model used in the protocol",
            "type": "object",
            "propertyNames": {
                "$ref": "#/definitions/pipetteName"
            },
            "patternProperties": {
                ".*": {
                    "type": "number"
                }
            },
            "additionalProperties": false
        },
        "flow-rate-params": {
            "properties": {
                "flow-rate": {
                    "description": "Flow rate for aspirate/dispense. If omitted, defaults to the corresponding values in \"default-values\"",
                    "type": "number"
                }
            }
        },
        "offsetFromBottomMm": {
            "description": "Offset from bottom of well in millimeters",
            "properties": {
                "offsetFromBottomMm": {
                    "$ref": "#/definitions/mm-offset"
                }
            }
        },
        "pipette-access-params": {
            "required": [
                "pipette",
                "labware",
                "well"
            ],
            "properties": {
                "pipette": {
                    "type": "string"
                },
                "labware": {
                    "type": "string"
                },
                "well": {
                    "type": "string"
                }
            }
        },
        "volume-params": {
            "required": [
                "volume"
            ],
            "volume": {
                "type": "number"
            }
        }
    },
    "type": "object",
    "additionalProperties": false,
    "required": [
        "protocol-schema",
        "default-values",
        "metadata",
        "robot",
        "pipettes",
        "labware",
        "procedure"
    ],
    "properties": {
        "protocol-schema": {
            "description": "A version string for the Opentrons JSON Protocol schema being used. \"<major>.<minor>.<patch>\"",
            "type": "string"
        },
        "metadata": {
            "description": "Optional metadata about the protocol",
            "type": "object",
            "properties": {
                "protocol-name": {
                    "description": "A short, human-readable name for the protocol",
                    "type": "string"
                },
                "author": {
                    "description": "The author or organization who created the protocol",
                    "type": "string"
                },
                "description": {
                    "description": "A text description of the protocol. For guidelines about how to write a good description, see (TODO WRITE DOCS & LINK HERE)",
                    "type": [
                        "string",
                        "null"
                    ]
                },
                "created": {
                    "description": "UNIX timestamp when this file was created",
                    "type": "number"
                },
                "last-modified": {
                    "description": "UNIX timestamp when this file was last modified",
                    "type": [
                        "number",
                        "null"
                    ]
                },
                "category": {
                    "description": "Category of protocol (eg, \"Basic Pipetting\")",
                    "type": [
                        "string",
                        "null"
                    ]
                },
                "subcategory": {
                    "description": "Subcategory of protocol (eg, \"Cell Plating\")",
                    "type": [
                        "string",
                        "null"
                    ]
                },
                "tags": {
                    "description": "Tags to be used in searching for this protocol",
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                }
            }
        },
        "default-values": {
            "description": "Default values required for protocol execution",
            "type": "object",
            "$note": "TODO: Ian 2018-10-29 make touch-tip-mm-from-top required (breaking change)",
            "required": [
                "aspirate-flow-rate",
                "dispense-flow-rate",
                "aspirate-mm-from-bottom",
                "dispense-mm-from-bottom"
            ],
            "properties": {
                "aspirate-flow-rate": {
                    "$ref": "#/definitions/flow-rate-for-pipettes"
                },
                "dispense-flow-rate": {
                    "$ref": "#/definitions/flow-rate-for-pipettes"
                },
                "aspirate-mm-from-bottom": {
                    "$ref": "#/definitions/mm-offset"
                },
                "dispense-mm-from-bottom": {
                    "$ref": "#/definitions/mm-offset"
                },
                "touch-tip-mm-from-top": {
                    "$ref": "#/definitions/mm-offset"
                }
            }
        },
        "designer-application": {
            "description": "Optional data & metadata not required to execute the protocol, used by the application that created this protocol",
            "type": "object",
            "properties": {
                "application-name": {
                    "description": "Name of the application that created the protocol. Should be namespaced under the organization or individual who owns the organization, and be kebab-cased, eg \"opentrons/protocol-designer\"",
                    "type": "string"
                },
                "application-version": {
                    "description": "Version of the application that created the protocol",
                    "type": "string"
                },
                "data": {
                    "description": "Any data used by the application that created this protocol)",
                    "type": "object"
                }
            }
        },
        "robot": {
            "required": [
                "model"
            ],
            "properties": {
                "model": {
                    "description": "Model of the robot this (currently only OT-2 Standard is supported)",
                    "type": "string",
                    "enum": [
                        "OT-2 Standard"
                    ]
                }
            }
        },
        "pipettes": {
            "description": "The pipettes used in this protocol, keyed by an arbitrary unique ID",
            "additionalProperties": false,
            "$comment": "TODO: Ian 2018-11-06 next breaking change, drop 'model' and require 'name' field",
            "patternProperties": {
                ".+": {
                    "description": "Fields describing an individual pipette",
                    "type": "object",
                    "required": [
                        "mount",
                        "model"
                    ],
                    "properties": {
                        "mount": {
                            "description": "Where the pipette is mounted",
                            "type": "string",
                            "enum": [
                                "left",
                                "right"
                            ]
                        },
                        "name": {
                            "$ref": "#/definitions/pipetteName"
                        },
                        "model": {
                            "$ref": "#/definitions/pipette-model"
                        }
                    }
                }
            }
        },
        "labware": {
            "description": "The labware used in this protocol, keyed by an arbitrary unique ID",
            "patternProperties": {
                ".+": {
                    "description": "Fields describing a single labware on the deck",
                    "type": "object",
                    "required": [
                        "slot",
                        "model"
                    ],
                    "properties": {
                        "slot": {
                            "description": "Which slot on the deck of an OT-2 robot the labware is placed into",
                            "type": "string",
                            "enum": [
                                "1",
                                "2",
                                "3",
                                "4",
                                "5",
                                "6",
                                "7",
                                "8",
                                "9",
                                "10",
                                "11",
                                "12"
                            ]
                        },
                        "model": {
                            "description": "Labware type, eg \"96-flat\". See http://docs.opentrons.com/containers.html for a full list of supported labware. TODO support custom labware in JSON",
                            "type": "string"
                        },
                        "display-name": {
                            "description": "An optional human-readable nickname for this labware. Eg \"Buffer Trough\"",
                            "type": "string"
                        }
                    }
                }
            }
        },
        "procedure": {
            "description": "An array of \"subprocedure\" objects representing the steps to be executed on the robot",
            "type": "array",
            "items": {
                "type": "object",
                "required": [
                    "subprocedure"
                ],
                "properties": {
                    "annotation": {
                        "description": "Optional info annotating the subprocedure",
                        "type": "object",
                        "required": [
                            "name",
                            "description"
                        ],
                        "properties": {
                            "name": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            },
                            "description": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            }
                        }
                    },
                    "subprocedure": {
                        "type": "array",
                        "items": {
                            "anyOf": [
                                {
                                    "description": "Aspirate / dispense / air gap commands",
                                    "type": "object",
                                    "required": [
                                        "command",
                                        "params"
                                    ],
                                    "additionalProperties": false,
                                    "properties": {
                                        "command": {
                                            "enum": [
                                                "aspirate",
                                                "dispense",
                                                "air-gap"
                                            ]
                                        },
                                        "params": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/definitions/flow-rate-params"
                                                },
                                                {
                                                    "$ref": "#/definitions/pipette-access-params"
                                                },
                                                {
                                                    "$ref": "#/definitions/volume-params"
                                                },
                                                {
                                                    "$ref": "#/definitions/offsetFromBottomMm"
                                                }
                                            ]
                                        }
                                    }
                                },
                                {
                                    "description": "Touch tip commands",
                                    "type": "object",
                                    "required": [
                                        "command",
                                        "params"
                                    ],
                                    "additionalProperties": false,
                                    "properties": {
                                        "command": {
                                            "enum": [
                                                "touch-tip"
                                            ]
                                        },
                                        "params": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/definitions/pipette-access-params"
                                                },
                                                {
                                                    "$ref": "#/definitions/offsetFromBottomMm"
                                                }
                                            ]
                                        }
                                    }
                                },
                                {
                                    "description": "Pick up tip / drop tip / blowout commands",
                                    "type": "object",
                                    "required": [
                                        "command",
                                        "params"
                                    ],
                                    "additionalProperties": false,
                                    "properties": {
                                        "command": {
                                            "enum": [
                                                "pick-up-tip",
                                                "drop-tip",
                                                "blowout"
                                            ]
                                        },
                                        "params": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/definitions/pipette-access-params"
                                                }
                                            ]
                                        }
                                    }
                                },
                                {
                                    "description": "Delay command",
                                    "type": "object",
                                    "required": [
                                        "command",
                                        "params"
                                    ],
                                    "additionalProperties": false,
                                    "properties": {
                                        "command": {
                                            "enum": [
                                                "delay"
                                            ]
                                        },
                                        "params": {
                                            "type": "object",
                                            "additionalProperties": false,
                                            "required": [
                                                "wait"
                                            ],
                                            "properties": {
                                                "wait": {
                                                    "description": "either a number of seconds to wait (fractional values OK), or `true` to wait indefinitely until the user manually resumes the protocol",
                                                    "anyOf": [
                                                        {
                                                            "type": "number"
                                                        },
                                                        {
                                                            "enum": [
                                                                true
                                                            ]
                                                        }
                                                    ]
                                                },
                                                "message": {
                                                    "description": "optional message describing the delay"
                                                }
                                            }
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        }
    }
}