762 lines
24 KiB
Go
762 lines
24 KiB
Go
package memory
|
||
|
||
import (
|
||
"fmt"
|
||
"log/slog"
|
||
"math"
|
||
"sort"
|
||
"strconv"
|
||
"strings"
|
||
"sync"
|
||
|
||
rtss_simulation "joylink.club/rtsssimulation"
|
||
|
||
"joylink.club/bj-rtsts-server/ats/verify/protos/graphicData"
|
||
"joylink.club/bj-rtsts-server/ats/verify/protos/state"
|
||
"joylink.club/bj-rtsts-server/dto"
|
||
"joylink.club/bj-rtsts-server/third_party/deprecated/vobc"
|
||
"joylink.club/bj-rtsts-server/third_party/message"
|
||
"joylink.club/ecs"
|
||
"joylink.club/rtsssimulation/repository"
|
||
"joylink.club/rtsssimulation/repository/model/proto"
|
||
)
|
||
|
||
// 轨旁仿真定义
|
||
type VerifySimulation struct {
|
||
//地图id
|
||
MapIds []int32
|
||
// 项目ID
|
||
ProjectId int32
|
||
//仿真id
|
||
SimulationId string
|
||
//仿真内存数据
|
||
Memory *WaysideMemory
|
||
//模型仓库
|
||
Repo *repository.Repository
|
||
//Rtss仿真世界的id
|
||
WorldId ecs.WorldId
|
||
World ecs.World
|
||
//设备UID映射
|
||
uidMap map[string]*elementIdStructure
|
||
}
|
||
|
||
// 轨旁仿真内存模型
|
||
type WaysideMemory struct {
|
||
//可变状态数据:轨旁仿真模型状态(全量数据)
|
||
Status *VerifyStatus
|
||
// 要变更的状态:用户操作过的状态记录在这里,增量推送次数据
|
||
ChangeStatus *ChangeVerifyStatus
|
||
//状态保护锁
|
||
rwLock *sync.RWMutex
|
||
}
|
||
|
||
// 轨旁仿真模型状态
|
||
type VerifyStatus struct {
|
||
//道岔状态,key为道岔id即索引 state.SwitchState
|
||
SwitchStateMap sync.Map
|
||
//轨道状态,key为轨道id即索引 state.LinkState
|
||
LinkStateMap sync.Map
|
||
//列车状态,key为列车id即索引 state.TrainState
|
||
TrainStateMap sync.Map
|
||
//计轴区段状态,key为计轴区段的id即索引 state.SectionState
|
||
AxleSectionStateMap sync.Map
|
||
//物理区段状态,key为物理区段id即索引 state.SectionState
|
||
PhysicalSectionStateMap sync.Map
|
||
//逻辑区段状态,key为逻辑区段id即索引 state.SectionState
|
||
LogicSectionStateMap sync.Map
|
||
//信号机状态,key为信号机id,即索引 state.SignalState
|
||
SignalStateMap sync.Map
|
||
}
|
||
|
||
// 轨旁仿真模型状态(变更)
|
||
type ChangeVerifyStatus struct {
|
||
VerifyStatus
|
||
//删除的列车ID列表
|
||
RemoveTrainId []string
|
||
}
|
||
|
||
func NewWaysideMemory() *WaysideMemory {
|
||
return &WaysideMemory{
|
||
Status: &VerifyStatus{},
|
||
ChangeStatus: &ChangeVerifyStatus{},
|
||
rwLock: &sync.RWMutex{},
|
||
}
|
||
}
|
||
|
||
// 创建仿真对象
|
||
func CreateSimulation(projectId int32, mapIds []int32) (*VerifySimulation, error) {
|
||
//构建Repository
|
||
sort.Slice(mapIds, func(i, j int) bool {
|
||
return mapIds[i] < mapIds[j]
|
||
})
|
||
var mapIdStrSlice []string
|
||
for _, id := range mapIds {
|
||
mapIdStrSlice = append(mapIdStrSlice, strconv.Itoa(int(id)))
|
||
}
|
||
repoId := strings.Join(mapIdStrSlice, "|")
|
||
repoVersion := "0.1"
|
||
repo := repository.FindRepository(repoId, repoVersion)
|
||
if repo == nil {
|
||
protoRepo, err := buildProtoRepository(mapIds)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
protoRepo.Id, protoRepo.Version = repoId, repoVersion
|
||
newRepo, err := repository.BuildRepository(protoRepo)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
repo = newRepo
|
||
}
|
||
// 目前用本地构建状态
|
||
worldMemory := NewWaysideMemory()
|
||
initWorldDeviceState(worldMemory.Status, repo)
|
||
// 构建所有UID映射关系,
|
||
allUidMap := buildRepositoryAllUidsMap(mapIds, repo)
|
||
//创建仿真
|
||
// worldId := world.CreateSimulation(repo)
|
||
w := rtss_simulation.NewSimulation(repo)
|
||
w.StartUp()
|
||
verifySimulation := &VerifySimulation{
|
||
MapIds: mapIds,
|
||
ProjectId: projectId,
|
||
Memory: worldMemory,
|
||
Repo: repo,
|
||
World: w,
|
||
WorldId: w.Id(),
|
||
uidMap: allUidMap,
|
||
}
|
||
return verifySimulation, nil
|
||
}
|
||
|
||
// 获取全量状态
|
||
func (s *VerifySimulation) GetAllState(mapId int32) *state.PushedDevicesStatus {
|
||
giType := QueryGiType(mapId)
|
||
if giType != graphicData.PictureType_StationLayout {
|
||
return &state.PushedDevicesStatus{
|
||
All: true,
|
||
AllStatus: &state.AllDevicesStatus{
|
||
ReplyState: GetMapAllRelayState(s, mapId),
|
||
},
|
||
}
|
||
}
|
||
return &state.PushedDevicesStatus{
|
||
All: true,
|
||
AllStatus: &state.AllDevicesStatus{
|
||
SwitchState: GetMapAllTurnoutState(s, mapId),
|
||
TrainState: GetAllTrainState(s),
|
||
SignalState: GetMapAllSignalState(s, mapId),
|
||
},
|
||
}
|
||
}
|
||
|
||
// 获取仿真世界信息
|
||
func (s *VerifySimulation) GetSimulationWorld() ecs.World {
|
||
return s.World
|
||
}
|
||
|
||
// 获取仿真世界信息
|
||
func (s *VerifySimulation) GetComIdByUid(uid string) string {
|
||
es := s.uidMap
|
||
if es == nil {
|
||
panic(&dto.ErrorDto{Code: dto.DataNotExist, Message: "无映射信息"})
|
||
}
|
||
if es[uid] == nil {
|
||
panic(&dto.ErrorDto{Code: dto.DataNotExist, Message: "无【uid】映射信息"})
|
||
}
|
||
return es[uid].CommonId
|
||
}
|
||
|
||
func (sim *VerifySimulation) BuildLineBaseInfo() *message.LineBaseInfo {
|
||
info := &message.LineBaseInfo{}
|
||
for _, model := range sim.Repo.LinkList() {
|
||
id, _ := strconv.Atoi(model.Id())
|
||
link := &message.Link{
|
||
ID: int32(id),
|
||
Len: int32(model.Length()),
|
||
}
|
||
info.LinkList = append(info.LinkList, link)
|
||
if model.ARelation() != nil {
|
||
turnoutId, _ := strconv.Atoi(sim.GetComIdByUid(model.ARelation().Device().Id()))
|
||
link.ARelTurnoutId = int32(turnoutId)
|
||
switch model.ARelation().Port() {
|
||
case proto.Port_A:
|
||
link.ARelTurnoutPoint = "A"
|
||
case proto.Port_B:
|
||
link.ARelTurnoutPoint = "B"
|
||
case proto.Port_C:
|
||
link.ARelTurnoutPoint = "C"
|
||
}
|
||
}
|
||
if model.BRelation() != nil {
|
||
turnoutId, _ := strconv.Atoi(sim.GetComIdByUid(model.BRelation().Device().Id()))
|
||
link.BRelTurnoutId = int32(turnoutId)
|
||
switch model.BRelation().Port() {
|
||
case proto.Port_A:
|
||
link.BRelTurnoutPoint = "A"
|
||
case proto.Port_B:
|
||
link.BRelTurnoutPoint = "B"
|
||
case proto.Port_C:
|
||
link.BRelTurnoutPoint = "C"
|
||
}
|
||
}
|
||
}
|
||
for _, model := range sim.Repo.SlopeList() {
|
||
id, _ := strconv.Atoi(sim.GetComIdByUid(model.Id()))
|
||
slope := &message.Slope{
|
||
ID: int32(id),
|
||
StartLinkOffset: int32(model.StartLinkPosition().Offset()),
|
||
EndLinkOffset: int32(model.EndLinkPosition().Offset()),
|
||
DegreeTrig: model.Degree(),
|
||
}
|
||
info.SlopeList = append(info.SlopeList, slope)
|
||
startLinkId, _ := strconv.Atoi(model.StartLinkPosition().Link().Id())
|
||
slope.StartLinkId = int32(startLinkId)
|
||
endLinkId, _ := strconv.Atoi(model.EndLinkPosition().Link().Id())
|
||
slope.EndLinkId = int32(endLinkId)
|
||
}
|
||
for _, model := range sim.Repo.SectionalCurvatureList() {
|
||
id, _ := strconv.Atoi(sim.GetComIdByUid(model.Id()))
|
||
curve := &message.Curve{
|
||
ID: int32(id),
|
||
StartLinkOffset: int32(model.StartLinkPosition().Offset()),
|
||
EndLinkOffset: int32(model.EndLinkPosition().Offset()),
|
||
Curvature: model.Radius(),
|
||
}
|
||
info.CurveList = append(info.CurveList, curve)
|
||
startLinkId, _ := strconv.Atoi(model.StartLinkPosition().Link().Id())
|
||
curve.StartLinkId = int32(startLinkId)
|
||
endLinkId, _ := strconv.Atoi(model.EndLinkPosition().Link().Id())
|
||
curve.EndLinkId = int32(endLinkId)
|
||
}
|
||
return info
|
||
}
|
||
|
||
// 采集动力学道岔状态
|
||
func (s *VerifySimulation) CollectDynamicsTurnoutInfo() []*message.DynamicsTurnoutInfo {
|
||
stateSlice := GetAllTurnoutState(s)
|
||
var turnoutStates []*message.DynamicsTurnoutInfo
|
||
for _, sta := range stateSlice {
|
||
code64, err := strconv.ParseUint(sta.Id, 10, 16)
|
||
if err != nil {
|
||
slog.Error("id转uint16报错", err)
|
||
}
|
||
info := message.DynamicsTurnoutInfo{
|
||
Code: uint16(code64),
|
||
NPosition: sta.Dw,
|
||
RPosition: sta.Fw,
|
||
}
|
||
turnoutStates = append(turnoutStates, &info)
|
||
}
|
||
return turnoutStates
|
||
}
|
||
|
||
// 处理动力学列车速度消息
|
||
func (s *VerifySimulation) HandleDynamicsTrainInfo(info *message.DynamicsTrainInfo) {
|
||
sta, ok := s.Memory.Status.TrainStateMap.Load(strconv.Itoa(int(info.Number)))
|
||
if !ok {
|
||
return
|
||
}
|
||
trainState := sta.(*state.TrainState)
|
||
// 给半实物仿真发送速度
|
||
vobc.SendTrainSpeedTask(math.Abs(float64(info.Speed * 36)))
|
||
// 更新列车状态
|
||
UpdateTrainState(s, convert(info, trainState, s))
|
||
}
|
||
|
||
func convert(info *message.DynamicsTrainInfo, sta *state.TrainState, simulation *VerifySimulation) *state.TrainState {
|
||
slog.Debug("收到动力学原始消息", "Number", info.Number, "Link", info.Link, "LinkOffset", info.LinkOffset)
|
||
id, port, offset, runDirection, pointTo, kilometer := QueryDeviceByCalcLink(simulation.Repo, strconv.Itoa(int(info.Link)), int64(info.LinkOffset), info.Up)
|
||
slog.Debug("处理动力学转换后的消息", "number", info.Number,
|
||
"车头位置", id, "偏移", offset, "是否上行", runDirection, "是否ab", pointTo)
|
||
sta.HeadDeviceId = simulation.GetComIdByUid(id)
|
||
sta.DevicePort = port
|
||
sta.HeadOffset = offset
|
||
sta.PointTo = pointTo
|
||
sta.TrainKilometer = kilometer
|
||
sta.RunDirection = runDirection
|
||
//判定车头方向
|
||
sta.HeadDirection = runDirection
|
||
if sta.VobcState != nil {
|
||
if sta.VobcState.DirectionForward {
|
||
sta.HeadDirection = runDirection
|
||
} else if sta.VobcState.DirectionBackward {
|
||
sta.HeadDirection = !runDirection
|
||
}
|
||
}
|
||
if info.Speed < 0 {
|
||
sta.RunDirection = !sta.RunDirection
|
||
}
|
||
// 赋值动力学信息
|
||
sta.DynamicState.Heartbeat = int32(info.LifeSignal)
|
||
sta.DynamicState.HeadLinkId = strconv.Itoa(int(info.Link))
|
||
sta.DynamicState.HeadLinkOffset = int64(info.LinkOffset)
|
||
sta.DynamicState.Slope = int32(info.Slope)
|
||
sta.DynamicState.Upslope = info.UpSlope
|
||
sta.DynamicState.RunningUp = info.Up
|
||
sta.DynamicState.RunningResistanceSum = float32(info.TotalResistance) / 1000
|
||
sta.DynamicState.AirResistance = float32(info.AirResistance) / 1000
|
||
sta.DynamicState.RampResistance = float32(info.SlopeResistance) / 1000
|
||
sta.DynamicState.CurveResistance = float32(info.CurveResistance) / 1000
|
||
sta.DynamicState.Speed = speedParse(info.Speed)
|
||
sta.DynamicState.HeadSensorSpeed1 = speedParse(info.HeadSpeed1)
|
||
sta.DynamicState.HeadSensorSpeed2 = speedParse(info.HeadSpeed2)
|
||
sta.DynamicState.TailSensorSpeed1 = speedParse(info.TailSpeed1)
|
||
sta.DynamicState.TailSensorSpeed2 = speedParse(info.TailSpeed2)
|
||
sta.DynamicState.HeadRadarSpeed = speedParse(info.HeadRadarSpeed)
|
||
sta.DynamicState.TailRadarSpeed = speedParse(info.TailRadarSpeed)
|
||
sta.DynamicState.Acceleration = info.Acceleration
|
||
return sta
|
||
}
|
||
|
||
// 发送给前端的速度格式化
|
||
func speedParse(speed float32) int32 {
|
||
return int32(math.Abs(float64(speed * 3.6 * 100)))
|
||
}
|
||
|
||
// 处理半实物仿真列车控制消息
|
||
func (s *VerifySimulation) HandleSemiPhysicalTrainControlMsg(msg *message.TrainControlMsg) {
|
||
|
||
}
|
||
|
||
func buildProtoRepository(mapIds []int32) (*proto.Repository, error) {
|
||
repo := &proto.Repository{}
|
||
var exceptStationGiMapIds []int32
|
||
//创建设备
|
||
for _, mapId := range mapIds {
|
||
giType := QueryGiType(mapId)
|
||
if giType == graphicData.PictureType_StationLayout {
|
||
stationGi := QueryGiData[*graphicData.RtssGraphicStorage](mapId)
|
||
fillProtoRepository(repo, stationGi, mapId)
|
||
} else {
|
||
exceptStationGiMapIds = append(exceptStationGiMapIds, mapId)
|
||
}
|
||
}
|
||
//构建并关联电子元件
|
||
for _, mapId := range exceptStationGiMapIds {
|
||
giType := QueryGiType(mapId)
|
||
if giType == graphicData.PictureType_RelayCabinetLayout {
|
||
relayGi := QueryGiData[*graphicData.RelayCabinetGraphicStorage](mapId)
|
||
buildAndRelateElectronicComponent(repo, relayGi, mapId)
|
||
}
|
||
}
|
||
return repo, nil
|
||
}
|
||
|
||
func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *graphicData.RelayCabinetGraphicStorage, mapId int32) {
|
||
uidsMap := queryUidStructure[*relayUidStructure](mapId)
|
||
city := relayGi.UniqueIdPrefix.City
|
||
lineId := relayGi.UniqueIdPrefix.LineId
|
||
station := relayGi.UniqueIdPrefix.BelongsConcentrationStation
|
||
for _, relay := range relayGi.Relays {
|
||
repo.Relays = append(repo.Relays, &proto.Relay{
|
||
Id: uidsMap.RelayIds[relay.Common.Id].Uid,
|
||
Code: relay.Code,
|
||
Model: convertRelayModel(relay.NewModel),
|
||
})
|
||
}
|
||
for _, pfp := range relayGi.PhaseFailureProtectors {
|
||
repo.PhaseFailureProtectors = append(repo.PhaseFailureProtectors, &proto.PhaseFailureProtector{
|
||
Id: uidsMap.RelayIds[pfp.Common.Id].Uid,
|
||
Code: pfp.Code,
|
||
})
|
||
}
|
||
turnoutMap := make(map[string]*proto.Turnout)
|
||
for _, turnout := range repo.Turnouts {
|
||
turnoutMap[turnout.Id] = turnout
|
||
}
|
||
signalMap := make(map[string]*proto.Signal)
|
||
for _, signal := range repo.Signals {
|
||
signalMap[signal.Id] = signal
|
||
}
|
||
for _, relationship := range relayGi.DeviceRelateRelayList {
|
||
switch relationship.DeviceType {
|
||
case graphicData.RelatedRef_Turnout:
|
||
turnout := turnoutMap[GenerateElementUid(city, lineId, []string{station}, relationship.Code)]
|
||
if turnout == nil {
|
||
continue
|
||
}
|
||
for _, group := range relationship.Combinationtypes {
|
||
var componentIds []string
|
||
for _, relayId := range group.RefRelays {
|
||
if uidsMap.RelayIds[relayId] == nil {
|
||
continue
|
||
}
|
||
componentIds = append(componentIds, uidsMap.RelayIds[relayId].Uid)
|
||
}
|
||
turnout.ElectronicComponentGroups = append(turnout.ElectronicComponentGroups,
|
||
&proto.ElectronicComponentGroup{
|
||
Code: group.Code,
|
||
ComponentIds: componentIds,
|
||
})
|
||
}
|
||
case graphicData.RelatedRef_signal:
|
||
signal := signalMap[GenerateElementUid(city, lineId, []string{station}, relationship.Code)]
|
||
if signal == nil {
|
||
continue
|
||
}
|
||
for _, group := range relationship.Combinationtypes {
|
||
var componentIds []string
|
||
for _, relayId := range group.RefRelays {
|
||
if uidsMap.RelayIds[relayId] == nil {
|
||
continue
|
||
}
|
||
componentIds = append(componentIds, uidsMap.RelayIds[relayId].Uid)
|
||
}
|
||
signal.ElectronicComponentGroups = append(signal.ElectronicComponentGroups,
|
||
&proto.ElectronicComponentGroup{
|
||
Code: group.Code,
|
||
ComponentIds: componentIds,
|
||
})
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func convertRelayModel(modelType graphicData.Relay_ModelType) proto.Relay_Model {
|
||
switch modelType {
|
||
case graphicData.Relay_Unknown:
|
||
return proto.Relay_Unknown
|
||
case graphicData.Relay_JPXC_1000:
|
||
return proto.Relay_JPXC_1000
|
||
case graphicData.Relay_JPXC_1700:
|
||
return proto.Relay_JPXC_1700
|
||
case graphicData.Relay_JWJXC_480:
|
||
return proto.Relay_JWJXC_480
|
||
case graphicData.Relay_JWJXC_H125_80:
|
||
return proto.Relay_JWJXC_H125_80
|
||
case graphicData.Relay_JWXC_1700:
|
||
return proto.Relay_JWXC_1700
|
||
case graphicData.Relay_JWXC_H340:
|
||
return proto.Relay_JWXC_H340
|
||
case graphicData.Relay_JYJXC_160_260:
|
||
return proto.Relay_JYJXC_160_260
|
||
case graphicData.Relay_JZXC_H18:
|
||
return proto.Relay_JZXC_H18
|
||
default:
|
||
panic(fmt.Sprintf("意料之外的继电器型号:%s", modelType))
|
||
}
|
||
}
|
||
|
||
func fillProtoRepository(repo *proto.Repository, storage *graphicData.RtssGraphicStorage, mapId int32) {
|
||
axleCountingMap := make(map[string]*graphicData.AxleCounting)
|
||
uidsMap := queryUidStructure[*stationUidStructure](mapId)
|
||
for _, data := range storage.AxleCountings {
|
||
axleCountingMap[data.Common.Id] = data
|
||
cpType := proto.CheckPointType_AxleCounter
|
||
if data.Type == graphicData.AxleCounting_SectionBoundary {
|
||
cpType = proto.CheckPointType_Boundary
|
||
}
|
||
cp := &proto.CheckPoint{
|
||
Id: data.Common.Id,
|
||
Km: convertKm(data.KilometerSystem),
|
||
Type: cpType,
|
||
DevicePorts: convertDevicePorts(data.AxleCountingRef),
|
||
}
|
||
repo.CheckPoints = append(repo.CheckPoints, converCheckPointUid(cp, uidsMap))
|
||
}
|
||
for _, data := range storage.Section {
|
||
var turnoutIds []string
|
||
if data.SectionType == graphicData.Section_TurnoutPhysical {
|
||
turnoutIds = findTurnoutIds(axleCountingMap, data.AxleCountings)
|
||
}
|
||
physicalSection := &proto.PhysicalSection{
|
||
Id: data.Common.Id,
|
||
ADevicePort: convertDevicePort(data.PaRef),
|
||
BDevicePort: convertDevicePort(data.PbRef),
|
||
TurnoutIds: turnoutIds,
|
||
}
|
||
repo.PhysicalSections = append(repo.PhysicalSections, converSectionUid(physicalSection, uidsMap))
|
||
}
|
||
for _, data := range storage.Turnouts {
|
||
var km *proto.Kilometer
|
||
for _, ks := range data.KilometerSystem {
|
||
if ks.Kilometer != 0 {
|
||
km = convertKm(ks)
|
||
break
|
||
}
|
||
}
|
||
var switchMachineType proto.Turnout_SwitchMachineType
|
||
switch data.SwitchMachineType {
|
||
case graphicData.Turnout_ZDJ9_Single:
|
||
switchMachineType = proto.Turnout_ZDJ9_Single
|
||
case graphicData.Turnout_ZDJ9_Double:
|
||
switchMachineType = proto.Turnout_ZDJ9_Double
|
||
}
|
||
turnout := &proto.Turnout{
|
||
Id: data.Common.Id,
|
||
Km: km,
|
||
ADevicePort: convertDevicePort(data.PaRef),
|
||
BDevicePort: convertDevicePort(data.PbRef),
|
||
CDevicePort: convertDevicePort(data.PcRef),
|
||
SwitchMachineType: switchMachineType,
|
||
}
|
||
repo.Turnouts = append(repo.Turnouts, converTurnoutUid(turnout, uidsMap))
|
||
}
|
||
for _, data := range storage.Signals {
|
||
var sectionId string
|
||
var turnoutPort *proto.DevicePort
|
||
switch data.RefDev.DeviceType {
|
||
case graphicData.RelatedRef_Section:
|
||
sectionId = data.RefDev.Id
|
||
case graphicData.RelatedRef_Turnout:
|
||
turnoutPort = convertDevicePort(data.RefDev)
|
||
}
|
||
signal := &proto.Signal{
|
||
Id: data.Common.Id,
|
||
Km: convertKm(data.KilometerSystem),
|
||
SectionId: sectionId,
|
||
TurnoutPort: turnoutPort,
|
||
}
|
||
repo.Signals = append(repo.Signals, converSignalUid(signal, uidsMap))
|
||
}
|
||
for _, data := range storage.Transponders {
|
||
var sectionId string
|
||
var turnoutPort *proto.DevicePort
|
||
switch data.TransponderRef.DeviceType {
|
||
case graphicData.RelatedRef_Section:
|
||
sectionId = data.TransponderRef.Id
|
||
case graphicData.RelatedRef_Turnout:
|
||
turnoutPort = convertDevicePort(data.TransponderRef)
|
||
}
|
||
responder := &proto.Transponder{
|
||
Id: data.Common.Id,
|
||
Km: convertKm(data.KilometerSystem),
|
||
SectionId: sectionId,
|
||
TurnoutPort: turnoutPort,
|
||
}
|
||
repo.Transponders = append(repo.Transponders, converTransponderUid(responder, uidsMap))
|
||
}
|
||
slopeKsMap := make(map[string]*graphicData.SlopeKiloMarker)
|
||
for _, data := range storage.SlopeKiloMarker {
|
||
slopeKsMap[data.Common.Id] = data
|
||
}
|
||
curveKsMap := make(map[string]*graphicData.CurvatureKiloMarker)
|
||
for _, data := range storage.CurvatureKiloMarker {
|
||
curveKsMap[data.Common.Id] = data
|
||
}
|
||
for _, data := range storage.Slopes {
|
||
var kms []*proto.Kilometer
|
||
for _, id := range data.RefDeviceId {
|
||
kms = append(kms, convertKm(slopeKsMap[id].KilometerSystem[0]))
|
||
}
|
||
slope := &proto.Slope{
|
||
Id: data.Common.Id,
|
||
Kms: kms,
|
||
Degree: data.SlopeNumber,
|
||
}
|
||
repo.Slopes = append(repo.Slopes, converSlopeUid(slope, uidsMap))
|
||
}
|
||
for _, data := range storage.Curvatures {
|
||
var kms []*proto.Kilometer
|
||
for _, id := range data.RefDeviceId {
|
||
kms = append(kms, convertKm(curveKsMap[id].KilometerSystem[0]))
|
||
}
|
||
slope := &proto.SectionalCurvature{
|
||
Id: data.Common.Id,
|
||
Kms: kms,
|
||
Radius: data.CurvatureNumber,
|
||
}
|
||
repo.SectionalCurvatures = append(repo.SectionalCurvatures, converCurvatureUid(slope, uidsMap))
|
||
}
|
||
for _, data := range storage.KilometerConvertList {
|
||
repo.KilometerConverts = append(repo.KilometerConverts, &proto.KilometerConvert{
|
||
KmA: convertKm(data.KmA),
|
||
KmB: convertKm(data.KmB),
|
||
SameTrend: data.SameTrend,
|
||
})
|
||
}
|
||
}
|
||
|
||
func converCheckPointUid(data *proto.CheckPoint, uidsMap *stationUidStructure) *proto.CheckPoint {
|
||
data.Id = uidsMap.AxlePointIds[data.Id].Uid
|
||
for _, c := range data.DevicePorts {
|
||
c.DeviceId = converRefUid(c.DeviceId, c.DeviceType, uidsMap)
|
||
}
|
||
return data
|
||
}
|
||
|
||
func converSectionUid(data *proto.PhysicalSection, uidsMap *stationUidStructure) *proto.PhysicalSection {
|
||
data.Id = uidsMap.PhysicalSectionIds[data.Id].Uid
|
||
if data.ADevicePort != nil {
|
||
data.ADevicePort.DeviceId = converRefUid(data.ADevicePort.DeviceId, data.ADevicePort.DeviceType, uidsMap)
|
||
}
|
||
if data.BDevicePort != nil {
|
||
data.BDevicePort.DeviceId = converRefUid(data.BDevicePort.DeviceId, data.BDevicePort.DeviceType, uidsMap)
|
||
}
|
||
tids := make([]string, len(data.TurnoutIds))
|
||
for i, tid := range data.TurnoutIds {
|
||
tids[i] = converRefUid(tid, proto.DeviceType_DeviceType_Turnout, uidsMap)
|
||
}
|
||
data.TurnoutIds = tids
|
||
return data
|
||
}
|
||
|
||
func converTurnoutUid(data *proto.Turnout, uidsMap *stationUidStructure) *proto.Turnout {
|
||
data.Id = uidsMap.TurnoutIds[data.Id].Uid
|
||
if data.ADevicePort != nil {
|
||
data.ADevicePort.DeviceId = converRefUid(data.ADevicePort.DeviceId, data.ADevicePort.DeviceType, uidsMap)
|
||
}
|
||
if data.BDevicePort != nil {
|
||
data.BDevicePort.DeviceId = converRefUid(data.BDevicePort.DeviceId, data.BDevicePort.DeviceType, uidsMap)
|
||
}
|
||
if data.CDevicePort != nil {
|
||
data.CDevicePort.DeviceId = converRefUid(data.CDevicePort.DeviceId, data.CDevicePort.DeviceType, uidsMap)
|
||
}
|
||
return data
|
||
}
|
||
|
||
func converSignalUid(data *proto.Signal, uidsMap *stationUidStructure) *proto.Signal {
|
||
data.Id = uidsMap.SignalIds[data.Id].Uid
|
||
if data.SectionId != "" {
|
||
data.SectionId = converRefUid(data.SectionId, proto.DeviceType_DeviceType_PhysicalSection, uidsMap)
|
||
}
|
||
if data.TurnoutPort != nil {
|
||
data.TurnoutPort.DeviceId = converRefUid(data.TurnoutPort.DeviceId, data.TurnoutPort.DeviceType, uidsMap)
|
||
}
|
||
return data
|
||
}
|
||
|
||
func converTransponderUid(data *proto.Transponder, uidsMap *stationUidStructure) *proto.Transponder {
|
||
data.Id = uidsMap.TransponderIds[data.Id].Uid
|
||
if data.SectionId != "" {
|
||
data.SectionId = converRefUid(data.SectionId, proto.DeviceType_DeviceType_PhysicalSection, uidsMap)
|
||
}
|
||
if data.TurnoutPort != nil {
|
||
data.TurnoutPort.DeviceId = converRefUid(data.TurnoutPort.DeviceId, data.TurnoutPort.DeviceType, uidsMap)
|
||
}
|
||
return data
|
||
}
|
||
|
||
func converSlopeUid(data *proto.Slope, uidsMap *stationUidStructure) *proto.Slope {
|
||
data.Id = uidsMap.SlopeIds[data.Id].Uid
|
||
return data
|
||
}
|
||
|
||
func converCurvatureUid(data *proto.SectionalCurvature, uidsMap *stationUidStructure) *proto.SectionalCurvature {
|
||
data.Id = uidsMap.CurvatureIds[data.Id].Uid
|
||
return data
|
||
}
|
||
|
||
func converRefUid(id string, d proto.DeviceType, uidsMap *stationUidStructure) string {
|
||
var elementId *elementIdStructure
|
||
switch d {
|
||
case proto.DeviceType_DeviceType_CheckPoint:
|
||
elementId = uidsMap.AxlePointIds[id]
|
||
case proto.DeviceType_DeviceType_PhysicalSection:
|
||
elementId = uidsMap.PhysicalSectionIds[id]
|
||
case proto.DeviceType_DeviceType_SectionalCurvature:
|
||
elementId = uidsMap.CurvatureIds[id]
|
||
case proto.DeviceType_DeviceType_Signal:
|
||
elementId = uidsMap.SignalIds[id]
|
||
case proto.DeviceType_DeviceType_Slope:
|
||
elementId = uidsMap.SlopeIds[id]
|
||
case proto.DeviceType_DeviceType_Transponder:
|
||
elementId = uidsMap.TransponderIds[id]
|
||
case proto.DeviceType_DeviceType_Turnout:
|
||
elementId = uidsMap.TurnoutIds[id]
|
||
default:
|
||
panic(&dto.ErrorDto{Code: dto.ArgumentParseError, Message: "异常的设备类型-" + d.String()})
|
||
}
|
||
return elementId.Uid
|
||
}
|
||
|
||
func convertKm(ks *graphicData.KilometerSystem) *proto.Kilometer {
|
||
var dir proto.Direction
|
||
switch ks.Direction {
|
||
case graphicData.Direction_LEFT:
|
||
dir = proto.Direction_LEFT
|
||
case graphicData.Direction_RIGHT:
|
||
dir = proto.Direction_RIGHT
|
||
}
|
||
return &proto.Kilometer{
|
||
Value: ks.Kilometer,
|
||
CoordinateSystem: ks.CoordinateSystem,
|
||
Direction: dir,
|
||
}
|
||
}
|
||
|
||
func convertDevicePort(ref *graphicData.RelatedRef) *proto.DevicePort {
|
||
if ref == nil {
|
||
return nil
|
||
}
|
||
var deviceType proto.DeviceType
|
||
var port proto.Port
|
||
switch ref.DevicePort {
|
||
case graphicData.RelatedRef_A:
|
||
port = proto.Port_A
|
||
case graphicData.RelatedRef_B:
|
||
port = proto.Port_B
|
||
case graphicData.RelatedRef_C:
|
||
port = proto.Port_C
|
||
}
|
||
switch ref.DeviceType {
|
||
case graphicData.RelatedRef_Section:
|
||
deviceType = proto.DeviceType_DeviceType_PhysicalSection
|
||
case graphicData.RelatedRef_Turnout:
|
||
deviceType = proto.DeviceType_DeviceType_Turnout
|
||
default:
|
||
panic(fmt.Sprintf("异常的设备类型-%s", ref.DeviceType))
|
||
}
|
||
return &proto.DevicePort{
|
||
DeviceId: ref.Id,
|
||
DeviceType: deviceType,
|
||
Port: port,
|
||
}
|
||
}
|
||
|
||
func convertDevicePorts(refList []*graphicData.RelatedRef) []*proto.DevicePort {
|
||
var dps []*proto.DevicePort
|
||
for _, ref := range refList {
|
||
dps = append(dps, convertDevicePort(ref))
|
||
}
|
||
return dps
|
||
}
|
||
|
||
func findTurnoutIds(axleCountingMap map[string]*graphicData.AxleCounting, axleIds []string) []string {
|
||
if len(axleIds) <= 2 {
|
||
return nil
|
||
}
|
||
turnoutMap := make(map[string]bool)
|
||
for _, axleId := range axleIds {
|
||
axle := axleCountingMap[axleId]
|
||
relTurnoutCount := 0
|
||
var turnoutId string
|
||
for _, ref := range axle.AxleCountingRef {
|
||
if ref.DeviceType == graphicData.RelatedRef_Turnout {
|
||
relTurnoutCount++
|
||
turnoutId = ref.Id
|
||
}
|
||
}
|
||
if relTurnoutCount == 1 {
|
||
turnoutMap[turnoutId] = true
|
||
}
|
||
}
|
||
var turnoutIds []string
|
||
for id := range turnoutMap {
|
||
turnoutIds = append(turnoutIds, id)
|
||
}
|
||
return turnoutIds
|
||
}
|
||
|
||
func initWorldDeviceState(status *VerifyStatus, repo *repository.Repository) {
|
||
initWorldTurnoutState(status, repo)
|
||
initWorldPhysicalSectionState(status, repo)
|
||
}
|
||
|
||
// 初始化道岔状态
|
||
func initWorldTurnoutState(status *VerifyStatus, repo *repository.Repository) {
|
||
for _, turnout := range repo.TurnoutList() {
|
||
id := turnout.Identity.Id()
|
||
status.SwitchStateMap.Store(id, &state.SwitchState{Id: id, Normal: true, Reverse: false})
|
||
}
|
||
}
|
||
|
||
// 初始化物理区段状态
|
||
func initWorldPhysicalSectionState(status *VerifyStatus, repo *repository.Repository) {
|
||
for _, section := range repo.PhysicalSectionList() {
|
||
id := section.Identity.Id()
|
||
status.PhysicalSectionStateMap.Store(id, &state.SectionState{Id: id, Occupied: false, Type: state.SectionType_Physic})
|
||
}
|
||
}
|