fuel_attack.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. // package fuel_attack -- объект боя на топливе
  2. package fuel_attack
  3. import (
  4. "fmt"
  5. "log"
  6. "os"
  7. "strings"
  8. "time"
  9. "wartank/pkg/arena"
  10. "wartank/pkg/components/arena_net"
  11. "wartank/pkg/cons"
  12. . "wartank/pkg/kernel/kernel_types"
  13. . "wartank/server/lev0/types"
  14. )
  15. // ТопливоБой -- объект боя на топливе
  16. type ТопливоБой struct {
  17. ИАрена
  18. ангар ИАнгар
  19. аренаСеть *arena_net.АренаСеть
  20. }
  21. // НовТопливоБой -- возвращает новый *ТопливоБойNet
  22. func НовТопливоБой(конт ИЯдроКонтекст, ангар ИАнгар) (*ТопливоБой, error) {
  23. аренаСеть := arena_net.НовАренаСеть(конт, ангар, "https://wartank.ru/battle")
  24. сам := &ТопливоБой{
  25. ангар: ангар,
  26. аренаСеть: аренаСеть,
  27. }
  28. аренаКонфиг := arena.АренаКонфиг{
  29. Бот_: ангар.Бот(),
  30. АренаИмя_: "ТопливоБой",
  31. СтрКонтроль_: `<title>Бой</title>`,
  32. ФнПуск_: сам.пуск,
  33. СтрУрл_: "https://wartank.ru/angar",
  34. }
  35. сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
  36. _ = ИАрена(сам)
  37. return сам, nil
  38. }
  39. func (сам *ТопливоБой) пуск() {
  40. for {
  41. time.Sleep(time.Second * 30) // Минимальный интервал ожидания прибавки топлива
  42. // сам.топливоПолуч()
  43. топливо := сам.ангар.Топливо().Получ()
  44. if топливо < cons.ТопливоМин { // Минимальная ёмкость бака -- 315
  45. continue
  46. }
  47. log.Printf("Fuel.Run: val=%v\n", топливо)
  48. списСтрБой, err := сам.начатьБой()
  49. if err != nil {
  50. // log._rintf("ERRO ТопливоБой.findFuel(): in get page battle, err=\n\t%v\n", err)
  51. continue
  52. }
  53. списВыстрел1, err := сам.выбратьБойСлабый(списСтрБой)
  54. if err != nil {
  55. // log._rintf("ERRO ТопливоБой.findFuel(): in get page shooting, err=\n\t%v\n", err)
  56. continue
  57. }
  58. if err := сам.сделатьВыстрелы(списВыстрел1); err != nil {
  59. log.Printf("ERRO ТопливоБой.findFuel(): in make shooting, err=\n\t%v\n", err)
  60. }
  61. }
  62. }
  63. // Получает количество топлива
  64. // Идёт в атаку, если топлива больше cons.ТопливоМин
  65. func (сам *ТопливоБой) начатьБой() (списСтрБой []string, err error) {
  66. // Получить ссылку на атаку
  67. // _mt.Println("\t ТопливоБой.начатьБой()")
  68. списАнгар := сам.ангар.СписПолучить()
  69. var стрАнализ string
  70. for _, стрАтак := range списАнгар {
  71. if strings.Contains(стрАтак, `<span>В бой!</span>`) {
  72. стрАнализ = стрАтак
  73. break
  74. }
  75. }
  76. // Вырезать ссылку на атаку
  77. списАнгар = strings.Split(стрАнализ, `<a class="simple-but border mb1" href="`)
  78. if len(списАнгар) < 2 { // Не та страница
  79. return nil, fmt.Errorf("ТопливоБой.начатьБой(): список строк для атаки пустой")
  80. }
  81. бойСсылка := списАнгар[1]
  82. списАнгар = strings.Split(бойСсылка, `"><span><span>В бой!</span></span></a>`)
  83. бойСсылка = "https://wartank.ru/" + списАнгар[0]
  84. списСтрБой, err = сам.аренаСеть.Get(бойСсылка)
  85. if err != nil {
  86. return nil, fmt.Errorf("ТопливоБой.начатьБой(): in make GET-request to battle, err=\n\t%w", err)
  87. }
  88. return списСтрБой, nil
  89. }
  90. // Выбирает первого более слабого противника и делает первый выстрел
  91. func (сам *ТопливоБой) выбратьБойСлабый(списСтрБой []string) (списСтрВыстрел1 []string, err error) {
  92. // _mt.Println("\tAngarNet.makeSelectBattle()")
  93. var стрАнализ string
  94. defer func() {
  95. if паника := recover(); паника != nil {
  96. msg := time.Now().Local().Format("2006-01-02 15:04:05.000 ") + "fnShoot1\n"
  97. msg += "\tNetClient.makeSelectBattle().fnShoot1()\n"
  98. msg0 := fmt.Sprintf("%v\n", паника)
  99. msg1 := ""
  100. for _, _msg := range strings.Split(msg0, "\n") {
  101. if _msg == "" {
  102. continue
  103. }
  104. msg1 += "\t" + _msg + "\n"
  105. }
  106. msg += msg1
  107. // _mt.Println(msg)
  108. err = fmt.Errorf("%v", msg)
  109. msg1 = "" // Сброс накопленной ошибки
  110. for _, _msg := range списСтрБой {
  111. if _msg == "" {
  112. continue
  113. }
  114. msg1 += "\t" + _msg + "\n"
  115. }
  116. msg += msg1
  117. // Выкинуть ошибку в файл
  118. _ = os.MkdirAll("./errors", 0700)
  119. err = os.WriteFile("./errors/attack_shoot1.html", []byte(msg), 0600)
  120. }
  121. }()
  122. // Выдернуть строку с первой ссылкой на противника
  123. for _, стрБой_ := range списСтрБой {
  124. if strings.Contains(стрБой_, `opponents-opponents-0`) {
  125. стрАнализ = стрБой_
  126. break
  127. }
  128. }
  129. var ссылкаБой string
  130. switch стрАнализ == "" {
  131. case true: // Такая ситуация возможна, если уже были какие-то выстрелы
  132. return списСтрБой, nil
  133. default: // Успешный выстрел
  134. // Вырезать ссылку из строки
  135. списСтрБой = strings.Split(стрАнализ, `<td class="cntr"><a href="`)
  136. ссылкаБой = списСтрБой[1]
  137. списСтрБой = strings.Split(ссылкаБой, `"><img class="tank-img" alt="tank" src="/tankimg?`)
  138. ссылкаБой = "https://wartank.ru/" + списСтрБой[0]
  139. }
  140. списСтрВыстрел1, err = сам.аренаСеть.Get(ссылкаБой)
  141. if err != nil {
  142. return nil, fmt.Errorf("ТопливоБой.makeSelectBattle(): in GET-response select battle tank, err=\n\t%w", err)
  143. }
  144. return списСтрВыстрел1, nil
  145. }
  146. // Ведёт бой в 2 выстрела (здесь только 2 и 3 выстрел -- первый сделан при слабом противнике)
  147. func (сам *ТопливоБой) сделатьВыстрелы(lstShoot2 []string) error {
  148. // _mt.Println("\tAngarNet.makeShooting()")
  149. var списВыстрел3 []string // Тело страницы для третьего выстрела
  150. фнВыстрел2 := func() (err error) { // Второй выстрел
  151. // _mt.Println("\tAngarNet.makeShooting().fnShoot2()")
  152. defer func() {
  153. if _panic := recover(); _panic != nil {
  154. msg := time.Now().Local().Format("2006-01-02 15:04:05.000 ") + "fnShoot2\n"
  155. msg += "\tNetClient.makeShooting().fnShoot2()\n"
  156. msg0 := fmt.Sprintf("%v\n", _panic)
  157. msg1 := ""
  158. for _, _msg := range strings.Split(msg0, "\n") {
  159. if _msg == "" {
  160. continue
  161. }
  162. msg1 += "\t" + _msg + "\n"
  163. }
  164. msg += msg1
  165. // _mt.Println(msg)
  166. err = fmt.Errorf("%v", msg)
  167. msg1 = "" // Сброс накопленной ошибки
  168. for _, _msg := range lstShoot2 {
  169. if _msg == "" {
  170. continue
  171. }
  172. msg1 += "\t" + _msg + "\n"
  173. }
  174. msg += msg1
  175. // Выкинуть ошибку в файл
  176. _ = os.MkdirAll("./errors", 0700)
  177. err = os.WriteFile("./errors/attack_shoot2.html", []byte(msg), 0600)
  178. }
  179. }()
  180. // Получить ссылку на второй выстрел
  181. var strOut string
  182. for _, strShoot := range lstShoot2 {
  183. if strings.Contains(strShoot, `<span>Добить</span>`) {
  184. strOut = strShoot
  185. break
  186. }
  187. }
  188. var linkShoot2 string
  189. switch strOut == "" {
  190. case true: // Первый выстрел был неудачным
  191. for _, strShoot := range lstShoot2 {
  192. if strings.Contains(strShoot, `<span>Взять реванш</span>`) {
  193. strOut = strShoot
  194. break
  195. }
  196. }
  197. if strOut == "" { // Это ситуация для третьего выстрела
  198. списВыстрел3 = lstShoot2
  199. return nil
  200. }
  201. // Вырезать ссылку из строки
  202. lstShoot2 = strings.Split(strOut, `<a class="simple-but border" href="`)
  203. linkShoot2 = lstShoot2[1]
  204. lstShoot2 = strings.Split(linkShoot2, `"><span><span>Взять реванш</span></span></a>`)
  205. linkShoot2 = "https://wartank.ru/" + lstShoot2[0]
  206. default: // Первый выстрел был удачным
  207. // Вырезать ссылку из строки
  208. lstShoot2 = strings.Split(strOut, `<a class="simple-but border" href="`)
  209. linkShoot2 = lstShoot2[1]
  210. lstShoot2 = strings.Split(linkShoot2, `"><span><span>Добить</span></span></a>`)
  211. linkShoot2 = "https://wartank.ru/" + lstShoot2[0]
  212. }
  213. списВыстрел3, err = сам.аренаСеть.Get(linkShoot2)
  214. if err != nil {
  215. return fmt.Errorf("ТопливоБой.makeShooting(): in Get-response shoot2, err=\n\t%w", err)
  216. }
  217. fuel := сам.ангар.Топливо().Получ()
  218. fuel -= 30
  219. сам.ангар.Топливо().Уст(fuel)
  220. return nil
  221. }
  222. if err := фнВыстрел2(); err != nil {
  223. return err
  224. }
  225. фнВыстрел3 := func() (err error) { // Третий выстрел
  226. // _mt.Println("\tAngarNet.makeShooting().fnShoot3()")
  227. defer func() {
  228. if _panic := recover(); _panic != nil {
  229. msg := time.Now().Local().Format("2006-01-02 15:04:05.000 fnShoot3\n")
  230. msg += "\tNetClient.makeShooting().fnShoot3()\n"
  231. msg0 := fmt.Sprintf("%v\n", _panic)
  232. msg1 := ""
  233. for _, _msg := range strings.Split(msg0, "\n") {
  234. if _msg == "" {
  235. continue
  236. }
  237. msg1 += "\t" + _msg + "\n"
  238. }
  239. msg += msg1
  240. // _mt.Println(msg)
  241. err = fmt.Errorf("%v", msg)
  242. msg1 = "" // Сброс накопленной ошибки
  243. for _, _msg := range списВыстрел3 {
  244. if _msg == "" {
  245. continue
  246. }
  247. msg1 += "\t" + _msg + "\n"
  248. }
  249. msg += msg1
  250. // Выкинуть ошибку в файл
  251. _ = os.MkdirAll("./errors", 0700)
  252. err = os.WriteFile("./errors/attack_shoot3.html", []byte(msg), 0600)
  253. }
  254. }()
  255. // Получить ссылку на третий выстрел
  256. var strOut string
  257. for _, strShoot3 := range списВыстрел3 {
  258. if strings.Contains(strShoot3, `<span>Уничтожить</span>`) {
  259. strOut = strShoot3
  260. break
  261. }
  262. }
  263. linkShoot3 := ""
  264. switch strOut == "" {
  265. case true: // Если не найдена ссылка -- значит было поражение в выстреле
  266. if strOut == "" {
  267. for _, strShoot3 := range списВыстрел3 {
  268. if strings.Contains(strShoot3, `<span>Взять реванш</span>`) {
  269. strOut = strShoot3
  270. break
  271. }
  272. }
  273. }
  274. // Вырезать ссылку из строки
  275. списВыстрел3 = strings.Split(strOut, `<a class="simple-but border" href="`)
  276. linkShoot3 = списВыстрел3[1]
  277. списВыстрел3 = strings.Split(linkShoot3, `"><span><span>Взять реванш</span></span></a>`)
  278. linkShoot3 = "https://wartank.ru/" + списВыстрел3[0]
  279. default: // Успешный выстрел
  280. // Вырезать ссылку из строки
  281. списВыстрел3 = strings.Split(strOut, `<a class="simple-but border" href="`)
  282. linkShoot3 = списВыстрел3[1]
  283. списВыстрел3 = strings.Split(linkShoot3, `"><span><span>Уничтожить</span></span></a>`)
  284. linkShoot3 = "https://wartank.ru/" + списВыстрел3[0]
  285. }
  286. if _, err = сам.аренаСеть.Get(linkShoot3); err != nil {
  287. return fmt.Errorf("ТопливоБой.makeShooting(): in Get-response shoot3, err=\n\t%w", err)
  288. }
  289. fuel := сам.ангар.Топливо().Получ()
  290. fuel -= 30
  291. сам.ангар.Топливо().Уст(fuel)
  292. return nil
  293. }
  294. if err := фнВыстрел3(); err != nil {
  295. return err
  296. }
  297. сам.ангар.РесурсыОбновить()
  298. return nil
  299. }