#!/usr/bin/env python3
"""Por qué en un trabajo colectivo importa la peor latencia y no el promedio.

    python3 tail_rounds.py <trabajadores> <probabilidad_lenta> <ms_normal> <ms_lento> [rondas]

Cada ronda espera al más lento de los trabajadores. Cada uno tarda ms_normal, y con la
probabilidad dada tarda ms_lento. Compara lo simulado con la cuenta exacta.
"""
import random
import sys


def expected_slow_fraction(workers, probability):
    """Probabilidad de que al menos un trabajador sea lento en una ronda."""
    return 1 - (1 - probability) ** workers


def simulate(workers, probability, normal, slow, rounds, seed=14):
    """Devuelve (promedio por trabajador, promedio por ronda, fracción de rondas lentas)."""
    rng = random.Random(seed)
    worker_total = 0.0
    round_total = 0.0
    slow_rounds = 0
    for _ in range(rounds):
        slow_workers = sum(rng.random() < probability for _ in range(workers))
        worker_total += slow_workers * slow + (workers - slow_workers) * normal
        round_total += slow if slow_workers else normal
        slow_rounds += bool(slow_workers)
    return worker_total / (workers * rounds), round_total / rounds, slow_rounds / rounds


def main():
    if len(sys.argv) not in (5, 6):
        print(__doc__)
        return 2
    workers, probability = int(sys.argv[1]), float(sys.argv[2])
    normal, slow = float(sys.argv[3]), float(sys.argv[4])
    rounds = int(sys.argv[5]) if len(sys.argv) == 6 else 20000
    per_worker, per_round, fraction = simulate(workers, probability, normal, slow, rounds)
    print(f"{workers} trabajadores, {probability:.2%} lentos: promedio por trabajador "
          f"{per_worker:.1f} ms; promedio por ronda {per_round:.1f} ms; rondas lentas "
          f"{fraction:.1%} (exacto: {expected_slow_fraction(workers, probability):.1%})")
    return 0


if __name__ == "__main__":
    sys.exit(main())
