重构并修完善link、linknode构建
This commit is contained in:
parent
9c0d3ba69a
commit
13c25c0ba8
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
1
example/data_proto/xian6styg.base64
Normal file
1
example/data_proto/xian6styg.base64
Normal file
File diff suppressed because one or more lines are too long
@ -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
|
||||
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
|
||||
*repo.RepoImpl
|
||||
DataMapping map[string]*DataMapping
|
||||
}
|
||||
|
||||
var _ repo.Repo = &Repository{}
|
||||
|
||||
func NewRepository(id string) *Repository {
|
||||
return &Repository{
|
||||
id: id,
|
||||
BuildErrorInfos: make([]error, 0),
|
||||
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),
|
||||
RepoImpl: repo.NewRepo(id),
|
||||
DataMapping: make(map[string]*DataMapping),
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
},
|
||||
}
|
||||
|
5
model/section_check_point.go
Normal file
5
model/section_check_point.go
Normal file
@ -0,0 +1,5 @@
|
||||
package model
|
||||
|
||||
type SectionCheckPoint interface {
|
||||
RtssModel
|
||||
}
|
@ -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,
|
||||
},
|
||||
}
|
||||
|
201
repo/repo.go
201
repo/repo.go
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user