polygon.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. package polygon
  2. import (
  3. "fmt"
  4. "log"
  5. "strconv"
  6. "strings"
  7. "time"
  8. "wartank/pkg/alias"
  9. "wartank/pkg/components/section"
  10. "wartank/pkg/types"
  11. "wartank/server/serv_bots/warbot/angar/base/polygon/polygonnet"
  12. )
  13. /*
  14. Объект полигона на базе
  15. */
  16. const (
  17. времОжидПлат = 60 // Время ожидания платного ускорения
  18. времОжидБесплат = 1810 // Время ожидания бесплатного ускорения
  19. )
  20. // Полигон -- объект полигона на базе
  21. type Полигон struct {
  22. *section.Секция
  23. бот types.ИБот
  24. танкСтат types.ИТанкСтат
  25. сеть *polygonnet.ПолигонСеть
  26. }
  27. // НовПолигон -- возвращает новый *Polygon
  28. func НовПолигон(base types.ИБаза) (*Полигон, error) {
  29. секция, ош := section.НовСекция(base.Бот(), "Полигон", `<title>Полигон</title>`)
  30. if ош != nil {
  31. return nil, fmt.Errorf("NewPolygon(): in create *Section, err=\n\t%w", ош)
  32. }
  33. сам := &Полигон{
  34. Секция: секция,
  35. бот: base.Бот(),
  36. танкСтат: base.Бот().Танк().ТанкСтат(),
  37. }
  38. сам.сеть, ош = polygonnet.НовПолигонСеть(сам)
  39. if ош != nil {
  40. return nil, fmt.Errorf("NewPolygon(): in create NetPolygon, err=\n\t%w", ош)
  41. }
  42. return сам, nil
  43. }
  44. // Пуск -- запускает работу полигона в отдельном потоке
  45. func (sf *Полигон) Пуск() error {
  46. go sf.пуск()
  47. return nil
  48. }
  49. // выполняет опрос полигона базы.
  50. func (сам *Полигон) пуск() {
  51. сам.ОбратВремяУст(2_000)
  52. for {
  53. select {
  54. case <-сам.бот.Кнт().Done():
  55. return
  56. case <-сам.ВремяОпрос().КаналСиг():
  57. default:
  58. mode := сам.РежимТекущ().Получ()
  59. if mode == "upgrade" {
  60. continue
  61. }
  62. сам.усилениеДобавить()
  63. сам.усилениеПровер()
  64. сам.времяОбнов()
  65. сам.построитьПровер()
  66. сам.проверитьУскорение()
  67. time.Sleep(time.Minute * 20)
  68. }
  69. }
  70. }
  71. // Проверяет на ускорение апгрейда полигона
  72. func (сам *Полигон) проверитьУскорение() {
  73. var (
  74. strOut = ""
  75. isFind bool
  76. )
  77. lstBase, err := сам.сеть.Клиент().Get("https://wartank.ru/buildings")
  78. if err != nil {
  79. log.Printf("Полигон.проверитьУскорение(): при обновлении строк базы, err=\n\t%v\n", err)
  80. return
  81. }
  82. { // Проверка на платное ускорение апгрейда + время
  83. for _, strOut = range lstBase {
  84. if strings.Contains(strOut, `Производит снаряды, ремкомплекты<br/>`) {
  85. // Убедиться что есть строка платного ускорения
  86. isFind = true
  87. break
  88. }
  89. }
  90. if !isFind {
  91. return
  92. }
  93. { // Платное ускорение
  94. if strings.Contains(strOut, `Ускорить за`) {
  95. if err := сам.ОбратВремяУст(времОжидПлат); err != nil {
  96. log.Printf("WARN Base.checkArsenalForce(): при установке платного времени ускорения апгрейда арсенала(%v)\n\terr=%v\n", времОжидПлат, err)
  97. }
  98. сам.РежимТекущ().Уст("upgrade")
  99. сам.РежимТекущ().РежимУст("апгрейд")
  100. return
  101. }
  102. }
  103. }
  104. { // Проверка на бесплатное ускорение апгрейда
  105. isFind = false
  106. for _, strOut = range lstBase {
  107. if strings.Contains(strOut, `Производит снаряды, ремкомплекты<br/>`) {
  108. // Убедиться что есть строка платного ускорения
  109. isFind = true
  110. break
  111. }
  112. }
  113. if !isFind {
  114. return
  115. }
  116. if !strings.Contains(strOut, `>Ускорение<`) {
  117. return
  118. }
  119. сам.РежимТекущ().Уст("upgrade")
  120. lstLink := strings.Split(strOut, `<td style="width:50%;padding-left:1px;"><a class="simple-but border" href="`)
  121. strLink := lstLink[1]
  122. lstLink = strings.Split(strLink, `"><span><span>Ускорение</span></span></a>`)
  123. strLink = "https://wartank.ru/" + lstLink[0]
  124. lstBase, err := сам.сеть.Get(strLink)
  125. if err != nil {
  126. // log._rintf("ERRO NetBank.checkArsenalForce(): при GET-запросе на бесплатном ускорении апгрейда арсенала, err=\n\t%v\n", err)
  127. return
  128. }
  129. // sound.ArsenalForce()
  130. if err := сам.СтрОбновить(lstBase); err != nil {
  131. // log._rintf("ERRO NetBank.checkArsenalForce(): при обновлении lstBase, err=\n\t%v\n", err)
  132. return
  133. }
  134. сам.РежимТекущ().Уст("upgrade")
  135. сам.РежимТекущ().РежимУст("апгрейд")
  136. if err := сам.ОбратВремяУст(времОжидБесплат); err != nil {
  137. log.Printf("WARN Base.checkArsenalForce(): при установке бесплатного времени ускорения апгрейда арсенала(%v)\n\terr=%v\n", времОжидБесплат, err)
  138. }
  139. }
  140. // Все проверки прошли -- это просто работа
  141. сам.РежимТекущ().Уст("work")
  142. }
  143. // Проверяет необходимость постройки полигона
  144. func (сам *Полигон) построитьПровер() {
  145. фнПостроить := func() bool { // Поиск кнопки строительства
  146. // https://wartank.ru/building-upgrade/Polygon
  147. списПолигон, ош := сам.сеть.Клиент().Get("https://wartank.ru/building-upgrade/Polygon")
  148. if ош != nil {
  149. log.Printf("Полигон.построитьПровер(): при чтении страницы строительства полигона, ош=\n\t%v\n", ош)
  150. return false
  151. }
  152. стрСсылка := ""
  153. еслиНайти := false
  154. // <a class="simple-but border mb5" href="Polygon?66-1.ILinkListener-upgradeLink-link">
  155. for _, стрСсылка = range списПолигон {
  156. if strings.Contains(стрСсылка, `href="Polygon?`) {
  157. еслиНайти = true
  158. break
  159. }
  160. }
  161. if !еслиНайти { // Время полигона вышло
  162. return false
  163. }
  164. _ссылка := strings.TrimPrefix(стрСсылка, `<a class="simple-but border mb5" href="`)
  165. _ссылка = strings.TrimSuffix(_ссылка, `">`)
  166. ссылка := "https://wartank.ru/building-upgrade/" + _ссылка
  167. // https://wartank.ru/building-upgrade/Polygon?83-1.ILinkListener-upgradeLink-link
  168. списПолигон, ош = сам.сеть.Клиент().Get(ссылка)
  169. if ош != nil {
  170. log.Printf("Полигон.построитьПровер(): при выполнении запроса на строительство, ош=\n\t%v\n", ош)
  171. return false
  172. }
  173. for _, стр := range списПолигон {
  174. if strings.Contains(стр, `href="Polygon?`) {
  175. return false
  176. }
  177. }
  178. { // подтверждение постройки
  179. // "<a class=\"simple-but border w50 mXa mb10\" w:id=\"confirmLink\" href=\"../wicket/page?13-1.ILinkListener-confirmLink\"><span><span>да, подтверждаю</span></span></a>"
  180. стрСсылка := ""
  181. еслиНайти := false
  182. for _, стрСсылка = range списПолигон {
  183. if strings.Contains(стрСсылка, `.ILinkListener-confirmLink`) {
  184. еслиНайти = true
  185. break
  186. }
  187. }
  188. if !еслиНайти { // Время полигона вышло
  189. return false
  190. }
  191. _ссылка := strings.TrimPrefix(стрСсылка, "<a class=\"simple-but border w50 mXa mb10\" w:id=\"confirmLink\" href=\"../")
  192. _ссылка = strings.TrimSuffix(_ссылка, "\"><span><span>да, подтверждаю</span></span></a>")
  193. ссылка := "https://wartank.ru/" + _ссылка
  194. // https://wartank.ru/wicket/page?135-1.ILinkListener-confirmLink
  195. _, ош = сам.сеть.Клиент().Get(ссылка)
  196. if ош != nil {
  197. log.Printf("Полигон.построитьПровер(): при выполнении запроса на строительство, ош=\n\t%v\n", ош)
  198. return false
  199. }
  200. }
  201. return true
  202. }
  203. фнПостроить()
  204. log.Printf("Полигон.построитьПровер(): построен упешно\n")
  205. }
  206. // Обновляет оставшееся время полигона
  207. //
  208. // Этот объект сам описывает своё время
  209. func (сам *Полигон) времяОбнов() {
  210. var (
  211. strLastTime string
  212. isFind bool
  213. isSet bool
  214. lstPolygon = сам.СписПолучить()
  215. )
  216. defer func() {
  217. if !isSet {
  218. сам.ОбратВремяУст(5_000)
  219. }
  220. }()
  221. for _, lastTime := range lstPolygon {
  222. if strings.Contains(lastTime, `>Осталось: `) {
  223. strLastTime = lastTime
  224. isFind = true
  225. break
  226. }
  227. }
  228. if !isFind { // Время полигона вышло
  229. return
  230. }
  231. lstTime := strings.Split(strLastTime, `>Осталось: `)
  232. strLastTime = lstTime[1]
  233. lstTime = strings.Split(strLastTime, `</span>`)
  234. strLastTime = lstTime[0]
  235. if err := сам.ParseCountDown(alias.Время(strLastTime)); err != nil {
  236. // log._rintf("ERRO Polygon.updateTime(): при установке времени ожидания полигона(%v)\n\terr=%v\n", strLastTime, err)
  237. return
  238. }
  239. isSet = true
  240. }
  241. // Проверяет что именно активировано
  242. func (сам *Полигон) усилениеПровер() {
  243. var (
  244. isFind bool
  245. lstPolygon = сам.СписПолучить()
  246. ind = 0
  247. strOut string
  248. )
  249. for ind, strOut = range lstPolygon {
  250. if strings.Contains(strOut, `<span>Активно</span>`) {
  251. ind -= 9
  252. isFind = true
  253. break
  254. }
  255. }
  256. if !isFind {
  257. return
  258. }
  259. strOut = lstPolygon[ind]
  260. форсажИмя := ""
  261. switch { // Вычисляем контрольную строку
  262. case strings.Contains(strOut, `>улучшение точности<`):
  263. форсажИмя = "fyne"
  264. case strings.Contains(strOut, `>увеличение прочности<`):
  265. форсажИмя = "hard"
  266. case strings.Contains(strOut, `>усиление брони<`):
  267. форсажИмя = "armor"
  268. case strings.Contains(strOut, `>усиление атаки<`):
  269. форсажИмя = "attack"
  270. }
  271. // Вычислим на сколько
  272. strOut = lstPolygon[ind+1]
  273. lstOut := strings.Split(strOut, `<span class="green2">+`)
  274. strOut = lstOut[1]
  275. lstOut = strings.Split(strOut, ` на `)
  276. strOut = lstOut[0]
  277. iForce, err := strconv.Atoi(strOut)
  278. if err != nil {
  279. // log._rintf("NetPolygon.checkTime(): force(%v) not number, err=\n\t%v\n", strOut, err)
  280. return
  281. }
  282. сам.танкСтат.ФорсажОбнов(форсажИмя, iForce)
  283. }
  284. // Выбирает самый слабый параметр и усиливает его
  285. func (сам *Полигон) усилениеДобавить() {
  286. if err := сам.сеть.UpdateLst(); err != nil {
  287. // log._rintf("Polygon.checkPolygon(): при принудительном обновлении lstPlygon, mode=%s\terr=\n\t%v\n", sf.ModeCurrent().Get(), err)
  288. сам.ОбратВремяУст(5_000)
  289. return
  290. }
  291. lstPoligon := сам.СписПолучить()
  292. if len(lstPoligon) == 0 {
  293. return
  294. }
  295. stat := сам.танкСтат
  296. iAttack := stat.Атака().Получ()
  297. iArmor := stat.Броня().Получ()
  298. iFyne := stat.Точность().Получ()
  299. iHard := stat.Прочность().Получ()
  300. strParam := "attack"
  301. iParam := iHard
  302. {
  303. /*
  304. Вычислить самый слабый параметр.
  305. Политика вычислений:
  306. 1) hard -- прочность, самый низкоприоритетный параметр
  307. 2) armor -- броня, чуть лучше power
  308. 3) fyne -- точность, чуть лучше armor
  309. 4) attack -- атака, самый важный
  310. */
  311. if iArmor <= iParam {
  312. iParam = iArmor
  313. strParam = "armor"
  314. }
  315. if iFyne <= iParam {
  316. iParam = iFyne
  317. strParam = "fyne"
  318. }
  319. if iAttack < iParam {
  320. strParam = "attack"
  321. }
  322. }
  323. // Найти нужную строку активации
  324. var (
  325. ind int
  326. strOut string
  327. isFind bool
  328. )
  329. switch strParam {
  330. case "attack": // Усиливаем атаку
  331. for ind, strOut = range lstPoligon {
  332. if strings.Contains(strOut, `>усиление атаки<`) {
  333. isFind = true
  334. break
  335. }
  336. }
  337. if !isFind {
  338. return
  339. }
  340. ind += 8
  341. strOut = lstPoligon[ind]
  342. if strOut == "" {
  343. return
  344. }
  345. lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
  346. strOut = lstLink[1]
  347. lstLink = strings.Split(strOut, `"><span><span>Получить бесплатно</span></span></a>`)
  348. strLink := "https://wartank.ru/" + lstLink[0]
  349. if _, err := сам.сеть.Get(strLink); err != nil {
  350. // log._rintf("ERRO NetPolygon.addForce(): in make request force attack, err=\n\t%v\n", err)
  351. return
  352. }
  353. { // Узнать на сколько форсирована атака
  354. strForce := lstPoligon[ind-7]
  355. lstForce := strings.Split(strForce, `<span class="green2">+`)
  356. strForce = lstForce[1]
  357. lstForce = strings.Split(strForce, ` на `)
  358. strForce = lstForce[0]
  359. iForce, err := strconv.Atoi(strForce)
  360. if err != nil {
  361. // log._rintf("ERRO NetPolygon.addForce(): strForceAttack(%v) not int, err=\n\t%v\n", strForce, err)
  362. return
  363. }
  364. сам.танкСтат.ФорсажОбнов("attack", iForce)
  365. сам.РежимТекущ().Уст("атака")
  366. }
  367. case "armor": // Усиливаем броню
  368. isFind = false
  369. for ind, strOut = range lstPoligon {
  370. if strings.Contains(strOut, `>усиление брони<`) {
  371. isFind = true
  372. break
  373. }
  374. }
  375. if !isFind {
  376. return
  377. }
  378. ind += 8
  379. strOut = lstPoligon[ind]
  380. if strOut == "" {
  381. return
  382. }
  383. lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
  384. strOut = lstLink[1]
  385. lstLink = strings.Split(strOut, `"><span><span>Получить бесплатно</span></span></a>`)
  386. strLink := "https://wartank.ru/" + lstLink[0]
  387. if _, err := сам.сеть.Get(strLink); err != nil {
  388. // log._rintf("NetPolygon.addForce(): in make request force armor, err=\n\t%v\n", err)
  389. return
  390. }
  391. { // Узнать на сколько форсирована броня
  392. strForce := lstPoligon[ind-7]
  393. lstForce := strings.Split(strForce, `<span class="green2">+`)
  394. strForce = lstForce[1]
  395. lstForce = strings.Split(strForce, ` на `)
  396. strForce = lstForce[0]
  397. iForce, err := strconv.Atoi(strForce)
  398. if err != nil {
  399. // log._rintf("ERRO NetPolygon.addForce(): strForceArmor(%v) not int, err=\n\t%v\n", strForce, err)
  400. return
  401. }
  402. сам.танкСтат.ФорсажОбнов("armor", iForce)
  403. сам.РежимТекущ().Уст("броня")
  404. }
  405. case "fyne": // Усиливаем точность
  406. isFind = false
  407. for ind, strOut = range lstPoligon {
  408. if strings.Contains(strOut, `>улучшение точности<`) {
  409. isFind = true
  410. break
  411. }
  412. }
  413. if !isFind {
  414. return
  415. }
  416. ind += 8
  417. strOut = lstPoligon[ind]
  418. if strOut == "" {
  419. return
  420. }
  421. lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
  422. strOut = lstLink[1]
  423. lstLink = strings.Split(strOut, `"><span><span>Получить бесплатно</span></span></a>`)
  424. strLink := "https://wartank.ru/" + lstLink[0]
  425. if _, err := сам.сеть.Get(strLink); err != nil {
  426. // log._rintf("ERRO NetPolygon.addForce(): in make request force fyne, err=\n\t%v\n", err)
  427. return
  428. }
  429. { // Узнать на сколько форсирована точность
  430. strForce := lstPoligon[ind-7]
  431. lstForce := strings.Split(strForce, `<span class="green2">+`)
  432. strForce = lstForce[1]
  433. lstForce = strings.Split(strForce, ` на `)
  434. strForce = lstForce[0]
  435. iForce, err := strconv.Atoi(strForce)
  436. if err != nil {
  437. // log._rintf("ERRO NetPolygon.addForce(): strForceFyne(%v) not int, err=\n\t%v\n", strForce, err)
  438. return
  439. }
  440. сам.танкСтат.ФорсажОбнов("fyne", iForce)
  441. сам.РежимТекущ().Уст("точность")
  442. }
  443. case "hard": // Усиливаем мощность
  444. isFind = false
  445. for ind, strOut = range lstPoligon {
  446. if strings.Contains(strOut, `>увеличение прочности<`) {
  447. isFind = true
  448. break
  449. }
  450. }
  451. if !isFind {
  452. return
  453. }
  454. ind += 8
  455. strOut = lstPoligon[ind]
  456. lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
  457. strOut = lstLink[1]
  458. lstLink = strings.Split(strOut, `"><span><span>Получить бесплатно</span></span></a>`)
  459. strLink := "https://wartank.ru/" + lstLink[0]
  460. if _, err := сам.сеть.Get(strLink); err != nil {
  461. // log._rintf("NetPolygon.addForce(): in make request force hard, err=\n\t%v\n", err)
  462. return
  463. }
  464. { // Узнать на сколько форсирована прочность
  465. strForce := lstPoligon[ind-7]
  466. lstForce := strings.Split(strForce, `<span class="green2">+`)
  467. strForce = lstForce[1]
  468. lstForce = strings.Split(strForce, ` на `)
  469. strForce = lstForce[0]
  470. iForce, err := strconv.Atoi(strForce)
  471. if err != nil {
  472. // log._rintf("ERRO NetPolygon.addForce(): strForceHard(%v) not int, err=\n\t%v\n", strForce, err)
  473. return
  474. }
  475. сам.танкСтат.ФорсажОбнов("hard", iForce)
  476. сам.РежимТекущ().Уст("прочность")
  477. }
  478. default: // Неизвестно что
  479. сам.РежимТекущ().Уст("неизвестно")
  480. // log._rintf("ERRO NetPolygon.addForce(): неизвестно что это, strParam=%q", strParam)
  481. return
  482. }
  483. }