{
  "schemaVersion": 1,
  "slug": "fabric-calculator",
  "category": "diy-craft",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "81d670f9b464133454a596913c737c3f2719501c38ac4ae838b0b2aec36630d7",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/fabric-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": "y45 = b45 × k; y60 = b60 × k; Y = { y60, w ≥ 58; (y45 + y60) ÷ 2, 50 ≤ w < 58; y45, w < 50 } + e",
    "vars": [
      [
        "b45",
        "garment base yards, 45 in width"
      ],
      [
        "b60",
        "garment base yards, 60 in width"
      ],
      [
        "k",
        "size factor"
      ],
      [
        "w",
        "fabric width (in)"
      ],
      [
        "e",
        "extra yards"
      ],
      [
        "y45",
        "adjusted yards, 45 in width"
      ],
      [
        "y60",
        "adjusted yards, 60 in width"
      ],
      [
        "Y",
        "yards to buy"
      ]
    ],
    "note": "Base yardage and size factors are illustrative lookup assumptions, not a universal pattern standard. Under 50 in uses the 45-in estimate; 50–57.99 in linearly averages 45- and 60-in estimates; 58 in and wider uses the 60-in estimate. Add allowance for print matching and layout."
  },
  "externalEvidence": null,
  "contract": {
    "compute": "const base = { tshirt: [1.25, 1.0], shirt: [2.25, 1.75], dress: [3.0, 2.25], skirt: [1.5, 1.25], trousers: [2.5, 2.0], jacket: [3.25, 2.5], childOutfit: [1.5, 1.25] }[garment] || [2, 1.75]; const scale = size === 'small' ? 0.85 : size === 'large' ? 1.15 : size === 'xlarge' ? 1.3 : 1; const y45 = base[0]*scale; const y60 = base[1]*scale; const needed = fabricWidth >= 58 ? y60 : fabricWidth >= 50 ? (y45 + y60)/2 : y45; const buy = needed + extraYards; return { yards45: y45 + extraYards, yards60: y60 + extraYards, yardsNeeded: buy, totalCost: buy*pricePerYard, meters: buy*0.9144 };",
    "inputs": [
      {
        "name": "garment",
        "type": "select",
        "default": "dress",
        "options": [
          {
            "value": "tshirt"
          },
          {
            "value": "shirt"
          },
          {
            "value": "dress"
          },
          {
            "value": "skirt"
          },
          {
            "value": "trousers"
          },
          {
            "value": "jacket"
          },
          {
            "value": "childOutfit"
          }
        ]
      },
      {
        "name": "size",
        "type": "select",
        "default": "medium",
        "options": [
          {
            "value": "small"
          },
          {
            "value": "medium"
          },
          {
            "value": "large"
          },
          {
            "value": "xlarge"
          }
        ]
      },
      {
        "name": "fabricWidth",
        "type": "number",
        "default": 45,
        "min": 20,
        "max": 120,
        "step": 1,
        "slider": true
      },
      {
        "name": "extraYards",
        "type": "number",
        "default": 0.25,
        "min": 0,
        "max": 10,
        "step": 0.25,
        "slider": true
      },
      {
        "name": "pricePerYard",
        "type": "number",
        "default": 8,
        "min": 0,
        "max": 500,
        "step": 0.01
      }
    ],
    "outputs": [
      {
        "name": "yards45",
        "precision": 2,
        "unit": "yards"
      },
      {
        "name": "yards60",
        "precision": 2,
        "unit": "yards"
      },
      {
        "name": "yardsNeeded",
        "precision": 2,
        "unit": "yards"
      },
      {
        "name": "totalCost",
        "precision": 2,
        "unit": "$"
      },
      {
        "name": "meters",
        "precision": 2,
        "unit": "m"
      }
    ],
    "interpret": null
  }
}
