arena_market.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. // package arena_market -- объект рынка
  2. package arena_market
  3. import (
  4. "log"
  5. "strconv"
  6. "strings"
  7. "time"
  8. "wartank/app/lev0/alias"
  9. . "wartank/app/lev0/types"
  10. "wartank/app/lev1/stat_param"
  11. "wartank/app/lev2/arena"
  12. )
  13. // АренаРынок -- объект рынка
  14. type АренаРынок struct {
  15. ИАрена
  16. бот ИБот
  17. уровень ИСтатПарам
  18. }
  19. // НовРынок -- возвращает новый рынок
  20. func НовРынок(конт ИБотКонтекст, база ИАренаБаза) *АренаРынок {
  21. сам := &АренаРынок{
  22. бот: база.Бот(),
  23. уровень: stat_param.НовСтатПарам("уровень"), // FIXME: вынести на уровень арены
  24. }
  25. аренаКонфиг := arena.АренаКонфиг{
  26. Бот_: база.Бот(),
  27. АренаИмя_: "Рынок",
  28. СтрКонтроль_: `<title>Рынок</title>`,
  29. ФнПуск_: сам.пуск,
  30. СтрУрл_: "https://wartank.ru/market",
  31. }
  32. сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
  33. return сам
  34. }
  35. // Пуск -- запускает всю работу рынка в отдельном потоке
  36. func (сам *АренаРынок) Пуск() {
  37. go сам.пуск()
  38. }
  39. // выполняет опрос рынка базы, должен работать как горутина
  40. func (сам *АренаРынок) пуск() {
  41. time.Sleep(time.Second * 7)
  42. фнРабота := func() {
  43. defer time.Sleep(time.Minute * 30)
  44. for !сам.уровеньОбновить() {
  45. }
  46. сам.ускорениеПровер()
  47. сам.проверОжидание()
  48. for сам.купитьЗолото() {
  49. }
  50. }
  51. for {
  52. select {
  53. case <-сам.бот.Контекст().Done():
  54. return
  55. default:
  56. фнРабота()
  57. }
  58. }
  59. }
  60. // Проверяет ускорение строительства
  61. func (сам *АренаРынок) ускорениеПровер() {
  62. списСтр := сам.Сеть().ВебВоркер().Получ("http://wartank.ru/buildings")
  63. // <span class="green2">Склад топлива -
  64. var (
  65. еслиНайти = false
  66. стр string
  67. )
  68. for _, стр = range списСтр {
  69. if strings.Contains(стр, `<span class="green2">Склад топлива - `) {
  70. еслиНайти = true
  71. break
  72. }
  73. }
  74. if !еслиНайти {
  75. return
  76. }
  77. }
  78. // Обновляет текущий уровень рынка (может быть не построен)
  79. func (сам *АренаРынок) уровеньОбновить() bool {
  80. списСтр := сам.Сеть().ВебВоркер().Получ("http://wartank.ru/buildings")
  81. // <span class="green2">Рынок -
  82. var (
  83. еслиНайти = false
  84. стр = ""
  85. )
  86. for _, стр = range списСтр {
  87. if strings.Contains(стр, `<span class="green2">Рынок -`) {
  88. еслиНайти = true
  89. break
  90. }
  91. }
  92. if !еслиНайти {
  93. return false
  94. }
  95. // <span class="green2">Рынок - 0</span><br/>
  96. _стр := strings.TrimPrefix(стр, `<span class="green2">Рынок - `)
  97. _стр = strings.TrimSuffix(_стр, `</span><br/>`)
  98. иУровень, ош := strconv.Atoi(_стр)
  99. if ош != nil {
  100. log.Printf("Рынок.уровеньОбновить(): строка уровня сбойная, стр=%q, ош=\n\t%v\n", стр, ош)
  101. return false
  102. }
  103. сам.уровень.Уст(иУровень)
  104. switch иУровень {
  105. case 0: // рынок надо построить
  106. for !сам.построить() {
  107. }
  108. default: // Может можно проапгрейдить
  109. счёт := 5
  110. for !сам.проапгрейдить() {
  111. счёт--
  112. if счёт >= 0 {
  113. break
  114. }
  115. }
  116. }
  117. return true
  118. }
  119. // Строит шахту при нулевом уровне
  120. func (сам *АренаРынок) построить() bool {
  121. time.Sleep(time.Millisecond * 1000)
  122. // <td style="width:50%;padding-left:1px;"><a class="simple-but border mb5" href="building-upgrade/Market"><span><span>Построить</span></span></a></td>
  123. var (
  124. еслиНайти = false
  125. списСтр []string
  126. стр = ""
  127. )
  128. фнКупить := func() bool {
  129. defer time.Sleep(time.Millisecond * 1000)
  130. списСтр = сам.Сеть().ВебВоркер().Получ("https://wartank.ru/building-upgrade/Market")
  131. for _, стр = range списСтр {
  132. // <a class="simple-but border mb5" href="Market?19-1.ILinkListener-upgradeLink-link">
  133. if strings.Contains(стр, `ILinkListener-upgradeLink-link`) {
  134. еслиНайти = true
  135. break
  136. }
  137. }
  138. if !еслиНайти {
  139. return true
  140. }
  141. // Пробуем построить шахту
  142. _стр := strings.TrimPrefix(стр, "<a class=\"simple-but border mb5\" href=\"")
  143. _стр = strings.TrimSuffix(_стр, "\">")
  144. // https://wartank.ru/building-upgrade/Market?18-1.ILinkListener-upgradeLink-link
  145. // <a class="simple-but border mb5" href="Market?19-1.ILinkListener-upgradeLink-link">
  146. ссылка := "https://wartank.ru/building-upgrade/" + _стр
  147. списСтр = сам.Сеть().ВебВоркер().Получ(ссылка)
  148. // Проверить, что постройка состоялась
  149. for _, стр := range списСтр {
  150. if strings.Contains(стр, "ILinkListener-upgradeLink-link") {
  151. log.Printf("Рынок.построить().фнКупить(): покупка склада топлива не прошла\n\tlink=%v\n\tстр=\n\t%v\n", ссылка, стр)
  152. return false // Покупка не оплачена
  153. }
  154. }
  155. log.Printf("+++++Рынок.построить().фнКупить(): покупка склада топлива прошла\n")
  156. return true
  157. }
  158. фнПодтверждение := func() bool {
  159. for _, стр = range списСтр {
  160. // <a class="simple-but border w50 mXa mb10" w:id="confirmLink" href="../wicket/page?21-1.ILinkListener-confirmLink"><span><span>да, подтверждаю</span></span></a>
  161. if strings.Contains(стр, `ILinkListener-confirmLink`) {
  162. еслиНайти = true
  163. break
  164. }
  165. }
  166. if !еслиНайти {
  167. return true
  168. }
  169. // Пробуем построить шахту
  170. _стр := strings.TrimPrefix(стр, `<a class="simple-but border w50 mXa mb10" w:id="confirmLink" href="..`)
  171. _стр = strings.TrimSuffix(_стр, `"><span><span>да, подтверждаю</span></span></a>`)
  172. // https://wartank.ru/wicket/page?20-1.ILinkListener-confirmLink
  173. ссылка := "https://wartank.ru" + _стр
  174. списСтр = сам.Сеть().ВебВоркер().Получ(ссылка)
  175. // Проверить, что постройка состоялась
  176. for _, стр := range списСтр {
  177. if strings.Contains(стр, "<title>Вы сделали слишком большую паузу</title>") {
  178. log.Printf("Рынок.построить().фнПодтверждение(): подтверждение покупка склада топлива не прошла\n\tlink=%v\n\tстр=\n\t%v\n", ссылка, стр)
  179. return false // Покупка не оплачена
  180. }
  181. }
  182. log.Printf("+++++Рынок.построить().фнПодтверждение(): подтверждение покупка склада топлива прошла\n")
  183. return true
  184. }
  185. фнКомплекс := func() {
  186. for {
  187. if фнКупить() {
  188. if фнПодтверждение() {
  189. break
  190. }
  191. }
  192. }
  193. }
  194. фнКомплекс()
  195. return true
  196. }
  197. // Пытается проапгрейдить топливный склад
  198. func (сам *АренаРынок) проапгрейдить() bool {
  199. time.Sleep(time.Millisecond * 1000)
  200. var (
  201. еслиНайти = false
  202. списСтр []string
  203. стр = ""
  204. )
  205. фнКупить := func() bool {
  206. defer time.Sleep(time.Millisecond * 1000)
  207. списСтр = сам.Сеть().ВебВоркер().Получ("https://wartank.ru/building-upgrade/Market")
  208. for _, стр = range списСтр {
  209. // <a class="simple-but border mb5" href="Market?5-1.ILinkListener-upgradeLink-link">
  210. if strings.Contains(стр, `ILinkListener-upgradeLink-link`) {
  211. еслиНайти = true
  212. break
  213. }
  214. }
  215. if !еслиНайти {
  216. return true
  217. }
  218. // Пробуем улучшить шахту
  219. _стр := strings.TrimPrefix(стр, "<a class=\"simple-but border mb5\" href=\"")
  220. _стр = strings.TrimSuffix(_стр, "\">")
  221. // https://wartank.ru/building-upgrade/Market?4-1.ILinkListener-upgradeLink-link
  222. // <a class="simple-but border mb5" href="Market?50-1.ILinkListener-upgradeLink-link">
  223. ссылка := "https://wartank.ru/building-upgrade/" + _стр
  224. списСтр = сам.Сеть().ВебВоркер().Получ(ссылка)
  225. // Проверить, что постройка состоялась
  226. for _, стр := range списСтр {
  227. if strings.Contains(стр, "ILinkListener-upgradeLink-link") {
  228. log.Printf("Рынок.проапгрейдить().фнКупить(): покупка рынка не прошла\n\tlink=%v\n\tстр=\n\t%v\n", ссылка, стр)
  229. return false // Покупка не оплачена
  230. }
  231. }
  232. log.Printf("+++++Рынок.проапгрейдить().фнКупить(): покупка рынка прошла\n")
  233. return true
  234. }
  235. фнПодтверждение := func() bool {
  236. for _, стр = range списСтр {
  237. // <a class="simple-but border w50 mXa mb10" w:id="confirmLink" href="../wicket/page?7-1.ILinkListener-confirmLink"><span><span>да, подтверждаю</span></span></a>
  238. if strings.Contains(стр, `ILinkListener-confirmLink`) {
  239. еслиНайти = true
  240. break
  241. }
  242. }
  243. if !еслиНайти {
  244. return true
  245. }
  246. // Пробуем построить шахту
  247. _стр := strings.TrimPrefix(стр, `<a class="simple-but border w50 mXa mb10" w:id="confirmLink" href="..`)
  248. _стр = strings.TrimSuffix(_стр, `"><span><span>да, подтверждаю</span></span></a>`)
  249. // https://wartank.ru/wicket/page?6-1.ILinkListener-confirmLink
  250. ссылка := "https://wartank.ru" + _стр
  251. списСтр = сам.Сеть().ВебВоркер().Получ(ссылка)
  252. // Проверить, что постройка состоялась
  253. for _, стр := range списСтр {
  254. if strings.Contains(стр, "<title>Вы сделали слишком большую паузу</title>") {
  255. log.Printf("Рынок.проапгрейдить().фнПодтверждение(): подтверждение покупка рынка не прошла\n\tlink=%v\n\tстр=\n\t%v\n", ссылка, стр)
  256. return false // Покупка не оплачена
  257. }
  258. }
  259. log.Printf("+++++Рынок.проапгрейдить().фнПодтверждение(): подтверждение покупка склада топлива прошла\n")
  260. return true
  261. }
  262. фнКомплекс := func() {
  263. count := 5
  264. for count > 0 {
  265. if фнКупить() {
  266. if фнПодтверждение() {
  267. break
  268. }
  269. }
  270. count--
  271. }
  272. }
  273. фнКомплекс()
  274. return true
  275. }
  276. // Проверяет время ожидания рынка
  277. func (сам *АренаРынок) проверОжидание() {
  278. var (
  279. strOut string
  280. еслиНайдено bool
  281. )
  282. // countDown := сам.CountDown().Get()
  283. фнЕслиСеребро := func() bool { // Найти счётчик цены серебра
  284. сам.Обновить()
  285. еслиНайдено := false
  286. lstMarket := сам.СписПолучить()
  287. for _, strOut = range lstMarket {
  288. if strings.Contains(strOut, `alt="Серебро" title="Серебро"> `) {
  289. еслиНайдено = true
  290. break
  291. }
  292. }
  293. if еслиНайдено {
  294. lstSilver := strings.Split(strOut, `<img class="ico vm" src="/images/icons/silver.png?2" alt="Серебро" title="Серебро"> `)
  295. strSilver := lstSilver[1]
  296. switch strSilver {
  297. case "10", "50", "100", "500":
  298. return true
  299. default:
  300. серебро := сам.бот.Ангар().СереброВсего()
  301. if серебро.Получ() > 1_000_000 {
  302. return true
  303. }
  304. return false
  305. }
  306. }
  307. return false
  308. }
  309. fnGetCountDown := func() { // Искать счётчик времени
  310. lstMarket := сам.СписПолучить()
  311. // Найти счётчик времени
  312. for _, strOut = range lstMarket {
  313. if strings.Contains(strOut, `Минимальная цена через `) {
  314. еслиНайдено = true
  315. break
  316. }
  317. }
  318. if !еслиНайдено {
  319. return // Минимальная цена
  320. }
  321. lstTime := strings.Split(strOut, `Минимальная цена через `)
  322. strTime := lstTime[1]
  323. if err := сам.ОбратВремяУст(alias.Время(strTime)); err != nil {
  324. // log._rintf("ERRO Market.checkTime(): при установке времени ожидания рынка(%v)\n\terr=%v\n", strTime, err)
  325. return // Возможно минимальная цена
  326. }
  327. }
  328. if фнЕслиСеребро() {
  329. return
  330. }
  331. fnGetCountDown()
  332. }
  333. // Проверяет рынок на режим покупки
  334. func (сам *АренаРынок) купитьЗолото() bool {
  335. var (
  336. ind int
  337. еслиНайдено bool
  338. strOut string
  339. lstMarket = сам.СписПолучить()
  340. strSilver string
  341. )
  342. for ind, strOut = range lstMarket {
  343. if strings.Contains(strOut, `alt="Серебро" title="Серебро"> `) {
  344. еслиНайдено = true
  345. break
  346. }
  347. }
  348. if !еслиНайдено { // Не найдена продажа золота за серебро
  349. return false
  350. }
  351. lstSilver := strings.Split(strOut, `<img class="ico vm" src="/images/icons/silver.png?2" alt="Серебро" title="Серебро"> `)
  352. strSilver = lstSilver[1]
  353. серебро := сам.бот.Ангар().СереброВсего().Получ()
  354. еслиКупить := false
  355. switch strSilver {
  356. case "10", "50", "100", "500": // Допустимые суммы трат
  357. еслиКупить = true
  358. case "1000": // Если стоит тысяча серебра
  359. if серебро > 500_000 { // Если серебра больше полумиллиона -- покупаем
  360. еслиКупить = true
  361. }
  362. case "5000", "10000": // Если большая сумма -- можно купить и больше
  363. if серебро > 1_000_000 {
  364. еслиКупить = true
  365. }
  366. }
  367. if !еслиКупить {
  368. return false
  369. }
  370. ind -= 15
  371. strOut = lstMarket[ind]
  372. lstLink := strings.Split(strOut, `<a class="simple-but border mb5" href="`)
  373. if len(lstLink) < 2 {
  374. return false
  375. }
  376. strLink := lstLink[1]
  377. lstLink = strings.Split(strLink, `"><span><span>Получить `)
  378. strLink = "https://wartank.ru/" + lstLink[0]
  379. lstMarket, err := сам.Сеть().Get(strLink)
  380. if err != nil {
  381. // log._rintf("ERRO Market.buyGold(): при выполнении GET-команды на покупку золота, err=\n\t%v\n", err)
  382. return true
  383. }
  384. for _, strOut = range lstMarket {
  385. if strings.Contains(strOut, `Ошибка на сервере. Сообщение админу уже отправлено.`) {
  386. // log._rintf("ERRO Market.buyGold(): при получении lstMarket, strHTML=%v, err=\nt%v\n", strOut, err)
  387. return false
  388. }
  389. }
  390. if err = сам.СтрОбновить(lstMarket); err != nil {
  391. // log._rintf("Market.buyGold(): при обновлении lstMarket, err=\n\t%v\n", err)
  392. return true
  393. }
  394. return true
  395. }