section 和 turnout模型关系构建和检查

This commit is contained in:
soul-walker 2024-06-26 19:00:01 +08:00
parent 5d8b8cf1ea
commit 58754c2b04
10 changed files with 320 additions and 30 deletions

View File

@ -1,6 +1,8 @@
package main package main
import ( import (
"fmt"
"joylink.club/rtss-core/example/data_proto" "joylink.club/rtss-core/example/data_proto"
modelimpl "joylink.club/rtss-core/example/model_impl" modelimpl "joylink.club/rtss-core/example/model_impl"
"joylink.club/rtss-core/example/repository" "joylink.club/rtss-core/example/repository"
@ -8,27 +10,148 @@ import (
) )
func main() { func main() {
repo := repository.NewRepository("test1").(*repository.Repository) repo1 := repository.NewRepository("test1")
rtssGraphicStorage := data_proto.GetLineSytle1() rtssGraphicStorage := data_proto.GetLineSytle1()
dataMapping := repository.NewDataMapping("1", rtssGraphicStorage)
repo1.DataMapping["1"] = dataMapping
// log.Println(rtssGraphicStorage.Stations) // log.Println(rtssGraphicStorage.Stations)
// log.Println(rtssGraphicStorage.Section) // log.Println(rtssGraphicStorage.Section)
// log.Println(rtssGraphicStorage.Turnouts) // log.Println(rtssGraphicStorage.Turnouts)
for _, station := range rtssGraphicStorage.Stations { for _, station := range rtssGraphicStorage.Stations {
repo.StationDataMap[station.Common.Id] = station dataMapping.StationDataMap[station.Common.Id] = station
uid := station.Code
dataMapping.AddIdMapping(repository.NewIdMapping(station.Common.Id, uid))
stationModel := model.NewStation(uid, station.ConcentrationStations)
repo1.StationMap[uid] = &modelimpl.Station{StationImpl: stationModel}
} }
for _, section := range rtssGraphicStorage.Section { for _, section := range rtssGraphicStorage.Section {
belongStation := repo.SectionDataMap[section.CentralizedStations[0]] if section.CentralizedStations == nil || len(section.CentralizedStations) == 0 {
if section.CentralizedStations == nil || len(section.CentralizedStations) == 0 || repo.SectionDataMap[section.CentralizedStations[0]] == nil {
continue continue
} }
repo.SectionDataMap[section.Common.Id] = section belongStation := dataMapping.StationDataMap[section.CentralizedStations[0]]
if belongStation == nil {
continue
}
dataMapping.SectionDataMap[section.Common.Id] = section
uid := getSectionUid(section, belongStation) uid := getSectionUid(section, belongStation)
repo.IpMapping = append(repo.IpMapping, repository.NewIdMapping(section.Common.Id, uid)) dataMapping.AddIdMapping(repository.NewIdMapping(section.Common.Id, uid))
sectionModel := model.NewSection(uid) sectionModel := model.NewSection(uid)
repo.SectionMap[uid] = &modelimpl.Section{SectionImpl: sectionModel} repo1.SectionMap[uid] = &modelimpl.Section{SectionImpl: sectionModel}
}
for _, turnout := range rtssGraphicStorage.Turnouts {
if turnout.CentralizedStations == nil || len(turnout.CentralizedStations) == 0 {
continue
}
belongStation := dataMapping.StationDataMap[turnout.CentralizedStations[0]]
if belongStation == nil {
continue
}
dataMapping.TurnoutDataMap[turnout.Common.Id] = turnout
uid := getTurnoutUid(turnout, belongStation)
dataMapping.AddIdMapping(repository.NewIdMapping(turnout.Common.Id, uid))
turnoutModel := model.NewTurnout(uid)
repo1.TurnoutMap[uid] = &modelimpl.Turnout{TurnoutImpl: turnoutModel}
}
// 构建区段关系
buildSectionRelationships(dataMapping, repo1)
// 构建道岔关系
buildTurnoutRelationships(dataMapping, repo1)
// 检查通道连接关系
err := repo1.CheckPipeLink()
if err != nil {
fmt.Println(err)
} }
} }
func getSectionUid(section *data_proto.Section, belongStation *data_proto.Section) string { func buildTurnoutRelationships(dataMapping *repository.DataMapping, repo1 *repository.Repository) {
for _, turnout := range dataMapping.TurnoutDataMap {
idmapping := dataMapping.IdMappingMap[turnout.Common.Id]
if idmapping == nil {
panic(fmt.Errorf("构建道岔关系错误idmapping异常为空"))
}
turnoutModel := repo1.TurnoutMap[idmapping.Uid]
buildTurnoutPortLinkRelation(turnout.PaRef, turnoutModel, model.PipePortA, repo1, dataMapping)
buildTurnoutPortLinkRelation(turnout.PbRef, turnoutModel, model.PipePortB, repo1, dataMapping)
buildTurnoutPortLinkRelation(turnout.PcRef, turnoutModel, model.PipePortC, repo1, dataMapping)
}
}
func buildSectionRelationships(dataMapping *repository.DataMapping, repo1 *repository.Repository) {
for _, section := range dataMapping.SectionDataMap {
idmapping := dataMapping.IdMappingMap[section.Common.Id]
if idmapping == nil {
panic(fmt.Errorf("构建区段关系错误idmapping异常为空"))
}
sectionModel := repo1.SectionMap[idmapping.Uid]
buildSectionPortLinkRelation(section.PaRef, sectionModel, model.PipePortA, repo1, dataMapping)
buildSectionPortLinkRelation(section.PbRef, sectionModel, model.PipePortB, repo1, dataMapping)
}
}
func buildTurnoutPortLinkRelation(pref *data_proto.RelatedRef, sourceModel *modelimpl.Turnout, port model.PipePort, repo1 *repository.Repository, dataMapping *repository.DataMapping) {
if pref == nil {
return
}
if pref.DeviceType == data_proto.RelatedRef_Section {
idmapping2 := dataMapping.IdMappingMap[pref.Id]
if idmapping2 != nil {
sectionModel := repo1.SectionMap[idmapping2.Uid]
if sectionModel != nil {
sourceModel.SetLinkedElement(port, model.NewPipeLink(sectionModel, convertPort(pref.DevicePort)))
}
}
}
if pref.DeviceType == data_proto.RelatedRef_Turnout {
idmapping2 := dataMapping.IdMappingMap[pref.Id]
if idmapping2 != nil {
turnoutModel2 := repo1.TurnoutMap[idmapping2.Uid]
if turnoutModel2 != nil {
sourceModel.SetLinkedElement(port, model.NewPipeLink(turnoutModel2, convertPort(pref.DevicePort)))
}
}
}
}
func buildSectionPortLinkRelation(pref *data_proto.RelatedRef, sourceModel *modelimpl.Section, port model.PipePort, repo1 *repository.Repository, dataMapping *repository.DataMapping) {
if pref == nil {
return
}
if pref.DeviceType == data_proto.RelatedRef_Section {
idmapping2 := dataMapping.IdMappingMap[pref.Id]
if idmapping2 != nil {
sectionModel := repo1.SectionMap[idmapping2.Uid]
if sectionModel != nil {
sourceModel.SetLinkedElement(port, model.NewPipeLink(sectionModel, convertPort(pref.DevicePort)))
}
}
}
if pref.DeviceType == data_proto.RelatedRef_Turnout {
idmapping2 := dataMapping.IdMappingMap[pref.Id]
if idmapping2 != nil {
turnoutModel := repo1.TurnoutMap[idmapping2.Uid]
if turnoutModel != nil {
sourceModel.SetLinkedElement(port, model.NewPipeLink(turnoutModel, convertPort(pref.DevicePort)))
}
}
}
}
func convertPort(port data_proto.RelatedRef_DevicePort) model.PipePort {
if port == data_proto.RelatedRef_A {
return model.PipePortA
} else if port == data_proto.RelatedRef_B {
return model.PipePortB
} else if port == data_proto.RelatedRef_C {
return model.PipePortC
}
panic(fmt.Errorf("未知的数据关联端口类型: %v", port))
}
func getSectionUid(section *data_proto.Section, belongStation *data_proto.Station) string {
return belongStation.Code + "-" + section.Code return belongStation.Code + "-" + section.Code
} }
func getTurnoutUid(turnout *data_proto.Turnout, belongStation *data_proto.Station) string {
return belongStation.Code + "-" + turnout.Code
}

View File

@ -3,5 +3,5 @@ package modelimpl
import "joylink.club/rtss-core/model" import "joylink.club/rtss-core/model"
type Station struct { type Station struct {
model.StationImpl *model.StationImpl
} }

View File

@ -3,5 +3,5 @@ package modelimpl
import "joylink.club/rtss-core/model" import "joylink.club/rtss-core/model"
type Turnout struct { type Turnout struct {
model.TurnoutImpl *model.TurnoutImpl
} }

View File

@ -1,6 +1,8 @@
package repository package repository
import ( import (
"errors"
"joylink.club/rtss-core/example/data_proto" "joylink.club/rtss-core/example/data_proto"
modelimpl "joylink.club/rtss-core/example/model_impl" modelimpl "joylink.club/rtss-core/example/model_impl"
"joylink.club/rtss-core/model" "joylink.club/rtss-core/model"
@ -20,24 +22,49 @@ func NewIdMapping(graphicId uint32, uid string) *IdMapping {
} }
} }
type Repository struct { type DataMapping struct {
id string id string
*data_proto.RtssGraphicStorage
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
IpMapping []*IdMapping IdMappingMap map[uint32]*IdMapping
UidMappingMap map[string]*IdMapping
}
func (d *DataMapping) AddIdMapping(idMapping *IdMapping) {
d.IdMappingMap[idMapping.GraphicId] = idMapping
d.UidMappingMap[idMapping.Uid] = idMapping
}
func NewDataMapping(id string, storage *data_proto.RtssGraphicStorage) *DataMapping {
return &DataMapping{
id: id,
RtssGraphicStorage: storage,
StationDataMap: make(map[uint32]*data_proto.Station),
SectionDataMap: make(map[uint32]*data_proto.Section),
TurnoutDataMap: make(map[uint32]*data_proto.Turnout),
IdMappingMap: make(map[uint32]*IdMapping),
UidMappingMap: make(map[string]*IdMapping),
}
}
type Repository struct {
id string
BuildErrorInfos []error
DataMapping map[string]*DataMapping
StationMap map[string]*modelimpl.Station StationMap map[string]*modelimpl.Station
SectionMap map[string]*modelimpl.Section SectionMap map[string]*modelimpl.Section
TurnoutMap map[string]*modelimpl.Turnout TurnoutMap map[string]*modelimpl.Turnout
} }
func NewRepository(id string) repo.Repo { var _ repo.Repo = &Repository{}
func NewRepository(id string) *Repository {
return &Repository{ return &Repository{
id: id, id: id,
StationDataMap: make(map[uint32]*data_proto.Station), BuildErrorInfos: make([]error, 0),
SectionDataMap: make(map[uint32]*data_proto.Section), DataMapping: make(map[string]*DataMapping),
TurnoutDataMap: make(map[uint32]*data_proto.Turnout),
IpMapping: make([]*IdMapping, 0),
StationMap: make(map[string]*modelimpl.Station), StationMap: make(map[string]*modelimpl.Station),
SectionMap: make(map[string]*modelimpl.Section), SectionMap: make(map[string]*modelimpl.Section),
TurnoutMap: make(map[string]*modelimpl.Turnout), TurnoutMap: make(map[string]*modelimpl.Turnout),
@ -59,3 +86,22 @@ func (r *Repository) GetSectionByUid(uid string) model.Section {
func (r *Repository) GetTurnoutByUid(uid string) model.Turnout { func (r *Repository) GetTurnoutByUid(uid string) model.Turnout {
return r.TurnoutMap[uid] return r.TurnoutMap[uid]
} }
func (r *Repository) CheckPipeLink() error {
for _, section := range r.SectionMap {
err := section.CheckPipeLink()
if err != nil {
r.BuildErrorInfos = append(r.BuildErrorInfos, err)
}
}
for _, turnout := range r.TurnoutMap {
err := turnout.CheckPipeLink()
if err != nil {
r.BuildErrorInfos = append(r.BuildErrorInfos, err)
}
}
if len(r.BuildErrorInfos) > 0 {
return errors.Join(r.BuildErrorInfos...)
}
return nil
}

View File

@ -6,7 +6,6 @@ type RR = io.Writer
// 轨道 // 轨道
type Link interface { type Link interface {
RtssModel
PipeElement PipeElement
} }
@ -62,6 +61,10 @@ func (l *LinkImpl) GetLinkedElement(port PipePort) *PipeLink {
return nil return nil
} }
func (n *LinkNodeImpl) Uid() string {
return n.turnout.Uid()
}
func (n *LinkNodeImpl) Turnout() Turnout { func (n *LinkNodeImpl) Turnout() Turnout {
return n.turnout return n.turnout
} }

View File

@ -30,10 +30,48 @@ type PipeLink struct {
Port PipePort Port PipePort
} }
func NewPipeLink(pipe PipeElement, port PipePort) *PipeLink {
if pipe == nil {
panic("pipe is nil")
}
return &PipeLink{
Pipe: pipe,
Port: port,
}
}
func (pl *PipeLink) Debug() string {
return "{" + "\"pipeUid\":" + pl.Pipe.Uid() + ", \"port\":" + pl.Port + "}"
}
// 通道元素 // 通道元素
type PipeElement interface { type PipeElement interface {
RtssModel
// 获取通道端口 // 获取通道端口
Ports() []PipePort Ports() []PipePort
// 获取指定端口连接的通道连接关系 // 获取指定端口连接的通道连接关系
GetLinkedElement(port PipePort) *PipeLink GetLinkedElement(port PipePort) *PipeLink
} }
type TwoPortsPipeElement struct {
uid string
paPipeLink *PipeLink
pbPipeLink *PipeLink
}
func (t *TwoPortsPipeElement) Ports() []PipePort {
return twoPorts
}
func (t *TwoPortsPipeElement) OppositePipeLink(port PipePort) PipeLink {
if port == PipePortA {
return *t.pbPipeLink
}
return *t.paPipeLink
}
type ThreePortsPipeElement struct{}
func (t *ThreePortsPipeElement) Ports() []PipePort {
return threePorts
}

View File

@ -1,8 +1,11 @@
package model package model
import (
"fmt"
)
// 区段 // 区段
type Section interface { type Section interface {
RtssModel
PipeElement PipeElement
} }
@ -20,6 +23,32 @@ func NewSection(uid string) *SectionImpl {
} }
} }
func (s *SectionImpl) SetLinkedElement(port PipePort, pipeLink *PipeLink) error {
if port == PipePortA {
if s.paPipeLink != nil {
return fmt.Errorf("区段uid=%s端口A已经设置关联元素: {uid=%s, port=%s}", s.uid, s.paPipeLink.Pipe.Uid(), s.paPipeLink.Port)
}
s.paPipeLink = pipeLink
} else if port == PipePortB {
if s.pbPipeLink != nil {
return fmt.Errorf("区段uid=%s端口B已经设置关联元素: {uid=%s, port=%s}", s.uid, s.pbPipeLink.Pipe.Uid(), s.pbPipeLink.Port)
}
s.pbPipeLink = pipeLink
} else {
return fmt.Errorf("区段uid=%s设置关联元素端口错误,不支持C端口", s.uid)
}
return nil
}
func (s *SectionImpl) CheckPipeLink() error {
err := checkPipePortLink(s, PipePortA, s.paPipeLink)
if err != nil {
return err
}
err = checkPipePortLink(s, PipePortB, s.pbPipeLink)
return err
}
func (s *SectionImpl) Uid() string { func (s *SectionImpl) Uid() string {
return s.uid return s.uid
} }

View File

@ -12,7 +12,7 @@ type StationImpl struct {
centralized bool centralized bool
} }
func NewStation(uid string, centralized bool) Station { func NewStation(uid string, centralized bool) *StationImpl {
return &StationImpl{ return &StationImpl{
uid: uid, uid: uid,
centralized: centralized, centralized: centralized,

View File

@ -1,10 +1,12 @@
package model package model
import "strings" import (
"fmt"
"strings"
)
// 道岔 // 道岔
type Turnout interface { type Turnout interface {
RtssModel
PipeElement PipeElement
} }
@ -26,6 +28,53 @@ func NewTurnout(uid string) *TurnoutImpl {
} }
} }
func (t *TurnoutImpl) SetLinkedElement(port PipePort, pipeLink *PipeLink) error {
if port == PipePortA {
if t.paPipeLink != nil {
return fmt.Errorf("道岔uid=%s端口A已经设置关联元素: {uid=%s, port=%s}", t.uid, t.paPipeLink.Pipe.Uid(), t.paPipeLink.Port)
}
t.paPipeLink = pipeLink
} else if port == PipePortB {
if t.pbPipeLink != nil {
return fmt.Errorf("道岔uid=%s端口B已经设置关联元素: {uid=%s, port=%s}", t.uid, t.pbPipeLink.Pipe.Uid(), t.pbPipeLink.Port)
}
t.pbPipeLink = pipeLink
} else if port == PipePortC {
if t.pcPipeLink != nil {
return fmt.Errorf("道岔uid=%s端口C已经设置关联元素: {uid=%s, port=%s}", t.uid, t.pcPipeLink.Pipe.Uid(), t.pcPipeLink.Port)
}
t.pcPipeLink = pipeLink
}
return nil
}
func (t *TurnoutImpl) CheckPipeLink() error {
err := checkPipePortLink(t, PipePortA, t.paPipeLink)
if err != nil {
return err
}
err = checkPipePortLink(t, PipePortB, t.pbPipeLink)
if err != nil {
return err
}
err = checkPipePortLink(t, PipePortC, t.pcPipeLink)
return err
}
func checkPipePortLink(pe PipeElement, port PipePort, pipeLink *PipeLink) error {
if pipeLink == nil {
return nil
}
plink := pipeLink.Pipe.GetLinkedElement(pipeLink.Port)
if plink == nil {
return fmt.Errorf("通道端口{uid=%s, port=%s}关联通道端口{uid=%s, port=%s},但关联通道的对应端口却未关联通道端口", pe.Uid(), port, pipeLink.Pipe.Uid(), pipeLink.Port)
} else if plink.Pipe.Uid() != pe.Uid() || plink.Port != port {
return fmt.Errorf("通道端口{uid=%s, port=%s}关联通道端口{uid=%s, port=%s},但关联通道的对应端口却关联了其他通道端口: {uid=%s, port=%s}", pe.Uid(), port, pipeLink.Pipe.Uid(), pipeLink.Port,
plink.Pipe.Uid(), plink.Port)
}
return nil
}
func (t *TurnoutImpl) Uid() string { func (t *TurnoutImpl) Uid() string {
return t.uid return t.uid
} }

View File

@ -8,4 +8,6 @@ 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
// 检查通道连接关系
CheckPipeLink() error
} }