{
  "schemaVersion": 1,
  "slug": "spin-the-wheel-calculator",
  "category": "gaming",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "f005a68762f37177b1bed89b2b7d6d46e209d8048359954be0a5e37fed4aeb25",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/spin-the-wheel-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": "w = list[⌊u×360 ÷ (360÷n)⌋ mod n]; a ← (a + 0x6D2B79F5) mod 2³², u = mix(a) ÷ 2³²",
    "vars": [
      [
        "n",
        "Number of options"
      ],
      [
        "s",
        "Seed"
      ],
      [
        "k",
        "Number of spins"
      ]
    ],
    "note": "Deterministic seeded PRNG (mulberry32), not random per visit: the same seed and options always give the same winner. Repeated k times; winner is the last spin. Angle 0–360°."
  },
  "externalEvidence": null,
  "contract": {
    "compute": "const rng = (s) => { let a = Math.floor(s) >>> 0; return () => { a = (a + 0x6D2B79F5) >>> 0; let t = a; t = Math.imul(t ^ (t >>> 15), t | 1); t ^= t + Math.imul(t ^ (t >>> 7), t | 61); return ((t ^ (t >>> 14)) >>> 0)/4294967296; }; }; const list = String(options).split(',').map((x) => x.trim()).filter((x) => x.length > 0); const r = rng(seed); const seg = list.length ? 360/list.length : 0; const results = []; let angle = 0; for (let i = 0; i < spin; i++) { angle = r()*360; results.push(list.length ? list[Math.floor(angle/seg) % list.length] : 'none'); } return { winner: results.length ? results[results.length - 1] : 'none', angle: angle, segmentSize: seg, totalOptions: list.length, allSpins: results.join(' > ') };",
    "inputs": [
      {
        "name": "options",
        "type": "text",
        "default": "Pizza, Tacos, Sushi, Burgers, Salad",
        "step": 1
      },
      {
        "name": "spin",
        "type": "number",
        "default": 1,
        "min": 1,
        "max": 50,
        "step": 1,
        "slider": true
      },
      {
        "name": "seed",
        "type": "number",
        "default": 3,
        "min": 0,
        "max": 1000000,
        "step": 1
      }
    ],
    "outputs": [
      {
        "name": "winner",
        "precision": 0,
        "unit": "",
        "type": "text"
      },
      {
        "name": "angle",
        "precision": 1,
        "unit": "degrees"
      },
      {
        "name": "segmentSize",
        "precision": 2,
        "unit": "degrees"
      },
      {
        "name": "totalOptions",
        "precision": 0,
        "unit": ""
      },
      {
        "name": "allSpins",
        "precision": 0,
        "unit": "",
        "type": "text"
      }
    ],
    "interpret": null
  }
}
