Fist commit

This commit is contained in:
Angel Ivan
2026-10-02 12:08:21 -06:00
commit 2a9eabce14
54 changed files with 10737 additions and 0 deletions

90
lib/timbre_core/Scheduler.h Executable file
View File

@@ -0,0 +1,90 @@
#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