// Reduce timings.json (bench.mjs output) to the per-process summary the article
// tables. Usage: node summarize.mjs timings.json > process-summary.json
import { readFileSync } from 'node:fs'
import { fileURLToPath } from 'node:url'

/** Median for any sample count; the midpoint mean when the count is even. */
export const median = values => {
  const sorted = [...values].sort((a, b) => a - b)
  const mid = sorted.length >> 1
  return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2
}

export function summarize(timings) {
  const { sessions } = timings
  const cells = sessions[0].cells.map((first, index) => {
    const perProcess = sessions.map(session => session.cells[index])
    if (perProcess.some(cell => cell.kernel !== first.kernel || cell.size !== first.size)) {
      throw new Error(`Sessions disagree on cell ${index}: ${first.kernel} ${first.size}`)
    }
    const variants = {}
    for (const variant of ['scalar', 'simd']) {
      const processMediansMs = perProcess.map(cell => cell.mediansMs[variant])
      variants[variant] = {
        processMediansMs,
        medianMs: median(processMediansMs),
        minMs: Math.min(...processMediansMs),
        maxMs: Math.max(...processMediansMs),
      }
    }
    const perProcessRatios = perProcess.map(cell => cell.simdOverScalar)
    return {
      kernel: first.kernel,
      size: first.size,
      variants,
      simdOverScalar: {
        perProcess: perProcessRatios,
        min: Math.min(...perProcessRatios),
        max: Math.max(...perProcessRatios),
      },
    }
  })
  return {
    source: 'timings.json',
    statistic: `median and observed min/max of ${sessions.length} process medians; not confidence intervals`,
    cells,
  }
}

if (process.argv[1] === fileURLToPath(import.meta.url)) {
  const timings = JSON.parse(readFileSync(process.argv[2], 'utf8'))
  process.stdout.write(JSON.stringify(summarize(timings), null, 2) + '\n')
}
