{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://wonghongwei.com/api/sg-mahjong/v1/schemas/companion-backup.schema.json",
  "title": "Singapore Mahjong companion backup",
  "description": "Portable local data exported by the Wong Hong Wei physical-table companion. The file may contain player names and private table ledgers.",
  "type": "object",
  "required": ["kind", "version", "exportedAt", "data"],
  "properties": {
    "kind": {"const":"wonghongwei-sg-mahjong-companion-backup"},
    "version": {"const":1},
    "exportedAt": {"type":"string","format":"date-time"},
    "data": {"$ref":"#/$defs/backupData"}
  },
  "additionalProperties": true,
  "$defs": {
    "profile": {
      "allOf": [
        {"$ref":"profile-choices.schema.json"},
        {
          "type":"object",
          "required":["version","name","preset"],
          "properties":{
            "version":{"const":1},
            "name":{"type":"string","minLength":1,"maxLength":42},
            "preset":{"enum":["wong","shooter","custom"]}
          }
        }
      ]
    },
    "scoreEntry": {
      "type":"object",
      "required":["type","title","detail","deltas"],
      "properties":{
        "type":{"enum":["hand","side"]},
        "title":{"type":"string","minLength":1,"maxLength":42},
        "detail":{"type":"string","maxLength":42},
        "deltas":{
          "type":"array",
          "minItems":4,
          "maxItems":4,
          "items":{"type":"number","minimum":-1000000,"maximum":1000000},
          "$comment":"The four deltas must sum to zero; the companion enforces this invariant during normalization."
        }
      },
      "additionalProperties":true
    },
    "session": {
      "type":"object",
      "required":["players","entries"],
      "properties":{
        "players":{"type":"array","minItems":4,"maxItems":4,"items":{"type":"string","minLength":1,"maxLength":42}},
        "entries":{"type":"array","maxItems":200,"items":{"$ref":"#/$defs/scoreEntry"}}
      },
      "additionalProperties":true
    },
    "savedProfile": {
      "type":"object",
      "required":["id","profile"],
      "properties":{
        "id":{"type":"string","minLength":1,"maxLength":64},
        "profile":{"$ref":"#/$defs/profile"}
      },
      "additionalProperties":true
    },
    "completedTable": {
      "type":"object",
      "required":["id","finishedAt","profile","players","entries"],
      "properties":{
        "id":{"type":"string","minLength":1,"maxLength":42},
        "finishedAt":{"type":"string","format":"date-time"},
        "profile":{"$ref":"#/$defs/profile"},
        "players":{"type":"array","minItems":4,"maxItems":4,"items":{"type":"string","minLength":1,"maxLength":42}},
        "entries":{"type":"array","minItems":1,"maxItems":200,"items":{"$ref":"#/$defs/scoreEntry"}}
      },
      "additionalProperties":true
    },
    "drillResult": {
      "type":"object",
      "required":["profileCode","best","plays"],
      "properties":{
        "profileCode":{"type":"string","minLength":1,"maxLength":3000},
        "best":{"type":"integer","minimum":0,"maximum":10},
        "plays":{"type":"integer","minimum":0,"maximum":999}
      },
      "additionalProperties":true
    },
    "backupData": {
      "type":"object",
      "required":["profiles","activeProfile","currentSession","history","drillResults"],
      "properties":{
        "profiles":{"type":"array","maxItems":12,"items":{"$ref":"#/$defs/savedProfile"}},
        "activeProfile":{"$ref":"#/$defs/profile"},
        "currentSession":{"$ref":"#/$defs/session"},
        "history":{"type":"array","maxItems":12,"items":{"$ref":"#/$defs/completedTable"}},
        "drillResults":{
          "type":"array",
          "maxItems":12,
          "items":{"$ref":"#/$defs/drillResult"},
          "$comment":"profileCode values are unique after companion normalization."
        }
      },
      "additionalProperties":true
    }
  }
}
