polygon.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. package polygon
  2. import (
  3. "fmt"
  4. "log"
  5. "strconv"
  6. "strings"
  7. "wartank/pkg/alias"
  8. "wartank/pkg/components/safe_int"
  9. "wartank/pkg/components/safe_string"
  10. "wartank/pkg/components/section"
  11. "wartank/pkg/components/section/down_time"
  12. "wartank/pkg/types"
  13. "wartank/server/serv_bots/warbot/angar/base/polygon/polygonnet"
  14. "wartank/server/serv_bots/warbot/tank/tankstat/static_param"
  15. )
  16. /*
  17. Объект полигона на базе
  18. */
  19. const (
  20. времОжидПлат = "05:00" // Время ожидания платного ускорения
  21. времОжидБесплат = "30:00" // Время ожидания бесплатного ускорения
  22. )
  23. // Полигон -- объект полигона на базе
  24. type Полигон struct {
  25. *section.Секция
  26. бот types.ИБот
  27. танкСтат types.ИТанкСтат
  28. сеть *polygonnet.ПолигонСеть
  29. времяОстат types.ИВремяОстат
  30. продуктСейчас *safe_string.БезопСтрока
  31. продуктКол *safe_int.БезопЦелое
  32. уровень *static_param.СтатПарам
  33. }
  34. // НовПолигон -- возвращает новый *Polygon
  35. func НовПолигон(база types.ИБаза) (*Полигон, error) {
  36. секция, ош := section.НовСекция(база.Бот(), "Полигон", `<title>Полигон</title>`)
  37. if ош != nil {
  38. return nil, fmt.Errorf("НовПолигон(): при создании ИСекция, ош=\n\t%w", ош)
  39. }
  40. уровень, ош := static_param.НовСтатПарам("уровень полигона")
  41. if ош != nil {
  42. return nil, fmt.Errorf("НовПолигон(): при создании уровня полигона, ош=\n\t%w", ош)
  43. }
  44. сам := &Полигон{
  45. Секция: секция,
  46. бот: база.Бот(),
  47. танкСтат: база.Бот().Танк().ТанкСтат(),
  48. времяОстат: down_time.НовВремОбрат(секция, 5_000),
  49. продуктСейчас: safe_string.НовБезопСтрока(),
  50. продуктКол: safe_int.НовБезопЦелое(),
  51. уровень: уровень,
  52. }
  53. сам.сеть, ош = polygonnet.НовПолигонСеть(сам)
  54. if ош != nil {
  55. return nil, fmt.Errorf("NewPolygon(): in create NetPolygon, err=\n\t%w", ош)
  56. }
  57. _ = types.ИБазаПолигон(сам)
  58. return сам, nil
  59. }
  60. // Уровень -- возвращает уровень полигона
  61. func (сам *Полигон) Уровень() types.ИСтатПарам {
  62. return сам.уровень
  63. }
  64. // ПродуктКолСейчас -- количество продукта, что именно сейчас производится на полигоне
  65. func (сам *Полигон) ПродуктКолСейчас() int {
  66. return сам.продуктКол.Получ()
  67. }
  68. // ПродуктИмяСейчас -- что именно сейчас производится на полигоне
  69. func (сам *Полигон) ПродуктИмяСейчас() string {
  70. return сам.продуктСейчас.Получ()
  71. }
  72. // ПродуктВремяСейчас -- сколько осталось времени до обновы полигона
  73. func (сам *Полигон) ПродуктВремяСейчас() string {
  74. return сам.времяОстат.String()
  75. }
  76. // Пуск -- запускает работу полигона в отдельном потоке
  77. func (sf *Полигон) Пуск() error {
  78. go sf.пуск()
  79. return nil
  80. }
  81. const (
  82. стрАпгрейд = "апгрейд"
  83. )
  84. // выполняет опрос полигона базы.
  85. func (сам *Полигон) пуск() {
  86. сам.ОбратВремяУст("02")
  87. фнРабота := func() {
  88. сам.усилениеДобавить()
  89. сам.усилениеПровер()
  90. сам.времяОбнов()
  91. сам.построитьПровер()
  92. сам.проверитьУскорение()
  93. if сам.продуктСейчас.Получ() == стрАпгрейд {
  94. сам.ВремяОстат().Уст("00:10:00")
  95. }
  96. }
  97. for {
  98. select {
  99. case <-сам.Кнт().Done():
  100. return
  101. case <-сам.ВремяОстат().КаналСиг():
  102. фнРабота()
  103. // default:
  104. // time.Sleep(time.Minute * 20)
  105. }
  106. }
  107. }
  108. // Проверяет на ускорение апгрейда полигона
  109. func (сам *Полигон) проверитьУскорение() {
  110. var (
  111. strOut = ""
  112. isFind bool
  113. )
  114. lstBase, err := сам.сеть.Клиент().Get("https://wartank.ru/buildings")
  115. if err != nil {
  116. log.Printf("Полигон.проверитьУскорение(): при обновлении строк базы, err=\n\t%v\n", err)
  117. return
  118. }
  119. // Проверка на платное ускорение апгрейда + время
  120. { // Платное ускорение
  121. if strings.Contains(strOut, `Ускорить за`) {
  122. if err := сам.ОбратВремяУст(времОжидПлат); err != nil {
  123. log.Printf("WARN Base.checkArsenalForce(): при установке платного времени ускорения апгрейда арсенала(%v)\n\terr=%v\n", времОжидПлат, err)
  124. }
  125. сам.РежимТекущ().Уст(стрАпгрейд)
  126. сам.РежимТекущ().РежимУст(стрАпгрейд)
  127. сам.продуктСейчас.Уст(стрАпгрейд)
  128. сам.продуктКол.Уст(0)
  129. return
  130. }
  131. }
  132. { // Проверка на бесплатное ускорение апгрейда
  133. isFind = false
  134. for _, strOut = range lstBase {
  135. if strings.Contains(strOut, `Производит снаряды, ремкомплекты<br/>`) {
  136. // Убедиться что есть строка платного ускорения
  137. isFind = true
  138. break
  139. }
  140. }
  141. if !isFind {
  142. return
  143. }
  144. if !strings.Contains(strOut, `>Ускорение<`) {
  145. return
  146. }
  147. сам.РежимТекущ().Уст(стрАпгрейд)
  148. сам.продуктСейчас.Уст(стрАпгрейд)
  149. сам.продуктКол.Уст(0)
  150. lstLink := strings.Split(strOut, `<td style="width:50%;padding-left:1px;"><a class="simple-but border" href="`)
  151. strLink := lstLink[1]
  152. lstLink = strings.Split(strLink, `"><span><span>Ускорение</span></span></a>`)
  153. strLink = "https://wartank.ru/" + lstLink[0]
  154. lstBase, err := сам.сеть.Get(strLink)
  155. if err != nil {
  156. // log._rintf("ERRO NetBank.checkArsenalForce(): при GET-запросе на бесплатном ускорении апгрейда арсенала, err=\n\t%v\n", err)
  157. return
  158. }
  159. // sound.ArsenalForce()
  160. if err := сам.СтрОбновить(lstBase); err != nil {
  161. // log._rintf("ERRO NetBank.checkArsenalForce(): при обновлении lstBase, err=\n\t%v\n", err)
  162. return
  163. }
  164. сам.РежимТекущ().Уст(стрАпгрейд)
  165. сам.РежимТекущ().РежимУст(стрАпгрейд)
  166. сам.продуктКол.Уст(0)
  167. if err := сам.ОбратВремяУст(времОжидБесплат); err != nil {
  168. log.Printf("WARN Base.checkArsenalForce(): при установке бесплатного времени ускорения апгрейда арсенала(%v)\n\terr=%v\n", времОжидБесплат, err)
  169. }
  170. }
  171. // Все проверки прошли -- это просто работа
  172. сам.РежимТекущ().Уст("work")
  173. }
  174. // Проверяет необходимость постройки полигона
  175. func (сам *Полигон) построитьПровер() {
  176. фнПостроить := func() bool { // Поиск кнопки строительства
  177. // https://wartank.ru/building-upgrade/Polygon
  178. списПолигон, ош := сам.сеть.Клиент().Get("https://wartank.ru/building-upgrade/Polygon")
  179. if ош != nil {
  180. log.Printf("Полигон.построитьПровер(): при чтении страницы строительства полигона, ош=\n\t%v\n", ош)
  181. return false
  182. }
  183. стрСсылка := ""
  184. еслиНайти := false
  185. // <a class="simple-but border mb5" href="Polygon?66-1.ILinkListener-upgradeLink-link">
  186. for _, стрСсылка = range списПолигон {
  187. if strings.Contains(стрСсылка, `href="Polygon?`) {
  188. еслиНайти = true
  189. break
  190. }
  191. }
  192. if !еслиНайти { // Время полигона вышло
  193. return false
  194. }
  195. _ссылка := strings.TrimPrefix(стрСсылка, `<a class="simple-but border mb5" href="`)
  196. _ссылка = strings.TrimSuffix(_ссылка, `">`)
  197. ссылка := "https://wartank.ru/building-upgrade/" + _ссылка
  198. // https://wartank.ru/building-upgrade/Polygon?83-1.ILinkListener-upgradeLink-link
  199. списПолигон, ош = сам.сеть.Клиент().Get(ссылка)
  200. if ош != nil {
  201. log.Printf("Полигон.построитьПровер(): при выполнении запроса на строительство, ош=\n\t%v\n", ош)
  202. return false
  203. }
  204. for _, стр := range списПолигон {
  205. if strings.Contains(стр, `href="Polygon?`) {
  206. return false
  207. }
  208. }
  209. { // подтверждение постройки
  210. // "<a class=\"simple-but border w50 mXa mb10\" w:id=\"confirmLink\" href=\"../wicket/page?13-1.ILinkListener-confirmLink\"><span><span>да, подтверждаю</span></span></a>"
  211. стрСсылка := ""
  212. еслиНайти := false
  213. for _, стрСсылка = range списПолигон {
  214. if strings.Contains(стрСсылка, `.ILinkListener-confirmLink`) {
  215. еслиНайти = true
  216. break
  217. }
  218. }
  219. if !еслиНайти { // Время полигона вышло
  220. return false
  221. }
  222. _ссылка := strings.TrimPrefix(стрСсылка, "<a class=\"simple-but border w50 mXa mb10\" w:id=\"confirmLink\" href=\"../")
  223. _ссылка = strings.TrimSuffix(_ссылка, "\"><span><span>да, подтверждаю</span></span></a>")
  224. ссылка := "https://wartank.ru/" + _ссылка
  225. // https://wartank.ru/wicket/page?135-1.ILinkListener-confirmLink
  226. _, ош = сам.сеть.Клиент().Get(ссылка)
  227. if ош != nil {
  228. log.Printf("Полигон.построитьПровер(): при выполнении запроса на строительство, ош=\n\t%v\n", ош)
  229. return false
  230. }
  231. }
  232. return true
  233. }
  234. фнПостроить()
  235. log.Printf("Полигон.построитьПровер(): построен упешно\n")
  236. }
  237. // Обновляет оставшееся время полигона
  238. //
  239. // Этот объект сам описывает своё время
  240. func (сам *Полигон) времяОбнов() {
  241. var (
  242. strLastTime string
  243. isFind bool
  244. isSet bool
  245. lstPolygon = сам.СписПолучить()
  246. )
  247. defer func() {
  248. if !isSet {
  249. сам.ОбратВремяУст("05")
  250. }
  251. }()
  252. for _, lastTime := range lstPolygon {
  253. if strings.Contains(lastTime, `>Осталось: `) {
  254. strLastTime = lastTime
  255. isFind = true
  256. break
  257. }
  258. }
  259. if !isFind { // Время полигона вышло
  260. return
  261. }
  262. lstTime := strings.Split(strLastTime, `>Осталось: `)
  263. strLastTime = lstTime[1]
  264. lstTime = strings.Split(strLastTime, `</span>`)
  265. strLastTime = lstTime[0]
  266. if err := сам.Уст(alias.Время(strLastTime)); err != nil {
  267. // log._rintf("ERRO Polygon.updateTime(): при установке времени ожидания полигона(%v)\n\terr=%v\n", strLastTime, err)
  268. return
  269. }
  270. isSet = true
  271. }
  272. // Проверяет что именно активировано
  273. func (сам *Полигон) усилениеПровер() {
  274. var (
  275. isFind bool
  276. lstPolygon = сам.СписПолучить()
  277. ind = 0
  278. strOut string
  279. )
  280. for ind, strOut = range lstPolygon {
  281. if strings.Contains(strOut, `<span>Активно</span>`) {
  282. ind -= 9
  283. isFind = true
  284. break
  285. }
  286. }
  287. if !isFind {
  288. return
  289. }
  290. strOut = lstPolygon[ind]
  291. форсажИмя := ""
  292. switch { // Вычисляем контрольную строку
  293. case strings.Contains(strOut, `>улучшение точности<`):
  294. форсажИмя = "fyne"
  295. case strings.Contains(strOut, `>увеличение прочности<`):
  296. форсажИмя = "hard"
  297. case strings.Contains(strOut, `>усиление брони<`):
  298. форсажИмя = "armor"
  299. case strings.Contains(strOut, `>усиление атаки<`):
  300. форсажИмя = "attack"
  301. }
  302. // Вычислим на сколько
  303. strOut = lstPolygon[ind+1]
  304. lstOut := strings.Split(strOut, `<span class="green2">+`)
  305. strOut = lstOut[1]
  306. lstOut = strings.Split(strOut, ` на `)
  307. strOut = lstOut[0]
  308. iForce, err := strconv.Atoi(strOut)
  309. if err != nil {
  310. // log._rintf("NetPolygon.checkTime(): force(%v) not number, err=\n\t%v\n", strOut, err)
  311. return
  312. }
  313. сам.танкСтат.ФорсажОбнов(форсажИмя, iForce)
  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. }