Преглед изворни кода

SVI Переделка на новую архитектуру

SVI пре 1 година
родитељ
комит
09d2f96868
79 измењених фајлова са 745 додато и 641 уклоњено
  1. 0 1
      Makefile
  2. 51 121
      app/lev0/bfunc/bf_fuel_attack/bf_fuel_attack.go
  3. 43 0
      app/lev0/bfunc/bf_fuel_find/bf_fuel_find.go
  4. 41 0
      app/lev0/bfunc/bf_gold_find/bf_gold_find.go
  5. 37 0
      app/lev0/bfunc/bf_silver_find/bf_silver_find.go
  6. 2 0
      app/lev0/bfunc/bfunc.go
  7. 0 87
      app/lev0/proc/proc_fuel_find/proc_fuel_find.go
  8. 5 7
      app/lev0/types/iapp.go
  9. 0 4
      app/lev0/types/ibot.go
  10. 0 10
      app/lev0/types/ibot_context.go
  11. 2 0
      app/lev0/types/itank_stat.go
  12. 0 7
      app/lev0/types/iweb_server.go
  13. 1 1
      app/lev1/lev1.go
  14. 2 2
      app/lev1/stat_param/stat_param.go
  15. 10 1
      app/lev1/web_render/web_render.go
  16. 5 3
      app/lev2/arena/arena.go
  17. 19 76
      app/lev2/arena/arena_angar/arena_angar.go
  18. 19 22
      app/lev2/arena/arena_arsenal/arena_arsenal.go
  19. 5 3
      app/lev2/arena/arena_bank/arena_bank.go
  20. 5 3
      app/lev2/arena/arena_bank/bank_mode/bank_mode.go
  21. 5 2
      app/lev2/arena/arena_base/arena_base.go
  22. 3 1
      app/lev2/arena/arena_battle/arena_battle.go
  23. 3 1
      app/lev2/arena/arena_battle/battle_register/battle_register.go
  24. 3 1
      app/lev2/arena/arena_battle/battle_wait/battle_wait.go
  25. 6 4
      app/lev2/arena/arena_battle/battle_worker/battle_worker.go
  26. 1 1
      app/lev2/arena/arena_battle/battle_worker/battle_worker/battle_worker.go
  27. 1 1
      app/lev2/arena/arena_battle/battle_worker/battleon/battleon.go
  28. 1 1
      app/lev2/arena/arena_context/arena_context.go
  29. 5 3
      app/lev2/arena/arena_convoy/arena_convoy.go
  30. 4 2
      app/lev2/arena/arena_death/death_worker/death_worker.go
  31. 3 1
      app/lev2/arena/arena_death/death_worker/process_death/process_death.go
  32. 1 1
      app/lev2/arena/arena_division/div_war/div_war.go
  33. 1 1
      app/lev2/arena/arena_division/div_war/process_divwar/process_divwar.go
  34. 13 11
      app/lev2/arena/arena_division/divwar/divwar.go
  35. 1 1
      app/lev2/arena/arena_division/divwar/divwaron/divwaron.go
  36. 3 1
      app/lev2/arena/arena_duel/arena_duel.go
  37. 39 0
      app/lev2/arena/arena_fuel/arena_fuel.go
  38. 3 1
      app/lev2/arena/arena_fuel_storage/arena_fuel_storage.go
  39. 4 2
      app/lev2/arena/arena_market/arena_market.go
  40. 2 2
      app/lev2/arena/arena_masters/arena_masters.go
  41. 13 14
      app/lev2/arena/arena_mine/arena_mine.go
  42. 2 2
      app/lev2/arena/arena_missions/arena_missions.go
  43. 3 3
      app/lev2/arena/arena_net/arena_net.go
  44. 1 1
      app/lev2/arena/arena_net/arena_web_worker/arena_web_worker.go
  45. 9 5
      app/lev2/arena/arena_polygon/arena_polygon.go
  46. 2 2
      app/lev2/arena/arena_string/arena_string.go
  47. 4 4
      app/lev2/arena/arena_upgrade/arena_upgrade.go
  48. 48 0
      app/lev2/lev2.go
  49. 44 37
      app/lev3/bot/bot.go
  50. 1 1
      app/lev3/bot/bot_net/bot_cookie/bot_cookie.go
  51. 3 3
      app/lev3/bot/bot_net/bot_net.go
  52. 4 4
      app/lev3/bot/bot_net/bot_net_login/bot_net_login.go
  53. 17 13
      app/lev3/bot/bot_net/bot_net_stat/bot_net_stat.go
  54. 5 4
      app/lev3/bot/bot_net/http_worker/http_worker.go
  55. 2 2
      app/lev3/bot/bot_net/http_worker/net_stat/net_stat.go
  56. 3 1
      app/lev3/bot/bot_stat/bot_resurs/bot_resurs.go
  57. 13 2
      app/lev3/bot/bot_stat/tank_stat/tank_stat.go
  58. 4 4
      app/lev3/farm_bots/dict_bot/dict_bot.go
  59. 6 4
      app/lev3/farm_bots/farm_bots.go
  60. 17 16
      app/lev3/serv_web/serv_web.go
  61. 11 12
      app/lev3/serv_web/web_api/web_api.go
  62. 1 1
      app/lev3/serv_web/web_gui/page_bot_add/page_bot_add.go
  63. 1 1
      app/lev3/serv_web/web_gui/page_bot_list/page_bot_list.go
  64. 18 18
      app/lev3/serv_web/web_gui/page_bot_show/bot_show.tmpl.html
  65. 10 9
      app/lev3/serv_web/web_gui/page_bot_show/page_bot_show.go
  66. 1 1
      app/lev3/serv_web/web_gui/web_gui.go
  67. 8 9
      app/lev3/server_stat/server_stat.go
  68. 0 56
      app/lev4/applic/applic.go
  69. 6 5
      app/lev4/build/build.go
  70. 12 0
      app/lev4/lev4.go
  71. 55 0
      app/lev4/mod_serv/mod_serv.go
  72. 14 2
      cmd/server/main.go
  73. 1 1
      go.mod
  74. 2 2
      go.sum
  75. 9 9
      vendor/gitp78su.ipnodns.ru/svi/kern/kern.go
  76. 15 2
      vendor/gitp78su.ipnodns.ru/svi/kern/mds/mod_kctx/mod_kctx.go
  77. 15 2
      vendor/gitp78su.ipnodns.ru/svi/kern/mds/mod_keeper/mod_keeper.go
  78. 15 2
      vendor/gitp78su.ipnodns.ru/svi/kern/mds/mod_serv_http/mod_serv_http.go
  79. 1 1
      vendor/modules.txt

+ 0 - 1
Makefile

@@ -30,7 +30,6 @@ dev:
 	mkdir -p ./bin_dev/web/tmpl
 	cp -r ./web ./bin_dev
 	go fmt ./...
-	# go build -race -o ./bin_dev/wartank_dev ./cmd/server/main.go
 	# go build -ldflags "-w -s -X main.GoVersion=$(GO_VERS) -X main.Version=${TAG} -X main.Date=${BUILD_DATE}" -o ./bin_dev/wartank_dev ./cmd/server/main.go
 	go build -race -o ./bin_dev/wartank_dev ./cmd/server/main.go
 	./run_dev.sh

+ 51 - 121
app/lev0/proc/proc_fuel_attack/proc_fuel_attack.go → app/lev0/bfunc/bf_fuel_attack/bf_fuel_attack.go

@@ -1,131 +1,64 @@
-// package fuel_attack -- объект боя на топливе
-package proc_fuel_attack
+// package bf_fuel_attack -- бизнес-процесс боя на топливе
+package bf_fuel_attack
 
 import (
 	"fmt"
-	"log"
 	"os"
 	"strings"
 	"time"
 
+	. "gitp78su.ipnodns.ru/svi/kern/kc/helpers"
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	"wartank/app/lev0/cons"
 	. "wartank/app/lev0/types"
-	"wartank/app/lev2/arena"
 )
 
-// ТопливоБой -- объект боя на топливе
-type ТопливоБой struct {
-	ИАрена
-	ангар  ИАренаАнгар
-	клиент ИХттпВоркер
-}
-
-// НовТопливоБой -- возвращает новый *ТопливоБойNet
-func НовТопливоБой(конт ИБотКонтекст, ангар ИАренаАнгар) (*ТопливоБой, error) {
-	хттпВоркер := конт.Get("хттпВоркер").(ИХттпВоркер)
-	сам := &ТопливоБой{
-		ангар:  ангар,
-		клиент: хттпВоркер,
+// ТопливоАтаковать -- бой на топливе
+func ТопливоАтаковать(конт ILocalCtx) {
+	ангар := конт.Get("ангар").Val().(ИАренаАнгар)
+	топливо := ангар.Топливо().Получ()
+	if топливо < cons.ТопливоМин { // Минимальная ёмкость бака -- 315
+		return
 	}
-
-	аренаКонфиг := arena.АренаКонфиг{
-		Бот_:         ангар.Бот(),
-		АренаИмя_:    "ТопливоБой",
-		СтрКонтроль_: `<title>Бой</title>`,
-		ФнПуск_:      сам.пуск,
-		СтрУрл_:      "https://wartank.ru/battle",
-	}
-	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
-	_ = ИАрена(сам)
-	return сам, nil
+	списСтрБой := начатьБой(конт)
+	списВыстрел1 := выбратьБойСлабый(конт, списСтрБой)
+	сделатьВыстрелы(конт, списВыстрел1)
 }
 
-func (сам *ТопливоБой) пуск() {
-	for {
-		time.Sleep(time.Second * 30) // Минимальный интервал ожидания прибавки топлива
-		// сам.топливоПолуч()
-		топливо := сам.ангар.Топливо().Получ()
-		if топливо < cons.ТопливоМин { // Минимальная ёмкость бака -- 315
-			continue
-		}
-		log.Printf("Fuel.Run: val=%v\n", топливо)
-		списСтрБой, err := сам.начатьБой()
-		if err != nil {
-			// log._rintf("ERRO ТопливоБой.findFuel(): in get page battle, err=\n\t%v\n", err)
-			continue
-		}
-		списВыстрел1, err := сам.выбратьБойСлабый(списСтрБой)
-		if err != nil {
-			// log._rintf("ERRO ТопливоБой.findFuel(): in get page shooting, err=\n\t%v\n", err)
-			continue
-		}
-		if err := сам.сделатьВыстрелы(списВыстрел1); err != nil {
-			log.Printf("ERRO ТопливоБой.findFuel(): in make shooting, err=\n\t%v\n", err)
-		}
-	}
-}
-
-// Получает количество топлива
-
 // Идёт в атаку, если топлива больше cons.ТопливоМин
-func (сам *ТопливоБой) начатьБой() (списСтрБой []string, err error) {
+func начатьБой(конт ILocalCtx) []string {
 	// Получить ссылку на атаку
-	// _mt.Println("\t ТопливоБой.начатьБой()")
-	списАнгар := сам.ангар.СписПолучить()
-	var стрАнализ string
+	ангар := конт.Get("ангар").Val().(ИАренаАнгар)
+	списАнгар := ангар.СписПолучить()
+	var (
+		стрАнализ string
+		еслиЕсть  bool
+	)
 	for _, стрАтак := range списАнгар {
 		if strings.Contains(стрАтак, `<span>В бой!</span>`) {
 			стрАнализ = стрАтак
+			еслиЕсть = true
 			break
 		}
 	}
+	Hassert(еслиЕсть, "начатьБой(): не найдена строка 'Начать бой'")
 	// Вырезать ссылку на атаку
 	списАнгар = strings.Split(стрАнализ, `<a class="simple-but border mb1" href="`)
-	if len(списАнгар) < 2 { // Не та страница
-		return nil, fmt.Errorf("ТопливоБой.начатьБой(): список строк для атаки пустой")
-	}
+	Hassert(len(списАнгар) >= 2, "начатьБой(): список строк для атаки пустой")
 	бойСсылка := списАнгар[1]
 	списАнгар = strings.Split(бойСсылка, `"><span><span>В бой!</span></span></a>`)
 	бойСсылка = "https://wartank.ru/" + списАнгар[0]
-	списСтрБой, err = сам.Сеть().Get(бойСсылка)
-	if err != nil {
-		return nil, fmt.Errorf("ТопливоБой.начатьБой(): in make GET-request to battle, err=\n\t%w", err)
-	}
-	return списСтрБой, nil
+	арена := конт.Get("арена_топливо").Val().(ИАрена)
+	списСтрБой, err := арена.Сеть().Get(бойСсылка)
+	Hassert(err == nil, "начатьБой(): in make GET-request to battle, err=\n\t%v", err)
+	return списСтрБой
 }
 
 // Выбирает первого более слабого противника и делает первый выстрел
-func (сам *ТопливоБой) выбратьБойСлабый(списСтрБой []string) (списСтрВыстрел1 []string, err error) {
+func выбратьБойСлабый(конт ILocalCtx, списСтрБой []string) []string {
 	// _mt.Println("\tAngarNet.makeSelectBattle()")
 	var стрАнализ string
-	defer func() {
-		if паника := recover(); паника != nil {
-			msg := time.Now().Local().Format("2006-01-02 15:04:05.000 ") + "fnShoot1\n"
-			msg += "\tNetClient.makeSelectBattle().fnShoot1()\n"
-			msg0 := fmt.Sprintf("%v\n", паника)
-			msg1 := ""
-			for _, _msg := range strings.Split(msg0, "\n") {
-				if _msg == "" {
-					continue
-				}
-				msg1 += "\t" + _msg + "\n"
-			}
-			msg += msg1
-			// _mt.Println(msg)
-			err = fmt.Errorf("%v", msg)
-			msg1 = "" // Сброс накопленной ошибки
-			for _, _msg := range списСтрБой {
-				if _msg == "" {
-					continue
-				}
-				msg1 += "\t" + _msg + "\n"
-			}
-			msg += msg1
-			// Выкинуть ошибку в файл
-			_ = os.MkdirAll("./errors", 0700)
-			err = os.WriteFile("./errors/attack_shoot1.html", []byte(msg), 0600)
-		}
-	}()
 	// Выдернуть строку с первой ссылкой на противника
 	for _, стрБой_ := range списСтрБой {
 		if strings.Contains(стрБой_, `opponents-opponents-0`) {
@@ -136,7 +69,7 @@ func (сам *ТопливоБой) выбратьБойСлабый(списС
 	var ссылкаБой string
 	switch стрАнализ == "" {
 	case true: // Такая ситуация возможна, если уже были какие-то выстрелы
-		return списСтрБой, nil
+		return списСтрБой
 	default: // Успешный выстрел
 		// Вырезать ссылку из строки
 		списСтрБой = strings.Split(стрАнализ, `<td class="cntr"><a href="`)
@@ -144,17 +77,18 @@ func (сам *ТопливоБой) выбратьБойСлабый(списС
 		списСтрБой = strings.Split(ссылкаБой, `"><img class="tank-img" alt="tank" src="/tankimg?`)
 		ссылкаБой = "https://wartank.ru/" + списСтрБой[0]
 	}
-	списСтрВыстрел1, err = сам.Сеть().Get(ссылкаБой)
-	if err != nil {
-		return nil, fmt.Errorf("ТопливоБой.makeSelectBattle(): in GET-response select battle tank, err=\n\t%w", err)
-	}
-	return списСтрВыстрел1, nil
+	арена := конт.Get("арена_топливо").Val().(ИАрена)
+	списСтрВыстрел1, err := арена.Сеть().Get(ссылкаБой)
+	Hassert(err == nil, "makeSelectBattle(): in GET-response select battle tank, err=\n\t%v", err)
+	return списСтрВыстрел1
 }
 
 // Ведёт бой в 2 выстрела (здесь только 2 и 3 выстрел -- первый сделан при слабом противнике)
-func (сам *ТопливоБой) сделатьВыстрелы(lstShoot2 []string) error {
+func сделатьВыстрелы(конт ILocalCtx, lstShoot2 []string) {
 	// _mt.Println("\tAngarNet.makeShooting()")
-	var списВыстрел3 []string          // Тело страницы для третьего выстрела
+	var списВыстрел3 []string // Тело страницы для третьего выстрела
+	арена := конт.Get("арена_топливо").Val().(ИАрена)
+	ангар := конт.Get("ангар").Val().(ИАренаАнгар)
 	фнВыстрел2 := func() (err error) { // Второй выстрел
 		// _mt.Println("\tAngarNet.makeShooting().fnShoot2()")
 		defer func() {
@@ -218,18 +152,16 @@ func (сам *ТопливоБой) сделатьВыстрелы(lstShoot2 []s
 			lstShoot2 = strings.Split(linkShoot2, `"><span><span>Добить</span></span></a>`)
 			linkShoot2 = "https://wartank.ru/" + lstShoot2[0]
 		}
-		списВыстрел3, err = сам.Сеть().Get(linkShoot2)
-		if err != nil {
-			return fmt.Errorf("ТопливоБой.makeShooting(): in Get-response shoot2, err=\n\t%w", err)
-		}
-		fuel := сам.ангар.Топливо().Получ()
+		_, err = арена.Сеть().Get(linkShoot2)
+		Hassert(err == nil, "сделатьВыстрелы(): in Get-response shoot2, err=\n\t%v", err)
+
+		fuel := ангар.Топливо().Получ()
 		fuel -= 30
-		сам.ангар.Топливо().Уст(fuel)
+		ангар.Топливо().Уст(fuel)
 		return nil
 	}
-	if err := фнВыстрел2(); err != nil {
-		return err
-	}
+	err := фнВыстрел2()
+	Hassert(err == nil, "сделатьВыстрелы(): при выполнении выстрел-2, ош=\n\t%v", err)
 	фнВыстрел3 := func() (err error) { // Третий выстрел
 		// _mt.Println("\tAngarNet.makeShooting().fnShoot3()")
 		defer func() {
@@ -292,17 +224,15 @@ func (сам *ТопливоБой) сделатьВыстрелы(lstShoot2 []s
 			linkShoot3 = "https://wartank.ru/" + списВыстрел3[0]
 		}
 
-		if _, err = сам.Сеть().Get(linkShoot3); err != nil {
+		if _, err = арена.Сеть().Get(linkShoot3); err != nil {
 			return fmt.Errorf("ТопливоБой.makeShooting(): in Get-response shoot3, err=\n\t%w", err)
 		}
-		fuel := сам.ангар.Топливо().Получ()
+		fuel := ангар.Топливо().Получ()
 		fuel -= 30
-		сам.ангар.Топливо().Уст(fuel)
+		ангар.Топливо().Уст(fuel)
 		return nil
 	}
-	if err := фнВыстрел3(); err != nil {
-		return err
-	}
-	сам.ангар.Обновить()
-	return nil
+	err = фнВыстрел3()
+	Hassert(err == nil, "сделатьВыстрелы().фнВыстрел3(): при выстрел-3, ош=\n\t%v", err)
+	ангар.Обновить()
 }

+ 43 - 0
app/lev0/bfunc/bf_fuel_find/bf_fuel_find.go

@@ -0,0 +1,43 @@
+// package bf_fuel_find -- процесс поиска топлива в баке
+package bf_fuel_find
+
+import (
+	"strconv"
+	"strings"
+
+	. "gitp78su.ipnodns.ru/svi/kern/kc/helpers"
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
+	. "wartank/app/lev0/types"
+)
+
+// ТопливоНайти -- возвращает топливо бота
+func ТопливоНайти(конт ILocalCtx) {
+	ангар := конт.Get("ангар").Val().(ИАренаАнгар)
+	lstAngar := ангар.СписПолучить()
+	var (
+		strOut   string
+		еслиЕсть bool
+	)
+	for _, strFuel := range lstAngar {
+		if strings.Contains(strFuel, `<img title="Топливо" `) {
+			strOut = strFuel
+			еслиЕсть = true
+			break
+		}
+	}
+	Hassert(еслиЕсть, "ТопливоНайти(): нет строки топлива")
+	// Выделить топливо
+	lstFuel := strings.Split(strOut, `<img title="Топливо" alt="Топливо" src="/images/icons/fuel.png?2"/> `)
+	// Здесь бывает ошибка (когда возвращена пустая строка)
+	Hassert(len(lstFuel) == 2, "Обновить(): при поиске строки топлива, стр=\n\t%v\n", strOut)
+	Hassert(lstFuel[1] != "", "Обновить(): пустое значение в строке топлива, стр=\n\t%v\n", strOut)
+	strFuel := lstFuel[1]
+	iFuel, err := strconv.Atoi(strFuel)
+	Hassert(err == nil, "ТопливоНайти(): топливо(%v) не число", iFuel)
+	ангар.Топливо().Уст(iFuel)
+	if iFuel <= 314 { // Минимальное значение "топливного склада-1" -- 315
+		return
+	}
+	конт.Set("топливо", iFuel, "Топливо бота")
+}

+ 41 - 0
app/lev0/bfunc/bf_gold_find/bf_gold_find.go

@@ -0,0 +1,41 @@
+// package bf_gold_find -- бизнес-процесс поиска золота
+package bf_gold_find
+
+import (
+	"strconv"
+	"strings"
+
+	. "gitp78su.ipnodns.ru/svi/kern/kc/helpers"
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
+	. "wartank/app/lev0/types"
+)
+
+// ЗолотоНайти -- ищет золото бота
+func ЗолотоНайти(конт ILocalCtx) {
+	ангар := конт.Get("ангар").Val().(ИАренаАнгар)
+	var (
+		lstAngar    = ангар.СписПолучить()
+		strOut      string
+		еслиНайдено bool
+	)
+	if len(lstAngar) == 0 {
+		ангар.Обновить()
+		lstAngar = ангар.СписПолучить()
+	}
+	for _, strGold := range lstAngar {
+		if strings.Contains(strGold, `<img title="Золото" `) {
+			strOut = strGold
+			еслиНайдено = true
+			break
+		}
+	}
+	Hassert(еслиНайдено, "ЗолотоНайти(): не найдена строка золота")
+	// Выделить топливо
+	lstGold := strings.Split(strOut, `<img title="Золото" alt="Золото" src="/images/icons/gold.png?2"/> `)
+	strGold := lstGold[1]
+	iGold, err := strconv.Atoi(strGold)
+	Hassert(err == nil, "ЗолотоНайти(): iGold(%v) не число, ош=%v", iGold, err)
+	ангар.Золото().Уст(iGold)
+	конт.Set("золото", iGold, "Золото бота")
+}

+ 37 - 0
app/lev0/bfunc/bf_silver_find/bf_silver_find.go

@@ -0,0 +1,37 @@
+// package bf_silver_find -- ищет серебро бота
+package bf_silver_find
+
+import (
+	"strconv"
+	"strings"
+
+	. "gitp78su.ipnodns.ru/svi/kern/kc/helpers"
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
+	. "wartank/app/lev0/types"
+)
+
+// СереброНайти -- ищет серебро бота
+func СереброНайти(конт ILocalCtx) {
+	ангар := конт.Get("ангар").Val().(ИАренаАнгар)
+	lstAngar := ангар.СписПолучить()
+	var (
+		strOut   string
+		еслиЕсть bool
+	)
+	for _, strSilver := range lstAngar {
+		if strings.Contains(strSilver, `<img title="Серебро" `) {
+			strOut = strSilver
+			еслиЕсть = true
+			break
+		}
+	}
+	Hassert(еслиЕсть, "СереброНайти()Ж строка серебра не найдена")
+	// Выделить топливо
+	lstSilver := strings.Split(strOut, `<img title="Серебро" alt="Серебро" src="/images/icons/silver.png?2"/> `)
+	strSilver := lstSilver[1]
+	iSilver, err := strconv.Atoi(strSilver)
+	Hassert(err == nil, "СереброНайти(): серебро(%v) не число", iSilver)
+	конт.Set("серебро", iSilver, "Серебро бота")
+	ангар.Серебро().Уст(iSilver)
+}

+ 2 - 0
app/lev0/bfunc/bfunc.go

@@ -0,0 +1,2 @@
+// package bfunc -- бизнес-функции
+package bfunc

+ 0 - 87
app/lev0/proc/proc_fuel_find/proc_fuel_find.go

@@ -1,87 +0,0 @@
-// package proc_fuel_find -- процесс поиска топлива в баке
-package proc_fuel_find
-
-import (
-	"strconv"
-	"strings"
-	"time"
-
-	. "gitp78su.ipnodns.ru/svi/kern"
-	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
-
-	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
-)
-
-// Топливо -- процесс поиска топлива в баке +1 каждые 15 сек
-type ПроцессТопливоНайти struct {
-	ИАренаАнгар
-	лог     ILogBuf
-	топливо ИСтатПарам
-}
-
-// НовТопливо -- возвращает новый топливный бак
-func НовПроцессТопливоНайти(конт ИБотКонтекст) ИПроцессТопливоНайти {
-
-	сам := &ПроцессТопливоНайти{
-		ИАренаАнгар: конт.Get("ангар").(ИАренаАнгар),
-		лог:         NewLogBuf(),
-		топливо:     stat_param.НовСтатПарам_("топливо"),
-	}
-	сам.лог.Debug("НовПроцессТопливоНайти\n")
-	конт.Set("проц_поиск_топливо", сам, "Процесс поиска топлива")
-	return сам
-}
-
-// Пуск -- блокирующий вызов поиска количества топлива
-func (сам *ПроцессТопливоНайти) Пуск() {
-	// Каждые 15 сек +1 топливо
-	for {
-		time.Sleep(time.Second * 15)
-		топливо := сам.топливо.Получ()
-		топливо++
-		сам.топливо.Уст(топливо)
-		// log.Printf("Fuel.Run: val=%v\n", fuel)
-	}
-}
-
-// Обновить -- ищет в теле текста ангара топливо
-func (сам *ПроцессТопливоНайти) Обновить() {
-	// _mt.Println("\tAngarNet.findFuel()")
-	сам.ИАренаАнгар.Обновить()
-	lstAngar := сам.СписПолучить()
-	var strOut string
-	for _, strFuel := range lstAngar {
-		if strings.Contains(strFuel, `<img title="Топливо" `) {
-			strOut = strFuel
-			break
-		}
-	}
-	// Выделить топливо
-	lstFuel := strings.Split(strOut, `<img title="Топливо" alt="Топливо" src="/images/icons/fuel.png?2"/> `)
-	// Здесь бывает ошибка (когда возвращена пустая строка)
-	if len(lstFuel) != 2 {
-		сам.лог.Err("Обновить(): бот=%q, при поиске строки топлива, стр=\n\t%v\n", сам.Бот().Имя(), strOut)
-		return
-	}
-	if lstFuel[1] == "" {
-		сам.лог.Err("Обновить(): %q, пустое значение в строке топлива, стр=\n\t%v\n", сам.Бот().Имя(), strOut)
-		return
-	}
-	strFuel := lstFuel[1]
-	iFuel, err := strconv.Atoi(strFuel)
-	if err != nil {
-		// log._rintf("ERRO Fuel.findFuel(): fuel(%v) not number, err=\n\t%v\n", strFuel, err)
-		return
-	}
-	сам.топливо.Уст(iFuel)
-	if iFuel <= 314 { // Минимальное значение "топливного склада-1" -- 315
-		return
-	}
-	// log._rintf("Fuel.findFuel():iFuel=%v\n", iFuel)
-}
-
-// Fuel -- возвращает объект статического параметра топлива
-func (сам *ПроцессТопливоНайти) Fuel() ИСтатПарам {
-	return сам.топливо
-}

+ 5 - 7
app/lev0/types/iapp.go

@@ -1,18 +1,16 @@
 package types
 
-import (
-	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
-)
-
 /*
 	Интерфейс для приложения
 */
 
+import (
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+)
+
 // ИСервер -- интерфейс для приложения
 type ИПриложение interface {
-	IKernelCtx
-	// Пуск -- запускает приложение в работу
-	Пуск()
+	IKernelModule
 	// ServBots -- словарь имеющихся ботов
 	ServBots() ИБотоФерма
 	// Стат -- возвращает статистику сервера

+ 0 - 4
app/lev0/types/ibot.go

@@ -13,8 +13,6 @@ type ИБот interface {
 	Пароль() string
 	// Номер -- возвращает номер бота
 	Номер() АБотНомер
-	// Ангар -- возвращает ангар бота
-	Ангар() ИАренаАнгар
 	// Стата -- возвращает статистику танка
 	Стата() ИТанкСтат
 	// Сеть -- возвращает объект сети
@@ -25,8 +23,6 @@ type ИБот interface {
 	Автозапуск() ISafeBoolReact
 	// ЕслиРабота -- признак, что бот работает
 	ЕслиРабота() bool
-	// Закончить -- отменяет контекст бота
-	Закончить()
 	//  КонтБот -- возвращает контекст бота
 	КонтБот() ILocalCtx
 }

+ 0 - 10
app/lev0/types/ibot_context.go

@@ -1,10 +0,0 @@
-package types
-
-import (
-	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
-)
-
-// ИБотКонтекст -- контекст бота
-type ИБотКонтекст interface {
-	ILocalCtx
-}

+ 2 - 0
app/lev0/types/itank_stat.go

@@ -20,4 +20,6 @@ type ИТанкСтат interface {
 	Форсаж() ИСтатПарам
 	// ФорсажОбнов -- обновляет параметры форсажа
 	ФорсажОбнов(имя string, парам int)
+	// Слава -- возвращает количество славы
+	Слава() ИСтатПарам
 }

+ 0 - 7
app/lev0/types/iweb_server.go

@@ -1,7 +0,0 @@
-package types
-
-// ИВебСервер -- интерфейс к веб-серверу
-type ИВебСервер interface {
-	// КонтБот -- возвращает контекст бота
-	КонтБот() ИБотКонтекст
-}

+ 1 - 1
app/lev1/lev1.go

@@ -8,5 +8,5 @@ import (
 
 // НовСтатПарам -- возвращает новый ИСтатПарам
 func НовСтатПарам(имя string) ИСтатПарам {
-	return stat_param.НовСтатПарам_(имя)
+	return stat_param.НовСтатПарам1(имя)
 }

+ 2 - 2
app/lev1/stat_param/stat_param.go

@@ -20,8 +20,8 @@ type статПарам struct {
 	лог  ILogBuf
 }
 
-// НовБотСтатистика -- возвращает новую статистику
-func НовСтатПарам_(имя string) ИСтатПарам {
+// НовСтатПарам1 -- возвращает новую статистику
+func НовСтатПарам1(имя string) ИСтатПарам {
 	Hassert(имя != "", "НовСтатПарам(): имя параметра пустое\n")
 	сам := &статПарам{
 		имя: имя,

+ 10 - 1
app/lev1/web_render/web_render.go

@@ -17,6 +17,7 @@ import (
 type ВебРендер struct {
 	лог     ILogBuf
 	слвБлок map[string]interface{}
+	шаблон string
 }
 
 //go:embed base.tmpl.html
@@ -34,6 +35,7 @@ func НовВебРендер(шаблон string) *ВебРендер {
 	сам := &ВебРендер{
 		лог:     лог,
 		слвБлок: map[string]interface{}{},
+		шаблон: шаблон,
 	}
 	сам.слвБлок["{.header}"] = стрЗаголовок
 	сам.слвБлок["{.main}"] = шаблон
@@ -45,8 +47,15 @@ func НовВебРендер(шаблон string) *ВебРендер {
 // Получ -- возвращает результат рендеринга
 func (сам *ВебРендер) Получ() string {
 	рез := стрБаза
+	рез = strings.ReplaceAll(рез, "{.header}", стрЗаголовок)
+	рез = strings.ReplaceAll(рез, "{.main}", сам.шаблон)
+	рез = strings.ReplaceAll(рез, "{.footer}", стрПодвал)
 	for ключ, блок := range сам.слвБлок {
-		рез = strings.ReplaceAll(рез, ключ, fmt.Sprint(блок))
+		знач:=fmt.Sprint(блок)
+		if ключ=="{.id}"{
+			рез = strings.ReplaceAll(рез, ключ, знач)
+		}
+		рез = strings.ReplaceAll(рез, ключ, знач)
 	}
 	return рез
 }

+ 5 - 3
app/lev2/arena/arena.go

@@ -5,6 +5,10 @@ import (
 	"fmt"
 	"log"
 	"sync"
+
+	. "gitp78su.ipnodns.ru/svi/kern/kc/helpers"
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	"wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
 	"wartank/app/lev1"
@@ -12,8 +16,6 @@ import (
 	"wartank/app/lev2/arena/arena_net"
 	"wartank/app/lev2/arena/arena_string"
 	"wartank/app/lev2/arena/down_time"
-
-	. "gitp78su.ipnodns.ru/svi/kern/kc/helpers"
 )
 
 // АренаКонфиг -- конфигурация арены
@@ -46,7 +48,7 @@ type Арена struct {
 }
 
 // НовАрена -- возвращает новую арену игры
-func НовАрена(конт ИБотКонтекст, конф АренаКонфиг) ИАрена {
+func НовАрена(конт ILocalCtx, конф АренаКонфиг) ИАрена {
 	log.Printf("НовАрена(): стрКонтроль=%q\n", конф.СтрКонтроль_)
 	конф.контроль()
 	аренаКонтекст := arena_context.НовАренаКонтекст(конт, конф.Бот_, конф.АренаИмя_)

+ 19 - 76
app/lev2/arena/arena_angar/arena_angar.go

@@ -2,12 +2,13 @@ package arena_angar
 
 import (
 	"log"
-	"strconv"
-	"strings"
 	"time"
 
+	. "gitp78su.ipnodns.ru/svi/kern/kc/helpers"
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
+	"wartank/app/lev1"
 	"wartank/app/lev2/arena"
 	"wartank/app/lev3/bot/bot_stat/bot_resurs"
 )
@@ -19,7 +20,7 @@ import (
 // Ангар -- ангар для танка
 type АренаАнгар struct {
 	ИАрена
-	прилож        ИПриложение
+	конт          ILocalCtx
 	бот           ИБот
 	progress      ИСтатПарам
 	топливо       ИСтатПарам
@@ -34,15 +35,19 @@ type АренаАнгар struct {
 }
 
 // НовАнгар -- возвращает новый *Angar
-func НовАнгар(конт ИБотКонтекст) ИАренаАнгар {
-	бот := конт.Get("бот").(ИБот)
+func НовАнгар(конт ILocalCtx) ИАренаАнгар {
+	Hassert(конт != nil, "НовАнгар(): ILocalCtx==nil")
+	бот := конт.Get("бот").Val().(ИБот)
 	сам := &АренаАнгар{
+		конт:          конт,
 		бот:           бот,
-		progress:      stat_param.НовСтатПарам_("прогресс"),
-		игроковОнлайн: stat_param.НовСтатПарам_("онлайн"),
-		сереброСессия: stat_param.НовСтатПарам_("серебро сессия"),
-		танкСтат:      конт.Get("танкПарам").(ИТанкСтат),
-		серебро:       stat_param.НовСтатПарам_("серебро"),
+		progress:      lev1.НовСтатПарам("прогресс"),
+		игроковОнлайн: lev1.НовСтатПарам("онлайн"),
+		сереброСессия: lev1.НовСтатПарам("серебро сессия"),
+		танкСтат:      конт.Get("танкСтат").Val().(ИТанкСтат),
+		серебро:       lev1.НовСтатПарам("серебро"),
+		золото:        lev1.НовСтатПарам("золото"),
+		топливо:       lev1.НовСтатПарам("топливо"),
 	}
 	аренаКонф := arena.АренаКонфиг{
 		Бот_:         бот,
@@ -77,11 +82,6 @@ func (сам *АренаАнгар) Серебро() ИСтатПарам {
 	return сам.серебро
 }
 
-// Обновить -- обновить ангар принудительно
-func (сам *АренаАнгар) Обновить() {
-	сам.РесурсыОбновить()
-}
-
 // Запускает обработку ангара
 func (сам *АренаАнгар) пуск() {
 	{ // Запуск компонентов
@@ -90,7 +90,7 @@ func (сам *АренаАнгар) пуск() {
 		сам.Обновить()
 		// сам.конвойПроверить()
 		if err := сам.ОбратВремяУст("01:00"); err != nil {
-			сам.прилож.Cancel()
+			сам.конт.Cancel()
 			log.Printf("Ангар.Run(): in update ICountTime, err=\n\t%v\n", err)
 			return false
 		}
@@ -100,12 +100,12 @@ func (сам *АренаАнгар) пуск() {
 		ош := сам.ОбратВремяУст("01")
 		if ош != nil {
 			log.Printf("Ангар.Run(): in update ICountTime, ош=\n\t%v\n", ош)
-			сам.прилож.Cancel()
+			сам.конт.Cancel()
 			return
 		}
 		for {
 			select {
-			case <-сам.прилож.Ctx().Done(): // Отмена контекста
+			case <-сам.конт.Ctx().Done(): // Отмена контекста
 				return
 			case <-сам.ВремяОстат().КаналСиг(): // Метка времени
 				if !фнЦикл() {
@@ -121,13 +121,6 @@ func (сам *АренаАнгар) пуск() {
 	}()
 }
 
-// Обновляет ресурсы ангара
-func (сам *АренаАнгар) РесурсыОбновить() {
-	сам.ИАрена.Обновить()
-	сам.золотоНайти()
-	сам.сереброНайти()
-}
-
 // Прогресс -- возвращает прогресс уровня игрока
 func (сам *АренаАнгар) Прогресс() ИСтатПарам {
 	return сам.progress
@@ -137,53 +130,3 @@ func (сам *АренаАнгар) Прогресс() ИСтатПарам {
 func (сам *АренаАнгар) ИгрокиОнлайн() ИСтатПарам {
 	return сам.игроковОнлайн
 }
-
-// Ищет в теле текста ангара серебро
-func (сам *АренаАнгар) сереброНайти() {
-	// _mt.Println("\tAngarNet.findSilver()")
-	lstAngar := сам.СписПолучить()
-	var strOut string
-	for _, strSilver := range lstAngar {
-		if strings.Contains(strSilver, `<img title="Серебро" `) {
-			strOut = strSilver
-			break
-		}
-	}
-	// Выделить топливо
-	lstSilver := strings.Split(strOut, `<img title="Серебро" alt="Серебро" src="/images/icons/silver.png?2"/> `)
-	strSilver := lstSilver[1]
-	_, err := strconv.Atoi(strSilver)
-	if err != nil {
-		// log._rintf("ERRO AngarNet.findSilver(): silver(%v) not number, err=\n\t%v\n", strSilver, err)
-		return
-	}
-}
-
-// Ищет в теле текста ангара золото
-func (сам *АренаАнгар) золотоНайти() {
-	var (
-		lstAngar    = сам.бот.Ангар().СписПолучить()
-		strOut      string
-		еслиНайдено bool
-	)
-
-	for _, strGold := range lstAngar {
-		if strings.Contains(strGold, `<img title="Золото" `) {
-			strOut = strGold
-			еслиНайдено = true
-			break
-		}
-	}
-	if !еслиНайдено {
-		return
-	}
-	// Выделить топливо
-	lstGold := strings.Split(strOut, `<img title="Золото" alt="Золото" src="/images/icons/gold.png?2"/> `)
-	strGold := lstGold[1]
-	iGold, err := strconv.Atoi(strGold)
-	if err != nil {
-		// log._rintf("ERRO AngarNet.findGold(): gold(%v) not number, err=\n\t%v\n", strGold, err)
-		return
-	}
-	сам.бот.Ангар().Золото().Уст(iGold)
-}

+ 19 - 22
app/lev2/arena/arena_arsenal/arena_arsenal.go

@@ -2,7 +2,6 @@
 package arena_arsenal
 
 import (
-	"context"
 	"fmt"
 	"log"
 	"strconv"
@@ -10,7 +9,7 @@ import (
 	"time"
 
 	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
+	"wartank/app/lev1"
 	"wartank/app/lev1/web_log"
 	"wartank/app/lev2/arena"
 
@@ -36,34 +35,31 @@ type АренаАрсенал struct {
 	бронебойка   ИСтатПарам
 	кумулятив    ИСтатПарам
 	ремка        ИСтатПарам
-	продуктИмя   string          // Что сейчас делается
-	продуктКол   ИСтатПарам      // Сколько делается прямо сейчас
-	продуктВремя string          // Сколько осталось времени прямо сейчас
-	кнт          context.Context // контекст шахты
-	фнОтмена     func()          // Функция отмены шахты
+	продуктИмя   string     // Что сейчас делается
+	продуктКол   ИСтатПарам // Сколько делается прямо сейчас
+	продуктВремя string     // Сколько осталось времени прямо сейчас
+	конт         ILocalCtx
 }
 
 // НовАрсенал -- возвращает новый *Arsenal
-func НовАрсенал(конт ИБотКонтекст, база ИАренаБаза) (ИАренаАрсенал, error) {
+func НовАрсенал(конт ILocalCtx) ИАренаАрсенал {
 	лог := NewLogBuf()
 	лог.Info("НовАрсенал()\n")
 
-	кнт, фнОтмена := context.WithCancel(база.Контекст())
 	сам := &АренаАрсенал{
-		бот:        база.Бот(),
-		база:       база,
-		фугас:      stat_param.НовСтатПарам_(стрФугасы),
-		бронебойка: stat_param.НовСтатПарам_(стрБронебойки),
-		кумулятив:  stat_param.НовСтатПарам_(стрКумулятивы),
-		ремка:      stat_param.НовСтатПарам_(стрРемки),
-		продуктКол: stat_param.НовСтатПарам_("свинец"),
-		кнт:        кнт,
-		фнОтмена:   фнОтмена,
+		бот:        конт.Get("бот").Val().(ИБот),
+		база:       конт.Get("база").Val().(ИАренаБаза),
+		фугас:      lev1.НовСтатПарам(стрФугасы),
+		бронебойка: lev1.НовСтатПарам(стрБронебойки),
+		кумулятив:  lev1.НовСтатПарам(стрКумулятивы),
+		ремка:      lev1.НовСтатПарам(стрРемки),
+		продуктКол: lev1.НовСтатПарам("свинец"),
+		конт:       конт,
 
 		лог: лог,
 	}
 	аренаКонфиг := arena.АренаКонфиг{
-		Бот_:         база.Бот(),
+		Бот_:         сам.бот,
 		АренаИмя_:    "Арсенал",
 		СтрКонтроль_: `<span class="green2">Ремкомплект</span><br/>`,
 		ФнПуск_:      сам.пуск,
@@ -71,9 +67,10 @@ func НовАрсенал(конт ИБотКонтекст, база ИАрен
 	}
 	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
 	сам.вЛог = web_log.НовВебЛог(true)
-	go сам.пуск()
+	// go сам.пуск()
 	сам.вЛог.Добавить("НовАрсенал(): Арсенал создан")
-	return сам, nil
+	конт.Set("арсенал", сам, "Арсенал бота")
+	return сам
 }
 
 // ПродуктКолСейчас -- возвращает количество производимого продукта
@@ -99,7 +96,7 @@ func (сам *АренаАрсенал) пуск() {
 		defer func() {
 			for сам.ВремяОстат().ПолучМилСек() > 0 {
 				select {
-				case <-сам.кнт.Done():
+				case <-сам.конт.Ctx().Done():
 					return
 				default:
 					time.Sleep(time.Second * 5)

+ 5 - 3
app/lev2/arena/arena_bank/arena_bank.go

@@ -7,9 +7,11 @@ import (
 	"strings"
 	"time"
 
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
+	"wartank/app/lev1"
 	"wartank/app/lev2/arena"
 	"wartank/app/lev2/arena/arena_bank/bank_mode"
 )
@@ -27,10 +29,10 @@ type АренаБанк struct {
 }
 
 // НовБанк -- возвращает новый арену банка
-func НовБанк(конт ИБотКонтекст) ИАренаБанк {
+func НовБанк(конт ILocalCtx) ИАренаБанк {
 
 	сам := &АренаБанк{
-		сереброБот: stat_param.НовСтатПарам_("серебро бота"),
+		сереброБот: lev1.НовСтатПарам("серебро бота"),
 		режим1:     bank_mode.NewBankMode(конт),
 		режим2:     bank_mode.NewBankMode(конт),
 	}

+ 5 - 3
app/lev2/arena/arena_bank/bank_mode/bank_mode.go

@@ -1,8 +1,10 @@
 package bank_mode
 
 import (
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
+	"wartank/app/lev1"
 )
 
 /*
@@ -16,9 +18,9 @@ type BankMode struct {
 }
 
 // NewBankMode -- возвращает новый *BankMode
-func NewBankMode(конт ИБотКонтекст) *BankMode {
+func NewBankMode(конт ILocalCtx) *BankMode {
 	return &BankMode{
-		серебро: stat_param.НовСтатПарам_("серебро"),
+		серебро: lev1.НовСтатПарам("серебро"),
 	}
 }
 

+ 5 - 2
app/lev2/arena/arena_base/arena_base.go

@@ -7,6 +7,8 @@ import (
 	"sync"
 	"time"
 
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/types"
 	"wartank/app/lev2/arena"
 )
@@ -28,8 +30,8 @@ type АренаБаза struct {
 }
 
 // НовБаза -- возвращает новую базу бота
-func НовБаза(конт ИБотКонтекст) ИАренаБаза {
-	бот := конт.Get("бот").(ИБот)
+func НовБаза(конт ILocalCtx) ИАренаБаза {
+	бот := конт.Get("бот").Val().(ИБот)
 	log.Printf("НовБаза(): %q\n", бот.Имя())
 	сам := &АренаБаза{
 		бот: бот,
@@ -42,6 +44,7 @@ func НовБаза(конт ИБотКонтекст) ИАренаБаза {
 		СтрУрл_:      "https://wartank.ru/buildings",
 	}
 	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
+	конт.Set("база", сам, "База бота")
 	return сам
 }
 

+ 3 - 1
app/lev2/arena/arena_battle/arena_battle.go

@@ -4,6 +4,8 @@ package arena_battle
 import (
 	"time"
 
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/types"
 	"wartank/app/lev2/arena"
 	"wartank/app/lev2/arena/arena_battle/battle_register"
@@ -24,7 +26,7 @@ type АренаСражение struct {
 }
 
 // НовСражение -- возвращает новый *Battle
-func НовСражение(конт ИБотКонтекст, бот ИБот) *АренаСражение {
+func НовСражение(конт ILocalCtx, бот ИБот) *АренаСражение {
 	сам := &АренаСражение{
 		бот:    бот,
 		клиент: бот.Сеть().ВебВоркер(),

+ 3 - 1
app/lev2/arena/arena_battle/battle_register/battle_register.go

@@ -6,6 +6,8 @@ import (
 	"strings"
 	"time"
 
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/types"
 	"wartank/app/lev2/arena"
 )
@@ -18,7 +20,7 @@ type СхваткаРегистрация struct {
 }
 
 // НовСражениеРегистрация -- возвращает новый ожидатель битвы
-func НовСражениеРегистрация(конт ИБотКонтекст, бот ИБот) *СхваткаРегистрация {
+func НовСражениеРегистрация(конт ILocalCtx, бот ИБот) *СхваткаРегистрация {
 	сам := &СхваткаРегистрация{
 		бот:          бот,
 		счётРегистер: 10_000,

+ 3 - 1
app/lev2/arena/arena_battle/battle_wait/battle_wait.go

@@ -5,6 +5,8 @@ import (
 	"strings"
 	"time"
 
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
 	"wartank/app/lev2/arena"
@@ -17,7 +19,7 @@ type СхваткаОжидание struct {
 }
 
 // НовСражениеОжидание -- возвращает новый ожидатель битвы
-func НовСражениеОжидание(конт ИБотКонтекст, бот ИБот) *СхваткаОжидание {
+func НовСражениеОжидание(конт ILocalCtx, бот ИБот) *СхваткаОжидание {
 	сам := &СхваткаОжидание{
 		бот: бот,
 	}

+ 6 - 4
app/lev2/arena/arena_battle/battle_worker/battle_worker.go

@@ -4,8 +4,10 @@ package battle_worker
 import (
 	"time"
 
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
+	"wartank/app/lev1"
 	"wartank/app/lev2/arena"
 	"wartank/app/lev2/arena/arena_battle/battle_worker/battle_worker"
 	"wartank/app/lev2/arena/arena_battle/battle_worker/battle_worker/battle_sound"
@@ -14,7 +16,7 @@ import (
 // СражениеДействие -- исполнение битвы
 type СхваткаИсполнитель struct {
 	ИАрена
-	конт ИБотКонтекст
+	конт ILocalCtx
 	бот  ИБот
 
 	еслиНачало ИСтатПарам
@@ -26,11 +28,11 @@ type СхваткаИсполнитель struct {
 }
 
 // НовСражениеДействие -- возвращает новый исполнитель битвы
-func НовСражениеИсполнитель(конт ИБотКонтекст, bot ИБот) *СхваткаИсполнитель {
+func НовСражениеИсполнитель(конт ILocalCtx, bot ИБот) *СхваткаИсполнитель {
 	сам := &СхваткаИсполнитель{
 		конт:       конт,
 		бот:        bot,
-		еслиНачало: stat_param.НовСтатПарам_("тревога"),
+		еслиНачало: lev1.НовСтатПарам("тревога"),
 		sound:      battle_sound.NewBattleSound(),
 	}
 	аренаКонфиг := arena.АренаКонфиг{

+ 1 - 1
app/lev2/arena/arena_battle/battle_worker/battle_worker/battle_worker.go

@@ -33,7 +33,7 @@ type СражениеДействие struct {
 }
 
 // НовСражениеДействие -- возвращает новый *BattleOn
-func НовСражениеДействие(конт ИБотКонтекст, бот ИБот) ИСражениеПроцесс {
+func НовСражениеДействие(конт ILocalCtx, бот ИБот) ИСражениеПроцесс {
 	// Ограничить время сражения бота
 	кнтСражение, фнОтменить := context.WithTimeout(бот.КонтБот().Ctx(), time.Second*305)
 	сам := &СражениеДействие{

+ 1 - 1
app/lev2/arena/arena_battle/battle_worker/battleon/battleon.go

@@ -33,7 +33,7 @@ type СражениеДействие struct {
 }
 
 // НовСражениеДействие -- возвращает новый *BattleOn
-func НовСражениеДействие(конт ИБотКонтекст) ИСражениеПроцесс {
+func НовСражениеДействие(конт ILocalCtx) ИСражениеПроцесс {
 	// Ограничить время сражения бота
 	бот := конт.Get("бот").Val().(ИБот)
 	кнтСражение, фнОтменить := context.WithTimeout(бот.КонтБот().Ctx(), time.Second*305)

+ 1 - 1
app/lev2/arena/arena_context/arena_context.go

@@ -26,7 +26,7 @@ type АренаКонтекст struct {
 }
 
 // НовАренаКонтекст -- возвращает новый контекст арены
-func НовАренаКонтекст(конт ИБотКонтекст, бот ИБот, сценаИмя alias.ААренаИмя) *АренаКонтекст {
+func НовАренаКонтекст(конт ILocalCtx, бот ИБот, сценаИмя alias.ААренаИмя) *АренаКонтекст {
 	Hassert(бот != nil, "НовАренаКонтекст(): ИБот==nil")
 	Hassert(сценаИмя != "", "НовАренаКонтекст(): сценаИмя не задано")
 	Hassert(конт != nil, "НовАренаКонтекст(): ИЯдроКонтекст==пусто")

+ 5 - 3
app/lev2/arena/arena_convoy/arena_convoy.go

@@ -7,9 +7,11 @@ import (
 	"strings"
 	"time"
 
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
+	"wartank/app/lev1"
 	"wartank/app/lev2/arena"
 )
 
@@ -25,10 +27,10 @@ type АренаКонвой struct {
 }
 
 // НовКонвой -- возвращает новый *Convoy
-func НовКонвой(конт ИБотКонтекст, бот ИБот) *АренаКонвой {
+func НовКонвой(конт ILocalCtx, бот ИБот) *АренаКонвой {
 	сам := &АренаКонвой{
 		бот:   бот,
-		слава: stat_param.НовСтатПарам_("слава"),
+		слава: lev1.НовСтатПарам("слава"),
 	}
 	аренаКонфиг := arena.АренаКонфиг{
 		Бот_:         сам.бот,

+ 4 - 2
app/lev2/arena/arena_death/death_worker/death_worker.go

@@ -4,6 +4,8 @@ package death_worker
 import (
 	"time"
 
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/types"
 	"wartank/app/lev1"
 	"wartank/app/lev2/arena"
@@ -14,7 +16,7 @@ import (
 // СражениеДействие -- исполнение схватки
 type СхваткаИсполнитель struct {
 	ИАрена
-	конт ИБотКонтекст
+	конт ILocalCtx
 	бот  ИБот
 
 	еслиНачало ИСтатПарам
@@ -26,7 +28,7 @@ type СхваткаИсполнитель struct {
 }
 
 // НовСражениеДействие -- возвращает новый исполнитель схватки
-func НовСхваткаИсполнитель(конт ИБотКонтекст, bot ИБот) *СхваткаИсполнитель {
+func НовСхваткаИсполнитель(конт ILocalCtx, bot ИБот) *СхваткаИсполнитель {
 	сам := &СхваткаИсполнитель{
 		конт:       конт,
 		бот:        bot,

+ 3 - 1
app/lev2/arena/arena_death/death_worker/process_death/process_death.go

@@ -4,6 +4,8 @@ import (
 	"context"
 	"time"
 
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/types"
 	"wartank/app/lev1/health"
 	"wartank/app/lev1/manevr"
@@ -30,7 +32,7 @@ type СхваткаПроцесс struct {
 }
 
 // НовСхваткаПроцесс -- возвращает новый процесс схватки
-func НовСхваткаПроцесс(конт ИБотКонтекст, бот ИБот) *СхваткаПроцесс {
+func НовСхваткаПроцесс(конт ILocalCtx, бот ИБот) *СхваткаПроцесс {
 	// Ограничить время сражения бота
 	кнтСражение, фнОтменить := context.WithTimeout(бот.КонтБот().Ctx(), time.Second*305)
 	сам := &СхваткаПроцесс{

+ 1 - 1
app/lev2/arena/arena_division/div_war/div_war.go

@@ -25,7 +25,7 @@ import (
 // DivWar -- объект ожидания битвы дивизий
 type DivWar struct {
 	ИАрена
-	конт  ИБотКонтекст
+	конт  ILocalCtx
 	bot   ИБот
 	alarm ИСтатПарам
 	net   *div_war_net.DivWarNet

+ 1 - 1
app/lev2/arena/arena_division/div_war/process_divwar/process_divwar.go

@@ -36,7 +36,7 @@ type ПроцессДивизияВойна struct {
 }
 
 // НовПроцессДивизияВойна -- возвращает новый *DivWarOn
-func НовПроцессДивизияВойна(конт ИБотКонтекст) ИСражениеПроцесс {
+func НовПроцессДивизияВойна(конт ILocalCtx) ИСражениеПроцесс {
 	лог := NewLogBuf()
 	бот := конт.Get("бот").Val().(ИБот)
 	ctxDivWar, fnCancelDivWar := context.WithTimeout(бот.КонтБот().Ctx(), time.Second*305)

+ 13 - 11
app/lev2/arena/arena_division/divwar/divwar.go

@@ -7,9 +7,11 @@ import (
 	"sync"
 	"time"
 
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
+	"wartank/app/lev1"
 	"wartank/app/lev2/arena"
 	"wartank/app/lev2/arena/arena_division/div_war/div_war_net"
 	"wartank/app/lev2/arena/arena_division/div_war/process_divwar"
@@ -23,7 +25,7 @@ import (
 // DivWar -- объект ожидания битвы дивизий
 type DivWar struct {
 	ИАрена
-	конт  ИБотКонтекст
+	конт  ILocalCtx
 	bot   ИБот
 	alarm ИСтатПарам
 	net   *div_war_net.DivWarNet
@@ -40,30 +42,30 @@ type DivWar struct {
 }
 
 // NewDivWar -- возвращает новый *DivWar
-func NewDivWar(конт ИБотКонтекст, bot ИБот) (*DivWar, error) {
-	if bot == nil {
+func NewDivWar(бот ИБот) (*DivWar, error) {
+	if бот == nil {
 		return nil, fmt.Errorf("NewDivWar(): IBot == nil")
 	}
 	сам := &DivWar{
-		конт:     конт,
-		bot:      bot,
-		alarm:    stat_param.НовСтатПарам_("тревога"),
+		конт:     бот.КонтБот(),
+		bot:      бот,
+		alarm:    lev1.НовСтатПарам("тревога"),
 		chDivWar: make(chan int, 1),
 		sound:    div_war_sound.NewDivWarSound(),
-		conn:     bot.Сеть().ВебВоркер(),
+		conn:     бот.Сеть().ВебВоркер(),
 		login:    "prospero tank",
 	}
 	аренаКонфиг := arena.АренаКонфиг{
-		Бот_:         bot,
+		Бот_:         бот,
 		АренаИмя_:    "Битва дивизий",
 		СтрКонтроль_: `<span>до начала `,
 		ФнПуск_:      сам.пуск,
 	}
-	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
+	сам.ИАрена = arena.НовАрена(сам.конт, аренаКонфиг)
 	// сам.shotTimeFull.Set(8000) // 8000 msec
 	var err error
 	{ // Net
-		сам.net, err = div_war_net.NewDivWarNet(bot)
+		сам.net, err = div_war_net.NewDivWarNet(бот)
 		if err != nil {
 			return nil, fmt.Errorf("NewDivWar(): при создании DivWarNet, err=\n\t%w", err)
 		}

+ 1 - 1
app/lev2/arena/arena_division/divwar/divwaron/divwaron.go

@@ -37,7 +37,7 @@ type DivWarOn struct {
 }
 
 // NewDivWarOn -- возвращает новый *DivWarOn
-func NewDivWarOn(конт ИБотКонтекст, bot ИБот) (*DivWarOn, error) {
+func NewDivWarOn(конт ILocalCtx, bot ИБот) (*DivWarOn, error) {
 	if bot == nil {
 		return nil, fmt.Errorf("NewDivWarOn(): IBot == nil")
 	}

+ 3 - 1
app/lev2/arena/arena_duel/arena_duel.go

@@ -4,6 +4,8 @@ package arena_duel
 import (
 	"time"
 
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/types"
 	"wartank/app/lev2/arena"
 )
@@ -16,7 +18,7 @@ type АренаДуэль struct {
 }
 
 // НовСражение -- возвращает новую арену дуэли
-func НовАренаДуэль(конт ИБотКонтекст, бот ИБот) *АренаДуэль {
+func НовАренаДуэль(конт ILocalCtx, бот ИБот) *АренаДуэль {
 	сам := &АренаДуэль{
 		бот:    бот,
 		клиент: бот.Сеть().ВебВоркер(),

+ 39 - 0
app/lev2/arena/arena_fuel/arena_fuel.go

@@ -0,0 +1,39 @@
+// package arena_fuel -- арена боя на топливе
+package arena_fuel
+
+import (
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
+	. "wartank/app/lev0/types"
+	"wartank/app/lev2/arena"
+)
+
+// АренаТопливо -- арена боя на топливе
+type АренаТопливо struct {
+	ИАрена
+	ангар  ИАренаАнгар
+	клиент ИХттпВоркер
+}
+
+// НовАренаТопливо -- возвращает новую арену топливного боя
+func НовАренаТопливо(конт ILocalCtx) *АренаТопливо {
+	хттпВоркер := конт.Get("хттпВоркер").Val().(ИХттпВоркер)
+	сам := &АренаТопливо{
+		ангар:  конт.Get("ангар").Val().(ИАренаАнгар),
+		клиент: хттпВоркер,
+	}
+
+	аренаКонфиг := arena.АренаКонфиг{
+		Бот_:         конт.Get("бот").Val().(ИБот),
+		АренаИмя_:    "ТопливоБой",
+		СтрКонтроль_: `<title>Бой</title>`,
+		ФнПуск_:      сам.пуск,
+		СтрУрл_:      "https://wartank.ru/battle",
+	}
+	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
+	конт.Set("арена_топливо", сам, "Арена 'Бой за топливо'")
+	_ = ИАрена(сам)
+	return сам
+}
+
+func (сам *АренаТопливо)пуск(){}

+ 3 - 1
app/lev2/arena/arena_fuel_storage/arena_fuel_storage.go

@@ -8,6 +8,8 @@ import (
 	"strings"
 	"time"
 
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/types"
 	"wartank/app/lev1"
 	"wartank/app/lev2/arena"
@@ -26,7 +28,7 @@ type АренаСкладТоплива struct {
 }
 
 // НовТопливо -- возвращает новой склад топлива
-func НовСкладТоплива(конт ИБотКонтекст, база ИАренаБаза) (*АренаСкладТоплива, error) {
+func НовСкладТоплива(конт ILocalCtx, база ИАренаБаза) (*АренаСкладТоплива, error) {
 	кнт, фнОтмена := context.WithCancel(база.Контекст())
 	сам := &АренаСкладТоплива{
 		бот:      база.Бот(),

+ 4 - 2
app/lev2/arena/arena_market/arena_market.go

@@ -7,6 +7,8 @@ import (
 	"strings"
 	"time"
 
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
 	"wartank/app/lev2/arena"
@@ -15,12 +17,12 @@ import (
 // АренаРынок -- объект рынка
 type АренаРынок struct {
 	ИАрена
-	конт ИБотКонтекст
+	конт ILocalCtx
 	бот  ИБот
 }
 
 // НовРынок -- возвращает новый рынок
-func НовРынок(конт ИБотКонтекст) ИАренаРынок {
+func НовРынок(конт ILocalCtx) ИАренаРынок {
 	сам := &АренаРынок{
 		бот: конт.Get("бот").(ИБот),
 	}

+ 2 - 2
app/lev2/arena/arena_masters/arena_masters.go

@@ -28,7 +28,7 @@ type БитваМастеров struct {
 }
 
 // НовБитваМастеров -- возвращает новый *BatMas
-func НовБитваМастеров(конт ИБотКонтекст, бот ИБот) *БитваМастеров {
+func НовБитваМастеров(бот ИБот) *БитваМастеров {
 	лог := NewLogBuf()
 	лог.Info("НовБитваМастеров()\n")
 	Hassert(бот != nil, "НовБитваМастеров(): ИБот == nil\n")
@@ -43,7 +43,7 @@ func НовБитваМастеров(конт ИБотКонтекст, бот
 		ФнПуск_:      сам.пуск,
 		СтрУрл_:      "https://wartank.ru/pvp",
 	}
-	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
+	сам.ИАрена = arena.НовАрена(бот.КонтБот(), аренаКонфиг)
 	return сам
 }
 

+ 13 - 14
app/lev2/arena/arena_mine/arena_mine.go

@@ -2,12 +2,13 @@
 package arena_mine
 
 import (
-	"context"
 	"fmt"
 	"strconv"
 	"strings"
 	"time"
 
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
 	"wartank/app/lev1"
@@ -25,27 +26,24 @@ type АренаШахта struct {
 	сталь        ИСтатПарам
 	свинец       ИСтатПарам
 	уровень      ИСтатПарам
-	продуктИмя   string          // Что сейчас делается
-	продуктКол   ИСтатПарам      // Сколько делается прямо сейчас
-	продуктВремя string          // Сколько осталось времени прямо сейчас
-	кнт          context.Context // контекст шахты
-	фнОтмена     func()          // Функция отмены шахты
+	продуктИмя   string     // Что сейчас делается
+	продуктКол   ИСтатПарам // Сколько делается прямо сейчас
+	продуктВремя string     // Сколько осталось времени прямо сейчас
+	кнт          ILocalCtx
 }
 
 // НовШахта -- возвращает новый *Mine
-func НовШахта(конт ИБотКонтекст, база ИАренаБаза) (ИАренаШахта, error) {
-	кнт, фнОтмена := context.WithCancel(база.Контекст())
+func НовШахта(конт ILocalCtx) ИАренаШахта {
 	сам := &АренаШахта{
-		бот:        база.Бот(),
-		база:       база,
+		бот:        конт.Get("бот").Val().(ИБот),
+		база:       конт.Get("база").Val().(ИАренаБаза),
 		руда:       lev1.НовСтатПарам("руда"),
 		железо:     lev1.НовСтатПарам("железо"),
 		сталь:      lev1.НовСтатПарам("сталь"),
 		свинец:     lev1.НовСтатПарам("свинец"),
 		продуктКол: lev1.НовСтатПарам("кол-во"),
 		уровень:    lev1.НовСтатПарам("уровень"),
-		кнт:        кнт,
-		фнОтмена:   фнОтмена,
+		кнт:        конт,
 	}
 	аренаКонфиг := arena.АренаКонфиг{
 		Бот_:         сам.бот,
@@ -59,7 +57,8 @@ func НовШахта(конт ИБотКонтекст, база ИАренаБ
 	go сам.пуск()
 	сам.лог.ОтклВывод()
 	сам.лог.Добавить("Шахта.НовШахта(): бот=%q\n", сам.бот.Имя())
-	return сам, nil
+	конт.Set("шахта", сам, "Шахта бота")
+	return сам
 }
 
 // пуск -- запускает обработку шахты
@@ -118,7 +117,7 @@ func (сам *АренаШахта) пуск() {
 	}
 	for {
 		select {
-		case <-сам.кнт.Done():
+		case <-сам.кнт.Ctx().Done():
 			return
 		case <-сам.ВремяОстат().КаналСиг():
 			фнРабота()

+ 2 - 2
app/lev2/arena/arena_missions/arena_missions.go

@@ -19,7 +19,7 @@ type АренаМиссии struct {
 }
 
 // НовМиссии -- возвращает новый *Миссии
-func НовМиссии(конт ИБотКонтекст, бот ИБот) (*АренаМиссии, error) {
+func НовМиссии(бот ИБот) (*АренаМиссии, error) {
 	сам := &АренаМиссии{
 		бот: бот,
 	}
@@ -30,7 +30,7 @@ func НовМиссии(конт ИБотКонтекст, бот ИБот) (*А
 		ФнПуск_:      сам.пуск,
 		СтрУрл_:      "https://wartank.ru/missions/", // https://wartank.ru/missions/
 	}
-	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
+	сам.ИАрена = arena.НовАрена(бот.КонтБот(), аренаКонфиг)
 	_ = ИМиссии(сам)
 	return сам, nil
 }

+ 3 - 3
app/lev2/arena/arena_net/arena_net.go

@@ -24,11 +24,11 @@ type АренаСеть struct {
 }
 
 // НовАренаСеть -- возвращает новый *АренаСеть
-func НовАренаСеть_(конт ИБотКонтекст, арена ИАрена, стрУрл string) *АренаСеть {
-	лог := NewLogBuf()
-	лог.Info("НовАренаСеть(): strUrl=%q\n", стрУрл)
+func НовАренаСеть_(конт ILocalCtx, арена ИАрена, стрУрл string) *АренаСеть {
 	Hassert(арена != nil, "НовАренаСеть(): ИСценаСтр == nil")
 	Hassert(стрУрл != "", "НовАренаСеть(): стрУрл пустой\n")
+	лог := NewLogBuf()
+	лог.Info("НовАренаСеть(): strUrl=%q\n", стрУрл)
 	сам := &АренаСеть{
 		ИБотСеть: арена.Бот().Сеть(),
 		арена:    арена,

+ 1 - 1
app/lev2/arena/arena_net/arena_web_worker/arena_web_worker.go

@@ -23,7 +23,7 @@ type АренаВебВоркер struct {
 }
 
 // НовАренаВебВоркер -- возвращает сетевого клиента
-func НовАренаВебВоркер(конт ИБотКонтекст) *АренаВебВоркер { //, ботСеть ИБотСеть)
+func НовАренаВебВоркер(конт ILocalCtx) *АренаВебВоркер { //, ботСеть ИБотСеть)
 	лог := NewLogBuf()
 	лог.Info("НовАренаВебВоркер()\n")
 	сам := &АренаВебВоркер{

+ 9 - 5
app/lev2/arena/arena_polygon/arena_polygon.go

@@ -36,27 +36,31 @@ type АренаПолигон struct {
 	продуктСейчас ISafeString
 	продуктКол    ISafeInt
 	лог           ILogBuf
+	конт          ILocalCtx
 }
 
 // НовПолигон -- возвращает новый *Polygon
-func НовПолигон(конт ИБотКонтекст, база ИАренаБаза) *АренаПолигон {
+func НовПолигон(конт ILocalCtx) *АренаПолигон {
 	лог := NewLogBuf()
-	лог.Info("НовПолигон(): бот=%s\n", база.Бот().Имя())
+	бот := конт.Get("бот").Val().(ИБот)
+	лог.Info("НовПолигон(): бот=%s\n", бот.Имя())
 	сам := &АренаПолигон{
-		бот:           база.Бот(),
-		танкСтат:      база.Бот().Стата(),
+		бот:           бот,
+		танкСтат:      бот.Стата(),
 		продуктСейчас: NewSafeString(),
 		продуктКол:    NewSafeInt(),
 		лог:           лог,
+		конт:          конт,
 	}
 	аренаКонфиг := arena.АренаКонфиг{
-		Бот_:         база.Бот(),
+		Бот_:         бот,
 		АренаИмя_:    "Полигон",
 		СтрКонтроль_: `<span class="green2">Полигон</span><br/>`,
 		ФнПуск_:      сам.пуск,
 		СтрУрл_:      "https://wartank.ru/polygon",
 	}
 	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
+	конт.Set("полигон", сам, "Полигон бота")
 	_ = ИАренаПолигон(сам)
 	return сам
 }

+ 2 - 2
app/lev2/arena/arena_string/arena_string.go

@@ -5,10 +5,10 @@ import (
 	"fmt"
 	"strings"
 	"sync"
-	. "wartank/app/lev0/types"
 
 	. "gitp78su.ipnodns.ru/svi/kern"
 	. "gitp78su.ipnodns.ru/svi/kern/kc/helpers"
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
 )
 
 // АренаСтроки -- потокобезопасный список строк арены
@@ -19,7 +19,7 @@ type АренаСтроки struct {
 }
 
 // НовАренаСтроки -- возвращает новый потокобезопасный список строк арены
-func НовАренаСтроки(конт ИБотКонтекст, strControl string) *АренаСтроки {
+func НовАренаСтроки(конт ILocalCtx, strControl string) *АренаСтроки {
 	лог := NewLogBuf()
 	лог.Debug("НовАренаСтроки(): strControl=%q", strControl)
 	Hassert(strControl != "", "НовАренаСтроки(): strControl is empty")

+ 4 - 4
app/lev2/arena/arena_upgrade/arena_upgrade.go

@@ -17,14 +17,14 @@ import (
 
 // ТанкПараметры -- параметры танка повышение
 type АренаАпгрейд struct {
-	конт   ИБотКонтекст
+	конт   ILocalCtx
 	прилож ИПриложение
 	номер  string // Номер танка в игре
 	лог    ILogBuf
 }
 
 // НовТанкПараметры -- возвращает новые параметры танка
-func НовТанкПараметры(конт ИБотКонтекст) *АренаАпгрейд {
+func НовТанкПараметры(конт ILocalCtx) *АренаАпгрейд {
 	лог := NewLogBuf()
 	лог.Info("НовТанкПараметры()\n")
 
@@ -47,12 +47,12 @@ func (сам *АренаАпгрейд) пуск() {
 	ош := сам.номерПолуч()
 	if ош != nil {
 		log.Printf("ТанкПараметры.пуск(): при получении параметров танка, ош=\n\t%v\n", ош)
-		сам.прилож.Cancel()
+		сам.конт.Cancel()
 		return
 	}
 	for {
 		select {
-		case <-сам.прилож.Ctx().Done():
+		case <-сам.конт.Ctx().Done():
 			return
 		default:
 			сам.работать()

+ 48 - 0
app/lev2/lev2.go

@@ -1,2 +1,50 @@
 // package lev2 -- слой арен
 package lev2
+
+import (
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
+	. "wartank/app/lev0/types"
+	"wartank/app/lev2/arena/arena_angar"
+	"wartank/app/lev2/arena/arena_arsenal"
+	"wartank/app/lev2/arena/arena_base"
+	"wartank/app/lev2/arena/arena_fuel"
+	"wartank/app/lev2/arena/arena_mine"
+	"wartank/app/lev2/arena/arena_polygon"
+)
+
+// НовАренаТопливо -- возвращает арену боя за топливо
+func НовАренаТопливо(конт ILocalCtx) ИАрена {
+	арена := arena_fuel.НовАренаТопливо(конт)
+	return арена
+}
+
+// НовАнгар -- возвращает новый ангар
+func НовАнгар(конт ILocalCtx) ИАренаАнгар {
+	ангар := arena_angar.НовАнгар(конт)
+	return ангар
+}
+
+// НовПолигон -- возвращает новый полигон
+func НовПолигон(конт ILocalCtx) ИАренаПолигон {
+	полигон := arena_polygon.НовПолигон(конт)
+	return полигон
+}
+
+// НовАрсенал -- возвращает новый арсенал
+func НовАрсенал(конт ILocalCtx) ИАренаАрсенал {
+	арсенал := arena_arsenal.НовАрсенал(конт)
+	return арсенал
+}
+
+// НовБаза -- возвращает новую базу
+func НовБаза(конт ILocalCtx) ИАренаБаза {
+	база := arena_base.НовБаза(конт)
+	return база
+}
+
+// НовШахта -- возвращает новую шахту
+func НовШахта(конт ILocalCtx) ИАренаШахта {
+	шахта := arena_mine.НовШахта(конт)
+	return шахта
+}

+ 44 - 37
app/lev3/bot/bot.go

@@ -2,7 +2,6 @@
 package bot
 
 import (
-	"context"
 	"fmt"
 	"log"
 	"strings"
@@ -13,8 +12,12 @@ import (
 	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
 
 	. "wartank/app/lev0/alias"
+	"wartank/app/lev0/bfunc/bf_fuel_attack"
+	"wartank/app/lev0/bfunc/bf_fuel_find"
+	"wartank/app/lev0/bfunc/bf_gold_find"
+	"wartank/app/lev0/bfunc/bf_silver_find"
 	. "wartank/app/lev0/types"
-	"wartank/app/lev2/arena/arena_angar"
+	"wartank/app/lev2"
 	"wartank/app/lev3/bot/bot_config"
 	"wartank/app/lev3/bot/bot_net"
 	"wartank/app/lev3/bot/bot_stat/tank_stat"
@@ -26,25 +29,24 @@ type Бот struct {
 	хран           IKernelStoreKv
 	стата          ИТанкСтат
 	errFinal       error // Финальная ошибка работы, если была
-	ангар          ИАренаАнгар
 	сеть           ИБотСеть
+	ангар          ИАренаАнгар
 	еслиРаботает   ISafeBool
 	еслиАвтозапуск ISafeBoolReact
-	конфиг         *bot_config.БотКонфиг // Конфиг бота для хранения в базе
-	кнт            context.Context       // Контекст бота
-	фтОтмена       func()                // Функция отменя контекста бота
 	лог            ILogBuf
-	конт           ИБотКонтекст
+	конт           ILocalCtx
+	конфиг         *bot_config.БотКонфиг
 }
 
 // ЗагрузитьВарБот -- загружает бота из базы
-func ЗагрузитьВарБот(конт IKernelCtx, номер АБотНомер) *Бот {
+func ЗагрузитьВарБот(номер АБотНомер) *Бот {
 	лог := NewLogBuf()
 	лог.Info("ЗагрузитьВарБот()\n")
 	Hassert(номер != 0, "ЗагрузитьВарБот(): номер пустой")
 	стрНомер := fmt.Sprint(номер)
 	лог.Info("ЗагрузитьВарБот(): номер=%q\n", стрНомер)
-	хран := конт.Get("kernStore").Val().(IKernelStoreKv)
+	конт := GetKernelCtx()
+	хран := конт.Get("kernStoreKV").Val().(IKernelStoreKv)
 	binData, err := хран.Get("/bots/" + стрНомер)
 	if err != nil {
 		if !strings.Contains(err.Error(), "not found") {
@@ -54,7 +56,7 @@ func ЗагрузитьВарБот(конт IKernelCtx, номер АБотНо
 	}
 	конфиг := &bot_config.БотКонфиг{}
 	конфиг.Unmarshal(binData)
-	сам := создатьЯдроВарБот(конт, конфиг)
+	сам := создатьЯдроВарБот(конфиг)
 	go сам.рестарт()
 	_ = ИБот(сам)
 	return сам
@@ -63,7 +65,7 @@ func ЗагрузитьВарБот(конт IKernelCtx, номер АБотНо
 // Каждые два часа перезапускает себя
 func (сам *Бот) рестарт() {
 	time.Sleep(time.Hour * 2)
-	сам.прилож.Cancel()
+	сам.конт.Cancel()
 	сам.лог.Info("рестарт(): бот %q перезагружен\n", сам.конфиг.Логин_)
 }
 
@@ -80,29 +82,27 @@ func НовВарБот(конт IKernelCtx, номер АБотНомер, ло
 		Пароль_:         пароль,
 		Номер_:          номер,
 	}
-	сам := создатьЯдроВарБот(конт, config)
+	сам := создатьЯдроВарБот(config)
 	сам.сохрКонфиг()
 	_ = ИБот(сам)
 	return сам
 }
 
 // Создаёт ядро бота
-func создатьЯдроВарБот(конт IKernelCtx, конфиг *bot_config.БотКонфиг) *Бот {
+func создатьЯдроВарБот(конфиг *bot_config.БотКонфиг) *Бот {
+	Hassert(конфиг != nil, "создатьЯдроВарБот(): ВарБотКонфиг==nil")
 	лог := NewLogBuf()
 	лог.Info("создатьЯдроВарБот()\n")
-	Hassert(конфиг != nil, "создатьЯдроВарБот(): ВарБотКонфиг==nil")
-	ctx, fnCancel := context.WithCancel(конт.Ctx())
-	приложение := конт.Get("приложение").Val().(ИПриложение)
+	конт := GetKernelCtx()
+	приложение := конт.Get("мод_сервер").Val().(ИПриложение)
 	контБот := NewLocalCtx(конт.Ctx())
 	сам := &Бот{
 		конт:         контБот,
 		прилож:       приложение,
-		хран:         конт.Get("kernStore").Val().(IKernelStoreKv),
-		стата:        tank_stat.НовТанкСтат(конт),
+		хран:         конт.Get("kernStoreKV").Val().(IKernelStoreKv),
+		стата:        tank_stat.НовТанкСтат(контБот),
 		еслиРаботает: NewSafeBool(),
 		конфиг:       конфиг,
-		кнт:          ctx,
-		фтОтмена:     fnCancel,
 		лог:          лог,
 	}
 	сам.еслиАвтозапуск = NewSafeBoolReact()
@@ -110,11 +110,16 @@ func создатьЯдроВарБот(конт IKernelCtx, конфиг *bot_c
 	сам.конт.Set("бот", сам, "создание ядра")
 	сам.конт.Set("приложение", приложение, "Приложение WarBot")
 	сам.сеть = bot_net.НовБотСеть(сам.конт)
-	сам.ангар = arena_angar.НовАнгар(сам.конт)
 	if сам.конфиг.ЕслиАвтозапуск_ {
 		сам.еслиАвтозапуск.Set()
 		сам.Пуск()
 	}
+	сам.ангар = lev2.НовАнгар(сам.конт)
+	_ = lev2.НовПолигон(сам.конт)
+	_ = lev2.НовБаза(сам.конт)
+	_ = lev2.НовШахта(сам.конт)
+	_ = lev2.НовАрсенал(сам.конт)
+	_ = lev2.НовАренаТопливо(сам.конт)
 	return сам
 }
 
@@ -143,20 +148,32 @@ func (сам *Бот) Пуск() {
 	if сам.еслиРаботает.Get() {
 		return
 	}
-	сам.ангар.Пуск()
+	go сам.пуск()
 	сам.еслиРаботает.Set()
 }
 
+// Работает в отдельном потоке ,пока сервер не даст команду остановки
+func (сам *Бот) пуск() {
+	for {
+		select {
+		case <-сам.конт.Ctx().Done():
+			return
+		default:
+			time.Sleep(time.Second * 5)
+			сам.ангар.Обновить()
+			bf_gold_find.ЗолотоНайти(сам.конт)
+			bf_silver_find.СереброНайти(сам.конт)
+			bf_fuel_find.ТопливоНайти(сам.конт)
+			bf_fuel_attack.ТопливоАтаковать(сам.конт)
+		}
+	}
+}
+
 // Error -- возвращает финальную ошибку работы, если была
 func (сам *Бот) Error() error {
 	return сам.errFinal
 }
 
-// Ангар -- возвращает ангар игры
-func (сам *Бот) Ангар() ИАренаАнгар {
-	return сам.ангар
-}
-
 // Стата -- возвращает статистику танка
 func (сам *Бот) Стата() ИТанкСтат {
 	return сам.стата
@@ -189,16 +206,6 @@ func (сам *Бот) сохрКонфиг() {
 	Hassert(err == nil, "ВарБот.сохрКонфиг(): err=\n\t%v\n", err)
 }
 
-// Контекст -- возвращает контекст бота
-func (сам *Бот) Контекст() context.Context {
-	return сам.кнт
-}
-
-// Закончить -- отменяет контекст бота
-func (сам *Бот) Закончить() {
-	сам.фтОтмена()
-}
-
 // КонтБот -- возвращает контекст бота
 func (сам *Бот) КонтБот() ILocalCtx {
 	return сам.конт

+ 1 - 1
app/lev3/bot/bot_net/bot_cookie/bot_cookie.go

@@ -33,7 +33,7 @@ func НовБотКуки() БотКуки {
 func (сам *БотКуки) Уст(cook []*http.Cookie) {
 	сам.блок.Lock()
 	defer сам.блок.Unlock()
-	Hassert(cook == nil, "БотКуки.Уст(): cookie == nil")
+	Hassert(cook != nil, "БотКуки.Уст(): cookie == nil")
 	сам.куки = cook
 	cookie := http.Cookie{
 		Name:  "JSESSIONID",

+ 3 - 3
app/lev3/bot/bot_net/bot_net.go

@@ -26,10 +26,10 @@ type БотСеть struct {
 }
 
 // НовБотСеть -- возвращает новый коннект к сети бота
-func НовБотСеть(конт ИБотКонтекст) *БотСеть {
+func НовБотСеть(конт ILocalCtx) *БотСеть {
 	лог := NewLogBuf()
 	лог.Info("НовБотСеть()\n")
-	бот := конт.Get("юот").(ИБот)
+	бот := конт.Get("бот").Val().(ИБот)
 	лог.Info("НовБотСеть(): имя=%q\n", бот.Имя())
 	ctx := NewLocalCtx(конт.Ctx())
 	сам := &БотСеть{
@@ -40,10 +40,10 @@ func НовБотСеть(конт ИБотКонтекст) *БотСеть {
 		лог:        лог,
 	}
 	конт.Set("хттпКлиент", сам.соедХттп.ХттпКлиент(), "HTTP-клиент для запросов")
+	конт.Set("ботСеть", сам, "Сеть бота")
 	сам.вебВоркер = http_worker.НовХттпВоркер(конт)
 
 	// Подключаем сетевой логин
-	конт.Set("ботСеть", сам, "Сеть бота")
 	сам.логин = bot_net_login.НовБотСетьЛогин(конт)
 
 	сам.еслиОнлайн.Set()

+ 4 - 4
app/lev3/bot/bot_net/bot_net_login/bot_net_login.go

@@ -7,11 +7,11 @@ import (
 	"net/url"
 	"strings"
 
-	. "wartank/app/lev0/types"
-
 	. "gitp78su.ipnodns.ru/svi/kern"
 	. "gitp78su.ipnodns.ru/svi/kern/kc/helpers"
 	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
+	. "wartank/app/lev0/types"
 )
 
 // БотСетьЛогин -- объект сетевого входа на сервер
@@ -23,11 +23,11 @@ type БотСетьЛогин struct {
 }
 
 // НовБотСетьЛогин -- возвращает новый *БотСетьЛогин
-func НовБотСетьЛогин(конт ИБотКонтекст) *БотСетьЛогин {
+func НовБотСетьЛогин(конт ILocalCtx) *БотСетьЛогин {
 	лог := NewLogBuf()
 	лог.Info("НовБотСетьЛогин()\n")
 
-	ботСеть := конт.Get("ботСеть").(ИБотСеть)
+	ботСеть := конт.Get("ботСеть").Val().(ИБотСеть)
 	хттпКлиент := конт.Get("хттпКлиент").Val().(*http.Client)
 	сам := &БотСетьЛогин{
 		сеть:       ботСеть,

+ 17 - 13
app/lev3/bot/bot_net/bot_net_stat/net_stat.go → app/lev3/bot/bot_net/bot_net_stat/bot_net_stat.go

@@ -21,10 +21,12 @@ type БотСетьСтат struct {
 	прилож ИПриложение
 	бот    ИБот
 	лог    ILogBuf
+	конт   ILocalCtx
+	ангар  ИАренаАнгар
 }
 
 // НовБотСетьСтат -- возвращает новый *NetStat
-func НовБотСетьСтат(конт ИБотКонтекст) *БотСетьСтат {
+func НовБотСетьСтат(конт ILocalCtx) *БотСетьСтат {
 	лог := NewLogBuf()
 	лог.Info("НовБотСетьСтат()\n")
 	bot := конт.Get("бот").(ИБот)
@@ -32,6 +34,8 @@ func НовБотСетьСтат(конт ИБотКонтекст) *БотСе
 		прилож: конт.Get("сервер").(ИПриложение),
 		бот:    bot,
 		лог:    лог,
+		конт:   конт,
+		ангар:  конт.Get("ангар").Val().(ИАренаАнгар),
 	}
 	return сам
 }
@@ -50,7 +54,7 @@ func (сам *БотСетьСтат) Update() {
 
 // Ищет в теле текста ангара мощность танка
 func (сам *БотСетьСтат) мощностьНайти() {
-	lstAngar := сам.бот.Ангар().СписПолучить()
+	lstAngar := сам.ангар.СписПолучить()
 	if len(lstAngar) == 0 {
 		// log._rintf("WARN NetStat.findPower(): lstAngar is empty\n")
 		return
@@ -76,7 +80,7 @@ func (сам *БотСетьСтат) мощностьНайти() {
 func (сам *БотСетьСтат) прочностьНайти() {
 	var (
 		strOut      string
-		lstAngar    = сам.бот.Ангар().СписПолучить()
+		lstAngar    = сам.ангар.СписПолучить()
 		еслиНайдено bool
 	)
 	if len(lstAngar) == 0 {
@@ -106,7 +110,7 @@ func (сам *БотСетьСтат) прочностьНайти() {
 func (сам *БотСетьСтат) точностьНайти() {
 	var (
 		strOut      string
-		lstAngar    = сам.бот.Ангар().СписПолучить()
+		lstAngar    = сам.ангар.СписПолучить()
 		еслиНайдено bool
 	)
 	if len(lstAngar) == 0 {
@@ -136,7 +140,7 @@ func (сам *БотСетьСтат) точностьНайти() {
 func (сам *БотСетьСтат) броняНайти() {
 	var (
 		strOut      string
-		lstAngar    = сам.бот.Ангар().СписПолучить()
+		lstAngar    = сам.ангар.СписПолучить()
 		еслиНайдено bool
 	)
 	if len(lstAngar) == 0 {
@@ -163,7 +167,7 @@ func (сам *БотСетьСтат) броняНайти() {
 
 // Ищет в теле текста ангара уровень танка
 func (сам *БотСетьСтат) findLevelTank() {
-	lstAngar := сам.бот.Ангар().СписПолучить()
+	lstAngar := сам.ангар.СписПолучить()
 	if len(lstAngar) == 0 {
 		// log._rintf("ERRO NetStat.findLevelTank(): пустой lstAngar")
 		return
@@ -182,12 +186,12 @@ func (сам *БотСетьСтат) findLevelTank() {
 	strLevel = lstLevel[0]
 	iLevel, ош := strconv.Atoi(strLevel)
 	Hassert(ош == nil, "NetStat.прочностьНайти(): уровень(%v) не число, ош=\n\t%v\n", strLevel, ош)
-	сам.бот.Ангар().Уровень().Уст(iLevel)
+	сам.ангар.Уровень().Уст(iLevel)
 }
 
 // Ищет в теле текста ангара прогресс уровня танка танка
 func (сам *БотСетьСтат) findLevelProgress() {
-	lstAngar := сам.бот.Ангар().СписПолучить()
+	lstAngar := сам.ангар.СписПолучить()
 	Hassert(len(lstAngar) != 0, "lstAngar пустой")
 	var strOut string
 	for _, strProg := range lstAngar {
@@ -203,14 +207,14 @@ func (сам *БотСетьСтат) findLevelProgress() {
 	strProg = lstProg[0]
 	iProg, ош := strconv.Atoi(strProg)
 	Hassert(ош == nil, "NetStat.прогрессНайти(): прогресс(%v) не число, ош=\n\t%v\n", strProg, ош)
-	сам.бот.Ангар().Прогресс().Уст(iProg)
+	сам.ангар.Прогресс().Уст(iProg)
 }
 
 // Ищет в теле текста ангара силу атаки танка
 func (сам *БотСетьСтат) атакаНайти() {
 	var (
 		strOut      string
-		lstAngar    = сам.бот.Ангар().СписПолучить()
+		lstAngar    = сам.ангар.СписПолучить()
 		еслиНайдено bool
 	)
 	for _, strOut = range lstAngar {
@@ -234,7 +238,7 @@ func (сам *БотСетьСтат) атакаНайти() {
 
 // Ищет в теле текста ангара силу атаки танка
 func (сам *БотСетьСтат) игроковОнлайнНайти() {
-	lstAngar := сам.бот.Ангар().СписПолучить()
+	lstAngar := сам.ангар.СписПолучить()
 	var strOut string
 	for _, стрАтака := range lstAngar {
 		if strings.Contains(стрАтака, `>Онлайн</a>: `) {
@@ -245,7 +249,7 @@ func (сам *БотСетьСтат) игроковОнлайнНайти() {
 	// Выделить число игроков онлайн
 	lstAngar = strings.Split(strOut, `<span class="yellow1">`)
 	if len(lstAngar) <= 1 {
-		сам.прилож.Cancel()
+		сам.конт.Cancel()
 		return
 	}
 	strOnline := lstAngar[1]
@@ -254,5 +258,5 @@ func (сам *БотСетьСтат) игроковОнлайнНайти() {
 	iOnline, ош := strconv.Atoi(strOnline)
 
 	Hassert(ош == nil, "NetStat.findOnline(): игроков онлайн(%v) не число, ош=\n\t%v\n", strOnline, ош)
-	сам.бот.Ангар().ИгрокиОнлайн().Уст(iOnline)
+	сам.ангар.ИгрокиОнлайн().Уст(iOnline)
 }

+ 5 - 4
app/lev3/bot/bot_net/http_worker/http_worker.go

@@ -30,11 +30,11 @@ type ХттпВоркер struct {
 }
 
 // НовХттпВоркер -- возвращает веб-воркера бота
-func НовХттпВоркер(конт ИБотКонтекст) *ХттпВоркер {
+func НовХттпВоркер(конт ILocalCtx) *ХттпВоркер {
 	лог := NewLogBuf()
 	лог.Info("НовХттпВоркер()\n")
 
-	ботСеть := конт.Get("ботСеть").(ИБотСеть)
+	ботСеть := конт.Get("ботСеть").Val().(ИБотСеть)
 	хттпКлиент := конт.Get("хттпКлиент").Val().(*http.Client)
 
 	сам := &ХттпВоркер{
@@ -44,6 +44,7 @@ func НовХттпВоркер(конт ИБотКонтекст) *ХттпВо
 		лог:        лог,
 	}
 	_ = ИХттпВоркер(сам)
+	конт.Set("хттпВоркер", сам, "HTTP-воркер бота")
 	return сам
 }
 
@@ -60,9 +61,9 @@ func (сам *ХттпВоркер) Получ(strLink string) []string {
 	ответ, ош := сам.хттпКлиент.Do(запрос)
 	Hassert(ош == nil, "ХттпВоркер.Получ(): при выполнении GET-запроса, err=\n\t%v\n", ош)
 	defer ответ.Body.Close()
-	Hassert(ответ.StatusCode != http.StatusOK, "ХттпВоркер.Получ(): code=%v, status=%v", ответ.StatusCode, ответ.Status)
+	Hassert(ответ.StatusCode == http.StatusOK, "ХттпВоркер.Получ(): code=%v, status=%v", ответ.StatusCode, ответ.Status)
 	binData, ош := io.ReadAll(ответ.Body)
-	Hassert(ош != nil, "ХттпВоркер.Получ(): при чтении тела ответа, err=\n\t%v\n", ош)
+	Hassert(ош == nil, "ХттпВоркер.Получ(): при чтении тела ответа, err=\n\t%v\n", ош)
 
 	Hassert(len(binData) != 0, "ХттпВоркер.Получ(): пустое тело ответа")
 	lenData := len(binData) + len(strLink)

+ 2 - 2
app/lev3/bot/bot_net/http_worker/net_stat/net_stat.go

@@ -29,11 +29,11 @@ type СетьСтата struct {
 }
 
 // НовСетьСтата -- возвращает новый *NetStat
-func НовСетьСтата(конт ИБотКонтекст) *СетьСтата {
+func НовСетьСтата(конт ILocalCtx) *СетьСтата {
 	лог := NewLogBuf()
 	лог.Info("НовСетьСтата()\n")
 
-	ботСеть := конт.Get("ботСеть").(ИБотСеть)
+	ботСеть := конт.Get("ботСеть").Val().(ИБотСеть)
 	сам := &СетьСтата{
 		ботСеть: ботСеть,
 		chTick:  make(chan int, 2),

+ 3 - 1
app/lev3/bot/bot_stat/bot_resurs/bot_resurs.go

@@ -2,6 +2,8 @@
 package bot_resurs
 
 import (
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/types"
 	"wartank/app/lev1"
 )
@@ -14,7 +16,7 @@ type БотРесурсы struct {
 }
 
 // НовБотРесурсы -- новая статистика ресурсов
-func НовБотРесурсы(конт ИБотКонтекст, ангар ИАренаАнгар) ИБотРесурсы {
+func НовБотРесурсы(конт ILocalCtx, ангар ИАренаАнгар) ИБотРесурсы {
 	сам := &БотРесурсы{
 		золото:       lev1.НовСтатПарам("золото"),
 		сереброВсего: lev1.НовСтатПарам("серебро"),

+ 13 - 2
app/lev3/bot/bot_stat/tank_stat/tank_stat.go

@@ -2,23 +2,26 @@
 package tank_stat
 
 import (
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/types"
 	"wartank/app/lev1"
 )
 
 // ТанкСтат -- статические параметры танка
 type ТанкСтат struct {
-	конт      ИБотКонтекст
+	конт      ILocalCtx
 	атака     ИСтатПарам
 	точность  ИСтатПарам
 	прочность ИСтатПарам
 	броня     ИСтатПарам
 	power     ИСтатПарам // Танковая мощь (может не совпадать по сумме, если есть усиление)
 	усиление  ИСтатПарам
+	слава     ИСтатПарам
 }
 
 // НовТанкСтат -- возвращает новый *TankStat
-func НовТанкСтат(конт ИБотКонтекст) *ТанкСтат {
+func НовТанкСтат(конт ILocalCtx) *ТанкСтат {
 	сам := &ТанкСтат{
 		конт:      конт,
 		атака:     lev1.НовСтатПарам("атака"),
@@ -27,10 +30,18 @@ func НовТанкСтат(конт ИБотКонтекст) *ТанкСтат
 		броня:     lev1.НовСтатПарам("броня"),
 		power:     lev1.НовСтатПарам("мощь"),
 		усиление:  lev1.НовСтатПарам("усиление"),
+		слава:     lev1.НовСтатПарам("слава"),
 	}
+	конт.Set("танкСтат", сам, "Стата танка")
+	_ = ИТанкСтат(сам)
 	return сам
 }
 
+// Слава -- возвращает объект славы танка
+func (сам *ТанкСтат) Слава() ИСтатПарам {
+	return сам.слава
+}
+
 // Атака -- возвращает объект силы атаки
 func (сам *ТанкСтат) Атака() ИСтатПарам {
 	return сам.атака

+ 4 - 4
app/lev3/farm_bots/dict_bot/dict_bot.go

@@ -36,8 +36,8 @@ func НовСловарьБотов(конт IKernelCtx) *СловарьБото
 	лог.Info("НовСловарьБотов()\n")
 	сам := &СловарьБотов{
 		конт:    конт,
-		прилож:  конт.Get("приложение").Val().(ИПриложение),
-		хран:    конт.Get("kernStore").Val().(IKernelStoreKv),
+		прилож:  конт.Get("мод_сервер").Val().(ИПриложение),
+		хран:    конт.Get("kernStoreKV").Val().(IKernelStoreKv),
 		словарь: map[АБотНомер]ИБот{},
 		лог:     лог,
 	}
@@ -84,7 +84,7 @@ func (сам *СловарьБотов) save() {
 	strNumber = strNumber[:len(strNumber)-1]
 	err := сам.хран.Set(strBotList, []byte(strNumber))
 	if err != nil {
-		сам.прилож.Cancel()
+		сам.конт.Cancel()
 	}
 }
 
@@ -112,7 +112,7 @@ func (сам *СловарьБотов) load() {
 		if isOk {
 			continue
 		}
-		bot := bot.ЗагрузитьВарБот(сам.конт, ботНомер)
+		bot := bot.ЗагрузитьВарБот(ботНомер)
 		if bot.Автозапуск().Get() {
 			go bot.Пуск()
 		}

+ 6 - 4
app/lev3/farm_bots/farm_bots.go

@@ -5,12 +5,13 @@ import (
 	"fmt"
 	"log"
 
+	. "gitp78su.ipnodns.ru/svi/kern"
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
 	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
 	"wartank/app/lev3/bot"
 	"wartank/app/lev3/farm_bots/dict_bot"
-
-	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
 )
 
 // БотоФерма -- бото-ферма
@@ -22,13 +23,14 @@ type БотоФерма struct {
 }
 
 // НовБотоФерма -- возвращает новую бото-ферму
-func НовБотоФерма(конт IKernelCtx) *БотоФерма {
+func НовБотоФерма() *БотоФерма {
+	конт := GetKernelCtx()
 	log.Println("НовБотоФерма()")
 	// приложение := конт.Получ("приложение").(ИПриложение)
 	сам := &БотоФерма{
 		конт: конт,
 		// прилож: приложение,
-		хран: конт.Get("kernStore").(IKernelStoreKv),
+		хран: конт.Get("kernStoreKV").Val().(IKernelStoreKv),
 	}
 	сам.словБот = dict_bot.НовСловарьБотов(конт)
 	return сам

+ 17 - 16
app/lev3/serv_web/serv_web.go

@@ -6,7 +6,6 @@ import (
 
 	"github.com/gofiber/fiber/v2"
 	. "gitp78su.ipnodns.ru/svi/kern"
-	. "gitp78su.ipnodns.ru/svi/kern/kc/helpers"
 	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
 
 	. "wartank/app/lev0/alias"
@@ -22,22 +21,22 @@ type СервВеб struct {
 }
 
 // НовСервВеб -- возвращает новый веб-сервер
-func НовСервВеб(серв ИПриложение) *СервВеб {
+func НовСервВеб() *СервВеб {
+	конт := GetKernelCtx()
 	лог := NewLogBuf()
 	лог.Info("НовСервВеб()\n")
-	Hassert(серв != nil, "НовСервВеб(): ИСервер==nil")
 
 	сам := &СервВеб{
-		конт: серв,
-		серв: серв,
+		конт: конт,
+		серв: конт.Get("мод_сервер").Val().(ИПриложение),
 		лог:  лог,
 	}
 
-	файбер := серв.Get("fiberApp").Val().(*fiber.App)
+	файбер := конт.Get("fiberApp").Val().(*fiber.App)
 	файбер.Get("/list_bot/get", сам.гетСписБот)
 	файбер.Post("/list_bot/add", сам.постБотНов)
 	файбер.Post("/bot/stat", сам.постБотСтат)
-	_ = web_api.НовВебАпи(сам.конт)
+	_ = web_api.НовВебАпи()
 	_ = web_gui.НовВебГуи(сам.конт)
 	return сам
 }
@@ -66,22 +65,23 @@ func (сам *СервВеб) постБотСтат(кнт *fiber.Ctx) error {
 	диктБот := map[string]string{}
 	диктБот["isAuto"] = fmt.Sprint(бот.Автозапуск().Get())
 	диктБот["isWork"] = fmt.Sprint(бот.ЕслиРабота())
-	топливо := бот.Ангар().Топливо().Получ()
+	ангар := бот.КонтБот().Get("ангар").Val().(ИАренаАнгар)
+	топливо := ангар.Топливо().Получ()
 	if топливо == 0 {
-		бот.Ангар().Обновить()
-		топливо = бот.Ангар().Топливо().Получ()
+		ангар.Обновить()
+		топливо = ангар.Топливо().Получ()
 	}
 	диктБот["топливо"] = fmt.Sprint(топливо)
-	диктБот["золото"] = fmt.Sprint(бот.Ангар().Золото().Получ())
+	диктБот["золото"] = fmt.Sprint(ангар.Золото().Получ())
 	диктБот["серебро"] = fmt.Sprint(бот.КонтБот().Get("серебро").Val().(int))
 	слава := бот.КонтБот().Get("слава").Val().(int)
 	if слава == 0 {
-		бот.Ангар().Обновить()
+		ангар.Обновить()
 		слава = бот.КонтБот().Get("слава").Val().(int)
 	}
 	диктБот["слава"] = fmt.Sprint(слава)
-	диктБот["прогресс"] = fmt.Sprintf("%v%%", бот.Ангар().Прогресс().Получ())
-	диктБот["уровень"] = fmt.Sprintf("%v", бот.Ангар().Уровень().Получ())
+	диктБот["прогресс"] = fmt.Sprintf("%v%%", ангар.Прогресс().Получ())
+	диктБот["уровень"] = fmt.Sprintf("%v", ангар.Уровень().Получ())
 	диктБот["атака"] = fmt.Sprintf("%v", бот.Стата().Атака().Получ())
 	диктБот["броня"] = fmt.Sprintf("%v", бот.Стата().Броня().Получ())
 	диктБот["точность"] = fmt.Sprintf("%v", бот.Стата().Точность().Получ())
@@ -157,8 +157,9 @@ func (сам *СервВеб) гетСписБот(кнт *fiber.Ctx) error {
 		_бот["name"] = бот.Имя()
 		_бот["isAuto"] = fmt.Sprint(бот.Автозапуск().Get())
 		_бот["isWork"] = fmt.Sprint(бот.ЕслиРабота())
-		_бот["gold"] = fmt.Sprint(бот.Ангар().Золото().Получ())
-		_бот["fuel"] = fmt.Sprint(бот.Ангар().Топливо().Получ())
+		ангар := бот.КонтБот().Get("ангар").Val().(ИАренаАнгар)
+		_бот["gold"] = ангар.Золото().ЗначСтр()
+		_бот["fuel"] = ангар.Топливо().ЗначСтр()
 		рез = append(рез, _бот)
 	}
 	return кнт.JSON(рез)

+ 11 - 12
app/lev3/serv_web/web_api/web_api.go

@@ -7,7 +7,6 @@ import (
 
 	"github.com/gofiber/fiber/v2"
 	. "gitp78su.ipnodns.ru/svi/kern"
-	. "gitp78su.ipnodns.ru/svi/kern/kc/helpers"
 	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
 
 	. "wartank/app/lev0/alias"
@@ -21,11 +20,11 @@ type ВебАпи struct {
 }
 
 // НовВебАпи -- возвращает новый веб-сервер для API
-func НовВебАпи(конт ИБотКонтекст) *ВебАпи {
+func НовВебАпи() *ВебАпи {
 	лог := NewLogBuf()
-	Hassert(конт != nil, "НовВебАпи(): ИВебСервер==nil")
+	конт := GetKernelCtx()
 	сам := &ВебАпи{
-		прилож: конт.Get("приложение").(ИПриложение),
+		прилож: конт.Get("мод_сервер").Val().(ИПриложение),
 		лог:    лог,
 	}
 	файбер := конт.Get("fiberApp").Val().(*fiber.App)
@@ -249,7 +248,7 @@ func (сам *ВебАпи) полигонРежим(кнт *fiber.Ctx) error {
 func (сам *ВебАпи) полигонУровень(кнт *fiber.Ctx) error {
 	номер, ош := кнт.ParamsInt("number")
 	if ош != nil {
-		сообщ := fmt.Sprintf("[Уровень: неправильный номер бота(%q), err=%v]", номер, ош.Error())
+		сообщ := fmt.Sprintf("[Уровень: неправильный номер бота(%q), err=<br><%v]", номер, ош.Error())
 		return кнт.SendString(сообщ)
 	}
 	ботНомер := АБотНомер(номер)
@@ -270,7 +269,7 @@ func (сам *ВебАпи) полигонУровень(кнт *fiber.Ctx) erro
 func (сам *ВебАпи) ангарСеребро(кнт *fiber.Ctx) error {
 	номер, ош := кнт.ParamsInt("number")
 	if ош != nil {
-		сообщ := fmt.Sprintf("[Серебро: неправильный номер бота(%q), err=%v]", номер, ош.Error())
+		сообщ := fmt.Sprintf("[Серебро: неправильный номер бота(%q), err=<br>%v]", номер, ош.Error())
 		return кнт.SendString(сообщ)
 	}
 	ботНомер := АБотНомер(номер)
@@ -278,11 +277,11 @@ func (сам *ВебАпи) ангарСеребро(кнт *fiber.Ctx) error {
 	if бот == nil {
 		return кнт.SendString("[Серебро: нет такого бота]")
 	}
-	серебро := бот.Ангар().Серебро().Получ()
-	if серебро == 0 {
+	ангар := бот.КонтБот().Get("ангар").Val().(ИАренаАнгар)
+	стрСеребро := ангар.Серебро().ЗначСтр()
+	if стрСеребро == "0" {
 		return кнт.SendString("[Серебро: пустое кол]")
 	}
-	стрСеребро := fmt.Sprint(серебро)
 	return кнт.SendString("[Серебро: " + стрСеребро + "]")
 }
 
@@ -298,11 +297,11 @@ func (сам *ВебАпи) танкТопливо(кнт *fiber.Ctx) error {
 	if бот == nil {
 		return кнт.SendString("[Топливо: нет такого бота]")
 	}
-	топливо := бот.Ангар().Топливо().Получ()
-	if топливо == 0 {
+	ангар := бот.КонтБот().Get("ангар").Val().(ИАренаАнгар)
+	стрТопливо := ангар.Топливо().ЗначСтр()
+	if стрТопливо == "0" {
 		return кнт.SendString("[Топливо: пустое кол]")
 	}
-	стрТопливо := fmt.Sprint(топливо)
 	return кнт.SendString("[Топливо: " + стрТопливо + "]")
 }
 

+ 1 - 1
app/lev3/serv_web/web_gui/page_bot_add/page_bot_add.go

@@ -30,7 +30,7 @@ func НовСтраницаБотовДобавить(конт IKernelCtx) *Ст
 	Hassert(конт != nil, "НовСтраницаБотовДобавить(): ИЯдроКонтекст==nil")
 	сам := &СтраницаБотаДобавить{
 		лог:    лог,
-		прилож: конт.Get("приложение").(ИПриложение),
+		прилож: конт.Get("мод_сервер").Val().(ИПриложение),
 		рендер: web_render.НовВебРендер(стрБотДобавить),
 	}
 	файбер := конт.Get("fiberApp").Val().(*fiber.App)

+ 1 - 1
app/lev3/serv_web/web_gui/page_bot_list/page_bot_list.go

@@ -32,7 +32,7 @@ func НовСтраницаСписокБотов(конт IKernelCtx) *Стра
 	Hassert(конт != nil, "НовСтраницаСписокБотов(): ИЯдроКонтекст==nil")
 	сам := &СтраницаСписокБотов{
 		лог:    лог,
-		прилож: конт.Get("приложение").(ИПриложение),
+		прилож: конт.Get("мод_сервер").Val().(ИПриложение),
 		рендер: web_render.НовВебРендер(стрСписок),
 	}
 	файбер := конт.Get("fiberApp").Val().(*fiber.App)

+ 18 - 18
app/lev3/serv_web/web_gui/page_bot_show/bot_show.tmpl.html

@@ -10,9 +10,9 @@
         </div>
         <div class="card-body">
             <p class="card-text">Золото: {.золото}</p>
-            <p class="card-text" hx-get="/api/bot/{.number}/angar/silver" hx-trigger="every 15s">Серебро: {.серебро}
+            <p class="card-text" hx-get="/api/bot/{.id}/angar/silver" hx-trigger="every 15s">Серебро: {.серебро}
             </p>
-            <p class="card-text" hx-get="/api/bot/{.number}/tank/fuel" hx-trigger="every 15s">Топливо: {.топливо}
+            <p class="card-text" hx-get="/api/bot/{.id}/tank/fuel" hx-trigger="every 15s">Топливо: {.топливо}
             </p>
             <p class="card-text">Слава: {.слава}</p>
         </div>
@@ -41,18 +41,18 @@
             <h3>Шахта</h3>
         </div>
         <div class="card-body">
-            <p class="card-text" hx-get="/api/bot/{.number}/mine/level" hx-trigger="every 15s">[Уровень:
+            <p class="card-text" hx-get="/api/bot/{.id}/mine/level" hx-trigger="every 15s">[Уровень:
                 {.шахта_уровень}]</p>
-            <p class="card-text" hx-get="/api/bot/{.number}/mine/mode" hx-trigger="every 15s">Режим: {.шахта_режим}
+            <p class="card-text" hx-get="/api/bot/{.id}/mine/mode" hx-trigger="every 15s">Режим: {.шахта_режим}
             </p>
-            <p class="card-text" hx-get="/api/bot/{.number}/mine/count_product" hx-trigger="every 15s">Кол:
+            <p class="card-text" hx-get="/api/bot/{.id}/mine/count_product" hx-trigger="every 15s">Кол:
                 {.шахта_сделать_кол}</p>
-            <p class="card-text" hx-get="/api/bot/{.number}/mine/name_product" hx-trigger="every 15s">Тип:
+            <p class="card-text" hx-get="/api/bot/{.id}/mine/name_product" hx-trigger="every 15s">Тип:
                 {.шахта_сделать_назв}</p>
         </div>
-        <div class="card-footer border-success" hx-get="/api/bot/{.number}/mine/back_time/" hx-trigger="every 5s">
+        <div class="card-footer border-success" hx-get="/api/bot/{.id}/mine/back_time/" hx-trigger="every 5s">
             Время: {.шахта_сделать_время}</div>
-        <button type="button" class="btn btn-secondary" hx-get="/api/bot/{.number}/mine/log" hx-trigger="click"
+        <button type="button" class="btn btn-secondary" hx-get="/api/bot/{.id}/mine/log" hx-trigger="click"
             hx-target="#mine_log">Лог</button>
         <div class="text" id="mine_log"></div>
     </div>
@@ -64,16 +64,16 @@
             <h3>Полигон</h3>
         </div>
         <div class="card-body">
-            <p class="card-text" hx-get="/api/bot/{.number}/polygon/level" hx-trigger="every 15s">Уровень:
+            <p class="card-text" hx-get="/api/bot/{.id}/polygon/level" hx-trigger="every 15s">Уровень:
                 {.полигон_уровень}</p>
-            <p class="card-text" hx-get="/api/bot/{.number}/polygon/mode" hx-trigger="every 15s">Режим:
+            <p class="card-text" hx-get="/api/bot/{.id}/polygon/mode" hx-trigger="every 15s">Режим:
                 {.полигон_режим}</p>
-            <p class="card-text" hx-get="/api/bot/{.number}/polygon/count_product" hx-trigger="every 15s">Кол:
+            <p class="card-text" hx-get="/api/bot/{.id}/polygon/count_product" hx-trigger="every 15s">Кол:
                 {.полигон_сделать_кол}</p>
-            <p class="card-text" hx-get="/api/bot/{.number}/polygon/name_product" hx-trigger="every 15s">Тип:
+            <p class="card-text" hx-get="/api/bot/{.id}/polygon/name_product" hx-trigger="every 15s">Тип:
                 {.полигон_сделать_назв}</p>
         </div>
-        <div class="card-footer border-success" hx-get="/api/bot/{.number}/polygon/back_time/" hx-trigger="every 5s">
+        <div class="card-footer border-success" hx-get="/api/bot/{.id}/polygon/back_time/" hx-trigger="every 5s">
             Время: {.полигон_сделать_время}</div>
     </div>
 
@@ -84,20 +84,20 @@
             <h3>Арсенал</h3>
         </div>
         <div class="card-body">
-            <p class="card-text" hx-get="/api/bot/{.number}/arsenal/level" hx-trigger="every 15s">Уровень:
+            <p class="card-text" hx-get="/api/bot/{.id}/arsenal/level" hx-trigger="every 15s">Уровень:
                 {.арсенал_уровень}</p>
-            <p class="card-text" hx-get="/api/bot/{.number}/arsenal/mode" hx-trigger="every 15s">Работа:
+            <p class="card-text" hx-get="/api/bot/{.id}/arsenal/mode" hx-trigger="every 15s">Работа:
                 {.оружейная_работа}</p>
-            <p class="card-text" hx-get="/api/bot/{.number}/arsenal/name_product" hx-trigger="every 15s">Тип:
+            <p class="card-text" hx-get="/api/bot/{.id}/arsenal/name_product" hx-trigger="every 15s">Тип:
                 {.оружейная_режим}</p>
             <p class="card-text">Кумул: {.оружейная_кумул}</p>
             <p class="card-text">Бронебойки: {.оружейная_бронебойки}</p>
             <p class="card-text">Фугасы: {.оружейная_фугасы}</p>
             <p class="card-text">Ремки: {.оружейная_ремки}</p>
         </div>
-        <div class="card-footer border-success" hx-get="/api/bot/{.number}/arsenal/back_time/" hx-trigger="every 5s">
+        <div class="card-footer border-success" hx-get="/api/bot/{.id}/arsenal/back_time/" hx-trigger="every 5s">
             Время: {.оружейная_время}</div>
-        <button type="button" class="btn btn-secondary" hx-get="/api/bot/{.number}/arsenal/log" hx-trigger="click"
+        <button type="button" class="btn btn-secondary" hx-get="/api/bot/{.id}/arsenal/log" hx-trigger="click"
             hx-target="#arsenal_log">Лог</button>
         <div class="text" id="arsenal_log"></div>
     </div>

+ 10 - 9
app/lev3/serv_web/web_gui/page_bot_show/page_bot_show.go

@@ -32,11 +32,11 @@ func НовСтраницаБотПоказать(конт IKernelCtx) *Стра
 	Hassert(конт != nil, "НовСтраницаБотПоказать(): ИЯдроКонтекст==nil")
 	сам := &СтраницаБотПоказать{
 		лог:    лог,
-		прилож: конт.Get("приложение").(ИПриложение),
+		прилож: конт.Get("мод_сервер").Val().(ИПриложение),
 		рендер: web_render.НовВебРендер(стрБотПоказать),
 	}
 	файбер := конт.Get("fiberApp").Val().(*fiber.App)
-	файбер.Get("/gui/bot/:number", сам.кукиПроверить, сам.гетБотПоказ)
+	файбер.Get("/gui/bot/:id", сам.кукиПроверить, сам.гетБотПоказ)
 	// файбер.Post("/gui/bot/add", сам.кукиПроверить, сам.постДобавитьБота)
 	return сам
 }
@@ -44,7 +44,7 @@ func НовСтраницаБотПоказать(конт IKernelCtx) *Стра
 // Показывает состояние бота по имени
 func (сам *СтраницаБотПоказать) гетБотПоказ(кнт *fiber.Ctx) error {
 	сам.лог.Debug("СтраницаБотПоказать.гетБотПоказ()\n")
-	стрНомер := кнт.Params("number")
+	стрНомер := кнт.Params("id")
 	иНомер, ош := strconv.Atoi(стрНомер)
 	if ош != nil {
 		return кнт.Redirect("/gui/bot", http.StatusSeeOther)
@@ -56,13 +56,14 @@ func (сам *СтраницаБотПоказать) гетБотПоказ(к
 		return кнт.Redirect("/gui/bot", http.StatusSeeOther)
 	}
 	{ // Глобальные показатели
-		ангар := бот.Ангар()
+		ангар := бот.КонтБот().Get("ангар").Val().(ИАренаАнгар)
 		сам.рендер.Доб("{.имя}", бот.Имя())
-		сам.рендер.Доб("{.number}", бот.Номер())
+		номер:=бот.Номер()
+		сам.рендер.Доб("{.id}", номер)
 		сам.рендер.Доб("{.золото}", ангар.Золото().ЗначСтр())
 		сам.рендер.Доб("{.серебро}", ангар.Серебро().ЗначСтр())
 		сам.рендер.Доб("{.топливо}", ангар.Топливо().ЗначСтр())
-		сам.рендер.Доб("{.слава}", бот.КонтБот().Get("слава").Val().(int))
+		сам.рендер.Доб("{.слава}", бот.Стата().Слава())
 	}
 	{ // Сила танка
 		стата := бот.Стата()
@@ -73,7 +74,7 @@ func (сам *СтраницаБотПоказать) гетБотПоказ(к
 		сам.рендер.Доб("{.мощь}", стата.Мощь().ЗначСтр())
 	}
 	{ // Шахта
-		шахта := бот.КонтБот().Get("шахта").(ИАренаШахта)
+		шахта := бот.КонтБот().Get("шахта").Val().(ИАренаШахта)
 		сам.рендер.Доб("{.шахта_уровень}", шахта.Уровень().Получ())
 		сам.рендер.Доб("{.шахта_режим}", шахта.АренаСостояние().Состояние())
 		сам.рендер.Доб("{.шахта_сделать_кол}", шахта.ПродуктКолСейчас())
@@ -81,7 +82,7 @@ func (сам *СтраницаБотПоказать) гетБотПоказ(к
 		сам.рендер.Доб("{.шахта_сделать_время}", шахта.ПродуктВремяСейчас())
 	}
 	{ // Полигон
-		полигон := бот.КонтБот().Get("полигон").(ИАренаПолигон)
+		полигон := бот.КонтБот().Get("полигон").Val().(ИАренаПолигон)
 		сам.рендер.Доб("полигон_уровень", полигон.Уровень().ЗначСтр())
 		сам.рендер.Доб("полигон_режим", полигон.АренаСостояние().Состояние())
 		сам.рендер.Доб("полигон_сделать_кол", полигон.ПродуктКолСейчас())
@@ -89,7 +90,7 @@ func (сам *СтраницаБотПоказать) гетБотПоказ(к
 		сам.рендер.Доб("полигон_сделать_время", полигон.ПродуктВремяСейчас())
 	}
 	{ // Арсенал
-		арс := бот.КонтБот().Get("арсенал").(ИАренаАрсенал)
+		арс := бот.КонтБот().Get("арсенал").Val().(ИАренаАрсенал)
 		сам.рендер.Доб("оружейная_уровень", арс.Уровень().ЗначСтр())
 		сам.рендер.Доб("оружейная_работа", арс.АренаСостояние().РаботаИмя())
 		сам.рендер.Доб("оружейная_режим", арс.АренаСостояние().Состояние())

+ 1 - 1
app/lev3/serv_web/web_gui/web_gui.go

@@ -27,7 +27,7 @@ func НовВебГуи(конт IKernelCtx) *ВебГуи {
 	лог := NewLogBuf()
 	Hassert(конт != nil, "НовВебГуи(): ИЯдроКонтекст==nil")
 	сам := &ВебГуи{
-		прилож: конт.Get("приложение").(ИПриложение),
+		прилож: конт.Get("мод_сервер").Val().(ИПриложение),
 		лог:    лог,
 	}
 	файбер := конт.Get("fiberApp").Val().(*fiber.App)

+ 8 - 9
app/lev3/server_stat/server_stat.go

@@ -10,13 +10,12 @@ import (
 	. "gitp78su.ipnodns.ru/svi/kern"
 	. "gitp78su.ipnodns.ru/svi/kern/kc/helpers"
 	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
-
-	. "wartank/app/lev0/types"
+	// . "wartank/app/lev0/types"
 )
 
 // СерверСтат -- структура статистики сервера
 type СерверСтат struct {
-	серв         ИПриложение
+	конт         IKernelCtx
 	CчётСтарт_   int           `json:"count_start"`  // Количество запусков
 	ВремяВсего_  time.Duration `json:"time_total"`   // Общее время работы в секундах
 	ВремяСессия_ time.Duration `json:"time_session"` // Время сессии в секундах
@@ -25,12 +24,12 @@ type СерверСтат struct {
 }
 
 // НовСерверСтат -- возвращает структуру статистики сервера
-func НовСерверСтат(серв ИПриложение) *СерверСтат {
+func НовСерверСтат() *СерверСтат {
+	конт := GetKernelCtx()
 	лог := NewLogBuf()
 	лог.Info("НовСерверСтат()\n")
-	Hassert(серв != nil, "НовСерверСтат: ИСервер == nil")
 	сам := &СерверСтат{
-		серв:         серв,
+		конт:         конт,
 		CчётСтарт_:   0,
 		ВремяВсего_:  0,
 		ВремяСессия_: 0,
@@ -45,7 +44,7 @@ func НовСерверСтат(серв ИПриложение) *СерверС
 
 // Загружает статистику сервера
 func (сам *СерверСтат) загр() {
-	store := сам.серв.Get("kernStore").(IKernelStoreKv)
+	store := сам.конт.Get("kernStoreKV").Val().(IKernelStoreKv)
 	бинДанные, ош := store.Get("server_stat")
 	if ош != nil {
 		if strings.Contains(ош.Error(), "not found") {
@@ -70,7 +69,7 @@ func (сам *СерверСтат) пуск() {
 	}
 	for {
 		select {
-		case <-сам.серв.Ctx().Done():
+		case <-сам.конт.Ctx().Done():
 			return
 		default:
 			фнПуск()
@@ -82,7 +81,7 @@ func (сам *СерверСтат) пуск() {
 func (сам *СерверСтат) сохр() {
 	бинДанные, ош := json.Marshal(сам)
 	Hassert(ош == nil, "СерверСтат.сохр(): при кодировании статистики в JSON, ош=\n\t%v\n", ош)
-	store := сам.серв.Get("kernStore").(IKernelStoreKv)
+	store := сам.конт.Get("kernStoreKV").Val().(IKernelStoreKv)
 	ош = store.Set("server_stat", бинДанные)
 	Hassert(ош == nil, "СерверСтат.сохр(): при сохранении статистики в хранилище, ош=\n\t%v\n", ош)
 }

+ 0 - 56
app/lev4/applic/applic.go

@@ -1,56 +0,0 @@
-// package applic -- главный тип приложения, содержит бота, интерфейсы и т.п.
-package applic
-
-import (
-	. "gitp78su.ipnodns.ru/svi/kern"
-	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
-
-	. "wartank/app/lev0/types"
-	"wartank/app/lev3/farm_bots"
-	"wartank/app/lev3/serv_web"
-	"wartank/app/lev3/server_stat"
-)
-
-// Приложение -- главный тип приложения
-type Приложение struct {
-	IKernelCtx
-	ботоФерма *farm_bots.БотоФерма
-	сервСтат  ИСерверСтат
-	лог       ILogBuf
-	ядроВеб   IKernelServerHttp
-}
-
-// НовПриложение -- возвращает новый объект приложения
-func НовПриложение() *Приложение {
-	лог := NewLogBuf()
-	лог.Info("НовПриложение()\n")
-	сам := &Приложение{
-		IKernelCtx: GetKernelCtx(),
-		лог:        лог,
-	}
-	_ = GetKernelStoreKv()
-	сам.ядроВеб = GetKernelServerHttp()
-	сам.Set("приложение", сам, "Приложение WarTank")
-	сам.ботоФерма = farm_bots.НовБотоФерма(сам)
-	_ = serv_web.НовСервВеб(сам)
-	сам.сервСтат = server_stat.НовСерверСтат(сам)
-	_ = ИПриложение(сам)
-	return сам
-}
-
-// Пуск -- запускает сервер бота в работу
-func (сам *Приложение) Пуск() {
-	сам.лог.Info("НовПриложение.Пуск()\n")
-	сам.ядроВеб.Run()
-	<-сам.Ctx().Done()
-}
-
-// Стат -- возвращает статистику сервера
-func (сам *Приложение) Стат() ИСерверСтат {
-	return сам.сервСтат
-}
-
-// ServBots -- возвращает словарь ботов
-func (сам *Приложение) ServBots() ИБотоФерма {
-	return сам.ботоФерма
-}

+ 6 - 5
app/lev4/build/build.go

@@ -8,20 +8,21 @@ import (
 	"time"
 
 	. "gitp78su.ipnodns.ru/svi/kern"
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
 
-	. "wartank/app/lev0/types"
-	"wartank/app/lev4/applic"
+	"wartank/app/lev4/mod_serv"
 )
 
-func СобратьПриложение() ИПриложение {
+func НовМодСервер() IKernelModule {
+	конт := GetKernelCtx()
 	go ЗапуститьПрофиль()
 	bi, _ := debug.ReadBuildInfo()
 	лог := NewLogBuf()
 	лог.Info("ИНФО \tgo = %v\n\tvers = %v\n", bi.GoVersion, bi.Main.Version)
-	прил := applic.НовПриложение()
+	прил := mod_serv.НовМодСервер()
 	go func() {
 		time.Sleep(time.Minute * 20)
-		прил.Cancel()
+		конт.Cancel()
 	}()
 	return прил
 }

+ 12 - 0
app/lev4/lev4.go

@@ -1,2 +1,14 @@
 // package lev4 -- сборочный слой
 package lev4
+
+import (
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
+	"wartank/app/lev4/mod_serv"
+)
+
+// НовМодСервер -- возвращает новый модуль сервера
+func НовМодСервер() IKernelModule {
+	сервер := mod_serv.НовМодСервер()
+	return сервер
+}

+ 55 - 0
app/lev4/mod_serv/mod_serv.go

@@ -0,0 +1,55 @@
+// package mod_serv -- главный тип приложения, содержит бота, интерфейсы и т.п.
+package mod_serv
+
+import (
+	. "gitp78su.ipnodns.ru/svi/kern"
+	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
+
+	. "wartank/app/lev0/types"
+	"wartank/app/lev3/farm_bots"
+	"wartank/app/lev3/serv_web"
+	"wartank/app/lev3/server_stat"
+)
+
+// МодульСервер -- главный тип приложения
+type МодульСервер struct {
+	IKernelModule
+	ботоФерма *farm_bots.БотоФерма
+	сервСтат  ИСерверСтат
+	лог       ILogBuf
+}
+
+// НовМодСервер -- возвращает новый модуль сервера
+func НовМодСервер() *МодульСервер {
+	лог := NewLogBuf()
+	лог.Info("НовМодСервер()\n")
+	сам := &МодульСервер{
+		IKernelModule: NewKernelModule("мод_сервер"),
+		лог:           лог,
+	}
+	конт := GetKernelCtx()
+	конт.Set("мод_сервер", сам, "Модуль сервера WarBot")
+	_ = GetKernelStoreKv()
+	сам.ботоФерма = farm_bots.НовБотоФерма()
+	сервВеб := serv_web.НовСервВеб()
+	сам.Ctx().Set("сервВеб", сервВеб, "Веб-сервер модуля сервера")
+	сам.сервСтат = server_stat.НовСерверСтат()
+	сам.Ctx().Set("сервСтат", сам.сервСтат, "Статистика сервера")
+	_ = ИПриложение(сам)
+	return сам
+}
+
+// Пуск -- запускает сервер бота в работу
+func (сам *МодульСервер) Run() {
+	сам.лог.Info("МодульСервер.Пуск()\n")
+}
+
+// Стат -- возвращает статистику сервера
+func (сам *МодульСервер) Стат() ИСерверСтат {
+	return сам.сервСтат
+}
+
+// ServBots -- возвращает словарь ботов
+func (сам *МодульСервер) ServBots() ИБотоФерма {
+	return сам.ботоФерма
+}

+ 14 - 2
cmd/server/main.go

@@ -9,10 +9,22 @@
 package main
 
 import (
+	. "gitp78su.ipnodns.ru/svi/kern"
+
 	"wartank/app/lev4/build"
 )
 
 func main() {
-	прилож := build.СобратьПриложение()
-	прилож.Пуск()
+	монолит := GetMonolitLocal("WarTank")
+
+	модКонт:=GetModuleKernelCtx()
+	монолит.Add(модКонт)
+
+	модВеб:=GetModuleServHttp()
+	монолит.Add(модВеб)
+
+	сервер := build.НовМодСервер()
+	монолит.Add(сервер)
+	монолит.Run()
+	монолит.Wait()
 }

+ 1 - 1
go.mod

@@ -4,7 +4,7 @@ go 1.24.0
 
 require (
 	github.com/gofiber/fiber/v2 v2.52.6
-	gitp78su.ipnodns.ru/svi/kern v1.5.0
+	gitp78su.ipnodns.ru/svi/kern v1.6.0
 )
 
 require (

+ 2 - 2
go.sum

@@ -55,8 +55,8 @@ github.com/valyala/fasthttp v1.59.0/go.mod h1:GTxNb9Bc6r2a9D0TWNSPwDz78UxnTGBViY
 github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
 github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-gitp78su.ipnodns.ru/svi/kern v1.5.0 h1:2+HRRj5T7ON8OqZMl8gwa+omNG2WTqhTdRmdkyrFu80=
-gitp78su.ipnodns.ru/svi/kern v1.5.0/go.mod h1:+8wsxQThUx9wegfPZffhRJx+s+hnyDHv4n3ODMQm6+w=
+gitp78su.ipnodns.ru/svi/kern v1.6.0 h1:kdwhSTy4SocFfdz91/DZOT0Cjd4lzZZVNYYz7TZYCDc=
+gitp78su.ipnodns.ru/svi/kern v1.6.0/go.mod h1:+8wsxQThUx9wegfPZffhRJx+s+hnyDHv4n3ODMQm6+w=
 go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
 go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
 go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=

+ 9 - 9
vendor/gitp78su.ipnodns.ru/svi/kern/kern.go

@@ -113,21 +113,21 @@ func NewClientBusHttp(url string) IBusClient {
 	return client
 }
 
-// NewModuleServHttp -- возвращает новый модуль для IKernelServHttp
-func NewModuleServHttp() IKernelModule {
-	modServHttp := mod_serv_http.NewModuleServHttp()
+// GetModuleServHttp -- возвращает модуль для IKernelServHttp
+func GetModuleServHttp() IKernelModule {
+	modServHttp := mod_serv_http.GetModuleServHttp()
 	return modServHttp
 }
 
-// NewModuleKernelCtx -- возвращает новый модуль для IKernelCtx
-func NewModuleKernelCtx() IKernelModule {
-	modKernelCtx := mod_kctx.NewModuleKernelCtx()
+// GetModuleKernelCtx -- возвращает модуль для IKernelCtx
+func GetModuleKernelCtx() IKernelModule {
+	modKernelCtx := mod_kctx.GetModuleKernelCtx()
 	return modKernelCtx
 }
 
-// NewModuleKernelKeeper -- возвращает новый модуль для IKernelKeeper
-func NewModuleKernelKeeper() IKernelModule {
-	modKernelKeeper := mod_keeper.NewModuleKeeper()
+// GetModuleKernelKeeper -- возвращает модуль для IKernelKeeper
+func GetModuleKernelKeeper() IKernelModule {
+	modKernelKeeper := mod_keeper.GetModuleKeeper()
 	return modKernelKeeper
 }
 

+ 15 - 2
vendor/gitp78su.ipnodns.ru/svi/kern/mds/mod_kctx/mod_kctx.go

@@ -2,6 +2,8 @@
 package mod_kctx
 
 import (
+	"sync"
+
 	"gitp78su.ipnodns.ru/svi/kern/krn/kctx"
 	"gitp78su.ipnodns.ru/svi/kern/krn/kmodule"
 	"gitp78su.ipnodns.ru/svi/kern/krn/kserv_http"
@@ -20,8 +22,18 @@ type ModuleKernelCtx struct {
 	log       ILogBuf
 }
 
-// NewModuleKernelCtx -- возвращает новый модуль контекста ядра
-func NewModuleKernelCtx() *ModuleKernelCtx {
+var (
+	mod   *ModuleKernelCtx
+	block sync.Mutex
+)
+
+// GetModuleKernelCtx -- возвращает новый модуль контекста ядра
+func GetModuleKernelCtx() *ModuleKernelCtx {
+	block.Lock()
+	defer block.Unlock()
+	if mod != nil {
+		return mod
+	}
 	sf := &ModuleKernelCtx{
 		kCtx:          kctx.GetKernelCtx(),
 		IKernelModule: kmodule.NewKernelModule("kCtx"),
@@ -33,6 +45,7 @@ func NewModuleKernelCtx() *ModuleKernelCtx {
 	_ = page_module.GetPageModule()
 
 	_ = http_api.NewHttpApi()
+	mod = sf
 	return sf
 }
 

+ 15 - 2
vendor/gitp78su.ipnodns.ru/svi/kern/mds/mod_keeper/mod_keeper.go

@@ -2,6 +2,8 @@
 package mod_keeper
 
 import (
+	"sync"
+
 	"gitp78su.ipnodns.ru/svi/kern/krn/kctx"
 	"gitp78su.ipnodns.ru/svi/kern/krn/kmodule"
 	"gitp78su.ipnodns.ru/svi/kern/krn/kserv_http"
@@ -20,8 +22,18 @@ type ModuleKeeper struct {
 	log       ILogBuf
 }
 
-// NewModuleKeeper -- возвращает новый модуль сторожа ядра
-func NewModuleKeeper() *ModuleKeeper {
+var (
+	mod   *ModuleKeeper
+	block sync.Mutex
+)
+
+// GetModuleKeeper -- возвращает новый модуль сторожа ядра
+func GetModuleKeeper() *ModuleKeeper {
+	block.Lock()
+	defer block.Unlock()
+	if mod != nil {
+		return nil
+	}
 	sf := &ModuleKeeper{
 		kCtx:          kctx.GetKernelCtx(),
 		IKernelModule: kmodule.NewKernelModule("kKeeper"),
@@ -33,6 +45,7 @@ func NewModuleKeeper() *ModuleKeeper {
 	_ = page_module.GetPageModule()
 
 	_ = http_api.NewHttpApi()
+	mod = sf
 	return sf
 }
 

+ 15 - 2
vendor/gitp78su.ipnodns.ru/svi/kern/mds/mod_serv_http/mod_serv_http.go

@@ -2,6 +2,8 @@
 package mod_serv_http
 
 import (
+	"sync"
+
 	"gitp78su.ipnodns.ru/svi/kern/krn/kmodule"
 	"gitp78su.ipnodns.ru/svi/kern/krn/kserv_http"
 	. "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
@@ -18,8 +20,18 @@ type ModuleServHttp struct {
 	log       ILogBuf
 }
 
-// NewModuleServHttp -- возвращает новый модуль HTTP-сервера
-func NewModuleServHttp() *ModuleServHttp {
+var (
+	mod   *ModuleServHttp
+	block sync.RWMutex
+)
+
+// GetModuleServHttp -- возвращает новый модуль HTTP-сервера
+func GetModuleServHttp() *ModuleServHttp {
+	block.Lock()
+	defer block.Unlock()
+	if mod != nil {
+		return mod
+	}
 	sf := &ModuleServHttp{
 		IKernelModule: kmodule.NewKernelModule("kServHttp"),
 		kServHttp:     kserv_http.GetKernelServHttp(),
@@ -30,6 +42,7 @@ func NewModuleServHttp() *ModuleServHttp {
 	_ = page_module.GetPageModule()
 
 	_ = http_api.NewHttpApi()
+	mod = sf
 	return sf
 }
 

+ 1 - 1
vendor/modules.txt

@@ -102,7 +102,7 @@ github.com/valyala/fasthttp/fasthttputil
 github.com/valyala/fasthttp/reuseport
 github.com/valyala/fasthttp/stackless
 github.com/valyala/fasthttp/tcplisten
-# gitp78su.ipnodns.ru/svi/kern v1.5.0
+# gitp78su.ipnodns.ru/svi/kern v1.6.0
 ## explicit; go 1.24.0
 gitp78su.ipnodns.ru/svi/kern
 gitp78su.ipnodns.ru/svi/kern/kc/helpers