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.

163 lines
3.5 KiB

3 years ago
3 years ago
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. roleMap map[int]int
  12. roleList map[int][]models.Device
  13. due bool
  14. lastInterval int64
  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. // Collect all devices into the undefined role (-1)
  20. for _, list := range s.roleList {
  21. for _, device := range list {
  22. devices = append(devices, device)
  23. s.roleMap[device.ID] = -1
  24. }
  25. }
  26. s.roleList = map[int][]models.Device{-1: devices}
  27. // Update data and reset devices.
  28. s.data = &data
  29. for _, device := range append(devices[:0:0], devices...) {
  30. s.UpsertDevice(device)
  31. }
  32. }
  33. // UpsertDevice moves the device if necessary and updates its state.
  34. func (s *Scene) UpsertDevice(device models.Device) {
  35. if s.data == nil {
  36. s.roleMap[device.ID] = -1
  37. s.roleList[-1] = append(s.roleList[-1], device)
  38. return
  39. }
  40. oldIndex, hasOldIndex := s.roleMap[device.ID]
  41. newIndex := s.data.RoleIndex(&device)
  42. s.roleMap[device.ID] = newIndex
  43. if hasOldIndex {
  44. for i, device2 := range s.roleList[oldIndex] {
  45. if device2.ID == device.ID {
  46. s.roleList[oldIndex] = append(s.roleList[oldIndex][:i], s.roleList[oldIndex][i+1:]...)
  47. break
  48. }
  49. }
  50. }
  51. s.due = true
  52. s.roleList[newIndex] = append(s.roleList[newIndex], device)
  53. if newIndex != -1 {
  54. s.data.Roles[newIndex].ApplyOrder(s.roleList[newIndex])
  55. }
  56. }
  57. // RemoveDevice finds and remove a device. It's a noop if the device does not exist in this scene.
  58. func (s *Scene) RemoveDevice(device models.Device) {
  59. roleIndex, hasRoleIndex := s.roleMap[device.ID]
  60. if !hasRoleIndex {
  61. return
  62. }
  63. for i, device2 := range s.roleList[roleIndex] {
  64. if device2.ID == device.ID {
  65. s.roleList[roleIndex] = append(s.roleList[roleIndex][:i], s.roleList[roleIndex][i+1:]...)
  66. break
  67. }
  68. }
  69. s.due = true
  70. delete(s.roleMap, device.ID)
  71. }
  72. func (s *Scene) Due() bool {
  73. if s.due {
  74. return true
  75. }
  76. if s.data.IntervalMS > 0 {
  77. interval := time.Duration(s.data.IntervalMS) * time.Millisecond
  78. return int64(time.Since(s.startTime)/interval) != s.lastInterval
  79. }
  80. return false
  81. }
  82. func (s *Scene) UnaffectedDevices() []models.Device {
  83. return append(s.roleList[-1][:0:0], s.roleList[-1]...)
  84. }
  85. func (s *Scene) AllDevices() []models.Device {
  86. res := make([]models.Device, 0, 16)
  87. for _, list := range s.roleList {
  88. res = append(res, list...)
  89. }
  90. return res
  91. }
  92. // Run runs the scene
  93. func (s *Scene) Run() []models.Device {
  94. if s.data == nil {
  95. return []models.Device{}
  96. }
  97. intervalNumber := int64(0)
  98. intervalMax := int64(1)
  99. if s.data.IntervalMS > 0 {
  100. interval := time.Duration(s.data.IntervalMS) * time.Millisecond
  101. intervalNumber = int64(time.Since(s.startTime) / interval)
  102. if !s.endTime.IsZero() {
  103. intervalMax = int64(s.endTime.Sub(s.startTime) / interval)
  104. } else {
  105. intervalMax = intervalNumber + 1
  106. }
  107. }
  108. updatedDevices := make([]models.Device, 0, 16)
  109. for i, list := range s.roleList {
  110. if i == -1 {
  111. continue
  112. }
  113. role := s.data.Roles[i]
  114. for j, device := range list {
  115. newState := role.ApplyEffect(&device, models.SceneRunContext{
  116. Index: j,
  117. Length: len(list),
  118. IntervalNumber: intervalNumber,
  119. IntervalMax: intervalMax,
  120. })
  121. err := device.SetState(newState)
  122. if err != nil {
  123. continue
  124. }
  125. updatedDevices = append(updatedDevices, device)
  126. }
  127. }
  128. s.due = false
  129. s.lastInterval = intervalNumber
  130. return updatedDevices
  131. }