生成代码工程

This commit is contained in:
root 2026-06-08 15:54:27 +08:00
parent 8c9b9e9814
commit 68c52570b3
8 changed files with 11950 additions and 2 deletions

28
CMakeLists.txt Normal file
View File

@ -0,0 +1,28 @@
cmake_minimum_required(VERSION 3.14)
project(ocpm VERSION 1.0.0 LANGUAGES CXX)
# C++17
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# MSVC UTF-8
if (MSVC)
add_compile_options(/utf-8)
endif()
#
add_executable(ocpm
src/main.cpp
src/app.cpp
)
target_include_directories(ocpm PRIVATE include)
#
add_executable(basic_test
tests/basic_test.cpp
src/app.cpp
)
target_include_directories(basic_test PRIVATE include)

View File

@ -1,3 +1,41 @@
# 智能体开发平台-演示系统 # OCPM — 作战指挥计划管理系统
暂无描述 ## 概述
OCPM (Operation Command Planning Manager) 是一个面向现代战争的作战指挥计划管理系统,支持从计划制定、优化、分发到执行监控的全流程闭环管理。本工程为其核心 C++ 后端原型。
## 功能模块
| 模块 | 说明 |
|------|------|
| 计划管理 (PlanManager) | 集中式计划 CRUD、排序、对比、重构、HITL |
| 分布式计划 (DistributedPlanManager) | 分布式计划拓扑管理与节点重构 |
| 指令分发与执行监控 (DispatchManager) | 计划分发、资产状态监控、仪表盘/流程图/告警 |
| 综合可视化 (Dashboard) | 全局态势总览 |
## 数据结构
- **Plan_Info**作战计划核心实体plan_id, plan_name, status, priority, plan_type 等)
- **AssetStatus**:资产状态枚举(就绪/忙碌/故障/离线)
- 各类 JSON 接口数据模型已在 `include/app.hpp` 中定义
## 编译与运行
```bash
# 配置
cmake -B build
# 构建
cmake --build build
# 运行主程序
./build/ocpm
# 运行测试
./build/basic_test
```
## 环境要求
- C++17 编译器GCC 8+, Clang 10+, MSVC 2019+
- CMake ≥ 3.14

10919
events.ndjson Normal file

File diff suppressed because one or more lines are too long

30
generation.json Normal file

File diff suppressed because one or more lines are too long

294
include/app.hpp Normal file
View File

@ -0,0 +1,294 @@
#ifndef OCPM_APP_HPP
#define OCPM_APP_HPP
#include <string>
#include <vector>
#include <map>
#include <memory>
#include <functional>
#include <chrono>
#include <ostream>
#include <stdexcept>
/// @brief 命名空间 ocpm — 作战指挥计划管理系统核心逻辑
namespace ocpm {
// ============================================================================
// 枚举定义
// ============================================================================
/// @brief 计划状态
enum class PlanStatus : int {
DRAFT = 0, ///< 草稿
ACTIVE = 1, ///< 生效
ARCHIVED = 2 ///< 归档
};
/// @brief 计划类型
enum class PlanType : int {
CENTRALIZED = 0, ///< 集中式
DISTRIBUTED = 1 ///< 分布式
};
/// @brief 资产状态码 (SRS-OCPM_I_COM_001)
enum class AssetStatusCode : int {
READY = 0, ///< 就绪 (绿灯)
BUSY = 1, ///< 忙碌 (黄灯)
FAULT = 2, ///< 故障 (红灯)
OFFLINE = 3 ///< 离线 (灰色)
};
/// @brief 排序方向 (SRS-OCPM_I_UI_002)
enum class SortDirection {
ASC, ///< 升序
DESC ///< 降序
};
/// @brief 异常等级
enum class AlertLevel {
INFO, ///< 信息
WARNING, ///< 警告
ERROR, ///< 错误
CRITICAL ///< 严重
};
// ============================================================================
// 核心数据结构
// ============================================================================
/// @brief 作战计划实体 — 对应数据库 Plan_Info 表
struct PlanInfo {
std::string plan_id; ///< 计划唯一标识
std::string plan_name; ///< 计划名称
std::string create_time; ///< 创建时间 (ISO 8601)
std::string update_time; ///< 最后修改时间
PlanStatus status = PlanStatus::DRAFT; ///< 计划状态
int priority = 0; ///< 优先级 (0~100)
PlanType plan_type = PlanType::CENTRALIZED; ///< 计划类型
std::string creator; ///< 创建人
};
/// @brief 计划查询请求 (SRS-OCPM_I_UI_001)
struct PlanQueryRequest {
int status_filter = -1; ///< 按状态过滤, -1 表示不限
int priority_min = 0;
std::string keyword; ///< 关键字模糊匹配
int page = 1; ///< 页码
int page_size = 100; ///< 每页条数, 上限 100
};
/// @brief 排序参数 (SRS-OCPM_I_UI_002)
struct SortParam {
std::string field; ///< 排序字段名 (如 "priority", "create_time")
SortDirection direction = SortDirection::ASC;
};
/// @brief 网络拓扑节点 — 用于分布式计划 (SRS-OCPM_I_DB_002)
struct TopoNode {
std::string node_id; ///< 节点标识
std::string label; ///< 显示标签
double x = 0.0; ///< 布局坐标 X
double y = 0.0; ///< 布局坐标 Y
};
/// @brief 网络拓扑边
struct TopoEdge {
std::string edge_id; ///< 边标识
std::string source_id; ///< 源节点
std::string target_id; ///< 目标节点
int bandwidth = 0; ///< 带宽 (Mbps)
};
/// @brief 分布式计划拓扑数据
struct DistributedPlanGraph {
std::vector<TopoNode> nodes; ///< 节点列表
std::vector<TopoEdge> edges; ///< 边列表
};
/// @brief HITL 事件 (SRS-OCPM_I_ALG_001)
struct HitlEvent {
std::string request_id; ///< 请求标识
std::string reason; ///< 需要人工干预的原因
std::vector<std::string> options; ///< 可选方案列表
std::string deadline; ///< 截止时间
};
/// @brief 重构指令 (SRS-OCPM_I_UI_007)
struct ReconstructCommand {
std::string plan_id; ///< 目标计划 ID
std::vector<std::string> modifications; ///< 修改描述列表
std::vector<std::string> target_tasks; ///< 目标任务列表
};
/// @brief 重构结果 (SRS-OCPM_O_UI_007)
struct ReconstructResult {
bool success = false; ///< 是否成功
std::string message; ///< 结果消息
std::string new_version; ///< 新版本号 (成功时)
};
/// @brief 子任务节点 — 用于流程图 (SRS-OCPM_I_SYS_004)
struct TaskNode {
std::string task_id; ///< 任务标识
std::string name; ///< 任务名称
std::string status; ///< 状态 (pending/running/completed/failed)
std::vector<std::string> dependency_ids; ///< 依赖的任务 ID 列表
};
/// @brief 异常事件 (SRS-OCPM_I_SYS_005)
struct AlertEvent {
int code; ///< 异常编码
AlertLevel level = AlertLevel::INFO;
std::string timestamp; ///< 发生时间
std::string task_id; ///< 关联任务
std::string description; ///< 描述
};
/// @brief 执行统计数据 (SRS-OCPM_I_SYS_003)
struct ExecutionStats {
int completed_tasks = 0; ///< 已完成任务数
int total_tasks = 0; ///< 总任务数
double remaining_time = 0.0; ///< 剩余时间 (分钟)
};
/// @brief 仪表盘聚合数据 (SRS-OCPM_I_SYS_006)
struct DashboardData {
ExecutionStats execution; ///< 执行进度
double resource_rate; ///< 资源剩余率 (0.0~1.0)
std::vector<AlertEvent> recent_alerts; ///< 最近异常
};
// ============================================================================
// 模块管理器类声明
// ============================================================================
/// @brief 计划管理器 — 负责集中式计划的 CRUD、排序、对比、重构
class PlanManager {
public:
PlanManager() = default;
virtual ~PlanManager() = default;
/// @brief 查询计划列表
/// @param query 查询请求参数
/// @param sort 排序参数
/// @return 计划列表
std::vector<PlanInfo> queryPlans(const PlanQueryRequest& query,
const SortParam& sort = {"priority", SortDirection::DESC});
/// @brief 获取单个计划详情
/// @param plan_id 计划 ID
/// @return PlanInfo
/// @throws std::invalid_argument 如果 plan_id 不存在
PlanInfo getPlanDetail(const std::string& plan_id);
/// @brief 对比两个计划
/// @param id_a 计划 A ID
/// @param id_b 计划 B ID
/// @return 差异描述列表 (每项格式: "字段名: A值 vs B值")
std::vector<std::string> comparePlans(const std::string& id_a, const std::string& id_b);
/// @brief 执行重构操作
/// @param cmd 重构指令
/// @return 重构结果
ReconstructResult reconstruct(const ReconstructCommand& cmd);
/// @brief 提交 HITL 事件通知
/// @param event HITL 事件
void notifyHitlEvent(const HitlEvent& event);
/// @brief 设置算法进度回调
/// @param cb 回调函数, 参数为 (stage, progress%)
void setAlgorithmProgressCallback(std::function<void(const std::string&, int)> cb);
/// @brief 模拟加载示例数据
void loadSampleData();
private:
std::vector<PlanInfo> plans_;
std::function<void(const std::string&, int)> algo_callback_;
};
/// @brief 分布式计划管理器
class DistributedPlanManager {
public:
DistributedPlanManager() = default;
virtual ~DistributedPlanManager() = default;
/// @brief 获取当前拓扑图
const DistributedPlanGraph& getGraph() const { return graph_; }
/// @brief 添加节点
/// @param node 新节点
void addNode(const TopoNode& node);
/// @brief 移除节点 (同时移除关联边)
/// @param node_id 节点 ID
void removeNode(const std::string& node_id);
/// @brief 添加边
/// @param edge 新边
void addEdge(const TopoEdge& edge);
/// @brief 移除边
/// @param edge_id 边 ID
void removeEdge(const std::string& edge_id);
/// @brief 模拟加载示例拓扑
void loadSampleData();
private:
DistributedPlanGraph graph_;
/// @brief 检查图连通性 (简单 BFS)
bool isConnected() const;
};
/// @brief 指令分发与执行监控管理器
class DispatchManager {
public:
DispatchManager() = default;
virtual ~DispatchManager() = default;
/// @brief 分发计划至多个资产
/// @param plan_id 计划 ID
/// @param asset_ids 目标资产 ID 列表
/// @return 成功分发的资产数
int dispatchPlan(const std::string& plan_id, const std::vector<std::string>& asset_ids);
/// @brief 查询资产状态
/// @param asset_id 资产 ID
/// @return 资产状态码
AssetStatusCode getAssetStatus(const std::string& asset_id);
/// @brief 获取执行统计
/// @return ExecutionStats
ExecutionStats getExecutionStats() const;
/// @brief 获取仪表盘数据
/// @return DashboardData
DashboardData getDashboardData() const;
/// @brief 获取子任务流程图
/// @return 子任务列表
std::vector<TaskNode> getTaskFlow() const;
/// @brief 获取未清除的异常事件列表
/// @param level_filter 按等级过滤, 传入 nullptr 不限制
std::vector<AlertEvent> getAlerts(const AlertLevel* level_filter = nullptr) const;
/// @brief 清除所有异常
void clearAlerts();
/// @brief 模拟加载示例数据
void loadSampleData();
private:
std::map<std::string, AssetStatusCode> asset_statuses_;
std::vector<AlertEvent> alerts_;
std::vector<TaskNode> task_flow_;
ExecutionStats stats_;
};
} // namespace ocpm
#endif // OCPM_APP_HPP

310
src/app.cpp Normal file
View File

@ -0,0 +1,310 @@
#include "app.hpp"
#include <algorithm>
#include <sstream>
#include <set>
#include <queue>
#include <random>
#include <ctime>
namespace ocpm {
// ============================================================================
// PlanManager 实现
// ============================================================================
std::vector<PlanInfo> PlanManager::queryPlans(const PlanQueryRequest& query,
const SortParam& sort) {
// 1. 过滤
std::vector<PlanInfo> result;
for (const auto& p : plans_) {
if (query.status_filter >= 0 && static_cast<int>(p.status) != query.status_filter)
continue;
if (p.priority < query.priority_min)
continue;
if (!query.keyword.empty()) {
auto pos = p.plan_name.find(query.keyword);
bool found = (pos != std::string::npos) ||
(p.plan_id.find(query.keyword) != std::string::npos);
if (!found)
continue;
}
result.push_back(p);
}
// 2. 排序
std::sort(result.begin(), result.end(),
[&sort](const PlanInfo& a, const PlanInfo& b) {
int cmp = 0;
if (sort.field == "priority") {
cmp = (a.priority < b.priority) ? -1 : (a.priority > b.priority ? 1 : 0);
} else if (sort.field == "create_time") {
cmp = a.create_time.compare(b.create_time);
} else if (sort.field == "update_time") {
cmp = a.update_time.compare(b.update_time);
} else if (sort.field == "plan_name") {
cmp = a.plan_name.compare(b.plan_name);
} else if (sort.field == "status") {
cmp = static_cast<int>(a.status) - static_cast<int>(b.status);
}
return (sort.direction == SortDirection::ASC) ? (cmp < 0) : (cmp > 0);
});
// 3. 分页
size_t start = static_cast<size_t>((query.page - 1)) * query.page_size;
if (start >= result.size())
return {};
size_t end = std::min(start + query.page_size, result.size());
return std::vector<PlanInfo>(result.begin() + static_cast<long>(start),
result.begin() + static_cast<long>(end));
}
PlanInfo PlanManager::getPlanDetail(const std::string& plan_id) {
for (const auto& p : plans_) {
if (p.plan_id == plan_id)
return p;
}
throw std::invalid_argument("Plan not found: " + plan_id);
}
std::vector<std::string> PlanManager::comparePlans(const std::string& id_a,
const std::string& id_b) {
PlanInfo a = getPlanDetail(id_a);
PlanInfo b = getPlanDetail(id_b);
std::vector<std::string> diffs;
if (a.plan_name != b.plan_name)
diffs.push_back("plan_name: \"" + a.plan_name + "\" vs \"" + b.plan_name + "\"");
if (a.priority != b.priority)
diffs.push_back("priority: " + std::to_string(a.priority) + " vs " + std::to_string(b.priority));
if (a.status != b.status)
diffs.push_back("status: " + std::to_string(static_cast<int>(a.status)) +
" vs " + std::to_string(static_cast<int>(b.status)));
if (a.plan_type != b.plan_type)
diffs.push_back("plan_type: " + std::to_string(static_cast<int>(a.plan_type)) +
" vs " + std::to_string(static_cast<int>(b.plan_type)));
if (diffs.empty())
diffs.push_back("(no differences)");
return diffs;
}
ReconstructResult PlanManager::reconstruct(const ReconstructCommand& cmd) {
// 模拟重构:找到对应计划,更新版本
for (auto& p : plans_) {
if (p.plan_id == cmd.plan_id) {
p.update_time = "2025-01-15T10:30:00Z";
ReconstructResult r;
r.success = true;
r.message = "重构成功,已应用 " + std::to_string(cmd.modifications.size()) + " 项修改";
r.new_version = p.plan_id + "-v2";
return r;
}
}
ReconstructResult r;
r.success = false;
r.message = "计划未找到: " + cmd.plan_id;
return r;
}
void PlanManager::notifyHitlEvent(const HitlEvent& event) {
/// @brief 模拟 HITL 通知: 记录事件到日志 (实际系统会推送至前端)
(void)event;
// 实际实现中会触发前端铃铛红点与弹窗
}
void PlanManager::setAlgorithmProgressCallback(
std::function<void(const std::string&, int)> cb) {
algo_callback_ = std::move(cb);
}
void PlanManager::loadSampleData() {
plans_.clear();
auto make = [](std::string id, std::string name, PlanStatus st, int pri,
PlanType tp, std::string creator) {
PlanInfo p;
p.plan_id = std::move(id);
p.plan_name = std::move(name);
p.create_time = "2025-01-10T08:00:00Z";
p.update_time = "2025-01-12T14:30:00Z";
p.status = st;
p.priority = pri;
p.plan_type = tp;
p.creator = std::move(creator);
return p;
};
plans_.push_back(make("PLAN-001", "突击行动-甲", PlanStatus::ACTIVE, 90, PlanType::CENTRALIZED, "张指挥"));
plans_.push_back(make("PLAN-002", "防御布署-乙", PlanStatus::DRAFT, 70, PlanType::CENTRALIZED, "李参谋"));
plans_.push_back(make("PLAN-003", "侦察协同-丙", PlanStatus::ACTIVE, 85, PlanType::DISTRIBUTED, "王处长"));
plans_.push_back(make("PLAN-004", "后方支援-丁", PlanStatus::ARCHIVED,50, PlanType::CENTRALIZED, "赵主任"));
plans_.push_back(make("PLAN-005", "电子对抗-戊", PlanStatus::DRAFT, 95, PlanType::DISTRIBUTED, "孙队长"));
}
// ============================================================================
// DistributedPlanManager 实现
// ============================================================================
void DistributedPlanManager::addNode(const TopoNode& node) {
// 去重
for (const auto& n : graph_.nodes) {
if (n.node_id == node.node_id)
return;
}
graph_.nodes.push_back(node);
}
void DistributedPlanManager::removeNode(const std::string& node_id) {
auto& nodes = graph_.nodes;
nodes.erase(
std::remove_if(nodes.begin(), nodes.end(),
[&](const TopoNode& n) { return n.node_id == node_id; }),
nodes.end());
// 移除相关边
auto& edges = graph_.edges;
edges.erase(
std::remove_if(edges.begin(), edges.end(),
[&](const TopoEdge& e) {
return e.source_id == node_id || e.target_id == node_id;
}),
edges.end());
}
void DistributedPlanManager::addEdge(const TopoEdge& edge) {
for (const auto& e : graph_.edges) {
if (e.edge_id == edge.edge_id)
return;
}
graph_.edges.push_back(edge);
}
void DistributedPlanManager::removeEdge(const std::string& edge_id) {
auto& edges = graph_.edges;
edges.erase(
std::remove_if(edges.begin(), edges.end(),
[&](const TopoEdge& e) { return e.edge_id == edge_id; }),
edges.end());
}
bool DistributedPlanManager::isConnected() const {
if (graph_.nodes.empty())
return true;
std::set<std::string> visited;
std::queue<std::string> q;
q.push(graph_.nodes.front().node_id);
visited.insert(graph_.nodes.front().node_id);
while (!q.empty()) {
auto cur = q.front(); q.pop();
for (const auto& e : graph_.edges) {
std::string neighbor;
if (e.source_id == cur)
neighbor = e.target_id;
else if (e.target_id == cur)
neighbor = e.source_id;
else
continue;
if (visited.find(neighbor) == visited.end()) {
visited.insert(neighbor);
q.push(neighbor);
}
}
}
return visited.size() == graph_.nodes.size();
}
void DistributedPlanManager::loadSampleData() {
graph_.nodes.clear();
graph_.edges.clear();
graph_.nodes.push_back({"NODE-01", "前沿指挥所", 100.0, 200.0});
graph_.nodes.push_back({"NODE-02", "火力单元-A", 300.0, 100.0});
graph_.nodes.push_back({"NODE-03", "侦察单元-B", 300.0, 300.0});
graph_.nodes.push_back({"NODE-04", "通信中继-C", 500.0, 200.0});
graph_.edges.push_back({"EDGE-01", "NODE-01", "NODE-02", 100});
graph_.edges.push_back({"EDGE-02", "NODE-01", "NODE-03", 100});
graph_.edges.push_back({"EDGE-03", "NODE-02", "NODE-04", 50});
graph_.edges.push_back({"EDGE-04", "NODE-03", "NODE-04", 50});
}
// ============================================================================
// DispatchManager 实现
// ============================================================================
int DispatchManager::dispatchPlan(const std::string& plan_id,
const std::vector<std::string>& asset_ids) {
/// @brief 模拟并发分发: 简单计数
(void)plan_id;
int success_count = 0;
for (const auto& aid : asset_ids) {
auto it = asset_statuses_.find(aid);
if (it != asset_statuses_.end() && it->second == AssetStatusCode::READY) {
success_count++;
}
}
return success_count;
}
AssetStatusCode DispatchManager::getAssetStatus(const std::string& asset_id) {
auto it = asset_statuses_.find(asset_id);
if (it != asset_statuses_.end())
return it->second;
return AssetStatusCode::OFFLINE;
}
ExecutionStats DispatchManager::getExecutionStats() const {
return stats_;
}
DashboardData DispatchManager::getDashboardData() const {
DashboardData dd;
dd.execution = stats_;
dd.resource_rate = 0.72;
dd.recent_alerts = alerts_;
return dd;
}
std::vector<TaskNode> DispatchManager::getTaskFlow() const {
return task_flow_;
}
std::vector<AlertEvent> DispatchManager::getAlerts(const AlertLevel* level_filter) const {
if (!level_filter)
return alerts_;
std::vector<AlertEvent> filtered;
for (const auto& a : alerts_) {
if (a.level == *level_filter)
filtered.push_back(a);
}
return filtered;
}
void DispatchManager::clearAlerts() {
alerts_.clear();
}
void DispatchManager::loadSampleData() {
// 资产状态
asset_statuses_["ASSET-001"] = AssetStatusCode::READY;
asset_statuses_["ASSET-002"] = AssetStatusCode::BUSY;
asset_statuses_["ASSET-003"] = AssetStatusCode::FAULT;
asset_statuses_["ASSET-004"] = AssetStatusCode::READY;
asset_statuses_["ASSET-005"] = AssetStatusCode::OFFLINE;
// 异常事件
alerts_.push_back({1001, AlertLevel::WARNING, "2025-01-14T09:15:00Z",
"TASK-03", "通信链路延迟超过阈值"});
alerts_.push_back({1002, AlertLevel::ERROR, "2025-01-14T09:20:00Z",
"TASK-05", "资产 ASSET-003 无响应"});
// 子任务流程图
task_flow_.push_back({"TASK-01", "侦察定位", "completed", {}});
task_flow_.push_back({"TASK-02", "目标锁定", "running", {"TASK-01"}});
task_flow_.push_back({"TASK-03", "火力计算", "pending", {"TASK-02"}});
task_flow_.push_back({"TASK-04", "打击执行", "pending", {"TASK-03"}});
task_flow_.push_back({"TASK-05", "效果评估", "pending", {"TASK-04"}});
// 执行统计
stats_.completed_tasks = 1;
stats_.total_tasks = 5;
stats_.remaining_time = 28.5;
}
} // namespace ocpm

156
src/main.cpp Normal file
View File

@ -0,0 +1,156 @@
#include "app.hpp"
#include <iostream>
#include <iomanip>
#include <exception>
/// @brief 打印分隔线
static void printSeparator() {
std::cout << "----------------------------------------\n";
}
/// @brief 打印单个 PlanInfo
/// @param p 计划信息
static void printPlan(const ocpm::PlanInfo& p) {
std::cout << " ID: " << p.plan_id << "\n"
<< " 名称: " << p.plan_name << "\n"
<< " 状态: " << static_cast<int>(p.status) << " (0=草稿 1=生效 2=归档)\n"
<< " 优先级: " << p.priority << "\n"
<< " 类型: " << (p.plan_type == ocpm::PlanType::CENTRALIZED ? "集中式" : "分布式") << "\n"
<< " 创建人: " << p.creator << "\n"
<< " 创建时间: " << p.create_time << "\n"
<< " 更新时间: " << p.update_time << "\n";
}
/// @brief 主入口 — 演示 OCPM 系统核心功能
int main() {
std::cout << "========================================\n";
std::cout << " OCPM - 作战指挥计划管理系统 v1.0\n";
std::cout << "========================================\n\n";
// ---- 计划管理演示 ----
std::cout << "[1] 计划管理模块演示\n";
printSeparator();
ocpm::PlanManager pm;
pm.loadSampleData();
// 查询所有计划
ocpm::PlanQueryRequest all_query;
all_query.page_size = 100;
auto plans = pm.queryPlans(all_query);
std::cout << " 加载了 " << plans.size() << " 个示例计划:\n";
for (const auto& p : plans) {
std::cout << " - " << p.plan_id << " | " << p.plan_name << "\n";
}
// 按优先级降序排序查询
ocpm::SortParam sort_by_prio{"priority", ocpm::SortDirection::DESC};
auto sorted = pm.queryPlans(all_query, sort_by_prio);
std::cout << "\n 按优先级降序排列:\n";
for (const auto& p : sorted) {
std::cout << " " << p.plan_id << " (优先级=" << p.priority << ")\n";
}
// 获取详情
try {
auto detail = pm.getPlanDetail("PLAN-001");
std::cout << "\n 计划详情 (PLAN-001):\n";
printPlan(detail);
} catch (const std::exception& e) {
std::cerr << " 错误: " << e.what() << "\n";
}
// 对比两个计划
auto diffs = pm.comparePlans("PLAN-001", "PLAN-002");
std::cout << "\n 计划对比 (PLAN-001 vs PLAN-002):\n";
for (const auto& d : diffs) {
std::cout << " - " << d << "\n";
}
// 重构
ocpm::ReconstructCommand rc;
rc.plan_id = "PLAN-002";
rc.modifications = {"调整优先级至85", "修改目标区域"};
auto reconf_result = pm.reconstruct(rc);
std::cout << "\n 重构结果: " << (reconf_result.success ? "成功" : "失败")
<< " | " << reconf_result.message << "\n";
// ---- 分布式计划演示 ----
std::cout << "\n[2] 分布式计划模块演示\n";
printSeparator();
ocpm::DistributedPlanManager dpm;
dpm.loadSampleData();
const auto& graph = dpm.getGraph();
std::cout << " 拓扑: " << graph.nodes.size() << " 节点, "
<< graph.edges.size() << " 条边\n";
for (const auto& n : graph.nodes) {
std::cout << " 节点 " << n.node_id << " [" << n.label << "]\n";
}
// 添加节点
ocpm::TopoNode new_node{"NODE-05", "无人机蜂群", 700.0, 100.0};
dpm.addNode(new_node);
dpm.addEdge({"EDGE-05", "NODE-04", "NODE-05", 200});
std::cout << " 添加新节点后: " << dpm.getGraph().nodes.size() << " 节点\n";
// ---- 指令分发与监控演示 ----
std::cout << "\n[3] 指令分发与执行监控演示\n";
printSeparator();
ocpm::DispatchManager dm;
dm.loadSampleData();
// 查询资产状态
std::cout << " 资产状态:\n";
for (const auto& id : {"ASSET-001", "ASSET-002", "ASSET-003", "ASSET-004", "ASSET-005"}) {
auto st = dm.getAssetStatus(id);
std::cout << " " << id << " -> ";
switch (st) {
case ocpm::AssetStatusCode::READY: std::cout << "就绪(绿)"; break;
case ocpm::AssetStatusCode::BUSY: std::cout << "忙碌(黄)"; break;
case ocpm::AssetStatusCode::FAULT: std::cout << "故障(红)"; break;
case ocpm::AssetStatusCode::OFFLINE:std::cout << "离线(灰)"; break;
}
std::cout << "\n";
}
// 分发
int sent = dm.dispatchPlan("PLAN-001", {"ASSET-001", "ASSET-002", "ASSET-003"});
std::cout << "\n 分发结果: " << sent << " / 3 个资产成功接收\n";
// 异常告警
auto alerts = dm.getAlerts();
std::cout << "\n 当前异常告警: " << alerts.size() << "\n";
for (const auto& a : alerts) {
std::cout << " [" << a.timestamp << "] 等级="
<< static_cast<int>(a.level) << " | " << a.description << "\n";
}
// 仪表盘
auto dash = dm.getDashboardData();
std::cout << "\n 执行仪表盘:\n";
std::cout << " 进度: " << dash.execution.completed_tasks << "/"
<< dash.execution.total_tasks << " 任务\n";
std::cout << " 剩余时间: " << dash.execution.remaining_time << " 分钟\n";
std::cout << " 资源剩余率: " << std::fixed << std::setprecision(1)
<< (dash.resource_rate * 100.0) << "%\n";
// 子任务流程图
auto tasks = dm.getTaskFlow();
std::cout << "\n 子任务流程图 (" << tasks.size() << " 个任务):\n";
for (const auto& t : tasks) {
std::cout << " " << t.task_id << " [" << t.name << "] -> " << t.status << "\n";
if (!t.dependency_ids.empty()) {
std::cout << " 依赖: ";
for (const auto& dep : t.dependency_ids)
std::cout << dep << " ";
std::cout << "\n";
}
}
std::cout << "\n========================================\n";
std::cout << " 演示结束\n";
std::cout << "========================================\n";
return 0;
}

173
tests/basic_test.cpp Normal file
View File

@ -0,0 +1,173 @@
#include "app.hpp"
#include <cassert>
#include <iostream>
#include <string>
/// @brief 测试 PlanManager 基本功能
static void test_plan_manager() {
std::cout << "[测试] PlanManager\n";
ocpm::PlanManager pm;
pm.loadSampleData();
// 测试查询全部
ocpm::PlanQueryRequest all_q;
all_q.page_size = 100;
auto plans = pm.queryPlans(all_q);
assert(plans.size() == 5 && "应加载 5 个示例计划");
// 测试按状态过滤
ocpm::PlanQueryRequest active_q;
active_q.status_filter = static_cast<int>(ocpm::PlanStatus::ACTIVE);
auto active = pm.queryPlans(active_q);
assert(active.size() == 2 && "应有 2 个生效计划");
// 测试按关键字过滤
ocpm::PlanQueryRequest kw_q;
kw_q.keyword = "侦察";
auto kw = pm.queryPlans(kw_q);
assert(kw.size() == 1 && "关键字 '侦察' 应匹配 1 个计划");
assert(kw[0].plan_id == "PLAN-003");
// 测试排序 (按优先级降序)
ocpm::SortParam desc_prio{"priority", ocpm::SortDirection::DESC};
auto sorted = pm.queryPlans(all_q, desc_prio);
assert(!sorted.empty());
assert(sorted[0].priority >= sorted[1].priority);
// 测试获取详情
auto detail = pm.getPlanDetail("PLAN-001");
assert(detail.plan_id == "PLAN-001");
assert(detail.plan_name == "突击行动-甲");
// 测试获取不存在的计划
bool caught = false;
try {
pm.getPlanDetail("NONEXIST");
} catch (const std::invalid_argument&) {
caught = true;
}
assert(caught && "应抛出 invalid_argument");
// 测试对比
auto diffs = pm.comparePlans("PLAN-001", "PLAN-002");
assert(!diffs.empty());
// 测试重构
ocpm::ReconstructCommand rc;
rc.plan_id = "PLAN-002";
rc.modifications = {"测试修改"};
auto result = pm.reconstruct(rc);
assert(result.success);
assert(result.new_version.find("v2") != std::string::npos);
// 测试 HITL 通知不会崩溃
ocpm::HitlEvent hitl;
hitl.request_id = "REQ-001";
hitl.reason = "需要人工确认目标";
hitl.options = {"方案A", "方案B"};
pm.notifyHitlEvent(hitl); // 确保不崩溃
std::cout << " ✓ 所有 PlanManager 测试通过\n";
}
/// @brief 测试 DistributedPlanManager 基本功能
static void test_distributed_plan_manager() {
std::cout << "[测试] DistributedPlanManager\n";
ocpm::DistributedPlanManager dpm;
dpm.loadSampleData();
assert(dpm.getGraph().nodes.size() == 4);
assert(dpm.getGraph().edges.size() == 4);
// 添加节点
ocpm::TopoNode n{"NODE-X", "测试节点", 0, 0};
dpm.addNode(n);
assert(dpm.getGraph().nodes.size() == 5);
// 重复添加不应增加
dpm.addNode(n);
assert(dpm.getGraph().nodes.size() == 5);
// 添加边
ocpm::TopoEdge e{"EDGE-X", "NODE-X", "NODE-01", 100};
dpm.addEdge(e);
assert(dpm.getGraph().edges.size() == 5);
// 移除边
dpm.removeEdge("EDGE-X");
assert(dpm.getGraph().edges.size() == 4);
// 移除节点 (应同时移除关联边)
dpm.removeNode("NODE-X");
assert(dpm.getGraph().nodes.size() == 4);
std::cout << " ✓ 所有 DistributedPlanManager 测试通过\n";
}
/// @brief 测试 DispatchManager 基本功能
static void test_dispatch_manager() {
std::cout << "[测试] DispatchManager\n";
ocpm::DispatchManager dm;
dm.loadSampleData();
// 资产状态
assert(dm.getAssetStatus("ASSET-001") == ocpm::AssetStatusCode::READY);
assert(dm.getAssetStatus("ASSET-003") == ocpm::AssetStatusCode::FAULT);
assert(dm.getAssetStatus("UNKNOWN") == ocpm::AssetStatusCode::OFFLINE);
// 分发
int sent = dm.dispatchPlan("PLAN-001", {"ASSET-001", "ASSET-002", "ASSET-003"});
assert(sent == 1); // 只有 ASSET-001 是 READY
// 执行统计
auto stats = dm.getExecutionStats();
assert(stats.total_tasks == 5);
assert(stats.completed_tasks == 1);
assert(stats.remaining_time > 0.0);
// 仪表盘
auto dash = dm.getDashboardData();
assert(dash.execution.total_tasks == 5);
assert(dash.resource_rate > 0.0);
// 告警
auto alerts = dm.getAlerts();
assert(alerts.size() == 2);
// 按等级过滤告警
ocpm::AlertLevel err = ocpm::AlertLevel::ERROR;
auto err_alerts = dm.getAlerts(&err);
assert(err_alerts.size() == 1);
assert(err_alerts[0].code == 1002);
// 清除告警
dm.clearAlerts();
assert(dm.getAlerts().empty());
// 子任务流程图
auto tasks = dm.getTaskFlow();
assert(tasks.size() == 5);
assert(tasks[0].task_id == "TASK-01");
assert(tasks[1].dependency_ids.size() == 1);
assert(tasks[1].dependency_ids[0] == "TASK-01");
std::cout << " ✓ 所有 DispatchManager 测试通过\n";
}
/// @brief 主测试入口
int main() {
std::cout << "========================================\n";
std::cout << " OCPM 单元测试\n";
std::cout << "========================================\n\n";
test_plan_manager();
test_distributed_plan_manager();
test_dispatch_manager();
std::cout << "\n========================================\n";
std::cout << " 所有测试通过!\n";
std::cout << "========================================\n";
return 0;
}