{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Disc Golf Course Schema",
  "description": "Simplified schema for defining disc golf courses with basic visual customization options. This schema is designed for Three.js rendering with a right-handed coordinate system where (0,0,0) represents the center of the course. The X and Z coordinates are used for ground plane positioning (X is left/right, Z is forward/back), while Y represents height (up/down). Ground-level objects should use Y=0.",
  "version": "1.0.0",
  "author": "Vibe Disc",
  "authorUrl": "https://vibedisc.com",
  "license": "MIT",
  "creationDate": "2025-03-23T12:00:00Z",
  "coordinateSystem": {
    "type": "object",
    "description": "The course uses a Three.js right-handed coordinate system where:",
    "properties": {
      "origin": {
        "type": "string",
        "description": "The origin (0,0,0) is at the center of the course"
      },
      "xAxis": {
        "type": "string",
        "description": "X axis: Positive values go right, negative values go left"
      },
      "yAxis": {
        "type": "string",
        "description": "Y axis: Represents height/elevation. Y=0 is ground level. Positive values go up, negative values go down"
      },
      "zAxis": {
        "type": "string",
        "description": "Z axis: Positive values go forward, negative values go backward"
      }
    }
  },
  "type": "object",
  "required": [
    "course_id",
    "name",
    "metadata",
    "courseSize",
    "holes",
    "terrain"
  ],
  "properties": {
    "course_id": {
      "type": "string",
      "description": "Unique identifier for the course"
    },
    "name": {
      "type": "string",
      "description": "Name of the disc golf course"
    },
    "metadata": {
      "type": "object",
      "required": [
        "description",
        "location",
        "difficulty",
        "source",
        "author",
        "version",
        "creationDate"
      ],
      "properties": {
        "description": {
          "type": "string",
          "description": "Detailed description of the course"
        },
        "location": {
          "type": "object",
          "required": ["latitude", "longitude", "address"],
          "properties": {
            "latitude": {
              "type": "number"
            },
            "longitude": {
              "type": "number"
            },
            "address": {
              "type": "string"
            }
          }
        },
        "difficulty": {
          "type": "integer",
          "minimum": 1,
          "maximum": 5,
          "description": "Course difficulty rating from 1 to 5"
        },
        "source": {
          "type": "string",
          "description": "Source of the course data"
        },
        "author": {
          "type": "string",
          "description": "Creator of the course"
        },
        "authorUrl": {
          "type": "string",
          "format": "uri",
          "description": "URL to the author's website or profile"
        },
        "version": {
          "type": "string",
          "description": "Version of the course data"
        },
        "creationDate": {
          "type": "string",
          "format": "date-time",
          "description": "Date when the course was created"
        },
        "dataUrl": {
          "type": "string",
          "format": "uri",
          "description": "URL to additional course data if available"
        },
        "schemaVersion": {
          "type": "string",
          "description": "Version of the schema"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Tags for the course"
        }
      }
    },
    "visualSettings": {
      "type": "object",
      "description": "Basic visual settings for the course",
      "properties": {
        "skyImageUrl": {
          "type": "string",
          "format": "uri",
          "description": "URL to a sky image/skybox texture"
        },
        "backgroundColor": {
          "type": "string",
          "pattern": "^#[0-9A-Fa-f]{6}$",
          "description": "Hex color code for the background/default sky color"
        }
      }
    },
    "courseSize": {
      "type": "object",
      "required": ["width", "length"],
      "properties": {
        "width": {
          "type": "number",
          "description": "Width of the course in meters"
        },
        "length": {
          "type": "number",
          "description": "Length of the course in meters"
        }
      }
    },
    "textures": {
      "type": "object",
      "description": "Default texture settings for various terrain types",
      "properties": {
        "fairway": {
          "type": "string",
          "format": "uri",
          "description": "Default texture URL for fairway terrain"
        },
        "rough": {
          "type": "string",
          "format": "uri",
          "description": "Default texture URL for rough terrain"
        },
        "water": {
          "type": "string",
          "format": "uri",
          "description": "Default texture URL for water surfaces"
        },
        "sand": {
          "type": "string",
          "format": "uri",
          "description": "Default texture URL for sand terrain"
        },
        "teepad": {
          "type": "string",
          "format": "uri",
          "description": "Default texture URL for tee pads"
        },
        "ground": {
          "type": "string",
          "format": "uri",
          "description": "Base texture for the ground plane"
        }
      }
    },
    "audio": {
      "type": "object",
      "description": "Sounds for the course",
      "properties": {
        "backgroundMusic": {
          "type": "string",
          "format": "uri",
          "description": "URL to the background music file"
        }
      }
    },
    "holes": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["holeNumber", "par", "teebox", "basket"],
        "properties": {
          "holeNumber": {
            "type": "integer",
            "minimum": 1,
            "description": "Number of the hole"
          },
          "par": {
            "type": "integer",
            "minimum": 2,
            "description": "Par for the hole"
          },
          "name": {
            "type": "string",
            "description": "Name of the hole"
          },
          "description": {
            "type": "string",
            "description": "Description of the hole including any notable features or challenges"
          },
          "teebox": {
            "type": "object",
            "required": ["position", "rotation", "type"],
            "properties": {
              "position": {
                "type": "object",
                "required": ["x", "y", "z"],
                "properties": {
                  "x": { "type": "number" },
                  "y": { "type": "number" },
                  "z": { "type": "number" }
                }
              },
              "rotation": {
                "type": "object",
                "required": ["x", "y", "z"],
                "description": "Rotation angles in degrees. Y rotation is most important, determining which direction the teebox faces.",
                "properties": {
                  "x": { "type": "number" },
                  "y": { "type": "number" },
                  "z": { "type": "number" }
                }
              },
              "type": {
                "type": "string",
                "enum": ["pro", "amateur", "recreational"],
                "description": "Type/difficulty of the tee position"
              },
              "textureUrl": {
                "type": "string",
                "format": "uri",
                "description": "Optional custom texture for this specific teebox"
              }
            }
          },
          "basket": {
            "type": "object",
            "required": ["position"],
            "properties": {
              "position": {
                "type": "object",
                "required": ["x", "y", "z"],
                "properties": {
                  "x": { "type": "number" },
                  "y": { "type": "number" },
                  "z": { "type": "number" }
                }
              }
            }
          }
        }
      }
    },
    "terrain": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["id", "type", "position", "scale"],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the terrain object"
          },
          "type": {
            "type": "string",
            "enum": [
              "fairway",
              "rough",
              "water",
              "sand",
              "tree",
              "bush",
              "rock",
              "path",
              "portal",
              "custom"
            ],
            "description": "Type of terrain feature"
          },
          "position": {
            "type": "object",
            "required": ["x", "y", "z"],
            "properties": {
              "x": { "type": "number" },
              "y": { "type": "number" },
              "z": { "type": "number" }
            }
          },
          "scale": {
            "type": "object",
            "required": ["x", "y", "z"],
            "properties": {
              "x": { "type": "number" },
              "y": { "type": "number" },
              "z": { "type": "number" }
            }
          },
          "rotation": {
            "type": "object",
            "properties": {
              "x": { "type": "number" },
              "y": { "type": "number" },
              "z": { "type": "number" }
            }
          },
          "visualProperties": {
            "type": "object",
            "description": "Visual appearance properties for the terrain",
            "properties": {
              "color": {
                "type": "string",
                "pattern": "^#[0-9A-Fa-f]{6}$",
                "description": "Hex color code for the terrain"
              },
              "roughness": {
                "type": "number",
                "minimum": 0,
                "maximum": 1,
                "description": "Material roughness (0 = smooth, 1 = rough)"
              },
              "metalness": {
                "type": "number",
                "minimum": 0,
                "maximum": 1,
                "description": "Material metalness (0 = non-metallic, 1 = metallic)"
              },
              "opacity": {
                "type": "number",
                "minimum": 0,
                "maximum": 1,
                "description": "Material opacity (0 = transparent, 1 = opaque)"
              },
              "textureUrl": {
                "type": "string",
                "format": "uri",
                "description": "URL to a texture image for this terrain object"
              }
            }
          },
          "variant": {
            "type": "string",
            "enum": ["default", "tall", "wide", "dense", "sparse"],
            "default": "default",
            "description": "Visual variant of the terrain type"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Custom tags for categorizing and filtering terrain objects"
          },
          "properties": {
            "type": "object",
            "description": "Additional properties specific to terrain type",
            "properties": {
              "hazardType": {
                "type": "string",
                "enum": ["none", "casual", "penalty"],
                "description": "Type of hazard for gameplay effects"
              },
              "depth": {
                "type": "number",
                "description": "Depth for water features"
              },
              "density": {
                "type": "number",
                "minimum": 0,
                "maximum": 1,
                "description": "Density for vegetation (rough, trees, bushes)"
              },
              "isEntry": {
                "type": "boolean",
                "description": "For portal type: true if this is an entry portal, false for exit portal"
              },
              "targetUrl": {
                "type": "string",
                "format": "uri",
                "description": "For portal type: The URL to redirect to when an exit portal is hit"
              },
              "ref": {
                "type": "string",
                "format": "uri",
                "description": "For portal type: The URL to return to when an entry portal is hit"
              },
              "modelUrl": {
                "type": "string",
                "description": "For custom type: URL to the 3D model file"
              }
            }
          },
          "shape": {
            "type": "object",
            "description": "Shape definition for ground-type terrains (fairway, rough, water, sand, path)",
            "required": ["type"],
            "properties": {
              "type": {
                "type": "string",
                "enum": ["rectangle", "ellipse"],
                "description": "The shape type - rectangle for rectangular/square areas, ellipse for circular/elliptical areas"
              },
              "width": {
                "type": "number",
                "description": "Width of the shape in meters"
              },
              "length": {
                "type": "number",
                "description": "Length of the shape in meters (for rectangle) or height (for ellipse)"
              },
              "rotation": {
                "type": "number",
                "description": "Rotation of the shape in radians around the Y axis"
              }
            }
          },
          "textureSettings": {
            "type": "object",
            "description": "Advanced texture settings for ground-type terrains",
            "properties": {
              "textureUrl": {
                "type": "string",
                "format": "uri",
                "description": "URL to the texture to use"
              },
              "normalMapUrl": {
                "type": "string",
                "format": "uri",
                "description": "URL to the normal map texture"
              },
              "tileSize": {
                "type": "number",
                "description": "Size of one texture tile in meters (e.g. 5 means one texture repeat every 5 meters)"
              },
              "rotation": {
                "type": "number",
                "description": "Rotation of the texture in radians (independent of shape rotation)"
              }
            }
          }
        }
      }
    }
  }
}