{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"$id": "otaman_exercise_v2",
	"title": "OTaMan Exercise",
	"type": "object",
	"required": [
		"$id",
		"name",
		"options",
		"targets"
	],
	"properties": {
		"$id": {
			"description": "Document identifier",
			"type": "string",
			"const": "otaman_exercise_v2"
		},
		"name": {
			"description": "The Exercise name",
			"type": "string"
		},
		"description": {
			"type": "string",
			"description": "Extended description of the exercise. Can contain multiple lines of text. Line breaks are achieved with \\n",
			"minLength": 10,
			"maxLength": 2000
		},
		"options": {
			"description": "Exercise options",
			"type": "object",
			"required": [
				"unit_types",
				"weapons"
			],
			"properties": {
				"unit_types": {
					"description": "Types of units for which the exercise is intended",
					"type": "array",
					"minItems": 1,
					"uniqueItems": true,
					"items": {
						"type": "string",
						"description": "Format: 'Branch code' or 'Branch code'.'Unit type code', or '*'",
						"pattern": "^(\\*|O|L|T|X|B|G(.[MTIRASD])?|A(.[BAFNTD])?|N(.[NUACIR])?|I(.[IPCMEDASN])?|P(.[KPIGSE])?|S(.[US])?)$"
					}
				},
				"weapons": {
					"description": "Types of weapons for which the exercise is intended",
					"type": "array",
					"uniqueItems": true,
					"items": {
						"type": "string",
						"pattern": "^[A-Z]{2}$",
						"enum": ["AR", "MG", "SM", "SR", "PI", "SG", "TR", "GL", "TG", "AG", "CM", "AW", "BW"]
					}
				},
				"time_of_day": {
					"description": "Time of day at which the exercise should be performed",
					"type": "string",
					"enum": [
						"any",
						"day",
						"night"
					],
					"default": "any"
				},
				"max_duration": {
					"description": "Maximum allowed time for the entire exercise in seconds (Hard Timeout). 0 means unlimited (not recommended for automated fields).",
					"type": "integer",
					"minimum": 0,
					"default": 600
				}
			},
			"additionalProperties": false
		},

		"targets": {
			"description": "Targets list",
			"type": "array",
			"items": {
				"allOf": [
					{
						"$ref": "#/$defs/targetBaseElement"
					},
					{
						"type": "object",
						"required": ["distance"],
						"properties": {
							"distance": {
								"description": "Distance in meters from the firing position to the target",
								"type": "integer",
								"minimum": 0
							}
						}
					}
				]
			}
		},

		"movers": {
			"description": "List of platforms for horizontal target movement",
			"type": "array",
			"items": {
				"type": "object",
				"required": [
					"type",
					"speed",
					"controller"
				],
				"properties": {
					"type": {
						"description": "Platform type: 'rail' (trolley on rails) or 'ugv' (unmanned ground vehicle / drone)",
						"type": "string",
						"enum": [
							"rail",
							"rail_heavy",
							"ugv",
							"ugv_heavy"
						]
					},
					"speed": {
						"description": "speed in meters per second",
						"type": "integer",
						"minimum": 0
					},
					"return_on_hit": {
						"description": "should return when hitting target on it?",
						"type": "boolean",
						"default": false
					},
					"imitation": {
						"$ref": "#/$defs/imitationElement"
					},
					"controller": {
						"$ref": "#/$defs/controllerElement"
					},
					"on_start": {
						"description": "Name of the control object that will be activated when start platform",
						"type": "string"
					},
					"on_stop": {
						"description": "Name of the control object that will be activated when stop platform",
						"type": "string"
					},
					"targets": {
						"description": "targets mounted on a platform",
						"type": "array",
						"items": {
							"allOf": [
								{
									"$ref": "#/$defs/targetBaseElement"
								},
								{
									"type": "object",
									"properties": {
										"back_points": {
											"description": "Number of points for hitting the target when reversing. If no value is specified, the system defaults to the value from the 'points' field",
											"type": "integer",
											"minimum": 0
										}
									}
								}
							]
						}
					}
				},
				"allOf": [
					{
						"if": { "properties": { "type": { "const": "rail" } } },
						"then": {
							"required": ["distance"],
							"properties": {
								"distance": {
									"description": "Distance in meters from the firing position to the near edge of the rails",
									"type": "integer",
									"minimum": 0
								},
								"targets": { "minItems": 1, "maxItems": 2 }
							}
						}
					},
					{
						"if": { "properties": { "type": { "const": "ugv" } } },
						"then": {
							"required": ["route"],
							"properties": {
								"route": {
									"$ref": "#/$defs/routeElement"
								},
								"targets": { "minItems": 1, "maxItems": 1 }
							}
						}
					}
				]
			}
		},

		"sensors": {
			"description": "Sensor list",
			"type": "array",
			"items": {
				"type": "object",
				"required": [
					"name",
					"type"
				],
				"properties": {
					"name": {
						"description": "Sensor name",
						"type": "string"
					},
					"type": {
						"description": "Sensor type: 'trigger' - has two states 0 (off) and 1 (on); 'discrete' - measures discrete (integer) values; 'analog' - measures analog values",
						"type": "string",
						"enum": [
							"trigger",
							"discrete",
							"analog"
						]
					},
					"distance": {
						"description": "Distance in meters from the firing position to the sensor",
						"type": "integer",
						"minimum": 0
					},
					"threshold": {
						"description": "Sensor threshold value. For a trigger, this value can be 0 or 1, which will indicate which of the trigger states is the threshold",
						"type": "number",
						"minimum": 0
					},
					"range": {
						"description": "Range of values around the threshold value (-range..+range). This value is not used for the trigger and is ignored",
						"type": "number",
						"minimum": 0
					},
					"on_enter": {
						"description": "Name of the control object that will be activated when the sensor value enters the threshold zone",
						"type": "string",
						"default": ""
					},
					"on_exit": {
						"description": "name of the control object that will be activated when the sensor value leaves the threshold zone",
						"type": "string",
						"default": ""
					}
				},
				"additionalProperties": false
			}
		},

		"grades": {
			"description": "Grading scale to map total earned points to performance grades",
			"type": "array",
			"minItems": 2,
			"items": {
				"type": "object",
				"required": ["score", "level"],
				"properties": {
					"level": {
						"description": "The performance level achieved",
						"type": "string",
						"enum": ["low", "mid", "high"]
					},
					"score": {
						"description": "The exact score or the score range required for this level",
						"oneOf": [
							{
								"description": "Exact total score required",
								"type": "integer",
								"minimum": 0
							},
							{
								"description": "Score range (inclusive)",
								"type": "object",
								"required": ["min", "max"],
								"properties": {
									"min": { "type": "integer", "minimum": 0 },
									"max": { "type": "integer", "minimum": 0 }
								}
							}
						]
					}
				},
				"additionalProperties": false
			}
		}
	},

	"$defs": {
		"imitationElement": {
			"description": "List of simulation effects applied to the target",
			"type": "array",
			"uniqueItems": true,
			"items": {
				"type": "string",
				"enum": [
					"backlight",
					"grenade",
					"shooting",
					"infrared",
					"thermal",
					"sound",
					"pyrotechnic"
				]
			},
			"default": []
		},

		"heaterElement": {
			"description": "Power gain of the infrared emitter",
			"type": "string",
			"enum": ["low", "normal", "high", "highest"],
			"default": "normal"
		},

		"targetBaseElement": {
			"type": "object",
			"required": [
				"type",
				"controller"
			],
			"properties": {
				"type": {
					"description": "Target mechanism type",
					"type": "string",
					"enum": [
						"popup",
						"popup_light",
						"popup_heavy",
						"turn",
						"turn_light",
						"lift",
						"lift_heavy",
						"cluster"
					]
				},
				"shape": {
					"description": "Geometric shape of the target",
					"type": "string",
					"default": ""
				},
				"points": {
					"description": "Number of points for hitting the target",
					"type": "integer",
					"minimum": 0,
					"default": 0
				},
				"down_on_hit": {
					"description": "Should down the target when hitting it?",
					"type": "boolean",
					"default": false
				},
				"imitation": {
					"$ref": "#/$defs/imitationElement"
				},
				"heater": {
					"$ref": "#/$defs/heaterElement"
				},
				"controller": {
					"$ref": "#/$defs/controllerElement"
				},
				"on_rise": {
					"description": "Name of the control object that will be activated when the target is raised",
					"type": "string"
				},
				"on_down": {
					"description": "Name of the control object that will be activated when the target is down",
					"type": "string"
				},
				"on_hit": {
					"description": "Name of the control object that will be activated upon target hit event",
					"type": "string"
				}
			}
		},

		"routeElement": {
			"description": "Drone route: either the name of a saved route or an array of GPS waypoints",
			"oneOf": [
				{
					"description": "Route name/ID",
					"type": "string"
				},
				{
					"type": "array",
					"description": "Built-in array of waypoints (coordinates)",
					"minItems": 2,
					"items": {
						"type": "object",
						"required": ["lat", "lng"],
						"properties": {
							"lat": {
								"description": "Latitude",
								"type": "number",
								"minimum": -90,
								"maximum": 90
							},
							"lng": {
								"description": "Longitude",
								"type": "number",
								"minimum": -180,
								"maximum": 180
							},
							"speed": {
								"description": "Recommended speed to this point (m/s)",
								"type": "number",
								"minimum": 0
							}
						},
						"additionalProperties": false
					}
				}
			]
		},

		"controllerElement": {
			"description": "Target control object or its name",
			"oneOf": [
				{
					"description": "Target control object name",
					"type": "string"
				},
				{
					"description": "Target control object",
					"type": "object",
					"required": ["name"],
					"properties": {
						"name": {
							"description": "Target control object name",
							"type": "string"
						},
						"activate": {
							"description": "Activation condition: start (at the start of the exercise), event (at the event from the target)",
							"type": "string",
							"enum": ["start", "event"],
							"default": "start"
						},
						"action": {
							"$ref": "#/$defs/actionElement"
						},
						"loop": {
							"description": "Cyclic action execution parameters",
							"type": "object",
							"required": ["count", "actions"],
							"properties": {
								"delay": {
									"description": "Delay before starting the loop (sec)",
									"$ref": "#/$defs/numericOrRandom"
								},
								"count": {
									"description": "Number of loop iterations",
									"$ref": "#/$defs/numericOrRandom"
								},
								"actions": {
									"description": "List of actions within one iteration step of a loop",
									"type": "array",
									"minItems": 1,
									"items": {
										"$ref": "#/$defs/actionElement"
									}
								}
							},
							"additionalProperties": false
						}
					}
				}
			]
		},

		"actionElement": {
			"description": "Action time parameters",
			"type": "object",
			"required": ["duration"],
			"properties": {
				"delay": {
					"description": "Delay before action (sec)",
					"$ref": "#/$defs/numericOrRandom"
				},
				"duration": {
					"description": "Duration of action execution / active state (sec)",
					"oneOf": [
						{
							"description": "Fixed duration value",
							"type": "integer",
							"minimum": 1
						},
						{
							"$ref": "#/$defs/randomStringFunction"
						}
					]
				},
				"additionalProperties": false
			}
		},

		"randomStringFunction": {
			"description": "Random value in the format random(max) [0 to max] or random(min, max)",
			"type": "string",
			"pattern": "^random\\(\\d+(\\s*,\\s*\\d+)?\\)$",
			"example": "random(5) or random(5,10)"
		},

		"numericOrRandom": {
			"oneOf": [
				{
					"description": "Fixed value",
					"type": "integer",
					"minimum": 0,
					"default": 0
				},
				{
					"$ref": "#/$defs/randomStringFunction"
				}
			]
		}
	}
}
