Part of the Country Resilience Score feature. See full plan: docs/plans/2026-03-29-feat-country-resilience-score-plan.md
Scope
Port 6 pure functions from qadr110's nrc-statistics.ts into server/_shared/resilience-stats.ts. No Redis reads, no side effects.
File: server/_shared/resilience-stats.ts
Functions:
cronbachAlpha(items: number[][]): number — composite reliability check, flags low-confidence scores
detectTrend(values: number[]): 'rising' | 'stable' | 'falling' — linear regression slope
detectChangepoints(values: number[], threshold?): number[] — CUSUM structural break detection
minMaxNormalize(values: number[]): number[] — dimension normalization utility
exponentialSmoothing(values: number[], alpha?): number[] — smoothing noisy real-time inputs
nrcForecast(history, horizonDays, alpha?): { values, confidenceIntervals, probabilityUp, probabilityDown } — hybrid ETS + linear trend
Do NOT port: deaEfficiency, controlChart, laggedCorrelation.
Tests: tests/resilience-stats.test.mts
cronbachAlpha: known matrix, single-row, all-same values
detectTrend: monotone up/down/flat, fewer than 3 values
detectChangepoints: bimodal series, constant series, short series
minMaxNormalize: boundary values (all same, empty, negatives)
nrcForecast: output length = horizonDays, CI lower ≤ upper, values in 0–100, probabilities sum to 1
Done when
All tests pass, typecheck:api clean.
Part of the Country Resilience Score feature. See full plan:
docs/plans/2026-03-29-feat-country-resilience-score-plan.mdScope
Port 6 pure functions from qadr110's
nrc-statistics.tsintoserver/_shared/resilience-stats.ts. No Redis reads, no side effects.File:
server/_shared/resilience-stats.tsFunctions:
cronbachAlpha(items: number[][]): number— composite reliability check, flags low-confidence scoresdetectTrend(values: number[]): 'rising' | 'stable' | 'falling'— linear regression slopedetectChangepoints(values: number[], threshold?): number[]— CUSUM structural break detectionminMaxNormalize(values: number[]): number[]— dimension normalization utilityexponentialSmoothing(values: number[], alpha?): number[]— smoothing noisy real-time inputsnrcForecast(history, horizonDays, alpha?): { values, confidenceIntervals, probabilityUp, probabilityDown }— hybrid ETS + linear trendDo NOT port:
deaEfficiency,controlChart,laggedCorrelation.Tests:
tests/resilience-stats.test.mtscronbachAlpha: known matrix, single-row, all-same valuesdetectTrend: monotone up/down/flat, fewer than 3 valuesdetectChangepoints: bimodal series, constant series, short seriesminMaxNormalize: boundary values (all same, empty, negatives)nrcForecast: output length = horizonDays, CI lower ≤ upper, values in 0–100, probabilities sum to 1Done when
All tests pass,
typecheck:apiclean.