package com.zt.life.modules.mainPart.taskReliability.service;
|
|
import cn.hutool.core.convert.Convert;
|
import cn.hutool.json.JSONArray;
|
import cn.hutool.json.JSONObject;
|
import com.zt.common.service.BaseService;
|
import com.zt.common.utils.JsonUtils2;
|
import com.zt.common.utils.UUIDUtil;
|
import com.zt.life.modules.mainPart.basicInfo.dao.ParamDataDao;
|
import com.zt.life.modules.mainPart.basicInfo.dao.XhProductModelDao;
|
import com.zt.life.modules.mainPart.basicInfo.model.ProductImg;
|
import com.zt.life.modules.mainPart.taskReliability.dao.*;
|
import com.zt.life.modules.mainPart.taskReliability.dto.ModelLinePairDto;
|
import com.zt.life.modules.mainPart.taskReliability.model.*;
|
import org.apache.commons.lang3.StringUtils;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import com.zt.common.db.query.QueryFilter;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
|
/**
|
* model_line
|
*
|
* @author zt generator
|
* @since 1.0.0 2024-02-28
|
*/
|
@Service
|
public class ModelLineService extends BaseService<ModelLineDao, ModelLine> {
|
private static final Logger logger = LoggerFactory.getLogger(ModelLineService.class);
|
|
// 运算
|
public static final String OPE_TYPE_SERIES = "series";
|
public static final String OPE_TYPE_PARALLEL = "parallel";
|
public static final String OPE_TYPE_SWITCH = "switch";
|
public static final String OPE_TYPE_VOTE = "vote";
|
public static final String OPE_TYPE_BRIDGE = "bridge";
|
|
// 节点
|
/* 自动布局:start与end的大小 */
|
public static final int LAYOUT_START_END_SIZE_X = 60;
|
public static final int LAYOUT_START_END_SIZE_Y = 40;
|
/* 自动布局:虚框的大小 */
|
public static final int LAYOUT_DASHED_BOX_SIZE_X = 60;
|
public static final int LAYOUT_DASHED_BOX_SIZE_Y = 40;
|
/* 自动布局:逻辑运算符的大小 */
|
public static final int LAYOUT_OPE_NODE_SIZE_X = 50;
|
public static final int LAYOUT_OPE_NODE_SIZE_Y = 50;
|
/* 自动布局:设备节点的大小 */
|
public static final int LAYOUT_DEVICE_NODE_SIZE_X = 60;
|
public static final int LAYOUT_DEVICE_NODE_SIZE_Y = 60;
|
/* 自动布局:connect的大小 */
|
public static final int LAYOUT_CONNECT_SIZE_X = 10;
|
public static final int LAYOUT_CONNECT_SIZE_Y = 10;
|
|
// 单元格(存放节点)
|
/* 自动布局:单元格大小 */
|
public static final int LAYOUT_CELL_SIZE_X = 120;
|
public static final int LAYOUT_CELL_SIZE_Y = 120;
|
/* 自动布局:节点占据单元格数量 */
|
public static final int LAYOUT_CELL_NUM_NODE_X = 1;
|
public static final int LAYOUT_CELL_NUM_NODE_Y = 1;
|
public static final int LAYOUT_CELL_NUM_CONNECT_X = 1;
|
public static final int LAYOUT_CELL_NUM_CONNECT_Y = 1;
|
|
@Autowired
|
private ModelLineDao modelLineDao;
|
@Autowired
|
private ModelNodeDao modelNodeDao;
|
@Autowired
|
private ModelRbdDao modelRbdDao;
|
@Autowired
|
private AlgorithmDao algorithmDao;
|
@Autowired
|
private ModelNodeAlgorithmDao modelNodeAlgorithmDao;
|
@Autowired
|
private XhProductModelDao xhProductModelDao;
|
@Autowired
|
private ParamDataDao paramDataDao;
|
|
/**
|
* 分页查询
|
*
|
* @param queryFilter
|
* @return
|
*/
|
public List<ModelLine> page(QueryFilter queryFilter) {
|
return baseDao.getList(queryFilter.getQueryParams());
|
}
|
|
public ModelRbd getDiagram(Long modelId) {
|
return modelRbdDao.getDiagram(modelId);
|
}
|
|
/**
|
* 删除
|
*
|
* @param ids
|
*/
|
public void delete(Long[] ids) {
|
super.deleteLogic(ids);
|
}
|
|
@Transactional(rollbackFor = Exception.class)
|
public void insert(ModelRbd modelRbd) {
|
if (modelRbd == null) return;
|
if (modelRbd.getId() == null) return;
|
Long modelId = modelRbd.getId();
|
|
// 删除既有数据
|
modelRbdDao.deleteByModelId(modelId);
|
|
// 插入数据
|
modelRbd.setId(UUIDUtil.generateId());
|
modelRbdDao.insert(modelRbd);
|
}
|
|
|
@Transactional(rollbackFor = Exception.class)
|
public void update(ModelRbd modelRbd) {
|
if (modelRbd == null) return;
|
if (modelRbd.getId() == null) return;
|
Long modelId = modelRbd.getId();
|
|
// 删除既有数据
|
modelRbdDao.deleteByModelId(modelId);
|
|
modelRbdDao.insert(modelRbd);
|
}
|
|
// 自动排版RBD
|
@Transactional(rollbackFor = Exception.class)
|
public boolean layout(ModelRbd modelRbd) {
|
boolean result = true;
|
if (modelRbd == null) return result;
|
Long modelId = modelRbd.getId();
|
result = layoutRbd(modelRbd);
|
return result;
|
}
|
|
@Transactional(rollbackFor = Exception.class)
|
public boolean analyze(ModelRbd modelRbd) {
|
boolean result = true;
|
if (modelRbd == null) return result;
|
Long modelId = modelRbd.getId();
|
result = analyzeRbd(modelRbd, true);
|
return result;
|
}
|
|
private boolean layoutRbd(ModelRbd modelRbd) {
|
boolean result = true;
|
String rbdsonStr = modelRbd.getContent();
|
|
JSONArray rbdJsonArray = new JSONObject(rbdsonStr).getJSONArray("cells");
|
if (rbdJsonArray == null) return result;
|
|
// 解析结果存放list
|
List<ModelNode> modelNodeList = new ArrayList<>();
|
List<ModelLine> modelLineList = new ArrayList<>();
|
List<Algorithm> algorithmList = new ArrayList<>();
|
List<ProductImg> productImgList = new ArrayList<>(); // 暂不使用(而使用数据库中的可靠性参数)
|
|
// 1. 解析出节点与边
|
getNodeAndLineFromRbd(modelRbd.getId(), rbdJsonArray, modelNodeList, modelLineList, productImgList);
|
// 2. 转换为树型结构
|
RbdTreeNode root = recognizeRbd(modelNodeList, modelLineList);
|
// 3. 递归计算RBD的布局空间大小
|
|
// 4. 递归计算RBD的布局空间参数(x、y坐标)
|
|
// 5. 保存自动布局模型
|
JSONObject jsonObject = new JSONObject();
|
jsonObject.put("cells", rbdJsonArray);
|
modelRbd.setContent(jsonObject.toString());
|
modelRbdDao.updateById(modelRbd);
|
|
return result;
|
/*
|
// 3. 复制产品节点(node)到list
|
List<ModelNode> modelNodeAndVnodeList = modelNodeList.stream().filter(item ->
|
"node".equals(item.getNodeType())).collect(Collectors.toList());
|
// 4. 不断将基本模型(串联、并联、旁联、表决、桥联)替换为虚节点而简化图形,直至无法简化为止。
|
// result = getAlgorithmFromRbd(modelRbd, modelNodeList, modelLineList, algorithmList, modelNodeAndVnodeList);
|
|
// 6. 递归计算RBD的布局空间大小
|
calcLayoutSize(modelRbd, algorithmList, modelNodeAndVnodeList);
|
Collections.reverse(algorithmList);
|
RbdTreeNode root2 = listToTree(algorithmList.get(0).getComputerList(), algorithmList, modelNodeAndVnodeList);
|
|
RbdTreeNode root = new RbdTreeNode();
|
|
root.setId(Convert.toLong("20000"));
|
|
root.setName("end");
|
root.setNodeType("vnode");
|
root.setAlgorithmType("parallel");
|
root.setPicId("20000");
|
root.setPairStartNodeId("10000");
|
|
root.setBlockWidthNum(root2.getBlockWidthNum() + 2);
|
root.setBlockHeightNum(root2.getBlockHeightNum());
|
root.getChildren().add(root2);
|
|
// 7. 递归计算RBD的布局空间参数(x、y坐标)
|
root.setBlockX(0);
|
root.setBlockY(0);
|
|
Map<String, RbdTreeNode> nodeMap = new HashMap<>();
|
calcPosition(rbdJsonArray, root, nodeMap);
|
setEdgeRouter(rbdJsonArray, nodeMap);
|
|
JSONObject jsonObject = new JSONObject();
|
jsonObject.put("cells", rbdJsonArray);
|
modelRbd.setContent(jsonObject.toString());
|
// calcLayoutPosition(modelRbd, algorithmList, modelNodeAndVnodeList);
|
|
// 8. 保存自动布局模型
|
// 更新RBD数据
|
// modelRbd.setAutoLayoutContent("测试文字");
|
// modelRbdDao.updateById(modelRbd);
|
*/
|
}
|
|
private void getNodeAndLineFromRbd(Long modelId,
|
JSONArray rbdJsonArray,
|
List<ModelNode> modelNodeList,
|
List<ModelLine> modelLineList,
|
List<ProductImg> productImgList) {
|
Object jsonValue = null;
|
for (int i = 0; i < rbdJsonArray.size(); i++) {
|
JSONObject jsonObject = rbdJsonArray.getJSONObject(i);
|
String shape = jsonObject.get("shape").toString();
|
if ("edge".equals(shape)) {
|
ModelLine modelLine = new ModelLine();
|
modelLine.setId(UUIDUtil.generateId());
|
modelLine.setModelId(modelId);
|
modelLine.setPicId(jsonObject.get("id").toString());
|
modelLine.setBeginCell(JsonUtils2.getJsonValueByPath(jsonObject, "source/cell".split("/")).toString());
|
modelLine.setEndCell(JsonUtils2.getJsonValueByPath(jsonObject, "target/cell".split("/")).toString());
|
modelLineList.add(modelLine);
|
} else if ("image".equals(shape)) {
|
ModelNode modelNode = new ModelNode();
|
modelNode.setId(UUIDUtil.generateId());
|
modelNode.setModelId(modelId);
|
modelNode.setPicId(jsonObject.get("id").toString());
|
modelNode.setNodeType(JsonUtils2.getJsonValueByPath(jsonObject, "data/nodeType".split("/")).toString());
|
modelNode.setPositionX(Double.valueOf(JsonUtils2.getJsonValueByPath(jsonObject, "position/x".split("/")).toString()));
|
modelNode.setPositionY(Double.valueOf(JsonUtils2.getJsonValueByPath(jsonObject, "position/y".split("/")).toString()));
|
modelNode.setWidth(new Double(JsonUtils2.getJsonValueByPath(jsonObject, "size/width".split("/")).toString()));
|
modelNode.setHeight(new Double(JsonUtils2.getJsonValueByPath(jsonObject, "size/height".split("/")).toString()));
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/voteNum".split("/"));
|
if (jsonValue != null && StringUtils.isNotBlank(jsonValue.toString())) {
|
modelNode.setVoteNum(Integer.valueOf(jsonValue.toString()));
|
}
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/startNodeId".split("/"));
|
if (jsonValue != null && StringUtils.isNotBlank(jsonValue.toString())) {
|
modelNode.setPairStartNodeId(jsonValue.toString());
|
}
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/endNodeId".split("/"));
|
if (jsonValue != null && StringUtils.isNotBlank(jsonValue.toString())) {
|
modelNode.setPairEndNodeId(jsonValue.toString());
|
}
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/edgeTopId".split("/"));
|
if (jsonValue != null && StringUtils.isNotBlank(jsonValue.toString())) {
|
modelNode.setBridgeEdgeTopId(jsonValue.toString());
|
}
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/edgeBottomId".split("/"));
|
if (jsonValue != null && StringUtils.isNotBlank(jsonValue.toString())) {
|
modelNode.setBridgeEdgeBottomId(jsonValue.toString());
|
}
|
if ("dashedBox".equals(modelNode.getNodeType())) {
|
modelNode.setNodeType("node");
|
} else if ("node".equals(modelNode.getNodeType())) {
|
ProductImg productImg = new ProductImg();
|
String dataId = JsonUtils2.getJsonValueByPath(jsonObject, "data/dataId".split("/")).toString();
|
modelNode.setDataId(Long.valueOf(dataId));
|
modelNode.setNodeTypeExt(JsonUtils2.getJsonValueByPath(jsonObject, "data/nodeTypeExt".split("/")).toString());
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "attrs/text/text".split("/"));
|
modelNode.setName(jsonValue == null ? "" : jsonValue.toString());
|
|
productImg.setDataId(dataId);
|
String productType = JsonUtils2.getJsonValueByPath(jsonObject, "data/productType".split("/")).toString();
|
productImg.setProductType(productType);
|
if ("product_sb".equals(productType)) {
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/reliabDistribType".split("/"));
|
if (jsonValue != null && StringUtils.isNotBlank(jsonValue.toString())) {
|
productImg.setReliabDistribType(Integer.valueOf(jsonValue.toString()));
|
if (3 == productImg.getReliabDistribType()) {
|
// 二项分布
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/simulatTimes".split("/"));
|
if (jsonValue != null && StringUtils.isNotBlank(jsonValue.toString())) {
|
productImg.setBinomialTotalNum(Integer.valueOf(jsonValue.toString()));
|
modelNode.setBinomialTotalNum(Integer.valueOf(jsonValue.toString()));
|
}
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/successTimes".split("/"));
|
if (jsonValue != null && StringUtils.isNotBlank(jsonValue.toString())) {
|
productImg.setBinomialSuccessNum(Integer.valueOf(jsonValue.toString()));
|
modelNode.setBinomialSuccessNum(Integer.valueOf(jsonValue.toString()));
|
}
|
}
|
}
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/taskMtbcf".split("/"));
|
if (null != jsonValue) productImg.setTaskMtbcf(jsonValue.toString());
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/taskMtbcfOtherParams2".split("/"));
|
if (null != jsonValue) productImg.setTaskMtbcfOtherParams2(jsonValue.toString());
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/taskMtbcfOtherParams3".split("/"));
|
if (null != jsonValue) productImg.setTaskMtbcfOtherParams3(jsonValue.toString());
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/isRepair".split("/"));
|
if (jsonValue != null && StringUtils.isNotBlank(jsonValue.toString()) && !"null".equals(jsonValue.toString())) {
|
productImg.setIsRepair(Integer.valueOf(jsonValue.toString()));
|
} else {
|
productImg.setIsRepair(0);
|
}
|
if (1 == productImg.getIsRepair()) {
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/repairDistribType".split("/"));
|
if (jsonValue != null && StringUtils.isNotBlank(jsonValue.toString())) {
|
productImg.setRepairDistribType(Integer.valueOf(jsonValue.toString()));
|
}
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/repairMttcr".split("/"));
|
if (null != jsonValue) productImg.setRepairMttcr(jsonValue.toString());
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/repairMttcrOtherParams2".split("/"));
|
if (null != jsonValue) productImg.setRepairMttcrOtherParams2(jsonValue.toString());
|
jsonValue = JsonUtils2.getJsonValueByPath(jsonObject, "data/repairMttcrOtherParams3".split("/"));
|
if (null != jsonValue) productImg.setRepairMttcrOtherParams3(jsonValue.toString());
|
}
|
}
|
productImgList.add(productImg);
|
}
|
modelNodeList.add(modelNode);
|
}
|
}
|
}
|
|
private void saveModel(ModelRbd modelRbd,
|
List<Algorithm> algoList,
|
List<ModelNode> modelNodeAndVnodeList) {
|
// 删除既有数据
|
algorithmDao.deleteByModelId(modelRbd.getId());
|
modelNodeAlgorithmDao.deleteByModelId(modelRbd.getId());
|
|
// 插入数据
|
for (Algorithm algorithm : algoList) {
|
algorithmDao.insert(algorithm);
|
}
|
for (ModelNode modelNode : modelNodeAndVnodeList) {
|
modelNodeAlgorithmDao.insert(ModelNodeAlgorithm.from(modelNode));
|
}
|
|
// 更新RBD数据
|
modelRbd.setPublishedContent(modelRbd.getContent());
|
modelRbdDao.updateById(modelRbd);
|
}
|
|
private RbdTreeNode recognizeRbd(List<ModelNode> modelNodeList,
|
List<ModelLine> modelLineList) {
|
Map<String, Integer> vnodeCounter = new HashMap<>();
|
vnodeCounter.put("vnodeCounter", 0);
|
RbdTreeNode root = new RbdTreeNode();
|
root.setAlgorithmType("series");
|
root.setId(UUIDUtil.generateId());
|
int counter = vnodeCounter.get("vnodeCounter");
|
root.setName("v" + counter);
|
counter++;
|
vnodeCounter.put("vnodeCounter", counter);
|
root.setNodeType("vnode");
|
|
ModelNode end = modelNodeList.stream().filter(item ->
|
"end".equals(item.getNodeType())).collect(Collectors.toList()).get(0);
|
RbdTreeNode endNode = new RbdTreeNode();
|
endNode.setId(end.getId());
|
endNode.setName("end");
|
endNode.setNodeType("end");
|
endNode.setPicId(end.getPicId());
|
endNode.setPairStartNodeId(end.getPairStartNodeId());
|
endNode.setMyWidth(end.getWidth());
|
endNode.setMyHeight(end.getHeight());
|
root.getChildren().add(endNode);
|
ModelLine lineRight = modelLineList.stream().filter(item ->
|
item.getEndCell().equals(end.getPicId())).collect(Collectors.toList()).get(0);
|
recognizeOneBranch(root,
|
lineRight,
|
null,
|
modelNodeList,
|
modelLineList,
|
vnodeCounter);
|
|
return root;
|
}
|
|
private void recognizeOneBranch(RbdTreeNode parent,
|
ModelLine lineRight, // 串联的起始线(右边)
|
ModelLine lineLeft, // 串联的结束线(左边)
|
List<ModelNode> modelNodeList,
|
List<ModelLine> modelLineList,
|
Map<String, Integer> vnodeCounter) {
|
ModelLine inLine = lineRight;
|
for (;;) {
|
ModelLine searchLine = inLine;
|
ModelNode node = modelNodeList.stream().filter(item ->
|
searchLine.getBeginCell().equals(item.getPicId())).collect(Collectors.toList()).get(0);
|
if ("node".equals(node.getNodeType())) {
|
RbdTreeNode treeNode = new RbdTreeNode();
|
treeNode.setId(node.getId());
|
treeNode.setName(node.getName());
|
treeNode.setNodeType(node.getNodeType());
|
treeNode.setPicId(node.getPicId());
|
treeNode.setDataId(node.getDataId());
|
treeNode.setMyWidth(node.getWidth());
|
treeNode.setMyHeight(node.getHeight());
|
parent.getChildren().add(treeNode);
|
inLine = modelLineList.stream().filter(item ->
|
item.getEndCell().equals(node.getPicId())).collect(Collectors.toList()).get(0);
|
} else if ("start".equals(node.getNodeType())) {
|
RbdTreeNode treeNode = new RbdTreeNode();
|
treeNode.setId(node.getId());
|
treeNode.setName(node.getNodeType());
|
treeNode.setNodeType(node.getNodeType());
|
treeNode.setPicId(node.getPicId());
|
treeNode.setMyWidth(node.getWidth());
|
treeNode.setMyHeight(node.getHeight());
|
parent.getChildren().add(treeNode);
|
break;
|
} else if ("connect".equals(node.getNodeType())) {
|
break;
|
} else if ("parallel,vote,switch,bridge".contains(node.getNodeType())) {
|
RbdTreeNode subNode = new RbdTreeNode();
|
subNode.setAlgorithmType("series");
|
subNode.setId(UUIDUtil.generateId());
|
int counter = vnodeCounter.get("vnodeCounter");
|
subNode.setName("v" + counter);
|
counter++;
|
vnodeCounter.put("vnodeCounter", counter);
|
subNode.setNodeType("vnode");
|
parent.getChildren().add(subNode);
|
ModelNode connect = modelNodeList.stream().filter(item ->
|
node.getPairStartNodeId().equals(item.getPicId())).collect(Collectors.toList()).get(0);
|
RbdTreeNode treeNode = new RbdTreeNode();
|
treeNode.setId(connect.getId());
|
treeNode.setName(connect.getNodeType());
|
treeNode.setNodeType(connect.getNodeType());
|
treeNode.setPicId(connect.getPicId());
|
treeNode.setMyWidth(connect.getWidth());
|
treeNode.setMyHeight(connect.getHeight());
|
subNode.getChildren().add(treeNode);
|
RbdTreeNode subNodeOpe = new RbdTreeNode();
|
subNodeOpe.setAlgorithmType(node.getNodeType());
|
subNodeOpe.setId(UUIDUtil.generateId());
|
counter = vnodeCounter.get("vnodeCounter");
|
subNodeOpe.setName("v" + counter);
|
counter++;
|
vnodeCounter.put("vnodeCounter", counter);
|
subNodeOpe.setNodeType("vnode");
|
subNodeOpe.setVoteNum(node.getVoteNum());
|
subNode.getChildren().add(subNodeOpe);
|
treeNode = new RbdTreeNode();
|
treeNode.setId(node.getId());
|
treeNode.setName(node.getNodeType());
|
treeNode.setNodeType(node.getNodeType());
|
treeNode.setPicId(node.getPicId());
|
treeNode.setPairStartNodeId(node.getPairStartNodeId());
|
treeNode.setMyWidth(node.getWidth());
|
treeNode.setMyHeight(node.getHeight());
|
subNode.getChildren().add(treeNode);
|
recognizeOpeBlock(subNodeOpe,
|
node,
|
modelNodeList,
|
modelLineList,
|
vnodeCounter);
|
inLine = modelLineList.stream().filter(item ->
|
item.getEndCell().equals(connect.getPicId())).collect(Collectors.toList()).get(0);
|
}
|
|
if (null != lineLeft) {
|
if (inLine.getPicId().equals(lineLeft.getPicId())) break;
|
}
|
}
|
if ("series".equals(parent.getAlgorithmType())) Collections.reverse(parent.getChildren());
|
}
|
|
private void recognizeOpeBlock(RbdTreeNode parent,
|
ModelNode rightNode, // rbd中的右节点(包括end及4种运算符)
|
List<ModelNode> modelNodeList,
|
List<ModelLine> modelLineList,
|
Map<String, Integer> vnodeCounter) {
|
if ("parallel,vote,switch".contains(parent.getAlgorithmType())) {
|
ModelNode searchNode = rightNode;
|
List<ModelLine> lines = modelLineList.stream().filter(item ->
|
item.getEndCell().equals(searchNode.getPicId())).collect(Collectors.toList());
|
List<ModelLine> sortedLines = sortLine(lines, modelNodeList);
|
for (ModelLine line : sortedLines) {
|
boolean isSeries = isSeriesBranch(rightNode, line, modelNodeList, modelLineList);
|
if (isSeries) {
|
RbdTreeNode subNode = new RbdTreeNode();
|
subNode.setAlgorithmType("series");
|
subNode.setId(UUIDUtil.generateId());
|
int counter = vnodeCounter.get("vnodeCounter");
|
subNode.setName("v" + counter);
|
counter++;
|
vnodeCounter.put("vnodeCounter", counter);
|
subNode.setNodeType("vnode");
|
parent.getChildren().add(subNode);
|
recognizeOneBranch(subNode, line, null, modelNodeList, modelLineList, vnodeCounter);
|
} else {
|
recognizeOneBranch(parent, line,null, modelNodeList, modelLineList, vnodeCounter);
|
}
|
}
|
} else if ("bridge".contains(parent.getAlgorithmType())) {
|
ModelNode searchNode = rightNode;
|
List<ModelLine> linesRight = modelLineList.stream().filter(item ->
|
item.getEndCell().equals(searchNode.getPicId())).collect(Collectors.toList());
|
List<ModelLine> sortedLinesRight = sortLine(linesRight, modelNodeList);
|
List<ModelLine> linesLeft = modelLineList.stream().filter(item ->
|
item.getBeginCell().equals(searchNode.getPairStartNodeId())).collect(Collectors.toList());
|
List<ModelLine> sortedLinesLeft = sortLine(linesLeft, modelNodeList);
|
ModelLine lineTop = modelLineList.stream().filter(item ->
|
item.getPicId().equals(searchNode.getBridgeEdgeTopId())).collect(Collectors.toList()).get(0);
|
ModelLine lineBottom = modelLineList.stream().filter(item ->
|
item.getPicId().equals(searchNode.getBridgeEdgeBottomId())).collect(Collectors.toList()).get(0);
|
ModelLine verticalLineUpper = modelLineList.stream().filter(item ->
|
item.getBeginCell().equals(searchNode.getBridgeEdgeTopId())).collect(Collectors.toList()).get(0);
|
ModelLine verticalLineLower = modelLineList.stream().filter(item ->
|
item.getEndCell().equals(searchNode.getBridgeEdgeBottomId())).collect(Collectors.toList()).get(0);
|
// 桥联的第1个支路
|
if (isSeriesBranch(lineTop, sortedLinesLeft.get(0), modelNodeList, modelLineList)) {
|
RbdTreeNode subNode = new RbdTreeNode();
|
subNode.setAlgorithmType("series");
|
subNode.setId(UUIDUtil.generateId());
|
int counter = vnodeCounter.get("vnodeCounter");
|
subNode.setName("v" + counter);
|
counter++;
|
vnodeCounter.put("vnodeCounter", counter);
|
subNode.setNodeType("vnode");
|
parent.getChildren().add(subNode);
|
recognizeOneBranch(subNode, lineTop, sortedLinesLeft.get(0), modelNodeList, modelLineList, vnodeCounter);
|
} else {
|
recognizeOneBranch(parent, lineTop, sortedLinesLeft.get(0), modelNodeList, modelLineList, vnodeCounter);
|
}
|
// 桥联的第2个支路
|
if (isSeriesBranch(sortedLinesRight.get(0), lineTop, modelNodeList, modelLineList)) {
|
RbdTreeNode subNode = new RbdTreeNode();
|
subNode.setAlgorithmType("series");
|
subNode.setId(UUIDUtil.generateId());
|
int counter = vnodeCounter.get("vnodeCounter");
|
subNode.setName("v" + counter);
|
counter++;
|
vnodeCounter.put("vnodeCounter", counter);
|
subNode.setNodeType("vnode");
|
parent.getChildren().add(subNode);
|
recognizeOneBranch(subNode, sortedLinesRight.get(0), lineTop, modelNodeList, modelLineList, vnodeCounter);
|
} else {
|
recognizeOneBranch(parent, sortedLinesRight.get(0), lineTop, modelNodeList, modelLineList, vnodeCounter);
|
}
|
// 桥联的第3个支路
|
if (isSeriesBranch(verticalLineLower, verticalLineUpper, modelNodeList, modelLineList)) {
|
RbdTreeNode subNode = new RbdTreeNode();
|
subNode.setAlgorithmType("series");
|
subNode.setId(UUIDUtil.generateId());
|
int counter = vnodeCounter.get("vnodeCounter");
|
subNode.setName("v" + counter);
|
counter++;
|
vnodeCounter.put("vnodeCounter", counter);
|
subNode.setNodeType("vnode");
|
parent.getChildren().add(subNode);
|
recognizeOneBranch(subNode, verticalLineLower, verticalLineUpper, modelNodeList, modelLineList, vnodeCounter);
|
} else {
|
recognizeOneBranch(parent, verticalLineLower, verticalLineUpper, modelNodeList, modelLineList, vnodeCounter);
|
}
|
// 桥联的第4个支路
|
if (isSeriesBranch(lineBottom, sortedLinesLeft.get(1), modelNodeList, modelLineList)) {
|
RbdTreeNode subNode = new RbdTreeNode();
|
subNode.setAlgorithmType("series");
|
subNode.setId(UUIDUtil.generateId());
|
int counter = vnodeCounter.get("vnodeCounter");
|
subNode.setName("v" + counter);
|
counter++;
|
vnodeCounter.put("vnodeCounter", counter);
|
subNode.setNodeType("vnode");
|
parent.getChildren().add(subNode);
|
recognizeOneBranch(subNode, lineBottom, sortedLinesLeft.get(1), modelNodeList, modelLineList, vnodeCounter);
|
} else {
|
recognizeOneBranch(parent, lineBottom, sortedLinesLeft.get(1), modelNodeList, modelLineList, vnodeCounter);
|
}
|
// 桥联的第5个支路
|
if (isSeriesBranch(sortedLinesRight.get(1), lineBottom, modelNodeList, modelLineList)) {
|
RbdTreeNode subNode = new RbdTreeNode();
|
subNode.setAlgorithmType("series");
|
subNode.setId(UUIDUtil.generateId());
|
int counter = vnodeCounter.get("vnodeCounter");
|
subNode.setName("v" + counter);
|
counter++;
|
vnodeCounter.put("vnodeCounter", counter);
|
subNode.setNodeType("vnode");
|
parent.getChildren().add(subNode);
|
recognizeOneBranch(subNode, sortedLinesRight.get(1), lineBottom, modelNodeList, modelLineList, vnodeCounter);
|
} else {
|
recognizeOneBranch(parent, sortedLinesRight.get(1), lineBottom, modelNodeList, modelLineList, vnodeCounter);
|
}
|
}
|
}
|
|
/**
|
* 按自上而下的顺序排序
|
*/
|
private List<ModelLine> sortLine(List<ModelLine> lines,
|
List<ModelNode> modelNodeList) {
|
for (ModelLine line : lines) {
|
ModelNode node = modelNodeList.stream().filter(item ->
|
line.getBeginCell().equals(item.getPicId())).collect(Collectors.toList()).get(0);
|
line.setBeginY(node.getPositionY());
|
}
|
lines.sort(Comparator.comparing(ModelLine::getBeginY));
|
|
return lines;
|
}
|
|
private boolean isSeriesBranch(ModelNode rightNode, // rbd中的右节点(包括end及4种运算符)
|
ModelLine line, // 右节点的入口线
|
List<ModelNode> modelNodeList,
|
List<ModelLine> modelLineList) {
|
boolean result = false;
|
ModelNode node = modelNodeList.stream().filter(item ->
|
line.getBeginCell().equals(item.getPicId())).collect(Collectors.toList()).get(0);
|
if ("node".equals(node.getNodeType())) {
|
ModelLine line1 = modelLineList.stream().filter(item ->
|
item.getEndCell().equals(node.getPicId())).collect(Collectors.toList()).get(0);
|
ModelNode node1 = modelNodeList.stream().filter(item ->
|
line1.getBeginCell().equals(item.getPicId())).collect(Collectors.toList()).get(0);
|
result = !node1.getPicId().equals(rightNode.getPairStartNodeId());
|
} else {
|
ModelNode node2 = modelNodeList.stream().filter(item ->
|
node.getPairStartNodeId().equals(item.getPicId())).collect(Collectors.toList()).get(0);
|
ModelLine line2 = modelLineList.stream().filter(item ->
|
item.getEndCell().equals(node2.getPicId())).collect(Collectors.toList()).get(0);
|
ModelNode node3 = modelNodeList.stream().filter(item ->
|
line2.getBeginCell().equals(item.getPicId())).collect(Collectors.toList()).get(0);
|
result = !node3.getPicId().equals(rightNode.getPairStartNodeId());
|
}
|
|
return result;
|
}
|
|
private boolean isSeriesBranch(ModelLine lineRight, // 串联的起始线(右边)
|
ModelLine lineLeft, // 串联的结束线(左边)
|
List<ModelNode> modelNodeList,
|
List<ModelLine> modelLineList) {
|
boolean result = false;
|
ModelNode node = modelNodeList.stream().filter(item ->
|
lineRight.getBeginCell().equals(item.getPicId())).collect(Collectors.toList()).get(0);
|
if ("node".equals(node.getNodeType())) {
|
ModelLine line1 = modelLineList.stream().filter(item ->
|
item.getEndCell().equals(node.getPicId())).collect(Collectors.toList()).get(0);
|
result = !line1.getPicId().equals(lineLeft.getPicId());
|
} else {
|
ModelNode node1 = modelNodeList.stream().filter(item ->
|
node.getPairStartNodeId().equals(item.getPicId())).collect(Collectors.toList()).get(0);
|
ModelLine line2 = modelLineList.stream().filter(item ->
|
item.getEndCell().equals(node1.getPicId())).collect(Collectors.toList()).get(0);
|
result = !line2.getPicId().equals(lineLeft.getPicId());
|
}
|
|
return result;
|
}
|
|
private boolean analyzeRbd(ModelRbd modelRbd, boolean saveFlag) {
|
boolean result = true;
|
String rbdsonStr = modelRbd.getContent();
|
|
JSONArray rbdJsonArray = new JSONObject(rbdsonStr).getJSONArray("cells");
|
if (rbdJsonArray == null) return result;
|
|
// 解析结果存放list
|
List<ModelNode> modelNodeList = new ArrayList<>();
|
List<ModelLine> modelLineList = new ArrayList<>();
|
List<Algorithm> algorithmList = new ArrayList<>();
|
List<ProductImg> productImgList = new ArrayList<>(); // 暂不使用(而使用数据库中的可靠性参数)
|
List<ModelNode> modelNodeAndVnodeList = new ArrayList<>();
|
|
// 1. 解析出节点与边
|
getNodeAndLineFromRbd(modelRbd.getId(), rbdJsonArray, modelNodeList, modelLineList, productImgList);
|
// 2. 转换为树型结构
|
RbdTreeNode root = recognizeRbd(modelNodeList, modelLineList);
|
// 3. 预处理
|
deleteSeriesForAutoArrange(root);
|
deleteStartEnd(root);
|
// 3. 生成算法
|
createAlgorithm(modelRbd.getId(), root, algorithmList, modelNodeAndVnodeList);
|
// 4. 保存模型
|
if (saveFlag) saveModel(modelRbd, algorithmList, modelNodeAndVnodeList);
|
|
return result;
|
}
|
|
private void createAlgorithm(Long modelId,
|
RbdTreeNode root,
|
List<Algorithm> algorithmList,
|
List<ModelNode> modelNodeAndVnodeList) {
|
List<RbdTreeNode> children = root.getChildren();
|
if (children.size() == 0) {
|
ModelNode node = new ModelNode();
|
node.setModelId(modelId);
|
node.setId(root.getId());
|
node.setPicId(root.getPicId());
|
node.setDataId(root.getDataId());
|
node.setNodeType(root.getNodeType());
|
node.setName(root.getName());
|
node.setVoteNum(root.getVoteNum());
|
modelNodeAndVnodeList.add(node);
|
} else {
|
Algorithm algo = new Algorithm();
|
algo.setModelId(modelId);
|
algo.setId(root.getId());
|
algo.setComputerId(algo.getId());
|
algo.setAlgorithmType(root.getAlgorithmType());
|
algo.setModelType(algo.getAlgorithmType());
|
algo.setStep(Integer.valueOf(root.getName().substring(1)));
|
algo.setVoteNum(root.getVoteNum());
|
algo.setObjectList(root.getChildren().stream().map(item ->
|
item.getName()).collect(Collectors.joining(",")));
|
algo.setComputerList(root.getChildren().stream().map(item ->
|
item.getId().toString()).collect(Collectors.joining(",")));
|
algorithmList.add(algo);
|
ModelNode node = new ModelNode();
|
node.setModelId(modelId);
|
node.setId(root.getId());
|
node.setPicId(root.getPicId());
|
node.setDataId(root.getDataId());
|
node.setNodeType(root.getNodeType());
|
node.setName(root.getName());
|
node.setVoteNum(root.getVoteNum());
|
modelNodeAndVnodeList.add(node);
|
for (RbdTreeNode treeNode : root.getChildren()) {
|
createAlgorithm(modelId, treeNode, algorithmList, modelNodeAndVnodeList);
|
}
|
}
|
}
|
|
/**
|
* 对树形结构进行预处理,包括:
|
* 1)将root的algorithmType替换为end,并去掉start和end节点
|
* 2)start与end间只有1个逻辑运算块,则去掉最外层的series
|
* @param root
|
*/
|
private void deleteStartEnd(RbdTreeNode root) {
|
root.setAlgorithmType("end");
|
List<RbdTreeNode> children = root.getChildren();
|
children.remove(children.size()-1);
|
children.remove(0);
|
if (children.size()>1 ||
|
!"vnode".equals(children.get(0).getNodeType())) {
|
RbdTreeNode subNode = new RbdTreeNode();
|
subNode.setAlgorithmType("series");
|
subNode.setId(UUIDUtil.generateId());
|
subNode.setName("v0");
|
subNode.setNodeType("vnode");
|
subNode.getChildren().addAll(children);
|
List<RbdTreeNode> list = new ArrayList<>();
|
list.add(subNode);
|
root.setChildren(list);
|
}
|
}
|
|
/**
|
* 对树形结构进行预处理:
|
* 去掉逻辑运算块中用于排版的外层series
|
* @param root
|
*/
|
private void deleteSeriesForAutoArrange(RbdTreeNode root) {
|
List<RbdTreeNode> children = root.getChildren();
|
for (int i = 0; i < children.size(); i++) {
|
RbdTreeNode treeNode = children.get(i);
|
if ("vnode".equals(treeNode.getNodeType()) &&
|
"series".equals(treeNode.getAlgorithmType()) &&
|
"connect".equals(treeNode.getChildren().get(0).getNodeType())) {
|
children.set(i, treeNode.getChildren().get(1));
|
}
|
deleteSeriesForAutoArrange(children.get(i));
|
}
|
}
|
|
private void setEdgeRouter(JSONArray rbdJsonArray, Map<String, RbdTreeNode> nodeMap) {
|
for (int i = 0; i < rbdJsonArray.size(); i++
|
) {
|
JSONObject jsonObject = rbdJsonArray.getJSONObject(i);
|
if (jsonObject.get("shape").equals("edge")) {
|
String sourceId = JsonUtils2.getJsonValueByPath(jsonObject, "source/cell".split("/")).toString();
|
String targetId = JsonUtils2.getJsonValueByPath(jsonObject, "target/cell".split("/")).toString();
|
RbdTreeNode sourceNode = nodeMap.get(sourceId);
|
RbdTreeNode targetNode = nodeMap.get(targetId);
|
if (sourceNode != null) {
|
if ("connect".equals(sourceNode.getNodeType()) && !"10000".equals(sourceId)){
|
if (sourceNode.getY()+sourceNode.getMyHeight()/2 == targetNode.getY()+targetNode.getMyHeight()/2){
|
JsonUtils2.setJsonValueByPath(jsonObject, "router/args/startDirections".split("/"),"right".split(","));
|
JsonUtils2.setJsonValueByPath(jsonObject, "router/args/endDirections".split("/"),"left".split(","));
|
}else{
|
JsonUtils2.setJsonValueByPath(jsonObject, "router/args/startDirections".split("/"),"top,bottom".split(","));
|
JsonUtils2.setJsonValueByPath(jsonObject, "router/args/endDirections".split("/"),"left".split(","));
|
}
|
}
|
}
|
if (targetNode != null) {
|
if ("parallel,vote".contains(targetNode.getNodeType())){
|
if (sourceNode.getY()+sourceNode.getMyHeight()/2 == targetNode.getY()+targetNode.getMyHeight()/2){
|
JsonUtils2.setJsonValueByPath(jsonObject, "router/args/startDirections".split("/"),"right".split(""));
|
JsonUtils2.setJsonValueByPath(jsonObject, "router/args/endDirections".split("/"),"left".split(""));
|
}else{
|
JsonUtils2.setJsonValueByPath(jsonObject, "router/args/startDirections".split("/"),"right".split(""));
|
JsonUtils2.setJsonValueByPath(jsonObject, "router/args/endDirections".split("/"),"top,bottom".split(""));
|
}
|
}
|
}
|
}
|
}
|
}
|
|
private void setNodePositionXY(JSONArray rbdJsonArray, RbdTreeNode block, Map<String, RbdTreeNode> nodeMap) {
|
Double x = block.getBlockX() + (block.getBlockWidth() - block.getMyWidth()) / 2;
|
Double y = block.getBlockY() + (block.getBlockHeight() - block.getMyHeight()) / 2;
|
block.setX(x);
|
block.setY(y);
|
nodeMap.put(block.getPicId(),block);
|
setRbdNodePosition(rbdJsonArray, block.getPicId(), x, y);
|
}
|
|
private void calcPosition(JSONArray rbdJsonArray, RbdTreeNode block, Map<String, RbdTreeNode> nodeMap) {
|
if (block.getNodeType().equals("node")) {
|
setNodePositionXY(rbdJsonArray, block,nodeMap);
|
} else {
|
double blockWidth = block.getBlockWidthNum() * LAYOUT_CELL_SIZE_X;
|
double blockHeight = block.getBlockHeightNum() * LAYOUT_CELL_SIZE_Y;
|
|
Double descentWidth = block.getDescentWidth();
|
if (descentWidth == null || descentWidth == 0.0) {
|
descentWidth = blockWidth;
|
}
|
Double descentHeight = block.getDescentHeight();
|
if (descentHeight == null || descentHeight == 0.0) {
|
descentHeight = blockHeight;
|
}
|
|
block.setBlockWidth(blockWidth);
|
block.setBlockHeight(blockHeight);
|
List<RbdTreeNode> children = block.getChildren();
|
|
if (OPE_TYPE_SERIES.equals(block.getAlgorithmType())) {
|
Double subBlockX = block.getBlockX();
|
for (RbdTreeNode child : children) {
|
|
child.setDescentWidth(blockWidth);
|
child.setDescentHeight(blockHeight);
|
|
double selfWidth = child.getBlockWidthNum() * LAYOUT_CELL_SIZE_X * descentWidth / blockWidth;
|
child.setBlockWidth(selfWidth);
|
child.setBlockHeight(blockHeight);
|
|
child.setBlockY(block.getBlockY());
|
child.setBlockX(subBlockX);
|
calcPosition(rbdJsonArray, child, nodeMap);
|
subBlockX = subBlockX + selfWidth;
|
|
}
|
} else {
|
|
Double subBlockY = block.getBlockY() + (descentHeight - blockHeight) / 2;
|
Double firstSubBlockY = subBlockY;
|
|
// 设置connect的位置
|
RbdTreeNode connectBlock = new RbdTreeNode();
|
connectBlock.setMyWidth(getRbdNodeInfo(rbdJsonArray, block.getPairStartNodeId(), "size/width"));
|
connectBlock.setMyHeight(getRbdNodeInfo(rbdJsonArray, block.getPairStartNodeId(), "size/height"));
|
connectBlock.setNodeType("connect");
|
connectBlock.setPicId(block.getPairStartNodeId());
|
connectBlock.setBlockX(block.getBlockX());
|
connectBlock.setBlockY(firstSubBlockY);
|
connectBlock.setBlockWidth(LAYOUT_CELL_SIZE_X);
|
connectBlock.setBlockHeight(blockHeight);
|
setNodePositionXY(rbdJsonArray, connectBlock, nodeMap);
|
|
for (RbdTreeNode child : children) {
|
child.setDescentWidth(block.getBlockWidth() - 2 * LAYOUT_CELL_SIZE_X);
|
child.setDescentHeight(blockHeight);
|
|
child.setBlockWidth(block.getBlockWidth() - 2 * LAYOUT_CELL_SIZE_X);
|
child.setBlockHeight(child.getBlockHeightNum() * LAYOUT_CELL_SIZE_Y);
|
|
child.setBlockX(block.getBlockX() + LAYOUT_CELL_SIZE_X);
|
child.setBlockY(subBlockY);
|
subBlockY = subBlockY + child.getBlockHeightNum() * LAYOUT_CELL_SIZE_Y;
|
calcPosition(rbdJsonArray, child, nodeMap);
|
}
|
|
// 设置运算符的位置
|
RbdTreeNode opeBlock = new RbdTreeNode();
|
|
opeBlock.setPicId(block.getPicId());
|
opeBlock.setNodeType("parallel");
|
opeBlock.setMyWidth(getRbdNodeInfo(rbdJsonArray, block.getPicId(), "size/width"));
|
opeBlock.setMyHeight(getRbdNodeInfo(rbdJsonArray, block.getPicId(), "size/height"));
|
opeBlock.setBlockX(block.getBlockX() + blockWidth - LAYOUT_CELL_SIZE_X);
|
opeBlock.setBlockY(firstSubBlockY);
|
opeBlock.setBlockWidth(LAYOUT_CELL_SIZE_X);
|
opeBlock.setBlockHeight(blockHeight);
|
setNodePositionXY(rbdJsonArray, opeBlock, nodeMap);
|
}
|
}
|
|
}
|
|
private RbdTreeNode listToTree(String id,
|
List<Algorithm> algorithmList,
|
List<ModelNode> modelNodeAndVnodeList) {
|
|
List<Algorithm> algos = algorithmList.stream().filter(item ->
|
id.equals(item.getId().toString())).collect(Collectors.toList());
|
|
RbdTreeNode subNode = new RbdTreeNode();
|
subNode.setId(Convert.toLong(id));
|
ModelNode nd = modelNodeAndVnodeList.stream().filter(item ->
|
id.equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
subNode.setName(nd.getName());
|
subNode.setNodeType(nd.getNodeType());
|
subNode.setPicId(nd.getPicId());
|
|
if (!"vnode".equals(nd.getNodeType())) {
|
subNode.setMyWidth(nd.getWidth());
|
subNode.setMyHeight(nd.getHeight());
|
}
|
subNode.setBlockWidthNum(nd.getVnodeCellNumX());
|
subNode.setBlockHeightNum(nd.getVnodeCellNumY());
|
subNode.setPairStartNodeId(nd.getPairStartNodeId());
|
subNode.setPairEndNodeId(nd.getPairEndNodeId());
|
if (algos.size() > 0) {
|
Algorithm algo = algos.get(0);
|
subNode.setAlgorithmType(algo.getAlgorithmType());
|
String str = algo.getComputerList();
|
String[] ids = str.split(",");
|
for (String subId : ids) {
|
subNode.getChildren().add(listToTree(subId, algorithmList, modelNodeAndVnodeList));
|
}
|
}
|
return subNode;
|
}
|
|
/*
|
*/
|
|
/**
|
* 根据顶层RBD的位置(x,y),自顶向下递归计算各个节点的位置(x,y)
|
*
|
* @param modelRbd
|
* @param algorithmList
|
* @param modelNodeAndVnodeList
|
*//*
|
|
private void calcLayoutPosition(ModelRbd modelRbd,
|
List<Algorithm> algorithmList,
|
List<ModelNode> modelNodeAndVnodeList) {
|
String rbdsonStr = modelRbd.getContent();
|
JSONArray rbdJsonArray = new JSONObject(rbdsonStr).getJSONArray("cells");
|
Algorithm endAlgo = algorithmList.stream().filter(item ->
|
"end".equals(item.getAlgorithmType())).collect(Collectors.toList()).get(0);
|
ModelNode topNode = modelNodeAndVnodeList.stream().filter(item ->
|
endAlgo.getComputerList().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
Algorithm topAlgo = algorithmList.stream().filter(item ->
|
endAlgo.getComputerList().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
// 将topNode的坐标定为Cell(0,0),反算所有节点的坐标
|
// 1. 计算节点的Cell位置
|
calcNodeLayoutPositionCell(rbdJsonArray, algorithmList, modelNodeAndVnodeList, topNode, topAlgo, 0, 0,
|
topNode.getVnodeCellNumX(), topNode.getVnodeCellNumY());
|
// 2. 计算节点的x,y坐标位置
|
calcNodeLayoutPosition(rbdJsonArray, algorithmList, modelNodeAndVnodeList, topNode, topAlgo);
|
// 3. 设置start的位置
|
double distance = 200.0;
|
double y = (topNode.getPositionCellY() + topNode.getVnodeCellNumY() / 2) * LAYOUT_CELL_SIZE_Y + (LAYOUT_CELL_SIZE_Y - LAYOUT_START_END_SIZE_Y) / 2;
|
setRbdNodePosition(rbdJsonArray, "10000", 0 - distance, y);
|
// 4. 设置end的位置
|
double x = topNode.getVnodeCellNumX() * LAYOUT_CELL_SIZE_X + distance - LAYOUT_START_END_SIZE_X;
|
setRbdNodePosition(rbdJsonArray, "20000", x, y);
|
JSONObject jsonObject = new JSONObject();
|
jsonObject.put("cells", rbdJsonArray);
|
modelRbd.setContent(jsonObject.toString());
|
}
|
*/
|
|
/*
|
// 递归函数(计算各节点的x,y坐标位置)
|
private void calcNodeLayoutPosition(JSONArray rbdJsonArray,
|
List<Algorithm> algorithmList,
|
List<ModelNode> modelNodeAndVnodeList,
|
ModelNode node,
|
Algorithm algo) {
|
// 未使用设备的实际宽、高
|
double x;
|
double y;
|
if ("node".equals(node.getNodeType())) {
|
x = node.getPositionCellX() * LAYOUT_CELL_SIZE_X + (LAYOUT_CELL_SIZE_X - LAYOUT_DEVICE_NODE_SIZE_X) / 2;
|
y = node.getPositionCellY() * LAYOUT_CELL_SIZE_Y + (LAYOUT_CELL_SIZE_Y - LAYOUT_DEVICE_NODE_SIZE_Y) / 2;
|
node.setPositionX(x);
|
node.setPositionY(y);
|
setRbdNodePosition(rbdJsonArray, node.getPicId(), node.getPositionX(), node.getPositionY());
|
} else if ("vnode".equals(node.getNodeType())) {
|
String[] computerNodeListStr = algo.getComputerList().split(",");
|
switch (algo.getAlgorithmType()) {
|
case OPE_TYPE_SERIES:
|
case OPE_TYPE_PARALLEL:
|
case OPE_TYPE_SWITCH:
|
case OPE_TYPE_VOTE:
|
for (String nodeStr : computerNodeListStr) {
|
ModelNode childNode = modelNodeAndVnodeList.stream().filter(item ->
|
nodeStr.equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
List<Algorithm> childAlgos = algorithmList.stream().filter(item ->
|
childNode.getId().equals(item.getId())).collect(Collectors.toList());
|
Algorithm childAlgo = childAlgos.size() > 0 ? childAlgos.get(0) : null;
|
calcNodeLayoutPosition(rbdJsonArray,
|
algorithmList,
|
modelNodeAndVnodeList,
|
childNode,
|
childAlgo);
|
}
|
if (OPE_TYPE_PARALLEL.equals(algo.getAlgorithmType())
|
|| OPE_TYPE_SWITCH.equals(algo.getAlgorithmType())
|
|| OPE_TYPE_VOTE.equals(algo.getAlgorithmType())) {
|
// 设置connect的位置
|
x = node.getPositionCellX() * LAYOUT_CELL_SIZE_X + (LAYOUT_CELL_SIZE_X - LAYOUT_CONNECT_SIZE_X) / 2;
|
y = (node.getPositionCellY() + node.getVnodeCellNumY() / 2) * LAYOUT_CELL_SIZE_Y + (LAYOUT_CELL_SIZE_Y - LAYOUT_CONNECT_SIZE_Y) / 2;
|
setRbdNodePosition(rbdJsonArray, node.getPairStartNodeId(), x, y);
|
// 设置运算符的位置
|
x = (node.getPositionCellX() + node.getVnodeCellNumX() - 1) * LAYOUT_CELL_SIZE_X + (LAYOUT_CELL_SIZE_X - LAYOUT_OPE_NODE_SIZE_X) / 2;
|
y = (node.getPositionCellY() + node.getVnodeCellNumY() / 2) * LAYOUT_CELL_SIZE_Y + (LAYOUT_CELL_SIZE_Y - LAYOUT_OPE_NODE_SIZE_Y) / 2;
|
setRbdNodePosition(rbdJsonArray, node.getPicId(), x, y);
|
}
|
break;
|
case OPE_TYPE_BRIDGE:
|
break;
|
default:
|
break;
|
}
|
}
|
}
|
|
// 递归函数(计算各节点的Cell位置,以左上角为Cell位置0,0)
|
private void calcNodeLayoutPositionCell(JSONArray rbdJsonArray,
|
List<Algorithm> algorithmList,
|
List<ModelNode> modelNodeAndVnodeList,
|
ModelNode node,
|
Algorithm algo,
|
double originCellX,
|
double originCellY,
|
double maxX,
|
double maxY) {
|
if ("node".equals(node.getNodeType())) {
|
//设置node(设备节点)Cell位置
|
double width = LAYOUT_DEVICE_NODE_SIZE_X * maxX;
|
double hight = LAYOUT_DEVICE_NODE_SIZE_Y * maxY;
|
double x = originCellX + (width - LAYOUT_DEVICE_NODE_SIZE_X) / 2;
|
double y = originCellY + (hight - LAYOUT_DEVICE_NODE_SIZE_Y) / 2;
|
node.setPositionCellX(x);
|
node.setPositionCellY(y);
|
} else if ("vnode".equals(node.getNodeType())) {
|
String[] computerNodeListStr = algo.getComputerList().split(",");
|
switch (algo.getAlgorithmType()) {
|
case OPE_TYPE_SERIES:
|
case OPE_TYPE_PARALLEL:
|
case OPE_TYPE_SWITCH:
|
case OPE_TYPE_VOTE:
|
double preNodeCellX = 0.0;
|
double preNodeCellY = 0.0;
|
for (String nodeStr : computerNodeListStr) {
|
ModelNode childNode = modelNodeAndVnodeList.stream().filter(item ->
|
nodeStr.equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
List<Algorithm> childAlgos = algorithmList.stream().filter(item ->
|
childNode.getId().equals(item.getId())).collect(Collectors.toList());
|
Algorithm childAlgo = childAlgos.size() > 0 ? childAlgos.get(0) : null;
|
if (OPE_TYPE_SERIES.equals(algo.getAlgorithmType())) {
|
calcNodeLayoutPositionCell(rbdJsonArray,
|
algorithmList,
|
modelNodeAndVnodeList,
|
childNode,
|
childAlgo,
|
originCellX + preNodeCellX,
|
originCellY, node.getVnodeCellNumX(), node.getVnodeCellNumY()
|
);
|
preNodeCellX += childNode.getVnodeCellNumX();
|
} else {
|
calcNodeLayoutPositionCell(rbdJsonArray,
|
algorithmList,
|
modelNodeAndVnodeList,
|
childNode,
|
childAlgo,
|
originCellX + 1,
|
originCellY + preNodeCellY, node.getVnodeCellNumX(), node.getVnodeCellNumY());
|
preNodeCellY += childNode.getVnodeCellNumY();
|
}
|
}
|
*/
|
/*
|
// 设置运算符的Cell位置
|
if (OPE_TYPE_SERIES.equals(algo.getAlgorithmType())) {
|
node.setPositionCellX(originCellX);
|
} else {
|
node.setPositionCellX(originCellX + node.getVnodeCellNumX() - 1);
|
}
|
node.setPositionCellY(originCellY + node.getVnodeCellNumY()/2);
|
*//*
|
|
// 需节点代表整个逻辑单元,因此其坐标为originCellX和originCellX
|
node.setPositionCellX(originCellX);
|
node.setPositionCellY(originCellX);
|
break;
|
case OPE_TYPE_BRIDGE:
|
*/
|
/*
|
ModelNode node1 = modelNodeAndVnodeList.stream().filter(item ->
|
computerNodeListStr[0].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
ModelNode node2 = modelNodeAndVnodeList.stream().filter(item ->
|
computerNodeListStr[1].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
ModelNode node3 = modelNodeAndVnodeList.stream().filter(item ->
|
computerNodeListStr[2].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
ModelNode node4 = modelNodeAndVnodeList.stream().filter(item ->
|
computerNodeListStr[3].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
ModelNode node5 = modelNodeAndVnodeList.stream().filter(item ->
|
computerNodeListStr[4].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
Algorithm algo1 = algorithmList.stream().filter(item ->
|
node1.getId().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
Algorithm algo2 = algorithmList.stream().filter(item ->
|
node2.getId().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
Algorithm algo3 = algorithmList.stream().filter(item ->
|
node3.getId().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
Algorithm algo4 = algorithmList.stream().filter(item ->
|
node4.getId().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
Algorithm algo5 = algorithmList.stream().filter(item ->
|
node5.getId().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
// 1,计算三行的总高度
|
// 1.1 计算第一行两个节点的高度
|
int firstRowCellNumY = Math.max(node1.getVnodeCellNumY(), node2.getVnodeCellNumY());
|
// 1.2 计算第二行桥联节点的高度
|
int secondRowCellNumY = node3.getVnodeCellNumY();
|
// 1.3 计算第三行两个节点的高度
|
int thirdRowCellNumY = Math.max(node4.getVnodeCellNumY(), node5.getVnodeCellNumY());
|
// int totalCellNumY = firstRowCellNumY + secondRowCellNumY + thirdRowCellNumY;
|
// 2. 计算三行各节点的坐标
|
// 2.1 计算第一行两个节点的坐标
|
calcNodeLayoutPositionCell(rbdJsonArray,
|
algorithmList,
|
modelNodeAndVnodeList,
|
node1,
|
algo1,
|
originCellX + 1,
|
originCellY);
|
calcNodeLayoutPositionCell(rbdJsonArray,
|
algorithmList,
|
modelNodeAndVnodeList,
|
node2,
|
algo2,
|
originCellX + 1 + node1.getPositionCellX(),
|
originCellY);
|
// 2.2 计算第二行桥联节点的坐标
|
calcNodeLayoutPositionCell(rbdJsonArray,
|
algorithmList,
|
modelNodeAndVnodeList,
|
node3,
|
algo3,
|
originCellX + 1,
|
originCellY + firstRowCellNumY);
|
// 2.3 计算第三行两个节点的坐标
|
calcNodeLayoutPositionCell(rbdJsonArray,
|
algorithmList,
|
modelNodeAndVnodeList,
|
node4,
|
algo4,
|
originCellX + 1,
|
originCellY + firstRowCellNumY + secondRowCellNumY);
|
calcNodeLayoutPositionCell(rbdJsonArray,
|
algorithmList,
|
modelNodeAndVnodeList,
|
node5,
|
algo5,
|
originCellX + 1 + node4.getPositionCellX(),
|
originCellY + firstRowCellNumY + secondRowCellNumY);
|
// 2.4 计算桥联运算符的坐标
|
node.setPositionCellX(originCellX + 1);
|
node.setPositionCellY(originCellY + node.getVnodeCellNumY()/2);
|
*//*
|
|
break;
|
default:
|
break;
|
}
|
}
|
}
|
*/
|
private void setRbdNodePosition(JSONArray rbdJsonArray,
|
String id,
|
double x,
|
double y) {
|
for (int i = 0; i < rbdJsonArray.size(); i++) {
|
JSONObject jsonObject = rbdJsonArray.getJSONObject(i);
|
if (id.equals(jsonObject.get("id").toString())) {
|
JsonUtils2.setJsonValueByPath(jsonObject, "position/x".split("/"), x);
|
JsonUtils2.setJsonValueByPath(jsonObject, "position/y".split("/"), y);
|
}
|
}
|
}
|
|
private Double getRbdNodeInfo(JSONArray rbdJsonArray,
|
String picId,
|
String path) {
|
for (int i = 0; i < rbdJsonArray.size(); i++) {
|
JSONObject jsonObject = rbdJsonArray.getJSONObject(i);
|
if (picId.equals(jsonObject.get("id").toString())) {
|
return Convert.toDouble(JsonUtils2.getJsonValueByPath(jsonObject, path.split("/")));
|
}
|
}
|
return null;
|
}
|
|
/**
|
* 自底向上递归合计出整个RBD的大小(横向及纵向所占单元格的数量)
|
*
|
* @param modelRbd
|
* @param algorithmList
|
* @param modelNodeAndVnodeList
|
*/
|
private void calcLayoutSize(
|
ModelRbd modelRbd,
|
List<Algorithm> algorithmList,
|
List<ModelNode> modelNodeAndVnodeList) {
|
Algorithm endAlgo = algorithmList.stream().filter(item ->
|
"end".equals(item.getAlgorithmType())).collect(Collectors.toList()).get(0);
|
ModelNode topNode = modelNodeAndVnodeList.stream().filter(item ->
|
endAlgo.getComputerList().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
Algorithm topAlgo = algorithmList.stream().filter(item ->
|
endAlgo.getComputerList().equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
calcNodeLayoutSize(algorithmList, modelNodeAndVnodeList, topNode, topAlgo);
|
}
|
|
// 递归函数
|
private void calcNodeLayoutSize(List<Algorithm> algorithmList,
|
List<ModelNode> modelNodeAndVnodeList,
|
ModelNode node,
|
Algorithm algo) {
|
if ("node".equals(node.getNodeType())) {
|
//设置node(设备节点)布局信息
|
// node.setWidth(LAYOUT_DEVICE_NODE_SIZE_X);
|
// node.setHeight(LAYOUT_DEVICE_NODE_SIZE_Y);
|
node.setCellNumX(LAYOUT_CELL_NUM_NODE_X);
|
node.setCellNumY(LAYOUT_CELL_NUM_NODE_Y);
|
node.setVnodeCellNumX(node.getCellNumX());
|
node.setVnodeCellNumY(node.getCellNumY());
|
} else if ("vnode".equals(node.getNodeType())) {
|
// 1. 设置vnode(运算节点)布局信息(其实串联没有运算符,不需要设置,但是设置了也没有坏处,所以不作区分)
|
// node.setWidth(LAYOUT_OPE_NODE_SIZE_X);
|
// node.setHeight(LAYOUT_OPE_NODE_SIZE_Y);
|
node.setCellNumX(LAYOUT_CELL_NUM_NODE_X);
|
node.setCellNumY(LAYOUT_CELL_NUM_NODE_Y);
|
|
// 2. 设置虚节点布局信息
|
// 2.1 设置虚节点内各运算对象的布局信息
|
String[] computerNodeListStr = algo.getComputerList().split(",");
|
for (String nodeStr : computerNodeListStr) {
|
ModelNode childNode = modelNodeAndVnodeList.stream().filter(item ->
|
nodeStr.equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
List<Algorithm> childAlgos = algorithmList.stream().filter(item ->
|
childNode.getId().equals(item.getId())).collect(Collectors.toList());
|
Algorithm childAlgo = childAlgos.size() > 0 ? childAlgos.get(0) : null;
|
calcNodeLayoutSize(algorithmList,
|
modelNodeAndVnodeList,
|
childNode,
|
childAlgo);
|
}
|
// 2.2 设置虚节点总的布局信息到运算节点中
|
setVnodeLayoutNum(computerNodeListStr, modelNodeAndVnodeList, node, algo);
|
}
|
}
|
|
private void setVnodeLayoutNum(String[] computerNodeListStr,
|
List<ModelNode> modelNodeAndVnodeList,
|
ModelNode vnode,
|
Algorithm algo) {
|
int numX = 0;
|
int numY = 0;
|
// 1. 计算串、并、旁联、表决
|
for (String nodeStr : computerNodeListStr) {
|
ModelNode childNode = modelNodeAndVnodeList.stream().filter(item ->
|
nodeStr.equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
switch (algo.getAlgorithmType()) {
|
case OPE_TYPE_SERIES:
|
numX += childNode.getVnodeCellNumX();
|
numY = childNode.getVnodeCellNumY() > numY ? childNode.getVnodeCellNumY() : numY;
|
break;
|
case OPE_TYPE_PARALLEL:
|
case OPE_TYPE_SWITCH:
|
case OPE_TYPE_VOTE:
|
numX = childNode.getVnodeCellNumX() > numX ? childNode.getVnodeCellNumX() : numX;
|
numY += childNode.getVnodeCellNumY();
|
break;
|
default:
|
break;
|
}
|
}
|
if (OPE_TYPE_PARALLEL.equals(algo.getAlgorithmType())
|
|| OPE_TYPE_SWITCH.equals(algo.getAlgorithmType())
|
|| OPE_TYPE_VOTE.equals(algo.getAlgorithmType())) {
|
// 加上connect的大小
|
numX += LAYOUT_CELL_NUM_CONNECT_X;
|
numX += vnode.getCellNumX();
|
}
|
// 2. 计算桥联
|
if (OPE_TYPE_BRIDGE.equals(algo.getAlgorithmType())) {
|
// 桥联支路算一行,整个桥联共3行
|
// 2.1 计算第一行
|
ModelNode node1 = modelNodeAndVnodeList.stream().filter(item ->
|
computerNodeListStr[0].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
ModelNode node2 = modelNodeAndVnodeList.stream().filter(item ->
|
computerNodeListStr[1].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
ModelNode node3 = modelNodeAndVnodeList.stream().filter(item ->
|
computerNodeListStr[2].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
ModelNode node4 = modelNodeAndVnodeList.stream().filter(item ->
|
computerNodeListStr[3].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
ModelNode node5 = modelNodeAndVnodeList.stream().filter(item ->
|
computerNodeListStr[4].equals(item.getId().toString())).collect(Collectors.toList()).get(0);
|
int numX1 = node1.getCellNumX() + node2.getCellNumX();
|
int numY1 = node1.getCellNumY() > node2.getCellNumY() ? node1.getCellNumY() : node2.getCellNumY();
|
// 2.2 计算第二行(桥联支路,横向画图)
|
int numX2 = node3.getCellNumX();
|
int numY2 = node3.getCellNumY();
|
// 2.3 计算第三行
|
int numX3 = node4.getCellNumX() + node5.getCellNumX();
|
int numY3 = node4.getCellNumY() > node5.getCellNumY() ? node4.getCellNumY() : node5.getCellNumY();
|
numX = Math.max(Math.max(numX1, numX2), numX3);
|
numY = numY1 + numY2 + numY3;
|
// 2.4 加上connect的大小
|
numX += LAYOUT_CELL_NUM_CONNECT_X;
|
numX += vnode.getCellNumX();
|
}
|
vnode.setVnodeCellNumX(numX);
|
vnode.setVnodeCellNumY(numY);
|
}
|
}
|