重构并修完善link、linknode构建

This commit is contained in:
walker-sheng” 2024-07-02 18:30:12 +08:00
parent 9c0d3ba69a
commit 13c25c0ba8
10 changed files with 313 additions and 233 deletions

View File

@ -2,7 +2,7 @@ package main
import (
"fmt"
"log"
"log/slog"
"joylink.club/rtss-core/example/data_proto"
modelimpl "joylink.club/rtss-core/example/model_impl"
@ -11,8 +11,9 @@ import (
)
func main() {
slog.SetLogLoggerLevel(slog.LevelDebug)
repo1 := repository.NewRepository("test1")
rtssGraphicStorage := data_proto.GetLineSytle1()
rtssGraphicStorage := data_proto.GetXian6STYG()
dataMapping := repository.NewDataMapping("1", rtssGraphicStorage)
repo1.DataMapping["1"] = dataMapping
// log.Println(rtssGraphicStorage.Stations)
@ -61,75 +62,20 @@ func main() {
// 检查区段、道岔通道连接关系
err := repo1.CheckPipeLink()
if err != nil {
log.Println(err)
slog.Error("区段道岔连接关系检查错误", "errMsg", err)
return
} else {
log.Println("区段、道岔连接关系检查通过")
slog.Info("区段、道岔连接关系检查通过")
}
// 构建link/linknode
buildLinkNode(repo1)
repo1.BuildLinks()
// 检查link/linknode
err = repo1.CheckPipeLink()
if err != nil {
log.Println(err)
slog.Error("link/linknode连接关系检查错误", "errMsg", err)
return
} else {
log.Println("link/linknode连接关系检查通过")
}
}
func buildLinkNode(repo1 *repository.Repository) {
for _, turnout := range repo1.TurnoutMap {
walkOverTurnouts(turnout, repo1)
break // 从一个道岔遍历所有区段、道岔
}
}
func walkOverTurnouts(turnout *modelimpl.Turnout, repo1 *repository.Repository) {
paNext := walkFromTurnoutPortToNextAndBuildLink(turnout, model.PipePortA, repo1)
if paNext != nil {
walkOverTurnouts(paNext, repo1)
}
pbNext := walkFromTurnoutPortToNextAndBuildLink(turnout, model.PipePortB, repo1)
if pbNext != nil {
walkOverTurnouts(pbNext, repo1)
}
pcNext := walkFromTurnoutPortToNextAndBuildLink(turnout, model.PipePortC, repo1)
if pcNext != nil {
walkOverTurnouts(pcNext, repo1)
}
}
func walkFromTurnoutPortToNextAndBuildLink(turnout *modelimpl.Turnout, port model.PipePort, repo1 *repository.Repository) *modelimpl.Turnout {
log.Println("walkFromTurnoutPortToNextAndBuildLink", turnout.Uid(), port)
ple := turnout.GetLinkedElement(port)
for {
if ple == nil {
log.Println("ple is nil")
} else {
log.Println("ple", ple.Pipe.Uid(), ple.Port)
}
if ple == nil {
nodea, nodeb, link := model.NewLinkNodeAndLinkAndBuildLinkship(turnout, port, nil, model.PipePortA)
allExist := repo1.IsLinkNodeAllExistOrStore(nodea, nodeb)
if !allExist {
repo1.LinkMap[link.Uid()] = link
}
log.Println("已存在", link.Uid())
return nil
}
if ple.Pipe.IsThreePorts() {
nextTurnout := ple.Pipe.(*modelimpl.Turnout)
nextPort := ple.Port
nodea, nodeb, link := model.NewLinkNodeAndLinkAndBuildLinkship(turnout, port, nextTurnout, nextPort)
allExist := repo1.IsLinkNodeAllExistOrStore(nodea, nodeb)
if allExist {
log.Println("已存在", link.Uid())
return nil
}
repo1.LinkMap[link.Uid()] = link
return nextTurnout
} else {
ple = ple.Pipe.(*modelimpl.Section).OppositePipeLink(ple.Port)
}
slog.Info("link/linknode连接关系检查通过")
}
}
@ -140,9 +86,9 @@ func buildTurnoutRelationships(dataMapping *repository.DataMapping, repo1 *repos
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)
buildTurnoutPortLinkship(turnout.PaRef, turnoutModel, model.PipePortA, repo1, dataMapping)
buildTurnoutPortLinkship(turnout.PbRef, turnoutModel, model.PipePortB, repo1, dataMapping)
buildTurnoutPortLinkship(turnout.PcRef, turnoutModel, model.PipePortC, repo1, dataMapping)
}
}
@ -158,7 +104,7 @@ func buildSectionRelationships(dataMapping *repository.DataMapping, repo1 *repos
}
}
func buildTurnoutPortLinkRelation(pref *data_proto.RelatedRef, sourceModel *modelimpl.Turnout, port model.PipePort, repo1 *repository.Repository, dataMapping *repository.DataMapping) {
func buildTurnoutPortLinkship(pref *data_proto.RelatedRef, sourceModel model.Turnout, port model.PipePort, repo1 *repository.Repository, dataMapping *repository.DataMapping) {
if pref == nil {
return
}
@ -182,7 +128,7 @@ func buildTurnoutPortLinkRelation(pref *data_proto.RelatedRef, sourceModel *mode
}
}
func buildSectionPortLinkRelation(pref *data_proto.RelatedRef, sourceModel *modelimpl.Section, 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 {
return
}

View File

@ -37,3 +37,24 @@ func GetLineSytle1() *RtssGraphicStorage {
}
return &rtssGraphicStorage
}
// / 西安6号线省体育馆集中区
func GetXian6STYG() *RtssGraphicStorage {
basePath, _ := os.Getwd()
filename := filepath.Join(basePath, "example/data_proto/xian6styg.base64")
bs, err := os.ReadFile(filename)
if err != nil {
panic(err)
}
protobytes, err := base64.StdEncoding.DecodeString(string(bs))
if err != nil {
panic(err)
}
rtssGraphicStorage := RtssGraphicStorage{}
err = proto.Unmarshal(protobytes, &rtssGraphicStorage)
if err != nil {
panic(err)
}
return &rtssGraphicStorage
}

File diff suppressed because one or more lines are too long

View File

@ -1,13 +1,9 @@
package repository
import (
"errors"
"fmt"
"log"
"joylink.club/rtss-core/example/data_proto"
modelimpl "joylink.club/rtss-core/example/model_impl"
"joylink.club/rtss-core/model"
"joylink.club/rtss-core/repo"
)
@ -57,98 +53,15 @@ func NewDataMapping(id string, storage *data_proto.RtssGraphicStorage) *DataMapp
}
type Repository struct {
id string
BuildErrorInfos []error
*repo.RepoImpl
DataMapping map[string]*DataMapping
StationMap map[string]*modelimpl.Station
SectionMap map[string]*modelimpl.Section
TurnoutMap map[string]*modelimpl.Turnout
LinkNodeMap map[string]*model.LinkNodeImpl
LinkMap map[string]*model.LinkImpl
}
var _ repo.Repo = &Repository{}
func NewRepository(id string) *Repository {
return &Repository{
id: id,
BuildErrorInfos: make([]error, 0),
RepoImpl: repo.NewRepo(id),
DataMapping: make(map[string]*DataMapping),
StationMap: make(map[string]*modelimpl.Station),
SectionMap: make(map[string]*modelimpl.Section),
TurnoutMap: make(map[string]*modelimpl.Turnout),
LinkNodeMap: make(map[string]*model.LinkNodeImpl),
LinkMap: make(map[string]*model.LinkImpl),
}
}
func (r *Repository) IsLinkNodeAllExistOrStore(nodea *model.LinkNodeImpl, nodeb *model.LinkNodeImpl) bool {
if nodea == nil && nodeb == nil {
panic("linkNode存在检查参数异常: node不能都为空")
}
for _, link := range r.LinkMap {
exist := link.IsEquals(nodea, nodeb)
if exist {
return true
}
}
if nodea == nil {
r.LinkNodeMap[nodeb.Uid()] = nodeb
} else if nodeb == nil {
r.LinkNodeMap[nodea.Uid()] = nodea
} else {
r.LinkNodeMap[nodea.Uid()] = nodea
r.LinkNodeMap[nodeb.Uid()] = nodeb
}
return false
}
func (r *Repository) Id() string {
return r.id
}
func (r *Repository) GetStationByUid(uid string) model.Station {
return r.StationMap[uid]
}
func (r *Repository) GetSectionByUid(uid string) model.Section {
return r.SectionMap[uid]
}
func (r *Repository) GetTurnoutByUid(uid string) model.Turnout {
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)
}
}
log.Println("link数量: ", len(r.LinkMap))
for _, link := range r.LinkMap {
log.Println("检查link", link.Uid())
err := link.CheckPipeLink()
if err != nil {
r.BuildErrorInfos = append(r.BuildErrorInfos, err)
}
}
for _, linkNode := range r.LinkNodeMap {
log.Println("检查linkNode", linkNode.Uid())
err := linkNode.CheckPipeLink()
if err != nil {
r.BuildErrorInfos = append(r.BuildErrorInfos, err)
}
}
if len(r.BuildErrorInfos) > 0 {
return errors.Join(r.BuildErrorInfos...)
}
return nil
}

View File

@ -1,6 +1,7 @@
package model
import (
"fmt"
"io"
)
@ -8,59 +9,32 @@ type RR = io.Writer
// 轨道
type Link interface {
PipeElement
TwoPortsPipeElement
IsEquals(pla *PipeLink, plb *PipeLink) bool
}
// 轨道连接点
type LinkNode interface {
Turnout() Turnout
PipeElement
ThreePortsPipeElement
}
var _ Link = (*LinkImpl)(nil)
var _ LinkNode = (*LinkNodeImpl)(nil)
type LinkImpl struct {
*TwoPortsPipeElement
*TwoPortsPipeElementImpl
}
type LinkNodeImpl struct {
turnout Turnout
*ThreePortsPipeElement
*ThreePortsPipeElementImpl
}
func NewLinkNodeAndLinkAndBuildLinkship(ta Turnout, tap PipePort, tb Turnout, tbp PipePort) (nodea *LinkNodeImpl, nodeb *LinkNodeImpl, link *LinkImpl) {
if ta == nil && tb == nil {
panic("构造LinkNode错误: 道岔不能都为空")
}
if ta == nil {
nodea = nil
nodeb = NewLinkNode(tb)
link = NewLink(nodea, nodeb)
link.SetLinkedElement(PipePortB, NewPipeLink(nodeb, tbp))
nodeb.SetLinkedElement(tbp, NewPipeLink(link, PipePortB))
} else if tb == nil {
nodea = NewLinkNode(ta)
nodeb = nil
link = NewLink(nodea, nodeb)
link.SetLinkedElement(PipePortA, NewPipeLink(nodea, tap))
nodea.SetLinkedElement(tap, NewPipeLink(link, PipePortA))
} else {
nodea = NewLinkNode(ta)
nodeb = NewLinkNode(tb)
link = NewLink(nodea, nodeb)
link.SetLinkedElement(PipePortA, NewPipeLink(nodea, tap))
link.SetLinkedElement(PipePortB, NewPipeLink(nodeb, tbp))
nodea.SetLinkedElement(tap, NewPipeLink(link, PipePortA))
nodeb.SetLinkedElement(tbp, NewPipeLink(link, PipePortB))
}
return
}
func NewLink(nodea *LinkNodeImpl, nodeb *LinkNodeImpl) *LinkImpl {
uid := buildLinkUid(nodea, nodeb)
func NewLink(pla *PipeLink, plb *PipeLink) *LinkImpl {
uid := buildLinkUid(pla, plb)
return &LinkImpl{
TwoPortsPipeElement: &TwoPortsPipeElement{
TwoPortsPipeElementImpl: &TwoPortsPipeElementImpl{
uid: uid,
},
}
@ -72,29 +46,29 @@ func NewLinkNode(turnout Turnout) *LinkNodeImpl {
}
return &LinkNodeImpl{
turnout: turnout,
ThreePortsPipeElement: &ThreePortsPipeElement{
ThreePortsPipeElementImpl: &ThreePortsPipeElementImpl{
uid: turnout.Uid(),
},
}
}
func (l *LinkImpl) IsEquals(nodea *LinkNodeImpl, nodeb *LinkNodeImpl) bool {
return l.uid == buildLinkUid(nodea, nodeb) || l.uid == buildLinkUid(nodeb, nodea)
func (l *LinkImpl) IsEquals(pla *PipeLink, plb *PipeLink) bool {
return l.uid == buildLinkUid(pla, plb) || l.uid == buildLinkUid(plb, pla)
}
func (n *LinkNodeImpl) Turnout() Turnout {
return n.turnout
}
func buildLinkUid(nodea *LinkNodeImpl, nodeb *LinkNodeImpl) string {
if nodea == nil && nodeb == nil {
panic("构造link Uid错误: nodea和nodeb不能同时为空")
func buildLinkUid(pla *PipeLink, plb *PipeLink) string {
if pla == nil && plb == nil {
panic("构造link Uid错误: pla和plb不能同时为空")
}
if nodea == nil {
return "end" + "->" + nodeb.Turnout().Uid()
if pla == nil {
return fmt.Sprintf("end->%s(%s)", plb.Pipe.Uid(), plb.Port)
}
if nodeb == nil {
return nodea.Turnout().Uid() + "->" + "end"
if plb == nil {
return fmt.Sprintf("%s(%s)->end", pla.Pipe.Uid(), pla.Port)
}
return nodea.Turnout().Uid() + "->" + nodeb.Turnout().Uid()
return fmt.Sprintf("%s(%s)->%s(%s)", pla.Pipe.Uid(), pla.Port, plb.Pipe.Uid(), plb.Port)
}

View File

@ -2,6 +2,7 @@ package model
import (
"fmt"
"log/slog"
)
type RtssModel interface {
@ -45,7 +46,11 @@ func NewPipeLink(pipe PipeElement, port PipePort) *PipeLink {
}
func (pl *PipeLink) Debug() string {
return "{" + "\"pipeUid\":" + pl.Pipe.Uid() + ", \"port\":" + pl.Port + "}"
return DebugPipeLink(pl.Pipe, pl.Port)
}
func DebugPipeLink(p PipeElement, port PipePort) string {
return fmt.Sprintf("{pipeUid=%s, port=%s}", p.Uid(), port)
}
// 通道元素
@ -57,12 +62,28 @@ type PipeElement interface {
IsThreePorts() bool
// 获取指定端口连接的通道连接关系
GetLinkedElement(port PipePort) *PipeLink
// 设置指定端口的通道连接关系
SetLinkedElement(port PipePort, pipeLink *PipeLink) error
// 检查通道连接关系
CheckPipeLink() error
}
type TwoPortsPipeElement interface {
PipeElement
// 获取指定端口的对端通道连接关系
OppositePipeLink(port PipePort) *PipeLink
}
type ThreePortsPipeElement interface {
PipeElement
}
func checkPipePortLink(pe PipeElement, port PipePort, pipeLink *PipeLink) error {
if pipeLink == nil {
slog.Debug("检查通道端口连接关系", "通道端口", DebugPipeLink(pe, port), "连接关系", "未连接")
return nil
}
slog.Debug("检查通道端口连接关系", "通道端口", DebugPipeLink(pe, port), "连接关系", pipeLink.Debug())
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)
@ -73,32 +94,32 @@ func checkPipePortLink(pe PipeElement, port PipePort, pipeLink *PipeLink) error
return nil
}
var _ PipeElement = (*TwoPortsPipeElement)(nil)
var _ TwoPortsPipeElement = (*TwoPortsPipeElementImpl)(nil)
// 两端口的线性通道元素
type TwoPortsPipeElement struct {
type TwoPortsPipeElementImpl struct {
uid string
paPipeLink *PipeLink
pbPipeLink *PipeLink
}
func (t *TwoPortsPipeElement) Uid() string {
func (t *TwoPortsPipeElementImpl) Uid() string {
return t.uid
}
func (t *TwoPortsPipeElement) Ports() []PipePort {
func (t *TwoPortsPipeElementImpl) Ports() []PipePort {
return twoPorts
}
func (t *TwoPortsPipeElement) IsTwoPorts() bool {
func (t *TwoPortsPipeElementImpl) IsTwoPorts() bool {
return true
}
func (t *TwoPortsPipeElement) IsThreePorts() bool {
func (t *TwoPortsPipeElementImpl) IsThreePorts() bool {
return false
}
func (s *TwoPortsPipeElement) GetLinkedElement(port PipePort) *PipeLink {
func (s *TwoPortsPipeElementImpl) GetLinkedElement(port PipePort) *PipeLink {
if port == PipePortA {
return s.paPipeLink
} else if port == PipePortB {
@ -107,14 +128,14 @@ func (s *TwoPortsPipeElement) GetLinkedElement(port PipePort) *PipeLink {
return nil
}
func (t *TwoPortsPipeElement) OppositePipeLink(port PipePort) *PipeLink {
func (t *TwoPortsPipeElementImpl) OppositePipeLink(port PipePort) *PipeLink {
if port == PipePortA {
return t.pbPipeLink
}
return t.paPipeLink
}
func (s *TwoPortsPipeElement) SetLinkedElement(port PipePort, pipeLink *PipeLink) error {
func (s *TwoPortsPipeElementImpl) 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)
@ -131,7 +152,7 @@ func (s *TwoPortsPipeElement) SetLinkedElement(port PipePort, pipeLink *PipeLink
return nil
}
func (s *TwoPortsPipeElement) CheckPipeLink() error {
func (s *TwoPortsPipeElementImpl) CheckPipeLink() error {
err := checkPipePortLink(s, PipePortA, s.paPipeLink)
if err != nil {
return err
@ -140,33 +161,33 @@ func (s *TwoPortsPipeElement) CheckPipeLink() error {
return err
}
var _ PipeElement = (*ThreePortsPipeElement)(nil)
var _ PipeElement = (*ThreePortsPipeElementImpl)(nil)
// 三端口的通道元素
type ThreePortsPipeElement struct {
type ThreePortsPipeElementImpl struct {
uid string
paPipeLink *PipeLink
pbPipeLink *PipeLink
pcPipeLink *PipeLink
}
func (t *ThreePortsPipeElement) Uid() string {
func (t *ThreePortsPipeElementImpl) Uid() string {
return t.uid
}
func (t *ThreePortsPipeElement) Ports() []PipePort {
func (t *ThreePortsPipeElementImpl) Ports() []PipePort {
return threePorts
}
func (t *ThreePortsPipeElement) IsTwoPorts() bool {
func (t *ThreePortsPipeElementImpl) IsTwoPorts() bool {
return false
}
func (t *ThreePortsPipeElement) IsThreePorts() bool {
func (t *ThreePortsPipeElementImpl) IsThreePorts() bool {
return true
}
func (t *ThreePortsPipeElement) GetLinkedElement(port PipePort) *PipeLink {
func (t *ThreePortsPipeElementImpl) GetLinkedElement(port PipePort) *PipeLink {
if port == PipePortA {
return t.paPipeLink
} else if port == PipePortB {
@ -177,7 +198,7 @@ func (t *ThreePortsPipeElement) GetLinkedElement(port PipePort) *PipeLink {
return nil
}
func (t *ThreePortsPipeElement) SetLinkedElement(port PipePort, pipeLink *PipeLink) error {
func (t *ThreePortsPipeElementImpl) 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)
@ -197,7 +218,7 @@ func (t *ThreePortsPipeElement) SetLinkedElement(port PipePort, pipeLink *PipeLi
return nil
}
func (t *ThreePortsPipeElement) CheckPipeLink() error {
func (t *ThreePortsPipeElementImpl) CheckPipeLink() error {
err := checkPipePortLink(t, PipePortA, t.paPipeLink)
if err != nil {
return err

View File

@ -2,18 +2,18 @@ package model
// 区段
type Section interface {
PipeElement
TwoPortsPipeElement
}
type SectionImpl struct {
*TwoPortsPipeElement
*TwoPortsPipeElementImpl
}
var _ Section = (*SectionImpl)(nil)
func NewSection(uid string) *SectionImpl {
return &SectionImpl{
TwoPortsPipeElement: &TwoPortsPipeElement{
TwoPortsPipeElementImpl: &TwoPortsPipeElementImpl{
uid: uid,
},
}

View File

@ -0,0 +1,5 @@
package model
type SectionCheckPoint interface {
RtssModel
}

View File

@ -6,13 +6,13 @@ import (
// 道岔
type Turnout interface {
PipeElement
ThreePortsPipeElement
}
var _ Turnout = (*TurnoutImpl)(nil)
type TurnoutImpl struct {
*ThreePortsPipeElement
*ThreePortsPipeElementImpl
}
func NewTurnout(uid string) *TurnoutImpl {
@ -20,7 +20,7 @@ func NewTurnout(uid string) *TurnoutImpl {
panic("Turnout uid is empty")
}
return &TurnoutImpl{
ThreePortsPipeElement: &ThreePortsPipeElement{
ThreePortsPipeElementImpl: &ThreePortsPipeElementImpl{
uid: uid,
},
}

View File

@ -1,6 +1,11 @@
package repo
import "joylink.club/rtss-core/model"
import (
"errors"
"log/slog"
"joylink.club/rtss-core/model"
)
type Repo interface {
// 模型仓库id
@ -11,3 +16,197 @@ type Repo interface {
// 检查通道连接关系
CheckPipeLink() error
}
var _ Repo = (*RepoImpl)(nil)
type RepoImpl struct {
id string
BuildErrorInfos []error
StationMap map[string]model.Station
SectionMap map[string]model.Section
TurnoutMap map[string]model.Turnout
LinkNodeMap map[string]model.LinkNode
LinkMap map[string]model.Link
}
func NewRepo(id string) *RepoImpl {
return &RepoImpl{
id: id,
StationMap: make(map[string]model.Station),
SectionMap: make(map[string]model.Section),
TurnoutMap: make(map[string]model.Turnout),
LinkNodeMap: make(map[string]model.LinkNode),
LinkMap: make(map[string]model.Link),
}
}
// CheckPipeLink implements Repo.
func (r *RepoImpl) 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)
}
}
slog.Debug("检查通道连接关系", "link数量", len(r.LinkMap))
for _, link := range r.LinkMap {
err := link.CheckPipeLink()
if err != nil {
r.BuildErrorInfos = append(r.BuildErrorInfos, err)
}
}
for _, linkNode := range r.LinkNodeMap {
err := linkNode.CheckPipeLink()
if err != nil {
r.BuildErrorInfos = append(r.BuildErrorInfos, err)
}
}
if len(r.BuildErrorInfos) > 0 {
return errors.Join(r.BuildErrorInfos...)
}
return nil
}
// GetSectionByUid implements Repo.
func (r *RepoImpl) GetSectionByUid(uid string) model.Section {
return r.SectionMap[uid]
}
// GetStationByUid implements Repo.
func (r *RepoImpl) GetStationByUid(uid string) model.Station {
return r.StationMap[uid]
}
// GetTurnoutByUid implements Repo.
func (r *RepoImpl) GetTurnoutByUid(uid string) model.Turnout {
return r.TurnoutMap[uid]
}
// Id implements Repo.
func (r *RepoImpl) Id() string {
return r.id
}
func (r *RepoImpl) BuildLinks() {
for _, turnout := range r.TurnoutMap {
walkOverTurnouts(turnout, r)
break // 从一个道岔遍历所有区段、道岔
}
}
func walkOverTurnouts(turnout model.Turnout, repo1 *RepoImpl) {
paNext := walkFromTurnoutPortToNextAndBuildLink(turnout, model.PipePortA, repo1)
if paNext != nil {
walkOverTurnouts(paNext, repo1)
}
pbNext := walkFromTurnoutPortToNextAndBuildLink(turnout, model.PipePortB, repo1)
if pbNext != nil {
walkOverTurnouts(pbNext, repo1)
}
pcNext := walkFromTurnoutPortToNextAndBuildLink(turnout, model.PipePortC, repo1)
if pcNext != nil {
walkOverTurnouts(pcNext, repo1)
}
}
func walkFromTurnoutPortToNextAndBuildLink(turnout model.Turnout, port model.PipePort, repo1 *RepoImpl) model.Turnout {
slog.Debug("walkFromTurnoutPortToNextAndBuildLink", "道岔id", turnout.Uid(), "端口", port)
ple := turnout.GetLinkedElement(port)
for {
if ple == nil {
link, exist := NewLinkNodeAndLinkAndBuildLinkship(turnout, port, nil, model.PipePortA, repo1)
if !exist {
repo1.LinkMap[link.Uid()] = link
}
slog.Debug("构建Link已存在", "LinkUid", link.Uid())
return nil
}
if ple.Pipe.IsThreePorts() {
nextTurnout := ple.Pipe
nextPort := ple.Port
link, exist := NewLinkNodeAndLinkAndBuildLinkship(turnout, port, nextTurnout, nextPort, repo1)
if exist {
slog.Debug("构建Link已存在", "LinkUid", link.Uid())
return nil
}
repo1.LinkMap[link.Uid()] = link
return nextTurnout
} else {
ple = ple.Pipe.(model.Section).OppositePipeLink(ple.Port)
}
}
}
func (r *RepoImpl) getOrBuildLinkNode(turnout model.Turnout) model.LinkNode {
node := r.LinkNodeMap[turnout.Uid()]
if node == nil {
node = model.NewLinkNode(turnout)
r.LinkNodeMap[turnout.Uid()] = node
}
return node
}
func (r *RepoImpl) isLinkExist(pla *model.PipeLink, plb *model.PipeLink) (bool, model.Link) {
for _, link := range r.LinkMap {
if link.IsEquals(pla, plb) {
return true, link
}
}
return false, nil
}
func NewLinkNodeAndLinkAndBuildLinkship(ta model.Turnout, tap model.PipePort, tb model.Turnout, tbp model.PipePort, repo1 *RepoImpl) (link model.Link, exist bool) {
if ta == nil && tb == nil {
panic("构造LinkNode错误: 道岔不能都为空")
}
var nodea model.LinkNode
var nodeb model.LinkNode
var pla *model.PipeLink
var plb *model.PipeLink
if ta == nil {
nodea = nil
nodeb = repo1.getOrBuildLinkNode(tb)
pla = nil
plb = model.NewPipeLink(nodeb, tbp)
exist, link = repo1.isLinkExist(pla, plb)
if exist {
return
}
link = model.NewLink(pla, plb)
link.SetLinkedElement(model.PipePortB, plb)
nodeb.SetLinkedElement(tbp, model.NewPipeLink(link, model.PipePortB))
} else if tb == nil {
nodea = repo1.getOrBuildLinkNode(ta)
nodeb = nil
pla = model.NewPipeLink(nodea, tap)
plb = nil
exist, link = repo1.isLinkExist(pla, plb)
if exist {
return
}
link = model.NewLink(pla, plb)
link.SetLinkedElement(model.PipePortA, pla)
nodea.SetLinkedElement(tap, model.NewPipeLink(link, model.PipePortA))
} else {
nodea = repo1.getOrBuildLinkNode(ta)
nodeb = repo1.getOrBuildLinkNode(tb)
pla = model.NewPipeLink(nodea, tap)
plb = model.NewPipeLink(nodeb, tbp)
exist, link = repo1.isLinkExist(pla, plb)
if exist {
return
}
link = model.NewLink(pla, plb)
link.SetLinkedElement(model.PipePortA, pla)
link.SetLinkedElement(model.PipePortB, plb)
nodea.SetLinkedElement(tap, model.NewPipeLink(link, model.PipePortA))
nodeb.SetLinkedElement(tbp, model.NewPipeLink(link, model.PipePortB))
}
return
}