package main

import (
	"fmt"
	"math"
	"slices"
)

func percentile(xs []float64, p float64) float64 {
	if len(xs) == 0 || p <= 0 || p > 1 {
		panic("invalid percentile input")
	}
	ys := slices.Clone(xs)
	slices.Sort(ys)
	return ys[int(math.Ceil(float64(len(ys))*p))-1]
}
func main() {
	const users, reads, writes, peak = 100000., 20., 2., 10.
	readQPS := users * reads / 86400
	writeQPS := users * writes / 86400
	fmt.Printf("read avg=%.2f peak=%.2f write avg=%.2f peak=%.2f\n", readQPS, readQPS*peak, writeQPS, writeQPS*peak)
	for _, days := range []float64{365, 730} {
		logical := users * writes * days * 1000
		provisioned := logical * 1.5 * 3 / .7
		fmt.Printf("days=%.0f logical=%.2f GB provisioned=%.2f GB\n", days, logical/1e9, provisioned/1e9)
	}
	fmt.Printf("egress=%.2f Mbit/s\n", readQPS*peak*4500*8/1e6)
	fmt.Printf("mean inflight=%.2f\n", (readQPS+writeQPS)*peak*.08)
	xs := make([]float64, 1000)
	for i := range xs {
		xs[i] = 10
		if i >= 980 {
			xs[i] = 1000
		}
	}
	total := 0.
	for _, x := range xs {
		total += x
	}
	fmt.Printf("synthetic latency mean=%.1f p50=%.0f p95=%.0f p99=%.0f ms\n", total/float64(len(xs)), percentile(xs, .5), percentile(xs, .95), percentile(xs, .99))
	for _, hit := range []float64{.99, .90, 0} {
		fmt.Printf("hit=%.0f%% DB reads=%.2f/s\n", hit*100, readQPS*peak*(1-hit))
	}
	// Deterministic queue model: arrivals then service within each 1 s bucket.
	backlog := 0
	for sec := 1; sec <= 3; sec++ {
		backlog += 1200
		backlog -= 1000
		fmt.Printf("second=%d backlog=%d\n", sec, backlog)
	}
	fmt.Printf("drain with 800 arrivals/s: %.0f seconds\n", float64(backlog)/(1000-800))
}
