// A web shop's monitoring: order values checked for outliers (z-score, MAD, IQR, Grubbs), hourly
// traffic over four days with a spike found against the same hour of earlier days, response times
// whose level shifted, caught by CUSUM and an EWMA chart.
//
//   quillo run anomalies.qwe      then open http://localhost:8080/orders and http://localhost:8080/traffic

use "anomalies.qwer"

let ORDERS = [42.0, 39.5, 45.0, 41.2, 38.9, 44.1, 40.3, 43.7, 980.0, 41.9, 39.0, 2.5, 42.6, 40.8]

route GET /orders = {
    z: anomaly_zscore(ORDERS, 3.0)?.outliers | map((o) => o.index),
    mad: anomaly_mad(ORDERS, 3.5)?.outliers | map((o) => o.index),
    iqr: anomaly_iqr(ORDERS, 1.5)?,
    grubbs: anomaly_grubbs(ORDERS, 0.05)?.outliers | map((o) => o.value),
}

let HOURLY = [10.0, 12.0, 16.0, 18.8, 26.0, 34.2, 40.0, 48.8, 57.0, 61.2, 67.0, 71.0, 70.0, 70.0, 68.0, 61.2, 56.0, 49.8, 40.0, 33.2, 27.0, 18.8, 15.0, 13.0, 10.0, 12.0, 16.0, 18.8, 26.0, 34.2, 40.0, 48.8, 57.0, 61.2, 67.0, 71.0, 70.0, 70.0, 68.0, 61.2, 56.0, 49.8, 40.0, 33.2, 27.0, 18.8, 15.0, 13.0, 10.0, 12.0, 16.0, 18.8, 26.0, 34.2, 40.0, 48.8, 57.0, 61.2, 67.0, 71.0, 70.0, 70.0, 68.0, 61.2, 56.0, 49.8, 40.0, 33.2, 27.0, 18.8, 15.0, 13.0, 10.0, 12.0, 16.0, 18.8, 26.0, 34.2, 40.0, 48.8, 57.0, 61.2, 67.0, 71.0, 70.0, 70.0, 158.0, 61.2, 56.0, 49.8, 40.0, 33.2, 27.0, 18.8, 15.0, 13.0]

route GET /traffic = {
    seasonal: anomaly_seasonal(HOURLY, 24, 4.0)?.anomalies,
}

let LATENCY = [20.0, 20.8, 21.6, 20.4, 21.2, 20.0, 20.8, 21.6, 20.4, 21.2, 20.0, 20.8, 21.6, 20.4, 21.2, 20.0, 20.8, 21.6, 20.4, 21.2, 20.0, 20.8, 21.6, 20.4, 21.2, 20.0, 20.8, 21.6, 20.4, 21.2, 23.5, 24.7, 23.9, 25.1, 24.3, 23.5, 24.7, 23.9, 25.1, 24.3, 23.5, 24.7, 23.9, 25.1, 24.3, 23.5, 24.7, 23.9, 25.1, 24.3]

route GET /latency = {
    cusum: anomaly_cusum(LATENCY, 0.5, 5.0, 20)?.shifts,
    ewma: anomaly_ewma(LATENCY, 0.2, 3.0, 20)?.out_of_control | map((p) => p.index) | slice(0, 3),
    spikes: anomaly_rolling(ORDERS, 5, 3.5)?.anomalies | map((a) => a.index),
}
