{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://www.calculatorx.com/schemas/education.final_grade.input.json",
  "title": "Final grade — input",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "mode": {
      "type": "string",
      "enum": [
        "need",
        "overall",
        "weighted",
        "points"
      ],
      "description": "need = score required on the final; overall = course % after a known final; weighted = category average / remaining work; points = final points → weight %"
    },
    "currentInput": {
      "type": "number",
      "description": "Pre-final current grade % (Need / Overall). Must exclude the final."
    },
    "goalInput": {
      "type": "number",
      "description": "Desired course grade % (Need / Weighted remaining)"
    },
    "weightInput": {
      "type": "number",
      "minimum": 0,
      "maximum": 100,
      "description": "Final exam weight W as a percent (40 = 40%). Need on final requires W > 0."
    },
    "finalScoreInput": {
      "type": "number",
      "description": "Final exam score % (Overall after final)"
    },
    "remainWeightInput": {
      "type": "number",
      "minimum": 0,
      "maximum": 100,
      "description": "Remaining weight % (Weighted). Omit to use 100 − Σ completed weights."
    },
    "categories": {
      "description": "Completed categories: array of {name?, grade, weight} or packed string name:grade:weight|…",
      "oneOf": [
        {
          "type": "string"
        },
        {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": true,
            "properties": {
              "name": {
                "type": "string"
              },
              "grade": {
                "type": "number"
              },
              "weight": {
                "type": "number"
              }
            }
          }
        }
      ]
    },
    "totalPointsInput": {
      "type": "number",
      "exclusiveMinimum": 0,
      "description": "Course total points including the final (Points → weight)"
    },
    "finalPointsInput": {
      "type": "number",
      "minimum": 0,
      "description": "Final exam points (Points → weight)"
    }
  },
  "required": [
    "mode"
  ],
  "oneOf": [
    {
      "title": "need",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "mode",
        "currentInput",
        "goalInput",
        "weightInput"
      ],
      "properties": {
        "mode": {
          "const": "need"
        },
        "currentInput": {
          "type": "number"
        },
        "goalInput": {
          "type": "number"
        },
        "weightInput": {
          "type": "number",
          "exclusiveMinimum": 0,
          "maximum": 100
        }
      }
    },
    {
      "title": "overall",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "mode",
        "currentInput",
        "finalScoreInput",
        "weightInput"
      ],
      "properties": {
        "mode": {
          "const": "overall"
        },
        "currentInput": {
          "type": "number"
        },
        "finalScoreInput": {
          "type": "number"
        },
        "weightInput": {
          "type": "number",
          "minimum": 0,
          "maximum": 100
        }
      }
    },
    {
      "title": "weighted",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "mode",
        "categories"
      ],
      "properties": {
        "mode": {
          "const": "weighted"
        },
        "categories": {
          "oneOf": [
            {
              "type": "string"
            },
            {
              "type": "array"
            }
          ]
        },
        "goalInput": {
          "type": "number"
        },
        "remainWeightInput": {
          "type": "number",
          "minimum": 0,
          "maximum": 100
        }
      }
    },
    {
      "title": "points",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "mode",
        "totalPointsInput",
        "finalPointsInput"
      ],
      "properties": {
        "mode": {
          "const": "points"
        },
        "totalPointsInput": {
          "type": "number",
          "exclusiveMinimum": 0
        },
        "finalPointsInput": {
          "type": "number",
          "minimum": 0
        }
      }
    }
  ],
  "description": "Need-on-final, overall after the exam, weighted categories, and points-to-weight for a fixed final exam share. (calculation_version 1.1.1)"
}
