feat(cosmobiologia): rectificador automático — curva del perfil del barrido

Tercer y último incremento: la visualización. El rectificador ya
muestra POR QUÉ una hora gana, no sólo cuál.

- cosmobiologia-canvas: CanvasState gana `rectificacion` +
  `set_rectificacion`. render_rectify_profile dibuja el barrido como
  un histograma en el footer — cada barra es una hora candidata, su
  altura crece cuanto menor el puntaje; la barra más alta (el valle
  del puntaje) es la hora rectificada, resaltada. Etiqueta los hitos
  (mejor, 0, extremos).
- shell: run_rectificacion publica el Rectificacion al canvas además
  del resumen textual al panel.

Con esto el rectificador automático (#67) queda completo: motor de
escaneo GR + UI de entrada + visualización del perfil.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
sergio
2026-05-22 16:42:59 +00:00
parent a7e9662fad
commit 208dc15569
2 changed files with 137 additions and 11 deletions
+25 -10
View File
@@ -1411,16 +1411,31 @@ impl Shell {
.to_string();
// Ventana ±15 min, paso 1 min — el barrido GR estándar.
let resultado = match cosmobiologia_engine::rectificar(&chart, &eventos, 15, 1, &key_gr) {
Ok(r) => format!(
"{:+} min · puntaje {:.2}",
r.mejor_offset_minutos, r.mejor_puntaje
),
Err(_) => "define al menos un evento (edad > 0)".to_string(),
};
self.panel.update(cx, |p, cx| {
p.set_string("primary_directions", "resultado", Some(resultado), cx)
});
match cosmobiologia_engine::rectificar(&chart, &eventos, 15, 1, &key_gr) {
Ok(r) => {
let resumen = format!(
"{:+} min · puntaje {:.2}",
r.mejor_offset_minutos, r.mejor_puntaje
);
self.panel.update(cx, |p, cx| {
p.set_string("primary_directions", "resultado", Some(resumen), cx)
});
// Publicar el perfil al canvas: dibuja la curva del
// barrido, cuyo valle marca la hora rectificada.
self.canvas
.update(cx, |c, cx| c.set_rectificacion(Some(r), cx));
}
Err(_) => {
self.panel.update(cx, |p, cx| {
p.set_string(
"primary_directions",
"resultado",
Some("define al menos un evento (edad > 0)".to_string()),
cx,
)
});
}
}
}
/// Snapshot del cielo en este instante anclado al lugar del