{
  "status": "verified",
  "inputKind": "synthetic",
  "settings": {
    "minSamplesPerPoint": 50,
    "rttMaxMs": 2000,
    "maxPointSpanSeconds": 180,
    "bootstrapSeed": 7,
    "bootstrapIterations": 5000
  },
  "totals": {
    "inputSamples": 672,
    "inputLocations": 13,
    "pairedLocations": 8,
    "excludedLocations": 5,
    "usedSamples": 477,
    "droppedSamples": 195,
    "otherClientSamples": 0
  },
  "comparison": {
    "medianDifferenceDb": -4.0,
    "madDb": 1.0,
    "robustSigmaDb": 1.4826,
    "intervalLowDb": -5.0,
    "intervalHighDb": -3.0,
    "intervalLabel": "95% percentile bootstrap interval across paired locations (descriptive)",
    "intervalStatus": "available"
  },
  "points": [
    {
      "id": "P01",
      "totalSamples": 60,
      "usedSamples": 60,
      "eligibleSamples": 60,
      "droppedRtt": 0,
      "missingRssi": 0,
      "missingRtt": 0,
      "surveyDbm": -54.0,
      "wlcMedianDbm": -58.0,
      "differenceDb": -4.0,
      "status": "paired",
      "reason": "Matches a survey location and meets the declared input rules."
    },
    {
      "id": "P02",
      "totalSamples": 60,
      "usedSamples": 60,
      "eligibleSamples": 60,
      "droppedRtt": 0,
      "missingRssi": 0,
      "missingRtt": 0,
      "surveyDbm": -58.0,
      "wlcMedianDbm": -61.0,
      "differenceDb": -3.0,
      "status": "paired",
      "reason": "Matches a survey location and meets the declared input rules."
    },
    {
      "id": "P03",
      "totalSamples": 60,
      "usedSamples": 57,
      "eligibleSamples": 57,
      "droppedRtt": 2,
      "missingRssi": 1,
      "missingRtt": 0,
      "surveyDbm": -61.0,
      "wlcMedianDbm": -66.0,
      "differenceDb": -5.0,
      "status": "paired",
      "reason": "Matches a survey location and meets the declared input rules."
    },
    {
      "id": "P04",
      "totalSamples": 60,
      "usedSamples": 60,
      "eligibleSamples": 60,
      "droppedRtt": 0,
      "missingRssi": 0,
      "missingRtt": 0,
      "surveyDbm": -63.0,
      "wlcMedianDbm": -67.0,
      "differenceDb": -4.0,
      "status": "paired",
      "reason": "Matches a survey location and meets the declared input rules."
    },
    {
      "id": "P05",
      "totalSamples": 60,
      "usedSamples": 60,
      "eligibleSamples": 60,
      "droppedRtt": 0,
      "missingRssi": 0,
      "missingRtt": 0,
      "surveyDbm": -67.0,
      "wlcMedianDbm": -71.0,
      "differenceDb": -4.0,
      "status": "paired",
      "reason": "Matches a survey location and meets the declared input rules."
    },
    {
      "id": "P06",
      "totalSamples": 60,
      "usedSamples": 60,
      "eligibleSamples": 60,
      "droppedRtt": 0,
      "missingRssi": 0,
      "missingRtt": 0,
      "surveyDbm": -70.0,
      "wlcMedianDbm": -73.0,
      "differenceDb": -3.0,
      "status": "paired",
      "reason": "Matches a survey location and meets the declared input rules."
    },
    {
      "id": "P07",
      "totalSamples": 60,
      "usedSamples": 60,
      "eligibleSamples": 60,
      "droppedRtt": 0,
      "missingRssi": 0,
      "missingRtt": 0,
      "surveyDbm": -73.0,
      "wlcMedianDbm": -78.0,
      "differenceDb": -5.0,
      "status": "paired",
      "reason": "Matches a survey location and meets the declared input rules."
    },
    {
      "id": "P08",
      "totalSamples": 60,
      "usedSamples": 60,
      "eligibleSamples": 60,
      "droppedRtt": 0,
      "missingRssi": 0,
      "missingRtt": 0,
      "surveyDbm": -75.0,
      "wlcMedianDbm": -93.0,
      "differenceDb": -18.0,
      "status": "paired",
      "reason": "Matches a survey location and meets the declared input rules."
    },
    {
      "id": "P09",
      "totalSamples": 12,
      "usedSamples": 0,
      "eligibleSamples": 12,
      "droppedRtt": 0,
      "missingRssi": 0,
      "missingRtt": 0,
      "surveyDbm": -64.0,
      "wlcMedianDbm": -68.0,
      "differenceDb": null,
      "status": "excluded",
      "reason": "Needs 50 eligible samples; 12 remain."
    },
    {
      "id": "P10",
      "totalSamples": 60,
      "usedSamples": 0,
      "eligibleSamples": 0,
      "droppedRtt": 0,
      "missingRssi": 0,
      "missingRtt": 0,
      "surveyDbm": -64.0,
      "wlcMedianDbm": null,
      "differenceDb": null,
      "status": "excluded",
      "reason": "Radio identity changed within this location; samples are not pooled."
    },
    {
      "id": "P11",
      "totalSamples": 60,
      "usedSamples": 0,
      "eligibleSamples": 60,
      "droppedRtt": 0,
      "missingRssi": 0,
      "missingRtt": 0,
      "surveyDbm": null,
      "wlcMedianDbm": -68.0,
      "differenceDb": null,
      "status": "excluded",
      "reason": "No survey reading for this controller location."
    },
    {
      "id": "P12",
      "totalSamples": 60,
      "usedSamples": 0,
      "eligibleSamples": 0,
      "droppedRtt": 0,
      "missingRssi": 60,
      "missingRtt": 0,
      "surveyDbm": -64.0,
      "wlcMedianDbm": null,
      "differenceDb": null,
      "status": "excluded",
      "reason": "Needs 50 eligible samples; 0 remain."
    },
    {
      "id": "P13",
      "totalSamples": 0,
      "usedSamples": 0,
      "eligibleSamples": 0,
      "droppedRtt": 0,
      "missingRssi": 0,
      "missingRtt": 0,
      "surveyDbm": -64.0,
      "wlcMedianDbm": null,
      "differenceDb": null,
      "status": "excluded",
      "reason": "No controller samples for this survey point."
    }
  ],
  "method": {
    "difference": "Controller median minus survey reading, in dB",
    "sourceNote": "Controller client-performance RSSI describes client-to-AP reception; a survey can describe AP-to-survey-device reception. Their difference is descriptive, not a universal device correction, coverage acceptance or voice target.",
    "citations": [
      {
        "label": "Cisco: the three RF relationships (slides 7-11)",
        "url": "https://www.ciscolive.com/c/dam/r/ciscolive/emea/docs/2024/pdf/BRKEWN-2087.pdf"
      }
    ]
  },
  "schemaVersion": "calibration-showcase-v1",
  "sourceDate": "2026-10-26",
  "dataKind": "synthetic",
  "verification": {
    "testCount": 58,
    "repeatRuns": 2,
    "byteIdentical": true,
    "semanticIdentical": true,
    "checks": [
      "All offline regression and mocked-protocol tests passed.",
      "Both CLI runs completed successfully with default analysis settings.",
      "Both input CSVs, analysis JSON and XLSX match byte for byte.",
      "Every workbook cell matches across the repeated runs.",
      "Workbook values reconcile to the public point and summary data.",
      "No real controller, survey project or clinical data was used."
    ]
  },
  "artifacts": {
    "report": "/demos/calibrate-ekahau/sample-report.xlsx",
    "samples": "/demos/calibrate-ekahau/wlc-samples.csv",
    "survey": "/demos/calibrate-ekahau/survey-points.csv",
    "summary": "/demos/calibrate-ekahau/verification.json"
  },
  "limits": [
    "Fictional fixed-time inputs; this verifies the offline comparison and report, not a hospital deployment.",
    "Survey inputs are a manual point CSV, not an imported Ekahau project.",
    "RESTCONF parsing is tested with mocked Cisco-shaped responses. No live controller acceptance or RSSI freshness is established.",
    "The two observation paths can have different radio directions, devices, antenna patterns and collection conditions. Their difference is not a universal correction.",
    "The bootstrap resamples paired locations, not repeated polls. Fewer than five pairs withholds the interval.",
    "Poll duration is elapsed time for the complete controller GET sequence, not client-path RTT or RF sample age.",
    "Unmatched eligible samples remain visible but are not counted as used in the paired comparison.",
    "No coverage, roaming, voice-service or clinical outcome is validated."
  ],
  "artifactHashes": {
    "wlc-samples.csv": "b71f8dee55f69f2d3e0d083707f76f99e455d9dde397aa57e8f8a2faa950f863",
    "survey-points.csv": "8b244823a3c6580facf74163d74c029134f85606fc74b45cb01912e486084b3d",
    "sample-report.xlsx": "67a2393c94a8f387fb3d2c3536fc9e8ea6d600d169f78cb885af19c9a19a3a40",
    "comparison.json": "3c0285c3da931fc82bb048d4ef31bb37ef4ea227b18ca2fcf990708823e4794c"
  },
  "runtime": {
    "python": "3.12.3",
    "openpyxl": "3.1.5"
  }
}
