JavaProjectRepo/business-css/SimController 及相关接口实现建议v4.md
2026-03-19 11:18:15 +08:00

153 lines
6.7 KiB
Markdown
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.

# SimController 及相关接口实现建议 v4
基于 [情景模拟分析结果v3.md](file:///e:/projectJava/JavaProjectRepo/business-css/%E6%83%85%E6%99%AF%E6%A8%A1%E6%8B%9F%E5%88%86%E6%9E%90%E7%BB%93%E6%9E%9Cv3.md) 中的分析,`SimController` 及其配套组件 (`SimService`, `SimBuilder`, `SimModel`) 代表了系统向**模块化、可测试化**方向演进的正确路径。
当前 `SimController` 处于不可用状态(依赖缺失、逻辑简化、代码注释)。为了将其转化为生产可用的仿真服务,以下是具体的实现建议与重构方案。
---
## 1. 总体架构设计
目标是将仿真逻辑从 `ProjectServiceImpl` 中剥离,构建独立的仿真层。
* **Controller 层 (`SimController`)**: 仅负责接收 HTTP 请求,参数校验,调用 Service返回结果。
* **Facade 层 (`SimDataFacade`)**: **新增组件**。负责与现有的 `ProjectService`, `EventService`, `InfluenceService` 交互获取原始数据Project 实体, Event 列表等),并屏蔽数据库细节。*注:原设计中的 `ProjectRepository` 等接口在本项目中没有实现,直接复用现有的 Service 层更符合现状。*
* **Builder 层 (`SimBuilder`)**: 负责将原始数据Entity/JSON转换为仿真专用的领域模型 (`SimUnit`, `SimEvent`, `SimInfluenceNode`)。
* **Engine 层 (`SimService`)**: **核心计算引擎**。纯内存计算,不依赖数据库。执行 `Static -> Event -> Influence -> Override` 的标准管线。
---
## 2. 详细实现建议
### 2.1 补齐数据获取层 (SimDataFacade)
`SimController` 依赖了不存在的 `ProjectRepository` 等接口。建议创建一个 `SimDataFacade` 来封装数据获取逻辑。
```java
@Component
public class SimDataFacade {
private final ProjectService projectService;
private final EventService eventService;
// ... 其他 Service
// 封装获取逻辑:获取项目拓扑、事件列表、影响关系等
public SimDataPackage loadSimulationData(String projectId, String scenarioId) {
Project project = projectService.getById(projectId);
List<Event> events = eventService.list(new QueryWrapper<Event>().eq("scenario_id", scenarioId));
// ... 获取其他必要数据
return new SimDataPackage(project, events);
}
}
```
### 2.2 激活并增强 Builder (SimBuilder)
`SimBuilder` 目前被注释掉了,需要激活并实现核心转换逻辑。重点是将 `ProjectServiceImpl.initSimulation` 中的解析逻辑迁移过来。
* **`buildUnits`**: 解析 `Project.topology` JSON提取 Device 和 Material构建 `SimUnit` 列表。
* *关键点*需要包含静态属性Static Values的解析作为 `SimUnit` 的初始状态。
* **`buildEvents`**: 解析 `Event.attr_changes` JSON构建 `SimEvent` 列表。
* *关键点*:区分 **普通事件 (Input)****强制覆盖事件 (Override)**。建议在 `SimEvent` 中增加 `isOverride` 标志。
* **`buildInfluenceNodes`**: 解析 `Project.topology` 中的 `properties` -> `influence` 节点,构建 `SimInfluenceNode` 列表。
### 2.3 重构计算引擎 (SimService)
这是最核心的部分,必须修正当前的“事件 -> 计算”逻辑,改为 **标准管线**
**建议代码结构:**
```java
public class SimService {
public SimContext runSimulation(List<SimUnit> units,
List<SimEvent> events,
List<SimInfluenceNode> nodes,
int steps) {
SimContext ctx = new SimContext();
// 1. 初始化静态基线 (Static)
// 将 SimUnit 中携带的静态属性写入 ctx (t=0)
for (SimUnit unit : units) {
unit.getStaticProperties().forEach((k, v) ->
ctx.setValue(SimPropertyKey.of(unit.id(), k), v)
);
}
// 2. 时间步推进
for (int step = 0; step <= steps; step++) {
// 2.1 应用输入事件 (Event Input)
// 筛选当前 step 的普通事件,写入 ctx
applyEvents(ctx, events, step, false);
// 2.2 执行影响计算 (Influence)
// 基于当前 ctx 状态,计算所有 InfluenceNode
// 注意:为了避免计算顺序依赖,建议使用双缓冲 (Snapshot) 或 拓扑排序
// 简单实现可先计算 diff再统一应用
applyInfluences(ctx, nodes);
// 2.3 应用强制覆盖事件 (Event Override)
// 筛选当前 step 的强制事件,再次写入 ctx覆盖计算结果
applyEvents(ctx, events, step, true);
// 2.4 保存快照
ctx.snapshot(step);
}
return ctx;
}
}
```
### 2.4 统一 API 接口 (SimController)
建议将 `SimController` 作为仿真功能的唯一入口。
```java
@RestController
@RequestMapping("/sim")
public class SimController {
@PostMapping("/run")
public Result<SimulationResult> run(@RequestBody SimulationRequest req) {
// 1. 加载数据
SimDataPackage data = simDataFacade.loadSimulationData(req.getProjectId(), req.getScenarioId());
// 2. 构建模型
List<SimUnit> units = SimBuilder.buildUnits(data.getProject());
List<SimEvent> events = SimBuilder.buildEvents(data.getEvents());
List<SimInfluenceNode> nodes = SimBuilder.buildInfluenceNodes(data.getProject());
// 3. 执行仿真
SimContext ctx = simService.runSimulation(units, events, nodes, req.getSteps());
// 4. 结果转换 (适配前端图表或 AI 推理)
return Result.success(SimResultConverter.convert(ctx));
}
}
```
---
## 3. 实施路线图
1. **基础类准备**:
* 完善 `SimUnit`: 增加 `Map<String, Double> staticProperties` 字段。
* 完善 `SimEvent`: 增加 `boolean isOverride` 字段。
* 创建 `SimDataFacade` 类。
2. **迁移解析逻辑**:
*`ProjectServiceImpl` 中解析 JSON (Topology, Event) 的代码块复制到 `SimBuilder` 中并适配。
* 确保单元测试覆盖 `SimBuilder`,保证解析正确性。
3. **实现计算逻辑**:
* 编写 `SimService.runSimulation`,严格按照推荐的 4 步管线实现。
* 编写单元测试,验证“事件覆盖计算”和“计算基于静态值”的场景。
4. **接口接入**:
*`SimController` 中装配上述组件。
* 前端对接新的 `/sim/run` 接口。
5. **清理**:
* 标记 `ProjectServiceImpl` 中的旧模拟代码为 `@Deprecated`,并在验证新接口无误后删除。
通过以上步骤,可以将复杂的仿真逻辑从业务 Service 中解耦,构建一个清晰、可维护、易扩展的仿真引擎。