{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "games": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string"
          },
          "hash": {
            "type": "string"
          },
          "replay_link": {
            "type": "string"
          },
          "players": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          },
          "final_results": {
            "type": "object",
            "patternProperties": {
              "^\\d+$": {
                "type": "object",
                "properties": {
                  "score": {
                    "type": "integer"
                  },
                  "rating_delta": {
                    "type": "number"
                  },
                  "place": {
                    "type": "integer"
                  }
                },
                "additionalProperties": false,
                "required": [
                  "score",
                  "rating",
                  "place"
                ]
              }
            }
          },
          "penalties": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "who": {
                  "type": "integer"
                },
                "amount": {
                  "type": "integer"
                },
                "reason": {
                  "type": "string"
                }
              },
              "additionalProperties": false,
              "required": [
                "who",
                "amount",
                "reason"
              ]
            }
          },
          "rounds": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "$ref": "#/definitions/ron"
                },
                {
                  "$ref": "#/definitions/multiron"
                },
                {
                  "$ref": "#/definitions/tsumo"
                },
                {
                  "$ref": "#/definitions/draw"
                },
                {
                  "$ref": "#/definitions/abort"
                },
                {
                  "$ref": "#/definitions/chombo"
                }
              ]
            }
          }
        },
        "additionalProperties": false,
        "required": [
          "date",
          "players",
          "final_results",
          "rounds",
          "replay_link",
          "hash"
        ]
      }
    },
    "players": {
      "type": "object",
      "patternProperties": {
        "^\\d+$": {
          "type": "object",
          "properties": {
            "id": {
              "type": "integer"
            },
            "display_name": {
              "type": "string"
            },
            "tenhou_id": {
              "type": "string"
            }
          },
          "additionalProperties": false,
          "required": [
            "id",
            "display_name",
            "tenhou_id"
          ]
        }
      }
    }
  },
  "definitions": {
    "ron": {
      "type": "object",
      "properties": {
        "round_index": {
          "type": "integer"
        },
        "outcome": {
          "type": "string"
        },
        "winner_id": {
          "type": "integer"
        },
        "loser_id": {
          "type": "integer"
        },
        "han": {
          "type": "integer"
        },
        "fu": {
          "type": "integer"
        },
        "yaku": {
          "type": "string"
        },
        "riichi_bets": {
          "type": "string"
        },
        "dora": {
          "type": "integer"
        },
        "uradora": {
          "type": "integer"
        },
        "kandora": {
          "type": "integer"
        },
        "kanuradora": {
          "type": "integer"
        },
        "open_hand": {
          "type": "boolean"
        }
      },
      "additionalProperties": false,
      "required": [
        "round_index",
        "outcome",
        "winner_id",
        "loser_id",
        "han",
        "fu",
        "yaku",
        "riichi_bets",
        "dora",
        "uradora",
        "kandora",
        "kanuradora",
        "open_hand"
      ]
    },
    "multiron": {
      "type": "object",
      "properties": {
        "round_index": {
          "type": "integer"
        },
        "outcome": {
          "type": "string"
        },
        "multi_ron": {
          "type": "integer"
        },
        "loser_id": {
          "type": "integer"
        },
        "wins": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "winner_id": {
                "type": "integer"
              },
              "han": {
                "type": "integer"
              },
              "fu": {
                "type": "integer"
              },
              "yaku": {
                "type": "string"
              },
              "riichi_bets": {
                "type": "string"
              },
              "dora": {
                "type": "integer"
              },
              "uradora": {
                "type": "integer"
              },
              "kandora": {
                "type": "integer"
              },
              "kanuradora": {
                "type": "integer"
              },
              "open_hand": {
                "type": "boolean"
              }
            },
            "additionalProperties": false,
            "required": [
              "winner_id",
              "han",
              "fu",
              "yaku",
              "riichi_bets",
              "dora",
              "uradora",
              "kandora",
              "kanuradora",
              "open_hand"
            ]
          }
        }
      },
      "additionalProperties": false,
      "required": [
        "round_index",
        "outcome",
        "multi_ron",
        "loser_id",
        "wins"
      ]
    },
    "tsumo": {
      "type": "object",
      "properties": {
        "round_index": {
          "type": "integer"
        },
        "outcome": {
          "type": "string"
        },
        "winner_id": {
          "type": "integer"
        },
        "han": {
          "type": "integer"
        },
        "fu": {
          "type": "integer"
        },
        "yaku": {
          "type": "string"
        },
        "riichi_bets": {
          "type": "string"
        },
        "dora": {
          "type": "integer"
        },
        "uradora": {
          "type": "integer"
        },
        "kandora": {
          "type": "integer"
        },
        "kanuradora": {
          "type": "integer"
        },
        "open_hand": {
          "type": "boolean"
        }
      },
      "additionalProperties": false,
      "required": [
        "round_index",
        "outcome",
        "winner_id",
        "han",
        "fu",
        "yaku",
        "riichi_bets",
        "dora",
        "uradora",
        "kandora",
        "kanuradora",
        "open_hand"
      ]
    },
    "draw": {
      "type": "object",
      "properties": {
        "round_index": {
          "type": "integer"
        },
        "outcome": {
          "type": "string"
        },
        "riichi_bets": {
          "type": "string"
        },
        "tempai": {
          "type": "string"
        }
      },
      "additionalProperties": false,
      "required": [
        "round_index",
        "outcome",
        "riichi_bets",
        "tempai"
      ]
    },
    "abort": {
      "type": "object",
      "properties": {
        "round_index": {
          "type": "integer"
        },
        "outcome": {
          "type": "string"
        },
        "riichi_bets": {
          "type": "string"
        }
      },
      "additionalProperties": false,
      "required": [
        "round_index",
        "outcome",
        "riichi_bets"
      ]
    },
    "chombo": {
      "type": "object",
      "properties": {
        "round_index": {
          "type": "integer"
        },
        "outcome": {
          "type": "string"
        },
        "loser_id": {
          "type": "integer"
        }
      },
      "additionalProperties": false,
      "required": [
        "round_index",
        "outcome",
        "loser_id"
      ]
    }
  },
  "additionalProperties": false,
  "required": [
    "games",
    "players"
  ]
}