317 lines
9.8 KiB
Go
317 lines
9.8 KiB
Go
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
|
||
})
|
||
}
|
||
}
|
||
}
|
||
}
|