diff --git a/example/build_repo_example/main.go b/example/build_repo_example/main.go index 0aaba24..f542de0 100644 --- a/example/build_repo_example/main.go +++ b/example/build_repo_example/main.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "log" "joylink.club/rtss-core/example/data_proto" modelimpl "joylink.club/rtss-core/example/model_impl" @@ -33,7 +34,7 @@ func main() { continue } dataMapping.SectionDataMap[section.Common.Id] = section - uid := getSectionUid(section, belongStation) + uid := getSectionUid(section, belongStation, dataMapping.GetLineInfo()) dataMapping.AddIdMapping(repository.NewIdMapping(section.Common.Id, uid)) sectionModel := model.NewSection(uid) repo1.SectionMap[uid] = &modelimpl.Section{SectionImpl: sectionModel} @@ -47,7 +48,7 @@ func main() { continue } dataMapping.TurnoutDataMap[turnout.Common.Id] = turnout - uid := getTurnoutUid(turnout, belongStation) + uid := getTurnoutUid(turnout, belongStation, dataMapping.GetLineInfo()) dataMapping.AddIdMapping(repository.NewIdMapping(turnout.Common.Id, uid)) turnoutModel := model.NewTurnout(uid) repo1.TurnoutMap[uid] = &modelimpl.Turnout{TurnoutImpl: turnoutModel} @@ -57,10 +58,34 @@ func main() { buildSectionRelationships(dataMapping, repo1) // 构建道岔关系 buildTurnoutRelationships(dataMapping, repo1) - // 检查通道连接关系 + // 检查区段、道岔通道连接关系 err := repo1.CheckPipeLink() if err != nil { - fmt.Println(err) + log.Println(err) + } else { + log.Println("区段、道岔连接关系检查通过") + } + // 构建link/linknode + buildLinkNode(repo1) +} + +func buildLinkNode(repo1 *repository.Repository) { + passedSectionMap := make(map[string]struct{}) + for _, turnout := range repo1.TurnoutMap { + walkToNextTurnout(turnout, model.PipePortA, passedSectionMap) + break // 从一个道岔遍历所有区段、道岔 + } +} + +func walkToNextTurnout(turnout *modelimpl.Turnout, port model.PipePort, passedSectionMap map[string]struct{}) (*modelimpl.Turnout, model.PipePort) { + plink := turnout.GetLinkedElement(port) + if plink == nil { + return nil, model.PipePortA + } + for { + if plink.Pipe.IsThreePorts() { + return plink.Pipe.(*modelimpl.Turnout), plink.Port + } } } @@ -148,10 +173,10 @@ func convertPort(port data_proto.RelatedRef_DevicePort) model.PipePort { panic(fmt.Errorf("未知的数据关联端口类型: %v", port)) } -func getSectionUid(section *data_proto.Section, belongStation *data_proto.Station) string { - return belongStation.Code + "-" + section.Code +func getSectionUid(section *data_proto.Section, belongStation *data_proto.Station, lineInfo string) string { + return fmt.Sprintf("%s/%s/%s", lineInfo, belongStation.Code, section.Code) } -func getTurnoutUid(turnout *data_proto.Turnout, belongStation *data_proto.Station) string { - return belongStation.Code + "-" + turnout.Code +func getTurnoutUid(turnout *data_proto.Turnout, belongStation *data_proto.Station, lineInfo string) string { + return fmt.Sprintf("%s/%s/%s", lineInfo, belongStation.Code, turnout.Code) } diff --git a/example/repository/repo.go b/example/repository/repo.go index 581ef5b..9fe972e 100644 --- a/example/repository/repo.go +++ b/example/repository/repo.go @@ -2,6 +2,7 @@ package repository import ( "errors" + "fmt" "joylink.club/rtss-core/example/data_proto" modelimpl "joylink.club/rtss-core/example/model_impl" @@ -37,6 +38,11 @@ func (d *DataMapping) AddIdMapping(idMapping *IdMapping) { d.UidMappingMap[idMapping.Uid] = idMapping } +func (d *DataMapping) GetLineInfo() string { + lineInfo := d.RtssGraphicStorage.UniqueIdPrefix + return fmt.Sprintf("%s%s", lineInfo.City, lineInfo.LineId) +} + func NewDataMapping(id string, storage *data_proto.RtssGraphicStorage) *DataMapping { return &DataMapping{ id: id, diff --git a/model/link.go b/model/link.go index 8b05736..f8e8b14 100644 --- a/model/link.go +++ b/model/link.go @@ -19,71 +19,36 @@ var _ Link = (*LinkImpl)(nil) var _ LinkNode = (*LinkNodeImpl)(nil) type LinkImpl struct { - uid string - paLinkNode *PipeLink - pbLinkNode *PipeLink + *TwoPortsPipeElement } type LinkNodeImpl struct { - turnout Turnout - paPipeLink *PipeLink - pbPipeLink *PipeLink - pcPipeLink *PipeLink + turnout Turnout + *ThreePortsPipeElement } func NewLink(nodea LinkNode, nodeb LinkNode) Link { uid := buildLinkUid(nodea, nodeb) return &LinkImpl{ - uid: uid, + TwoPortsPipeElement: &TwoPortsPipeElement{ + uid: uid, + }, } } func NewLinkNode(turnout Turnout) LinkNode { return &LinkNodeImpl{ turnout: turnout, + ThreePortsPipeElement: &ThreePortsPipeElement{ + uid: turnout.Uid(), + }, } } -func (l *LinkImpl) Uid() string { - return l.uid -} - -func (l *LinkImpl) Ports() []PipePort { - return twoPorts -} - -func (l *LinkImpl) GetLinkedElement(port PipePort) *PipeLink { - if port == PipePortA { - return l.paLinkNode - } else if port == PipePortB { - return l.pbLinkNode - } - return nil -} - -func (n *LinkNodeImpl) Uid() string { - return n.turnout.Uid() -} - func (n *LinkNodeImpl) Turnout() Turnout { return n.turnout } -func (n *LinkNodeImpl) Ports() []PipePort { - return threePorts -} - -func (n *LinkNodeImpl) GetLinkedElement(port PipePort) *PipeLink { - if port == PipePortA { - return n.paPipeLink - } else if port == PipePortB { - return n.pbPipeLink - } else if port == PipePortC { - return n.pcPipeLink - } - return nil -} - func buildLinkUid(nodea LinkNode, nodeb LinkNode) string { if nodea == nil && nodeb == nil { panic("构造link Uid错误: nodea和nodeb不能同时为空") diff --git a/model/model.go b/model/model.go index 2cab843..3ec9d63 100644 --- a/model/model.go +++ b/model/model.go @@ -1,5 +1,9 @@ package model +import ( + "fmt" +) + type RtssModel interface { // RtssModel unique id Uid() string @@ -49,20 +53,60 @@ type PipeElement interface { RtssModel // 获取通道端口 Ports() []PipePort + IsTwoPorts() bool + IsThreePorts() bool // 获取指定端口连接的通道连接关系 GetLinkedElement(port PipePort) *PipeLink } +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 +} + +var _ PipeElement = (*TwoPortsPipeElement)(nil) + +// 两端口的线性通道元素 type TwoPortsPipeElement struct { uid string paPipeLink *PipeLink pbPipeLink *PipeLink } +func (t *TwoPortsPipeElement) Uid() string { + return t.uid +} + func (t *TwoPortsPipeElement) Ports() []PipePort { return twoPorts } +func (t *TwoPortsPipeElement) IsTwoPorts() bool { + return true +} + +func (t *TwoPortsPipeElement) IsThreePorts() bool { + return false +} + +func (s *TwoPortsPipeElement) GetLinkedElement(port PipePort) *PipeLink { + if port == PipePortA { + return s.paPipeLink + } else if port == PipePortB { + return s.pbPipeLink + } + return nil +} + func (t *TwoPortsPipeElement) OppositePipeLink(port PipePort) PipeLink { if port == PipePortA { return *t.pbPipeLink @@ -70,8 +114,98 @@ func (t *TwoPortsPipeElement) OppositePipeLink(port PipePort) PipeLink { return *t.paPipeLink } -type ThreePortsPipeElement struct{} +func (s *TwoPortsPipeElement) 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 *TwoPortsPipeElement) CheckPipeLink() error { + err := checkPipePortLink(s, PipePortA, s.paPipeLink) + if err != nil { + return err + } + err = checkPipePortLink(s, PipePortB, s.pbPipeLink) + return err +} + +var _ PipeElement = (*ThreePortsPipeElement)(nil) + +// 三端口的通道元素 +type ThreePortsPipeElement struct { + uid string + paPipeLink *PipeLink + pbPipeLink *PipeLink + pcPipeLink *PipeLink +} + +func (t *ThreePortsPipeElement) Uid() string { + return t.uid +} func (t *ThreePortsPipeElement) Ports() []PipePort { return threePorts } + +func (t *ThreePortsPipeElement) IsTwoPorts() bool { + return false +} + +func (t *ThreePortsPipeElement) IsThreePorts() bool { + return true +} + +func (t *ThreePortsPipeElement) GetLinkedElement(port PipePort) *PipeLink { + if port == PipePortA { + return t.paPipeLink + } else if port == PipePortB { + return t.pbPipeLink + } else if port == PipePortC { + return t.pcPipeLink + } + return nil +} + +func (t *ThreePortsPipeElement) 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 *ThreePortsPipeElement) 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 +} diff --git a/model/section.go b/model/section.go index 5779c24..4642f87 100644 --- a/model/section.go +++ b/model/section.go @@ -1,67 +1,20 @@ package model -import ( - "fmt" -) - // 区段 type Section interface { PipeElement } type SectionImpl struct { - uid string - paPipeLink *PipeLink - pbPipeLink *PipeLink + *TwoPortsPipeElement } var _ Section = (*SectionImpl)(nil) func NewSection(uid string) *SectionImpl { return &SectionImpl{ - uid: uid, + TwoPortsPipeElement: &TwoPortsPipeElement{ + uid: uid, + }, } } - -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 { - return s.uid -} - -func (s *SectionImpl) Ports() []PipePort { - return twoPorts -} - -func (s *SectionImpl) GetLinkedElement(port PipePort) *PipeLink { - if port == PipePortA { - return s.paPipeLink - } else if port == PipePortB { - return s.pbPipeLink - } - return nil -} diff --git a/model/turnout.go b/model/turnout.go index f911862..49132d6 100644 --- a/model/turnout.go +++ b/model/turnout.go @@ -1,7 +1,6 @@ package model import ( - "fmt" "strings" ) @@ -13,10 +12,7 @@ type Turnout interface { var _ Turnout = (*TurnoutImpl)(nil) type TurnoutImpl struct { - uid string - paPipeLink *PipeLink - pbPipeLink *PipeLink - pcPipeLink *PipeLink + *ThreePortsPipeElement } func NewTurnout(uid string) *TurnoutImpl { @@ -24,72 +20,8 @@ func NewTurnout(uid string) *TurnoutImpl { panic("Turnout uid is empty") } return &TurnoutImpl{ - uid: uid, + ThreePortsPipeElement: &ThreePortsPipeElement{ + uid: uid, + }, } } - -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 { - return t.uid -} - -func (t *TurnoutImpl) Ports() []PipePort { - return threePorts -} - -func (t *TurnoutImpl) GetLinkedElement(port PipePort) *PipeLink { - if port == PipePortA { - return t.paPipeLink - } else if port == PipePortB { - return t.pbPipeLink - } else if port == PipePortC { - return t.pcPipeLink - } - return nil -}