#include "app.hpp" #include #include #include #include // ══════════════════════════════════════════════════════════════════════════════ // CmsEngine 构造与辅助 // ══════════════════════════════════════════════════════════════════════════════ /** * @brief 构造函数,初始化系统状态上下文与自增计数器 */ CmsEngine::CmsEngine() : nextId_(0) { systemContext_.currentMode = RunMode::Idle; systemContext_.consistencyMark = 0; systemContext_.switchTime = std::chrono::system_clock::now(); systemContext_.contextSnapshot = R"({"mode":"Idle","version":"1.0.0"})"; } /** * @brief 生成自增唯一标识 * * @return std::string 格式如 "ID-00001" */ std::string CmsEngine::generateNextId() { std::ostringstream oss; oss << "ID-" << std::setw(5) << std::setfill('0') << (++nextId_); return oss.str(); } // ══════════════════════════════════════════════════════════════════════════════ // 事件处理 // ══════════════════════════════════════════════════════════════════════════════ /** * @brief 接入原始战场事件 * * 执行基本合法性校验(ID 不能为空、优先级范围检查),通过后存入事件库。 * * @param event 战场事件 * @return true 接入成功 * @return false 接入失败 */ bool CmsEngine::ingestEvent(const EventRecord& event) { if (event.id.empty()) { return false; } if (event.priority > 255) { return false; } events_.push_back(event); return true; } /** * @brief 处理待处理事件队列 * * 遍历事件库中所有 Pending 状态的事件,自动将其状态标记为 Generated, * 并据此生成一个对应的 TaskPlan 草案。 * * @return size_t 处理的事件数量 */ size_t CmsEngine::processPendingEvents() { size_t count = 0; for (auto& evt : events_) { if (evt.status == EventStatus::Pending) { evt.status = EventStatus::Generated; TaskPlan plan; plan.id = generateNextId(); plan.name = "AutoPlan-" + evt.id; plan.type = PlanType::Centralized; plan.status = PlanStatus::Drafting; plan.createTime = std::chrono::system_clock::now(); plan.relatedEventId = evt.id; plan.resourceQuota = 0.5; plan.constraints = "自动生成约束"; plans_.push_back(plan); ++count; } } return count; } /** * @brief 根据事件 ID 查找事件 * * @param eventId 事件标识 * @return const EventRecord* 事件指针,未找到返回 nullptr */ const EventRecord* CmsEngine::findEventById(const std::string& eventId) const { for (const auto& evt : events_) { if (evt.id == eventId) { return &evt; } } return nullptr; } // ══════════════════════════════════════════════════════════════════════════════ // 任务方案管理 // ══════════════════════════════════════════════════════════════════════════════ /** * @brief 创建任务方案 * * 校验方案名称非空后,为其分配系统 ID 并存入方案库。 * * @param plan 待创建方案(id 由系统填充) * @return true 创建成功 * @return false 名称不合法 */ bool CmsEngine::createTaskPlan(TaskPlan& plan) { if (plan.name.empty()) { return false; } plan.id = generateNextId(); plan.createTime = std::chrono::system_clock::now(); plans_.push_back(plan); return true; } /** * @brief 获取所有任务方案列表 * * @return const std::vector& 方案列表 */ const std::vector& CmsEngine::getAllPlans() const { return plans_; } /** * @brief 根据 ID 查找任务方案 * * @param planId 任务标识 * @return const TaskPlan* 方案指针,未找到返回 nullptr */ const TaskPlan* CmsEngine::findPlanById(const std::string& planId) const { for (const auto& plan : plans_) { if (plan.id == planId) { return &plan; } } return nullptr; } /** * @brief 更新任务方案状态 * * @param planId 任务标识 * @param newStatus 新状态 * @return true 更新成功 * @return false 未找到方案 */ bool CmsEngine::updatePlanStatus(const std::string& planId, PlanStatus newStatus) { for (auto& plan : plans_) { if (plan.id == planId) { plan.status = newStatus; return true; } } return false; } // ══════════════════════════════════════════════════════════════════════════════ // 模板管理 // ══════════════════════════════════════════════════════════════════════════════ /** * @brief 注册模板实例 * * @param tmpl 模板实例 */ void CmsEngine::registerTemplate(const TemplateInstance& tmpl) { templates_.push_back(tmpl); } /** * @brief 根据场景匹配最佳模板 * * 遍历模板库,返回置信度最高的模板(简单策略:置信度最大者)。 * * @param scenario 场景描述(当前未用于精确匹配,仅做演示) * @return const TemplateInstance* 最佳模板,无匹配返回 nullptr */ const TemplateInstance* CmsEngine::matchTemplate(const std::string& scenario) const { (void)scenario; if (templates_.empty()) { return nullptr; } const TemplateInstance* best = &templates_.front(); for (const auto& tmpl : templates_) { if (tmpl.confidence > best->confidence) { best = &tmpl; } } return best; } // ══════════════════════════════════════════════════════════════════════════════ // 执行监控 // ══════════════════════════════════════════════════════════════════════════════ /** * @brief 上报节点执行状态 * * 将节点遥测数据写入内部状态表,按 nodeId 覆盖更新。 * * @param status 执行状态 */ void CmsEngine::reportExecutionStatus(const ExecutionStatus& status) { nodeStatus_[status.nodeId] = status; } /** * @brief 检查所有节点健康状态 * * 异常判据:健康指数 < 0.5 或异常码 != 0 或心跳超时(距最后上报 > 30秒)。 * * @return std::vector 异常节点列表 */ std::vector CmsEngine::checkHealth() const { std::vector unhealthy; const auto now = std::chrono::system_clock::now(); for (const auto& [nodeId, status] : nodeStatus_) { (void)nodeId; bool isUnhealthy = false; if (status.healthIndex < 0.5) { isUnhealthy = true; } if (status.errorCode != 0) { isUnhealthy = true; } auto elapsed = std::chrono::duration_cast( now - status.lastReport).count(); if (elapsed > 30) { isUnhealthy = true; } if (isUnhealthy) { unhealthy.push_back(status); } } return unhealthy; } // ══════════════════════════════════════════════════════════════════════════════ // 用户会话管理 // ══════════════════════════════════════════════════════════════════════════════ /** * @brief 创建用户会话 * * 校验 userId 非空且不重复后存入会话表。 * * @param session 用户会话 * @return true 创建成功 * @return false 用户已存在或 ID 为空 */ bool CmsEngine::createSession(const UserSession& session) { if (session.userId.empty()) { return false; } if (sessions_.find(session.userId) != sessions_.end()) { return false; } sessions_[session.userId] = session; return true; } /** * @brief 校验用户权限 * * 检查用户会话的权限位图是否包含所需的权限掩码。 * * @param userId 用户 ID * @param permissionMask 所需权限位掩码 * @return true 有权限 * @return false 无权限或用户不存在 */ bool CmsEngine::checkPermission(const std::string& userId, uint64_t permissionMask) const { auto it = sessions_.find(userId); if (it == sessions_.end()) { return false; } return (it->second.permissionBitmap & permissionMask) == permissionMask; } // ══════════════════════════════════════════════════════════════════════════════ // 通知管理 // ══════════════════════════════════════════════════════════════════════════════ /** * @brief 推送通知消息 * * @param msg 通知消息 */ void CmsEngine::pushNotification(const NotificationMessage& msg) { notifications_.push_back(msg); } /** * @brief 获取所有未读通知 * * @return std::vector 未读通知列表 */ std::vector CmsEngine::getUnreadNotifications() const { std::vector unread; for (const auto& msg : notifications_) { if (!msg.isRead) { unread.push_back(msg); } } return unread; } // ══════════════════════════════════════════════════════════════════════════════ // 系统状态管理 // ══════════════════════════════════════════════════════════════════════════════ /** * @brief 切换系统运行模式 * * 降级模式下不允许切换到其他模式(模拟故障隔离策略),其余模式可自由切换。 * * @param newMode 目标模式 * @return true 切换成功 * @return false 切换被拒绝 */ bool CmsEngine::switchMode(RunMode newMode) { if (systemContext_.currentMode == RunMode::Degraded && newMode != RunMode::Degraded) { // 降级模式下不允许退出降级(模拟安全策略) return false; } systemContext_.currentMode = newMode; systemContext_.switchTime = std::chrono::system_clock::now(); systemContext_.consistencyMark = nextId_; return true; } /** * @brief 获取当前系统状态上下文 * * @return const SystemStateContext& 状态上下文 */ const SystemStateContext& CmsEngine::getSystemContext() const { return systemContext_; } /** * @brief 获取引擎摘要信息 * * @return std::string 包含事件数、方案数、节点数、未读通知数等 */ std::string CmsEngine::getSummary() const { std::ostringstream oss; oss << "=== CMS Engine Summary ===\n" << " Events : " << events_.size() << "\n" << " Plans : " << plans_.size() << "\n" << " Templates : " << templates_.size() << "\n" << " Monitor Nodes : " << nodeStatus_.size() << "\n" << " Active Sessions : " << sessions_.size() << "\n" << " Notifications : " << notifications_.size() << "\n" << " Mode : "; switch (systemContext_.currentMode) { case RunMode::Idle: oss << "Idle"; break; case RunMode::HumanLoop: oss << "HumanLoop"; break; case RunMode::AutoExec: oss << "AutoExec"; break; case RunMode::Degraded: oss << "Degraded"; break; default: oss << "Unknown"; break; } oss << "\n============================"; return oss.str(); }