// package arsenal -- объект оружейной на базе package arsenal import ( "context" "fmt" "log" "strconv" "strings" "time" "wartank/pkg/section" "wartank/pkg/types" "wartank/server/serv_bots/warbot/angar/base/arsenal/arsenalnet" "wartank/server/serv_bots/warbot/tank/tankstat/static_param" ) const ( стрКумулятивы = "кумулятивы" стрБронебойки = "бронебойки" стрФугасы = "фугасы" стрРемки = "ремки" ) // Арсенал -- объект оружейной на базе type Арсенал struct { *section.Секция слог types.ИСлог бот types.ИБот база types.ИБаза сеть *arsenalnet.ArsenalNet фугас types.ИСтатПарам бронебойка types.ИСтатПарам кумулятив types.ИСтатПарам ремка types.ИСтатПарам уровень types.ИСтатПарам продуктИмя string // Что сейчас делается продуктКол types.ИСтатПарам // Сколько делается прямо сейчас продуктВремя string // Сколько осталось времени прямо сейчас кнт context.Context // контекст шахты фнОтмена func() // Функция отмены шахты } // НовАрсенал -- возвращает новый *Arsenal func НовАрсенал(база types.ИБаза) (*Арсенал, error) { section, err := section.НовСекция(база.Бот(), "Арсенал", `Ремкомплект
`) if err != nil { return nil, fmt.Errorf("НовАрсенал(): in create ISection, err=\n\t%w", err) } фугас, ош := static_param.НовСтатПарам(стрФугасы) if ош != nil { return nil, fmt.Errorf("НовАрсенал(): при создании статистики фугасов, ош=\n\t%w", ош) } бронейбойки, ош := static_param.НовСтатПарам(стрБронебойки) if ош != nil { return nil, fmt.Errorf("НовАрсенал(): при создании статистики бронебоек, ош=\n\t%w", ош) } кумулятив, ош := static_param.НовСтатПарам(стрКумулятивы) if ош != nil { return nil, fmt.Errorf("НовАрсенал(): при создании статистики кумулятивов, ош=\n\t%w", ош) } ремка, ош := static_param.НовСтатПарам(стрРемки) if ош != nil { return nil, fmt.Errorf("НовАрсенал(): при создании статистики ремок, ош=\n\t%w", ош) } уровень, ош := static_param.НовСтатПарам("уровень") if ош != nil { return nil, fmt.Errorf("НовАрсенал(): при создании статистики числа добычи, ош=\n\t%w", ош) } продуктКол, ош := static_param.НовСтатПарам("свинец") if ош != nil { return nil, fmt.Errorf("НовШахта(): при создании статистики числа добычи, ош=\n\t%w", ош) } кнт, фнОтмена := context.WithCancel(база.Контекст()) сам := &Арсенал{ Секция: section, бот: база.Бот(), слог: база.Бот().Сервер().Слог(), база: база, фугас: фугас, бронебойка: бронейбойки, кумулятив: кумулятив, ремка: ремка, уровень: уровень, продуктКол: продуктКол, кнт: кнт, фнОтмена: фнОтмена, } { // ArsenalNet сам.сеть, err = arsenalnet.НовАрсеналСеть(сам) if err != nil { return nil, fmt.Errorf("НовАрсенал(): in create NetArsenal, err=\n\t%w", err) } } _ = types.ИАрсенал(сам) return сам, nil } // Уровень -- возвращает уровень шахты func (сам *Арсенал) Уровень() types.ИСтатПарам { return сам.уровень } // ПродуктКолСейчас -- возвращает количество прозводимого продукта func (сам *Арсенал) ПродуктКолСейчас() int { return сам.продуктКол.Получ() } // ПродуктИмяСейчас -- возвращает имя прозводимого продукта func (сам *Арсенал) ПродуктИмяСейчас() string { return сам.продуктИмя } // ПродуктВремяСейчас -- сколько осталось времени до производства продукта func (сам *Арсенал) ПродуктВремяСейчас() string { return сам.продуктВремя // return сам.Секция.ВремяОпрос().Стр() } func (сам *Арсенал) Пуск() error { go сам.пуск() return nil } // запускает обработку арсенала func (сам *Арсенал) пуск() { // сам.getTime() time.Sleep(time.Second * 3) фнРабота := func() { defer func() { for сам.ВремяОстат().ПолучМилСек() > 0 { time.Sleep(time.Second * 5) } }() { // стройка счёт := 5 for счёт > 0 { if сам.построить() { break } счёт-- } } { // апгрейд счёт := 5 for счёт > 0 { if сам.проапгрейдить() { break } счёт-- } } _ = сам.уровеньОбновить() ош := сам.СтатаОбновить() if ош != nil { сам.слог.Ошибка("ArsenalNet.Run(): in update stat, err=\n\t%w", ош) } сам.забрать() сам.сделать() log.Printf("Арсенал.пуск(): бот=%q, цикл завершён\n", сам.бот.Имя()) } for { select { case <-сам.кнт.Done(): return // case <-сам.ВремяОпрос().КаналСиг(): // if сам.РежимТекущ().Получ() == "upgrade" { // continue // } // if err := сам.updateArsenal(); err != nil { // return fmt.Errorf("ArsenalNet.Run(): in update arsenal, err=\n\t%w", err) // } default: фнРабота() } } } // Обновляет текущий уровень оружейки (может быть не построена) func (сам *Арсенал) уровеньОбновить() bool { списСтр, ош := сам.сеть.ВебВоркер().Получ("http://wartank.ru/buildings") if ош != nil { log.Printf("Арсенал.уровеньОбновить(): in make request, err=\n\t%v\n", ош) return false } // Арсенал - 0
var ( еслиНайти = false стр = "" ) for _, стр = range списСтр { if strings.Contains(стр, `Арсенал - `) { еслиНайти = true break } } if !еслиНайти { return false } _стр := strings.TrimPrefix(стр, `Арсенал - `) _стр = strings.TrimSuffix(_стр, `
`) иУровень, ош := strconv.Atoi(_стр) if ош != nil { log.Printf("Арсенал.уровеньОбновить(): строка уровня сбойная, стр=%q, ош=\n\t%v\n", стр, ош) return false } сам.уровень.Уст(иУровень) return true } // Строит оружейку при нулевом уровне func (сам *Арсенал) построить() bool { списСтр, ош := сам.сеть.ВебВоркер().Получ("http://wartank.ru/buildings") if ош != nil { log.Printf("Арсенал.уровеньОбновить(): in make request, err=\n\t%v\n", ош) return false } // Арсенал - 0
var ( еслиНайти = false стр = "" ) for _, стр = range списСтр { if strings.Contains(стр, `Арсенал - `) { еслиНайти = true break } } if !еслиНайти { return false } _стр := strings.TrimPrefix(стр, `Арсенал - `) _стр = strings.TrimSuffix(_стр, `
`) иУровень, ош := strconv.Atoi(_стр) if ош != nil { log.Printf("Арсенал.уровеньОбновить(): строка уровня сбойная, стр=%q, ош=\n\t%v\n", стр, ош) return false } сам.уровень.Уст(иУровень) // Построить стр = "" еслиНайти = false for _, стр = range списСтр { if strings.Contains(стр, `href="building-upgrade/Armory">Построить`) { еслиНайти = true break } } if !еслиНайти { return true } // Пробуем построить оружейку _стр = strings.TrimPrefix(стр, `Построить`) ссылка := "https://wartank.ru/" + _стр списСтр, ош = сам.сеть.ВебВоркер().Получ(ссылка) if ош != nil { log.Printf("ERRO Арсенал.построить(): при GET-команде 'построить оружейку', err=\n\t%v\n", ош) return false } еслиНайти = false // "" for _, стр = range списСтр { if strings.Contains(стр, `ILinkListener-upgradeLink-link`) { еслиНайти = true break } } if !еслиНайти { return true } _стр = strings.TrimPrefix(стр, "") // http://wartank.ru/building-upgrade/Armory?16-1.ILinkListener-upgradeLink-link ссылка = "https://wartank.ru/building-upgrade/" + _стр _, ош = сам.сеть.ВебВоркер().Получ(ссылка) if ош != nil { log.Printf("ERRO Арсенал.построить(): при GET-команде 'купить постройку оружейки', err=\n\t%v\n", ош) return false } return true } // Пытается проапгрейдить оружейку func (сам *Арсенал) проапгрейдить() bool { time.Sleep(time.Millisecond * 1000) var ( еслиНайти = false списСтр []string стр = "" ош error ) фнКупить := func() bool { defer time.Sleep(time.Millisecond * 1000) списСтр, ош = сам.сеть.ВебВоркер().Получ("https://wartank.ru/building-upgrade/Armory") if ош != nil { log.Printf("Арсенал.проапгрейдить().фнКупить(): при GET-команде 'купить постройку оружейки', err=\n\t%v\n", ош) return false } for _, стр = range списСтр { // if strings.Contains(стр, `ILinkListener-upgradeLink-link`) { еслиНайти = true break } } if !еслиНайти { return true } // Пробуем улучшить шахту _стр := strings.TrimPrefix(стр, "") // https://wartank.ru/building-upgrade/Armory?4-1.ILinkListener-upgradeLink-link // ссылка := "https://wartank.ru/building-upgrade/" + _стр списСтр, ош = сам.сеть.ВебВоркер().Получ(ссылка) if ош != nil { log.Printf("Арсенал.проапгрейдить().фнКупить(): при GET-команде 'купить постройку оружейки', err=\n\t%v\n", ош) return false } // Проверить, что постройка состоялась for _, стр := range списСтр { if strings.Contains(стр, "ILinkListener-upgradeLink-link") { log.Printf("Арсенал.проапгрейдить().фнКупить(): покупка оружейкине прошла\n\tlink=%v\n\tстр=\n\t%v\n", ссылка, стр) return false // Покупка не оплачена } } log.Printf("!!!!! Арсенал.проапгрейдить().фнКупить(): покупка оружейки прошла\n") return true } фнПодтверждение := func() bool { for _, стр = range списСтр { // да, подтверждаю if strings.Contains(стр, `ILinkListener-confirmLink`) { еслиНайти = true break } } if !еслиНайти { return true } // Пробуем построить шахту _стр := strings.TrimPrefix(стр, `да, подтверждаю`) // https://wartank.ru/wicket/page?6-1.ILinkListener-confirmLink ссылка := "https://wartank.ru" + _стр списСтр, ош = сам.сеть.ВебВоркер().Получ(ссылка) if ош != nil { log.Printf("Арсенал.проапгрейдить().фнПодтверждение(): при GET-команде 'подтвердить постройку склада топлива', err=\n\t%v\n", ош) return false } // Проверить, что постройка состоялась for _, стр := range списСтр { if strings.Contains(стр, "Вы сделали слишком большую паузу") { log.Printf("Арсенал.проапгрейдить().фнПодтверждение(): подтверждение покупка склада топлива не прошла\n\tlink=%v\n\tстр=\n\t%v\n", ссылка, стр) return false // Покупка не оплачена } } log.Printf("+++++Арсенал.проапгрейдить().фнПодтверждение(): подтверждение покупка склада топлива прошла\n") return true } фнКомплекс := func() { count := 5 for count > 0 { if фнКупить() { if фнПодтверждение() { break } } count-- } } фнКомплекс() return true } // Проверяет на забрать оружейную func (сам *Арсенал) забрать() bool { var ( strOut string ind int еслиНайдено bool lstBase = сам.СписПолучить() ) for ind, strOut = range lstBase { if strings.Contains(strOut, `Моя амуниция`) { еслиНайдено = true ind += 17 strOut = lstBase[ind] break } } if !еслиНайдено { return false } if !strings.Contains(strOut, `">Забрать`) { return false } lstLink := strings.Split(strOut, `Забрать`) // https://wartank.ru/buildings?80-1.ILinkListener-buildings-0-building-rootBlock-actionPanel-takeProductionLink strLink = "https://wartank.ru/" + lstLink[0] var ( лстАрсенал []string ош error ) time.Sleep(time.Millisecond * 100) лстАрсенал, ош = сам.сеть.Get(strLink) if ош != nil { log.Printf("Арсенал.забрать(): при выполнении Get-запроса? err=\n\t%v\n", ош) return false } if len(лстАрсенал) == 0 { log.Printf("Арсенал.забрать(): len lstBase(%v)==0", len(lstBase)) return false } for _, strOut = range лстАрсенал { if strings.Contains(strOut, `Производство`) { return false } } if ош = сам.СтрОбновить(лстАрсенал); ош != nil { log.Printf("Арсенал.checkArsenalGet(): при обновлении lstBase, err=\n\t%v\n", ош) } if ош = сам.СтрОбновить(лстАрсенал); ош != nil { log.Printf("Арсенал.checkArsenalGet(): при обновлении lstArsenal, err=\n\t%v\n", ош) } return true } // Фугасы -- возвращает объект числа фугасов func (сам *Арсенал) Фугасы() types.ИСтатПарам { return сам.фугас } // Бронебойки -- возвращает объект бронебойных снарядов func (сам *Арсенал) Бронебойки() types.ИСтатПарам { return сам.бронебойка } // Кумулятивы -- возвращает объект бронебойных снарядов func (сам *Арсенал) Кумулятивы() types.ИСтатПарам { return сам.кумулятив } // Ремки -- возвращает объект ремкомплектов func (сам *Арсенал) Ремки() types.ИСтатПарам { return сам.ремка } // Обновляет состояние арсенала по требованию func (сам *Арсенал) СтатаОбновить() (err error) { // _mt.Println("\tArsenalNet.updateArsenal()") if ош := сам.сеть.Обновить(); ош != nil { return fmt.Errorf("Арсенал.СтатаОбновить(): при обновлении lstArsenal, err=%w", ош) } var ( strOut string lstArsenal = сам.СписПолучить() ) { // Найти маркер фугасного снаряда for _, strFugas := range lstArsenal { if strings.Contains(strFugas, `Фугасный снаряд `) { strOut = strFugas break } } lstFugas := strings.Split(strOut, `Фугасный снаряд `) strFugas := lstFugas[1] lstFugas = strings.Split(strFugas, `   `) strFugas = lstFugas[0] iFugas, err := strconv.Atoi(strFugas) if err != nil { return fmt.Errorf("Арсенал.СтатаОбновить(): fugas(%v) not number, err=\n\t%w", strFugas, err) } сам.Фугасы().Уст(iFugas) } { // Найти маркер бронебойного снаряда for _, strArmor := range lstArsenal { if strings.Contains(strArmor, `alt="Бронебойный снаряд"`) { strOut = strArmor break } } lstArmor := strings.Split(strOut, `Бронебойный снаряд `) strArmor := lstArmor[1] lstArmor = strings.Split(strArmor, `   `) strArmor = lstArmor[0] iArmor, err := strconv.Atoi(strArmor) if err != nil { return fmt.Errorf("Арсенал.СтатаОбновить(): armor(%v) not number, err=\n\t%w", strArmor, err) } сам.Бронебойки().Уст(iArmor) } { // Найти маркер кумулятивного снаряда for _, strKumul := range lstArsenal { if strings.Contains(strKumul, `Кумулятивный снаряд `) { strOut = strKumul break } } lstKumul := strings.Split(strOut, `Кумулятивный снаряд `) strKumul := lstKumul[1] lstKumul = strings.Split(strKumul, `   `) strKumul = lstKumul[0] iKumul, err := strconv.Atoi(strKumul) if err != nil { return fmt.Errorf("Арсенал.СтатаОбновить(): kumul(%v) not number, err=\n\t%w", strKumul, err) } сам.Кумулятивы().Уст(iKumul) } { // Найти маркер ремкомплекта for ind, strRemka := range lstArsenal { if strings.Contains(strRemka, ` `) { strOut = lstArsenal[ind] break } } lstRemka := strings.Split(strOut, ` `) strRemka := lstRemka[1] lstRemka = strings.Split(strRemka, ``) strRemka = lstRemka[0] iRemka, err := strconv.Atoi(strRemka) if err != nil { return fmt.Errorf("Арсенал.СтатаОбновить(): remka(%v) not number, err=\n\t%w", strRemka, err) } сам.Ремки().Уст(iRemka) } return nil } // Выбирает что надо делать, запускает процесс изготовления func (сам *Арсенал) сделать() bool { ош := сам.сеть.Обновить() if ош != nil { // log._rintf("ERRO Арсенал.сделать(): при обновлении lstArsenal, err=\n\t%v\n", err) return false } // _mt.Println("\tArsenalNet.сделать()") var ( ремкаКол = сам.Ремки().Получ() фугасКол = сам.Фугасы().Получ() кумульКол = сам.Кумулятивы().Получ() ббКол = сам.Бронебойки().Получ() снарядТип string ) if ремкаКол < 70 { // Контроль ремки по времени суток и минимальному количеству ремок for !сам.сделатьРемку() { } сам.продуктИмя = стрРемки return true } { // Контроль по числу снарядов. В равных долях без приоритетов // снарядТип = стрФугасы снарядТип = стрБронебойки if ббКол > фугасКол { снарядТип = стрФугасы } if фугасКол > кумульКол { снарядТип = стрКумулятивы } switch снарядТип { case стрФугасы: // Мало фугасов for !сам.сделатьФугасы() { } case стрКумулятивы: // Мало кумулятивов for !сам.сделатьКумули() { } case стрБронебойки: // Мало бронебойных for !сам.сделатьБронебойки() { } default: // log._rintf("ERRO Арсенал.сделать(): неизвестный тип арсенала(%v)", typeArmor) } сам.продуктИмя = снарядТип } return true } // Создать бронебойные func (сам *Арсенал) сделатьБронебойки() bool { var ( стрВых string lstArsenal = сам.СписПолучить() еслиНайдено bool инд int ) for инд, стрВых = range lstArsenal { if strings.Contains(стрВых, `Бронебойный снаряд
`) { еслиНайдено = true break } } if !еслиНайдено { return false } стрВых = lstArsenal[инд+10] // Получить ссылку на бронебойные lstArmor := strings.Split(стрВых, `Начать производство`) strLink = "https://wartank.ru/production/" + lstArmor[0] time.Sleep(time.Millisecond * 50) if _, err := сам.сеть.Get(strLink); err != nil { // log._rintf("ERRO ArsenalNet.makeArmor(): in update lstArsenal, err=\n\t%v\n", err) return false } сам.СценаРежим().РежимУст(стрБронебойки) return true } // Создать кумулятивные func (сам *Арсенал) сделатьКумули() bool { var ( стрВых string lstArsenal = сам.СписПолучить() еслиНайдено bool инд int ) for инд, стрВых = range lstArsenal { if strings.Contains(стрВых, `Кумулятивный снаряд
`) { еслиНайдено = true break } } if !еслиНайдено { return false } стрВых = lstArsenal[инд+10] if !strings.Contains(стрВых, `>Начать производство<`) { return false } // Получить ссылку на кумулятив lstKumul := strings.Split(стрВых, `Начать производство`) strLink = "https://wartank.ru/production/" + lstKumul[0] time.Sleep(time.Millisecond * 50) if _, err := сам.сеть.Get(strLink); err != nil { // log._rintf("ERRO ArsenalNet.makeKumul(): in make product arsenal kumul , err=\n\t%v\n", err) return false } сам.СценаРежим().РежимУст(стрКумулятивы) return true } // Создать фугасы func (сам *Арсенал) сделатьФугасы() bool { var ( lstArsenal = сам.СписПолучить() стрВых string еслиНадено bool инд int ) for инд, стрВых = range lstArsenal { if strings.Contains(стрВых, `Фугасный снаряд
`) { еслиНадено = true break } } if !еслиНадено { return false } стрВых = lstArsenal[инд+10] if !strings.Contains(стрВых, `">Начать производство`) { return false } // Получить ссылку на ремку lstKumul := strings.Split(стрВых, `Начать производство`) strLink = "https://wartank.ru/production/" + lstKumul[0] time.Sleep(time.Millisecond * 50) if _, err := сам.сеть.Get(strLink); err != nil { // log._rintf("ERRO ArsenalNet.makeFugas(): in make request arsenal product, err=\n\t%v\n", err) return false } сам.СценаРежим().РежимУст(стрФугасы) // log._rintf("INFO Арсенал.makeFugas()\n") return true } // Создать ремку. Выполняется если подходят условия func (сам *Арсенал) сделатьРемку() bool { // _mt.Println("\tArsenalNet.makeRemka()") var ( стрВых string еслиНайдено bool инд int ) lstArsenal, ош := сам.сеть.ВебВоркер().Получ("https://wartank.ru/production/Armory") if ош != nil { log.Printf("Арсенал.сделатьРемку(): при получении страницы оружейки, err=\n\t%v\n", ош) return false } // Ремкомплект
for инд, стрВых = range lstArsenal { if strings.Contains(стрВых, `Ремкомплект
`) { еслиНайдено = true break } } if !еслиНайдено { return false } стрВых = lstArsenal[инд+10] // Если кривая строка, то надо вернуться if strings.Contains(стрВых, ``) { return true } // Получить ссылку на ремку _ссылка := strings.TrimPrefix(стрВых, `Начать производство`) // https://wartank.ru/production/Armory?37-1.ILinkListener-productions-3-production-startProduceLink ссылка := "https://wartank.ru/production/" + _ссылка time.Sleep(time.Millisecond * 50) if _, err := сам.сеть.ВебВоркер().Получ(ссылка); err != nil { log.Printf("Арсенал.сделатьРемку(): при отдаче команды сделать ремку, err=\n\t%v\n", err) return false } сам.СценаРежим().РежимУст(стрРемки) return true }