fix: el jitter era demasiado regular; planificar por adelantado

El 96% de las entradas caian en solo dos minutos (08:58 / 08:59). El historial
real del usuario tiene 4 valores repartidos, o sea que el bot resultaba MAS
regular que una persona.

Tres cosas estaban mal:

- La deriva de la costumbre se aplicaba SUMANDO segundos. Cuando salia negativa
  hundia el valor contra el suelo y amontonaba medio año en el mismo minuto,
  justo lo contrario de lo que pretendia. Ahora va en escala logaritmica:
  multiplica el centro en vez de sumarse. Solo con eso la moda baja del 50% al
  39%, sin coste ninguno.

- La distribucion diaria era uniforme. Una lognormal da mas minutos distintos
  por menos presencia extra, porque la mayoria de los dias caen baratos cerca de
  la hora y solo unos pocos se van lejos. Ademas es la forma real de la llegada
  de alguien que intenta ser puntual.

- El tope recortaba con min(), asi que un 3% de los dias caia exactamente en el
  limite y se veia como un muro en el histograma. Ahora resortea.

El compromiso de fondo no tiene truco: solo se puede variar hacia atras, y
alejarse cuesta presencia. Perfiles medidos sobre los 226 dias laborables del
año, los tres con saldo 0:

    discreto    2,8 min/dia   entrada 2 minutos, moda 75%
    natural     4,2 min/dia   entrada 5 minutos, moda 51%   <- por defecto
    camuflado   5,5 min/dia   entrada 4 minutos, moda 43%

Ademas, /proximos mostraba una banda estimada que ocultaba la cola. Ahora se
planifican 21 dias por adelantado y se muestran las horas exactas, con lo que
la prevision es real y se puede decidir sobre ella. El plan guardado se
revalida contra el calendario de Timenet y se regenera si cambia el tipo de
jornada de un dia. Google Calendar se consulta con una sola autenticacion para
todo el horizonte.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-24 19:36:38 +02:00
parent 365f676a1f
commit a496b1c672
5 changed files with 133 additions and 87 deletions

View File

@@ -19,18 +19,28 @@ DEFAULTS = {
# margen, en segundos, con el que se ficha respecto de la hora teorica.
# Entradas ANTES (Timenet no acredita nada fuera de la ventana, pero si
# debita las entradas tardias). Salidas DESPUES.
# perfil "equilibrado": saldo 0 con ~3,6 min/dia de presencia extra.
# Mas holgado (40/150/30/130) = mas seguro pero ~5,7 min/dia.
# Mas ajustado (20/70/15/45) = ~2,7 min/dia pero solo 15s de colchon.
"entry_before_min": 30,
"entry_before_max": 100,
"exit_after_min": 20,
"exit_after_max": 70,
# deriva lenta de la hora habitual, para no parecer un dado nuevo cada dia
"drift_sigma": 25,
"drift_clamp": 60,
# Lognormal: la moda queda pegada a la hora teorica y la cola va hacia
# mas margen. Da mas minutos distintos por menos presencia extra que una
# uniforme (ver la nota de cabecera de app/jitter.py).
# floor = margen minimo, median = mediana, sigma = longitud de la cola,
# cap = tope duro.
# perfil "natural": 5 minutos distintos en la entrada, 4,1 min/dia de
# presencia extra. Ver la tabla de perfiles en el README.
"entry_floor": 12,
"entry_median": 58,
"entry_sigma": 0.95,
"entry_cap": 330,
"exit_floor": 10,
"exit_median": 42,
"exit_sigma": 0.95,
"exit_cap": 300,
# Deriva lenta de la hora habitual, en unidades LOGARITMICAS (multiplica
# el centro). Mueve la moda de una semana a otra, lo que ensancha lo que se
# ve a lo largo del mes con coste medio practicamente nulo.
"drift_sigma": 0.30,
"drift_clamp": 0.75,
# margen de seguridad: nunca fichar una entrada a menos de X s de la hora
"entry_guard": 20,
"entry_guard": 12,
},
"geo_jitter_meters": 12.0,
"telegram": {},