{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://save-one-stroke.invalid/level-v3.schema.json",
  "title": "救一笔！v3 模块化场景",
  "description": "可信模块组成的惰性 JSON；跨字段约束仍由共享运行时验证。",
  "$comment": "自动生成：npm run content:build。不要手改。",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "format",
    "version",
    "id",
    "chapter",
    "title",
    "tag",
    "brief",
    "condition",
    "quip",
    "success",
    "failure",
    "ink",
    "gold",
    "load",
    "hint",
    "scene",
    "progression"
  ],
  "properties": {
    "format": {
      "const": "save-one-stroke-level"
    },
    "version": {
      "const": 3
    },
    "id": {
      "type": "string",
      "maxLength": 100,
      "pattern": "^[a-z0-9-]+/[a-z0-9-]+$"
    },
    "chapter": {
      "type": "string",
      "minLength": 1,
      "maxLength": 40,
      "pattern": "\\S"
    },
    "title": {
      "type": "string",
      "minLength": 1,
      "maxLength": 40,
      "pattern": "\\S"
    },
    "tag": {
      "type": "string",
      "minLength": 1,
      "maxLength": 80,
      "pattern": "\\S"
    },
    "brief": {
      "type": "string",
      "minLength": 1,
      "maxLength": 240,
      "pattern": "\\S"
    },
    "condition": {
      "type": "string",
      "minLength": 1,
      "maxLength": 300,
      "pattern": "\\S"
    },
    "quip": {
      "type": "string",
      "minLength": 1,
      "maxLength": 120,
      "pattern": "\\S"
    },
    "success": {
      "type": "string",
      "minLength": 1,
      "maxLength": 240,
      "pattern": "\\S"
    },
    "failure": {
      "type": "string",
      "minLength": 1,
      "maxLength": 240,
      "pattern": "\\S"
    },
    "ink": {
      "type": "number",
      "minimum": 10,
      "maximum": 2000
    },
    "gold": {
      "type": "number",
      "minimum": 10,
      "maximum": 2000
    },
    "load": {
      "$ref": "#/$defs/load"
    },
    "hint": {
      "type": "array",
      "minItems": 1,
      "maxItems": 4,
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 300,
        "pattern": "\\S"
      }
    },
    "gap": {
      "type": "array",
      "minItems": 2,
      "maxItems": 2,
      "items": {
        "type": "number",
        "minimum": 0,
        "maximum": 720
      }
    },
    "labels": {
      "type": "array",
      "minItems": 0,
      "maxItems": 12,
      "items": {
        "$ref": "#/$defs/label"
      }
    },
    "progression": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "groupOrder",
        "order",
        "difficulty"
      ],
      "properties": {
        "groupOrder": {
          "type": "number",
          "minimum": 0,
          "maximum": 99999
        },
        "order": {
          "type": "number",
          "minimum": 0,
          "maximum": 99999
        },
        "difficulty": {
          "enum": [
            "easy",
            "medium",
            "hard"
          ]
        }
      }
    },
    "drawArea": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "drawTop": {
          "type": "number",
          "minimum": 40,
          "maximum": 400
        },
        "drawBottom": {
          "type": "number",
          "minimum": 100,
          "maximum": 465
        }
      }
    },
    "source": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "prototype",
        "url"
      ],
      "properties": {
        "prototype": {
          "type": "string",
          "minLength": 1,
          "maxLength": 80,
          "pattern": "\\S"
        },
        "url": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200,
          "pattern": "^https?://\\S+$"
        },
        "credit": {
          "type": "string",
          "maxLength": 80
        },
        "note": {
          "type": "string",
          "maxLength": 160
        }
      }
    },
    "scene": {
      "type": "array",
      "minItems": 1,
      "maxItems": 80,
      "items": {
        "oneOf": [
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "core/anchors"
              },
              "params": {
                "type": "array",
                "minItems": 1,
                "maxItems": 4,
                "items": {
                  "$ref": "#/$defs/anchor"
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "core/cats"
              },
              "params": {
                "type": "array",
                "minItems": 1,
                "maxItems": 10,
                "items": {
                  "$ref": "#/$defs/zoneRect"
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "core/chair"
              },
              "params": {
                "type": "array",
                "minItems": 1,
                "maxItems": 30,
                "items": {
                  "$ref": "#/$defs/woodRect"
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "core/drops"
              },
              "params": {
                "type": "array",
                "minItems": 1,
                "maxItems": 3,
                "items": {
                  "$ref": "#/$defs/drop"
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "core/forces"
              },
              "params": {
                "type": "array",
                "minItems": 1,
                "maxItems": 10,
                "items": {
                  "$ref": "#/$defs/force"
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "core/gravity"
              },
              "params": {
                "type": "array",
                "minItems": 1,
                "maxItems": 6,
                "items": {
                  "$ref": "#/$defs/gravityChange"
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "core/temporary-terrain"
              },
              "params": {
                "type": "array",
                "minItems": 1,
                "maxItems": 8,
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "target",
                    "removeAt",
                    "label"
                  ],
                  "properties": {
                    "target": {
                      "type": "string",
                      "pattern": "^[a-z0-9/-]+$"
                    },
                    "removeAt": {
                      "type": "number",
                      "minimum": 750,
                      "maximum": 4000
                    },
                    "label": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 60
                    }
                  }
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "core/terrain"
              },
              "params": {
                "$ref": "#/$defs/terrainRect"
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "lab/elevator"
              },
              "params": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "x",
                  "y",
                  "w",
                  "h",
                  "dx",
                  "dy",
                  "start",
                  "end",
                  "label"
                ],
                "properties": {
                  "x": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 719
                  },
                  "y": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 480
                  },
                  "w": {
                    "type": "number",
                    "minimum": 20,
                    "maximum": 300
                  },
                  "h": {
                    "type": "number",
                    "minimum": 10,
                    "maximum": 60
                  },
                  "dx": {
                    "type": "number",
                    "minimum": -160,
                    "maximum": 160
                  },
                  "dy": {
                    "type": "number",
                    "minimum": -120,
                    "maximum": 120
                  },
                  "start": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 3000
                  },
                  "end": {
                    "type": "number",
                    "minimum": 500,
                    "maximum": 4000
                  },
                  "label": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60
                  }
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "lab/trigger-lift"
              },
              "params": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "button",
                  "x",
                  "y",
                  "w",
                  "h",
                  "dx",
                  "dy",
                  "speed",
                  "label"
                ],
                "properties": {
                  "button": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "x",
                      "y",
                      "w",
                      "h"
                    ],
                    "properties": {
                      "x": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 719
                      },
                      "y": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 480
                      },
                      "w": {
                        "type": "number",
                        "minimum": 20,
                        "maximum": 120
                      },
                      "h": {
                        "type": "number",
                        "minimum": 6,
                        "maximum": 30
                      }
                    }
                  },
                  "x": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 719
                  },
                  "y": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 480
                  },
                  "w": {
                    "type": "number",
                    "minimum": 20,
                    "maximum": 300
                  },
                  "h": {
                    "type": "number",
                    "minimum": 10,
                    "maximum": 60
                  },
                  "dx": {
                    "type": "number",
                    "minimum": -160,
                    "maximum": 160
                  },
                  "dy": {
                    "type": "number",
                    "minimum": -120,
                    "maximum": 120
                  },
                  "speed": {
                    "type": "number",
                    "minimum": 0.02,
                    "maximum": 0.08
                  },
                  "label": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60
                  }
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "nova/belt"
              },
              "params": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "x",
                  "y",
                  "w",
                  "h",
                  "speeds",
                  "label"
                ],
                "properties": {
                  "x": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 719
                  },
                  "y": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 480
                  },
                  "w": {
                    "type": "number",
                    "minimum": 30,
                    "maximum": 500
                  },
                  "h": {
                    "type": "number",
                    "minimum": 10,
                    "maximum": 60
                  },
                  "speeds": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 4,
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "at",
                        "vx"
                      ],
                      "properties": {
                        "at": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 4500
                        },
                        "vx": {
                          "type": "number",
                          "minimum": -6,
                          "maximum": 6
                        }
                      }
                    }
                  },
                  "label": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  }
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "nova/field"
              },
              "params": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "x",
                  "y",
                  "w",
                  "h",
                  "fx",
                  "fy",
                  "start",
                  "end",
                  "label"
                ],
                "properties": {
                  "x": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 719
                  },
                  "y": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 480
                  },
                  "w": {
                    "type": "number",
                    "minimum": 20,
                    "maximum": 600
                  },
                  "h": {
                    "type": "number",
                    "minimum": 20,
                    "maximum": 480
                  },
                  "fx": {
                    "type": "number",
                    "minimum": -2,
                    "maximum": 2
                  },
                  "fy": {
                    "type": "number",
                    "minimum": -2,
                    "maximum": 2
                  },
                  "start": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 4500
                  },
                  "end": {
                    "type": "number",
                    "minimum": 500,
                    "maximum": 5000
                  },
                  "ball": {
                    "type": "string",
                    "pattern": "^[a-z][a-z0-9-]{0,15}$"
                  },
                  "label": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  }
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "nova/gate"
              },
              "params": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "x",
                  "y",
                  "w",
                  "h",
                  "windows",
                  "label"
                ],
                "properties": {
                  "x": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 719
                  },
                  "y": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 480
                  },
                  "w": {
                    "type": "number",
                    "minimum": 8,
                    "maximum": 300
                  },
                  "h": {
                    "type": "number",
                    "minimum": 8,
                    "maximum": 400
                  },
                  "windows": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 3,
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "open",
                        "close"
                      ],
                      "properties": {
                        "open": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 4500
                        },
                        "close": {
                          "type": "number",
                          "minimum": 500,
                          "maximum": 5000
                        }
                      }
                    }
                  },
                  "label": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  }
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "nova/goals"
              },
              "params": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "targets"
                ],
                "properties": {
                  "ordered": {
                    "type": "boolean"
                  },
                  "targets": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 6,
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "ball",
                        "x",
                        "y",
                        "w",
                        "h",
                        "mode",
                        "label"
                      ],
                      "properties": {
                        "ball": {
                          "type": "string",
                          "pattern": "^[a-z][a-z0-9-]{0,15}$"
                        },
                        "x": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 719
                        },
                        "y": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 480
                        },
                        "w": {
                          "type": "number",
                          "minimum": 20,
                          "maximum": 720
                        },
                        "h": {
                          "type": "number",
                          "minimum": 20,
                          "maximum": 480
                        },
                        "mode": {
                          "enum": [
                            "visit",
                            "hold"
                          ]
                        },
                        "openAt": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 4500
                        },
                        "closeAt": {
                          "type": "number",
                          "minimum": 500,
                          "maximum": 5000
                        },
                        "label": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 40
                        }
                      }
                    }
                  }
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "nova/launcher"
              },
              "params": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "ball",
                  "x",
                  "y",
                  "at",
                  "vx",
                  "vy",
                  "radius",
                  "mass",
                  "label"
                ],
                "properties": {
                  "ball": {
                    "type": "string",
                    "pattern": "^[a-z][a-z0-9-]{0,15}$"
                  },
                  "x": {
                    "type": "number",
                    "minimum": 24,
                    "maximum": 696
                  },
                  "y": {
                    "type": "number",
                    "minimum": 40,
                    "maximum": 350
                  },
                  "at": {
                    "type": "number",
                    "minimum": 500,
                    "maximum": 3500
                  },
                  "vx": {
                    "type": "number",
                    "minimum": -14,
                    "maximum": 14
                  },
                  "vy": {
                    "type": "number",
                    "minimum": -14,
                    "maximum": 14
                  },
                  "radius": {
                    "type": "number",
                    "minimum": 10,
                    "maximum": 30
                  },
                  "mass": {
                    "type": "number",
                    "minimum": 0.1,
                    "maximum": 30
                  },
                  "restitution": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1
                  },
                  "label": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  }
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "nova/portal"
              },
              "params": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "entry",
                  "exit",
                  "turn",
                  "label"
                ],
                "properties": {
                  "entry": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "x",
                      "y",
                      "radius"
                    ],
                    "properties": {
                      "x": {
                        "type": "number",
                        "minimum": 24,
                        "maximum": 696
                      },
                      "y": {
                        "type": "number",
                        "minimum": 40,
                        "maximum": 440
                      },
                      "radius": {
                        "type": "number",
                        "minimum": 18,
                        "maximum": 45
                      }
                    }
                  },
                  "exit": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "x",
                      "y",
                      "radius"
                    ],
                    "properties": {
                      "x": {
                        "type": "number",
                        "minimum": 24,
                        "maximum": 696
                      },
                      "y": {
                        "type": "number",
                        "minimum": 40,
                        "maximum": 440
                      },
                      "radius": {
                        "type": "number",
                        "minimum": 18,
                        "maximum": 45
                      }
                    }
                  },
                  "turn": {
                    "type": "number",
                    "minimum": -180,
                    "maximum": 180
                  },
                  "charges": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 6
                  },
                  "ball": {
                    "type": "string",
                    "pattern": "^[a-z][a-z0-9-]{0,15}$"
                  },
                  "label": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  }
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "nova/seesaw"
              },
              "params": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "x",
                  "y",
                  "w",
                  "h",
                  "pivot",
                  "mass",
                  "label"
                ],
                "properties": {
                  "x": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 719
                  },
                  "y": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 480
                  },
                  "w": {
                    "type": "number",
                    "minimum": 80,
                    "maximum": 300
                  },
                  "h": {
                    "type": "number",
                    "minimum": 10,
                    "maximum": 30
                  },
                  "pivot": {
                    "type": "number",
                    "minimum": 0.2,
                    "maximum": 0.8
                  },
                  "mass": {
                    "type": "number",
                    "minimum": 2,
                    "maximum": 60
                  },
                  "label": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  }
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "workshop/hanging-kit"
              },
              "params": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "span",
                  "floorY",
                  "removeAt"
                ],
                "properties": {
                  "span": {
                    "type": "number",
                    "minimum": 160,
                    "maximum": 250
                  },
                  "floorY": {
                    "type": "number",
                    "minimum": 150,
                    "maximum": 300
                  },
                  "removeAt": {
                    "type": "number",
                    "minimum": 750,
                    "maximum": 4000
                  }
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          },
          {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "params"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9-]{1,60}$"
              },
              "type": {
                "const": "workshop/seat"
              },
              "params": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "legs"
                ],
                "properties": {
                  "legs": {
                    "enum": [
                      "none",
                      "left",
                      "both"
                    ]
                  }
                }
              },
              "at": {
                "$ref": "#/$defs/point"
              }
            }
          }
        ]
      }
    }
  },
  "not": {
    "required": [
      "forbidden",
      "forbiddenZones"
    ]
  },
  "$defs": {
    "x": {
      "type": "number",
      "minimum": 0,
      "maximum": 719
    },
    "y": {
      "type": "number",
      "minimum": 0,
      "maximum": 480
    },
    "w": {
      "type": "number",
      "minimum": 1,
      "maximum": 720
    },
    "h": {
      "type": "number",
      "minimum": 1,
      "maximum": 600
    },
    "rect": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "x",
        "y",
        "w",
        "h"
      ],
      "properties": {
        "x": {
          "$ref": "#/$defs/x"
        },
        "y": {
          "$ref": "#/$defs/y"
        },
        "w": {
          "$ref": "#/$defs/w"
        },
        "h": {
          "$ref": "#/$defs/h"
        }
      }
    },
    "woodRect": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "x",
        "y",
        "w",
        "h",
        "kind"
      ],
      "properties": {
        "x": {
          "$ref": "#/$defs/x"
        },
        "y": {
          "$ref": "#/$defs/y"
        },
        "w": {
          "$ref": "#/$defs/w"
        },
        "h": {
          "$ref": "#/$defs/h"
        },
        "kind": {
          "enum": [
            "seat",
            "leg"
          ]
        }
      }
    },
    "terrainRect": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "x",
        "y",
        "w",
        "h"
      ],
      "properties": {
        "x": {
          "$ref": "#/$defs/x"
        },
        "y": {
          "$ref": "#/$defs/y"
        },
        "w": {
          "$ref": "#/$defs/w"
        },
        "h": {
          "$ref": "#/$defs/h"
        },
        "step": {
          "type": "boolean"
        },
        "friction": {
          "type": "number",
          "minimum": 0,
          "maximum": 1.5
        }
      }
    },
    "zoneRect": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "x",
        "y",
        "w",
        "h"
      ],
      "properties": {
        "x": {
          "$ref": "#/$defs/x"
        },
        "y": {
          "$ref": "#/$defs/y"
        },
        "w": {
          "$ref": "#/$defs/w"
        },
        "h": {
          "$ref": "#/$defs/h"
        },
        "label": {
          "type": "string",
          "minLength": 1,
          "maxLength": 40,
          "pattern": "\\S"
        }
      }
    },
    "point": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "x",
        "y"
      ],
      "properties": {
        "x": {
          "type": "number",
          "minimum": 0,
          "maximum": 720
        },
        "y": {
          "$ref": "#/$defs/y"
        }
      }
    },
    "load": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "x",
        "mass"
      ],
      "properties": {
        "x": {
          "type": "number",
          "minimum": 25,
          "maximum": 695
        },
        "mass": {
          "type": "number",
          "minimum": 0.1,
          "maximum": 200
        },
        "cat": {
          "type": "boolean"
        },
        "catX": {
          "type": "number",
          "minimum": 25,
          "maximum": 695
        },
        "catMass": {
          "type": "number",
          "minimum": 0.1,
          "maximum": 200
        }
      },
      "if": {
        "required": [
          "cat"
        ],
        "properties": {
          "cat": {
            "const": true
          }
        }
      },
      "then": {
        "required": [
          "catX",
          "catMass"
        ]
      }
    },
    "label": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "x",
        "y",
        "text",
        "to"
      ],
      "properties": {
        "x": {
          "type": "number",
          "minimum": 0,
          "maximum": 720
        },
        "y": {
          "$ref": "#/$defs/y"
        },
        "text": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100,
          "pattern": "\\S"
        },
        "to": {
          "type": "array",
          "minItems": 2,
          "maxItems": 2,
          "prefixItems": [
            {
              "type": "number",
              "minimum": 0,
              "maximum": 720
            },
            {
              "$ref": "#/$defs/y"
            }
          ],
          "items": false
        }
      }
    },
    "force": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "start",
        "end",
        "fx",
        "at",
        "label"
      ],
      "properties": {
        "start": {
          "type": "number",
          "minimum": 0,
          "maximum": 5000
        },
        "end": {
          "type": "number",
          "minimum": 0,
          "maximum": 5000
        },
        "fx": {
          "type": "number",
          "minimum": -0.1,
          "maximum": 0.1
        },
        "fy": {
          "type": "number",
          "minimum": -0.1,
          "maximum": 0.1
        },
        "at": {
          "$ref": "#/$defs/point"
        },
        "label": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100,
          "pattern": "\\S"
        }
      }
    },
    "temporaryTerrain": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "index",
        "removeAt",
        "label"
      ],
      "properties": {
        "index": {
          "type": "integer",
          "minimum": 0,
          "maximum": 29
        },
        "removeAt": {
          "type": "number",
          "minimum": 750,
          "maximum": 4000
        },
        "label": {
          "type": "string",
          "minLength": 1,
          "maxLength": 60,
          "pattern": "\\S"
        }
      }
    },
    "anchor": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "x",
        "y",
        "radius",
        "label"
      ],
      "properties": {
        "x": {
          "type": "number",
          "minimum": 24,
          "maximum": 696
        },
        "y": {
          "type": "number",
          "minimum": 40,
          "maximum": 460
        },
        "radius": {
          "type": "number",
          "minimum": 6,
          "maximum": 14
        },
        "label": {
          "type": "string",
          "minLength": 1,
          "maxLength": 60,
          "pattern": "\\S"
        },
        "releaseAt": {
          "type": "number",
          "minimum": 750,
          "maximum": 4000
        }
      }
    },
    "gravityChange": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "at",
        "x",
        "y",
        "label"
      ],
      "properties": {
        "at": {
          "type": "number",
          "minimum": 0,
          "maximum": 4000
        },
        "x": {
          "type": "number",
          "minimum": -1.5,
          "maximum": 1.5
        },
        "y": {
          "type": "number",
          "minimum": -1.5,
          "maximum": 1.5
        },
        "label": {
          "type": "string",
          "minLength": 1,
          "maxLength": 60,
          "pattern": "\\S"
        }
      }
    },
    "drop": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "at",
        "x",
        "y",
        "radius",
        "mass",
        "label"
      ],
      "properties": {
        "at": {
          "type": "number",
          "minimum": 500,
          "maximum": 3500
        },
        "x": {
          "type": "number",
          "minimum": 24,
          "maximum": 696
        },
        "y": {
          "type": "number",
          "minimum": 40,
          "maximum": 350
        },
        "radius": {
          "type": "number",
          "minimum": 10,
          "maximum": 35
        },
        "mass": {
          "type": "number",
          "minimum": 0.1,
          "maximum": 30
        },
        "label": {
          "type": "string",
          "minLength": 1,
          "maxLength": 60,
          "pattern": "\\S"
        },
        "restitution": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        }
      }
    },
    "mechanics": {
      "type": "object",
      "additionalProperties": false,
      "required": [],
      "properties": {
        "drawTop": {
          "type": "number",
          "minimum": 40,
          "maximum": 400
        },
        "drawBottom": {
          "type": "number",
          "minimum": 100,
          "maximum": 465
        },
        "temporaryTerrain": {
          "type": "array",
          "minItems": 1,
          "maxItems": 8,
          "items": {
            "$ref": "#/$defs/temporaryTerrain"
          }
        },
        "anchors": {
          "type": "array",
          "minItems": 1,
          "maxItems": 4,
          "items": {
            "$ref": "#/$defs/anchor"
          }
        },
        "gravity": {
          "type": "array",
          "minItems": 1,
          "maxItems": 6,
          "items": {
            "$ref": "#/$defs/gravityChange"
          },
          "prefixItems": [
            {
              "allOf": [
                {
                  "$ref": "#/$defs/gravityChange"
                },
                {
                  "properties": {
                    "at": {
                      "const": 0
                    }
                  }
                }
              ]
            }
          ]
        },
        "drops": {
          "type": "array",
          "minItems": 1,
          "maxItems": 3,
          "items": {
            "$ref": "#/$defs/drop"
          }
        }
      },
      "anyOf": [
        {
          "required": [
            "temporaryTerrain"
          ]
        },
        {
          "required": [
            "anchors"
          ]
        },
        {
          "required": [
            "gravity"
          ]
        },
        {
          "required": [
            "drops"
          ]
        }
      ]
    }
  }
}
