فهرست منبع

SVI Устрание ошибок сетевого опроса

SVI 2 سال پیش
والد
کامیت
1f58a2cd61

+ 4 - 0
pkg/components/scene_net/netclient/netclient.go

@@ -4,6 +4,7 @@ import (
 	"context"
 	"fmt"
 	"io"
+	"log"
 	"net/http"
 	"strings"
 	"sync"
@@ -47,6 +48,9 @@ func NewNetClient(botNet types.ИБотСеть) *NetClient {
 func (сам *NetClient) Get(strLink string) (lstString []string, err error) {
 	сам.block.Lock()
 	defer сам.block.Unlock()
+	// if strLink == "https://wartank.ru/production/Mine" {
+		log.Printf("NetClient.Get(): link=%v\n", strLink)
+	// }
 	ctxCancel, fnCancel := context.WithTimeout(сам.botNet.Кнт(), time.Second*10)
 	defer fnCancel()
 	defer func() { // Возможный перехват паники

+ 9 - 0
pkg/types/ibase_fuel.go

@@ -0,0 +1,9 @@
+package types
+
+// ИБазаТопливо -- база с топливом
+type ИБазаТопливо interface {
+	ИСценаСтр
+	ИБазаСтроение
+	// Топливо -- возвращает предельное количество топлива
+	Топливо() ИСтатПарам
+}

+ 5 - 7
server/serv_bots/warbot/angar/base/arsenal/arsenal.go

@@ -367,7 +367,7 @@ func (сам *Оружейная) сделать() bool {
 	{ // Контроль ремки по времени суток и минимальному количеству
 		iRemka := сам.Ремки().Получ()
 		if iRemka < 70 {
-			for сам.сделатьРемку() {
+			for !сам.сделатьРемку() {
 			}
 			return true
 		}
@@ -423,12 +423,6 @@ func (сам *Оружейная) сделатьБронебойки() bool {
 		return false
 	}
 	стрВых = lstArsenal[инд+10]
-	if стрВых == `<div class="clrb"></div>` { // Уже запущено производство
-		return false
-	}
-	if стрВых == `</div></div></div></div></div></div></div></div>` { // Уже запущено производство
-		return false
-	}
 	// Получить ссылку на бронебойные
 	lstArmor := strings.Split(стрВых, `<a class="simple-but border" href="`)
 	strLink := lstArmor[1]
@@ -539,6 +533,10 @@ func (сам *Оружейная) сделатьРемку() bool {
 		return false
 	}
 	стрВых = lstArsenal[инд+10]
+	// Если кривая строка, то надо вернуться
+	if strings.Contains(стрВых, `</div></div></div></div></div></div></div></div>`) {
+		return true
+	}
 	// Получить ссылку на ремку
 	_ссылка := strings.TrimPrefix(стрВых, `<a class="simple-but border" href="`)
 	_ссылка = strings.TrimSuffix(_ссылка, `"><span><span>Начать производство</span></span></a>`)

+ 28 - 16
server/serv_bots/warbot/angar/base/base.go

@@ -15,6 +15,7 @@ import (
 	"wartank/server/serv_bots/warbot/angar/base/arsenal"
 	"wartank/server/serv_bots/warbot/angar/base/bank"
 	"wartank/server/serv_bots/warbot/angar/base/basenet"
+	"wartank/server/serv_bots/warbot/angar/base/fuel"
 	"wartank/server/serv_bots/warbot/angar/base/market"
 	"wartank/server/serv_bots/warbot/angar/base/mine"
 	"wartank/server/serv_bots/warbot/angar/base/polygon"
@@ -33,23 +34,24 @@ const (
 // База -- объект базы
 type База struct {
 	*section.Секция
-	сеть      *basenet.BaseNet
-	арсенал   *arsenal.Оружейная
-	банк      *bank.Банк
-	полигон   *polygon.Полигон
-	шахта     *mine.Шахта
-	ранок     *market.Рынок
-	времОстат int // Сколько времени спать до опроса базы
-	блок      sync.Mutex
+	сеть         *basenet.BaseNet
+	арсенал      *arsenal.Оружейная
+	банк         *bank.Банк
+	полигон      *polygon.Полигон
+	шахта        *mine.Шахта
+	ранок        *market.Рынок
+	складТоплива *fuel.СкладТоплива
+	времОстат    int // Сколько времени спать до опроса базы
+	блок         sync.Mutex
 }
 
 // НовБаза -- возвращает новую базу бота
 func НовБаза(ангар types.ИАнгар) (*База, error) {
 	section, err := section.НовСекция(ангар.Бот(), "База", `<title>База</title>`)
 	if err != nil {
-		return nil, fmt.Errorf("NewBase(): in create ISection, err=\n\t%w", err)
+		return nil, fmt.Errorf("НовБаза(): in create ISection, err=\n\t%w", err)
 	}
-	log.Printf("NewBase(): %q\n", section.Бот().Имя())
+	log.Printf("НовБаза(): %q\n", section.Бот().Имя())
 	сам := &База{
 		Секция: section,
 	}
@@ -89,6 +91,12 @@ func НовБаза(ангар types.ИАнгар) (*База, error) {
 			return nil, fmt.Errorf("NewBase(): in create IPolygon, err=\n\t%w", err)
 		}
 	}
+	{ // Склад топлива
+		сам.складТоплива, err = fuel.НовСкладТоплива(сам)
+		if err != nil {
+			return nil, fmt.Errorf("НовБаза(): при создании склада топлива, err=\n\t%w", err)
+		}
+	}
 	return сам, nil
 }
 
@@ -125,6 +133,7 @@ func (сам *База) пуск() {
 		// case <-сам.ВремяОпрос().КаналСиг():
 		// 	фнЦикл()
 		default:
+			log.Printf("База.пуск()\n")
 			фнЦикл()
 		}
 	}
@@ -132,23 +141,26 @@ func (сам *База) пуск() {
 
 // Запускает компоненты
 func (сам *База) runComponent() error {
-	log.Printf("Base.run()\n")
+	log.Printf("Base.runComponent()\n")
 	сам.блок.Lock()
 	defer сам.блок.Unlock()
 	if err := сам.арсенал.Пуск(); err != nil {
-		return fmt.Errorf("Base.run(): in run IArsenal, err=\n\t%w", err)
+		return fmt.Errorf("Base.runComponent(): in run IArsenal, err=\n\t%w", err)
 	}
 	if err := сам.банк.Пуск(); err != nil {
-		return fmt.Errorf("Base.run(): in run IBank, err=\n\t%w", err)
+		return fmt.Errorf("Base.runComponent(): in run IBank, err=\n\t%w", err)
 	}
 	if err := сам.шахта.Пуск(); err != nil {
-		return fmt.Errorf("Base.run(): in run IMine, err=\n\t%w", err)
+		return fmt.Errorf("Base.runComponent(): in run IMine, err=\n\t%w", err)
 	}
 	if err := сам.ранок.Пуск(); err != nil {
-		return fmt.Errorf("Base.run(): in run IMarket, err=\n\t%w", err)
+		return fmt.Errorf("Base.runComponent(): in run IMarket, err=\n\t%w", err)
 	}
 	if err := сам.полигон.Пуск(); err != nil {
-		return fmt.Errorf("Base.run(): in run IPolygon, err=\n\t%w", err)
+		return fmt.Errorf("Base.runComponent(): in run IPolygon, err=\n\t%w", err)
+	}
+	if err := сам.складТоплива.Пуск(); err != nil {
+		return fmt.Errorf("Base.runComponent(): при запуске склада топлива, err=\n\t%w", err)
 	}
 	return nil
 }

+ 302 - 0
server/serv_bots/warbot/angar/base/fuel/fuel.go

@@ -0,0 +1,302 @@
+// package fuel -- склад топлива
+package fuel
+
+import (
+	"context"
+	"fmt"
+	"log"
+	"strconv"
+	"strings"
+	"time"
+
+	"wartank/pkg/section"
+	"wartank/pkg/types"
+	"wartank/server/serv_bots/warbot/angar/base/fuel/fuel_net"
+	"wartank/server/serv_bots/warbot/tank/tankstat/static_param"
+)
+
+// СкладТоплива -- склад топлива
+type СкладТоплива struct {
+	*section.Секция
+	сеть         *fuel_net.ТопливоСеть
+	бот          types.ИБот
+	база         types.ИБаза
+	топливо      types.ИСтатПарам
+	уровень      types.ИСтатПарам
+	продуктВремя string          // Сколько осталось времени прямо сейчас
+	кнт          context.Context // контекст шахты
+	фнОтмена     func()          // Функция отмены шахты
+}
+
+// НовТопливо -- возвращает новой склад топлива
+func НовСкладТоплива(база types.ИБаза) (*СкладТоплива, error) {
+	секция, ош := section.НовСекция(база.Бот(), "Склад_топлива", `<span class="green2">Склад топлива - `)
+	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", ош)
+	}
+	кнт, фнОтмена := context.WithCancel(база.Кнт())
+	сам := &СкладТоплива{
+		Секция:   секция,
+		бот:      база.Бот(),
+		база:     база,
+		топливо:  топливо,
+		кнт:      кнт,
+		фнОтмена: фнОтмена,
+		уровень:  уровень,
+	}
+
+	сам.сеть, ош = fuel_net.НовТопливоСеть(сам)
+	if ош != nil {
+		return nil, fmt.Errorf("NewMine(): in create *ТопливоСеть, err=\n\t%w", ош)
+	}
+	_ = types.ИБазаТопливо(сам)
+	return сам, nil
+}
+
+func (сам *СкладТоплива) Пуск() error {
+	go сам.пуск()
+	return nil
+}
+
+// пуск -- запускает обработку шахты
+func (сам *СкладТоплива) пуск() {
+	time.Sleep(time.Second * 3)
+	фнРабота := func() {
+		defer time.Sleep(time.Minute * 30)
+		for !сам.уровеньОбновить() {
+		}
+		сам.ускорениеПровер()
+		сам.количествоПолучить()
+	}
+	for {
+		select {
+		case <-сам.кнт.Done():
+			return
+		case <-сам.ВремяОстат().КаналСиг():
+		default:
+			log.Printf("СкладТоплива.пуск()\n")
+			фнРабота()
+		}
+	}
+}
+
+// Проверяет количество продукта в шахте
+func (сам *СкладТоплива) количествоПолучить() {
+	var (
+		strOut      string
+		еслиНайдено bool
+	)
+	lstMine, err := сам.сеть.Клиент().Get("https://wartank.ru/buildings")
+	if err != nil {
+		log.Printf("СкладТоплива.количествоПолучить(): при обновлении строк шахты, ош=\n\t%v\n", err)
+		return
+	}
+	/*
+		<img class="ico vm" src="/images/icons/fuel.png?2" alt="Топливо" title="Топливо"> 720
+	*/
+	for _, strOut = range lstMine {
+		if strings.Contains(strOut, `src=" alt="Топливо" title="Топливо"`) {
+			еслиНайдено = true
+			break
+		}
+	}
+	if !еслиНайдено {
+		return
+	}
+	_число := strings.TrimPrefix(strOut, `<img class="ico vm" src="/images/icons/fuel.png?2" alt="Топливо" title="Топливо"> `)
+	iNum, err := strconv.Atoi(_число)
+	if err != nil {
+		log.Printf("СкладТоплива.количествоПолучить(): кол-во топлива (%v) не число, err=\n\t%v\n", _число, err)
+		return
+	}
+	сам.топливо.Уст(iNum)
+}
+
+// Проверяет ускорение строительства
+func (сам *СкладТоплива) ускорениеПровер() {
+	списСтр, ош := сам.сеть.Клиент().Get("http://wartank.ru/buildings")
+	if ош != nil {
+		log.Printf("СкладТоплива.ускорениеПровер(): in make request, err=\n\t%v\n", ош)
+		return
+	}
+	// <span class="green2">Склад топлива -
+	var (
+		еслиНайти = false
+		стр       = ""
+	)
+	for _, стр = range списСтр {
+		if strings.Contains(стр, `<span class="green2">Склад топлива - `) {
+			еслиНайти = true
+			break
+		}
+	}
+	if !еслиНайти {
+		return
+	}
+}
+
+// Обновляет текущий уровень шахты (может быть не построена)
+func (сам *СкладТоплива) уровеньОбновить() bool {
+	списСтр, ош := сам.сеть.Клиент().Get("http://wartank.ru/buildings")
+	if ош != nil {
+		log.Printf("СкладТоплива.уровеньОбновить(): in make request, err=\n\t%v\n", ош)
+		return false
+	}
+	// <span class="green2">Склад топлива -
+	var (
+		еслиНайти = false
+		стр       = ""
+	)
+	for _, стр = range списСтр {
+		if strings.Contains(стр, `<span class="green2">Склад топлива - `) {
+			еслиНайти = true
+			break
+		}
+	}
+	if !еслиНайти {
+		return false
+	}
+	// <span class="green2">Склад топлива - 0</span><br/>
+	_стр := strings.TrimPrefix(стр, `<span class="green2">Склад топлива - `)
+	_стр = strings.TrimSuffix(_стр, `</span><br/>`)
+	иУровень, ош := strconv.Atoi(_стр)
+	if ош != nil {
+		log.Printf("СкладТоплива.уровеньОбновить(): строка уровня сбойная, стр=%q, ош=\n\t%v\n", стр, ош)
+		return false
+	}
+	сам.уровень.Уст(иУровень)
+	if иУровень == 0 { // склад топлива надо построить
+		for !сам.построить() {
+		}
+	}
+	return true
+}
+
+// Строит шахту при нулевом уровне
+func (сам *СкладТоплива) построить() bool {
+	time.Sleep(time.Millisecond * 1000)
+	// <td style="width:50%;padding-left:1px;"><a class="simple-but border mb5" href="building-upgrade/FuelStorage"><span><span>Построить</span></span></a></td>
+	var (
+		еслиНайти = false
+		списСтр   []string
+		стр       = ""
+		ош        error
+	)
+	фнКупить := func() bool {
+		defer time.Sleep(time.Millisecond * 1000)
+		списСтр, ош = сам.сеть.Клиент().Get("https://wartank.ru/building-upgrade/FuelStorage")
+		if ош != nil {
+			log.Printf("СкладТоплива.построить().фнКупить(): при GET-команде 'купить постройку склада топлива', err=\n\t%v\n", ош)
+			return false
+		}
+		for _, стр = range списСтр {
+			// <a class="simple-but border mb5" href="FuelStorage?71-1.ILinkListener-upgradeLink-link">
+			if strings.Contains(стр, `ILinkListener-upgradeLink-link`) {
+				еслиНайти = true
+				break
+			}
+		}
+		if !еслиНайти {
+			return true
+		}
+		// Пробуем построить шахту
+		_стр := strings.TrimPrefix(стр, "<a class=\"simple-but border mb5\" href=\"")
+		_стр = strings.TrimSuffix(_стр, "\">")
+		// https://wartank.ru/building-upgrade/FuelStorage?49-1.ILinkListener-upgradeLink-link
+		// <a class="simple-but border mb5" href="FuelStorage?50-1.ILinkListener-upgradeLink-link">
+		// https://wartank.ru/building-upgrade/FuelStorage?72-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 списСтр {
+			// <a class="simple-but border w50 mXa mb10" w:id="confirmLink" href="../wicket/page?5-1.ILinkListener-confirmLink"><span><span>да, подтверждаю</span></span></a>
+			if strings.Contains(стр, `ILinkListener-confirmLink`) {
+				еслиНайти = true
+				break
+			}
+		}
+		if !еслиНайти {
+			return true
+		}
+		// Пробуем построить шахту
+		_стр := strings.TrimPrefix(стр, `<a class="simple-but border w50 mXa mb10" w:id="confirmLink" href="..`)
+		_стр = strings.TrimSuffix(_стр, `"><span><span>да, подтверждаю</span></span></a>`)
+		// https://wartank.ru/wicket/page?4-1.ILinkListener-confirmLink
+		// <a class="simple-but border mb5" href="FuelStorage?50-1.ILinkListener-upgradeLink-link">
+		ссылка := "https://wartank.ru" + _стр
+		списСтр, ош = сам.сеть.Клиент().Get(ссылка)
+		if ош != nil {
+			log.Printf("СкладТоплива.построить().фнПодтверждение(): при GET-команде 'подтвердить постройку склада топлива', err=\n\t%v\n", ош)
+			return false
+		}
+		// Проверить, что постройка состоялась
+		for _, стр := range списСтр {
+			if strings.Contains(стр, "<title>Вы сделали слишком большую паузу</title>") {
+				log.Printf("СкладТоплива.построить().фнПодтверждение(): подтверждение покупка склада топлива не прошла\n\tlink=%v\n\tстр=\n\t%v\n", ссылка, стр)
+				return false // Покупка не оплачена
+			}
+		}
+		log.Printf("+++++СкладТоплива.построить().фнПодтверждение(): подтверждение покупка склада топлива прошла\n")
+		return true
+	}
+
+	фнКомплекс := func() {
+		for {
+			if фнКупить() {
+				if фнПодтверждение() {
+					break
+				}
+			}
+		}
+	}
+	фнКомплекс()
+	return true
+}
+
+// Уровень -- возвращает уровень топливного склада
+func (сам *СкладТоплива) Уровень() types.ИСтатПарам {
+	return сам.уровень
+}
+
+// Тоаливо -- возвращает топливо
+func (сам *СкладТоплива) Топливо() types.ИСтатПарам {
+	return сам.топливо
+}
+
+// ПродуктКолСейчас -- возвращает кол-во продукта прямо сейчас
+func (сам *СкладТоплива) ПродуктКолСейчас() int {
+	return сам.топливо.Получ()
+}
+
+// ПродуктИмяСейчас -- возвращает имя продукта прямо сейчас
+func (сам *СкладТоплива) ПродуктИмяСейчас() string {
+	return "топливо"
+}
+
+// ПродуктВремяСейчас -- возвращает сколько осталось времени прямо сейчас
+func (сам *СкладТоплива) ПродуктВремяСейчас() string {
+	return сам.продуктВремя
+}

+ 25 - 0
server/serv_bots/warbot/angar/base/fuel/fuel_net/fuel_net.go

@@ -0,0 +1,25 @@
+// package fuel_net -- склад топлива
+package fuel_net
+
+import (
+	"fmt"
+	"wartank/pkg/components/scene_net"
+	"wartank/pkg/types"
+)
+
+// ТопливоСеть -- опрашивает склад топлива на базе
+type ТопливоСеть struct {
+	*scene_net.СценаСеть
+}
+
+// НовТопливоСеть -- возвращает новый склад топлива
+func НовТопливоСеть(складТоплива types.ИБазаТопливо) (*ТопливоСеть, error) {
+	sectionNet, err := scene_net.НовСекцияСеть(складТоплива, "https://wartank.ru/fuelStore")
+	if err != nil {
+		return nil, fmt.Errorf("НовТопливоСеть(): при создании *Топливо сеть, ош=\n\t%w", err)
+	}
+	сам := &ТопливоСеть{
+		СценаСеть: sectionNet,
+	}
+	return сам, nil
+}

+ 13 - 11
server/serv_bots/warbot/angar/base/mine/mine.go

@@ -100,7 +100,8 @@ func (сам *Шахта) пуск() {
 	time.Sleep(time.Second * 3)
 	фнРабота := func() {
 		defer time.Sleep(time.Minute * 5)
-		сам.шахтаЗабрать()
+		for !сам.шахтаЗабрать() {
+		}
 		сам.уровеньОбновить()
 		сам.Сделать()
 		сам.ускорениеПровер()
@@ -177,7 +178,7 @@ func (сам *Шахта) количествоПолучить() {
 }
 
 // Проверяет на забор из шахты
-func (сам *Шахта) шахтаЗабрать() {
+func (сам *Шахта) шахтаЗабрать() bool {
 	var (
 		strOut      string
 		еслиНайдено bool
@@ -185,7 +186,7 @@ func (сам *Шахта) шахтаЗабрать() {
 	списШахта, ош := сам.сеть.Клиент().Get("https://wartank.ru/buildings")
 	if ош != nil {
 		log.Printf("Шахта.шахтаЗабрать(): при обновлении списШахта, ош=\n\t%v\n", ош)
-		return
+		return false
 	}
 	// <a class="simple-but border" href="buildings?35-1.ILinkListener-buildings-0-building-rootBlock-actionPanel-takeProductionLink"><span><span>Забрать</span></span></a>
 	for _, strOut = range списШахта {
@@ -195,7 +196,7 @@ func (сам *Шахта) шахтаЗабрать() {
 		}
 	}
 	if !еслиНайдено {
-		return
+		return true
 	}
 	_ссылка := strings.TrimPrefix(strOut, `<a class="simple-but border" href="`)
 	_ссылка = strings.TrimSuffix(_ссылка, `"><span><span>Забрать</span></span></a>`)
@@ -204,12 +205,13 @@ func (сам *Шахта) шахтаЗабрать() {
 	lstBase1, err := сам.сеть.Клиент().Get(ссылка)
 	if err != nil {
 		log.Printf("Шахта.шахтаЗабрать(): при выполнении Get-запроса 'забрать', err=\n\t%v\n", err)
-		return
+		return false
 	}
 	if err = сам.СтрОбновить(lstBase1); err != nil {
 		log.Printf("Шахта.шахтаЗабрать(): при обновлении lstMine, err=\n\t%v\n", err)
-		return
+		return false
 	}
+	return true
 }
 
 // Проверяет ускорение строительства
@@ -276,7 +278,7 @@ func (сам *Шахта) уровеньОбновить() bool {
 	return true
 }
 
-// Строит шахту принулевом уровне
+// Строит шахту при нулевом уровне
 func (сам *Шахта) построить(списСтр []string) {
 	// <td style="width:50%;padding-left:1px;"><a class="simple-but border mb5" href="building-upgrade/Mine"><span><span>Построить</span></span></a></td>
 	var (
@@ -485,7 +487,7 @@ func (сам *Шахта) рудаСделать() bool {
 		return false
 	}
 	if !strings.Contains(strLink, `>Начать производство<`) {
-		return false
+		return true
 	}
 	// "Mine?16-1.ILinkListener-productions-0-production-startProduceLink\"><span><span>Начать производство</span></span></a>"
 	// "<a class=\"simple-but border\" href=\"Mine?16-1.ILinkListener-productions-0-production-startProduceLink\"><span><span>Начать производство</span></span></a>"
@@ -549,7 +551,7 @@ func (сам *Шахта) железоСделать() bool {
 		return false
 	}
 	if !strings.Contains(strLink, `>Начать производство<`) {
-		return false
+		return true
 	}
 	lstLink := strings.Split(strLink, `<a class="simple-but border" href="`)
 	strLink = lstLink[1]
@@ -611,7 +613,7 @@ func (сам *Шахта) стальСделать() bool {
 		return false
 	}
 	if !strings.Contains(strLink, `>Начать производство<`) {
-		return false
+		return true
 	}
 	lstLink := strings.Split(strLink, `<a class="simple-but border" href="`)
 	strLink = lstLink[1]
@@ -673,7 +675,7 @@ func (сам *Шахта) свинецСделать() bool {
 		return false
 	}
 	if !strings.Contains(strLink, `>Начать производство<`) {
-		return false
+		return true
 	}
 	lstLink := strings.Split(strLink, `<a class="simple-but border" href="`)
 	strLink = lstLink[1]