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 //无效开门码 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) { // psdCellQuery.Each(w, func(cellEntry *ecs.Entry) { me.calculateCellMove(w, cellEntry) }) // 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, cellEntry *ecs.Entry) { move := PercentageDeviceStateComponent.Get(cellEntry) cell := PsdCellStateComponent.Get(cellEntry) cell.Rate = move.GetRate() if cell.actOpening { move.V = 50 if cell.Rate >= PsdCellRateOpened { //开门到位 move.V = 0 } } if cell.actClosing { move.V = -50 if cell.Rate <= PsdCellRateClosed { //关门到位 move.V = 0 } } if !cell.actOpening && !cell.actClosing { move.V = 0 } } // 车站屏蔽门电路系统继电器励磁运算 ????????-----信息缺失 func (me *PsdsCircuitSystem) calculateRelayLc(w ecs.World, psdCircuitEntry *ecs.Entry) { //psd := PsdCircuitStateComponent.Get(psdCircuitEntry) // } // 车站上行侧所有屏蔽门子门关运算 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 }) } } } }