divwar.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. package divwar
  2. import (
  3. "fmt"
  4. "log"
  5. "strings"
  6. "sync"
  7. "time"
  8. "wartank/pkg/alias"
  9. "wartank/pkg/section"
  10. "wartank/pkg/types"
  11. "wartank/server/serv_bots/warbot/angar/division/divwar/divwarnet"
  12. "wartank/server/serv_bots/warbot/angar/division/divwar/divwaron"
  13. "wartank/server/serv_bots/warbot/angar/division/divwar/divwaron/divwarsound"
  14. "wartank/server/serv_bots/warbot/tank/tankstat/static_param"
  15. )
  16. /*
  17. Объект ожидания битвы дивизий
  18. */
  19. // DivWar -- объект ожидания битвы дивизий
  20. type DivWar struct {
  21. *section.Секция
  22. bot types.ИБот
  23. alarm types.ИСтатПарам
  24. net *divwarnet.DivWarNet
  25. conn types.ИВебВоркер
  26. // Непосредственная битва
  27. divon *divwaron.DivWarOn
  28. login string // Для несоредственной битвы дивизий
  29. block sync.Mutex
  30. chDivWar chan int // Сигнал начала битвы дивизий
  31. sound *divwarsound.DivWarSound // Однопоточное проигрывание звука
  32. }
  33. // NewDivWar -- возвращает новый *DivWar
  34. func NewDivWar(bot types.ИБот) (*DivWar, error) {
  35. if bot == nil {
  36. return nil, fmt.Errorf("NewDivWar(): IBot == nil")
  37. }
  38. еслиНач, ош := static_param.НовСтатПарам("alarm")
  39. if ош != nil {
  40. return nil, fmt.Errorf("NewDivWar(): при создании стат еслиНач, ош=\n\t%w", ош)
  41. }
  42. сам := &DivWar{
  43. bot: bot,
  44. alarm: еслиНач,
  45. chDivWar: make(chan int, 1),
  46. sound: divwarsound.NewDivWarSound(),
  47. conn: bot.Сеть().ВебВоркер(),
  48. login: "prospero tank",
  49. }
  50. // сам.shotTimeFull.Set(8000) // 8000 msec
  51. var err error
  52. { // ISection
  53. сам.Секция, err = section.НовСекция(bot, "Битва дивизий", `<span>до начала `)
  54. if err != nil {
  55. return nil, fmt.Errorf("NewDivWar(): in create *Section, err=\n\t%w", err)
  56. }
  57. }
  58. { // Net
  59. сам.net, err = divwarnet.NewDivWarNet(bot)
  60. if err != nil {
  61. return nil, fmt.Errorf("NewDivWar(): при создании DivWarNet, err=\n\t%w", err)
  62. }
  63. }
  64. go сам.run()
  65. go сам.reservTick()
  66. return сам, nil
  67. }
  68. func (сам *DivWar) reservTick() {
  69. for {
  70. select {
  71. case <-сам.bot.Кнт().Done():
  72. return
  73. default:
  74. ct0 := сам.ВремяОстат().ПолучМилСек()
  75. time.Sleep(time.Second * 7)
  76. ct1 := сам.ВремяОстат().ПолучМилСек()
  77. if ct1.Сек() != ct0.Сек() {
  78. continue
  79. }
  80. if сам.divon != nil {
  81. continue
  82. }
  83. сам.chDivWar <- 1
  84. }
  85. }
  86. }
  87. // запускает в работу битву дивизий
  88. func (сам *DivWar) run() {
  89. сам.chDivWar <- 1
  90. for {
  91. select {
  92. case <-сам.bot.Кнт().Done():
  93. return
  94. case <-сам.ВремяОстат().КаналСиг(): // Время обновить данные по сражению
  95. сам.findTimeCount()
  96. сам.upDivWar()
  97. case <-сам.chDivWar: // Сигнал к началу сражения
  98. сам.block.Lock()
  99. if сам.divon != nil {
  100. continue
  101. }
  102. сам.alarm.Уст(1)
  103. сам.sound.Play()
  104. go сам.DivWar() // Запустить цикл непосредственного сражения
  105. time.Sleep(time.Second * 10) // Задержка для звука на странице
  106. сам.alarm.Уст(0)
  107. }
  108. }
  109. }
  110. // Ищет время до начала битвы дивизий
  111. func (сам *DivWar) findTimeCount() {
  112. if err := сам.net.Обновить(); err != nil { // Здесь может уже обратный отсчёт перед сражением
  113. сам.chDivWar <- 1
  114. return
  115. }
  116. var (
  117. strOut string
  118. lstDivWar = сам.СписПолучить()
  119. еслиНайдено bool
  120. ind int
  121. )
  122. for ind, strOut = range lstDivWar {
  123. if strings.Contains(strOut, `до начала: `) {
  124. ind++
  125. strOut = lstDivWar[ind]
  126. еслиНайдено = true
  127. break
  128. }
  129. if strings.Contains(strOut, `>ОБЫЧНЫЕ<`) { // Это уже битва
  130. сам.chDivWar <- 1
  131. return
  132. }
  133. }
  134. if !еслиНайдено { // Битва дивизий уже идёт
  135. сам.chDivWar <- 1
  136. return
  137. }
  138. lstTime := strings.Split(strOut, `<span>`)
  139. strTime := lstTime[1]
  140. lstTime = strings.Split(strTime, `</span>`)
  141. strTime = lstTime[0]
  142. if err := сам.Уст(alias.Время(strTime)); err != nil {
  143. // log._rintf("WARN DivWar.findTimeCount(): при установке времени ожидания битвы дивизий(%v)\n\terr=%v\n", strTime, err)
  144. return
  145. }
  146. }
  147. // При необходимости поднимает взвод в атаку, вызывается только если обнаружено приглашение (+)
  148. func (сам *DivWar) upDivWar() {
  149. var (
  150. strOut string
  151. lstDivWar = сам.СписПолучить()
  152. еслиНайдено bool
  153. )
  154. for _, strOut = range lstDivWar {
  155. if strings.Contains(strOut, `>Взвод, подъем! В атаку!<`) {
  156. еслиНайдено = true
  157. break
  158. }
  159. if strings.Contains(strOut, `<div class="white medium cntr bold mb5">Вы в рядах участников</div>`) {
  160. // log._rintf("INFO DivWar.upDivWar(): уже зарегистрирован\n")
  161. return
  162. }
  163. }
  164. if !еслиНайдено {
  165. return
  166. }
  167. // Найдено приглашение на участие
  168. lstUp := strings.Split(strOut, `<a class="simple-but border" href="`)
  169. linkUp := lstUp[1]
  170. lstUp = strings.Split(linkUp, `"><span><span>Взвод, подъем! В атаку!</span></span></a>`)
  171. linkUp = "https://wartank.ru/" + lstUp[0]
  172. lstDivWar, err := сам.net.Get(linkUp)
  173. if err != nil {
  174. // log._rintf("ERRO DivWar.upDivWar(): при выполнении GET-команды на подъём в атаку, err=\n\t%v\n", err)
  175. return
  176. }
  177. if err = сам.СтрОбновить(lstDivWar); err != nil {
  178. log.Printf("DivWar.upDivWar(): при обновлении lstDivWar, err=\n\t%v\n", err)
  179. }
  180. // log._rintf("INFO DivWar.upDivWar(): регистрация прошла успешно\n")
  181. }
  182. // Ведёт сражение
  183. func (сам *DivWar) DivWar() {
  184. defer func() {
  185. сам.divon = nil
  186. сам.block.Unlock()
  187. if err := сам.Секция.ОбратВремяУст("01"); err != nil {
  188. panic(fmt.Errorf("DivWar.DivWar(): при установке CountDown, err=\n\t%w", err))
  189. }
  190. // log.Printf("INFO DivWar.DivWar(): сражение завершено\n")
  191. }()
  192. var err error
  193. сам.divon, err = divwaron.NewDivWarOn(сам.bot) // IDivWarOn (онлайн)
  194. if err != nil {
  195. // log._rintf("ERRO DivWar.DivWarOn(): при создании IDivWarOn, err=\n\t%v\n", err)
  196. time.Sleep(time.Millisecond * 250)
  197. return
  198. }
  199. // Цикл ожидания окончания сражения
  200. for !сам.divon.ЕслиКонец().Получ() {
  201. time.Sleep(time.Second * 1)
  202. }
  203. }
  204. // Alarm -- возвращает признак начала сражения (для браузера)
  205. func (сам *DivWar) Alarm() types.ИСтатПарам {
  206. return сам.alarm
  207. }