{
  "openapi": "3.1.0",
  "info": {
    "title": "雀天 API",
    "version": "1.0.0",
    "summary": "麻雀の計算（向聴・受け入れ・何切る・点数）と描画（手牌の画像）",
    "description": "雀天の対局で動いている麻雀エンジン（mahjong-core）をそのまま公開しています。無料・登録不要・CORS 対応。/api/v1/ は互換を保ちます（項目は足すことがありますが、名前と意味は変えません）。計算の API は IP ごとに 1 分 60 回まで。画像を載せるときは雀天へのリンクを近くに置いてください。",
    "termsOfService": "https://janten.net/api#terms",
    "contact": {
      "name": "雀天",
      "url": "https://janten.net/api"
    }
  },
  "servers": [
    {
      "url": "https://janten.net"
    }
  ],
  "tags": [
    {
      "name": "計算",
      "description": "JSON を返す。答えは入力だけで決まる（乱数も AI の推論も使わない）"
    },
    {
      "name": "描画",
      "description": "画像を返す。記事に貼られた URL を壊さないよう、読めない文字は読み飛ばす"
    }
  ],
  "paths": {
    "/api/v1/analyze": {
      "get": {
        "operationId": "analyzeHand",
        "summary": "牌効率（向聴・受け入れ・何切る）",
        "description": "手牌の向聴数と受け入れを返す。ツモ前の形（3n+1 枚）なら有効牌と残り枚数、ツモ後の形（3n+2 枚）なら打牌ごとの向聴・受け入れを、良い順に並べて返す",
        "tags": [
          "計算"
        ],
        "parameters": [
          {
            "name": "tiles",
            "in": "query",
            "required": true,
            "description": "手牌。副露を除いて 1〜14 枚。牌の書き方: 数字のあとに m（萬子）・p（筒子）・s（索子）・z（字牌。1 東 2 南 3 西 4 北 5 白 6 發 7 中）。0 は赤五（0m・0p・0s）。123m456p のようにまとめても、1m2m3m と 1 枚ずつでもよい",
            "schema": {
              "description": "手牌。副露を除いて 1〜14 枚。牌の書き方: 数字のあとに m（萬子）・p（筒子）・s（索子）・z（字牌。1 東 2 南 3 西 4 北 5 白 6 發 7 中）。0 は赤五（0m・0p・0s）。123m456p のようにまとめても、1m2m3m と 1 枚ずつでもよい",
              "examples": [
                "2334m456p3478s55z6s"
              ],
              "type": "string",
              "pattern": "^([0-9]+[mps]|[1-7]+z)+$",
              "maxLength": 120
            }
          },
          {
            "name": "melds",
            "in": "query",
            "required": false,
            "description": "副露（鳴いた面子）。種類:牌 をカンマで区切る。種類は pon（ポン）・chi（チー）・kan（大明槓）・kakan（加槓）・ankan（暗槓）。例: pon:555z,chi:345s。副露の牌は残り枚数から自動で引く",
            "schema": {
              "description": "副露（鳴いた面子）。種類:牌 をカンマで区切る。種類は pon（ポン）・chi（チー）・kan（大明槓）・kakan（加槓）・ankan（暗槓）。例: pon:555z,chi:345s。副露の牌は残り枚数から自動で引く",
              "examples": [
                "pon:555z"
              ],
              "type": "string",
              "maxLength": 120
            }
          },
          {
            "name": "visible",
            "in": "query",
            "required": false,
            "description": "ほかに見えている牌（河・ドラ表示牌など）。受け入れの残り枚数から引く",
            "schema": {
              "description": "ほかに見えている牌（河・ドラ表示牌など）。受け入れの残り枚数から引く",
              "examples": [
                "1z2z9m"
              ],
              "type": "string",
              "pattern": "^([0-9]+[mps]|[1-7]+z)+$",
              "maxLength": 120
            }
          }
        ],
        "responses": {
          "200": {
            "description": "計算の結果",
            "headers": {
              "Server-Timing": {
                "description": "サーバーで計算にかかった時間（calc;dur=ミリ秒）",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "残りの回数（IETF の草案の書き方。v1 の約束には含めない）",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyzeResult"
                }
              }
            }
          },
          "400": {
            "description": "パラメータの誤り。param と position で場所を示す",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "呼び出しが多すぎる（IP ごとに 1 分 60 回。牌効率は全体で 1 秒 5 回も）",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/score": {
      "get": {
        "operationId": "scoreHand",
        "summary": "点数計算（役・符・点数）",
        "description": "和了形から役・翻・符（内訳つき）・点数を返す。ルールは雀天の標準（喰いタンあり・切り上げ満貫あり・数え役満なし・単独のダブル役満なし。複合役満は倍数で数える）で、応答の rules に書く",
        "tags": [
          "計算"
        ],
        "parameters": [
          {
            "name": "tiles",
            "in": "query",
            "required": true,
            "description": "和了牌を含む手牌（副露を除く）。牌の書き方: 数字のあとに m（萬子）・p（筒子）・s（索子）・z（字牌。1 東 2 南 3 西 4 北 5 白 6 發 7 中）。0 は赤五（0m・0p・0s）。123m456p のようにまとめても、1m2m3m と 1 枚ずつでもよい",
            "schema": {
              "description": "和了牌を含む手牌（副露を除く）。牌の書き方: 数字のあとに m（萬子）・p（筒子）・s（索子）・z（字牌。1 東 2 南 3 西 4 北 5 白 6 發 7 中）。0 は赤五（0m・0p・0s）。123m456p のようにまとめても、1m2m3m と 1 枚ずつでもよい",
              "examples": [
                "234m567p23678s55s4s"
              ],
              "type": "string",
              "pattern": "^([0-9]+[mps]|[1-7]+z)+$",
              "maxLength": 120
            }
          },
          {
            "name": "win",
            "in": "query",
            "required": true,
            "description": "和了牌（tiles に含まれている 1 枚）",
            "schema": {
              "description": "和了牌（tiles に含まれている 1 枚）",
              "examples": [
                "4s"
              ],
              "type": "string",
              "pattern": "^[0-9][mps]$|^[1-7]z$"
            }
          },
          {
            "name": "by",
            "in": "query",
            "required": true,
            "description": "和了の仕方。tsumo（ツモ）か ron（ロン）",
            "schema": {
              "description": "和了の仕方。tsumo（ツモ）か ron（ロン）",
              "examples": [
                "tsumo"
              ],
              "type": "string",
              "enum": [
                "tsumo",
                "ron"
              ]
            }
          },
          {
            "name": "melds",
            "in": "query",
            "required": false,
            "description": "副露（鳴いた面子）。種類:牌 をカンマで区切る。種類は pon（ポン）・chi（チー）・kan（大明槓）・kakan（加槓）・ankan（暗槓）。例: pon:555z,chi:345s",
            "schema": {
              "description": "副露（鳴いた面子）。種類:牌 をカンマで区切る。種類は pon（ポン）・chi（チー）・kan（大明槓）・kakan（加槓）・ankan（暗槓）。例: pon:555z,chi:345s",
              "examples": [
                "pon:777z"
              ],
              "type": "string",
              "maxLength": 120
            }
          },
          {
            "name": "riichi",
            "in": "query",
            "required": false,
            "description": "立直しているか",
            "schema": {
              "description": "立直しているか",
              "examples": [
                true
              ],
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "double_riichi",
            "in": "query",
            "required": false,
            "description": "ダブル立直か（立直を含む）",
            "schema": {
              "description": "ダブル立直か（立直を含む）",
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "ippatsu",
            "in": "query",
            "required": false,
            "description": "一発か（立直が要る）",
            "schema": {
              "description": "一発か（立直が要る）",
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "haitei",
            "in": "query",
            "required": false,
            "description": "最後の牌での和了か（ツモなら海底摸月、ロンなら河底撈魚）",
            "schema": {
              "description": "最後の牌での和了か（ツモなら海底摸月、ロンなら河底撈魚）",
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "rinshan",
            "in": "query",
            "required": false,
            "description": "嶺上開花か（槓のあとのツモ）",
            "schema": {
              "description": "嶺上開花か（槓のあとのツモ）",
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "chankan",
            "in": "query",
            "required": false,
            "description": "槍槓か（加槓した牌でのロン）",
            "schema": {
              "description": "槍槓か（加槓した牌でのロン）",
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "seat",
            "in": "query",
            "required": false,
            "description": "自風（1z 東〜4z 北）。1z が親",
            "schema": {
              "description": "自風（1z 東〜4z 北）。1z が親",
              "examples": [
                "2z"
              ],
              "type": "string",
              "enum": [
                "1z",
                "2z",
                "3z",
                "4z"
              ],
              "default": "1z"
            }
          },
          {
            "name": "round",
            "in": "query",
            "required": false,
            "description": "場風（1z 東〜4z 北）",
            "schema": {
              "description": "場風（1z 東〜4z 北）",
              "type": "string",
              "enum": [
                "1z",
                "2z",
                "3z",
                "4z"
              ],
              "default": "1z"
            }
          },
          {
            "name": "dora",
            "in": "query",
            "required": false,
            "description": "ドラ表示牌（ドラそのものではなく、表示されている牌）",
            "schema": {
              "description": "ドラ表示牌（ドラそのものではなく、表示されている牌）",
              "examples": [
                "3p"
              ],
              "type": "string",
              "pattern": "^([0-9]+[mps]|[1-7]+z)+$",
              "maxLength": 120
            }
          },
          {
            "name": "ura",
            "in": "query",
            "required": false,
            "description": "裏ドラ表示牌（立直が要る）",
            "schema": {
              "description": "裏ドラ表示牌（立直が要る）",
              "type": "string",
              "pattern": "^([0-9]+[mps]|[1-7]+z)+$",
              "maxLength": 120
            }
          },
          {
            "name": "honba",
            "in": "query",
            "required": false,
            "description": "本場。1 本につき 300 点（ツモは 1 人 100 点ずつ）を足す",
            "schema": {
              "description": "本場。1 本につき 300 点（ツモは 1 人 100 点ずつ）を足す",
              "type": "integer",
              "minimum": 0,
              "maximum": 99,
              "default": 0
            }
          },
          {
            "name": "kyotaku",
            "in": "query",
            "required": false,
            "description": "供託の立直棒の本数。1 本 1,000 点を和了者が受け取る",
            "schema": {
              "description": "供託の立直棒の本数。1 本 1,000 点を和了者が受け取る",
              "type": "integer",
              "minimum": 0,
              "maximum": 99,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "計算の結果",
            "headers": {
              "Server-Timing": {
                "description": "サーバーで計算にかかった時間（calc;dur=ミリ秒）",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "残りの回数（IETF の草案の書き方。v1 の約束には含めない）",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScoreResult"
                }
              }
            }
          },
          "400": {
            "description": "パラメータの誤り。param と position で場所を示す",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "和了の形でない・役が無い・状況が成り立たない",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "呼び出しが多すぎる（IP ごとに 1 分 60 回。牌効率は全体で 1 秒 5 回も）",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/mahjong/tehai": {
      "get": {
        "operationId": "tehaiImage",
        "summary": "手牌画像",
        "description": "手牌・ツモ・副露・ドラ・捨て牌を SVG で描く。<img> にそのまま入れられる",
        "tags": [
          "描画"
        ],
        "parameters": [
          {
            "name": "tiles",
            "in": "query",
            "required": false,
            "description": "手牌（tiles と melds のどちらかは必須）。牌の書き方: 数字のあとに m（萬子）・p（筒子）・s（索子）・z（字牌。1 東 2 南 3 西 4 北 5 白 6 發 7 中）。0 は赤五（0m・0p・0s）。123m456p のようにまとめても、1m2m3m と 1 枚ずつでもよい",
            "schema": {
              "description": "手牌（tiles と melds のどちらかは必須）。牌の書き方: 数字のあとに m（萬子）・p（筒子）・s（索子）・z（字牌。1 東 2 南 3 西 4 北 5 白 6 發 7 中）。0 は赤五（0m・0p・0s）。123m456p のようにまとめても、1m2m3m と 1 枚ずつでもよい",
              "examples": [
                "123m456p789s11z"
              ],
              "type": "string",
              "pattern": "^([0-9]+[mps]|[1-7]+z)+$",
              "maxLength": 120
            }
          },
          {
            "name": "tsumo",
            "in": "query",
            "required": false,
            "description": "ツモ牌。手牌の右に少し離して描く",
            "schema": {
              "description": "ツモ牌。手牌の右に少し離して描く",
              "examples": [
                "7z"
              ],
              "type": "string",
              "pattern": "^[0-9][mps]$|^[1-7]z$"
            }
          },
          {
            "name": "melds",
            "in": "query",
            "required": false,
            "description": "副露（鳴いた面子）。種類:牌 をカンマで区切る。種類は pon（ポン）・chi（チー）・kan（大明槓）・kakan（加槓）・ankan（暗槓）。例: pon:555z,chi:345s。kan と kakan は横向きの牌で描き分ける",
            "schema": {
              "description": "副露（鳴いた面子）。種類:牌 をカンマで区切る。種類は pon（ポン）・chi（チー）・kan（大明槓）・kakan（加槓）・ankan（暗槓）。例: pon:555z,chi:345s。kan と kakan は横向きの牌で描き分ける",
              "examples": [
                "pon:555z,chi:345s"
              ],
              "type": "string",
              "maxLength": 120
            }
          },
          {
            "name": "dora",
            "in": "query",
            "required": false,
            "description": "ドラ表示牌。ドラに当たる牌を黄色で強調する",
            "schema": {
              "description": "ドラ表示牌。ドラに当たる牌を黄色で強調する",
              "examples": [
                "2m"
              ],
              "type": "string",
              "pattern": "^([0-9]+[mps]|[1-7]+z)+$",
              "maxLength": 120
            }
          },
          {
            "name": "discards",
            "in": "query",
            "required": false,
            "description": "捨て牌。手牌の下に描く",
            "schema": {
              "description": "捨て牌。手牌の下に描く",
              "examples": [
                "1z2z3p8s"
              ],
              "type": "string",
              "pattern": "^([0-9]+[mps]|[1-7]+z)+$",
              "maxLength": 120
            }
          },
          {
            "name": "shanten",
            "in": "query",
            "required": false,
            "description": "true で向聴数を描く。手牌・ツモ・副露 × 3 で 13〜14 枚、同じ牌は副露を含めて 4 枚までのときだけ",
            "schema": {
              "description": "true で向聴数を描く。手牌・ツモ・副露 × 3 で 13〜14 枚、同じ牌は副露を含めて 4 枚までのときだけ",
              "examples": [
                true
              ],
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "waits",
            "in": "query",
            "required": false,
            "description": "true で待ち牌を描く。手牌と副露 × 3 がちょうど 13 枚で、同じ牌が 4 枚までのときだけ",
            "schema": {
              "description": "true で待ち牌を描く。手牌と副露 × 3 がちょうど 13 枚で、同じ牌が 4 枚までのときだけ",
              "examples": [
                true
              ],
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "theme",
            "in": "query",
            "required": false,
            "description": "配色",
            "schema": {
              "description": "配色",
              "type": "string",
              "enum": [
                "green",
                "dark",
                "white",
                "classic"
              ],
              "default": "green"
            }
          },
          {
            "name": "size",
            "in": "query",
            "required": false,
            "description": "大きさ。ogp は 1200×630（SNS のカード用）",
            "schema": {
              "description": "大きさ。ogp は 1200×630（SNS のカード用）",
              "type": "string",
              "enum": [
                "small",
                "medium",
                "large",
                "ogp"
              ],
              "default": "medium"
            }
          },
          {
            "name": "nosort",
            "in": "query",
            "required": false,
            "description": "true で手牌を並べ替えずに描く",
            "schema": {
              "description": "true で手牌を並べ替えずに描く",
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "nobg",
            "in": "query",
            "required": false,
            "description": "true で背景を透明にする",
            "schema": {
              "description": "true で背景を透明にする",
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "手牌画像",
            "content": {
              "image/svg+xml": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "パラメータの誤り"
          }
        }
      }
    },
    "/api/mahjong/tile": {
      "get": {
        "operationId": "tileImage",
        "summary": "牌 1 枚の画像",
        "description": "牌 1 枚を WebP で返す。34 種・3 サイズ。1 年キャッシュ",
        "tags": [
          "描画"
        ],
        "parameters": [
          {
            "name": "key",
            "in": "query",
            "required": true,
            "description": "牌（1m〜9m・1p〜9p・1s〜9s・1z〜7z。赤五は無い）",
            "schema": {
              "description": "牌（1m〜9m・1p〜9p・1s〜9s・1z〜7z。赤五は無い）",
              "examples": [
                "5p"
              ],
              "type": "string",
              "pattern": "^[1-9][mps]$|^[1-7]z$"
            }
          },
          {
            "name": "size",
            "in": "query",
            "required": false,
            "description": "幅 36・60・100px",
            "schema": {
              "description": "幅 36・60・100px",
              "type": "string",
              "enum": [
                "small",
                "medium",
                "large"
              ],
              "default": "small"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "牌 1 枚の画像",
            "content": {
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "パラメータの誤り"
          }
        }
      }
    },
    "/api/mahjong/stick": {
      "get": {
        "operationId": "stickImage",
        "summary": "点棒の画像",
        "description": "点棒（100・1,000・5,000・10,000 点）を PNG で返す。幅を指定できる",
        "tags": [
          "描画"
        ],
        "parameters": [
          {
            "name": "denom",
            "in": "query",
            "required": true,
            "description": "点棒の種類",
            "schema": {
              "description": "点棒の種類",
              "examples": [
                "1000"
              ],
              "type": "string",
              "enum": [
                "100",
                "1000",
                "5000",
                "10000"
              ]
            }
          },
          {
            "name": "w",
            "in": "query",
            "required": false,
            "description": "幅（px）。省略すると元の大きさ",
            "schema": {
              "description": "幅（px）。省略すると元の大きさ",
              "examples": [
                200
              ],
              "type": "integer",
              "minimum": 20,
              "maximum": 1000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "点棒の画像",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "パラメータの誤り"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "TileCount": {
        "type": "object",
        "required": [
          "tile",
          "remaining"
        ],
        "properties": {
          "tile": {
            "type": "string",
            "pattern": "^[1-9][mps]$|^[1-7]z$",
            "examples": [
              "2s"
            ]
          },
          "remaining": {
            "type": "integer",
            "minimum": 0,
            "maximum": 4
          }
        }
      },
      "ShantenDetail": {
        "type": "object",
        "required": [
          "value",
          "standard",
          "chiitoitsu",
          "kokushi"
        ],
        "properties": {
          "value": {
            "type": "integer",
            "description": "一般形・七対子・国士無双のうち最小。-1 は和了形"
          },
          "standard": {
            "type": "integer"
          },
          "chiitoitsu": {
            "type": [
              "integer",
              "null"
            ],
            "description": "副露が無く 13・14 枚のときだけ"
          },
          "kokushi": {
            "type": [
              "integer",
              "null"
            ],
            "description": "副露が無く 13・14 枚のときだけ"
          }
        }
      },
      "DiscardOption": {
        "type": "object",
        "required": [
          "discard",
          "shanten",
          "ukeire",
          "tiles"
        ],
        "properties": {
          "discard": {
            "type": "string",
            "pattern": "^[1-9][mps]$|^[1-7]z$",
            "examples": [
              "2s"
            ]
          },
          "hasRed": {
            "type": "boolean",
            "const": true,
            "description": "手牌にこの牌の赤五がある"
          },
          "shanten": {
            "type": "integer"
          },
          "ukeire": {
            "type": "integer",
            "description": "有効牌の残り枚数の合計"
          },
          "tiles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TileCount"
            }
          },
          "waits": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TileCount"
            },
            "description": "切ったあとが聴牌のときの待ち"
          }
        }
      },
      "AnalyzeResult": {
        "type": "object",
        "required": [
          "tiles",
          "phase",
          "shanten"
        ],
        "properties": {
          "tiles": {
            "type": "string"
          },
          "phase": {
            "enum": [
              "draw",
              "discard"
            ],
            "description": "draw はツモ前（3n+1 枚）、discard はツモ後（3n+2 枚）"
          },
          "shanten": {
            "$ref": "#/components/schemas/ShantenDetail"
          },
          "ukeire": {
            "type": "object",
            "required": [
              "total",
              "tiles"
            ],
            "properties": {
              "total": {
                "type": "integer"
              },
              "tiles": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TileCount"
                }
              }
            }
          },
          "waits": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TileCount"
            }
          },
          "discards": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DiscardOption"
            }
          }
        }
      },
      "Yaku": {
        "type": "object",
        "required": [
          "id",
          "name",
          "han"
        ],
        "properties": {
          "id": {
            "enum": [
              "riichi",
              "double_riichi",
              "ippatsu",
              "menzen_tsumo",
              "tanyao",
              "pinfu",
              "iipeikou",
              "ryanpeikou",
              "round_wind",
              "seat_wind",
              "haku",
              "hatsu",
              "chun",
              "ittsu",
              "sanshoku_doujun",
              "sanshoku_doukou",
              "toitoi",
              "sankantsu",
              "sanankou",
              "shousangen",
              "honitsu",
              "chinitsu",
              "honroutou",
              "chanta",
              "junchan",
              "chiitoitsu",
              "haitei",
              "houtei",
              "rinshan",
              "chankan",
              "dora",
              "aka_dora",
              "ura_dora",
              "tenhou",
              "chiihou",
              "suukantsu",
              "kokushi",
              "kokushi_13",
              "suuankou",
              "suuankou_tanki",
              "daisangen",
              "tsuuiisou",
              "chinroutou",
              "ryuuiisou",
              "daisuushii",
              "shousuushii",
              "chuuren",
              "junsei_chuuren"
            ]
          },
          "name": {
            "type": "string"
          },
          "han": {
            "type": "integer"
          }
        }
      },
      "FuPart": {
        "type": "object",
        "required": [
          "id",
          "name",
          "fu"
        ],
        "properties": {
          "id": {
            "enum": [
              "base",
              "menzen_ron",
              "tsumo",
              "pair",
              "wait",
              "mentsu",
              "pinfu_tsumo",
              "chiitoitsu"
            ]
          },
          "name": {
            "type": "string"
          },
          "fu": {
            "type": "integer"
          },
          "tile": {
            "type": "string",
            "pattern": "^[1-9][mps]$|^[1-7]z$",
            "examples": [
              "2s"
            ]
          }
        }
      },
      "ScoreResult": {
        "type": "object",
        "required": [
          "han",
          "fu",
          "yaku",
          "fuParts",
          "limit",
          "points",
          "rules"
        ],
        "properties": {
          "han": {
            "type": "integer"
          },
          "fu": {
            "type": [
              "integer",
              "null"
            ],
            "description": "役満は null"
          },
          "yaku": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Yaku"
            }
          },
          "fuParts": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/FuPart"
            }
          },
          "limit": {
            "enum": [
              "mangan",
              "haneman",
              "baiman",
              "sanbaiman",
              "yakuman",
              null
            ]
          },
          "yakumanCount": {
            "type": "integer"
          },
          "points": {
            "type": "object",
            "required": [
              "base",
              "total",
              "label"
            ],
            "properties": {
              "base": {
                "type": "integer",
                "description": "本場・供託を除いた点"
              },
              "total": {
                "type": "integer",
                "description": "和了者が受け取る点（本場・供託を含む）"
              },
              "ron": {
                "type": "integer"
              },
              "tsumo": {
                "oneOf": [
                  {
                    "type": "object",
                    "required": [
                      "each"
                    ],
                    "properties": {
                      "each": {
                        "type": "integer"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "required": [
                      "dealer",
                      "nonDealer"
                    ],
                    "properties": {
                      "dealer": {
                        "type": "integer"
                      },
                      "nonDealer": {
                        "type": "integer"
                      }
                    }
                  }
                ]
              },
              "label": {
                "type": "string",
                "examples": [
                  "1300-2600",
                  "7700",
                  "4000オール"
                ]
              }
            }
          },
          "rules": {
            "type": "object",
            "required": [
              "kuitan",
              "kiriageMangan",
              "kazoeYakuman",
              "doubleYakuman",
              "compositeYakuman"
            ],
            "properties": {
              "kuitan": {
                "type": "boolean"
              },
              "kiriageMangan": {
                "type": "boolean"
              },
              "kazoeYakuman": {
                "type": "boolean"
              },
              "doubleYakuman": {
                "type": "boolean",
                "description": "四暗刻単騎・国士十三面・大四喜・純正九蓮をダブル役満にするか"
              },
              "compositeYakuman": {
                "type": "boolean",
                "description": "役満が複数そろったら倍数で数えるか"
              }
            }
          }
        }
      },
      "Problem": {
        "type": "object",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "param": {
            "type": "string",
            "description": "誤りのあるパラメータ"
          },
          "position": {
            "type": "integer",
            "description": "そのパラメータの何文字目か（1 始まり）"
          },
          "shanten": {
            "type": "integer",
            "description": "not-winning-hand のとき、14 枚の手として数えた向聴数"
          }
        }
      }
    }
  }
}