{
  "openapi": "3.1.0",
  "info": {
    "title": "Snuug room tools",
    "version": "1.0.0",
    "summary": "Room calculators: rug, sofa fit, TV and picture height, room and home size, curtains, lighting, paint, wallpaper, dining table, pendant light, kua number and bagua map.",
    "description": "Free, read-only and stateless: no key, no sign-up. Lengths are in cm (a TV in inches, areas in m²). Every rule cites its source, with the date it was checked. The same tools are an MCP server at https://snuug.app/mcp.",
    "contact": {
      "name": "Snuug",
      "url": "https://snuug.app",
      "email": "support@snuug.app"
    }
  },
  "servers": [
    {
      "url": "https://snuug.app"
    }
  ],
  "externalDocs": {
    "description": "The tools for agents, in llms.txt",
    "url": "https://snuug.app/llms.txt"
  },
  "tags": [
    {
      "name": "tools",
      "description": "One calculator each."
    }
  ],
  "paths": {
    "/api/v1/tools": {
      "get": {
        "operationId": "list_tools",
        "summary": "List the tools",
        "description": "Every tool, its inputs, and its API, example and page URLs.",
        "responses": {
          "200": {
            "description": "The tools.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/rug-size": {
      "get": {
        "operationId": "rug_size",
        "summary": "What size rug do I need for my living room?",
        "description": "Use when someone asks what size rug fits their living room or goes under or in front of their sofa. Returns the UK and US stock rug sizes that run past each end of the sofa and leave bare floor to the walls. Every rule cites its source. The calculator: https://snuug.app/tools/rug-size",
        "tags": [
          "tools"
        ],
        "parameters": [
          {
            "name": "sofa_width_cm",
            "in": "query",
            "required": false,
            "description": "The sofa’s width, arm to arm (cm).",
            "schema": {
              "type": "number",
              "default": 210,
              "minimum": 60,
              "maximum": 500
            }
          },
          {
            "name": "sofa_depth_cm",
            "in": "query",
            "required": false,
            "description": "The sofa’s depth, back to front (cm).",
            "schema": {
              "type": "number",
              "default": 90,
              "minimum": 50,
              "maximum": 200
            }
          },
          {
            "name": "room_width_cm",
            "in": "query",
            "required": false,
            "description": "The room’s width along the wall the sofa stands against (cm).",
            "schema": {
              "type": "number",
              "default": 400,
              "minimum": 150,
              "maximum": 1500
            }
          },
          {
            "name": "room_length_cm",
            "in": "query",
            "required": false,
            "description": "The room’s length, out from the sofa wall (cm).",
            "schema": {
              "type": "number",
              "default": 450,
              "minimum": 150,
              "maximum": 1500
            }
          },
          {
            "name": "legs_on_rug",
            "in": "query",
            "required": false,
            "description": "Which sofa legs stand on the rug: all, front (the usual choice) or none (the rug sits under the coffee table only).",
            "schema": {
              "type": "string",
              "default": "front",
              "enum": [
                "all",
                "front",
                "none"
              ]
            }
          },
          {
            "name": "armchairs",
            "in": "query",
            "required": false,
            "description": "none, or two armchairs facing the sofa, which the rug must also reach.",
            "schema": {
              "type": "string",
              "default": "none",
              "enum": [
                "none",
                "two"
              ]
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (the default) or text: one paragraph to quote. Accept: text/plain does the same.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "text"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/rug_size"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "An input is missing, unknown, repeated or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/sofa-fit": {
      "get": {
        "operationId": "sofa_fit",
        "summary": "Will my sofa fit through the door?",
        "description": "Use when someone asks whether a sofa (or another large piece) will fit through a door, round a turn in a hall or up to a room. Applies the furniture shops’ straight, tipped-back, on-end and swing tests and grades each ok, tight or no. Every rule cites its source. The calculator: https://snuug.app/tools/sofa-fit",
        "tags": [
          "tools"
        ],
        "parameters": [
          {
            "name": "door_width_cm",
            "in": "query",
            "required": false,
            "description": "The door’s clear width: the gap with the door open, frame to door edge (cm).",
            "schema": {
              "type": "number",
              "default": 74,
              "minimum": 40,
              "maximum": 300
            }
          },
          {
            "name": "door_height_cm",
            "in": "query",
            "required": false,
            "description": "The door’s clear height (cm).",
            "schema": {
              "type": "number",
              "default": 198,
              "minimum": 120,
              "maximum": 400
            }
          },
          {
            "name": "hall_width_cm",
            "in": "query",
            "required": false,
            "description": "The width of the hall or landing beyond the door, where the sofa must turn (cm).",
            "schema": {
              "type": "number",
              "default": 100,
              "minimum": 40,
              "maximum": 1000
            }
          },
          {
            "name": "route",
            "in": "query",
            "required": false,
            "description": "turn if the sofa must turn into the room after the door, straight if it goes straight on.",
            "schema": {
              "type": "string",
              "default": "turn",
              "enum": [
                "turn",
                "straight"
              ]
            }
          },
          {
            "name": "sofa_width_cm",
            "in": "query",
            "required": false,
            "description": "The sofa’s width, arm to arm (its length when carried) (cm).",
            "schema": {
              "type": "number",
              "default": 180,
              "minimum": 50,
              "maximum": 500
            }
          },
          {
            "name": "sofa_depth_cm",
            "in": "query",
            "required": false,
            "description": "The sofa’s depth, back to front (cm).",
            "schema": {
              "type": "number",
              "default": 86,
              "minimum": 40,
              "maximum": 250
            }
          },
          {
            "name": "sofa_height_cm",
            "in": "query",
            "required": false,
            "description": "The sofa’s height, floor to the top of the back (cm).",
            "schema": {
              "type": "number",
              "default": 80,
              "minimum": 40,
              "maximum": 250
            }
          },
          {
            "name": "sofa_diagonal_cm",
            "in": "query",
            "required": false,
            "description": "The sofa’s diagonal depth: from the back bottom corner to a straight edge laid from the top of the back to the front of the arm (cm).",
            "schema": {
              "type": "number",
              "default": 72,
              "minimum": 30,
              "maximum": 250
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (the default) or text: one paragraph to quote. Accept: text/plain does the same.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "text"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/sofa_fit"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "An input is missing, unknown, repeated or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/tv-height-distance": {
      "get": {
        "operationId": "tv_height_distance",
        "summary": "How high should I mount my TV, and how far away should I sit?",
        "description": "Use when someone asks how high to mount or hang a TV, whether it can go above a fireplace, or how far to sit from a screen of a given size. Returns the centre height, the edges, the viewing angles and the THX and SMPTE seat distances. Every rule cites its source. The calculator: https://snuug.app/tools/tv-height-distance",
        "tags": [
          "tools"
        ],
        "parameters": [
          {
            "name": "screen_size_in",
            "in": "query",
            "required": false,
            "description": "The screen’s diagonal size in inches, as sold (in).",
            "schema": {
              "type": "number",
              "default": 55,
              "minimum": 19,
              "maximum": 120
            }
          },
          {
            "name": "seat_distance_cm",
            "in": "query",
            "required": false,
            "description": "The distance from the seat to the screen (cm).",
            "schema": {
              "type": "number",
              "default": 270,
              "minimum": 80,
              "maximum": 1000
            }
          },
          {
            "name": "eye_height_cm",
            "in": "query",
            "required": false,
            "description": "Seated eye height from the floor (most sofas: 100–110 cm) (cm).",
            "schema": {
              "type": "number",
              "default": 105,
              "minimum": 60,
              "maximum": 180
            }
          },
          {
            "name": "above_fireplace",
            "in": "query",
            "required": false,
            "description": "yes if the screen goes above a fireplace or mantel.",
            "schema": {
              "type": "string",
              "default": "no",
              "enum": [
                "no",
                "yes"
              ]
            }
          },
          {
            "name": "mantel_height_cm",
            "in": "query",
            "required": false,
            "description": "The mantel’s height from the floor (only with above_fireplace yes) (cm).",
            "schema": {
              "type": "number",
              "default": 120,
              "minimum": 40,
              "maximum": 250
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (the default) or text: one paragraph to quote. Accept: text/plain does the same.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "text"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/tv_height_distance"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "An input is missing, unknown, repeated or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/picture-height": {
      "get": {
        "operationId": "picture_height",
        "summary": "How high should I hang a picture?",
        "description": "Use when someone asks how high to hang a picture, a print, a mirror or art, on an open wall or above a sofa, bed or sideboard. Returns the hook’s height from the floor and checks the art’s width against the furniture. Every rule cites its source. The calculator: https://snuug.app/tools/picture-height",
        "tags": [
          "tools"
        ],
        "parameters": [
          {
            "name": "frame_height_cm",
            "in": "query",
            "required": false,
            "description": "The frame’s height (cm).",
            "schema": {
              "type": "number",
              "default": 50,
              "minimum": 5,
              "maximum": 300
            }
          },
          {
            "name": "frame_width_cm",
            "in": "query",
            "required": false,
            "description": "The frame’s width (cm).",
            "schema": {
              "type": "number",
              "default": 40,
              "minimum": 5,
              "maximum": 400
            }
          },
          {
            "name": "hanger_drop_cm",
            "in": "query",
            "required": false,
            "description": "The hanger drop: from the frame’s top edge down to the wire pulled tight, or to the D-ring (cm).",
            "schema": {
              "type": "number",
              "default": 8,
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "place",
            "in": "query",
            "required": false,
            "description": "open_wall, or over_furniture (a sofa, bed or sideboard).",
            "schema": {
              "type": "string",
              "default": "open_wall",
              "enum": [
                "open_wall",
                "over_furniture"
              ]
            }
          },
          {
            "name": "centre_height_cm",
            "in": "query",
            "required": false,
            "description": "On an open wall, the picture’s centre height (default 145, the gallery height; 150 also common) (cm).",
            "schema": {
              "type": "number",
              "default": 145,
              "minimum": 100,
              "maximum": 200
            }
          },
          {
            "name": "furniture_height_cm",
            "in": "query",
            "required": false,
            "description": "Over furniture: the furniture’s top, from the floor (cm).",
            "schema": {
              "type": "number",
              "default": 85,
              "minimum": 20,
              "maximum": 200
            }
          },
          {
            "name": "furniture_gap_cm",
            "in": "query",
            "required": false,
            "description": "Over furniture: the gap from its top to the frame (designers use 15–25 cm) (cm).",
            "schema": {
              "type": "number",
              "default": 20,
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "furniture_width_cm",
            "in": "query",
            "required": false,
            "description": "Over furniture: its width, to check the art is about two thirds of it (cm).",
            "schema": {
              "type": "number",
              "default": 210,
              "minimum": 20,
              "maximum": 500
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (the default) or text: one paragraph to quote. Accept: text/plain does the same.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "text"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/picture_height"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "An input is missing, unknown, repeated or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/room-size": {
      "get": {
        "operationId": "room_size",
        "summary": "How big is my room in square metres or square feet?",
        "description": "Use when someone asks for a room’s floor area, perimeter, volume or carpet and skirting amounts, or what a size such as 3 × 4 m or 12 × 12 ft means (a box room, a single or double bedroom). Handles L-shaped rooms and bay windows. Every rule cites its source. The calculator: https://snuug.app/tools/room-size",
        "tags": [
          "tools"
        ],
        "parameters": [
          {
            "name": "shape",
            "in": "query",
            "required": false,
            "description": "rectangle, or l_shape (a second part on the right-hand wall, flush with the far corner).",
            "schema": {
              "type": "string",
              "default": "rectangle",
              "enum": [
                "rectangle",
                "l_shape"
              ]
            }
          },
          {
            "name": "room_width_cm",
            "in": "query",
            "required": false,
            "description": "The room’s width (along the window wall) (cm).",
            "schema": {
              "type": "number",
              "default": 350,
              "minimum": 30,
              "maximum": 5000
            }
          },
          {
            "name": "room_length_cm",
            "in": "query",
            "required": false,
            "description": "The room’s length (cm).",
            "schema": {
              "type": "number",
              "default": 400,
              "minimum": 30,
              "maximum": 5000
            }
          },
          {
            "name": "part2_length_cm",
            "in": "query",
            "required": false,
            "description": "An L-shaped room’s second part: its length along the main room (cm).",
            "schema": {
              "type": "number",
              "default": 200,
              "minimum": 0,
              "maximum": 5000
            }
          },
          {
            "name": "part2_depth_cm",
            "in": "query",
            "required": false,
            "description": "An L-shaped room’s second part: how far it sticks out (cm).",
            "schema": {
              "type": "number",
              "default": 150,
              "minimum": 0,
              "maximum": 5000
            }
          },
          {
            "name": "bay",
            "in": "query",
            "required": false,
            "description": "A bay window in the front wall: none, square (sides at 90°) or angled (sides at 45°, the usual UK canted bay).",
            "schema": {
              "type": "string",
              "default": "none",
              "enum": [
                "none",
                "square",
                "angled"
              ]
            }
          },
          {
            "name": "bay_width_cm",
            "in": "query",
            "required": false,
            "description": "The bay’s width at the wall (cm).",
            "schema": {
              "type": "number",
              "default": 200,
              "minimum": 0,
              "maximum": 5000
            }
          },
          {
            "name": "bay_depth_cm",
            "in": "query",
            "required": false,
            "description": "How far the bay sticks out (cm).",
            "schema": {
              "type": "number",
              "default": 60,
              "minimum": 0,
              "maximum": 500
            }
          },
          {
            "name": "ceiling_height_cm",
            "in": "query",
            "required": false,
            "description": "The ceiling height, for the volume (cm).",
            "schema": {
              "type": "number",
              "default": 240,
              "minimum": 150,
              "maximum": 1000
            }
          },
          {
            "name": "doors",
            "in": "query",
            "required": false,
            "description": "Doorways, left out of the skirting.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 0,
              "maximum": 12
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (the default) or text: one paragraph to quote. Accept: text/plain does the same.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "text"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/room_size"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "An input is missing, unknown, repeated or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/home-size": {
      "get": {
        "operationId": "home_size",
        "summary": "How much space does a home need for my household?",
        "description": "Use when someone asks how big a flat or house should be for a number of people or bedrooms, whether a home or bedroom is big enough, or what England’s nationally described space standard requires. England only; it is a planning standard for new homes. Every rule cites its source. The calculator: https://snuug.app/tools/home-size",
        "tags": [
          "tools"
        ],
        "parameters": [
          {
            "name": "people",
            "in": "query",
            "required": false,
            "description": "The people the home is for (one bed space each).",
            "schema": {
              "type": "integer",
              "default": 4,
              "minimum": 1,
              "maximum": 12
            }
          },
          {
            "name": "bedrooms",
            "in": "query",
            "required": false,
            "description": "The number of bedrooms.",
            "schema": {
              "type": "integer",
              "default": 3,
              "minimum": 1,
              "maximum": 6
            }
          },
          {
            "name": "storeys",
            "in": "query",
            "required": false,
            "description": "The floors the home has (1 for a flat).",
            "schema": {
              "type": "integer",
              "default": 2,
              "minimum": 1,
              "maximum": 3
            }
          },
          {
            "name": "home_area_m2",
            "in": "query",
            "required": false,
            "description": "Optional: the home’s gross internal floor area, to compare with the standard (m²).",
            "schema": {
              "type": "number",
              "minimum": 10,
              "maximum": 2000
            }
          },
          {
            "name": "bedroom_1_width_cm",
            "in": "query",
            "required": false,
            "description": "Optional: bedroom 1's width, with its length. The bedrooms are ranked by floor area before the checks (cm).",
            "schema": {
              "type": "number",
              "minimum": 100,
              "maximum": 2000
            }
          },
          {
            "name": "bedroom_1_length_cm",
            "in": "query",
            "required": false,
            "description": "Optional: bedroom 1's length, with its width (cm).",
            "schema": {
              "type": "number",
              "minimum": 100,
              "maximum": 2000
            }
          },
          {
            "name": "bedroom_2_width_cm",
            "in": "query",
            "required": false,
            "description": "Optional: bedroom 2's width, with its length. The bedrooms are ranked by floor area before the checks (cm).",
            "schema": {
              "type": "number",
              "minimum": 100,
              "maximum": 2000
            }
          },
          {
            "name": "bedroom_2_length_cm",
            "in": "query",
            "required": false,
            "description": "Optional: bedroom 2's length, with its width (cm).",
            "schema": {
              "type": "number",
              "minimum": 100,
              "maximum": 2000
            }
          },
          {
            "name": "bedroom_3_width_cm",
            "in": "query",
            "required": false,
            "description": "Optional: bedroom 3's width, with its length. The bedrooms are ranked by floor area before the checks (cm).",
            "schema": {
              "type": "number",
              "minimum": 100,
              "maximum": 2000
            }
          },
          {
            "name": "bedroom_3_length_cm",
            "in": "query",
            "required": false,
            "description": "Optional: bedroom 3's length, with its width (cm).",
            "schema": {
              "type": "number",
              "minimum": 100,
              "maximum": 2000
            }
          },
          {
            "name": "bedroom_4_width_cm",
            "in": "query",
            "required": false,
            "description": "Optional: bedroom 4's width, with its length. The bedrooms are ranked by floor area before the checks (cm).",
            "schema": {
              "type": "number",
              "minimum": 100,
              "maximum": 2000
            }
          },
          {
            "name": "bedroom_4_length_cm",
            "in": "query",
            "required": false,
            "description": "Optional: bedroom 4's length, with its width (cm).",
            "schema": {
              "type": "number",
              "minimum": 100,
              "maximum": 2000
            }
          },
          {
            "name": "bedroom_5_width_cm",
            "in": "query",
            "required": false,
            "description": "Optional: bedroom 5's width, with its length. The bedrooms are ranked by floor area before the checks (cm).",
            "schema": {
              "type": "number",
              "minimum": 100,
              "maximum": 2000
            }
          },
          {
            "name": "bedroom_5_length_cm",
            "in": "query",
            "required": false,
            "description": "Optional: bedroom 5's length, with its width (cm).",
            "schema": {
              "type": "number",
              "minimum": 100,
              "maximum": 2000
            }
          },
          {
            "name": "bedroom_6_width_cm",
            "in": "query",
            "required": false,
            "description": "Optional: bedroom 6's width, with its length. The bedrooms are ranked by floor area before the checks (cm).",
            "schema": {
              "type": "number",
              "minimum": 100,
              "maximum": 2000
            }
          },
          {
            "name": "bedroom_6_length_cm",
            "in": "query",
            "required": false,
            "description": "Optional: bedroom 6's length, with its width (cm).",
            "schema": {
              "type": "number",
              "minimum": 100,
              "maximum": 2000
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (the default) or text: one paragraph to quote. Accept: text/plain does the same.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "text"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/home_size"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "An input is missing, unknown, repeated or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/curtain-size": {
      "get": {
        "operationId": "curtain_size",
        "summary": "What size curtains do I need?",
        "description": "Use when someone asks what size curtains, curtain pole or track to buy, how high to hang a curtain pole, or which UK ready-made curtain size fits a window. Returns the pole’s length and height, the ready-made pair and the made-to-measure sizes. Every rule cites its source. The calculator: https://snuug.app/tools/curtain-size",
        "tags": [
          "tools"
        ],
        "parameters": [
          {
            "name": "window_width_cm",
            "in": "query",
            "required": false,
            "description": "The window’s width, outside the frame (cm).",
            "schema": {
              "type": "number",
              "default": 120,
              "minimum": 30,
              "maximum": 600
            }
          },
          {
            "name": "window_height_cm",
            "in": "query",
            "required": false,
            "description": "The window’s height, outside the frame (cm).",
            "schema": {
              "type": "number",
              "default": 115,
              "minimum": 30,
              "maximum": 400
            }
          },
          {
            "name": "sill_height_cm",
            "in": "query",
            "required": false,
            "description": "The sill’s height from the floor (cm).",
            "schema": {
              "type": "number",
              "default": 90,
              "minimum": 0,
              "maximum": 200
            }
          },
          {
            "name": "ceiling_height_cm",
            "in": "query",
            "required": false,
            "description": "The ceiling’s height from the floor (cm).",
            "schema": {
              "type": "number",
              "default": 240,
              "minimum": 180,
              "maximum": 500
            }
          },
          {
            "name": "fitting",
            "in": "query",
            "required": false,
            "description": "pole or track.",
            "schema": {
              "type": "string",
              "default": "pole",
              "enum": [
                "pole",
                "track"
              ]
            }
          },
          {
            "name": "heading",
            "in": "query",
            "required": false,
            "description": "The curtain heading: eyelet, pencil_pleat or tab_top.",
            "schema": {
              "type": "string",
              "default": "eyelet",
              "enum": [
                "eyelet",
                "pencil_pleat",
                "tab_top"
              ]
            }
          },
          {
            "name": "fullness",
            "in": "query",
            "required": false,
            "description": "The curtains’ total flat width ÷ the pole’s length; default the heading’s usual (2, or 1.5 for tab top).",
            "schema": {
              "type": "number",
              "default": 2,
              "minimum": 1.2,
              "maximum": 3
            }
          },
          {
            "name": "length",
            "in": "query",
            "required": false,
            "description": "Where the hem ends: sill, below_sill, floor or puddle (on the floor).",
            "schema": {
              "type": "string",
              "default": "floor",
              "enum": [
                "sill",
                "below_sill",
                "floor",
                "puddle"
              ]
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (the default) or text: one paragraph to quote. Accept: text/plain does the same.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "text"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/curtain_size"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "An input is missing, unknown, repeated or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/lighting": {
      "get": {
        "operationId": "room_lighting",
        "summary": "How many lumens do I need for my room?",
        "description": "Use when someone asks how bright a room’s lights should be, how many lumens, bulbs or downlights a room needs, how far apart to space downlights, or what colour temperature to choose. Every rule cites its source. The calculator: https://snuug.app/tools/lighting",
        "tags": [
          "tools"
        ],
        "parameters": [
          {
            "name": "room_length_cm",
            "in": "query",
            "required": false,
            "description": "The room’s length (cm).",
            "schema": {
              "type": "number",
              "default": 450,
              "minimum": 100,
              "maximum": 2000
            }
          },
          {
            "name": "room_width_cm",
            "in": "query",
            "required": false,
            "description": "The room’s width (cm).",
            "schema": {
              "type": "number",
              "default": 400,
              "minimum": 100,
              "maximum": 2000
            }
          },
          {
            "name": "ceiling_height_cm",
            "in": "query",
            "required": false,
            "description": "The ceiling height (cm).",
            "schema": {
              "type": "number",
              "default": 240,
              "minimum": 200,
              "maximum": 600
            }
          },
          {
            "name": "room_type",
            "in": "query",
            "required": false,
            "description": "living, bedroom, kitchen, bathroom or home_office.",
            "schema": {
              "type": "string",
              "default": "living",
              "enum": [
                "living",
                "bedroom",
                "kitchen",
                "bathroom",
                "home_office"
              ]
            }
          },
          {
            "name": "wall_colour",
            "in": "query",
            "required": false,
            "description": "light, or dark (dark walls reflect less, so the room needs more light).",
            "schema": {
              "type": "string",
              "default": "light",
              "enum": [
                "light",
                "dark"
              ]
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (the default) or text: one paragraph to quote. Accept: text/plain does the same.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "text"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/room_lighting"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "An input is missing, unknown, repeated or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/paint": {
      "get": {
        "operationId": "paint_quantity",
        "summary": "How much paint do I need for my room?",
        "description": "Use when someone asks how much paint, how many litres or which tins they need for a room’s walls, its ceiling or one feature wall. Returns litres and the cheapest mix of 5 l and 2.5 l tins. Every rule cites its source. The calculator: https://snuug.app/tools/paint",
        "tags": [
          "tools"
        ],
        "parameters": [
          {
            "name": "room_length_cm",
            "in": "query",
            "required": false,
            "description": "The room’s length (cm).",
            "schema": {
              "type": "number",
              "default": 400,
              "minimum": 100,
              "maximum": 3000
            }
          },
          {
            "name": "room_width_cm",
            "in": "query",
            "required": false,
            "description": "The room’s width (cm).",
            "schema": {
              "type": "number",
              "default": 300,
              "minimum": 100,
              "maximum": 3000
            }
          },
          {
            "name": "ceiling_height_cm",
            "in": "query",
            "required": false,
            "description": "The ceiling height (cm).",
            "schema": {
              "type": "number",
              "default": 240,
              "minimum": 150,
              "maximum": 600
            }
          },
          {
            "name": "surfaces",
            "in": "query",
            "required": false,
            "description": "What to paint: walls, ceiling, both (walls and ceiling) or feature (one wall).",
            "schema": {
              "type": "string",
              "default": "walls",
              "enum": [
                "walls",
                "ceiling",
                "both",
                "feature"
              ]
            }
          },
          {
            "name": "feature_wall",
            "in": "query",
            "required": false,
            "description": "For a feature wall: a length wall or a width wall.",
            "schema": {
              "type": "string",
              "default": "length",
              "enum": [
                "length",
                "width"
              ]
            }
          },
          {
            "name": "doors",
            "in": "query",
            "required": false,
            "description": "Doors to leave out (default 1; 0 for a feature wall).",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 0,
              "maximum": 12
            }
          },
          {
            "name": "windows",
            "in": "query",
            "required": false,
            "description": "Windows to leave out (default 1; 0 for a feature wall).",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 0,
              "maximum": 12
            }
          },
          {
            "name": "door_width_cm",
            "in": "query",
            "required": false,
            "description": "A door’s width (default the UK standard internal door) (cm).",
            "schema": {
              "type": "number",
              "default": 76.2,
              "minimum": 40,
              "maximum": 300
            }
          },
          {
            "name": "door_height_cm",
            "in": "query",
            "required": false,
            "description": "A door’s height (default the UK standard internal door) (cm).",
            "schema": {
              "type": "number",
              "default": 198.1,
              "minimum": 150,
              "maximum": 300
            }
          },
          {
            "name": "window_width_cm",
            "in": "query",
            "required": false,
            "description": "A window’s width (cm).",
            "schema": {
              "type": "number",
              "default": 120,
              "minimum": 20,
              "maximum": 600
            }
          },
          {
            "name": "window_height_cm",
            "in": "query",
            "required": false,
            "description": "A window’s height (cm).",
            "schema": {
              "type": "number",
              "default": 120,
              "minimum": 20,
              "maximum": 400
            }
          },
          {
            "name": "coats",
            "in": "query",
            "required": false,
            "description": "Coats of paint (default 2).",
            "schema": {
              "type": "integer",
              "default": 2,
              "minimum": 1,
              "maximum": 5
            }
          },
          {
            "name": "paint",
            "in": "query",
            "required": false,
            "description": "matt, silk or custom (then give coverage_m2_per_l).",
            "schema": {
              "type": "string",
              "default": "matt",
              "enum": [
                "matt",
                "silk",
                "custom"
              ]
            }
          },
          {
            "name": "coverage_m2_per_l",
            "in": "query",
            "required": false,
            "description": "The square metres a litre covers, from the tin (m²/l).",
            "schema": {
              "type": "number",
              "default": 13,
              "minimum": 3,
              "maximum": 25
            }
          },
          {
            "name": "new_plaster",
            "in": "query",
            "required": false,
            "description": "yes for new plaster, which needs a mist coat first.",
            "schema": {
              "type": "string",
              "default": "no",
              "enum": [
                "no",
                "yes"
              ]
            }
          },
          {
            "name": "spare_pct",
            "in": "query",
            "required": false,
            "description": "Extra paint to buy, in % (default 10) (%).",
            "schema": {
              "type": "number",
              "default": 10,
              "minimum": 0,
              "maximum": 50
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (the default) or text: one paragraph to quote. Accept: text/plain does the same.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "text"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/paint_quantity"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "An input is missing, unknown, repeated or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/wallpaper": {
      "get": {
        "operationId": "wallpaper_rolls",
        "summary": "How many rolls of wallpaper do I need?",
        "description": "Use when someone asks how many rolls of wallpaper they need for a room, some walls or one feature wall, including a pattern repeat and a straight or offset match. Every rule cites its source. The calculator: https://snuug.app/tools/wallpaper",
        "tags": [
          "tools"
        ],
        "parameters": [
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "description": "room (all four walls), walls (some walls) or feature (one wall).",
            "schema": {
              "type": "string",
              "default": "room",
              "enum": [
                "room",
                "walls",
                "feature"
              ]
            }
          },
          {
            "name": "room_length_cm",
            "in": "query",
            "required": false,
            "description": "For a room: its length (cm).",
            "schema": {
              "type": "number",
              "default": 400,
              "minimum": 100,
              "maximum": 3000
            }
          },
          {
            "name": "room_width_cm",
            "in": "query",
            "required": false,
            "description": "For a room: its width (cm).",
            "schema": {
              "type": "number",
              "default": 300,
              "minimum": 100,
              "maximum": 3000
            }
          },
          {
            "name": "wall_width_cm",
            "in": "query",
            "required": false,
            "description": "For walls or a feature wall: the width, the walls added up (cm).",
            "schema": {
              "type": "number",
              "default": 350,
              "minimum": 20,
              "maximum": 10000
            }
          },
          {
            "name": "wall_height_cm",
            "in": "query",
            "required": false,
            "description": "The wall height, skirting to ceiling (cm).",
            "schema": {
              "type": "number",
              "default": 240,
              "minimum": 50,
              "maximum": 600
            }
          },
          {
            "name": "roll_length_cm",
            "in": "query",
            "required": false,
            "description": "The roll’s length (default the UK standard, 1005 cm) (cm).",
            "schema": {
              "type": "number",
              "default": 1005,
              "minimum": 100,
              "maximum": 5000
            }
          },
          {
            "name": "roll_width_cm",
            "in": "query",
            "required": false,
            "description": "The roll’s width (default 53 cm) (cm).",
            "schema": {
              "type": "number",
              "default": 53,
              "minimum": 20,
              "maximum": 200
            }
          },
          {
            "name": "pattern_repeat_cm",
            "in": "query",
            "required": false,
            "description": "The pattern repeat, from the label (0 for none) (cm).",
            "schema": {
              "type": "number",
              "default": 0,
              "minimum": 0,
              "maximum": 200
            }
          },
          {
            "name": "match",
            "in": "query",
            "required": false,
            "description": "free (or plain), straight or offset (half-drop).",
            "schema": {
              "type": "string",
              "default": "free",
              "enum": [
                "free",
                "straight",
                "offset"
              ]
            }
          },
          {
            "name": "doors",
            "in": "query",
            "required": false,
            "description": "Doors, each saving a drop (default 1 for a room, else 0).",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 0,
              "maximum": 12
            }
          },
          {
            "name": "trim_cm",
            "in": "query",
            "required": false,
            "description": "Extra on each drop for trimming (default 10 cm) (cm).",
            "schema": {
              "type": "number",
              "default": 10,
              "minimum": 0,
              "maximum": 50
            }
          },
          {
            "name": "spare_rolls",
            "in": "query",
            "required": false,
            "description": "Spare rolls from the same batch (default 1).",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 0,
              "maximum": 10
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (the default) or text: one paragraph to quote. Accept: text/plain does the same.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "text"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/wallpaper_rolls"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "An input is missing, unknown, repeated or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/dining-table": {
      "get": {
        "operationId": "dining_table_size",
        "summary": "What size dining table fits my room, or seats my family?",
        "description": "Use when someone asks what size dining table fits a room, how many people a table seats, or how big a room must be for a table for a number of people. Uses UK stock table sizes and the space a chair needs behind it. Every rule cites its source. The calculator: https://snuug.app/tools/dining-table",
        "tags": [
          "tools"
        ],
        "parameters": [
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "description": "room (start from the room’s size) or people (start from how many people).",
            "schema": {
              "type": "string",
              "default": "room",
              "enum": [
                "room",
                "people"
              ]
            }
          },
          {
            "name": "room_width_cm",
            "in": "query",
            "required": false,
            "description": "In room mode: the room’s width (cm).",
            "schema": {
              "type": "number",
              "default": 300,
              "minimum": 150,
              "maximum": 1500
            }
          },
          {
            "name": "room_length_cm",
            "in": "query",
            "required": false,
            "description": "In room mode: the room’s length (cm).",
            "schema": {
              "type": "number",
              "default": 360,
              "minimum": 150,
              "maximum": 1500
            }
          },
          {
            "name": "people",
            "in": "query",
            "required": false,
            "description": "In people mode: the number of people.",
            "schema": {
              "type": "integer",
              "default": 6,
              "minimum": 1,
              "maximum": 14
            }
          },
          {
            "name": "shape",
            "in": "query",
            "required": false,
            "description": "rectangle, round or oval.",
            "schema": {
              "type": "string",
              "default": "rectangle",
              "enum": [
                "rectangle",
                "round",
                "oval"
              ]
            }
          },
          {
            "name": "clearance",
            "in": "query",
            "required": false,
            "description": "The gap behind the chairs: tight, no_traffic (to a wall), edge_past or walk_past (someone passes).",
            "schema": {
              "type": "string",
              "default": "edge_past",
              "enum": [
                "tight",
                "no_traffic",
                "edge_past",
                "walk_past"
              ]
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (the default) or text: one paragraph to quote. Accept: text/plain does the same.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "text"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/dining_table_size"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "An input is missing, unknown, repeated or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/pendant-light": {
      "get": {
        "operationId": "pendant_light",
        "summary": "How high should I hang a pendant light, and how big should it be?",
        "description": "Use when someone asks how high to hang a pendant or chandelier over a dining table or kitchen island, how long its drop should be, or what diameter of light suits a table or room. Every rule cites its source. The calculator: https://snuug.app/tools/pendant-light",
        "tags": [
          "tools"
        ],
        "parameters": [
          {
            "name": "place",
            "in": "query",
            "required": false,
            "description": "table (over a table or island) or floor (over open floor or a hall).",
            "schema": {
              "type": "string",
              "default": "table",
              "enum": [
                "table",
                "floor"
              ]
            }
          },
          {
            "name": "ceiling_height_cm",
            "in": "query",
            "required": false,
            "description": "The ceiling height (cm).",
            "schema": {
              "type": "number",
              "default": 240,
              "minimum": 180,
              "maximum": 600
            }
          },
          {
            "name": "fitting_height_cm",
            "in": "query",
            "required": false,
            "description": "The shade’s own height, top to bottom (cm).",
            "schema": {
              "type": "number",
              "default": 30,
              "minimum": 2,
              "maximum": 200
            }
          },
          {
            "name": "table_width_cm",
            "in": "query",
            "required": false,
            "description": "Over a table: its width (cm).",
            "schema": {
              "type": "number",
              "default": 90,
              "minimum": 40,
              "maximum": 200
            }
          },
          {
            "name": "table_length_cm",
            "in": "query",
            "required": false,
            "description": "Over a table: its length (cm).",
            "schema": {
              "type": "number",
              "default": 180,
              "minimum": 40,
              "maximum": 400
            }
          },
          {
            "name": "table_height_cm",
            "in": "query",
            "required": false,
            "description": "Over a table: its height (cm).",
            "schema": {
              "type": "number",
              "default": 75,
              "minimum": 40,
              "maximum": 120
            }
          },
          {
            "name": "lights",
            "in": "query",
            "required": false,
            "description": "Over a table: how many lights in a row (1–3).",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1,
              "maximum": 3
            }
          },
          {
            "name": "room_length_cm",
            "in": "query",
            "required": false,
            "description": "The room’s length, for the room-size rule (cm).",
            "schema": {
              "type": "number",
              "default": 400,
              "minimum": 100,
              "maximum": 2000
            }
          },
          {
            "name": "room_width_cm",
            "in": "query",
            "required": false,
            "description": "The room’s width, for the room-size rule (cm).",
            "schema": {
              "type": "number",
              "default": 350,
              "minimum": 100,
              "maximum": 2000
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (the default) or text: one paragraph to quote. Accept: text/plain does the same.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "text"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/pendant_light"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "An input is missing, unknown, repeated or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/kua-number": {
      "get": {
        "operationId": "kua_number",
        "summary": "What is my kua number, and which directions are lucky for me?",
        "description": "Use when someone asks for their feng shui kua number, East or West group, or favourable directions from a birth date. It reports what the Eight Mansions school says; feng shui is a tradition, not a science. Every rule cites its source. The calculator: https://snuug.app/tools/kua-number",
        "tags": [
          "tools"
        ],
        "parameters": [
          {
            "name": "birth_date",
            "in": "query",
            "required": true,
            "description": "The birth date, YYYY-MM-DD, from 1901 to 2099.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
              "examples": [
                "1990-06-15"
              ]
            }
          },
          {
            "name": "birth_time",
            "in": "query",
            "required": false,
            "description": "Optional: the local birth time, HH:MM. It matters only on the day of Li Chun (about 4 February).",
            "schema": {
              "type": "string",
              "pattern": "^\\d{1,2}:\\d{2}$",
              "examples": [
                "08:30"
              ]
            }
          },
          {
            "name": "utc_offset_minutes",
            "in": "query",
            "required": false,
            "description": "The birth place’s offset from UTC in early February, in minutes (0 for the UK, 480 for China) (minutes).",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": -720,
              "maximum": 840
            }
          },
          {
            "name": "formula",
            "in": "query",
            "required": false,
            "description": "both, female or male: the tradition has one formula for each sex at birth.",
            "schema": {
              "type": "string",
              "default": "both",
              "enum": [
                "both",
                "female",
                "male"
              ]
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (the default) or text: one paragraph to quote. Accept: text/plain does the same.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "text"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/kua_number"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "An input is missing, unknown, repeated or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/bagua-map": {
      "get": {
        "operationId": "bagua_map",
        "summary": "How do I lay a bagua map over my room?",
        "description": "Use when someone asks how to use a feng shui bagua map in a room or a home, which area of a room is wealth or relationships, or where their door falls on the bagua. It reports what the tradition says; feng shui is a tradition, not a science. Every rule cites its source. The calculator: https://snuug.app/tools/bagua-map",
        "tags": [
          "tools"
        ],
        "parameters": [
          {
            "name": "room_width_cm",
            "in": "query",
            "required": false,
            "description": "The room’s width, across the plan (cm).",
            "schema": {
              "type": "number",
              "default": 300,
              "minimum": 50,
              "maximum": 3000
            }
          },
          {
            "name": "room_length_cm",
            "in": "query",
            "required": false,
            "description": "The room’s length, up the plan (cm).",
            "schema": {
              "type": "number",
              "default": 350,
              "minimum": 50,
              "maximum": 3000
            }
          },
          {
            "name": "door_wall",
            "in": "query",
            "required": false,
            "description": "The wall the door is on, as drawn on the plan: bottom, left, top or right.",
            "schema": {
              "type": "string",
              "default": "bottom",
              "enum": [
                "bottom",
                "left",
                "top",
                "right"
              ]
            }
          },
          {
            "name": "door_position",
            "in": "query",
            "required": false,
            "description": "Where the door is on that wall, standing in the doorway looking in: left, middle or right.",
            "schema": {
              "type": "string",
              "default": "middle",
              "enum": [
                "left",
                "middle",
                "right"
              ]
            }
          },
          {
            "name": "method",
            "in": "query",
            "required": false,
            "description": "btb (from the door, the Western school) or compass.",
            "schema": {
              "type": "string",
              "default": "btb",
              "enum": [
                "btb",
                "compass"
              ]
            }
          },
          {
            "name": "facing",
            "in": "query",
            "required": false,
            "description": "For the compass method: the way you face as you walk in, N, NE, E, SE, S, SW, W or NW.",
            "schema": {
              "type": "string",
              "default": "N",
              "enum": [
                "N",
                "NE",
                "E",
                "SE",
                "S",
                "SW",
                "W",
                "NW"
              ]
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (the default) or text: one paragraph to quote. Accept: text/plain does the same.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "text"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/bagua_map"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "An input is missing, unknown, repeated or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "rug_size": {
        "type": "object",
        "required": [
          "tool",
          "version",
          "inputs",
          "answer",
          "summary",
          "working",
          "notes",
          "sources",
          "page_url",
          "snuug"
        ],
        "properties": {
          "tool": {
            "type": "string",
            "const": "rug-size",
            "description": "The tool, as named in its API and page URLs."
          },
          "version": {
            "type": "string",
            "description": "The version of this contract."
          },
          "inputs": {
            "type": "object",
            "description": "Every input as the tool used it: given, a default, or filled in from the rules.",
            "required": [
              "sofa_width_cm",
              "sofa_depth_cm",
              "room_width_cm",
              "room_length_cm",
              "legs_on_rug",
              "armchairs"
            ],
            "additionalProperties": false,
            "properties": {
              "sofa_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The sofa’s width, arm to arm (cm).",
                "minimum": 60,
                "maximum": 500
              },
              "sofa_depth_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The sofa’s depth, back to front (cm).",
                "minimum": 50,
                "maximum": 200
              },
              "room_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The room’s width along the wall the sofa stands against (cm).",
                "minimum": 150,
                "maximum": 1500
              },
              "room_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The room’s length, out from the sofa wall (cm).",
                "minimum": 150,
                "maximum": 1500
              },
              "legs_on_rug": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Which sofa legs stand on the rug: all, front (the usual choice) or none (the rug sits under the coffee table only).",
                "enum": [
                  "all",
                  "front",
                  "none"
                ]
              },
              "armchairs": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "none, or two armchairs facing the sofa, which the rug must also reach.",
                "enum": [
                  "none",
                  "two"
                ]
              }
            }
          },
          "answer": {
            "type": "object",
            "required": [
              "uk_rug",
              "us_rug",
              "needed",
              "least_floor_cm",
              "plan"
            ],
            "additionalProperties": false,
            "properties": {
              "uk_rug": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "A stock rug: name, width_cm (along the sofa), depth_cm, turned, meets_rule, past_sofa_end_cm (negative: short of the sofa), floor_each_side_cm, floor_far_end_cm, sofa_share. The smallest UK size that meets the rule and fits the room, else the closest that fits; null if none fits"
              },
              "us_rug": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "A stock rug: name, width_cm (along the sofa), depth_cm, turned, meets_rule, past_sofa_end_cm (negative: short of the sofa), floor_each_side_cm, floor_far_end_cm, sofa_share. The same for US sizes (in feet)"
              },
              "needed": {
                "type": "object",
                "description": "The rug the rule asks for: width_cm, ideal_width_cm, depth_cm"
              },
              "least_floor_cm": {
                "type": "number",
                "description": "The least bare floor between rug and wall"
              },
              "plan": {
                "type": "object",
                "description": "Where things sit, out from the sofa wall: rug_from_cm, table_from_cm, table_length_cm, chairs_from_cm"
              }
            },
            "description": "The answer as named values."
          },
          "summary": {
            "type": "string",
            "description": "The answer in one sentence to quote."
          },
          "working": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "How the answer was worked out, one step a line."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Caveats to pass on with the answer."
          },
          "sources": {
            "type": "array",
            "description": "The sources of the rules used. Every rule cites its source, with the date it was checked.",
            "items": {
              "type": "object",
              "required": [
                "label",
                "url",
                "checked"
              ],
              "properties": {
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "checked": {
                  "type": "string",
                  "format": "date"
                }
              }
            }
          },
          "page_url": {
            "type": "string",
            "format": "uri",
            "description": "The calculator on snuug.app with these inputs filled in."
          },
          "snuug": {
            "type": "string",
            "description": "One line about Snuug, the app behind the calculators."
          }
        }
      },
      "sofa_fit": {
        "type": "object",
        "required": [
          "tool",
          "version",
          "inputs",
          "answer",
          "summary",
          "working",
          "notes",
          "sources",
          "page_url",
          "snuug"
        ],
        "properties": {
          "tool": {
            "type": "string",
            "const": "sofa-fit",
            "description": "The tool, as named in its API and page URLs."
          },
          "version": {
            "type": "string",
            "description": "The version of this contract."
          },
          "inputs": {
            "type": "object",
            "description": "Every input as the tool used it: given, a default, or filled in from the rules.",
            "required": [
              "door_width_cm",
              "door_height_cm",
              "hall_width_cm",
              "route",
              "sofa_width_cm",
              "sofa_depth_cm",
              "sofa_height_cm",
              "sofa_diagonal_cm"
            ],
            "additionalProperties": false,
            "properties": {
              "door_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The door’s clear width: the gap with the door open, frame to door edge (cm).",
                "minimum": 40,
                "maximum": 300
              },
              "door_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The door’s clear height (cm).",
                "minimum": 120,
                "maximum": 400
              },
              "hall_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The width of the hall or landing beyond the door, where the sofa must turn (cm).",
                "minimum": 40,
                "maximum": 1000
              },
              "route": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "turn if the sofa must turn into the room after the door, straight if it goes straight on.",
                "enum": [
                  "turn",
                  "straight"
                ]
              },
              "sofa_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The sofa’s width, arm to arm (its length when carried) (cm).",
                "minimum": 50,
                "maximum": 500
              },
              "sofa_depth_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The sofa’s depth, back to front (cm).",
                "minimum": 40,
                "maximum": 250
              },
              "sofa_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The sofa’s height, floor to the top of the back (cm).",
                "minimum": 40,
                "maximum": 250
              },
              "sofa_diagonal_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The sofa’s diagonal depth: from the back bottom corner to a straight edge laid from the top of the back to the front of the arm (cm).",
                "minimum": 30,
                "maximum": 250
              }
            }
          },
          "answer": {
            "type": "object",
            "required": [
              "verdict",
              "door",
              "turn",
              "checks",
              "end_across_cm",
              "end_across",
              "margin_cm",
              "size_varies_pct"
            ],
            "additionalProperties": false,
            "properties": {
              "verdict": {
                "type": "string",
                "description": "ok, tight or no"
              },
              "door": {
                "type": "object",
                "description": "The better way through the door: how (straight or tipped), clear_cm (to spare; negative: too big), grade"
              },
              "turn": {
                "type": "object",
                "description": "The better way to turn after it: how (end, swing or none), clear_cm (null with none), grade"
              },
              "checks": {
                "type": "object",
                "description": "Each test: straight, tipped, on_end and swing, each with clear_cm and grade"
              },
              "end_across_cm": {
                "type": "number",
                "description": "The sofa’s end across the door"
              },
              "end_across": {
                "type": "string",
                "description": "Which side goes across: depth or height"
              },
              "margin_cm": {
                "type": "number",
                "description": "Under this much to spare is tight"
              },
              "size_varies_pct": {
                "type": "number",
                "description": "How far sofas vary from their listed size"
              }
            },
            "description": "The answer as named values."
          },
          "summary": {
            "type": "string",
            "description": "The answer in one sentence to quote."
          },
          "working": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "How the answer was worked out, one step a line."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Caveats to pass on with the answer."
          },
          "sources": {
            "type": "array",
            "description": "The sources of the rules used. Every rule cites its source, with the date it was checked.",
            "items": {
              "type": "object",
              "required": [
                "label",
                "url",
                "checked"
              ],
              "properties": {
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "checked": {
                  "type": "string",
                  "format": "date"
                }
              }
            }
          },
          "page_url": {
            "type": "string",
            "format": "uri",
            "description": "The calculator on snuug.app with these inputs filled in."
          },
          "snuug": {
            "type": "string",
            "description": "One line about Snuug, the app behind the calculators."
          }
        }
      },
      "tv_height_distance": {
        "type": "object",
        "required": [
          "tool",
          "version",
          "inputs",
          "answer",
          "summary",
          "working",
          "notes",
          "sources",
          "page_url",
          "snuug"
        ],
        "properties": {
          "tool": {
            "type": "string",
            "const": "tv-height-distance",
            "description": "The tool, as named in its API and page URLs."
          },
          "version": {
            "type": "string",
            "description": "The version of this contract."
          },
          "inputs": {
            "type": "object",
            "description": "Every input as the tool used it: given, a default, or filled in from the rules.",
            "required": [
              "screen_size_in",
              "seat_distance_cm",
              "eye_height_cm",
              "above_fireplace",
              "mantel_height_cm"
            ],
            "additionalProperties": false,
            "properties": {
              "screen_size_in": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The screen’s diagonal size in inches, as sold (in).",
                "minimum": 19,
                "maximum": 120
              },
              "seat_distance_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The distance from the seat to the screen (cm).",
                "minimum": 80,
                "maximum": 1000
              },
              "eye_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Seated eye height from the floor (most sofas: 100–110 cm) (cm).",
                "minimum": 60,
                "maximum": 180
              },
              "above_fireplace": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "yes if the screen goes above a fireplace or mantel.",
                "enum": [
                  "no",
                  "yes"
                ]
              },
              "mantel_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The mantel’s height from the floor (only with above_fireplace yes) (cm).",
                "minimum": 40,
                "maximum": 250
              }
            }
          },
          "answer": {
            "type": "object",
            "required": [
              "centre_height_cm",
              "bottom_edge_cm",
              "top_edge_cm",
              "screen_width_cm",
              "screen_height_cm",
              "look_up_deg",
              "look_down_deg",
              "within_limit",
              "limit_deg",
              "seat_for_limit_cm",
              "seat_range_cm",
              "thx_farthest_cm",
              "view_angle_deg",
              "size_for_seat",
              "study_seat_cm"
            ],
            "additionalProperties": false,
            "properties": {
              "centre_height_cm": {
                "type": "number",
                "description": "The screen’s centre from the floor"
              },
              "bottom_edge_cm": {
                "type": "number"
              },
              "top_edge_cm": {
                "type": "number"
              },
              "screen_width_cm": {
                "type": "number"
              },
              "screen_height_cm": {
                "type": "number"
              },
              "look_up_deg": {
                "type": "number",
                "description": "From the eyes to the top edge"
              },
              "look_down_deg": {
                "type": "number",
                "description": "From the eyes to the bottom edge (negative: up)"
              },
              "within_limit": {
                "type": "boolean",
                "description": "Both within limit_deg"
              },
              "limit_deg": {
                "type": "number",
                "description": "THX and CEDIA’s limit"
              },
              "seat_for_limit_cm": {
                "type": "number",
                "description": "The seat distance that keeps the top edge within the limit"
              },
              "seat_range_cm": {
                "type": "array",
                "description": "[THX 40°, SMPTE 30°] seat distances for this screen"
              },
              "thx_farthest_cm": {
                "type": "number",
                "description": "The far end of THX’s range"
              },
              "view_angle_deg": {
                "type": "number",
                "description": "How much of the view the screen fills from the seat"
              },
              "size_for_seat": {
                "type": "object",
                "description": "The screen sizes that fill SMPTE’s and THX’s angles from this seat: smpte_in, thx_in"
              },
              "study_seat_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The distance people chose in one lab study (24–65 in screens only)"
              }
            },
            "description": "The answer as named values."
          },
          "summary": {
            "type": "string",
            "description": "The answer in one sentence to quote."
          },
          "working": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "How the answer was worked out, one step a line."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Caveats to pass on with the answer."
          },
          "sources": {
            "type": "array",
            "description": "The sources of the rules used. Every rule cites its source, with the date it was checked.",
            "items": {
              "type": "object",
              "required": [
                "label",
                "url",
                "checked"
              ],
              "properties": {
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "checked": {
                  "type": "string",
                  "format": "date"
                }
              }
            }
          },
          "page_url": {
            "type": "string",
            "format": "uri",
            "description": "The calculator on snuug.app with these inputs filled in."
          },
          "snuug": {
            "type": "string",
            "description": "One line about Snuug, the app behind the calculators."
          }
        }
      },
      "picture_height": {
        "type": "object",
        "required": [
          "tool",
          "version",
          "inputs",
          "answer",
          "summary",
          "working",
          "notes",
          "sources",
          "page_url",
          "snuug"
        ],
        "properties": {
          "tool": {
            "type": "string",
            "const": "picture-height",
            "description": "The tool, as named in its API and page URLs."
          },
          "version": {
            "type": "string",
            "description": "The version of this contract."
          },
          "inputs": {
            "type": "object",
            "description": "Every input as the tool used it: given, a default, or filled in from the rules.",
            "required": [
              "frame_height_cm",
              "frame_width_cm",
              "hanger_drop_cm",
              "place",
              "centre_height_cm",
              "furniture_height_cm",
              "furniture_gap_cm",
              "furniture_width_cm"
            ],
            "additionalProperties": false,
            "properties": {
              "frame_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The frame’s height (cm).",
                "minimum": 5,
                "maximum": 300
              },
              "frame_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The frame’s width (cm).",
                "minimum": 5,
                "maximum": 400
              },
              "hanger_drop_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The hanger drop: from the frame’s top edge down to the wire pulled tight, or to the D-ring (cm).",
                "minimum": 0,
                "maximum": 100
              },
              "place": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "open_wall, or over_furniture (a sofa, bed or sideboard).",
                "enum": [
                  "open_wall",
                  "over_furniture"
                ]
              },
              "centre_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "On an open wall, the picture’s centre height (default 145, the gallery height; 150 also common) (cm).",
                "minimum": 100,
                "maximum": 200
              },
              "furniture_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Over furniture: the furniture’s top, from the floor (cm).",
                "minimum": 20,
                "maximum": 200
              },
              "furniture_gap_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Over furniture: the gap from its top to the frame (designers use 15–25 cm) (cm).",
                "minimum": 0,
                "maximum": 100
              },
              "furniture_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Over furniture: its width, to check the art is about two thirds of it (cm).",
                "minimum": 20,
                "maximum": 500
              }
            }
          },
          "answer": {
            "type": "object",
            "required": [
              "hook_height_cm",
              "picture_centre_cm",
              "bottom_edge_cm",
              "top_edge_cm",
              "width_share",
              "width_share_range",
              "ideal_width_cm"
            ],
            "additionalProperties": false,
            "properties": {
              "hook_height_cm": {
                "type": "number",
                "description": "The hook from the floor"
              },
              "picture_centre_cm": {
                "type": "number"
              },
              "bottom_edge_cm": {
                "type": "number"
              },
              "top_edge_cm": {
                "type": "number"
              },
              "width_share": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Over furniture: the frame’s width ÷ the furniture’s"
              },
              "width_share_range": {
                "type": [
                  "array",
                  "null"
                ],
                "description": "Over furniture: the share designers aim for"
              },
              "ideal_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Over furniture: two thirds of its width"
              }
            },
            "description": "The answer as named values."
          },
          "summary": {
            "type": "string",
            "description": "The answer in one sentence to quote."
          },
          "working": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "How the answer was worked out, one step a line."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Caveats to pass on with the answer."
          },
          "sources": {
            "type": "array",
            "description": "The sources of the rules used. Every rule cites its source, with the date it was checked.",
            "items": {
              "type": "object",
              "required": [
                "label",
                "url",
                "checked"
              ],
              "properties": {
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "checked": {
                  "type": "string",
                  "format": "date"
                }
              }
            }
          },
          "page_url": {
            "type": "string",
            "format": "uri",
            "description": "The calculator on snuug.app with these inputs filled in."
          },
          "snuug": {
            "type": "string",
            "description": "One line about Snuug, the app behind the calculators."
          }
        }
      },
      "room_size": {
        "type": "object",
        "required": [
          "tool",
          "version",
          "inputs",
          "answer",
          "summary",
          "working",
          "notes",
          "sources",
          "page_url",
          "snuug"
        ],
        "properties": {
          "tool": {
            "type": "string",
            "const": "room-size",
            "description": "The tool, as named in its API and page URLs."
          },
          "version": {
            "type": "string",
            "description": "The version of this contract."
          },
          "inputs": {
            "type": "object",
            "description": "Every input as the tool used it: given, a default, or filled in from the rules.",
            "required": [
              "shape",
              "room_width_cm",
              "room_length_cm",
              "part2_length_cm",
              "part2_depth_cm",
              "bay",
              "bay_width_cm",
              "bay_depth_cm",
              "ceiling_height_cm",
              "doors"
            ],
            "additionalProperties": false,
            "properties": {
              "shape": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "rectangle, or l_shape (a second part on the right-hand wall, flush with the far corner).",
                "enum": [
                  "rectangle",
                  "l_shape"
                ]
              },
              "room_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The room’s width (along the window wall) (cm).",
                "minimum": 30,
                "maximum": 5000
              },
              "room_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The room’s length (cm).",
                "minimum": 30,
                "maximum": 5000
              },
              "part2_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "An L-shaped room’s second part: its length along the main room (cm).",
                "minimum": 0,
                "maximum": 5000
              },
              "part2_depth_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "An L-shaped room’s second part: how far it sticks out (cm).",
                "minimum": 0,
                "maximum": 5000
              },
              "bay": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "A bay window in the front wall: none, square (sides at 90°) or angled (sides at 45°, the usual UK canted bay).",
                "enum": [
                  "none",
                  "square",
                  "angled"
                ]
              },
              "bay_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The bay’s width at the wall (cm).",
                "minimum": 0,
                "maximum": 5000
              },
              "bay_depth_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "How far the bay sticks out (cm).",
                "minimum": 0,
                "maximum": 500
              },
              "ceiling_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The ceiling height, for the volume (cm).",
                "minimum": 150,
                "maximum": 1000
              },
              "doors": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Doorways, left out of the skirting.",
                "minimum": 0,
                "maximum": 12
              }
            }
          },
          "answer": {
            "type": "object",
            "required": [
              "area_m2",
              "area_sq_ft",
              "parts",
              "perimeter_cm",
              "walls_cm",
              "skirting_cm",
              "skirting_boards",
              "volume_m3",
              "volume_cu_ft",
              "bounds",
              "carpet",
              "average_home_share",
              "polygon_cm"
            ],
            "additionalProperties": false,
            "properties": {
              "area_m2": {
                "type": "number",
                "description": "The floor area"
              },
              "area_sq_ft": {
                "type": "number"
              },
              "parts": {
                "type": "object",
                "description": "The area by part: main_m2, part2_m2, bay_m2"
              },
              "perimeter_cm": {
                "type": "number"
              },
              "walls_cm": {
                "type": "array",
                "description": "Each wall, round the room"
              },
              "skirting_cm": {
                "type": "number",
                "description": "The perimeter less the doorways"
              },
              "skirting_boards": {
                "type": "array",
                "description": "Boards to buy by length: board_cm, count"
              },
              "volume_m3": {
                "type": "number"
              },
              "volume_cu_ft": {
                "type": "number"
              },
              "bounds": {
                "type": "object",
                "description": "The room’s outer size: width_cm, length_cm"
              },
              "carpet": {
                "type": "object",
                "description": "The cheapest cut: roll_cm, cut_cm, joins, bought_m2"
              },
              "average_home_share": {
                "type": "number",
                "description": "The floor area ÷ the average home in England’s"
              },
              "polygon_cm": {
                "type": "array",
                "description": "The floor as [x, y] corners, the window wall along y = 0"
              }
            },
            "description": "The answer as named values."
          },
          "summary": {
            "type": "string",
            "description": "The answer in one sentence to quote."
          },
          "working": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "How the answer was worked out, one step a line."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Caveats to pass on with the answer."
          },
          "sources": {
            "type": "array",
            "description": "The sources of the rules used. Every rule cites its source, with the date it was checked.",
            "items": {
              "type": "object",
              "required": [
                "label",
                "url",
                "checked"
              ],
              "properties": {
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "checked": {
                  "type": "string",
                  "format": "date"
                }
              }
            }
          },
          "page_url": {
            "type": "string",
            "format": "uri",
            "description": "The calculator on snuug.app with these inputs filled in."
          },
          "snuug": {
            "type": "string",
            "description": "One line about Snuug, the app behind the calculators."
          }
        }
      },
      "home_size": {
        "type": "object",
        "required": [
          "tool",
          "version",
          "inputs",
          "answer",
          "summary",
          "working",
          "notes",
          "sources",
          "page_url",
          "snuug"
        ],
        "properties": {
          "tool": {
            "type": "string",
            "const": "home-size",
            "description": "The tool, as named in its API and page URLs."
          },
          "version": {
            "type": "string",
            "description": "The version of this contract."
          },
          "inputs": {
            "type": "object",
            "description": "Every input as the tool used it: given, a default, or filled in from the rules.",
            "required": [
              "people",
              "bedrooms",
              "storeys",
              "home_area_m2",
              "bedroom_1_width_cm",
              "bedroom_1_length_cm",
              "bedroom_2_width_cm",
              "bedroom_2_length_cm",
              "bedroom_3_width_cm",
              "bedroom_3_length_cm",
              "bedroom_4_width_cm",
              "bedroom_4_length_cm",
              "bedroom_5_width_cm",
              "bedroom_5_length_cm",
              "bedroom_6_width_cm",
              "bedroom_6_length_cm"
            ],
            "additionalProperties": false,
            "properties": {
              "people": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The people the home is for (one bed space each).",
                "minimum": 1,
                "maximum": 12
              },
              "bedrooms": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The number of bedrooms.",
                "minimum": 1,
                "maximum": 6
              },
              "storeys": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The floors the home has (1 for a flat).",
                "minimum": 1,
                "maximum": 3
              },
              "home_area_m2": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Optional: the home’s gross internal floor area, to compare with the standard (m²).",
                "minimum": 10,
                "maximum": 2000
              },
              "bedroom_1_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Optional: bedroom 1's width, with its length. The bedrooms are ranked by floor area before the checks (cm).",
                "minimum": 100,
                "maximum": 2000
              },
              "bedroom_1_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Optional: bedroom 1's length, with its width (cm).",
                "minimum": 100,
                "maximum": 2000
              },
              "bedroom_2_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Optional: bedroom 2's width, with its length. The bedrooms are ranked by floor area before the checks (cm).",
                "minimum": 100,
                "maximum": 2000
              },
              "bedroom_2_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Optional: bedroom 2's length, with its width (cm).",
                "minimum": 100,
                "maximum": 2000
              },
              "bedroom_3_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Optional: bedroom 3's width, with its length. The bedrooms are ranked by floor area before the checks (cm).",
                "minimum": 100,
                "maximum": 2000
              },
              "bedroom_3_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Optional: bedroom 3's length, with its width (cm).",
                "minimum": 100,
                "maximum": 2000
              },
              "bedroom_4_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Optional: bedroom 4's width, with its length. The bedrooms are ranked by floor area before the checks (cm).",
                "minimum": 100,
                "maximum": 2000
              },
              "bedroom_4_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Optional: bedroom 4's length, with its width (cm).",
                "minimum": 100,
                "maximum": 2000
              },
              "bedroom_5_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Optional: bedroom 5's width, with its length. The bedrooms are ranked by floor area before the checks (cm).",
                "minimum": 100,
                "maximum": 2000
              },
              "bedroom_5_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Optional: bedroom 5's length, with its width (cm).",
                "minimum": 100,
                "maximum": 2000
              },
              "bedroom_6_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Optional: bedroom 6's width, with its length. The bedrooms are ranked by floor area before the checks (cm).",
                "minimum": 100,
                "maximum": 2000
              },
              "bedroom_6_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Optional: bedroom 6's length, with its width (cm).",
                "minimum": 100,
                "maximum": 2000
              }
            }
          },
          "answer": {
            "type": "object",
            "required": [
              "type",
              "bed_spaces",
              "doubles",
              "singles",
              "storeys_used",
              "min_area_m2",
              "min_area_sq_ft",
              "storage_m2",
              "ceiling_cm",
              "bedroom_plan",
              "bedrooms_checked",
              "bedroom_bed_spaces",
              "home",
              "averages"
            ],
            "additionalProperties": false,
            "properties": {
              "type": {
                "type": "string",
                "description": "The standard’s home type, bedrooms (b) and bed spaces (p): 3b4p"
              },
              "bed_spaces": {
                "type": "number"
              },
              "doubles": {
                "type": "number"
              },
              "singles": {
                "type": "number"
              },
              "storeys_used": {
                "type": "number",
                "description": "The storey column used"
              },
              "min_area_m2": {
                "type": "number",
                "description": "The least gross internal area for a new home"
              },
              "min_area_sq_ft": {
                "type": "number"
              },
              "storage_m2": {
                "type": "number",
                "description": "The built-in storage within it"
              },
              "ceiling_cm": {
                "type": "number",
                "description": "The standard’s least ceiling height"
              },
              "bedroom_plan": {
                "type": "array",
                "description": "Each bedroom the standard plans, largest first: place, slot, min_area_m2, min_width_cm"
              },
              "bedrooms_checked": {
                "type": "array",
                "description": "Each given bedroom: bedroom, width_cm, length_cm, area_m2, narrow_cm, counts_as, slot, needs (area_m2, width_cm), grade, bed_spaces"
              },
              "bedroom_bed_spaces": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The bed spaces the given bedrooms make (all must be given)"
              },
              "home": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "The given home against the standard: area_m2, vs_min_m2, min_share, per_person_m2"
              },
              "averages": {
                "type": "object",
                "description": "England’s averages: england_m2, typical (home, area_m2), england_per_person_m2, household_people"
              }
            },
            "description": "The answer as named values."
          },
          "summary": {
            "type": "string",
            "description": "The answer in one sentence to quote."
          },
          "working": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "How the answer was worked out, one step a line."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Caveats to pass on with the answer."
          },
          "sources": {
            "type": "array",
            "description": "The sources of the rules used. Every rule cites its source, with the date it was checked.",
            "items": {
              "type": "object",
              "required": [
                "label",
                "url",
                "checked"
              ],
              "properties": {
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "checked": {
                  "type": "string",
                  "format": "date"
                }
              }
            }
          },
          "page_url": {
            "type": "string",
            "format": "uri",
            "description": "The calculator on snuug.app with these inputs filled in."
          },
          "snuug": {
            "type": "string",
            "description": "One line about Snuug, the app behind the calculators."
          }
        }
      },
      "curtain_size": {
        "type": "object",
        "required": [
          "tool",
          "version",
          "inputs",
          "answer",
          "summary",
          "working",
          "notes",
          "sources",
          "page_url",
          "snuug"
        ],
        "properties": {
          "tool": {
            "type": "string",
            "const": "curtain-size",
            "description": "The tool, as named in its API and page URLs."
          },
          "version": {
            "type": "string",
            "description": "The version of this contract."
          },
          "inputs": {
            "type": "object",
            "description": "Every input as the tool used it: given, a default, or filled in from the rules.",
            "required": [
              "window_width_cm",
              "window_height_cm",
              "sill_height_cm",
              "ceiling_height_cm",
              "fitting",
              "heading",
              "fullness",
              "length"
            ],
            "additionalProperties": false,
            "properties": {
              "window_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The window’s width, outside the frame (cm).",
                "minimum": 30,
                "maximum": 600
              },
              "window_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The window’s height, outside the frame (cm).",
                "minimum": 30,
                "maximum": 400
              },
              "sill_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The sill’s height from the floor (cm).",
                "minimum": 0,
                "maximum": 200
              },
              "ceiling_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The ceiling’s height from the floor (cm).",
                "minimum": 180,
                "maximum": 500
              },
              "fitting": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "pole or track.",
                "enum": [
                  "pole",
                  "track"
                ]
              },
              "heading": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The curtain heading: eyelet, pencil_pleat or tab_top.",
                "enum": [
                  "eyelet",
                  "pencil_pleat",
                  "tab_top"
                ]
              },
              "fullness": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The curtains’ total flat width ÷ the pole’s length; default the heading’s usual (2, or 1.5 for tab top).",
                "minimum": 1.2,
                "maximum": 3
              },
              "length": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Where the hem ends: sill, below_sill, floor or puddle (on the floor).",
                "enum": [
                  "sill",
                  "below_sill",
                  "floor",
                  "puddle"
                ]
              }
            }
          },
          "answer": {
            "type": "object",
            "required": [
              "pole_length_cm",
              "pole_top_cm",
              "above_window_cm",
              "below_ceiling_cm",
              "ready_made",
              "made_to_measure",
              "window_top_cm",
              "overhang_cm",
              "hem_cm",
              "hem_at",
              "ring_eye_cm",
              "two_thirds_cm",
              "lowest_pole_top_cm",
              "highest_pole_top_cm",
              "room_above",
              "stack_cm",
              "glass_covered_cm"
            ],
            "additionalProperties": false,
            "properties": {
              "pole_length_cm": {
                "type": "number",
                "description": "Without the finials"
              },
              "pole_top_cm": {
                "type": "number",
                "description": "The pole’s top from the floor"
              },
              "above_window_cm": {
                "type": "number",
                "description": "(negative: below the window top, when the ceiling leaves no room)"
              },
              "below_ceiling_cm": {
                "type": "number"
              },
              "ready_made": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "The UK ready-made pair: name, width_cm, drop_cm, width_in, drop_in, shorten_cm, fullness"
              },
              "made_to_measure": {
                "type": "object",
                "description": "pole_width_cm, drop_cm, fabric_width_cm"
              },
              "window_top_cm": {
                "type": "number"
              },
              "overhang_cm": {
                "type": "number",
                "description": "The pole past each side of the window"
              },
              "hem_cm": {
                "type": "number",
                "description": "The hem from the floor (negative: on the floor, puddled)"
              },
              "hem_at": {
                "type": "string",
                "description": "The length used (below_sill becomes floor when the sill is low)"
              },
              "ring_eye_cm": {
                "type": "number",
                "description": "Where the drop is measured from, below the pole top"
              },
              "two_thirds_cm": {
                "type": "number",
                "description": "Two thirds of the way to the ceiling"
              },
              "lowest_pole_top_cm": {
                "type": "number"
              },
              "highest_pole_top_cm": {
                "type": "number"
              },
              "room_above": {
                "type": "string",
                "description": "ok, tight or none: the room above the window for a pole"
              },
              "stack_cm": {
                "type": "number",
                "description": "Each open curtain’s stack"
              },
              "glass_covered_cm": {
                "type": "number",
                "description": "How much glass each stack covers"
              }
            },
            "description": "The answer as named values."
          },
          "summary": {
            "type": "string",
            "description": "The answer in one sentence to quote."
          },
          "working": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "How the answer was worked out, one step a line."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Caveats to pass on with the answer."
          },
          "sources": {
            "type": "array",
            "description": "The sources of the rules used. Every rule cites its source, with the date it was checked.",
            "items": {
              "type": "object",
              "required": [
                "label",
                "url",
                "checked"
              ],
              "properties": {
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "checked": {
                  "type": "string",
                  "format": "date"
                }
              }
            }
          },
          "page_url": {
            "type": "string",
            "format": "uri",
            "description": "The calculator on snuug.app with these inputs filled in."
          },
          "snuug": {
            "type": "string",
            "description": "One line about Snuug, the app behind the calculators."
          }
        }
      },
      "room_lighting": {
        "type": "object",
        "required": [
          "tool",
          "version",
          "inputs",
          "answer",
          "summary",
          "working",
          "notes",
          "sources",
          "page_url",
          "snuug"
        ],
        "properties": {
          "tool": {
            "type": "string",
            "const": "lighting",
            "description": "The tool, as named in its API and page URLs."
          },
          "version": {
            "type": "string",
            "description": "The version of this contract."
          },
          "inputs": {
            "type": "object",
            "description": "Every input as the tool used it: given, a default, or filled in from the rules.",
            "required": [
              "room_length_cm",
              "room_width_cm",
              "ceiling_height_cm",
              "room_type",
              "wall_colour"
            ],
            "additionalProperties": false,
            "properties": {
              "room_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The room’s length (cm).",
                "minimum": 100,
                "maximum": 2000
              },
              "room_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The room’s width (cm).",
                "minimum": 100,
                "maximum": 2000
              },
              "ceiling_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The ceiling height (cm).",
                "minimum": 200,
                "maximum": 600
              },
              "room_type": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "living, bedroom, kitchen, bathroom or home_office.",
                "enum": [
                  "living",
                  "bedroom",
                  "kitchen",
                  "bathroom",
                  "home_office"
                ]
              },
              "wall_colour": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "light, or dark (dark walls reflect less, so the room needs more light).",
                "enum": [
                  "light",
                  "dark"
                ]
              }
            }
          },
          "answer": {
            "type": "object",
            "required": [
              "total_lm",
              "target_lux",
              "task_lux",
              "layers",
              "bulbs",
              "downlights",
              "colour_temperature_k",
              "area_m2",
              "room_index",
              "utilisation",
              "utilisation_light_walls",
              "task_light"
            ],
            "additionalProperties": false,
            "properties": {
              "total_lm": {
                "type": "array",
                "description": "[low, high] lumens from all bulbs together"
              },
              "target_lux": {
                "type": "array",
                "description": "[low, high]"
              },
              "task_lux": {
                "type": "number",
                "description": "Where you read, chop or work"
              },
              "layers": {
                "type": "object",
                "description": "ceiling, lamps and task, each share_pct and light_lm [low, high]"
              },
              "bulbs": {
                "type": "array",
                "description": "bulb_lm and count [low, high] of that bulb"
              },
              "downlights": {
                "type": "object",
                "description": "If the ceiling light is downlights: count, columns, rows, spacing_cm, from_wall_cm, each_lm"
              },
              "colour_temperature_k": {
                "type": "array",
                "description": "[low, high]"
              },
              "area_m2": {
                "type": "number"
              },
              "room_index": {
                "type": "number"
              },
              "utilisation": {
                "type": "number",
                "description": "The share of the light that reaches the floor"
              },
              "utilisation_light_walls": {
                "type": "number",
                "description": "The same with light walls"
              },
              "task_light": {
                "type": "string",
                "description": "The task light this room needs"
              }
            },
            "description": "The answer as named values."
          },
          "summary": {
            "type": "string",
            "description": "The answer in one sentence to quote."
          },
          "working": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "How the answer was worked out, one step a line."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Caveats to pass on with the answer."
          },
          "sources": {
            "type": "array",
            "description": "The sources of the rules used. Every rule cites its source, with the date it was checked.",
            "items": {
              "type": "object",
              "required": [
                "label",
                "url",
                "checked"
              ],
              "properties": {
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "checked": {
                  "type": "string",
                  "format": "date"
                }
              }
            }
          },
          "page_url": {
            "type": "string",
            "format": "uri",
            "description": "The calculator on snuug.app with these inputs filled in."
          },
          "snuug": {
            "type": "string",
            "description": "One line about Snuug, the app behind the calculators."
          }
        }
      },
      "paint_quantity": {
        "type": "object",
        "required": [
          "tool",
          "version",
          "inputs",
          "answer",
          "summary",
          "working",
          "notes",
          "sources",
          "page_url",
          "snuug"
        ],
        "properties": {
          "tool": {
            "type": "string",
            "const": "paint",
            "description": "The tool, as named in its API and page URLs."
          },
          "version": {
            "type": "string",
            "description": "The version of this contract."
          },
          "inputs": {
            "type": "object",
            "description": "Every input as the tool used it: given, a default, or filled in from the rules.",
            "required": [
              "room_length_cm",
              "room_width_cm",
              "ceiling_height_cm",
              "surfaces",
              "feature_wall",
              "doors",
              "windows",
              "door_width_cm",
              "door_height_cm",
              "window_width_cm",
              "window_height_cm",
              "coats",
              "paint",
              "coverage_m2_per_l",
              "new_plaster",
              "spare_pct"
            ],
            "additionalProperties": false,
            "properties": {
              "room_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The room’s length (cm).",
                "minimum": 100,
                "maximum": 3000
              },
              "room_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The room’s width (cm).",
                "minimum": 100,
                "maximum": 3000
              },
              "ceiling_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The ceiling height (cm).",
                "minimum": 150,
                "maximum": 600
              },
              "surfaces": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "What to paint: walls, ceiling, both (walls and ceiling) or feature (one wall).",
                "enum": [
                  "walls",
                  "ceiling",
                  "both",
                  "feature"
                ]
              },
              "feature_wall": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "For a feature wall: a length wall or a width wall.",
                "enum": [
                  "length",
                  "width"
                ]
              },
              "doors": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Doors to leave out (default 1; 0 for a feature wall).",
                "minimum": 0,
                "maximum": 12
              },
              "windows": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Windows to leave out (default 1; 0 for a feature wall).",
                "minimum": 0,
                "maximum": 12
              },
              "door_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "A door’s width (default the UK standard internal door) (cm).",
                "minimum": 40,
                "maximum": 300
              },
              "door_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "A door’s height (default the UK standard internal door) (cm).",
                "minimum": 150,
                "maximum": 300
              },
              "window_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "A window’s width (cm).",
                "minimum": 20,
                "maximum": 600
              },
              "window_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "A window’s height (cm).",
                "minimum": 20,
                "maximum": 400
              },
              "coats": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Coats of paint (default 2).",
                "minimum": 1,
                "maximum": 5
              },
              "paint": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "matt, silk or custom (then give coverage_m2_per_l).",
                "enum": [
                  "matt",
                  "silk",
                  "custom"
                ]
              },
              "coverage_m2_per_l": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The square metres a litre covers, from the tin (m²/l).",
                "minimum": 3,
                "maximum": 25
              },
              "new_plaster": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "yes for new plaster, which needs a mist coat first.",
                "enum": [
                  "no",
                  "yes"
                ]
              },
              "spare_pct": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Extra paint to buy, in % (default 10) (%).",
                "minimum": 0,
                "maximum": 50
              }
            }
          },
          "answer": {
            "type": "object",
            "required": [
              "paint_l",
              "with_spare_l",
              "tins",
              "tins_text",
              "in_tins_l",
              "tins_without_spare",
              "tins_without_spare_text",
              "area",
              "mist_coat"
            ],
            "additionalProperties": false,
            "properties": {
              "paint_l": {
                "type": "number",
                "description": "The paint the job uses"
              },
              "with_spare_l": {
                "type": "number",
                "description": "With the spare"
              },
              "tins": {
                "type": "array",
                "description": "The tins to buy: size_l, count"
              },
              "tins_text": {
                "type": "string",
                "description": "The tins in words"
              },
              "in_tins_l": {
                "type": "number",
                "description": "What those tins hold"
              },
              "tins_without_spare": {
                "type": "array"
              },
              "tins_without_spare_text": {
                "type": "string"
              },
              "area": {
                "type": "object",
                "description": "walls_gross_m2, openings_m2, walls_net_m2, ceiling_m2, total_m2"
              },
              "mist_coat": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "New plaster only: paint_l and paint_to_water [parts, parts]"
              }
            },
            "description": "The answer as named values."
          },
          "summary": {
            "type": "string",
            "description": "The answer in one sentence to quote."
          },
          "working": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "How the answer was worked out, one step a line."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Caveats to pass on with the answer."
          },
          "sources": {
            "type": "array",
            "description": "The sources of the rules used. Every rule cites its source, with the date it was checked.",
            "items": {
              "type": "object",
              "required": [
                "label",
                "url",
                "checked"
              ],
              "properties": {
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "checked": {
                  "type": "string",
                  "format": "date"
                }
              }
            }
          },
          "page_url": {
            "type": "string",
            "format": "uri",
            "description": "The calculator on snuug.app with these inputs filled in."
          },
          "snuug": {
            "type": "string",
            "description": "One line about Snuug, the app behind the calculators."
          }
        }
      },
      "wallpaper_rolls": {
        "type": "object",
        "required": [
          "tool",
          "version",
          "inputs",
          "answer",
          "summary",
          "working",
          "notes",
          "sources",
          "page_url",
          "snuug"
        ],
        "properties": {
          "tool": {
            "type": "string",
            "const": "wallpaper",
            "description": "The tool, as named in its API and page URLs."
          },
          "version": {
            "type": "string",
            "description": "The version of this contract."
          },
          "inputs": {
            "type": "object",
            "description": "Every input as the tool used it: given, a default, or filled in from the rules.",
            "required": [
              "mode",
              "room_length_cm",
              "room_width_cm",
              "wall_width_cm",
              "wall_height_cm",
              "roll_length_cm",
              "roll_width_cm",
              "pattern_repeat_cm",
              "match",
              "doors",
              "trim_cm",
              "spare_rolls"
            ],
            "additionalProperties": false,
            "properties": {
              "mode": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "room (all four walls), walls (some walls) or feature (one wall).",
                "enum": [
                  "room",
                  "walls",
                  "feature"
                ]
              },
              "room_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "For a room: its length (cm).",
                "minimum": 100,
                "maximum": 3000
              },
              "room_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "For a room: its width (cm).",
                "minimum": 100,
                "maximum": 3000
              },
              "wall_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "For walls or a feature wall: the width, the walls added up (cm).",
                "minimum": 20,
                "maximum": 10000
              },
              "wall_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The wall height, skirting to ceiling (cm).",
                "minimum": 50,
                "maximum": 600
              },
              "roll_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The roll’s length (default the UK standard, 1005 cm) (cm).",
                "minimum": 100,
                "maximum": 5000
              },
              "roll_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The roll’s width (default 53 cm) (cm).",
                "minimum": 20,
                "maximum": 200
              },
              "pattern_repeat_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The pattern repeat, from the label (0 for none) (cm).",
                "minimum": 0,
                "maximum": 200
              },
              "match": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "free (or plain), straight or offset (half-drop).",
                "enum": [
                  "free",
                  "straight",
                  "offset"
                ]
              },
              "doors": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Doors, each saving a drop (default 1 for a room, else 0).",
                "minimum": 0,
                "maximum": 12
              },
              "trim_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Extra on each drop for trimming (default 10 cm) (cm).",
                "minimum": 0,
                "maximum": 50
              },
              "spare_rolls": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Spare rolls from the same batch (default 1).",
                "minimum": 0,
                "maximum": 10
              }
            }
          },
          "answer": {
            "type": "object",
            "required": [
              "rolls",
              "rolls_without_spare",
              "spare_rolls",
              "drops_needed",
              "drops_per_roll",
              "cuts"
            ],
            "additionalProperties": false,
            "properties": {
              "rolls": {
                "type": "number",
                "description": "Rolls to buy, the spare included"
              },
              "rolls_without_spare": {
                "type": "number"
              },
              "spare_rolls": {
                "type": "number"
              },
              "drops_needed": {
                "type": "number"
              },
              "drops_per_roll": {
                "type": "number"
              },
              "cuts": {
                "type": "object",
                "description": "wall_width_cm, drop_cut_cm, drop_used_cm (with the pattern match), offcut_per_roll_cm, wall_area_m2, doors_saved_drops"
              }
            },
            "description": "The answer as named values."
          },
          "summary": {
            "type": "string",
            "description": "The answer in one sentence to quote."
          },
          "working": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "How the answer was worked out, one step a line."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Caveats to pass on with the answer."
          },
          "sources": {
            "type": "array",
            "description": "The sources of the rules used. Every rule cites its source, with the date it was checked.",
            "items": {
              "type": "object",
              "required": [
                "label",
                "url",
                "checked"
              ],
              "properties": {
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "checked": {
                  "type": "string",
                  "format": "date"
                }
              }
            }
          },
          "page_url": {
            "type": "string",
            "format": "uri",
            "description": "The calculator on snuug.app with these inputs filled in."
          },
          "snuug": {
            "type": "string",
            "description": "One line about Snuug, the app behind the calculators."
          }
        }
      },
      "dining_table_size": {
        "type": "object",
        "required": [
          "tool",
          "version",
          "inputs",
          "answer",
          "summary",
          "working",
          "notes",
          "sources",
          "page_url",
          "snuug"
        ],
        "properties": {
          "tool": {
            "type": "string",
            "const": "dining-table",
            "description": "The tool, as named in its API and page URLs."
          },
          "version": {
            "type": "string",
            "description": "The version of this contract."
          },
          "inputs": {
            "type": "object",
            "description": "Every input as the tool used it: given, a default, or filled in from the rules.",
            "required": [
              "mode",
              "room_width_cm",
              "room_length_cm",
              "people",
              "shape",
              "clearance"
            ],
            "additionalProperties": false,
            "properties": {
              "mode": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "room (start from the room’s size) or people (start from how many people).",
                "enum": [
                  "room",
                  "people"
                ]
              },
              "room_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "In room mode: the room’s width (cm).",
                "minimum": 150,
                "maximum": 1500
              },
              "room_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "In room mode: the room’s length (cm).",
                "minimum": 150,
                "maximum": 1500
              },
              "people": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "In people mode: the number of people.",
                "minimum": 1,
                "maximum": 14
              },
              "shape": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "rectangle, round or oval.",
                "enum": [
                  "rectangle",
                  "round",
                  "oval"
                ]
              },
              "clearance": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The gap behind the chairs: tight, no_traffic (to a wall), edge_past or walk_past (someone passes).",
                "enum": [
                  "tight",
                  "no_traffic",
                  "edge_past",
                  "walk_past"
                ]
              }
            }
          },
          "answer": {
            "type": "object",
            "required": [
              "table",
              "clearance_cm",
              "largest_made_to_measure",
              "least_room",
              "shapes"
            ],
            "additionalProperties": false,
            "properties": {
              "table": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "The stock table: shape, length_cm, width_cm (a round table’s diameter is its length), seats; null if none fits"
              },
              "clearance_cm": {
                "type": "number",
                "description": "From the table edge to the wall"
              },
              "largest_made_to_measure": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "Room mode: the biggest table the room takes"
              },
              "least_room": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "People mode: the least room, length_cm and width_cm"
              },
              "shapes": {
                "type": "object",
                "description": "The same answer for each shape: rectangle, round, oval"
              }
            },
            "description": "The answer as named values."
          },
          "summary": {
            "type": "string",
            "description": "The answer in one sentence to quote."
          },
          "working": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "How the answer was worked out, one step a line."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Caveats to pass on with the answer."
          },
          "sources": {
            "type": "array",
            "description": "The sources of the rules used. Every rule cites its source, with the date it was checked.",
            "items": {
              "type": "object",
              "required": [
                "label",
                "url",
                "checked"
              ],
              "properties": {
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "checked": {
                  "type": "string",
                  "format": "date"
                }
              }
            }
          },
          "page_url": {
            "type": "string",
            "format": "uri",
            "description": "The calculator on snuug.app with these inputs filled in."
          },
          "snuug": {
            "type": "string",
            "description": "One line about Snuug, the app behind the calculators."
          }
        }
      },
      "pendant_light": {
        "type": "object",
        "required": [
          "tool",
          "version",
          "inputs",
          "answer",
          "summary",
          "working",
          "notes",
          "sources",
          "page_url",
          "snuug"
        ],
        "properties": {
          "tool": {
            "type": "string",
            "const": "pendant-light",
            "description": "The tool, as named in its API and page URLs."
          },
          "version": {
            "type": "string",
            "description": "The version of this contract."
          },
          "inputs": {
            "type": "object",
            "description": "Every input as the tool used it: given, a default, or filled in from the rules.",
            "required": [
              "place",
              "ceiling_height_cm",
              "fitting_height_cm",
              "table_width_cm",
              "table_length_cm",
              "table_height_cm",
              "lights",
              "room_length_cm",
              "room_width_cm"
            ],
            "additionalProperties": false,
            "properties": {
              "place": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "table (over a table or island) or floor (over open floor or a hall).",
                "enum": [
                  "table",
                  "floor"
                ]
              },
              "ceiling_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The ceiling height (cm).",
                "minimum": 180,
                "maximum": 600
              },
              "fitting_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The shade’s own height, top to bottom (cm).",
                "minimum": 2,
                "maximum": 200
              },
              "table_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Over a table: its width (cm).",
                "minimum": 40,
                "maximum": 200
              },
              "table_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Over a table: its length (cm).",
                "minimum": 40,
                "maximum": 400
              },
              "table_height_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Over a table: its height (cm).",
                "minimum": 40,
                "maximum": 120
              },
              "lights": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Over a table: how many lights in a row (1–3).",
                "minimum": 1,
                "maximum": 3
              },
              "room_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The room’s length, for the room-size rule (cm).",
                "minimum": 100,
                "maximum": 2000
              },
              "room_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The room’s width, for the room-size rule (cm).",
                "minimum": 100,
                "maximum": 2000
              }
            }
          },
          "answer": {
            "type": "object",
            "required": [
              "hang_above_table_cm",
              "bottom_from_floor_cm",
              "drop_cm",
              "overall_drop_cm",
              "drop_range_cm",
              "hang_range_cm",
              "diameter_cm",
              "room_rule_diameter_cm",
              "fits",
              "tallest_fitting_cm",
              "centres_from_table_end_cm",
              "chandelier_height_cm",
              "least_clear_cm"
            ],
            "additionalProperties": false,
            "properties": {
              "hang_above_table_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Table: the shade’s bottom above the table"
              },
              "bottom_from_floor_cm": {
                "type": "number",
                "description": "The shade’s bottom from the floor"
              },
              "drop_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Cord or rod, ceiling to the top of the shade; null if the shade does not fit"
              },
              "overall_drop_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Table: ceiling to the bottom of the shade"
              },
              "drop_range_cm": {
                "type": [
                  "array",
                  "null"
                ],
                "description": "Table: the drop across the range"
              },
              "hang_range_cm": {
                "type": [
                  "array",
                  "null"
                ],
                "description": "Table: the range above the table"
              },
              "diameter_cm": {
                "type": "array",
                "description": "[low, high] shade size to choose (table: from its width; floor: the room rule)"
              },
              "room_rule_diameter_cm": {
                "type": "array",
                "description": "[low, high] from the room-size rule"
              },
              "fits": {
                "type": "boolean",
                "description": "The shade fits at that height"
              },
              "tallest_fitting_cm": {
                "type": "number"
              },
              "centres_from_table_end_cm": {
                "type": [
                  "array",
                  "null"
                ],
                "description": "Table: where each light goes"
              },
              "chandelier_height_cm": {
                "type": [
                  "array",
                  "null"
                ],
                "description": "Table: a chandelier’s own height for this ceiling"
              },
              "least_clear_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Floor: the least clearance one shop gives"
              }
            },
            "description": "The answer as named values."
          },
          "summary": {
            "type": "string",
            "description": "The answer in one sentence to quote."
          },
          "working": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "How the answer was worked out, one step a line."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Caveats to pass on with the answer."
          },
          "sources": {
            "type": "array",
            "description": "The sources of the rules used. Every rule cites its source, with the date it was checked.",
            "items": {
              "type": "object",
              "required": [
                "label",
                "url",
                "checked"
              ],
              "properties": {
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "checked": {
                  "type": "string",
                  "format": "date"
                }
              }
            }
          },
          "page_url": {
            "type": "string",
            "format": "uri",
            "description": "The calculator on snuug.app with these inputs filled in."
          },
          "snuug": {
            "type": "string",
            "description": "One line about Snuug, the app behind the calculators."
          }
        }
      },
      "kua_number": {
        "type": "object",
        "required": [
          "tool",
          "version",
          "inputs",
          "answer",
          "summary",
          "working",
          "notes",
          "sources",
          "page_url",
          "snuug"
        ],
        "properties": {
          "tool": {
            "type": "string",
            "const": "kua-number",
            "description": "The tool, as named in its API and page URLs."
          },
          "version": {
            "type": "string",
            "description": "The version of this contract."
          },
          "inputs": {
            "type": "object",
            "description": "Every input as the tool used it: given, a default, or filled in from the rules.",
            "required": [
              "birth_date",
              "birth_time",
              "utc_offset_minutes",
              "formula"
            ],
            "additionalProperties": false,
            "properties": {
              "birth_date": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The birth date, YYYY-MM-DD, from 1901 to 2099.",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "examples": [
                  "1990-06-15"
                ]
              },
              "birth_time": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Optional: the local birth time, HH:MM. It matters only on the day of Li Chun (about 4 February).",
                "pattern": "^\\d{1,2}:\\d{2}$",
                "examples": [
                  "08:30"
                ]
              },
              "utc_offset_minutes": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The birth place’s offset from UTC in early February, in minutes (0 for the UK, 480 for China) (minutes).",
                "minimum": -720,
                "maximum": 840
              },
              "formula": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "both, female or male: the tradition has one formula for each sex at birth.",
                "enum": [
                  "both",
                  "female",
                  "male"
                ]
              }
            }
          },
          "answer": {
            "type": "object",
            "required": [
              "kua_number",
              "counted_year",
              "li_chun",
              "born_before_li_chun",
              "li_chun_day",
              "li_chun_day_unresolved",
              "li_chun_too_close",
              "female",
              "male",
              "if_born_before_li_chun_time",
              "lunar_new_year_alternative"
            ],
            "additionalProperties": false,
            "properties": {
              "kua_number": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "With formula female or male: that kua number"
              },
              "counted_year": {
                "type": "number",
                "description": "The year the tradition counts (Li Chun, about 4 February, starts it)"
              },
              "li_chun": {
                "type": "object",
                "description": "utc, local_date, local_time"
              },
              "born_before_li_chun": {
                "type": "boolean"
              },
              "li_chun_day": {
                "type": "boolean"
              },
              "li_chun_day_unresolved": {
                "type": "boolean",
                "description": "Born on Li Chun with no time given"
              },
              "li_chun_too_close": {
                "type": "boolean",
                "description": "Born within 20 minutes of it"
              },
              "female": {
                "type": "object",
                "description": "The female formula: kua_number, group, favourable and unfavourable directions, and more"
              },
              "male": {
                "type": "object",
                "description": "The male formula, the same way"
              },
              "if_born_before_li_chun_time": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "With li_chun_day_unresolved: both formulas for the year before"
              },
              "lunar_new_year_alternative": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "Born 21 Jan–20 Feb: the other year some teachers count"
              }
            },
            "description": "The answer as named values."
          },
          "summary": {
            "type": "string",
            "description": "The answer in one sentence to quote."
          },
          "working": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "How the answer was worked out, one step a line."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Caveats to pass on with the answer."
          },
          "sources": {
            "type": "array",
            "description": "The sources of the rules used. Every rule cites its source, with the date it was checked.",
            "items": {
              "type": "object",
              "required": [
                "label",
                "url",
                "checked"
              ],
              "properties": {
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "checked": {
                  "type": "string",
                  "format": "date"
                }
              }
            }
          },
          "page_url": {
            "type": "string",
            "format": "uri",
            "description": "The calculator on snuug.app with these inputs filled in."
          },
          "snuug": {
            "type": "string",
            "description": "One line about Snuug, the app behind the calculators."
          }
        }
      },
      "bagua_map": {
        "type": "object",
        "required": [
          "tool",
          "version",
          "inputs",
          "answer",
          "summary",
          "working",
          "notes",
          "sources",
          "page_url",
          "snuug"
        ],
        "properties": {
          "tool": {
            "type": "string",
            "const": "bagua-map",
            "description": "The tool, as named in its API and page URLs."
          },
          "version": {
            "type": "string",
            "description": "The version of this contract."
          },
          "inputs": {
            "type": "object",
            "description": "Every input as the tool used it: given, a default, or filled in from the rules.",
            "required": [
              "room_width_cm",
              "room_length_cm",
              "door_wall",
              "door_position",
              "method",
              "facing"
            ],
            "additionalProperties": false,
            "properties": {
              "room_width_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The room’s width, across the plan (cm).",
                "minimum": 50,
                "maximum": 3000
              },
              "room_length_cm": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The room’s length, up the plan (cm).",
                "minimum": 50,
                "maximum": 3000
              },
              "door_wall": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The wall the door is on, as drawn on the plan: bottom, left, top or right.",
                "enum": [
                  "bottom",
                  "left",
                  "top",
                  "right"
                ]
              },
              "door_position": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Where the door is on that wall, standing in the doorway looking in: left, middle or right.",
                "enum": [
                  "left",
                  "middle",
                  "right"
                ]
              },
              "method": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "btb (from the door, the Western school) or compass.",
                "enum": [
                  "btb",
                  "compass"
                ]
              },
              "facing": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "For the compass method: the way you face as you walk in, N, NE, E, SE, S, SW, W or NW.",
                "enum": [
                  "N",
                  "NE",
                  "E",
                  "SE",
                  "S",
                  "SW",
                  "W",
                  "NW"
                ]
              }
            }
          },
          "answer": {
            "type": "object",
            "required": [
              "cell",
              "cells",
              "door",
              "north_angle_deg"
            ],
            "additionalProperties": false,
            "properties": {
              "cell": {
                "type": "object",
                "description": "Each area’s size: width_cm, length_cm"
              },
              "cells": {
                "type": "array",
                "description": "The nine areas: area, name, place, direction, rect (x_cm, y_cm, width_cm, length_cm), door, and what the tradition says"
              },
              "door": {
                "type": "object",
                "description": "x_cm, y_cm, width_cm, wall, area"
              },
              "north_angle_deg": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Compass method: north on the plan, clockwise from up"
              }
            },
            "description": "The answer as named values."
          },
          "summary": {
            "type": "string",
            "description": "The answer in one sentence to quote."
          },
          "working": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "How the answer was worked out, one step a line."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Caveats to pass on with the answer."
          },
          "sources": {
            "type": "array",
            "description": "The sources of the rules used. Every rule cites its source, with the date it was checked.",
            "items": {
              "type": "object",
              "required": [
                "label",
                "url",
                "checked"
              ],
              "properties": {
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "checked": {
                  "type": "string",
                  "format": "date"
                }
              }
            }
          },
          "page_url": {
            "type": "string",
            "format": "uri",
            "description": "The calculator on snuug.app with these inputs filled in."
          },
          "snuug": {
            "type": "string",
            "description": "One line about Snuug, the app behind the calculators."
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "field",
              "fields"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "invalid_input, invalid_format, not_found or server_error."
              },
              "message": {
                "type": "string",
                "description": "Every problem, in words."
              },
              "field": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The first bad input."
              },
              "fields": {
                "type": "array",
                "description": "Each bad input: its code (unknown_input, repeated, required, empty, not_a_number, not_whole, out_of_range, not_allowed, bad_format) and, where it has them, its limits.",
                "items": {
                  "type": "object",
                  "required": [
                    "field",
                    "code",
                    "message"
                  ],
                  "properties": {
                    "field": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "min": {
                      "type": [
                        "number",
                        "string"
                      ]
                    },
                    "max": {
                      "type": [
                        "number",
                        "string"
                      ]
                    },
                    "allowed": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
