{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://elections.dutystation.ai/data/poll-catalog.schema.json",
  "title": "DutyStation poll question catalog 1.0",
  "type": "object",
  "required": [
    "schema_version",
    "generated_at",
    "as_of",
    "sources",
    "source_hashes",
    "counts",
    "polls"
  ],
  "properties": {
    "schema_version": {
      "const": "1.0"
    },
    "generated_at": {
      "type": "string",
      "format": "date-time"
    },
    "as_of": {
      "type": "string",
      "format": "date"
    },
    "polls": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "chamber",
          "race_id",
          "poll_id",
          "question_id",
          "pollster",
          "start_date",
          "end_date",
          "sample_size",
          "answers",
          "included"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "chamber": {
            "enum": [
              "senate",
              "house",
              "generic"
            ]
          },
          "sample_size": {
            "type": "integer",
            "minimum": 100
          },
          "included": {
            "type": "boolean",
            "description": "Question containing a selected model pair; other candidate answers need not enter the model."
          },
          "race_id": {
            "type": "string"
          },
          "poll_id": {
            "type": "string"
          },
          "question_id": {
            "type": "string"
          },
          "pollster": {
            "type": "string"
          },
          "start_date": {
            "type": "string",
            "format": "date"
          },
          "end_date": {
            "type": "string",
            "format": "date"
          },
          "population": {
            "type": "string"
          },
          "partisan": {
            "type": "boolean"
          },
          "final_rcv": {
            "type": "boolean"
          },
          "model_pair": {
            "type": [
              "object",
              "null"
            ],
            "description": "Exact pair/margin used from this question, with reported versus normalized basis."
          },
          "margin": {
            "type": [
              "number",
              "null"
            ]
          },
          "url": {
            "type": [
              "string",
              "null"
            ]
          },
          "answers": {
            "type": "array",
            "minItems": 2,
            "items": {
              "type": "object",
              "required": [
                "name",
                "party",
                "source_party",
                "pct"
              ],
              "properties": {
                "name": {
                  "type": "string"
                },
                "pct": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 100
                }
              }
            }
          }
        }
      }
    }
  }
}