{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://xcit.org/nback.schema.json",
  "title": "Behaverse N-back Dataset",
  "description": "A list of events collected using Behaverse N-back task.",
  "type": "array",
  "items": {
    "$ref": "#/definitions/Event"
  },
  "definitions": {
    "Event":{
      "title": "A N-back Event",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "base": { "$ref": "#/definitions/Base" },
        "types": { "$ref": "#/definitions/Types" },
        "custom": { "$ref": "#/definitions/Custom" }
      },
      "required": ["base", "types", "custom"]
    },
    "Base":{
      "title": "Basic N-back Event Data",
      "type": "object",
      "properties": {
        "tsGenerated": {
          "type": "string",
          "format": "date-time"
        },
        "userId": {
          "type": "string",
          "format": "uuid"
        },
        "sessionId": {
          "type": "string",
          "format": "uuid"
        }
      },
      "required": ["tsGenerated", "userId", "sessionId"]
    },
    "Types":{
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "string"
      }
    },
    "Custom_NBack_TaskStart": {
      "$comment": "NBack.TaskStart custom field",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "timeline": {"type": "string"},
        "seed": {"type": "number"}
      }
    },
    "Custom_NBack_BlockStart": {
      "$comment": "NBack.BlockStart custom field. We need to seperate Instructions blocks from Game blocks",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "id": {"type": "number"},
        "type": {"type": "string", "enum": [null, "Game", "Instructions"]}
      }
    },
    "Custom_NBack_BlockEnd": {
      "$comment": "NBack.BlockEnd custom field.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "id": {"type": "number"},
        "type": {"type": "string", "enum": ["Game", "Instructions"]},
        "name": {"type": "string"},
        "seed": {"type": "number"},
        "accuracy": {"type": "number"},
        "hitCount": {"type": "number", "minimum": 0},
        "missCount": {"type": "number", "minimum": 0},
        "falseAlarmCount": {"type": "number"},
        "correctRejectionCount": {"type": "number"},
        "timeOutCount": {"type": "number", "minimum": 0}

      },
      "required": ["id","type","name","seed","accuracy","hitCount","missCount", "falseAlaram", "correctRejectionCount", "timeOutCount"]
    },
    "Custom_NBack_TaskEnd": {
      "$comment": "NBack.TaskEnd custom field.",
      "type": "object",
      "additionalProperties": false,
      "properties": {}
    },
    "Custom_NBack_TrialEnd": {
      "$comment": "NBack.TrialEnd custom field.",
      "type": "object",
      "additionalProperties": false,
      "properties": {}
    },
    "Custom_NBack_TrialStart": {
      "$comment": "NBack.TrialStart custom field.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "id": {"type": "number"},
        "seed": {"type": "number"}
      }
    },
    "Custom_NBack_MatchingButtonClick": {
      "$comment": "NBack.MatchingButtonClick custom field.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "isMatch": {"type": "boolean"},
        "pressDuration": {"type": "number"},
        "pressTime": {"type": "string", "format": "date-time"},
        "streamIndex": {"type": "number"},
        "responseTime": {"type": ["number", "null"]},
        "viewportPosition": { "$ref": "#/definitions/XY_Position" },
        "worldPosition": { "$ref": "#/definitions/XY_Position" }
      },
      "required": ["worldPosition", "viewportPosition", "pressTime", "pressDuration", "isMatch", "streamIndex", "responseTime"]
    },
    "Custom":{
      "type": "object",
      "$comment": "extract custom keys using this JQ query: '[.[] | .custom | keys | .[]] | unique | sort'",
      "properties": {
        "accuracy": {"type": "number"},
        "buttons": {"type": "array"},
        "correctRejectionCount": {"type": "number"},
        "falseAlarmCount": {"type": "number"},
        "gameObject": {"type": "string", "enum": ["Button"]},
        "hitCount": {"type": "number", "minimum": 0},
        "id": {"type": "number"},
        "isMatch": {"type": "boolean"},
        "missCount": {"type": "number", "minimum": 0},
        "name": {"type": "string"},
        "parameters": {"type": "object"},
        "pressDuration": {"type": "number"},
        "pressTime": {"type": "string", "format": "date-time"},
        "responseDuration": {"type": ["number", "null"]},
        "responseTime": {"type": ["number", "null"]},
        "seed": {"type": "number"},
        "stream": {"type": "number"},
        "streamIndex": {"type": "number"},
        "streamResults": {"type": "array"},
        "timeline": {"type": "string"},
        "timeOutCount": {"type": "number", "minimum": 0},
        "type": {"type": "string", "enum": [null, "Game", "Instructions"]},
        "value": {"type": ["number", "null"]},
        "viewportPosition": { "$ref": "#/definitions/XY_Position" },
        "worldPosition": { "$ref": "#/definitions/XY_Position" }
      },
      "additionalProperties": false,
      "oneOf": [
        { "$ref": "#/definitions/Custom_NBack_TaskStart"},
        { "$ref": "#/definitions/Custom_NBack_BlockStart"},
        { "$ref": "#/definitions/Custom_NBack_BlockEnd"},
        { "$ref": "#/definitions/Custom_NBack_TaskEnd"},
        { "$ref": "#/definitions/Custom_NBack_TrialEnd"},
        { "$ref": "#/definitions/Custom_NBack_TrialStart"},
        { "$ref": "#/definitions/Custom_NBack_MatchingButtonClick"}
      ]
    },
    "XY_Position": {
      "title": "XY Spatial Position",
      "type": ["null", "object"],
      "additionalProperties": false,
      "properties": {
        "x": {"type": "number"},
        "y": {"type": "number"}
      },
      "required": ["x", "y"]
    },
    "InstructionCustom": {
      "title": "Custom element for instruction blocks",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "id": {"type": "number"},
        "type": {"type": "string", "enum": ["Instruction"]}
      },
      "required": ["id", "type"]
    }
  }
}