divwaron.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package divwaron
  2. import (
  3. "context"
  4. "fmt"
  5. "strings"
  6. "time"
  7. "wartank/pkg/components/safebool"
  8. "wartank/pkg/components/section"
  9. "wartank/pkg/components/sectionnet"
  10. "wartank/pkg/types"
  11. "wartank/server/serv_bots/warbot/angar/division/divwar/divwaron/health"
  12. "wartank/server/serv_bots/warbot/angar/division/divwar/divwaron/manevr"
  13. "wartank/server/serv_bots/warbot/angar/division/divwar/divwaron/shot"
  14. )
  15. /*
  16. Предоставляет сетевой компонент при непосредственном сражении
  17. */
  18. // DivWarOn -- непосредственно танкует в сражении
  19. type DivWarOn struct {
  20. *section.Section
  21. net *sectionnet.SectionNet
  22. server types.IServer
  23. ctxDivWar context.Context // Контекст сражения
  24. fnCancelDivWar func() // Функция отмены сражения
  25. shot *shot.Shot // Объект выстрела
  26. health *health.Health // Текущее здоровье танка
  27. manevr *manevr.Manevr // Возможность маневрирования
  28. login string
  29. isMasking *safebool.SafeBool // Признак необходимости маскирования (запрет стрельбы, когда слабое здоровье)
  30. chTick chan int // Ежесекудная проверка на окончание сражения
  31. isEnd *safebool.SafeBool
  32. }
  33. // NewDivWarOn -- возвращает новый *DivWarOn
  34. func NewDivWarOn(server types.IServer, bot types.IServBot) (*DivWarOn, error) {
  35. { // Предусловия
  36. if server == nil {
  37. return nil, fmt.Errorf("NewDivWarOn(): IServer == nil")
  38. }
  39. if bot == nil {
  40. return nil, fmt.Errorf("NewDivWarOn(): IServBot == nil")
  41. }
  42. }
  43. ctxDivWar, fnCancelDivWar := context.WithTimeout(server.CtxApp(), time.Second*305)
  44. sf := &DivWarOn{
  45. server: server,
  46. ctxDivWar: ctxDivWar,
  47. fnCancelDivWar: fnCancelDivWar,
  48. login: bot.Name(),
  49. isMasking: safebool.NewSafeBool(),
  50. isEnd: safebool.NewSafeBool(),
  51. }
  52. var err error
  53. { // ISection (ожидание)
  54. sf.Section, err = section.NewSection(server, `<title>Сражения</title>`)
  55. if err != nil {
  56. return nil, fmt.Errorf("NewDivWarOn(): in create *Section, err=\n\t%w", err)
  57. }
  58. }
  59. // sf.net = sectionnet.NewSectionNet(server, bot, "http://wartank.ru/pve")
  60. if sf.checkEnd() {
  61. return nil, fmt.Errorf("NewDivWarOn(): нет страницы для сражения")
  62. }
  63. go sf.makeTick()
  64. go sf.run()
  65. return sf, nil
  66. }
  67. // Ежесекудный тик
  68. func (sf *DivWarOn) makeTick() {
  69. defer func() {
  70. close(sf.chTick)
  71. sf.isEnd.Set()
  72. }()
  73. for !sf.isEnd.Get() {
  74. select {
  75. case <-sf.server.Done(): // Отмена контекста приложения
  76. return
  77. case <-sf.ctxDivWar.Done(): // Битва закончилась
  78. return
  79. default:
  80. if sf.isEnd.Get() {
  81. return
  82. }
  83. sf.chTick <- 1
  84. time.Sleep(time.Second * 1)
  85. }
  86. }
  87. }
  88. // запускает сражение
  89. func (sf *DivWarOn) run() {
  90. // defer log._rintf("DivWarOn.run(): сражение завершено\n")
  91. { // Подготовка к сражению
  92. var err error
  93. sf.shot, err = shot.NewShot(sf, sf.login) // Объект выстрела
  94. if err != nil {
  95. // log._rintf("ERRO DivWarOn.Run(): при создании выстрела танка, err=\n\t%v\n", err)
  96. return
  97. }
  98. sf.health, err = health.NewHealth(sf, sf.shot.IsEnd(), sf.login)
  99. if err != nil {
  100. // log._rintf("ERRO DivWarOn.Run(): при создании здоровья танка, err=\n\t%v\n", err)
  101. sf.shot.IsEnd().Reset()
  102. return
  103. }
  104. sf.manevr, err = manevr.NewManevr(sf, sf.shot.IsEnd())
  105. if err != nil {
  106. // log._rintf("ERRO DivWarOn.Run(): при создании маневра танка, err=\n\t%v\n", err)
  107. sf.shot.IsEnd().Reset()
  108. return
  109. }
  110. }
  111. for { // Рабочий цикл сражения
  112. select {
  113. case <-sf.ctxDivWar.Done():
  114. return
  115. case <-sf.CountDown().ChanSig():
  116. if sf.checkEnd() {
  117. return
  118. }
  119. }
  120. }
  121. }
  122. // Net -- возвращает сетевой компонент секции
  123. func (sf *DivWarOn) Net() types.ISectionNet {
  124. return sf.net
  125. }
  126. // Проверяет окончание сражения
  127. func (sf *DivWarOn) checkEnd() bool {
  128. defer func() {
  129. if sf.isEnd.Get() {
  130. sf.fnCancelDivWar()
  131. // log._rintf("DivWarOn.checkEnd(): сражение завершено\n")
  132. }
  133. }()
  134. if err := sf.net.UpdateLst("Битва дивизий+"); err != nil {
  135. // log._rintf("WARN DivWarOn.checkEnd(): при обновлении lstDivWarOn, err=\n\t%v\n", err)
  136. sf.isEnd.Set()
  137. sf.fnCancelDivWar()
  138. return true
  139. }
  140. lstDivWarOn := sf.GetLst()
  141. for _, strOut := range lstDivWarOn {
  142. if strings.Contains(strOut, `" class="simple-but gray"><span><span>ОБЫЧНЫЕ</span></span></a>`) {
  143. sf.isEnd.Reset()
  144. return false
  145. }
  146. }
  147. sf.isEnd.Set()
  148. sf.fnCancelDivWar()
  149. return true
  150. }
  151. // IsEnd -- возвращает признак окончания сражения (интерфейс)
  152. func (sf *DivWarOn) IsEnd() *safebool.SafeBool {
  153. return sf.isEnd
  154. }
  155. func (sf *DivWarOn) Manevr() {
  156. if sf.manevr == nil {
  157. return
  158. }
  159. if sf.manevr.IsReady() {
  160. sf.manevr.Manevr()
  161. }
  162. }
  163. // Masking -- признак запрета стрельбы при слабом здоровье
  164. func (sf *DivWarOn) Masking() *safebool.SafeBool {
  165. return sf.isMasking
  166. }
  167. // Ctx -- возвращает контекст отмены сражения
  168. func (sf *DivWarOn) Ctx() context.Context {
  169. return sf.ctxDivWar
  170. }
  171. // CancelBattle - -вызов функции отмены контекста сражения
  172. func (sf *DivWarOn) CancelBattle() {
  173. sf.fnCancelDivWar()
  174. }