Compare commits
No commits in common. "1a610c01baa6058c0b4659f1067ea845498e2765" and "b3271b497adc0158e86bccbce581db9f805bd233" have entirely different histories.
1a610c01ba
...
b3271b497a
@ -11,59 +11,23 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
slog.SetLogLoggerLevel(slog.LevelDebug)
|
// slog.SetLogLoggerLevel(slog.LevelDebug)
|
||||||
// slog.SetLogLoggerLevel(slog.LevelInfo)
|
slog.SetLogLoggerLevel(slog.LevelInfo)
|
||||||
repo1 := repository.NewRepository("test1")
|
repo1 := repository.NewRepository("test1")
|
||||||
rtssGraphicStorage := data_proto.GetXian6STYG()
|
rtssGraphicStorage := data_proto.GetXian6STYG()
|
||||||
dataMapping := repository.NewDataMapping("1", rtssGraphicStorage)
|
dataMapping := repository.NewDataMapping("1", rtssGraphicStorage)
|
||||||
repo1.DataMapping["1"] = dataMapping
|
repo1.DataMapping["1"] = dataMapping
|
||||||
basicDataMappingAndModelBuild(dataMapping, repo1)
|
// log.Println(rtssGraphicStorage.Stations)
|
||||||
|
// log.Println(rtssGraphicStorage.Section)
|
||||||
// 构建公里标转换器
|
// log.Println(rtssGraphicStorage.Turnouts)
|
||||||
buildKilometerMarkConverters(dataMapping, repo1)
|
for _, station := range rtssGraphicStorage.Stations {
|
||||||
|
|
||||||
// 构建区段关系
|
|
||||||
buildSectionRelationships(dataMapping, repo1)
|
|
||||||
// 构建道岔关系
|
|
||||||
buildTurnoutRelationships(dataMapping, repo1)
|
|
||||||
// 检查区段、道岔通道连接关系
|
|
||||||
err := repo1.CheckSectionAndTurnoutPipeLink()
|
|
||||||
if err != nil {
|
|
||||||
slog.Error("区段道岔连接关系检查错误", "errMsg", err)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
slog.Info("区段、道岔连接关系检查通过")
|
|
||||||
}
|
|
||||||
// 构建区段、道岔公里标
|
|
||||||
buildKilometerMark(dataMapping, repo1)
|
|
||||||
err = repo1.CheckSectionAndTurnoutPortKms()
|
|
||||||
if err != nil {
|
|
||||||
slog.Error("区段道岔公里标检查错误", "errMsg", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 构建link/linknode
|
|
||||||
repo1.BuildLinks()
|
|
||||||
// 检查link/linknode
|
|
||||||
err = repo1.CheckLinkAndLinkNodePipeLink()
|
|
||||||
if err != nil {
|
|
||||||
slog.Error("link/linknode连接关系检查错误", "errMsg", err)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
slog.Info("link/linknode连接关系检查通过")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func basicDataMappingAndModelBuild(dataMapping *repository.DataMapping, repo1 *repository.Repository) {
|
|
||||||
// 车站
|
|
||||||
for _, station := range dataMapping.Stations {
|
|
||||||
dataMapping.StationDataMap[station.Common.Id] = station
|
dataMapping.StationDataMap[station.Common.Id] = station
|
||||||
uid := station.Code
|
uid := station.Code
|
||||||
dataMapping.AddIdMapping(repository.NewIdMapping(station.Common.Id, uid))
|
dataMapping.AddIdMapping(repository.NewIdMapping(station.Common.Id, uid))
|
||||||
stationModel := model.NewStation(uid, station.ConcentrationStations)
|
stationModel := model.NewStation(uid, station.ConcentrationStations)
|
||||||
repo1.StationMap[uid] = &modelimpl.Station{StationImpl: stationModel}
|
repo1.StationMap[uid] = &modelimpl.Station{StationImpl: stationModel}
|
||||||
}
|
}
|
||||||
// 物理区段
|
for _, section := range rtssGraphicStorage.Section {
|
||||||
for _, section := range dataMapping.Section {
|
|
||||||
if section.CentralizedStations == nil || len(section.CentralizedStations) == 0 {
|
if section.CentralizedStations == nil || len(section.CentralizedStations) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -74,16 +38,10 @@ func basicDataMappingAndModelBuild(dataMapping *repository.DataMapping, repo1 *r
|
|||||||
dataMapping.SectionDataMap[section.Common.Id] = section
|
dataMapping.SectionDataMap[section.Common.Id] = section
|
||||||
uid := getSectionUid(section, belongStation, dataMapping.GetLineInfo())
|
uid := getSectionUid(section, belongStation, dataMapping.GetLineInfo())
|
||||||
dataMapping.AddIdMapping(repository.NewIdMapping(section.Common.Id, uid))
|
dataMapping.AddIdMapping(repository.NewIdMapping(section.Common.Id, uid))
|
||||||
if section.SectionType == data_proto.Section_Physical {
|
sectionModel := model.NewSection(uid)
|
||||||
sectionModel := model.NewPhysicalSection(uid)
|
repo1.SectionMap[uid] = &modelimpl.Section{SectionImpl: sectionModel}
|
||||||
repo1.PhysicalSectionMap[uid] = &modelimpl.PhysicalSection{PhysicalSectionImpl: sectionModel}
|
|
||||||
} else {
|
|
||||||
tsModel := model.NewTurnoutSection(uid)
|
|
||||||
repo1.TurnoutSectionMap[uid] = tsModel
|
|
||||||
}
|
}
|
||||||
}
|
for _, turnout := range rtssGraphicStorage.Turnouts {
|
||||||
// 道岔
|
|
||||||
for _, turnout := range dataMapping.Turnouts {
|
|
||||||
if turnout.CentralizedStations == nil || len(turnout.CentralizedStations) == 0 {
|
if turnout.CentralizedStations == nil || len(turnout.CentralizedStations) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -97,86 +55,67 @@ func basicDataMappingAndModelBuild(dataMapping *repository.DataMapping, repo1 *r
|
|||||||
turnoutModel := model.NewTurnout(uid)
|
turnoutModel := model.NewTurnout(uid)
|
||||||
repo1.TurnoutMap[uid] = &modelimpl.Turnout{TurnoutImpl: turnoutModel}
|
repo1.TurnoutMap[uid] = &modelimpl.Turnout{TurnoutImpl: turnoutModel}
|
||||||
}
|
}
|
||||||
// 区段检测点
|
|
||||||
for _, axleCounting := range dataMapping.AxleCountings {
|
|
||||||
dataMapping.SectionCheckPointMap[axleCounting.Common.Id] = axleCounting
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildKilometerMarkConverters(dataMapping *repository.DataMapping, repo1 *repository.Repository) {
|
// 构建区段关系
|
||||||
if dataMapping.KilometerConvertList == nil || len(dataMapping.KilometerConvertList) == 0 {
|
buildSectionRelationships(dataMapping, repo1)
|
||||||
slog.Info("没有公里标转换数据")
|
// 构建道岔关系
|
||||||
|
buildTurnoutRelationships(dataMapping, repo1)
|
||||||
|
// 检查区段、道岔通道连接关系
|
||||||
|
err := repo1.CheckPipeLink()
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("区段道岔连接关系检查错误", "errMsg", err)
|
||||||
return
|
return
|
||||||
|
} else {
|
||||||
|
slog.Info("区段、道岔连接关系检查通过")
|
||||||
}
|
}
|
||||||
for _, kmConverter := range dataMapping.KilometerConvertList {
|
// 构建区段、道岔公里标
|
||||||
km1 := convertKs2Km(kmConverter.KmA)
|
buildKilometerMark(dataMapping, repo1)
|
||||||
km2 := convertKs2Km(kmConverter.KmB)
|
// 构建link/linknode
|
||||||
repo1.KilometerMarkConverters = append(repo1.KilometerMarkConverters,
|
repo1.BuildLinks()
|
||||||
model.NewKilometerMarkConverter(km1, km2, kmConverter.SameTrend))
|
// 检查link/linknode
|
||||||
|
err = repo1.CheckPipeLink()
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("link/linknode连接关系检查错误", "errMsg", err)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
slog.Info("link/linknode连接关系检查通过")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertKs2Km(ks *data_proto.KilometerSystem) *model.KilometerMark {
|
|
||||||
return model.NewKilometerMark(ks.CoordinateSystem, ks.Kilometer)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建区段、道岔公里标
|
// 构建区段、道岔公里标
|
||||||
func buildKilometerMark(dataMapping *repository.DataMapping, repo1 *repository.Repository) {
|
func buildKilometerMark(dataMapping *repository.DataMapping, repo1 *repository.Repository) {
|
||||||
for _, turnout := range dataMapping.TurnoutDataMap {
|
|
||||||
if len(turnout.KilometerSystem) == 0 {
|
|
||||||
repo1.BuildErrorInfos = append(repo1.BuildErrorInfos, fmt.Errorf("构建区段、道岔公里标数据错误:道岔[id=%d]未关联任何公里标", turnout.Common.Id))
|
|
||||||
} else {
|
|
||||||
km := convertKs2Km(turnout.KilometerSystem[0])
|
|
||||||
turnoutModel := repo1.TurnoutMap[dataMapping.IdMappingMap[turnout.Common.Id].Uid]
|
|
||||||
turnoutModel.(*modelimpl.Turnout).Km = km
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, checkpoint := range dataMapping.AxleCountings {
|
for _, checkpoint := range dataMapping.AxleCountings {
|
||||||
if checkpoint.AxleCountingRef == nil || len(checkpoint.AxleCountingRef) == 0 {
|
if checkpoint.AxleCountingRef == nil || len(checkpoint.AxleCountingRef) == 0 {
|
||||||
repo1.BuildErrorInfos = append(repo1.BuildErrorInfos, fmt.Errorf("构建区段、道岔公里标数据错误:检测点[id=%d]未关联任何区段、道岔", checkpoint.Common.Id))
|
repo1.BuildErrorInfos = append(repo1.BuildErrorInfos, fmt.Errorf("构建区段、道岔公里标错误:检测点[id=%d]未关联任何区段、道岔", checkpoint.Common.Id))
|
||||||
}
|
}
|
||||||
for _, linkship := range checkpoint.AxleCountingRef {
|
for _, linkship := range checkpoint.AxleCountingRef {
|
||||||
slog.Debug("区段检测点关联数据", "code", checkpoint.Code, "linkship", fmt.Sprintf("{type=%s, id=%d, port=%s}", linkship.DeviceType, linkship.Id, linkship.DevicePort))
|
slog.Info("区段检测点关联数据", "code", checkpoint.Code, "linkship", fmt.Sprintf("{type=%s, id=%d, port=%s}", linkship.DeviceType, linkship.Id, linkship.DevicePort))
|
||||||
idmapping := dataMapping.IdMappingMap[linkship.Id]
|
idmapping := dataMapping.IdMappingMap[linkship.Id]
|
||||||
if idmapping == nil {
|
if idmapping == nil {
|
||||||
repo1.BuildErrorInfos = append(repo1.BuildErrorInfos, fmt.Errorf("构建区段、道岔公里标数据错误:检测点[id=%d]关联的{type=%s,id=%d}不存在", checkpoint.Common.Id, linkship.DeviceType, linkship.Id))
|
repo1.BuildErrorInfos = append(repo1.BuildErrorInfos, fmt.Errorf("构建区段、道岔公里标错误:检测点[id=%d]关联的{type=%s,id=%d}不存在", checkpoint.Common.Id, linkship.DeviceType, linkship.Id))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if linkship.DeviceType == data_proto.RelatedRef_Section {
|
if linkship.DeviceType == data_proto.RelatedRef_Section {
|
||||||
sectionModel, ok := repo1.PhysicalSectionMap[idmapping.Uid]
|
sectionModel := repo1.SectionMap[idmapping.Uid]
|
||||||
if !ok {
|
if sectionModel == nil {
|
||||||
panic(fmt.Errorf("构建区段、道岔公里标数据错误:检测点[id=%d]关联的区段模型[uid=%s]不存在", checkpoint.Common.Id, idmapping.Uid))
|
panic(fmt.Errorf("构建区段、道岔公里标错误:检测点[id=%d]关联的区段模型[uid=%s]不存在", checkpoint.Common.Id, idmapping.Uid))
|
||||||
}
|
}
|
||||||
km := convertKs2Km(checkpoint.KilometerSystem)
|
sectionModel.(*modelimpl.Section).PaKm = model.NewKilometerMark(checkpoint.KilometerSystem.CoordinateSystem, convertKmDirection(checkpoint.KilometerSystem.Direction), checkpoint.KilometerSystem.Kilometer)
|
||||||
if linkship.DevicePort == data_proto.RelatedRef_A {
|
|
||||||
sectionModel.(*modelimpl.PhysicalSection).PaKm = km
|
|
||||||
} else if linkship.DevicePort == data_proto.RelatedRef_B {
|
|
||||||
sectionModel.(*modelimpl.PhysicalSection).PbKm = km
|
|
||||||
} else {
|
|
||||||
panic(fmt.Errorf("构建区段、道岔公里标数据错误:检测点[id=%d]关联的区段模型[uid=%s]未知的端口类型: %v", checkpoint.Common.Id, idmapping.Uid, linkship.DevicePort))
|
|
||||||
}
|
|
||||||
} else if linkship.DeviceType == data_proto.RelatedRef_Turnout {
|
|
||||||
turnoutModel, ok := repo1.TurnoutMap[idmapping.Uid]
|
|
||||||
if !ok {
|
|
||||||
panic(fmt.Errorf("构建区段、道岔公里标数据错误:检测点[id=%d]关联的道岔模型[uid=%s]不存在", checkpoint.Common.Id, idmapping.Uid))
|
|
||||||
}
|
|
||||||
km := convertKs2Km(checkpoint.KilometerSystem)
|
|
||||||
if linkship.DevicePort == data_proto.RelatedRef_A {
|
|
||||||
turnoutModel.(*modelimpl.Turnout).PaKm = km
|
|
||||||
} else if linkship.DevicePort == data_proto.RelatedRef_B {
|
|
||||||
turnoutModel.(*modelimpl.Turnout).PbKm = km
|
|
||||||
} else if linkship.DevicePort == data_proto.RelatedRef_C {
|
|
||||||
turnoutModel.(*modelimpl.Turnout).PcKm = km
|
|
||||||
} else {
|
|
||||||
panic(fmt.Errorf("构建区段、道岔公里标数据错误:检测点[id=%d]关联的道岔模型[uid=%s]未知的端口类型: %v", checkpoint.Common.Id, idmapping.Uid, linkship.DevicePort))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic(fmt.Errorf("构建区段、道岔公里标数据错误:检测点[id=%d]未知的关联设备类型: %v", checkpoint.Common.Id, linkship.DeviceType))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertKmDirection(kddata data_proto.KilometerSystem_Direction) model.OperationDirection {
|
||||||
|
if kddata == data_proto.KilometerSystem_LEFT {
|
||||||
|
return model.OperationDirectionDown
|
||||||
|
}
|
||||||
|
if kddata == data_proto.KilometerSystem_RIGHT {
|
||||||
|
return model.OperationDirectionUp
|
||||||
|
}
|
||||||
|
panic(fmt.Errorf("未知的公里标方向类型: %v", kddata))
|
||||||
|
}
|
||||||
|
|
||||||
func buildTurnoutRelationships(dataMapping *repository.DataMapping, repo1 *repository.Repository) {
|
func buildTurnoutRelationships(dataMapping *repository.DataMapping, repo1 *repository.Repository) {
|
||||||
for _, turnout := range dataMapping.TurnoutDataMap {
|
for _, turnout := range dataMapping.TurnoutDataMap {
|
||||||
idmapping := dataMapping.IdMappingMap[turnout.Common.Id]
|
idmapping := dataMapping.IdMappingMap[turnout.Common.Id]
|
||||||
@ -192,41 +131,13 @@ func buildTurnoutRelationships(dataMapping *repository.DataMapping, repo1 *repos
|
|||||||
|
|
||||||
func buildSectionRelationships(dataMapping *repository.DataMapping, repo1 *repository.Repository) {
|
func buildSectionRelationships(dataMapping *repository.DataMapping, repo1 *repository.Repository) {
|
||||||
for _, section := range dataMapping.SectionDataMap {
|
for _, section := range dataMapping.SectionDataMap {
|
||||||
idmapping := dataMapping.GetIdMapping(section.Common.Id)
|
idmapping := dataMapping.IdMappingMap[section.Common.Id]
|
||||||
if section.SectionType == data_proto.Section_Physical {
|
if idmapping == nil {
|
||||||
sectionModel := repo1.PhysicalSectionMap[idmapping.Uid]
|
panic(fmt.Errorf("构建区段关系错误:idmapping异常为空"))
|
||||||
|
}
|
||||||
|
sectionModel := repo1.SectionMap[idmapping.Uid]
|
||||||
buildSectionPortLinkRelation(section.PaRef, sectionModel, model.PipePortA, repo1, dataMapping)
|
buildSectionPortLinkRelation(section.PaRef, sectionModel, model.PipePortA, repo1, dataMapping)
|
||||||
buildSectionPortLinkRelation(section.PbRef, sectionModel, model.PipePortB, repo1, dataMapping)
|
buildSectionPortLinkRelation(section.PbRef, sectionModel, model.PipePortB, repo1, dataMapping)
|
||||||
} else {
|
|
||||||
tsModel := repo1.TurnoutSectionMap[idmapping.Uid]
|
|
||||||
turnoutPorts := make(map[uint32]map[model.PipePort]struct{})
|
|
||||||
for _, axleId := range section.AxleCountings {
|
|
||||||
slog.Debug("区段关联检测点", "sectionId", section.Common.Id, "axleId", axleId)
|
|
||||||
axleCounting := dataMapping.SectionCheckPointMap[axleId]
|
|
||||||
if axleCounting == nil {
|
|
||||||
repo1.BuildErrorInfos = append(repo1.BuildErrorInfos, fmt.Errorf("构建区段关系错误:区段[id=%d]关联的检测点[id=%d]不存在", section.Common.Id, axleId))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, ref := range axleCounting.AxleCountingRef {
|
|
||||||
if ref.DeviceType == data_proto.RelatedRef_Turnout {
|
|
||||||
portMap := turnoutPorts[ref.Id]
|
|
||||||
if portMap == nil {
|
|
||||||
portMap = make(map[model.PipePort]struct{})
|
|
||||||
turnoutPorts[ref.Id] = portMap
|
|
||||||
}
|
|
||||||
portMap[convertPort(ref.DevicePort)] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
slog.Debug("区段关联检测点关联道岔", "sectionId", section.Common.Id, "turnoutPorts", turnoutPorts)
|
|
||||||
for turnoutId, portMap := range turnoutPorts {
|
|
||||||
if len(portMap) == 3 {
|
|
||||||
turnoutModel := repo1.TurnoutMap[dataMapping.GetIdMapping(turnoutId).Uid]
|
|
||||||
tsModel.AddTurnout(turnoutModel.(*modelimpl.Turnout))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,7 +148,7 @@ func buildTurnoutPortLinkship(pref *data_proto.RelatedRef, sourceModel model.Tur
|
|||||||
if pref.DeviceType == data_proto.RelatedRef_Section {
|
if pref.DeviceType == data_proto.RelatedRef_Section {
|
||||||
idmapping2 := dataMapping.IdMappingMap[pref.Id]
|
idmapping2 := dataMapping.IdMappingMap[pref.Id]
|
||||||
if idmapping2 != nil {
|
if idmapping2 != nil {
|
||||||
sectionModel := repo1.PhysicalSectionMap[idmapping2.Uid]
|
sectionModel := repo1.SectionMap[idmapping2.Uid]
|
||||||
if sectionModel != nil {
|
if sectionModel != nil {
|
||||||
sourceModel.SetLinkedElement(port, model.NewPipeLink(sectionModel, convertPort(pref.DevicePort)))
|
sourceModel.SetLinkedElement(port, model.NewPipeLink(sectionModel, convertPort(pref.DevicePort)))
|
||||||
}
|
}
|
||||||
@ -254,14 +165,14 @@ func buildTurnoutPortLinkship(pref *data_proto.RelatedRef, sourceModel model.Tur
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildSectionPortLinkRelation(pref *data_proto.RelatedRef, sourceModel model.PhysicalSection, port model.PipePort, repo1 *repository.Repository, dataMapping *repository.DataMapping) {
|
func buildSectionPortLinkRelation(pref *data_proto.RelatedRef, sourceModel model.Section, port model.PipePort, repo1 *repository.Repository, dataMapping *repository.DataMapping) {
|
||||||
if pref == nil {
|
if pref == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if pref.DeviceType == data_proto.RelatedRef_Section {
|
if pref.DeviceType == data_proto.RelatedRef_Section {
|
||||||
idmapping2 := dataMapping.IdMappingMap[pref.Id]
|
idmapping2 := dataMapping.IdMappingMap[pref.Id]
|
||||||
if idmapping2 != nil {
|
if idmapping2 != nil {
|
||||||
sectionModel := repo1.PhysicalSectionMap[idmapping2.Uid]
|
sectionModel := repo1.SectionMap[idmapping2.Uid]
|
||||||
if sectionModel != nil {
|
if sectionModel != nil {
|
||||||
sourceModel.SetLinkedElement(port, model.NewPipeLink(sectionModel, convertPort(pref.DevicePort)))
|
sourceModel.SetLinkedElement(port, model.NewPipeLink(sectionModel, convertPort(pref.DevicePort)))
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,6 @@ package modelimpl
|
|||||||
|
|
||||||
import "joylink.club/rtss-core/model"
|
import "joylink.club/rtss-core/model"
|
||||||
|
|
||||||
type PhysicalSection struct {
|
type Section struct {
|
||||||
*model.PhysicalSectionImpl
|
*model.SectionImpl
|
||||||
}
|
}
|
||||||
|
@ -26,19 +26,10 @@ type DataMapping struct {
|
|||||||
StationDataMap map[uint32]*data_proto.Station
|
StationDataMap map[uint32]*data_proto.Station
|
||||||
SectionDataMap map[uint32]*data_proto.Section
|
SectionDataMap map[uint32]*data_proto.Section
|
||||||
TurnoutDataMap map[uint32]*data_proto.Turnout
|
TurnoutDataMap map[uint32]*data_proto.Turnout
|
||||||
SectionCheckPointMap map[uint32]*data_proto.AxleCounting
|
|
||||||
IdMappingMap map[uint32]*IdMapping
|
IdMappingMap map[uint32]*IdMapping
|
||||||
UidMappingMap map[string]*IdMapping
|
UidMappingMap map[string]*IdMapping
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DataMapping) GetIdMapping(graphicId uint32) *IdMapping {
|
|
||||||
mapping, ok := d.IdMappingMap[graphicId]
|
|
||||||
if !ok {
|
|
||||||
panic(fmt.Sprintf("不存在{graphicId=%v}的IdMapping数据", graphicId))
|
|
||||||
}
|
|
||||||
return mapping
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DataMapping) AddIdMapping(idMapping *IdMapping) {
|
func (d *DataMapping) AddIdMapping(idMapping *IdMapping) {
|
||||||
d.IdMappingMap[idMapping.GraphicId] = idMapping
|
d.IdMappingMap[idMapping.GraphicId] = idMapping
|
||||||
d.UidMappingMap[idMapping.Uid] = idMapping
|
d.UidMappingMap[idMapping.Uid] = idMapping
|
||||||
@ -56,7 +47,6 @@ func NewDataMapping(id string, storage *data_proto.RtssGraphicStorage) *DataMapp
|
|||||||
StationDataMap: make(map[uint32]*data_proto.Station),
|
StationDataMap: make(map[uint32]*data_proto.Station),
|
||||||
SectionDataMap: make(map[uint32]*data_proto.Section),
|
SectionDataMap: make(map[uint32]*data_proto.Section),
|
||||||
TurnoutDataMap: make(map[uint32]*data_proto.Turnout),
|
TurnoutDataMap: make(map[uint32]*data_proto.Turnout),
|
||||||
SectionCheckPointMap: make(map[uint32]*data_proto.AxleCounting),
|
|
||||||
IdMappingMap: make(map[uint32]*IdMapping),
|
IdMappingMap: make(map[uint32]*IdMapping),
|
||||||
UidMappingMap: make(map[string]*IdMapping),
|
UidMappingMap: make(map[string]*IdMapping),
|
||||||
}
|
}
|
||||||
|
@ -5,22 +5,29 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 公里标
|
// 运营方向(上行/下行)
|
||||||
// 类似地铁线路一般正线都是双线,公里标一般以类似YDK/ZDK开头,
|
type OperationDirection int8
|
||||||
// 虽然从信号布置图上看,YDK/ZDK相近位置的值似乎是一样的,以为他们是同一个坐标系,
|
|
||||||
// 但这种情况的原因其实是因为两条线的起始点很接近,他们依然是两个独立的坐标系。
|
const (
|
||||||
// 左线和右线中间有渡线可以相互切换,但公里标如何转换暂时不清楚,
|
// 上行
|
||||||
// 暂时考虑先通过添加转换配置来实现(比如转换可以配置0或根据道岔处勾股定理大概估算,虽然不同道岔处可能不一样,但暂时不考虑复杂情况)。
|
OperationDirectionUp OperationDirection = 1
|
||||||
|
// 下行
|
||||||
|
OperationDirectionDown OperationDirection = 0
|
||||||
|
)
|
||||||
|
|
||||||
type KilometerMark struct {
|
type KilometerMark struct {
|
||||||
// 公里标坐标系
|
// 公里标坐标系
|
||||||
coordinate string
|
coordinate string
|
||||||
|
// 公里标上下行方向
|
||||||
|
direction OperationDirection
|
||||||
// 公里标值
|
// 公里标值
|
||||||
value int64
|
value int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewKilometerMark(coordinate string, value int64) *KilometerMark {
|
func NewKilometerMark(coordinate string, direction OperationDirection, value int64) *KilometerMark {
|
||||||
return &KilometerMark{
|
return &KilometerMark{
|
||||||
coordinate: coordinate,
|
coordinate: coordinate,
|
||||||
|
direction: direction,
|
||||||
value: value,
|
value: value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,10 +36,6 @@ func (km *KilometerMark) Coordinate() string {
|
|||||||
return km.coordinate
|
return km.coordinate
|
||||||
}
|
}
|
||||||
|
|
||||||
func (km *KilometerMark) Value() int64 {
|
|
||||||
return km.value
|
|
||||||
}
|
|
||||||
|
|
||||||
// 是否为同一坐标系
|
// 是否为同一坐标系
|
||||||
func (km *KilometerMark) IsCoordinateEqual(coordinate string) bool {
|
func (km *KilometerMark) IsCoordinateEqual(coordinate string) bool {
|
||||||
return km.coordinate == coordinate
|
return km.coordinate == coordinate
|
||||||
@ -40,23 +43,12 @@ func (km *KilometerMark) IsCoordinateEqual(coordinate string) bool {
|
|||||||
|
|
||||||
// 公里标转换配置
|
// 公里标转换配置
|
||||||
type KilometerMarkConverter struct {
|
type KilometerMarkConverter struct {
|
||||||
km1 *KilometerMark
|
km1 KilometerMark
|
||||||
km2 *KilometerMark
|
km2 KilometerMark
|
||||||
// 趋势是否相同
|
// 趋势是否相同
|
||||||
trendSame bool
|
trendSame bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewKilometerMarkConverter(km1, km2 *KilometerMark, trendSame bool) *KilometerMarkConverter {
|
|
||||||
if km1 == nil || km2 == nil {
|
|
||||||
panic("km1 or km2 is nil")
|
|
||||||
}
|
|
||||||
return &KilometerMarkConverter{
|
|
||||||
km1: km1,
|
|
||||||
km2: km2,
|
|
||||||
trendSame: trendSame,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (kmc *KilometerMarkConverter) Debug() string {
|
func (kmc *KilometerMarkConverter) Debug() string {
|
||||||
return fmt.Sprintf("{%s<->%s(%s)}", kmc.km1.coordinate, kmc.km2.coordinate, strconv.FormatBool(kmc.trendSame))
|
return fmt.Sprintf("{%s<->%s(%s)}", kmc.km1.coordinate, kmc.km2.coordinate, strconv.FormatBool(kmc.trendSame))
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,19 @@ import (
|
|||||||
|
|
||||||
func TestConvertKilometerMark(t *testing.T) {
|
func TestConvertKilometerMark(t *testing.T) {
|
||||||
// 1. 配置公里标转换关系
|
// 1. 配置公里标转换关系
|
||||||
km1 := NewKilometerMark("YDK", 0)
|
km1 := NewKilometerMark("DBCSK", OperationDirectionUp, 0)
|
||||||
km2 := NewKilometerMark("ZDK", 200)
|
km2 := NewKilometerMark("DCSK", OperationDirectionUp, 200)
|
||||||
kmc1 := NewKilometerMarkConverter(km1, km2, true)
|
kmc1 := &KilometerMarkConverter{
|
||||||
|
km1: *km1,
|
||||||
|
km2: *km2,
|
||||||
|
trendSame: true,
|
||||||
|
}
|
||||||
t.Log(kmc1.Debug())
|
t.Log(kmc1.Debug())
|
||||||
kmc2 := *NewKilometerMarkConverter(km1, km2, false)
|
kmc2 := &KilometerMarkConverter{
|
||||||
|
km1: *km1,
|
||||||
|
km2: *km2,
|
||||||
|
trendSame: false,
|
||||||
|
}
|
||||||
t.Log(kmc2.Debug())
|
t.Log(kmc2.Debug())
|
||||||
|
|
||||||
// 2. 验证公里标转换关系
|
// 2. 验证公里标转换关系
|
||||||
@ -20,12 +28,12 @@ func TestConvertKilometerMark(t *testing.T) {
|
|||||||
expect1 int64
|
expect1 int64
|
||||||
expect2 int64
|
expect2 int64
|
||||||
}{
|
}{
|
||||||
{km: NewKilometerMark("YDK", 0), coordinate: km2.Coordinate(), expect1: 200, expect2: 200},
|
{km: NewKilometerMark("DBCSK", OperationDirectionUp, 0), coordinate: km2.Coordinate(), expect1: 200, expect2: 200},
|
||||||
{km: NewKilometerMark("YDK", 100), coordinate: km2.Coordinate(), expect1: 300, expect2: 100},
|
{km: NewKilometerMark("DBCSK", OperationDirectionUp, 100), coordinate: km2.Coordinate(), expect1: 300, expect2: 100},
|
||||||
{km: NewKilometerMark("YDK", -100), coordinate: km2.Coordinate(), expect1: 100, expect2: 300},
|
{km: NewKilometerMark("DBCSK", OperationDirectionUp, -100), coordinate: km2.Coordinate(), expect1: 100, expect2: 300},
|
||||||
{km: NewKilometerMark("ZDK", 200), coordinate: km1.Coordinate(), expect1: 0, expect2: 0},
|
{km: NewKilometerMark("DCSK", OperationDirectionUp, 200), coordinate: km1.Coordinate(), expect1: 0, expect2: 0},
|
||||||
{km: NewKilometerMark("ZDK", 300), coordinate: km1.Coordinate(), expect1: 100, expect2: -100},
|
{km: NewKilometerMark("DCSK", OperationDirectionUp, 300), coordinate: km1.Coordinate(), expect1: 100, expect2: -100},
|
||||||
{km: NewKilometerMark("ZDK", 100), coordinate: km1.Coordinate(), expect1: -100, expect2: 100},
|
{km: NewKilometerMark("DCSK", OperationDirectionUp, 100), coordinate: km1.Coordinate(), expect1: -100, expect2: 100},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
result1 := kmc1.Convert(test.km, test.coordinate)
|
result1 := kmc1.Convert(test.km, test.coordinate)
|
||||||
|
@ -3,105 +3,27 @@ package model
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type RR = io.Writer
|
type RR = io.Writer
|
||||||
|
|
||||||
// 轨道
|
// 轨道
|
||||||
// 默认坐标系为以A端为起点,B端为终点的单轴坐标系
|
|
||||||
type Link interface {
|
type Link interface {
|
||||||
TwoPortsPipeElement
|
TwoPortsPipeElement
|
||||||
IsEquals(pla *PipeLink, plb *PipeLink) bool
|
IsEquals(pla *PipeLink, plb *PipeLink) bool
|
||||||
// 获取轨道长度,单位:毫米mm
|
|
||||||
GetLength() int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 轨道连接点(使用的是道岔岔心),然后有三个方向A/B/C,还是使用PipePort枚举,但表示的含义是方向,而不是道岔的三个端口
|
// 轨道连接点
|
||||||
type LinkNode interface {
|
type LinkNode interface {
|
||||||
Turnout() Turnout
|
Turnout() Turnout
|
||||||
ThreePortsPipeElement
|
ThreePortsPipeElement
|
||||||
}
|
}
|
||||||
|
|
||||||
type LinkDirection int
|
|
||||||
|
|
||||||
const (
|
|
||||||
LinkDirectionB2A LinkDirection = -1
|
|
||||||
LinkDirectionA2B LinkDirection = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
// link位置
|
|
||||||
type LinkPosition struct {
|
|
||||||
link Link
|
|
||||||
pos int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewLinkPosition(link Link, pos int64) *LinkPosition {
|
|
||||||
return &LinkPosition{
|
|
||||||
link: link,
|
|
||||||
pos: pos,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lp *LinkPosition) Link() Link {
|
|
||||||
return lp.link
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lp *LinkPosition) Position() int64 {
|
|
||||||
return lp.pos
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lp *LinkPosition) IsIn(linkRange LinkRange) bool {
|
|
||||||
return lp.link.Uid() == linkRange.link.Uid() && lp.IsInRange(linkRange.start, linkRange.end)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lp *LinkPosition) IsInRange(a int64, b int64) bool {
|
|
||||||
start := int64(math.Min(float64(a), float64(b)))
|
|
||||||
end := int64(math.Max(float64(a), float64(b)))
|
|
||||||
return lp.pos >= start && lp.pos <= end
|
|
||||||
}
|
|
||||||
|
|
||||||
// 移动位置
|
|
||||||
func (lp *LinkPosition) Move(len uint32, direction LinkDirection) (overflow bool) {
|
|
||||||
lp.pos += int64(len) * int64(direction)
|
|
||||||
if lp.pos > lp.link.GetLength() || lp.pos < 0 {
|
|
||||||
overflow = true
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// link范围
|
|
||||||
type LinkRange struct {
|
|
||||||
link Link
|
|
||||||
start int64
|
|
||||||
end int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构造link范围
|
|
||||||
// link: 轨道 不能为nil
|
|
||||||
// a: 起始位置,b: 结束位置,单位:毫米mm,a和b不能相等
|
|
||||||
func NewLinkRange(link Link, a int64, b int64) *LinkRange {
|
|
||||||
if link == nil {
|
|
||||||
panic("构造LinkRange错误: link不能为空")
|
|
||||||
}
|
|
||||||
if a == b {
|
|
||||||
panic("构造LinkRange错误: a和b不能相等")
|
|
||||||
}
|
|
||||||
start := int64(math.Min(float64(a), float64(b)))
|
|
||||||
end := int64(math.Max(float64(a), float64(b)))
|
|
||||||
return &LinkRange{
|
|
||||||
link: link,
|
|
||||||
start: start,
|
|
||||||
end: end,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ Link = (*LinkImpl)(nil)
|
var _ Link = (*LinkImpl)(nil)
|
||||||
var _ LinkNode = (*LinkNodeImpl)(nil)
|
var _ LinkNode = (*LinkNodeImpl)(nil)
|
||||||
|
|
||||||
type LinkImpl struct {
|
type LinkImpl struct {
|
||||||
*TwoPortsPipeElementImpl
|
*TwoPortsPipeElementImpl
|
||||||
len int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type LinkNodeImpl struct {
|
type LinkNodeImpl struct {
|
||||||
@ -134,14 +56,6 @@ func (l *LinkImpl) IsEquals(pla *PipeLink, plb *PipeLink) bool {
|
|||||||
return l.uid == buildLinkUid(pla, plb) || l.uid == buildLinkUid(plb, pla)
|
return l.uid == buildLinkUid(pla, plb) || l.uid == buildLinkUid(plb, pla)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LinkImpl) GetLength() int64 {
|
|
||||||
return l.len
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LinkImpl) SetLength(len int64) {
|
|
||||||
l.len = len
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *LinkNodeImpl) Turnout() Turnout {
|
func (n *LinkNodeImpl) Turnout() Turnout {
|
||||||
return n.turnout
|
return n.turnout
|
||||||
}
|
}
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
package model_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"joylink.club/rtss-core/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestLinkPositionInRange(t *testing.T) {
|
|
||||||
// 1. 配置连接关系
|
|
||||||
turnout := model.NewTurnout("1")
|
|
||||||
ln1 := model.NewLinkNode(turnout)
|
|
||||||
pla := model.NewPipeLink(ln1, model.PipePortA)
|
|
||||||
link1 := model.NewLink(pla, nil)
|
|
||||||
link1.SetLength(1000)
|
|
||||||
linkPos1 := model.NewLinkPosition(link1, 100)
|
|
||||||
// 2. 验证连接关系
|
|
||||||
inRangeTests := []struct {
|
|
||||||
start int64
|
|
||||||
end int64
|
|
||||||
expect bool
|
|
||||||
}{
|
|
||||||
{start: 0, end: 50, expect: false},
|
|
||||||
{start: 0, end: 100, expect: true},
|
|
||||||
{start: 100, end: 101, expect: true},
|
|
||||||
{start: 100, end: 100, expect: true},
|
|
||||||
{start: 101, end: 100, expect: true},
|
|
||||||
{start: 101, end: 200, expect: false},
|
|
||||||
}
|
|
||||||
for _, test := range inRangeTests {
|
|
||||||
in := linkPos1.IsInRange(test.start, test.end)
|
|
||||||
if in != test.expect {
|
|
||||||
t.Errorf("expect: %v, but got: %v", test.expect, in)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLinkPositionAdd(t *testing.T) {
|
|
||||||
// 1. 配置连接关系
|
|
||||||
turnout := model.NewTurnout("1")
|
|
||||||
ln1 := model.NewLinkNode(turnout)
|
|
||||||
pla := model.NewPipeLink(ln1, model.PipePortA)
|
|
||||||
link1 := model.NewLink(pla, nil)
|
|
||||||
link1.SetLength(1000)
|
|
||||||
// 2. 验证连接关系
|
|
||||||
addTests := []struct {
|
|
||||||
len uint32
|
|
||||||
direction model.LinkDirection
|
|
||||||
expect bool
|
|
||||||
expectValue int64
|
|
||||||
}{
|
|
||||||
{len: 0, direction: model.LinkDirectionA2B, expect: false, expectValue: 100},
|
|
||||||
{len: 10, direction: model.LinkDirectionA2B, expect: false, expectValue: 110},
|
|
||||||
{len: 10, direction: model.LinkDirectionB2A, expect: false, expectValue: 90},
|
|
||||||
{len: 1000, direction: model.LinkDirectionA2B, expect: true, expectValue: 1100},
|
|
||||||
{len: 1000, direction: model.LinkDirectionB2A, expect: true, expectValue: -900},
|
|
||||||
}
|
|
||||||
for _, test := range addTests {
|
|
||||||
linkPos1 := model.NewLinkPosition(link1, 100)
|
|
||||||
overflow := linkPos1.Move(test.len, test.direction)
|
|
||||||
if overflow != test.expect {
|
|
||||||
t.Errorf("expect: %v, but got: %v", test.expect, overflow)
|
|
||||||
}
|
|
||||||
if linkPos1.Position() != test.expectValue {
|
|
||||||
t.Errorf("expect: %v, but got: %v", test.expectValue, linkPos1.Position())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -80,7 +80,7 @@ type ThreePortsPipeElement interface {
|
|||||||
|
|
||||||
func checkPipePortLink(pe PipeElement, port PipePort, pipeLink *PipeLink) error {
|
func checkPipePortLink(pe PipeElement, port PipePort, pipeLink *PipeLink) error {
|
||||||
if pipeLink == nil {
|
if pipeLink == nil {
|
||||||
slog.Debug("检查通道端口连接关系", "通道端口", DebugPipeLink(pe, port), "连接关系", "无连接")
|
slog.Debug("检查通道端口连接关系", "通道端口", DebugPipeLink(pe, port), "连接关系", "未连接")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
slog.Debug("检查通道端口连接关系", "通道端口", DebugPipeLink(pe, port), "连接关系", pipeLink.Debug())
|
slog.Debug("检查通道端口连接关系", "通道端口", DebugPipeLink(pe, port), "连接关系", pipeLink.Debug())
|
||||||
@ -138,24 +138,21 @@ func (t *TwoPortsPipeElementImpl) OppositePipeLink(port PipePort) *PipeLink {
|
|||||||
func (s *TwoPortsPipeElementImpl) SetLinkedElement(port PipePort, pipeLink *PipeLink) error {
|
func (s *TwoPortsPipeElementImpl) SetLinkedElement(port PipePort, pipeLink *PipeLink) error {
|
||||||
if port == PipePortA {
|
if port == PipePortA {
|
||||||
if s.paPipeLink != nil {
|
if s.paPipeLink != nil {
|
||||||
return fmt.Errorf("区段{uid=%s}端口A已经设置关联元素: {uid=%s, port=%s}", s.uid, s.paPipeLink.Pipe.Uid(), s.paPipeLink.Port)
|
return fmt.Errorf("区段uid=%s端口A已经设置关联元素: {uid=%s, port=%s}", s.uid, s.paPipeLink.Pipe.Uid(), s.paPipeLink.Port)
|
||||||
}
|
}
|
||||||
s.paPipeLink = pipeLink
|
s.paPipeLink = pipeLink
|
||||||
} else if port == PipePortB {
|
} else if port == PipePortB {
|
||||||
if s.pbPipeLink != nil {
|
if s.pbPipeLink != nil {
|
||||||
return fmt.Errorf("区段{uid=%s}端口B已经设置关联元素: {uid=%s, port=%s}", s.uid, s.pbPipeLink.Pipe.Uid(), s.pbPipeLink.Port)
|
return fmt.Errorf("区段uid=%s端口B已经设置关联元素: {uid=%s, port=%s}", s.uid, s.pbPipeLink.Pipe.Uid(), s.pbPipeLink.Port)
|
||||||
}
|
}
|
||||||
s.pbPipeLink = pipeLink
|
s.pbPipeLink = pipeLink
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("区段{uid=%s}设置关联元素端口错误,不支持C端口", s.uid)
|
return fmt.Errorf("区段uid=%s设置关联元素端口错误,不支持C端口", s.uid)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TwoPortsPipeElementImpl) CheckPipeLink() error {
|
func (s *TwoPortsPipeElementImpl) CheckPipeLink() error {
|
||||||
if s.paPipeLink == nil && s.pbPipeLink == nil {
|
|
||||||
return fmt.Errorf("区段{uid=%s}两端都没有关联通道连接关系", s.uid)
|
|
||||||
}
|
|
||||||
err := checkPipePortLink(s, PipePortA, s.paPipeLink)
|
err := checkPipePortLink(s, PipePortA, s.paPipeLink)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -204,17 +201,17 @@ func (t *ThreePortsPipeElementImpl) GetLinkedElement(port PipePort) *PipeLink {
|
|||||||
func (t *ThreePortsPipeElementImpl) SetLinkedElement(port PipePort, pipeLink *PipeLink) error {
|
func (t *ThreePortsPipeElementImpl) SetLinkedElement(port PipePort, pipeLink *PipeLink) error {
|
||||||
if port == PipePortA {
|
if port == PipePortA {
|
||||||
if t.paPipeLink != nil {
|
if t.paPipeLink != nil {
|
||||||
return fmt.Errorf("道岔{uid=%s}端口A已经设置关联元素: {uid=%s, port=%s}", t.uid, t.paPipeLink.Pipe.Uid(), t.paPipeLink.Port)
|
return fmt.Errorf("道岔uid=%s端口A已经设置关联元素: {uid=%s, port=%s}", t.uid, t.paPipeLink.Pipe.Uid(), t.paPipeLink.Port)
|
||||||
}
|
}
|
||||||
t.paPipeLink = pipeLink
|
t.paPipeLink = pipeLink
|
||||||
} else if port == PipePortB {
|
} else if port == PipePortB {
|
||||||
if t.pbPipeLink != nil {
|
if t.pbPipeLink != nil {
|
||||||
return fmt.Errorf("道岔{uid=%s}端口B已经设置关联元素: {uid=%s, port=%s}", t.uid, t.pbPipeLink.Pipe.Uid(), t.pbPipeLink.Port)
|
return fmt.Errorf("道岔uid=%s端口B已经设置关联元素: {uid=%s, port=%s}", t.uid, t.pbPipeLink.Pipe.Uid(), t.pbPipeLink.Port)
|
||||||
}
|
}
|
||||||
t.pbPipeLink = pipeLink
|
t.pbPipeLink = pipeLink
|
||||||
} else if port == PipePortC {
|
} else if port == PipePortC {
|
||||||
if t.pcPipeLink != nil {
|
if t.pcPipeLink != nil {
|
||||||
return fmt.Errorf("道岔{uid=%s}端口C已经设置关联元素: {uid=%s, port=%s}", t.uid, t.pcPipeLink.Pipe.Uid(), t.pcPipeLink.Port)
|
return fmt.Errorf("道岔uid=%s端口C已经设置关联元素: {uid=%s, port=%s}", t.uid, t.pcPipeLink.Pipe.Uid(), t.pcPipeLink.Port)
|
||||||
}
|
}
|
||||||
t.pcPipeLink = pipeLink
|
t.pcPipeLink = pipeLink
|
||||||
}
|
}
|
||||||
|
101
model/section.go
101
model/section.go
@ -1,122 +1,33 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 区段
|
// 区段
|
||||||
type Section interface {
|
type Section interface {
|
||||||
RtssModel
|
|
||||||
}
|
|
||||||
|
|
||||||
// 物理区段(非道岔区段)
|
|
||||||
// 用于和道岔连接构成轨道网络
|
|
||||||
// 然后使用轨道网络构建link和linkNode形成新的以道岔岔心为节点的网络,用于路径计算等
|
|
||||||
type PhysicalSection interface {
|
|
||||||
TwoPortsPipeElement
|
TwoPortsPipeElement
|
||||||
// 获取A端和B端的公里标
|
// 获取A端和B端的公里标
|
||||||
GetPaKm() *KilometerMark
|
GetPaKm() *KilometerMark
|
||||||
GetPbKm() *KilometerMark
|
GetPbKm() *KilometerMark
|
||||||
// 计算各个端口到岔心的距离
|
|
||||||
CalculateDistance(calculateKmDistance func(km1, km2 *KilometerMark) (int64, error)) error
|
|
||||||
GetLength() int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 道岔区段(道岔物理区段)
|
type SectionImpl struct {
|
||||||
// 道岔处的由至少3个及以上的计轴或绝缘节所确定的区段
|
|
||||||
type TurnoutSection interface {
|
|
||||||
Section
|
|
||||||
// 获取关联的道岔列表
|
|
||||||
GetTurnouts() []Turnout
|
|
||||||
// 添加关联道岔
|
|
||||||
AddTurnout(turnout Turnout)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 逻辑区段
|
|
||||||
// 是在物理区段基础上进一步细分的区段,为了相对更精细的列车追踪和进路触发等控制
|
|
||||||
// 最终映射到link上,做相应的逻辑处理
|
|
||||||
type LogicalSection interface {
|
|
||||||
Section
|
|
||||||
// 所属物理区段(可能是一般物理区段也可能是道岔区段)
|
|
||||||
BelongSection() Section
|
|
||||||
// 获取A端和B端的公里标
|
|
||||||
GetPaKm() *KilometerMark
|
|
||||||
GetPbKm() *KilometerMark
|
|
||||||
}
|
|
||||||
|
|
||||||
type PhysicalSectionImpl struct {
|
|
||||||
*TwoPortsPipeElementImpl
|
*TwoPortsPipeElementImpl
|
||||||
PaKm *KilometerMark
|
PaKm *KilometerMark
|
||||||
PbKm *KilometerMark
|
PbKm *KilometerMark
|
||||||
len int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ PhysicalSection = (*PhysicalSectionImpl)(nil)
|
var _ Section = (*SectionImpl)(nil)
|
||||||
|
|
||||||
func NewPhysicalSection(uid string) *PhysicalSectionImpl {
|
func NewSection(uid string) *SectionImpl {
|
||||||
return &PhysicalSectionImpl{
|
return &SectionImpl{
|
||||||
TwoPortsPipeElementImpl: &TwoPortsPipeElementImpl{
|
TwoPortsPipeElementImpl: &TwoPortsPipeElementImpl{
|
||||||
uid: uid,
|
uid: uid,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PhysicalSectionImpl) GetLength() int64 {
|
func (s *SectionImpl) GetPaKm() *KilometerMark {
|
||||||
return s.len
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *PhysicalSectionImpl) CalculateDistance(calculateKmDistance func(km1, km2 *KilometerMark) (int64, error)) error {
|
|
||||||
if s.PaKm == nil || s.PbKm == nil {
|
|
||||||
return fmt.Errorf("区段公里标不能为空")
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
s.len, err = calculateKmDistance(s.PaKm, s.PbKm)
|
|
||||||
slog.Debug("计算物理区段公里标距离", "uid", s.Uid(), "length", s.len)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *PhysicalSectionImpl) GetPaKm() *KilometerMark {
|
|
||||||
return s.PaKm
|
return s.PaKm
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PhysicalSectionImpl) GetPbKm() *KilometerMark {
|
func (s *SectionImpl) GetPbKm() *KilometerMark {
|
||||||
return s.PbKm
|
return s.PbKm
|
||||||
}
|
}
|
||||||
|
|
||||||
type SectionImpl struct {
|
|
||||||
uid string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SectionImpl) Uid() string {
|
|
||||||
return s.uid
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ TurnoutSection = (*TurnoutSectionImpl)(nil)
|
|
||||||
|
|
||||||
type TurnoutSectionImpl struct {
|
|
||||||
*SectionImpl
|
|
||||||
Turnouts []Turnout
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewTurnoutSection(uid string) *TurnoutSectionImpl {
|
|
||||||
return &TurnoutSectionImpl{
|
|
||||||
SectionImpl: &SectionImpl{
|
|
||||||
uid: uid,
|
|
||||||
},
|
|
||||||
Turnouts: make([]Turnout, 0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TurnoutSectionImpl) AddTurnout(turnout Turnout) {
|
|
||||||
for _, exist := range t.Turnouts {
|
|
||||||
if exist.Uid() == turnout.Uid() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
t.Turnouts = append(t.Turnouts, turnout)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TurnoutSectionImpl) GetTurnouts() []Turnout {
|
|
||||||
return t.Turnouts
|
|
||||||
}
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,14 +15,6 @@ type Turnout interface {
|
|||||||
GetPbKm() *KilometerMark
|
GetPbKm() *KilometerMark
|
||||||
// 获取道岔C端公里标
|
// 获取道岔C端公里标
|
||||||
GetPcKm() *KilometerMark
|
GetPcKm() *KilometerMark
|
||||||
// 计算各个端口到岔心的距离
|
|
||||||
CalculateDistances(calculateKmDistance func(km1, km2 *KilometerMark) (int64, error)) error
|
|
||||||
// 获取到指定端口的长度
|
|
||||||
GetLength(port PipePort) int64
|
|
||||||
// 获取A端到B端的距离
|
|
||||||
GetPaPbLength() int64
|
|
||||||
// 获取A端到C端的距离
|
|
||||||
GetPaPcLength() int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Turnout = (*TurnoutImpl)(nil)
|
var _ Turnout = (*TurnoutImpl)(nil)
|
||||||
@ -35,9 +25,6 @@ type TurnoutImpl struct {
|
|||||||
PaKm *KilometerMark
|
PaKm *KilometerMark
|
||||||
PbKm *KilometerMark
|
PbKm *KilometerMark
|
||||||
PcKm *KilometerMark
|
PcKm *KilometerMark
|
||||||
paLen int64
|
|
||||||
pbLen int64
|
|
||||||
pcLen int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTurnout(uid string) *TurnoutImpl {
|
func NewTurnout(uid string) *TurnoutImpl {
|
||||||
@ -51,47 +38,6 @@ func NewTurnout(uid string) *TurnoutImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TurnoutImpl) GetLength(port PipePort) int64 {
|
|
||||||
switch port {
|
|
||||||
case PipePortA:
|
|
||||||
return t.paLen
|
|
||||||
case PipePortB:
|
|
||||||
return t.pbLen
|
|
||||||
case PipePortC:
|
|
||||||
return t.pcLen
|
|
||||||
}
|
|
||||||
panic(fmt.Sprintf("获取道岔指定端口长度异常:错误的端口参数'%s'", port))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TurnoutImpl) GetPaPbLength() int64 {
|
|
||||||
return t.pbLen + t.paLen
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TurnoutImpl) GetPaPcLength() int64 {
|
|
||||||
return t.pcLen + t.paLen
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TurnoutImpl) CalculateDistances(calculateKmDistance func(km1, km2 *KilometerMark) (int64, error)) error {
|
|
||||||
if t.Km == nil || t.PaKm == nil || t.PbKm == nil || t.PcKm == nil {
|
|
||||||
return fmt.Errorf("道岔公里标不能为空")
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
t.paLen, err = calculateKmDistance(t.Km, t.PaKm)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
t.pbLen, err = calculateKmDistance(t.Km, t.PbKm)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
t.pcLen, err = calculateKmDistance(t.Km, t.PcKm)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
slog.Debug("计算道岔公里标距离", "uid", t.Uid(), "A端距离", t.paLen, "B端距离", t.pbLen, "C端距离", t.pcLen)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TurnoutImpl) GetKm() *KilometerMark {
|
func (t *TurnoutImpl) GetKm() *KilometerMark {
|
||||||
return t.Km
|
return t.Km
|
||||||
}
|
}
|
||||||
|
145
repo/repo.go
145
repo/repo.go
@ -4,7 +4,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"math"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"joylink.club/rtss-core/model"
|
"joylink.club/rtss-core/model"
|
||||||
@ -16,16 +15,10 @@ type Repo interface {
|
|||||||
GetStationByUid(uid string) model.Station
|
GetStationByUid(uid string) model.Station
|
||||||
GetSectionByUid(uid string) model.Section
|
GetSectionByUid(uid string) model.Section
|
||||||
GetTurnoutByUid(uid string) model.Turnout
|
GetTurnoutByUid(uid string) model.Turnout
|
||||||
// 检查区段、道岔通道连接关系
|
// 检查通道连接关系
|
||||||
CheckSectionAndTurnoutPipeLink() error
|
CheckPipeLink() error
|
||||||
// 检查区段、道岔公里标
|
|
||||||
CheckSectionAndTurnoutPortKms() error
|
|
||||||
// 检查Link、LinkNode通道连接关系
|
|
||||||
CheckLinkAndLinkNodePipeLink() error
|
|
||||||
// 转换公里标
|
// 转换公里标
|
||||||
ConvertKilometerMark(km *model.KilometerMark, targetCoordinate string) (int64, error)
|
ConvertKilometerMark(km *model.KilometerMark, targetCoordinate string) (int64, error)
|
||||||
// 计算公里标间距离
|
|
||||||
CalculateKmDistance(km1 *model.KilometerMark, km2 *model.KilometerMark) (int64, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Repo = (*RepoImpl)(nil)
|
var _ Repo = (*RepoImpl)(nil)
|
||||||
@ -34,31 +27,26 @@ type RepoImpl struct {
|
|||||||
id string
|
id string
|
||||||
BuildErrorInfos []error
|
BuildErrorInfos []error
|
||||||
StationMap map[string]model.Station
|
StationMap map[string]model.Station
|
||||||
PhysicalSectionMap map[string]model.PhysicalSection
|
SectionMap map[string]model.Section
|
||||||
TurnoutSectionMap map[string]model.TurnoutSection
|
|
||||||
TurnoutMap map[string]model.Turnout
|
TurnoutMap map[string]model.Turnout
|
||||||
LinkNodeMap map[string]model.LinkNode
|
LinkNodeMap map[string]model.LinkNode
|
||||||
LinkMap map[string]model.Link
|
LinkMap map[string]model.Link
|
||||||
KilometerMarkConverters []*model.KilometerMarkConverter
|
KilometerMarkConverters []model.KilometerMarkConverter
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRepo(id string) *RepoImpl {
|
func NewRepo(id string) *RepoImpl {
|
||||||
return &RepoImpl{
|
return &RepoImpl{
|
||||||
id: id,
|
id: id,
|
||||||
StationMap: make(map[string]model.Station),
|
StationMap: make(map[string]model.Station),
|
||||||
PhysicalSectionMap: make(map[string]model.PhysicalSection),
|
SectionMap: make(map[string]model.Section),
|
||||||
TurnoutSectionMap: make(map[string]model.TurnoutSection),
|
|
||||||
TurnoutMap: make(map[string]model.Turnout),
|
TurnoutMap: make(map[string]model.Turnout),
|
||||||
LinkNodeMap: make(map[string]model.LinkNode),
|
LinkNodeMap: make(map[string]model.LinkNode),
|
||||||
LinkMap: make(map[string]model.Link),
|
LinkMap: make(map[string]model.Link),
|
||||||
KilometerMarkConverters: make([]*model.KilometerMarkConverter, 0),
|
KilometerMarkConverters: make([]model.KilometerMarkConverter, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RepoImpl) ConvertKilometerMark(km *model.KilometerMark, targetCoordinate string) (int64, error) {
|
func (r *RepoImpl) ConvertKilometerMark(km *model.KilometerMark, targetCoordinate string) (int64, error) {
|
||||||
if km.Coordinate() == targetCoordinate {
|
|
||||||
return km.Value(), nil
|
|
||||||
}
|
|
||||||
for _, converter := range r.KilometerMarkConverters {
|
for _, converter := range r.KilometerMarkConverters {
|
||||||
if converter.IsMatch(km, targetCoordinate) {
|
if converter.IsMatch(km, targetCoordinate) {
|
||||||
return converter.Convert(km, targetCoordinate), nil
|
return converter.Convert(km, targetCoordinate), nil
|
||||||
@ -71,87 +59,20 @@ func (r *RepoImpl) ConvertKilometerMark(km *model.KilometerMark, targetCoordinat
|
|||||||
return 0, fmt.Errorf("未找到公里标转换配置: %s<->%s, 全部配置项为: %s", km.Coordinate(), targetCoordinate, strings.Join(existConfigs, ","))
|
return 0, fmt.Errorf("未找到公里标转换配置: %s<->%s, 全部配置项为: %s", km.Coordinate(), targetCoordinate, strings.Join(existConfigs, ","))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RepoImpl) CalculateKmDistance(km1 *model.KilometerMark, km2 *model.KilometerMark) (int64, error) {
|
// CheckPipeLink implements Repo.
|
||||||
if km1.Coordinate() == km2.Coordinate() {
|
func (r *RepoImpl) CheckPipeLink() error {
|
||||||
return int64(math.Abs(float64(km2.Value() - km1.Value()))), nil
|
for _, section := range r.SectionMap {
|
||||||
} else {
|
|
||||||
km1Value, err := r.ConvertKilometerMark(km1, km2.Coordinate())
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return int64(math.Abs(float64(km2.Value() - km1Value))), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *RepoImpl) CheckSectionAndTurnoutPortKms() error {
|
|
||||||
for _, section := range r.PhysicalSectionMap {
|
|
||||||
slog.Debug("检查区段公里标", "uid", section.Uid(), "A端公里标", section.GetPaKm(), "B端公里标", section.GetPbKm())
|
|
||||||
if section.GetPaKm() == nil {
|
|
||||||
r.BuildErrorInfos = append(r.BuildErrorInfos, fmt.Errorf("区段[uid=%s]无A端公里标", section.Uid()))
|
|
||||||
}
|
|
||||||
if section.GetPbKm() == nil {
|
|
||||||
r.BuildErrorInfos = append(r.BuildErrorInfos, fmt.Errorf("区段[uid=%s]无B端公里标", section.Uid()))
|
|
||||||
}
|
|
||||||
if section.GetPaKm() != nil && section.GetPbKm() != nil {
|
|
||||||
section.CalculateDistance(r.CalculateKmDistance)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, turnout := range r.TurnoutMap {
|
|
||||||
slog.Debug("检查道岔公里标", "uid", turnout.Uid(), "公里标", turnout.GetKm(), "A端公里标", turnout.GetPaKm(), "B端公里标", turnout.GetPbKm(), "C端公里标", turnout.GetPcKm())
|
|
||||||
if turnout.GetKm() == nil {
|
|
||||||
r.BuildErrorInfos = append(r.BuildErrorInfos, fmt.Errorf("道岔[uid=%s]无公里标", turnout.Uid()))
|
|
||||||
}
|
|
||||||
if turnout.GetPaKm() == nil {
|
|
||||||
r.BuildErrorInfos = append(r.BuildErrorInfos, fmt.Errorf("道岔[uid=%s]无A端公里标", turnout.Uid()))
|
|
||||||
}
|
|
||||||
if turnout.GetPbKm() == nil {
|
|
||||||
r.BuildErrorInfos = append(r.BuildErrorInfos, fmt.Errorf("道岔[uid=%s]无B端公里标", turnout.Uid()))
|
|
||||||
}
|
|
||||||
if turnout.GetPcKm() == nil {
|
|
||||||
r.BuildErrorInfos = append(r.BuildErrorInfos, fmt.Errorf("道岔[uid=%s]无C端公里标", turnout.Uid()))
|
|
||||||
}
|
|
||||||
if turnout.GetKm() != nil && turnout.GetPaKm() != nil && turnout.GetPbKm() != nil && turnout.GetPcKm() != nil {
|
|
||||||
turnout.CalculateDistances(r.CalculateKmDistance)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(r.BuildErrorInfos) > 0 {
|
|
||||||
return errors.Join(r.BuildErrorInfos...)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckSectionAndTurnoutPipeLink implements Repo.
|
|
||||||
func (r *RepoImpl) CheckSectionAndTurnoutPipeLink() error {
|
|
||||||
for _, section := range r.PhysicalSectionMap {
|
|
||||||
err := section.CheckPipeLink()
|
err := section.CheckPipeLink()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.BuildErrorInfos = append(r.BuildErrorInfos, err)
|
r.BuildErrorInfos = append(r.BuildErrorInfos, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, tsModel := range r.TurnoutSectionMap {
|
|
||||||
turnouts := make([]string, 0)
|
|
||||||
for _, turnout := range tsModel.GetTurnouts() {
|
|
||||||
turnouts = append(turnouts, turnout.Uid())
|
|
||||||
}
|
|
||||||
slog.Debug("检查道岔区段关联道岔", "uid", tsModel.Uid(), "关联道岔", fmt.Sprintf("[%s]", strings.Join(turnouts, ",")))
|
|
||||||
if len(tsModel.GetTurnouts()) == 0 {
|
|
||||||
r.BuildErrorInfos = append(r.BuildErrorInfos, fmt.Errorf("道岔区段[uid=%s]未关联道岔", tsModel.Uid()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, turnout := range r.TurnoutMap {
|
for _, turnout := range r.TurnoutMap {
|
||||||
err := turnout.CheckPipeLink()
|
err := turnout.CheckPipeLink()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.BuildErrorInfos = append(r.BuildErrorInfos, err)
|
r.BuildErrorInfos = append(r.BuildErrorInfos, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(r.BuildErrorInfos) > 0 {
|
|
||||||
return errors.Join(r.BuildErrorInfos...)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckLinkAndLinkNodePipeLink implements Repo.
|
|
||||||
func (r *RepoImpl) CheckLinkAndLinkNodePipeLink() error {
|
|
||||||
slog.Debug("检查通道连接关系", "link数量", len(r.LinkMap))
|
slog.Debug("检查通道连接关系", "link数量", len(r.LinkMap))
|
||||||
for _, link := range r.LinkMap {
|
for _, link := range r.LinkMap {
|
||||||
err := link.CheckPipeLink()
|
err := link.CheckPipeLink()
|
||||||
@ -173,7 +94,7 @@ func (r *RepoImpl) CheckLinkAndLinkNodePipeLink() error {
|
|||||||
|
|
||||||
// GetSectionByUid implements Repo.
|
// GetSectionByUid implements Repo.
|
||||||
func (r *RepoImpl) GetSectionByUid(uid string) model.Section {
|
func (r *RepoImpl) GetSectionByUid(uid string) model.Section {
|
||||||
return r.PhysicalSectionMap[uid]
|
return r.SectionMap[uid]
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStationByUid implements Repo.
|
// GetStationByUid implements Repo.
|
||||||
@ -216,51 +137,29 @@ func walkOverTurnouts(turnout model.Turnout, repo1 *RepoImpl) {
|
|||||||
func walkFromTurnoutPortToNextAndBuildLink(turnout model.Turnout, port model.PipePort, repo1 *RepoImpl) model.Turnout {
|
func walkFromTurnoutPortToNextAndBuildLink(turnout model.Turnout, port model.PipePort, repo1 *RepoImpl) model.Turnout {
|
||||||
slog.Debug("walkFromTurnoutPortToNextAndBuildLink", "道岔id", turnout.Uid(), "端口", port)
|
slog.Debug("walkFromTurnoutPortToNextAndBuildLink", "道岔id", turnout.Uid(), "端口", port)
|
||||||
ple := turnout.GetLinkedElement(port)
|
ple := turnout.GetLinkedElement(port)
|
||||||
pathSections := make([]model.PhysicalSection, 0)
|
|
||||||
var nextTurnout model.Turnout = nil
|
|
||||||
var nextPort model.PipePort
|
|
||||||
for {
|
for {
|
||||||
if ple == nil { // 到尽头
|
if ple == nil {
|
||||||
nextPort = model.PipePortA
|
link, exist := NewLinkNodeAndLinkAndBuildLinkship(turnout, port, nil, model.PipePortA, repo1)
|
||||||
break
|
if !exist {
|
||||||
}
|
repo1.LinkMap[link.Uid()] = link
|
||||||
if ple.Pipe.IsThreePorts() { // 到下一个道岔
|
|
||||||
nextTurnout = ple.Pipe.(model.Turnout)
|
|
||||||
nextPort = ple.Port
|
|
||||||
break
|
|
||||||
} else { // 到下一个区段
|
|
||||||
section := ple.Pipe.(model.PhysicalSection)
|
|
||||||
pathSections = append(pathSections, section)
|
|
||||||
ple = section.OppositePipeLink(ple.Port)
|
|
||||||
}
|
}
|
||||||
|
slog.Debug("构建Link已存在", "LinkUid", link.Uid())
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
if ple.Pipe.IsThreePorts() {
|
||||||
|
nextTurnout := ple.Pipe.(model.Turnout)
|
||||||
|
nextPort := ple.Port
|
||||||
link, exist := NewLinkNodeAndLinkAndBuildLinkship(turnout, port, nextTurnout, nextPort, repo1)
|
link, exist := NewLinkNodeAndLinkAndBuildLinkship(turnout, port, nextTurnout, nextPort, repo1)
|
||||||
if exist {
|
if exist {
|
||||||
slog.Debug("构建Link已存在", "LinkUid", link.Uid())
|
slog.Debug("构建Link已存在", "LinkUid", link.Uid())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
repo1.LinkMap[link.Uid()] = link // 添加到仓库
|
repo1.LinkMap[link.Uid()] = link
|
||||||
// 构建link的长度和道岔以及区段的映射
|
|
||||||
buildLinkLengthAndElementMappings(link.(*model.LinkImpl), pathSections, repo1)
|
|
||||||
return nextTurnout
|
return nextTurnout
|
||||||
|
} else {
|
||||||
|
ple = ple.Pipe.(model.Section).OppositePipeLink(ple.Port)
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildLinkLengthAndElementMappings(link *model.LinkImpl, pathSections []model.PhysicalSection, repo1 *RepoImpl) {
|
|
||||||
len := int64(0)
|
|
||||||
pale := link.GetLinkedElement(model.PipePortA)
|
|
||||||
if pale == nil {
|
|
||||||
panic("构建Link长度错误: A端通道连接关系不能为空")
|
|
||||||
}
|
}
|
||||||
len += pale.Pipe.(model.LinkNode).Turnout().GetLength(pale.Port)
|
|
||||||
pble := link.GetLinkedElement(model.PipePortB)
|
|
||||||
if pble != nil {
|
|
||||||
len += pble.Pipe.(model.LinkNode).Turnout().GetLength(pble.Port)
|
|
||||||
}
|
|
||||||
for _, section := range pathSections {
|
|
||||||
len += section.GetLength()
|
|
||||||
}
|
|
||||||
link.SetLength(len)
|
|
||||||
slog.Debug("构建Link长度", "LinkUid", link.Uid(), "长度(m)", len/1000)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RepoImpl) getOrBuildLinkNode(turnout model.Turnout) model.LinkNode {
|
func (r *RepoImpl) getOrBuildLinkNode(turnout model.Turnout) model.LinkNode {
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
package repo_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"joylink.club/rtss-core/model"
|
|
||||||
"joylink.club/rtss-core/repo"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRepositoryConvertKilometerMark(t *testing.T) {
|
|
||||||
// 1. 配置公里标转换关系
|
|
||||||
km1 := model.NewKilometerMark("YDK", 0)
|
|
||||||
km2 := model.NewKilometerMark("ZDK", 200)
|
|
||||||
kmc1 := model.NewKilometerMarkConverter(km1, km2, true)
|
|
||||||
t.Log(kmc1.Debug())
|
|
||||||
repo1 := repo.NewRepo("Test")
|
|
||||||
repo1.KilometerMarkConverters = append(repo1.KilometerMarkConverters, kmc1)
|
|
||||||
|
|
||||||
// 2. 验证公里标转换关系
|
|
||||||
tests := []struct {
|
|
||||||
km *model.KilometerMark
|
|
||||||
targetCoordinate string
|
|
||||||
expect int64
|
|
||||||
expectError bool
|
|
||||||
}{
|
|
||||||
{km: model.NewKilometerMark("YDK", 0), targetCoordinate: km2.Coordinate(), expect: 200, expectError: false},
|
|
||||||
{km: model.NewKilometerMark("ZDK", 0), targetCoordinate: km1.Coordinate(), expect: -200, expectError: false},
|
|
||||||
{km: model.NewKilometerMark("YDK", 100), targetCoordinate: "Other", expect: 0, expectError: true},
|
|
||||||
}
|
|
||||||
t.Logf("tests: %v", tests)
|
|
||||||
for _, test := range tests {
|
|
||||||
result, err := repo1.ConvertKilometerMark(test.km, test.targetCoordinate)
|
|
||||||
if test.expectError {
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("expect error, but got nil")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("expect %d, but got error: %v", test.expect, err)
|
|
||||||
}
|
|
||||||
if result != test.expect {
|
|
||||||
t.Errorf("expect: %d, but got: %d", test.expect, result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user