diff --git a/simulation/components/common_component.go b/simulation/components/common.go similarity index 79% rename from simulation/components/common_component.go rename to simulation/components/common.go index dc20ceb..8164223 100644 --- a/simulation/components/common_component.go +++ b/simulation/components/common.go @@ -5,11 +5,16 @@ import ( "joylink.club/rtsssimulation/state" ) +// 系统时钟组件 +var ComSystemTimer = ecs.NewComponentType[state.SystemTimer]() + // 身份组件 var ComDeviceIdentity = ecs.NewComponentType[state.DeviceIdentity]() // 道岔状态组件 var ComSwitchState = ecs.NewComponentType[state.SwitchState]() + +// 道岔正常转动组件 var ComSwitchTurnOperating = ecs.NewComponentType[state.SwitchTurnOperating]() // 物理区段状态组件 diff --git a/simulation/examples/main.go b/simulation/examples/main.go new file mode 100644 index 0000000..a3266ee --- /dev/null +++ b/simulation/examples/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "fmt" + "time" + + "joylink.club/ecs" + "joylink.club/rtsssimulation/components" + "joylink.club/rtsssimulation/memory" + "joylink.club/rtsssimulation/state" + "joylink.club/rtsssimulation/system" +) + +func main() { + world := ecs.NewWorld(300) + worlTime := time.Now() + //外界与world交互的门面 + face := memory.InitializeWorld(world, worlTime) + //当组件为显示set值时,world会初始化组件的零值 + switch1Entry := world.Create(components.ComDeviceIdentity, components.ComSwitchState, components.ComSwitchTurnOperating) + components.ComDeviceIdentity.Set(switch1Entry, &state.DeviceIdentity{Id: "switch1"}) + components.ComSwitchState.Set(switch1Entry, &state.SwitchState{Normal: true, Reverse: false}) + world.AddSystem(system.NewSwitchSystem()) + // + world.StartUp() + time.Sleep(2 * time.Second) + // + + reslult, _ := face.Call(func(w ecs.World) any { + fmt.Println("==>>3触发转动道岔 ...") + return system.FireSwitchTurn(w, "switch1", false, 3000) + }) + fmt.Println("==>>3触发转动道岔 。。。", reslult) + // + fmt.Println("==>>world 当前时间:", face.WorldTime().GoString()) + time.Sleep(4 * time.Second) + world.Close() +} diff --git a/simulation/memory/init_world.go b/simulation/memory/init_world.go new file mode 100644 index 0000000..bc8492b --- /dev/null +++ b/simulation/memory/init_world.go @@ -0,0 +1,23 @@ +package memory + +import ( + "time" + + "joylink.club/ecs" + "joylink.club/rtsssimulation/components" + "joylink.club/rtsssimulation/state" + "joylink.club/rtsssimulation/system" +) + +// 初始化world,添加一些内置的组件和系统 +func InitializeWorld(w ecs.World, worldTime time.Time) *system.FaceSystem { + //初始化world时钟 + timeEntry := w.Create(components.ComSystemTimer) + components.ComSystemTimer.Set(timeEntry, state.NewSystemTimer(&worldTime)) + w.AddSystem(system.NewTimerSystem()) + //初始化world与外界交互的门面 + faceSystem := system.NewFaceSystem(w) + w.AddSystem(faceSystem) + // + return faceSystem +} diff --git a/simulation/state/system_state.go b/simulation/state/system_state.go new file mode 100644 index 0000000..b1d00b3 --- /dev/null +++ b/simulation/state/system_state.go @@ -0,0 +1,32 @@ +package state + +import "time" + +// 此文件中为与设备无关的仿真系统自身的状态定义 + +// 系统时钟,单例 +type SystemTimer struct { + timer *time.Time +} + +// 以指定时间构建 +func NewSystemTimer(time *time.Time) *SystemTimer { + return &SystemTimer{ + timer: time, + } +} + +// 重置时间 +func (me *SystemTimer) ResetTime(time time.Time) { + *me.timer = time +} + +// 获取当前时间的副本 +func (me *SystemTimer) Now() time.Time { + return *me.timer +} + +// tick系统时钟,单位ms +func (me *SystemTimer) Tick(tick int) { + *me.timer = me.timer.Add(time.Duration(tick) * time.Millisecond) +} diff --git a/simulation/system/face_system.go b/simulation/system/face_system.go new file mode 100644 index 0000000..ecfd3a2 --- /dev/null +++ b/simulation/system/face_system.go @@ -0,0 +1,71 @@ +package system + +import ( + "sync" + "time" + + "joylink.club/ecs" +) + +// 外界与world交互请求定义 +type FaceRequest func(w ecs.World) any +type faceOutcome struct { + outcome any + ok bool +} + +// 外界与world的交互 +type FaceSystem struct { + req chan FaceRequest + rsp chan *faceOutcome + world ecs.World + //保证与world的交互串行 + locker *sync.Mutex +} + +func NewFaceSystem(w ecs.World) *FaceSystem { + return &FaceSystem{req: make(chan FaceRequest), rsp: make(chan *faceOutcome), locker: &sync.Mutex{}, world: w} +} + +// world 执行 +func (me *FaceSystem) Update(world ecs.World) { + select { + case reqFunc := <-me.req: + { + response := reqFunc(world) + if nil != response { + me.rsp <- &faceOutcome{outcome: response, ok: true} + } else { + me.rsp <- &faceOutcome{outcome: nil, ok: false} + } + } + default: + } +} + +// 外界调用此方法与world交互 +func (me *FaceSystem) Call(request FaceRequest) (any, bool) { + if !me.world.Running() { + return nil, false + } + // + me.locker.Lock() + defer me.locker.Unlock() + // + me.req <- request + // + result := <-me.rsp + return result.outcome, result.ok +} + +// 获取world当前时间 +func (me *FaceSystem) WorldTime() *time.Time { + now, ok := me.Call(func(w ecs.World) any { + return GetWorldNow(w) + }) + if ok { + return now.(*time.Time) + } else { + return nil + } +} diff --git a/simulation/system/SwitchSystem.go b/simulation/system/switch_system.go similarity index 88% rename from simulation/system/SwitchSystem.go rename to simulation/system/switch_system.go index 7729f84..d5688eb 100644 --- a/simulation/system/SwitchSystem.go +++ b/simulation/system/switch_system.go @@ -1,6 +1,8 @@ package system import ( + "fmt" + "github.com/yohamta/donburi/filter" "joylink.club/ecs" "joylink.club/rtsssimulation/components" @@ -24,7 +26,7 @@ func NewSwitchSystem() *SwitchSystem { // switchId: 道岔id // turnNormal: true-道岔转动到定位,false-道岔转动到反位 // turnTime: 道岔转动耗时ms -func FireSwitchTurn(w ecs.World, switchId string, turnNormal bool, turnTime int64) bool { +func FireSwitchTurn(w ecs.World, switchId string, turnNormal bool, turnTime int) bool { fireQuery := ecs.NewQuery(filter.Contains(components.ComDeviceIdentity, components.ComSwitchTurnOperating)) // var turnOperating *state.SwitchTurnOperating @@ -39,7 +41,7 @@ func FireSwitchTurn(w ecs.World, switchId string, turnNormal bool, turnTime int6 } // turnOperating.TurnNormal = turnNormal - turnOperating.TurningTime = turnTime + turnOperating.TurningTime = int64(turnTime) turnOperating.StartTurn = true return true } @@ -50,7 +52,8 @@ func (me *SwitchSystem) Update(w ecs.World) { me.turningQuery.Each(w, func(e *ecs.Entry) { if turnOperting := components.ComSwitchTurnOperating.Get(e); turnOperting.StartTurn { if turnOperting.TurningTime > 0 { //正在转动 - //todo + turnOperting.TurningTime -= int64(w.Tick()) + fmt.Println("==>>正在转动道岔 ...") } else { //转动完成 turnOperting.StartTurn = false state := components.ComSwitchState.Get(e) @@ -61,6 +64,7 @@ func (me *SwitchSystem) Update(w ecs.World) { state.Normal = false state.Reverse = true } + fmt.Println("==>>完成转动道岔") } } }) diff --git a/simulation/system/timer_system.go b/simulation/system/timer_system.go new file mode 100644 index 0000000..ff202ea --- /dev/null +++ b/simulation/system/timer_system.go @@ -0,0 +1,45 @@ +package system + +import ( + "time" + + "github.com/yohamta/donburi/filter" + "joylink.club/ecs" + "joylink.club/rtsssimulation/components" +) + +var timerQuery *ecs.Query = ecs.NewQuery(filter.Contains(components.ComSystemTimer)) + +// 系统时钟操作 +type TimerSystem struct { +} + +func NewTimerSystem() *TimerSystem { + return &TimerSystem{} +} + +// world 执行 +func (me *TimerSystem) Update(w ecs.World) { + if e, ok := timerQuery.First(w); ok { + timer := components.ComSystemTimer.Get(e) + timer.Tick(w.Tick()) + } +} + +// 重置world时间 +func ResetWorldTimer(w ecs.World, time time.Time) { + if e, ok := timerQuery.First(w); ok { + timer := components.ComSystemTimer.Get(e) + timer.ResetTime(time) + } +} + +// 获取world当前时间 +func GetWorldNow(w ecs.World) *time.Time { + if e, ok := timerQuery.First(w); ok { + timer := components.ComSystemTimer.Get(e) + now := timer.Now() + return &now + } + return nil +}