417 lines
13 KiB
Go
417 lines
13 KiB
Go
package system
|
||
|
||
import (
|
||
"github.com/yohamta/donburi/filter"
|
||
"joylink.club/ecs"
|
||
sysEvent "joylink.club/rtsssimulation/system/event"
|
||
)
|
||
|
||
// PsdDriveXGMJ 联锁驱动XGMJ
|
||
func PsdDriveXGMJ(w ecs.World, psdCircuitId string, lsDrive bool) bool {
|
||
psdEntry := FindEntityById(w, psdCircuitId)
|
||
if psdEntry == nil {
|
||
return false
|
||
}
|
||
psdState := PsdCircuitStateComponent.Get(psdEntry)
|
||
psdState.XGMLs = lsDrive
|
||
return true
|
||
}
|
||
|
||
// PsdDriveSGMJ 联锁驱动SGMJ
|
||
func PsdDriveSGMJ(w ecs.World, psdCircuitId string, lsDrive bool) bool {
|
||
psdEntry := FindEntityById(w, psdCircuitId)
|
||
if psdEntry == nil {
|
||
return false
|
||
}
|
||
psdState := PsdCircuitStateComponent.Get(psdEntry)
|
||
psdState.SGMLs = lsDrive
|
||
return true
|
||
}
|
||
|
||
// PsdDrive4XKMJ 联锁驱动4XKMJ
|
||
func PsdDrive4XKMJ(w ecs.World, psdCircuitId string, lsDrive bool) bool {
|
||
psdEntry := FindEntityById(w, psdCircuitId)
|
||
if psdEntry == nil {
|
||
return false
|
||
}
|
||
psdState := PsdCircuitStateComponent.Get(psdEntry)
|
||
psdState.G4XKMLs = lsDrive
|
||
return true
|
||
}
|
||
|
||
// PsdDrive4SKMJ 联锁驱动4SKMJ
|
||
func PsdDrive4SKMJ(w ecs.World, psdCircuitId string, lsDrive bool) bool {
|
||
psdEntry := FindEntityById(w, psdCircuitId)
|
||
if psdEntry == nil {
|
||
return false
|
||
}
|
||
psdState := PsdCircuitStateComponent.Get(psdEntry)
|
||
psdState.G4SKMLs = lsDrive
|
||
return true
|
||
}
|
||
|
||
// PsdDrive8XKMJ 联锁驱动8XKMJ
|
||
func PsdDrive8XKMJ(w ecs.World, psdCircuitId string, lsDrive bool) bool {
|
||
psdEntry := FindEntityById(w, psdCircuitId)
|
||
if psdEntry == nil {
|
||
return false
|
||
}
|
||
psdState := PsdCircuitStateComponent.Get(psdEntry)
|
||
psdState.G8XKMLs = lsDrive
|
||
return true
|
||
}
|
||
|
||
// PsdDrive8SKMJ 联锁驱动8SKMJ
|
||
func PsdDrive8SKMJ(w ecs.World, psdCircuitId string, lsDrive bool) bool {
|
||
psdEntry := FindEntityById(w, psdCircuitId)
|
||
if psdEntry == nil {
|
||
return false
|
||
}
|
||
psdState := PsdCircuitStateComponent.Get(psdEntry)
|
||
psdState.G8SKMLs = lsDrive
|
||
return true
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////
|
||
|
||
// PsdCircuitState 站台门控制电路状态,Psd为车站所有屏蔽门子门的集合
|
||
// 旁路继电器的工作原理是,当电路中的电流超过预定的阈值时,旁路继电器会自动断开电路,从而防止电路发生短路或过载等故障。
|
||
type PsdCircuitState struct {
|
||
//关门继电器,true-吸合
|
||
XGMJ bool
|
||
//true-联锁驱动
|
||
XGMLs bool
|
||
//4编组开门继电器,true-吸合
|
||
G4XKMJ bool
|
||
//true-联锁驱动
|
||
G4XKMLs bool
|
||
//8编组开门继电器,true-吸合
|
||
G8XKMJ bool
|
||
//true-联锁驱动
|
||
G8XKMLs bool
|
||
//门关闭继电器,true-吸合
|
||
XMGJ bool
|
||
//门旁路继电器,true-吸合
|
||
XMPLJ bool
|
||
//车站下行侧屏蔽门开门码
|
||
XOpenCode OpenCode
|
||
//关门继电器,true-吸合
|
||
SGMJ bool
|
||
//true-联锁驱动
|
||
SGMLs bool
|
||
//4编组开门继电器,true-吸合
|
||
G4SKMJ bool
|
||
//true-联锁驱动
|
||
G4SKMLs bool
|
||
//8编组开门继电器,true-吸合
|
||
G8SKMJ bool
|
||
//true-联锁驱动
|
||
G8SKMLs 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 //无效开门码
|
||
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) {
|
||
|
||
//
|
||
psdCircuitQuery.Each(w, func(psdCircuitEntry *ecs.Entry) {
|
||
me.calculateMG(w, psdCircuitEntry)
|
||
me.calculateGM(w, psdCircuitEntry)
|
||
me.calculate4KM(w, psdCircuitEntry)
|
||
me.calculate8KM(w, psdCircuitEntry)
|
||
me.calculateCellAct(w, psdCircuitEntry)
|
||
me.calculateCellMove(w, psdCircuitEntry)
|
||
})
|
||
}
|
||
|
||
// 屏蔽门子门移动运算,暂定门从全关到全开耗时2000ms,则v=50/ms
|
||
func (me *PsdsCircuitSystem) calculateCellMove(w ecs.World, psdCircuitEntry *ecs.Entry) {
|
||
psdTags := PsdTagsComponent.Get(psdCircuitEntry)
|
||
psdTags.psdCellsQuery(psdTags.XTag).Each(w, func(cellEntry *ecs.Entry) {
|
||
cellState := PsdCellStateComponent.Get(cellEntry)
|
||
cellMove := PercentageDeviceStateComponent.Get(cellEntry)
|
||
if cellState.actClosing {
|
||
cellMove.V = -50
|
||
}
|
||
if cellState.actOpening {
|
||
cellMove.V = 50
|
||
}
|
||
cellState.Rate = cellMove.GetRate()
|
||
})
|
||
psdTags.psdCellsQuery(psdTags.STag).Each(w, func(cellEntry *ecs.Entry) {
|
||
cellState := PsdCellStateComponent.Get(cellEntry)
|
||
cellMove := PercentageDeviceStateComponent.Get(cellEntry)
|
||
if cellState.actClosing {
|
||
cellMove.V = -50
|
||
}
|
||
if cellState.actOpening {
|
||
cellMove.V = 50
|
||
}
|
||
cellState.Rate = cellMove.GetRate()
|
||
})
|
||
}
|
||
|
||
// 屏蔽门子门移动运算,暂定门从全关到全开耗时2000ms,则v=50/ms
|
||
func (me *PsdsCircuitSystem) calculateCellAct(w ecs.World, psdCircuitEntry *ecs.Entry) {
|
||
state := PsdCircuitStateComponent.Get(psdCircuitEntry)
|
||
psdTags := PsdTagsComponent.Get(psdCircuitEntry)
|
||
//关门
|
||
if state.XGMJ {
|
||
psdTags.psdCellsQuery(psdTags.XTag).Each(w, func(cellEntry *ecs.Entry) {
|
||
cellState := PsdCellStateComponent.Get(cellEntry)
|
||
cellState.actClosing = true
|
||
cellState.actOpening = false
|
||
})
|
||
}
|
||
if state.SGMJ {
|
||
psdTags.psdCellsQuery(psdTags.STag).Each(w, func(cellEntry *ecs.Entry) {
|
||
cellState := PsdCellStateComponent.Get(cellEntry)
|
||
cellState.actClosing = true
|
||
cellState.actOpening = false
|
||
})
|
||
}
|
||
//开门
|
||
if state.G4XKMJ {
|
||
var cellTag EntityTag = nil
|
||
if state.XOpenCode == OpenCodeUp {
|
||
cellTag = psdTags.X4KmUpTag
|
||
} else if state.XOpenCode == OpenCodeDown {
|
||
cellTag = psdTags.X4KmDownTag
|
||
}
|
||
if cellTag != nil {
|
||
psdTags.psdCellsQuery(cellTag).Each(w, func(cellEntry *ecs.Entry) {
|
||
cellState := PsdCellStateComponent.Get(cellEntry)
|
||
cellState.actClosing = false
|
||
cellState.actOpening = true
|
||
})
|
||
}
|
||
}
|
||
if state.G4SKMJ {
|
||
var cellTag EntityTag = nil
|
||
if state.SOpenCode == OpenCodeUp {
|
||
cellTag = psdTags.S4KmUpTag
|
||
} else if state.SOpenCode == OpenCodeDown {
|
||
cellTag = psdTags.S4KmDownTag
|
||
}
|
||
if cellTag != nil {
|
||
psdTags.psdCellsQuery(cellTag).Each(w, func(cellEntry *ecs.Entry) {
|
||
cellState := PsdCellStateComponent.Get(cellEntry)
|
||
cellState.actClosing = false
|
||
cellState.actOpening = true
|
||
})
|
||
}
|
||
}
|
||
if state.G8XKMJ {
|
||
var cellTag EntityTag = nil
|
||
if state.XOpenCode == OpenCodeUp {
|
||
cellTag = psdTags.X8KmUpTag
|
||
} else if state.XOpenCode == OpenCodeDown {
|
||
cellTag = psdTags.X8KmDownTag
|
||
}
|
||
if cellTag != nil {
|
||
psdTags.psdCellsQuery(cellTag).Each(w, func(cellEntry *ecs.Entry) {
|
||
cellState := PsdCellStateComponent.Get(cellEntry)
|
||
cellState.actClosing = false
|
||
cellState.actOpening = true
|
||
})
|
||
}
|
||
}
|
||
if state.G8SKMJ {
|
||
var cellTag EntityTag = nil
|
||
if state.SOpenCode == OpenCodeUp {
|
||
cellTag = psdTags.S8KmUpTag
|
||
} else if state.SOpenCode == OpenCodeDown {
|
||
cellTag = psdTags.S8KmDownTag
|
||
}
|
||
if cellTag != nil {
|
||
psdTags.psdCellsQuery(cellTag).Each(w, func(cellEntry *ecs.Entry) {
|
||
cellState := PsdCellStateComponent.Get(cellEntry)
|
||
cellState.actClosing = false
|
||
cellState.actOpening = true
|
||
})
|
||
}
|
||
}
|
||
}
|
||
|
||
func (me *PsdsCircuitSystem) calculateMG(w ecs.World, psdCircuitEntry *ecs.Entry) {
|
||
state := PsdCircuitStateComponent.Get(psdCircuitEntry)
|
||
psdTags := PsdTagsComponent.Get(psdCircuitEntry)
|
||
//
|
||
isXMG := true
|
||
psdTags.psdCellsQuery(psdTags.XTag).Each(w, func(cellEntry *ecs.Entry) {
|
||
if isXMG {
|
||
cellState := PsdCellStateComponent.Get(cellEntry)
|
||
if cellState.Rate > PsdCellRateClosed {
|
||
isXMG = false
|
||
}
|
||
}
|
||
})
|
||
if isXMG != state.XMGJ {
|
||
if event, ok := createRelayNeedChangeEvent(w, EntityIdentityComponent.Get(psdCircuitEntry).Id, PSD_GT, PSD_XMGJ, isXMG); ok {
|
||
sysEvent.RelayNeedChangeEventBus.Publish(w, event)
|
||
}
|
||
}
|
||
//
|
||
isSMG := true
|
||
psdTags.psdCellsQuery(psdTags.STag).Each(w, func(cellEntry *ecs.Entry) {
|
||
if isSMG {
|
||
cellState := PsdCellStateComponent.Get(cellEntry)
|
||
if cellState.Rate > PsdCellRateClosed {
|
||
isSMG = false
|
||
}
|
||
}
|
||
})
|
||
if isSMG != state.SMGJ {
|
||
if event, ok := createRelayNeedChangeEvent(w, EntityIdentityComponent.Get(psdCircuitEntry).Id, PSD_GT, PSD_SMGJ, isSMG); ok {
|
||
sysEvent.RelayNeedChangeEventBus.Publish(w, event)
|
||
}
|
||
}
|
||
}
|
||
|
||
func (me *PsdsCircuitSystem) calculateGM(w ecs.World, psdCircuitEntry *ecs.Entry) {
|
||
state := PsdCircuitStateComponent.Get(psdCircuitEntry)
|
||
//关门继电器:联锁励磁||自闭保持
|
||
isXGM := state.XGMLs || state.XGMJ && !state.G4XKMJ && !state.G8XKMJ
|
||
isSGM := state.SGMLs || state.SGMJ && !state.G4SKMJ && !state.G8SKMJ
|
||
if isXGM != state.XGMJ {
|
||
if event, ok := createRelayNeedChangeEvent(w, EntityIdentityComponent.Get(psdCircuitEntry).Id, PSD_GT, PSD_XGMJ, isXGM); ok {
|
||
sysEvent.RelayNeedChangeEventBus.Publish(w, event)
|
||
}
|
||
}
|
||
if isSGM != state.SGMJ {
|
||
if event, ok := createRelayNeedChangeEvent(w, EntityIdentityComponent.Get(psdCircuitEntry).Id, PSD_GT, PSD_SGMJ, isSGM); ok {
|
||
sysEvent.RelayNeedChangeEventBus.Publish(w, event)
|
||
}
|
||
}
|
||
}
|
||
|
||
func (me *PsdsCircuitSystem) calculate4KM(w ecs.World, psdCircuitEntry *ecs.Entry) {
|
||
//4编组开门继电器:联锁励磁||自闭保持
|
||
state := PsdCircuitStateComponent.Get(psdCircuitEntry)
|
||
is4XKM := state.G4XKMLs || state.G4XKMJ && !state.G8XKMJ && !state.XGMJ
|
||
is4SKM := state.G4SKMLs || state.G4SKMJ && !state.G8SKMJ && !state.SGMJ
|
||
if is4XKM != state.G4XKMJ {
|
||
if event, ok := createRelayNeedChangeEvent(w, EntityIdentityComponent.Get(psdCircuitEntry).Id, PSD_GT, PSD_4XKMJ, is4XKM); ok {
|
||
sysEvent.RelayNeedChangeEventBus.Publish(w, event)
|
||
}
|
||
}
|
||
if is4SKM != state.G4SKMJ {
|
||
if event, ok := createRelayNeedChangeEvent(w, EntityIdentityComponent.Get(psdCircuitEntry).Id, PSD_GT, PSD_4SKMJ, is4SKM); ok {
|
||
sysEvent.RelayNeedChangeEventBus.Publish(w, event)
|
||
}
|
||
}
|
||
}
|
||
|
||
func (me *PsdsCircuitSystem) calculate8KM(w ecs.World, psdCircuitEntry *ecs.Entry) {
|
||
//8编组开门继电器:联锁励磁||自闭保持
|
||
state := PsdCircuitStateComponent.Get(psdCircuitEntry)
|
||
is8XKM := state.G8XKMLs || state.G8XKMJ && !state.G4XKMJ && !state.XGMJ
|
||
is8SKM := state.G8SKMLs || state.G8SKMJ && !state.G4SKMJ && !state.SGMJ
|
||
if is8XKM != state.G8XKMJ {
|
||
if event, ok := createRelayNeedChangeEvent(w, EntityIdentityComponent.Get(psdCircuitEntry).Id, PSD_GT, PSD_8XKMJ, is8XKM); ok {
|
||
sysEvent.RelayNeedChangeEventBus.Publish(w, event)
|
||
}
|
||
}
|
||
if is8SKM != state.G8SKMJ {
|
||
if event, ok := createRelayNeedChangeEvent(w, EntityIdentityComponent.Get(psdCircuitEntry).Id, PSD_GT, PSD_8SKMJ, is8SKM); ok {
|
||
sysEvent.RelayNeedChangeEventBus.Publish(w, event)
|
||
}
|
||
}
|
||
}
|