添加公里标及公里标转换相关model及逻辑

This commit is contained in:
walker-sheng” 2024-07-04 20:16:10 +08:00
parent 8e20a049a4
commit 5a18ea69fe
6 changed files with 201 additions and 19 deletions

79
model/kilometer_mark.go Normal file
View File

@ -0,0 +1,79 @@
package model
import (
"fmt"
"strconv"
)
// 运营方向(上行/下行)
type OperationDirection int8
const (
// 上行
OperationDirectionUp OperationDirection = 1
// 下行
OperationDirectionDown OperationDirection = 0
)
type KilometerMark struct {
// 公里标坐标系
coordinate string
// 公里标上下行方向
direction OperationDirection
// 公里标值
value int64
}
func NewKilometerMark(coordinate string, direction OperationDirection, value int64) *KilometerMark {
return &KilometerMark{
coordinate: coordinate,
direction: direction,
value: value,
}
}
func (km *KilometerMark) Coordinate() string {
return km.coordinate
}
// 是否为同一坐标系
func (km *KilometerMark) IsCoordinateEqual(coordinate string) bool {
return km.coordinate == coordinate
}
// 公里标转换配置
type KilometerMarkConverter struct {
km1 KilometerMark
km2 KilometerMark
// 趋势是否相同
trendSame bool
}
func (kmc *KilometerMarkConverter) Debug() string {
return fmt.Sprintf("{%s<->%s(%s)}", kmc.km1.coordinate, kmc.km2.coordinate, strconv.FormatBool(kmc.trendSame))
}
func (kmc *KilometerMarkConverter) IsMatch(km *KilometerMark, coordinate2 string) bool {
coordinate1 := km.coordinate
return kmc.km1.coordinate == coordinate1 && kmc.km2.coordinate == coordinate2 ||
kmc.km1.coordinate == coordinate2 && kmc.km2.coordinate == coordinate1
}
// 将源公里标km转换为目标坐标系targetCoordinate的公里标值
func (kmc *KilometerMarkConverter) Convert(km *KilometerMark, targetCoordinate string) int64 {
var tvalue int64 = 0
if kmc.km1.IsCoordinateEqual(km.coordinate) {
if kmc.trendSame {
tvalue = km.value - kmc.km1.value + kmc.km2.value
} else {
tvalue = kmc.km1.value - km.value + kmc.km2.value
}
} else {
if kmc.trendSame {
tvalue = km.value - kmc.km2.value + kmc.km1.value
} else {
tvalue = kmc.km2.value - km.value + kmc.km1.value
}
}
return tvalue
}

View File

@ -0,0 +1,48 @@
package model
import (
"testing"
)
func TestConvertKilometerMark(t *testing.T) {
// 1. 配置公里标转换关系
km1 := NewKilometerMark("DBCSK", OperationDirectionUp, 0)
km2 := NewKilometerMark("DCSK", OperationDirectionUp, 200)
kmc1 := &KilometerMarkConverter{
km1: *km1,
km2: *km2,
trendSame: true,
}
t.Log(kmc1.Debug())
kmc2 := &KilometerMarkConverter{
km1: *km1,
km2: *km2,
trendSame: false,
}
t.Log(kmc2.Debug())
// 2. 验证公里标转换关系
tests := []struct {
km *KilometerMark
coordinate string
expect1 int64
expect2 int64
}{
{km: NewKilometerMark("DBCSK", OperationDirectionUp, 0), coordinate: km2.Coordinate(), expect1: 200, expect2: 200},
{km: NewKilometerMark("DBCSK", OperationDirectionUp, 100), coordinate: km2.Coordinate(), expect1: 300, expect2: 100},
{km: NewKilometerMark("DBCSK", OperationDirectionUp, -100), coordinate: km2.Coordinate(), expect1: 100, expect2: 300},
{km: NewKilometerMark("DCSK", OperationDirectionUp, 200), coordinate: km1.Coordinate(), expect1: 0, expect2: 0},
{km: NewKilometerMark("DCSK", OperationDirectionUp, 300), coordinate: km1.Coordinate(), expect1: 100, expect2: -100},
{km: NewKilometerMark("DCSK", OperationDirectionUp, 100), coordinate: km1.Coordinate(), expect1: -100, expect2: 100},
}
for _, test := range tests {
result1 := kmc1.Convert(test.km, test.coordinate)
if result1 != test.expect1 {
t.Errorf("expect1: %d, but got: %d", test.expect1, result1)
}
result2 := kmc2.Convert(test.km, test.coordinate)
if result2 != test.expect2 {
t.Errorf("expect2: %d, but got: %d", test.expect2, result2)
}
}
}

View File

@ -3,10 +3,15 @@ package model
// 区段
type Section interface {
TwoPortsPipeElement
// 获取A端和B端的公里标
GetPaKm() KilometerMark
GetPbKm() KilometerMark
}
type SectionImpl struct {
*TwoPortsPipeElementImpl
PaKm KilometerMark
PbKm KilometerMark
}
var _ Section = (*SectionImpl)(nil)
@ -18,3 +23,11 @@ func NewSection(uid string) *SectionImpl {
},
}
}
func (s *SectionImpl) GetPaKm() KilometerMark {
return s.PaKm
}
func (s *SectionImpl) GetPbKm() KilometerMark {
return s.PbKm
}

View File

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

View File

@ -7,12 +7,24 @@ import (
// 道岔
type Turnout interface {
ThreePortsPipeElement
// 获取道岔岔心公里标
GetKm() KilometerMark
// 获取道岔A端公里标
GetPaKm() KilometerMark
// 获取道岔B端公里标
GetPbKm() KilometerMark
// 获取道岔C端公里标
GetPcKm() KilometerMark
}
var _ Turnout = (*TurnoutImpl)(nil)
type TurnoutImpl struct {
*ThreePortsPipeElementImpl
Km KilometerMark
PaKm KilometerMark
PbKm KilometerMark
PcKm KilometerMark
}
func NewTurnout(uid string) *TurnoutImpl {
@ -25,3 +37,19 @@ func NewTurnout(uid string) *TurnoutImpl {
},
}
}
func (t *TurnoutImpl) GetKm() KilometerMark {
return t.Km
}
func (t *TurnoutImpl) GetPaKm() KilometerMark {
return t.PaKm
}
func (t *TurnoutImpl) GetPbKm() KilometerMark {
return t.PbKm
}
func (t *TurnoutImpl) GetPcKm() KilometerMark {
return t.PcKm
}

View File

@ -2,7 +2,9 @@ package repo
import (
"errors"
"fmt"
"log/slog"
"strings"
"joylink.club/rtss-core/model"
)
@ -15,31 +17,48 @@ type Repo interface {
GetTurnoutByUid(uid string) model.Turnout
// 检查通道连接关系
CheckPipeLink() error
// 转换公里标
ConvertKilometerMark(km *model.KilometerMark, targetCoordinate string) (int64, 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
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
}
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),
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),
}
}
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, ","))
}
// CheckPipeLink implements Repo.
func (r *RepoImpl) CheckPipeLink() error {
for _, section := range r.SectionMap {
@ -128,7 +147,7 @@ func walkFromTurnoutPortToNextAndBuildLink(turnout model.Turnout, port model.Pip
return nil
}
if ple.Pipe.IsThreePorts() {
nextTurnout := ple.Pipe
nextTurnout := ple.Pipe.(model.Turnout)
nextPort := ple.Port
link, exist := NewLinkNodeAndLinkAndBuildLinkship(turnout, port, nextTurnout, nextPort, repo1)
if exist {