Files
pluriwave/lib/servicios/servicio_programacion_alarmas.dart
T
FreeTLab a3a648c633
Build & Deploy Pluriwave / Análisis de código (push) Successful in 15s
Build & Deploy Pluriwave / Build APK + AAB release (push) Successful in 4m21s
feat(alarm): complete musical alarm flows
2026-05-22 00:40:01 +02:00

115 lines
3.2 KiB
Dart

import '../modelos/alarma_musical.dart';
class ServicioProgramacionAlarmas {
DateTime? calcularProxima({
required AlarmaMusical alarma,
required DateTime desde,
List<RangoVacaciones> vacaciones = const [],
List<ExcepcionAlarma> excepciones = const [],
}) {
if (!alarma.activa) return null;
final diaBase =
alarma.tipoProgramacion == TipoProgramacionAlarma.unica &&
alarma.fechaUnica != null
? alarma.fechaUnica!
: desde;
final inicio = DateTime(
diaBase.year,
diaBase.month,
diaBase.day,
alarma.hora,
alarma.minuto,
);
final primerCandidato =
alarma.tipoProgramacion == TipoProgramacionAlarma.unica
? inicio
: inicio.isAfter(desde)
? inicio
: inicio.add(const Duration(days: 1));
return switch (alarma.tipoProgramacion) {
TipoProgramacionAlarma.unica =>
primerCandidato.isAfter(desde) &&
_esValida(alarma, primerCandidato, vacaciones, excepciones)
? primerCandidato
: null,
TipoProgramacionAlarma.diaria => _buscarDiaria(
alarma,
primerCandidato,
vacaciones,
excepciones,
),
TipoProgramacionAlarma.diasSemana => _buscarPorDiasSemana(
alarma,
primerCandidato,
vacaciones,
excepciones,
),
};
}
DateTime calcularSnooze(DateTime desde, int minutos) {
final seguro = minutos == 3 || minutos == 5 || minutos == 10 ? minutos : 5;
return desde.add(Duration(minutes: seguro));
}
bool estaEnVacaciones(DateTime fecha, List<RangoVacaciones> vacaciones) =>
vacaciones.any((rango) => rango.contiene(fecha));
DateTime? _buscarDiaria(
AlarmaMusical alarma,
DateTime candidato,
List<RangoVacaciones> vacaciones,
List<ExcepcionAlarma> excepciones,
) {
var actual = candidato;
for (var i = 0; i < 370; i++) {
if (_esValida(alarma, actual, vacaciones, excepciones)) return actual;
actual = actual.add(const Duration(days: 1));
}
return null;
}
DateTime? _buscarPorDiasSemana(
AlarmaMusical alarma,
DateTime candidato,
List<RangoVacaciones> vacaciones,
List<ExcepcionAlarma> excepciones,
) {
if (alarma.diasSemana.isEmpty) return null;
var actual = candidato;
for (var i = 0; i < 370; i++) {
if (alarma.diasSemana.contains(actual.weekday) &&
_esValida(alarma, actual, vacaciones, excepciones)) {
return actual;
}
actual = actual.add(const Duration(days: 1));
}
return null;
}
bool _esValida(
AlarmaMusical alarma,
DateTime candidato,
List<RangoVacaciones> vacaciones,
List<ExcepcionAlarma> excepciones,
) {
if (!alarma.sonarEnVacaciones && estaEnVacaciones(candidato, vacaciones)) {
return false;
}
return !excepciones.any(
(excepcion) =>
excepcion.alarmaId == alarma.id &&
_mismaEjecucion(excepcion.ejecucion, candidato),
);
}
bool _mismaEjecucion(DateTime a, DateTime b) =>
a.year == b.year &&
a.month == b.month &&
a.day == b.day &&
a.hour == b.hour &&
a.minute == b.minute;
}