market.go 15 KB

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