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 }