生成代码工程
This commit is contained in:
parent
99b59b1877
commit
a5d1d8f8bc
|
|
@ -0,0 +1,23 @@
|
|||
cmake_minimum_required(VERSION 3.14)
|
||||
project(BattlefieldTaskPlanner VERSION 1.0.0 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if (MSVC)
|
||||
add_compile_options(/utf-8)
|
||||
endif()
|
||||
|
||||
# 头文件搜索路径
|
||||
include_directories(include)
|
||||
|
||||
# 收集核心模块源文件(不含 main.cpp)
|
||||
file(GLOB_RECURSE CORE_SOURCES src/core/*.cpp)
|
||||
list(APPEND CORE_SOURCES src/app.cpp)
|
||||
|
||||
# ---------- 主程序 ----------
|
||||
add_executable(battle_planner src/main.cpp ${CORE_SOURCES})
|
||||
|
||||
# ---------- 测试程序 ----------
|
||||
add_executable(basic_test tests/basic_test.cpp ${CORE_SOURCES})
|
||||
target_include_directories(basic_test PRIVATE include)
|
||||
41
README.md
41
README.md
|
|
@ -1,3 +1,40 @@
|
|||
# 任务自主规划与执行软件
|
||||
# BattlefieldTaskPlanner — 战场任务规划原型系统
|
||||
|
||||
暂无描述
|
||||
基于 C++17 实现的作战任务规划原型系统,覆盖从事件感知、任务生成、模板管理、
|
||||
方案制定到分发监控的全流程核心模型。
|
||||
|
||||
## 工程结构
|
||||
|
||||
```
|
||||
├── CMakeLists.txt
|
||||
├── README.md
|
||||
├── include/
|
||||
│ ├── app.hpp # 顶层应用门面
|
||||
│ └── core/
|
||||
│ ├── event.hpp # 事件接收与处理模块
|
||||
│ ├── task.hpp # 任务生成模块
|
||||
│ ├── template.hpp # 模板管理模块
|
||||
│ ├── plan.hpp # 方案管理模块
|
||||
│ └── dispatch.hpp # 分发监控模块
|
||||
├── src/
|
||||
│ ├── main.cpp # 命令行入口
|
||||
│ ├── app.cpp # 应用实现
|
||||
│ └── core/
|
||||
│ ├── event.cpp
|
||||
│ ├── task.cpp
|
||||
│ ├── template.cpp
|
||||
│ ├── plan.cpp
|
||||
│ └── dispatch.cpp
|
||||
└── tests/
|
||||
└── basic_test.cpp # 基于 assert 的单元测试
|
||||
```
|
||||
|
||||
## 编译与运行
|
||||
|
||||
```bash
|
||||
mkdir -p build && cd build
|
||||
cmake ..
|
||||
cmake --build .
|
||||
./battle_planner # 运行主程序
|
||||
./basic_test # 运行测试
|
||||
```
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef BATTLEFIELD_APP_HPP
|
||||
#define BATTLEFIELD_APP_HPP
|
||||
|
||||
#include <string>
|
||||
#include "core/event.hpp"
|
||||
#include "core/task.hpp"
|
||||
#include "core/template.hpp"
|
||||
#include "core/plan.hpp"
|
||||
#include "core/dispatch.hpp"
|
||||
|
||||
namespace battlefield {
|
||||
|
||||
/// @brief 战场任务规划系统顶层应用门面
|
||||
/// 组合所有核心模块,提供统一的全流程编排入口。
|
||||
class App {
|
||||
public:
|
||||
/// @brief 构造函数,初始化各模块
|
||||
App();
|
||||
|
||||
/// @brief 运行完整的演示流程
|
||||
/// 模拟:事件接收 → 任务生成 → 模板选择 → 方案制定 → 分发监控
|
||||
void Run();
|
||||
|
||||
/// @brief 获取事件处理器引用
|
||||
EventProcessor& GetEventProcessor() { return eventProcessor_; }
|
||||
/// @brief 获取任务生成器引用
|
||||
TaskGenerator& GetTaskGenerator() { return taskGenerator_; }
|
||||
/// @brief 获取模板管理器引用
|
||||
TemplateManager& GetTemplateManager() { return templateManager_; }
|
||||
/// @brief 获取方案管理器引用
|
||||
PlanManager& GetPlanManager() { return planManager_; }
|
||||
/// @brief 获取分发监控器引用
|
||||
DispatchMonitor& GetDispatchMonitor() { return dispatchMonitor_; }
|
||||
|
||||
private:
|
||||
EventProcessor eventProcessor_;
|
||||
TaskGenerator taskGenerator_;
|
||||
TemplateManager templateManager_;
|
||||
PlanManager planManager_;
|
||||
DispatchMonitor dispatchMonitor_;
|
||||
};
|
||||
|
||||
} // namespace battlefield
|
||||
|
||||
#endif // BATTLEFIELD_APP_HPP
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef BATTLEFIELD_CORE_DISPATCH_HPP
|
||||
#define BATTLEFIELD_CORE_DISPATCH_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include "core/plan.hpp"
|
||||
|
||||
namespace battlefield {
|
||||
|
||||
/// @brief 指令包数据结构,对应 IF-03 输出格式
|
||||
struct CmdPacket {
|
||||
std::string packetId; ///< 指令包ID
|
||||
std::string planId; ///< 关联方案ID
|
||||
std::string targetUnit; ///< 目标执行单元
|
||||
std::string payload; ///< 指令载荷(JSON)
|
||||
std::chrono::system_clock::time_point issueTime; ///< 下发时间
|
||||
};
|
||||
|
||||
/// @brief 分发日志记录,对应 T_DISPATCH_LOG
|
||||
struct DispatchLog {
|
||||
std::string logId; ///< 日志ID
|
||||
std::string planId; ///< 方案ID
|
||||
std::string action; ///< 操作描述
|
||||
std::chrono::system_clock::time_point timestamp; ///< 时间戳
|
||||
bool success{true}; ///< 是否成功
|
||||
};
|
||||
|
||||
/// @brief 监控状态快照
|
||||
struct MonitorStatus {
|
||||
int32_t totalTasks{0}; ///< 总任务数
|
||||
int32_t completedTasks{0}; ///< 已完成
|
||||
int32_t inProgressTasks{0}; ///< 进行中
|
||||
int32_t failedTasks{0}; ///< 失败
|
||||
double progressPercent{0.0}; ///< 总体进度百分比
|
||||
};
|
||||
|
||||
/// @brief 分发监控模块(覆盖 SRS-F-06-001 ~ SRS-F-06-003)
|
||||
class DispatchMonitor {
|
||||
public:
|
||||
/// @brief 驱动最终方案的分发执行(对应 IF-03 / IF-05)
|
||||
/// @param plan 待分发的最终方案
|
||||
/// @param targetUnit 目标执行单元
|
||||
/// @return 生成的指令包
|
||||
CmdPacket DispatchPlan(const Plan& plan, const std::string& targetUnit);
|
||||
|
||||
/// @brief 获取当前状态监控仪表盘数据
|
||||
/// @return MonitorStatus 结构体
|
||||
MonitorStatus GetMonitorStatus() const;
|
||||
|
||||
/// @brief 构建总览看板数据(含反馈闭环,触发重规划标识)
|
||||
/// @return 看板摘要字符串
|
||||
std::string GetDashboardData() const;
|
||||
|
||||
/// @brief 记录分发日志
|
||||
/// @param planId 方案ID
|
||||
/// @param action 操作描述
|
||||
/// @param success 是否成功
|
||||
void LogDispatch(const std::string& planId, const std::string& action, bool success);
|
||||
|
||||
/// @brief 模拟推进执行进度
|
||||
/// @param completed 新完成的任务数
|
||||
void AdvanceProgress(int32_t completed);
|
||||
|
||||
private:
|
||||
std::vector<CmdPacket> issuedPackets_; ///< 已下发的指令包
|
||||
std::vector<DispatchLog> logs_; ///< 分发日志
|
||||
MonitorStatus status_; ///< 当前监控状态
|
||||
};
|
||||
|
||||
} // namespace battlefield
|
||||
|
||||
#endif // BATTLEFIELD_CORE_DISPATCH_HPP
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
#ifndef BATTLEFIELD_CORE_EVENT_HPP
|
||||
#define BATTLEFIELD_CORE_EVENT_HPP
|
||||
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
namespace battlefield {
|
||||
|
||||
/// @brief 事件类型枚举
|
||||
enum class EventType : int32_t {
|
||||
UNKNOWN = 0, ///< 未知类型
|
||||
INTEL = 1, ///< 情报事件
|
||||
THREAT = 2, ///< 威胁事件
|
||||
MISSION = 3, ///< 任务事件
|
||||
LOGISTIC = 4 ///< 后勤事件
|
||||
};
|
||||
|
||||
/// @brief 事件状态枚举
|
||||
enum class EventStatus : int32_t {
|
||||
PENDING = 0, ///< 待处理
|
||||
PROCESSING = 1, ///< 处理中
|
||||
RESOLVED = 2, ///< 已解决
|
||||
ARCHIVED = 3 ///< 已归档
|
||||
};
|
||||
|
||||
/// @brief 战场事件数据结构,对应数据库表 T_EVENT
|
||||
struct Event {
|
||||
std::string id; ///< EVENT_ID
|
||||
EventType type; ///< EVENT_TYPE
|
||||
std::chrono::system_clock::time_point timestamp; ///< TIMESTAMP
|
||||
std::string location; ///< LOCATION
|
||||
int32_t priority{0}; ///< PRIORITY
|
||||
EventStatus status{EventStatus::PENDING}; ///< STATUS
|
||||
};
|
||||
|
||||
/// @brief 事件接收与处理模块(覆盖 SRS-F-01-001 ~ SRS-F-01-004)
|
||||
class EventProcessor {
|
||||
public:
|
||||
/// @brief 接收外部事件数据包(对应接口 IF-01)
|
||||
/// @param rawJson 原始 JSON 格式的事件数据
|
||||
/// @return 成功接收返回 true
|
||||
bool ReceiveEvent(const std::string& rawJson);
|
||||
|
||||
/// @brief 对事件数据进行过滤、转化和封装
|
||||
/// @param raw 原始字符串数据
|
||||
/// @return 标准化后的 Event 对象
|
||||
Event TransformEvent(const std::string& raw);
|
||||
|
||||
/// @brief 获取当前所有待处理事件列表
|
||||
/// @return 事件列表(按接收顺序)
|
||||
std::vector<Event> GetPendingEvents() const;
|
||||
|
||||
/// @brief 按优先级对待处理事件排序
|
||||
/// @param ascending true 为升序(低优先级在前),false 为降序
|
||||
void SortEventsByPriority(bool ascending = true);
|
||||
|
||||
/// @brief 获取事件总数
|
||||
/// @return 事件数量
|
||||
size_t GetEventCount() const { return events_.size(); }
|
||||
|
||||
private:
|
||||
std::vector<Event> events_; ///< 内部事件存储
|
||||
};
|
||||
|
||||
} // namespace battlefield
|
||||
|
||||
#endif // BATTLEFIELD_CORE_EVENT_HPP
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
#ifndef BATTLEFIELD_CORE_PLAN_HPP
|
||||
#define BATTLEFIELD_CORE_PLAN_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
|
||||
namespace battlefield {
|
||||
|
||||
/// @brief 子任务关系图谱节点,对应 T_PLAN_SUBTASK
|
||||
struct PlanSubTask {
|
||||
std::string id; ///< 子任务ID
|
||||
std::string parentId; ///< 父任务ID(空字符串表示根任务)
|
||||
std::string name; ///< 子任务名称
|
||||
std::string description; ///< 描述
|
||||
int32_t orderIndex{0}; ///< 执行顺序
|
||||
std::string assignedUnit; ///< 执行单元
|
||||
};
|
||||
|
||||
/// @brief 作战方案主数据结构,对应 T_PLAN
|
||||
struct Plan {
|
||||
std::string id; ///< 方案ID
|
||||
std::string name; ///< 方案名称
|
||||
std::string description; ///< 方案描述
|
||||
std::vector<PlanSubTask> subTasks; ///< 子任务列表
|
||||
double score{0.0}; ///< 方案评分
|
||||
};
|
||||
|
||||
/// @brief 方案管理模块(覆盖 SRS-F-05-001 ~ SRS-F-05-004)
|
||||
class PlanManager {
|
||||
public:
|
||||
/// @brief 创建新方案
|
||||
/// @param name 方案名称
|
||||
/// @param description 方案描述
|
||||
/// @return 创建的 Plan 对象
|
||||
Plan CreatePlan(const std::string& name, const std::string& description);
|
||||
|
||||
/// @brief 获取所有方案列表
|
||||
/// @return 方案列表
|
||||
std::vector<Plan> GetPlanList() const;
|
||||
|
||||
/// @brief 按评分排序方案列表
|
||||
/// @param ascending 是否升序
|
||||
void SortPlansByScore(bool ascending = false);
|
||||
|
||||
/// @brief 对比两个方案的详细信息
|
||||
/// @param planIdA 方案A的ID
|
||||
/// @param planIdB 方案B的ID
|
||||
/// @return 差异描述字符串
|
||||
std::string ComparePlans(const std::string& planIdA, const std::string& planIdB);
|
||||
|
||||
/// @brief 重组方案(调整子任务顺序或分配)
|
||||
/// @param planId 方案ID
|
||||
/// @param newSubTasks 新的子任务列表
|
||||
/// @return 是否成功重组
|
||||
bool ReorganizePlan(const std::string& planId, const std::vector<PlanSubTask>& newSubTasks);
|
||||
|
||||
/// @brief 合并多个方案为一个融合方案
|
||||
/// @param planIds 待融合的方案ID列表
|
||||
/// @return 融合后的新方案
|
||||
Plan MergePlans(const std::vector<std::string>& planIds);
|
||||
|
||||
private:
|
||||
std::map<std::string, Plan> plans_; ///< 方案存储(key为方案ID)
|
||||
};
|
||||
|
||||
} // namespace battlefield
|
||||
|
||||
#endif // BATTLEFIELD_CORE_PLAN_HPP
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef BATTLEFIELD_CORE_TASK_HPP
|
||||
#define BATTLEFIELD_CORE_TASK_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include "core/event.hpp"
|
||||
|
||||
namespace battlefield {
|
||||
|
||||
/// @brief 任务草案状态枚举
|
||||
enum class DraftStatus : int32_t {
|
||||
DRAFT = 0, ///< 草稿
|
||||
SUBMITTED = 1, ///< 已提交
|
||||
APPROVED = 2, ///< 已批准
|
||||
REJECTED = 3 ///< 已驳回
|
||||
};
|
||||
|
||||
/// @brief 任务草案数据结构,对应 T_TASK_DRAFT(内存缓存后持久化)
|
||||
struct TaskDraft {
|
||||
std::string id; ///< 任务草案ID
|
||||
std::string title; ///< 任务标题
|
||||
std::string description; ///< 任务描述
|
||||
int32_t priority{0}; ///< 优先级
|
||||
DraftStatus status{DraftStatus::DRAFT}; ///< 状态
|
||||
std::string relatedEventId; ///< 关联事件ID
|
||||
};
|
||||
|
||||
/// @brief 任务生成模块(覆盖 SRS-F-02-001 ~ SRS-F-02-004)
|
||||
class TaskGenerator {
|
||||
public:
|
||||
/// @brief 基于选定事件生成作战任务草案
|
||||
/// @param event 源事件
|
||||
/// @return 生成的 TaskDraft 对象
|
||||
TaskDraft CreateTaskFromEvent(const Event& event);
|
||||
|
||||
/// @brief 获取当前所有任务草案列表
|
||||
/// @return 草案列表
|
||||
std::vector<TaskDraft> GetDraftList() const;
|
||||
|
||||
/// @brief 提交任务草案送交处理(对应接口 IF-02)
|
||||
/// @param draftId 草案ID
|
||||
/// @param targetUrl 目标任务引擎地址
|
||||
/// @return 是否提交成功
|
||||
bool SubmitDraft(const std::string& draftId, const std::string& targetUrl);
|
||||
|
||||
/// @brief 按优先级排序草案列表
|
||||
/// @param ascending 是否升序
|
||||
void SortDraftsByPriority(bool ascending = true);
|
||||
|
||||
private:
|
||||
std::vector<TaskDraft> drafts_; ///< 内存暂存的任务草案
|
||||
};
|
||||
|
||||
} // namespace battlefield
|
||||
|
||||
#endif // BATTLEFIELD_CORE_TASK_HPP
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef BATTLEFIELD_CORE_TEMPLATE_HPP
|
||||
#define BATTLEFIELD_CORE_TEMPLATE_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
namespace battlefield {
|
||||
|
||||
/// @brief 任务模板数据结构,对应 T_TEMPLATE,含版本管理字段 VERSION_ID
|
||||
struct TaskTemplate {
|
||||
std::string versionId; ///< VERSION_ID(版本号)
|
||||
std::string name; ///< 模板名称
|
||||
std::string description; ///< 模板描述
|
||||
std::string content; ///< 模板内容(JSON格式)
|
||||
std::string dateIndex; ///< 日期索引
|
||||
bool isActive{true}; ///< 是否当前激活版本
|
||||
};
|
||||
|
||||
/// @brief 模板管理模块(覆盖 SRS-F-03 / SRS-F-04 相关需求)
|
||||
class TemplateManager {
|
||||
public:
|
||||
/// @brief 加载任务模板集合(模拟从文件系统读取 JSON 模板文件)
|
||||
/// @param directory 模板文件目录
|
||||
/// @return 成功加载的模板数量
|
||||
size_t LoadTemplates(const std::string& directory);
|
||||
|
||||
/// @brief 获取所有模板列表
|
||||
/// @return 模板列表
|
||||
std::vector<TaskTemplate> GetTemplateList() const;
|
||||
|
||||
/// @brief 按名称排序模板列表
|
||||
/// @param ascending 是否升序
|
||||
void SortTemplatesByName(bool ascending = true);
|
||||
|
||||
/// @brief 选择指定版本的模板(人环模式)
|
||||
/// @param versionId 版本ID
|
||||
/// @return 选中的模板,若不存在返回空
|
||||
TaskTemplate SelectTemplate(const std::string& versionId);
|
||||
|
||||
/// @brief 自动推荐最优模板(自主模式)
|
||||
/// @return 推荐的模板
|
||||
TaskTemplate RecommendTemplate();
|
||||
|
||||
/// @brief 获取模板总数
|
||||
/// @return 模板数量
|
||||
size_t GetTemplateCount() const { return templates_.size(); }
|
||||
|
||||
private:
|
||||
std::vector<TaskTemplate> templates_; ///< 模板集合
|
||||
};
|
||||
|
||||
} // namespace battlefield
|
||||
|
||||
#endif // BATTLEFIELD_CORE_TEMPLATE_HPP
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
#include "app.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace battlefield {
|
||||
|
||||
App::App() {
|
||||
// 各模块使用默认构造初始化
|
||||
}
|
||||
|
||||
void App::Run() {
|
||||
std::cout << "========== 战场任务规划系统 (BattlefieldTaskPlanner) ==========\n\n";
|
||||
|
||||
// ---- 1. 事件接收处理 ----
|
||||
std::cout << "[1] 事件接收处理 (SRS-F-01)\n";
|
||||
eventProcessor_.ReceiveEvent(R"({"type":"intel","source":"drone","priority":8})");
|
||||
eventProcessor_.ReceiveEvent(R"({"type":"threat","source":"radar","priority":9})");
|
||||
eventProcessor_.ReceiveEvent(R"({"type":"logistic","source":"supply","priority":3})");
|
||||
std::cout << " 已接收 " << eventProcessor_.GetEventCount() << " 个事件\n";
|
||||
eventProcessor_.SortEventsByPriority(false);
|
||||
auto pendingEvents = eventProcessor_.GetPendingEvents();
|
||||
for (const auto& e : pendingEvents) {
|
||||
std::cout << " - " << e.id << " (Priority: " << e.priority << ")\n";
|
||||
}
|
||||
|
||||
// ---- 2. 任务生成 ----
|
||||
std::cout << "\n[2] 任务生成 (SRS-F-02)\n";
|
||||
for (const auto& e : pendingEvents) {
|
||||
TaskDraft draft = taskGenerator_.CreateTaskFromEvent(e);
|
||||
std::cout << " 生成任务草案: " << draft.id << " <- " << draft.title << "\n";
|
||||
}
|
||||
taskGenerator_.SubmitDraft("DRF-EVT-{", "http://task-engine.local/submit");
|
||||
|
||||
// ---- 3. 模板管理 ----
|
||||
std::cout << "\n[3] 模板管理 (SRS-F-03 / SRS-F-04)\n";
|
||||
templateManager_.LoadTemplates("/lib/tpcs/templates");
|
||||
std::cout << " 已加载 " << templateManager_.GetTemplateCount() << " 个模板\n";
|
||||
auto selected = templateManager_.SelectTemplate("v1.1");
|
||||
if (!selected.versionId.empty()) {
|
||||
std::cout << " 选择模板: " << selected.name << " (v" << selected.versionId << ")\n";
|
||||
}
|
||||
auto recommended = templateManager_.RecommendTemplate();
|
||||
std::cout << " 自主推荐模板: " << recommended.name << "\n";
|
||||
|
||||
// ---- 4. 方案管理 ----
|
||||
std::cout << "\n[4] 方案管理 (SRS-F-05)\n";
|
||||
Plan planA = planManager_.CreatePlan("Offensive Plan A", "Direct strike approach");
|
||||
Plan planB = planManager_.CreatePlan("Defensive Plan B", "Perimeter hold approach");
|
||||
std::cout << " 创建方案: " << planA.name << " (" << planA.id << ")\n";
|
||||
std::cout << " 创建方案: " << planB.name << " (" << planB.id << ")\n";
|
||||
std::cout << " 对比结果:\n" << planManager_.ComparePlans(planA.id, planB.id) << "\n";
|
||||
|
||||
// ---- 5. 分发监控 ----
|
||||
std::cout << "\n[5] 分发监控 (SRS-F-06)\n";
|
||||
CmdPacket cmd = dispatchMonitor_.DispatchPlan(planA, "battalion-1");
|
||||
std::cout << " 下发指令包: " << cmd.packetId << " -> " << cmd.targetUnit << "\n";
|
||||
dispatchMonitor_.AdvanceProgress(2);
|
||||
std::cout << " 推进执行进度...\n";
|
||||
std::cout << " 看板数据:\n" << dispatchMonitor_.GetDashboardData() << "\n";
|
||||
|
||||
std::cout << "\n========== 流程演示完毕 ==========\n";
|
||||
}
|
||||
|
||||
} // namespace battlefield
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
#include "core/dispatch.hpp"
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace battlefield {
|
||||
|
||||
CmdPacket DispatchMonitor::DispatchPlan(const Plan& plan, const std::string& targetUnit) {
|
||||
CmdPacket packet;
|
||||
packet.packetId = "CMD-" + plan.id;
|
||||
packet.planId = plan.id;
|
||||
packet.targetUnit = targetUnit;
|
||||
packet.payload = "{\"plan\": \"" + plan.name + "\", \"tasks\": " +
|
||||
std::to_string(plan.subTasks.size()) + "}";
|
||||
packet.issueTime = std::chrono::system_clock::now();
|
||||
issuedPackets_.push_back(packet);
|
||||
|
||||
// 更新监控状态
|
||||
status_.totalTasks += static_cast<int32_t>(plan.subTasks.size());
|
||||
status_.inProgressTasks += static_cast<int32_t>(plan.subTasks.size());
|
||||
|
||||
LogDispatch(plan.id, "DISPATCH", true);
|
||||
return packet;
|
||||
}
|
||||
|
||||
MonitorStatus DispatchMonitor::GetMonitorStatus() const {
|
||||
return status_;
|
||||
}
|
||||
|
||||
std::string DispatchMonitor::GetDashboardData() const {
|
||||
std::stringstream ss;
|
||||
auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||
ss << "=== Dashboard ===\n"
|
||||
<< "Time: " << std::put_time(std::gmtime(&now), "%Y-%m-%d %H:%M:%S") << "\n"
|
||||
<< "Total Tasks: " << status_.totalTasks << "\n"
|
||||
<< "Completed: " << status_.completedTasks << "\n"
|
||||
<< "In Progress: " << status_.inProgressTasks << "\n"
|
||||
<< "Failed: " << status_.failedTasks << "\n"
|
||||
<< "Progress: " << std::fixed << std::setprecision(1)
|
||||
<< status_.progressPercent << "%\n"
|
||||
<< "Issued Packets: " << issuedPackets_.size() << "\n"
|
||||
<< "Log Entries: " << logs_.size();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void DispatchMonitor::LogDispatch(const std::string& planId,
|
||||
const std::string& action, bool success) {
|
||||
DispatchLog log;
|
||||
log.logId = "LOG-" + std::to_string(logs_.size() + 1);
|
||||
log.planId = planId;
|
||||
log.action = action;
|
||||
log.timestamp = std::chrono::system_clock::now();
|
||||
log.success = success;
|
||||
logs_.push_back(log);
|
||||
}
|
||||
|
||||
void DispatchMonitor::AdvanceProgress(int32_t completed) {
|
||||
int32_t actualCompleted = std::min(completed, status_.inProgressTasks);
|
||||
status_.completedTasks += actualCompleted;
|
||||
status_.inProgressTasks -= actualCompleted;
|
||||
if (status_.totalTasks > 0) {
|
||||
status_.progressPercent =
|
||||
100.0 * static_cast<double>(status_.completedTasks) /
|
||||
static_cast<double>(status_.totalTasks);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace battlefield
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#include "core/event.hpp"
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
namespace battlefield {
|
||||
|
||||
bool EventProcessor::ReceiveEvent(const std::string& rawJson) {
|
||||
// 模拟接收:将原始 JSON 转化为 Event 对象并加入列表
|
||||
Event evt = TransformEvent(rawJson);
|
||||
events_.push_back(evt);
|
||||
return true;
|
||||
}
|
||||
|
||||
Event EventProcessor::TransformEvent(const std::string& raw) {
|
||||
// 模拟转化逻辑:从原始字符串解析字段
|
||||
Event evt;
|
||||
// 简单模拟:使用字符串内容生成 ID 和类型
|
||||
std::stringstream ss(raw);
|
||||
std::string token;
|
||||
std::getline(ss, token, ',');
|
||||
evt.id = "EVT-" + token.substr(0, 4);
|
||||
evt.type = EventType::INTEL;
|
||||
evt.priority = 5;
|
||||
evt.location = "zone-alpha";
|
||||
evt.timestamp = std::chrono::system_clock::now();
|
||||
evt.status = EventStatus::PENDING;
|
||||
return evt;
|
||||
}
|
||||
|
||||
std::vector<Event> EventProcessor::GetPendingEvents() const {
|
||||
std::vector<Event> pending;
|
||||
for (const auto& e : events_) {
|
||||
if (e.status == EventStatus::PENDING) {
|
||||
pending.push_back(e);
|
||||
}
|
||||
}
|
||||
return pending;
|
||||
}
|
||||
|
||||
void EventProcessor::SortEventsByPriority(bool ascending) {
|
||||
std::sort(events_.begin(), events_.end(),
|
||||
[ascending](const Event& a, const Event& b) {
|
||||
return ascending ? (a.priority < b.priority) : (a.priority > b.priority);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace battlefield
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
#include "core/plan.hpp"
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <numeric>
|
||||
|
||||
namespace battlefield {
|
||||
|
||||
Plan PlanManager::CreatePlan(const std::string& name, const std::string& description) {
|
||||
Plan plan;
|
||||
plan.id = "PLN-" + std::to_string(plans_.size() + 1);
|
||||
plan.name = name;
|
||||
plan.description = description;
|
||||
plan.score = 0.0;
|
||||
plans_[plan.id] = plan;
|
||||
return plan;
|
||||
}
|
||||
|
||||
std::vector<Plan> PlanManager::GetPlanList() const {
|
||||
std::vector<Plan> result;
|
||||
for (const auto& pair : plans_) {
|
||||
result.push_back(pair.second);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void PlanManager::SortPlansByScore(bool ascending) {
|
||||
// map 本身无序,需要先转成 vector 排序后再重建
|
||||
std::vector<Plan> sorted;
|
||||
for (const auto& pair : plans_) sorted.push_back(pair.second);
|
||||
std::sort(sorted.begin(), sorted.end(),
|
||||
[ascending](const Plan& a, const Plan& b) {
|
||||
return ascending ? (a.score < b.score) : (a.score > b.score);
|
||||
});
|
||||
plans_.clear();
|
||||
for (const auto& p : sorted) {
|
||||
plans_[p.id] = p;
|
||||
}
|
||||
}
|
||||
|
||||
std::string PlanManager::ComparePlans(const std::string& planIdA, const std::string& planIdB) {
|
||||
auto itA = plans_.find(planIdA);
|
||||
auto itB = plans_.find(planIdB);
|
||||
if (itA == plans_.end() || itB == plans_.end()) return "Plan not found.";
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Comparison [" << itA->second.name << " vs " << itB->second.name << "]:\n"
|
||||
<< " Score: " << itA->second.score << " vs " << itB->second.score << "\n"
|
||||
<< " SubTasks: " << itA->second.subTasks.size() << " vs "
|
||||
<< itB->second.subTasks.size();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bool PlanManager::ReorganizePlan(const std::string& planId,
|
||||
const std::vector<PlanSubTask>& newSubTasks) {
|
||||
auto it = plans_.find(planId);
|
||||
if (it == plans_.end()) return false;
|
||||
it->second.subTasks = newSubTasks;
|
||||
return true;
|
||||
}
|
||||
|
||||
Plan PlanManager::MergePlans(const std::vector<std::string>& planIds) {
|
||||
Plan merged;
|
||||
merged.id = "PLN-MERGED-" + std::to_string(plans_.size() + 1);
|
||||
merged.name = "Merged Plan";
|
||||
merged.description = "Fusion of " + std::to_string(planIds.size()) + " plans";
|
||||
|
||||
int subTaskIndex = 0;
|
||||
for (const auto& pid : planIds) {
|
||||
auto it = plans_.find(pid);
|
||||
if (it != plans_.end()) {
|
||||
for (const auto& st : it->second.subTasks) {
|
||||
PlanSubTask copy = st;
|
||||
copy.id = "MST-" + std::to_string(++subTaskIndex);
|
||||
merged.subTasks.push_back(copy);
|
||||
}
|
||||
merged.score += it->second.score;
|
||||
}
|
||||
}
|
||||
if (!planIds.empty()) merged.score /= static_cast<double>(planIds.size());
|
||||
|
||||
plans_[merged.id] = merged;
|
||||
return merged;
|
||||
}
|
||||
|
||||
} // namespace battlefield
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#include "core/task.hpp"
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
namespace battlefield {
|
||||
|
||||
TaskDraft TaskGenerator::CreateTaskFromEvent(const Event& event) {
|
||||
TaskDraft draft;
|
||||
draft.id = "DRF-" + event.id;
|
||||
draft.title = "Task from " + event.id;
|
||||
draft.description = "Auto-generated task based on event: " + event.id;
|
||||
draft.priority = event.priority;
|
||||
draft.status = DraftStatus::DRAFT;
|
||||
draft.relatedEventId = event.id;
|
||||
drafts_.push_back(draft);
|
||||
return draft;
|
||||
}
|
||||
|
||||
std::vector<TaskDraft> TaskGenerator::GetDraftList() const {
|
||||
return drafts_;
|
||||
}
|
||||
|
||||
bool TaskGenerator::SubmitDraft(const std::string& draftId, const std::string& targetUrl) {
|
||||
for (auto& d : drafts_) {
|
||||
if (d.id == draftId) {
|
||||
d.status = DraftStatus::SUBMITTED;
|
||||
// 模拟向 targetUrl 发送任务草案(对应 IF-02)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TaskGenerator::SortDraftsByPriority(bool ascending) {
|
||||
std::sort(drafts_.begin(), drafts_.end(),
|
||||
[ascending](const TaskDraft& a, const TaskDraft& b) {
|
||||
return ascending ? (a.priority < b.priority) : (a.priority > b.priority);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace battlefield
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
#include "core/template.hpp"
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
|
||||
namespace battlefield {
|
||||
|
||||
size_t TemplateManager::LoadTemplates(const std::string& directory) {
|
||||
// 模拟加载:生成若干示例模板
|
||||
for (int i = 1; i <= 3; ++i) {
|
||||
TaskTemplate tmpl;
|
||||
tmpl.versionId = "v1." + std::to_string(i);
|
||||
tmpl.name = "Template-" + std::to_string(i);
|
||||
tmpl.description = "Standard mission template " + std::to_string(i);
|
||||
tmpl.content = "{\"type\": \"mission\", \"version\": \"" + tmpl.versionId + "\"}";
|
||||
tmpl.dateIndex = "2025-03-01";
|
||||
tmpl.isActive = (i == 1);
|
||||
templates_.push_back(tmpl);
|
||||
}
|
||||
return templates_.size();
|
||||
}
|
||||
|
||||
std::vector<TaskTemplate> TemplateManager::GetTemplateList() const {
|
||||
return templates_;
|
||||
}
|
||||
|
||||
void TemplateManager::SortTemplatesByName(bool ascending) {
|
||||
std::sort(templates_.begin(), templates_.end(),
|
||||
[ascending](const TaskTemplate& a, const TaskTemplate& b) {
|
||||
return ascending ? (a.name < b.name) : (a.name > b.name);
|
||||
});
|
||||
}
|
||||
|
||||
TaskTemplate TemplateManager::SelectTemplate(const std::string& versionId) {
|
||||
for (const auto& t : templates_) {
|
||||
if (t.versionId == versionId) return t;
|
||||
}
|
||||
return TaskTemplate{};
|
||||
}
|
||||
|
||||
TaskTemplate TemplateManager::RecommendTemplate() {
|
||||
// 自主模式:返回评分最高的模板(模拟选第一个激活的)
|
||||
for (const auto& t : templates_) {
|
||||
if (t.isActive) return t;
|
||||
}
|
||||
return templates_.empty() ? TaskTemplate{} : templates_.front();
|
||||
}
|
||||
|
||||
} // namespace battlefield
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#include "app.hpp"
|
||||
|
||||
/// @brief 命令行入口
|
||||
/// @return 程序退出码
|
||||
int main() {
|
||||
battlefield::App app;
|
||||
app.Run();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "core/event.hpp"
|
||||
#include "core/task.hpp"
|
||||
#include "core/template.hpp"
|
||||
#include "core/plan.hpp"
|
||||
#include "core/dispatch.hpp"
|
||||
|
||||
/// @brief 测试 EventProcessor 模块
|
||||
static void TestEventProcessor() {
|
||||
battlefield::EventProcessor ep;
|
||||
|
||||
bool ok = ep.ReceiveEvent(R"({"type":"intel","priority":7})");
|
||||
assert(ok);
|
||||
assert(ep.GetEventCount() == 1);
|
||||
|
||||
ok = ep.ReceiveEvent(R"({"type":"threat","priority":9})");
|
||||
assert(ok);
|
||||
assert(ep.GetEventCount() == 2);
|
||||
|
||||
auto pending = ep.GetPendingEvents();
|
||||
assert(pending.size() == 2);
|
||||
|
||||
ep.SortEventsByPriority(false); // 降序
|
||||
pending = ep.GetPendingEvents();
|
||||
assert(pending[0].priority >= pending[1].priority);
|
||||
|
||||
std::cout << "[PASS] TestEventProcessor\n";
|
||||
}
|
||||
|
||||
/// @brief 测试 TaskGenerator 模块
|
||||
static void TestTaskGenerator() {
|
||||
battlefield::TaskGenerator tg;
|
||||
battlefield::Event evt;
|
||||
evt.id = "EVT-001";
|
||||
evt.priority = 8;
|
||||
evt.type = battlefield::EventType::INTEL;
|
||||
|
||||
battlefield::TaskDraft draft = tg.CreateTaskFromEvent(evt);
|
||||
assert(draft.relatedEventId == "EVT-001");
|
||||
assert(draft.status == battlefield::DraftStatus::DRAFT);
|
||||
|
||||
auto list = tg.GetDraftList();
|
||||
assert(list.size() == 1);
|
||||
|
||||
bool submitted = tg.SubmitDraft(draft.id, "http://engine.local");
|
||||
assert(submitted);
|
||||
|
||||
list = tg.GetDraftList();
|
||||
assert(list[0].status == battlefield::DraftStatus::SUBMITTED);
|
||||
|
||||
std::cout << "[PASS] TestTaskGenerator\n";
|
||||
}
|
||||
|
||||
/// @brief 测试 TemplateManager 模块
|
||||
static void TestTemplateManager() {
|
||||
battlefield::TemplateManager tm;
|
||||
size_t count = tm.LoadTemplates("/fake/path");
|
||||
assert(count == 3);
|
||||
assert(tm.GetTemplateCount() == 3);
|
||||
|
||||
auto list = tm.GetTemplateList();
|
||||
assert(list.size() == 3);
|
||||
|
||||
auto selected = tm.SelectTemplate("v1.1");
|
||||
assert(!selected.versionId.empty());
|
||||
assert(selected.name == "Template-1");
|
||||
|
||||
auto recommended = tm.RecommendTemplate();
|
||||
assert(!recommended.versionId.empty());
|
||||
|
||||
std::cout << "[PASS] TestTemplateManager\n";
|
||||
}
|
||||
|
||||
/// @brief 测试 PlanManager 模块
|
||||
static void TestPlanManager() {
|
||||
battlefield::PlanManager pm;
|
||||
battlefield::Plan a = pm.CreatePlan("Plan A", "First option");
|
||||
battlefield::Plan b = pm.CreatePlan("Plan B", "Second option");
|
||||
assert(!a.id.empty());
|
||||
assert(!b.id.empty());
|
||||
|
||||
auto list = pm.GetPlanList();
|
||||
assert(list.size() == 2);
|
||||
|
||||
std::string cmp = pm.ComparePlans(a.id, b.id);
|
||||
assert(cmp.find("Score") != std::string::npos);
|
||||
|
||||
// 融合测试
|
||||
battlefield::Plan merged = pm.MergePlans({a.id, b.id});
|
||||
assert(merged.id.find("MERGED") != std::string::npos);
|
||||
|
||||
std::cout << "[PASS] TestPlanManager\n";
|
||||
}
|
||||
|
||||
/// @brief 测试 DispatchMonitor 模块
|
||||
static void TestDispatchMonitor() {
|
||||
battlefield::DispatchMonitor dm;
|
||||
battlefield::Plan plan;
|
||||
plan.id = "PLN-TEST";
|
||||
plan.name = "Test Plan";
|
||||
|
||||
battlefield::PlanSubTask st;
|
||||
st.id = "ST-1";
|
||||
st.name = "Recon";
|
||||
plan.subTasks.push_back(st);
|
||||
|
||||
battlefield::CmdPacket cmd = dm.DispatchPlan(plan, "unit-alpha");
|
||||
assert(cmd.packetId.find("CMD-") != std::string::npos);
|
||||
assert(cmd.targetUnit == "unit-alpha");
|
||||
|
||||
auto status = dm.GetMonitorStatus();
|
||||
assert(status.totalTasks == 1);
|
||||
|
||||
dm.AdvanceProgress(1);
|
||||
status = dm.GetMonitorStatus();
|
||||
assert(status.completedTasks == 1);
|
||||
assert(status.progressPercent == 100.0);
|
||||
|
||||
std::string dash = dm.GetDashboardData();
|
||||
assert(dash.find("Progress") != std::string::npos);
|
||||
|
||||
std::cout << "[PASS] TestDispatchMonitor\n";
|
||||
}
|
||||
|
||||
/// @brief 主测试入口
|
||||
/// @return 0 全部通过
|
||||
int main() {
|
||||
std::cout << "========== BattlefieldTaskPlanner 单元测试 ==========\n\n";
|
||||
|
||||
TestEventProcessor();
|
||||
TestTaskGenerator();
|
||||
TestTemplateManager();
|
||||
TestPlanManager();
|
||||
TestDispatchMonitor();
|
||||
|
||||
std::cout << "\n========== 全部测试通过 ==========\n";
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue