package mine import ( "context" "fmt" "log" "strconv" "strings" "time" "wartank/pkg/alias" "wartank/pkg/section" "wartank/pkg/types" "wartank/server/serv_bots/warbot/angar/base/mine/minenet" "wartank/server/serv_bots/warbot/tank/tankstat/static_param" ) /* Объект шахты на базе */ // Шахта -- объект шахты на базе type Шахта struct { *section.Секция сеть *minenet.MineNet бот types.ИБот база types.ИБаза руда types.ИСтатПарам железо types.ИСтатПарам сталь types.ИСтатПарам свинец types.ИСтатПарам уровень types.ИСтатПарам продуктИмя string // Что сейчас делается продуктКол types.ИСтатПарам // Сколько делается прямо сейчас продуктВремя string // Сколько осталось времени прямо сейчас кнт context.Context // контекст шахты фнОтмена func() // Функция отмены шахты } // НовШахта -- возвращает новый *Mine func НовШахта(база types.ИБаза) (*Шахта, error) { секция, ош := section.НовСекция(база.Бот(), "Шахта", `Руда
`) if ош != nil { return nil, fmt.Errorf("НовШахта(): in create *Section, err=\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", ош) } уровень, ош := static_param.НовСтатПарам("уровень") if ош != nil { return nil, fmt.Errorf("НовШахта(): при создании статистики числа добычи, ош=\n\t%w", ош) } кнт, фнОтмена := context.WithCancel(база.Кнт()) сам := &Шахта{ Секция: секция, бот: база.Бот(), база: база, руда: руда, железо: железо, сталь: сталь, свинец: свинец, продуктКол: добычаЧисло, уровень: уровень, кнт: кнт, фнОтмена: фнОтмена, } сам.сеть, ош = minenet.NewMineNet(сам) if ош != nil { return nil, fmt.Errorf("NewMine(): in create NetMine, err=\n\t%w", ош) } _ = types.ИБазаШахта(сам) return сам, nil } func (сам *Шахта) Пуск() error { go сам.пуск() return nil } // пуск -- запускает обработку шахты func (сам *Шахта) пуск() { time.Sleep(time.Second * 3) фнРабота := func() { defer time.Sleep(time.Minute * 5) счёт := 5 for счёт > 0 { if сам.шахтаЗабрать() { break } счёт-- } сам.уровеньОбновить() сам.ускорениеПровер() счёт = 5 for счёт > 0 { if сам.проапгрейдить() { break } счёт-- } сам.количествоПолучить() сам.бот.Ангар().РесурсыОбновить() сам.Сделать() } for { select { case <-сам.кнт.Done(): return case <-сам.ВремяОстат().КаналСиг(): default: log.Printf("Шахта.пуск()\n") фнРабота() } } } // Проверяет количество продукта в шахте func (сам *Шахта) количествоПолучить() { var ( ind int strOut string еслиНайдено bool режим string ) lstMine, err := сам.сеть.Клиент().Get("https://wartank.ru/buildings") if err != nil { log.Printf("Шахта.количествоПолучить(): при обновлении строк шахты, ош=\n\t%v\n", err) return } /* Режим (руда-1):
ore 1
Время (+8 строк):
ore 1
*/ for ind, strOut = range lstMine { // Руда if strings.Contains(strOut, `src="/images/icons/ore.png?2" alt="ore"`) { //
ore 1
еслиНайдено = true режим = "руда" break } } if !еслиНайдено { return } switch режим { case "руда": _число := strings.TrimPrefix(strOut, `
ore `) _число = strings.TrimSuffix(_число, `
`) iNum, err := strconv.Atoi(_число) if err != nil { log.Printf("Шахта.количествоПолучить(): кол-во руды (%v) не число, err=\n\t%v\n", _число, err) return } сам.продуктКол.Уст(iNum) сам.продуктИмя = "руда" default: } //
00:00:34
strTime := lstMine[ind+3] //
00:19:53
strTime = strings.TrimPrefix(strTime, `
`) strTime = strings.TrimSuffix(strTime, `
`) сам.продуктВремя = strTime if err := сам.Уст(alias.Время(strTime)); err != nil { log.Printf("Шахта.количествоПолучить(): при установке времени производства(%v), err=\n\t%v\n", strTime, err) } } // Проверяет на забор из шахты func (сам *Шахта) шахтаЗабрать() bool { var ( strOut string еслиНайдено bool ) списШахта, ош := сам.сеть.Клиент().Get("https://wartank.ru/buildings") if ош != nil { log.Printf("Шахта.шахтаЗабрать(): при обновлении списШахта, ош=\n\t%v\n", ош) return false } // Забрать for _, strOut = range списШахта { if strings.Contains(strOut, `.ILinkListener-buildings-0-building-rootBlock-actionPanel-takeProductionLink`) { еслиНайдено = true break } } if !еслиНайдено { return true } _ссылка := strings.TrimPrefix(strOut, `Забрать`) ссылка := "https://wartank.ru/" + _ссылка // http://wartank.ru/buildings?5-1.ILinkListener-buildings-0-building-rootBlock-actionPanel-takeProductionLink lstBase1, err := сам.сеть.Клиент().Get(ссылка) if err != nil { log.Printf("Шахта.шахтаЗабрать(): при выполнении Get-запроса 'забрать', err=\n\t%v\n", err) return false } if err = сам.СтрОбновить(lstBase1); err != nil { log.Printf("Шахта.шахтаЗабрать(): при обновлении lstMine, err=\n\t%v\n", err) return false } return true } // Проверяет ускорение строительства func (сам *Шахта) ускорениеПровер() { списСтр, ош := сам.сеть.Клиент().Get("http://wartank.ru/buildings") if ош != nil { log.Printf("Шахта.ускорениеПровер(): in make request, err=\n\t%v\n", ош) return } // Шахта - 0
var ( еслиНайти = false стр = "" ) for _, стр = range списСтр { if strings.Contains(стр, `Шахта - `) { еслиНайти = true break } } if !еслиНайти { return } } // Уровень -- возвращает уровень шахты func (сам *Шахта) Уровень() types.ИСтатПарам { return сам.уровень } // Обновляет текущий уровень шахты (может быть не построена) func (сам *Шахта) уровеньОбновить() bool { списСтр, ош := сам.сеть.Клиент().Get("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 } сам.уровень.Уст(иУровень) switch иУровень { case 0: // шахту надо построить счёт := 5 for счёт > 0 { if сам.построить(списСтр) { break } счёт-- } default: // Пробуем проапгрейдить счёт := 5 for счёт > 0 { if сам.проапгрейдить() { break } счёт-- } } return true } // Строит шахту при нулевом уровне func (сам *Шахта) построить(списСтр []string) bool { // Построить var ( еслиНайти = false стр = "" ) for _, стр = range списСтр { if strings.Contains(стр, `href="building-upgrade/Mine">Построить`) { еслиНайти = true break } } if !еслиНайти { return true } // Пробуем построить шахту _стр := strings.TrimPrefix(стр, `Построить`) ссылка := "https://wartank.ru/" + _стр списСтр, ош := сам.сеть.Клиент().Get(ссылка) 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/Mine?16-1.ILinkListener-upgradeLink-link ссылка = "https://wartank.ru/building-upgrade/" + _стр _, ош = сам.сеть.Клиент().Get(ссылка) 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) списСтр, ош = сам.сеть.Клиент().Get("https://wartank.ru/building-upgrade/Mine") 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/Mine?4-1.ILinkListener-upgradeLink-link // ссылка := "https://wartank.ru/building-upgrade/" + _стр списСтр, ош = сам.сеть.Клиент().Get(ссылка) 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" + _стр списСтр, ош = сам.сеть.Клиент().Get(ссылка) 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 (сам *Шахта) Сделать() { if ош := сам.сеть.Обновить(); ош != nil { log.Printf("ERRO Шахта.Сделать(): при обновлении lstMine, err=\n\t%v\n", ош) return } if err := сам.выбратьМеталл(); err != nil { log.Printf("ERRO Шахта.Сделать(): при выборе продукции, err=\n\t%v\n", err) return } работа := сам.СценаРежим().Работа() switch работа { case "руда": for !сам.рудаСделать() { } case "железо": for !сам.железоСделать() { } case "сталь": for !сам.стальСделать() { } case "свинец": for !сам.свинецСделать() { } default: log.Printf("ERRO Шахта.Сделать(): неизвестный режим производства, режим=%q\n", работа) } } // Свинец -- возвращает объект свинца func (сам *Шахта) Свинец() types.ИСтатПарам { return сам.свинец } // Сталь -- возвращает объект стали func (сам *Шахта) Сталь() types.ИСтатПарам { return сам.сталь } // Железо -- возвращает объект железа func (сам *Шахта) Железо() types.ИСтатПарам { return сам.железо } // Руда -- возвращает объект руды func (сам *Шахта) Руда() types.ИСтатПарам { return сам.руда } // ПродуктКолСейчас -- возвращает количество прозводимого продукта func (сам *Шахта) ПродуктКолСейчас() int { return сам.продуктКол.Получ() } // ПродуктИмяСейчас -- возвращает имя прозводимого продукта func (сам *Шахта) ПродуктИмяСейчас() string { return сам.продуктИмя } // ПродуктВремяСейчас -- сколько осталось времени до производства продукта func (сам *Шахта) ПродуктВремяСейчас() string { сам.количествоПолучить() return сам.продуктВремя // return сам.Секция.ВремяОпрос().Стр() } // Выбирает продукцию по возможности произвести и её количеству func (сам *Шахта) выбратьМеталл() error { var ( диктПродукция = make(map[string]bool) // Словарь известной продукции lstMine = сам.СписПолучить() ) фнВыбратьПродукт := func() { // вычисляет список допустимой продукции диктПродукция["руда"] = true // Руда есть всегда диктПродукция["железо"] = false диктПродукция["сталь"] = false диктПродукция["свинец"] = false for _, strProd := range lstMine { // Проверить руду if strings.Contains(strProd, `Руда
`) { диктПродукция["руда"] = true break } } for _, strProd := range lstMine { // Проверить руду if strings.Contains(strProd, `Железо
`) { диктПродукция["железо"] = true break } } for _, strProd := range lstMine { // Проверить сталь if strings.Contains(strProd, `Сталь
`) { диктПродукция["сталь"] = true break } } for _, strProd := range lstMine { // Проверить свинец if strings.Contains(strProd, `Свинец
`) { диктПродукция["свинец"] = true break } } } фнВыбратьПродукт() сам.СценаРежим().РаботаУст("руда") руда := сам.Руда().Получ() железо := сам.Железо().Получ() if диктПродукция["железо"] { if руда > железо*2 { сам.СценаРежим().РаботаУст("железо") } } сталь := сам.Сталь().Получ() if диктПродукция["сталь"] { if железо > сталь*2 { сам.СценаРежим().РаботаУст("сталь") } } свинец := сам.Свинец().Получ() if диктПродукция["свинец"] { if сталь > свинец*2 { сам.СценаРежим().РаботаУст("свинец") } } return nil } // Создаёт руду func (сам *Шахта) рудаСделать() bool { time.Sleep(time.Millisecond * 55) lstMine, err := сам.сеть.Get("https://wartank.ru/production/Mine") if err != nil { // log._rintf("ERRO Шахта.сделатьРуду(): при GET-команде 'начать производство руды', err=\n\t%v\n", err) return false } var ( инд int стрВых string strTime string strLink string strNum string еслиНайдено bool ) for инд, стрВых = range lstMine { if strings.Contains(стрВых, `Руда
`) { // Руда
strNum = lstMine[инд+1] strTime = lstMine[инд+3] strLink = lstMine[инд+10] еслиНайдено = true break } } if !еслиНайдено { return false } if !strings.Contains(strLink, `>Начать производство<`) { return true } // "Mine?16-1.ILinkListener-productions-0-production-startProduceLink\">Начать производство" // "Начать производство" _link := strings.TrimPrefix(strLink, `Начать производство") strLink = "https://wartank.ru/production/" + _link // https://wartank.ru/production/Mine?19-1.ILinkListener-productions-0-production-startProduceLink time.Sleep(time.Millisecond * 55) lstMine, err = сам.сеть.Get(strLink) if err != nil { // log._rintf("ERRO Шахта.сделатьРуду(): при GET-команде 'начать производство руды', err=\n\t%v\n", err) return false } еслиНайдено = false for инд, стрВых = range lstMine { if strings.Contains(стрВых, `>Начать производство`) { return false } } if err = сам.СтрОбновить(lstMine); err != nil { // log._rintf("ERRO Шахта.сделатьРуду(): при обновлении lstMine, err=\n\t%v\n", err) return false } if err := сам.Уст(alias.Время(strTime)); err != nil { log.Printf("ERRO Шахта.сделатьРуду(): при установке времени ожидания добычи руды(%v)\n\terr=%v\n", strTime, err) } lstNum := strings.Split(strNum, `Кол-во: `) strNum = lstNum[1] lstNum = strings.Split(strNum, `
`) strNum = lstNum[0] iNum, err := strconv.Atoi(strNum) if err != nil { // log._rintf("ERRO Шахта.сделатьРуду(): кол-во(%v) не число, err=\n\t%v\n", strNum, err) return false } сам.продуктКол.Уст(iNum) return true } // Создаёт железо func (сам *Шахта) железоСделать() bool { var ( lstMine = сам.СписПолучить() ind int strOut string strTime string strLink string strNum string еслиНайдено bool ) for ind, strOut = range lstMine { if strings.Contains(strOut, `Железо
`) { // Железо
strNum = lstMine[ind+1] // Кол-во: 1
strTime = lstMine[ind+3] // Начать производство strLink = lstMine[ind+10] еслиНайдено = true break } } if !еслиНайдено { return true } lstLink := strings.Split(strLink, `Начать производство`) strLink = "https://wartank.ru/production/" + lstLink[0] // https://wartank.ru/production/Mine?4-1.ILinkListener-productions-1-production-startProduceLink lstMine, err := сам.сеть.Get(strLink) if err != nil { // log._rintf("ERRO MineNet.makeFerrum(): при GET-команде 'начать производство железа', err=\n\t%v\n", err) return false } for _, strOut := range lstMine { // Проверка на базу if strings.Contains(strOut, `База`) { // log._rintf("ERRO MineNet.makeFerrum(): при обновлении lstMine найден lstBase") return false } } if err = сам.СтрОбновить(lstMine); err != nil { // log._rintf("ERRO MineNet.makeFerrum(): при обновлении lstMine, err=\n\t%v\n", err) return false } if err := сам.Уст(alias.Время(strTime)); err != nil { log.Printf("ERRO Mine.makeFerrum(): при установке времени производства железа(%v)\n\terr=%v\n", strTime, err) } lstNum := strings.Split(strNum, `Кол-во: `) strNum = lstNum[1] lstNum = strings.Split(strNum, `
`) strNum = lstNum[0] iNum, err := strconv.Atoi(strNum) if err != nil { // log._rintf("ERRO MineNet.makeFerrum(): кол-во(%v) не число, err=\n\t%v\n", strNum, err) return false } сам.продуктКол.Уст(iNum) return true } // Создаёт сталь func (сам *Шахта) стальСделать() bool { var ( lstMine = сам.СписПолучить() ind int strOut string strTime string strLink string strNum string еслиНайдено bool ) for ind, strOut = range lstMine { if strings.Contains(strOut, `Сталь
`) { strNum = lstMine[ind+1] strTime = lstMine[ind+3] strLink = lstMine[ind+10] еслиНайдено = true break } } if !еслиНайдено { return true } lstLink := strings.Split(strLink, `Начать производство`) strLink = "https://wartank.ru/production/" + lstLink[0] time.Sleep(time.Millisecond * 55) lstMine, err := сам.сеть.Get(strLink) if err != nil { // log._rintf("ERRO MineNet.makeSteel(): при GET-команде 'начать производство стали', err=\n\t%v\n", err) return false } for _, strOut := range lstMine { // Проверка на базу if strings.Contains(strOut, `База`) { // log._rintf("ERRO MineNet.makeSteel(): при обновлении lstMine найден lstBase") return false } } if err = сам.СтрОбновить(lstMine); err != nil { // log._rintf("ERRO MineNet.makeSteel(): при обновлении lstMine, err=\n\t%v\n", err) return false } if err := сам.Уст(alias.Время(strTime)); err != nil { log.Printf("ERRO Mine.makeSteel(): при установке времени производства железа(%v)\n\terr=%v\n", strTime, err) } lstNum := strings.Split(strNum, `Кол-во: `) strNum = lstNum[1] lstNum = strings.Split(strNum, `
`) strNum = lstNum[0] iNum, err := strconv.Atoi(strNum) if err != nil { // log._rintf("ERRO MineNet.makeSteel(): кол-во(%v) не число, err=\n\t%v\n", strNum, err) return false } сам.продуктКол.Уст(iNum) return true } // Создаёт свинец func (сам *Шахта) свинецСделать() bool { var ( lstMine = сам.СписПолучить() ind int strOut string strTime string strLink string strNum string еслиНайдено bool ) for ind, strOut = range lstMine { if strings.Contains(strOut, `Свинец
`) { strNum = lstMine[ind+1] strTime = lstMine[ind+3] strLink = lstMine[ind+10] еслиНайдено = true break } } if !еслиНайдено { return true } lstLink := strings.Split(strLink, `Начать производство`) strLink = "https://wartank.ru/production/" + lstLink[0] time.Sleep(time.Millisecond * 55) lstMine, err := сам.сеть.Get(strLink) if err != nil { // log._rintf("ERRO Шахта.сделатьСвинец(): при GET-команде 'начать производство стали', err=\n\t%v\n", err) return false } for _, strOut := range lstMine { // Проверка на базу if strings.Contains(strOut, `База`) { // log._rintf("ERRO Шахта.сделатьСвинец(): при обновлении lstMine найден lstBase") return false } } if err = сам.СтрОбновить(lstMine); err != nil { // log._rintf("ERRO Шахта.сделатьСвинец(): при обновлении lstMine, err=\n\t%v\n", err) return false } if err := сам.Уст(alias.Время(strTime)); err != nil { log.Printf("ERRO Шахта.сделатьСвинец(): при установке времени производства железа(%v)\n\terr=%v\n", strTime, err) } lstNum := strings.Split(strNum, `Кол-во: `) strNum = lstNum[1] lstNum = strings.Split(strNum, `
`) strNum = lstNum[0] iNum, err := strconv.Atoi(strNum) if err != nil { // log._rintf("ERRO Шахта.сделатьСвинец(): кол-во(%v) не число, err=\n\t%v\n", strNum, err) return false } сам.продуктКол.Уст(iNum) return true }