2024-06-07 18:38:38 +08:00
|
|
|
package repo
|
|
|
|
|
2024-07-02 18:30:12 +08:00
|
|
|
import (
|
|
|
|
"errors"
|
2024-07-04 20:16:10 +08:00
|
|
|
"fmt"
|
2024-07-02 18:30:12 +08:00
|
|
|
"log/slog"
|
2024-07-04 20:16:10 +08:00
|
|
|
"strings"
|
2024-07-02 18:30:12 +08:00
|
|
|
|
|
|
|
"joylink.club/rtss-core/model"
|
|
|
|
)
|
2024-06-19 19:29:46 +08:00
|
|
|
|
2024-06-07 18:38:38 +08:00
|
|
|
type Repo interface {
|
|
|
|
// 模型仓库id
|
|
|
|
Id() string
|
2024-06-19 19:29:46 +08:00
|
|
|
GetStationByUid(uid string) model.Station
|
|
|
|
GetSectionByUid(uid string) model.Section
|
|
|
|
GetTurnoutByUid(uid string) model.Turnout
|
2024-06-26 19:00:01 +08:00
|
|
|
// 检查通道连接关系
|
|
|
|
CheckPipeLink() error
|
2024-07-04 20:16:10 +08:00
|
|
|
// 转换公里标
|
|
|
|
ConvertKilometerMark(km *model.KilometerMark, targetCoordinate string) (int64, error)
|
2024-06-07 18:38:38 +08:00
|
|
|
}
|
2024-07-02 18:30:12 +08:00
|
|
|
|
|
|
|
var _ Repo = (*RepoImpl)(nil)
|
|
|
|
|
|
|
|
type RepoImpl struct {
|
2024-07-04 20:16:10 +08:00
|
|
|
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
|
|
|
|
KilometerMarkConverters []model.KilometerMarkConverter
|
2024-07-02 18:30:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewRepo(id string) *RepoImpl {
|
|
|
|
return &RepoImpl{
|
2024-07-04 20:16:10 +08:00
|
|
|
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),
|
|
|
|
KilometerMarkConverters: make([]model.KilometerMarkConverter, 0),
|
2024-07-02 18:30:12 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-04 20:16:10 +08:00
|
|
|
func (r *RepoImpl) ConvertKilometerMark(km *model.KilometerMark, targetCoordinate string) (int64, error) {
|
|
|
|
for _, converter := range r.KilometerMarkConverters {
|
|
|
|
if converter.IsMatch(km, targetCoordinate) {
|
|
|
|
return converter.Convert(km, targetCoordinate), nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
existConfigs := make([]string, 0)
|
|
|
|
for _, converter := range r.KilometerMarkConverters {
|
|
|
|
existConfigs = append(existConfigs, converter.Debug())
|
|
|
|
}
|
|
|
|
return 0, fmt.Errorf("未找到公里标转换配置: %s<->%s, 全部配置项为: %s", km.Coordinate(), targetCoordinate, strings.Join(existConfigs, ","))
|
|
|
|
}
|
|
|
|
|
2024-07-02 18:30:12 +08:00
|
|
|
// 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() {
|
2024-07-04 20:16:10 +08:00
|
|
|
nextTurnout := ple.Pipe.(model.Turnout)
|
2024-07-02 18:30:12 +08:00
|
|
|
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)
|
|
|
|
} else if tb == nil {
|
|
|
|
nodea = repo1.getOrBuildLinkNode(ta)
|
|
|
|
nodeb = nil
|
|
|
|
pla = model.NewPipeLink(nodea, tap)
|
|
|
|
plb = nil
|
|
|
|
} else {
|
|
|
|
nodea = repo1.getOrBuildLinkNode(ta)
|
|
|
|
nodeb = repo1.getOrBuildLinkNode(tb)
|
|
|
|
pla = model.NewPipeLink(nodea, tap)
|
|
|
|
plb = model.NewPipeLink(nodeb, tbp)
|
2024-07-02 18:34:39 +08:00
|
|
|
}
|
|
|
|
exist, link = repo1.isLinkExist(pla, plb)
|
|
|
|
if exist {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
link = model.NewLink(pla, plb)
|
|
|
|
link.SetLinkedElement(model.PipePortA, pla)
|
|
|
|
link.SetLinkedElement(model.PipePortB, plb)
|
|
|
|
if nodea != nil {
|
2024-07-02 18:30:12 +08:00
|
|
|
nodea.SetLinkedElement(tap, model.NewPipeLink(link, model.PipePortA))
|
2024-07-02 18:34:39 +08:00
|
|
|
}
|
|
|
|
if nodeb != nil {
|
2024-07-02 18:30:12 +08:00
|
|
|
nodeb.SetLinkedElement(tbp, model.NewPipeLink(link, model.PipePortB))
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|