{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://openteesheet.com/schemas/league-season.schema.json",
  "title": "OpenTeeSheet league season (open format v1)",
  "description": "A league season at a sim studio: a weekly night on named bays for N weeks, teams of a fixed size, an entry fee per golfer and a league-only bay rate per team per night (whole dollars, in cents), and one of three scoring rules. Making a season reserves every league night on those bays as a real league booking.",
  "type": "object",
  "properties": {
    "object": {
      "const": "league_season"
    },
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "venue_id": {
      "type": "string",
      "format": "uuid"
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 80
    },
    "starts_on": {
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      "description": "The first league night, venue-local date; the season plays that weekday every week."
    },
    "start_time": {
      "type": "string",
      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
      "description": "Venue-local start, HH:MM."
    },
    "duration_minutes": {
      "type": "integer",
      "minimum": 60,
      "maximum": 300
    },
    "weeks": {
      "type": "integer",
      "minimum": 1,
      "maximum": 26
    },
    "bay_ids": {
      "type": "array",
      "items": {
        "type": "string",
        "format": "uuid"
      }
    },
    "team_size": {
      "type": "integer",
      "minimum": 1,
      "maximum": 4
    },
    "roster_cap": {
      "type": "integer",
      "minimum": 1,
      "maximum": 8
    },
    "substitutes_allowed": {
      "type": "boolean"
    },
    "entry_fee_cents": {
      "type": "integer",
      "minimum": 0,
      "description": "Per golfer, paid once at sign-up. Whole dollars."
    },
    "league_rate_cents": {
      "type": "integer",
      "minimum": 0,
      "description": "What one team pays per league night for its share of the bay, instead of the walk-in rate; the captain pays the season's total at sign-up. Whole dollars."
    },
    "scoring": {
      "type": "string",
      "enum": [
        "match_play",
        "field_rank",
        "low_total"
      ]
    },
    "max_teams": {
      "type": "integer",
      "minimum": 2
    },
    "status": {
      "type": "string",
      "enum": [
        "open",
        "closed"
      ]
    },
    "created_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time"
    }
  },
  "required": [
    "object",
    "id",
    "venue_id",
    "name",
    "starts_on",
    "start_time",
    "duration_minutes",
    "weeks",
    "bay_ids",
    "team_size",
    "roster_cap",
    "substitutes_allowed",
    "entry_fee_cents",
    "league_rate_cents",
    "scoring",
    "max_teams",
    "status"
  ],
  "additionalProperties": false
}
