polygon.go 20 KB

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