aissia/src/modules/SchedulerModule.cpp
StillHammer 0dfb5f1535 chore: Normalize line endings and update project documentation
- Normalize CRLF to LF across all source files
- Replace CLAUDE.md.old with updated CLAUDE.md
- Standardize configuration file formatting
- Update module source files with consistent line endings

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 22:13:16 +08:00

180 lines
6.4 KiB
C++

#include "SchedulerModule.h"
#include <grove/JsonDataNode.h>
namespace aissia {
SchedulerModule::SchedulerModule() {
m_logger = spdlog::get("SchedulerModule");
if (!m_logger) {
m_logger = spdlog::stdout_color_mt("SchedulerModule");
}
m_config = std::make_unique<grove::JsonDataNode>("config");
}
void SchedulerModule::setConfiguration(const grove::IDataNode& configNode,
grove::IIO* io,
grove::ITaskScheduler* scheduler) {
m_io = io;
m_config = std::make_unique<grove::JsonDataNode>("config");
// Charger la configuration
m_hyperfocusThresholdMinutes = configNode.getInt("hyperfocusThresholdMinutes", 120);
m_breakReminderIntervalMinutes = configNode.getInt("breakReminderIntervalMinutes", 45);
m_breakDurationMinutes = configNode.getInt("breakDurationMinutes", 10);
m_logger->info("SchedulerModule configuré: hyperfocus={}min, break_interval={}min",
m_hyperfocusThresholdMinutes, m_breakReminderIntervalMinutes);
}
const grove::IDataNode& SchedulerModule::getConfiguration() {
return *m_config;
}
void SchedulerModule::process(const grove::IDataNode& input) {
float currentTime = input.getDouble("gameTime", 0.0);
float dt = input.getDouble("deltaTime", 0.016);
// Convertir le temps en minutes pour les calculs
float sessionMinutes = (currentTime - m_sessionStartTime) / 60.0f;
// Vérifier l'hyperfocus
checkHyperfocus(currentTime);
// Vérifier les rappels de pause
checkBreakReminder(currentTime);
// Log périodique (toutes les 5 minutes simulées)
static float lastLog = 0;
if (currentTime - lastLog > 300.0f) { // 300 secondes = 5 minutes
lastLog = currentTime;
m_logger->debug("Session: {:.1f}min, Focus aujourd'hui: {}min, Tâche: {}",
sessionMinutes, m_totalFocusMinutesToday,
m_currentTaskId.empty() ? "(aucune)" : m_currentTaskId);
}
}
void SchedulerModule::checkHyperfocus(float currentTime) {
if (m_currentTaskId.empty()) return;
float sessionMinutes = (currentTime - m_sessionStartTime) / 60.0f;
if (sessionMinutes >= m_hyperfocusThresholdMinutes && !m_hyperfocusAlertSent) {
m_hyperfocusAlertSent = true;
m_logger->warn("HYPERFOCUS DÉTECTÉ! Session de {:.0f} minutes sur '{}'",
sessionMinutes, m_currentTaskId);
// Publier l'alerte (si IO disponible)
// Note: Dans une version complète, on publierait via m_io
}
}
void SchedulerModule::checkBreakReminder(float currentTime) {
float timeSinceBreak = (currentTime - m_lastBreakTime) / 60.0f;
if (timeSinceBreak >= m_breakReminderIntervalMinutes) {
m_lastBreakTime = currentTime;
m_logger->info("RAPPEL: Pause de {} minutes recommandée!", m_breakDurationMinutes);
// Publier le rappel (si IO disponible)
}
}
void SchedulerModule::startTask(const std::string& taskId) {
// Compléter la tâche précédente si nécessaire
if (!m_currentTaskId.empty()) {
completeCurrentTask();
}
m_currentTaskId = taskId;
m_sessionStartTime = m_lastActivityTime;
m_hyperfocusAlertSent = false;
Task* task = findTask(taskId);
if (task) {
m_logger->info("Tâche démarrée: {} (estimé: {}min)", task->name, task->estimatedMinutes);
}
}
void SchedulerModule::completeCurrentTask() {
if (m_currentTaskId.empty()) return;
Task* task = findTask(m_currentTaskId);
if (task) {
float sessionMinutes = (m_lastActivityTime - m_sessionStartTime) / 60.0f;
task->actualMinutes = static_cast<int>(sessionMinutes);
task->completed = true;
m_totalFocusMinutesToday += task->actualMinutes;
m_logger->info("Tâche terminée: {} (réel: {}min vs estimé: {}min)",
task->name, task->actualMinutes, task->estimatedMinutes);
}
m_currentTaskId.clear();
}
SchedulerModule::Task* SchedulerModule::findTask(const std::string& taskId) {
for (auto& task : m_tasks) {
if (task.id == taskId) return &task;
}
return nullptr;
}
std::unique_ptr<grove::IDataNode> SchedulerModule::getHealthStatus() {
auto status = std::make_unique<grove::JsonDataNode>("status");
status->setString("status", "running");
status->setInt("taskCount", m_tasks.size());
status->setString("currentTask", m_currentTaskId);
status->setInt("totalFocusMinutesToday", m_totalFocusMinutesToday);
status->setBool("hyperfocusAlertSent", m_hyperfocusAlertSent);
return status;
}
void SchedulerModule::shutdown() {
if (!m_currentTaskId.empty()) {
completeCurrentTask();
}
m_logger->info("SchedulerModule arrêté. Focus total: {}min", m_totalFocusMinutesToday);
}
std::unique_ptr<grove::IDataNode> SchedulerModule::getState() {
auto state = std::make_unique<grove::JsonDataNode>("state");
state->setString("currentTaskId", m_currentTaskId);
state->setDouble("sessionStartTime", m_sessionStartTime);
state->setDouble("lastBreakTime", m_lastBreakTime);
state->setDouble("lastActivityTime", m_lastActivityTime);
state->setBool("hyperfocusAlertSent", m_hyperfocusAlertSent);
state->setInt("totalFocusMinutesToday", m_totalFocusMinutesToday);
state->setInt("taskCount", m_tasks.size());
m_logger->debug("État sauvegardé: {} tâches, focus={}min", m_tasks.size(), m_totalFocusMinutesToday);
return state;
}
void SchedulerModule::setState(const grove::IDataNode& state) {
m_currentTaskId = state.getString("currentTaskId", "");
m_sessionStartTime = state.getDouble("sessionStartTime", 0.0);
m_lastBreakTime = state.getDouble("lastBreakTime", 0.0);
m_lastActivityTime = state.getDouble("lastActivityTime", 0.0);
m_hyperfocusAlertSent = state.getBool("hyperfocusAlertSent", false);
m_totalFocusMinutesToday = state.getInt("totalFocusMinutesToday", 0);
m_logger->info("État restauré: tâche='{}', focus={}min",
m_currentTaskId.empty() ? "(aucune)" : m_currentTaskId,
m_totalFocusMinutesToday);
}
} // namespace aissia
extern "C" {
grove::IModule* createModule() {
return new aissia::SchedulerModule();
}
void destroyModule(grove::IModule* module) {
delete module;
}
}