{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://wattreplay.com/plan.schema.json",
  "title": "WattReplay normalized plan v1",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "product",
    "version",
    "fields",
    "tables",
    "demo"
  ],
  "properties": {
    "product": {
      "const": "electricity-time-of-use-comparison"
    },
    "version": {
      "const": 1
    },
    "demo": {
      "type": "boolean"
    },
    "fields": {
      "type": "object",
      "required": [
        "timezone",
        "flat",
        "flatFixed",
        "offPeak",
        "peak",
        "touFixed",
        "peakStart",
        "peakEnd",
        "weekends",
        "rider",
        "demand",
        "tax",
        "shift",
        "simpleDailyKwh",
        "simplePeakShare",
        "simpleDays",
        "tier1Limit",
        "tier1Rate",
        "tier2Rate",
        "tierFixed",
        "seasonalRates",
        "summerStartMonth",
        "summerEndMonth",
        "summerPeakRate",
        "summerOffPeakRate",
        "solarExportKwh",
        "exportRate",
        "scheduleMode",
        "peakDays",
        "evKwh"
      ],
      "additionalProperties": false,
      "properties": {
        "timezone": {
          "type": "string",
          "enum": [
            "America/New_York",
            "America/Chicago",
            "America/Denver",
            "America/Los_Angeles",
            "Europe/London",
            "Australia/Sydney",
            "UTC"
          ],
          "description": "Utility timezone"
        },
        "flat": {
          "type": "number",
          "minimum": 0,
          "maximum": 10,
          "description": "Flat energy rate (USD/kWh)"
        },
        "flatFixed": {
          "type": "number",
          "minimum": 0,
          "maximum": 10000,
          "description": "Flat-plan fixed charge (USD / bill)"
        },
        "offPeak": {
          "type": "number",
          "minimum": 0,
          "maximum": 10,
          "description": "TOU off-peak rate (USD/kWh)"
        },
        "peak": {
          "type": "number",
          "minimum": 0,
          "maximum": 10,
          "description": "TOU peak rate (USD/kWh)"
        },
        "touFixed": {
          "type": "number",
          "minimum": 0,
          "maximum": 10000,
          "description": "TOU fixed charge (USD / bill)"
        },
        "peakStart": {
          "type": "integer",
          "minimum": 0,
          "maximum": 23,
          "description": "Peak window starts (local hour)"
        },
        "peakEnd": {
          "type": "integer",
          "minimum": 0,
          "maximum": 24,
          "description": "Peak window ends (local hour)"
        },
        "weekends": {
          "type": "string",
          "enum": [
            "Yes",
            "No"
          ],
          "description": "Weekends off-peak"
        },
        "rider": {
          "type": "number",
          "minimum": 0,
          "maximum": 10,
          "description": "Common delivery / rider (USD/kWh)"
        },
        "demand": {
          "type": "number",
          "minimum": 0,
          "maximum": 1000,
          "description": "TOU demand charge (USD/kW)"
        },
        "tax": {
          "type": "number",
          "minimum": 0,
          "maximum": 40,
          "description": "Tax on subtotal (%)"
        },
        "shift": {
          "type": "number",
          "minimum": 0,
          "maximum": 100,
          "description": "Peak usage shifted in scenario (%)"
        },
        "simpleDailyKwh": {
          "type": "number",
          "minimum": 0,
          "maximum": 1000,
          "description": "Typical daily usage (kWh/day)"
        },
        "simplePeakShare": {
          "type": "number",
          "minimum": 0,
          "maximum": 100,
          "description": "Share used during peak hours (%)"
        },
        "simpleDays": {
          "type": "integer",
          "minimum": 1,
          "maximum": 90,
          "description": "Days to generate (days)"
        },
        "tier1Limit": {
          "type": "number",
          "minimum": 0,
          "maximum": 100000,
          "description": "Tier 1 usage limit (kWh)"
        },
        "tier1Rate": {
          "type": "number",
          "minimum": 0,
          "maximum": 10,
          "description": "Tier 1 rate (USD/kWh)"
        },
        "tier2Rate": {
          "type": "number",
          "minimum": 0,
          "maximum": 10,
          "description": "Tier 2 rate (above limit) (USD/kWh)"
        },
        "tierFixed": {
          "type": "number",
          "minimum": 0,
          "maximum": 10000,
          "description": "Tiered-plan fixed charge (USD / bill)"
        },
        "seasonalRates": {
          "type": "string",
          "enum": [
            "Yes",
            "No"
          ],
          "description": "Use seasonal TOU rates"
        },
        "summerStartMonth": {
          "type": "integer",
          "minimum": 1,
          "maximum": 12,
          "description": "Summer season starts (month (1-12))"
        },
        "summerEndMonth": {
          "type": "integer",
          "minimum": 1,
          "maximum": 12,
          "description": "Summer season ends (month (1-12))"
        },
        "summerPeakRate": {
          "type": "number",
          "minimum": 0,
          "maximum": 10,
          "description": "Summer TOU peak rate (USD/kWh)"
        },
        "summerOffPeakRate": {
          "type": "number",
          "minimum": 0,
          "maximum": 10,
          "description": "Summer TOU off-peak rate (USD/kWh)"
        },
        "solarExportKwh": {
          "type": "number",
          "minimum": 0,
          "maximum": 1000000,
          "description": "Solar energy exported (kWh)"
        },
        "exportRate": {
          "type": "number",
          "minimum": 0,
          "maximum": 10,
          "description": "Net-metering export credit rate (USD/kWh)"
        },
        "scheduleMode": {
          "type": "string",
          "enum": [
            "Weekday/weekend",
            "Custom days"
          ],
          "description": "Weekly peak schedule"
        },
        "peakDays": {
          "type": "string",
          "maxLength": 20000,
          "description": "Custom peak days"
        },
        "evKwh": {
          "type": "number",
          "minimum": 0,
          "maximum": 1000,
          "description": "EV overnight charging added (kWh/night)"
        }
      }
    },
    "tables": {
      "type": "object",
      "required": [
        "usage"
      ],
      "additionalProperties": false,
      "properties": {
        "usage": {
          "type": "array",
          "maxItems": 10000,
          "items": {
            "type": "object",
            "required": [
              "start",
              "minutes",
              "kwh"
            ],
            "additionalProperties": false,
            "properties": {
              "start": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2})?(Z|[+-]\\d{2}:\\d{2})$"
              },
              "minutes": {
                "type": "integer",
                "minimum": 1,
                "maximum": 60
              },
              "kwh": {
                "type": "number",
                "minimum": 0,
                "maximum": 100000
              }
            }
          }
        }
      }
    },
    "source": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "kind",
        "label"
      ],
      "properties": {
        "kind": {
          "enum": [
            "example",
            "import",
            "manual",
            "unverified"
          ]
        },
        "label": {
          "type": "string",
          "maxLength": 120
        }
      }
    }
  },
  "$comment": "Additional semantic validation rejects equal peak boundaries, invalid dates, overlaps, and duplicate instants. No live utility data. All monetary inputs use USD."
}