iscs bas 大系统
This commit is contained in:
parent
3cb6678a19
commit
7a4ad7d1bb
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.23.1
|
||||
// source: component/ci.proto
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.23.1
|
||||
// source: component/common.proto
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.23.1
|
||||
// source: component/points.proto
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.23.1
|
||||
// source: component/psd.proto
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.23.1
|
||||
// source: component/signal.proto
|
||||
|
||||
|
@ -10,7 +10,7 @@ type AirConditioning struct {
|
||||
var (
|
||||
AirConditioningType = ecs.NewComponentType[AirConditioning]() //空调
|
||||
|
||||
CombinationAirConditionerTag = ecs.NewTag() //组合式空调
|
||||
CombinationAirConditionerTag = ecs.NewTag() //组合式空调(变频空调)
|
||||
AirConditioningGroupTag = ecs.NewTag() //空调群控系统
|
||||
AirConditionerTag = ecs.NewTag() //空调器
|
||||
)
|
||||
|
@ -2,37 +2,128 @@ package component
|
||||
|
||||
import "joylink.club/ecs"
|
||||
|
||||
// FluidPipe 流体管线
|
||||
type FluidPipe struct {
|
||||
Direction PipeFlowDirection //管线内综合流动方向
|
||||
FlowSpeed float32 //管线内综合流量,m3/h
|
||||
Sources []*SourceFlow //该管线内所有流体源投射的分量
|
||||
}
|
||||
///////////////////////////////////////////
|
||||
//组合空调柜AHU-A01 二通阀MOV-A01
|
||||
//回排风机RAF-A01 风阀MDD-A03
|
||||
//排烟风机SEF-A01 风阀MDD-A04
|
||||
//排风阀MDA-A02
|
||||
//回风阀MDA-A03
|
||||
//小新风阀MDA-A01
|
||||
//空调柜MDD-A02
|
||||
//防烟防火SFD-A01
|
||||
|
||||
// SourceFlow 流体源进入管线的流体描述
|
||||
type SourceFlow struct {
|
||||
Direction PipeFlowDirection
|
||||
FlowSpeed float32
|
||||
}
|
||||
|
||||
// PipeFlowDirection 管线内流体流动方向定义
|
||||
type PipeFlowDirection int8
|
||||
// PipeMatter 管线中传输的物质类型
|
||||
type PipeMatter uint8
|
||||
|
||||
const (
|
||||
PipeFlowNon PipeFlowDirection = iota //流体未流动
|
||||
PipeFlowAb //流体从管线的A->B
|
||||
PipeFlowBa //流体从管线的B->A
|
||||
PmtNon PipeMatter = iota //未知或没有
|
||||
PmtWater
|
||||
PmtElectricity //电
|
||||
PmtAir //正常空气
|
||||
PmtSmoke //含有有害烟的空气(如火灾时的烟气)
|
||||
PmtOil //油
|
||||
)
|
||||
|
||||
func (d *PipeFlowDirection) IsFlowAb() bool {
|
||||
return *d == PipeFlowAb
|
||||
func (m *PipeMatter) IsNon() bool {
|
||||
return *m == PmtNon
|
||||
}
|
||||
func (d *PipeFlowDirection) IsFlowBa() bool {
|
||||
return *d == PipeFlowBa
|
||||
func (m *PipeMatter) IsEle() bool {
|
||||
return *m == PmtElectricity
|
||||
}
|
||||
func (d *PipeFlowDirection) IsFlowNon() bool {
|
||||
return *d == PipeFlowNon
|
||||
|
||||
// PipeDirection 管线中物质传输方向定义
|
||||
type PipeDirection uint8
|
||||
|
||||
const (
|
||||
PdNon PipeDirection = iota //无方向
|
||||
PdAb //方向A=>B
|
||||
PdBa //方向B=>A
|
||||
)
|
||||
|
||||
func (d *PipeDirection) IsAb() bool {
|
||||
return *d == PdAb
|
||||
}
|
||||
func (d *PipeDirection) IsBa() bool {
|
||||
return *d == PdBa
|
||||
}
|
||||
func (d *PipeDirection) IsNon() bool {
|
||||
return *d == PdNon
|
||||
}
|
||||
|
||||
// Pipe 管线一般状态定义
|
||||
type Pipe struct {
|
||||
Matter PipeMatter //管线中物质类型
|
||||
Direction PipeDirection //管线中物质运动方向
|
||||
}
|
||||
|
||||
// PipeElectricity 电线(三相交流,一般单相交流,直流)
|
||||
// 如果是三相电,则简化认为每相电压电流一样
|
||||
type PipeElectricity struct {
|
||||
U uint32 //电压
|
||||
I uint32 //电流
|
||||
Sx bool //true-三相交流电,此时Ac无效;false-一般单相电,此时Ua Ia Ac有效
|
||||
Ac bool //true-交流;false-直流
|
||||
Sources map[string]*ElectricitySource //key-电源实体id,value-电源投影
|
||||
}
|
||||
|
||||
func NewPipeElectricity() *PipeElectricity {
|
||||
return &PipeElectricity{Sources: make(map[string]*ElectricitySource)}
|
||||
}
|
||||
func (p *PipeElectricity) FromElectricitySource(es *ElectricitySource) {
|
||||
p.U = es.U
|
||||
p.Sx = es.Sx
|
||||
p.Ac = es.Ac
|
||||
}
|
||||
func (p *PipeElectricity) TransPower(powerSourceId string, power *ElectricitySource) {
|
||||
ep, ok := p.Sources[powerSourceId]
|
||||
if ok {
|
||||
*ep = *power
|
||||
ep.Fresh -= 1
|
||||
} else {
|
||||
p.Sources[powerSourceId] = &ElectricitySource{}
|
||||
*p.Sources[powerSourceId] = *power
|
||||
p.Sources[powerSourceId].Fresh -= 1
|
||||
}
|
||||
}
|
||||
|
||||
// ElectricitySource 电源(三相交流,一般单相交流,直流)
|
||||
type ElectricitySource struct {
|
||||
Fresh int64 //该电力值更新的时间戳
|
||||
U uint32 //电压
|
||||
I uint32 //电流
|
||||
Sx bool //true-三相交流电,此时Ac无效;false-一般单相电,此时Ua Ia Ac有效
|
||||
Ac bool //true-交流;false-直流
|
||||
}
|
||||
|
||||
func NewElectricitySource() *ElectricitySource {
|
||||
return &ElectricitySource{}
|
||||
}
|
||||
|
||||
// SetOut0 设置0输出
|
||||
func (s *ElectricitySource) SetOut0() {
|
||||
s.U = 0
|
||||
s.I = 0
|
||||
}
|
||||
|
||||
// PipeFluid 流体(液体气体)管线
|
||||
type PipeFluid struct {
|
||||
T float32 //温度
|
||||
}
|
||||
|
||||
func NewPipeFluid() *PipeFluid {
|
||||
return &PipeFluid{}
|
||||
}
|
||||
|
||||
var (
|
||||
PipeType = ecs.NewComponentType[Pipe]() //电线
|
||||
PipeElectricityType = ecs.NewComponentType[PipeElectricity]() //电线电力
|
||||
PipeFluidType = ecs.NewComponentType[PipeFluid]() //管线流体
|
||||
|
||||
ElectricitySourceType = ecs.NewComponentType[ElectricitySource]() //电源
|
||||
|
||||
)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// FluidDriver 流体驱动器
|
||||
type FluidDriver struct {
|
||||
@ -40,6 +131,5 @@ type FluidDriver struct {
|
||||
}
|
||||
|
||||
var (
|
||||
FluidPipeType = ecs.NewComponentType[FluidPipe]() //流体管线
|
||||
FluidDriverType = ecs.NewComponentType[FluidDriver]() //流体驱动器
|
||||
)
|
||||
|
@ -102,32 +102,6 @@ type EarthingDevice struct {
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
// PowerPipe 电力母线
|
||||
type PowerPipe struct {
|
||||
Voltage uint32 //母线当前电压
|
||||
Ac bool //true-交流电;false-直流电
|
||||
Sources map[string]*ElePower //key-电源PowerSource实体id
|
||||
}
|
||||
|
||||
func (p *PowerPipe) TransPower(powerSourceId string, power *ElePower) {
|
||||
ep, ok := p.Sources[powerSourceId]
|
||||
if ok {
|
||||
*ep = *power
|
||||
ep.Fresh -= 1
|
||||
} else {
|
||||
p.Sources[powerSourceId] = &ElePower{}
|
||||
*p.Sources[powerSourceId] = *power
|
||||
p.Sources[powerSourceId].Fresh -= 1
|
||||
}
|
||||
}
|
||||
|
||||
// ElePower 传输中的电力
|
||||
type ElePower struct {
|
||||
Fresh int64 //该电力值更新的时间戳
|
||||
Voltage uint32 //电压
|
||||
Ac bool //true-交流电;false-直流电
|
||||
}
|
||||
|
||||
// PscadaVoltageLevel 电力母线当前电压等级定义
|
||||
type PscadaVoltageLevel uint8
|
||||
|
||||
@ -139,12 +113,6 @@ const (
|
||||
PscadaVoltageDc1500V //1500V直流
|
||||
)
|
||||
|
||||
// PowerSource 电源(国家电网)
|
||||
type PowerSource struct {
|
||||
Voltage uint32 //电压
|
||||
Ac bool //true-交流电;false-直流电
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var (
|
||||
@ -156,8 +124,6 @@ var (
|
||||
LightningArresterType = ecs.NewComponentType[LightningArrester]() //避雷器
|
||||
RectifierType = ecs.NewComponentType[Rectifier]() //整流器
|
||||
VoltageTransformerType = ecs.NewComponentType[VoltageTransformer]() //变压器
|
||||
PowerPipeType = ecs.NewComponentType[PowerPipe]() //电力母线
|
||||
PowerSourceType = ecs.NewComponentType[PowerSource]() //电源
|
||||
EarthingDeviceType = ecs.NewComponentType[EarthingDevice]() //接地装置
|
||||
)
|
||||
|
||||
|
@ -2,7 +2,6 @@ package entity
|
||||
|
||||
import (
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/repository/model/proto"
|
||||
)
|
||||
|
||||
// LoadIscs 加载ISCS相关设备实体
|
||||
@ -10,10 +9,7 @@ func LoadIscs(w ecs.World) error {
|
||||
data := GetWorldData(w)
|
||||
//电力母线实体
|
||||
for _, pipe := range data.Repo.PipeMap {
|
||||
switch pipe.PipeType {
|
||||
case proto.Pipe_ElectricPower:
|
||||
NewPowerPipeEntity(w, pipe.Id())
|
||||
}
|
||||
NewPipeEntity(w, pipe.Id())
|
||||
}
|
||||
//断路器
|
||||
for _, circuitBreaker := range data.Repo.CircuitBreakerMap {
|
||||
@ -41,7 +37,7 @@ func LoadIscs(w ecs.World) error {
|
||||
}
|
||||
//电源
|
||||
for _, ps := range data.Repo.PowerSourceMap {
|
||||
NewPowerSourceEntity(w, ps.Id(), ps.Ac, ps.Voltage)
|
||||
NewPowerSourceEntity(w, ps.Id())
|
||||
}
|
||||
//避雷器
|
||||
for _, la := range data.Repo.LightningArresterMap {
|
||||
|
@ -107,27 +107,23 @@ func NewVoltageTransformerEntity(w ecs.World, id string) *ecs.Entry {
|
||||
return e
|
||||
}
|
||||
|
||||
// NewPowerPipeEntity 创建PSCADA电力母线实体
|
||||
func NewPowerPipeEntity(w ecs.World, id string) *ecs.Entry {
|
||||
func NewPipeEntity(w ecs.World, id string) *ecs.Entry {
|
||||
wd := GetWorldData(w)
|
||||
e, ok := wd.EntityMap[id]
|
||||
if !ok {
|
||||
e = w.Entry(w.Create(component.UidType, component.PowerPipeType))
|
||||
component.UidType.SetValue(e, component.Uid{Id: id})
|
||||
component.PowerPipeType.Set(e, &component.PowerPipe{Sources: make(map[string]*component.ElePower)})
|
||||
e = w.Entry(w.Create(component.UidType, component.PipeType))
|
||||
wd.EntityMap[id] = e
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// NewPowerSourceEntity 创建PSCADA电源实体
|
||||
func NewPowerSourceEntity(w ecs.World, id string, ac bool, voltage uint32) *ecs.Entry {
|
||||
func NewPowerSourceEntity(w ecs.World, id string) *ecs.Entry {
|
||||
wd := GetWorldData(w)
|
||||
e, ok := wd.EntityMap[id]
|
||||
if !ok {
|
||||
e = w.Entry(w.Create(component.UidType, component.PowerSourceType))
|
||||
e = w.Entry(w.Create(component.UidType, component.ElectricitySourceType))
|
||||
component.UidType.SetValue(e, component.Uid{Id: id})
|
||||
component.PowerSourceType.Set(e, &component.PowerSource{Ac: ac, Voltage: voltage})
|
||||
wd.EntityMap[id] = e
|
||||
}
|
||||
return e
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit e83feb89dd84e3456aafebb7d6dbe179675344e8
|
||||
Subproject commit bd947baa4edadb6b7bd059f6e324fb20f8171f8f
|
@ -607,11 +607,6 @@ message Pipe{
|
||||
string code = 2;
|
||||
DevicePort portA = 3;//管线的A端连接的设备
|
||||
DevicePort portB = 4;//管线的B端连接的设备
|
||||
enum Type{
|
||||
Fluid = 0;//流体(气体、液体)
|
||||
ElectricPower = 1;//电力母线、电线
|
||||
}
|
||||
Type pipeType = 5; //管线类型
|
||||
}
|
||||
//管件
|
||||
//管件端口分别为A B C D
|
||||
@ -668,12 +663,13 @@ message VoltageTransformer{
|
||||
message PowerSource{
|
||||
string id = 1;
|
||||
string code = 2;
|
||||
//true-三相交流电;false-单相电
|
||||
bool sx = 3;
|
||||
//true-交流电源;false-直流电源
|
||||
bool ac = 3;
|
||||
bool ac = 4;
|
||||
//电源电压
|
||||
uint32 voltage = 4;
|
||||
uint32 voltage = 5;
|
||||
}
|
||||
|
||||
//避雷器
|
||||
message LightningArrester{
|
||||
string id = 1;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.23.1
|
||||
// source: cg_repo.proto
|
||||
|
||||
|
@ -11,13 +11,12 @@ import (
|
||||
type Pipe struct {
|
||||
Identity
|
||||
Code string
|
||||
PipeType proto.Pipe_Type
|
||||
PortA DevicePort //管线的A端连接的设备
|
||||
PortB DevicePort //管线的B端连接的设备
|
||||
}
|
||||
|
||||
func NewPipe(id string, code string, pipeType proto.Pipe_Type) *Pipe {
|
||||
return &Pipe{Identity: &identity{id: id, deviceType: proto.DeviceType_DeviceType_Pipe}, Code: code, PipeType: pipeType}
|
||||
func NewPipe(id string, code string) *Pipe {
|
||||
return &Pipe{Identity: &identity{id: id, deviceType: proto.DeviceType_DeviceType_Pipe}, Code: code}
|
||||
}
|
||||
func (p *Pipe) PortNum() int {
|
||||
return 2
|
||||
@ -105,16 +104,6 @@ func (p *PipeFitting) Ports() []*PipePort {
|
||||
return ports
|
||||
}
|
||||
|
||||
// IsEle true-管件为电力管件
|
||||
func (p *PipeFitting) IsEle() bool {
|
||||
for _, port := range p.Ports() {
|
||||
if port.pipe.PipeType != proto.Pipe_ElectricPower {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// PipeFittingPort 管件端口
|
||||
//
|
||||
// implement DevicePort
|
||||
@ -365,16 +354,18 @@ type PowerSource struct {
|
||||
Identity
|
||||
Code string
|
||||
PortA *PipePort //电源A端口连接的管线
|
||||
Ac bool //true-交流;false-直流
|
||||
Voltage uint32 //电压,单位V
|
||||
Sx bool //true-三相交流电;false-单相
|
||||
Ac bool //true-交流;false-直流
|
||||
}
|
||||
|
||||
func NewPowerSource(id string, code string, ac bool, voltage uint32) *PowerSource {
|
||||
func NewPowerSource(id string, code string, voltage uint32, sx bool, ac bool) *PowerSource {
|
||||
return &PowerSource{
|
||||
Identity: &identity{id: id, deviceType: proto.DeviceType_DeviceType_PowerSource},
|
||||
Code: code,
|
||||
Ac: ac,
|
||||
Voltage: voltage,
|
||||
Sx: sx,
|
||||
Ac: ac,
|
||||
}
|
||||
}
|
||||
func (p *PowerSource) PortNum() int {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,7 @@ import "joylink.club/rtsssimulation/repository/model/proto"
|
||||
func buildIscsModels(source *proto.Repository, repository *Repository) error {
|
||||
//ISCS管线
|
||||
for _, protoData := range source.Pipes {
|
||||
m := NewPipe(protoData.Id, protoData.Code, protoData.PipeType)
|
||||
m := NewPipe(protoData.Id, protoData.Code)
|
||||
repository.PipeMap[m.Id()] = m
|
||||
}
|
||||
//ISCS管件
|
||||
@ -46,7 +46,7 @@ func buildIscsModels(source *proto.Repository, repository *Repository) error {
|
||||
}
|
||||
//ISCS电源
|
||||
for _, protoData := range source.PowerSources {
|
||||
m := NewPowerSource(protoData.Id, protoData.Code, protoData.Ac, protoData.Voltage)
|
||||
m := NewPowerSource(protoData.Id, protoData.Code, protoData.Voltage, protoData.Sx, protoData.Ac)
|
||||
repository.PowerSourceMap[m.Id()] = m
|
||||
}
|
||||
//ISCS避雷器
|
||||
|
@ -23,7 +23,7 @@ type FluidDriverSystem struct {
|
||||
func NewFluidDriverSystem() *FluidDriverSystem {
|
||||
return &FluidDriverSystem{
|
||||
query: ecs.NewQuery(filter.Contains(component.UidType, component.FluidDriverType)),
|
||||
queryFluidPipe: ecs.NewQuery(filter.Contains(component.UidType, component.FluidPipeType)),
|
||||
queryFluidPipe: ecs.NewQuery(filter.Contains(component.UidType, component.PipeFluidType)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,125 +38,7 @@ func (s *FluidDriverSystem) findFluidPath(fromDevice repository.Identity, fromDe
|
||||
return sp
|
||||
}
|
||||
func (s *FluidDriverSystem) Update(w ecs.World) {
|
||||
wd := entity.GetWorldData(w)
|
||||
s.query.Each(w, func(entry *ecs.Entry) {
|
||||
fdId := component.UidType.Get(entry).Id
|
||||
fd := component.FluidDriverType.Get(entry)
|
||||
fluidDriverOn := fd.On
|
||||
fdModel := wd.Repo.FindById(fdId)
|
||||
if fdModel == nil {
|
||||
fmt.Printf("==>>FluidDriver[%s]模型不存在\n", fdId)
|
||||
} else {
|
||||
switch fdModel.Type() {
|
||||
case proto.DeviceType_DeviceType_Fan: //风机
|
||||
{
|
||||
fanModel := fdModel.(*repository.Fan)
|
||||
fanOutPort := *fanModel.PortA
|
||||
fanInPort := *fanModel.PortB
|
||||
fanOutPath := s.findFluidPath(fanModel, fanOutPort, true)
|
||||
fanInPath := s.findFluidPath(fanModel, fanInPort, false)
|
||||
//
|
||||
s.calculateFluid(w, fluidDriverOn, fanOutPath, fanInPath)
|
||||
}
|
||||
case proto.DeviceType_DeviceType_AirPavilion: //风亭,其中送风亭为动力源
|
||||
{
|
||||
apModel := fdModel.(*repository.AirPavilion)
|
||||
if apModel.PavilionType == proto.AirPavilion_AirSupplyPavilion {
|
||||
apOutPort := *apModel.PortA
|
||||
apOutPath := s.findFluidPath(apModel, apOutPort, true)
|
||||
s.calculateFluid(w, fluidDriverOn, apOutPath, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
//
|
||||
s.queryFluidPipe.Each(w, func(entry *ecs.Entry) {
|
||||
pipe := component.FluidPipeType.Get(entry)
|
||||
if len(pipe.Sources) > 0 {
|
||||
directionAb := int8(0)
|
||||
for _, ps := range pipe.Sources {
|
||||
if ps.Direction.IsFlowAb() {
|
||||
directionAb++
|
||||
}
|
||||
if ps.Direction.IsFlowBa() {
|
||||
directionAb--
|
||||
}
|
||||
}
|
||||
if directionAb > 0 {
|
||||
pipe.Direction = component.PipeFlowAb
|
||||
} else if directionAb < 0 {
|
||||
pipe.Direction = component.PipeFlowBa
|
||||
} else {
|
||||
pipe.Direction = component.PipeFlowNon
|
||||
}
|
||||
} else {
|
||||
pipe.Direction = component.PipeFlowNon
|
||||
pipe.FlowSpeed = 0
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 计算流体在管线中的流动参数
|
||||
func (s *FluidDriverSystem) calculateFluid(w ecs.World, fluidDriverOn bool, outPath []*SearchedPath, inPath []*SearchedPath) {
|
||||
for _, out := range outPath {
|
||||
s.clearFluidPathSources(w, out)
|
||||
}
|
||||
for _, in := range inPath {
|
||||
s.clearFluidPathSources(w, in)
|
||||
}
|
||||
//
|
||||
if fluidDriverOn {
|
||||
var validOutPath, validInPath []*SearchedPath
|
||||
for _, out := range outPath {
|
||||
if s.isFluidPathUnblocked(out, w) {
|
||||
validOutPath = append(validOutPath, out)
|
||||
}
|
||||
}
|
||||
for _, in := range inPath {
|
||||
if s.isFluidPathUnblocked(in, w) {
|
||||
validInPath = append(validInPath, in)
|
||||
}
|
||||
}
|
||||
isValid := len(outPath) > 0 && len(inPath) > 0 && len(validInPath) > 0 && len(validOutPath) > 0 || len(outPath) > 0 && len(inPath) == 0 && len(inPath) > 0
|
||||
if isValid {
|
||||
wd := entity.GetWorldData(w)
|
||||
for _, outSp := range validOutPath {
|
||||
for _, outPipe := range outSp.ViaPipes {
|
||||
pipeEntry := wd.EntityMap[outPipe.Device().Id()]
|
||||
fluidPipe := component.FluidPipeType.Get(pipeEntry)
|
||||
fluidPipe.Sources = append(fluidPipe.Sources, &component.SourceFlow{Direction: convertFlowDirection(outPipe)})
|
||||
}
|
||||
}
|
||||
for _, inSp := range validInPath {
|
||||
for _, inPipe := range inSp.ViaPipes {
|
||||
pipeEntry := wd.EntityMap[inPipe.Device().Id()]
|
||||
fluidPipe := component.FluidPipeType.Get(pipeEntry)
|
||||
fluidPipe.Sources = append(fluidPipe.Sources, &component.SourceFlow{Direction: convertFlowDirection(inPipe)})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
func convertFlowDirection(sp repository.PipePort) component.PipeFlowDirection {
|
||||
switch sp.Port() {
|
||||
case proto.Port_A:
|
||||
return component.PipeFlowAb
|
||||
case proto.Port_B:
|
||||
return component.PipeFlowBa
|
||||
default:
|
||||
return component.PipeFlowNon
|
||||
}
|
||||
}
|
||||
|
||||
// 清空管线流体源
|
||||
func (s *FluidDriverSystem) clearFluidPathSources(w ecs.World, path *SearchedPath) {
|
||||
wd := entity.GetWorldData(w)
|
||||
for _, pipe := range path.ViaPipes {
|
||||
pipeEntry := wd.EntityMap[pipe.Device().Id()]
|
||||
fluidPipe := component.FluidPipeType.Get(pipeEntry)
|
||||
fluidPipe.Sources = fluidPipe.Sources[0:0]
|
||||
}
|
||||
}
|
||||
|
||||
// 判断路径是否畅通
|
||||
|
@ -46,10 +46,17 @@ func towPipePortsTransPower(
|
||||
breakerPortB *repository.PipePort) {
|
||||
//断路器A端连接的管线
|
||||
breakerPortAPipeEntry := wd.EntityMap[breakerPortA.Device().Id()]
|
||||
breakerPortAPipe := component.PowerPipeType.Get(breakerPortAPipeEntry)
|
||||
if !breakerPortAPipeEntry.HasComponent(component.PipeElectricityType) {
|
||||
breakerPortAPipeEntry.AddComponent(component.PipeElectricityType)
|
||||
}
|
||||
breakerPortAPipe := component.PipeElectricityType.Get(breakerPortAPipeEntry)
|
||||
//断路器B端连接的管线
|
||||
breakerPortBPipeEntry := wd.EntityMap[breakerPortB.Device().Id()]
|
||||
breakerPortBPipe := component.PowerPipeType.Get(breakerPortBPipeEntry)
|
||||
if !breakerPortBPipeEntry.HasComponent(component.PipeElectricityType) {
|
||||
breakerPortBPipeEntry.AddComponent(component.PipeElectricityType)
|
||||
}
|
||||
breakerPortBPipe := component.PipeElectricityType.Get(breakerPortBPipeEntry)
|
||||
|
||||
//A->B
|
||||
for portAPipePsId, portAPipePs := range breakerPortAPipe.Sources { //A
|
||||
portBPipePs, ok := breakerPortBPipe.Sources[portAPipePsId] //B
|
||||
@ -58,15 +65,15 @@ func towPipePortsTransPower(
|
||||
*breakerPortBPipe.Sources[portAPipePsId] = *portAPipePs
|
||||
breakerPortBPipe.Sources[portAPipePsId].Fresh -= 1
|
||||
if !closed {
|
||||
breakerPortBPipe.Sources[portAPipePsId].Voltage = 0
|
||||
breakerPortBPipe.Sources[portAPipePsId].SetOut0()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
breakerPortBPipe.Sources[portAPipePsId] = &component.ElePower{}
|
||||
breakerPortBPipe.Sources[portAPipePsId] = component.NewElectricitySource()
|
||||
*breakerPortBPipe.Sources[portAPipePsId] = *portAPipePs
|
||||
breakerPortBPipe.Sources[portAPipePsId].Fresh -= 1
|
||||
if !closed {
|
||||
breakerPortBPipe.Sources[portAPipePsId].Voltage = 0
|
||||
breakerPortBPipe.Sources[portAPipePsId].SetOut0()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -78,15 +85,15 @@ func towPipePortsTransPower(
|
||||
*breakerPortAPipe.Sources[portBPipePsId] = *portBPipePs
|
||||
breakerPortAPipe.Sources[portBPipePsId].Fresh -= 1
|
||||
if !closed {
|
||||
breakerPortAPipe.Sources[portBPipePsId].Voltage = 0
|
||||
breakerPortAPipe.Sources[portBPipePsId].SetOut0()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
breakerPortAPipe.Sources[portBPipePsId] = &component.ElePower{}
|
||||
breakerPortAPipe.Sources[portBPipePsId] = component.NewElectricitySource()
|
||||
*breakerPortAPipe.Sources[portBPipePsId] = *portBPipePs
|
||||
breakerPortAPipe.Sources[portBPipePsId].Fresh -= 1
|
||||
if !closed {
|
||||
breakerPortAPipe.Sources[portBPipePsId].Voltage = 0
|
||||
breakerPortAPipe.Sources[portBPipePsId].SetOut0()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,10 +28,13 @@ func (s *EarthingDeviceSystem) Update(w ecs.World) {
|
||||
edModel := (wd.Repo.FindById(edId)).(*repository.EarthingDevice)
|
||||
if edModel.PortA != nil {
|
||||
edPipeEntry := wd.EntityMap[edModel.PortA.Device().Id()]
|
||||
edPipe := component.PowerPipeType.Get(edPipeEntry)
|
||||
ed.Voltage = edPipe.Voltage
|
||||
if !edPipeEntry.HasComponent(component.PipeElectricityType) {
|
||||
edPipeEntry.AddComponent(component.PipeElectricityType)
|
||||
}
|
||||
edPipe := component.PipeElectricityType.Get(edPipeEntry)
|
||||
ed.Voltage = edPipe.U
|
||||
} else {
|
||||
ed.Voltage = 1 //零电压
|
||||
ed.Voltage = 0 //零电压
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
package iscs_sys
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/component"
|
||||
"joylink.club/rtsssimulation/entity"
|
||||
"joylink.club/rtsssimulation/repository"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
type PipeFittingSystem struct {
|
||||
@ -13,18 +16,27 @@ func NewPipeFittingSystem() *PipeFittingSystem {
|
||||
return &PipeFittingSystem{}
|
||||
}
|
||||
|
||||
// Update 母线管件电能传递
|
||||
// Update in world
|
||||
func (s *PipeFittingSystem) Update(w ecs.World) {
|
||||
wd := entity.GetWorldData(w)
|
||||
for _, pf := range wd.Repo.PipeFittingMap {
|
||||
if pf.IsEle() {
|
||||
//与管件连接的所有管线
|
||||
pipes := pf.Ports()
|
||||
if s.initPipeFitting(wd, pf) && s.isPipeFittingEle(wd, pf) {
|
||||
//筛选出相对电源
|
||||
pipePsMap := make(map[string]*component.ElePower)
|
||||
for _, pipePort := range pipes {
|
||||
pipePsMap := s.findEleSourcePipe(wd, pf)
|
||||
//管件连接的管线间电能传递
|
||||
s.transEle(wd, pf, pipePsMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 筛选出相对电源
|
||||
func (s *PipeFittingSystem) findEleSourcePipe(wd *component.WorldData, pf *repository.PipeFitting) map[string]*component.ElectricitySource {
|
||||
//筛选出相对电源
|
||||
pipePsMap := make(map[string]*component.ElectricitySource)
|
||||
for _, pipePort := range pf.Ports() {
|
||||
pipeEntry := wd.EntityMap[pipePort.Device().Id()]
|
||||
powerPipe := component.PowerPipeType.Get(pipeEntry)
|
||||
if pipeEntry.HasComponent(component.PipeElectricityType) {
|
||||
powerPipe := component.PipeElectricityType.Get(pipeEntry)
|
||||
for epId, ep := range powerPipe.Sources {
|
||||
pipePs, ok := pipePsMap[epId]
|
||||
if ok {
|
||||
@ -36,11 +48,16 @@ func (s *PipeFittingSystem) Update(w ecs.World) {
|
||||
}
|
||||
}
|
||||
}
|
||||
//管件连接的管线间电能传递
|
||||
for _, pipePort := range pipes {
|
||||
}
|
||||
return pipePsMap
|
||||
}
|
||||
|
||||
// 管件连接的管线间电能传递
|
||||
func (s *PipeFittingSystem) transEle(wd *component.WorldData, pf *repository.PipeFitting, pipePsMap map[string]*component.ElectricitySource) {
|
||||
for _, pipePort := range pf.Ports() {
|
||||
for pipePsId, pipePs := range pipePsMap { //相对电源
|
||||
pipeEntry := wd.EntityMap[pipePort.Device().Id()]
|
||||
powerPipe := component.PowerPipeType.Get(pipeEntry)
|
||||
powerPipe := component.PipeElectricityType.Get(pipeEntry)
|
||||
pipePortPs, ok := powerPipe.Sources[pipePsId]
|
||||
if ok {
|
||||
if pipePs.Fresh > pipePortPs.Fresh {
|
||||
@ -48,12 +65,79 @@ func (s *PipeFittingSystem) Update(w ecs.World) {
|
||||
powerPipe.Sources[pipePsId].Fresh -= 1 //保证相对性
|
||||
}
|
||||
} else {
|
||||
powerPipe.Sources[pipePsId] = &component.ElePower{}
|
||||
powerPipe.Sources[pipePsId] = &component.ElectricitySource{}
|
||||
*powerPipe.Sources[pipePsId] = *pipePs
|
||||
powerPipe.Sources[pipePsId].Fresh -= 1 //保证相对性
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 判断该管件是否为连接电线
|
||||
func (s *PipeFittingSystem) isPipeFittingEle(wd *component.WorldData, pf *repository.PipeFitting) bool {
|
||||
for _, pipePort := range pf.Ports() {
|
||||
pipeEntry := wd.EntityMap[pipePort.Device().Id()]
|
||||
pipe := component.PipeType.Get(pipeEntry)
|
||||
if pipe.Matter.IsEle() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 由于初始的管线是无性质的,现根据管件的某个已有性质的管线来初始化管件其他的管线
|
||||
func (s *PipeFittingSystem) initPipeFitting(wd *component.WorldData, pf *repository.PipeFitting) bool {
|
||||
pipeMatter := component.PmtNon
|
||||
for _, pipePort := range pf.Ports() {
|
||||
pipeEntry := wd.EntityMap[pipePort.Device().Id()]
|
||||
pipe := component.PipeType.Get(pipeEntry)
|
||||
if !pipe.Matter.IsNon() {
|
||||
pipeMatter = pipe.Matter
|
||||
break
|
||||
}
|
||||
}
|
||||
//
|
||||
if pipeMatter.IsNon() {
|
||||
return false
|
||||
}
|
||||
//
|
||||
for _, pipePort := range pf.Ports() {
|
||||
pipeEntry := wd.EntityMap[pipePort.Device().Id()]
|
||||
pipe := component.PipeType.Get(pipeEntry)
|
||||
pipe.Matter = pipeMatter
|
||||
switch pipe.Matter {
|
||||
case component.PmtElectricity:
|
||||
{
|
||||
if !pipeEntry.HasComponent(component.PipeElectricityType) {
|
||||
pipeEntry.AddComponent(component.PipeElectricityType)
|
||||
component.PipeElectricityType.Set(pipeEntry, component.NewPipeElectricity())
|
||||
}
|
||||
}
|
||||
case component.PmtAir:
|
||||
fallthrough
|
||||
case component.PmtOil:
|
||||
fallthrough
|
||||
case component.PmtSmoke:
|
||||
fallthrough
|
||||
case component.PmtWater:
|
||||
{
|
||||
if !pipeEntry.HasComponent(component.PipeFluidType) {
|
||||
pipeEntry.AddComponent(component.PipeFluidType)
|
||||
component.PipeFluidType.Set(pipeEntry, component.NewPipeFluid())
|
||||
}
|
||||
}
|
||||
default:
|
||||
slog.Warn(fmt.Sprintf("PipeFittingSystem.initPipeFitting 未处理的管道物质[%d]", pipe.Matter))
|
||||
}
|
||||
}
|
||||
//
|
||||
return true
|
||||
}
|
||||
|
||||
// 从电线实体获取电线
|
||||
func getPipeElectricity(pipeEntry *ecs.Entry) *component.PipeElectricity {
|
||||
if !pipeEntry.HasComponent(component.PipeElectricityType) {
|
||||
pipeEntry.AddComponent(component.PipeElectricityType)
|
||||
}
|
||||
return component.PipeElectricityType.Get(pipeEntry)
|
||||
}
|
||||
|
@ -6,30 +6,34 @@ import (
|
||||
"joylink.club/rtsssimulation/component"
|
||||
)
|
||||
|
||||
// PowerPipeSystem 电力
|
||||
type PowerPipeSystem struct {
|
||||
query *ecs.Query
|
||||
}
|
||||
|
||||
func NewPowerPipeSystem() *PowerPipeSystem {
|
||||
return &PowerPipeSystem{
|
||||
query: ecs.NewQuery(filter.Contains(component.PowerPipeType)),
|
||||
query: ecs.NewQuery(filter.Contains(component.PipeElectricityType)),
|
||||
}
|
||||
}
|
||||
|
||||
// Update 电力母线中电力计算
|
||||
// Update 电线中电力计算
|
||||
func (s *PowerPipeSystem) Update(w ecs.World) {
|
||||
s.query.Each(w, func(entry *ecs.Entry) {
|
||||
pipe := component.PowerPipeType.Get(entry)
|
||||
pipe := component.PipeElectricityType.Get(entry)
|
||||
voltage := uint32(0)
|
||||
ac := false
|
||||
sx := false
|
||||
for _, power := range pipe.Sources {
|
||||
if power.Voltage > voltage {
|
||||
voltage = power.Voltage
|
||||
if power.U > voltage {
|
||||
voltage = power.U
|
||||
ac = power.Ac
|
||||
sx = power.Sx
|
||||
}
|
||||
}
|
||||
//
|
||||
pipe.Voltage = voltage
|
||||
pipe.U = voltage
|
||||
pipe.Ac = ac
|
||||
pipe.Sx = sx
|
||||
})
|
||||
}
|
||||
|
@ -9,26 +9,43 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// PowerSourceSystem 国网
|
||||
type PowerSourceSystem struct {
|
||||
query *ecs.Query
|
||||
}
|
||||
|
||||
func NewPowerSourceSystem() *PowerSourceSystem {
|
||||
return &PowerSourceSystem{
|
||||
query: ecs.NewQuery(filter.Contains(component.UidType, component.PowerSourceType)),
|
||||
query: ecs.NewQuery(filter.Contains(component.UidType, component.ElectricitySourceType)),
|
||||
}
|
||||
}
|
||||
func (s *PowerSourceSystem) Update(w ecs.World) {
|
||||
wd := entity.GetWorldData(w)
|
||||
s.query.Each(w, func(entry *ecs.Entry) {
|
||||
psId := component.UidType.Get(entry).Id
|
||||
ps := component.PowerSourceType.Get(entry)
|
||||
ps := component.ElectricitySourceType.Get(entry)
|
||||
//
|
||||
psModel := (wd.Repo.FindById(psId)).(*repository.PowerSource)
|
||||
pipeId := psModel.PortA.Device().Id()
|
||||
//
|
||||
ps.Fresh = time.Now().UnixMilli()
|
||||
ps.Sx = psModel.Sx
|
||||
ps.Ac = psModel.Ac
|
||||
ps.U = psModel.Voltage
|
||||
//电源传递电力给母线
|
||||
pipeEntry := wd.EntityMap[pipeId]
|
||||
powerPipe := component.PowerPipeType.Get(pipeEntry)
|
||||
powerPipe.TransPower(psId, &component.ElePower{Ac: ps.Ac, Voltage: ps.Voltage, Fresh: time.Now().UnixMilli()})
|
||||
s.transPower(wd, pipeId, ps, psId)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *PowerSourceSystem) transPower(wd *component.WorldData, pipeId string, ps *component.ElectricitySource, psId string) {
|
||||
pipeEntry := wd.EntityMap[pipeId]
|
||||
if !pipeEntry.HasComponent(component.PipeElectricityType) {
|
||||
pipeEntry.AddComponent(component.PipeElectricityType)
|
||||
component.PipeElectricityType.Set(pipeEntry, component.NewPipeElectricity())
|
||||
}
|
||||
pipe := component.PipeType.Get(pipeEntry)
|
||||
pipe.Matter = component.PmtElectricity
|
||||
//
|
||||
powerPipe := component.PipeElectricityType.Get(pipeEntry)
|
||||
powerPipe.TransPower(psId, ps)
|
||||
}
|
||||
|
@ -45,24 +45,25 @@ func (s *RectifierSystem) rectifierTransPower(wd *component.WorldData, entry *ec
|
||||
portF := rectifierModel.PortD //直负
|
||||
//
|
||||
portLPipeEntry := wd.EntityMap[portL.Device().Id()]
|
||||
portLPipe := component.PowerPipeType.Get(portLPipeEntry)
|
||||
portLPipe := component.PipeElectricityType.Get(portLPipeEntry)
|
||||
//
|
||||
portZPipeEntry := wd.EntityMap[portZ.Device().Id()]
|
||||
portZPipe := component.PowerPipeType.Get(portZPipeEntry)
|
||||
portZPipe := component.PipeElectricityType.Get(portZPipeEntry)
|
||||
portFPipeEntry := wd.EntityMap[portF.Device().Id()]
|
||||
portFPipe := component.PowerPipeType.Get(portFPipeEntry)
|
||||
portFPipe := component.PipeElectricityType.Get(portFPipeEntry)
|
||||
//L->Z、F
|
||||
for lpsId, lps := range portLPipe.Sources {
|
||||
if lps.Ac {
|
||||
dcVoltage := uint32(float64(lps.Voltage) * 0.9) //交流电压转直流电压
|
||||
dcVoltage := uint32(float64(lps.U) * 0.9) //交流电压转直流电压
|
||||
//L->Z
|
||||
zps, zpsOk := portZPipe.Sources[lpsId]
|
||||
if zpsOk {
|
||||
zps.Voltage = dcVoltage
|
||||
zps.U = dcVoltage
|
||||
zps.Fresh = lps.Fresh - 1
|
||||
zps.Ac = false
|
||||
zps.Sx = false
|
||||
} else {
|
||||
portZPipe.Sources[lpsId] = &component.ElePower{Ac: false, Voltage: dcVoltage, Fresh: lps.Fresh - 1}
|
||||
portZPipe.Sources[lpsId] = &component.ElectricitySource{Ac: false, Sx: false, U: dcVoltage, Fresh: lps.Fresh - 1}
|
||||
}
|
||||
//L->F
|
||||
fps, fpsOk := portFPipe.Sources[lpsId]
|
||||
@ -71,11 +72,12 @@ func (s *RectifierSystem) rectifierTransPower(wd *component.WorldData, entry *ec
|
||||
dcFVoltage = 1
|
||||
}
|
||||
if fpsOk {
|
||||
fps.Voltage = dcFVoltage
|
||||
fps.U = dcFVoltage
|
||||
fps.Fresh = lps.Fresh - 1
|
||||
fps.Ac = false
|
||||
fps.Sx = false
|
||||
} else {
|
||||
portFPipe.Sources[lpsId] = &component.ElePower{Ac: false, Voltage: dcFVoltage, Fresh: lps.Fresh - 1}
|
||||
portFPipe.Sources[lpsId] = &component.ElectricitySource{Ac: false, Sx: false, U: dcFVoltage, Fresh: lps.Fresh - 1}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,49 +37,48 @@ func (s *VoltageTransformerSystem) voltageTransformerTransPower(wd *component.Wo
|
||||
//
|
||||
vtPortA := vtModel.PortA
|
||||
vtPortAEntry := wd.EntityMap[vtPortA.Device().Id()]
|
||||
vtPortAPipe := component.PowerPipeType.Get(vtPortAEntry) //变压器一次侧连接的管线
|
||||
vtPortAPipe := getPipeElectricity(vtPortAEntry) //变压器一次侧连接的管线
|
||||
//
|
||||
var vtPortBPipe *component.PowerPipe = nil
|
||||
var vtPortBPipe *component.PipeElectricity = nil
|
||||
if vtModel.PortB != nil {
|
||||
vtPortB := vtModel.PortB
|
||||
vtPortBEntry := wd.EntityMap[vtPortB.Device().Id()]
|
||||
vtPortBPipe = component.PowerPipeType.Get(vtPortBEntry)
|
||||
vtPortBPipe = getPipeElectricity(vtPortBEntry)
|
||||
}
|
||||
//
|
||||
var vtPortCPipe *component.PowerPipe = nil
|
||||
var vtPortCPipe *component.PipeElectricity = nil
|
||||
if vtModel.PortC != nil {
|
||||
vtPortC := vtModel.PortC
|
||||
vtPortCEntry := wd.EntityMap[vtPortC.Device().Id()]
|
||||
vtPortCPipe = component.PowerPipeType.Get(vtPortCEntry)
|
||||
vtPortCPipe = getPipeElectricity(vtPortCEntry)
|
||||
}
|
||||
//变压比
|
||||
rate := float64(vtModel.E2) / float64(vtModel.E1)
|
||||
//A->B、C ,电能从一次侧向二次侧传递
|
||||
for psId, ps := range vtPortAPipe.Sources {
|
||||
//二次侧输出电压
|
||||
outV := uint32(rate * float64(ps.Voltage))
|
||||
outV := uint32(rate * float64(ps.U))
|
||||
if vtPortBPipe != nil { //二次侧火线
|
||||
portBPs, ok := vtPortBPipe.Sources[psId]
|
||||
if ok {
|
||||
portBPs.Voltage = outV
|
||||
portBPs.U = outV
|
||||
portBPs.Ac = ps.Ac
|
||||
portBPs.Sx = ps.Sx
|
||||
portBPs.Fresh = ps.Fresh - 1
|
||||
} else {
|
||||
vtPortBPipe.Sources[psId] = &component.ElePower{Ac: ps.Ac, Voltage: outV, Fresh: ps.Fresh - 1}
|
||||
vtPortBPipe.Sources[psId] = &component.ElectricitySource{Ac: ps.Ac, Sx: ps.Sx, U: outV, Fresh: ps.Fresh - 1}
|
||||
}
|
||||
}
|
||||
if vtPortCPipe != nil { //二次侧零线
|
||||
portCPs, ok := vtPortCPipe.Sources[psId]
|
||||
cV := uint32(0)
|
||||
if outV > 0 { //当二次火线电压大于零时,二次侧零线电压值1表示零电位
|
||||
cV = 1
|
||||
}
|
||||
if ok {
|
||||
portCPs.Voltage = cV
|
||||
portCPs.U = cV
|
||||
portCPs.Ac = ps.Ac
|
||||
portCPs.Sx = ps.Sx
|
||||
portCPs.Fresh = ps.Fresh - 1
|
||||
} else {
|
||||
vtPortCPipe.Sources[psId] = &component.ElePower{Ac: ps.Ac, Voltage: cV, Fresh: ps.Fresh - 1}
|
||||
vtPortCPipe.Sources[psId] = &component.ElectricitySource{Ac: ps.Ac, Sx: ps.Sx, U: cV, Fresh: ps.Fresh - 1}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user