fuel_attack.go 12 KB

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