rts-sim-testing-service/ats/calculate/calculate.go

164 lines
5.5 KiB
Go
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.

package calculate
import (
"errors"
"fmt"
"math"
"strconv"
"joylink.club/bj-rtsts-server/ats/verify/simulation/wayside/face"
"joylink.club/bj-rtsts-server/ats/verify/simulation/wayside/memory"
"joylink.club/bj-rtsts-server/ats/verify/simulation/wayside/model/device"
"joylink.club/bj-rtsts-server/ats/verify/simulation/wayside/model/ref"
)
// CalculateLinkPositionAndDirection 根据起始link位置、偏移量、偏移方向计算偏移后的位置及方向。偏移方向上的剩余距离不够会返回error
func CalculateLinkPositionAndDirection(simulation *memory.VerifySimulation, linkIndex int32, linkOffset int32, up bool,
offset int32) (int32, int32, bool, error) {
vs := memory.QueryMapVerifyStructure(simulation.MapId)
direction := "下"
if up {
direction = "上"
}
var tempOffset int32
if up {
tempOffset = linkOffset + offset
linkModel := vs.LinkModelMap[linkIndex]
if tempOffset <= linkModel.Length {
return linkIndex, tempOffset, up, nil
}
if linkModel.BRelatedSwitchRef == nil {
return linkIndex, 0, up, errors.New(fmt.Sprintf("link位置[%d-%d]向[%s]偏移[%d]超出极限", linkIndex, linkOffset, direction, offset))
}
turnoutState := memory.GetTurnoutState(simulation, linkModel.ARelatedSwitchRef.SwitchDevice.GetIndex())
turnoutModel := linkModel.ARelatedSwitchRef.SwitchDevice.(*device.SwitchDeviceModel)
var linkPort *ref.DevicePort[*device.LinkModel]
if turnoutState.Normal {
switch linkModel.BRelatedSwitchRef.Port {
case face.A:
linkPort = turnoutModel.BLinkPort
case face.B:
linkPort = turnoutModel.ALinkPort
}
} else if turnoutState.Reverse {
switch linkModel.BRelatedSwitchRef.Port {
case face.A:
linkPort = turnoutModel.CLinkPort
case face.C:
linkPort = turnoutModel.ALinkPort
}
}
if linkPort != nil {
var newOffset int32
var newUp bool
i, _ := strconv.Atoi(linkPort.Device.Index)
switch linkPort.Port {
case face.A:
newOffset = 0
newUp = true
case face.B:
newOffset = linkPort.Device.Length
newUp = false
}
return CalculateLinkPositionAndDirection(simulation, int32(i), newOffset, newUp, tempOffset-linkModel.Length)
} else {
return linkIndex, 0, up, errors.New(fmt.Sprintf("link位置[%d-%d]向[%s]偏移[%d]超出极限", linkIndex, linkOffset, direction, offset))
}
} else {
tempOffset = linkOffset - offset
if tempOffset >= 0 {
return linkIndex, tempOffset, up, nil
}
linkModel := vs.LinkModelMap[linkIndex]
if linkModel.ARelatedSwitchRef == nil {
return linkIndex, 0, up, errors.New(fmt.Sprintf("link位置[%d-%d]向[%s]偏移[%d]超出极限", linkIndex, linkOffset, direction, offset))
}
turnoutState := memory.GetTurnoutState(simulation, linkModel.ARelatedSwitchRef.SwitchDevice.GetIndex())
turnoutModel := linkModel.ARelatedSwitchRef.SwitchDevice.(*device.SwitchDeviceModel)
var linkPort *ref.DevicePort[*device.LinkModel]
if turnoutState.Normal {
switch linkModel.ARelatedSwitchRef.Port {
case face.A:
linkPort = turnoutModel.BLinkPort
case face.B:
linkPort = turnoutModel.ALinkPort
}
} else if turnoutState.Reverse {
switch linkModel.ARelatedSwitchRef.Port {
case face.A:
linkPort = turnoutModel.CLinkPort
case face.C:
linkPort = turnoutModel.ALinkPort
}
}
if linkPort != nil {
var newOffset int32
var newUp bool
i, _ := strconv.Atoi(linkPort.Device.Index)
switch linkPort.Port {
case face.A:
newOffset = 0
newUp = true
case face.B:
newOffset = linkPort.Device.Length
newUp = false
}
return CalculateLinkPositionAndDirection(simulation, int32(i), newOffset, newUp, int32(math.Abs(float64(tempOffset))))
} else {
return linkIndex, 0, up, errors.New(fmt.Sprintf("link位置[%d-%d]向[%s]偏移[%d]超出极限", linkIndex, linkOffset, direction, offset))
}
}
}
// CalculateLen 计算两个link位置的间距
// @param up 优先向这个方向查找终点
func CalculateLen(start *ref.DevicePosition[*device.LinkModel], end *ref.DevicePosition[*device.LinkModel], up bool) (int, error) {
return calculateLen(start, end, up, 0)
}
//// CalculateDirection 计算以{link}为基准的dp方向
//// @param up 优先向这个方向查找link
//func CalculateDirection(dp *ref.DevicePort[*device.LinkModel], link *device.LinkModel, up bool) *ref.DevicePort[*device.LinkModel] {
// if link == dp.Device {
// return dp
// }
//
//}
func calculateLen(start *ref.DevicePosition[*device.LinkModel], end *ref.DevicePosition[*device.LinkModel],
up bool, l int) (int, error) {
if start.Device == end.Device {
return l + int(math.Abs(float64(start.Offset-end.Offset))), nil
}
var turnoutPort *ref.SwitchRef
if up {
l += int(start.Device.Length - start.Offset)
turnoutPort = start.Device.BRelatedSwitchRef
} else {
l += int(start.Offset)
turnoutPort = start.Device.ARelatedSwitchRef
}
var lps []*ref.DevicePosition[*device.LinkModel]
if turnoutPort != nil {
turnoutModel := start.Device.BRelatedSwitchRef.SwitchDevice.(*device.SwitchDeviceModel)
device.ConvertFromDevicePort(turnoutModel.BLinkPort)
switch turnoutPort.Port {
case face.A:
lps = append(lps, device.ConvertFromDevicePort(turnoutModel.BLinkPort))
lps = append(lps, device.ConvertFromDevicePort(turnoutModel.CLinkPort))
case face.B | face.C:
lps = append(lps, device.ConvertFromDevicePort(turnoutModel.ALinkPort))
}
}
for _, lp := range lps {
i, err := calculateLen(lp, end, lp.Offset == 0, l)
if err == nil {
return i, nil
}
}
return 0, errors.New(fmt.Sprintf("从[%s]到[%s]的间距无法计算", start.String(), end.String()))
}