divwar.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. package divwar
  2. import (
  3. "fmt"
  4. // "log"
  5. "net/http"
  6. "strings"
  7. "sync"
  8. "time"
  9. "wartank/pkg/components/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.Section
  22. bot types.ИБот
  23. alarm types.ИСтатПарам
  24. net *divwarnet.DivWarNet
  25. conn *http.Client
  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. sf := &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. // sf.shotTimeFull.Set(8000) // 8000 msec
  51. var err error
  52. { // ISection
  53. sf.Section, err = section.NewSection(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. sf.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 sf.run()
  65. go sf.reservTick()
  66. return sf, nil
  67. }
  68. func (sf *DivWar) reservTick() {
  69. defer sf.ВремяОпрос().Стоп()
  70. for {
  71. select {
  72. case <-sf.bot.Кнт().Done():
  73. return
  74. default:
  75. ct0 := sf.ВремяОпрос().Получ()
  76. time.Sleep(time.Second * 7)
  77. ct1 := sf.ВремяОпрос().Получ()
  78. if ct1 != ct0 {
  79. continue
  80. }
  81. if sf.divon != nil {
  82. continue
  83. }
  84. sf.chDivWar <- 1
  85. }
  86. }
  87. }
  88. // запускает в работу битву дивизий
  89. func (sf *DivWar) run() {
  90. sf.chDivWar <- 1
  91. for {
  92. select {
  93. case <-sf.bot.Кнт().Done():
  94. sf.ВремяОпрос().Стоп()
  95. return
  96. case <-sf.ВремяОпрос().КаналСиг(): // Время обновить данные по сражению
  97. sf.findTimeCount()
  98. sf.upDivWar()
  99. case <-sf.chDivWar: // Сигнал к началу сражения
  100. sf.block.Lock()
  101. if sf.divon != nil {
  102. continue
  103. }
  104. sf.alarm.Уст(1)
  105. sf.sound.Play()
  106. go sf.DivWar() // Запустить цикл непосредственного сражения
  107. time.Sleep(time.Second * 10) // Задержка для звука на странице
  108. sf.alarm.Уст(0)
  109. }
  110. }
  111. }
  112. // Ищет время до начала битвы дивизий
  113. func (sf *DivWar) findTimeCount() {
  114. if err := sf.net.UpdateLst(); err != nil { // Здесь может уже обратный отсчёт перед сражением
  115. sf.chDivWar <- 1
  116. return
  117. }
  118. var (
  119. strOut string
  120. lstDivWar = sf.СписПолучить()
  121. isFind bool
  122. ind int
  123. )
  124. for ind, strOut = range lstDivWar {
  125. if strings.Contains(strOut, `до начала: `) {
  126. ind++
  127. strOut = lstDivWar[ind]
  128. isFind = true
  129. break
  130. }
  131. if strings.Contains(strOut, `>ОБЫЧНЫЕ<`) { // Это уже битва
  132. sf.chDivWar <- 1
  133. return
  134. }
  135. }
  136. if !isFind { // Битва дивизий уже идёт
  137. sf.chDivWar <- 1
  138. return
  139. }
  140. lstTime := strings.Split(strOut, `<span>`)
  141. strTime := lstTime[1]
  142. lstTime = strings.Split(strTime, `</span>`)
  143. strTime = lstTime[0]
  144. if err := sf.ParseCountDown(strTime); err != nil {
  145. // log._rintf("WARN DivWar.findTimeCount(): при установке времени ожидания битвы дивизий(%v)\n\terr=%v\n", strTime, err)
  146. return
  147. }
  148. }
  149. // При необходимости поднимает взвод в атаку, вызывается только если обнаружено приглашение (+)
  150. func (sf *DivWar) upDivWar() {
  151. var (
  152. strOut string
  153. lstDivWar = sf.СписПолучить()
  154. isFind bool
  155. )
  156. for _, strOut = range lstDivWar {
  157. if strings.Contains(strOut, `>Взвод, подъем! В атаку!<`) {
  158. isFind = true
  159. break
  160. }
  161. if strings.Contains(strOut, `<div class="white medium cntr bold mb5">Вы в рядах участников</div>`) {
  162. // log._rintf("INFO DivWar.upDivWar(): уже зарегистрирован\n")
  163. return
  164. }
  165. }
  166. if !isFind {
  167. return
  168. }
  169. // Найдено приглашение на участие
  170. lstUp := strings.Split(strOut, `<a class="simple-but border" href="`)
  171. linkUp := lstUp[1]
  172. lstUp = strings.Split(linkUp, `"><span><span>Взвод, подъем! В атаку!</span></span></a>`)
  173. linkUp = "https://wartank.ru/" + lstUp[0]
  174. lstDivWar, err := sf.net.Get(linkUp)
  175. if err != nil {
  176. // log._rintf("ERRO DivWar.upDivWar(): при выполнении GET-команды на подъём в атаку, err=\n\t%v\n", err)
  177. return
  178. }
  179. if err = sf.СтрОбновить(lstDivWar); err != nil {
  180. // log._rintf("ERRO DivWar.upDivWar(): при обновлении lstDivWar, err=\n\t%v\n", err)
  181. }
  182. // log._rintf("INFO DivWar.upDivWar(): регистрация прошла успешно\n")
  183. }
  184. // Ведёт сражение
  185. func (sf *DivWar) DivWar() {
  186. defer func() {
  187. sf.divon = nil
  188. sf.block.Unlock()
  189. if err := sf.SetCountDown(1); err != nil {
  190. panic(fmt.Errorf("DivWar.DivWar(): при установке CountDown, err=\n\t%w", err))
  191. }
  192. // log.Printf("INFO DivWar.DivWar(): сражение завершено\n")
  193. }()
  194. var err error
  195. sf.divon, err = divwaron.NewDivWarOn(sf.bot) // IDivWarOn (онлайн)
  196. if err != nil {
  197. // log._rintf("ERRO DivWar.DivWarOn(): при создании IDivWarOn, err=\n\t%v\n", err)
  198. time.Sleep(time.Millisecond * 250)
  199. return
  200. }
  201. // Цикл ожидания окончания сражения
  202. for !sf.divon.ЕслиКонец().Получ() {
  203. time.Sleep(time.Second * 1)
  204. }
  205. }
  206. // Alarm -- возвращает признак начала сражения (для браузера)
  207. func (sf *DivWar) Alarm() types.ИСтатПарам {
  208. return sf.alarm
  209. }