plan_execute_t1/src/app.cpp

403 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "app.hpp"
#include <algorithm>
#include <sstream>
#include <iomanip>
#include <ctime>
// ══════════════════════════════════════════════════════════════════════════════
// 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<TaskPlan>& 方案列表
*/
const std::vector<TaskPlan>& 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<ExecutionStatus> 异常节点列表
*/
std::vector<ExecutionStatus> CmsEngine::checkHealth() const
{
std::vector<ExecutionStatus> 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<std::chrono::seconds>(
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<NotificationMessage> 未读通知列表
*/
std::vector<NotificationMessage> CmsEngine::getUnreadNotifications() const
{
std::vector<NotificationMessage> 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();
}