convoy.go 15 KB

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