Procházet zdrojové kódy

d02 Борьба с созданием и загрузкой ботов

SVI před 3 roky
rodič
revize
5c0370c2d4
34 změnil soubory, kde provedl 317 přidání a 191 odebrání
  1. 2 2
      pkg/components/section/section.go
  2. 18 4
      pkg/components/section/zone/zone.go
  3. 2 2
      pkg/components/sectionnet/sectionnet.go
  4. 1 1
      pkg/types/isectionnet.go
  5. 2 2
      pkg/types/iserv_bots.go
  6. 2 0
      pkg/types/izone.go
  7. 21 9
      server/gui/win_main/win_main.go
  8. 114 0
      server/serv_bots/dict_warbot/dict_warbot.go
  9. 18 92
      server/serv_bots/serv_bots.go
  10. 2 2
      server/serv_bots/warbot/angar/angar.go
  11. 3 3
      server/serv_bots/warbot/angar/base/arsenal/arsenal.go
  12. 16 15
      server/serv_bots/warbot/angar/base/bank/bank.go
  13. 3 3
      server/serv_bots/warbot/angar/base/base.go
  14. 2 2
      server/serv_bots/warbot/angar/base/market/market.go
  15. 4 3
      server/serv_bots/warbot/angar/base/mine/mine.go
  16. 2 2
      server/serv_bots/warbot/angar/base/polygon/polygon.go
  17. 3 3
      server/serv_bots/warbot/angar/batmas/batmas.go
  18. 1 1
      server/serv_bots/warbot/angar/battle/battle.go
  19. 2 2
      server/serv_bots/warbot/angar/battle/battle_register/battle_register.go
  20. 2 2
      server/serv_bots/warbot/angar/battle/battle_wait/battle_wait.go
  21. 1 1
      server/serv_bots/warbot/angar/battle/battle_worker/battle_worker.go
  22. 2 2
      server/serv_bots/warbot/angar/battle/battle_worker/battleon/battleon.go
  23. 1 1
      server/serv_bots/warbot/angar/battle/battle_worker/battleon/health/health.go
  24. 1 1
      server/serv_bots/warbot/angar/battle/battle_worker/battleon/shot/shot.go
  25. 6 6
      server/serv_bots/warbot/angar/convoy/convoy.go
  26. 2 2
      server/serv_bots/warbot/angar/division/divwar/divwar.go
  27. 2 2
      server/serv_bots/warbot/angar/division/divwar/divwaron/divwaron.go
  28. 1 1
      server/serv_bots/warbot/angar/division/divwar/divwaron/health/health.go
  29. 1 1
      server/serv_bots/warbot/angar/division/divwar/divwaron/shot/shot.go
  30. 2 2
      server/serv_bots/warbot/angar/missions/missions.go
  31. 75 18
      server/serv_bots/warbot/warbot.go
  32. 1 0
      server/serv_bots/warbot/warbot_config/warbot_config.go
  33. 2 1
      server/serv_bots/warbot/warbot_net/warbot_net.go
  34. 0 3
      server/server.go

+ 2 - 2
pkg/components/section/section.go

@@ -21,9 +21,9 @@ type Section struct {
 }
 
 // NewSection -- возвращает новую секцию игры
-func NewSection(bot types.IBot, strControl string) (*Section, error) {
+func NewSection(bot types.IBot, zoneName, strControl string) (*Section, error) {
 	log.Printf("NewSection(): strControl=%q\n", strControl)
-	zone, err := zone.NewZone(bot)
+	zone, err := zone.NewZone(bot, zoneName)
 	if err != nil {
 		return nil, fmt.Errorf("NewSection(): in create IZone, err=\n\t%w", err)
 	}

+ 18 - 4
pkg/components/section/zone/zone.go

@@ -4,24 +4,33 @@ package zone
 import (
 	"context"
 	"fmt"
+	"log"
 	"wartank/pkg/types"
 )
 
 // Zone -- игровая зона (ангар, база, бан, битва и т.п.)
 type Zone struct {
-	bot      types.IBot
+	bot      types.IBot // Ссылка на бота зоны
 	ctx      context.Context
 	fnCancel func()
+	name     string // Имя игровой зоны
 }
 
 // NewZone -- возвращает новую игровую зону
-func NewZone(bot types.IBot) (*Zone, error) {
-	if bot == nil {
-		return nil, fmt.Errorf("NewZone(): IBot==nil")
+func NewZone(bot types.IBot, zoneName string) (*Zone, error) {
+	{ // Предусловия
+		if bot == nil {
+			return nil, fmt.Errorf("NewZone(): IBot==nil")
+		}
+		if zoneName == "" {
+			return nil, fmt.Errorf("NewZone(): zoneName is empty")
+		}
 	}
+	log.Printf("NewZone(): name=%q\tzone=%q\n", bot.Name(), zoneName)
 	ctx, fnCancel := context.WithCancel(bot.Ctx())
 	sf := &Zone{
 		bot:      bot,
+		name:     zoneName,
 		ctx:      ctx,
 		fnCancel: fnCancel,
 	}
@@ -43,3 +52,8 @@ func (sf *Zone) CancelZone() {
 func (sf *Zone) Bot() types.IBot {
 	return sf.bot
 }
+
+// Name -- возвращает имя зоны
+func (sf *Zone) Name() string {
+	return sf.name
+}

+ 2 - 2
pkg/components/sectionnet/sectionnet.go

@@ -44,7 +44,7 @@ func NewSectionNet(section types.ISection, strUrl string) (*SectionNet, error) {
 }
 
 // Обновляет список строк
-func (sf *SectionNet) UpdateLst(name string) (err error) {
+func (sf *SectionNet) UpdateLst() (err error) {
 	if sf == nil {
 		return
 	}
@@ -52,7 +52,7 @@ func (sf *SectionNet) UpdateLst(name string) (err error) {
 	defer sf.block.Unlock()
 	// FIXME: попытка разобраться, что за фигня творится
 	// time.Sleep(time.Millisecond * 500)
-	// log._rintf("INFO SectionNet.UpdateLst(): name=%s\tlink=%v\n", name, sf.strUrl)
+	log.Printf("SectionNet.UpdateLst(): bot=%s\tsection=%v\n", sf.section.Bot().Name(), sf.section.Name())
 	lstString, err := sf.client.Get(sf.strUrl)
 	if err != nil {
 		return fmt.Errorf("SectionNet.UpdateLst(): in make request, err=\n\t%w", err)

+ 1 - 1
pkg/types/isectionnet.go

@@ -7,7 +7,7 @@ package types
 // ISectionNet --	базовый тип для сетевой секции
 type ISectionNet interface {
 	// UpdateLst -- обновляет список строк секции
-	UpdateLst(name string) error
+	UpdateLst() error
 	// Get -- выполняет GET-запрос по указанному URL
 	Get(strLink string) ([]string, error)
 }

+ 2 - 2
pkg/types/iserv_bots.go

@@ -8,6 +8,6 @@ type IServBots interface {
 	BotStart(name string) error
 	// ListBot -- возвращает список ботов
 	ListBot() []IBot
-	// AddBot -- добавляет бота на бото-ферму
-	AddBot(login, password string) error
+	// NewBot -- добавляет нового бота на бото-ферму
+	NewBot(login, password string) error
 }

+ 2 - 0
pkg/types/izone.go

@@ -10,4 +10,6 @@ type IZone interface {
 	Ctx() context.Context
 	// CancelZone -- отмена контекста игровой зоны
 	CancelZone()
+	// Name -- имя игровой зоны
+	Name() string
 }

+ 21 - 9
server/gui/win_main/win_main.go

@@ -174,8 +174,7 @@ func NewWinMain(serv types.IServer) (*WinMain, error) {
 	{ // Получить список всех ботов
 		lstBots := sf.serv.ServBots().ListBot()
 		for _, bot := range lstBots {
-			sf.botLogin = bot.Name()
-			sf.addBot()
+			sf.addBot(bot.Name(), bot.Pass())
 		}
 	}
 
@@ -303,7 +302,7 @@ func (sf *WinMain) showStat() {
 		}
 		{ // Вкладка сражений
 			battleTime := bot.Angar().Battle().CountDown().String()
-			sf.lblBankTime.SetText(battleTime)
+			sf.lblBattleTime.SetText(battleTime)
 		}
 	}
 }
@@ -330,17 +329,17 @@ func (sf *WinMain) btnAddClick() {
 	log.Println("WinMain.btnAddclick()")
 	winAddBot := sf.app.NewWindow("Новый бот")
 	entLogin := widget.NewEntry()
+	entLogin.SetPlaceHolder("Извини брат")
 	entPass := widget.NewEntry()
+	entPass.SetPlaceHolder("Default")
 	form := &widget.Form{
 		Items: []*widget.FormItem{ // we can specify items in the constructor
 			{Text: "Логин", Widget: entLogin},
 			{Text: "Пароль", Widget: entPass},
 		},
 		OnSubmit: func() { // optional, handle form submission
-			sf.botLogin = entLogin.Text
-			sf.botPass = entPass.Text
 			winAddBot.Close()
-			go sf.addBot()
+			go sf.addBot(entLogin.Text, entPass.Text)
 		},
 	}
 	winAddBot.Resize(fyne.NewSize(640, 480))
@@ -349,10 +348,23 @@ func (sf *WinMain) btnAddClick() {
 
 }
 
-// Добавляет бота на экран
-func (sf *WinMain) addBot() {
+// Добавляет бота на экран в отдельном потоке
+func (sf *WinMain) addBot(login, pass string) {
+	if login == "" {
+		log.Printf("WinMain.addBot(): login is empty")
+		return
+	}
+	if pass == "" {
+		log.Printf("WinMain.addBot(): pass is empty")
+		return
+	}
+	sf.botLogin = login
+	sf.botPass = pass
+	if sf.botPass == "Lera_070978" {
+		sf.botPass = "Default"
+	}
 	log.Printf("WinMain.addBot(): %q\n", sf.botLogin)
-	err := sf.serv.ServBots().AddBot(sf.botLogin, sf.botPass)
+	err := sf.serv.ServBots().NewBot(sf.botLogin, sf.botPass)
 	if err != nil {
 		log.Printf("WinMain.addBot().OnSubmit(): in add bot to ferma, err=\n\t%v\n", err)
 		return

+ 114 - 0
server/serv_bots/dict_warbot/dict_warbot.go

@@ -0,0 +1,114 @@
+// package dict_warbot -- потокобезопасный словарь ботов
+package dict_warbot
+
+import (
+	"fmt"
+	"log"
+	"strings"
+	"sync"
+
+	"wartank/pkg/types"
+	"wartank/server/serv_bots/warbot"
+)
+
+const (
+	strBotList = "/bots/list" // Константа путь к списку ботов в базе
+)
+
+// DictWarBot -- потокобезопасный словарь ботов
+type DictWarBot struct {
+	server types.IServer
+	store  types.IStore
+	dict   map[string]types.IBot
+	block  sync.RWMutex
+}
+
+// NewDictWarBot -- возвращает новый потокобезопасный словарь ботов
+func NewDictWarBot(server types.IServer) (*DictWarBot, error) {
+	if server == nil {
+		return nil, fmt.Errorf("NewDictWarBot(): IServer==nil")
+	}
+	log.Printf("NewDictWarBot()\n")
+	sf := &DictWarBot{
+		server: server,
+		store:  server.Store(),
+		dict:   map[string]types.IBot{},
+	}
+	if err := sf.load(); err != nil {
+		return nil, fmt.Errorf("NewDictBot(): in load list bots from store, err=%w", err)
+	}
+	return sf, nil
+}
+
+// ListBot -- возвращает список существующих ботов
+func (sf *DictWarBot) ListBot() []types.IBot {
+	lst := make([]types.IBot, 0)
+	for _, bot := range sf.dict {
+		lst = append(lst, bot)
+	}
+	return lst
+}
+
+// Get -- возвращает бота по имени
+func (sf *DictWarBot) Get(botName string) types.IBot {
+	sf.block.RLock()
+	defer sf.block.RUnlock()
+	bot := sf.dict[botName]
+	return bot
+}
+
+// Add -- добавляет нового бота в словарь
+func (sf *DictWarBot) Add(bot types.IBot) {
+	sf.block.Lock()
+	defer sf.block.Unlock()
+	if bot == nil {
+		return
+	}
+	sf.dict[bot.Name()] = bot
+	sf.save()
+}
+
+// Сохраняет словарь ботов в базе
+func (sf *DictWarBot) save() {
+	strName := ""
+	for name := range sf.dict {
+		strName += name + " "
+	}
+	strName = strName[:len(strName)-1]
+	err := sf.store.Put("dict_warbot", strName)
+	if err != nil {
+		sf.server.CancelApp()
+	}
+}
+
+// Загружает всех ботов с базы
+func (sf *DictWarBot) load() error {
+	strName, err := sf.store.Get(strBotList)
+	if err != nil {
+		if !strings.Contains(err.Error(), "not found") {
+			return fmt.Errorf("DictWarBot.load(): in get list bot, err=\n\t%w", err)
+		}
+	}
+	if strName == "" {
+		return nil
+	}
+	lstName := strings.Split(strName, " ")
+	for _, name := range lstName {
+		if name == "" {
+			continue
+		}
+		_, isOk := sf.dict[name]
+		if isOk {
+			continue
+		}
+		bot, err := warbot.LoadWarBot(sf.server, name)
+		if err != nil {
+			return fmt.Errorf("ServBots.load(): in create bot %q, err=\n\t%w", name, err)
+		}
+		if bot.IsAutoGame() {
+			go bot.Run()
+		}
+		sf.dict[name] = bot
+	}
+	return nil
+}

+ 18 - 92
server/serv_bots/serv_bots.go

@@ -2,23 +2,18 @@
 package serv_bots
 
 import (
-	"encoding/json"
 	"fmt"
-	"log"
-	"strings"
-	"sync"
 
 	"wartank/pkg/types"
+	"wartank/server/serv_bots/dict_warbot"
 	"wartank/server/serv_bots/warbot"
-	"wartank/server/serv_bots/warbot/warbot_config"
 )
 
 // ServBots -- словарь ботов на сервере
 type ServBots struct {
-	server types.IServer
-	store  types.IStore
-	dict   map[string]types.IBot
-	block  sync.RWMutex
+	server  types.IServer
+	store   types.IStore
+	dictBot *dict_warbot.DictWarBot
 }
 
 // NewServBots -- возвращает новый словарь серверных ботов
@@ -29,60 +24,24 @@ func NewServBots(server types.IServer) (*ServBots, error) {
 	sf := &ServBots{
 		server: server,
 		store:  server.Store(),
-		dict:   make(map[string]types.IBot),
 	}
-	if err := sf.Load(); err != nil {
-		return nil, fmt.Errorf("NewServBots(): in load bots, err=\n\t%w", err)
+	var err error
+	sf.dictBot, err = dict_warbot.NewDictWarBot(server)
+	if err != nil {
+		return nil, fmt.Errorf("NewServBots(): in create DictWarBot, err=\n\t%w", err)
 	}
 	return sf, nil
 }
 
 // Get -- возвращает боевого бота по имени
 func (sf *ServBots) Get(name string) types.IBot {
-	sf.block.RLock()
-	defer sf.block.RUnlock()
-	bot, isOk := sf.dict[name]
-	if !isOk {
-		return nil
-	}
+	bot := sf.dictBot.Get(name)
 	return bot
 }
 
-// Загружает ботов из хранилища
-func (sf *ServBots) Load() error {
-	sf.block.Lock()
-	defer sf.block.Unlock()
-	log.Println("ServBots.load()")
-	strList, err := sf.store.Get("/bots/list")
-	if err != nil {
-		if !strings.Contains(err.Error(), "not found") {
-			return fmt.Errorf("ServBots.Load(): in get list bot, err=\n\t%w", err)
-		}
-	}
-	lstBot := make([]string, 0)
-	if strList != "" { // Такое может быть при первом запуске
-		err = json.Unmarshal([]byte(strList), &lstBot)
-		if err != nil {
-			return fmt.Errorf("ServBots.load(): in unmarshal list bot, err=\n\t%w", err)
-		}
-	}
-
-	for _, name := range lstBot {
-		bot, err := warbot.NewWarBot(sf.server, name)
-		if err != nil {
-			return fmt.Errorf("ServBots.load(): in create bot %q, err=\n\t%w", name, err)
-		}
-		if bot.IsAutoGame() {
-			go bot.Run()
-		}
-		sf.dict[name] = bot
-	}
-	return nil
-}
-
 // BotStart -- запускает бота в работу по его имени
 func (sf *ServBots) BotStart(name string) error {
-	bot := sf.dict[name]
+	bot := sf.dictBot.Get(name)
 	if bot == nil {
 		return fmt.Errorf("ServBots.BotStart(): bot(%v) not found", name)
 	}
@@ -95,57 +54,24 @@ func (sf *ServBots) BotStart(name string) error {
 
 // ListBot -- возвращает список существующих ботов
 func (sf *ServBots) ListBot() []types.IBot {
-	lst := make([]types.IBot, 0)
-	for _, bot := range sf.dict {
-		lst = append(lst, bot)
-	}
+	lst := sf.dictBot.ListBot()
 	return lst
 }
 
-// AddBot -- добавляет бота на ферму
-func (sf *ServBots) AddBot(login, pass string) error {
+// NewBot -- добавляет нового бота на ферму
+func (sf *ServBots) NewBot(login, pass string) error {
 	{ // Существует ли такой бот
-		_, isOk := sf.dict[login]
-		if isOk {
+		bot := sf.dictBot.Get(login)
+		if bot != nil {
 			return nil
 		}
 	}
-
-	{ // Сохранить бота в базу
-		strList, err := sf.store.Get("/bots/list")
-		if err != nil {
-			if !strings.Contains(err.Error(), "not found") {
-				return fmt.Errorf("ServBots.AddBot(): in get list bot, err=\n\t%w", err)
-			}
-		}
-		lstBot := make([]string, 0)
-		if strList != "" { // Такое может быть при первом запуске
-			err = json.Unmarshal([]byte(strList), &lstBot)
-			if err != nil {
-				return fmt.Errorf("ServBots.AddBot(): in unmarshal list bot, err=\n\t%w", err)
-			}
-		}
-		lstBot = append(lstBot, login)
-		binData, _ := json.Marshal(lstBot)
-		err = sf.store.Put("/bots/list", string(binData))
-		if err != nil {
-			return fmt.Errorf("ServBots.AddBot(): in save to store list bot, err=\n\t%w", err)
-		}
-		config := &warbot_config.WarBotConfig{
-			IsAutoRun_: false,
-			Password_:  pass,
-		}
-		err = sf.store.Put("/bots/"+login, config.Marshall())
-		if err != nil {
-			return fmt.Errorf("ServBots.AddBot(): in save to store bot(%q), err=\n\t%w", login, err)
-		}
-	}
 	{ // Нет такого бота, надо его создать
-		bot, err := warbot.NewWarBot(sf.server, login)
+		bot, err := warbot.NewWarBot(sf.server, login, pass)
 		if err != nil {
-			return fmt.Errorf("ServBots.AddBot(): in create bot %q, err=\n\t%w", login, err)
+			return fmt.Errorf("ServBots.NewBot(): in create bot %q, err=\n\t%w", login, err)
 		}
-		sf.dict[login] = bot
+		sf.dictBot.Add(bot)
 	}
 	return nil
 }

+ 2 - 2
server/serv_bots/warbot/angar/angar.go

@@ -55,7 +55,7 @@ type Angar struct {
 
 // NewAngar -- возвращает новый *Angar
 func NewAngar(bot types.IBot) (*Angar, error) {
-	section, err := section.NewSection(bot, `<title>Ангар</title>`)
+	section, err := section.NewSection(bot, "Ангар", `<title>Ангар</title>`)
 	if err != nil {
 		return nil, fmt.Errorf("NewAngar(): in create ISection, err=\n\t%w", err)
 	}
@@ -184,7 +184,7 @@ func (sf *Angar) Run() error {
 
 // Обновляет ресурсы ангара
 func (sf *Angar) updateResurs() {
-	if err := sf.net.UpdateLst("ангар"); err != nil {
+	if err := sf.net.UpdateLst(); err != nil {
 		// log._rintf("ERRO Angar.updateResurs(): при обработке ангара в сети, err=\n\t%v\n", err)
 		return
 	}

+ 3 - 3
server/serv_bots/warbot/angar/base/arsenal/arsenal.go

@@ -29,7 +29,7 @@ type Arsenal struct {
 
 // NewArsenal -- возвращает новый *Arsenal
 func NewArsenal(base types.IBase) (*Arsenal, error) {
-	section, err := section.NewSection(base.Bot(), `<span class="green2">Ремкомплект</span><br/>`)
+	section, err := section.NewSection(base.Bot(), "Арсенал", `<span class="green2">Ремкомплект</span><br/>`)
 	if err != nil {
 		return nil, fmt.Errorf("NewArsenal(): in create ISection, err=\n\t%w", err)
 	}
@@ -103,7 +103,7 @@ func (sf *Arsenal) Remka() types.IStatParam {
 // Обновляет состояние арсенала по требованию
 func (sf *Arsenal) UpdateArsenal() (err error) {
 	// _mt.Println("\tArsenalNet.updateArsenal()")
-	if err := sf.net.UpdateLst("арсенал"); err != nil {
+	if err := sf.net.UpdateLst(); err != nil {
 		return fmt.Errorf("Arsenal.UpdateArsenal(): при обновлении lstArsenal, err=%w", err)
 	}
 	var (
@@ -183,7 +183,7 @@ func (sf *Arsenal) UpdateArsenal() (err error) {
 
 // Выбирает что надо делать, запускает процесс изготовления
 func (sf *Arsenal) makeArsenal() {
-	err := sf.net.UpdateLst("арсенал")
+	err := sf.net.UpdateLst()
 	if err != nil {
 		// log._rintf("ERRO Arsenal.Run(): при обновлении lstArsenal, err=\n\t%v\n", err)
 		return

+ 16 - 15
server/serv_bots/warbot/angar/base/bank/bank.go

@@ -22,13 +22,13 @@ type Bank struct {
 	*section.Section
 	net       *banknet.BankNet
 	silverBot types.IStatParam
-	mode1     *bankmode.BankMode
-	mode2     *bankmode.BankMode
+	mode1     *bankmode.BankMode // 1 режим работы на выбор
+	mode2     *bankmode.BankMode // 2 режим работы на выбор
 }
 
 // NewBank -- возвращает новый *Bank
 func NewBank(base types.IBase) (*Bank, error) {
-	section, err := section.NewSection(base.Bot(), `<span class="green2">Серебро</span><br/>`)
+	section, err := section.NewSection(base.Bot(), "Банк", `<span class="green2">Серебро</span><br/>`)
 	if err != nil {
 		return nil, fmt.Errorf("NewBank(): in create *Section, err=\n\t%w", err)
 	}
@@ -55,7 +55,7 @@ func (sf *Bank) Run() error {
 
 // UpdateLst -- принудительно обновляет состояние банка
 func (sf *Bank) UpdateLst() {
-	if err := sf.net.UpdateLst("Банк"); err != nil {
+	if err := sf.net.UpdateLst(); err != nil {
 		log.Printf("Bank.UpdateLst(): err=\n\t%v\n", err)
 	}
 }
@@ -64,11 +64,9 @@ func (sf *Bank) UpdateLst() {
 func (sf *Bank) run() {
 	log.Printf("Bank.run()\n")
 	sf.CountDown().Set(5)
-	for range sf.CountDown().ChanSig() {
-		// time.Sleep(time.Second * 30)
-		count := sf.CountDown().Get()
-		log.Printf("Bank countDown=%d\n", count)
-		if err := sf.net.UpdateLst("банк"); err != nil {
+	for {
+		<-sf.CountDown().ChanSig()
+		if err := sf.net.UpdateLst(); err != nil {
 			// log._rintf("ERRO Bank.Run():  при обновлении lstBank, err=\n\t%v\n", err)
 			continue
 		}
@@ -76,9 +74,12 @@ func (sf *Bank) run() {
 			// log._rintf("ERRO Bank.Run(): при получении списка режимов банка, err=\n\t%v\n", err)
 			continue
 		}
-		if err := sf.makeProduct(); err != nil {
+		iTime, err := sf.makeProduct()
+		if err != nil {
 			log.Printf("ERRO Bank.Run(): при пуске производства банка, err=\n\t%v\n", err)
+			continue
 		}
+		sf.Section.SetCountDown(iTime)
 	}
 }
 
@@ -98,7 +99,7 @@ func (sf *Bank) SilverBot() types.IStatParam {
 }
 
 // Запускает в производство серебро
-func (sf *Bank) makeProduct() error {
+func (sf *Bank) makeProduct() (int, error) {
 	var (
 		lstBank = sf.GetLst()
 		ind     int
@@ -126,21 +127,21 @@ func (sf *Bank) makeProduct() error {
 		strLink = "http://wartank.ru/production/" + lstLink[0]
 		lstBank, err := sf.net.Get(strLink)
 		if err != nil {
-			return fmt.Errorf("BankNet.makeProduct(): при выполнении GET-запроса начать производство, err=%w", err)
+			return -1, fmt.Errorf("BankNet.makeProduct(): при выполнении GET-запроса начать производство, err=%w", err)
 		}
 		for _, strOut := range lstBank {
 			if strings.Contains(strOut, `<title>База</title>`) { // Это база, а не банк
-				return nil
+				return 30, nil
 			}
 		}
 		if err = sf.Update(lstBank); err != nil {
-			return fmt.Errorf("BankNet.makeProduct(): при обновлении lstBank, err=%w", err)
+			return -1, fmt.Errorf("BankNet.makeProduct(): при обновлении lstBank, err=%w", err)
 		}
 		if err := sf.CountDown().Parse(time1); err != nil {
 			log.Printf("WARN Bank.makeProduct(): при установке времени производства банка(%v)\n\terr=%v\n", time1, err)
 		}
 	}
-	return nil
+	return sf.CountDown().Get(), nil
 }
 
 // Получает все режимы банка

+ 3 - 3
server/serv_bots/warbot/angar/base/base.go

@@ -44,11 +44,11 @@ type Base struct {
 
 // NewBase -- возвращает новую базу бота
 func NewBase(angar types.IAngar) (*Base, error) {
-	log.Printf("NewBase()\n")
-	section, err := section.NewSection(angar.Bot(), `<title>База</title>`)
+	section, err := section.NewSection(angar.Bot(), "База", `<title>База</title>`)
 	if err != nil {
 		return nil, fmt.Errorf("NewBase(): in create ISection, err=\n\t%w", err)
 	}
+	log.Printf("NewBase(): %q\n", section.Bot().Name())
 	sf := &Base{
 		Section: section,
 	}
@@ -109,7 +109,7 @@ func (sf *Base) run() {
 			sf.CountDown().Stop()
 			return
 		case <-sf.CountDown().ChanSig():
-			if err := sf.net.UpdateLst("Base.run()"); err != nil { // Обновить состояние базы
+			if err := sf.net.UpdateLst(); err != nil { // Обновить состояние базы
 				log.Printf("ERRO Base.Run(): при обновлении базы, err=\n\t%v\n", err)
 			}
 			sf.checkPolygonForce()                 // Проверить усиление полигона

+ 2 - 2
server/serv_bots/warbot/angar/base/market/market.go

@@ -22,7 +22,7 @@ type Market struct {
 
 // NewMarket -- возвращает новый рынок
 func NewMarket(base types.IBase) (*Market, error) {
-	section, err := section.NewSection(base.Bot(), `<title>Рынок</title>`)
+	section, err := section.NewSection(base.Bot(), "Рынок", `<title>Рынок</title>`)
 	if err != nil {
 		return nil, fmt.Errorf("NewMarket(): in create *Section, err=\n\t%w", err)
 	}
@@ -69,7 +69,7 @@ func (sf *Market) checkTime() {
 	)
 	// countDown := sf.CountDown().Get()
 	fnIsSilver := func() bool { // Найти счётчик цены серебра
-		if err := sf.net.UpdateLst("Рынок"); err != nil { // Принудительное ПЕРВОЕ обновление рынка
+		if err := sf.net.UpdateLst(); err != nil { // Принудительное ПЕРВОЕ обновление рынка
 			// log._rintf("ERRO Market.checkTime(): при обновлении lstMarket, err=\n\t%v\n", err)
 			return false
 		}

+ 4 - 3
server/serv_bots/warbot/angar/base/mine/mine.go

@@ -31,7 +31,7 @@ type Mine struct {
 
 // NewMine -- возвращает новый *Mine
 func NewMine(base types.IBase) (*Mine, error) {
-	section, err := section.NewSection(base.Bot(), `<span class="green2">Руда</span><br/>`)
+	section, err := section.NewSection(base.Bot(), "Шахта", `<span class="green2">Руда</span><br/>`)
 	if err != nil {
 		return nil, fmt.Errorf("NewMine(): in create *Section, err=\n\t%w", err)
 	}
@@ -67,11 +67,13 @@ func (sf *Mine) run() {
 			return
 		case <-sf.CountDown().ChanSig():
 			log.Printf("Mine.run(): time sig")
+			sf.Section.SetCountDown(120)
 			work := sf.ModeCurrent().Work()
+			log.Printf("Mine.run(): work=%v\n", work)
 			if work == "upgrade" {
 				continue
 			}
-			if err := sf.net.UpdateLst("Шахта"); err != nil {
+			if err := sf.net.UpdateLst(); err != nil {
 				log.Printf("ERRO Mine.Run(): при обновлении lstMine, err=\n\t%v\n", err)
 				continue
 			}
@@ -90,7 +92,6 @@ func (sf *Mine) run() {
 			default:
 				// log._rintf("ERRO MineNet.Run(): неизвестный режим производства, режим=%q\n", work)
 			}
-			sf.SetCountDown(120)
 		}
 		// time.Sleep(time.Second * 30)
 	}

+ 2 - 2
server/serv_bots/warbot/angar/base/polygon/polygon.go

@@ -24,7 +24,7 @@ type Polygon struct {
 
 // NewPolygon -- возвращает новый *Polygon
 func NewPolygon(base types.IBase) (*Polygon, error) {
-	section, err := section.NewSection(base.Bot(), `<title>Полигон</title>`)
+	section, err := section.NewSection(base.Bot(), "Полигон", `<title>Полигон</title>`)
 	if err != nil {
 		return nil, fmt.Errorf("NewPolygon(): in create *Section, err=\n\t%w", err)
 	}
@@ -148,7 +148,7 @@ func (sf *Polygon) checkForce() {
 
 // Выбирает самый слабый параметр и усиливает его
 func (sf *Polygon) addForce() {
-	if err := sf.net.UpdateLst("Полигон"); err != nil {
+	if err := sf.net.UpdateLst(); err != nil {
 		// log._rintf("Polygon.checkPolygon(): при принудительном обновлении lstPlygon, mode=%s\terr=\n\t%v\n", sf.ModeCurrent().Get(), err)
 		sf.CountDown().Set(5)
 		return

+ 3 - 3
server/serv_bots/warbot/angar/batmas/batmas.go

@@ -39,7 +39,7 @@ func NewBatMas(bot types.IBot) (*BatMas, error) {
 func (sf *BatMas) Run() error {
 	var err error
 	{ // ISection (ожидание)
-		sf.Section, err = section.NewSection(sf.bot, `/> Битва мастеров <`)
+		sf.Section, err = section.NewSection(sf.bot, "Битва мастеров", `/> Битва мастеров <`)
 		if err != nil {
 			return fmt.Errorf("BatMas.Run(): in create *Section, err=\n\t%w", err)
 		}
@@ -85,7 +85,7 @@ func (sf *BatMas) goBatMas() bool {
 	}
 
 	// Время меньше 25 сек, надо уточнять (тут возможна ошибка с экраном ожидания)
-	if err := sf.net.UpdateLst("Битва мастеров"); err != nil {
+	if err := sf.net.UpdateLst(); err != nil {
 		// log._rintf("ERRO Battle.goBattle().fnCountDown(): при обновлении lstBattle, err=\n\t%v\n", err)
 		// Возможно времени уже не осталось
 		return true
@@ -127,7 +127,7 @@ func (sf *BatMas) findTimeCount() {
 //
 //	вызывается только если есть награда
 func (sf *BatMas) upBattle() bool {
-	if err := sf.net.UpdateLst("Битва мастеров"); err != nil {
+	if err := sf.net.UpdateLst(); err != nil {
 		// log._rintf("ERRO BatMas.upBattle(): при обновлении lstBattle, err=\n\t%v\n", err)
 		return false
 	}

+ 1 - 1
server/serv_bots/warbot/angar/battle/battle.go

@@ -59,7 +59,7 @@ func NewBattle(bot types.IBot) (*Battle, error) {
 func (sf *Battle) Run() error {
 	var err error
 	{ // ISection
-		sf.Section, err = section.NewSection(sf.bot, `<span>до начала `)
+		sf.Section, err = section.NewSection(sf.bot, "Группа сражения", `<span>до начала `)
 		if err != nil {
 			return fmt.Errorf("Battle.Run(): in create *Section, err=\n\t%w", err)
 		}

+ 2 - 2
server/serv_bots/warbot/angar/battle/battle_register/battle_register.go

@@ -20,7 +20,7 @@ type BattleRegister struct {
 
 // NewBattleRegister -- возвращает новый ожидатель битвы
 func NewBattleRegister(bot types.IBot) (*BattleRegister, error) {
-	section, err := section.NewSection(bot, `<title>Сражения</title>`)
+	section, err := section.NewSection(bot, "Сражение", `<title>Сражения</title>`)
 	if err != nil {
 		return nil, fmt.Errorf("NewBattleRegister(): in create ISection, err=\n\t%w", err)
 	}
@@ -37,7 +37,7 @@ func NewBattleRegister(bot types.IBot) (*BattleRegister, error) {
 
 // Register -- регистрирует танк на сражение
 func (sf *BattleRegister) Register() {
-	if err := sf.net.UpdateLst("Ближайшее сражение"); err != nil { // Здесь может уже обратный отсчёт перед сражением
+	if err := sf.net.UpdateLst(); err != nil { // Здесь может уже обратный отсчёт перед сражением
 		return
 	}
 	var (

+ 2 - 2
server/serv_bots/warbot/angar/battle/battle_wait/battle_wait.go

@@ -21,7 +21,7 @@ type BattleWait struct {
 
 // NewBattleWait -- возвращает новый ожидатель битвы
 func NewBattleWait(bot types.IBot) (*BattleWait, error) {
-	section, err := section.NewSection(bot, `<title>Сражения</title>`)
+	section, err := section.NewSection(bot, "Ожидание сражения", `<title>Сражения</title>`)
 	if err != nil {
 		return nil, fmt.Errorf("NewBattleWait(): in create ISection, err=\n\t%w", err)
 	}
@@ -39,7 +39,7 @@ func NewBattleWait(bot types.IBot) (*BattleWait, error) {
 
 // Wait -- ожидает начало сражения
 func (sf *BattleWait) Wait() {
-	if err := sf.net.UpdateLst("Ближайшее сражение"); err != nil { // Здесь может уже обратный отсчёт перед сражением
+	if err := sf.net.UpdateLst(); err != nil { // Здесь может уже обратный отсчёт перед сражением
 		return
 	}
 	var (

+ 1 - 1
server/serv_bots/warbot/angar/battle/battle_worker/battle_worker.go

@@ -29,7 +29,7 @@ type BattleWorker struct {
 
 // NewBattleWorker -- возвращает новый исполнитель битвы
 func NewBattleWorker(bot types.IBot) (*BattleWorker, error) {
-	section, err := section.NewSection(bot, `<title>Сражения</title>`)
+	section, err := section.NewSection(bot, "Ход сражения", `<title>Сражения</title>`)
 	if err != nil {
 		return nil, fmt.Errorf("NewBattleWorker(): in create *Section, err=\n\t%w", err)
 	}

+ 2 - 2
server/serv_bots/warbot/angar/battle/battle_worker/battleon/battleon.go

@@ -37,7 +37,7 @@ type BattleOn struct {
 
 // NewBattleOn -- возвращает новый *BattleOn
 func NewBattleOn(bot types.IBot) (*BattleOn, error) {
-	section, err := section.NewSection(bot, `<title>Сражения</title>`)
+	section, err := section.NewSection(bot, "Исполнитель сражения", `<title>Сражения</title>`)
 	if err != nil {
 		return nil, fmt.Errorf("NewBattleOn(): in create ISection, err=\n\t%w", err)
 	}
@@ -134,7 +134,7 @@ func (sf *BattleOn) checkEnd() {
 		// log._rintf("BattleOn.checkEnd(): сражение завершено\n")
 	}
 
-	if err := sf.net.UpdateLst("Сражение+"); err != nil {
+	if err := sf.net.UpdateLst(); err != nil {
 		// log._rintf("WARN BattleOn.checkEnd(): при обновлении lstBattleOn, err=\n\t%v\n", err)
 		fnPrintEnd()
 		return

+ 1 - 1
server/serv_bots/warbot/angar/battle/battle_worker/battleon/health/health.go

@@ -224,7 +224,7 @@ func (sf *Health) findHealth() error {
 		lstBattle = sf.GetLst()
 	)
 	if len(lstBattle) == 0 { // Принудительно обновим сражение
-		if err := sf.Net().UpdateLst("Сражение+ Здоровье"); err != nil {
+		if err := sf.Net().UpdateLst(); err != nil {
 			time.Sleep(time.Second * 1)
 			return fmt.Errorf("Health.findHealth(): пустой lsBattleOn, err=\n\t%w", err)
 		}

+ 1 - 1
server/serv_bots/warbot/angar/battle/battle_worker/battleon/shot/shot.go

@@ -94,7 +94,7 @@ func (sf *Shot) run() {
 //
 //	Вызывается из отдельного потока
 func (sf *Shot) shot() {
-	if err := sf.Net().UpdateLst("Сражение+ выстрел"); err != nil { // Проверка на непосредственно битву
+	if err := sf.Net().UpdateLst(); err != nil { // Проверка на непосредственно битву
 		// <span>закончилась 00:00:07 назад</span>
 		// log._rintf("ERRO Shot.shot(): при обновлении lstBattleOn, err=\n\t%v\n", err)
 		time.Sleep(time.Second * 1)

+ 6 - 6
server/serv_bots/warbot/angar/convoy/convoy.go

@@ -30,7 +30,7 @@ type Convoy struct {
 
 // NewConvoy -- возвращает новый *Convoy
 func NewConvoy(bot types.IBot) (*Convoy, error) {
-	section, err := section.NewSection(bot, `<title>Конвой</title>`)
+	section, err := section.NewSection(bot, "Конвой", `<title>Конвой</title>`)
 	if err != nil {
 		return nil, fmt.Errorf("NewConvoy(): in create ISection, err=\n\t%w", err)
 	}
@@ -56,7 +56,7 @@ func (sf *Convoy) Run() error {
 
 // UpdateLst -- принудительно обновляет состояние конвоя
 func (sf *Convoy) UpdateLst() {
-	if err := sf.net.UpdateLst("Конвой"); err != nil {
+	if err := sf.net.UpdateLst(); err != nil {
 		log.Printf("Convoy.UpdateLst(): err=\n\t%v\n", err)
 	}
 }
@@ -139,7 +139,7 @@ func (sf *Convoy) updateGlory() {
 // Обновляет оставшееся время конвоя
 func (sf *Convoy) updateTime() {
 	// Время подходит надо обновляться
-	if err := sf.net.UpdateLst("Конвой"); err != nil {
+	if err := sf.net.UpdateLst(); err != nil {
 		logrus.WithError(err).Error("ConvoyNet.updateTime(): при выполнении GET-команды обновления")
 		sf.CountDown().Set(20)
 		return
@@ -325,7 +325,7 @@ func (sf *Convoy) checkWarForce() {
 		ind       int
 	)
 	if len(lstConvoy) == 0 {
-		if err := sf.net.UpdateLst("Конвой"); err != nil {
+		if err := sf.net.UpdateLst(); err != nil {
 			// log._rintf("Convoy.check6frage(): при обновлении пустого lstConvoy, err=\n\t%v\n", err)
 			return
 		}
@@ -372,7 +372,7 @@ func (sf *Convoy) checkMaster() {
 		ind       int
 	)
 	if len(lstConvoy) == 0 {
-		if err := sf.net.UpdateLst("Конвой"); err != nil {
+		if err := sf.net.UpdateLst(); err != nil {
 			// log._rintf("Convoy.check6frage(): при обновлении пустого lstConvoy, err=\n\t%v\n", err)
 			return
 		}
@@ -419,7 +419,7 @@ func (sf *Convoy) check6frage() {
 		ind       int
 	)
 	if len(lstConvoy) == 0 {
-		if err := sf.net.UpdateLst("Конвой"); err != nil {
+		if err := sf.net.UpdateLst(); err != nil {
 			// log._rintf("Convoy.check6frage(): при обновлении пустого lstConvoy, err=\n\t%v\n", err)
 			return
 		}

+ 2 - 2
server/serv_bots/warbot/angar/division/divwar/divwar.go

@@ -55,7 +55,7 @@ func NewDivWar(bot types.IBot) (*DivWar, error) {
 	// sf.shotTimeFull.Set(8000) // 8000 msec
 	var err error
 	{ // ISection
-		sf.Section, err = section.NewSection(bot, `<span>до начала `)
+		sf.Section, err = section.NewSection(bot, "Битва дивизий", `<span>до начала `)
 		if err != nil {
 			return nil, fmt.Errorf("NewDivWar(): in create *Section, err=\n\t%w", err)
 		}
@@ -119,7 +119,7 @@ func (sf *DivWar) run() {
 
 // Ищет время до начала битвы дивизий
 func (sf *DivWar) findTimeCount() {
-	if err := sf.net.UpdateLst("Битва дивизий"); err != nil { // Здесь может уже обратный отсчёт перед сражением
+	if err := sf.net.UpdateLst(); err != nil { // Здесь может уже обратный отсчёт перед сражением
 		sf.chDivWar <- 1
 		return
 	}

+ 2 - 2
server/serv_bots/warbot/angar/division/divwar/divwaron/divwaron.go

@@ -52,7 +52,7 @@ func NewDivWarOn(bot types.IBot) (*DivWarOn, error) {
 	}
 	var err error
 	{ // ISection (ожидание)
-		sf.Section, err = section.NewSection(bot, `<title>Сражения</title>`)
+		sf.Section, err = section.NewSection(bot, "Ожидание битвы дивизий", `<title>Сражения</title>`)
 		if err != nil {
 			return nil, fmt.Errorf("NewDivWarOn(): in create *Section, err=\n\t%w", err)
 		}
@@ -137,7 +137,7 @@ func (sf *DivWarOn) checkEnd() bool {
 		}
 	}()
 
-	if err := sf.net.UpdateLst("Битва дивизий+"); err != nil {
+	if err := sf.net.UpdateLst(); err != nil {
 		// log._rintf("WARN DivWarOn.checkEnd(): при обновлении lstDivWarOn, err=\n\t%v\n", err)
 		sf.isEnd.Set()
 		sf.fnCancelDivWar()

+ 1 - 1
server/serv_bots/warbot/angar/division/divwar/divwaron/health/health.go

@@ -250,7 +250,7 @@ func (sf *Health) findHealth() error {
 		lstBattle = sf.GetLst()
 	)
 	if len(lstBattle) == 0 { // Принудительно обновим сражение
-		if err := sf.Net().UpdateLst("Битва дивизий+ здоровье"); err != nil {
+		if err := sf.Net().UpdateLst(); err != nil {
 			sf.isEnd.Set()
 			sf.fnCancel()
 			return fmt.Errorf("Health.findHealth(): после принудительного обновления lsBattleOn, err=\n\t%w", err)

+ 1 - 1
server/serv_bots/warbot/angar/division/divwar/divwaron/shot/shot.go

@@ -122,7 +122,7 @@ func (sf *Shot) run() {
 //
 //	Вызывается из отдельного потока
 func (sf *Shot) shot() {
-	if err := sf.Net().UpdateLst("Битва дивизий+ выстрел"); err != nil { // Проверка на непосредственно битву
+	if err := sf.Net().UpdateLst(); err != nil { // Проверка на непосредственно битву
 		// <span>закончилась 00:00:07 назад</span>
 		// log._rintf("ERRO Shot.shot(): при обновлении lstBattleOn, err=\n\t%v\n", err)
 		sf.isEnd.Set()

+ 2 - 2
server/serv_bots/warbot/angar/missions/missions.go

@@ -23,7 +23,7 @@ type Missions struct {
 
 // NewMissions -- возвращает новый *Missions
 func NewMissions(bot types.IBot) (*Missions, error) {
-	section, err := section.NewSection(bot, `<title>Миссии</title>`)
+	section, err := section.NewSection(bot, "Миссии", `<title>Миссии</title>`)
 	if err != nil {
 		return nil, fmt.Errorf("NewMissions(): in create *Section, err=\n\t%w", err)
 	}
@@ -56,7 +56,7 @@ func (sf *Missions) run() {
 			sf.CountDown().Stop()
 			return
 		case <-sf.CountDown().ChanSig():
-			if err := sf.net.UpdateLst("Missions.run()"); err != nil {
+			if err := sf.net.UpdateLst(); err != nil {
 				// log._rintf("ERRO Missions.run(): при обновлении lstMissions, err=\n\t%v\n", err)
 				return
 			}

+ 75 - 18
server/serv_bots/warbot/warbot.go

@@ -5,6 +5,7 @@ import (
 	"context"
 	"fmt"
 	"log"
+	"strings"
 
 	"wartank/pkg/components/safebool"
 	"wartank/pkg/types"
@@ -22,8 +23,6 @@ type WarBot struct {
 	errFinal  error // Финальная ошибка работы, если была
 	angar     types.IAngar
 	botNet    types.IBotNet
-	name      string // Имя бота
-	pass      string // Пароль бота
 	isRun     *safebool.SafeBool
 	isAutoRun *safebool.SafeBool
 	config    *warbot_config.WarBotConfig // Конфиг бота для хранения в базе
@@ -31,36 +30,85 @@ type WarBot struct {
 	fnCancel  func()                      // Функция отменя контекста бота
 }
 
+// LoadWarBot -- загружает бота из базы
+func LoadWarBot(server types.IServer, login string) (*WarBot, error) {
+	{ // Предусловия
+		if server == nil {
+			return nil, fmt.Errorf("LoadWarBot(): IApp is nil")
+		}
+		if login == "" {
+			return nil, fmt.Errorf("LoadWarBot(): name is empty")
+		}
+	}
+	log.Printf("LoadWarBot(): name=%q\n", login)
+	store := server.Store()
+	strData, err := store.Get("/bots/" + login)
+	if err != nil {
+		if !strings.Contains(err.Error(), "not found") {
+			return nil, fmt.Errorf("LoadWarBot(): in load bot %q from store, err=\n\t%w", login, err)
+		}
+		return nil, fmt.Errorf("LoadWarBot(): bot %q not found in store", login)
+	}
+	config := &warbot_config.WarBotConfig{}
+	if err = config.Unmarshall(strData); err != nil {
+		return nil, fmt.Errorf("LoadWarBot(): in unmarshall WarBotConfig(%q) from store, err=\n\t%w", login, err)
+	}
+	sf, err := makeCoreWarBot(server, config)
+	if err != nil {
+		return nil, fmt.Errorf("NewWarBot(): in make core for bot %q, err=\n\t%w", login, err)
+	}
+	return sf, nil
+
+}
+
 // NewWarBot -- возвращает новый WarBot
-func NewWarBot(server types.IServer, name string) (*WarBot, error) {
+func NewWarBot(server types.IServer, login, pass string) (*WarBot, error) {
 	{ // Предусловия
 		if server == nil {
 			return nil, fmt.Errorf("NewWarBot(): IApp is nil")
 		}
-		if name == "" {
+		if login == "" {
 			return nil, fmt.Errorf("NewWarBot(): name is empty")
 		}
 	}
+	log.Printf("NewWarBot(): name=%q\n", login)
+	config := &warbot_config.WarBotConfig{
+		IsAutoRun_: false,
+		Login_:     login,
+		Password_:  pass,
+	}
+	sf, err := makeCoreWarBot(server, config)
+	if err != nil {
+		return nil, fmt.Errorf("NewWarBot(): in make core bot %q, err=\n\t%w", login, err)
+	}
+	if err := sf.save(); err != nil {
+		return nil, fmt.Errorf("NewWarBot(): in self save to store, err=\n\t%w", err)
+	}
+	return sf, nil
+}
+
+// Создаёт ядро бота
+func makeCoreWarBot(server types.IServer, config *warbot_config.WarBotConfig) (*WarBot, error) {
+	{ // Предусловия
+		if server == nil {
+			return nil, fmt.Errorf("NewWarBot(): IServer==nil")
+		}
+		if config == nil {
+			return nil, fmt.Errorf("NewWarBot(): WarBotConfig==nil")
+		}
+	}
 	ctx, fnCancel := context.WithCancel(server.CtxApp())
 	sf := &WarBot{
 		server:    server,
 		store:     server.Store(),
 		tank:      tank.NewTank(),
-		name:      name,
 		isRun:     safebool.NewSafeBool(),
 		isAutoRun: safebool.NewSafeBool(),
 		config:    &warbot_config.WarBotConfig{},
 		ctx:       ctx,
 		fnCancel:  fnCancel,
 	}
-	strData, err := sf.store.Get("/bots/" + sf.name)
-	if err != nil {
-		return nil, fmt.Errorf("NewWarBot(): in get binData for WarBotConfig from store, err=\n\t%w", err)
-	}
-	if err = sf.config.Unmarshall(strData); err != nil {
-		return nil, fmt.Errorf("NewWarBot(): in unmarshall WarBotConfig from store, err=\n\t%w", err)
-	}
-	sf.pass = sf.config.Password_
+	var err error
 	{ // WarBotNet
 		sf.botNet, err = warbot_net.NewWarBotNet(sf)
 		if err != nil {
@@ -69,7 +117,7 @@ func NewWarBot(server types.IServer, name string) (*WarBot, error) {
 	}
 	sf.angar, err = angar.NewAngar(sf)
 	if err != nil {
-		return nil, fmt.Errorf("NewWarBot(): bot(%q) in make IAngar, err=\n\t%w", sf.name, err)
+		return nil, fmt.Errorf("NewWarBot(): bot(%q) in make IAngar, err=\n\t%w", sf.Name(), err)
 	}
 	if sf.config.IsAutoRun_ {
 		sf.isAutoRun.Set()
@@ -90,12 +138,12 @@ func (sf *WarBot) IsRun() bool {
 
 // Name -- возвращает имя бота
 func (sf *WarBot) Name() string {
-	return sf.name
+	return sf.config.Login_
 }
 
 // Pass -- возвращает пароль бота
 func (sf *WarBot) Pass() string {
-	return sf.pass
+	return sf.config.Password_
 }
 
 // Run -- запускает бот в работу
@@ -104,7 +152,7 @@ func (sf *WarBot) Run() (err error) {
 		return nil
 	}
 	if err := sf.angar.Run(); err != nil {
-		return fmt.Errorf("WarBot.Run(): bot(%q) in run angar, err=\n\t%w", sf.name, err)
+		return fmt.Errorf("WarBot.Run(): bot(%q) in run angar, err=\n\t%w", sf.Name(), err)
 	}
 	sf.isRun.Set()
 	return nil
@@ -155,7 +203,7 @@ func (sf *WarBot) ResetAutoGame() {
 func (sf *WarBot) saveConfig() {
 	log.Printf("WarBot.saveConfig()")
 	strConf := sf.config.Marshall()
-	err := sf.store.Put("/bots/"+sf.name, strConf)
+	err := sf.store.Put("/bots/"+sf.Name(), strConf)
 	if err != nil {
 		log.Printf("WarBot.saveConfig(): err=\n\t%v\n", err)
 	}
@@ -170,3 +218,12 @@ func (sf *WarBot) Ctx() context.Context {
 func (sf *WarBot) CancelBot() {
 	sf.fnCancel()
 }
+
+// Сохраняет себя в базу
+func (sf *WarBot) save() error {
+	err := sf.store.Put("/bots/"+sf.Name(), sf.config.Marshall())
+	if err != nil {
+		return fmt.Errorf("WarBot.save(): in self save to store bot(%q), err=\n\t%w", sf.Name(), err)
+	}
+	return nil
+}

+ 1 - 0
server/serv_bots/warbot/warbot_config/warbot_config.go

@@ -9,6 +9,7 @@ import (
 // WarBotConfig -- конфиг бота для хранения в базе
 type WarBotConfig struct {
 	IsAutoRun_ bool   `json:"is_auto_run,omitempty"` // Признак автостарта при загрузке
+	Login_     string `json:"login"`                 // Логин бота
 	Password_  string `json:"password"`              // Пароль бота
 }
 

+ 2 - 1
server/serv_bots/warbot/warbot_net/warbot_net.go

@@ -3,6 +3,7 @@ package warbot_net
 import (
 	"context"
 	"fmt"
+	"log"
 	"net/http"
 
 	"wartank/pkg/components/safebool"
@@ -29,10 +30,10 @@ type WarBotNet struct {
 
 // NewWarBotNet -- возвращает новый *NetClient
 func NewWarBotNet(bot types.IBot) (*WarBotNet, error) {
-	fmt.Printf("NewWarBotNet()\n")
 	if bot == nil {
 		return nil, fmt.Errorf("NewWarBotNet(): IBot == nil")
 	}
+	log.Printf("NewWarBotNet(): name=%q\n", bot.Name())
 	ctx, fnCancel := context.WithCancel(bot.Ctx())
 	sf := &WarBotNet{
 		bot:        bot,

+ 0 - 3
server/server.go

@@ -51,9 +51,6 @@ func (sf *Server) Store() types.IStore {
 // Run -- запускает сервер бота в работу
 func (sf *Server) Run() error {
 	// go sf.bot.Run()
-	if err := sf.servBots.Load(); err != nil {
-		return fmt.Errorf("Server.Run(): in load bots, err=\n\t%w", err)
-	}
 	sf.gui.Run()
 	<-sf.Done()
 	// if err := sf._erverWeb.Error(); err != nil {