wireplanner/internal/services/connection.go

221 lines
4.8 KiB
Go

package services
import (
"fmt"
"lostcavewireplanner/internal/db"
"lostcavewireplanner/internal/models"
)
type Segment struct {
DeviceID int64
DeviceName string
ModelName string
PortID int64
PortName string
Side string
}
type TraceResult struct {
FarSegments []Segment
ConnectionID int64
ConnectionType string
Color string
Label1 string
Label2 string
ClickedPortID int64
ClickedPortName string
ClickedDeviceID int64
ClickedDeviceName string
ClickedModelName string
ClickedSide string
NearSegments []Segment
HasConnection bool
}
func TraceConnection(store *db.Store, clickedPortID int64) (*TraceResult, error) {
clickedPort, err := store.PortGetByID(clickedPortID)
if err != nil {
return nil, err
}
if clickedPort == nil {
return nil, fmt.Errorf("port not found")
}
clickedDevice, err := store.DeviceGetByID(clickedPort.DeviceID)
if err != nil {
return nil, err
}
result := &TraceResult{
ClickedPortID: clickedPort.ID,
ClickedPortName: clickedPort.Name,
ClickedDeviceID: clickedDevice.ID,
ClickedDeviceName: clickedDevice.Name,
ClickedSide: clickedPort.Side,
}
if clickedDevice.Model != nil {
result.ClickedModelName = clickedDevice.Model.Name
}
conn, err := store.ConnectionGetByPortID(clickedPortID)
if err != nil {
return nil, err
}
if conn == nil {
return result, nil
}
result.HasConnection = true
result.ConnectionID = conn.ID
result.Color = conn.Color
if conn.Label1 != nil {
result.Label1 = *conn.Label1
}
if conn.Label2 != nil {
result.Label2 = *conn.Label2
}
if conn.ConnectionType != nil {
result.ConnectionType = conn.ConnectionType.Name
}
var remotePort *models.DevicePort
if conn.PortID1 != nil && *conn.PortID1 == clickedPortID {
if conn.PortID2 != nil {
remotePort, _ = store.PortGetByID(*conn.PortID2)
}
} else if conn.PortID2 != nil && *conn.PortID2 == clickedPortID {
if conn.PortID1 != nil {
remotePort, _ = store.PortGetByID(*conn.PortID1)
}
}
if remotePort != nil {
result.FarSegments = traceAway(store, remotePort.ID, conn.ID)
}
result.NearSegments = traceThrough(store, clickedPortID, conn.ID)
return result, nil
}
func traceAway(store *db.Store, portID int64, excludeConnID int64) []Segment {
var segments []Segment
visitedPorts := map[int64]bool{}
currentPortID := portID
for {
if visitedPorts[currentPortID] {
break
}
visitedPorts[currentPortID] = true
port, err := store.PortGetByID(currentPortID)
if err != nil || port == nil {
break
}
device, err := store.DeviceGetByID(port.DeviceID)
if err != nil || device == nil {
break
}
modelName := ""
if device.Model != nil {
modelName = device.Model.Name
}
segments = append(segments, Segment{
DeviceID: device.ID,
DeviceName: device.Name,
ModelName: modelName,
PortID: port.ID,
PortName: port.Name,
Side: port.Side,
})
isPatch := device.Model != nil && (device.Model.IsPatchPanel || device.Model.IsWallSocket)
if !isPatch {
break
}
pairedSide := "back"
if port.Side == "back" {
pairedSide = "front"
}
pairedPort, err := store.PortGetPaired(port.DeviceID, port.Name, pairedSide)
if err != nil || pairedPort == nil {
break
}
if visitedPorts[pairedPort.ID] {
break
}
nextConn, err := store.ConnectionGetByPortIDExcluding(pairedPort.ID, excludeConnID)
if err != nil || nextConn == nil {
break
}
var nextPortID int64
if nextConn.PortID1 != nil && *nextConn.PortID1 != pairedPort.ID {
nextPortID = *nextConn.PortID1
} else if nextConn.PortID2 != nil && *nextConn.PortID2 != pairedPort.ID {
nextPortID = *nextConn.PortID2
} else {
break
}
excludeConnID = nextConn.ID
currentPortID = nextPortID
}
return segments
}
func traceThrough(store *db.Store, portID int64, excludeConnID int64) []Segment {
var segments []Segment
port, err := store.PortGetByID(portID)
if err != nil || port == nil {
return segments
}
device, err := store.DeviceGetByID(port.DeviceID)
if err != nil || device == nil {
return segments
}
isPatch := device.Model != nil && (device.Model.IsPatchPanel || device.Model.IsWallSocket)
if !isPatch {
return segments
}
pairedSide := "back"
if port.Side == "back" {
pairedSide = "front"
}
pairedPort, err := store.PortGetPaired(port.DeviceID, port.Name, pairedSide)
if err != nil || pairedPort == nil {
return segments
}
nextConn, err := store.ConnectionGetByPortIDExcluding(pairedPort.ID, excludeConnID)
if err != nil || nextConn == nil {
return segments
}
var nextPortID int64
if nextConn.PortID1 != nil && *nextConn.PortID1 != pairedPort.ID {
nextPortID = *nextConn.PortID1
} else if nextConn.PortID2 != nil && *nextConn.PortID2 != pairedPort.ID {
nextPortID = *nextConn.PortID2
} else {
return segments
}
return traceAway(store, nextPortID, nextConn.ID)
}