// 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 }