JavaProjectRepo/business-css/SimController及相关接口详细实现文档.md
2026-03-19 11:18:15 +08:00

195 lines
7.6 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-2
本文档基于 [SimController 及相关接口实现建议v4.md](file:///e:/projectJava/JavaProjectRepo/business-css/SimController%20%E5%8F%8A%E7%9B%B8%E5%85%B3%E6%8E%A5%E5%8F%A3%E5%AE%9E%E7%8E%B0%E5%BB%BA%E8%AE%AEv4.md) 进一步细化提供了更贴合当前代码库ProjectServiceImpl的详细实现方案。
## 1. 核心目标
* **激活 `SimController`**:使其成为仿真服务的唯一入口,替代分散在 `ProjectController` 中的逻辑。
* **标准化计算管线**:实现 `Static -> Event(Input) -> Influence -> Event(Override)` 的标准计算流程。
* **复用现有逻辑**:最大程度复用 `ProjectServiceImpl` 中已有的 JSON 解析和数据组装代码,避免重复造轮子。
---
## 2. 模块详细设计与实现
### 2.1 数据获取层 (SimDataFacade)
负责从 DB 获取原始数据,并进行初步的组装。
**File:** `src/main/java/com/yfd/business/css/facade/SimDataFacade.java` (新建)
```java
@Component
public class SimDataFacade {
@Autowired private ProjectService projectService;
@Autowired private EventService eventService;
@Autowired private MaterialService materialService; // 用于补全物料静态属性
public SimDataPackage loadSimulationData(String projectId, String scenarioId) {
// 1. 获取项目与拓扑
Project project = projectService.getById(projectId);
if (project == null) throw new IllegalArgumentException("Project not found: " + projectId);
// 2. 获取事件
List<Event> events = eventService.list(new QueryWrapper<Event>().eq("scenario_id", scenarioId));
// 3. 预加载物料库 (用于后续补全静态属性)
// 逻辑复用 ProjectServiceImpl.buildMaterialStaticFromDb
// 这里先返回原始数据,由 Builder 处理具体的补全逻辑
return new SimDataPackage(project, events);
}
}
```
### 2.2 模型构建层 (SimBuilder)
负责将 `Project` (JSON) 和 `Event` (JSON) 转换为 `SimUnit`, `SimEvent`, `SimInfluenceNode`
**关键策略**:直接复用 `ProjectServiceImpl` 中的解析方法(`parseDeviceStaticsAndInfluences`, `buildValueProviders` 等),将其重构为静态工具方法或独立组件。
**File:** `src/main/java/com/yfd/business/css/build/SimBuilder.java` (激活并重构)
```java
public class SimBuilder {
private final ObjectMapper objectMapper = new ObjectMapper();
// 1. 构建单元 (SimUnit) - 包含静态属性
public List<SimUnit> buildUnits(Project project, MaterialService materialService) {
List<SimUnit> units = new ArrayList<>();
JsonNode root = objectMapper.readTree(project.getTopology());
// 解析设备静态属性 (复用 ProjectServiceImpl.parseDeviceStaticsAndInfluences 的部分逻辑)
// 解析物料静态属性 (复用 ProjectServiceImpl.buildMaterialStaticFromDb)
// 伪代码示例
for (JsonNode deviceNode : root.path("devices")) {
String deviceId = deviceNode.path("deviceId").asText();
Map<String, Double> staticProps = new HashMap<>();
// 1.1 解析 topology 中的 static 节点
// 1.2 解析 Device.size 并注入
// 1.3 如果有绑定的 material查询 DB 并注入物料属性
units.add(new SimUnit(deviceId, ..., staticProps));
}
return units;
}
// 2. 构建事件 (SimEvent)
public List<SimEvent> buildEvents(List<Event> events) {
// 复用 ProjectServiceImpl.buildValueProviders 解析 attr_changes
// 将解析出的 Schedule 转换为 List<SimEvent>
// 注意区分 isOverride (强制覆盖)
}
// 3. 构建影响关系 (SimInfluenceNode)
public List<SimInfluenceNode> buildInfluenceNodes(Project project) {
// 复用 ProjectServiceImpl.parseDeviceStaticsAndInfluences 中的 influence 解析逻辑
}
}
```
### 2.3 核心计算引擎 (SimService)
实现标准计算管线。
**File:** `src/main/java/com/yfd/business/css/service/SimService.java` (重构)
```java
public class SimService {
public SimContext runSimulation(List<SimUnit> units,
List<SimEvent> events,
List<SimInfluenceNode> nodes,
int steps) {
SimContext ctx = new SimContext();
// Step 1: 初始化静态基线 (t=0)
for (SimUnit unit : units) {
unit.getStaticProperties().forEach((k, v) ->
ctx.setValue(SimPropertyKey.of(unit.unitId(), k), v)
);
}
// Step 2: 循环推进 (t=1 to steps)
for (int step = 1; step <= steps; step++) {
// 2.1 Event (Input): 应用普通事件
applyEvents(ctx, events, step, false);
// 2.2 Influence: 计算影响关系
// 基于当前 ctx (包含 static + input event) 计算
applyInfluences(ctx, nodes);
// 2.3 Event (Override): 应用强制覆盖事件
// 再次覆盖,确保强制逻辑生效
applyEvents(ctx, events, step, true);
// 2.4 Snapshot
ctx.snapshot(step);
}
return ctx;
}
// 辅助方法applyEvents, applyInfluences
}
```
### 2.4 统一控制器 (SimController)
**File:** `src/main/java/com/yfd/business/css/controller/SimController.java` (激活)
```java
@RestController
@RequestMapping("/sim")
public class SimController {
@Autowired private SimDataFacade simDataFacade;
@Autowired private SimBuilder simBuilder; // 如果是 Bean
@Autowired private SimService simService;
// 标准运行接口
@PostMapping("/run")
public Result<Map<String, Object>> run(@RequestBody SimulationRequest req) {
// 1. Load Data
SimDataPackage data = simDataFacade.loadSimulationData(req.getProjectId(), req.getScenarioId());
// 2. Build Model
List<SimUnit> units = simBuilder.buildUnits(data.getProject(), ...);
List<SimEvent> events = simBuilder.buildEvents(data.getEvents());
List<SimInfluenceNode> nodes = simBuilder.buildInfluenceNodes(data.getProject());
// 3. Run Engine
SimContext ctx = simService.runSimulation(units, events, nodes, req.getSteps());
// 4. Convert Result (复用 DeviceDataParser 或 InferenceConverter)
// 保持与前端/推理接口的数据格式兼容
return Result.success(SimResultConverter.toFrames(ctx));
}
}
```
---
## 3. 具体复用点清单 (ProjectServiceImpl -> SimBuilder)
为了加快开发,以下方法建议直接从 `ProjectServiceImpl` 提取到 `SimBuilder` 或工具类 `SimParserUtils` 中:
1. **`injectDeviceSize`**: 解析设备尺寸。
2. **`buildMaterialStaticFromDb`**: 补全物料静态属性。
3. **`parseDeviceStaticsAndInfluences`**: 解析设备静态值和影响关系。
4. **`parseMaterialStaticsAndInfluences`**: 解析物料静态值和影响关系。
5. **`buildValueProviders`**: 解析事件 JSON (attr_changes)。
**注意**:在提取时,需要将原本直接操作 `Map<String, Object> state` 的逻辑,改为构建 `SimUnit``SimInfluenceNode` 对象。
---
## 4. 兼容性与迁移
* **API 兼容**:新接口 `/sim/run` 的返回结构应尽量与原 `/projects/simulation/run` 中的 `frames` 结构保持一致,以便前端无缝切换。
* **分步上线**
1. 先上线 `/sim/run` 供测试使用。
2. 验证无误后,将前端调用切到新接口。
3. 废弃 `ProjectController` 中的相关接口。