|
|
package publisher
import ( "git.aiterp.net/lucifer/new-server/models" "time" )
type Scene struct { data *models.Scene group string startTime time.Time endTime time.Time interval time.Duration roleMap map[int]int roleList map[int][]models.Device
due bool }
// UpdateScene updates the scene data and re-seats all devices.
func (s *Scene) UpdateScene(data models.Scene) { devices := make([]models.Device, 0, 16)
for ri, list := range s.roleList { for _, device := range list { devices = append(devices, device) s.roleMap[device.ID] = -1 } }
s.roleList = map[int][]models.Device {-1: devices}
for _, device := range append(devices[:0:0], devices...) { s.UpsertDevice(device) } }
// UpsertDevice moves the device if neccesary and updates its state.
func (s *Scene) UpsertDevice(device models.Device) { if s.data == nil { s.roleMap[device.ID] = -1 s.roleList[-1] = append(s.roleList[-1], device) return }
oldIndex, hasOldIndex := s.roleMap[device.ID] newIndex := s.data.RoleIndex(&device)
if hasOldIndex { if oldIndex == newIndex { for i, device2 := range s.roleList[newIndex] { if device2.ID == device.ID { s.roleList[newIndex][i] = device s.data.Roles[oldIndex].ApplyOrder(s.roleList[oldIndex]) break } }
return } else { for i, device2 := range s.roleList[oldIndex] { if device2.ID == device.ID { s.roleList[oldIndex] = append(s.roleList[oldIndex][:i], s.roleList[oldIndex][i+1:]...) break } } } }
s.roleList[newIndex] = append(s.roleList[newIndex], device) s.data.Roles[newIndex].ApplyOrder(s.roleList[newIndex]) }
// RemoveDevice finds and remove a device. It's a noop if the device does not exist in this scene.
func (s *Scene) RemoveDevice(device models.Device) { roleIndex, hasRoleIndex := s.roleMap[device.ID] if !hasRoleIndex { return }
for i, device2 := range s.roleList[roleIndex] { if device2.ID == device.ID { s.roleList[roleIndex] = append(s.roleList[roleIndex][:i], s.roleList[roleIndex][i+1:]...) break } }
delete(s.roleMap, device.ID) }
// Run runs the scene
func (s *Scene) Run() []models.Device { if s.data == nil { return []models.Device{} }
intervalNumber := int64(0) intervalMax := int64(1) if s.interval > 0 { intervalNumber = int64(time.Since(s.startTime) / s.interval)
if !s.endTime.IsZero() { intervalMax = int64(s.endTime.Sub(s.startTime) / s.interval) } else { intervalMax = intervalNumber + 1 } }
updatedDevices := make([]models.Device, 0, 16) for i, list := range s.roleList { if i == -1 { continue }
role := s.data.Roles[i]
for j, device := range list { newState := role.ApplyEffect(&device, models.SceneRunContext{ Index: j, Length: len(list), IntervalNumber: intervalNumber, IntervalMax: intervalMax, })
err := device.SetState(newState) if err != nil { continue }
updatedDevices = append(updatedDevices, device) } }
return updatedDevices }
|