{
  "schemaVersion": 1,
  "slug": "carpet-cleaning-cost-calculator",
  "category": "cleaning",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "47a003cca7b39015cd5ae90d4c76b5f31e702a3527e893994a901ce4c66f8a7b",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/carpet-cleaning-cost-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": "B = C_m ÷ (n × (P − c)),  P = max(A·p, r·m)",
    "vars": [
      [
        "B",
        "Break-even in years"
      ],
      [
        "C_m",
        "Cost of buying a machine"
      ],
      [
        "n",
        "Cleanings per year"
      ],
      [
        "P",
        "Professional cost per visit"
      ],
      [
        "c",
        "Chemical cost per cleaning"
      ],
      [
        "A",
        "Carpet area (sq ft)"
      ],
      [
        "p",
        "Professional price per sq ft"
      ],
      [
        "r",
        "Rooms cleaned"
      ],
      [
        "m",
        "Minimum charge per room"
      ]
    ],
    "note": "Break-even years = machine price ÷ [(professional price per visit − chemical cost per visit) × cleanings per year]. If annual savings are zero or negative, there is no finite break-even. Maintenance and resale value are excluded."
  },
  "externalEvidence": null,
  "contract": {
    "compute": "const pro = Math.max(area*proPricePerSqFt, rooms*proRoomMinimum); const rental = rentalCost + chemicalCost; const perYear = rental*cleaningsPerYear; const proYear = pro*cleaningsPerYear; const annualOwnershipSaving = (pro-chemicalCost)*cleaningsPerYear; const breakevenYears = annualOwnershipSaving > 0 ? machineCost/annualOwnershipSaving : null; return { professionalCost: pro, rentalTotal: rental, doItYourselfTotal: perYear, savings: proYear-perYear, breakevenYears, cheapest: pro < rental ? 'Professional cleaning' : 'Renting a machine' };",
    "inputs": [
      {
        "name": "area",
        "type": "number",
        "default": 1200,
        "min": 10,
        "max": 100000,
        "step": 10
      },
      {
        "name": "rooms",
        "type": "number",
        "default": 4,
        "min": 1,
        "max": 60,
        "step": 1,
        "slider": true
      },
      {
        "name": "proPricePerSqFt",
        "type": "number",
        "default": 0.35,
        "min": 0,
        "max": 20,
        "step": 0.01,
        "slider": true
      },
      {
        "name": "proRoomMinimum",
        "type": "number",
        "default": 45,
        "min": 0,
        "max": 1000,
        "step": 1,
        "slider": true
      },
      {
        "name": "rentalCost",
        "type": "number",
        "default": 40,
        "min": 0,
        "max": 1000,
        "step": 1,
        "slider": true
      },
      {
        "name": "chemicalCost",
        "type": "number",
        "default": 15,
        "min": 0,
        "max": 500,
        "step": 1,
        "slider": true
      },
      {
        "name": "cleaningsPerYear",
        "type": "number",
        "default": 2,
        "min": 1,
        "max": 52,
        "step": 1,
        "slider": true
      },
      {
        "name": "machineCost",
        "type": "number",
        "default": 300,
        "min": 0,
        "max": 10000,
        "step": 10,
        "slider": true
      }
    ],
    "outputs": [
      {
        "name": "professionalCost",
        "precision": 2,
        "unit": "$"
      },
      {
        "name": "rentalTotal",
        "precision": 2,
        "unit": "$"
      },
      {
        "name": "doItYourselfTotal",
        "precision": 2,
        "unit": "$"
      },
      {
        "name": "savings",
        "precision": 2,
        "unit": "$"
      },
      {
        "name": "breakevenYears",
        "precision": 1,
        "unit": "years",
        "optional": true
      },
      {
        "name": "cheapest",
        "precision": 0,
        "unit": "",
        "type": "text"
      }
    ],
    "interpret": null
  }
}
