物理区段状态

This commit is contained in:
xzb 2023-11-13 13:53:46 +08:00
parent e9a90ac013
commit 1cbdf59876
5 changed files with 59 additions and 15 deletions

View File

@ -1,6 +1,9 @@
package component package component
import "joylink.club/ecs" import (
"fmt"
"joylink.club/ecs"
)
// TrainPositionInfo 列车当前位置信息 // TrainPositionInfo 列车当前位置信息
type TrainPositionInfo struct { type TrainPositionInfo struct {
@ -19,6 +22,10 @@ type TrainPositionInfo struct {
TailLinkOffset int64 TailLinkOffset int64
} }
func (t *TrainPositionInfo) ToString() string {
return fmt.Sprintf("Up=%t len=%d headLink=%s headOff=%d tailLink=%s tailOff=%d", t.Up, t.Len, t.HeadLink, t.HeadLinkOffset, t.TailLink, t.TailLinkOffset)
}
var ( var (
TrainPositionInfoType = ecs.NewComponentType[TrainPositionInfo]() TrainPositionInfoType = ecs.NewComponentType[TrainPositionInfo]()
) )

View File

@ -44,9 +44,9 @@ func UpdateTrainPositionFromDynamics(w ecs.World, tpi TrainPositionInfo) error {
train.Up = tpi.Up train.Up = tpi.Up
train.Len = int64(tpi.Len) train.Len = int64(tpi.Len)
train.HeadLink = tpi.HeadLink train.HeadLink = tpi.HeadLink
train.HeadLinkOffset = int64(tpi.TailLinkOffset) train.HeadLinkOffset = int64(tpi.HeadLinkOffset)
train.TailLink = tpi.TailLink train.TailLink = tpi.TailLink
train.TailLinkOffset = int64(tpi.HeadLinkOffset) train.TailLinkOffset = int64(tpi.TailLinkOffset)
return ecs.NewOkEmptyResult() return ecs.NewOkEmptyResult()
} else { } else {
return ecs.NewErrResult(fmt.Errorf("列车[%s]实体不存在", tpi.TrainId)) return ecs.NewErrResult(fmt.Errorf("列车[%s]实体不存在", tpi.TrainId))

@ -1 +1 @@
Subproject commit 4171b05a7c23c3e40a755ccd7d08b4cfd6aa26a0 Subproject commit 5aa1f62ee8ba0f720e4444a05b53cdbaffe4780a

View File

@ -32,6 +32,20 @@ func NewLink(id string) *Link {
} }
} }
// GetAllPhysicalSection 获取与该link关联的所有物理区段(包括岔区非岔区)
func (l *Link) GetAllPhysicalSection() []*PhysicalSection {
var rt []*PhysicalSection
if l.physicalSections != nil {
rt = append(rt, l.physicalSections...)
}
if l.aRelation != nil {
rt = append(rt, l.aRelation.turnout.section)
}
if l.bRelation != nil {
rt = append(rt, l.bRelation.turnout.section)
}
return rt
}
func (l *Link) Length() int64 { func (l *Link) Length() int64 {
return l.length return l.length
} }

View File

@ -10,6 +10,7 @@ import (
"joylink.club/rtsssimulation/repository" "joylink.club/rtsssimulation/repository"
"joylink.club/rtsssimulation/repository/model/proto" "joylink.club/rtsssimulation/repository/model/proto"
"log/slog" "log/slog"
"strings"
) )
// SectionDetectSystem 区段检测系统 // SectionDetectSystem 区段检测系统
@ -28,7 +29,9 @@ func (s *SectionDetectSystem) Update(w ecs.World) {
//所有列车 //所有列车
s.trainQuery.Each(w, func(entry *donburi.Entry) { s.trainQuery.Each(w, func(entry *donburi.Entry) {
tp := component.TrainPositionInfoType.Get(entry) tp := component.TrainPositionInfoType.Get(entry)
//fmt.Println("============>>>>>>列车位置信息:", tp.ToString())
trainSectionIds := s.doSearchTrainOccupiedSections(w, tp) trainSectionIds := s.doSearchTrainOccupiedSections(w, tp)
//fmt.Println("============>>>>>>列车所在物理区段:", trainSectionIds)
for _, sectionId := range trainSectionIds { //车所在区段 for _, sectionId := range trainSectionIds { //车所在区段
tc, find := sectionTrainMap[sectionId] tc, find := sectionTrainMap[sectionId]
if !find { if !find {
@ -61,18 +64,11 @@ func newTrainCount() *trainCount {
func (c *trainCount) add() { func (c *trainCount) add() {
c.count++ c.count++
} }
func (s *SectionDetectSystem) doSearchTrainOccupiedSections(w ecs.World, tp *component.TrainPositionInfo) []string { func (s *SectionDetectSystem) doSearchTrainOccupiedSections(w ecs.World, tp *component.TrainPositionInfo) []string {
wd := entity.GetWorldData(w) wd := entity.GetWorldData(w)
curLink := wd.Repo.FindLink(tp.HeadLink) curLink := wd.Repo.FindLink(tp.HeadLink)
stp := &stpContext{w: w, trainLen: tp.Len, curLink: curLink, curOffset: tp.HeadLinkOffset, searchDirection: !tp.Up, acLen: 0} stp := &stpContext{w: w, trainLen: tp.Len, curLink: curLink, curOffset: tp.HeadLinkOffset, searchDirection: !tp.Up, acLen: 0}
c := 0
for stp.needAccumulate() { for stp.needAccumulate() {
c++
if c > 50 {
slog.Warn("======>>>>搜索列车所占物理区段,迭代次数过多!!!!")
break
}
stp.accumulateLen() stp.accumulateLen()
if stp.needAccumulate() { if stp.needAccumulate() {
stp.nextLink() stp.nextLink()
@ -96,6 +92,14 @@ type stpContext struct {
acRanges []*stpLinkRange //轨道range列表 acRanges []*stpLinkRange //轨道range列表
} }
func (s *stpContext) printStpLinkRanges() {
var sb strings.Builder
for _, r := range s.acRanges {
sb.WriteString(fmt.Sprintf("[linkId=%s start=%d end=%d linkLen=%d]->", r.link.Id(), r.start, r.end, r.link.Length()))
}
fmt.Println("===========>>>>列车所在link range 链:", sb.String())
}
// 获取列车所占的物理区段 // 获取列车所占的物理区段
func (s *stpContext) trainSections() []string { func (s *stpContext) trainSections() []string {
secs := make(map[string]string) secs := make(map[string]string)
@ -105,6 +109,9 @@ func (s *stpContext) trainSections() []string {
secs[id] = id secs[id] = id
} }
} }
//
//s.printStpLinkRanges()
//
var sectionIds []string var sectionIds []string
for _, id := range secs { for _, id := range secs {
sectionIds = append(sectionIds, id) sectionIds = append(sectionIds, id)
@ -212,17 +219,20 @@ type stpLinkRange struct {
// 获取link range 上的物理区段的id // 获取link range 上的物理区段的id
func (s *stpLinkRange) sectionIds() []string { func (s *stpLinkRange) sectionIds() []string {
var ids []string var ids []string
ps := s.link.PhysicalSections() ps := s.link.GetAllPhysicalSection()
for _, p := range ps { for _, p := range ps {
for _, pr := range p.LinkRanges() { for _, pr := range p.LinkRanges() {
if isRangeOverlap(s.start, s.end, pr.Start(), pr.End()) { if isRangeOverlap(s.link.Id(), s.start, s.end, pr.Link().Id(), pr.Start(), pr.End()) {
ids = append(ids, p.Id()) ids = append(ids, p.Id())
} }
} }
} }
return ids return ids
} }
func isRangeOverlap(r1Start int64, r1End int64, r2Start int64, r2End int64) bool { func isRangeOverlap(r1LinkId string, r1Start int64, r1End int64, r2LinkId string, r2Start int64, r2End int64) bool {
if r1LinkId != r2LinkId {
return false
}
r1Start, r1End = formatRange(r1Start, r1End) r1Start, r1End = formatRange(r1Start, r1End)
r2Start, r2End = formatRange(r2Start, r2End) r2Start, r2End = formatRange(r2Start, r2End)
if r2Start > r1Start && r2Start < r1End { if r2Start > r1Start && r2Start < r1End {
@ -231,9 +241,13 @@ func isRangeOverlap(r1Start int64, r1End int64, r2Start int64, r2End int64) bool
if r2End > r1Start && r2End < r1End { if r2End > r1Start && r2End < r1End {
return true return true
} }
if r1Start == r2Start && r1End == r2End { if r1Start > r2Start && r1Start < r2End {
return true return true
} }
if r1End > r2Start && r1End < r2End {
return true
}
//
return false return false
} }
func formatRange(start int64, end int64) (int64, int64) { func formatRange(start int64, end int64) (int64, int64) {
@ -243,3 +257,12 @@ func formatRange(start int64, end int64) (int64, int64) {
return end, start return end, start
} }
} }
func printPhSectionRange(w ecs.World, id string) string {
wd := entity.GetWorldData(w)
var sb strings.Builder
sb.WriteString(fmt.Sprintf("物理区段[%s]range列表", id))
for _, r := range wd.Repo.FindPhysicalSection(id).LinkRanges() {
sb.WriteString(fmt.Sprintf("[linkId=%s start=%d end=%d],", r.Link().Id(), r.Start(), r.End()))
}
return sb.String()
}