91 lines
3.2 KiB
C++
Executable File
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
|