{
  "schemaVersion": 1,
  "slug": "cricket-run-rate-calculator",
  "category": "sports",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "dae3854d4ea1a475ded261798757cc91f48071b65e81790a4865067df783d621",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/cricket-run-rate-calculator.json",
    "src/engine.js"
  ],
  "runtimeSource": "/sources/engine.txt",
  "runtimeHash": "5c888d8898afbdee36267bb9977829e1e2ac568f6677c8ee87469c139864645c",
  "scope": "The compute function records implemented equations, constants, lookup tables and custom rules. Inputs record defaults and allowed values; outputs record precision and units. Defaults are examples, not recommendations. General background references are not evidence for this specific algorithm.",
  "publishedFormula": {
    "formula": "RRR = max(0, T − R + 1) ÷ max(0, O − o)",
    "vars": [
      [
        "T",
        "Target score"
      ],
      [
        "R",
        "Runs scored now"
      ],
      [
        "O",
        "Total overs"
      ],
      [
        "o",
        "Overs bowled"
      ]
    ],
    "note": "Balls remaining = (O − o) × balls per over (rounded); current run rate = R ÷ o; the verdict compares RRR with the current rate in bands (+3 runs)."
  },
  "externalEvidence": null,
  "contract": {
    "compute": "const ints=[targetRuns,currentRuns,wicketsLost,oversBowled,totalOvers,ballsPerOver,ballsBowled];if(!ints.every(Number.isFinite)||!ints.every(Number.isInteger)||targetRuns<0||currentRuns<0||wicketsLost<0||wicketsLost>10||oversBowled<0||totalOvers<1||oversBowled>totalOvers||ballsPerOver<4||ballsPerOver>8||ballsBowled<0||ballsBowled>=ballsPerOver||(oversBowled===totalOvers&&ballsBowled>0))return{currentRunRate:null,requiredRunRate:null,runsNeeded:null,oversRemaining:null,ballsRemaining:null,verdict:null,__error:'inputError'};const runsNeeded=Math.max(0,targetRuns-currentRuns+1),oversRemaining=totalOvers-oversBowled-ballsBowled/ballsPerOver,ballsRemaining=Math.max(0,(totalOvers-oversBowled)*ballsPerOver-ballsBowled),oversCompleted=oversBowled+ballsBowled/ballsPerOver,currentRunRate=oversCompleted>0?currentRuns/oversCompleted:null,requiredRunRate=oversRemaining>0?runsNeeded/oversRemaining:0;let verdict;if(runsNeeded===0)verdict='Target already passed';else if(ballsRemaining===0||wicketsLost===10)verdict='Chase is over';else if(currentRunRate!==null&&requiredRunRate<=currentRunRate)verdict='Ahead of the rate — keep the same approach';else if(currentRunRate!==null&&requiredRunRate<=currentRunRate+3)verdict='Chasing hard but achievable with regular boundaries';else verdict='Required rate is very high — need to accelerate immediately';return{currentRunRate,requiredRunRate,runsNeeded,oversRemaining,ballsRemaining,verdict};",
    "inputs": [
      {
        "name": "targetRuns",
        "type": "number",
        "default": 180,
        "min": 0,
        "max": 1000,
        "step": 1,
        "slider": true
      },
      {
        "name": "currentRuns",
        "type": "number",
        "default": 96,
        "min": 0,
        "max": 1000,
        "step": 1,
        "slider": true
      },
      {
        "name": "wicketsLost",
        "type": "number",
        "default": 3,
        "min": 0,
        "max": 10,
        "step": 1,
        "slider": true
      },
      {
        "name": "oversBowled",
        "type": "number",
        "default": 12,
        "min": 0,
        "max": 60,
        "step": 1,
        "slider": true
      },
      {
        "name": "ballsBowled",
        "type": "number",
        "default": 0,
        "min": 0,
        "max": 5,
        "step": 1
      },
      {
        "name": "totalOvers",
        "type": "number",
        "default": 20,
        "min": 1,
        "max": 60,
        "step": 1,
        "slider": true
      },
      {
        "name": "ballsPerOver",
        "type": "number",
        "default": 6,
        "min": 4,
        "max": 8,
        "step": 1
      }
    ],
    "outputs": [
      {
        "name": "currentRunRate",
        "precision": 2,
        "unit": "per over",
        "optional": true
      },
      {
        "name": "requiredRunRate",
        "precision": 2,
        "unit": "per over"
      },
      {
        "name": "runsNeeded",
        "precision": 0,
        "unit": ""
      },
      {
        "name": "oversRemaining",
        "precision": 1,
        "unit": "overs"
      },
      {
        "name": "ballsRemaining",
        "precision": 0,
        "unit": ""
      },
      {
        "name": "verdict",
        "precision": 0,
        "unit": "",
        "type": "text"
      }
    ],
    "interpret": null
  }
}
