polygon.go 19 KB

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