polygon.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  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/cons"
  11. "wartank/pkg/section"
  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. стрБроня = "броня"
  25. стрАтака = "атака"
  26. )
  27. // Полигон -- объект полигона на базе
  28. type Полигон struct {
  29. *section.Секция
  30. бот types.ИБот
  31. танкСтат types.ИТанкСтат
  32. сеть *polygonnet.ПолигонСеть
  33. продуктСейчас *safe_string.БезопСтрока
  34. продуктКол *safe_int.БезопЦелое
  35. уровень *static_param.СтатПарам
  36. }
  37. // НовПолигон -- возвращает новый *Polygon
  38. func НовПолигон(база types.ИБаза) (*Полигон, error) {
  39. секция, ош := section.НовСекция(база.Бот(), "Полигон", `<title>Полигон</title>`)
  40. if ош != nil {
  41. return nil, fmt.Errorf("НовПолигон(): при создании ИСекция, ош=\n\t%w", ош)
  42. }
  43. уровень, ош := static_param.НовСтатПарам("уровень полигона")
  44. if ош != nil {
  45. return nil, fmt.Errorf("НовПолигон(): при создании уровня полигона, ош=\n\t%w", ош)
  46. }
  47. сам := &Полигон{
  48. Секция: секция,
  49. бот: база.Бот(),
  50. танкСтат: база.Бот().Танк().ТанкСтат(),
  51. продуктСейчас: safe_string.НовБезопСтрока(),
  52. продуктКол: safe_int.НовБезопЦелое(),
  53. уровень: уровень,
  54. }
  55. сам.сеть, ош = polygonnet.НовПолигонСеть(сам)
  56. if ош != nil {
  57. return nil, fmt.Errorf("NewPolygon(): in create NetPolygon, err=\n\t%w", ош)
  58. }
  59. _ = types.ИБазаПолигон(сам)
  60. return сам, nil
  61. }
  62. // Уровень -- возвращает уровень полигона
  63. func (сам *Полигон) Уровень() types.ИСтатПарам {
  64. return сам.уровень
  65. }
  66. // ПродуктКолСейчас -- количество продукта, что именно сейчас производится на полигоне
  67. func (сам *Полигон) ПродуктКолСейчас() int {
  68. return сам.продуктКол.Получ()
  69. }
  70. // ПродуктИмяСейчас -- что именно сейчас производится на полигоне
  71. func (сам *Полигон) ПродуктИмяСейчас() string {
  72. return сам.продуктСейчас.Получ()
  73. }
  74. // ПродуктВремяСейчас -- сколько осталось времени до обновы полигона
  75. func (сам *Полигон) ПродуктВремяСейчас() string {
  76. return сам.ВремяОстат().String()
  77. }
  78. // Пуск -- запускает работу полигона в отдельном потоке
  79. func (сам *Полигон) Пуск() error {
  80. go сам.пуск()
  81. return nil
  82. }
  83. const (
  84. стрАпгрейд = "апгрейд"
  85. )
  86. // выполняет опрос полигона базы.
  87. func (сам *Полигон) пуск() {
  88. сам.ОбратВремяУст("02")
  89. фнРабота := func() {
  90. сам.усилениеДобавить()
  91. сам.усилениеПровер()
  92. сам.времяОбнов()
  93. сам.построитьПровер()
  94. сам.проверитьУскорение()
  95. if сам.продуктСейчас.Получ() == стрАпгрейд {
  96. сам.ВремяОстат().Уст("00:10:00")
  97. }
  98. }
  99. for {
  100. select {
  101. case <-сам.Кнт().Done():
  102. return
  103. case <-сам.ВремяОстат().КаналСиг():
  104. фнРабота()
  105. // default:
  106. // time.Sleep(time.Minute * 20)
  107. }
  108. }
  109. }
  110. // Проверяет на ускорение апгрейда полигона
  111. func (сам *Полигон) проверитьУскорение() {
  112. var (
  113. strOut = ""
  114. еслиНайдено bool
  115. )
  116. lstBase, err := сам.сеть.Клиент().Get("https://wartank.ru/buildings")
  117. if err != nil {
  118. log.Printf("Полигон.проверитьУскорение(): при обновлении строк базы, err=\n\t%v\n", err)
  119. return
  120. }
  121. // Проверка на платное ускорение апгрейда + время
  122. { // Платное ускорение
  123. if strings.Contains(strOut, `Ускорить за`) {
  124. if err := сам.ОбратВремяУст(времОжидПлат); err != nil {
  125. log.Printf("WARN Base.checkArsenalForce(): при установке платного времени ускорения апгрейда арсенала(%v)\n\terr=%v\n", времОжидПлат, err)
  126. }
  127. сам.СценаРежим().РаботаУст(стрАпгрейд)
  128. сам.СценаРежим().РежимУст(cons.РежимАпгрейд)
  129. сам.продуктСейчас.Уст(стрАпгрейд)
  130. сам.продуктКол.Уст(0)
  131. return
  132. }
  133. }
  134. { // Проверка на бесплатное ускорение апгрейда
  135. еслиНайдено = false
  136. for _, strOut = range lstBase {
  137. if strings.Contains(strOut, `Производит снаряды, ремкомплекты<br/>`) {
  138. // Убедиться что есть строка платного ускорения
  139. еслиНайдено = true
  140. break
  141. }
  142. }
  143. if !еслиНайдено {
  144. return
  145. }
  146. if !strings.Contains(strOut, `>Ускорение<`) {
  147. return
  148. }
  149. сам.СценаРежим().РежимУст(cons.РежимАпгрейд)
  150. сам.продуктСейчас.Уст(стрАпгрейд)
  151. сам.продуктКол.Уст(0)
  152. lstLink := strings.Split(strOut, `<td style="width:50%;padding-left:1px;"><a class="simple-but border" href="`)
  153. strLink := lstLink[1]
  154. lstLink = strings.Split(strLink, `"><span><span>Ускорение</span></span></a>`)
  155. strLink = "https://wartank.ru/" + lstLink[0]
  156. lstBase, err := сам.сеть.Get(strLink)
  157. if err != nil {
  158. // log._rintf("ERRO NetBank.checkArsenalForce(): при GET-запросе на бесплатном ускорении апгрейда арсенала, err=\n\t%v\n", err)
  159. return
  160. }
  161. // sound.ArsenalForce()
  162. if err := сам.СтрОбновить(lstBase); err != nil {
  163. // log._rintf("ERRO NetBank.checkArsenalForce(): при обновлении lstBase, err=\n\t%v\n", err)
  164. return
  165. }
  166. сам.СценаРежим().РаботаУст(стрАпгрейд)
  167. сам.СценаРежим().РежимУст(cons.РежимАпгрейд)
  168. сам.продуктКол.Уст(0)
  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. еслиНайдено 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. еслиНайдено = true
  258. break
  259. }
  260. }
  261. if !еслиНайдено { // Время полигона вышло
  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. еслиНайдено 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. еслиНайдено = true
  286. break
  287. }
  288. }
  289. if !еслиНайдено {
  290. return
  291. }
  292. strOut = lstPolygon[ind]
  293. форсажИмя := ""
  294. switch { // Вычисляем контрольную строку
  295. case strings.Contains(strOut, `>улучшение точности<`):
  296. форсажИмя = стрТочность
  297. case strings.Contains(strOut, `>увеличение прочности<`):
  298. форсажИмя = стрПрочность
  299. case strings.Contains(strOut, `>усиление брони<`):
  300. форсажИмя = стрБроня
  301. case strings.Contains(strOut, `>усиление атаки<`):
  302. форсажИмя = стрАтака
  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. сам.продуктКол.Уст(iForce)
  318. }
  319. // Выбирает самый слабый параметр и усиливает его
  320. func (сам *Полигон) усилениеДобавить() {
  321. if ош := сам.сеть.Обновить(); ош != nil {
  322. // log._rintf("Polygon.checkPolygon(): при принудительном обновлении lstPlygon, mode=%s\terr=\n\t%v\n", сам.ModeCurrent().Get(), err)
  323. сам.ОбратВремяУст("05")
  324. return
  325. }
  326. lstPoligon := сам.СписПолучить()
  327. if len(lstPoligon) == 0 {
  328. return
  329. }
  330. stat := сам.танкСтат
  331. iAttack := stat.Атака().Получ()
  332. iArmor := stat.Броня().Получ()
  333. iFyne := stat.Точность().Получ()
  334. iHard := stat.Прочность().Получ()
  335. strParam := стрАтака
  336. iParam := iHard
  337. {
  338. /*
  339. Вычислить самый слабый параметр.
  340. Политика вычислений:
  341. 1) hard -- прочность, самый низкоприоритетный параметр
  342. 2) armor -- броня, чуть лучше power
  343. 3) fyne -- точность, чуть лучше armor
  344. 4) attack -- атака, самый важный
  345. */
  346. if iArmor <= iParam {
  347. iParam = iArmor
  348. strParam = стрБроня
  349. }
  350. if iFyne <= iParam {
  351. iParam = iFyne
  352. strParam = стрТочность
  353. }
  354. if iAttack < iParam {
  355. strParam = стрАтака
  356. }
  357. }
  358. // Найти нужную строку активации
  359. var (
  360. ind int
  361. strOut string
  362. еслиНайдено bool
  363. )
  364. switch strParam {
  365. case стрАтака: // Усиливаем атаку
  366. for ind, strOut = range lstPoligon {
  367. if strings.Contains(strOut, `>усиление атаки<`) {
  368. еслиНайдено = true
  369. break
  370. }
  371. }
  372. if !еслиНайдено {
  373. return
  374. }
  375. ind += 8
  376. strOut = lstPoligon[ind]
  377. if strOut == "" {
  378. return
  379. }
  380. lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
  381. strOut = lstLink[1]
  382. lstLink = strings.Split(strOut, `"><span><span>Получить бесплатно</span></span></a>`)
  383. strLink := "https://wartank.ru/" + lstLink[0]
  384. if _, err := сам.сеть.Get(strLink); err != nil {
  385. // log._rintf("ERRO NetPolygon.addForce(): in make request force attack, err=\n\t%v\n", err)
  386. return
  387. }
  388. { // Узнать на сколько форсирована атака
  389. strForce := lstPoligon[ind-7]
  390. lstForce := strings.Split(strForce, `<span class="green2">+`)
  391. strForce = lstForce[1]
  392. lstForce = strings.Split(strForce, ` на `)
  393. strForce = lstForce[0]
  394. iForce, err := strconv.Atoi(strForce)
  395. if err != nil {
  396. // log._rintf("ERRO NetPolygon.addForce(): strForceAttack(%v) not int, err=\n\t%v\n", strForce, err)
  397. return
  398. }
  399. сам.танкСтат.ФорсажОбнов("attack", iForce)
  400. сам.СценаРежим().РаботаУст(стрАтака)
  401. }
  402. case стрБроня: // Усиливаем броню
  403. еслиНайдено = false
  404. for ind, strOut = range lstPoligon {
  405. if strings.Contains(strOut, `>усиление брони<`) {
  406. еслиНайдено = true
  407. break
  408. }
  409. }
  410. if !еслиНайдено {
  411. return
  412. }
  413. ind += 8
  414. strOut = lstPoligon[ind]
  415. if strOut == "" {
  416. return
  417. }
  418. lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
  419. strOut = lstLink[1]
  420. lstLink = strings.Split(strOut, `"><span><span>Получить бесплатно</span></span></a>`)
  421. strLink := "https://wartank.ru/" + lstLink[0]
  422. if _, err := сам.сеть.Get(strLink); err != nil {
  423. // log._rintf("NetPolygon.addForce(): in make request force armor, err=\n\t%v\n", err)
  424. return
  425. }
  426. { // Узнать на сколько форсирована броня
  427. strForce := lstPoligon[ind-7]
  428. lstForce := strings.Split(strForce, `<span class="green2">+`)
  429. strForce = lstForce[1]
  430. lstForce = strings.Split(strForce, ` на `)
  431. strForce = lstForce[0]
  432. iForce, err := strconv.Atoi(strForce)
  433. if err != nil {
  434. // log._rintf("ERRO NetPolygon.addForce(): strForceArmor(%v) not int, err=\n\t%v\n", strForce, err)
  435. return
  436. }
  437. сам.танкСтат.ФорсажОбнов(стрБроня, iForce)
  438. сам.СценаРежим().РаботаУст(стрБроня)
  439. }
  440. case стрТочность: // Усиливаем точность
  441. еслиНайдено = false
  442. for ind, strOut = range lstPoligon {
  443. if strings.Contains(strOut, `>улучшение точности<`) {
  444. еслиНайдено = true
  445. break
  446. }
  447. }
  448. if !еслиНайдено {
  449. return
  450. }
  451. ind += 8
  452. strOut = lstPoligon[ind]
  453. if strOut == "" {
  454. return
  455. }
  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("ERRO NetPolygon.addForce(): in make request force fyne, 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(): strForceFyne(%v) not int, err=\n\t%v\n", strForce, err)
  473. return
  474. }
  475. сам.танкСтат.ФорсажОбнов(стрТочность, iForce)
  476. сам.СценаРежим().РаботаУст(стрТочность)
  477. }
  478. case стрПрочность: // Усиливаем мощность
  479. еслиНайдено = false
  480. for ind, strOut = range lstPoligon {
  481. if strings.Contains(strOut, `>увеличение прочности<`) {
  482. еслиНайдено = true
  483. break
  484. }
  485. }
  486. if !еслиНайдено {
  487. return
  488. }
  489. ind += 8
  490. strOut = lstPoligon[ind]
  491. lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
  492. strOut = lstLink[1]
  493. lstLink = strings.Split(strOut, `"><span><span>Получить бесплатно</span></span></a>`)
  494. strLink := "https://wartank.ru/" + lstLink[0]
  495. if _, err := сам.сеть.Get(strLink); err != nil {
  496. // log._rintf("NetPolygon.addForce(): in make request force hard, err=\n\t%v\n", err)
  497. return
  498. }
  499. { // Узнать на сколько форсирована прочность
  500. strForce := lstPoligon[ind-7]
  501. lstForce := strings.Split(strForce, `<span class="green2">+`)
  502. strForce = lstForce[1]
  503. lstForce = strings.Split(strForce, ` на `)
  504. strForce = lstForce[0]
  505. iForce, err := strconv.Atoi(strForce)
  506. if err != nil {
  507. // log._rintf("ERRO NetPolygon.addForce(): strForceHard(%v) not int, err=\n\t%v\n", strForce, err)
  508. return
  509. }
  510. сам.танкСтат.ФорсажОбнов(стрПрочность, iForce)
  511. сам.СценаРежим().РаботаУст(стрПрочность)
  512. }
  513. default: // Неизвестно что
  514. сам.СценаРежим().РаботаУст("неизвестно")
  515. // log._rintf("ERRO NetPolygon.addForce(): неизвестно что это, strParam=%q", strParam)
  516. return
  517. }
  518. }