{
  "schemaVersion": 1,
  "slug": "picture-frame-calculator",
  "category": "diy-craft",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "92a0aec578fca5ddaf77db6b7ec71db6d4bebfafbfb881a21a08fdd8e1457d34",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/picture-frame-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": "Pm = 2 × (W + H + 4b + 4f); L(in) = Pm × 1.10; L(ft) = Pm ÷ 12 × 1.10; C = Pm ÷ 12 × p × 1.15",
    "vars": [
      [
        "Pm",
        "Outer perimeter (in)"
      ],
      [
        "W",
        "Artwork width"
      ],
      [
        "H",
        "Artwork height"
      ],
      [
        "b",
        "Mat border width"
      ],
      [
        "f",
        "Frame moulding width"
      ],
      [
        "C",
        "Moulding cost"
      ]
    ],
    "note": "Glass dimensions = artwork dimensions + 2 × mat border; frame outer dimensions = glass dimensions + 2 × frame width. Mat opening = artwork dimensions − 2 × overlap and must remain positive. Moulding includes a 10% cutting allowance; cost includes a separate 15% allowance."
  },
  "externalEvidence": null,
  "contract": {
    "compute": "const mw=artWidth-matOverlap*2,mh=artHeight-matOverlap*2;if(mw<=0||mh<=0)return{frameOuterWidth:null,frameOuterHeight:null,mouldingLength:null,mouldingFeet:null,glassWidth:null,glassHeight:null,matOpening:null,mouldingCost:null,__error:'inputError'};const glassW=artWidth+matBorder*2,glassH=artHeight+matBorder*2,outerW=glassW+frameWidth*2,outerH=glassH+frameWidth*2,perimeter=2*(outerW+outerH);return{frameOuterWidth:outerW,frameOuterHeight:outerH,mouldingLength:perimeter*1.10,mouldingFeet:perimeter/12*1.10,glassWidth:glassW,glassHeight:glassH,matOpening:mw+' x '+mh+' in',mouldingCost:perimeter/12*mouldingPricePerFoot*1.15};",
    "inputs": [
      {
        "name": "artWidth",
        "type": "number",
        "default": 16,
        "min": 1,
        "max": 200,
        "step": 0.25,
        "slider": true
      },
      {
        "name": "artHeight",
        "type": "number",
        "default": 12,
        "min": 1,
        "max": 200,
        "step": 0.25,
        "slider": true
      },
      {
        "name": "matBorder",
        "type": "number",
        "default": 2,
        "min": 0,
        "max": 12,
        "step": 0.25,
        "slider": true
      },
      {
        "name": "matOverlap",
        "type": "number",
        "default": 0.25,
        "min": 0,
        "max": 1,
        "step": 0.25
      },
      {
        "name": "frameWidth",
        "type": "number",
        "default": 1,
        "min": 0.25,
        "max": 6,
        "step": 0.25,
        "slider": true
      },
      {
        "name": "mouldingPricePerFoot",
        "type": "number",
        "default": 3,
        "min": 0,
        "max": 100,
        "step": 0.01
      }
    ],
    "outputs": [
      {
        "name": "frameOuterWidth",
        "precision": 2,
        "unit": "in"
      },
      {
        "name": "frameOuterHeight",
        "precision": 2,
        "unit": "in"
      },
      {
        "name": "mouldingLength",
        "precision": 1,
        "unit": "in"
      },
      {
        "name": "mouldingFeet",
        "precision": 2,
        "unit": "ft"
      },
      {
        "name": "glassWidth",
        "precision": 2,
        "unit": "in"
      },
      {
        "name": "glassHeight",
        "precision": 2,
        "unit": "in"
      },
      {
        "name": "matOpening",
        "precision": 0,
        "unit": "",
        "type": "text"
      },
      {
        "name": "mouldingCost",
        "precision": 2,
        "unit": "$"
      }
    ],
    "interpret": null
  }
}
