{
  "schemaVersion": 1,
  "slug": "friction-calculator",
  "category": "science",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "194d60f4c0864bdcaa11a62da7c2c066390f9ae2b86606b2fcba47a124f9f0aa",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/friction-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": "N = mg cos θ; G = mg sin θ; Fmax = μN; D = appliedForce + G; if D ≤ Fmax: friction = D, net = a = 0; otherwise friction = Fmax, net = D − Fmax, a = net ÷ m",
    "vars": [
      [
        "m",
        "mass"
      ],
      [
        "g",
        "gravitational acceleration"
      ],
      [
        "θ",
        "incline angle in degrees"
      ],
      [
        "μ",
        "friction coefficient"
      ],
      [
        "a",
        "acceleration"
      ],
      [
        "P",
        "applied force downhill"
      ]
    ],
    "note": "N = mg cos θ; downhill gravity = mg sin θ; maximum static friction = μN. Downhill drive is applied force + gravity component. Below μN, static friction balances the drive and net force/acceleration are zero; above it, the same μ estimates moving friction."
  },
  "externalEvidence": {
    "reviewedAt": "2026-10-04",
    "sources": [
      {
        "name": "OpenStax — Static and kinetic friction",
        "url": "https://openstax.org/books/university-physics-volume-1/pages/6-2-friction"
      }
    ],
    "basis": "Friction capacity is coefficient × normal force; the incline resolves weight into normal and downhill components.",
    "limitations": "The page uses one coefficient for both the breakaway threshold and moving friction, unlike separate static and kinetic coefficients in the reference. Its applied force is added in the downhill direction; it is a simplified one-dimensional model.",
    "implementationHash": "194d60f4c0864bdcaa11a62da7c2c066390f9ae2b86606b2fcba47a124f9f0aa"
  },
  "contract": {
    "compute": "const rad = angle*Math.PI/180; const W = mass*gravity; const N = W*Math.cos(rad); const slope = W*Math.sin(rad); const F=coefficient*N; const applied=appliedForce+slope; const moves=applied>F; const friction=moves?F:Math.max(0,applied); const net=moves?applied-F:0; const acc=mass>0?net/mass:0; return { weight: W, normalForce: N, frictionForce: friction, forceToMove: Math.max(0,F-slope), netForce: net, acceleration: acc, moves: moves ? 'Yes — it accelerates' : 'No — static friction holds it' };",
    "inputs": [
      {
        "name": "mass",
        "type": "number",
        "default": 10,
        "min": 0,
        "max": 1000000,
        "step": 0.1
      },
      {
        "name": "coefficient",
        "type": "number",
        "default": 0.4,
        "min": 0,
        "max": 5,
        "step": 0.01,
        "slider": true
      },
      {
        "name": "angle",
        "type": "number",
        "default": 0,
        "min": 0,
        "max": 89,
        "step": 0.5,
        "slider": true
      },
      {
        "name": "appliedForce",
        "type": "number",
        "default": 100,
        "min": 0,
        "max": 10000000,
        "step": 0.1
      },
      {
        "name": "gravity",
        "type": "number",
        "default": 9.81,
        "min": 0.1,
        "max": 100,
        "step": 0.01
      }
    ],
    "outputs": [
      {
        "name": "weight",
        "precision": 2,
        "unit": "N"
      },
      {
        "name": "normalForce",
        "precision": 2,
        "unit": "N"
      },
      {
        "name": "frictionForce",
        "precision": 2,
        "unit": "N"
      },
      {
        "name": "forceToMove",
        "precision": 2,
        "unit": "N"
      },
      {
        "name": "netForce",
        "precision": 2,
        "unit": "N"
      },
      {
        "name": "acceleration",
        "precision": 2,
        "unit": "m/s²"
      },
      {
        "name": "moves",
        "precision": 0,
        "unit": "",
        "type": "text"
      }
    ],
    "interpret": null
  }
}
