2023-08-01 14:54:11 +08:00
|
|
|
package memory
|
|
|
|
|
2023-08-01 17:08:45 +08:00
|
|
|
import (
|
2023-09-20 15:14:40 +08:00
|
|
|
"fmt"
|
2023-09-21 14:54:27 +08:00
|
|
|
"sort"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
|
2023-09-20 15:14:40 +08:00
|
|
|
"joylink.club/bj-rtsts-server/ats/verify/protos/graphicData"
|
2023-08-01 17:08:45 +08:00
|
|
|
"joylink.club/bj-rtsts-server/ats/verify/protos/state"
|
2023-09-21 14:54:27 +08:00
|
|
|
"joylink.club/bj-rtsts-server/dto"
|
|
|
|
"joylink.club/ecs"
|
2023-09-20 15:14:40 +08:00
|
|
|
"joylink.club/rtsssimulation/repository"
|
|
|
|
"joylink.club/rtsssimulation/repository/model/proto"
|
|
|
|
"joylink.club/rtsssimulation/simulation"
|
2023-08-01 17:08:45 +08:00
|
|
|
)
|
|
|
|
|
2023-08-01 14:54:11 +08:00
|
|
|
// 轨旁仿真定义
|
|
|
|
type VerifySimulation struct {
|
|
|
|
//地图id
|
2023-09-19 11:02:50 +08:00
|
|
|
MapIds []int32
|
2023-08-30 13:25:57 +08:00
|
|
|
// 项目ID
|
|
|
|
ProjectId int32
|
2023-08-01 14:54:11 +08:00
|
|
|
//仿真id
|
|
|
|
SimulationId string
|
|
|
|
//仿真内存数据
|
|
|
|
Memory *WaysideMemory
|
2023-09-20 15:14:40 +08:00
|
|
|
//模型仓库
|
|
|
|
Repo *repository.Repository
|
|
|
|
//Rtss仿真世界的id
|
|
|
|
WorldId int
|
2023-08-01 14:54:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 创建仿真对象
|
2023-09-20 15:14:40 +08:00
|
|
|
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 {
|
|
|
|
var storages []*graphicData.RtssGraphicStorage
|
2023-09-21 14:54:27 +08:00
|
|
|
var rmapIds []int32
|
2023-09-20 15:14:40 +08:00
|
|
|
for _, mapId := range mapIds {
|
2023-09-21 14:54:27 +08:00
|
|
|
storage := QueryGraphicStorage(mapId)
|
|
|
|
if storage == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
storages = append(storages, storage)
|
|
|
|
rmapIds = append(rmapIds, mapId)
|
2023-09-20 15:14:40 +08:00
|
|
|
}
|
2023-09-21 14:54:27 +08:00
|
|
|
protoRepo := buildProtoRepository(storages, rmapIds)
|
2023-09-20 15:14:40 +08:00
|
|
|
newRepo, err := repository.BuildRepository(protoRepo)
|
|
|
|
repo = newRepo
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//创建仿真
|
|
|
|
worldId := simulation.CreateSimulation(repo, &simulation.WorldConfig{})
|
2023-08-01 14:54:11 +08:00
|
|
|
verifySimulation := &VerifySimulation{
|
2023-09-19 11:02:50 +08:00
|
|
|
MapIds: mapIds,
|
|
|
|
ProjectId: projectId,
|
2023-09-20 15:14:40 +08:00
|
|
|
Memory: NewWaysideMemory(),
|
|
|
|
Repo: repo,
|
|
|
|
WorldId: worldId,
|
2023-09-19 11:02:50 +08:00
|
|
|
}
|
2023-09-20 15:14:40 +08:00
|
|
|
return verifySimulation, nil
|
2023-08-01 14:54:11 +08:00
|
|
|
}
|
2023-08-01 17:08:45 +08:00
|
|
|
|
|
|
|
// 获取全量状态
|
|
|
|
func (s *VerifySimulation) GetAllState() *state.PushedDevicesStatus {
|
|
|
|
return &state.PushedDevicesStatus{
|
|
|
|
All: true,
|
|
|
|
AllStatus: &state.AllDevicesStatus{
|
2023-08-03 10:41:43 +08:00
|
|
|
SwitchState: GetAllTurnoutState(s),
|
|
|
|
TrainState: GetAllTrainState(s),
|
|
|
|
SectionState: append(GetAllAxleSectionState(s), GetAllPhysicalSectionState(s)...),
|
2023-08-01 17:08:45 +08:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-21 14:54:27 +08:00
|
|
|
// 获取仿真地图数据
|
|
|
|
func (s *VerifySimulation) GetMapAllState(mid string) *state.PushedDevicesStatus {
|
2023-08-01 17:08:45 +08:00
|
|
|
return &state.PushedDevicesStatus{
|
2023-09-21 14:54:27 +08:00
|
|
|
All: true,
|
|
|
|
AllStatus: &state.AllDevicesStatus{
|
|
|
|
SwitchState: GetMapAllTurnoutState(s, mid),
|
|
|
|
TrainState: GetMapAllTrainState(s, mid),
|
|
|
|
SectionState: GetMapAllPhysicalSectionState(s, mid),
|
2023-08-01 17:08:45 +08:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2023-09-20 15:14:40 +08:00
|
|
|
|
2023-09-21 14:54:27 +08:00
|
|
|
// 获取仿真世界信息
|
|
|
|
func (s *VerifySimulation) GetSimulationWorld() {
|
|
|
|
ecsSimulation := simulation.FindSimulation(ecs.WorldId(s.WorldId))
|
|
|
|
if ecsSimulation == nil {
|
|
|
|
panic(&dto.ErrorDto{Code: dto.DataNotExist, Message: "ecs 仿真不存在"})
|
|
|
|
}
|
|
|
|
//return ecsSimulation.getWorld()
|
|
|
|
}
|
|
|
|
|
|
|
|
func buildProtoRepository(storages []*graphicData.RtssGraphicStorage, mapIds []int32) *proto.Repository {
|
2023-09-20 15:14:40 +08:00
|
|
|
repo := &proto.Repository{}
|
2023-09-21 14:54:27 +08:00
|
|
|
for i, storage := range storages {
|
|
|
|
fillProtoRepository(repo, storage, mapIds[i])
|
2023-09-20 15:14:40 +08:00
|
|
|
}
|
|
|
|
return repo
|
|
|
|
}
|
|
|
|
|
2023-09-21 14:54:27 +08:00
|
|
|
func fillProtoRepository(repo *proto.Repository, storage *graphicData.RtssGraphicStorage, mapId int32) {
|
2023-09-20 15:14:40 +08:00
|
|
|
axleCountingMap := make(map[string]*graphicData.AxleCounting)
|
|
|
|
for _, data := range storage.AxleCountings {
|
|
|
|
if data.KilometerSystem == nil {
|
|
|
|
println(fmt.Sprintf("计轴[%s]缺少公里标", data.Common.Id))
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
axleCountingMap[data.Common.Id] = data
|
|
|
|
cpType := proto.CheckPointType_AxleCounter
|
2023-09-21 14:54:27 +08:00
|
|
|
if data.Type == graphicData.AxleCounting_SectionBoundary {
|
2023-09-20 15:14:40 +08:00
|
|
|
cpType = proto.CheckPointType_Boundary
|
|
|
|
}
|
|
|
|
cp := &proto.CheckPoint{
|
2023-09-21 14:54:27 +08:00
|
|
|
Id: GetDeviceUidByCommonId(mapId, data.Common.Id, data),
|
2023-09-20 15:14:40 +08:00
|
|
|
Km: convertKm(data.KilometerSystem),
|
|
|
|
Type: cpType,
|
|
|
|
DevicePorts: convertDevicePorts(data.AxleCountingRef),
|
|
|
|
}
|
|
|
|
repo.CheckPoints = append(repo.CheckPoints, cp)
|
|
|
|
}
|
|
|
|
for _, data := range storage.Section {
|
|
|
|
var turnoutIds []string
|
|
|
|
if data.SectionType == graphicData.Section_TurnoutPhysical {
|
|
|
|
turnoutIds = findTurnoutIds(axleCountingMap, data.AxleCountings)
|
|
|
|
}
|
|
|
|
physicalSection := &proto.PhysicalSection{
|
2023-09-21 14:54:27 +08:00
|
|
|
Id: GetDeviceUidByCommonId(mapId, data.Common.Id, data),
|
2023-09-20 15:14:40 +08:00
|
|
|
ADevicePort: convertDevicePort(data.PaRef),
|
|
|
|
BDevicePort: convertDevicePort(data.PbRef),
|
|
|
|
TurnoutIds: turnoutIds,
|
|
|
|
}
|
|
|
|
repo.PhysicalSections = append(repo.PhysicalSections, physicalSection)
|
|
|
|
}
|
|
|
|
for _, data := range storage.Turnouts {
|
|
|
|
var km *proto.Kilometer
|
|
|
|
for _, ks := range data.KilometerSystem {
|
|
|
|
if ks.Kilometer != 0 {
|
|
|
|
km = convertKm(ks)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2023-09-21 14:54:27 +08:00
|
|
|
repo.KilometerConverts = append(repo.KilometerConverts, buildKmConverts(data.KilometerSystem)...)
|
2023-09-20 15:14:40 +08:00
|
|
|
turnout := &proto.Turnout{
|
2023-09-21 14:54:27 +08:00
|
|
|
Id: GetDeviceUidByCommonId(mapId, data.Common.Id, data),
|
2023-09-20 15:14:40 +08:00
|
|
|
Km: km,
|
|
|
|
ADevicePort: convertDevicePort(data.PaRef),
|
|
|
|
BDevicePort: convertDevicePort(data.PbRef),
|
|
|
|
CDevicePort: convertDevicePort(data.PcRef),
|
|
|
|
}
|
|
|
|
repo.Turnouts = append(repo.Turnouts, turnout)
|
|
|
|
}
|
|
|
|
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{
|
2023-09-21 14:54:27 +08:00
|
|
|
Id: GetDeviceUidByCommonId(mapId, data.Common.Id, data),
|
2023-09-20 15:14:40 +08:00
|
|
|
Km: convertKm(data.KilometerSystem),
|
|
|
|
SectionId: sectionId,
|
|
|
|
TurnoutPort: turnoutPort,
|
|
|
|
}
|
|
|
|
repo.Signals = append(repo.Signals, signal)
|
|
|
|
}
|
|
|
|
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{
|
2023-09-21 14:54:27 +08:00
|
|
|
Id: GetDeviceUidByCommonId(mapId, data.Common.Id, data),
|
2023-09-20 15:14:40 +08:00
|
|
|
Km: convertKm(data.KilometerSystem),
|
|
|
|
SectionId: sectionId,
|
|
|
|
TurnoutPort: turnoutPort,
|
|
|
|
}
|
|
|
|
repo.Transponders = append(repo.Transponders, responder)
|
|
|
|
}
|
|
|
|
slopeKsMap := make(map[string]*graphicData.SlopeKiloMarker)
|
|
|
|
for _, data := range storage.SlopeKiloMarker {
|
|
|
|
slopeKsMap[data.Common.Id] = data
|
2023-09-21 14:54:27 +08:00
|
|
|
repo.KilometerConverts = append(repo.KilometerConverts, buildKmConverts(data.KilometerSystem)...)
|
2023-09-20 15:14:40 +08:00
|
|
|
}
|
|
|
|
curveKsMap := make(map[string]*graphicData.CurvatureKiloMarker)
|
|
|
|
for _, data := range storage.CurvatureKiloMarker {
|
|
|
|
curveKsMap[data.Common.Id] = data
|
2023-09-21 14:54:27 +08:00
|
|
|
repo.KilometerConverts = append(repo.KilometerConverts, buildKmConverts(data.KilometerSystem)...)
|
2023-09-20 15:14:40 +08:00
|
|
|
}
|
|
|
|
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{
|
2023-09-21 14:54:27 +08:00
|
|
|
Id: GetDeviceUidByCommonId(mapId, data.Common.Id, data),
|
2023-09-20 15:14:40 +08:00
|
|
|
Kms: kms,
|
|
|
|
Degree: data.SlopeNumber,
|
|
|
|
}
|
|
|
|
repo.Slopes = append(repo.Slopes, slope)
|
|
|
|
}
|
|
|
|
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{
|
2023-09-21 14:54:27 +08:00
|
|
|
Id: GetDeviceUidByCommonId(mapId, data.Common.Id, data),
|
2023-09-20 15:14:40 +08:00
|
|
|
Kms: kms,
|
|
|
|
Radius: data.CurvatureNumber,
|
|
|
|
}
|
|
|
|
repo.SectionalCurvatures = append(repo.SectionalCurvatures, slope)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2023-09-21 14:54:27 +08:00
|
|
|
for id := range turnoutMap {
|
2023-09-20 15:14:40 +08:00
|
|
|
turnoutIds = append(turnoutIds, id)
|
|
|
|
}
|
|
|
|
return turnoutIds
|
|
|
|
}
|
|
|
|
|
|
|
|
func buildKmConverts(ksList []*graphicData.KilometerSystem) []*proto.KilometerConvert {
|
|
|
|
var kmConverts []*proto.KilometerConvert
|
|
|
|
for i, ks := range ksList {
|
|
|
|
if ks.Kilometer == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
for j := i + 1; j < len(ksList); j++ {
|
|
|
|
if ks.Kilometer == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
kmConverts = append(kmConverts, buildKmConvert(ks, ksList[j]))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return kmConverts
|
|
|
|
}
|
|
|
|
|
|
|
|
func buildKmConvert(ks1 *graphicData.KilometerSystem, ks2 *graphicData.KilometerSystem) *proto.KilometerConvert {
|
|
|
|
return &proto.KilometerConvert{
|
|
|
|
KmA: convertKm(ks1),
|
|
|
|
KmB: convertKm(ks2),
|
|
|
|
SameTrend: false,
|
|
|
|
}
|
|
|
|
}
|