You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
3.0 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package publisher
  2. import (
  3. "git.aiterp.net/lucifer/new-server/models"
  4. "time"
  5. )
  6. type Scene struct {
  7. data *models.Scene
  8. group string
  9. startTime time.Time
  10. endTime time.Time
  11. interval time.Duration
  12. roleMap map[int]int
  13. roleList map[int][]models.Device
  14. due bool
  15. }
  16. // UpdateScene updates the scene data and re-seats all devices.
  17. func (s *Scene) UpdateScene(data models.Scene) {
  18. devices := make([]models.Device, 0, 16)
  19. for ri, list := range s.roleList {
  20. for _, device := range list {
  21. devices = append(devices, device)
  22. s.roleMap[device.ID] = -1
  23. }
  24. }
  25. s.roleList = map[int][]models.Device {-1: devices}
  26. for _, device := range append(devices[:0:0], devices...) {
  27. s.UpsertDevice(device)
  28. }
  29. }
  30. // UpsertDevice moves the device if neccesary and updates its state.
  31. func (s *Scene) UpsertDevice(device models.Device) {
  32. if s.data == nil {
  33. s.roleMap[device.ID] = -1
  34. s.roleList[-1] = append(s.roleList[-1], device)
  35. return
  36. }
  37. oldIndex, hasOldIndex := s.roleMap[device.ID]
  38. newIndex := s.data.RoleIndex(&device)
  39. if hasOldIndex {
  40. if oldIndex == newIndex {
  41. for i, device2 := range s.roleList[newIndex] {
  42. if device2.ID == device.ID {
  43. s.roleList[newIndex][i] = device
  44. s.data.Roles[oldIndex].ApplyOrder(s.roleList[oldIndex])
  45. break
  46. }
  47. }
  48. return
  49. } else {
  50. for i, device2 := range s.roleList[oldIndex] {
  51. if device2.ID == device.ID {
  52. s.roleList[oldIndex] = append(s.roleList[oldIndex][:i], s.roleList[oldIndex][i+1:]...)
  53. break
  54. }
  55. }
  56. }
  57. }
  58. s.roleList[newIndex] = append(s.roleList[newIndex], device)
  59. s.data.Roles[newIndex].ApplyOrder(s.roleList[newIndex])
  60. }
  61. // RemoveDevice finds and remove a device. It's a noop if the device does not exist in this scene.
  62. func (s *Scene) RemoveDevice(device models.Device) {
  63. roleIndex, hasRoleIndex := s.roleMap[device.ID]
  64. if !hasRoleIndex {
  65. return
  66. }
  67. for i, device2 := range s.roleList[roleIndex] {
  68. if device2.ID == device.ID {
  69. s.roleList[roleIndex] = append(s.roleList[roleIndex][:i], s.roleList[roleIndex][i+1:]...)
  70. break
  71. }
  72. }
  73. delete(s.roleMap, device.ID)
  74. }
  75. // Run runs the scene
  76. func (s *Scene) Run() []models.Device {
  77. if s.data == nil {
  78. return []models.Device{}
  79. }
  80. intervalNumber := int64(0)
  81. intervalMax := int64(1)
  82. if s.interval > 0 {
  83. intervalNumber = int64(time.Since(s.startTime) / s.interval)
  84. if !s.endTime.IsZero() {
  85. intervalMax = int64(s.endTime.Sub(s.startTime) / s.interval)
  86. } else {
  87. intervalMax = intervalNumber + 1
  88. }
  89. }
  90. updatedDevices := make([]models.Device, 0, 16)
  91. for i, list := range s.roleList {
  92. if i == -1 {
  93. continue
  94. }
  95. role := s.data.Roles[i]
  96. for j, device := range list {
  97. newState := role.ApplyEffect(&device, models.SceneRunContext{
  98. Index: j,
  99. Length: len(list),
  100. IntervalNumber: intervalNumber,
  101. IntervalMax: intervalMax,
  102. })
  103. err := device.SetState(newState)
  104. if err != nil {
  105. continue
  106. }
  107. updatedDevices = append(updatedDevices, device)
  108. }
  109. }
  110. return updatedDevices
  111. }