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