{
  "schemaVersion": 1,
  "slug": "golf-handicap-calculator",
  "category": "gaming",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "eaec3291b35309155c4218858e01dd41f274eb8251958ceac00c35b630dfbe87",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/golf-handicap-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": "HI = round(10 × mean(d₍₁₎,…,d₍ₙ₎)) ÷ 10; CH = round(HI × S ÷ 113 + CR − P)",
    "vars": [
      [
        "d_(i)",
        "n smallest score differentials, sorted ascending"
      ],
      [
        "n",
        "Number of rounds counted"
      ],
      [
        "HI",
        "Handicap index"
      ],
      [
        "S",
        "Slope rating"
      ],
      [
        "CR",
        "Course rating"
      ],
      [
        "P",
        "Course par"
      ]
    ],
    "note": "This is a simplified illustration, not an official WHS Handicap Index calculation. WHS uses specific score-differential rules, round-count adjustments, caps, and current playing conditions; verify with your golf association."
  },
  "externalEvidence": {
    "reviewedAt": "2026-10-12",
    "sources": [
      {
        "name": "USGA — Official World Handicap System rules",
        "url": "https://www.usga.org/handicapping/roh/2024-rules-of-handicapping.html"
      }
    ],
    "referenceRole": "context",
    "implementationHash": "eaec3291b35309155c4218858e01dd41f274eb8251958ceac00c35b630dfbe87",
    "basis": "HI = round(10 × mean(d₍₁₎,…,d₍ₙ₎)) ÷ 10; CH = round(HI × S ÷ 113 + CR − P)",
    "limitations": "The references provide context and limitations. They do not validate this page’s illustrative multipliers, lookup values or predictions."
  },
  "contract": {
    "compute": "const raw=String(differentials).split(',').map(x=>x.trim());const valid=raw.length>=1&&raw.every(x=>/^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)$/.test(x)&&Number.isFinite(Number(x)));const nums=valid?raw.map(Number):[];if(!valid||nums.length>20||![roundsCounted,courseRating,slopeRating,coursePar].every(Number.isFinite)||!Number.isInteger(roundsCounted)||roundsCounted<1||roundsCounted>20||courseRating<50||courseRating>80||slopeRating<55||slopeRating>155||coursePar<54||coursePar>81)return{handicapIndex:null,averageDifferential:null,countedRounds:null,bestDifferential:null,courseHandicap:null,differentialsProvided:null,__error:'inputError'};const sorted=nums.slice().sort((a,b)=>a-b),n=Math.min(nums.length,roundsCounted),used=sorted.slice(0,n),avg=used.reduce((a,b)=>a+b,0)/n,index=Math.round(avg*10)/10,course=Math.round(index*slopeRating/113+(courseRating-coursePar));return{handicapIndex:index,averageDifferential:avg,countedRounds:n,bestDifferential:sorted[0],courseHandicap:course,differentialsProvided:nums.length};",
    "inputs": [
      {
        "name": "differentials",
        "type": "text",
        "default": "14.2, 16.8, 12.5, 18.1, 15.3, 13.9, 17.4, 11.8, 16.2, 14.7, 19.5, 12.9, 15.8, 13.1, 17.9, 14.4, 16.6, 12.2, 18.7, 15.1",
        "step": 1
      },
      {
        "name": "roundsCounted",
        "type": "number",
        "default": 8,
        "min": 1,
        "max": 20,
        "step": 1,
        "slider": true
      },
      {
        "name": "courseRating",
        "type": "number",
        "default": 71.5,
        "min": 50,
        "max": 80,
        "step": 0.1,
        "slider": true
      },
      {
        "name": "slopeRating",
        "type": "number",
        "default": 125,
        "min": 55,
        "max": 155,
        "step": 1,
        "slider": true
      },
      {
        "name": "coursePar",
        "type": "number",
        "default": 72,
        "min": 54,
        "max": 81,
        "step": 1,
        "slider": true
      }
    ],
    "outputs": [
      {
        "name": "handicapIndex",
        "precision": 1,
        "unit": ""
      },
      {
        "name": "averageDifferential",
        "precision": 2,
        "unit": ""
      },
      {
        "name": "countedRounds",
        "precision": 0,
        "unit": ""
      },
      {
        "name": "bestDifferential",
        "precision": 1,
        "unit": ""
      },
      {
        "name": "courseHandicap",
        "precision": 0,
        "unit": ""
      },
      {
        "name": "differentialsProvided",
        "precision": 0,
        "unit": ""
      }
    ],
    "interpret": null
  }
}
