Files
TimbreESP32/lib/timbre_core/Scheduler.h
Angel Ivan 2a9eabce14 Fist commit
2026-10-02 12:08:21 -06:00

91 lines
3.2 KiB
C++
Executable File

#pragma once
#include "CivilTime.h"
#include "Model.h"
#include "SessionClock.h"
#include <cstdint>
namespace timbre_core {
struct ScheduleDecision {
bool due = false;
bool firstObservation = false;
bool alreadyProcessed = false;
bool blockedByHoliday = false;
bool invalidTime = false;
ScheduleId scheduleId = kInvalidId;
PatternId patternId = PatternId::A;
std::uint64_t missedMinutes = 0;
constexpr explicit operator bool() const noexcept { return due; }
constexpr bool triggered() const noexcept { return due; }
};
using ScheduleMatch = ScheduleDecision;
class Scheduler {
public:
Scheduler() = default;
// Only the currently observed local minute is considered. If the source
// jumped from minute N to N+K, the intermediate minutes are intentionally
// discarded rather than replayed.
ScheduleDecision poll(const AppState& state,
const CivilDateTime& localTime,
bool firstObservation = false);
ScheduleDecision process(const AppState& state,
const CivilDateTime& localTime,
bool firstObservation = false) {
return poll(state, localTime, firstObservation);
}
// Convenience integration with SessionClock. The caller supplies the
// current wall value; the injected monotonic source remains authoritative
// inside SessionClock.
ScheduleDecision poll(const AppState& state,
SessionClock& clock,
std::int64_t utcEpochSeconds);
ScheduleDecision poll(const AppState& state,
const SessionClock::Observation& observation) {
if (!observation.valid) {
ScheduleDecision decision;
decision.invalidTime = true;
return decision;
}
return poll(state, observation.local, observation.firstObservation);
}
ScheduleDecision process(const AppState& state,
SessionClock& clock,
std::int64_t utcEpochSeconds) {
return poll(state, clock, utcEpochSeconds);
}
ScheduleDecision tick(const AppState& state,
const CivilDateTime& localTime,
bool firstObservation = false) {
return poll(state, localTime, firstObservation);
}
ScheduleDecision evaluate(const AppState& state,
const CivilDateTime& localTime,
bool firstObservation = false) {
return poll(state, localTime, firstObservation);
}
bool hasLastKey() const noexcept { return hasLastKey_; }
const LocalMinuteKey& lastKey() const noexcept { return lastKey_; }
const LocalMinuteKey& key() const noexcept { return lastKey_; }
void reset() noexcept;
static bool isHoliday(const AppState& state, std::uint8_t month,
std::uint8_t day) noexcept;
static bool scheduleMatches(const Schedule& schedule,
const AppState& state,
const CivilDateTime& localTime) noexcept;
private:
bool hasLastKey_ = false;
LocalMinuteKey lastKey_{};
};
} // namespace timbre_core