down_time.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // package down_time -- счётчик обратного времени в мсек
  2. package down_time
  3. import (
  4. "strings"
  5. "sync"
  6. "time"
  7. . "gitp78su.ipnodns.ru/svi/kern"
  8. . "gitp78su.ipnodns.ru/svi/kern/kc/helpers"
  9. . "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
  10. . "wartank/app/lev0/alias"
  11. . "wartank/app/lev0/types"
  12. "wartank/app/lev1/product/parser_time"
  13. )
  14. const (
  15. спатьИнтервал = time.Millisecond * 250 // Малый интервал сна, в мсек
  16. )
  17. // ВремОбрат -- счётчик обратного времени для игровой зоны (анга, база, битва и т.п.)
  18. type ВремОбрат struct {
  19. конт ILocalCtx
  20. остатПарсер ИПарсерВремя // Парсер значения (мсек)
  21. времПорог ISafeInt // Целевое время срабатывания, мсек
  22. канВызов chan int // Канал для отправки сигналов (для верхнего уровня)
  23. блок sync.RWMutex
  24. }
  25. // НовВремОбрат -- возвращает новый *CountTime
  26. func НовВремОбрат(конт ILocalCtx, время АМилСек) *ВремОбрат {
  27. сам := &ВремОбрат{
  28. конт: конт,
  29. времПорог: NewSafeInt(),
  30. канВызов: make(chan int, 2),
  31. остатПарсер: parser_time.НовПарсерВремя(),
  32. }
  33. мСек := АМилСек(TimeNow()) + время
  34. сам.времПорог.Set(int(мСек))
  35. go сам.пуск()
  36. _ = ИВремяОстат(сам)
  37. return сам
  38. }
  39. // ПолучМилСек -- возвращает оставшееся хранимое время остатка
  40. func (сам *ВремОбрат) ПолучМилСек() АМилСек {
  41. return сам.остатПарсер.ПолучМилСек()
  42. }
  43. func (сам *ВремОбрат) ждать() {
  44. time.Sleep(спатьИнтервал)
  45. цОстат := сам.времПорог.Get() - int(TimeNow())
  46. остат := time.Millisecond * time.Duration(цОстат)
  47. стрОстат := остат.String()
  48. if strings.HasPrefix(стрОстат, "-") {
  49. if len(сам.канВызов) < 3 {
  50. сам.канВызов <- 1
  51. }
  52. }
  53. }
  54. // Запускает тикер для интервалов сна (через каждые 1000 мСек)
  55. func (сам *ВремОбрат) пуск() {
  56. defer close(сам.канВызов)
  57. for {
  58. select {
  59. case <-сам.конт.Ctx().Done(): // Отмена контекста тикера (а может и сцены, может и бота)
  60. return
  61. default:
  62. сам.ждать()
  63. }
  64. }
  65. }
  66. // Уст -- устанавливает число оставшихся сек
  67. func (сам *ВремОбрат) Уст(время АВремя) {
  68. сам.блок.Lock()
  69. defer сам.блок.Unlock()
  70. сам.остатПарсер.Уст(время)
  71. _val := сам.остатПарсер.ПолучМилСек()
  72. сам.времПорог.Set(int(TimeNow()) + int(_val))
  73. }
  74. // String -- возвращает строковое представление оставшихся сек
  75. func (сам *ВремОбрат) String() string {
  76. сам.блок.RLock()
  77. defer сам.блок.RUnlock()
  78. цОстат := сам.времПорог.Get() - int(TimeNow())
  79. остат := time.Millisecond * time.Duration(цОстат)
  80. стрОстат := остат.String()
  81. return стрОстат
  82. }
  83. // КаналСиг -- возвращает канал чтения тиков
  84. func (сам *ВремОбрат) КаналСиг() <-chan int {
  85. return сам.канВызов
  86. }