Procházet zdrojové kódy

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

SVI před 1 rokem
rodič
revize
fb19b08e25
100 změnil soubory, kde provedl 1389 přidání a 1570 odebrání
  1. 18 21
      app/lev0/alias/alias.go
  2. 4 4
      app/lev0/alias/msec.go
  3. 4 4
      app/lev0/cons/cons.go
  4. 4 4
      app/lev0/proc/proc_fuel_attack/proc_fuel_attack.go
  5. 86 0
      app/lev0/proc/proc_fuel_find/proc_fuel_find.go
  6. 3 1
      app/lev0/types/iarena.go
  7. 4 18
      app/lev0/types/iarena_angar.go
  8. 2 1
      app/lev0/types/iarena_bank.go
  9. 0 10
      app/lev0/types/iarena_base.go
  10. 1 1
      app/lev0/types/iarena_ctx.go
  11. 6 0
      app/lev0/types/iarena_market.go
  12. 5 5
      app/lev0/types/iarena_state.go
  13. 1 1
      app/lev0/types/ibot.go
  14. 11 0
      app/lev0/types/ibot_resurses.go
  15. 1 1
      app/lev0/types/iparser_hour.go
  16. 1 1
      app/lev0/types/iparser_min.go
  17. 4 2
      app/lev0/types/iparser_sec.go
  18. 5 3
      app/lev0/types/iparser_simple.go
  19. 8 0
      app/lev0/types/iproc_fuel_find.go
  20. 7 0
      app/lev0/types/iprocess.go
  21. 11 1
      app/lev1/lev1.go
  22. 9 9
      app/lev1/product/parser_time/parse_hour/parse_hour.go
  23. 9 9
      app/lev1/product/parser_time/parse_min/parse_min.go
  24. 9 9
      app/lev1/product/parser_time/parse_sec/parse_sec.go
  25. 11 11
      app/lev1/product/parser_time/parser_time.go
  26. 2 2
      app/lev1/shot/damage/damage.go
  27. 6 5
      app/lev1/shot/shot.go
  28. 6 7
      app/lev1/shot/shot_time/shot_time.go
  29. 7 8
      app/lev1/stat_param/stat_param.go
  30. 11 4
      app/lev2/arena/arena.go
  31. 189 0
      app/lev2/arena/arena_angar/arena_angar.go
  32. 0 0
      app/lev2/arena/arena_arsenal/arena_arsenal.go
  33. 9 10
      app/lev2/arena/arena_bank/arena_bank.go
  34. 0 0
      app/lev2/arena/arena_bank/bank_mode/bank_mode.go
  35. 83 0
      app/lev2/arena/arena_base/arena_base.go
  36. 0 0
      app/lev2/arena/arena_battle/arena_battle.go
  37. 0 0
      app/lev2/arena/arena_battle/battle_register/battle_register.go
  38. 2 2
      app/lev2/arena/arena_battle/battle_wait/battle_wait.go
  39. 0 0
      app/lev2/arena/arena_battle/battle_worker/battle_worker.go
  40. 0 0
      app/lev2/arena/arena_battle/battle_worker/battle_worker/battle_sound/battle_sound.go
  41. 0 0
      app/lev2/arena/arena_battle/battle_worker/battle_worker/battle_worker.go
  42. 0 0
      app/lev2/arena/arena_battle/battle_worker/battleon/battleon.go
  43. 0 0
      app/lev2/arena/arena_battle/isrun/isrun.go
  44. 3 3
      app/lev2/arena/arena_context/arena_context.go
  45. 10 10
      app/lev2/arena/arena_context/arena_state/arena_state.go
  46. 3 3
      app/lev2/arena/arena_convoy/arena_convoy.go
  47. 0 0
      app/lev2/arena/arena_death/arena_death.go
  48. 0 0
      app/lev2/arena/arena_death/death_register/death_register.go
  49. 2 2
      app/lev2/arena/arena_death/death_wait/death_wait.go
  50. 3 3
      app/lev2/arena/arena_death/death_worker/death_worker.go
  51. 0 0
      app/lev2/arena/arena_death/death_worker/process_death/battle_sound/battle_sound.go
  52. 0 0
      app/lev2/arena/arena_death/death_worker/process_death/battle_sound/is_play/is_play.go
  53. 0 0
      app/lev2/arena/arena_death/death_worker/process_death/battlesound/battlesound.go
  54. 0 0
      app/lev2/arena/arena_death/death_worker/process_death/health/health.go
  55. 0 0
      app/lev2/arena/arena_death/death_worker/process_death/health/healthtime/healthtime.go
  56. 0 0
      app/lev2/arena/arena_death/death_worker/process_death/health/isrepair/isrepair.go
  57. 0 0
      app/lev2/arena/arena_death/death_worker/process_death/health/repairtime/repairtime.go
  58. 0 0
      app/lev2/arena/arena_death/death_worker/process_death/process_death.go
  59. 3 3
      app/lev2/arena/arena_death/death_worker/process_death/shot/damage/damage.go
  60. 0 0
      app/lev2/arena/arena_death/death_worker/process_death/shot/is_shot/is_shot.go
  61. 0 0
      app/lev2/arena/arena_death/death_worker/process_death/shot/shot.go
  62. 4 4
      app/lev2/arena/arena_death/death_worker/process_death/shottime/shottime.go
  63. 0 0
      app/lev2/arena/arena_death/isrun/isrun.go
  64. 0 0
      app/lev2/arena/arena_division/arena_division.go
  65. 2 2
      app/lev2/arena/arena_division/div_war/div_war.go
  66. 0 0
      app/lev2/arena/arena_division/div_war/div_war_net/div_war_net.go
  67. 3 3
      app/lev2/arena/arena_division/div_war/div_war_on/shot/damage/damage.go
  68. 0 0
      app/lev2/arena/arena_division/div_war/process_divwar/div_war_sound/div_war_sound.go
  69. 0 0
      app/lev2/arena/arena_division/div_war/process_divwar/div_war_sound/isplay/isplay.go
  70. 0 0
      app/lev2/arena/arena_division/div_war/process_divwar/process_divwar.go
  71. 0 0
      app/lev2/arena/arena_division/divwar/div_war_on/div_war_on.go
  72. 2 2
      app/lev2/arena/arena_division/divwar/divwar.go
  73. 0 0
      app/lev2/arena/arena_division/divwar/divwarnet/divwarnet.go
  74. 0 0
      app/lev2/arena/arena_division/divwar/divwaron/divwaron.go
  75. 0 0
      app/lev2/arena/arena_duel/arena_duel.go
  76. 3 3
      app/lev2/arena/arena_fuel_storage/arena_fuel_storage.go
  77. 0 0
      app/lev2/arena/arena_laborator/arena_laborator.go
  78. 10 12
      app/lev2/arena/arena_market/arena_market.go
  79. 3 3
      app/lev2/arena/arena_masters/arena_masters.go
  80. 13 13
      app/lev2/arena/arena_mine/arena_mine.go
  81. 0 0
      app/lev2/arena/arena_missions/arena_missions.go
  82. 5 5
      app/lev2/arena/arena_polygon/arena_polygon.go
  83. 0 0
      app/lev2/arena/arena_upgrade/arena_upgrade.go
  84. 5 5
      app/lev2/arena/down_time/down_time.go
  85. 0 304
      app/lev2/arena_angar/arena_angar.go
  86. 0 83
      app/lev2/arena_angar/fuel/fuel.go
  87. 0 873
      app/lev2/arena_base/arena_base.go
  88. 4 7
      app/lev3/bot/bot.go
  89. 40 0
      app/lev3/bot/bot_stat/bot_resurs/bot_resurs.go
  90. 0 46
      app/lev3/bot/bot_stat/stat_resurs/stat_resurs.go
  91. 8 8
      app/lev3/bot/bot_stat/tank_stat/tank_stat.go
  92. 16 14
      app/lev3/serv_web/serv_web.go
  93. 5 5
      app/lev3/serv_web/web_gui/page_bot_show/page_bot_show.go
  94. 11 0
      pkg/alias/alias.go
  95. 173 0
      pkg/components/counttime/counttime.go
  96. 256 0
      pkg/components/counttime/counttime_test.go
  97. 56 0
      pkg/components/kernel/keeper/keeper.go
  98. 85 0
      pkg/components/kernel/keeper/keeper_test.go
  99. 79 0
      pkg/components/kernel/kernel.go
  100. 43 0
      pkg/components/kernel/kernel_test.go

+ 18 - 21
app/lev0/alias/alias.go

@@ -4,32 +4,29 @@ package alias
 // АБотНомер -- номер бота
 type АБотНомер int
 
-// ADAmage -- урон от выстрела
-type Урон int
+// АУрон -- урон от выстрела
+type АУрон int
 
-// ОкноИмя -- имя окно показа
-type ОкноИмя string
+// АВремя -- строковый тип количества времени
+type АВремя string
 
-// Время -- строковый тип количества времени
-type Время string
+// АЧас -- количество часов
+type АЧас uint
 
-// Час -- количество часов
-type Час uint
+// АМин -- количество минут
+type АМин uint
 
-// Мин -- количество минут
-type Мин uint
+// АСек -- количество секунд
+type АСек uint
 
-// Сек -- количество секунд
-type Сек uint
+// ААренаИмя -- имя арены
+type ААренаИмя string
 
-// АренаИмя -- имя арены
-type АренаИмя string
+// ААренаСостояние -- состояние арены (не существует, апгрейд, ожидание, работа)
+type ААренаСостояние string
 
-// АренаСостояние -- состояние арены (не существует, апгрейд, ожидание, работа)
-type АренаСостояние string
+// АРаботаИмя -- имя текущей работы арены (серебро-1, серебро-3, зависит от выбранного режима)
+type АРаботаИмя string
 
-// АренаРаботаИмя -- имя текущей работы арены (серебро-1, серебро-3, зависит от выбранного режима)
-type АренаРаботаИмя string
-
-// АренаРежимНомер -- номер режима арены (1/2/...)
-type АренаРежимНомер int
+// АРежим -- номер режима арены (1/2/...)
+type АРежим int

+ 4 - 4
app/lev0/alias/msec.go

@@ -1,9 +1,9 @@
 package alias
 
-// МилСек -- время в миллисекундах
-type МилСек uint
+// АМилСек -- время в миллисекундах
+type АМилСек uint
 
 // Сек -- возвращает полное число секунд
-func (сам МилСек) Сек() Сек {
-	return Сек(сам / 1_000)
+func (сам АМилСек) Сек() АСек {
+	return АСек(сам / 1_000)
 }

+ 4 - 4
app/lev0/cons/cons.go

@@ -14,10 +14,10 @@ const ( // Задержки для работы
 )
 
 const ( // Режимы работы
-	РежимНеСуществует = alias.АренаСостояние("режим_не_существует")
-	РежимАпгрейд      = alias.АренаСостояние("режим_апгрейд")
-	РежимОжидание     = alias.АренаСостояние("режим_ожидание")
-	РежимРабота       = alias.АренаСостояние("режим_работа")
+	РежимНеСуществует = alias.ААренаСостояние("режим_не_существует")
+	РежимАпгрейд      = alias.ААренаСостояние("режим_апгрейд")
+	РежимОжидание     = alias.ААренаСостояние("режим_ожидание")
+	РежимРабота       = alias.ААренаСостояние("режим_работа")
 )
 
 // const (

+ 4 - 4
app/lev2/arena_angar/fuel_attack/fuel_attack.go → app/lev0/proc/proc_fuel_attack/proc_fuel_attack.go

@@ -1,5 +1,5 @@
 // package fuel_attack -- объект боя на топливе
-package fuel_attack
+package proc_fuel_attack
 
 import (
 	"fmt"
@@ -16,12 +16,12 @@ import (
 // ТопливоБой -- объект боя на топливе
 type ТопливоБой struct {
 	ИАрена
-	ангар  ИАнгар
+	ангар  ИАренаАнгар
 	клиент ИХттпВоркер
 }
 
 // НовТопливоБой -- возвращает новый *ТопливоБойNet
-func НовТопливоБой(конт ИБотКонтекст, ангар ИАнгар) (*ТопливоБой, error) {
+func НовТопливоБой(конт ИБотКонтекст, ангар ИАренаАнгар) (*ТопливоБой, error) {
 	хттпВоркер := конт.Получ("хттпВоркер").(ИХттпВоркер)
 	сам := &ТопливоБой{
 		ангар:  ангар,
@@ -303,6 +303,6 @@ func (сам *ТопливоБой) сделатьВыстрелы(lstShoot2 []s
 	if err := фнВыстрел3(); err != nil {
 		return err
 	}
-	сам.ангар.РесурсыОбновить()
+	сам.ангар.Обновить()
 	return nil
 }

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

@@ -0,0 +1,86 @@
+// package proc_fuel_find -- процесс поиска топлива в баке
+package proc_fuel_find
+
+import (
+	"strconv"
+	"strings"
+	"time"
+
+	. "wartank/app/lev0/types"
+	"wartank/app/lev1/stat_param"
+	"wartank/kernel"
+	. "wartank/kernel/kernel_types"
+)
+
+// Топливо -- процесс поиска топлива в баке +1 каждые 15 сек
+type ПроцессТопливоНайти struct {
+	ИАренаАнгар
+	лог     ИЯдроЛог
+	топливо ИСтатПарам
+}
+
+// НовТопливо -- возвращает новый топливный бак
+func НовПроцессТопливоНайти(конт ИБотКонтекст) ИПроцессТопливоНайти {
+	лог := kernel.НовЛог("ПроцессТопливоНайти")
+	лог.Отладка("НовПроцессТопливоНайти\n")
+	сам := &ПроцессТопливоНайти{
+		ИАренаАнгар: конт.Получ("ангар").(ИАренаАнгар),
+		лог:лог,
+		топливо:     stat_param.НовСтатПарам("топливо"),
+	}
+	конт.Уст("проц_поиск_топливо", сам)
+	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 {
+		сам.лог.Ошибка("Обновить(): бот=%q, при поиске строки топлива, стр=\n\t%v\n", сам.Бот().Имя(), strOut)
+		return
+	}
+	if lstFuel[1] == "" {
+		сам.лог.Ошибка("Обновить(): %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 сам.топливо
+}

+ 3 - 1
app/lev0/types/iarena.go

@@ -12,11 +12,13 @@ type ИАрена interface {
 	// СтрОбновить -- обновляет список строк арены
 	СтрОбновить(lstString []string) error
 	// ОбратВремяУст -- устанавливает новое значение обратного счётчика времени
-	ОбратВремяУст(времяСек alias.Время) error
+	ОбратВремяУст(времяСек alias.АВремя) error
 	// Обновить -- обновляет список строк арены
 	Обновить()
 	// Пуск -- запускает арену в обработку на текущий шаг
 	Пуск()
 	// Сеть -- возвращает ссылку на сеть арены
 	Сеть() ИАренаСеть
+	// Уровень -- возвращает уровень арены
+	Уровень() ИСтатПарам
 }

+ 4 - 18
app/lev0/types/iarena_angar.go

@@ -5,34 +5,20 @@ package types
 */
 
 // ИАнгар -- интерфейс ангара
-type ИАнгар interface {
+type ИАренаАнгар interface {
 	ИАрена
-	// Конвой -- возвращает объект конвоя
-	Конвой() ИАренаКонвой
 	// Золото -- возвращает объект золота
 	Золото() ИСтатПарам
 	// Топливо -- возвращает объект топлива
 	Топливо() ИСтатПарам
-	// Уровень -- возвращает объект уровня игрока
-	Уровень() ИСтатПарам
 	// Прогресс -- возвращает прогресс уровня игрока
 	Прогресс() ИСтатПарам
 	// ИгрокиОнлайн -- возвращает число игроков онлайн
 	ИгрокиОнлайн() ИСтатПарам
 	// СереброЗаработаноСессия -- возвращает заработанное серебро с момента запуска бота
-	СереброЗаработаноСессия() ИСтатПарам
-	// СереброВсего -- возвращает всё серебро бота
-	СереброВсего() ИСтатПарам
-	// СереброОбновить -- на основе фактического серебра -- обновляет вырабатанное серебро
-	СереброОбновить(silverFact int)
-	// Сражение -- возвращает объект сражения
-	Сражение() ИСражениеСцена
-	// База -- возвращает объект базы
-	База() ИАренаБаза
-	// Миссии -- возвращает объект миссий
-	Миссии() ИМиссии
-	// РесурсыОбновить -- принудительно обновляет ресурсы бота
-	РесурсыОбновить()
+	СереброСессия() ИСтатПарам
+	// Серебро -- возвращает всё серебро бота
+	Серебро() ИСтатПарам
 	// Обновить -- требует обновления ангара
 	Обновить()
 	// Пуск -- запускает ангар в работу

+ 2 - 1
app/lev0/types/iarena_bank.go

@@ -5,7 +5,8 @@ package types
 */
 
 // ИБанк -- интерфейс банка на базе
-type ИБанк interface {
+type ИАренаБанк interface {
+	ИАрена
 	// СереброБот -- сколько серебра заработал бот
 	СереброБот() ИСтатПарам
 	// РежимРаботы1 -- объект первого режима производства

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

@@ -7,14 +7,4 @@ package types
 // ИАренаБаза -- интерфейс к базе игры
 type ИАренаБаза interface {
 	ИАрена
-	// Арсенал -- возвращает объект арсенала
-	Арсенал() ИАренаАрсенал
-	// Банк -- возвращает объект банка
-	Банк() ИБанк
-	// Полигон -- возвращает объект полигона
-	Полигон() ИАренаПолигон
-	// Шахта -- возвращает объект шахты
-	Шахта() ИАренаШахта
-	// Рынок -- возвращает рынок
-	Рынок() ИРынок
 }

+ 1 - 1
app/lev0/types/iarena_ctx.go

@@ -14,7 +14,7 @@ type ИАренаКонтекст interface {
 	// Отменить -- вызывает отмены контекста арены
 	Отменить()
 	// Имя -- имя игровой арены
-	Имя() alias.АренаИмя
+	Имя() alias.ААренаИмя
 	// АренаСостояние -- состояние арены
 	АренаСостояние() ИАренаСостояние
 	// ВебЛог -- возвращает веб-лог арены

+ 6 - 0
app/lev0/types/iarena_market.go

@@ -0,0 +1,6 @@
+package types
+
+// ИАренаРынок -- интерфейс к рынку
+type ИАренаРынок interface{
+	ИАрена
+}

+ 5 - 5
app/lev0/types/iarena_state.go

@@ -5,14 +5,14 @@ import "wartank/app/lev0/alias"
 // ИАренаСостояние -- состояние арены
 type ИАренаСостояние interface {
 	// СостояниеУст -- устанавливает состояние арены (не существует, ожидание, апгрейд. работа)
-	СостояниеУст(alias.АренаСостояние)
+	СостояниеУст(alias.ААренаСостояние)
 	// Состояние -- возвращает состояние арены (не существует, ожидание, апгрейд, работа)
-	Состояние() alias.АренаСостояние
+	Состояние() alias.ААренаСостояние
 	// РаботаИмя -- возвращает имя текущей работы (зависит от режим-1/2, если позволяет режим)
-	РаботаИмя() alias.АренаРаботаИмя
+	РаботаИмя() alias.АРаботаИмя
 	// РаботаИмяУст -- устанавливает имя текущей работы(зависит от режим-1/2, если позволяет режим)
-	РаботаИмяУст(name alias.АренаРаботаИмя)
+	РаботаИмяУст(name alias.АРаботаИмя)
 	// РежимНомер -- возвращает номер режима
-	РежимНомер() alias.АренаРежимНомер
+	РежимНомер() alias.АРежим
 	// РежимНомерУст -- возвращает имя режима
 }

+ 1 - 1
app/lev0/types/ibot.go

@@ -16,7 +16,7 @@ type ИБот interface {
 	// Номер -- возвращает номер бота
 	Номер() АБотНомер
 	// Ангар -- возвращает ангар бота
-	Ангар() ИАнгар
+	Ангар() ИАренаАнгар
 	// Стата -- возвращает статистику танка
 	Стата() ИТанкСтат
 	// Сеть -- возвращает объект сети

+ 11 - 0
app/lev0/types/ibot_resurses.go

@@ -0,0 +1,11 @@
+package types
+
+// ИБотРесурсы -- ресурсы бота
+type ИБотРесурсы interface {
+	// Золото -- возвращает золото бота
+	Золото() ИСтатПарам
+	// Серебро -- возвращает серебро бота
+	Серебро() ИСтатПарам
+	// Топливо -- возвращает топливо бота
+	Топливо() ИСтатПарам
+}

+ 1 - 1
app/lev0/types/iparser_hour.go

@@ -6,5 +6,5 @@ import "wartank/app/lev0/alias"
 type ИПарсерЧас interface {
 	ИПарсерПростой
 	// Получ -- возвращает числовое значение часа
-	Получ() alias.Час
+	Получ() alias.АЧас
 }

+ 1 - 1
app/lev0/types/iparser_min.go

@@ -6,5 +6,5 @@ import "wartank/app/lev0/alias"
 type ИПарсерМин interface {
 	ИПарсерПростой
 	// Получ -- возвращает числовое значение минут
-	Получ() alias.Мин
+	Получ() alias.АМин
 }

+ 4 - 2
app/lev0/types/iparser_sec.go

@@ -1,10 +1,12 @@
 package types
 
-import "wartank/app/lev0/alias"
+import (
+	. "wartank/app/lev0/alias"
+)
 
 // ИПарсерСек -- парсер секунд
 type ИПарсерСек interface {
 	ИПарсерПростой
 	// Получ -- возвращает числовое значение секунд
-	Получ() alias.Сек
+	Получ() АСек
 }

+ 5 - 3
app/lev0/types/iparser_simple.go

@@ -1,15 +1,17 @@
 package types
 
-import "wartank/app/lev0/alias"
+import (
+	. "wartank/app/lev0/alias"
+)
 
 // ИПарсерПростой -- базовый интерфейс парсеру времени
 type ИПарсерПростой interface {
 	// Уст -- устанавливает часы
-	Уст(alias.Время) error
+	Уст(АВремя) error
 	// Сброс -- сбрасывает хранимое значение
 	Сброс()
 	// String -- возвращает строковое представление
 	String() string
 	// ПолучМилСек -- возвращает хранимое количество мсек
-	ПолучМилСек() alias.МилСек
+	ПолучМилСек() АМилСек
 }

+ 8 - 0
app/lev0/types/iproc_fuel_find.go

@@ -0,0 +1,8 @@
+package types
+
+// ИПроцессТопливоНайти -- процесс поиска топлива в баке
+type ИПроцессТопливоНайти interface {
+	ИПроцесс
+	// Обновить -- обновляет количество топлива
+	Обновить()
+}

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

@@ -0,0 +1,7 @@
+package types
+
+// ИПроцесс -- интерфейс процесса
+type ИПроцесс interface{
+	// Пуск -- выполняет себя
+	Пуск()
+}

+ 11 - 1
app/lev1/lev1.go

@@ -1,2 +1,12 @@
-// package lev1 -- слой сущностей
+// package lev1 -- слой сущностей, компонентов
 package lev1
+
+import (
+	. "wartank/app/lev0/types"
+	"wartank/app/lev1/stat_param"
+)
+
+// НовСтатПарам -- возвращает новый ИСтатПарам
+func НовСтатПарам(имя string) ИСтатПарам {
+	return stat_param.НовСтатПарам_(имя)
+}

+ 9 - 9
app/lev1/product/parser_time/parse_hour/parse_hour.go

@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"strconv"
 	"sync"
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
 )
 
@@ -14,7 +14,7 @@ import (
 
 // ПарсерЧас -- потокобезопасный парсер часа из строки
 type ПарсерЧас struct {
-	знач alias.Час // Значение часа
+	знач АЧас // Значение часа
 	блок sync.RWMutex
 }
 
@@ -26,12 +26,12 @@ func НовПарсерЧас() *ПарсерЧас {
 }
 
 // ПолучМилСек -- возвращает общее число милСек
-func (сам *ПарсерЧас) ПолучМилСек() alias.МилСек {
-	return alias.МилСек(сам.знач * 3_600 * 1_000)
+func (сам *ПарсерЧас) ПолучМилСек() АМилСек {
+	return АМилСек(сам.знач * 3_600 * 1_000)
 }
 
 // Получ -- возвращает хранимое значение
-func (сам *ПарсерЧас) Получ() alias.Час {
+func (сам *ПарсерЧас) Получ() АЧас {
 	сам.блок.RLock()
 	defer сам.блок.RUnlock()
 	return сам.знач
@@ -55,7 +55,7 @@ func (сам *ПарсерЧас) Сброс() {
 // Уст -- устанавливает значение часов
 //
 //	Значение часов может быть больше 24
-func (сам *ПарсерЧас) Уст(часы alias.Время) error {
+func (сам *ПарсерЧас) Уст(часы АВремя) error {
 	сам.блок.Lock()
 	defer сам.блок.Unlock()
 	цЧасы, err := strconv.Atoi(string(часы))
@@ -65,14 +65,14 @@ func (сам *ПарсерЧас) Уст(часы alias.Время) error {
 	if цЧасы < 0 {
 		return fmt.Errorf("ПарсерЧас.Уст(): часы(%q) меньше нуля, err=\n\t%w", часы, err)
 	}
-	if err := сам.уст(alias.Час(цЧасы)); err != nil {
+	if err := сам.уст(АЧас(цЧасы)); err != nil {
 		return fmt.Errorf("ПарсерЧас.Уст(): in internal set hour(%q), err=\n\t%w", часы, err)
 	}
 	return nil
 }
 
 // УстЧас -- устанавливает числовое значение часов
-func (сам *ПарсерЧас) УстЧас(часы alias.Час) error {
+func (сам *ПарсерЧас) УстЧас(часы АЧас) error {
 	сам.блок.Lock()
 	defer сам.блок.Unlock()
 	if err := сам.уст(часы); err != nil {
@@ -82,7 +82,7 @@ func (сам *ПарсерЧас) УстЧас(часы alias.Час) error {
 }
 
 // Внутренняя процедура для числовой установки часов без блокировки
-func (сам *ПарсерЧас) уст(часы alias.Час) error {
+func (сам *ПарсерЧас) уст(часы АЧас) error {
 	сам.знач = часы
 	return nil
 }

+ 9 - 9
app/lev1/product/parser_time/parse_min/parse_min.go

@@ -5,7 +5,7 @@ import (
 	"strconv"
 	"sync"
 
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
 )
 
@@ -15,7 +15,7 @@ import (
 
 // ПарсерМинут -- потокобезопасный парсер минут из строки
 type ПарсерМинут struct {
-	знач alias.Мин // Значение минут
+	знач АМин // Значение минут
 	блок sync.RWMutex
 }
 
@@ -27,12 +27,12 @@ func НовПарсерМинут() *ПарсерМинут {
 }
 
 // ПолучМилСек -- возвращает общее число миллисекунд в значении
-func (сам *ПарсерМинут) ПолучМилСек() alias.МилСек {
-	return alias.МилСек(сам.знач * 60 * 1_000)
+func (сам *ПарсерМинут) ПолучМилСек() АМилСек {
+	return АМилСек(сам.знач * 60 * 1_000)
 }
 
 // Получ -- возвращает хранимое значение
-func (сам *ПарсерМинут) Получ() alias.Мин {
+func (сам *ПарсерМинут) Получ() АМин {
 	сам.блок.RLock()
 	defer сам.блок.RUnlock()
 	return сам.знач
@@ -54,14 +54,14 @@ func (сам *ПарсерМинут) Сброс() {
 }
 
 // Уст -- устанавливает значение минут
-func (сам *ПарсерМинут) Уст(стрМин alias.Время) error {
+func (сам *ПарсерМинут) Уст(стрМин АВремя) error {
 	сам.блок.Lock()
 	defer сам.блок.Unlock()
 	_цМин, err := strconv.Atoi(string(стрМин))
 	if err != nil {
 		return fmt.Errorf("ПарсерМинут.Parse(): минуты(%v) не число, err=%w", стрМин, err)
 	}
-	цМин := alias.Мин(_цМин)
+	цМин := АМин(_цМин)
 	if err := сам.уст(цМин); err != nil {
 		return fmt.Errorf("ПарсерМинут.Parse(): in internal set, err=\n\t%w", err)
 	}
@@ -69,7 +69,7 @@ func (сам *ПарсерМинут) Уст(стрМин alias.Время) erro
 }
 
 // УстМин -- устанавливает целочисленное значение минут
-func (сам *ПарсерМинут) УстМин(цМин alias.Мин) error {
+func (сам *ПарсерМинут) УстМин(цМин АМин) error {
 	сам.блок.Lock()
 	defer сам.блок.Unlock()
 	if err := сам.уст(цМин); err != nil {
@@ -79,7 +79,7 @@ func (сам *ПарсерМинут) УстМин(цМин alias.Мин) error
 }
 
 // Внутренняя установка минут
-func (сам *ПарсерМинут) уст(цМин alias.Мин) error {
+func (сам *ПарсерМинут) уст(цМин АМин) error {
 	if цМин >= 60 {
 		return fmt.Errorf("ПарсерМинут.уст(): минуты не в диапазоне(%v) 0..60", цМин)
 	}

+ 9 - 9
app/lev1/product/parser_time/parse_sec/parse_sec.go

@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"strconv"
 	"sync"
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
 )
 
@@ -14,7 +14,7 @@ import (
 
 // ПарсерСекунд -- парсер секунд
 type ПарсерСекунд struct {
-	знач alias.Сек
+	знач АСек
 	блок sync.RWMutex
 }
 
@@ -26,12 +26,12 @@ func НовПарсерСекунд() *ПарсерСекунд {
 }
 
 // ПолучМилСек -- возвращает число милСек в хранимых секундах
-func (сам *ПарсерСекунд) ПолучМилСек() alias.МилСек {
-	return alias.МилСек(сам.знач * 1_000)
+func (сам *ПарсерСекунд) ПолучМилСек() АМилСек {
+	return АМилСек(сам.знач * 1_000)
 }
 
 // Получ -- возвращает хранимое значение секунд
-func (сам *ПарсерСекунд) Получ() alias.Сек {
+func (сам *ПарсерСекунд) Получ() АСек {
 	сам.блок.RLock()
 	defer сам.блок.RUnlock()
 	return сам.знач
@@ -53,14 +53,14 @@ func (сам *ПарсерСекунд) Сброс() {
 }
 
 // Уст -- устанавливает значение секунд
-func (сам *ПарсерСекунд) Уст(стрСек alias.Время) error {
+func (сам *ПарсерСекунд) Уст(стрСек АВремя) error {
 	сам.блок.Lock()
 	defer сам.блок.Unlock()
 	_цСек, err := strconv.Atoi(string(стрСек))
 	if err != nil {
 		return fmt.Errorf("ПарсерСекунд.Уст(): секунды(%v) не число, ош=\n\t%w", стрСек, err)
 	}
-	цСек := alias.Сек(_цСек)
+	цСек := АСек(_цСек)
 	if err := сам.уст(цСек); err != nil {
 		return fmt.Errorf("ПарсерСекунд.Уст(): при внутренней установке, ош=\n\t%w", err)
 	}
@@ -68,7 +68,7 @@ func (сам *ПарсерСекунд) Уст(стрСек alias.Время) er
 }
 
 // УстСек -- устанавливает хранимое значение секунд
-func (сам *ПарсерСекунд) УстСек(цСек alias.Сек) error {
+func (сам *ПарсерСекунд) УстСек(цСек АСек) error {
 	сам.блок.Lock()
 	defer сам.блок.Unlock()
 	if ош := сам.уст(цСек); ош != nil {
@@ -78,7 +78,7 @@ func (сам *ПарсерСекунд) УстСек(цСек alias.Сек) erro
 }
 
 // Внутренняя установка значения секунд
-func (сам *ПарсерСекунд) уст(цСек alias.Сек) error {
+func (сам *ПарсерСекунд) уст(цСек АСек) error {
 	if цСек >= 60 {
 		return fmt.Errorf("ПарсерСекунд.уст(): секунды(%v) не в диапазоне 0..60", цСек)
 	}

+ 11 - 11
app/lev1/product/parser_time/parser_time.go

@@ -5,7 +5,7 @@ import (
 	"strings"
 	"sync"
 
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
 	"wartank/app/lev1/product/parser_time/parse_hour"
 	"wartank/app/lev1/product/parser_time/parse_min"
@@ -18,7 +18,7 @@ import (
 
 // ПарсерВремя -- потокобезопасный ковырятор строки времени
 type ПарсерВремя struct {
-	всегоМилСек alias.МилСек // Числовое значение хранимого времени
+	всегоМилСек АМилСек // Числовое значение хранимого времени
 	час         ИПарсерЧас   // Часы метки времени
 	мин         ИПарсерМин   // Минуты метки времени
 	сек         ИПарсерСек   // Секунды метки времени
@@ -45,14 +45,14 @@ func (сам *ПарсерВремя) Сброс() {
 }
 
 // ПолучМилСек -- возвращает общее число секунд
-func (сам *ПарсерВремя) ПолучМилСек() alias.МилСек {
+func (сам *ПарсерВремя) ПолучМилСек() АМилСек {
 	сам.блок.RLock()
 	defer сам.блок.RUnlock()
 	return сам.всегоМилСек
 }
 
 // Уст -- разбирает строковое представление на части
-func (сам *ПарсерВремя) Уст(стрВремя alias.Время) error {
+func (сам *ПарсерВремя) Уст(стрВремя АВремя) error {
 	сам.блок.Lock()
 	defer сам.блок.Unlock()
 	if стрВремя == "" {
@@ -60,33 +60,33 @@ func (сам *ПарсерВремя) Уст(стрВремя alias.Время)
 	}
 	сам.Сброс()
 	списВремя := strings.Split(string(стрВремя), ":")
-	фнСекУст := func(стрВремя alias.Время) error {
+	фнСекУст := func(стрВремя АВремя) error {
 		if ош := сам.сек.Уст(стрВремя); ош != nil {
 			return fmt.Errorf("ПарсерВремя.Уст().фнСекУст(): при установке секунд, ош=\n\t%w", ош)
 		}
 		return nil
 	}
 	фнМинУст := func() error {
-		стрСек := alias.Время(списВремя[1])
+		стрСек := АВремя(списВремя[1])
 		if ош := фнСекУст(стрСек); ош != nil {
 			return fmt.Errorf("ПарсерВремя.Уст().фнМинУст(): при установке секунд, ош=\n\t%w", ош)
 		}
-		стрМин := alias.Время(списВремя[0])
+		стрМин := АВремя(списВремя[0])
 		if ош := сам.мин.Уст(стрМин); ош != nil {
 			return fmt.Errorf("ПарсерВремя.Уст().фнМинУст(): при установке минут, ош=\n\t%w", ош)
 		}
 		return nil
 	}
 	фнЧасУст := func() error {
-		стрСек := alias.Время(списВремя[2])
+		стрСек := АВремя(списВремя[2])
 		if ош := фнСекУст(стрСек); ош != nil {
 			return fmt.Errorf("ПарсерВремя.Уст().фнЧасУст(): при установке секунд, ош=\n\t%w", ош)
 		}
-		стрМин := alias.Время(списВремя[1])
+		стрМин := АВремя(списВремя[1])
 		if ош := сам.мин.Уст(стрМин); ош != nil {
 			return fmt.Errorf("ПарсерВремя.Уст().фнЧасУст(): при установке минут, ош=\n\t%w", ош)
 		}
-		стрЧас := alias.Время(списВремя[0])
+		стрЧас := АВремя(списВремя[0])
 		if ош := сам.час.Уст(стрЧас); ош != nil {
 			return fmt.Errorf("ПарсерВремя.Уст().фнЧасУст(): при установке часов, ош=\n\t%w", ош)
 		}
@@ -97,7 +97,7 @@ func (сам *ПарсерВремя) Уст(стрВремя alias.Время)
 	// Разбить время, перевести в секунды
 	switch len(списВремя) {
 	case 1: // Только секунды
-		стрСек := alias.Время(списВремя[0])
+		стрСек := АВремя(списВремя[0])
 		if ош := фнСекУст(стрСек); ош != nil {
 			return ош
 		}

+ 2 - 2
app/lev1/shot/damage/damage.go

@@ -14,7 +14,7 @@ import (
 
 // Damage -- урон танка с памятью
 type Damage struct {
-	val   alias.Урон
+	val   alias.АУрон
 	res   string
 	block sync.RWMutex
 }
@@ -27,7 +27,7 @@ func NewDamage() *Damage {
 }
 
 // Set -- устанавливает урон
-func (сам *Damage) Set(val alias.Урон) {
+func (сам *Damage) Set(val alias.АУрон) {
 	сам.block.Lock()
 	defer сам.block.Unlock()
 	if сам.val == 0 { // Первоначальное присвоение

+ 6 - 5
app/lev1/shot/shot.go

@@ -12,6 +12,7 @@ import (
 	"wartank/app/lev1/shot/damage"
 	"wartank/app/lev1/shot/shot_time"
 	"wartank/kernel"
+
 	// "wartank/internal/components/sound"
 	"wartank/app/lev0/alias"
 	. "wartank/kernel/helpers"
@@ -32,7 +33,7 @@ type выстрел struct {
 	ИСражениеПроцесс                     // FIXME:
 	recharge         *shot_time.ShotTime // Сколько времени нужно для полной перезарядки
 	damage           *damage.Damage      // Урон от выстрела с памятью
-	damageSum        alias.Урон          // Суммарный урон
+	damageSum        alias.АУрон         // Суммарный урон
 	isEnd            ИБезопБул           // Признак конца сражения
 	еслиБлок         ИБезопБул           // Признак блокировки выстрела
 	login            string              // Логин для поиска контрольных строк
@@ -201,21 +202,21 @@ func (сам *выстрел) findDamage() {
 		// log._rintf("WARN Shot.findDamage(): ошибка в значении урона(%v)\n", iDamage)
 		iDamage = 0
 	}
-	сам.damageSum += alias.Урон(iDamage)
+	сам.damageSum += alias.АУрон(iDamage)
 	// log._rintf("INFO Shot.Damage(): damageSum=%v\n", сам.damageSum)
 	if iDamage < 70 {
-		сам.damage.Set(alias.Урон(iDamage))
+		сам.damage.Set(alias.АУрон(iDamage))
 		сам.recharge.Inc210()
 	}
 	// log._rintf("INFO Shot.findDamage(): выстрел=+%v, урон=%v", iDamage, сам.damageSum)
 	if iDamage == 0 {
 		return
 	}
-	сам.setDamage(alias.Урон(iDamage))
+	сам.setDamage(alias.АУрон(iDamage))
 }
 
 // setDamage -- обновляет время перезарядки в зависимости от произведённого урона
-func (сам *выстрел) setDamage(val alias.Урон) {
+func (сам *выстрел) setDamage(val alias.АУрон) {
 	сам.damage.Set(val)
 	switch сам.damage.Result() {
 	case "none":

+ 6 - 7
app/lev1/shot/shot_time/shot_time.go

@@ -2,10 +2,9 @@ package shot_time
 
 import (
 	"sync"
+	"log"
 
-	"github.com/sirupsen/logrus"
-
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 )
 
 /*
@@ -14,7 +13,7 @@ import (
 
 // ShotTime -- время до выстрела
 type ShotTime struct {
-	val   alias.МилСек // Время в мсек
+	val   АМилСек // Время в мсек
 	block sync.RWMutex
 }
 
@@ -24,7 +23,7 @@ func NewShotTime() *ShotTime {
 }
 
 // Get -- возвращает хранимое время до выстрела
-func (сам *ShotTime) Get() alias.МилСек {
+func (сам *ShotTime) Get() АМилСек {
 	сам.block.RLock()
 	defer сам.block.RUnlock()
 	return сам.val
@@ -65,11 +64,11 @@ func (сам *ShotTime) IsZero() bool {
 }
 
 // Set -- устанавливает значение по требованию
-func (сам *ShotTime) Set(val alias.МилСек) {
+func (сам *ShotTime) Set(val АМилСек) {
 	сам.block.Lock()
 	defer сам.block.Unlock()
 	if val > 500_000 {
-		logrus.WithField("val", val).Error("ShotTime.Set(): отрицательное значение")
+		log.Printf("ShotTime.Set(): отрицательное значение, val=%v\n", val)
 		return
 	}
 	сам.val = val

+ 7 - 8
app/lev1/stat_param/stat_param.go

@@ -10,47 +10,46 @@ import (
 )
 
 // СтатПарам -- потокобезопасная статистика
-type СтатПарам struct {
+type статПарам struct {
 	имя  string // Имя параметра
 	знач int    // Значение параметра
 	блок sync.RWMutex
 }
 
 // НовБотСтатистика -- возвращает новую статистику
-func НовСтатПарам(имя string) *СтатПарам {
+func НовСтатПарам_(имя string) ИСтатПарам {
 	лог := kernel.НовЛог("СтатПарам")
 	лог.Инфо("НовСтатПарам(%s)\n", имя)
 	лог.Паника(имя == "", "НовСтатПарам(): имя параметра пустое\n")
-	сам := &СтатПарам{
+	сам := &статПарам{
 		имя: имя,
 	}
-	_ = ИСтатПарам(сам)
 	return сам
 }
 
 // ЗначСтр -- строковое представление значение параметра
-func (сам *СтатПарам) ЗначСтр() string {
+func (сам *статПарам) ЗначСтр() string {
 	сам.блок.RLock()
 	defer сам.блок.RUnlock()
 	return fmt.Sprint(сам.знач)
 }
 
 // Уст -- устанавливает значение параметра
-func (сам *СтатПарам) Уст(val int) {
+func (сам *статПарам) Уст(val int) {
 	сам.блок.Lock()
 	defer сам.блок.Unlock()
 	сам.знач = val
 }
 
 // Получ -- значение хранимого параметра
-func (сам *СтатПарам) Получ() int {
+func (сам *статПарам) Получ() int {
 	сам.блок.RLock()
 	defer сам.блок.RUnlock()
 	return сам.знач
 }
 
 // Имя -- возвращает имя хранимого параметра
-func (сам *СтатПарам) Имя() string {
+func (сам *статПарам) Имя() string {
 	сам.блок.RLock()
 	defer сам.блок.RUnlock()
 	return сам.имя

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

@@ -7,6 +7,7 @@ import (
 	"sync"
 	"wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
+	"wartank/app/lev1"
 	"wartank/app/lev2/arena/arena_context"
 	"wartank/app/lev2/arena/arena_net"
 	"wartank/app/lev2/arena/arena_string"
@@ -17,7 +18,7 @@ import (
 // АренаКонфиг -- конфигурация арены
 type АренаКонфиг struct {
 	Бот_         ИБот
-	АренаИмя_    alias.АренаИмя
+	АренаИмя_    alias.ААренаИмя
 	СтрКонтроль_ string // Контрольная строка для арены
 	СтрУрл_      string // Адрес арены
 	ФнПуск_      func()
@@ -38,23 +39,24 @@ type Арена struct {
 	времяОстат ИВремяОстат               // Обратный отсчёт до окончания работы режима
 	списСтр    *arena_string.АренаСтроки // Список строк из сети для анализа секции
 	конф       АренаКонфиг
+	уровень    ИСтатПарам
 	сеть       ИАренаСеть
 	блок       sync.RWMutex
 }
 
 // НовАрена -- возвращает новую арену игры
-func НовАрена(конт ИБотКонтекст, конф АренаКонфиг) *Арена {
+func НовАрена(конт ИБотКонтекст, конф АренаКонфиг) ИАрена {
 	log.Printf("НовАрена(): стрКонтроль=%q\n", конф.СтрКонтроль_)
 	конф.контроль()
 	аренаКонтекст := arena_context.НовАренаКонтекст(конт, конф.Бот_, конф.АренаИмя_)
 	сам := &Арена{
 		ИАренаКонтекст: аренаКонтекст,
+		уровень:        lev1.НовСтатПарам("уровень"),
 		времяОстат:     down_time.НовВремОбрат(аренаКонтекст, 5),
 		списСтр:        arena_string.НовАренаСтроки(конт, конф.СтрКонтроль_),
 		конф:           конф,
 	}
 	сам.сеть = arena_net.НовАренаСеть_(конт, сам, конф.СтрУрл_) //"https://wartank.ru/angar")
-	_ = ИАрена(сам)
 	return сам
 }
 
@@ -86,13 +88,18 @@ func (сам *Арена) СтрОбновить(lstString []string) error {
 	return nil
 }
 
+// Уровень -- возвращает уровень арены
+func (сам *Арена) Уровень() ИСтатПарам {
+	return сам.уровень
+}
+
 // СписПолучить -- возвращает список строк секции
 func (сам *Арена) СписПолучить() []string {
 	return сам.списСтр.Получ()
 }
 
 // ОбратВремяУст -- устанавливает новое значение обратного счётчика времени
-func (сам *Арена) ОбратВремяУст(времяСек alias.Время) error {
+func (сам *Арена) ОбратВремяУст(времяСек alias.АВремя) error {
 	ош := сам.времяОстат.Уст(времяСек)
 	if ош != nil {
 		return fmt.Errorf("Арена.ОбратВремяУст(): ош=\n\t%w", ош)

+ 189 - 0
app/lev2/arena/arena_angar/arena_angar.go

@@ -0,0 +1,189 @@
+package arena_angar
+
+import (
+	"log"
+	"strconv"
+	"strings"
+	"time"
+
+	. "wartank/app/lev0/types"
+	"wartank/app/lev1/stat_param"
+	"wartank/app/lev2/arena"
+	"wartank/app/lev3/bot/bot_stat/bot_resurs"
+)
+
+/*
+	Объект ангара приложения
+*/
+
+// Ангар -- ангар для танка
+type АренаАнгар struct {
+	ИАрена
+	прилож        ИПриложение
+	бот           ИБот
+	progress      ИСтатПарам
+	топливо       ИСтатПарам
+	серебро       ИСтатПарам
+	золото        ИСтатПарам
+	игроковОнлайн ИСтатПарам
+
+	сереброСессия ИСтатПарам
+
+	ресурсы  ИБотРесурсы
+	танкСтат ИТанкСтат
+}
+
+// НовАнгар -- возвращает новый *Angar
+func НовАнгар(конт ИБотКонтекст) ИАренаАнгар {
+	бот := конт.Получ("бот").(ИБот)
+	сам := &АренаАнгар{
+		бот:           бот,
+		progress:      stat_param.НовСтатПарам("прогресс"),
+		игроковОнлайн: stat_param.НовСтатПарам("онлайн"),
+		сереброСессия: stat_param.НовСтатПарам("серебро сессия"),
+		танкСтат:      конт.Получ("танкПарам").(ИТанкСтат),
+		серебро:       stat_param.НовСтатПарам("серебро"),
+	}
+	аренаКонф := arena.АренаКонфиг{
+		Бот_:         бот,
+		АренаИмя_:    "Ангар",
+		СтрКонтроль_: "<title>Ангар</title>",
+		ФнПуск_:      сам.пуск,
+		СтрУрл_:      "https://wartank.ru/angar",
+	}
+	конт.Уст("ангар", сам)
+	сам.ИАрена = arena.НовАрена(конт, аренаКонф)
+	сам.ресурсы = bot_resurs.НовБотРесурсы(конт, сам)
+	return сам
+}
+
+// Золото -- возвращает объект топлива в ангаре
+func (сам *АренаАнгар) Золото() ИСтатПарам {
+	return сам.золото
+}
+
+// Топливо -- возвращает объект топлива в ангаре
+func (сам *АренаАнгар) Топливо() ИСтатПарам {
+	return сам.топливо
+}
+
+// СереброСессия -- возвращает объект серебра за текущую сессию
+func (сам *АренаАнгар) СереброСессия() ИСтатПарам {
+	return сам.сереброСессия
+}
+
+// Серебро -- возвращает объект серебра в ангаре
+func (сам *АренаАнгар) Серебро() ИСтатПарам {
+	return сам.серебро
+}
+
+// Обновить -- обновить ангар принудительно
+func (сам *АренаАнгар) Обновить() {
+	сам.РесурсыОбновить()
+}
+
+// Запускает обработку ангара
+func (сам *АренаАнгар) пуск() {
+	{ // Запуск компонентов
+	}
+	фнЦикл := func() bool {
+		сам.Обновить()
+		// сам.конвойПроверить()
+		if err := сам.ОбратВремяУст("01:00"); err != nil {
+			сам.Отменить()
+			log.Printf("Ангар.Run(): in update ICountTime, err=\n\t%v\n", err)
+			return false
+		}
+		return true
+	}
+	go func() {
+		ош := сам.ОбратВремяУст("01")
+		if ош != nil {
+			log.Printf("Ангар.Run(): in update ICountTime, ош=\n\t%v\n", ош)
+			сам.прилож.Отменить()
+			return
+		}
+		for {
+			select {
+			case <-сам.прилож.Конт().Done(): // Отмена контекста
+				return
+			case <-сам.ВремяОстат().КаналСиг(): // Метка времени
+				if !фнЦикл() {
+					return
+				}
+			default: // Запускается раз в минуту
+				if !фнЦикл() {
+					return
+				}
+				time.Sleep(time.Minute * 1)
+			}
+		}
+	}()
+}
+
+// Обновляет ресурсы ангара
+func (сам *АренаАнгар) РесурсыОбновить() {
+	сам.ИАрена.Обновить()
+	сам.золотоНайти()
+	сам.сереброНайти()
+}
+
+// Прогресс -- возвращает прогресс уровня игрока
+func (сам *АренаАнгар) Прогресс() ИСтатПарам {
+	return сам.progress
+}
+
+// ИгрокиОнлайн -- возвращает количество игроков онлайн
+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)
+}

+ 0 - 0
app/lev2/arena_arsenal/arena_arsenal.go → app/lev2/arena/arena_arsenal/arena_arsenal.go


+ 9 - 10
app/lev2/arena_bank/arena_bank.go → app/lev2/arena/arena_bank/arena_bank.go

@@ -7,11 +7,11 @@ import (
 	"strings"
 	"time"
 
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
 	"wartank/app/lev1/stat_param"
 	"wartank/app/lev2/arena"
-	"wartank/app/lev2/arena_bank/bank_mode"
+	"wartank/app/lev2/arena/arena_bank/bank_mode"
 )
 
 /*
@@ -26,8 +26,8 @@ type АренаБанк struct {
 	режим2     *bank_mode.BankMode // 2 режим работы на выбор
 }
 
-// НовБанк -- возвращает новый *Bank
-func НовБанк(конт ИБотКонтекст, база ИАренаБаза) (*АренаБанк, error) {
+// НовБанк -- возвращает новый арену банка
+func НовБанк(конт ИБотКонтекст) ИАренаБанк {
 
 	сам := &АренаБанк{
 		сереброБот: stat_param.НовСтатПарам("серебро бота"),
@@ -35,21 +35,20 @@ func НовБанк(конт ИБотКонтекст, база ИАренаБа
 		режим2:     bank_mode.NewBankMode(конт),
 	}
 	аренаКонфиг := arena.АренаКонфиг{
-		Бот_:         база.Бот(),
+		Бот_:         конт.Получ("бот").(ИБот),
 		АренаИмя_:    "Банк",
 		СтрКонтроль_: `<span class="green2">Серебро</span><br/>`,
 		ФнПуск_:      сам.пуск,
 		СтрУрл_:      "https://wartank.ru/production/Bank",
 	}
 	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
-	return сам, nil
+	return сам
 }
 
 // Пуск -- запускает банк в работу
-func (сам *АренаБанк) Пуск() error {
+func (сам *АренаБанк) Пуск() {
 	log.Printf("Банк.Run()\n")
 	go сам.пуск()
-	return nil
 }
 
 // UpdateLst -- принудительно обновляет состояние банка
@@ -218,7 +217,7 @@ func (сам *АренаБанк) СереброБот() ИСтатПарам {
 }
 
 // Запускает в производство серебро
-func (сам *АренаБанк) сделатьСеребро() (alias.МилСек, error) {
+func (сам *АренаБанк) сделатьСеребро() (АМилСек, error) {
 	var (
 		lstBank     = сам.СписПолучить()
 		ind         int
@@ -256,7 +255,7 @@ func (сам *АренаБанк) сделатьСеребро() (alias.МилС
 		if err = сам.СтрОбновить(lstBank); err != nil {
 			return 0, fmt.Errorf("BankNet.makeProduct(): при обновлении lstBank, err=%w", err)
 		}
-		if err := сам.ОбратВремяУст(alias.Время(time1)); err != nil {
+		if err := сам.ОбратВремяУст(АВремя(time1)); err != nil {
 			log.Printf("WARN Банк.makeProduct(): при установке времени производства банка(%v)\n\terr=%v\n", time1, err)
 		}
 	}

+ 0 - 0
app/lev2/arena_bank/bank_mode/bank_mode.go → app/lev2/arena/arena_bank/bank_mode/bank_mode.go


+ 83 - 0
app/lev2/arena/arena_base/arena_base.go

@@ -0,0 +1,83 @@
+// package arena_base -- база в игре
+package arena_base
+
+import (
+	"fmt"
+	"log"
+	"sync"
+	"time"
+
+	. "wartank/app/lev0/types"
+	"wartank/app/lev2/arena"
+)
+
+/*
+	Объект базы в игре.
+*/
+
+const (
+	// времОжидПлат    = "01:00" // Время ожидания платного ускорения
+	// времОжидБесплат = "30:00" // Время ожидания бесплатного ускорения
+)
+
+// База -- объект базы
+type АренаБаза struct {
+	ИАрена
+	бот          ИБот
+	блок         sync.Mutex
+}
+
+// НовБаза -- возвращает новую базу бота
+func НовБаза(конт ИБотКонтекст) ИАренаБаза {
+	бот := конт.Получ("бот").(ИБот)
+	log.Printf("НовБаза(): %q\n", бот.Имя())
+	сам := &АренаБаза{
+		бот: бот,
+	}
+	аренаКонфиг := arena.АренаКонфиг{
+		Бот_:         бот,
+		АренаИмя_:    "База",
+		СтрКонтроль_: `<title>База</title>`,
+		ФнПуск_:      сам.пуск,
+		СтрУрл_:      "https://wartank.ru/buildings",
+	}
+	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
+	return сам
+}
+
+// Запускает базу в обработку
+func (сам *АренаБаза) Пуск() {
+	log.Printf("Base.Run()\n")
+	if err := сам.runComponent(); err != nil {
+		panic(fmt.Errorf("Base.Run(): run, err=\n\t%w", err))
+	}
+	go сам.пуск()
+}
+
+// Собственная работа
+func (сам *АренаБаза) пуск() {
+	фнЦикл := func() {
+		defer time.Sleep(time.Minute * 2)
+		сам.Обновить()
+
+	}
+	for {
+		select {
+		case <-сам.Контекст().Done():
+			return
+		// case <-сам.ВремяОпрос().КаналСиг():
+		// 	фнЦикл()
+		default:
+			log.Printf("База.пуск()\n")
+			фнЦикл()
+		}
+	}
+}
+
+// Запускает компоненты
+func (сам *АренаБаза) runComponent() error {
+	log.Printf("Base.runComponent()\n")
+	сам.блок.Lock()
+	defer сам.блок.Unlock()
+	return nil
+}

+ 0 - 0
app/lev2/arena_battle/arena_battle.go → app/lev2/arena/arena_battle/arena_battle.go


+ 0 - 0
app/lev2/arena_battle/battle_register/battle_register.go → app/lev2/arena/arena_battle/battle_register/battle_register.go


+ 2 - 2
app/lev2/arena_battle/battle_wait/battle_wait.go → app/lev2/arena/arena_battle/battle_wait/battle_wait.go

@@ -5,7 +5,7 @@ import (
 	"strings"
 	"time"
 
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
 	"wartank/app/lev2/arena"
 )
@@ -102,7 +102,7 @@ func (сам *СхваткаОжидание) ждать() string {
 	strTime := lstTime[1]
 	lstTime = strings.Split(strTime, ` (`)
 	strTime = lstTime[0]
-	if err := сам.ОбратВремяУст(alias.Время(strTime)); err != nil { // Возможно уже всё
+	if err := сам.ОбратВремяУст(АВремя(strTime)); err != nil { // Возможно уже всё
 		// log._rintf("WARN BattleWait.Wait(): при установке времени ожидания сражения(%v)\n\terr=%v\n", strTime, err)
 		return ""
 	}

+ 0 - 0
app/lev2/arena_battle/battle_worker/battle_worker.go → app/lev2/arena/arena_battle/battle_worker/battle_worker.go


+ 0 - 0
app/lev2/arena_battle/battle_worker/battle_worker/battle_sound/battle_sound.go → app/lev2/arena/arena_battle/battle_worker/battle_worker/battle_sound/battle_sound.go


+ 0 - 0
app/lev2/arena_battle/battle_worker/battle_worker/battle_worker.go → app/lev2/arena/arena_battle/battle_worker/battle_worker/battle_worker.go


+ 0 - 0
app/lev2/arena_battle/battle_worker/battleon/battleon.go → app/lev2/arena/arena_battle/battle_worker/battleon/battleon.go


+ 0 - 0
app/lev2/arena_battle/isrun/isrun.go → app/lev2/arena/arena_battle/isrun/isrun.go


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

@@ -16,7 +16,7 @@ import (
 // АренаКонтекст -- контекст арены
 type АренаКонтекст struct {
 	бот       ИБот
-	аренаИмя  alias.АренаИмя
+	аренаИмя  alias.ААренаИмя
 	кнт       context.Context
 	фнОтмена  func()
 	состояние ИАренаСостояние
@@ -25,7 +25,7 @@ type АренаКонтекст struct {
 }
 
 // НовАренаКонтекст -- возвращает новый контекст арены
-func НовАренаКонтекст(конт ИБотКонтекст, бот ИБот, сценаИмя alias.АренаИмя) *АренаКонтекст {
+func НовАренаКонтекст(конт ИБотКонтекст, бот ИБот, сценаИмя alias.ААренаИмя) *АренаКонтекст {
 	Паника(конт != nil, "НовАренаКонтекст(): ИЯдроКонтекст==пусто")
 	лог := kernel.НовЛог("АренаКонтекст " + string(сценаИмя))
 	лог.Инфо("НовАренаКонтекст() " + string(сценаИмя) + "\n")
@@ -66,7 +66,7 @@ func (сам *АренаКонтекст) Контекст() context.Context {
 }
 
 // Имя -- возвращает имя арены
-func (сам *АренаКонтекст) Имя() alias.АренаИмя {
+func (сам *АренаКонтекст) Имя() alias.ААренаИмя {
 	return сам.аренаИмя
 }
 

+ 10 - 10
app/lev2/arena/arena_context/arena_state/arena_state.go

@@ -9,9 +9,9 @@ import (
 
 // СценаСостояние -- состояние сцены
 type АренаСостояние struct {
-	состояниеИмя alias.АренаСостояние // Имя режима
-	работаИмя    alias.АренаРаботаИмя // Имя работы
-	режимНомер   alias.АренаРежимНомер
+	состояниеИмя alias.ААренаСостояние // Имя режима
+	работаИмя    alias.АРаботаИмя      // Имя работы
+	режимНомер   alias.АРежим
 	block        sync.RWMutex
 }
 
@@ -25,49 +25,49 @@ func НовАренаСостояние() *АренаСостояние {
 }
 
 // РежимНомер -- возвращает номер режима арены
-func (сам *АренаСостояние) РежимНомер() alias.АренаРежимНомер {
+func (сам *АренаСостояние) РежимНомер() alias.АРежим {
 	сам.block.RLock()
 	defer сам.block.RUnlock()
 	return сам.режимНомер
 }
 
 // РаботаИмяУст -- устанавливает имя текущей работы арены
-func (сам *АренаСостояние) РаботаИмяУст(имя alias.АренаРаботаИмя) {
+func (сам *АренаСостояние) РаботаИмяУст(имя alias.АРаботаИмя) {
 	сам.block.Lock()
 	defer сам.block.Unlock()
 	сам.работаИмя = имя
 }
 
 // РаботаИмя -- возвращает имя текущей работы арены
-func (сам *АренаСостояние) РаботаИмя() alias.АренаРаботаИмя {
+func (сам *АренаСостояние) РаботаИмя() alias.АРаботаИмя {
 	сам.block.RLock()
 	defer сам.block.RUnlock()
 	return сам.работаИмя
 }
 
 // СостояниеУст -- устанавливает состояние арены
-func (сам *АренаСостояние) СостояниеУст(состояние alias.АренаСостояние) {
+func (сам *АренаСостояние) СостояниеУст(состояние alias.ААренаСостояние) {
 	сам.block.Lock()
 	defer сам.block.Unlock()
 	сам.состояниеИмя = состояние
 }
 
 // Состояние -- возвращает состояние арены
-func (сам *АренаСостояние) Состояние() alias.АренаСостояние {
+func (сам *АренаСостояние) Состояние() alias.ААренаСостояние {
 	сам.block.RLock()
 	defer сам.block.RUnlock()
 	return сам.состояниеИмя
 }
 
 // Работа -- возвращает хранимое имя работы арены
-func (сам *АренаСостояние) Работа() alias.АренаРаботаИмя {
+func (сам *АренаСостояние) Работа() alias.АРаботаИмя {
 	сам.block.RLock()
 	defer сам.block.RUnlock()
 	return сам.работаИмя
 }
 
 // РаботаУст -- устанавливает хранимое имя работы арены
-func (сам *АренаСостояние) РаботаУст(работаИмя alias.АренаРаботаИмя) {
+func (сам *АренаСостояние) РаботаУст(работаИмя alias.АРаботаИмя) {
 	сам.block.Lock()
 	defer сам.block.Unlock()
 	сам.работаИмя = работаИмя

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

@@ -7,7 +7,7 @@ import (
 	"strings"
 	"time"
 
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
 	"wartank/app/lev1/stat_param"
 	"wartank/app/lev2/arena"
@@ -163,7 +163,7 @@ func (сам *АренаКонвой) обновитьВремя() {
 		// Ждём окончания ожидания конвоя
 		lstTime := strings.Split(strLastTime, `До следующего конвоя: `)
 		strLastTime = lstTime[1]
-		if err := сам.ОбратВремяУст(alias.Время(strLastTime)); err != nil {
+		if err := сам.ОбратВремяУст(АВремя(strLastTime)); err != nil {
 			// log._rintf("WARN Конвой.обновитьВремя(): при установке времени ожидания конвоя(%v)\n\terr=%v\n", strLastTime, err)
 			err := сам.ОбратВремяУст("10")
 			if err != nil {
@@ -175,7 +175,7 @@ func (сам *АренаКонвой) обновитьВремя() {
 		// Ждём окончания ожидания конвоя
 		lstTime := strings.Split(strLastTime, `Полная маскировка через `)
 		strLastTime = lstTime[1]
-		if err := сам.ОбратВремяУст(alias.Время(strLastTime)); err != nil {
+		if err := сам.ОбратВремяУст(АВремя(strLastTime)); err != nil {
 			// log._rintf("ERRO BКонвой.обновитьВремя(): при установке времени банка для 1го режима(%v)\n\terr=%v\n", strLastTime, err)
 			err := сам.ОбратВремяУст("10")
 			if err != nil {

+ 0 - 0
app/lev2/arena_death/arena_death.go → app/lev2/arena/arena_death/arena_death.go


+ 0 - 0
app/lev2/arena_death/death_register/death_register.go → app/lev2/arena/arena_death/death_register/death_register.go


+ 2 - 2
app/lev2/arena_death/death_wait/death_wait.go → app/lev2/arena/arena_death/death_wait/death_wait.go

@@ -5,7 +5,7 @@ import (
 	"strings"
 	"time"
 
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
 	"wartank/app/lev2/arena"
 	. "wartank/kernel/kernel_types"
@@ -104,7 +104,7 @@ func (сам *СражениеОжидание) ждать() string {
 	strTime := lstTime[1]
 	lstTime = strings.Split(strTime, ` (`)
 	strTime = lstTime[0]
-	if err := сам.ОбратВремяУст(alias.Время(strTime)); err != nil { // Возможно уже всё
+	if err := сам.ОбратВремяУст(АВремя(strTime)); err != nil { // Возможно уже всё
 		// log._rintf("WARN BattleWait.Wait(): при установке времени ожидания сражения(%v)\n\terr=%v\n", strTime, err)
 		return ""
 	}

+ 3 - 3
app/lev2/arena_death/death_worker/death_worker.go → app/lev2/arena/arena_death/death_worker/death_worker.go

@@ -5,7 +5,7 @@ import (
 	"time"
 
 	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
+	"wartank/app/lev1"
 	"wartank/app/lev2/arena"
 	"wartank/app/lev2/arena_death/death_worker/process_death"
 	"wartank/app/lev2/arena_death/death_worker/process_death/battle_sound"
@@ -30,7 +30,7 @@ func НовСхваткаИсполнитель(конт ИБотКонтекс
 	сам := &СхваткаИсполнитель{
 		конт:       конт,
 		бот:        bot,
-		еслиНачало: stat_param.НовСтатПарам("тревога"),
+		еслиНачало: lev1.НовСтатПарам("тревога"),
 		sound:      battle_sound.NewBattleSound(),
 	}
 	аренаКонфиг := arena.АренаКонфиг{
@@ -46,7 +46,7 @@ func НовСхваткаИсполнитель(конт ИБотКонтекс
 
 // пуск исполнителя схватки
 func (сам *СхваткаИсполнитель) пуск() {
-	сам.еслиНачало = stat_param.НовСтатПарам("тревога")
+	сам.еслиНачало = lev1.НовСтатПарам("тревога")
 }
 
 // Танковать -- выполняет битву

+ 0 - 0
app/lev2/arena_death/death_worker/process_death/battle_sound/battle_sound.go → app/lev2/arena/arena_death/death_worker/process_death/battle_sound/battle_sound.go


+ 0 - 0
app/lev2/arena_death/death_worker/process_death/battle_sound/is_play/is_play.go → app/lev2/arena/arena_death/death_worker/process_death/battle_sound/is_play/is_play.go


+ 0 - 0
app/lev2/arena_death/death_worker/process_death/battlesound/battlesound.go → app/lev2/arena/arena_death/death_worker/process_death/battlesound/battlesound.go


+ 0 - 0
app/lev2/arena_death/death_worker/process_death/health/health.go → app/lev2/arena/arena_death/death_worker/process_death/health/health.go


+ 0 - 0
app/lev2/arena_death/death_worker/process_death/health/healthtime/healthtime.go → app/lev2/arena/arena_death/death_worker/process_death/health/healthtime/healthtime.go


+ 0 - 0
app/lev2/arena_death/death_worker/process_death/health/isrepair/isrepair.go → app/lev2/arena/arena_death/death_worker/process_death/health/isrepair/isrepair.go


+ 0 - 0
app/lev2/arena_death/death_worker/process_death/health/repairtime/repairtime.go → app/lev2/arena/arena_death/death_worker/process_death/health/repairtime/repairtime.go


+ 0 - 0
app/lev2/arena_death/death_worker/process_death/process_death.go → app/lev2/arena/arena_death/death_worker/process_death/process_death.go


+ 3 - 3
app/lev2/arena_death/death_worker/process_death/shot/damage/damage.go → app/lev2/arena/arena_death/death_worker/process_death/shot/damage/damage.go

@@ -3,7 +3,7 @@ package damage
 import (
 	"sync"
 
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 )
 
 /*
@@ -14,7 +14,7 @@ import (
 
 // Damage -- урон танка с памятью
 type Damage struct {
-	val   alias.Урон
+	val   АУрон
 	res   string
 	block sync.RWMutex
 }
@@ -27,7 +27,7 @@ func NewDamage() *Damage {
 }
 
 // Set -- устанавливает урон
-func (сам *Damage) Set(val alias.Урон) {
+func (сам *Damage) Set(val АУрон) {
 	сам.block.Lock()
 	defer сам.block.Unlock()
 	if сам.val == 0 { // Первоначальное присвоение

+ 0 - 0
app/lev2/arena_death/death_worker/process_death/shot/is_shot/is_shot.go → app/lev2/arena/arena_death/death_worker/process_death/shot/is_shot/is_shot.go


+ 0 - 0
app/lev2/arena_death/death_worker/process_death/shot/shot.go → app/lev2/arena/arena_death/death_worker/process_death/shot/shot.go


+ 4 - 4
app/lev2/arena_death/death_worker/process_death/shottime/shottime.go → app/lev2/arena/arena_death/death_worker/process_death/shottime/shottime.go

@@ -4,7 +4,7 @@ import (
 	"log"
 	"sync"
 
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 )
 
 /*
@@ -13,7 +13,7 @@ import (
 
 // ShotTime -- время до выстрела
 type ShotTime struct {
-	val   alias.МилСек // Время в мсек
+	val   АМилСек // Время в мсек
 	block sync.RWMutex
 }
 
@@ -23,7 +23,7 @@ func NewShotTime() *ShotTime {
 }
 
 // Get -- возвращает хранимое время до выстрела
-func (сам *ShotTime) Get() alias.МилСек {
+func (сам *ShotTime) Get() АМилСек {
 	сам.block.RLock()
 	defer сам.block.RUnlock()
 	return сам.val
@@ -64,7 +64,7 @@ func (сам *ShotTime) IsZero() bool {
 }
 
 // Set -- устанавливает значение по требованию
-func (сам *ShotTime) Set(val alias.МилСек) {
+func (сам *ShotTime) Set(val АМилСек) {
 	сам.block.Lock()
 	defer сам.block.Unlock()
 	if val > 10_0000 {

+ 0 - 0
app/lev2/arena_death/isrun/isrun.go → app/lev2/arena/arena_death/isrun/isrun.go


+ 0 - 0
app/lev2/arena_division/arena_division.go → app/lev2/arena/arena_division/arena_division.go


+ 2 - 2
app/lev2/arena_division/div_war/div_war.go → app/lev2/arena/arena_division/div_war/div_war.go

@@ -9,7 +9,7 @@ import (
 
 	"wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
+	"wartank/app/lev1"
 	"wartank/app/lev2/arena"
 	"wartank/app/lev2/arena_division/div_war/div_war_net"
 	"wartank/app/lev2/arena_division/div_war/process_divwar"
@@ -47,7 +47,7 @@ func NewDivWar(конт ИЯдроКонтекст, bot ИБот) (*DivWar, erro
 	}
 	сам := &DivWar{
 		bot:      bot,
-		alarm:    stat_param.НовСтатПарам("тревога"),
+		alarm:    lev1.НовСтатПарам("тревога"),
 		chDivWar: make(chan int, 1),
 		sound:    div_war_sound.NewDivWarSound(),
 		conn:     bot.Сеть().ВебВоркер(),

+ 0 - 0
app/lev2/arena_division/div_war/div_war_net/div_war_net.go → app/lev2/arena/arena_division/div_war/div_war_net/div_war_net.go


+ 3 - 3
app/lev2/arena_division/div_war/div_war_on/shot/damage/damage.go → app/lev2/arena/arena_division/div_war/div_war_on/shot/damage/damage.go

@@ -3,7 +3,7 @@ package damage
 import (
 	"sync"
 
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 )
 
 /*
@@ -14,7 +14,7 @@ import (
 
 // Damage -- урон танка с памятью
 type Damage struct {
-	val   alias.Урон
+	val   АУрон
 	res   string
 	block sync.RWMutex
 }
@@ -27,7 +27,7 @@ func NewDamage() *Damage {
 }
 
 // Set -- устанавливает урон
-func (сам *Damage) Set(val alias.Урон) {
+func (сам *Damage) Set(val АУрон) {
 	сам.block.Lock()
 	defer сам.block.Unlock()
 	if сам.val == 0 { // Первоначальное присвоение

+ 0 - 0
app/lev2/arena_division/div_war/process_divwar/div_war_sound/div_war_sound.go → app/lev2/arena/arena_division/div_war/process_divwar/div_war_sound/div_war_sound.go


+ 0 - 0
app/lev2/arena_division/div_war/process_divwar/div_war_sound/isplay/isplay.go → app/lev2/arena/arena_division/div_war/process_divwar/div_war_sound/isplay/isplay.go


+ 0 - 0
app/lev2/arena_division/div_war/process_divwar/process_divwar.go → app/lev2/arena/arena_division/div_war/process_divwar/process_divwar.go


+ 0 - 0
app/lev2/arena_division/divwar/div_war_on/div_war_on.go → app/lev2/arena/arena_division/divwar/div_war_on/div_war_on.go


+ 2 - 2
app/lev2/arena_division/divwar/divwar.go → app/lev2/arena/arena_division/divwar/divwar.go

@@ -7,7 +7,7 @@ import (
 	"sync"
 	"time"
 
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
 	"wartank/app/lev1/stat_param"
 	"wartank/app/lev2/arena"
@@ -150,7 +150,7 @@ func (сам *DivWar) findTimeCount() {
 	strTime := lstTime[1]
 	lstTime = strings.Split(strTime, `</span>`)
 	strTime = lstTime[0]
-	if err := сам.ОбратВремяУст(alias.Время(strTime)); err != nil {
+	if err := сам.ОбратВремяУст(АВремя(strTime)); err != nil {
 		// log._rintf("WARN DivWar.findTimeCount(): при установке времени ожидания битвы дивизий(%v)\n\terr=%v\n", strTime, err)
 		return
 	}

+ 0 - 0
app/lev2/arena_division/divwar/divwarnet/divwarnet.go → app/lev2/arena/arena_division/divwar/divwarnet/divwarnet.go


+ 0 - 0
app/lev2/arena_division/divwar/divwaron/divwaron.go → app/lev2/arena/arena_division/divwar/divwaron/divwaron.go


+ 0 - 0
app/lev2/arena_duel/arena_duel.go → app/lev2/arena/arena_duel/arena_duel.go


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

@@ -9,7 +9,7 @@ import (
 	"time"
 
 	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
+	"wartank/app/lev1"
 	"wartank/app/lev2/arena"
 )
 
@@ -31,10 +31,10 @@ func НовСкладТоплива(конт ИБотКонтекст, база
 	сам := &АренаСкладТоплива{
 		бот:      база.Бот(),
 		база:     база,
-		топливо:  stat_param.НовСтатПарам("топливо"),
+		топливо:  lev1.НовСтатПарам("топливо"),
 		кнт:      кнт,
 		фнОтмена: фнОтмена,
-		уровень:  stat_param.НовСтатПарам("уровень"), // FIXME: вынести на уровень арены
+		уровень:  lev1.НовСтатПарам("уровень"), // FIXME: вынести на уровень арены
 	}
 	аренаКонфиг := arena.АренаКонфиг{
 		Бот_:         база.Бот(),

+ 0 - 0
app/lev2/arena_laborator/arena_laborator.go → app/lev2/arena/arena_laborator/arena_laborator.go


+ 10 - 12
app/lev2/arena_market/arena_market.go → app/lev2/arena/arena_market/arena_market.go

@@ -7,27 +7,25 @@ import (
 	"strings"
 	"time"
 
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
 	"wartank/app/lev2/arena"
 )
 
 // АренаРынок -- объект рынка
 type АренаРынок struct {
 	ИАрена
+	конт ИБотКонтекст
 	бот     ИБот
-	уровень ИСтатПарам
 }
 
 // НовРынок -- возвращает новый рынок
-func НовРынок(конт ИБотКонтекст, база ИАренаБаза) *АренаРынок {
+func НовРынок(конт ИБотКонтекст) ИАренаРынок {
 	сам := &АренаРынок{
-		бот:     база.Бот(),
-		уровень: stat_param.НовСтатПарам("уровень"), // FIXME: вынести на уровень арены
+		бот:     конт.Получ("бот").(ИБот),
 	}
 	аренаКонфиг := arena.АренаКонфиг{
-		Бот_:         база.Бот(),
+		Бот_:         сам.бот,
 		АренаИмя_:    "Рынок",
 		СтрКонтроль_: `<title>Рынок</title>`,
 		ФнПуск_:      сам.пуск,
@@ -108,7 +106,7 @@ func (сам *АренаРынок) уровеньОбновить() bool {
 		log.Printf("Рынок.уровеньОбновить(): строка уровня сбойная, стр=%q, ош=\n\t%v\n", стр, ош)
 		return false
 	}
-	сам.уровень.Уст(иУровень)
+	сам.Уровень().Уст(иУровень)
 	switch иУровень {
 	case 0: // рынок надо построить
 		for !сам.построить() {
@@ -313,8 +311,8 @@ func (сам *АренаРынок) проверОжидание() {
 			case "10", "50", "100", "500":
 				return true
 			default:
-				серебро := сам.бот.Ангар().СереброВсего()
-				if серебро.Получ() > 1_000_000 {
+				серебро := сам.конт.Получ("серебро").(int)
+				if серебро > 1_000_000 {
 					return true
 				}
 				return false
@@ -337,7 +335,7 @@ func (сам *АренаРынок) проверОжидание() {
 		}
 		lstTime := strings.Split(strOut, `Минимальная цена через `)
 		strTime := lstTime[1]
-		if err := сам.ОбратВремяУст(alias.Время(strTime)); err != nil {
+		if err := сам.ОбратВремяУст(АВремя(strTime)); err != nil {
 			// log._rintf("ERRO Market.checkTime(): при установке времени ожидания рынка(%v)\n\terr=%v\n", strTime, err)
 			return // Возможно минимальная цена
 		}
@@ -368,7 +366,7 @@ func (сам *АренаРынок) купитьЗолото() bool {
 	}
 	lstSilver := strings.Split(strOut, `<img class="ico vm" src="/images/icons/silver.png?2" alt="Серебро" title="Серебро"> `)
 	strSilver = lstSilver[1]
-	серебро := сам.бот.Ангар().СереброВсего().Получ()
+	серебро := сам.конт.Получ("серебро").(int)
 	еслиКупить := false
 	switch strSilver {
 	case "10", "50", "100", "500": // Допустимые суммы трат

+ 3 - 3
app/lev2/arena_masters/arena_masters.go → app/lev2/arena/arena_masters/arena_masters.go

@@ -5,7 +5,7 @@ import (
 	"strings"
 	"time"
 
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
 	"wartank/app/lev2/arena"
 	"wartank/kernel"
@@ -73,7 +73,7 @@ func (сам *БитваМастеров) goBatMas() bool {
 	}
 	countTime := сам.ВремяОстат().String()
 	if countTime > "00:25:00" {
-		if err := сам.ОбратВремяУст(alias.Время(countTime)); err != nil {
+		if err := сам.ОбратВремяУст(АВремя(countTime)); err != nil {
 			сам.лог.Ошибка("goBatMas(): при установке времени ожидания битвы мастеров(%v)\n\terr=%v\n", countTime, err)
 		}
 		return false
@@ -108,7 +108,7 @@ func (сам *БитваМастеров) findTimeCount() {
 		lstTime = strings.Split(strTime, ` (`)
 		strTime = lstTime[0]
 
-		if err := сам.ОбратВремяУст(alias.Время(strTime)); err != nil {
+		if err := сам.ОбратВремяУст(АВремя(strTime)); err != nil {
 			log.Printf("WARN BatMas.findTimeCount(): при установке времени ожидания битвы мастеров(%v)\n\terr=%v\n", strTime, err)
 		}
 	}

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

@@ -8,9 +8,9 @@ import (
 	"strings"
 	"time"
 
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
+	"wartank/app/lev1"
 	"wartank/app/lev2/arena"
 )
 
@@ -38,12 +38,12 @@ func НовШахта(конт ИБотКонтекст, база ИАренаБ
 	сам := &АренаШахта{
 		бот:        база.Бот(),
 		база:       база,
-		руда:       stat_param.НовСтатПарам("руда"),
-		железо:     stat_param.НовСтатПарам("железо"),
-		сталь:      stat_param.НовСтатПарам("сталь"),
-		свинец:     stat_param.НовСтатПарам("свинец"),
-		продуктКол: stat_param.НовСтатПарам("кол-во"),
-		уровень:    stat_param.НовСтатПарам("уровень"),
+		руда:       lev1.НовСтатПарам("руда"),
+		железо:     lev1.НовСтатПарам("железо"),
+		сталь:      lev1.НовСтатПарам("сталь"),
+		свинец:     lev1.НовСтатПарам("свинец"),
+		продуктКол: lev1.НовСтатПарам("кол-во"),
+		уровень:    lev1.НовСтатПарам("уровень"),
 		кнт:        кнт,
 		фнОтмена:   фнОтмена,
 	}
@@ -234,7 +234,7 @@ func (сам *АренаШахта) количествоПолучить() (bool
 	strTime = strings.TrimPrefix(strTime, `<td><div class="value-block lh1"><span><span>`)
 	strTime = strings.TrimSuffix(strTime, `</span></span></div></td>`)
 	сам.продуктВремя = strTime
-	if err := сам.ОбратВремяУст(alias.Время(strTime)); err != nil {
+	if err := сам.ОбратВремяУст(АВремя(strTime)); err != nil {
 		сам.лог.Добавить("ОШИБКА Шахта.количествоПолучить(): при установке времени производства(%v), err=\n\t%v\n", strTime, err)
 	}
 	сам.лог.Добавить("Шахта.количествоПолучить(): время=%q\n", strTime)
@@ -644,7 +644,7 @@ func (сам *АренаШахта) рудаСделать() bool {
 		// log._rintf("ERRO Шахта.сделатьРуду(): при обновлении lstMine, err=\n\t%v\n", err)
 		return false
 	}
-	if err := сам.ОбратВремяУст(alias.Время(strTime)); err != nil {
+	if err := сам.ОбратВремяУст(АВремя(strTime)); err != nil {
 		сам.лог.Добавить("ERRO Шахта.сделатьРуду(): при установке времени ожидания добычи руды(%v)\n\terr=%v\n", strTime, err)
 	}
 	lstNum := strings.Split(strNum, `Кол-во: <span class="green2">`)
@@ -706,7 +706,7 @@ func (сам *АренаШахта) железоСделать() bool {
 		// log._rintf("ERRO MineNet.makeFerrum(): при обновлении lstMine, err=\n\t%v\n", err)
 		return false
 	}
-	if err := сам.ОбратВремяУст(alias.Время(strTime)); err != nil {
+	if err := сам.ОбратВремяУст(АВремя(strTime)); err != nil {
 		сам.лог.Добавить("ERRO Mine.makeFerrum(): при установке времени производства железа(%v)\n\terr=%v\n", strTime, err)
 	}
 	lstNum := strings.Split(strNum, `Кол-во: <span class="green2">`)
@@ -765,7 +765,7 @@ func (сам *АренаШахта) стальСделать() bool {
 		// log._rintf("ERRO MineNet.makeSteel(): при обновлении lstMine, err=\n\t%v\n", err)
 		return false
 	}
-	if err := сам.ОбратВремяУст(alias.Время(strTime)); err != nil {
+	if err := сам.ОбратВремяУст(АВремя(strTime)); err != nil {
 		сам.лог.Добавить("ERRO Mine.makeSteel(): при установке времени производства железа(%v)\n\terr=%v\n", strTime, err)
 	}
 	lstNum := strings.Split(strNum, `Кол-во: <span class="green2">`)
@@ -824,7 +824,7 @@ func (сам *АренаШахта) свинецСделать() bool {
 		// log._rintf("ERRO Шахта.сделатьСвинец(): при обновлении lstMine, err=\n\t%v\n", err)
 		return false
 	}
-	if err := сам.ОбратВремяУст(alias.Время(strTime)); err != nil {
+	if err := сам.ОбратВремяУст(АВремя(strTime)); err != nil {
 		сам.лог.Добавить("ERRO Шахта.сделатьСвинец(): при установке времени производства железа(%v)\n\terr=%v\n", strTime, err)
 	}
 	lstNum := strings.Split(strNum, `Кол-во: <span class="green2">`)

+ 0 - 0
app/lev2/arena_missions/arena_missions.go → app/lev2/arena/arena_missions/arena_missions.go


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

@@ -6,10 +6,10 @@ import (
 	"strings"
 	"time"
 
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 	"wartank/app/lev0/cons"
 	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
+	"wartank/app/lev1"
 	"wartank/app/lev2/arena"
 	"wartank/kernel"
 	. "wartank/kernel/kernel_types"
@@ -35,7 +35,7 @@ type АренаПолигон struct {
 	танкСтат      ИТанкСтат
 	продуктСейчас ИБезопСтрока
 	продуктКол    ИБезопЦелое
-	уровень       *stat_param.СтатПарам
+	уровень       ИСтатПарам
 	лог           ИЯдроЛог
 }
 
@@ -48,7 +48,7 @@ func НовПолигон(конт ИБотКонтекст, база ИАрен
 		танкСтат:      база.Бот().Стата(),
 		продуктСейчас: kernel.НовБезопСтрока(),
 		продуктКол:    kernel.НовБезопЦелое(),
-		уровень:       stat_param.НовСтатПарам("уровень"), // FIXME: вынести на уровень арены
+		уровень:       lev1.НовСтатПарам("уровень"), // FIXME: вынести на уровень арены
 		лог:           лог,
 	}
 	аренаКонфиг := arena.АренаКонфиг{
@@ -354,7 +354,7 @@ func (сам *АренаПолигон) времяОбнов() {
 	strLastTime = lstTime[1]
 	lstTime = strings.Split(strLastTime, `</span>`)
 	strLastTime = lstTime[0]
-	if err := сам.ОбратВремяУст(alias.Время(strLastTime)); err != nil {
+	if err := сам.ОбратВремяУст(АВремя(strLastTime)); err != nil {
 		// log._rintf("ERRO Polygon.updateTime(): при установке времени ожидания полигона(%v)\n\terr=%v\n", strLastTime, err)
 		return
 	}

+ 0 - 0
app/lev2/arena_upgrade/arena_upgrade.go → app/lev2/arena/arena_upgrade/arena_upgrade.go


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

@@ -8,7 +8,7 @@ import (
 	// "log"
 	"sync"
 	"time"
-	"wartank/app/lev0/alias"
+	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
 	"wartank/app/lev1/product/parser_time"
 	"wartank/kernel"
@@ -38,7 +38,7 @@ type ВремОбрат struct {
 }
 
 // НовВремОбрат -- возвращает новый *CountTime
-func НовВремОбрат(сцена ИАренаКонтекст, время alias.МилСек) *ВремОбрат {
+func НовВремОбрат(сцена ИАренаКонтекст, время АМилСек) *ВремОбрат {
 	if сцена == nil {
 		panic("НовВремОбрат(): ИСцена == nil")
 	}
@@ -53,7 +53,7 @@ func НовВремОбрат(сцена ИАренаКонтекст, врем
 		кнт:          кнт,
 		фнОтмена:     фнОтмена,
 	}
-	мСек := alias.МилСек(time.Now().UTC().UnixMilli()) + время
+	мСек := АМилСек(time.Now().UTC().UnixMilli()) + время
 	сам.лимит.Уст(int(мСек))
 	сам.еслиРаботает.Уст()
 	go сам.пуск()
@@ -63,7 +63,7 @@ func НовВремОбрат(сцена ИАренаКонтекст, врем
 }
 
 // ПолучМилСек -- возвращает оставшееся хранимое время остатка
-func (сам *ВремОбрат) ПолучМилСек() alias.МилСек {
+func (сам *ВремОбрат) ПолучМилСек() АМилСек {
 	return сам.остатПарсер.ПолучМилСек()
 }
 
@@ -108,7 +108,7 @@ func (сам *ВремОбрат) Стоп() {
 }
 
 // Уст -- устанавливает число оставшихся сек
-func (сам *ВремОбрат) Уст(время alias.Время) error {
+func (сам *ВремОбрат) Уст(время АВремя) error {
 	сам.блок.Lock()
 	defer сам.блок.Unlock()
 	if ош := сам.остатПарсер.Уст(время); ош != nil {

+ 0 - 304
app/lev2/arena_angar/arena_angar.go

@@ -1,304 +0,0 @@
-package arena_angar
-
-import (
-	"fmt"
-	"log"
-	"strconv"
-	"strings"
-	"time"
-
-	"wartank/app/lev0/alias"
-	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
-	"wartank/app/lev2/arena"
-	"wartank/app/lev2/arena_angar/fuel_attack"
-	"wartank/app/lev2/arena_base"
-	"wartank/app/lev2/arena_convoy"
-	"wartank/app/lev2/arena_duel"
-	"wartank/app/lev2/arena_masters"
-	"wartank/app/lev2/arena_missions"
-	"wartank/app/lev2/arena_upgrade"
-	"wartank/app/lev3/bot/bot_net/bot_net_stat"
-	"wartank/app/lev3/bot/bot_stat/stat_resurs"
-)
-
-/*
-	Объект ангара приложения
-*/
-
-// Ангар -- ангар для танка
-type АренаАнгар struct {
-	ИАрена
-	прилож ИПриложение
-	бот    ИБот
-
-	уровень  ИСтатПарам
-	progress ИСтатПарам
-	// топливо       *fuel.Топливо
-	игроковОнлайн ИСтатПарам
-
-	silverOnline ИСтатПарам
-
-	сетьТанкСтат *bot_net_stat.БотСетьСтат
-	танкПарам    *arena_upgrade.АренаАпгрейд
-	словАрена    map[alias.АренаИмя]ИАрена
-	ресурсы      *stat_resurs.СтатРесурсы
-}
-
-// НовАнгар -- возвращает новый *Angar
-func НовАнгар(конт ИБотКонтекст) (*АренаАнгар, error) {
-	танкПарам := arena_upgrade.НовТанкПараметры(конт)
-	бот := конт.Получ("бот").(ИБот)
-	сам := &АренаАнгар{
-		бот:           бот,
-		уровень:       stat_param.НовСтатПарам("уровень"),
-		progress:      stat_param.НовСтатПарам("прогресс"),
-		игроковОнлайн: stat_param.НовСтатПарам("онлайн"),
-		silverOnline:  stat_param.НовСтатПарам("серебро онлайн"),
-		танкПарам:     танкПарам,
-		словАрена:     make(map[alias.АренаИмя]ИАрена),
-	}
-	аренаКонф := arena.АренаКонфиг{
-		Бот_:         бот,
-		АренаИмя_:    "Ангар",
-		СтрКонтроль_: "<title>Ангар</title>",
-		ФнПуск_:      сам.пуск,
-		СтрУрл_:      "https://wartank.ru/angar",
-	}
-	конт.Уст("ангар", сам)
-	сам.ИАрена = arena.НовАрена(конт, аренаКонф)
-	var err error
-	топливоБой, err := fuel_attack.НовТопливоБой(конт, сам)
-	if err != nil {
-		return nil, fmt.Errorf("НовАнгар(): in create <AngarAttackNet>, err=\n\t%w", err)
-	}
-	сам.словАрена["топливоБой"] = топливоБой
-	// Статистика
-	сам.сетьТанкСтат = bot_net_stat.НовБотСетьСтат(конт)
-
-	конвой := arena_convoy.НовКонвой(конт, сам.бот)
-	сам.словАрена["конвой"] = конвой
-	сражение := arena_duel.НовАренаДуэль(конт, сам.бот)
-	сам.словАрена["сражение"] = сражение
-	битваМастеров := arena_masters.НовБитваМастеров(конт, сам.бот)
-	сам.словАрена["битваМастеров"] = битваМастеров
-	база, err := arena_base.НовБаза(конт, сам)
-	if err != nil {
-		return nil, fmt.Errorf("НовАнгар(): in make IBase, err=\n\t%w", err)
-	}
-	сам.словАрена["база"] = база
-	миссии, err := arena_missions.НовМиссии(конт, сам.бот)
-	if err != nil {
-		return nil, fmt.Errorf("НовАнгар(): in make *Missions, err=\n\t%w", err)
-	}
-	сам.словАрена["миссии"] = миссии
-	сам.ресурсы = stat_resurs.НовСтатРесурсы(конт, сам)
-	_ = ИАнгар(сам)
-	return сам, nil
-}
-
-// Обновить -- обновить ангар принудительно
-func (сам *АренаАнгар) Обновить() {
-	сам.РесурсыОбновить()
-	сам.сетьТанкСтат.Update()
-	сам.словАрена["конвой"].Пуск()
-	сам.ресурсы.Топливо().Обновить()
-}
-
-// Запускает обработку ангара
-func (сам *АренаАнгар) пуск() {
-	{ // Запуск компонентов
-		сам.танкПарам.Пуск()
-		go сам.ресурсы.Топливо().Run()
-	}
-	фнЦикл := func() bool {
-		сам.Обновить()
-		// сам.конвойПроверить()
-		if err := сам.ОбратВремяУст("01:00"); err != nil {
-			сам.Отменить()
-			log.Printf("Ангар.Run(): in update ICountTime, err=\n\t%v\n", err)
-			return false
-		}
-		for _, арена := range сам.словАрена {
-			арена.Пуск()
-		}
-		return true
-	}
-	go func() {
-		ош := сам.ОбратВремяУст("01")
-		if ош != nil {
-			log.Printf("Ангар.Run(): in update ICountTime, ош=\n\t%v\n", ош)
-			сам.прилож.Отменить()
-			return
-		}
-		for {
-			select {
-			case <-сам.прилож.Конт().Done(): // Отмена контекста
-				return
-			case <-сам.ВремяОстат().КаналСиг(): // Метка времени
-				if !фнЦикл() {
-					return
-				}
-			default: // Запускается раз в минуту
-				if !фнЦикл() {
-					return
-				}
-				time.Sleep(time.Minute * 1)
-			}
-		}
-	}()
-}
-
-// Обновляет ресурсы ангара
-func (сам *АренаАнгар) РесурсыОбновить() {
-	сам.ИАрена.Обновить()
-	сам.золотоНайти()
-	сам.сереброНайти()
-}
-
-// IMissions -- возвращает ссылку на объект миссий
-func (сам *АренаАнгар) Миссии() ИМиссии {
-	return сам.словАрена["миссии"].(ИМиссии)
-}
-
-// Сражение -- возвращает объект сражения
-func (сам *АренаАнгар) Сражение() ИСражениеСцена {
-	return сам.словАрена["сражение"].(ИСражениеСцена)
-}
-
-// Конвой -- возвращает объект конвоя
-func (сам *АренаАнгар) Конвой() ИАренаКонвой {
-	return сам.словАрена["конвой"].(ИАренаКонвой)
-}
-
-// Золото -- возвращает объект золота
-func (сам *АренаАнгар) Золото() ИСтатПарам {
-	return сам.ресурсы.Золото()
-}
-
-// Топливо -- возвращает объект топлива
-func (сам *АренаАнгар) Топливо() ИСтатПарам {
-	return сам.ресурсы.Топливо().Fuel()
-}
-
-// Уровень -- возвращает объект уровня игрока
-func (сам *АренаАнгар) Уровень() ИСтатПарам {
-	return сам.уровень
-}
-
-// Прогресс -- возвращает прогресс уровня игрока
-func (сам *АренаАнгар) Прогресс() ИСтатПарам {
-	return сам.progress
-}
-
-// ИгрокиОнлайн -- возвращает количество игроков онлайн
-func (сам *АренаАнгар) ИгрокиОнлайн() ИСтатПарам {
-	return сам.игроковОнлайн
-}
-
-// СереброВсего -- возвращает объект всего серебра в ангаре
-func (сам *АренаАнгар) СереброВсего() ИСтатПарам {
-	return сам.ресурсы.СереброВсего()
-}
-
-// СереброЗаработаноСессия -- возвращает объект серебра за сессию в ангаре
-func (сам *АренаАнгар) СереброЗаработаноСессия() ИСтатПарам {
-	return сам.silverOnline
-}
-
-// СереброОбновить -- на основе фактического серебра -- обновляет выработанное серебро
-func (сам *АренаАнгар) СереброОбновить(silverFact int) {
-	if сам.СереброВсего().Получ() == 0 { // Если запуск
-		сам.СереброВсего().Уст(silverFact)
-		return
-	}
-	if сам.СереброВсего().Получ() > silverFact { // Если потрачено серебро
-		сам.СереброВсего().Уст(silverFact)
-		return
-	}
-	if сам.СереброВсего().Получ() < silverFact { // Если заработано
-		so := сам.silverOnline.Получ()
-		sd := silverFact - сам.СереброВсего().Получ()
-		сам.silverOnline.Уст(so + sd)
-	}
-	сам.СереброВсего().Уст(silverFact)
-}
-
-// База -- возвращает базу
-func (сам *АренаАнгар) База() ИАренаБаза {
-	return сам.словАрена["база"].(ИАренаБаза)
-}
-
-/* Проверяет на исполнение конвоя
-func (сам *Ангар) конвойПроверить() {
-	var (
-		strOut   string
-		еслиНайдено   bool
-		lstAngar = сам.СписПолучить()
-	)
-	for _, strOut = range lstAngar {
-		if strings.Contains(strOut, `>Конвой</span>`) {
-			еслиНайдено = true
-			break
-		}
-	}
-	if !еслиНайдено {
-		return
-	}
-	if !strings.Contains(strOut, `<a class="simple-but border gray mb1" href="convoy"><span><span>Конвой</span></span></a>`) {
-		return
-	}
-	сам.конвой.UpdateLst()
-}
-*/
-
-// Ищет в теле текста ангара серебро
-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]
-	iSilver, err := strconv.Atoi(strSilver)
-	if err != nil {
-		// log._rintf("ERRO AngarNet.findSilver(): silver(%v) not number, err=\n\t%v\n", strSilver, err)
-		return
-	}
-	сам.СереброВсего().Уст(iSilver)
-}
-
-// Ищет в теле текста ангара золото
-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)
-}

+ 0 - 83
app/lev2/arena_angar/fuel/fuel.go

@@ -1,83 +0,0 @@
-// package fuel -- топливо в баке
-package fuel
-
-import (
-	"fmt"
-	"log"
-	"strconv"
-	"strings"
-	"time"
-
-	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
-)
-
-// Топливо -- топливо в баке, +1 каждые 15 сек
-type Топливо struct {
-	ангар   ИАнгар
-	топливо ИСтатПарам
-}
-
-// НовТопливо -- возвращает новый топливный бак
-func НовТопливо(конт ИБотКонтекст, ангар ИАнгар) (*Топливо, error) {
-	if ангар == nil {
-		return nil, fmt.Errorf("NewFuel(): IAngar == nil")
-	}
-	сам := &Топливо{
-		ангар:   ангар,
-		топливо: stat_param.НовСтатПарам("топливо"),
-	}
-	return сам, nil
-}
-
-// Run -- должен работать в отдельном потоке, контролит топливо
-func (сам *Топливо) Run() {
-	// Каждые 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 {
-		log.Printf("ERRO Топливо.Обновить(): %q, при поиске строки топлива, стр=\n\t%v\n", сам.ангар.Бот().Имя(), strOut)
-		return
-	}
-	if lstFuel[1] == "" {
-		log.Printf("ERRO Топливо.Обновить(): %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 сам.топливо
-}

+ 0 - 873
app/lev2/arena_base/arena_base.go

@@ -1,873 +0,0 @@
-// package arena_base -- база в игре
-package arena_base
-
-import (
-	"fmt"
-	"log"
-	"strconv"
-	"strings"
-	"sync"
-	"time"
-
-	"wartank/app/lev0/alias"
-	"wartank/app/lev0/cons"
-	. "wartank/app/lev0/types"
-	"wartank/app/lev2/arena"
-	"wartank/app/lev2/arena_arsenal"
-	"wartank/app/lev2/arena_bank"
-	"wartank/app/lev2/arena_fuel_storage"
-	"wartank/app/lev2/arena_laborator"
-	"wartank/app/lev2/arena_market"
-	"wartank/app/lev2/arena_mine"
-	"wartank/app/lev2/arena_polygon"
-)
-
-/*
-	Объект базы в игре.
-*/
-
-const (
-	времОжидПлат    = "01:00" // Время ожидания платного ускорения
-	времОжидБесплат = "30:00" // Время ожидания бесплатного ускорения
-)
-
-// База -- объект базы
-type АренаБаза struct {
-	ИАрена
-	бот          ИБот
-	арсенал      ИАренаАрсенал
-	банк         *arena_bank.АренаБанк
-	полигон      *arena_polygon.АренаПолигон
-	шахта        ИАренаШахта
-	рынок        *arena_market.АренаРынок
-	складТоплива *arena_fuel_storage.АренаСкладТоплива
-	лаборатория  *arena_laborator.АренаЛаборатория
-	времОстат    int // Сколько времени спать до опроса базы
-	блок         sync.Mutex
-}
-
-// НовБаза -- возвращает новую базу бота
-func НовБаза(конт ИБотКонтекст, ангар ИАнгар) (*АренаБаза, error) {
-	log.Printf("НовБаза(): %q\n", ангар.Бот().Имя())
-	сам := &АренаБаза{
-		бот: ангар.Бот(),
-	}
-	аренаКонфиг := arena.АренаКонфиг{
-		Бот_:         ангар.Бот(),
-		АренаИмя_:    "База",
-		СтрКонтроль_: `<title>База</title>`,
-		ФнПуск_:      сам.пуск,
-		СтрУрл_:      "https://wartank.ru/buildings",
-	}
-	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
-	var ош error
-	{ // Arsenal
-		сам.арсенал, ош = arena_arsenal.НовАрсенал(конт, сам)
-		if ош != nil {
-			return nil, fmt.Errorf("NewBase(): in create IArsenal, err=\n\t%w", ош)
-		}
-	}
-	{ // Bank
-		сам.банк, ош = arena_bank.НовБанк(конт, сам)
-		if ош != nil {
-			return nil, fmt.Errorf("NewBase(): in create IBank, err=\n\t%w", ош)
-		}
-	}
-	{ // Mine
-		сам.шахта, ош = arena_mine.НовШахта(конт, сам)
-		if ош != nil {
-			return nil, fmt.Errorf("NewBase(): in create IMine, err=\n\t%w", ош)
-		}
-	}
-	сам.рынок = arena_market.НовРынок(конт, сам)
-	// Polygon
-	сам.полигон = arena_polygon.НовПолигон(конт, сам)
-	{ // Лаборатория
-		сам.лаборатория, ош = arena_laborator.НоваяЛаборатория(ангар.Бот())
-		if ош != nil {
-			return nil, fmt.Errorf("НовБаза(): при создании лаборатории, err=\n\t%w", ош)
-		}
-	}
-	{ // Склад топлива
-		сам.складТоплива, ош = arena_fuel_storage.НовСкладТоплива(конт, сам)
-		if ош != nil {
-			return nil, fmt.Errorf("НовБаза(): при создании склада топлива, err=\n\t%w", ош)
-		}
-	}
-	return сам, nil
-}
-
-// Запускает базу в обработку
-func (сам *АренаБаза) Пуск() {
-	log.Printf("Base.Run()\n")
-	if err := сам.runComponent(); err != nil {
-		panic(fmt.Errorf("Base.Run(): run, err=\n\t%w", err))
-	}
-	go сам.пуск()
-}
-
-// Собственная работа
-func (сам *АренаБаза) пуск() {
-	фнЦикл := func() {
-		defer time.Sleep(time.Minute * 2)
-		сам.Обновить()
-		сам.проверитьПолигонУсиление()              // Проверить усиление полигона
-		if err := сам.проверитьБанк(); err != nil { // Проверка режимов банка
-			log.Printf("ERRO Base.Run(): при проверке банка, err=\n\t%v\n", err)
-		}
-		сам.проверитьАрсенал() // Проверка арсенала
-		сам.проверитьШахту()   // Проверка шахты
-		сам.setCountDown()     // Установка счётчика времени
-
-	}
-	for {
-		select {
-		case <-сам.Контекст().Done():
-			return
-		// case <-сам.ВремяОпрос().КаналСиг():
-		// 	фнЦикл()
-		default:
-			log.Printf("База.пуск()\n")
-			фнЦикл()
-		}
-	}
-}
-
-// Запускает компоненты
-func (сам *АренаБаза) runComponent() error {
-	log.Printf("Base.runComponent()\n")
-	сам.блок.Lock()
-	defer сам.блок.Unlock()
-	if err := сам.банк.Пуск(); err != nil {
-		return fmt.Errorf("Base.runComponent(): in run IBank, err=\n\t%w", err)
-	}
-	сам.рынок.Пуск()
-	сам.полигон.Пуск()
-	сам.складТоплива.Пуск()
-	сам.лаборатория.Пуск()
-	return nil
-}
-
-// Выбирает время обновления базы по компонентам
-func (сам *АренаБаза) setCountDown() {
-	timeBase := сам.банк.ВремяОстат().String()
-	timeCount := timeBase
-	timeArsenal := сам.арсенал.ВремяОстат().String()
-	timeMine := сам.шахта.ВремяОстат().String()
-	if timeArsenal < timeCount {
-		timeCount = timeArsenal
-	}
-	if timeMine < timeCount {
-		timeCount = timeMine
-	}
-	if timeCount <= "05" {
-		сам.времОстат = 5
-		return
-	}
-	if timeCount > "00:10:00" {
-		сам.времОстат = 600
-	}
-	ош := сам.ОбратВремяУст(alias.Время(timeCount))
-	if ош != nil {
-		log.Printf("ERRO Base.setCountDown(): при установке обратного отсчёта времени, err=\n\t%v\n", ош)
-		сам.Отменить()
-	}
-}
-
-// Арсенал -- возвращает объект арсенала
-func (сам *АренаБаза) Арсенал() ИАренаАрсенал {
-	return сам.арсенал
-}
-
-// Банк -- возвращает объект банка
-func (сам *АренаБаза) Банк() ИБанк {
-	сам.блок.Lock()
-	defer сам.блок.Unlock()
-	return сам.банк
-}
-
-// Полигон -- возвращает объект полигона
-func (сам *АренаБаза) Полигон() ИАренаПолигон {
-	return сам.полигон
-}
-
-// Шахта -- возвращает объект шахты
-func (сам *АренаБаза) Шахта() ИАренаШахта {
-	return сам.шахта
-}
-
-// Рынок -- возвращает объект рынка
-func (сам *АренаБаза) Рынок() ИРынок {
-	return сам.рынок
-}
-
-// Проверяет на забрать шахту
-func (сам *АренаБаза) проверитьШахту() {
-	if сам.шахта.Руда().Получ() == 0 {
-		сам.шахтаСтатаОбновить()
-	}
-	сам.шахтаАпгрейдФорсаж() // Нужно ли ускорить апгрейд шахты
-	if сам.шахта.АренаСостояние().Состояние() == "upgrade" {
-		return
-	}
-	сам.шахтаСтатаОбновить()
-	сам.checkMineTime()
-}
-
-// Проверяет время ожидания шахты
-func (сам *АренаБаза) checkMineTime() {
-	var (
-		lstBase     = сам.СписПолучить()
-		strOut      string
-		еслиНайдено bool
-		ind         int
-	)
-	for ind, strOut = range lstBase {
-		if !strings.Contains(strOut, `<span class="green2">Шахта - `) {
-			continue
-		}
-		ind += 11
-		strOut = lstBase[ind]
-		еслиНайдено = true
-		break
-	}
-	if !еслиНайдено {
-		return
-	}
-	if !strings.Contains(strOut, `<td><div class="value-block lh1"><span><span>`) {
-		return
-	}
-	/*
-		lstTime := strings.Split(strOut, `<td><div class="value-block lh1"><span><span>`)
-		strTime := lstTime[1]
-		lstTime = strings.Split(strTime, `</span></span></div></td>`)
-		strTime = lstTime[0]
-		if err := сам.шахта.Уст(alias.Время(strTime)); err != nil {
-			log.Printf("ERRO Base.checkMineTime(): при установке обратного отсчёта(%v), err=\n\t%v\n", strTime, err)
-		}
-	*/
-}
-
-// Проверка статистики шахты
-func (сам *АренаБаза) шахтаСтатаОбновить() {
-	var (
-		lstMine     = сам.СписПолучить()
-		strOut      string
-		еслиНайдено bool
-		ind         int
-	)
-	{ // Ищем руду
-		for _, strOut = range lstMine {
-			if strings.Contains(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/ore.png?2" alt="Руда" title="Руда"/>`) {
-				еслиНайдено = true
-				break
-			}
-		}
-		if еслиНайдено && strings.Contains(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/ore.png?2" alt="Руда" title="Руда"/> `) {
-			списРуда := strings.Split(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/ore.png?2" alt="Руда" title="Руда"/> `)
-			стрРуда := списРуда[1]
-			списРуда = strings.Split(стрРуда, ` &nbsp;&nbsp;</span>`)
-			стрРуда = списРуда[0]
-			целРуда, err := strconv.Atoi(стрРуда)
-			if err != nil {
-				log.Printf("ERRO Base.checkMineStat(): руда(%v) не число, err=\n\t%v\n", стрРуда, err)
-				return
-			}
-			сам.шахта.Руда().Уст(целРуда)
-		}
-	}
-	{ // Ищем железо
-		for _, strOut = range lstMine {
-			if strings.Contains(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/iron.png?2" alt="Железо" title="Железо"/> `) {
-				еслиНайдено = true
-				break
-			}
-		}
-		if еслиНайдено && strings.Contains(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/iron.png?2" alt="Железо" title="Железо"/> `) {
-			lstFerrum := strings.Split(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/iron.png?2" alt="Железо" title="Железо"/> `)
-			strFerrum := lstFerrum[1]
-			lstFerrum = strings.Split(strFerrum, ` &nbsp;&nbsp;</span>`)
-			strFerrum = lstFerrum[0]
-			iFerrum, err := strconv.Atoi(strFerrum)
-			if err != nil {
-				log.Printf("ERRO Base.checkMineStat(): железо(%v) не число, err=\n\t%v\n", strFerrum, err)
-				return
-			}
-			сам.шахта.Железо().Уст(iFerrum)
-		}
-	}
-	{ // Ищем сталь
-		for _, strOut = range lstMine {
-			if strings.Contains(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/steel.png?2" alt="Сталь" title="Сталь"/> `) {
-				еслиНайдено = true
-				break
-			}
-		}
-		if еслиНайдено && strings.Contains(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/steel.png?2" alt="Сталь" title="Сталь"/> `) {
-			lstSteel := strings.Split(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/steel.png?2" alt="Сталь" title="Сталь"/> `)
-			strSteel := lstSteel[1]
-			lstSteel = strings.Split(strSteel, ` &nbsp;&nbsp;</span>`)
-			strSteel = lstSteel[0]
-			iSteel, err := strconv.Atoi(strSteel)
-			if err != nil {
-				log.Printf("ERRO Base.checkMineStat(): сталь(%v) не число, err=\n\t%v\n", strSteel, err)
-				return
-			}
-			сам.шахта.Сталь().Уст(iSteel)
-		}
-	}
-	{ // Ищем свинец
-		for _, strOut = range lstMine {
-			if strings.Contains(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/plumbum.png?2" alt="Свинец" title="Свинец"/> `) {
-				еслиНайдено = true
-				break
-			}
-		}
-		if еслиНайдено && strings.Contains(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/plumbum.png?2" alt="Свинец" title="Свинец"/> `) {
-			lstPlumbum := strings.Split(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/plumbum.png?2" alt="Свинец" title="Свинец"/> `)
-			strPlumbum := lstPlumbum[1]
-			lstPlumbum = strings.Split(strPlumbum, ` &nbsp;&nbsp;</span>`)
-			strPlumbum = lstPlumbum[0]
-			iPlumbum, err := strconv.Atoi(strPlumbum)
-			if err != nil {
-				log.Printf("ERRO Base.checkMineStat(): свинец(%v) не число, err=\n\t%v\n", strPlumbum, err)
-				return
-			}
-			сам.шахта.Свинец().Уст(iPlumbum)
-		}
-	}
-	{ // Ищем время обработки и режим
-		lstBase := сам.СписПолучить()
-		/*
-			for ind, strOut = range lstBase {
-				if strings.Contains(strOut, `<span class="green2">Шахта - `) {
-					еслиНайдено = true
-					ind += 11
-					strOut = lstBase[ind]
-					break
-				}
-			}
-			/*
-				/*
-			if еслиНайдено && strings.Contains(strOut, `<td><div class="value-block lh1"><span><span>`) {
-				lstTime := strings.Split(strOut, `<td><div class="value-block lh1"><span><span>`)
-				strTime := lstTime[1]
-				lstTime = strings.Split(strTime, `</span></span></div></td>`)
-				strTime = lstTime[0]
-				if err := сам.шахта.Уст(alias.Время(strTime)); err != nil {
-					log.Printf("ERRO Base.checkMineStat(): при установке времени ожидания шахты(%v)\n\terr=%v\n", strTime, err)
-				}
-			}
-		*/
-
-		ind -= 3
-		if ind < 0 {
-			log.Printf("Base.checkMineStat(): отрицательный индекс(%v)!\n", ind)
-			return
-		}
-		strOut = lstBase[ind]
-		switch {
-		case strings.Contains(strOut, `/images/icons/iron.png`): // Железо
-			lstNum := strings.Split(strOut, `<td class="vam"><div class="nwr pr5 gray1"><img class="rico vm" src="/images/icons/iron.png?2" alt="iron"/>&nbsp;`)
-			strNum := lstNum[1]
-			lstNum = strings.Split(strNum, `</div></td>`)
-			strNum = lstNum[0]
-			работа := alias.АренаРаботаИмя("Железо-" + strNum)
-			сам.шахта.АренаСостояние().РаботаИмяУст(работа)
-		case strings.Contains(strOut, `/images/icons/ore.png`): // Руда
-			lstNum := strings.Split(strOut, `<td class="vam"><div class="nwr pr5 gray1"><img class="rico vm" src="/images/icons/ore.png?2" alt="ore"/>&nbsp;`)
-			strNum := lstNum[1]
-			lstNum = strings.Split(strNum, `</div></td>`)
-			strNum = lstNum[0]
-			работа := alias.АренаРаботаИмя("Руда-" + strNum)
-			сам.шахта.АренаСостояние().РаботаИмяУст(работа)
-		case strings.Contains(strOut, `/images/icons/steel.png`): // Руда
-			lstNum := strings.Split(strOut, `<td class="vam"><div class="nwr pr5 gray1"><img class="rico vm" src="/images/icons/steel.png?2" alt="steel"/>&nbsp;`)
-			strNum := lstNum[1]
-			lstNum = strings.Split(strNum, `</div></td>`)
-			strNum = lstNum[0]
-			работа := alias.АренаРаботаИмя("Сталь-" + strNum)
-			сам.шахта.АренаСостояние().РаботаИмяУст(работа)
-		}
-	}
-}
-
-// Проверяет режимы арсенала
-func (сам *АренаБаза) проверитьАрсенал() {
-	// countTime := сам.арсенал.ВремяОпрос().Получ()
-	// if countTime > 3 {
-	// 	return
-	// }
-	/*
-		if err := сам.арсенал.СтатаОбновить(); err != nil {
-			// log._rintf("ERRO Base.checkArsenal(): при обновлении арсенала, err=\n\t%v\n", err)
-			return
-		}
-	*/
-	if работа := сам.арсенал.АренаСостояние().РаботаИмя(); работа == "" {
-		сам.проверитьАрсеналРежим()
-	}
-	сам.проверитьАрсеналУскорение() // Нужно ли ускорить апгрейд арсенала
-	if сам.арсенал.АренаСостояние().Состояние() == cons.РежимАпгрейд {
-		return
-	}
-	сам.проверитьАрсеналВремя()
-	сам.проверитьАрсеналРежим()
-}
-
-// Проверяет время готовности арсенала
-func (сам *АренаБаза) проверитьАрсеналВремя() {
-	var (
-		lstBase     = сам.СписПолучить()
-		ind         int
-		strOut      string
-		еслиНайдено bool
-	)
-	for ind, strOut = range lstBase {
-		if !strings.Contains(strOut, `Производит снаряды, ремкомплекты<br/>`) {
-			continue
-		}
-		ind += 10
-		strOut = lstBase[ind]
-		еслиНайдено = true
-		break
-	}
-	if !еслиНайдено {
-		return
-	}
-	if !strings.Contains(strOut, ":") {
-		return
-	}
-	lstTime := strings.Split(strOut, `<td><div class="value-block lh1"><span><span>`)
-	if len(lstTime) != 2 { // Возможно, производство
-		return
-	}
-	/*
-		strTime := lstTime[1]
-		lstTime = strings.Split(strTime, `</span></span></div></td>`)
-		strTime = lstTime[0]
-		if err := сам.арсенал.Уст(alias.Время(strTime)); err != nil {
-			log.Printf("ERRO Base.checkArsenalTime(): при установке времени ожидания арсенала(%v)\n\terr=%v\n", strTime, err)
-		}
-	*/
-}
-
-// Проверяет режим производства арсенала
-func (сам *АренаБаза) проверитьАрсеналРежим() {
-	var (
-		strOut  string
-		lstBase = сам.СписПолучить()
-	)
-	for _, strOut = range lstBase {
-		if strings.Contains(strOut, `HollowCharge.png`) {
-			сам.арсенал.АренаСостояние().СостояниеУст("кумулятивы")
-			return
-		}
-		if strings.Contains(strOut, `ArmorPiercing.png`) {
-			сам.арсенал.АренаСостояние().СостояниеУст("бронебойки")
-			return
-		}
-		if strings.Contains(strOut, `HighExplosive.png`) {
-			сам.арсенал.АренаСостояние().СостояниеУст("фугасы")
-			return
-		}
-		if strings.Contains(strOut, `repairkit.gif`) {
-			сам.арсенал.АренаСостояние().СостояниеУст("ремки")
-			return
-		}
-	}
-}
-
-// Проверяет на ускорение апгрейда арсенала
-func (сам *АренаБаза) проверитьАрсеналУскорение() {
-	var (
-		ind         int
-		strOut      = ""
-		еслиНайдено bool
-		lstBase     = сам.СписПолучить()
-	)
-	{ // Проверка на платное ускорение апгрейда + время
-		for ind, strOut = range lstBase {
-			if strings.Contains(strOut, `Производит снаряды, ремкомплекты<br/>`) {
-				// Убедиться что есть строка платного ускорения
-				еслиНайдено = true
-				ind += 29
-				strOut = lstBase[ind]
-				break
-			}
-		}
-		if !еслиНайдено {
-			return
-		}
-		{ // Платное ускорение
-			if strings.Contains(strOut, `Ускорить за`) {
-				/*
-					if err := сам.арсенал.ОбратВремяУст(времОжидПлат); err != nil {
-						log.Printf("WARN Base.checkArsenalForce(): при установке платного времени ускорения апгрейда арсенала(%v)\n\terr=%v\n", времОжидПлат, err)
-					}
-				*/
-				сам.арсенал.АренаСостояние().СостояниеУст("апгрейд")
-				сам.арсенал.АренаСостояние().СостояниеУст(cons.РежимАпгрейд)
-				return
-			}
-		}
-	}
-	{ // Проверка на бесплатное ускорение апгрейда
-		еслиНайдено = false
-		for ind, strOut = range lstBase {
-			if strings.Contains(strOut, `Производит снаряды, ремкомплекты<br/>`) {
-				// Убедиться что есть строка платного ускорения
-				еслиНайдено = true
-				ind += 26
-				strOut = lstBase[ind]
-				break
-			}
-		}
-		if !еслиНайдено {
-			return
-		}
-		if !strings.Contains(strOut, `>Ускорение<`) {
-			return
-		}
-		сам.арсенал.АренаСостояние().СостояниеУст(cons.РежимАпгрейд)
-		lstLink := strings.Split(strOut, `<td style="width:50%;padding-left:1px;"><a class="simple-but border" href="`)
-		strLink := lstLink[1]
-		lstLink = strings.Split(strLink, `"><span><span>Ускорение</span></span></a>`)
-		strLink = "https://wartank.ru/" + lstLink[0]
-		lstBase, err := сам.Сеть().Get(strLink)
-		if err != nil {
-			// log._rintf("ERRO NetBank.checkArsenalForce(): при GET-запросе на бесплатном ускорении апгрейда арсенала, err=\n\t%v\n", err)
-			return
-		}
-		// sound.ArsenalForce()
-		if err := сам.СтрОбновить(lstBase); err != nil {
-			// log._rintf("ERRO NetBank.checkArsenalForce(): при обновлении lstBase, err=\n\t%v\n", err)
-			return
-		}
-		сам.арсенал.АренаСостояние().СостояниеУст("апгрейд")
-		сам.арсенал.АренаСостояние().СостояниеУст(cons.РежимАпгрейд)
-		/*
-			if err := сам.арсенал.ОбратВремяУст(времОжидБесплат); err != nil {
-				log.Printf("WARN Base.checkArsenalForce(): при установке бесплатного времени ускорения апгрейда арсенала(%v)\n\terr=%v\n", времОжидБесплат, err)
-			}
-		*/
-	}
-	// Все проверки прошли -- это просто работа
-	сам.арсенал.АренаСостояние().СостояниеУст(cons.РежимРабота)
-}
-
-// Проверяет режим банка
-func (сам *АренаБаза) проверитьБанк() error {
-	if сам.банк.АренаСостояние().РаботаИмя() == "" {
-		сам.checkBankMode()
-	}
-	сам.checkBankTime() // Проверка времени ожидания
-	countTime := сам.банк.ВремяОстат().ПолучМилСек()
-	if countTime > 5_000 {
-		return nil
-	}
-	сам.checkBankForce() // Нужно ли ускорить апгрейд банка
-	if сам.банк.АренаСостояние().Состояние() == cons.РежимАпгрейд {
-		return nil
-	}
-	сам.checkBankProduct() // Запуск производства в  банке
-	return nil
-}
-
-// Проверяет режим работы банка
-func (сам *АренаБаза) checkBankMode() {
-	var (
-		strOut      string
-		еслиНайдено bool
-		lstBase     = сам.СписПолучить()
-	)
-	for _, strOut = range lstBase {
-		if strings.Contains(strOut, `<td class="vam"><div class="nwr pr5 gray1"><img class="rico vm" src="/images/icons/silver.png?2" alt="silver"/>&nbsp;`) {
-			еслиНайдено = true
-			break
-		}
-	}
-	if !еслиНайдено {
-		return
-	}
-	lstSilver := strings.Split(strOut, `<td class="vam"><div class="nwr pr5 gray1"><img class="rico vm" src="/images/icons/silver.png?2" alt="silver"/>&nbsp;`)
-	strSilver := lstSilver[1]
-	lstSilver = strings.Split(strSilver, `</div></td>`)
-	работа := alias.АренаРаботаИмя("Серебро-" + lstSilver[0])
-	сам.банк.АренаСостояние().РаботаИмяУст(работа)
-	сам.банк.АренаСостояние().СостояниеУст(cons.РежимРабота)
-
-}
-
-// Проверяет на время ожидания банка
-func (сам *АренаБаза) checkBankTime() {
-	var (
-		strOut      string
-		ind         int
-		еслиНайдено bool
-		lstBase     = сам.СписПолучить()
-	)
-	for ind, strOut = range lstBase {
-		if strings.Contains(strOut, `Производит серебро<br/>`) {
-			еслиНайдено = true
-			ind += 10
-			strOut = lstBase[ind]
-			break
-		}
-	}
-	if !еслиНайдено {
-		return
-	}
-	if !strings.Contains(strOut, `<td><div class="value-block lh1"><span><span>`) {
-		return
-	}
-	lstTime := strings.Split(strOut, `<td><div class="value-block lh1"><span><span>`)
-	strTime := lstTime[1]
-	lstTime = strings.Split(strTime, `</span></span></div></td>`)
-	strTime = lstTime[0]
-	if err := сам.банк.ОбратВремяУст(alias.Время(strTime)); err != nil {
-		log.Printf("ERRO Base.checkBankTime(): при установке времени ожидания банка(%v)\n\terr=%v\n", strTime, err)
-	}
-}
-
-// Проверяет на произвести в банке
-func (сам *АренаБаза) checkBankProduct() {
-	var (
-		strOut      string
-		ind         int
-		еслиНайдено bool
-		lstBase     = сам.СписПолучить()
-	)
-	for ind, strOut = range lstBase {
-		if strings.Contains(strOut, `Производит серебро<br/>`) {
-			еслиНайдено = true
-			ind += 11
-			strOut = lstBase[ind]
-			break
-		}
-	}
-	if !еслиНайдено {
-		return
-	}
-	if !strings.Contains(strOut, `>Производство</span>`) {
-		return
-	}
-	сам.банк.UpdateLst()
-	ош := сам.банк.ОбратВремяУст("01:00")
-	if ош != nil {
-		log.Printf("ERRO Base.checkBankProduct(): при установке обратного времени ожидания банка, err=\n\t%v\n", ош)
-		сам.Отменить()
-	}
-}
-
-// Проверка получения серебра из банка
-
-// Проверяет на ускорение апгрейда банка
-func (сам *АренаБаза) checkBankForce() {
-	var (
-		ind     int
-		strOut  = ""
-		isOut   bool
-		lstBase = сам.СписПолучить()
-	)
-	{ // Проверка на платное ускорение апгрейда
-		for ind, strOut = range lstBase {
-			if strings.Contains(strOut, `Производит серебро<br/>`) {
-				// Убедиться что есть строка платного ускорения
-				isOut = true
-				ind += 29
-				strOut = lstBase[ind]
-				break
-			}
-		}
-		if isOut && strings.Contains(strOut, `Ускорить за`) {
-			if err := сам.банк.ОбратВремяУст(времОжидПлат); err != nil {
-				log.Printf("WARN Base.checkBankForce(): при установке времени ожидания платного ускорения апгрейда банка(%v)\n\terr=%v\n", времОжидПлат, err)
-			}
-			сам.банк.АренаСостояние().РаботаИмяУст("")
-			сам.банк.АренаСостояние().СостояниеУст(cons.РежимАпгрейд)
-			return
-		}
-	}
-	{ // Проверка на бесплатное ускорение апгрейда
-		isOut = false
-		for ind, strOut = range lstBase {
-			if strings.Contains(strOut, `Производит серебро<br/>`) {
-				// Убедиться что есть строка платного ускорения
-				isOut = true
-				ind += 26
-				strOut = lstBase[ind]
-				break
-			}
-		}
-		if isOut && strings.Contains(strOut, `>Ускорение<`) {
-
-			lstLink := strings.Split(strOut, `<td style="width:50%;padding-left:1px;"><a class="simple-but border" href="`)
-			strLink := lstLink[1]
-			lstLink = strings.Split(strLink, `"><span><span>Ускорение</span></span></a>`)
-			strLink = "https://wartank.ru/" + lstLink[0]
-			lstBase, err := сам.Сеть().Get(strLink)
-			if err != nil {
-				// log._rintf("ERRO NetBank.checkBankForce(): при GET-запросе на бесплатном ускорении апгрейда банка, err=\n\t%v\n", err)
-				return
-			}
-			if err := сам.СтрОбновить(lstBase); err != nil {
-				// log._rintf("ERRO NetBank.checkBankForce(): при обновлении lstBase, err=\n\t%v\n", err)
-				return
-			}
-			сам.банк.АренаСостояние().РаботаИмяУст("")
-			сам.банк.АренаСостояние().СостояниеУст(cons.РежимАпгрейд)
-			if err := сам.банк.ОбратВремяУст(времОжидБесплат); err != nil {
-				log.Printf("WARN Base.checkBankForce(): при установке времени бесплатного ускорения апгрейда банка(%v)\n\terr=%v\n", времОжидБесплат, err)
-			}
-		}
-	}
-}
-
-// Проверяет на ускорение апгрейда шахты
-func (сам *АренаБаза) шахтаАпгрейдФорсаж() {
-	var (
-		ind     int
-		strOut  = ""
-		isOut   bool
-		lstBase = сам.СписПолучить()
-	)
-	{ // Проверка на платное ускорение апгрейда
-		for ind, strOut = range lstBase {
-			if strings.Contains(strOut, `Производит ресурсы<br/>`) {
-				// Убедиться что есть строка платного ускорения
-				isOut = true
-				ind += 29
-				strOut = lstBase[ind]
-				break
-			}
-		}
-		if isOut && strings.Contains(strOut, `Ускорить за`) {
-			сам.шахта.АренаСостояние().РаботаИмяУст("")
-			сам.шахта.АренаСостояние().СостояниеУст(cons.РежимАпгрейд)
-			/*
-				if err := сам.шахта.ОбратВремяУст(времОжидПлат); err != nil {
-					log.Printf("WARN Base.checkMineForce(): при установке времени платного апгрейда шахты(%v)\n\terr=%v\n", времОжидПлат, err)
-				}
-			*/
-			return
-		}
-	}
-	{ // Проверка на время бесплатного ускорение апгрейда
-		isOut = false
-		for ind, strOut = range lstBase {
-			if strings.Contains(strOut, `Производит ресурсы<br/>`) {
-				// Убедиться что есть строка платного ускорения
-				isOut = true
-				ind += 26
-				strOut = lstBase[ind]
-				break
-			}
-		}
-		if isOut && strings.Contains(strOut, `>Ускорение<`) {
-			lstLink := strings.Split(strOut, `<td style="width:50%;padding-left:1px;"><a class="simple-but border" href="`)
-			strLink := lstLink[1]
-			lstLink = strings.Split(strLink, `"><span><span>Ускорение</span></span></a>`)
-			strLink = "https://wartank.ru/" + lstLink[0]
-			lstBase, err := сам.Сеть().Get(strLink)
-			if err != nil {
-				// log._rintf("ERRO NetBank.checkMineForce(): при GET-запросе на бесплатном ускорении апгрейда шахты, err=\n\t%v\n", err)
-				return
-			}
-			if err := сам.СтрОбновить(lstBase); err != nil {
-				// log._rintf("ERRO NetBank.checkMineForce(): при обновлении lstBase, err=\n\t%v\n", err)
-				return
-			}
-			/*
-				if err := сам.шахта.ОбратВремяУст(времОжидБесплат); err != nil {
-					log.Printf("WARN Base.checkMineForce(): при установке времени апгрейда шахты(%v)\n\terr=%v\n", времОжидБесплат, err)
-				}
-			*/
-			// sound.MineForce()
-			сам.шахта.АренаСостояние().РаботаИмяУст("")
-			сам.шахта.АренаСостояние().СостояниеУст(cons.РежимАпгрейд)
-			return
-		}
-	}
-	// Все проверки прошли -- это просто работа
-	сам.шахта.АренаСостояние().СостояниеУст(cons.РежимРабота)
-}
-
-// Проверяет на ускорение апгрейда полигона
-func (сам *АренаБаза) проверитьПолигонУсиление() {
-	var (
-		ind     int
-		strOut  = ""
-		isOut   bool
-		lstBase = сам.СписПолучить()
-	)
-	countTime := сам.полигон.ВремяОстат().ПолучМилСек()
-	if countTime > 3_000 {
-		return
-	}
-	{ // Проверка на платное ускорение апгрейда
-		for ind, strOut = range lstBase {
-			if strings.Contains(strOut, `Производит усиление танка<br/>`) {
-				// Убедиться что есть строка платного ускорения
-				isOut = true
-				ind += 29
-				strOut = lstBase[ind]
-				break
-			}
-		}
-		if isOut && strings.Contains(strOut, `Ускорить за`) {
-			// strTime := lstBase[ind-21]
-			// lstTime := strings.Split(strTime, `<td><div class="value-block lh1"><span><span>`)
-			// strTime = lstTime[1]
-			// lstTime = strings.Split(strTime, `</span></span></div></td>`)
-			// strTime = lstTime[0]
-			// if err := сам.polygon.CountDown().Set(strTime); err != nil {
-			// 	// log._rintf("WARN Base.checkMineForce(): при установке времени апгрейда полигона(%v)\n\terr=%v\n", strTime, err)
-			// }
-			сам.полигон.АренаСостояние().РаботаИмяУст("")
-			сам.полигон.АренаСостояние().СостояниеУст(cons.РежимАпгрейд)
-			if err := сам.полигон.ОбратВремяУст(времОжидПлат); err != nil {
-				log.Printf("WARN Base.checkPolygonForce(): при установке платного времени апгрейда полигона(%v)\n\terr=%v\n", времОжидПлат, err)
-			}
-			return
-		}
-	}
-	{ // Проверка на бесплатное ускорение апгрейда
-		isOut = false
-		for ind, strOut = range lstBase {
-			if strings.Contains(strOut, `Производит усиление танка<br/>`) {
-				// Убедиться что есть строка платного ускорения
-				isOut = true
-				ind += 26
-				strOut = lstBase[ind]
-				break
-			}
-		}
-		if isOut && strings.Contains(strOut, `>Ускорение<`) {
-			lstLink := strings.Split(strOut, `<td style="width:50%;padding-left:1px;"><a class="simple-but border" href="`)
-			strLink := lstLink[1]
-			lstLink = strings.Split(strLink, `"><span><span>Ускорение</span></span></a>`)
-			strLink = "https://wartank.ru/" + lstLink[0]
-			lstBase, err := сам.Сеть().Get(strLink)
-			if err != nil {
-				// log._rintf("ERRO NetBank.checkPolygonForce(): при GET-запросе на бесплатном ускорении апгрейда полигона, err=\n\t%v\n", err)
-				return
-			}
-			if err := сам.СтрОбновить(lstBase); err != nil {
-				// log._rintf("ERRO NetBank.checkPolygonForce(): при обновлении lstBase, err=\n\t%v\n", err)
-				return
-			}
-			// sound.MineForce()
-			сам.полигон.АренаСостояние().РаботаИмяУст("")
-			сам.полигон.АренаСостояние().СостояниеУст(cons.РежимАпгрейд)
-			// Установить время ожидания для обновления
-			if err := сам.полигон.ОбратВремяУст(времОжидБесплат); err != nil {
-				log.Printf("WARN Base.checkPolygonForce(): при установке времени бесплатного апгрейда полигона(%v)\n\terr=%v\n", времОжидБесплат, err)
-			}
-			// log._rintf("INFO NetBank.checkPolygonForce(): ускорено строительство полигона\n")
-			return
-		}
-	}
-	// Все проверки прошли -- это просто работа
-	сам.полигон.АренаСостояние().СостояниеУст(cons.РежимРабота)
-}

+ 4 - 7
app/lev3/bot/bot.go

@@ -10,7 +10,7 @@ import (
 
 	. "wartank/app/lev0/alias"
 	. "wartank/app/lev0/types"
-	"wartank/app/lev2/arena_angar"
+	"wartank/app/lev2/arena/arena_angar"
 	"wartank/app/lev3/bot/bot_config"
 	"wartank/app/lev3/bot/bot_net"
 	"wartank/app/lev3/bot/bot_stat/tank_stat"
@@ -24,7 +24,7 @@ type Бот struct {
 	хран           ИЯдроХранилище
 	стата          ИТанкСтат
 	errFinal       error // Финальная ошибка работы, если была
-	ангар          ИАнгар
+	ангар          ИАренаАнгар
 	сеть           ИБотСеть
 	еслиРаботает   ИБезопБул
 	еслиАвтозапуск ИБезопБулНаблюд
@@ -106,11 +106,8 @@ func создатьЯдроВарБот(конт ИЯдроКонтекст, к
 	сам.еслиАвтозапуск = kernel.НовБезопБулНаблюд(сам.Имя(), сам.автозапускИзм)
 	сам.конт.Уст("бот", сам)
 	сам.конт.Уст("приложение", приложение)
-	var err error
-	// WarBotNet
 	сам.сеть = bot_net.НовБотСеть(сам.конт)
-	сам.ангар, err = arena_angar.НовАнгар(сам.конт)
-	сам.лог.Паника(err != nil, "НовВарБот(): in make IAngar, err=\n\t%w", err)
+	сам.ангар = arena_angar.НовАнгар(сам.конт)
 	if сам.конфиг.ЕслиАвтозапуск_ {
 		сам.еслиАвтозапуск.Уст()
 		сам.Пуск()
@@ -153,7 +150,7 @@ func (сам *Бот) Error() error {
 }
 
 // Ангар -- возвращает ангар игры
-func (сам *Бот) Ангар() ИАнгар {
+func (сам *Бот) Ангар() ИАренаАнгар {
 	return сам.ангар
 }
 

+ 40 - 0
app/lev3/bot/bot_stat/bot_resurs/bot_resurs.go

@@ -0,0 +1,40 @@
+// package bot_resurs -- статистика ресурсов
+package bot_resurs
+
+import (
+	. "wartank/app/lev0/types"
+	"wartank/app/lev1"
+)
+
+// БотРесурсы -- статистика ресурсов
+type БотРесурсы struct {
+	золото       ИСтатПарам
+	сереброВсего ИСтатПарам
+	топливо      ИСтатПарам
+}
+
+// НовБотРесурсы -- новая статистика ресурсов
+func НовБотРесурсы(конт ИБотКонтекст, ангар ИАренаАнгар) ИБотРесурсы {
+	сам := &БотРесурсы{
+		золото:       lev1.НовСтатПарам("золото"),
+		сереброВсего: lev1.НовСтатПарам("серебро"),
+		топливо:      lev1.НовСтатПарам("топливо"),
+	}
+
+	return сам
+}
+
+// Топливо -- возвращает топливо
+func (сам *БотРесурсы) Топливо() ИСтатПарам {
+	return сам.топливо
+}
+
+// Серебро -- возвращает общее количество серебро
+func (сам *БотРесурсы) Серебро() ИСтатПарам {
+	return сам.сереброВсего
+}
+
+// Золото -- возвращает количество золотых ресурсов
+func (сам *БотРесурсы) Золото() ИСтатПарам {
+	return сам.золото
+}

+ 0 - 46
app/lev3/bot/bot_stat/stat_resurs/stat_resurs.go

@@ -1,46 +0,0 @@
-// package stat_resurs -- статистика ресурсов
-package stat_resurs
-
-import (
-	"fmt"
-
-	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
-	"wartank/app/lev2/arena_angar/fuel"
-)
-
-// СтатРесурсы -- статистика ресурсов
-type СтатРесурсы struct {
-	золото       ИСтатПарам
-	сереброВсего ИСтатПарам
-	топливо      *fuel.Топливо
-}
-
-// НовСтатРесурсы -- новая статистика ресурсов
-func НовСтатРесурсы(конт ИБотКонтекст, ангар ИАнгар) *СтатРесурсы {
-	сам := &СтатРесурсы{
-		золото:       stat_param.НовСтатПарам("золото"),
-		сереброВсего: stat_param.НовСтатПарам("серебро всего"),
-	}
-	var ош error
-	сам.топливо, ош = fuel.НовТопливо(конт, ангар)
-	if ош != nil {
-		panic(fmt.Errorf("НовСтатРесурсы(): in make *Missions, err=\n\t%w", ош))
-	}
-	return сам
-}
-
-// Топливо -- возвращает топливо
-func (сам *СтатРесурсы) Топливо() *fuel.Топливо {
-	return сам.топливо
-}
-
-// СереброВсего -- возвращает общее количество серебро
-func (сам *СтатРесурсы) СереброВсего() ИСтатПарам {
-	return сам.сереброВсего
-}
-
-// Золото -- возвращает количество золотых ресурсов
-func (сам *СтатРесурсы) Золото() ИСтатПарам {
-	return сам.золото
-}

+ 8 - 8
app/lev3/bot/bot_stat/tank_stat/tank_stat.go

@@ -3,7 +3,7 @@ package tank_stat
 
 import (
 	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
+	"wartank/app/lev1"
 )
 
 // ТанкСтат -- статические параметры танка
@@ -21,12 +21,12 @@ type ТанкСтат struct {
 func НовТанкСтат(конт ИБотКонтекст) *ТанкСтат {
 	сам := &ТанкСтат{
 		конт:      конт,
-		атака:     stat_param.НовСтатПарам("атака"),
-		точность:  stat_param.НовСтатПарам("точность"),
-		прочность: stat_param.НовСтатПарам("прочность"),
-		броня:     stat_param.НовСтатПарам("броня"),
-		power:     stat_param.НовСтатПарам("мощь"),
-		усиление:  stat_param.НовСтатПарам("усиление"),
+		атака:     lev1.НовСтатПарам("атака"),
+		точность:  lev1.НовСтатПарам("точность"),
+		прочность: lev1.НовСтатПарам("прочность"),
+		броня:     lev1.НовСтатПарам("броня"),
+		power:     lev1.НовСтатПарам("мощь"),
+		усиление:  lev1.НовСтатПарам("усиление"),
 	}
 	return сам
 }
@@ -63,6 +63,6 @@ func (сам *ТанкСтат) Форсаж() ИСтатПарам {
 
 // Форсаж -- возвращает объект форсированного параметра
 func (сам *ТанкСтат) ФорсажОбнов(парам string, знач int) {
-	сам.усиление = stat_param.НовСтатПарам("усиление")
+	сам.усиление = lev1.НовСтатПарам("усиление")
 	сам.усиление.Уст(знач)
 }

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

@@ -72,11 +72,11 @@ func (сам *СервВеб) постБотСтат(кнт *fiber.Ctx) error {
 	}
 	диктБот["топливо"] = fmt.Sprint(топливо)
 	диктБот["золото"] = fmt.Sprint(бот.Ангар().Золото().Получ())
-	диктБот["серебро"] = fmt.Sprint(бот.Ангар().СереброВсего().Получ())
-	слава := бот.Ангар().Конвой().Слава().Получ()
+	диктБот["серебро"] = fmt.Sprint(бот.КонтБот().Получ("серебро").(int))
+	слава := бот.КонтБот().Получ("слава").(int)
 	if слава == 0 {
 		бот.Ангар().Обновить()
-		слава = бот.Ангар().Конвой().Слава().Получ()
+		слава = бот.КонтБот().Получ("слава").(int)
 	}
 	диктБот["слава"] = fmt.Sprint(слава)
 	диктБот["прогресс"] = fmt.Sprintf("%v%%", бот.Ангар().Прогресс().Получ())
@@ -87,17 +87,19 @@ func (сам *СервВеб) постБотСтат(кнт *fiber.Ctx) error {
 	диктБот["прочность"] = fmt.Sprintf("%v", бот.Стата().Прочность().Получ())
 	диктБот["мощь"] = fmt.Sprintf("%v", бот.Стата().Мощь().Получ())
 
-	диктБот["шахта_уровень"] = fmt.Sprintf("%v", бот.Ангар().База().Шахта().Уровень().Получ())
-	диктБот["шахта_режим"] = fmt.Sprintf("%v", бот.Ангар().База().Шахта().АренаСостояние().Состояние())
-	диктБот["шахта_сделать_кол"] = fmt.Sprintf("%v", бот.Ангар().База().Шахта().ПродуктКолСейчас())
-	диктБот["шахта_сделать_назв"] = бот.Ангар().База().Шахта().ПродуктИмяСейчас()
-	диктБот["шахта_сделать_время"] = бот.Ангар().База().Шахта().ПродуктВремяСейчас()
-
-	диктБот["полигон_уровень"] = fmt.Sprintf("%v", бот.Ангар().База().Полигон().Уровень().Получ())
-	диктБот["полигон_режим"] = fmt.Sprintf("%v", бот.Ангар().База().Полигон().АренаСостояние().Состояние())
-	диктБот["полигон_сделать_кол"] = fmt.Sprintf("%v", бот.Ангар().База().Полигон().ПродуктКолСейчас())
-	диктБот["полигон_сделать_назв"] = бот.Ангар().База().Полигон().ПродуктИмяСейчас()
-	диктБот["полигон_сделать_время"] = бот.Ангар().База().Полигон().ПродуктВремяСейчас()
+	шахта:= бот.КонтБот().Получ("шахта").(ИАренаШахта)
+	диктБот["шахта_уровень"] =шахта.Уровень().ЗначСтр()
+	диктБот["шахта_режим"] = string(шахта.АренаСостояние().Состояние())
+	диктБот["шахта_сделать_кол"] = fmt.Sprint(шахта.ПродуктКолСейчас())
+	диктБот["шахта_сделать_назв"] = шахта.ПродуктИмяСейчас()
+	диктБот["шахта_сделать_время"] = шахта.ПродуктВремяСейчас()
+
+	полигон:=бот.КонтБот().Получ("полигон").(ИАренаПолигон)
+	диктБот["полигон_уровень"] = полигон.Уровень().ЗначСтр()
+	диктБот["полигон_режим"] = string(полигон.АренаСостояние().Состояние())
+	диктБот["полигон_сделать_кол"] = fmt.Sprint(полигон.ПродуктКолСейчас())
+	диктБот["полигон_сделать_назв"] = полигон.ПродуктИмяСейчас()
+	диктБот["полигон_сделать_время"] = полигон.ПродуктВремяСейчас()
 	return кнт.JSON(диктБот)
 }
 

+ 5 - 5
app/lev3/serv_web/web_gui/page_bot_show/page_bot_show.go

@@ -59,9 +59,9 @@ func (сам *СтраницаБотПоказать) гетБотПоказ(к
 		сам.рендер.Доб("{.имя}", бот.Имя())
 		сам.рендер.Доб("{.number}", бот.Номер())
 		сам.рендер.Доб("{.золото}", ангар.Золото().ЗначСтр())
-		сам.рендер.Доб("{.серебро}", ангар.СереброВсего().ЗначСтр())
+		сам.рендер.Доб("{.серебро}", ангар.Серебро().ЗначСтр())
 		сам.рендер.Доб("{.топливо}", ангар.Топливо().ЗначСтр())
-		сам.рендер.Доб("{.слава}", ангар.Конвой().Слава().ЗначСтр())
+		сам.рендер.Доб("{.слава}", бот.КонтБот().Получ("слава").(int))
 	}
 	{ // Сила танка
 		стата := бот.Стата()
@@ -72,7 +72,7 @@ func (сам *СтраницаБотПоказать) гетБотПоказ(к
 		сам.рендер.Доб("{.мощь}", стата.Мощь().ЗначСтр())
 	}
 	{ // Шахта
-		шахта := бот.Ангар().База().Шахта()
+		шахта := бот.КонтБот().Получ("шахта").(ИАренаШахта)
 		сам.рендер.Доб("{.шахта_уровень}", шахта.Уровень().Получ())
 		сам.рендер.Доб("{.шахта_режим}", шахта.АренаСостояние().Состояние())
 		сам.рендер.Доб("{.шахта_сделать_кол}", шахта.ПродуктКолСейчас())
@@ -80,7 +80,7 @@ func (сам *СтраницаБотПоказать) гетБотПоказ(к
 		сам.рендер.Доб("{.шахта_сделать_время}", шахта.ПродуктВремяСейчас())
 	}
 	{ // Полигон
-		полигон := бот.Ангар().База().Полигон()
+		полигон := бот.КонтБот().Получ("полигон").(ИАренаПолигон)
 		сам.рендер.Доб("полигон_уровень", полигон.Уровень().ЗначСтр())
 		сам.рендер.Доб("полигон_режим", полигон.АренаСостояние().Состояние())
 		сам.рендер.Доб("полигон_сделать_кол", полигон.ПродуктКолСейчас())
@@ -88,7 +88,7 @@ func (сам *СтраницаБотПоказать) гетБотПоказ(к
 		сам.рендер.Доб("полигон_сделать_время", полигон.ПродуктВремяСейчас())
 	}
 	{ // Арсенал
-		арс := бот.Ангар().База().Арсенал()
+		арс := бот.КонтБот().Получ("арсенал").(ИАренаАрсенал)
 		сам.рендер.Доб("оружейная_уровень", арс.Уровень().ЗначСтр())
 		сам.рендер.Доб("оружейная_работа", арс.АренаСостояние().РаботаИмя())
 		сам.рендер.Доб("оружейная_режим", арс.АренаСостояние().Состояние())

+ 11 - 0
pkg/alias/alias.go

@@ -0,0 +1,11 @@
+package alias
+
+/*
+	Содержит алиасы типов, необходимые для работы.
+*/
+
+// AMilSec -- время в миллисекундах
+type AMilSec int
+
+// ADAmage -- урон от выстрела
+type ADamage int

+ 173 - 0
pkg/components/counttime/counttime.go

@@ -0,0 +1,173 @@
+package counttime
+
+import (
+	"fmt"
+	// "log"
+	"sync"
+	"time"
+
+	"wartank/pkg/components/parsetime"
+	"wartank/pkg/components/safebool"
+	"wartank/pkg/components/safeint"
+	"wartank/pkg/types"
+)
+
+/*
+	Счётчик обратного временив мсек
+*/
+
+const (
+	iSleep = time.Millisecond * 100
+)
+
+// CountTime -- счётчик обратного времени
+type CountTime struct {
+	app    types.IServer
+	val    *safeint.SafeInt
+	parser *parsetime.ParseTime
+
+	chTick     chan int
+	chCall     chan int           // Канал для отправки сигналов
+	isWork     *safebool.SafeBool // Признак работы
+	timeTarget *safeint.SafeInt   // Целевое время срабатывания
+
+	block sync.RWMutex
+}
+
+// NewCountTime -- возвращает новый *CountTime
+func NewCountTime(app types.IServer) *CountTime {
+	if app == nil {
+		panic("NewCountTime(): app==nil")
+	}
+	sf := &CountTime{
+		app:        app,
+		val:        safeint.NewSafeInt(),
+		chTick:     make(chan int, 3),
+		chCall:     make(chan int, 2),
+		isWork:     safebool.NewSafeBool(),
+		parser:     parsetime.NewParseTime(),
+		timeTarget: safeint.NewSafeInt(),
+	}
+	sf.isWork.Set()
+	go sf.makeTick()
+	go sf.run()
+	return sf
+}
+
+// Запускает тикер для секундных интервалов
+func (sf *CountTime) makeTick() {
+	defer func() {
+		if !sf.isWork.Get() {
+			return
+		}
+		sf.isWork.Reset()
+		close(sf.chTick)
+		// log._rintf("CountTime.makeTick(): работа завершена")
+	}()
+	countSleep := time.Duration(0)
+	for {
+		select {
+		case <-sf.app.Done(): // Отмена контекста приложения
+			// log._rintf("CountTime.makeTick(): глобальная отмена контекста\n")
+			return
+		default:
+			if !sf.isWork.Get() {
+				return
+			}
+
+			if countSleep >= time.Second {
+				sf.chTick <- 1
+				countSleep = 0
+			}
+			countSleep += iSleep
+			time.Sleep(iSleep)
+		}
+	}
+}
+
+// Главный цикл обратного отсчёта
+func (sf *CountTime) run() {
+	for range sf.chTick {
+		timeNow := time.Now().UTC().Unix()
+		if sf.timeTarget.Get() > int(timeNow) {
+			val := sf.timeTarget.Get() - int(timeNow)
+			val -= 1
+			sf.Set(val)
+			continue
+		}
+		sf.chCall <- 1
+		continue
+	}
+	close(sf.chCall)
+}
+
+// Stop -- останавливает работу чяётчика
+func (sf *CountTime) Stop() {
+	sf.isWork.Reset()
+}
+
+// Get -- возвращает число оставшихся сек
+func (sf *CountTime) Get() int {
+	return sf.val.Get()
+}
+
+// Parse -- устанавливает число оставшихся сек
+func (sf *CountTime) Parse(val string) error {
+	sf.block.Lock()
+	defer sf.block.Unlock()
+	if val == "" {
+		return fmt.Errorf("CountTime.Set(): val is empty")
+	}
+	sf.parser.Parse(val)
+	_val := sf.parser.Hour().Get()*3600 + sf.parser.Min().Get()*60 + sf.parser.Min().Get()
+	sf.val.Set(_val)
+	_val = int(time.Now().UTC().Unix()) + sf.val.Get()
+	sf.timeTarget.Set(_val)
+	return nil
+}
+
+// Set -- устанавливает число оставшихся сек
+func (sf *CountTime) Set(val int) error {
+	sf.block.Lock()
+	defer sf.block.Unlock()
+	if val < 0 {
+		return fmt.Errorf("CountTime.Set(): val(%v)<0", val)
+	}
+	sf.val.Set(val)
+	{ // Обновить локальные счётчики
+		if val < 60 {
+			sf.parser.Hour().Reset()
+			sf.parser.Min().Reset()
+			sf.parser.Sec().Set(val)
+			return nil
+		}
+		if 60 < val && val < 3600 {
+			sf.parser.Hour().Reset()
+			iMin := val / 60
+			sf.parser.Min().Set(iMin)
+			val -= iMin * 60
+			sf.parser.Sec().Set(val)
+			return nil
+		}
+		sf.parser.Hour().Set(val / 3600)
+		val -= sf.parser.Hour().Get() * 3600
+		sf.parser.Min().Set(val / 60)
+		val -= sf.parser.Min().Get() * 60
+		sf.parser.Sec().Set(val)
+		val = int(time.Now().UTC().Unix()) + sf.val.Get()
+		sf.timeTarget.Set(val)
+	}
+	return nil
+}
+
+// String -- возвращает строковое представление оставшихся сек
+func (sf *CountTime) String() string {
+	sf.block.RLock()
+	defer sf.block.RUnlock()
+	return sf.parser.String()
+}
+
+// ChanSig -- возвращает канал чтения тиков
+func (sf *CountTime) ChanSig() <-chan int {
+	return sf.chCall
+}

+ 256 - 0
pkg/components/counttime/counttime_test.go

@@ -0,0 +1,256 @@
+package counttime
+
+import (
+	"testing"
+	"time"
+	"wartank/pkg/components/safebool"
+	"wartank/pkg/mock/mockapp"
+)
+
+/*
+	Тест для счётчика времени
+*/
+
+// Тестер для счётчика времени
+type tester struct {
+	t      *testing.T
+	app    *mockapp.MockApp
+	ct     *CountTime
+	err    error
+	isCall *safebool.SafeBool // Признак обратного вызова
+}
+
+// Обратный вызов для счётчика времени
+func (sf *tester) call() {
+	<-sf.ct.chCall
+}
+
+func TestCountTime(t *testing.T) {
+	test := &tester{
+		t:      t,
+		isCall: safebool.NewSafeBool(),
+		app:    mockapp.NewMockApp(),
+	}
+	time.Sleep(time.Millisecond * 100)
+	test.create()
+	test.setInt()
+	test.setStr()
+	test.checkTick()
+	test.cancel()
+}
+
+// Оменяет работу таймера
+func (sf *tester) cancel() {
+	sf.t.Logf("=cancel=\n")
+	ct := NewCountTime(sf.app)
+	for len(ct.chTick) > 0 {
+		<-ct.chTick
+	}
+	sf.app.CancelApp()
+	time.Sleep(time.Millisecond * 150)
+}
+
+// Проверяет обработчик тика
+func (sf *tester) checkTick() {
+	ct := NewCountTime(sf.app)
+	{ // Секундный тик
+		ct.Parse("00:00:08")
+		time.Sleep(time.Second * 1)
+		ct.chTick <- 1
+		time.Sleep(time.Millisecond * 20)
+		if val := ct.String(); val != "00:00:08" {
+			sf.t.Errorf("checkTick(): счётчик(%v)!='00:00:08'", val)
+		}
+	}
+	{ // Проверка времени прямо сейчас
+		ct.chTick <- 1
+		time.Sleep(time.Millisecond * 20)
+		if val := ct.String(); val != "00:00:08" {
+			sf.t.Errorf("checkTick(): счётчик(%v)!='00:00:08'", val)
+		}
+	}
+	{ // Проверка обратного вызова прямо сейчас
+		strTime := time.Now().UTC().Format("15:04:05")
+		ct.Parse(strTime)
+		if val := ct.String(); val != strTime {
+			sf.t.Errorf("checkTick(): счётчик(%v)!=%s", val, strTime)
+		}
+		ct.chTick <- 1
+		// Выход из функции -- и есть факт обратного вызова
+		sf.call()
+		{ // Проверка отсутствия обратного вызова прямо сейчас
+			ct.Parse("00:00:00")
+			ct.chTick <- 1
+			// Выход из функции -- и есть факт обратного вызова
+			sf.call()
+			if val := ct.Get(); val != 0 {
+				sf.t.Errorf("checkTick(): счётчик(%v)!=0", val)
+			}
+			ct.Stop()
+			sf.app.CancelApp()
+			time.Sleep(time.Millisecond * 50)
+		}
+	}
+}
+
+func (sf *tester) setStrBad1(strBad string) {
+	defer func() {
+		if _panic := recover(); _panic == nil {
+			sf.t.Errorf("setStrBad1(): panic==nil\n")
+		}
+	}()
+	if sf.err = sf.ct.Parse(strBad); sf.err == nil {
+		sf.t.Errorf("setStrBad1(): BAD-2 err==nil")
+	}
+}
+
+// Устанавливает строковое значение времени
+func (sf *tester) setStr() {
+	go sf.call()
+	ct := NewCountTime(sf.app)
+	{ // BAD-1 пустая строка
+		if sf.err = ct.Parse(""); sf.err == nil {
+			sf.t.Errorf("setStr(): BAD-1 err==nil")
+		}
+	}
+	// BAD-2 неформатная строка
+	sf.setStrBad1(":::")
+	// BAD-3 кривые часы
+	sf.setStrBad1("a1:02:03")
+	// BAD-4 кривые минуты
+	sf.setStrBad1("01:a2:03")
+	// BAD-5 кривые секунды
+	sf.setStrBad1("01:02:a3")
+	// BAD-6 кривые только секунды
+	sf.setStrBad1("a3")
+	// BAD-7 кривые минуты +секунды
+	sf.setStrBad1("a2:03")
+	// BAD-8 кривые часы +минуты +секунды
+	sf.setStrBad1("a1:02:03")
+	// BAD-9 минуты +кривые секунды
+	sf.setStrBad1("02:a3")
+	// BAD-10 кривые минуты +секунды
+	sf.setStrBad1("60:03")
+	// BAD-11 кривые минуты +секунды
+	sf.setStrBad1("-1:03")
+	// BAD-12 минуты +кривые секунды
+	sf.setStrBad1("01:60")
+	// BAD-13 минуты +кривые секунды
+	sf.setStrBad1("01:-1")
+	// BAD-14 кривые часы +минуты + секунды
+	sf.setStrBad1("-1:02:03")
+	// BAD-15 кривые часы +минуты + секунды
+	//sf.setStrBad1("24:02:03")
+	{ // GOOD-1 секунды
+		if sf.err = ct.Parse("03"); sf.err != nil {
+			sf.t.Errorf("setStr(): GOOD-1 err=%v", sf.err)
+		}
+	}
+	{ // GOOD-2 минуты секунды
+		if sf.err = ct.Parse("02:03"); sf.err != nil {
+			sf.t.Errorf("setStr(): GOOD-2 err=%v", sf.err)
+		}
+	}
+	{ // GOOD-3 часы минуты секунды
+		if sf.err = ct.Parse("01:02:03"); sf.err != nil {
+			sf.t.Errorf("setStr(): GOOD-3 err=%v", sf.err)
+		}
+	}
+}
+
+// Устанавливает число секунд для отсчёта
+func (sf *tester) setInt() {
+	go sf.call()
+	ct := NewCountTime(sf.app)
+	{ // Bad-1 Отрицательное число
+		if sf.err = ct.Set(-1); sf.err == nil {
+			sf.t.Errorf("setInt(): BAD-1 err==nil")
+		}
+	}
+	{ // GOOD-1
+		if sf.err = ct.Set(8); sf.err != nil {
+			sf.t.Errorf("setInt(): GOOD-1 err=%v", sf.err)
+		}
+		if ct.parser.Hour().Get() != 0 {
+			sf.t.Errorf("setInt(): GOOD-1 hour(%v)!=0", sf.ct.parser.Hour().Get())
+		}
+		if ct.parser.Min().Get() != 0 {
+			sf.t.Errorf("setInt(): GOOD-1 min(%v)!=0", sf.ct.parser.Min().Get())
+		}
+		if ct.parser.Sec().Get() != 8 {
+			sf.t.Errorf("setInt(): GOOD-1 sec(%v)!=8", sf.ct.parser.Sec().Get())
+		}
+		if strVal := ct.String(); strVal != "00:00:08" {
+			sf.t.Errorf("setInt(): GOOD-1 strVal(%v)!='00:00:08'", strVal)
+		}
+	}
+	{ // GOOD-2
+		if sf.err = ct.Set(121); sf.err != nil {
+			sf.t.Errorf("setInt(): GOOD-2 err=%v", sf.err)
+		}
+		if ct.parser.Hour().Get() != 0 {
+			sf.t.Errorf("setInt(): GOOD-2 hour(%v)!=0", sf.ct.parser.Hour().Get())
+		}
+		if ct.parser.Min().Get() != 2 {
+			sf.t.Errorf("setInt(): GOOD-2 min(%v)!=2", sf.ct.parser.Min().Get())
+		}
+		if ct.parser.Sec().Get() != 1 {
+			sf.t.Errorf("setInt(): GOOD-2 sec(%v)!=1", sf.ct.parser.Sec().Get())
+		}
+		if strVal := ct.String(); strVal != "00:02:01" {
+			sf.t.Errorf("setInt(): GOOD-2 strVal(%v)!='00:02:01'", strVal)
+		}
+	}
+	{ // GOOD-3
+		if sf.err = ct.Set(7203); sf.err != nil {
+			sf.t.Errorf("setInt(): GOOD-3 err=%v", sf.err)
+		}
+		if ct.parser.Hour().Get() != 2 {
+			sf.t.Errorf("setInt(): GOOD-3 hour(%v)!=2", sf.ct.parser.Hour().Get())
+		}
+		if ct.parser.Min().Get() != 0 {
+			sf.t.Errorf("setInt(): GOOD-3 min(%v)!=0", sf.ct.parser.Min().Get())
+		}
+		if ct.parser.Sec().Get() != 3 {
+			sf.t.Errorf("setInt(): GOOD-3 sec(%v)!=3", sf.ct.parser.Sec().Get())
+		}
+		if strVal := ct.String(); strVal != "02:00:03" {
+			sf.t.Errorf("setInt(): GOOD-3 strVal(%v)!='02:00:03'", strVal)
+		}
+	}
+}
+
+// Нет обратного канала
+func (sf *tester) createBad1() {
+	defer func() {
+		if _panic := recover(); _panic == nil {
+			sf.t.Errorf("createBad1(): panic==nil")
+		}
+	}()
+	sf.ct = NewCountTime(nil)
+	if sf.ct != nil {
+		sf.t.Errorf("createBad1(): countTime!=nil")
+	}
+}
+
+// Правильное создание
+func (sf *tester) createGood1() {
+	defer func() {
+		if _panic := recover(); _panic != nil {
+			sf.t.Errorf("createGood1(): panic=%v", _panic)
+		}
+	}()
+	ct := NewCountTime(sf.app)
+	if ct == nil {
+		sf.t.Errorf("createGood1(): countTime==nil")
+	}
+	if val := ct.Get(); val != 0 {
+		sf.t.Errorf("createGood1(): val(%v)!=0", val)
+	}
+}
+
+// Создание счётчика обратного времени
+func (sf *tester) create() {
+	sf.createBad1()
+	sf.createGood1()
+}

+ 56 - 0
pkg/components/kernel/keeper/keeper.go

@@ -0,0 +1,56 @@
+package keeper
+
+/*
+	Сторож системных сигналов.
+	Мониторит ОС и части сервиса на завершение работы.
+	В системе он должен быть только один.
+*/
+
+import (
+	"os"
+	"os/signal"
+	"syscall"
+
+	"wartank/pkg/types"
+)
+
+// Keeper -- сторож системных и внутренних сигналов
+type Keeper struct {
+	kernel types.IKernel
+	slog   types.ISlog
+	chSys  chan os.Signal
+}
+
+// NewKeeper -- возвращает глобальный объект сторожа *Keeper
+func NewKeeper(kernel types.IKernel) *Keeper {
+	if kernel == nil {
+		panic("GetKeeper(): IKernel is nil")
+	}
+
+	sf := &Keeper{
+		kernel: kernel,
+		slog:   kernel.Slog(),
+		chSys:  make(chan os.Signal, 3),
+	}
+	sf.kernel.Wg().Add("keeper")
+	signal.Notify(sf.chSys, os.Interrupt, syscall.SIGTERM)
+	go sf.run()
+	sf.slog.Debugf("NewKeeper()\n")
+	return sf
+}
+
+// Слушает сигналы завершения изнутри и снаружи
+func (sf *Keeper) run() {
+	sf.slog.Infof("Keeper.run()\n")
+	defer func() {
+		sf.slog.Infof("Keeper.run(): end\n")
+		sf.kernel.Wg().Done("keeper")
+	}()
+	select {
+	case sig := <-sf.kernel.Done(): // глобальная отмена контекста
+		sf.slog.Infof("Keeper.run(): intern_sig=%q\n", sig)
+	case sig := <-sf.chSys: // Системный сигнал закрытия
+		sf.kernel.CancelApp()
+		sf.slog.Infof("Keeper.run(): sys_sig=%v\n", sig)
+	}
+}

+ 85 - 0
pkg/components/kernel/keeper/keeper_test.go

@@ -0,0 +1,85 @@
+package keeper
+
+import (
+	"os"
+	"syscall"
+	"testing"
+	"time"
+
+	"wartank/pkg/components/kernel/slog"
+	"wartank/pkg/mock/mockenv"
+	"wartank/pkg/mock/mockkernel"
+)
+
+/*
+	Тест для сторожа
+*/
+
+// Тестер для сторожа
+type tester struct {
+	t    *testing.T
+	err  error
+	me   *mockenv.MockEnv
+	kp   *Keeper
+	kern *mockkernel.MockKernel
+}
+
+func TestKeeper(t *testing.T) {
+	test := &tester{
+		t:  t,
+		me: mockenv.NewMockEnv(),
+	}
+	test.create()
+	test.cancel()
+	_ = os.RemoveAll("./log")
+}
+
+// Отмена глобального контекста приложения
+func (sf *tester) cancel() {
+	sf.kp.chSys <- syscall.SIGTERM
+	time.Sleep(time.Microsecond * 150)
+	sf.createGood1()
+	sf.kern.CancelApp()
+	time.Sleep(time.Microsecond * 150)
+}
+
+// Создание сторожа
+func (sf *tester) create() {
+	sf.createBad1()
+	sf.createGood1()
+}
+
+func (sf *tester) createGood1() {
+	defer func() {
+		if _panic := recover(); _panic != nil {
+			sf.t.Errorf("createGood1(: panic=\n\t%v\n", _panic)
+		}
+	}()
+	sf.me.Unset()
+	if err := sf.me.InitLocal(); err != nil {
+		sf.t.Errorf("createGood1(): не локальное окружение, err=\n\t%v\n", err)
+		return
+	}
+	sf.kern = mockkernel.NewMockKernel()
+	sf.kern.Slog_, sf.err = slog.NewSlog(sf.kern)
+	if sf.err != nil {
+		sf.t.Errorf("createGood1(): in create ISlog, err=\n\t%v", sf.err)
+	}
+	sf.kp = NewKeeper(sf.kern)
+	if sf.kp == nil {
+		sf.t.Errorf("createGood1(): keep==nil")
+	}
+}
+
+// Нет объекта приложения
+func (sf *tester) createBad1() {
+	defer func() {
+		if _panic := recover(); _panic == nil {
+			sf.t.Errorf("createBad1(: panic==nil\n")
+		}
+		if sf.kp != nil {
+			sf.t.Errorf("createBad1(): keep!=nil")
+		}
+	}()
+	sf.kp = NewKeeper(nil)
+}

+ 79 - 0
pkg/components/kernel/kernel.go

@@ -0,0 +1,79 @@
+// Package kernel -- объект ядра прилоэжения
+//
+//	Содержит базовый функционал сервиса
+package kernel
+
+import (
+	"context"
+	"fmt"
+	"sync"
+	// "time"
+
+	"wartank/pkg/components/kernel/keeper"
+	"wartank/pkg/components/kernel/slog"
+	"wartank/pkg/components/kernel/wgname"
+	"wartank/pkg/types"
+)
+
+/*
+	Базовый объект приложения.
+*/
+
+// Kernel -- объект ядра приложения
+type Kernel struct {
+	ctxBg    context.Context // Неотменяемый контекст приложения
+	ctxApp   context.Context // Отменяемый контекст приложения
+	fnCancel func()          // Функция отмены приложения
+	keeper   *keeper.Keeper  // Сторож системных сигналов
+	slog     *slog.Slog      // Логгер в два вывода
+	wg       *wgname.WgName  // Групповое ожидание частей приложения
+	block    sync.Mutex
+}
+
+// NewKernel -- возвращает новый *Kernel
+func NewKernel() (sf *Kernel, err error) {
+	// timeStart := time.Now().UTC().Format("2006-10-02 15:04:05.000")
+	// fmt._rintf("%v\t%v\tCI/CD test\n", cons.SelfName, timeStart)
+	sf = &Kernel{
+		ctxBg: context.Background(),
+		wg:    wgname.NewWgName(),
+	}
+	sf.ctxApp, sf.fnCancel = context.WithCancel(sf.ctxBg)
+	sf.block.Lock()
+	sf.slog, err = slog.NewSlog(sf)
+	sf.block.Unlock()
+	if err != nil {
+		return nil, fmt.Errorf("NewKernel(): in creste ISlog, err=%w", err)
+	}
+	sf.slog.Debugf("NewKernel()")
+	sf.keeper = keeper.NewKeeper(sf)
+	return sf, nil
+}
+
+// Wg -- возвращает объект групповой сихнронизации
+func (sf *Kernel) Wg() types.IWgName {
+	return sf.wg
+}
+
+// CtxApp -- возвращает глобальный контекст приложения
+func (sf *Kernel) CtxApp() context.Context {
+	return sf.ctxApp
+}
+
+// Done -- возвращает канал отмены контекста приложения
+func (sf *Kernel) Done() <-chan struct{} {
+	return sf.ctxApp.Done()
+}
+
+// CancelApp -- отменяет глобальный контекст приложения
+func (sf *Kernel) CancelApp() {
+	sf.block.Lock()
+	defer sf.block.Unlock()
+	sf.slog.Infof("Kernel.CancelApp()\n")
+	sf.fnCancel()
+}
+
+// Slog -- возвращает глобальный лог приложения
+func (sf *Kernel) Slog() types.ISlog {
+	return sf.slog
+}

+ 43 - 0
pkg/components/kernel/kernel_test.go

@@ -0,0 +1,43 @@
+package kernel
+
+import (
+	"os"
+	"testing"
+)
+
+// Тестер для базового объекта приложения
+type tester struct {
+	t    *testing.T
+	err  error
+	kern *Kernel
+}
+
+func TestKernel(t *testing.T) {
+	test := &tester{
+		t: t,
+	}
+	test.create()
+	_ = os.RemoveAll("./log")
+}
+
+// Создание базового объекта
+func (sf *tester) create() {
+	sf.t.Logf("create\n")
+	sf.kern, sf.err = NewKernel()
+	if sf.err != nil {
+		sf.t.Errorf("create(): err=\n\t%v", sf.err)
+	}
+	if sf.kern == nil {
+		sf.t.Errorf("create(): kernel==nil\n")
+	}
+	if wg := sf.kern.Wg(); wg == nil {
+		sf.t.Errorf("create(): wg==nil\n")
+	}
+	if ctx := sf.kern.CtxApp(); ctx == nil {
+		sf.t.Errorf("create(): ctx==nil\n")
+	}
+	if slog := sf.kern.Slog(); slog == nil {
+		sf.t.Errorf("create(): slog==nil\n")
+	}
+	sf.kern.CancelApp()
+}

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů