rts-sim-module/system/psd_system.go
2023-09-22 16:42:39 +08:00

317 lines
9.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package system
import (
"github.com/yohamta/donburi/filter"
"joylink.club/ecs"
)
// PsdCircuitState 站台门控制电路状态Psd为车站所有屏蔽门子门的集合
// 旁路继电器的工作原理是,当电路中的电流超过预定的阈值时,旁路继电器会自动断开电路,从而防止电路发生短路或过载等故障。
type PsdCircuitState struct {
//关门继电器,true-吸合
XGMJ bool
//4编组开门继电器,true-吸合
G4XKMJ bool
//8编组开门继电器,true-吸合
G8XKMJ bool
//门关闭继电器,true-吸合
XMGJ bool
//门旁路继电器,true-吸合
XMPLJ bool
//车站下行侧屏蔽门开门码
XOpenCode OpenCode
//关门继电器,true-吸合
SGMJ bool
//4编组开门继电器,true-吸合
G4SKMJ bool
//8编组开门继电器,true-吸合
G8SKMJ bool
//门关闭继电器,true-吸合
SMGJ bool
//门旁路继电器,true-吸合
SMPLJ bool
//车站上行侧屏蔽门开门码
SOpenCode OpenCode
}
// PsdCellState 车站屏蔽门子门
type PsdCellState struct {
//屏蔽门打开的百分比则0-完全关闭100-完全打开
Rate int8
//关门操作被激活
actClosing bool
//开门操作被激活
actOpening bool
}
// PsdTags 屏蔽门标签
type PsdTags struct {
STag EntityTag //上行侧屏蔽门子门标签
S4KmUpTag EntityTag //上行侧4编组运行方向上行时屏蔽门子门标签
S4KmDownTag EntityTag //上行侧4编组运行方向下行时屏蔽门子门标签
S8KmUpTag EntityTag //上行侧8编组运行方向上行时屏蔽门子门标签
S8KmDownTag EntityTag //上行侧8编组运行方向下行时屏蔽门子门标签
XTag EntityTag
X4KmUpTag EntityTag
X4KmDownTag EntityTag
X8KmUpTag EntityTag
X8KmDownTag EntityTag
queryMap map[EntityTag]*ecs.Query
}
// 屏蔽门子门查询
func (me *PsdTags) psdCellsQuery(tag EntityTag) *ecs.Query {
if query, ok := me.queryMap[tag]; !ok {
query = ecs.NewQuery(filter.Contains(tag))
me.queryMap[tag] = query
}
return me.queryMap[tag]
}
// PsdsCircuitSystem 站台门电路系统
type PsdsCircuitSystem struct {
}
func NewPsdsCircuitSystem() *PsdsCircuitSystem {
return &PsdsCircuitSystem{}
}
func NewPsdTags() *PsdTags {
return &PsdTags{S4KmUpTag: NewTag(), S8KmDownTag: NewTag(), S4KmDownTag: NewTag(), S8KmUpTag: NewTag(), STag: NewTag(),
XTag: NewTag(), X4KmDownTag: NewTag(), X4KmUpTag: NewTag(), X8KmDownTag: NewTag(), X8KmUpTag: NewTag(),
queryMap: make(map[EntityTag]*ecs.Query, 10)}
}
func NewPsdCellState() *PsdCellState {
return &PsdCellState{}
}
func NewPsdCircuitState() *PsdCircuitState {
return &PsdCircuitState{XMGJ: true, SMGJ: true, XMPLJ: false, XGMJ: false, XOpenCode: OpenCodeNon, G8SKMJ: false,
G4SKMJ: false, G4XKMJ: false, G8XKMJ: false, SGMJ: false, SMPLJ: false, SOpenCode: OpenCodeNon}
}
var (
PsdCircuitStateComponent = ecs.NewComponentType[PsdCircuitState]()
PsdCellStateComponent = ecs.NewComponentType[PsdCellState]()
PsdTagsComponent = ecs.NewComponentType[PsdTags]()
psdCircuitQuery = ecs.NewQuery(filter.Contains(PsdCircuitStateComponent))
psdCellQuery = ecs.NewQuery(filter.Contains(PsdCellStateComponent))
)
// OpenCode 开门码
type OpenCode int8
// 开门码枚举
const (
OpenCodeNon OpenCode = iota + 1 //无效开门码
OpenCodeUp //运行方向为上行的开门码
OpenCodeDown //运行方向为下行的开门码
)
const (
PsdCellRateClosed int8 = 0
PsdCellRateOpened int8 = 100
)
// PSD组合类型和继电器功能名称
const (
PSD_GT = "PSD"
PSD_XGMJ = "XGMJ"
PSD_4XKMJ = "4XKMJ"
PSD_8XKMJ = "8XKMJ"
PSD_XMGJ = "XMGJ"
PSD_XMPLJ = "XMPLJ"
PSD_SGMJ = "SGMJ"
PSD_4SKMJ = "4SKMJ"
PSD_8SKMJ = "8SKMJ"
PSD_SMGJ = "SMGJ"
PSD_SMPLJ = "SMPLJ"
)
// Update world 执行
func (me *PsdsCircuitSystem) Update(w ecs.World) {
me.calculateCellMove(w)
//
psdCircuitQuery.Each(w, func(psdCircuitEntry *ecs.Entry) {
me.calculateSMG(w, psdCircuitEntry)
me.calculateXMG(w, psdCircuitEntry)
me.calculateSGM(w, psdCircuitEntry)
me.calculateXGM(w, psdCircuitEntry)
me.calculate4SKM(w, psdCircuitEntry)
me.calculate4XKM(w, psdCircuitEntry)
me.calculate8SKM(w, psdCircuitEntry)
me.calculate8XKM(w, psdCircuitEntry)
})
}
// 屏蔽门子门移动运算,暂定门从全关到全开耗时2000ms,则v=50/ms
func (me *PsdsCircuitSystem) calculateCellMove(w ecs.World) {
psdCellQuery.Each(w, func(cellEntry *ecs.Entry) {
move := PercentageDeviceStateComponent.Get(cellEntry)
cell := PsdCellStateComponent.Get(cellEntry)
cell.Rate = move.GetRate()
if cell.actOpening {
move.V = 50
}
if cell.actClosing {
move.V = -50
}
if !cell.actOpening && !cell.actClosing {
move.V = 0
}
})
}
// 车站上行侧所有屏蔽门子门关运算
func (me *PsdsCircuitSystem) calculateSMG(w ecs.World, psdCircuitEntry *ecs.Entry) {
tags := PsdTagsComponent.Get(psdCircuitEntry)
isSMG := true
tags.psdCellsQuery(tags.STag).Each(w, func(cellEntry *ecs.Entry) {
if isSMG {
cell := PsdCellStateComponent.Get(cellEntry)
isSMG = cell.Rate <= PsdCellRateClosed
}
})
PsdCircuitStateComponent.Get(psdCircuitEntry).SMGJ = isSMG
}
// 车站下行侧所有屏蔽门子门关运算
func (me *PsdsCircuitSystem) calculateXMG(w ecs.World, psdCircuitEntry *ecs.Entry) {
tags := PsdTagsComponent.Get(psdCircuitEntry)
isXMG := true
tags.psdCellsQuery(tags.XTag).Each(w, func(cellEntry *ecs.Entry) {
if isXMG {
cell := PsdCellStateComponent.Get(cellEntry)
isXMG = cell.Rate <= PsdCellRateClosed
}
})
PsdCircuitStateComponent.Get(psdCircuitEntry).XMGJ = isXMG
}
// 车站上行侧关门操作运算
func (me *PsdsCircuitSystem) calculateSGM(w ecs.World, psdCircuitEntry *ecs.Entry) {
psd := PsdCircuitStateComponent.Get(psdCircuitEntry)
if psd.SGMJ && !psd.G4SKMJ && !psd.G8SKMJ {
tags := PsdTagsComponent.Get(psdCircuitEntry)
tags.psdCellsQuery(tags.STag).Each(w, func(cellEntry *ecs.Entry) {
cell := PsdCellStateComponent.Get(cellEntry)
cell.actClosing = cell.Rate > PsdCellRateClosed
cell.actOpening = false
})
}
}
// 车站下行侧关门操作运算
func (me *PsdsCircuitSystem) calculateXGM(w ecs.World, psdCircuitEntry *ecs.Entry) {
psd := PsdCircuitStateComponent.Get(psdCircuitEntry)
if psd.XGMJ && !psd.G4XKMJ && !psd.G8XKMJ {
tags := PsdTagsComponent.Get(psdCircuitEntry)
tags.psdCellsQuery(tags.XTag).Each(w, func(cellEntry *ecs.Entry) {
cell := PsdCellStateComponent.Get(cellEntry)
cell.actClosing = cell.Rate > PsdCellRateClosed
cell.actOpening = false
})
}
}
// 车站上行侧4编组开门操作运算
func (me *PsdsCircuitSystem) calculate4SKM(w ecs.World, psdCircuitEntry *ecs.Entry) {
psd := PsdCircuitStateComponent.Get(psdCircuitEntry)
if psd.G4SKMJ && !psd.G8SKMJ && !psd.SGMJ && psd.SOpenCode != OpenCodeNon {
tags := PsdTagsComponent.Get(psdCircuitEntry)
switch {
case psd.SOpenCode == OpenCodeUp:
{
tags.psdCellsQuery(tags.S4KmUpTag).Each(w, func(cellEntry *ecs.Entry) {
cell := PsdCellStateComponent.Get(cellEntry)
cell.actClosing = false
cell.actOpening = cell.Rate < PsdCellRateOpened
})
}
case psd.SOpenCode == OpenCodeDown:
{
tags.psdCellsQuery(tags.S4KmDownTag).Each(w, func(cellEntry *ecs.Entry) {
cell := PsdCellStateComponent.Get(cellEntry)
cell.actClosing = false
cell.actOpening = cell.Rate < PsdCellRateOpened
})
}
}
}
}
// 车站下行侧4编组开门操作运算
func (me *PsdsCircuitSystem) calculate4XKM(w ecs.World, psdCircuitEntry *ecs.Entry) {
psd := PsdCircuitStateComponent.Get(psdCircuitEntry)
if psd.G4XKMJ && !psd.G8XKMJ && !psd.XGMJ && psd.XOpenCode != OpenCodeNon {
tags := PsdTagsComponent.Get(psdCircuitEntry)
switch {
case psd.XOpenCode == OpenCodeUp:
{
tags.psdCellsQuery(tags.X4KmUpTag).Each(w, func(cellEntry *ecs.Entry) {
cell := PsdCellStateComponent.Get(cellEntry)
cell.actClosing = false
cell.actOpening = cell.Rate < PsdCellRateOpened
})
}
case psd.XOpenCode == OpenCodeDown:
{
tags.psdCellsQuery(tags.X4KmDownTag).Each(w, func(cellEntry *ecs.Entry) {
cell := PsdCellStateComponent.Get(cellEntry)
cell.actClosing = false
cell.actOpening = cell.Rate < PsdCellRateOpened
})
}
}
}
}
// 车站上行侧8编组开门操作运算
func (me *PsdsCircuitSystem) calculate8SKM(w ecs.World, psdCircuitEntry *ecs.Entry) {
psd := PsdCircuitStateComponent.Get(psdCircuitEntry)
if !psd.G4SKMJ && psd.G8SKMJ && !psd.SGMJ && psd.SOpenCode != OpenCodeNon {
tags := PsdTagsComponent.Get(psdCircuitEntry)
switch {
case psd.SOpenCode == OpenCodeUp:
{
tags.psdCellsQuery(tags.S8KmUpTag).Each(w, func(cellEntry *ecs.Entry) {
cell := PsdCellStateComponent.Get(cellEntry)
cell.actClosing = false
cell.actOpening = cell.Rate < PsdCellRateOpened
})
}
case psd.SOpenCode == OpenCodeDown:
{
tags.psdCellsQuery(tags.S8KmDownTag).Each(w, func(cellEntry *ecs.Entry) {
cell := PsdCellStateComponent.Get(cellEntry)
cell.actClosing = false
cell.actOpening = cell.Rate < PsdCellRateOpened
})
}
}
}
}
// 车站下行侧8编组开门操作运算
func (me *PsdsCircuitSystem) calculate8XKM(w ecs.World, psdCircuitEntry *ecs.Entry) {
psd := PsdCircuitStateComponent.Get(psdCircuitEntry)
if !psd.G4XKMJ && psd.G8XKMJ && !psd.XGMJ && psd.XOpenCode != OpenCodeNon {
tags := PsdTagsComponent.Get(psdCircuitEntry)
switch {
case psd.XOpenCode == OpenCodeUp:
{
tags.psdCellsQuery(tags.X8KmUpTag).Each(w, func(cellEntry *ecs.Entry) {
cell := PsdCellStateComponent.Get(cellEntry)
cell.actClosing = false
cell.actOpening = cell.Rate < PsdCellRateOpened
})
}
case psd.XOpenCode == OpenCodeDown:
{
tags.psdCellsQuery(tags.X8KmDownTag).Each(w, func(cellEntry *ecs.Entry) {
cell := PsdCellStateComponent.Get(cellEntry)
cell.actClosing = false
cell.actOpening = cell.Rate < PsdCellRateOpened
})
}
}
}
}