rts-sim-testing-service/ts/simulation/wayside/memory/wayside_memory_map.go

617 lines
20 KiB
Go
Raw Normal View History

2023-08-01 14:54:11 +08:00
package memory
import (
"fmt"
"sort"
2023-09-21 14:54:27 +08:00
"strings"
2023-08-01 14:54:11 +08:00
"sync"
2023-11-08 11:02:41 +08:00
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
2023-09-21 14:54:27 +08:00
"joylink.club/rtsssimulation/repository"
proto2 "joylink.club/rtsssimulation/repository/model/proto"
2023-09-21 14:54:27 +08:00
2023-08-01 14:54:11 +08:00
"google.golang.org/protobuf/proto"
2023-10-17 17:51:26 +08:00
"joylink.club/bj-rtsts-server/db/dbquery"
2023-08-01 14:54:11 +08:00
"joylink.club/bj-rtsts-server/db/model"
2023-08-10 14:18:55 +08:00
"joylink.club/bj-rtsts-server/dto"
2023-10-26 10:05:28 +08:00
"joylink.club/bj-rtsts-server/sys_error"
2023-10-26 17:16:07 +08:00
"joylink.club/bj-rtsts-server/ts/protos/graphicData"
2023-08-01 14:54:11 +08:00
)
var (
2023-09-22 15:15:04 +08:00
giTypeMap sync.Map
giNameMap sync.Map
2023-09-22 15:15:04 +08:00
giDataMap sync.Map
)
2023-08-01 14:54:11 +08:00
2023-08-02 15:50:46 +08:00
// 将发布的地图数据放入内存中
2023-09-21 14:54:27 +08:00
func PublishMapVerifyStructure(graphic *model.PublishedGi) {
giTypeMap.Store(graphic.ID, graphicData.PictureType(graphic.Type))
giNameMap.Store(graphic.Name, graphic.ID)
var message proto.Message
switch graphicData.PictureType(graphic.Type) {
case graphicData.PictureType_StationLayout:
message = &graphicData.RtssGraphicStorage{}
case graphicData.PictureType_RelayCabinetLayout:
message = &graphicData.RelayCabinetGraphicStorage{}
case graphicData.PictureType_Psl:
message = &graphicData.PslGraphicStorage{}
2023-10-13 15:19:17 +08:00
case graphicData.PictureType_IBP:
message = &graphicData.IBPGraphicStorage{}
}
err := proto.Unmarshal(graphic.Proto, message)
if err != nil {
2023-09-26 14:12:26 +08:00
panic(&dto.ErrorDto{Code: dto.LogicError, Message: fmt.Sprintf("[id:%d]proto数据反序列化失败:%s", graphic.ID, err)})
}
giDataMap.Store(graphic.ID, message)
2023-08-02 15:50:46 +08:00
// 初始化地图结构
2023-09-22 15:15:04 +08:00
switch graphicData.PictureType(graphic.Type) {
case graphicData.PictureType_StationLayout:
graphicStorage := message.(*graphicData.RtssGraphicStorage)
2023-09-22 15:15:04 +08:00
giUidMap.Store(graphic.ID, initStationUid(graphicStorage))
case graphicData.PictureType_RelayCabinetLayout:
graphicStorage := message.(*graphicData.RelayCabinetGraphicStorage)
giUidMap.Store(graphic.ID, initRelayCabinetUid(graphicStorage))
2023-09-21 14:54:27 +08:00
}
2023-08-01 14:54:11 +08:00
}
func GenerateElementUid(city, lineId string, stationIndexList []string, code string) string {
sort.Strings(stationIndexList)
var idArr []string
idArr = append(idArr, city, lineId)
idArr = append(idArr, stationIndexList...)
2023-09-21 14:54:27 +08:00
idArr = append(idArr, code)
return strings.Join(idArr, "_")
2023-08-01 14:54:11 +08:00
}
// 移除内存中的地图信息
func DeleteMapVerifyStructure(mapId int32) {
2023-09-26 14:12:26 +08:00
giTypeMap.Delete(mapId)
giDataMap.Delete(mapId)
giUidMap.Delete(mapId)
2023-08-01 14:54:11 +08:00
}
func QueryGiType(mapId int32) graphicData.PictureType {
2023-09-26 14:12:26 +08:00
value, ok := giTypeMap.Load(mapId)
if !ok {
2023-10-17 17:51:26 +08:00
graphic, err := dbquery.PublishedGi.Debug().Where(dbquery.PublishedGi.ID.Eq(mapId)).First() // 当缓存缺失新地图时,查询一次
if err != nil {
panic(sys_error.New(fmt.Sprintf("[mapId:%d]类型映射错误 :%v", mapId, value), err))
2023-10-17 17:51:26 +08:00
}
PublishMapVerifyStructure(graphic)
return graphicData.PictureType(graphic.Type)
2023-09-26 14:12:26 +08:00
}
return value.(graphicData.PictureType)
}
func QueryGiData[T proto.Message](mapId int32) T {
value, _ := giDataMap.Load(mapId)
return value.(T)
}
func QueryGiId(name string) int32 {
value, _ := giNameMap.Load(name)
return value.(int32)
}
func GetStorageIBPMapData(mapCode string) *graphicData.IBPGraphicStorage {
// 处理关联的IBP盘信息
if mapCode == "" {
return nil
}
ibpId, ok := giNameMap.Load(mapCode)
if !ok {
return nil
}
ibpMapData, ok := giDataMap.Load(ibpId)
if !ok {
return nil
}
return ibpMapData.(*graphicData.IBPGraphicStorage)
}
2023-11-08 11:02:41 +08:00
// 转换成统一坐标公里标
func convertRepoBaseKm(r *repository.Repository, km *proto2.Kilometer) *proto2.Kilometer {
k, err := r.ConvertKilometer(km, r.GetCoordinateInfo().Coordinate)
if err != nil {
2023-11-08 11:02:41 +08:00
panic(sys_error.New(fmt.Sprintf("公里标转换【%s->%s】错误", km.CoordinateSystem, r.GetCoordinateInfo().Coordinate)))
2023-08-10 14:18:55 +08:00
}
2023-11-08 11:02:41 +08:00
return k
2023-08-10 14:18:55 +08:00
}
2023-11-08 11:02:41 +08:00
// 根据传入link、偏移、link运行方向查找所在设备信息
// 入参仿真、linkId、link偏移量、link运行方向
// 输出linkId、设备Id、设备端口、link偏移量、设备上偏移量、偏移量对应的公里标
func CalcInitializeLink(sim *VerifySimulation, linkId string, offset int64, up bool) (
2023-11-09 17:54:31 +08:00
outLinkId, deviceId, port string, outLinkOffset, deviceOffset int64, km *proto2.Kilometer, err error) {
2023-11-08 11:02:41 +08:00
link := sim.Repo.FindLink(linkId)
2023-09-20 18:21:00 +08:00
if link == nil {
2023-11-09 17:54:31 +08:00
err = sys_error.New(fmt.Sprintf("未找到link【%s】", linkId))
2023-09-20 18:21:00 +08:00
}
2023-11-08 11:02:41 +08:00
// 获取计算link与所在偏移
2023-11-09 17:54:31 +08:00
outLinkId, outLinkOffset, err = findCalcLinkIdAndOffset(sim, link, offset)
if err != nil {
return
}
2023-11-08 11:02:41 +08:00
calcLink := sim.Repo.FindLink(outLinkId)
2023-09-27 16:49:10 +08:00
// 判断是否在道岔上
2023-11-08 11:02:41 +08:00
onTurnout, isA := isOnLinkTurnout(calcLink, outLinkOffset)
2023-09-27 16:49:10 +08:00
if onTurnout {
2023-11-08 11:02:41 +08:00
deviceId, port, deviceOffset, km = calcTurnoutOffset(sim.Repo, calcLink, isA, outLinkOffset, up)
2023-09-27 16:49:10 +08:00
} else {
2023-11-08 11:02:41 +08:00
deviceId, port, deviceOffset, km = calcSectionOffset(sim.Repo, calcLink, outLinkOffset, up)
2023-09-27 16:49:10 +08:00
}
2023-11-08 11:02:41 +08:00
// 输出当前所在设备、端口、设备偏移
return
2023-09-27 16:49:10 +08:00
}
2023-11-08 11:02:41 +08:00
// 列车是否在link的道岔上
2023-09-27 16:49:10 +08:00
func isOnLinkTurnout(link *repository.Link, offset int64) (bool, bool) {
2023-09-20 18:21:00 +08:00
aTp := link.ARelation()
2023-09-27 16:49:10 +08:00
var turnoutOffset int64
if aTp != nil {
turnoutOffset = aTp.Turnout().FindLinkPositionByPort(aTp.Port()).Offset()
}
if offset <= turnoutOffset {
return true, true
}
2023-09-20 18:21:00 +08:00
bTp := link.BRelation()
2023-09-27 16:49:10 +08:00
if bTp != nil {
turnoutOffset = bTp.Turnout().FindLinkPositionByPort(bTp.Port()).Offset()
return offset >= turnoutOffset, false
}
return false, false
}
2023-11-08 11:02:41 +08:00
// 查找最终的linkId与link偏移
// 入参仿真、link、link偏移量
// 输出linkId、link偏移量
2023-11-09 17:54:31 +08:00
func findCalcLinkIdAndOffset(sim *VerifySimulation, link *repository.Link, offset int64) (outId string, outOffset int64, err error) {
2023-11-08 11:02:41 +08:00
if 0 <= offset && offset <= link.Length() {
2023-11-09 17:54:31 +08:00
outId, outOffset, err = link.Id(), offset, nil
return
2023-11-08 11:02:41 +08:00
}
// 超出端、超出长度
tp, length := link.ARelation(), 0-offset
if offset > 0 {
tp, length = link.BRelation(), offset-link.Length()
}
if tp == nil {
2023-11-09 17:54:31 +08:00
err = sys_error.New("列车偏移超出link位置")
return
2023-11-08 11:02:41 +08:00
}
2023-11-09 17:54:31 +08:00
nextPort, er1 := getTurnoutNextPort(sim, tp.Device().Id(), tp.Port().String())
if er1 != nil {
err = er1
return
2023-11-08 11:02:41 +08:00
}
var nextLink *repository.Link
var isB bool
// 寻找匹配到的link
for _, l := range sim.Repo.LinkList() {
if l.ARelation() != nil && l.ARelation().Port() == nextPort && l.ARelation().Device().Id() == tp.Device().Id() {
nextLink = l
break
}
if l.BRelation() != nil && l.BRelation().Port() == nextPort && l.BRelation().Device().Id() == tp.Device().Id() {
nextLink = l
isB = true
break
}
}
// 没有找到连接信息,说明已经到尽头找不到位置
if nextLink == nil {
2023-11-09 17:54:31 +08:00
err = sys_error.New(fmt.Sprintf("未找到对应的link信息, linkId=%s, offset=%d", link.Id(), offset))
return
2023-11-08 11:02:41 +08:00
}
// 下个link偏移
nextOffset := length
if isB {
nextOffset = nextLink.Length() - length
}
2023-11-09 17:54:31 +08:00
outId, outOffset, err = findCalcLinkIdAndOffset(sim, nextLink, nextOffset)
return
2023-11-08 11:02:41 +08:00
}
// 根据当前link端寻找下一个link连接端端口
// 入参:仿真、道岔端口
// 输出:道岔端口
2023-11-09 17:54:31 +08:00
func getTurnoutNextPort(sim *VerifySimulation, turnoutId string, port string) (nextPort proto2.Port, err error) {
entry, ok := entity.GetEntityByUid(sim.World, turnoutId)
2023-11-08 11:02:41 +08:00
if !ok {
2023-11-09 17:54:31 +08:00
err = sys_error.New(fmt.Sprintf("道岔不存在: World id=%d,道岔id=%s", sim.World.Id(), turnoutId))
return
2023-11-08 11:02:41 +08:00
}
if !entry.HasComponent(component.TurnoutPositionType) {
2023-11-09 17:54:31 +08:00
err = sys_error.New(fmt.Sprintf("道岔没有TurnoutPosition组件: World id=%d,道岔id=%s", sim.World.Id(), turnoutId))
return
2023-11-08 11:02:41 +08:00
}
// 获取定反数据
pos := component.TurnoutPositionType.Get(entry)
switch port {
case "A":
2023-11-08 11:02:41 +08:00
if pos.Dw {
2023-11-09 17:54:31 +08:00
nextPort = proto2.Port_B
2023-11-08 11:02:41 +08:00
} else {
2023-11-09 17:54:31 +08:00
nextPort = proto2.Port_C
2023-11-08 11:02:41 +08:00
}
2023-11-09 17:54:31 +08:00
return
case "B":
2023-11-08 11:02:41 +08:00
if pos.Dw {
2023-11-09 17:54:31 +08:00
nextPort = proto2.Port_A
2023-11-08 11:02:41 +08:00
} else {
2023-11-09 17:54:31 +08:00
nextPort = proto2.Port_None
2023-11-08 11:02:41 +08:00
}
2023-11-09 17:54:31 +08:00
return
case "C":
2023-11-08 11:02:41 +08:00
if pos.Dw {
2023-11-09 17:54:31 +08:00
nextPort = proto2.Port_None
2023-11-08 11:02:41 +08:00
} else {
2023-11-09 17:54:31 +08:00
nextPort = proto2.Port_A
2023-11-08 11:02:41 +08:00
}
2023-11-09 17:54:31 +08:00
return
2023-11-08 11:02:41 +08:00
}
2023-11-09 17:54:31 +08:00
err = sys_error.New(fmt.Sprintf("非法端口:端口=%s", port))
return
2023-11-08 11:02:41 +08:00
}
// 计算link offset 在道岔上的位置
// 入参仿真Repository、link、是否从A端开始、link偏移量、link运行方向
// 输出设备Id、设备所在端口、设备偏移量、公里标信息地图主坐标系
func calcTurnoutOffset(repo *repository.Repository, link *repository.Link, isA bool, offset int64, up bool) (
deviceId, port string, deviceOffset int64, km *proto2.Kilometer) {
2023-09-27 16:49:10 +08:00
tp := link.ARelation()
if !isA {
tp = link.BRelation()
}
2023-11-08 11:02:41 +08:00
// 设备ID
2023-09-27 16:49:10 +08:00
deviceId = tp.Turnout().Id()
2023-11-08 11:02:41 +08:00
// 端口信息
port = tp.Port().String()
// 设备上的偏移量
2023-09-27 16:49:10 +08:00
if isA {
2023-11-08 11:02:41 +08:00
deviceOffset = offset
2023-09-27 16:49:10 +08:00
} else {
2023-09-20 18:21:00 +08:00
deviceOffset = link.Length() - offset
2023-09-27 16:49:10 +08:00
}
2023-11-08 11:02:41 +08:00
// 公里标计算
crossKmInfo := convertRepoBaseKm(repo, tp.Turnout().GetTurnoutKm(proto2.Port_None))
portKmInfo := convertRepoBaseKm(repo, tp.Turnout().GetTurnoutKm(tp.Port()))
km = &proto2.Kilometer{CoordinateSystem: crossKmInfo.CoordinateSystem}
if crossKmInfo.Value > portKmInfo.Value {
km.Value = crossKmInfo.Value - deviceOffset
2023-09-27 16:49:10 +08:00
} else {
2023-11-08 11:02:41 +08:00
km.Value = crossKmInfo.Value + deviceOffset
2023-09-27 16:49:10 +08:00
}
return
}
2023-11-08 11:02:41 +08:00
// 计算link offset 在区段上的位置
// 入参仿真Repository、link、link偏移量、link运行方向
// 输出设备Id、设备所在端口、设备偏移量、公里标信息地图主坐标系
func calcSectionOffset(repo *repository.Repository, link *repository.Link, offset int64, up bool) (
deviceId, port string, deviceOffset int64, km *proto2.Kilometer) {
2023-09-27 16:49:10 +08:00
var section *repository.PhysicalSection
for _, s := range link.PhysicalSections() {
ao, bo := s.ALinkPosition().Offset(), s.BLinkPosition().Offset()
2023-10-19 18:04:21 +08:00
if (ao < offset && offset <= bo) || (bo < offset && offset <= ao) {
2023-09-27 16:49:10 +08:00
section = s
break
2023-09-20 18:21:00 +08:00
}
}
2023-09-27 16:49:10 +08:00
if section == nil {
2023-11-08 11:02:41 +08:00
panic(sys_error.New(fmt.Sprintf("未找到link设备偏移【%d】", offset)))
2023-09-27 16:49:10 +08:00
}
// 元素ID
deviceId = section.Id()
// a点偏移 大于 b点偏移
2023-11-08 11:02:41 +08:00
ao, bo := section.ALinkPosition().Offset(), section.BLinkPosition().Offset()
2023-09-27 16:49:10 +08:00
if ao > bo {
deviceOffset = ao - offset
} else {
deviceOffset = offset - ao
}
// a点公里标 大于 b点公里标
2023-11-08 11:02:41 +08:00
ak, bk := convertRepoBaseKm(repo, section.AKilometer()), convertRepoBaseKm(repo, section.BKilometer())
km = &proto2.Kilometer{CoordinateSystem: ak.CoordinateSystem}
if ak.Value > bk.Value {
km.Value = ak.Value - deviceOffset
2023-09-27 16:49:10 +08:00
} else {
2023-11-08 11:02:41 +08:00
km.Value = ak.Value + deviceOffset
2023-09-27 16:49:10 +08:00
}
2023-09-20 18:21:00 +08:00
return
2023-08-11 16:48:21 +08:00
}
2023-11-08 11:02:41 +08:00
// 根据设备查找link
// 入参设备ID、端口、设备偏移
// 输出linkId、link偏移
func QueryLinkAndOffsetByDevice(repo *repository.Repository, uid, port string, offset int64) (linkId string, linkOffset int64) {
if port == "" {
linkId, linkOffset = sectionToLink(repo, uid, offset)
} else {
2023-11-08 11:02:41 +08:00
linkId, linkOffset = turnoutToLink(repo, uid, port, offset)
}
2023-11-08 11:02:41 +08:00
return
}
2023-10-19 17:42:01 +08:00
2023-11-08 11:02:41 +08:00
// 根据区段设备查找link
// 入参仿真Repository、设备ID、设备偏移
// 输出linkId、link偏移、公里标
func sectionToLink(repo *repository.Repository, uid string, offset int64) (string, int64) {
section := repo.FindPhysicalSection(uid)
if section == nil {
panic(sys_error.New(fmt.Sprintf("地图不存在uid:%s缓存", uid)))
}
2023-11-08 11:02:41 +08:00
ao, bo := section.ALinkPosition().Offset(), section.BLinkPosition().Offset()
if ao < bo {
return section.ALinkPosition().Link().Id(), ao + offset
} else {
return section.ALinkPosition().Link().Id(), ao - offset
}
}
// 根据道岔设备查找link
// 入参仿真Repository、道岔设备ID、道岔端口、设备偏移
// 输出linkId、link偏移
func turnoutToLink(repo *repository.Repository, uid, port string, offset int64) (string, int64) {
turnout := repo.FindTurnout(uid)
if turnout == nil {
panic(sys_error.New(fmt.Sprintf("不存在道岔【uid:%s】", uid)))
}
var portPosition *repository.LinkPosition
switch port {
case "A":
portPosition = turnout.FindLinkPositionByPort(proto2.Port_A)
case "B":
portPosition = turnout.FindLinkPositionByPort(proto2.Port_B)
case "C":
portPosition = turnout.FindLinkPositionByPort(proto2.Port_C)
default:
panic(sys_error.New(fmt.Sprintf("无效端口【%s】偏移量", port)))
}
// 关联link
link := portPosition.Link()
isStart := link.ARelation().Device().Id() == uid
if isStart {
return link.Id(), offset
} else {
return link.Id(), link.Length() - offset
}
}
// 根据设备信息、上下行获取link运行方向ab指向
// 入参仿真Repository、uid、端口、上下行
// 输出link运行方向、设备上的指向
func QueryUpAndABByDevice(repo *repository.Repository, uid, port string, runDirection bool) (up, ab bool) {
if port == "" {
up, ab = runDirectionSectionToUpAndAB(repo, uid, runDirection)
} else {
up, ab = runDirectionTurnoutToUpAndAB(repo, uid, port, runDirection)
}
return
}
// 根据区段及上下行获取link运行方向ab指向
// 入参仿真Repository、区段UID、上下行
// 输出link运行方向、设备上的指向
func runDirectionSectionToUpAndAB(repo *repository.Repository, id string, runDirection bool) (up, ab bool) {
section := repo.FindPhysicalSection(id)
if section == nil {
panic(sys_error.New(fmt.Sprintf("地图不存在uid:%s缓存", id)))
}
ao, bo := section.ALinkPosition().Offset(), section.BLinkPosition().Offset()
// 是否从A到B统一坐标
ak, bk := convertRepoBaseKm(repo, section.AKilometer()), convertRepoBaseKm(repo, section.BKilometer())
ab = (runDirection == (ak.Value <= bk.Value))
up = (ab == (ao < bo))
return
}
// 根据区段及上下行获取link运行方向ab指向
// 入参仿真Repository、道岔UID、道岔端口、上下行
// 输出link运行方向设备上的指向
func runDirectionTurnoutToUpAndAB(repo *repository.Repository, id, port string, runDirection bool) (up, ab bool) {
turnout := repo.FindTurnout(id)
if turnout == nil {
panic(sys_error.New(fmt.Sprintf("不存在道岔【uid:%s】", id)))
}
var portKm *proto2.Kilometer
var portPosition *repository.LinkPosition
switch port {
case "A":
portKm = convertRepoBaseKm(repo, turnout.GetTurnoutKm(proto2.Port_A))
portPosition = turnout.FindLinkPositionByPort(proto2.Port_A)
case "B":
portKm = convertRepoBaseKm(repo, turnout.GetTurnoutKm(proto2.Port_B))
portPosition = turnout.FindLinkPositionByPort(proto2.Port_B)
case "C":
portKm = convertRepoBaseKm(repo, turnout.GetTurnoutKm(proto2.Port_C))
portPosition = turnout.FindLinkPositionByPort(proto2.Port_C)
default:
panic(sys_error.New(fmt.Sprintf("无效端口【%s】偏移量", port)))
}
// 岔心公里标
crossKm := convertRepoBaseKm(repo, turnout.GetTurnoutKm(proto2.Port_None))
// 是否是link的起始断点
isStart := (portPosition.Link().ARelation() != nil && portPosition.Link().ARelation().Device().Id() == id)
up = runDirection
if (portKm.Value > crossKm.Value) != isStart {
up = !runDirection
}
ab = (portKm.Value > crossKm.Value) == runDirection
return
2023-10-19 17:42:01 +08:00
}
2023-10-26 10:05:28 +08:00
2023-11-08 11:02:41 +08:00
// 根据设备以及link运行方向获取上下行、设备上的运行指向
// 入参仿真Repository、道岔UID、道岔端口、上下行
// 输出link运行方向设备上的指向
func QueryDirectionAndABByDevice(repo *repository.Repository, uid, port string, up bool) (runDirection, ab bool) {
if port == "" {
runDirection, ab = upSectionToDirectionAndAB(repo, uid, up)
} else {
runDirection, ab = upTurnoutToDirectionAndAB(repo, uid, port, up)
2023-10-26 10:05:28 +08:00
}
2023-11-08 11:02:41 +08:00
return
}
// 根据区段以及link运行方向获取上下行、设备上的运行指向
// 入参仿真Repository、道岔UID、道岔端口、上下行
// 输出link运行方向设备上的指向
func upSectionToDirectionAndAB(repo *repository.Repository, uid string, up bool) (runDirection, ab bool) {
section := repo.FindPhysicalSection(uid)
if section == nil {
panic(sys_error.New(fmt.Sprintf("地图不存在uid:%s缓存", uid)))
2023-10-26 10:05:28 +08:00
}
2023-11-08 11:02:41 +08:00
// a点偏移、b点偏移
ao, bo := section.ALinkPosition().Offset(), section.BLinkPosition().Offset()
// a点公里标、b点公里标
ak, bk := convertRepoBaseKm(repo, section.AKilometer()), convertRepoBaseKm(repo, section.BKilometer())
if up {
runDirection = ((ao < bo) == (ak.Value < bk.Value))
} else {
runDirection = ((ao > bo) == (ak.Value < bk.Value))
}
ab = (runDirection == (ak.Value < bk.Value))
return
}
// 根据道岔以及link运行方向获取上下行、设备上的运行指向
// 入参仿真Repository、道岔UID、道岔端口、上下行
// 输出link运行方向设备上的指向
func upTurnoutToDirectionAndAB(repo *repository.Repository, uid, port string, up bool) (runDirection, ab bool) {
turnout := repo.FindTurnout(uid)
if turnout == nil {
panic(sys_error.New(fmt.Sprintf("不存在道岔【uid:%s】", uid)))
}
var port_enum proto2.Port
switch port {
case "A":
port_enum = proto2.Port_A
case "B":
port_enum = proto2.Port_B
case "C":
port_enum = proto2.Port_C
default:
panic(sys_error.New(fmt.Sprintf("无效端口【%s】偏移量", port)))
2023-10-26 10:05:28 +08:00
}
2023-11-08 11:02:41 +08:00
tpo := turnout.FindLinkPositionByPort(port_enum)
isA := tpo.Link().ARelation() != nil && tpo.Link().ARelation().Device().Id() == uid
crossKmInfo := convertRepoBaseKm(repo, turnout.GetTurnoutKm(proto2.Port_None))
portKmInfo := convertRepoBaseKm(repo, turnout.GetTurnoutKm(port_enum))
if isA {
ab = !up
runDirection = (up == (crossKmInfo.Value < portKmInfo.Value))
} else {
ab = up
runDirection = (up == (crossKmInfo.Value > portKmInfo.Value))
}
return
}
// 根据设备获取列车公里标
2023-11-09 10:20:50 +08:00
// 入参仿真Repository、UID、端口、上下行、设备偏移
2023-11-08 11:02:41 +08:00
// 输出:公里标信息
func CalcTrainKilometer(repo *repository.Repository, uid, port string, runDirection bool, offset int64) (
km *proto2.Kilometer) {
if port == "" {
km = sectionOffsetToKilometer(repo, uid, runDirection, offset)
} else {
km = turnoutOffsetToKilometer(repo, uid, runDirection, offset)
}
return
}
// 获取区段的上公里标
2023-11-09 10:20:50 +08:00
// 入参仿真Repository、UID、上下行、设备偏移
2023-11-08 11:02:41 +08:00
// 输出:公里标信息
func sectionOffsetToKilometer(repo *repository.Repository, uid string, runDirection bool, offset int64) (km *proto2.Kilometer) {
section := repo.FindPhysicalSection(uid)
if section == nil {
panic(sys_error.New(fmt.Sprintf("地图不存在uid:%s缓存", uid)))
}
km = convertRepoBaseKm(repo, section.AKilometer())
if runDirection {
km.Value = km.Value + offset
} else {
km.Value = km.Value - offset
}
return
}
// 获取道岔的公里标
2023-11-09 10:20:50 +08:00
// 入参仿真Repository、UID、上下行、设备偏移
2023-11-08 11:02:41 +08:00
// 输出:公里标信息
func turnoutOffsetToKilometer(repo *repository.Repository, uid string, runDirection bool, offset int64) (km *proto2.Kilometer) {
turnout := repo.FindTurnout(uid)
if turnout == nil {
panic(sys_error.New(fmt.Sprintf("不存在道岔【uid:%s】", uid)))
}
// 岔心公里标
km = convertRepoBaseKm(repo, turnout.GetTurnoutKm(proto2.Port_None))
if runDirection {
km.Value = km.Value + offset
} else {
km.Value = km.Value - offset
}
return
2023-10-26 10:05:28 +08:00
}
// 根据起始与末尾端查找经过的设备ID列表
// 入参起始设备uid、起始设备端口、终点设备uid、在区段a->b或道岔->岔心)上的找寻方向
// 输出占用物理区段的ID
2023-11-09 17:54:31 +08:00
func QueryDeviceRoutePath(sim *VerifySimulation, startUid, endUid, startPort string, pointTo bool) (paths []string, err error) {
suid, port, direction := startUid, startPort, pointTo
for {
device := sim.Repo.FindById(suid)
var nextRelation repository.DevicePort
switch device.Type() {
case proto2.DeviceType_DeviceType_PhysicalSection: // 区段
d := device.(*repository.PhysicalSection)
paths = append(paths, d.Id())
nextRelation = d.ARelation()
if direction {
nextRelation = d.BRelation()
}
case proto2.DeviceType_DeviceType_Turnout: // 道岔
d := device.(*repository.Turnout)
if d.GetPhysicalSection() == nil {
2023-11-09 17:54:31 +08:00
err = sys_error.New(fmt.Sprintf("道岔%s没有绑定物理区段", device.Id()))
}
paths = append(paths, d.GetPhysicalSection().Id())
var nextPort proto2.Port
switch port {
case "A":
nextPort = proto2.Port_A
case "B":
nextPort = proto2.Port_B
case "C":
nextPort = proto2.Port_C
}
if pointTo { // -> 岔心
2023-11-09 17:54:31 +08:00
nextPort, err = getTurnoutNextPort(sim, d.Id(), port)
}
nextRelation = d.GindDevicePortByPort(nextPort)
default:
2023-11-09 17:54:31 +08:00
err = sys_error.New(fmt.Sprintf("查找路径设备类型%s无处理处理", device.Type().String()))
}
2023-11-09 17:54:31 +08:00
if err != nil {
return
}
2023-11-09 17:54:31 +08:00
if suid == endUid {
return
}
if nextRelation == nil {
return
}
suid = nextRelation.Device().Id() // 下一个设备ID
port = nextRelation.Port().String() // 下一个道岔端
switch nextRelation.Device().Type() { // 查找方向
case proto2.DeviceType_DeviceType_PhysicalSection:
direction = nextRelation.Port() == proto2.Port_A
case proto2.DeviceType_DeviceType_Turnout:
direction = true
}
}
}