convoy.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. package convoy
  2. import (
  3. "fmt"
  4. "log"
  5. "strconv"
  6. "strings"
  7. "time"
  8. "github.com/sirupsen/logrus"
  9. "wartank/pkg/components/section"
  10. "wartank/pkg/types"
  11. "wartank/server/serv_bots/warbot/angar/convoy/convoynet"
  12. "wartank/server/serv_bots/warbot/tank/tankstat/static_param"
  13. )
  14. /*
  15. Объект конвоя в ангаре
  16. */
  17. // Convoy -- объект конвоя в ангаре
  18. type Convoy struct {
  19. *section.Section
  20. net *convoynet.ConvoyNet
  21. bot types.IBot
  22. glory types.IStatParam // Количество славы
  23. chAttack chan int // Канал проведения атаки
  24. }
  25. // NewConvoy -- возвращает новый *Convoy
  26. func NewConvoy(bot types.IBot) (*Convoy, error) {
  27. sf := &Convoy{
  28. bot: bot,
  29. glory: static_param.NewStaticParam("glory"),
  30. chAttack: make(chan int, 5),
  31. }
  32. return sf, nil
  33. }
  34. func (sf *Convoy) Run() error {
  35. var err error
  36. { // Section
  37. sf.Section, err = section.NewSection(sf.bot, `<title>Конвой</title>`)
  38. if err != nil {
  39. return fmt.Errorf("Convoy.Run(): in create *Section, err=\n\t%w", err)
  40. }
  41. }
  42. { // SectionNet
  43. sf.net, err = convoynet.NewConvoyNet(sf.bot)
  44. if err != nil {
  45. return fmt.Errorf("Convoy.Run(): in create *SectionNet, err=\n\t%w", err)
  46. }
  47. if err := sf.net.Run(); err != nil {
  48. return fmt.Errorf("Convoy.Run(): in run *SectionNet, err=\n\t%w", err)
  49. }
  50. }
  51. go sf.reservTick()
  52. go sf.run()
  53. return nil
  54. }
  55. // UpdateLst -- принудительно обновляет состояние конвоя
  56. func (sf *Convoy) UpdateLst() {
  57. if err := sf.net.UpdateLst("Конвой"); err != nil {
  58. log.Printf("Convoy.UpdateLst(): err=\n\t%v\n", err)
  59. }
  60. }
  61. // Glory --возвращает счётчик славы конвоя
  62. func (sf *Convoy) Glory() types.IStatParam {
  63. return sf.glory
  64. }
  65. // Если время конвоя замерло -- посылает контрольный сигнал на атаку
  66. func (sf *Convoy) reservTick() {
  67. defer func() {
  68. close(sf.chAttack)
  69. }()
  70. for {
  71. select {
  72. case <-sf.bot.Ctx().Done():
  73. return
  74. default:
  75. ct0 := sf.CountDown().Get()
  76. time.Sleep(time.Second * 60)
  77. ct1 := sf.CountDown().Get()
  78. if ct1 != ct0 {
  79. continue
  80. }
  81. sf.chAttack <- 1
  82. }
  83. }
  84. }
  85. // обрабатывает конвой
  86. func (sf *Convoy) run() {
  87. sf.chAttack <- 1
  88. for {
  89. select {
  90. case <-sf.bot.Ctx().Done():
  91. sf.CountDown().Stop()
  92. return
  93. case <-sf.CountDown().ChanSig(): // Время истекло
  94. sf.updateTime()
  95. sf.updateGlory()
  96. case <-sf.chAttack: // Сигнал к атаке
  97. sf.attackConvoy() // в этом месте только атаковать
  98. sf.checkWarForce()
  99. sf.checkMaster()
  100. sf.check6frage()
  101. }
  102. }
  103. }
  104. // Обновляет славу потребованию
  105. func (sf *Convoy) updateGlory() {
  106. // Найти строку с упоминанием оставшегося времени конвоя
  107. lstConvoy := sf.GetLst()
  108. var (
  109. strGlory string
  110. isFind bool
  111. )
  112. for _, lastTime := range lstConvoy {
  113. if strings.Contains(lastTime, `alt="Слава" title="Слава"> `) {
  114. strGlory = lastTime
  115. isFind = true
  116. break
  117. }
  118. }
  119. if !isFind { // Не найдена строка со славой -- это атака
  120. return
  121. }
  122. // Ищем количество славы
  123. lstGlory := strings.Split(strGlory, `alt="Слава" title="Слава"> `)
  124. strGlory = lstGlory[1]
  125. iGlory, err := strconv.Atoi(strGlory)
  126. if err != nil {
  127. // log._rintf("ERRO ConvoyNet.updateGlory(): слава(%v) не число, err=\n\t%v\n", strGlory, err)
  128. return
  129. }
  130. sf.glory.Set(iGlory)
  131. }
  132. // Обновляет оставшееся время конвоя
  133. func (sf *Convoy) updateTime() {
  134. // Время подходит надо обновляться
  135. if err := sf.net.UpdateLst("Конвой"); err != nil {
  136. logrus.WithError(err).Error("ConvoyNet.updateTime(): при выполнении GET-команды обновления")
  137. sf.CountDown().Set(20)
  138. return
  139. }
  140. // Найти строку с упоминанием оставшегося времени конвоя
  141. lstConvoy := sf.GetLst()
  142. var (
  143. strLastTime string
  144. isFind bool
  145. isMask bool
  146. )
  147. for _, lastTime := range lstConvoy {
  148. if strings.Contains(lastTime, `До следующего конвоя: `) {
  149. strLastTime = lastTime
  150. isFind = true
  151. break
  152. }
  153. if strings.Contains(lastTime, `Полная маскировка через `) {
  154. strLastTime = lastTime
  155. isMask = true
  156. break
  157. }
  158. // <div class="bot"><a class="simple-but border red" w:id="startFight" href="convoy?7-1.ILinkListener-root-startFight"><span><span>В БОЙ!</span></span></a></div>
  159. if strings.Contains(lastTime, `ILinkListener-root-startFight`) {
  160. sf.chAttack <- 1
  161. return
  162. }
  163. if strings.Contains(lastTime, `ILinkListener-root-findEnemy`) {
  164. sf.chAttack <- 1
  165. return
  166. }
  167. // <div class="bot"><a class="simple-but border" w:id="startMasking" href="convoy?12-1.ILinkListener-root-startMasking"><span><span>В БОЙ!</span></span></a></div>
  168. if strings.Contains(lastTime, `ILinkListener-root-startMasking`) {
  169. sf.chAttack <- 1
  170. return
  171. }
  172. }
  173. switch {
  174. case isFind: // Большая пауза между конвоями
  175. // Ждём окончания ожидания конвоя
  176. lstTime := strings.Split(strLastTime, `До следующего конвоя: `)
  177. strLastTime = lstTime[1]
  178. if err := sf.CountDown().Parse(strLastTime); err != nil {
  179. // log._rintf("WARN Convoy.updateTime(): при установке времени ожидания конвоя(%v)\n\terr=%v\n", strLastTime, err)
  180. sf.CountDown().Set(10)
  181. }
  182. case isMask: // Если маскировка между конвоями
  183. // Ждём окончания ожидания конвоя
  184. lstTime := strings.Split(strLastTime, `Полная маскировка через `)
  185. strLastTime = lstTime[1]
  186. if err := sf.CountDown().Parse(strLastTime); err != nil {
  187. // log._rintf("ERRO Bank.getAllMode(): при установке времени банка для 1го режима(%v)\n\terr=%v\n", strLastTime, err)
  188. sf.CountDown().Set(10)
  189. }
  190. }
  191. }
  192. // Проводит атаку на конвой
  193. func (sf *Convoy) attackConvoy() {
  194. // Найти контрольную строку
  195. var (
  196. strOut = ""
  197. lstConvoy = sf.GetLst()
  198. isFind bool
  199. )
  200. for _, strLink := range lstConvoy {
  201. if strings.Contains(strLink, `>Начать разведку<`) {
  202. strOut = strLink
  203. lstLink := strings.Split(strOut, `<div class="bot"><a class="simple-but border" w:id="findEnemy" href="`)
  204. strOut = lstLink[1]
  205. lstLink = strings.Split(strOut, `"><span><span>Начать разведку</span></span></a></div>`)
  206. strOut = "http://wartank.ru/" + lstLink[0]
  207. isFind = true
  208. break
  209. }
  210. if strings.Contains(strLink, `<span>В БОЙ!</span>`) {
  211. strOut = strLink
  212. lstLink := strings.Split(strOut, `<div class="bot"><a class="simple-but border" w:id="startMasking" href="`)
  213. if len(lstLink) == 1 {
  214. lstLink = strings.Split(strOut, `<div class="bot"><a class="simple-but border red" w:id="startFight" href="`)
  215. }
  216. strOut = lstLink[1]
  217. lstLink = strings.Split(strOut, `"><span><span>В БОЙ!</span></span></a></div>`)
  218. strOut = "http://wartank.ru/" + lstLink[0]
  219. isFind = true
  220. break
  221. }
  222. if strings.Contains(strLink, `>ОБЫЧНЫЕ<`) {
  223. strOut = strLink
  224. lstLink := strings.Split(strOut, `<a href="`)
  225. strOut = lstLink[1]
  226. lstLink = strings.Split(strOut, `" class="simple-but gray"><span><span>ОБЫЧНЫЕ</span></span></a>`)
  227. strOut = "http://wartank.ru/" + lstLink[0]
  228. isFind = true
  229. break
  230. }
  231. }
  232. if !isFind { // Время ожидания
  233. if err := sf.CountDown().Set(1); err != nil {
  234. panic(fmt.Errorf("ConvoyNet.attackConvoy(): пр установке CountDown, err=\n\t%w", err))
  235. }
  236. return
  237. }
  238. strLink := strOut
  239. // Можно начать разведку
  240. lstConvoy, err := sf.net.Get(strLink)
  241. if err != nil {
  242. // log._rintf("ERRO ConvoyNet.attackConvoy(): при выполнении GET-команды 'В атаку!', err=\n\t%v\n", err)
  243. return
  244. }
  245. if err = sf.Update(lstConvoy); err != nil {
  246. for _, strOut = range lstConvoy {
  247. if strings.Contains(strOut, `<title>Ошибка на сервере. Сообщение админу уже отправлено.</title>`) {
  248. // log._rintf("ERRO ConvoyNet.attackConvoy(): при обновлении lstConvoy, strOut=\n\t%v\n", strOut)
  249. return
  250. }
  251. }
  252. for _, strOut = range lstConvoy {
  253. if strings.Contains(strOut, `<title>База</title>`) {
  254. // log._rintf("ERRO ConvoyNet.attackConvoy(): при обновлении lstConvoy (найдено lstBase), strOut=\n\t%v\n", strOut)
  255. return
  256. }
  257. }
  258. // log._rintf("ERRO ConvoyNet.attackConvoy(): при обновлении lstConvoy, err=\n\t%v\n", err)
  259. return
  260. }
  261. for sf.attack() {
  262. }
  263. if err := sf.CountDown().Set(1); err != nil {
  264. panic(fmt.Errorf("ConvoyNet.attackConvoy(): при установке CountDown, err=\n\t%w", err))
  265. }
  266. }
  267. // Выполняет атаку на конвой
  268. func (sf *Convoy) attack() (isNext bool) {
  269. // Вырезать ссылку на атаку
  270. strOut := ""
  271. lstConvoy := sf.GetLst()
  272. // <a href="convoy?13-2.ILinkListener-root-fightView-attackRegular" class="simple-but gray"><span><span>ОБЫЧНЫЕ</span></span></a>
  273. for _, strAttack := range lstConvoy {
  274. if strings.Contains(strAttack, `>ОБЫЧНЫЕ<`) {
  275. strOut = strAttack
  276. break
  277. }
  278. // Полная маскировка через 39:53
  279. if strings.Contains(strAttack, `Полная маскировка через `) {
  280. return false
  281. }
  282. }
  283. if strOut == "" { // Нечего атаковать
  284. return false
  285. }
  286. // Атакуем конвой
  287. lstLink := strings.Split(strOut, `<a href="`)
  288. if len(lstLink) != 2 {
  289. return false
  290. }
  291. strLink := lstLink[1]
  292. lstLink = strings.Split(strLink, `" class="simple-but gray"><span><span>ОБЫЧНЫЕ</span></span></a>`)
  293. strLink = "http://wartank.ru/" + lstLink[0]
  294. { // Выполнить атаку
  295. var err error
  296. lstConvoy, err = sf.net.Get(strLink)
  297. if err != nil {
  298. logrus.WithError(err).Error("ConvoyNet.attack(): in get page find attack")
  299. return false
  300. }
  301. if err = sf.Update(lstConvoy); err != nil {
  302. logrus.WithError(err).Error("Convoy.attack(): при обновлении lstConvoy")
  303. return false
  304. }
  305. }
  306. return true
  307. }
  308. // Забирает награду в конвое "Активируй боевую силу"
  309. func (sf *Convoy) checkWarForce() {
  310. var (
  311. strOut string
  312. isFind bool
  313. lstConvoy = sf.GetLst()
  314. ind int
  315. )
  316. if len(lstConvoy) == 0 {
  317. if err := sf.net.UpdateLst("Конвой"); err != nil {
  318. // log._rintf("Convoy.check6frage(): при обновлении пустого lstConvoy, err=\n\t%v\n", err)
  319. return
  320. }
  321. lstConvoy = sf.GetLst()
  322. }
  323. for ind, strOut = range lstConvoy {
  324. if strings.Contains(strOut, `Активируй усиление &quot;Боевая сила&quot;<br/>`) {
  325. isFind = true
  326. ind += 23
  327. strOut = lstConvoy[ind]
  328. break
  329. }
  330. }
  331. if !isFind {
  332. return
  333. }
  334. // <a class="simple-but border" href="convoy?70-1.ILinkListener-missions-cc-0-c-awardLink"><span><span>Получить награду</span></span></a>
  335. if !strings.Contains(strOut, `ILinkListener-missions-cc-0-c-awardLink`) {
  336. return
  337. }
  338. lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
  339. strLink := lstLink[1]
  340. lstLink = strings.Split(strLink, `"><span><span>Получить награду</span></span></a>`)
  341. // http://wartank.ru/convoy?80-1.ILinkListener-missions-cc-0-c-awardLink
  342. strLink = "http://wartank.ru/" + lstLink[0]
  343. lstConvoy, err := sf.net.Get(strLink)
  344. if err != nil {
  345. // log._rintf("ERRO Convoy.checkWarForce(): при выполнени команды GET, err=\n\t%v\n", err)
  346. return
  347. }
  348. if err := sf.Update(lstConvoy); err != nil {
  349. // log._rintf("ERRO Convoy.checkWarForce(): пр обновлении lstConvoy, err=\n\t%v\n", err)
  350. return
  351. }
  352. // log._rintf("INFO Convoy.checkWarForce(): награда получена\n")
  353. }
  354. // Забирает награду в конвое "Мастер дозора"
  355. func (sf *Convoy) checkMaster() {
  356. var (
  357. strOut string
  358. isFind bool
  359. lstConvoy = sf.GetLst()
  360. ind int
  361. )
  362. if len(lstConvoy) == 0 {
  363. if err := sf.net.UpdateLst("Конвой"); err != nil {
  364. // log._rintf("Convoy.check6frage(): при обновлении пустого lstConvoy, err=\n\t%v\n", err)
  365. return
  366. }
  367. lstConvoy = sf.GetLst()
  368. }
  369. for ind, strOut = range lstConvoy {
  370. if strings.Contains(strOut, `Проведи разведку в конвое<br/>`) {
  371. isFind = true
  372. ind += 23
  373. strOut = lstConvoy[ind]
  374. break
  375. }
  376. }
  377. if !isFind {
  378. return
  379. }
  380. // <a class="simple-but border" href="convoy?61-1.ILinkListener-missions-cc-0-c-awardLink"><span><span>Получить награду</span></span></a>
  381. if !strings.Contains(strOut, `ILinkListener-missions-cc-0-c-awardLink`) {
  382. return
  383. }
  384. lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
  385. strLink := lstLink[1]
  386. lstLink = strings.Split(strLink, `"><span><span>Получить награду</span></span></a>`)
  387. // http://wartank.ru/convoy?61-1.ILinkListener-missions-cc-0-c-awardLink
  388. strLink = "http://wartank.ru/" + lstLink[0]
  389. lstConvoy, err := sf.net.Get(strLink)
  390. if err != nil {
  391. // log._rintf("ERRO Convoy.checkMaster(): при выполнени команды GET, err=\n\t%v\n", err)
  392. return
  393. }
  394. if err := sf.Update(lstConvoy); err != nil {
  395. // log._rintf("ERRO Convoy.checkMaster(): пр обновлении lstConvoy, err=\n\t%v\n", err)
  396. return
  397. }
  398. // log._rintf("INFO Convoy.checkMaster(): награда получена\n")
  399. }
  400. // Забирает награду в конвое "Уничтожь 6 врагов в конвое"
  401. func (sf *Convoy) check6frage() {
  402. var (
  403. strOut string
  404. isFind bool
  405. lstConvoy = sf.GetLst()
  406. ind int
  407. )
  408. if len(lstConvoy) == 0 {
  409. if err := sf.net.UpdateLst("Конвой"); err != nil {
  410. // log._rintf("Convoy.check6frage(): при обновлении пустого lstConvoy, err=\n\t%v\n", err)
  411. return
  412. }
  413. lstConvoy = sf.GetLst()
  414. }
  415. for ind, strOut = range lstConvoy {
  416. if strings.Contains(strOut, `Уничтожь 6 врагов в конвое<br/>`) {
  417. isFind = true
  418. ind += 23
  419. strOut = lstConvoy[ind]
  420. break
  421. }
  422. }
  423. if !isFind {
  424. return
  425. }
  426. // <a class="simple-but border" href="convoy?61-1.ILinkListener-missions-cc-0-c-awardLink"><span><span>Получить награду</span></span></a>
  427. if !strings.Contains(strOut, `ILinkListener-missions-cc-0-c-awardLink`) {
  428. return
  429. }
  430. lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
  431. strLink := lstLink[1]
  432. lstLink = strings.Split(strLink, `"><span><span>Получить награду</span></span></a>`)
  433. // http://wartank.ru/convoy?61-1.ILinkListener-missions-cc-0-c-awardLink
  434. strLink = "http://wartank.ru/" + lstLink[0]
  435. lstConvoy, err := sf.net.Get(strLink)
  436. if err != nil {
  437. // log._rintf("ERRO Convoy.check6frage(): при выполнени команды GET, err=\n\t%v\n", err)
  438. return
  439. }
  440. if err := sf.Update(lstConvoy); err != nil {
  441. // log._rintf("ERRO Convoy.check6frage(): пр обновлении lstConvoy, err=\n\t%v\n", err)
  442. return
  443. }
  444. // log._rintf("INFO Convoy.check6frage(): награда получена\n")
  445. }