#include "SchedulerModule.h" #include namespace aissia { SchedulerModule::SchedulerModule() { m_logger = spdlog::get("SchedulerModule"); if (!m_logger) { m_logger = spdlog::stdout_color_mt("SchedulerModule"); } m_config = std::make_unique("config"); } void SchedulerModule::setConfiguration(const grove::IDataNode& configNode, grove::IIO* io, grove::ITaskScheduler* scheduler) { m_io = io; m_config = std::make_unique("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(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 SchedulerModule::getHealthStatus() { auto status = std::make_unique("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 SchedulerModule::getState() { auto state = std::make_unique("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; } }