modelRT/database/query_topologic.go

170 lines
5.0 KiB
Go

// Package database define database operation functions
package database
import (
"context"
"fmt"
"time"
"modelRT/constant"
"modelRT/diagram"
"modelRT/orm"
"modelRT/sql"
"github.com/gofrs/uuid"
"go.uber.org/zap"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
// QueryTopologic return the topologic info of the circuit diagram
func QueryTopologic(ctx context.Context, tx *gorm.DB, logger *zap.Logger) ([]orm.Topologic, error) {
var topologics []orm.Topologic
// ctx超时判断
cancelCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
result := tx.WithContext(cancelCtx).Clauses(clause.Locking{Strength: "UPDATE"}).Raw(sql.RecursiveSQL, constant.SpecialUUIDStr).Scan(&topologics)
if result.Error != nil {
logger.Error("query circuit diagram topologic info by start node uuid failed", zap.String("start_node_uuid", constant.SpecialUUIDStr), zap.Error(result.Error))
return nil, result.Error
}
return topologics, nil
}
// TODO 电流互感器不单独划分间隔
// TODO 以母线、浇筑母线、变压器为间隔原件
// QueryTopologicFromDB return the result of query topologic info from DB
func QueryTopologicFromDB(ctx context.Context, tx *gorm.DB, logger *zap.Logger, componentTypeMap map[uuid.UUID]int) error {
topologicInfos, err := QueryTopologic(ctx, tx, logger)
if err != nil {
logger.Error("query topologic info failed", zap.Error(err))
return err
}
// err = InitCircuitDiagramTopologic(topologicInfos, componentTypeMap)
// if err != nil {
// logger.Error("init topologic failed", zap.Error(err))
// return err
// }
_, err = BuildMultiBranchTree(topologicInfos, componentTypeMap)
if err != nil {
logger.Error("init topologic failed", zap.Error(err))
return err
}
return nil
}
// InitCircuitDiagramTopologic return circuit diagram topologic info from postgres
func InitCircuitDiagramTopologic(topologicNodes []orm.Topologic, componentTypeMap map[uuid.UUID]int) error {
var rootVertex *diagram.MultiBranchTreeNode
for _, node := range topologicNodes {
if node.UUIDFrom == constant.SpecialUUID {
// rootVertex = node.UUIDTo
var componentType int
componentType, ok := componentTypeMap[node.UUIDFrom]
if !ok {
return fmt.Errorf("can not get component type by uuid: %s", node.UUIDFrom)
}
rootVertex = diagram.NewMultiBranchTree(node.UUIDFrom, componentType)
break
}
}
if rootVertex == nil {
return fmt.Errorf("root vertex is nil")
}
for _, node := range topologicNodes {
if node.UUIDFrom == constant.SpecialUUID {
var componentType int
componentType, ok := componentTypeMap[node.UUIDTo]
if !ok {
return fmt.Errorf("can not get component type by uuid: %s", node.UUIDTo)
}
nodeVertex := diagram.NewMultiBranchTree(node.UUIDTo, componentType)
rootVertex.AddChild(nodeVertex)
}
}
node := rootVertex
for _, nodeVertex := range node.Children {
nextVertexs := make([]*diagram.MultiBranchTreeNode, 0)
nextVertexs = append(nextVertexs, nodeVertex)
}
return nil
}
func IntervalBoundaryDetermine(uuid uuid.UUID) bool {
// TODO 从diagramsOverview中根据 uuid 获取 component 信息
var componentID int64
diagram.GetComponentMap(componentID)
// TODO 判断 component 的类型是否为间隔
return true
}
// BuildMultiBranchTree return the multi branch tree by topologic info and component type map
func BuildMultiBranchTree(topologics []orm.Topologic, componentTypeMap map[uuid.UUID]int) (*diagram.MultiBranchTreeNode, error) {
nodeMap := make(map[uuid.UUID]*diagram.MultiBranchTreeNode, len(topologics))
for _, topo := range topologics {
// skip special uuid
if topo.UUIDFrom != constant.SpecialUUID {
if _, exists := nodeMap[topo.UUIDFrom]; !exists {
componentType, ok := componentTypeMap[topo.UUIDFrom]
if !ok {
return nil, fmt.Errorf("can not get component type by uuid: %s", topo.UUIDFrom)
}
nodeMap[topo.UUIDFrom] = &diagram.MultiBranchTreeNode{
ID: topo.UUIDFrom,
NodeComponentType: componentType,
}
}
}
if _, exists := nodeMap[topo.UUIDTo]; !exists {
componentType, ok := componentTypeMap[topo.UUIDTo]
if !ok {
return nil, fmt.Errorf("can not get component type by uuid: %s", topo.UUIDTo)
}
nodeMap[topo.UUIDTo] = &diagram.MultiBranchTreeNode{
ID: topo.UUIDTo,
NodeComponentType: componentType,
}
}
}
for _, topo := range topologics {
var parent *diagram.MultiBranchTreeNode
if topo.UUIDFrom == constant.SpecialUUID {
componentType, ok := componentTypeMap[topo.UUIDTo]
if !ok {
return nil, fmt.Errorf("can not get component type by uuid: %s", topo.UUIDTo)
}
parent = &diagram.MultiBranchTreeNode{
ID: constant.SpecialUUID,
NodeComponentType: componentType,
}
nodeMap[constant.SpecialUUID] = parent
} else {
parent = nodeMap[topo.UUIDFrom]
}
child := nodeMap[topo.UUIDTo]
child.Parent = parent
parent.Children = append(parent.Children, child)
}
// return root vertex
root, exists := nodeMap[constant.SpecialUUID]
if !exists {
return nil, fmt.Errorf("root node not found")
}
return root, nil
}