import { useMemo } from 'react'
/**
* Chart 4: Predicted draws by year vs. observed — for three-year models only.
* Shows model's predicted median and 95% interval alongside the observed value,
* faceted by four quadrants (1yr baseline / 1yr covariate / 3yr baseline / 3yr covariate).
* Mirrors wp_fig_district_intervals() from paper_figures.R.
*/
const QUADRANT_LABELS = [
{ key: 'unified_m1_mod', label: 'One-year, no covariate' },
{ key: 'unified_m2_mod', label: 'One-year + referral rate' },
{ key: 'unified_m3_mod', label: 'Three-year, no covariate' },
{ key: 'unified_m4_mod', label: 'Three-year + referral rate' },
]
const WAVE_LABELS = { '15-16': '2015–16', '17-18': '2017–18', '21-22': '2021–22' }
export default function ModelDrawsComparison({ data, waves, districtName }) {
// Derive per-wave observed arrest totals from the time series
const waveData = useMemo(() => {
return ['15-16', '17-18', '21-22'].map(year => {
const rows = (data.waves && data.waves[year]) || []
return {
year, label: WAVE_LABELS[year],
arrests: rows.reduce((sum, r) => sum + (r.observed_arrests || 0), 0),
enroll: rows.reduce((sum, r) => sum + (r.stu_enroll || 0), 0),
}
})
}, [data.waves])
const quadModels = data.quadData || {}
// Compute max arrests for Y-axis scaling across all quadrants and years
const allArrestValues = []
waveData.forEach(d => allArrestValues.push(d.arrests))
Object.entries(quadModels).forEach(([modelId, rows]) => {
['15-16', '17-18', '21-22'].forEach(year => {
const yearRow = (rows || []).find(r => r.year === year)
if (yearRow) allArrestValues.push(Math.round((yearRow.count_median || 0)))
})
})
const maxArrests = Math.max(...allArrestValues, 1)
return (
{/* Chart title */}
Model predictions vs. observed — by wave & model type
{/* Four small multiples (one per quadrant) */}
{QUADRANT_LABELS.map((q) => (
))}
{/* Note */}
Red circles = observed arrests. Teal points + error bars (three-year models only) show Bayesian model median and 90% interval. One-year models can only compare against the most recent wave.
)
}
/** Single quadrant chart: predicted vs observed for one model specification */
function QuadrantChart({ q, waveData, quadModels, maxArrests }) {
const width = 360
const height = 280
const margin = { top: 45, right: 25, bottom: 70, left: 55 }
// For three-year models show all 3 waves; for one-year only the most recent
const showYears = (q.key.includes('m3') || q.key.includes('m4')) ? ['15-16', '17-18', '21-22'] : ['21-22']
// Derive chart dimensions from margin + width/height
const innerWidth = width - margin.left - margin.right
const innerHeight = height - margin.top - margin.bottom
return (