--- name: duration_stats kind: function lang: go domain: datascience version: "1.0.0" purity: pure signature: "func DurationStatsFrom(durations []int64) DurationStats" description: "Calcula estadisticas descriptivas (N, media, P50/P90/P99) de un slice de duraciones en milisegundos. Ordena una copia local sin mutar el input. Retorna DurationStats{} para slice vacio." tags: [statistics, duration, percentile, metrics, int64] uses_functions: - percentile_int64_go_datascience uses_types: - DurationStats_go_datascience returns: - DurationStats_go_datascience returns_optional: false error_type: "" imports: - sort params: - name: durations desc: "Slice de duraciones en milisegundos. No necesita estar ordenado; se ordena internamente sobre una copia." output: "DurationStats con N, AvgMs, P50Ms, P90Ms y P99Ms calculados. DurationStats{} si el slice esta vacio." tested: true tests: - "slice vacio retorna estadisticas cero" - "un solo elemento produce estadisticas identicas" - "cinco elementos calcula media y percentiles correctos" - "input original no se muta" - "diez elementos p90 usa idx truncado" test_file_path: "functions/datascience/duration_stats_test.go" file_path: "functions/datascience/duration_stats.go" source_repo: "https://github.com/egutierrez/fn_registry/apps/kanban" source_license: "private" source_file: "apps/kanban/backend/metrics.go" --- ## Ejemplo ```go durations := []int64{50, 10, 30, 40, 20} stats := DurationStatsFrom(durations) // stats.N = 5 // stats.AvgMs = 30 // stats.P50Ms = 30 // stats.P90Ms = 50 // stats.P99Ms = 50 ``` ## Notas Ordena una copia con `sort.Slice` para no mutar el slice original. Compone `Percentile` (`percentile_int64_go_datascience`) para los calculos de P50/P90/P99. Extraido y generalizado desde `apps/kanban/backend/metrics.go:113-130`.