Просмотр исходного кода

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

SVI 1 год назад
Родитель
Сommit
f2cf3f0155
85 измененных файлов с 819 добавлено и 2720 удалено
  1. 2 2
      Makefile
  2. 1 1
      app/lev0/types/iarena_ctx.go
  3. 0 10
      app/lev0/types/ibattle_action.go
  4. 4 0
      app/lev0/types/ibattle_health.go
  5. 11 0
      app/lev0/types/ibattle_manevr.go
  6. 20 0
      app/lev0/types/ibattle_process.go
  7. 7 0
      app/lev0/types/ibattle_shot.go
  8. 6 10
      app/lev0/types/ibot.go
  9. 0 30
      app/lev0/types/idiv_war_action.go
  10. 1 1
      app/lev0/types/iparser_simple.go
  11. 31 40
      app/lev1/health/health.go
  12. 0 77
      app/lev1/health/health_repair_time/health_repair_time.go
  13. 0 0
      app/lev1/manevr/ismanevr/ismanevr.go
  14. 198 0
      app/lev1/manevr/manevr.go
  15. 6 6
      app/lev1/repair_time/repair_time.go
  16. 0 0
      app/lev1/shot/damage/damage.go
  17. 45 43
      app/lev1/shot/shot.go
  18. 3 2
      app/lev1/shot/shot_time/shot_time.go
  19. 0 0
      app/lev1/sound/is_sound_play/is_sound_play.go
  20. 1 1
      app/lev2/arena/arena.go
  21. 1 1
      app/lev2/arena/arena_context/arena_context.go
  22. 1 1
      app/lev2/arena_base/arena_base.go
  23. 1 1
      app/lev2/arena_battle/battle_worker/battle_worker/battle_sound/battle_sound.go
  24. 15 30
      app/lev2/arena_battle/battle_worker/battle_worker/battle_worker.go
  25. 0 48
      app/lev2/arena_battle/battle_worker/battle_worker/battlesound/battlesound.go
  26. 0 43
      app/lev2/arena_battle/battle_worker/battle_worker/manevr/is_manevr/is_manevr.go
  27. 0 166
      app/lev2/arena_battle/battle_worker/battle_worker/manevr/manevr.go
  28. 0 90
      app/lev2/arena_battle/battle_worker/battle_worker/shot/shot.go
  29. 0 76
      app/lev2/arena_battle/battle_worker/battle_worker/shottime/shottime.go
  30. 14 31
      app/lev2/arena_battle/battle_worker/battleon/battleon.go
  31. 3 3
      app/lev2/arena_convoy/arena_convoy.go
  32. 9 9
      app/lev2/arena_death/arena_death.go
  33. 2 2
      app/lev2/arena_death/death_wait/death_wait.go
  34. 0 110
      app/lev2/arena_death/death_worker/death_on/death_on.go
  35. 0 102
      app/lev2/arena_death/death_worker/death_on/health/health.go
  36. 0 46
      app/lev2/arena_death/death_worker/death_on/health/healthtime/healthtime.go
  37. 0 41
      app/lev2/arena_death/death_worker/death_on/health/isrepair/isrepair.go
  38. 0 173
      app/lev2/arena_death/death_worker/death_on/manevr/manevr.go
  39. 0 41
      app/lev2/arena_death/death_worker/death_on/shot/is_shot/is_shot.go
  40. 4 4
      app/lev2/arena_death/death_worker/death_worker.go
  41. 1 1
      app/lev2/arena_death/death_worker/process_death/battle_sound/battle_sound.go
  42. 0 0
      app/lev2/arena_death/death_worker/process_death/battle_sound/is_play/is_play.go
  43. 1 1
      app/lev2/arena_death/death_worker/process_death/battlesound/battlesound.go
  44. 5 5
      app/lev2/arena_death/death_worker/process_death/health/health.go
  45. 0 0
      app/lev2/arena_death/death_worker/process_death/health/healthtime/healthtime.go
  46. 0 0
      app/lev2/arena_death/death_worker/process_death/health/isrepair/isrepair.go
  47. 0 0
      app/lev2/arena_death/death_worker/process_death/health/repairtime/repairtime.go
  48. 89 0
      app/lev2/arena_death/death_worker/process_death/process_death.go
  49. 0 0
      app/lev2/arena_death/death_worker/process_death/shot/damage/damage.go
  50. 0 0
      app/lev2/arena_death/death_worker/process_death/shot/is_shot/is_shot.go
  51. 5 5
      app/lev2/arena_death/death_worker/process_death/shot/shot.go
  52. 0 0
      app/lev2/arena_death/death_worker/process_death/shottime/shottime.go
  53. 11 17
      app/lev2/arena_division/div_war/div_war.go
  54. 0 178
      app/lev2/arena_division/div_war/div_war_on/div_war_on.go
  55. 0 48
      app/lev2/arena_division/div_war/div_war_on/divwarsound/divwarsound.go
  56. 0 43
      app/lev2/arena_division/div_war/div_war_on/manevr/is_manevr/ismanevr.go
  57. 0 193
      app/lev2/arena_division/div_war/div_war_on/manevr/manevr.go
  58. 0 230
      app/lev2/arena_division/div_war/div_war_on/shot/shot.go
  59. 0 178
      app/lev2/arena_division/div_war/divwaron/divwaron.go
  60. 1 1
      app/lev2/arena_division/div_war/process_divwar/div_war_sound/div_war_sound.go
  61. 0 0
      app/lev2/arena_division/div_war/process_divwar/div_war_sound/isplay/isplay.go
  62. 157 0
      app/lev2/arena_division/div_war/process_divwar/process_divwar.go
  63. 16 38
      app/lev2/arena_division/divwar/div_war_on/div_war_on.go
  64. 4 10
      app/lev2/arena_division/divwar/divwar.go
  65. 11 31
      app/lev2/arena_division/divwar/divwaron/divwaron.go
  66. 0 19
      app/lev2/arena_duel/arena_duel.go
  67. 4 4
      app/lev2/arena_polygon/arena_polygon.go
  68. 0 222
      app/lev3/bot/angar/division/div_war/div_war.go
  69. 0 193
      app/lev3/bot/angar/division/div_war/div_war_on/manevr/manevr.go
  70. 28 49
      app/lev3/bot/bot.go
  71. 3 3
      app/lev3/bot/bot_net/bot_net_stat/net_stat.go
  72. 1 1
      app/lev3/farm_bots/dict_bot/dict_bot.go
  73. 4 4
      app/lev3/serv_web/serv_web.go
  74. 0 0
      kernel/helpers/helper.go
  75. 0 0
      kernel/helpers/helpers.go
  76. 0 0
      kernel/helpers/helpers_test.go
  77. 0 0
      kernel/helpers/result.txt
  78. 1 1
      kernel/internal/kernel_ctx/kernel_keeper/kernel_keeper.go
  79. 1 1
      kernel/internal/kernel_ctx/kernel_wg/kernel_wg.go
  80. 1 1
      kernel/internal/kernel_serv_http/kernel_serv_http.go
  81. 1 1
      kernel/internal/kernel_store/kernel_store.go
  82. 67 0
      kernel/internal/safe_bool_observer/safe_bool_observer.go
  83. 5 0
      kernel/kernel.go
  84. 15 0
      kernel/kernel_types/ikernel_safe_bool_observer.go
  85. 1 1
      pkg/mock/mock_env/mock_env.go

+ 2 - 2
Makefile

@@ -55,8 +55,8 @@ lint:
 	clear
 	go fmt ./...
 	golangci-lint run ./cmd/server/...
-	golangci-lint run ./pkg/...
-	golangci-lint run ./server/...
+	golangci-lint run ./app/...
+	golangci-lint run ./kernel/...
 .PHONY: graph
 graph:
 	# #go install github.com/kisielk/godepgraph@latest

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

@@ -11,7 +11,7 @@ type ИАренаКонтекст interface {
 	Бот() ИБот
 	// Контекст -- контекст игровой арены
 	Контекст() context.Context
-	// Отменить -- вызывает контекст отмены битвы
+	// Отменить -- вызывает отмены контекста арены
 	Отменить()
 	// Имя -- имя игровой арены
 	Имя() alias.АренаИмя

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

@@ -1,10 +0,0 @@
-package types
-
-// ИСражениеДействие -- интерфейс к непосредственному сражению
-type ИСражениеДействие interface {
-	ИАрена
-	// МанёврНадоУст -- устанавливает признак необходимости манёвра
-	МанёврНадоУст()
-	// ВыстрелБлок -- признак запрета на стрельбу
-	ВыстрелБлок() ИЕслиВыстрел
-}

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

@@ -0,0 +1,4 @@
+package types
+
+// ИЗдоровье -- интерфейс к здоровью танка
+type ИЗдоровье interface{}

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

@@ -0,0 +1,11 @@
+package types
+
+// ИМанёвр -- объект манёвра
+type ИМанёвр interface {
+	// УстНадо -- требование манёвра
+	УстНадо()
+	// ЕслиГотов -- возвращает признак готовности к манёвру
+	ЕслиГотов()bool
+	// Выполнить -- выполняет манёвр, если доступно
+	Выполнить()
+}

+ 20 - 0
app/lev0/types/ibattle_process.go

@@ -0,0 +1,20 @@
+package types
+
+import (
+	. "wartank/kernel/kernel_types"
+)
+
+/*
+	Интерфейс к сражению
+*/
+
+// ИДивизияВойнаДействие -- интерфейс к непосредственному сражению
+type ИСражениеПроцесс interface {
+	ИАрена
+	// Манёвр -- выполняет манёвр по требованию
+	Манёвр()ИМанёвр
+	// ЕслиКонец -- признак окончания битвы дивизий
+	ЕслиКонец() ИБезопБул
+	// Выстрел -- объект маскировки
+	Выстрел() ИВыстрел
+}

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

@@ -0,0 +1,7 @@
+package types
+
+// ИВыстрел -- объект выстрела
+type ИВыстрел interface {
+	// ЕслиБлок -- если установлена блокировка на выстрел
+	ЕслиБлок() bool
+}

+ 6 - 10
app/lev0/types/ibot.go

@@ -2,7 +2,9 @@ package types
 
 import (
 	"context"
+
 	. "wartank/app/lev0/alias"
+	. "wartank/kernel/kernel_types"
 )
 
 // ИБот -- серверный бот с реальным состоянием
@@ -21,16 +23,10 @@ type ИБот interface {
 	Сеть() ИБотСеть
 	// Пуск -- запускает бота в работу
 	Пуск()
-	// АвтоИграУст -- устанавливает признак автоматического начала игры
-	АвтоИграУст()
-	// АвтоИграСброс -- сбрасывает признак автоматического начала игры
-	АвтоИграСброс()
-	// АвтоИграЕсли -- возвращает признак автоматического начала игры
-	АвтоИграЕсли() bool
-	// ЕслиПуск -- признак, что бот работает
-	ЕслиПуск() bool
-	// Сервер -- возвращает ссылку на объект сервера
-	Сервер() ИПриложение
+	// Автозапуск -- возвращает признак автоматического начала игры
+	Автозапуск() ИБезопБулНаблюд
+	// ЕслиРабота -- признак, что бот работает
+	ЕслиРабота() bool
 	// Контекст -- возвращает контекст бота
 	Контекст() context.Context
 	// Закончить -- отменяет контекст бота

+ 0 - 30
app/lev0/types/idiv_war_action.go

@@ -1,30 +0,0 @@
-package types
-
-import (
-	"context"
-
-	. "wartank/kernel/kernel_types"
-)
-
-/*
-	Интерфейс к сражению
-*/
-
-// ИДивизияВойнаДействие -- интерфейс к непосредственному сражению
-type ИДивизияВойнаДействие interface {
-	ИАрена
-	// IsEnd -- признак окончания сражения
-	// IsEnd() *is_divwar.IsDivWar
-	// Манёвр -- выполняет манёвр по требованию
-	Манёвр()
-	// Masking -- признак запрета на стрельбу
-	// Masking() *is_repair.IsRepair
-	// Ctx -- возвращает контекст битвы
-	Ctx() context.Context
-	// CancelBattle -- вызывает контекст отмены битвы
-	CancelBattle()
-	// ЕслиКонец -- признак окончания битвы дивизий
-	ЕслиКонец() ИБезопБул
-	// ВыстрелБлок -- объект маскировки
-	ВыстрелБлок() ИБезопБул
-}

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

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

+ 31 - 40
app/lev1/health/health.go

@@ -2,7 +2,6 @@ package health
 
 import (
 	"context"
-	"fmt"
 
 	// "log"
 	// "strconv"
@@ -10,11 +9,12 @@ import (
 	"time"
 
 	. "wartank/app/lev0/types"
-	"wartank/app/lev1/health/health_repair_time"
 	"wartank/app/lev1/health/health_time"
+	"wartank/app/lev1/repair_time"
 
 	// "wartank/internal/components/sound"
 	"wartank/kernel"
+	. "wartank/kernel/helpers"
 	. "wartank/kernel/kernel_types"
 )
 
@@ -24,54 +24,45 @@ import (
 
 // Здоровье -- контроль здоровья танка
 type Здоровье struct {
-	ИДивизияВойнаДействие // FIXME:
-	fnCancel              func()
-	temp                  *health_time.HealthTime        // Изменяемое здоровье танка
-	full                  *health_time.HealthTime        // Полное здоровье танка
-	isRepair              ИБезопБул                      // Необходимость восстановления
-	repairTime            *health_repair_time.RepairTime // Время до восстановления
-	isEnd                 ИБезопБул                      // Ссылка на признак конца сражения
-	login                 string                         // Для поиска контрольных строк
-	chTick                chan int                       // Канал для ровной отправки тиков
+	ИСражениеПроцесс // FIXME:
+	fnCancel         func()
+	temp             *health_time.HealthTime // Изменяемое здоровье танка
+	full             *health_time.HealthTime // Полное здоровье танка
+	isRepair         ИБезопБул               // Необходимость восстановления
+	repairTime       *repair_time.RepairTime // Время до восстановления
+	isEnd            ИБезопБул               // Ссылка на признак конца сражения
+	login            string                  // Для поиска контрольных строк
+	chTick           chan int                // Канал для ровной отправки тиков
 	// deltaOld                    int                    // Старая дельта потери здоровья
 	// countLow                    int
 	ctxBattle context.Context // Контекст сражения
 }
 
 // НовЗдоровье -- возвращает новый *Health
-func НовЗдоровье(дивВойна ИДивизияВойнаДействие, isEnd ИБезопБул, login string) (*Здоровье, error) {
-	{ // Предусловия
-		if дивВойна == nil {
-			return nil, fmt.Errorf("NewHealth(): дивВойна is nil")
-		}
-		if isEnd == nil {
-			return nil, fmt.Errorf("NewHealth(): isEnd is nil")
-		}
-		if login == "" {
-			return nil, fmt.Errorf("NewHealth(): login is empty")
-		}
-	}
+func НовЗдоровье(проц ИСражениеПроцесс) *Здоровье {
+	Паника(проц!=nil, "НовЗдоровье(): ИСражениеПроцесс == nil")
+	логин:=проц.Бот().Имя()
 	сам := &Здоровье{
-		ИДивизияВойнаДействие: дивВойна,
-		fnCancel:   дивВойна.CancelBattle,
-		ctxBattle:  дивВойна.Ctx(),
-		temp:       health_time.NewHealthTime(),
-		full:       health_time.NewHealthTime(),
-		isRepair:   kernel.НовБезопБул(),
-		repairTime: health_repair_time.NewRepairTime(),
-		isEnd:      дивВойна.ЕслиКонец(),
-		login:      login,
-		chTick:     make(chan int, 2),
+		ИСражениеПроцесс: проц,
+		fnCancel:         проц.Отменить,
+		ctxBattle:        проц.Бот().Контекст(),
+		temp:             health_time.NewHealthTime(),
+		full:             health_time.NewHealthTime(),
+		isRepair:         kernel.НовБезопБул(),
+		repairTime:       repair_time.NewRepairTime(),
+		isEnd:            проц.ЕслиКонец(),
+		login:            логин,
+		chTick:           make(chan int, 2),
 	}
 	go сам.makeTik()
 	go сам.run()
-	return сам, nil
+	return сам
 }
 
 // Отправляет тики с заданным равным интервалом
 func (сам *Здоровье) makeTik() {
 	defer func() {
-		сам.CancelBattle()
+		сам.Отменить()
 		close(сам.chTick)
 		// log._rintf("Health.makeTick(): сражение завершёно\n")
 	}()
@@ -113,7 +104,7 @@ func (сам *Здоровье) run() {
 			// 	// log._rintf("ERRO Health.run(): при попытке найти здоровье, err=\n\t%v\n", err)
 			// }
 			сам.findRepairTime()
-			if сам.ВыстрелБлок().Получ() {
+			if сам.Выстрел().ЕслиБлок() {
 				if сам.isRepair.Получ() {
 					go сам.repair()
 				}
@@ -143,7 +134,7 @@ func (сам *Здоровье) IsDeath() bool {
 			// log._rintf("INFO Health.repair(): танк подбит\n")
 			сам.temp.Set(0)
 			сам.isEnd.Уст()
-			сам.CancelBattle()
+			сам.Отменить()
 			return true
 		}
 	}
@@ -189,7 +180,7 @@ func (сам *Здоровье) findRepairTime() {
 	if len(lstTime) < 2 {
 		// log._rintf("ERRO Health.findRepair(): при попытке получить ссылку на ремонт, strOut=\n%v\n", strOut)
 		сам.isEnd.Уст()
-		сам.CancelBattle()
+		сам.Отменить()
 		return
 	}
 	// strTime := lstTime[1]
@@ -229,13 +220,13 @@ func (сам *Здоровье) repair() {
 	if err != nil {
 		// log._rintf("ERRO Health.repair(): при выполнении GET-команды ремонта, err=\n\t%v\n", err)
 		сам.isEnd.Уст()
-		сам.CancelBattle()
+		сам.Отменить()
 		return
 	}
 	if err = сам.СтрОбновить(lstBattleOn); err != nil {
 		// log._rintf("ERRO Health.repair(): при обновлении lstBattle, err=\n\t%v\n", err)
 		сам.isEnd.Уст()
-		сам.CancelBattle()
+		сам.Отменить()
 		return
 	}
 	// sound.Repair()

+ 0 - 77
app/lev1/health/health_repair_time/health_repair_time.go

@@ -1,77 +0,0 @@
-package health_repair_time
-
-import (
-	"fmt"
-	"strconv"
-	"sync"
-)
-
-/*
-	Потокобезопасное время ожидания до восстановлении ремки
-*/
-
-// RepairTime -- потокобезопасное время до восстановления ремки
-type RepairTime struct {
-	val    int
-	valOld int // Старое время до ремки
-	block  sync.RWMutex
-}
-
-// NewRepairTime -- возвращает новый *RepairTime
-func NewRepairTime() *RepairTime {
-	return &RepairTime{}
-}
-
-// Get -- возвращает хранимое значение времени
-func (сам *RepairTime) Get() int {
-	сам.block.RLock()
-	defer сам.block.RUnlock()
-	return сам.val
-}
-
-// GetOld -- возвращает хранимое старое значение времени
-func (сам *RepairTime) GetOld() int {
-	сам.block.RLock()
-	defer сам.block.RUnlock()
-	return сам.valOld
-}
-
-// Set -- устанавливает хранимое время восстановления ремки
-func (сам *RepairTime) Set(val string) error {
-	сам.block.Lock()
-	defer сам.block.Unlock()
-	iVal, err := strconv.Atoi(val)
-	if err != nil {
-		return fmt.Errorf("RepairTime.Set(): val(%v) не число, err=%w", val, err)
-	}
-	if iVal < 0 {
-		return fmt.Errorf("RepairTime.Set(): val(%v) < 0", iVal)
-	}
-	сам.valOld = сам.val
-	сам.val = iVal
-	return nil
-}
-
-// Dec -- уменьшает на секунду время восстановления
-func (сам *RepairTime) Dec() {
-	сам.block.Lock()
-	defer сам.block.Unlock()
-	if сам.val > 0 {
-		сам.valOld = сам.val
-		сам.val--
-	}
-}
-
-// IsReady -- возвращает признак готовности восстановления
-func (сам *RepairTime) IsReady() bool {
-	сам.block.RLock()
-	defer сам.block.RUnlock()
-	return сам.val == 0
-}
-
-// IsChange -- возвращает признак изменения здоровья после присвоения
-func (сам *RepairTime) IsChange() bool {
-	сам.block.RLock()
-	defer сам.block.RUnlock()
-	return сам.val == сам.valOld
-}

+ 0 - 0
app/lev2/arena_death/death_worker/death_on/manevr/ismanevr/ismanevr.go → app/lev1/manevr/ismanevr/ismanevr.go


+ 198 - 0
app/lev1/manevr/manevr.go

@@ -0,0 +1,198 @@
+package manevr
+
+import (
+	"context"
+
+	// "log"
+	"strings"
+	"time"
+
+	"wartank/app/lev1/repair_time"
+	"wartank/kernel"
+	// "wartank/internal/components/sound"
+	. "wartank/app/lev0/types"
+	. "wartank/kernel/kernel_types"
+)
+
+/*
+	Пытается маневрировать после выстрела
+*/
+
+// манёвр -- маневрирует после выстрела
+type манёвр struct {
+	ИСражениеПроцесс // FIXME:
+	лог              ИЯдроЛог
+	isEnd            ИБезопБул
+	ctxEnd           context.Context
+	еслиНадо         ИБезопБул
+	еслиГотов        ИБезопБул               // Возможность выполнить манёвр
+	manevrTime       *repair_time.RepairTime // Время до восстановления манёвра
+	chTick           chan int                // Тики для поиска маневра
+}
+
+// НовМанёвр -- возвращает новый манёвр
+func НовМанёвр(проц ИСражениеПроцесс) ИМанёвр {
+	лог := kernel.НовЛог("манёвр")
+	лог.Паника(проц != nil, "НовМанёвр(): ИСражениеПроцесс==nil")
+	сам := &манёвр{
+		ИСражениеПроцесс: проц,
+		лог:              лог,
+		ctxEnd:           проц.Контекст(),
+		еслиНадо:         kernel.НовБезопБул(),
+		isEnd:            проц.ЕслиКонец(),
+		еслиГотов:        kernel.НовБезопБул(),
+		manevrTime:       repair_time.NewRepairTime(),
+		chTick:           make(chan int, 1),
+	}
+	_ = сам.manevrTime.Set("0") // При запуске боя есть возможность маневрировать
+	go сам.makeTick()
+	go сам.run()
+	return сам
+}
+
+// ЕслиГотов -- возвращает признак готовности к манёвру
+func (сам *манёвр) ЕслиГотов() bool {
+	return сам.еслиГотов.Получ()
+}
+
+// УстНадо -- устанавливает требование манёвра
+func (сам *манёвр) УстНадо() {
+	сам.еслиНадо.Уст()
+}
+
+// Генерирует тик для уменьшения времени ожидания восстановления возможности манёвра
+func (сам *манёвр) makeTick() {
+	defer func() {
+		close(сам.chTick)
+		// log._rintf("манёвр.makeTick(): сражение завершено\n")
+	}()
+	for {
+		select {
+		case <-сам.ctxEnd.Done():
+			return
+		default:
+			if сам.manevrTime.Get() == 0 {
+				сам.chTick <- 1
+			}
+
+			сам.manevrTime.Dec()
+			time.Sleep(time.Second * 1)
+		}
+	}
+}
+
+// Рабочий цикл поиска маневра (~)
+func (сам *манёвр) run() {
+	for range сам.chTick {
+		if !сам.еслиГотов.Получ() {
+			continue
+		}
+		сам.findManevrTime()
+	}
+}
+
+// Ищет время для манёвра
+func (сам *манёвр) findManevrTime() {
+	var (
+		еслиНайдено bool
+		ind         int
+		lstBattleOn = сам.СписПолучить()
+		стрВых      string
+	)
+	for ind, стрВых = range lstBattleOn {
+		// <a href="pve?4-88.ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>5 секунд</span></span></a>
+		if strings.Contains(стрВых, `-currentControl-maneuverLink`) {
+			еслиНайдено = true
+			break
+		}
+	}
+	if !еслиНайдено { // Или манёвр успел восстановиться, или конец сражения
+		if strings.Contains(стрВых, `<span>Маневр</span>`) {
+			_ = сам.manevrTime.Set("0")
+			time.Sleep(time.Second * 1)
+			return
+		}
+		if сам.isEnd.Получ() {
+			time.Sleep(time.Second * 1)
+			return
+		}
+		сам.лог.Внимание("findManevrTime(): ошибка в поиске времени манёвра, стрВых=%v", стрВых)
+		time.Sleep(time.Second * 1)
+		return
+	}
+	{ // Найти время манёвра
+		lstTime := strings.Split(стрВых, `ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>`)
+		if len(lstTime) != 2 {
+			сам.лог.Ошибка("манёвр.findManevrTime(): нет двух полей во времени ожидания инд=%v\n\n%v\n%v\n%v",
+			ind,
+			lstBattleOn[ind-1],
+			стрВых,
+			lstBattleOn[ind+1],
+		)
+			сам.еслиГотов.Сброс()
+			time.Sleep(time.Second * 1)
+			return
+		}
+		strTime := lstTime[1]
+		lstTime = strings.Split(strTime, ` секунд</span></span></a>`)
+		strTime = lstTime[0]
+		if err := сам.manevrTime.Set(strTime); err != nil {
+			сам.лог.Ошибка("манёвр.findManevrTime(): при обновлении времени ожидания манёвра, ош=\n\t%v", err)
+			сам.еслиГотов.Сброс()
+			time.Sleep(time.Second * 1)
+			return
+		}
+	}
+	сам.еслиГотов.Уст()
+	сам.лог.Инфо("манёвр.findManevrTime(): до манёвра, время=%v", сам.manevrTime.Get())
+}
+
+// Выполнить -- принудительный манёвр по требованию
+func (сам *манёвр) Выполнить() {
+	var (
+		еслиНайдено = false
+		lstBattleOn = сам.СписПолучить()
+		strOut      = ""
+	)
+	if !сам.еслиГотов.Получ() {
+		time.Sleep(time.Second * 1)
+		return
+	}
+	for _, strOut = range lstBattleOn {
+		// <a href="pve?4-21.ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>Маневр</span></span></a>
+		if strings.Contains(strOut, `<span>Маневр</span>`) {
+			еслиНайдено = true
+			break
+		}
+	}
+	if !еслиНайдено { // Либо ждём восстановления манёвра, либо сражение закончилось
+		сам.еслиГотов.Сброс()
+		time.Sleep(time.Second * 1)
+		return
+	}
+	{ // Попытка манёвра
+		lstLink := strings.Split(strOut, `<a href="`)
+		strLink := lstLink[1]
+		lstLink = strings.Split(strLink, `" class="simple-but blue"><span><span>Маневр</span></span></a>`)
+		strLink = "https://wartank.ru/" + lstLink[0]
+		lstBattleOn, err := сам.Сеть().Get(strLink)
+		if err != nil {
+			сам.лог.Ошибка("манёвр.Выполнить(): при выполнении GET-команды маневра, ош=\n\t%v", err)
+			сам.еслиГотов.Сброс()
+			time.Sleep(time.Second * 1)
+			return
+		}
+		if err = сам.СтрОбновить(lstBattleOn); err != nil {
+			сам.лог.Ошибка("манёвр.Выполнить(): при обновлении lstBattle, ош=\n\t%v", err)
+			сам.еслиГотов.Сброс()
+			time.Sleep(time.Second * 1)
+			return
+		}
+		// sound.манёвр()
+	}
+}
+
+// IsReady -- возвращает готовность манёвра
+func (сам *манёвр) IsReady() bool {
+	return сам.manevrTime.IsReady()
+}

+ 6 - 6
app/lev2/arena_battle/battle_worker/battle_worker/health/repair_time/repair_time.go → app/lev1/repair_time/repair_time.go

@@ -22,8 +22,8 @@ func NewRepairTime() *RepairTime {
 	return &RepairTime{}
 }
 
-// Получ -- возвращает хранимое значение времени
-func (сам *RepairTime) Получ() int {
+// Get -- возвращает хранимое значение времени
+func (сам *RepairTime) Get() int {
 	сам.block.RLock()
 	defer сам.block.RUnlock()
 	return сам.val
@@ -62,15 +62,15 @@ func (сам *RepairTime) Dec() {
 	}
 }
 
-// ЕслиГотово -- возвращает признак готовности восстановления
-func (сам *RepairTime) ЕслиМожно() bool {
+// IsReady -- возвращает признак готовности восстановления
+func (сам *RepairTime) IsReady() bool {
 	сам.block.RLock()
 	defer сам.block.RUnlock()
 	return сам.val == 0
 }
 
-// ЕслиИзменилось -- возвращает признак изменения здоровья после присвоения
-func (сам *RepairTime) ЕслиИзменилось() bool {
+// IsChange -- возвращает признак изменения здоровья после присвоения
+func (сам *RepairTime) IsChange() bool {
 	сам.block.RLock()
 	defer сам.block.RUnlock()
 	return сам.val == сам.valOld

+ 0 - 0
app/lev2/arena_battle/battle_worker/battle_worker/shot/damage/damage.go → app/lev1/shot/damage/damage.go


+ 45 - 43
app/lev3/bot/angar/division/div_war/div_war_on/shot/shot.go → app/lev1/shot/shot.go

@@ -2,7 +2,6 @@ package shot
 
 import (
 	"context"
-	"fmt"
 
 	// "log"
 	"strconv"
@@ -10,10 +9,12 @@ import (
 	"time"
 
 	. "wartank/app/lev0/types"
-	"wartank/app/lev2/arena_division/div_war/div_war_on/shot/damage"
-	"wartank/app/lev2/arena_division/div_war/div_war_on/shot_time"
+	"wartank/app/lev1/shot/damage"
+	"wartank/app/lev1/shot/shot_time"
+	"wartank/kernel"
 	// "wartank/internal/components/sound"
 	"wartank/app/lev0/alias"
+	. "wartank/kernel/helpers"
 	. "wartank/kernel/kernel_types"
 )
 
@@ -26,50 +27,51 @@ import (
 	Второй параметр меняется медленно (в зависимости от количества очков после выстрела)
 */
 
-// Shot -- объект выстрела
-type Shot struct {
-	ИДивизияВойнаДействие                     // FIXME:
-	recharge              *shot_time.ShotTime // Сколько времени нужно для полной перезарядки
-	damage                *damage.Damage      // Урон от выстрела с памятью
-	damageSum             alias.Урон          // Суммарный урон
-	isEnd                 ИБезопБул           // Признак конца сражения
-	login                 string              // Логин для поиска контрольных строк
-	chTick                chan int            // Тик для выстрела
-	ctxEnd                context.Context     // Признак окончания сражения
+// выстрел -- объект выстрела
+type выстрел struct {
+	ИСражениеПроцесс                     // FIXME:
+	recharge         *shot_time.ShotTime // Сколько времени нужно для полной перезарядки
+	damage           *damage.Damage      // Урон от выстрела с памятью
+	damageSum        alias.Урон          // Суммарный урон
+	isEnd            ИБезопБул           // Признак конца сражения
+	еслиБлок         ИБезопБул           // Признак блокировки выстрела
+	login            string              // Логин для поиска контрольных строк
+	chTick           chan int            // Тик для выстрела
+	ctxEnd           context.Context     // Признак окончания сражения
 }
 
-// NewShot -- возвращает новый *Shot
-func NewShot(divWar ИДивизияВойнаДействие, login string) (*Shot, error) {
-	{ // Предусловия
-		if divWar == nil {
-			return nil, fmt.Errorf("NewShot(): battle is nil")
-		}
-		if login == "" {
-			return nil, fmt.Errorf("NewShot(): login is empty")
-		}
-	}
-	сам := &Shot{
-		ИДивизияВойнаДействие: divWar,
-		ctxEnd:   divWar.Ctx(),
-		recharge: shot_time.NewShotTime(),
-		damage:   damage.NewDamage(),
-		isEnd:    divWar.ЕслиКонец(),
-		login:    login,
-		chTick:   make(chan int, 2),
+// НовВыстрел -- возвращает новый выстрел
+func НовВыстрел(проц ИСражениеПроцесс) ИВыстрел {
+	Паника(проц != nil, "НовВыстрел(): ИСражениеПроцесс == nil")
+	логинТанк := проц.Бот().Имя()
+	сам := &выстрел{
+		ИСражениеПроцесс: проц,
+		ctxEnd:           проц.Контекст(),
+		recharge:         shot_time.NewShotTime(),
+		damage:           damage.NewDamage(),
+		еслиБлок:         kernel.НовБезопБул(),
+		isEnd:            проц.ЕслиКонец(),
+		login:            логинТанк,
+		chTick:           make(chan int, 2),
 	}
 	// Установить время перезарядки
 	сам.recharge.Set(6800)
 	go сам.makeTick()
 	go сам.run()
-	return сам, nil
+	return сам
+}
+
+// ЕслиБлок -- возвращает признак блокировки выстрела
+func (сам *выстрел) ЕслиБлок() bool {
+	return сам.еслиБлок.Получ()
 }
 
 // Генерирует тики, когда можно стрелять
-func (сам *Shot) makeTick() {
+func (сам *выстрел) makeTick() {
 	defer func() {
 		сам.isEnd.Уст()
 		close(сам.chTick)
-		сам.CancelBattle()
+		сам.Отменить()
 		// log._rintf("Shot.makeTick(): сражение завершёно\n")
 	}()
 	countMasking := 0
@@ -81,7 +83,7 @@ func (сам *Shot) makeTick() {
 			if сам.isEnd.Получ() { // Битва закончилась
 				return
 			}
-			switch сам.ВыстрелБлок().Получ() { // Проверить запрет на стрельбу при слабом здоровье
+			switch сам.еслиБлок.Получ() { // Проверить запрет на стрельбу при слабом здоровье
 			case true:
 				// log._rintf("WARN Shot.run(): запрет на выстрел\n")
 				countMasking++
@@ -104,7 +106,7 @@ func (сам *Shot) makeTick() {
 }
 
 // Цикл выстрела (в отдельном потоке)
-func (сам *Shot) run() {
+func (сам *выстрел) run() {
 	for {
 		select {
 		case <-сам.ctxEnd.Done():
@@ -120,7 +122,7 @@ func (сам *Shot) run() {
 // Обновляет возможность выстрела (~)
 //
 //	Вызывается из отдельного потока
-func (сам *Shot) shot() {
+func (сам *выстрел) shot() {
 	сам.Обновить()
 	var (
 		strOut      string
@@ -138,7 +140,7 @@ func (сам *Shot) shot() {
 	if !еслиНайдено {
 		// log._rintf("WARN Shot.shot(): не найдены ссылка на выстрел\n")
 		сам.isEnd.Уст()
-		сам.CancelBattle()
+		сам.Отменить()
 		return
 	}
 	lstLink := strings.Split(strOut, `<a href="`)
@@ -149,13 +151,13 @@ func (сам *Shot) shot() {
 	if err != nil {
 		// log._rintf("ERRO Shot.shot(): при исполнении GET-команды выстрела обычным снарядом, err=\n\t%v\n", err)
 		сам.isEnd.Уст()
-		сам.CancelBattle()
+		сам.Отменить()
 		return
 	}
 	if err = сам.СтрОбновить(lstBattle); err != nil {
 		// log._rintf("ERRO Shot.shot(): при обновлении lstBattle, err=\n\t%v\n", err)
 		сам.isEnd.Уст()
-		сам.CancelBattle()
+		сам.Отменить()
 		return
 	}
 	// sound.Shot()
@@ -163,7 +165,7 @@ func (сам *Shot) shot() {
 }
 
 // Ищет урон от выстрела
-func (сам *Shot) findDamage() {
+func (сам *выстрел) findDamage() {
 	var (
 		ind         int
 		еслиНайдено bool
@@ -213,7 +215,7 @@ func (сам *Shot) findDamage() {
 }
 
 // setDamage -- обновляет время перезарядки в зависимости от произведённого урона
-func (сам *Shot) setDamage(val alias.Урон) {
+func (сам *выстрел) setDamage(val alias.Урон) {
 	сам.damage.Set(val)
 	switch сам.damage.Result() {
 	case "none":
@@ -226,6 +228,6 @@ func (сам *Shot) setDamage(val alias.Урон) {
 }
 
 // IsEnd -- возвращает объект разрешения стрельбы
-func (сам *Shot) IsEnd() ИБезопБул {
+func (сам *выстрел) IsEnd() ИБезопБул {
 	return сам.isEnd
 }

+ 3 - 2
app/lev2/arena_division/div_war/div_war_on/shot_time/shot_time.go → app/lev1/shot/shot_time/shot_time.go

@@ -1,9 +1,10 @@
 package shot_time
 
 import (
-	"log"
 	"sync"
 
+	"github.com/sirupsen/logrus"
+
 	"wartank/app/lev0/alias"
 )
 
@@ -68,7 +69,7 @@ func (сам *ShotTime) Set(val alias.МилСек) {
 	сам.block.Lock()
 	defer сам.block.Unlock()
 	if val > 500_000 {
-		log.Printf("ShotTime.Set(): слишком большое значение, val=%v\n", val)
+		logrus.WithField("val", val).Error("ShotTime.Set(): отрицательное значение")
 		return
 	}
 	сам.val = val

+ 0 - 0
app/lev2/arena_battle/battle_worker/battle_worker/battle_sound/is_sound_play/is_sound_play.go → app/lev1/sound/is_sound_play/is_sound_play.go


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

@@ -11,7 +11,7 @@ import (
 	"wartank/app/lev2/arena/arena_net"
 	"wartank/app/lev2/arena/arena_string"
 	"wartank/app/lev2/arena/down_time"
-	. "wartank/pkg/helpers"
+	. "wartank/kernel/helpers"
 )
 
 // АренаКонфиг -- конфигурация арены

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

@@ -9,8 +9,8 @@ import (
 	"wartank/app/lev1/web_log"
 	"wartank/app/lev2/arena/arena_context/arena_state"
 	"wartank/kernel"
+	. "wartank/kernel/helpers"
 	. "wartank/kernel/kernel_types"
-	. "wartank/pkg/helpers"
 )
 
 // АренаКонтекст -- контекст арены

+ 1 - 1
app/lev2/arena_base/arena_base.go

@@ -656,7 +656,7 @@ func (сам *АренаБаза) checkBankProduct() {
 	ош := сам.банк.ОбратВремяУст("01:00")
 	if ош != nil {
 		log.Printf("ERRO Base.checkBankProduct(): при установке обратного времени ожидания банка, err=\n\t%v\n", ош)
-		сам.бот.Сервер().Отменить()
+		сам.Отменить()
 	}
 }
 

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

@@ -3,7 +3,7 @@ package battle_sound
 import (
 	"time"
 	"wartank/app/lev1/sound"
-	"wartank/app/lev2/arena_battle/battle_worker/battle_worker/battle_sound/is_sound_play"
+	"wartank/app/lev1/sound/is_sound_play"
 )
 
 /*

+ 15 - 30
app/lev2/arena_battle/battle_worker/battle_worker/battle_worker.go

@@ -6,10 +6,9 @@ import (
 
 	. "wartank/app/lev0/types"
 	"wartank/app/lev2/arena"
-	"wartank/app/lev2/arena_battle/battle_worker/battle_worker/health"
-	"wartank/app/lev2/arena_battle/battle_worker/battle_worker/manevr"
-	"wartank/app/lev2/arena_battle/battle_worker/battle_worker/shot"
-	"wartank/app/lev2/arena_battle/battle_worker/battle_worker/shot/is_shot"
+	"wartank/app/lev1/health"
+	"wartank/app/lev1/manevr"
+	"wartank/app/lev1/shot"
 )
 
 /*
@@ -23,15 +22,14 @@ type СражениеДействие struct {
 	кнт        context.Context // Контекст сражения
 	фнОтменить func()          // Функция отмены сражения
 
-	выстрел     *shot.Выстрел    // Объект выстрела
-	здоровье    *health.Здоровье // Текущее здоровье танка
-	манёвр      *manevr.Манёвр   // Возможность маневрирования
+	выстрел     ИВыстрел    // Объект выстрела
+	здоровье    ИЗдоровье // Текущее здоровье танка
+	манёвр      ИМанёвр   // Возможность маневрирования
 	логин       string
-	еслиВыстрел *is_shot.IsShot // Признак необходимости маскирования (запрет стрельбы, когда слабое здоровье)
 }
 
 // НовСражениеДействие -- возвращает новый *BattleOn
-func НовСражениеДействие(конт ИБотКонтекст, бот ИБот) *СражениеДействие {
+func НовСражениеДействие(конт ИБотКонтекст, бот ИБот) ИСражениеПроцесс {
 	// Ограничить время сражения бота
 	кнтСражение, фнОтменить := context.WithTimeout(бот.Контекст(), time.Second*305)
 	сам := &СражениеДействие{
@@ -39,7 +37,6 @@ func НовСражениеДействие(конт ИБотКонтекст, 
 		кнт:         кнтСражение,
 		фнОтменить:  фнОтменить,
 		логин:       бот.Имя(),
-		еслиВыстрел: is_shot.NewIsShot(),
 	}
 	аренаКонфиг := arena.АренаКонфиг{
 		Бот_:         сам.бот,
@@ -50,10 +47,11 @@ func НовСражениеДействие(конт ИБотКонтекст, 
 	}
 	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
 	go сам.пуск()
-	_ = ИСражениеДействие(сам)
 	return сам
 }
 
+
+
 // запускает сражение
 func (сам *СражениеДействие) пуск() {
 	defer func() {
@@ -61,22 +59,9 @@ func (сам *СражениеДействие) пуск() {
 		// log._rintf("BattleOn.run(): сражение завершено\n")
 	}()
 	{ // Подготовка к сражению
-		var err error
-		сам.выстрел, err = shot.НовВыстрел(сам) // Объект выстрела
-		if err != nil {
-			// log._rintf("ERRO BattleOn.Run(): при создании выстрела танка, err=\n\t%v\n", err)
-			return
-		}
-		сам.здоровье, err = health.НовЗдоровье(сам)
-		if err != nil {
-			// log._rintf("ERRO BattleOn.Run(): при создании здоровья танка, err=\n\t%v\n", err)
-			return
-		}
-		сам.манёвр, err = manevr.НовМанёвр(сам)
-		if err != nil {
-			// log._rintf("ERRO BattleOn.Run(): при создании маневра танка, err=\n\t%v\n", err)
-			return
-		}
+		сам.выстрел = shot.НовВыстрел(сам) // Объект выстрела
+		сам.здоровье = health.НовЗдоровье(сам)
+		сам.манёвр = manevr.НовМанёвр(сам)
 	}
 	// Рабочий цикл сражения
 	<-сам.кнт.Done()
@@ -89,9 +74,9 @@ func (сам *СражениеДействие) МанёврНадоУст() {
 	сам.манёвр.УстНадо()
 }
 
-// ВыстрелБлок -- признак запрета стрельбы при слабом здоровье
-func (сам *СражениеДействие) ВыстрелБлок() ИЕслиВыстрел {
-	return сам.еслиВыстрел
+// Выстрел -- возвращает объект выстрела
+func (сам *СражениеДействие) Выстрел() ИВыстрел {
+	return сам.выстрел
 }
 
 // Кнт -- возвращает контекст отмены сражения

+ 0 - 48
app/lev2/arena_battle/battle_worker/battle_worker/battlesound/battlesound.go

@@ -1,48 +0,0 @@
-package battle_sound
-
-import (
-	"time"
-	"wartank/app/lev1/sound"
-	"wartank/app/lev2/arena_battle/battle_worker/battle_worker/battle_sound/is_sound_play"
-)
-
-/*
-	Выполняет контроль за запуском одной озвучки битвы
-*/
-
-// BattleSound -- контроль одного раза запуска звука битвы
-type BattleSound struct {
-	isPlay *is_sound_play.IsPlay
-}
-
-// NewBattleSound -- возвращает новый  *BattleSound
-func NewBattleSound() *BattleSound {
-	return &BattleSound{
-		isPlay: is_sound_play.NewIsPlay(),
-	}
-}
-
-// Play -- играет музончик, если можно
-func (сам *BattleSound) Play() {
-	if сам.isPlay.Get() {
-		return
-	}
-	go сам.play()
-}
-
-// Проигрывает экслюзивно в отдельном потоке звук
-func (сам *BattleSound) play() {
-	сам.isPlay.Set()
-	val := 7
-	for val > 0 {
-		sound.Battle()
-		val--
-		time.Sleep(time.Second * 1)
-	}
-	val = 600 // Пауза для блокировки повторного включения начатой битвы
-	for val >= 0 {
-		val--
-		time.Sleep(time.Second * 1)
-	}
-	сам.isPlay.Reset()
-}

+ 0 - 43
app/lev2/arena_battle/battle_worker/battle_worker/manevr/is_manevr/is_manevr.go

@@ -1,43 +0,0 @@
-package is_manevr
-
-import (
-	"sync"
-)
-
-/*
-	Потокобезопасный признак внешнего разрешения манёвра
-*/
-
-// IsManevr -- потокобезопасный признак внешнего разрешения манёвра
-type IsManevr struct {
-	val   bool
-	block sync.RWMutex
-}
-
-// NewIsManevr -- возвращает новый *IsManevr
-func NewIsManevr() *IsManevr {
-	return &IsManevr{
-		val: true,
-	}
-}
-
-// Get -- возвращает хранимое состояние
-func (сам *IsManevr) Get() bool {
-	сам.block.RLock()
-	defer сам.block.RUnlock()
-	return сам.val
-}
-
-// Set -- устанавливает хранимое состояние
-func (сам *IsManevr) Set() {
-	сам.block.Lock()
-	defer сам.block.Unlock()
-	сам.val = true
-}
-
-// Сброс -- сбрасывает хранимое состояние
-func (сам *IsManevr) Сброс() {
-	сам.block.Lock()
-	defer сам.block.Unlock()
-	сам.val = false
-}

+ 0 - 166
app/lev2/arena_battle/battle_worker/battle_worker/manevr/manevr.go

@@ -1,166 +0,0 @@
-package manevr
-
-import (
-	"fmt"
-	"log"
-	"strings"
-	"time"
-	"wartank/app/lev2/arena_battle/battle_worker/battle_worker/health/repair_time"
-	"wartank/app/lev2/arena_battle/battle_worker/battle_worker/manevr/is_manevr"
-	// "wartank/internal/components/sound"
-	. "wartank/app/lev0/types"
-)
-
-/*
-	Пытается маневрировать после выстрела
-*/
-
-// Манёвр -- маневрирует после выстрела
-type Манёвр struct {
-	ИСражениеДействие                         // FIXME:
-	еслиМанёврНадо    *is_manevr.IsManevr     // Требование выполнить манёвр
-	времяЖдать        *repair_time.RepairTime // Время до восстановления манёвра
-	chTick            chan int                // Тики для поиска маневра
-}
-
-// НовМанёвр -- возвращает новый *Manevr
-func НовМанёвр(действие ИСражениеДействие) (*Манёвр, error) {
-	{ // Предусловия
-		if действие == nil {
-			return nil, fmt.Errorf("НовМанёвр(): действие==nil")
-		}
-	}
-	сам := &Манёвр{
-		ИСражениеДействие: действие,
-		еслиМанёврНадо:    is_manevr.NewIsManevr(),
-		времяЖдать:        repair_time.NewRepairTime(),
-		chTick:            make(chan int, 1),
-	}
-	_ = сам.времяЖдать.Set("0") // При запуске боя есть возможность маневрировать
-	go сам.makeTick()
-	go сам.пуск()
-	return сам, nil
-}
-
-// Генерирует тик для уменьшения времени ожидания восстановления возможности манёвра
-func (сам *Манёвр) makeTick() {
-	defer func() {
-		close(сам.chTick)
-		// log._rintf("Manevr.makeTick(): сражение завершено\n")
-	}()
-	for {
-		select {
-		case <-сам.Контекст().Done():
-			return
-		default:
-			if сам.времяЖдать.Получ() <= 0 {
-				сам.chTick <- 1
-			}
-			сам.времяЖдать.Dec()
-			time.Sleep(time.Second * 1)
-		}
-	}
-}
-
-// Рабочий цикл поиска маневра (~)
-func (сам *Манёвр) пуск() {
-	for range сам.chTick {
-		if !сам.еслиМанёврНадо.Get() { // Если нет требования манёвра -- пропускаем
-			continue
-		}
-		сам.манёвр()
-		сам.времяМанёврНайти() // Найти время после манёвра
-	}
-}
-
-// Ищет время для манёвра
-func (сам *Манёвр) времяМанёврНайти() {
-	var (
-		еслиНайдено bool
-		ind         int
-		lstBattleOn = сам.СписПолучить()
-		strOut      string
-	)
-	for ind, strOut = range lstBattleOn {
-		// <a href="pve?4-88.ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>5 секунд</span></span></a>
-		if strings.Contains(strOut, `-currentControl-maneuverLink`) {
-			еслиНайдено = true
-			break
-		}
-	}
-	if !еслиНайдено { // Или манёвр успел восстановиться, или конец сражения
-		if strings.Contains(strOut, `<span>Маневр</span>`) {
-			_ = сам.времяЖдать.Set("0")
-			return
-		}
-		log.Printf("Манёвр.времяМанёврНайти(): не найдено время манёвра")
-		сам.Отменить()
-		return
-	}
-	{ // Найти время манёвра
-		lstTime := strings.Split(strOut, `ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>`)
-		if len(lstTime) != 2 {
-			log.Printf("Manevr.findManevrTime(): нет двух полей во времени ожидания, ind=%v, lstBattleOn[-1]=%v, lstBattleOn[ind]=%v, lstBattleOn[+1]=%v",
-				ind, lstBattleOn[ind-1], strOut, lstBattleOn[ind+1])
-			сам.Отменить()
-			return
-		}
-		strTime := lstTime[1]
-		lstTime = strings.Split(strTime, ` секунд</span></span></a>`)
-		strTime = lstTime[0]
-		if err := сам.времяЖдать.Set(strTime); err != nil {
-			log.Println("Manevr.findManevrTime(): при обновлении времени ожидания манёвра")
-			сам.Отменить()
-			return
-		}
-	}
-	log.Printf("Manevr.findManevrTime(): до манёвра %v\n", сам.времяЖдать.Получ())
-}
-
-// Манёвр по возможности
-func (сам *Манёвр) манёвр() {
-	var (
-		еслиНайдено = false
-		lstBattleOn = сам.СписПолучить()
-		strOut      = ""
-	)
-	for _, strOut = range lstBattleOn {
-		// <a href="pve?4-21.ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>Маневр</span></span></a>
-		if strings.Contains(strOut, `<span>Маневр</span>`) {
-			еслиНайдено = true
-			break
-		}
-	}
-	if !еслиНайдено { // Либо ждём восстановления манёвра, либо сражение закончилось
-		return
-	}
-	{ // Попытка манёвра
-		lstLink := strings.Split(strOut, `<a href="`)
-		strLink := lstLink[1]
-		lstLink = strings.Split(strLink, `" class="simple-but blue"><span><span>Маневр</span></span></a>`)
-		strLink = "https://wartank.ru/" + lstLink[0]
-		lstBattleOn, err := сам.Сеть().Get(strLink)
-		if err != nil {
-			log.Printf("Manevr.Manevr(): при выполнении GET-команды маневра, err=\n\t%v\n", err)
-			сам.Отменить()
-			return
-		}
-		if err = сам.СтрОбновить(lstBattleOn); err != nil {
-			log.Printf("Manevr.Manevr(): при обновлении lstBattle, err=\n\t%v\n", err)
-			сам.Отменить()
-			return
-		}
-		// sound.Manevr()
-	}
-	сам.еслиМанёврНадо.Сброс()
-}
-
-// ЕслиГотов -- возвращает готовность манёвра
-func (сам *Манёвр) ЕслиГотов() bool {
-	return сам.времяЖдать.ЕслиМожно()
-}
-
-// УстНадо -- устанавливает признак необходимости манёвра
-func (сам *Манёвр) УстНадо() {
-	сам.еслиМанёврНадо.Set()
-}

+ 0 - 90
app/lev2/arena_battle/battle_worker/battle_worker/shot/shot.go

@@ -1,90 +0,0 @@
-package shot
-
-import (
-	"fmt"
-	// "log"
-	"strings"
-	"time"
-
-	. "wartank/app/lev0/types"
-)
-
-/*
-	Исходник предоставляет выстрел со свойствами:
-		- время до выстрела
-		- длительность перезарядки
-
-	Первый параметр постоянно изменяется (после выстрела восстанавливается)
-	Второй параметр меняется медленно (в зависимости от количества очков после выстрела)
-*/
-
-// Выстрел -- объект выстрела
-type Выстрел struct {
-	ИСражениеДействие          // FIXME!!!
-	канТик            chan int // Тик для выстрела
-	выстрелСчёт       int      // Счётчик выстрелов для сервера
-}
-
-// НовВыстрел -- возвращает новый *Shot
-func НовВыстрел(действие ИСражениеДействие) (*Выстрел, error) {
-	{ // Предусловия
-		if действие == nil {
-			return nil, fmt.Errorf("НовВыстрел(): действие==nil")
-		}
-	}
-	сам := &Выстрел{
-		ИСражениеДействие: действие,
-		выстрелСчёт:       1,
-		канТик:            make(chan int, 2),
-	}
-	go сам.делайТик()
-	go сам.пуск()
-	return сам, nil
-}
-
-// Генерирует тики, когда можно стрелять
-func (сам *Выстрел) делайТик() {
-	defer func() {
-		close(сам.канТик)
-		// log._rintf("Shot.makeTick(): сражение завершёно\n")
-	}()
-	for {
-		select {
-		case <-сам.Контекст().Done():
-			return
-		default:
-			сам.канТик <- 1 // Первый выстрел, потом спать по таймингу
-			// log._rintf("INFO Shot.run() перезарядка=%v msec\n", recharge)
-			// Если идёт перезарядка -- постепенно обнуляем время ожидания
-			time.Sleep(time.Millisecond * 6800)
-		}
-	}
-}
-
-// Цикл выстрела (в отдельном потоке)
-func (сам *Выстрел) пуск() {
-	for range сам.канТик {
-		// Стрелять можно, стандартное ожидание
-		сам.выстрел()
-	}
-}
-
-// Обновляет возможность выстрела (~)
-//
-//	Вызывается из отдельного потока
-func (сам *Выстрел) выстрел() {
-	сам.Сеть().Обновить()
-
-	// <a href="pve?6-26.ILinkListener-currentControl-attackRegularShellLink" class="simple-but gray"><span><span>ОБЫЧНЫЕ</span></span></a>
-
-	strLink := "https://wartank.ru/pve?6-{count}.ILinkListener-currentControl-attackRegularShellLink"
-	strLink = strings.ReplaceAll(strLink, "{count}", fmt.Sprint(сам.выстрелСчёт))
-	сам.выстрелСчёт++
-	_, err := сам.Сеть().Get(strLink)
-	if err != nil {
-		// log._rintf("ERRO Shot.shot(): при исполнении GET-команды выстрела обычным снарядом, err=\n\t%v\n", err)
-		return
-	}
-	сам.МанёврНадоУст()
-	// sound.Shot()
-}

+ 0 - 76
app/lev2/arena_battle/battle_worker/battle_worker/shottime/shottime.go

@@ -1,76 +0,0 @@
-package shottime
-
-import (
-	"sync"
-
-	"github.com/sirupsen/logrus"
-
-	"wartank/app/lev0/alias"
-)
-
-/*
-	Содержит время до выстрела
-*/
-
-// ShotTime -- время до выстрела
-type ShotTime struct {
-	val   alias.МилСек // Время в мсек
-	block sync.RWMutex
-}
-
-// NewShotTime -- возвращает новый ShotTime
-func NewShotTime() *ShotTime {
-	return &ShotTime{}
-}
-
-// Get -- возвращает хранимое время до выстрела
-func (сам *ShotTime) Get() alias.МилСек {
-	сам.block.RLock()
-	defer сам.block.RUnlock()
-	return сам.val
-}
-
-// Dec5 -- уменьшает время до выстрела на 5 мсек
-func (сам *ShotTime) Dec5() {
-	сам.block.Lock()
-	defer сам.block.Unlock()
-	сам.val -= 5
-	if сам.val > 500_000 {
-		сам.val = 0
-	}
-}
-
-// Dec30 -- уменьшает время до выстрела на 30 мсек
-func (сам *ShotTime) Dec30() {
-	сам.block.Lock()
-	defer сам.block.Unlock()
-	сам.val -= 30
-	if сам.val > 500_000 {
-		сам.val = 0
-	}
-}
-
-// Inc210 -- увеличивает время до выстрела на 210 мсек
-func (сам *ShotTime) Inc210() {
-	сам.block.Lock()
-	defer сам.block.Unlock()
-	сам.val += 210
-}
-
-// IsZero -- возвращает истину, если значение обнулено
-func (сам *ShotTime) IsZero() bool {
-	сам.block.RLock()
-	defer сам.block.RUnlock()
-	return сам.val == 0
-}
-
-// Set -- устанавливает значение по требованию
-func (сам *ShotTime) Set(val alias.МилСек) {
-	сам.block.Lock()
-	defer сам.block.Unlock()
-	if val > 500_000 {
-		logrus.WithField("val", val).Error("ShotTime.Set(): отрицательное значение")
-		return
-	}
-	сам.val = val
-}

+ 14 - 31
app/lev2/arena_battle/battle_worker/battleon/battleon.go

@@ -6,11 +6,9 @@ import (
 
 	. "wartank/app/lev0/types"
 	"wartank/app/lev2/arena"
-	"wartank/app/lev2/arena_battle/battle_worker/battle_worker/health"
-	"wartank/app/lev2/arena_battle/battle_worker/battle_worker/manevr"
-	"wartank/app/lev2/arena_battle/battle_worker/battle_worker/shot"
-	"wartank/app/lev2/arena_battle/battle_worker/battle_worker/shot/is_shot"
-	. "wartank/kernel/kernel_types"
+	"wartank/app/lev1/health"
+	"wartank/app/lev1/manevr"
+	"wartank/app/lev1/shot"
 )
 
 /*
@@ -24,23 +22,22 @@ type СражениеДействие struct {
 	кнт        context.Context // Контекст сражения
 	фнОтменить func()          // Функция отмены сражения
 
-	выстрел     *shot.Выстрел    // Объект выстрела
-	здоровье    *health.Здоровье // Текущее здоровье танка
-	манёвр      *manevr.Манёвр   // Возможность маневрирования
+	выстрел     ИВыстрел    // Объект выстрела
+	здоровье    ИЗдоровье // Текущее здоровье танка
+	манёвр      ИМанёвр   // Возможность маневрирования
 	логин       string
-	еслиВыстрел *is_shot.IsShot // Признак необходимости маскирования (запрет стрельбы, когда слабое здоровье)
 }
 
 // НовСражениеДействие -- возвращает новый *BattleOn
-func НовСражениеДействие(конт ИЯдроКонтекст, бот ИБот) *СражениеДействие {
+func НовСражениеДействие(конт ИБотКонтекст) ИСражениеПроцесс {
 	// Ограничить время сражения бота
+	бот:=конт.Получ("бот").(ИБот)
 	кнтСражение, фнОтменить := context.WithTimeout(бот.Контекст(), time.Second*305)
 	сам := &СражениеДействие{
 		бот:         бот,
 		кнт:         кнтСражение,
 		фнОтменить:  фнОтменить,
 		логин:       бот.Имя(),
-		еслиВыстрел: is_shot.NewIsShot(),
 	}
 	аренаКонфиг := arena.АренаКонфиг{
 		Бот_:         сам.бот,
@@ -51,7 +48,6 @@ func НовСражениеДействие(конт ИЯдроКонтекст,
 	}
 	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
 	go сам.пуск()
-	_ = ИСражениеДействие(сам)
 	return сам
 }
 
@@ -62,22 +58,9 @@ func (сам *СражениеДействие) пуск() {
 		// log._rintf("BattleOn.run(): сражение завершено\n")
 	}()
 	{ // Подготовка к сражению
-		var err error
-		сам.выстрел, err = shot.НовВыстрел(сам) // Объект выстрела
-		if err != nil {
-			// log._rintf("ERRO BattleOn.Run(): при создании выстрела танка, err=\n\t%v\n", err)
-			return
-		}
-		сам.здоровье, err = health.НовЗдоровье(сам)
-		if err != nil {
-			// log._rintf("ERRO BattleOn.Run(): при создании здоровья танка, err=\n\t%v\n", err)
-			return
-		}
-		сам.манёвр, err = manevr.НовМанёвр(сам)
-		if err != nil {
-			// log._rintf("ERRO BattleOn.Run(): при создании маневра танка, err=\n\t%v\n", err)
-			return
-		}
+		сам.выстрел = shot.НовВыстрел(сам) // Объект выстрела
+		сам.здоровье = health.НовЗдоровье(сам)
+		сам.манёвр = manevr.НовМанёвр(сам)
 	}
 	// Рабочий цикл сражения
 	<-сам.кнт.Done()
@@ -90,9 +73,9 @@ func (сам *СражениеДействие) МанёврНадоУст() {
 	сам.манёвр.УстНадо()
 }
 
-// ВыстрелБлок -- признак запрета стрельбы при слабом здоровье
-func (сам *СражениеДействие) ВыстрелБлок() ИЕслиВыстрел {
-	return сам.еслиВыстрел
+// Выстрел -- 
+func (сам *СражениеДействие) Выстрел() ИВыстрел {
+	return сам.выстрел
 }
 
 // Кнт -- возвращает контекст отмены сражения

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

@@ -125,7 +125,7 @@ func (сам *АренаКонвой) обновитьВремя() {
 	ош := сам.ОбратВремяУст("20")
 	if ош != nil {
 		log.Printf("Конвой.обновитьВремя(): при обновлении времени, ош=\n\t%v\n", ош)
-		сам.бот.Сервер().Отменить()
+		сам.Отменить()
 		return
 	}
 	// Найти строку с упоминанием оставшегося времени конвоя
@@ -168,7 +168,7 @@ func (сам *АренаКонвой) обновитьВремя() {
 			err := сам.ОбратВремяУст("10")
 			if err != nil {
 				log.Printf("Конвой.обновитьВремя(): при установке времени ожидания конвоя(%v)\n\terr=%v\n", strLastTime, err)
-				сам.бот.Сервер().Отменить()
+				сам.Отменить()
 			}
 		}
 	case isMask: // Если маскировка между конвоями
@@ -180,7 +180,7 @@ func (сам *АренаКонвой) обновитьВремя() {
 			err := сам.ОбратВремяУст("10")
 			if err != nil {
 				log.Printf("Конвой.обновитьВремя(): при установке времени банка для 1го режима(%v)\n\terr=%v\n", strLastTime, err)
-				сам.бот.Сервер().Отменить()
+				сам.Отменить()
 			}
 		}
 	}

+ 9 - 9
app/lev2/arena_death/arena_death.go

@@ -6,9 +6,9 @@ import (
 
 	. "wartank/app/lev0/types"
 	"wartank/app/lev2/arena"
-	"wartank/app/lev2/arena_duel/battle_register"
-	"wartank/app/lev2/arena_duel/battle_wait"
-	"wartank/app/lev2/arena_duel/battle_worker"
+	"wartank/app/lev2/arena_death/death_register"
+	"wartank/app/lev2/arena_death/death_wait"
+	"wartank/app/lev2/arena_death/death_worker"
 	. "wartank/kernel/kernel_types"
 )
 
@@ -18,9 +18,9 @@ type АренаСхватка struct {
 	бот    ИБот
 	клиент ИХттпВоркер
 
-	регистрация *battle_register.СхваткаРегистрация // Регистратор на сражение
-	ожидание    *battle_wait.СхваткаОжидание        // Ожидатель начала схватки
-	действие    *battle_worker.СхваткаИсполнитель   // Исполнитель схватки
+	регистрация *death_register.СхваткаРегистрация // Регистратор на сражение
+	ожидание    *death_wait.СражениеОжидание       // Ожидатель начала схватки
+	действие    *death_worker.СхваткаИсполнитель   // Исполнитель схватки
 
 }
 
@@ -38,9 +38,9 @@ func НовСхватка(конт ИЯдроКонтекст, бот ИБот)
 		СтрУрл_:      "https://wartank.ru/dm",
 	}
 	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
-	сам.регистрация = battle_register.НовСражениеРегистрация(конт, бот)
-	сам.ожидание = battle_wait.НовСражениеОжидание(конт, бот)
-	сам.действие = battle_worker.НовСражениеИсполнитель(конт, бот)
+	сам.регистрация = death_register.НовСхваткаРегистрация(конт, бот)
+	сам.ожидание = death_wait.НовСражениеОжидание(конт, бот)
+	сам.действие = death_worker.НовСхваткаИсполнитель(конт, бот)
 	// сам.shotTimeFull.Set(8000) // 8000 msec
 	return сам
 }

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

@@ -1,5 +1,5 @@
-// package battle_wait -- заставляет ожидать начало битвы
-package battle_wait
+// package death_wait -- заставляет ожидать начало битвы
+package death_wait
 
 import (
 	"strings"

+ 0 - 110
app/lev2/arena_death/death_worker/death_on/death_on.go

@@ -1,110 +0,0 @@
-package death_on
-
-import (
-	"context"
-	"time"
-
-	. "wartank/app/lev0/types"
-	"wartank/app/lev2/arena"
-	"wartank/app/lev2/arena_death/death_worker/death_on/health"
-	"wartank/app/lev2/arena_death/death_worker/death_on/manevr"
-	"wartank/app/lev2/arena_death/death_worker/death_on/shot"
-	"wartank/app/lev2/arena_death/death_worker/death_on/shot/is_shot"
-)
-
-/*
-	Предоставляет сетевой компонент при непосредственном сражении
-*/
-
-// СхваткаДействие -- непосредственно танкует в сражении
-type СхваткаДействие struct {
-	ИАрена
-	сеть       ИАренаСеть
-	бот        ИБот
-	кнт        context.Context // Контекст сражения
-	фнОтменить func()          // Функция отмены сражения
-
-	выстрел     *shot.Выстрел    // Объект выстрела
-	здоровье    *health.Здоровье // Текущее здоровье танка
-	манёвр      *manevr.Манёвр   // Возможность маневрирования
-	логин       string
-	еслиВыстрел *is_shot.IsShot // Признак необходимости маскирования (запрет стрельбы, когда слабое здоровье)
-}
-
-// НовСхваткаДействие -- возвращает новый *СхваткаДействие
-func НовСхваткаДействие(конт ИБотКонтекст, бот ИБот) *СхваткаДействие {
-	// Ограничить время сражения бота
-	кнтСражение, фнОтменить := context.WithTimeout(бот.Контекст(), time.Second*305)
-	сам := &СхваткаДействие{
-		бот:         бот,
-		кнт:         кнтСражение,
-		фнОтменить:  фнОтменить,
-		логин:       бот.Имя(),
-		еслиВыстрел: is_shot.NewIsShot(),
-	}
-	аренаКонфиг := arena.АренаКонфиг{
-		Бот_:         сам.бот,
-		АренаИмя_:    "Исполнитель схватки",
-		СтрКонтроль_: `<title>Схватка</title>`,
-		ФнПуск_:      сам.пуск,
-		СтрУрл_:      "https://wartank.ru/de",
-	}
-	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
-	go сам.пуск()
-	return сам
-}
-
-// запускает сражение
-func (сам *СхваткаДействие) пуск() {
-	defer func() {
-		сам.фнОтменить()
-		// log._rintf("СхваткаДействие.run(): сражение завершено\n")
-	}()
-	{ // Подготовка к сражению
-		var err error
-		сам.выстрел, err = shot.НовВыстрел(сам) // Объект выстрела
-		if err != nil {
-			// log._rintf("ERRO СхваткаДействие.Run(): при создании выстрела танка, err=\n\t%v\n", err)
-			return
-		}
-		сам.здоровье, err = health.НовЗдоровье(сам)
-		if err != nil {
-			// log._rintf("ERRO СхваткаДействие.Run(): при создании здоровья танка, err=\n\t%v\n", err)
-			return
-		}
-		сам.манёвр, err = manevr.НовМанёвр(сам)
-		if err != nil {
-			// log._rintf("ERRO СхваткаДействие.Run(): при создании маневра танка, err=\n\t%v\n", err)
-			return
-		}
-	}
-	// Рабочий цикл сражения
-	<-сам.кнт.Done()
-}
-
-// Сеть -- возвращает сетевой компонент секции
-func (сам *СхваткаДействие) Сеть() ИАренаСеть {
-	return сам.сеть
-}
-
-func (сам *СхваткаДействие) МанёврНадоУст() {
-	if сам.манёвр == nil {
-		return
-	}
-	сам.манёвр.УстНадо()
-}
-
-// ВыстрелБлок -- признак запрета стрельбы при слабом здоровье
-func (сам *СхваткаДействие) ВыстрелБлок() ИЕслиВыстрел {
-	return сам.еслиВыстрел
-}
-
-// Кнт -- возвращает контекст отмены сражения
-func (сам *СхваткаДействие) Контекст() context.Context {
-	return сам.кнт
-}
-
-// ОтменитьДействие -- вызов функции отмены контекста сражения
-func (сам *СхваткаДействие) Отменить() {
-	сам.фнОтменить()
-}

+ 0 - 102
app/lev2/arena_death/death_worker/death_on/health/health.go

@@ -1,102 +0,0 @@
-package health
-
-import (
-	"fmt"
-	"strings"
-	"time"
-
-	. "wartank/app/lev0/types"
-)
-
-/*
-	Контролирует состояние здоровья танка
-*/
-
-// Здоровье -- контроль здоровья танка
-type Здоровье struct {
-	ИСражениеДействие
-	канТик     chan int // Канал для ровной отправки тиков
-	счётЛечить int      // Счётчик вызовов лечения
-}
-
-// НовЗдоровье -- возвращает новый *Здоровье
-func НовЗдоровье(действие ИСражениеДействие) (*Здоровье, error) {
-	{ // Предусловия
-		if действие == nil {
-			return nil, fmt.Errorf("НовЗдоровье(): действие==nil")
-		}
-	}
-	сам := &Здоровье{
-		ИСражениеДействие: действие,
-		канТик:            make(chan int, 2),
-	}
-	go сам.makeTik()
-	go сам.пуск()
-	return сам, nil
-}
-
-// Отправляет тики с заданным равным интервалом
-func (сам *Здоровье) makeTik() {
-	defer func() {
-		close(сам.канТик)
-		сам.Отменить()
-		// log._rintf("Здоровье.makeTick(): сражение завершёно\n")
-	}()
-	for {
-		select {
-		case <-сам.Контекст().Done():
-			return
-		default:
-			сам.канТик <- 1
-			time.Sleep(time.Second * 10)
-		}
-	}
-}
-
-// Главный цикл обработки здоровья в сражении
-func (сам *Здоровье) пуск() {
-	defer func() {
-		сам.Отменить()
-	}()
-	for range сам.канТик {
-		сам.лечить()
-	}
-}
-
-// Полное -- возвращает объект полного здоровья танка
-func (сам *Здоровье) Полное() int {
-	return 0
-}
-
-// ЕслиМёртвый -- возвращает признак мертвичины танка
-func (сам *Здоровье) ЕслиМёртвый() bool {
-	lstBattle := сам.СписПолучить()
-	for _, strOut := range lstBattle {
-		if strings.Contains(strOut, `>Ваш танк подбит.`) {
-			// log._rintf("INFO Здоровье.repair(): танк подбит\n")
-			сам.Отменить()
-			return true
-		}
-	}
-	return false
-}
-
-// Восстанавливает здоровье (~)
-func (сам *Здоровье) лечить() {
-
-	// <span>Ремкомплект</span>
-	// <a href="pve?19-14.ILinkListener-currentControl-repairLink" class="simple-but blue"><span><span>Ремкомплект</span></span></a>
-
-	strLink := "https://wartank.ru/pve?19-{count}.ILinkListener-currentControl-repairLink"
-	// <a href="pve?6-26.ILinkListener-currentControl-repairLink" class="simple-but blue"><span><span>Ремкомплект</span></span></a>
-	strLink = strings.ReplaceAll(strLink, "{count}", fmt.Sprint(сам.счётЛечить))
-	lstBattleOn, err := сам.Сеть().Get(strLink)
-	if err != nil {
-		// log._rintf("ERRO Здоровье.repair(): при выполнении GET-команды ремонта, err=\n\t%v\n", err)
-		return
-	}
-	if err = сам.СтрОбновить(lstBattleOn); err != nil {
-		// log._rintf("ERRO Здоровье.repair(): при обновлении lstBattle, err=\n\t%v\n", err)
-		return
-	}
-}

+ 0 - 46
app/lev2/arena_death/death_worker/death_on/health/healthtime/healthtime.go

@@ -1,46 +0,0 @@
-package healthtime
-
-import (
-	"sync"
-)
-
-/*
-	Содержит временное здоровье
-*/
-
-// HealthTime -- временное здоровье
-type HealthTime struct {
-	val   int // Здоровье FIXME: переделать в алиас
-	block sync.RWMutex
-}
-
-// NewHealthTime -- возвращает новый *HealthTime
-func NewHealthTime() *HealthTime {
-	return &HealthTime{}
-}
-
-// Get -- возвращает хранимое временное здоровье
-func (сам *HealthTime) Get() int {
-	сам.block.RLock()
-	defer сам.block.RUnlock()
-	return сам.val
-}
-
-// IsZero -- возвращает истину, если значение обнулено
-func (сам *HealthTime) IsZero() bool {
-	сам.block.RLock()
-	defer сам.block.RUnlock()
-	return сам.val == 0
-}
-
-// Set -- устанавливает значение по требованию
-func (сам *HealthTime) Set(val int) {
-	сам.block.Lock()
-	defer сам.block.Unlock()
-	if val < 0 {
-		// log._rintf("WARN HealthTime.Set(): отрицательное значение(%v)\n", val)
-		сам.val = 0
-		return
-	}
-	сам.val = val
-}

+ 0 - 41
app/lev2/arena_death/death_worker/death_on/health/isrepair/isrepair.go

@@ -1,41 +0,0 @@
-package isrepair
-
-import (
-	"sync"
-)
-
-/*
-	Потокобезопасный признак необходимости восстановления здоровья
-*/
-
-// IsRepair -- потокобезопасный признак восстановления здоровья
-type IsRepair struct {
-	val   bool
-	block sync.RWMutex
-}
-
-// NewIsRepair -- возвращает новый *IsRepair
-func NewIsRepair() *IsRepair {
-	return &IsRepair{}
-}
-
-// Get -- возвращает хранимое состояние
-func (сам *IsRepair) Get() bool {
-	сам.block.RLock()
-	defer сам.block.RUnlock()
-	return сам.val
-}
-
-// Set -- устанавливает хранимое состояние
-func (сам *IsRepair) Set() {
-	сам.block.Lock()
-	defer сам.block.Unlock()
-	сам.val = true
-}
-
-// Reset -- сбрасывает хранимое состояние
-func (сам *IsRepair) Reset() {
-	сам.block.Lock()
-	defer сам.block.Unlock()
-	сам.val = false
-}

+ 0 - 173
app/lev2/arena_death/death_worker/death_on/manevr/manevr.go

@@ -1,173 +0,0 @@
-package manevr
-
-import (
-	"fmt"
-	// "log"
-	"strings"
-	"time"
-
-	"github.com/sirupsen/logrus"
-
-	"wartank/app/lev2/arena_duel/battle_worker/battle_worker/health/repair_time"
-	"wartank/app/lev2/arena_duel/battle_worker/battle_worker/manevr/is_manevr"
-
-	// "wartank/internal/components/sound"
-	. "wartank/app/lev0/types"
-)
-
-/*
-	Пытается маневрировать после выстрела
-*/
-
-// Манёвр -- маневрирует после выстрела
-type Манёвр struct {
-	ИСражениеДействие                         // FIXME:
-	еслиМанёврНадо    *is_manevr.IsManevr     // Требование выполнить манёвр
-	времяЖдать        *repair_time.RepairTime // Время до восстановления манёвра
-	chTick            chan int                // Тики для поиска маневра
-}
-
-// НовМанёвр -- возвращает новый *Manevr
-func НовМанёвр(действие ИСражениеДействие) (*Манёвр, error) {
-	{ // Предусловия
-		if действие == nil {
-			return nil, fmt.Errorf("НовМанёвр(): действие==nil")
-		}
-	}
-	сам := &Манёвр{
-		ИСражениеДействие: действие,
-		еслиМанёврНадо:    is_manevr.NewIsManevr(),
-		времяЖдать:        repair_time.NewRepairTime(),
-		chTick:            make(chan int, 1),
-	}
-	_ = сам.времяЖдать.Set("0") // При запуске боя есть возможность маневрировать
-	go сам.makeTick()
-	go сам.пуск()
-	return сам, nil
-}
-
-// Генерирует тик для уменьшения времени ожидания восстановления возможности манёвра
-func (сам *Манёвр) makeTick() {
-	defer func() {
-		close(сам.chTick)
-		// log._rintf("Manevr.makeTick(): сражение завершено\n")
-	}()
-	for {
-		select {
-		case <-сам.Контекст().Done():
-			return
-		default:
-			if сам.времяЖдать.Получ() <= 0 {
-				сам.chTick <- 1
-			}
-			сам.времяЖдать.Dec()
-			time.Sleep(time.Second * 1)
-		}
-	}
-}
-
-// Рабочий цикл поиска маневра (~)
-func (сам *Манёвр) пуск() {
-	for range сам.chTick {
-		if !сам.еслиМанёврНадо.Get() { // Если нет требования манёвра -- пропускаем
-			continue
-		}
-		сам.манёвр()
-		сам.времяМанёврНайти() // Найти время после манёвра
-	}
-}
-
-// Ищет время для манёвра
-func (сам *Манёвр) времяМанёврНайти() {
-	var (
-		еслиНайдено bool
-		ind         int
-		lstBattleOn = сам.СписПолучить()
-		strOut      string
-	)
-	for ind, strOut = range lstBattleOn {
-		// <a href="pve?4-88.ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>5 секунд</span></span></a>
-		if strings.Contains(strOut, `-currentControl-maneuverLink`) {
-			еслиНайдено = true
-			break
-		}
-	}
-	if !еслиНайдено { // Или манёвр успел восстановиться, или конец сражения
-		if strings.Contains(strOut, `<span>Маневр</span>`) {
-			_ = сам.времяЖдать.Set("0")
-			return
-		}
-		logrus.WithField("strOut", strOut).Warn("Манёвр.времяМанёврНайти(): ошибка в поиске времени манёвра")
-		сам.Отменить()
-		return
-	}
-	{ // Найти время манёвра
-		lstTime := strings.Split(strOut, `ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>`)
-		if len(lstTime) != 2 {
-			logrus.WithField("ind", ind).
-				WithField("lstBattleOn[-1]", lstBattleOn[ind-1]).
-				WithField("lstBattleOn[ind]", strOut).
-				WithField("lstBattleOn[+1]", lstBattleOn[ind+1]).
-				Errorf("Manevr.findManevrTime(): нет двух полей во времени ожидания")
-			сам.Отменить()
-			return
-		}
-		strTime := lstTime[1]
-		lstTime = strings.Split(strTime, ` секунд</span></span></a>`)
-		strTime = lstTime[0]
-		if err := сам.времяЖдать.Set(strTime); err != nil {
-			logrus.WithError(err).Error("Manevr.findManevrTime(): при обновлении времени ожидания манёвра")
-			сам.Отменить()
-			return
-		}
-	}
-	logrus.WithField("время", сам.времяЖдать.Получ()).Info("Manevr.findManevrTime(): до манёвра")
-}
-
-// Манёвр по возможности
-func (сам *Манёвр) манёвр() {
-	var (
-		еслиНайдено = false
-		lstBattleOn = сам.СписПолучить()
-		strOut      = ""
-	)
-	for _, strOut = range lstBattleOn {
-		// <a href="pve?4-21.ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>Маневр</span></span></a>
-		if strings.Contains(strOut, `<span>Маневр</span>`) {
-			еслиНайдено = true
-			break
-		}
-	}
-	if !еслиНайдено { // Либо ждём восстановления манёвра, либо сражение закончилось
-		return
-	}
-	{ // Попытка манёвра
-		lstLink := strings.Split(strOut, `<a href="`)
-		strLink := lstLink[1]
-		lstLink = strings.Split(strLink, `" class="simple-but blue"><span><span>Маневр</span></span></a>`)
-		strLink = "https://wartank.ru/" + lstLink[0]
-		lstBattleOn, err := сам.Сеть().Get(strLink)
-		if err != nil {
-			logrus.WithError(err).Error("Manevr.Manevr(): при выполнении GET-команды маневра")
-			сам.Отменить()
-			return
-		}
-		if err = сам.СтрОбновить(lstBattleOn); err != nil {
-			logrus.WithError(err).Error("Manevr.Manevr(): при обновлении lstBattle")
-			сам.Отменить()
-			return
-		}
-		// sound.Manevr()
-	}
-	сам.еслиМанёврНадо.Сброс()
-}
-
-// ЕслиГотов -- возвращает готовность манёвра
-func (сам *Манёвр) ЕслиГотов() bool {
-	return сам.времяЖдать.ЕслиМожно()
-}
-
-// УстНадо -- устанавливает признак необходимости манёвра
-func (сам *Манёвр) УстНадо() {
-	сам.еслиМанёврНадо.Set()
-}

+ 0 - 41
app/lev2/arena_death/death_worker/death_on/shot/is_shot/is_shot.go

@@ -1,41 +0,0 @@
-package is_shot
-
-import (
-	"sync"
-)
-
-/*
-	Потокобезопасный признак внешнего разрешения выстрела
-*/
-
-// IsShot -- потокобезопасный признак внешнего разрешения выстрела
-type IsShot struct {
-	val   bool
-	block sync.RWMutex
-}
-
-// NewIsShot -- возвращает новый *IsShot
-func NewIsShot() *IsShot {
-	return &IsShot{}
-}
-
-// Get -- возвращает хранимое состояние
-func (сам *IsShot) Get() bool {
-	сам.block.RLock()
-	defer сам.block.RUnlock()
-	return сам.val
-}
-
-// Set -- устанавливает хранимое состояние
-func (сам *IsShot) Set() {
-	сам.block.Lock()
-	defer сам.block.Unlock()
-	сам.val = true
-}
-
-// Reset -- сбрасывает хранимое состояние
-func (сам *IsShot) Reset() {
-	сам.block.Lock()
-	defer сам.block.Unlock()
-	сам.val = false
-}

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

@@ -7,8 +7,8 @@ import (
 	. "wartank/app/lev0/types"
 	"wartank/app/lev1/stat_param"
 	"wartank/app/lev2/arena"
-	"wartank/app/lev2/arena_death/death_worker/death_on"
-	"wartank/app/lev2/arena_death/death_worker/death_on/battle_sound"
+	"wartank/app/lev2/arena_death/death_worker/process_death"
+	"wartank/app/lev2/arena_death/death_worker/process_death/battle_sound"
 )
 
 // СражениеДействие -- исполнение схватки
@@ -20,7 +20,7 @@ type СхваткаИсполнитель struct {
 	еслиНачало ИСтатПарам
 
 	// Непосредственное сражение
-	действие *death_on.СхваткаДействие
+	действие *process_death.СхваткаПроцесс
 
 	sound *battle_sound.BattleSound // Однопоточное проигрывание звука
 }
@@ -51,7 +51,7 @@ func (сам *СхваткаИсполнитель) пуск() {
 
 // Танковать -- выполняет битву
 func (сам *СхваткаИсполнитель) Танковать() {
-	сам.действие = death_on.НовСхваткаДействие(сам.конт, сам.бот) // IBattleOn (онлайн)
+	сам.действие = process_death.НовСхваткаПроцесс(сам.конт, сам.бот) // IBattleOn (онлайн)
 	сам.sound.Play()
 	time.Sleep(time.Second * 10) // Задержка для звука на странице
 	<-сам.действие.Контекст().Done()

+ 1 - 1
app/lev2/arena_death/death_worker/death_on/battle_sound/battle_sound.go → app/lev2/arena_death/death_worker/process_death/battle_sound/battle_sound.go

@@ -3,7 +3,7 @@ package battle_sound
 import (
 	"time"
 	"wartank/app/lev1/sound"
-	"wartank/app/lev2/arena_duel/battle_worker/battle_worker/battle_sound/is_sound_play"
+	"wartank/app/lev1/sound/is_sound_play"
 )
 
 /*

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


+ 1 - 1
app/lev2/arena_death/death_worker/death_on/battlesound/battlesound.go → app/lev2/arena_death/death_worker/process_death/battlesound/battlesound.go

@@ -3,7 +3,7 @@ package battle_sound
 import (
 	"time"
 	"wartank/app/lev1/sound"
-	"wartank/app/lev2/arena_duel/battle_worker/battle_worker/battle_sound/is_sound_play"
+	"wartank/app/lev1/sound/is_sound_play"
 )
 
 /*

+ 5 - 5
app/lev2/arena_battle/battle_worker/battle_worker/health/health.go → app/lev2/arena_death/death_worker/process_death/health/health.go

@@ -14,21 +14,21 @@ import (
 
 // Здоровье -- контроль здоровья танка
 type Здоровье struct {
-	ИСражениеДействие
+	ИСражениеПроцесс
 	канТик     chan int // Канал для ровной отправки тиков
 	счётЛечить int      // Счётчик вызовов лечения
 }
 
 // НовЗдоровье -- возвращает новый *Здоровье
-func НовЗдоровье(действие ИСражениеДействие) (*Здоровье, error) {
+func НовЗдоровье(проц ИСражениеПроцесс) (*Здоровье, error) {
 	{ // Предусловия
-		if действие == nil {
+		if проц == nil {
 			return nil, fmt.Errorf("НовЗдоровье(): действие==nil")
 		}
 	}
 	сам := &Здоровье{
-		ИСражениеДействие: действие,
-		канТик:            make(chan int, 2),
+		ИСражениеПроцесс: проц,
+		канТик:           make(chan int, 2),
 	}
 	go сам.makeTik()
 	go сам.пуск()

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


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


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


+ 89 - 0
app/lev2/arena_death/death_worker/process_death/process_death.go

@@ -0,0 +1,89 @@
+package process_death
+
+import (
+	"context"
+	"time"
+
+	. "wartank/app/lev0/types"
+	"wartank/app/lev1/health"
+	"wartank/app/lev1/manevr"
+	"wartank/app/lev1/shot"
+	"wartank/app/lev2/arena"
+)
+
+/*
+	Предоставляет сетевой компонент при непосредственном сражении
+*/
+
+// СхваткаПроцесс -- непосредственно танкует в сражении
+type СхваткаПроцесс struct {
+	ИСражениеПроцесс
+	арена      ИАрена
+	бот        ИБот
+	кнт        context.Context // Контекст сражения
+	фнОтменить func()          // Функция отмены сражения
+
+	выстрел  ИВыстрел    // Объект выстрела
+	здоровье *health.Здоровье // Текущее здоровье танка
+	манёвр   ИМанёвр          // Возможность маневрирования
+	логин    string
+}
+
+// НовСхваткаПроцесс -- возвращает новый процесс схватки
+func НовСхваткаПроцесс(конт ИБотКонтекст, бот ИБот) *СхваткаПроцесс {
+	// Ограничить время сражения бота
+	кнтСражение, фнОтменить := context.WithTimeout(бот.Контекст(), time.Second*305)
+	сам := &СхваткаПроцесс{
+		бот:        бот,
+		кнт:        кнтСражение,
+		фнОтменить: фнОтменить,
+		логин:      бот.Имя(),
+	}
+	аренаКонфиг := arena.АренаКонфиг{
+		Бот_:         сам.бот,
+		АренаИмя_:    "Исполнитель схватки",
+		СтрКонтроль_: `<title>Схватка</title>`,
+		ФнПуск_:      сам.пуск,
+		СтрУрл_:      "https://wartank.ru/de",
+	}
+	сам.арена = arena.НовАрена(конт, аренаКонфиг)
+	go сам.пуск()
+	return сам
+}
+
+// запускает сражение
+func (сам *СхваткаПроцесс) пуск() {
+	defer func() {
+		сам.фнОтменить()
+		// log._rintf("СхваткаПроцесс.run(): сражение завершено\n")
+	}()
+	{ // Подготовка к сражению
+		сам.выстрел = shot.НовВыстрел(сам) // Объект выстрела
+		сам.здоровье = health.НовЗдоровье(сам)
+		сам.манёвр = manevr.НовМанёвр(сам)
+	}
+	// Рабочий цикл сражения
+	<-сам.кнт.Done()
+}
+
+func (сам *СхваткаПроцесс) МанёврНадоУст() {
+	if сам.манёвр == nil {
+		return
+	}
+	сам.манёвр.УстНадо()
+}
+
+// Выстрел -- признак запрета стрельбы при слабом здоровье
+func (сам *СхваткаПроцесс) Выстрел() ИВыстрел {
+	return сам.выстрел
+}
+
+// Кнт -- возвращает контекст отмены сражения
+func (сам *СхваткаПроцесс) Контекст() context.Context {
+	return сам.кнт
+}
+
+// ОтменитьДействие -- вызов функции отмены контекста сражения
+func (сам *СхваткаПроцесс) Отменить() {
+	сам.фнОтменить()
+}

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


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


+ 5 - 5
app/lev2/arena_death/death_worker/death_on/shot/shot.go → app/lev2/arena_death/death_worker/process_death/shot/shot.go

@@ -20,20 +20,20 @@ import (
 
 // Выстрел -- объект выстрела
 type Выстрел struct {
-	ИСражениеДействие          // FIXME!!!
+	ИСражениеПроцесс          // FIXME!!!
 	канТик            chan int // Тик для выстрела
 	выстрелСчёт       int      // Счётчик выстрелов для сервера
 }
 
 // НовВыстрел -- возвращает новый *Shot
-func НовВыстрел(действие ИСражениеДействие) (*Выстрел, error) {
+func НовВыстрел(проц ИСражениеПроцесс) (*Выстрел, error) {
 	{ // Предусловия
-		if действие == nil {
+		if проц == nil {
 			return nil, fmt.Errorf("НовВыстрел(): действие==nil")
 		}
 	}
 	сам := &Выстрел{
-		ИСражениеДействие: действие,
+		ИСражениеПроцесс: проц,
 		выстрелСчёт:       1,
 		канТик:            make(chan int, 2),
 	}
@@ -85,6 +85,6 @@ func (сам *Выстрел) выстрел() {
 		// log._rintf("ERRO Shot.shot(): при исполнении GET-команды выстрела обычным снарядом, err=\n\t%v\n", err)
 		return
 	}
-	сам.МанёврНадоУст()
+	сам.Манёвр().УстНадо()
 	// sound.Shot()
 }

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


+ 11 - 17
app/lev2/arena_division/div_war/div_war.go

@@ -12,8 +12,8 @@ import (
 	"wartank/app/lev1/stat_param"
 	"wartank/app/lev2/arena"
 	"wartank/app/lev2/arena_division/div_war/div_war_net"
-	"wartank/app/lev2/arena_division/div_war/div_war_on"
-	"wartank/app/lev2/arena_division/div_war/div_war_on/div_war_sound"
+	"wartank/app/lev2/arena_division/div_war/process_divwar"
+	"wartank/app/lev2/arena_division/div_war/process_divwar/div_war_sound"
 	. "wartank/kernel/kernel_types"
 )
 
@@ -24,15 +24,15 @@ import (
 // DivWar -- объект ожидания битвы дивизий
 type DivWar struct {
 	ИАрена
-	конт  ИЯдроКонтекст
+	конт  ИБотКонтекст
 	bot   ИБот
 	alarm ИСтатПарам
 	net   *div_war_net.DivWarNet
 	conn  ИХттпВоркер
 
 	// Непосредственная битва
-	divOn *div_war_on.DivWarOn
-	login string // Для непосредственной битвы дивизий
+	процВойна ИСражениеПроцесс
+	логин string // Для непосредственной битвы дивизий
 	block sync.Mutex
 
 	chDivWar chan int // Сигнал начала битвы дивизий
@@ -51,7 +51,7 @@ func NewDivWar(конт ИЯдроКонтекст, bot ИБот) (*DivWar, erro
 		chDivWar: make(chan int, 1),
 		sound:    div_war_sound.NewDivWarSound(),
 		conn:     bot.Сеть().ВебВоркер(),
-		login:    "prospero tank",
+		логин:    "prospero tank",
 	}
 	аренаКонфиг := arena.АренаКонфиг{
 		Бот_:         bot,
@@ -89,7 +89,7 @@ func (сам *DivWar) резервТик() {
 			if ct1.Сек() != ct0.Сек() {
 				continue
 			}
-			if сам.divOn != nil {
+			if сам.процВойна != nil {
 				continue
 			}
 			сам.chDivWar <- 1
@@ -109,7 +109,7 @@ func (сам *DivWar) run() {
 			сам.upDivWar()
 		case <-сам.chDivWar: // Сигнал к началу сражения
 			сам.block.Lock()
-			if сам.divOn != nil {
+			if сам.процВойна != nil {
 				continue
 			}
 			сам.alarm.Уст(1)
@@ -195,22 +195,16 @@ func (сам *DivWar) upDivWar() {
 // Ведёт сражение
 func (сам *DivWar) DivWar() {
 	defer func() {
-		сам.divOn = nil
+		сам.процВойна = nil
 		сам.block.Unlock()
 		if err := сам.ОбратВремяУст("01"); err != nil {
 			panic(fmt.Errorf("DivWar.DivWar(): при установке CountDown, err=\n\t%w", err))
 		}
 		// log.Printf("INFO DivWar.DivWar(): сражение завершено\n")
 	}()
-	var err error
-	сам.divOn, err = div_war_on.NewDivWarOn(сам.конт, сам.bot) // IDivWarOn (онлайн)
-	if err != nil {
-		// log._rintf("ERRO DivWar.DivWarOn(): при создании IDivWarOn, err=\n\t%v\n", err)
-		time.Sleep(time.Millisecond * 250)
-		return
-	}
+	сам.процВойна = process_divwar.НовПроцессДивизияВойна(сам.конт) // IDivWarOn (онлайн)
 	// Цикл ожидания окончания сражения
-	for !сам.divOn.ЕслиКонец().Получ() {
+	for !сам.процВойна.ЕслиКонец().Получ() {
 		time.Sleep(time.Second * 1)
 	}
 

+ 0 - 178
app/lev2/arena_division/div_war/div_war_on/div_war_on.go

@@ -1,178 +0,0 @@
-package div_war_on
-
-import (
-	"context"
-	"fmt"
-	"strings"
-	"time"
-
-	. "wartank/app/lev0/types"
-	"wartank/app/lev1/health"
-	"wartank/app/lev2/arena"
-	"wartank/app/lev3/bot/angar/division/div_war/div_war_on/manevr"
-	"wartank/app/lev3/bot/angar/division/div_war/div_war_on/shot"
-	"wartank/kernel"
-	. "wartank/kernel/kernel_types"
-)
-
-/*
-	Предоставляет сетевой компонент при непосредственном сражении
-*/
-
-// DivWarOn -- непосредственно танкует в сражении
-type DivWarOn struct {
-	ИАрена
-	bot            ИБот
-	ctxDivWar      context.Context // Контекст сражения
-	fnCancelDivWar func()          // Функция отмены сражения
-
-	shot      *shot.Shot       // Объект выстрела
-	health    *health.Здоровье // Текущее здоровье танка
-	manevr    *manevr.Manevr   // Возможность маневрирования
-	login     string
-	isMasking ИБезопБул // Признак необходимости маскирования (запрет стрельбы, когда слабое здоровье)
-	chTick    chan int  // Ежесекундная проверка на окончание сражения
-	isEnd     ИБезопБул
-}
-
-// NewDivWarOn -- возвращает новый *DivWarOn
-func NewDivWarOn(конт ИБотКонтекст, bot ИБот) (*DivWarOn, error) {
-	if bot == nil {
-		return nil, fmt.Errorf("NewDivWarOn(): IBot == nil")
-	}
-	ctxDivWar, fnCancelDivWar := context.WithTimeout(bot.Контекст(), time.Second*305)
-	сам := &DivWarOn{
-		bot:            bot,
-		ctxDivWar:      ctxDivWar,
-		fnCancelDivWar: fnCancelDivWar,
-		login:          bot.Имя(),
-		isMasking:      kernel.НовБезопБул(),
-		isEnd:          kernel.НовБезопБул(),
-	}
-	аренаКонфиг := arena.АренаКонфиг{
-		Бот_:         bot,
-		АренаИмя_:    "Сражение",
-		СтрКонтроль_: `<title>Сражения</title>`,
-		ФнПуск_:      сам.пуск,
-		СтрУрл_:      "https://wartank.ru/pve",
-	}
-	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
-	if сам.checkEnd() {
-		return nil, fmt.Errorf("NewDivWarOn(): нет страницы для сражения")
-	}
-	go сам.makeTick()
-	go сам.run()
-	return сам, nil
-}
-
-// пускает сражение
-func (сам *DivWarOn) пуск() {
-}
-
-// Ежесекудный тик
-func (сам *DivWarOn) makeTick() {
-	defer func() {
-		close(сам.chTick)
-		сам.isEnd.Уст()
-	}()
-	for !сам.isEnd.Получ() {
-		select {
-		case <-сам.bot.Контекст().Done(): // Отмена контекста приложения
-			return
-		case <-сам.ctxDivWar.Done(): // Битва закончилась
-			return
-		default:
-			if сам.isEnd.Получ() {
-				return
-			}
-			сам.chTick <- 1
-			time.Sleep(time.Second * 1)
-		}
-	}
-}
-
-// запускает сражение
-func (сам *DivWarOn) run() {
-	// defer log._rintf("DivWarOn.run(): сражение завершено\n")
-	{ // Подготовка к сражению
-		var err error
-		сам.shot, err = shot.NewShot(сам, сам.login) // Объект выстрела
-		if err != nil {
-			// log._rintf("ERRO DivWarOn.Run(): при создании выстрела танка, err=\n\t%v\n", err)
-			return
-		}
-		сам.health, err = health.НовЗдоровье(сам, сам.shot.IsEnd(), сам.login)
-		if err != nil {
-			// log._rintf("ERRO DivWarOn.Run(): при создании здоровья танка, err=\n\t%v\n", err)
-			сам.shot.IsEnd().Сброс()
-			return
-		}
-		сам.manevr, err = manevr.NewManevr(сам, сам.shot.IsEnd())
-		if err != nil {
-			// log._rintf("ERRO DivWarOn.Run(): при создании маневра танка, err=\n\t%v\n", err)
-			сам.shot.IsEnd().Сброс()
-			return
-		}
-	}
-	for { // Рабочий цикл сражения
-		select {
-		case <-сам.ctxDivWar.Done():
-			return
-		case <-сам.ВремяОстат().КаналСиг():
-			if сам.checkEnd() {
-				return
-			}
-		}
-	}
-}
-
-// Проверяет окончание сражения
-func (сам *DivWarOn) checkEnd() bool {
-	defer func() {
-		if сам.isEnd.Получ() {
-			сам.fnCancelDivWar()
-			// log._rintf("DivWarOn.checkEnd(): сражение завершено\n")
-		}
-	}()
-
-	сам.Обновить()
-	lstDivWarOn := сам.СписПолучить()
-	for _, strOut := range lstDivWarOn {
-		if strings.Contains(strOut, `" class="simple-but gray"><span><span>ОБЫЧНЫЕ</span></span></a>`) {
-			сам.isEnd.Сброс()
-			return false
-		}
-	}
-	сам.isEnd.Уст()
-	сам.fnCancelDivWar()
-	return true
-}
-
-// ЕслиКонец -- возвращает признак окончания сражения (интерфейс)
-func (сам *DivWarOn) ЕслиКонец() ИБезопБул {
-	return сам.isEnd
-}
-
-func (сам *DivWarOn) Манёвр() {
-	if сам.manevr == nil {
-		return
-	}
-	if сам.manevr.IsReady() {
-		сам.manevr.Manevr()
-	}
-}
-
-// ВыстрелБлок -- признак запрета стрельбы при слабом здоровье
-func (сам *DivWarOn) ВыстрелБлок() ИБезопБул {
-	return сам.isMasking
-}
-
-// Ctx -- возвращает контекст отмены сражения
-func (сам *DivWarOn) Ctx() context.Context {
-	return сам.ctxDivWar
-}
-
-// CancelBattle - -вызов функции отмены контекста сражения
-func (сам *DivWarOn) CancelBattle() {
-	сам.fnCancelDivWar()
-}

+ 0 - 48
app/lev2/arena_division/div_war/div_war_on/divwarsound/divwarsound.go

@@ -1,48 +0,0 @@
-package div_war_sound
-
-import (
-	"time"
-	"wartank/app/lev1/sound"
-	"wartank/app/lev2/arena_duel/battle_worker/battle_worker/battle_sound/is_sound_play"
-)
-
-/*
-	Выполняет контроль за запуском одной озвучки битвы
-*/
-
-// DivWarSound -- контроль одного раза запуска звука битвы
-type DivWarSound struct {
-	isPlay *is_sound_play.IsPlay
-}
-
-// NewDivWarSound -- возвращает новый  *DivWarSound
-func NewDivWarSound() *DivWarSound {
-	return &DivWarSound{
-		isPlay: is_sound_play.NewIsPlay(),
-	}
-}
-
-// Play -- играет музончик, если можно
-func (сам *DivWarSound) Play() {
-	if сам.isPlay.Get() {
-		return
-	}
-	go сам.play()
-}
-
-// Проигрывает экслюзивно в отдельном потоке звук
-func (сам *DivWarSound) play() {
-	сам.isPlay.Set()
-	val := 7
-	for val > 0 {
-		sound.DivWar()
-		val--
-		time.Sleep(time.Second * 1)
-	}
-	val = 600 // Пауза для блокировки повторного включения начатой битвы
-	for val >= 0 {
-		val--
-		time.Sleep(time.Second * 1)
-	}
-	сам.isPlay.Reset()
-}

+ 0 - 43
app/lev2/arena_division/div_war/div_war_on/manevr/is_manevr/ismanevr.go

@@ -1,43 +0,0 @@
-package is_manevr
-
-import (
-	"sync"
-)
-
-/*
-	Потокобезопасный признак внешнего разрешения манёвра
-*/
-
-// ЕслиМанёвр -- потокобезопасный признак внешнего разрешения манёвра
-type ЕслиМанёвр struct {
-	val   bool
-	block sync.RWMutex
-}
-
-// НовЕслиМанёвр -- возвращает новый *IsManevr
-func НовЕслиМанёвр() *ЕслиМанёвр {
-	return &ЕслиМанёвр{
-		val: true,
-	}
-}
-
-// Get -- возвращает хранимое состояние
-func (сам *ЕслиМанёвр) Get() bool {
-	сам.block.RLock()
-	defer сам.block.RUnlock()
-	return сам.val
-}
-
-// Set -- устанавливает хранимое состояние
-func (сам *ЕслиМанёвр) Set() {
-	сам.block.Lock()
-	defer сам.block.Unlock()
-	сам.val = true
-}
-
-// Reset -- сбрасывает хранимое состояние
-func (сам *ЕслиМанёвр) Reset() {
-	сам.block.Lock()
-	defer сам.block.Unlock()
-	сам.val = false
-}

+ 0 - 193
app/lev2/arena_division/div_war/div_war_on/manevr/manevr.go

@@ -1,193 +0,0 @@
-package manevr
-
-import (
-	"context"
-	"fmt"
-
-	// "log"
-	"strings"
-	"time"
-
-	"github.com/sirupsen/logrus"
-
-	"wartank/app/lev2/arena_division/div_war/div_war_on/health/repair_time"
-	"wartank/app/lev2/arena_division/div_war/div_war_on/manevr/is_manevr"
-
-	// "wartank/internal/components/sound"
-	. "wartank/app/lev0/types"
-	. "wartank/kernel/kernel_types"
-)
-
-/*
-	Пытается маневрировать после выстрела
-*/
-
-// Manevr -- маневрирует после выстрела
-type Manevr struct {
-	ИДивизияВойнаДействие // FIXME:
-	isEnd                 ИБезопБул
-	ctxEnd                context.Context
-	еслиМаневр            *is_manevr.ЕслиМанёвр   // Возможность выполнить манёвр
-	manevrTime            *repair_time.RepairTime // Время до восстановления манёвра
-	chTick                chan int                // Тики для поиска маневра
-}
-
-// NewManevr -- возвращает новый *Manevr
-func NewManevr(дивВойна ИДивизияВойнаДействие, isDivWar ИБезопБул) (*Manevr, error) {
-	{ // Предусловия
-		if дивВойна == nil {
-			return nil, fmt.Errorf("NewManevr(): battle is nil")
-		}
-	}
-	if isDivWar == nil {
-		return nil, fmt.Errorf("NewManevr(): isBattle is nil")
-	}
-	сам := &Manevr{
-		ИДивизияВойнаДействие: дивВойна,
-		ctxEnd:     дивВойна.Ctx(),
-		isEnd:      isDivWar,
-		еслиМаневр: is_manevr.НовЕслиМанёвр(),
-		manevrTime: repair_time.NewRepairTime(),
-		chTick:     make(chan int, 1),
-	}
-	_ = сам.manevrTime.Set("0") // При запуске боя есть возможность маневрировать
-	go сам.makeTick()
-	go сам.run()
-	return сам, nil
-}
-
-// Генерирует тик для уменьшения времени ожидания восстановления возможности манёвра
-func (сам *Manevr) makeTick() {
-	defer func() {
-		close(сам.chTick)
-		// log._rintf("Manevr.makeTick(): сражение завершено\n")
-	}()
-	for {
-		select {
-		case <-сам.ctxEnd.Done():
-			return
-		default:
-			if сам.manevrTime.Get() == 0 {
-				сам.chTick <- 1
-			}
-
-			сам.manevrTime.Dec()
-			time.Sleep(time.Second * 1)
-		}
-	}
-}
-
-// Рабочий цикл поиска маневра (~)
-func (сам *Manevr) run() {
-	for range сам.chTick {
-		if !сам.еслиМаневр.Get() {
-			continue
-		}
-		сам.findManevrTime()
-	}
-}
-
-// Ищет время для манёвра
-func (сам *Manevr) findManevrTime() {
-	var (
-		еслиНайдено bool
-		ind         int
-		lstBattleOn = сам.СписПолучить()
-		strOut      string
-	)
-	for ind, strOut = range lstBattleOn {
-		// <a href="pve?4-88.ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>5 секунд</span></span></a>
-		if strings.Contains(strOut, `-currentControl-maneuverLink`) {
-			еслиНайдено = true
-			break
-		}
-	}
-	if !еслиНайдено { // Или манёвр успел восстановиться, или конец сражения
-		if strings.Contains(strOut, `<span>Маневр</span>`) {
-			_ = сам.manevrTime.Set("0")
-			time.Sleep(time.Second * 1)
-			return
-		}
-		if сам.isEnd.Получ() {
-			time.Sleep(time.Second * 1)
-			return
-		}
-		logrus.WithField("strOut", strOut).Warn("Manevr.findManevrTime(): ошибка в поиске времени манёвра")
-		time.Sleep(time.Second * 1)
-		return
-	}
-	{ // Найти время манёвра
-		lstTime := strings.Split(strOut, `ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>`)
-		if len(lstTime) != 2 {
-			logrus.WithField("ind", ind).
-				WithField("lstBattleOn[-1]", lstBattleOn[ind-1]).
-				WithField("lstBattleOn[ind]", strOut).
-				WithField("lstBattleOn[+1]", lstBattleOn[ind+1]).
-				Errorf("Manevr.findManevrTime(): нет двух полей во времени ожидания")
-			сам.еслиМаневр.Reset()
-			time.Sleep(time.Second * 1)
-			return
-		}
-		strTime := lstTime[1]
-		lstTime = strings.Split(strTime, ` секунд</span></span></a>`)
-		strTime = lstTime[0]
-		if err := сам.manevrTime.Set(strTime); err != nil {
-			logrus.WithError(err).Error("Manevr.findManevrTime(): при обновлении времени ожидания манёвра")
-			сам.еслиМаневр.Reset()
-			time.Sleep(time.Second * 1)
-			return
-		}
-	}
-	сам.еслиМаневр.Set()
-	logrus.WithField("время", сам.manevrTime.Get()).Info("Manevr.findManevrTime(): до манёвра")
-}
-
-// Manevr -- принудительный манёвр по требованию
-func (сам *Manevr) Manevr() {
-	var (
-		еслиНайдено = false
-		lstBattleOn = сам.СписПолучить()
-		strOut      = ""
-	)
-	if !сам.еслиМаневр.Get() {
-		time.Sleep(time.Second * 1)
-		return
-	}
-	for _, strOut = range lstBattleOn {
-		// <a href="pve?4-21.ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>Маневр</span></span></a>
-		if strings.Contains(strOut, `<span>Маневр</span>`) {
-			еслиНайдено = true
-			break
-		}
-	}
-	if !еслиНайдено { // Либо ждём восстановления манёвра, либо сражение закончилось
-		сам.еслиМаневр.Reset()
-		time.Sleep(time.Second * 1)
-		return
-	}
-	{ // Попытка манёвра
-		lstLink := strings.Split(strOut, `<a href="`)
-		strLink := lstLink[1]
-		lstLink = strings.Split(strLink, `" class="simple-but blue"><span><span>Маневр</span></span></a>`)
-		strLink = "https://wartank.ru/" + lstLink[0]
-		lstBattleOn, err := сам.Сеть().Get(strLink)
-		if err != nil {
-			logrus.WithError(err).Error("Manevr.Manevr(): при выполнении GET-команды маневра")
-			сам.еслиМаневр.Reset()
-			time.Sleep(time.Second * 1)
-			return
-		}
-		if err = сам.СтрОбновить(lstBattleOn); err != nil {
-			logrus.WithError(err).Error("Manevr.Manevr(): при обновлении lstBattle")
-			сам.еслиМаневр.Reset()
-			time.Sleep(time.Second * 1)
-			return
-		}
-		// sound.Manevr()
-	}
-}
-
-// IsReady -- возвращает готовность манёвра
-func (сам *Manevr) IsReady() bool {
-	return сам.manevrTime.IsReady()
-}

+ 0 - 230
app/lev2/arena_division/div_war/div_war_on/shot/shot.go

@@ -1,230 +0,0 @@
-package shot
-
-import (
-	"context"
-	"fmt"
-	// "log"
-	"strconv"
-	"strings"
-	"time"
-
-	"wartank/app/lev2/arena_division/div_war/div_war_on/shot/damage"
-	"wartank/app/lev2/arena_division/div_war/div_war_on/shot_time"
-	// "wartank/internal/components/sound"
-	"wartank/app/lev0/alias"
-	. "wartank/app/lev0/types"
-	. "wartank/kernel/kernel_types"
-)
-
-/*
-	Исходник предоставляет выстрел со свойствами:
-		- время до выстрела
-		- длительность перезарядки
-
-	Первый параметр постоянно изменяется (после выстрела восстанавливается)
-	Второй параметр меняется медленно (в зависимости от количества очков после выстрела)
-*/
-
-// Shot -- объект выстрела
-type Shot struct {
-	ИДивизияВойнаДействие                     // FIXME:
-	recharge              *shot_time.ShotTime // Сколько времени нужно для полной перезарядки
-	damage                *damage.Damage      // Урон от выстрела с памятью
-	damageSum             alias.Урон          // Суммарный урон
-	isEnd                 ИБезопБул           // Признак конца сражения
-	login                 string              // Логин для поиска контрольных строк
-	chTick                chan int            // Тик для выстрела
-	ctxEnd                context.Context     // Признак окончания сражения
-}
-
-// NewShot -- возвращает новый *Shot
-func NewShot(divWar ИДивизияВойнаДействие, login string) (*Shot, error) {
-	{ // Предусловия
-		if divWar == nil {
-			return nil, fmt.Errorf("NewShot(): battle is nil")
-		}
-		if login == "" {
-			return nil, fmt.Errorf("NewShot(): login is empty")
-		}
-	}
-	сам := &Shot{
-		ИДивизияВойнаДействие: divWar,
-		ctxEnd:   divWar.Ctx(),
-		recharge: shot_time.NewShotTime(),
-		damage:   damage.NewDamage(),
-		isEnd:    divWar.ЕслиКонец(),
-		login:    login,
-		chTick:   make(chan int, 2),
-	}
-	// Установить время перезарядки
-	сам.recharge.Set(6800)
-	go сам.makeTick()
-	go сам.run()
-	return сам, nil
-}
-
-// Генерирует тики, когда можно стрелять
-func (сам *Shot) makeTick() {
-	defer func() {
-		сам.isEnd.Уст()
-		close(сам.chTick)
-		сам.CancelBattle()
-		// log._rintf("Shot.makeTick(): сражение завершёно\n")
-	}()
-	countMasking := 0
-	for {
-		select {
-		case <-сам.ctxEnd.Done():
-			return
-		default:
-			if сам.isEnd.Получ() { // Битва закончилась
-				return
-			}
-			switch сам.ВыстрелБлок().Получ() { // Проверить запрет на стрельбу при слабом здоровье
-			case true:
-				// log._rintf("WARN Shot.run(): запрет на выстрел\n")
-				countMasking++
-				if countMasking >= 200 {
-					return
-				}
-				сам.Манёвр()
-				time.Sleep(time.Millisecond * 500)
-				continue
-			default:
-				countMasking = 0
-			}
-			сам.chTick <- 1 // Здесь же первый выстрел
-			recharge := сам.recharge.Get()
-			// log._rintf("INFO Shot.run() перезарядка=%v msec\n", recharge)
-			// Если идёт перезарядка -- постепенно обнуляем время ожидания
-			time.Sleep(time.Millisecond * time.Duration(recharge))
-		}
-	}
-}
-
-// Цикл выстрела (в отдельном потоке)
-func (сам *Shot) run() {
-	for {
-		select {
-		case <-сам.ctxEnd.Done():
-			return
-		case <-сам.chTick:
-			// Стрелять можно, стандартное ожидание
-			сам.shot()
-			сам.findDamage()
-		}
-	}
-}
-
-// Обновляет возможность выстрела (~)
-//
-//	Вызывается из отдельного потока
-func (сам *Shot) shot() {
-	сам.Сеть().Обновить()
-	var (
-		strOut      string
-		lstBattle   = сам.СписПолучить()
-		еслиНайдено bool
-		err         error
-	)
-	// <a href="pve?6-26.ILinkListener-currentControl-attackRegularShellLink" class="simple-but gray"><span><span>ОБЫЧНЫЕ</span></span></a>
-	for _, strOut = range lstBattle {
-		if strings.Contains(strOut, `-currentControl-attackRegularShellLink`) {
-			еслиНайдено = true
-			break
-		}
-	}
-	if !еслиНайдено {
-		// log._rintf("WARN Shot.shot(): не найдены ссылка на выстрел\n")
-		сам.isEnd.Уст()
-		сам.CancelBattle()
-		return
-	}
-	lstLink := strings.Split(strOut, `<a href="`)
-	strLink := lstLink[1]
-	lstLink = strings.Split(strLink, `" class="simple-but gray"><span><span>ОБЫЧНЫЕ</span></span></a>`)
-	strLink = "https://wartank.ru/" + lstLink[0]
-	lstBattle, err = сам.Сеть().Get(strLink)
-	if err != nil {
-		// log._rintf("ERRO Shot.shot(): при исполнении GET-команды выстрела обычным снарядом, err=\n\t%v\n", err)
-		сам.isEnd.Уст()
-		сам.CancelBattle()
-		return
-	}
-	if err = сам.СтрОбновить(lstBattle); err != nil {
-		// log._rintf("ERRO Shot.shot(): при обновлении lstBattle, err=\n\t%v\n", err)
-		сам.isEnd.Уст()
-		сам.CancelBattle()
-		return
-	}
-	// sound.Shot()
-	сам.Манёвр()
-}
-
-// Ищет урон от выстрела
-func (сам *Shot) findDamage() {
-	var (
-		ind         int
-		еслиНайдено bool
-		lstShot     = сам.СписПолучить()
-		strOut      string
-	)
-
-	for ind, strOut = range lstShot {
-		// <span class="yellow1 td_u">prospero tank</span>
-		if strings.Contains(strOut, `<span class="yellow1 td_u">`+сам.login+`</span>`) {
-			ind += 2
-			strOut = lstShot[ind]
-			еслиНайдено = true
-			break
-		}
-	}
-	if !еслиНайдено { // Возможно был рикошет или манёвр
-		// log._rintf("WARN Shot.findDamage(): не найден урон от выстрела, strOut=%q, ind=%v\n", strOut, ind)
-		return
-	}
-	lstDamage := strings.Split(strOut, ` на  <span class="red1">`)
-	if len(lstDamage) == 1 {
-		return
-	}
-	strDamage := lstDamage[1]
-	iDamage, err := strconv.Atoi(strDamage)
-	if err != nil {
-		// log._rintf("ERRO Shot.findDamage(): damage(%v) не число, err=\n\t%v\n", strDamage, err)
-		return
-	}
-	if iDamage <= 0 { // Кривой урон от выстрела
-		сам.recharge.Dec5()
-		// log._rintf("WARN Shot.findDamage(): ошибка в значении урона(%v)\n", iDamage)
-		iDamage = 0
-	}
-	сам.damageSum += alias.Урон(iDamage)
-	// log._rintf("INFO Shot.Damage(): damageSum=%v\n", сам.damageSum)
-	if iDamage < 70 {
-		сам.damage.Set(alias.Урон(iDamage))
-		сам.recharge.Inc210()
-	}
-	// log._rintf("INFO Shot.findDamage(): выстрел=+%v, урон=%v", iDamage, сам.damageSum)
-	if iDamage == 0 {
-		return
-	}
-	сам.setDamage(alias.Урон(iDamage))
-}
-
-// setDamage -- обновляет время перезарядки в зависимости от произведённого урона
-func (сам *Shot) setDamage(val alias.Урон) {
-	сам.damage.Set(val)
-	switch сам.damage.Result() {
-	case "none":
-		сам.recharge.Dec5()
-	case "up":
-		сам.recharge.Dec30()
-	case "down":
-		сам.recharge.Inc210()
-	}
-}
-
-// IsEnd -- возвращает объект разрешения стрельбы
-func (сам *Shot) IsEnd() ИБезопБул {
-	return сам.isEnd
-}

+ 0 - 178
app/lev2/arena_division/div_war/divwaron/divwaron.go

@@ -1,178 +0,0 @@
-package div_war_on
-
-import (
-	"context"
-	"fmt"
-	"strings"
-	"time"
-
-	. "wartank/app/lev0/types"
-	"wartank/app/lev2/arena"
-		"wartank/app/lev1/health"
-	"wartank/app/lev3/bot/angar/division/div_war/div_war_on/manevr"
-	"wartank/app/lev3/bot/angar/division/div_war/div_war_on/shot"
-	"wartank/kernel"
-	. "wartank/kernel/kernel_types"
-)
-
-/*
-	Предоставляет сетевой компонент при непосредственном сражении
-*/
-
-// DivWarOn -- непосредственно танкует в сражении
-type DivWarOn struct {
-	ИАрена
-	bot            ИБот
-	ctxDivWar      context.Context // Контекст сражения
-	fnCancelDivWar func()          // Функция отмены сражения
-
-	shot      *shot.Shot       // Объект выстрела
-	health    *health.Здоровье // Текущее здоровье танка
-	manevr    *manevr.Manevr   // Возможность маневрирования
-	login     string
-	isMasking ИБезопБул // Признак необходимости маскирования (запрет стрельбы, когда слабое здоровье)
-	chTick    chan int  // Ежесекундная проверка на окончание сражения
-	isEnd     ИБезопБул
-}
-
-// NewDivWarOn -- возвращает новый *DivWarOn
-func NewDivWarOn(конт ИЯдроКонтекст, bot ИБот) (*DivWarOn, error) {
-	if bot == nil {
-		return nil, fmt.Errorf("NewDivWarOn(): IBot == nil")
-	}
-	ctxDivWar, fnCancelDivWar := context.WithTimeout(bot.Контекст(), time.Second*305)
-	сам := &DivWarOn{
-		bot:            bot,
-		ctxDivWar:      ctxDivWar,
-		fnCancelDivWar: fnCancelDivWar,
-		login:          bot.Имя(),
-		isMasking:      kernel.НовБезопБул(),
-		isEnd:          kernel.НовБезопБул(),
-	}
-	аренаКонфиг := arena.АренаКонфиг{
-		Бот_:         bot,
-		АренаИмя_:    "Сражение",
-		СтрКонтроль_: `<title>Сражения</title>`,
-		ФнПуск_:      сам.пуск,
-		СтрУрл_:      "https://wartank.ru/pve",
-	}
-	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
-	if сам.checkEnd() {
-		return nil, fmt.Errorf("NewDivWarOn(): нет страницы для сражения")
-	}
-	go сам.makeTick()
-	go сам.run()
-	return сам, nil
-}
-
-// пускает сражение
-func (сам *DivWarOn) пуск() {
-}
-
-// Ежесекудный тик
-func (сам *DivWarOn) makeTick() {
-	defer func() {
-		close(сам.chTick)
-		сам.isEnd.Уст()
-	}()
-	for !сам.isEnd.Получ() {
-		select {
-		case <-сам.bot.Контекст().Done(): // Отмена контекста приложения
-			return
-		case <-сам.ctxDivWar.Done(): // Битва закончилась
-			return
-		default:
-			if сам.isEnd.Получ() {
-				return
-			}
-			сам.chTick <- 1
-			time.Sleep(time.Second * 1)
-		}
-	}
-}
-
-// запускает сражение
-func (сам *DivWarOn) run() {
-	// defer log._rintf("DivWarOn.run(): сражение завершено\n")
-	{ // Подготовка к сражению
-		var err error
-		сам.shot, err = shot.NewShot(сам, сам.login) // Объект выстрела
-		if err != nil {
-			// log._rintf("ERRO DivWarOn.Run(): при создании выстрела танка, err=\n\t%v\n", err)
-			return
-		}
-		сам.health, err = health.НовЗдоровье(сам, сам.shot.IsEnd(), сам.login)
-		if err != nil {
-			// log._rintf("ERRO DivWarOn.Run(): при создании здоровья танка, err=\n\t%v\n", err)
-			сам.shot.IsEnd().Сброс()
-			return
-		}
-		сам.manevr, err = manevr.NewManevr(сам, сам.shot.IsEnd())
-		if err != nil {
-			// log._rintf("ERRO DivWarOn.Run(): при создании маневра танка, err=\n\t%v\n", err)
-			сам.shot.IsEnd().Сброс()
-			return
-		}
-	}
-	for { // Рабочий цикл сражения
-		select {
-		case <-сам.ctxDivWar.Done():
-			return
-		case <-сам.ВремяОстат().КаналСиг():
-			if сам.checkEnd() {
-				return
-			}
-		}
-	}
-}
-
-// Проверяет окончание сражения
-func (сам *DivWarOn) checkEnd() bool {
-	defer func() {
-		if сам.isEnd.Получ() {
-			сам.fnCancelDivWar()
-			// log._rintf("DivWarOn.checkEnd(): сражение завершено\n")
-		}
-	}()
-
-	сам.Обновить()
-	lstDivWarOn := сам.СписПолучить()
-	for _, strOut := range lstDivWarOn {
-		if strings.Contains(strOut, `" class="simple-but gray"><span><span>ОБЫЧНЫЕ</span></span></a>`) {
-			сам.isEnd.Сброс()
-			return false
-		}
-	}
-	сам.isEnd.Уст()
-	сам.fnCancelDivWar()
-	return true
-}
-
-// ЕслиКонец -- возвращает признак окончания сражения (интерфейс)
-func (сам *DivWarOn) ЕслиКонец() ИБезопБул {
-	return сам.isEnd
-}
-
-func (сам *DivWarOn) Манёвр() {
-	if сам.manevr == nil {
-		return
-	}
-	if сам.manevr.IsReady() {
-		сам.manevr.Manevr()
-	}
-}
-
-// ВыстрелБлок -- признак запрета стрельбы при слабом здоровье
-func (сам *DivWarOn) ВыстрелБлок() ИБезопБул {
-	return сам.isMasking
-}
-
-// Ctx -- возвращает контекст отмены сражения
-func (сам *DivWarOn) Ctx() context.Context {
-	return сам.ctxDivWar
-}
-
-// CancelBattle - -вызов функции отмены контекста сражения
-func (сам *DivWarOn) CancelBattle() {
-	сам.fnCancelDivWar()
-}

+ 1 - 1
app/lev2/arena_division/div_war/div_war_on/div_war_sound/div_war_sound.go → app/lev2/arena_division/div_war/process_divwar/div_war_sound/div_war_sound.go

@@ -3,7 +3,7 @@ package div_war_sound
 import (
 	"time"
 	"wartank/app/lev1/sound"
-	"wartank/app/lev2/arena_duel/battle_worker/battle_worker/battle_sound/is_sound_play"
+	"wartank/app/lev1/sound/is_sound_play"
 )
 
 /*

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


+ 157 - 0
app/lev2/arena_division/div_war/process_divwar/process_divwar.go

@@ -0,0 +1,157 @@
+package process_divwar
+
+import (
+	"context"
+	"strings"
+	"time"
+
+	. "wartank/app/lev0/types"
+	"wartank/app/lev1/health"
+	"wartank/app/lev1/manevr"
+	"wartank/app/lev1/shot"
+	"wartank/app/lev2/arena"
+	"wartank/kernel"
+	. "wartank/kernel/kernel_types"
+)
+
+/*
+	Предоставляет сетевой компонент при непосредственном сражении
+*/
+
+// ПроцессДивизияВойна -- непосредственно танкует в сражении
+type ПроцессДивизияВойна struct {
+	ИАрена
+	бот            ИБот
+	лог ИЯдроЛог
+	ctxDivWar      context.Context // Контекст сражения
+	fnCancelDivWar func()          // Функция отмены сражения
+
+	выстрел  ИВыстрел  // Объект выстрела
+	здоровье ИЗдоровье // Текущее здоровье танка
+	манёвр   ИМанёвр   // Возможность маневрирования
+	логин    string
+	chTick   chan int // Ежесекундная проверка на окончание сражения
+	isEnd    ИБезопБул
+}
+
+// НовПроцессДивизияВойна -- возвращает новый *DivWarOn
+func НовПроцессДивизияВойна(конт ИБотКонтекст) ИСражениеПроцесс {
+	лог:=kernel.НовЛог("ПроцессДивизияВойна")
+	бот:=конт.Получ("бот").(ИБот)
+	ctxDivWar, fnCancelDivWar := context.WithTimeout(бот.Контекст(), time.Second*305)
+	сам := &ПроцессДивизияВойна{
+		бот:            бот,
+		лог:лог,
+		ctxDivWar:      ctxDivWar,
+		fnCancelDivWar: fnCancelDivWar,
+		логин:          бот.Имя(),
+		isEnd:          kernel.НовБезопБул(),
+	}
+	аренаКонфиг := arena.АренаКонфиг{
+		Бот_:         бот,
+		АренаИмя_:    "Сражение",
+		СтрКонтроль_: `<title>Сражения</title>`,
+		ФнПуск_:      сам.пуск,
+		СтрУрл_:      "https://wartank.ru/pve",
+	}
+	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
+	if сам.checkEnd() {
+		return nil
+	}
+	go сам.makeTick()
+	go сам.run()
+	return сам
+}
+
+// Манёвр -- возвращает объект манёвра
+func (сам *ПроцессДивизияВойна) Манёвр() ИМанёвр {
+	return сам.манёвр
+}
+
+// Выстрел -- возвращает объект выстрела
+func (сам *ПроцессДивизияВойна) Выстрел() ИВыстрел {
+	return сам.выстрел
+}
+
+// пускает сражение
+func (сам *ПроцессДивизияВойна) пуск() {
+}
+
+// Ежесекудный тик
+func (сам *ПроцессДивизияВойна) makeTick() {
+	defer func() {
+		close(сам.chTick)
+		сам.isEnd.Уст()
+	}()
+	for !сам.isEnd.Получ() {
+		select {
+		case <-сам.бот.Контекст().Done(): // Отмена контекста приложения
+			return
+		case <-сам.ctxDivWar.Done(): // Битва закончилась
+			return
+		default:
+			if сам.isEnd.Получ() {
+				return
+			}
+			сам.chTick <- 1
+			time.Sleep(time.Second * 1)
+		}
+	}
+}
+
+// запускает сражение
+func (сам *ПроцессДивизияВойна) run() {
+	// defer log._rintf("ПроцессДивизияВойна.run(): сражение завершено\n")
+	{ // Подготовка к сражению
+		сам.выстрел = shot.НовВыстрел(сам) // Объект выстрела
+		сам.здоровье = health.НовЗдоровье(сам)
+		сам.манёвр = manevr.НовМанёвр(сам)
+	}
+	for { // Рабочий цикл сражения
+		select {
+		case <-сам.ctxDivWar.Done():
+			return
+		case <-сам.ВремяОстат().КаналСиг():
+			if сам.checkEnd() {
+				return
+			}
+		}
+	}
+}
+
+// Проверяет окончание сражения
+func (сам *ПроцессДивизияВойна) checkEnd() bool {
+	defer func() {
+		if сам.isEnd.Получ() {
+			сам.fnCancelDivWar()
+			// log._rintf("DivWarOn.checkEnd(): сражение завершено\n")
+		}
+	}()
+
+	сам.Обновить()
+	lstDivWarOn := сам.СписПолучить()
+	for _, strOut := range lstDivWarOn {
+		if strings.Contains(strOut, `" class="simple-but gray"><span><span>ОБЫЧНЫЕ</span></span></a>`) {
+			сам.isEnd.Сброс()
+			return false
+		}
+	}
+	сам.isEnd.Уст()
+	сам.fnCancelDivWar()
+	return true
+}
+
+// ЕслиКонец -- возвращает признак окончания сражения (интерфейс)
+func (сам *ПроцессДивизияВойна) ЕслиКонец() ИБезопБул {
+	return сам.isEnd
+}
+
+// Ctx -- возвращает контекст отмены сражения
+func (сам *ПроцессДивизияВойна) Ctx() context.Context {
+	return сам.ctxDivWar
+}
+
+// CancelBattle - -вызов функции отмены контекста сражения
+func (сам *ПроцессДивизияВойна) CancelBattle() {
+	сам.fnCancelDivWar()
+}

+ 16 - 38
app/lev2/arena_division/divwar/div_war_on/div_war_on.go

@@ -7,10 +7,10 @@ import (
 	"time"
 
 	. "wartank/app/lev0/types"
+	"wartank/app/lev1/health"
+	"wartank/app/lev1/manevr"
+	"wartank/app/lev1/shot"
 	"wartank/app/lev2/arena"
-		"wartank/app/lev1/health"
-	"wartank/app/lev3/bot/angar/division/div_war/div_war_on/manevr"
-	"wartank/app/lev3/bot/angar/division/div_war/div_war_on/shot"
 	"wartank/kernel"
 	. "wartank/kernel/kernel_types"
 )
@@ -26,13 +26,12 @@ type DivWarOn struct {
 	ctxDivWar      context.Context // Контекст сражения
 	fnCancelDivWar func()          // Функция отмены сражения
 
-	shot      *shot.Shot       // Объект выстрела
-	health    *health.Здоровье // Текущее здоровье танка
-	manevr    *manevr.Manevr   // Возможность маневрирования
-	login     string
-	isMasking ИБезопБул // Признак необходимости маскирования (запрет стрельбы, когда слабое здоровье)
-	chTick    chan int  // Ежесекундная проверка на окончание сражения
-	isEnd     ИБезопБул
+	выстрел ИВыстрел  // Объект выстрела
+	health  ИЗдоровье // Текущее здоровье танка
+	manevr  ИМанёвр   // Возможность маневрирования
+	login   string
+	chTick  chan int // Ежесекундная проверка на окончание сражения
+	isEnd   ИБезопБул
 }
 
 // NewDivWarOn -- возвращает новый *DivWarOn
@@ -46,7 +45,6 @@ func NewDivWarOn(конт ИЯдроКонтекст, bot ИБот) (*DivWarOn,
 		ctxDivWar:      ctxDivWar,
 		fnCancelDivWar: fnCancelDivWar,
 		login:          bot.Имя(),
-		isMasking:      kernel.НовБезопБул(),
 		isEnd:          kernel.НовБезопБул(),
 	}
 	аренаКонфиг := arena.АренаКонфиг{
@@ -95,24 +93,9 @@ func (сам *DivWarOn) makeTick() {
 func (сам *DivWarOn) run() {
 	// defer log._rintf("DivWarOn.run(): сражение завершено\n")
 	{ // Подготовка к сражению
-		var err error
-		сам.shot, err = shot.NewShot(сам, сам.login) // Объект выстрела
-		if err != nil {
-			// log._rintf("ERRO DivWarOn.Run(): при создании выстрела танка, err=\n\t%v\n", err)
-			return
-		}
-		сам.health, err = health.НовЗдоровье(сам, сам.shot.IsEnd(), сам.login)
-		if err != nil {
-			// log._rintf("ERRO DivWarOn.Run(): при создании здоровья танка, err=\n\t%v\n", err)
-			сам.shot.IsEnd().Сброс()
-			return
-		}
-		сам.manevr, err = manevr.NewManevr(сам, сам.shot.IsEnd())
-		if err != nil {
-			// log._rintf("ERRO DivWarOn.Run(): при создании маневра танка, err=\n\t%v\n", err)
-			сам.shot.IsEnd().Сброс()
-			return
-		}
+		сам.выстрел = shot.НовВыстрел(сам) // Объект выстрела
+		сам.health = health.НовЗдоровье(сам)
+		сам.manevr = manevr.НовМанёвр(сам)
 	}
 	for { // Рабочий цикл сражения
 		select {
@@ -153,18 +136,13 @@ func (сам *DivWarOn) ЕслиКонец() ИБезопБул {
 	return сам.isEnd
 }
 
-func (сам *DivWarOn) Манёвр() {
-	if сам.manevr == nil {
-		return
-	}
-	if сам.manevr.IsReady() {
-		сам.manevr.Manevr()
-	}
+func (сам *DivWarOn) Манёвр() ИМанёвр {
+	return сам.manevr
 }
 
 // ВыстрелБлок -- признак запрета стрельбы при слабом здоровье
-func (сам *DivWarOn) ВыстрелБлок() ИБезопБул {
-	return сам.isMasking
+func (сам *DivWarOn) Выстрел() ИВыстрел {
+	return сам.выстрел
 }
 
 // Ctx -- возвращает контекст отмены сражения

+ 4 - 10
app/lev2/arena_division/divwar/divwar.go

@@ -12,8 +12,8 @@ import (
 	"wartank/app/lev1/stat_param"
 	"wartank/app/lev2/arena"
 	"wartank/app/lev2/arena_division/div_war/div_war_net"
-	"wartank/app/lev2/arena_division/div_war/div_war_on"
-	"wartank/app/lev2/arena_division/div_war/div_war_on/div_war_sound"
+	"wartank/app/lev2/arena_division/div_war/process_divwar"
+	"wartank/app/lev2/arena_division/div_war/process_divwar/div_war_sound"
 )
 
 /*
@@ -30,7 +30,7 @@ type DivWar struct {
 	conn  ИХттпВоркер
 
 	// Непосредственная битва
-	дивОн *div_war_on.DivWarOn
+	дивОн *process_divwar.ПроцессДивизияВойна
 	login string // Для непосредственной битвы дивизий
 	block sync.Mutex
 
@@ -202,13 +202,7 @@ func (сам *DivWar) DivWar() {
 		}
 		// log.Printf("INFO DivWar.DivWar(): сражение завершено\n")
 	}()
-	var err error
-	сам.дивОн, err = div_war_on.NewDivWarOn(сам.конт, сам.bot) // IDivWarOn (онлайн)
-	if err != nil {
-		// log._rintf("ERRO DivWar.DivWarOn(): при создании IDivWarOn, err=\n\t%v\n", err)
-		time.Sleep(time.Millisecond * 250)
-		return
-	}
+	сам.дивОн = process_divwar.НовПроцессДивизияВойна(сам.конт) // IDivWarOn (онлайн)
 	// Цикл ожидания окончания сражения
 	for !сам.дивОн.ЕслиКонец().Получ() {
 		time.Sleep(time.Second * 1)

+ 11 - 31
app/lev2/arena_division/divwar/divwaron/divwaron.go

@@ -7,10 +7,10 @@ import (
 	"time"
 
 	. "wartank/app/lev0/types"
+	"wartank/app/lev1/health"
+	"wartank/app/lev1/manevr"
+	"wartank/app/lev1/shot"
 	"wartank/app/lev2/arena"
-		"wartank/app/lev1/health"
-	"wartank/app/lev3/bot/angar/division/div_war/div_war_on/manevr"
-	"wartank/app/lev3/bot/angar/division/div_war/div_war_on/shot"
 	"wartank/kernel"
 	. "wartank/kernel/kernel_types"
 )
@@ -26,9 +26,9 @@ type DivWarOn struct {
 	ctxDivWar      context.Context // Контекст сражения
 	fnCancelDivWar func()          // Функция отмены сражения
 
-	shot      *shot.Shot       // Объект выстрела
-	health    *health.Здоровье // Текущее здоровье танка
-	manevr    *manevr.Manevr   // Возможность маневрирования
+	shot      ИВыстрел    // Объект выстрела
+	health    ИЗдоровье // Текущее здоровье танка
+	manevr    ИМанёвр   // Возможность маневрирования
 	login     string
 	isMasking ИБезопБул // Признак необходимости маскирования (запрет стрельбы, когда слабое здоровье)
 	chTick    chan int  // Ежесекундная проверка на окончание сражения
@@ -95,24 +95,9 @@ func (сам *DivWarOn) makeTick() {
 func (сам *DivWarOn) run() {
 	// defer log._rintf("DivWarOn.run(): сражение завершено\n")
 	{ // Подготовка к сражению
-		var err error
-		сам.shot, err = shot.NewShot(сам, сам.login) // Объект выстрела
-		if err != nil {
-			// log._rintf("ERRO DivWarOn.Run(): при создании выстрела танка, err=\n\t%v\n", err)
-			return
-		}
-		сам.health, err = health.НовЗдоровье(сам, сам.shot.IsEnd(), сам.login)
-		if err != nil {
-			// log._rintf("ERRO DivWarOn.Run(): при создании здоровья танка, err=\n\t%v\n", err)
-			сам.shot.IsEnd().Сброс()
-			return
-		}
-		сам.manevr, err = manevr.NewManevr(сам, сам.shot.IsEnd())
-		if err != nil {
-			// log._rintf("ERRO DivWarOn.Run(): при создании маневра танка, err=\n\t%v\n", err)
-			сам.shot.IsEnd().Сброс()
-			return
-		}
+		сам.shot = shot.НовВыстрел(сам) // Объект выстрела
+		сам.health = health.НовЗдоровье(сам)
+		сам.manevr = manevr.НовМанёвр(сам)
 	}
 	for { // Рабочий цикл сражения
 		select {
@@ -153,13 +138,8 @@ func (сам *DivWarOn) ЕслиКонец() ИБезопБул {
 	return сам.isEnd
 }
 
-func (сам *DivWarOn) Манёвр() {
-	if сам.manevr == nil {
-		return
-	}
-	if сам.manevr.IsReady() {
-		сам.manevr.Manevr()
-	}
+func (сам *DivWarOn) Манёвр()ИМанёвр {
+	return сам.manevr
 }
 
 // ВыстрелБлок -- признак запрета стрельбы при слабом здоровье

+ 0 - 19
app/lev2/arena_duel/arena_duel.go

@@ -6,9 +6,6 @@ import (
 
 	. "wartank/app/lev0/types"
 	"wartank/app/lev2/arena"
-	"wartank/app/lev2/arena_duel/battle_register"
-	"wartank/app/lev2/arena_duel/battle_wait"
-	"wartank/app/lev2/arena_duel/battle_worker"
 )
 
 // АренаДуэль -- арена дуэли за топливо
@@ -16,11 +13,6 @@ type АренаДуэль struct {
 	ИАрена
 	бот    ИБот
 	клиент ИХттпВоркер
-
-	регистрация *battle_register.СхваткаРегистрация // Регистратор на сражение
-	ожидание    *battle_wait.СхваткаОжидание        // Ожидатель начала сражения
-	действие    *battle_worker.СхваткаИсполнитель   // Исполнитель сражения
-
 }
 
 // НовСражение -- возвращает новую арену дуэли
@@ -37,9 +29,6 @@ func НовАренаДуэль(конт ИБотКонтекст, бот ИБо
 		СтрУрл_:      "https://wartank.ru/battle",
 	}
 	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
-	сам.регистрация = battle_register.НовСражениеРегистрация(конт, бот)
-	сам.ожидание = battle_wait.НовСражениеОжидание(конт, бот)
-	сам.действие = battle_worker.НовСражениеИсполнитель(конт, бот)
 
 	// сам.shotTimeFull.Set(8000) // 8000 msec
 	return сам
@@ -56,15 +45,7 @@ func (сам *АренаДуэль) пуск() {
 		case <-сам.бот.Контекст().Done():
 			return
 		default:
-			сам.регистрация.Зарегистрироваться()
-			сам.ожидание.Ожидать()
-			сам.действие.Пуск()
 			time.Sleep(time.Second * 2) // Пауза между циклами, чтобы сервер не долбить запросами
 		}
 	}
 }
-
-// ЕслиНачало -- возвращает признак начала сражения (для браузера)
-func (сам *АренаДуэль) ЕслиНачало() ИСтатПарам {
-	return сам.действие.Тревога()
-}

+ 4 - 4
app/lev2/arena_polygon/arena_polygon.go

@@ -97,7 +97,7 @@ func (сам *АренаПолигон) пуск() {
 	ош := сам.ОбратВремяУст("02")
 	if ош != nil {
 		log.Printf("Полигон(): при установке времени обратного отсчета, ош=\n\t%v\n", ош)
-		сам.бот.Сервер().Отменить()
+		сам.Отменить()
 		return
 	}
 	фнРабота := func() {
@@ -125,7 +125,7 @@ func (сам *АренаПолигон) пуск() {
 			ош := сам.ВремяОстат().Уст("00:10:00")
 			if ош != nil {
 				log.Printf("Полигон(): при установке времени обратного отсчета, ош=\n\t%v\n", ош)
-				сам.бот.Сервер().Отменить()
+				сам.Отменить()
 				return
 			}
 		}
@@ -335,7 +335,7 @@ func (сам *АренаПолигон) времяОбнов() {
 			ош := сам.ОбратВремяУст("05")
 			if ош != nil {
 				log.Printf("Полигон.времяОбнов(): при установке обратного времени ожидания полигона, ош=\n\t%v\n", ош)
-				сам.бот.Сервер().Отменить()
+				сам.Отменить()
 				return
 			}
 		}
@@ -414,7 +414,7 @@ func (сам *АренаПолигон) усилениеДобавить() {
 	// log._rintf("Polygon.checkPolygon(): при принудительном обновлении lstPolygon, mode=%s\terr=\n\t%v\n", сам.ModeCurrent().Get(), err)
 	if err := сам.ОбратВремяУст("05"); err != nil {
 		log.Printf("Polygon.checkPolygon(): при принудительном обновлении обратного времени, время=`05`\terr=\n\t%v\n", err)
-		сам.бот.Сервер().Отменить()
+		сам.Отменить()
 		return
 	}
 	lstPolygon := сам.СписПолучить()

+ 0 - 222
app/lev3/bot/angar/division/div_war/div_war.go

@@ -1,222 +0,0 @@
-package div_war
-
-import (
-	"fmt"
-	"log"
-	"strings"
-	"sync"
-	"time"
-
-	"wartank/app/lev0/alias"
-	. "wartank/app/lev0/types"
-	"wartank/app/lev1/stat_param"
-	"wartank/app/lev2/arena"
-	"wartank/app/lev2/arena_division/div_war/div_war_net"
-	"wartank/app/lev2/arena_division/div_war/div_war_on"
-	"wartank/app/lev2/arena_division/div_war/div_war_on/div_war_sound"
-	. "wartank/kernel/kernel_types"
-)
-
-/*
-	Объект ожидания битвы дивизий
-*/
-
-// DivWar -- объект ожидания битвы дивизий
-type DivWar struct {
-	ИАрена
-	конт  ИЯдроКонтекст
-	bot   ИБот
-	alarm ИСтатПарам
-	net   *div_war_net.DivWarNet
-	conn  ИХттпВоркер
-
-	// Непосредственная битва
-	divOn *div_war_on.DivWarOn
-	login string // Для непосредственной битвы дивизий
-	block sync.Mutex
-
-	chDivWar chan int // Сигнал начала битвы дивизий
-
-	sound *div_war_sound.DivWarSound // Однопоточное проигрывание звука
-}
-
-// NewDivWar -- возвращает новый *DivWar
-func NewDivWar(конт ИЯдроКонтекст, bot ИБот) (*DivWar, error) {
-	if bot == nil {
-		return nil, fmt.Errorf("NewDivWar(): IBot == nil")
-	}
-	сам := &DivWar{
-		bot:      bot,
-		alarm:    stat_param.НовСтатПарам("тревога"),
-		chDivWar: make(chan int, 1),
-		sound:    div_war_sound.NewDivWarSound(),
-		conn:     bot.Сеть().ВебВоркер(),
-		login:    "prospero tank",
-	}
-	аренаКонфиг := arena.АренаКонфиг{
-		Бот_:         bot,
-		АренаИмя_:    "Битва дивизий",
-		СтрКонтроль_: `<span>до начала `,
-		ФнПуск_:      сам.пуск,
-	}
-	сам.ИАрена = arena.НовАрена(конт, аренаКонфиг)
-	// сам.shotTimeFull.Set(8000) // 8000 msec
-	var err error
-	{ // Net
-		сам.net, err = div_war_net.NewDivWarNet(bot)
-		if err != nil {
-			return nil, fmt.Errorf("NewDivWar(): при создании DivWarNet, err=\n\t%w", err)
-		}
-	}
-	go сам.run()
-	go сам.резервТик()
-	return сам, nil
-}
-
-// запускает в работу битву дивизий
-func (сам *DivWar) пуск() {
-}
-
-func (сам *DivWar) резервТик() {
-	for {
-		select {
-		case <-сам.bot.Контекст().Done():
-			return
-		default:
-			ct0 := сам.ВремяОстат().ПолучМилСек()
-			time.Sleep(time.Second * 7)
-			ct1 := сам.ВремяОстат().ПолучМилСек()
-			if ct1.Сек() != ct0.Сек() {
-				continue
-			}
-			if сам.divOn != nil {
-				continue
-			}
-			сам.chDivWar <- 1
-		}
-	}
-}
-
-// запускает в работу битву дивизий
-func (сам *DivWar) run() {
-	сам.chDivWar <- 1
-	for {
-		select {
-		case <-сам.bot.Контекст().Done():
-			return
-		case <-сам.ВремяОстат().КаналСиг(): // Время обновить данные по сражению
-			сам.findTimeCount()
-			сам.upDivWar()
-		case <-сам.chDivWar: // Сигнал к началу сражения
-			сам.block.Lock()
-			if сам.divOn != nil {
-				continue
-			}
-			сам.alarm.Уст(1)
-			сам.sound.Play()
-			go сам.DivWar()              // Запустить цикл непосредственного сражения
-			time.Sleep(time.Second * 10) // Задержка для звука на странице
-			сам.alarm.Уст(0)
-		}
-	}
-}
-
-// Ищет время до начала битвы дивизий
-func (сам *DivWar) findTimeCount() {
-	сам.net.Обновить()
-	var (
-		strOut      string
-		lstDivWar   = сам.СписПолучить()
-		еслиНайдено bool
-		ind         int
-	)
-	for ind, strOut = range lstDivWar {
-		if strings.Contains(strOut, `до начала: `) {
-			ind++
-			strOut = lstDivWar[ind]
-			еслиНайдено = true
-			break
-		}
-		if strings.Contains(strOut, `>ОБЫЧНЫЕ<`) { // Это уже битва
-			сам.chDivWar <- 1
-			return
-		}
-	}
-	if !еслиНайдено { // Битва дивизий уже идёт
-		сам.chDivWar <- 1
-		return
-	}
-	lstTime := strings.Split(strOut, `<span>`)
-	strTime := lstTime[1]
-	lstTime = strings.Split(strTime, `</span>`)
-	strTime = lstTime[0]
-	if err := сам.ОбратВремяУст(alias.Время(strTime)); err != nil {
-		// log._rintf("WARN DivWar.findTimeCount(): при установке времени ожидания битвы дивизий(%v)\n\terr=%v\n", strTime, err)
-		return
-	}
-}
-
-// При необходимости поднимает взвод в атаку, вызывается только если обнаружено приглашение (+)
-func (сам *DivWar) upDivWar() {
-	var (
-		strOut      string
-		lstDivWar   = сам.СписПолучить()
-		еслиНайдено bool
-	)
-	for _, strOut = range lstDivWar {
-		if strings.Contains(strOut, `>Взвод, подъем! В атаку!<`) {
-			еслиНайдено = true
-			break
-		}
-		if strings.Contains(strOut, `<div class="white medium cntr bold mb5">Вы в рядах участников</div>`) {
-			// log._rintf("INFO DivWar.upDivWar(): уже зарегистрирован\n")
-			return
-		}
-	}
-	if !еслиНайдено {
-		return
-	}
-	// Найдено приглашение на участие
-	lstUp := strings.Split(strOut, `<a class="simple-but border" href="`)
-	linkUp := lstUp[1]
-	lstUp = strings.Split(linkUp, `"><span><span>Взвод, подъем! В атаку!</span></span></a>`)
-	linkUp = "https://wartank.ru/" + lstUp[0]
-	lstDivWar, err := сам.net.Get(linkUp)
-	if err != nil {
-		// log._rintf("ERRO DivWar.upDivWar(): при выполнении GET-команды на подъём в атаку, err=\n\t%v\n", err)
-		return
-	}
-	if err = сам.СтрОбновить(lstDivWar); err != nil {
-		log.Printf("DivWar.upDivWar(): при обновлении lstDivWar, err=\n\t%v\n", err)
-	}
-	// log._rintf("INFO DivWar.upDivWar(): регистрация прошла успешно\n")
-}
-
-// Ведёт сражение
-func (сам *DivWar) DivWar() {
-	defer func() {
-		сам.divOn = nil
-		сам.block.Unlock()
-		if err := сам.ОбратВремяУст("01"); err != nil {
-			panic(fmt.Errorf("DivWar.DivWar(): при установке CountDown, err=\n\t%w", err))
-		}
-		// log.Printf("INFO DivWar.DivWar(): сражение завершено\n")
-	}()
-	var err error
-	сам.divOn, err = div_war_on.NewDivWarOn(сам.конт, сам.bot) // IDivWarOn (онлайн)
-	if err != nil {
-		// log._rintf("ERRO DivWar.DivWarOn(): при создании IDivWarOn, err=\n\t%v\n", err)
-		time.Sleep(time.Millisecond * 250)
-		return
-	}
-	// Цикл ожидания окончания сражения
-	for !сам.divOn.ЕслиКонец().Получ() {
-		time.Sleep(time.Second * 1)
-	}
-
-}
-
-// Alarm -- возвращает признак начала сражения (для браузера)
-func (сам *DivWar) Alarm() ИСтатПарам {
-	return сам.alarm
-}

+ 0 - 193
app/lev3/bot/angar/division/div_war/div_war_on/manevr/manevr.go

@@ -1,193 +0,0 @@
-package manevr
-
-import (
-	"context"
-	"fmt"
-
-	// "log"
-	"strings"
-	"time"
-
-	"github.com/sirupsen/logrus"
-
-	"wartank/app/lev2/arena_division/div_war/div_war_on/health/repair_time"
-	"wartank/app/lev2/arena_division/div_war/div_war_on/manevr/is_manevr"
-
-	// "wartank/internal/components/sound"
-	. "wartank/app/lev0/types"
-	. "wartank/kernel/kernel_types"
-)
-
-/*
-	Пытается маневрировать после выстрела
-*/
-
-// Manevr -- маневрирует после выстрела
-type Manevr struct {
-	ИДивизияВойнаДействие // FIXME:
-	isEnd                 ИБезопБул
-	ctxEnd                context.Context
-	еслиМаневр            *is_manevr.ЕслиМанёвр   // Возможность выполнить манёвр
-	manevrTime            *repair_time.RepairTime // Время до восстановления манёвра
-	chTick                chan int                // Тики для поиска маневра
-}
-
-// NewManevr -- возвращает новый *Manevr
-func NewManevr(дивВойна ИДивизияВойнаДействие, isDivWar ИБезопБул) (*Manevr, error) {
-	{ // Предусловия
-		if дивВойна == nil {
-			return nil, fmt.Errorf("NewManevr(): battle is nil")
-		}
-	}
-	if isDivWar == nil {
-		return nil, fmt.Errorf("NewManevr(): isBattle is nil")
-	}
-	сам := &Manevr{
-		ИДивизияВойнаДействие: дивВойна,
-		ctxEnd:     дивВойна.Ctx(),
-		isEnd:      isDivWar,
-		еслиМаневр: is_manevr.НовЕслиМанёвр(),
-		manevrTime: repair_time.NewRepairTime(),
-		chTick:     make(chan int, 1),
-	}
-	_ = сам.manevrTime.Set("0") // При запуске боя есть возможность маневрировать
-	go сам.makeTick()
-	go сам.run()
-	return сам, nil
-}
-
-// Генерирует тик для уменьшения времени ожидания восстановления возможности манёвра
-func (сам *Manevr) makeTick() {
-	defer func() {
-		close(сам.chTick)
-		// log._rintf("Manevr.makeTick(): сражение завершено\n")
-	}()
-	for {
-		select {
-		case <-сам.ctxEnd.Done():
-			return
-		default:
-			if сам.manevrTime.Get() == 0 {
-				сам.chTick <- 1
-			}
-
-			сам.manevrTime.Dec()
-			time.Sleep(time.Second * 1)
-		}
-	}
-}
-
-// Рабочий цикл поиска маневра (~)
-func (сам *Manevr) run() {
-	for range сам.chTick {
-		if !сам.еслиМаневр.Get() {
-			continue
-		}
-		сам.findManevrTime()
-	}
-}
-
-// Ищет время для манёвра
-func (сам *Manevr) findManevrTime() {
-	var (
-		еслиНайдено bool
-		ind         int
-		lstBattleOn = сам.СписПолучить()
-		strOut      string
-	)
-	for ind, strOut = range lstBattleOn {
-		// <a href="pve?4-88.ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>5 секунд</span></span></a>
-		if strings.Contains(strOut, `-currentControl-maneuverLink`) {
-			еслиНайдено = true
-			break
-		}
-	}
-	if !еслиНайдено { // Или манёвр успел восстановиться, или конец сражения
-		if strings.Contains(strOut, `<span>Маневр</span>`) {
-			_ = сам.manevrTime.Set("0")
-			time.Sleep(time.Second * 1)
-			return
-		}
-		if сам.isEnd.Получ() {
-			time.Sleep(time.Second * 1)
-			return
-		}
-		logrus.WithField("strOut", strOut).Warn("Manevr.findManevrTime(): ошибка в поиске времени манёвра")
-		time.Sleep(time.Second * 1)
-		return
-	}
-	{ // Найти время манёвра
-		lstTime := strings.Split(strOut, `ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>`)
-		if len(lstTime) != 2 {
-			logrus.WithField("ind", ind).
-				WithField("lstBattleOn[-1]", lstBattleOn[ind-1]).
-				WithField("lstBattleOn[ind]", strOut).
-				WithField("lstBattleOn[+1]", lstBattleOn[ind+1]).
-				Errorf("Manevr.findManevrTime(): нет двух полей во времени ожидания")
-			сам.еслиМаневр.Reset()
-			time.Sleep(time.Second * 1)
-			return
-		}
-		strTime := lstTime[1]
-		lstTime = strings.Split(strTime, ` секунд</span></span></a>`)
-		strTime = lstTime[0]
-		if err := сам.manevrTime.Set(strTime); err != nil {
-			logrus.WithError(err).Error("Manevr.findManevrTime(): при обновлении времени ожидания манёвра")
-			сам.еслиМаневр.Reset()
-			time.Sleep(time.Second * 1)
-			return
-		}
-	}
-	сам.еслиМаневр.Set()
-	logrus.WithField("время", сам.manevrTime.Get()).Info("Manevr.findManevrTime(): до манёвра")
-}
-
-// Manevr -- принудительный манёвр по требованию
-func (сам *Manevr) Manevr() {
-	var (
-		еслиНайдено = false
-		lstBattleOn = сам.СписПолучить()
-		strOut      = ""
-	)
-	if !сам.еслиМаневр.Get() {
-		time.Sleep(time.Second * 1)
-		return
-	}
-	for _, strOut = range lstBattleOn {
-		// <a href="pve?4-21.ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>Маневр</span></span></a>
-		if strings.Contains(strOut, `<span>Маневр</span>`) {
-			еслиНайдено = true
-			break
-		}
-	}
-	if !еслиНайдено { // Либо ждём восстановления манёвра, либо сражение закончилось
-		сам.еслиМаневр.Reset()
-		time.Sleep(time.Second * 1)
-		return
-	}
-	{ // Попытка манёвра
-		lstLink := strings.Split(strOut, `<a href="`)
-		strLink := lstLink[1]
-		lstLink = strings.Split(strLink, `" class="simple-but blue"><span><span>Маневр</span></span></a>`)
-		strLink = "https://wartank.ru/" + lstLink[0]
-		lstBattleOn, err := сам.Сеть().Get(strLink)
-		if err != nil {
-			logrus.WithError(err).Error("Manevr.Manevr(): при выполнении GET-команды маневра")
-			сам.еслиМаневр.Reset()
-			time.Sleep(time.Second * 1)
-			return
-		}
-		if err = сам.СтрОбновить(lstBattleOn); err != nil {
-			logrus.WithError(err).Error("Manevr.Manevr(): при обновлении lstBattle")
-			сам.еслиМаневр.Reset()
-			time.Sleep(time.Second * 1)
-			return
-		}
-		// sound.Manevr()
-	}
-}
-
-// IsReady -- возвращает готовность манёвра
-func (сам *Manevr) IsReady() bool {
-	return сам.manevrTime.IsReady()
-}

+ 28 - 49
app/lev3/bot/bot.go

@@ -27,7 +27,7 @@ type Бот struct {
 	ангар          ИАнгар
 	сеть           ИБотСеть
 	еслиРаботает   ИБезопБул
-	еслиАвтозапуск ИБезопБул
+	еслиАвтозапуск ИБезопБулНаблюд
 	конфиг         *bot_config.БотКонфиг // Конфиг бота для хранения в базе
 	кнт            context.Context       // Контекст бота
 	фтОтмена       func()                // Функция отменя контекста бота
@@ -41,7 +41,7 @@ func ЗагрузитьВарБот(конт ИЯдроКонтекст, ном
 	лог.Инфо("ЗагрузитьВарБот()\n")
 	лог.Паника(номер == 0, "ЗагрузитьВарБот(): номер пустой")
 	стрНомер := fmt.Sprint(номер)
-	log.Printf("ЗагрузитьВарБот(): номер=%q\n", стрНомер)
+	лог.Инфо("ЗагрузитьВарБот(): номер=%q\n", стрНомер)
 	хран := конт.Получ("kernStore").(ИЯдроХранилище)
 	binData, err := хран.Get("/bots/" + стрНомер)
 	if err != nil {
@@ -62,7 +62,7 @@ func ЗагрузитьВарБот(конт ИЯдроКонтекст, ном
 func (сам *Бот) рестарт() {
 	time.Sleep(time.Hour * 2)
 	сам.прилож.Отменить()
-	log.Printf("ВарБот.рестарт(): бот %q перезагружен\n", сам.конфиг.Логин_)
+	сам.лог.Инфо("рестарт(): бот %q перезагружен\n", сам.конфиг.Логин_)
 }
 
 // НовВарБот -- возвращает новый WarBot
@@ -71,7 +71,7 @@ func НовВарБот(конт ИЯдроКонтекст, номер АБот
 	лог.Инфо("НовВарБот()\n")
 	лог.Паника(логин == "", "НовВарБот(): логин пустой")
 	лог.Паника(пароль == "", "НовВарБот(): пароль пустой")
-	log.Printf("НовВарБот(): name=%q\n", логин)
+	лог.Инфо("НовВарБот(): name=%q\n", логин)
 	config := &bot_config.БотКонфиг{
 		ЕслиАвтозапуск_: еслиАвто,
 		Логин_:          логин,
@@ -79,7 +79,7 @@ func НовВарБот(конт ИЯдроКонтекст, номер АБот
 		Номер_:          номер,
 	}
 	сам := создатьЯдроВарБот(конт, config)
-	сам.сохр()
+	сам.сохрКонфиг()
 	_ = ИБот(сам)
 	return сам
 }
@@ -93,17 +93,17 @@ func создатьЯдроВарБот(конт ИЯдроКонтекст, к
 	приложение := конт.Получ("приложение").(ИПриложение)
 	контБот := kernel.НовКонтекст()
 	сам := &Бот{
-		конт:           контБот,
-		прилож:         приложение,
-		хран:           конт.Получ("kernStore").(ИЯдроХранилище),
-		стата:          tank_stat.НовТанкСтат(конт),
-		еслиРаботает:   kernel.НовБезопБул(),
-		еслиАвтозапуск: kernel.НовБезопБул(),
-		конфиг:         конфиг,
-		кнт:            ctx,
-		фтОтмена:       fnCancel,
-		лог:            лог,
+		конт:         контБот,
+		прилож:       приложение,
+		хран:         конт.Получ("kernStore").(ИЯдроХранилище),
+		стата:        tank_stat.НовТанкСтат(конт),
+		еслиРаботает: kernel.НовБезопБул(),
+		конфиг:       конфиг,
+		кнт:          ctx,
+		фтОтмена:     fnCancel,
+		лог:          лог,
 	}
+	сам.еслиАвтозапуск = kernel.НовБезопБулНаблюд(сам.Имя(), сам.автозапускИзм)
 	сам.конт.Уст("бот", сам)
 	сам.конт.Уст("приложение", приложение)
 	var err error
@@ -118,13 +118,8 @@ func создатьЯдроВарБот(конт ИЯдроКонтекст, к
 	return сам
 }
 
-// Сервер -- возвращает ссылку на объект сервера
-func (сам *Бот) Сервер() ИПриложение {
-	return сам.прилож
-}
-
-// ЕслиПуск -- возвращает признак, что бот подключен
-func (сам *Бот) ЕслиПуск() bool {
+// ЕслиРабота -- возвращает признак, что бот подключен
+func (сам *Бот) ЕслиРабота() bool {
 	return сам.еслиРаботает.Получ()
 }
 
@@ -172,24 +167,16 @@ func (сам *Бот) Сеть() ИБотСеть {
 	return сам.сеть
 }
 
-// АвтоИграЕсли -- возвращает признак автоматического запуска бота
-func (сам *Бот) АвтоИграЕсли() bool {
-	return сам.еслиАвтозапуск.Получ()
-}
-
-// АвтоИграУст -- устанавливает признак автоматического запуска бота
-func (сам *Бот) АвтоИграУст() {
-	log.Printf("WarBot.SetAutoGame()")
-	сам.еслиАвтозапуск.Уст()
-	сам.конфиг.ЕслиАвтозапуск_ = true
-	сам.сохрКонфиг()
+// Автозапуск -- возвращает признак автоматического запуска бота
+func (сам *Бот) Автозапуск() ИБезопБулНаблюд {
+	return сам.еслиАвтозапуск
 }
 
-// АвтоИграСброс -- сбрасывает признак автоматического запуска бота
-func (сам *Бот) АвтоИграСброс() {
-	log.Printf("WarBot.ResetAutoGame()")
-	сам.еслиАвтозапуск.Уст()
-	сам.конфиг.ЕслиАвтозапуск_ = false
+// Обратный вызов автоматического запуска бота
+func (сам *Бот) автозапускИзм(знач bool) {
+	сам.лог.Отладка("Бот.автозапускИзм()")
+	// сам.еслиАвтозапуск.Уст()
+	сам.конфиг.ЕслиАвтозапуск_ = знач
 	сам.сохрКонфиг()
 }
 
@@ -197,10 +184,9 @@ func (сам *Бот) АвтоИграСброс() {
 func (сам *Бот) сохрКонфиг() {
 	log.Printf("ВарБот.сохрКонфиг()")
 	strConf := сам.конфиг.Marshall()
-	err := сам.хран.Set("/bots/"+сам.Имя(), strConf)
-	if err != nil {
-		log.Printf("ВарБот.сохрКонфиг(): err=\n\t%v\n", err)
-	}
+	стрНомер := fmt.Sprint(сам.Номер())
+	err := сам.хран.Set("/bots/"+стрНомер, strConf)
+	сам.лог.Паника(err != nil, "ВарБот.сохрКонфиг(): err=\n\t%v\n", err)
 }
 
 // Контекст -- возвращает контекст бота
@@ -213,13 +199,6 @@ func (сам *Бот) Закончить() {
 	сам.фтОтмена()
 }
 
-// Сохраняет себя в базу
-func (сам *Бот) сохр() {
-	стрНомер := fmt.Sprint(сам.Номер())
-	err := сам.хран.Set("/bots/"+стрНомер, сам.конфиг.Marshall())
-	сам.лог.Паника(err != nil, "ВарБот.сохр(): err=\n\t%v\n", err)
-}
-
 // КонтБот -- возвращает контекст бота
 func (сам *Бот) КонтБот() ИБотКонтекст {
 	return сам.конт

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

@@ -16,7 +16,7 @@ import (
 
 // БотНетСтат -- статистика уровня бота
 type БотСетьСтат struct {
-	server ИПриложение
+	прилож ИПриложение
 	бот    ИБот
 	лог    ИЯдроЛог
 }
@@ -27,7 +27,7 @@ func НовБотСетьСтат(конт ИБотКонтекст) *БотСе
 	лог.Инфо("НовБотСетьСтат()\n")
 	bot := конт.Получ("бот").(ИБот)
 	сам := &БотСетьСтат{
-		server: bot.Сервер(),
+		прилож: конт.Получ("сервер").(ИПриложение),
 		бот:    bot,
 		лог:    лог,
 	}
@@ -243,7 +243,7 @@ func (сам *БотСетьСтат) игроковОнлайнНайти() {
 	// Выделить число игроков онлайн
 	lstAngar = strings.Split(strOut, `<span class="yellow1">`)
 	if len(lstAngar) <= 1 {
-		сам.server.Отменить()
+		сам.прилож.Отменить()
 		return
 	}
 	strOnline := lstAngar[1]

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

@@ -111,7 +111,7 @@ func (сам *СловарьБотов) load() {
 			continue
 		}
 		bot := bot.ЗагрузитьВарБот(сам.конт, ботНомер)
-		if bot.АвтоИграЕсли() {
+		if bot.Автозапуск().Получ() {
 			go bot.Пуск()
 		}
 		сам.словарь[ботНомер] = bot

+ 4 - 4
app/lev3/serv_web/serv_web.go

@@ -63,8 +63,8 @@ func (сам *СервВеб) постБотСтат(кнт *fiber.Ctx) error {
 		})
 	}
 	диктБот := map[string]string{}
-	диктБот["isAuto"] = fmt.Sprint(бот.АвтоИграЕсли())
-	диктБот["isWork"] = fmt.Sprint(бот.ЕслиПуск())
+	диктБот["isAuto"] = fmt.Sprint(бот.Автозапуск().Получ())
+	диктБот["isWork"] = fmt.Sprint(бот.ЕслиРабота())
 	топливо := бот.Ангар().Топливо().Получ()
 	if топливо == 0 {
 		бот.Ангар().Обновить()
@@ -152,8 +152,8 @@ func (сам *СервВеб) гетСписБот(кнт *fiber.Ctx) error {
 	for _, бот := range списБот {
 		_бот := map[string]string{}
 		_бот["name"] = бот.Имя()
-		_бот["isAuto"] = fmt.Sprint(бот.АвтоИграЕсли())
-		_бот["isWork"] = fmt.Sprint(бот.ЕслиПуск())
+		_бот["isAuto"] = fmt.Sprint(бот.Автозапуск().Получ())
+		_бот["isWork"] = fmt.Sprint(бот.ЕслиРабота())
 		_бот["gold"] = fmt.Sprint(бот.Ангар().Золото().Получ())
 		_бот["fuel"] = fmt.Sprint(бот.Ангар().Топливо().Получ())
 		рез = append(рез, _бот)

+ 0 - 0
pkg/helpers/helper.go → kernel/helpers/helper.go


+ 0 - 0
pkg/helpers/helpers.go → kernel/helpers/helpers.go


+ 0 - 0
pkg/helpers/helpers_test.go → kernel/helpers/helpers_test.go


+ 0 - 0
pkg/helpers/result.txt → kernel/helpers/result.txt


+ 1 - 1
kernel/internal/kernel_ctx/kernel_keeper/kernel_keeper.go

@@ -8,8 +8,8 @@ import (
 	"os/signal"
 	"syscall"
 
+	. "wartank/kernel/helpers"
 	. "wartank/kernel/kernel_types"
-	. "wartank/pkg/helpers"
 )
 
 // kernelKeeper -- сторож системных сигналов

+ 1 - 1
kernel/internal/kernel_ctx/kernel_wg/kernel_wg.go

@@ -10,10 +10,10 @@ import (
 	"sync"
 	"time"
 
+	. "wartank/kernel/helpers"
 	. "wartank/kernel/internal/kernel_alias"
 	"wartank/kernel/internal/safe_bool"
 	. "wartank/kernel/kernel_types"
-	. "wartank/pkg/helpers"
 )
 
 // ядроОп -- именованный ожидатель потоков ядра

+ 1 - 1
kernel/internal/kernel_serv_http/kernel_serv_http.go

@@ -14,9 +14,9 @@ import (
 	"github.com/gofiber/fiber/v2/middleware/filesystem"
 	"github.com/gofiber/fiber/v2/middleware/monitor"
 
+	. "wartank/kernel/helpers"
 	"wartank/kernel/internal/safe_bool"
 	. "wartank/kernel/kernel_types"
-	. "wartank/pkg/helpers"
 )
 
 const (

+ 1 - 1
kernel/internal/kernel_store/kernel_store.go

@@ -10,9 +10,9 @@ import (
 
 	"github.com/dgraph-io/badger/v4"
 
+	. "wartank/kernel/helpers"
 	"wartank/kernel/internal/safe_bool"
 	. "wartank/kernel/kernel_types"
-	. "wartank/pkg/helpers"
 )
 
 const (

+ 67 - 0
kernel/internal/safe_bool_observer/safe_bool_observer.go

@@ -0,0 +1,67 @@
+// package safe_bool_observer -- безопасное булево значение с наблюдателями
+package safe_bool_observer
+
+import (
+	"sync"
+	. "wartank/kernel/helpers"
+	. "wartank/kernel/kernel_types"
+)
+
+// БезопБулНаблюд -- безопасное булево значение с наблюдателями
+type БезопБулНаблюд struct {
+	знач      bool
+	слвНаблюд map[string]func(bool) // Словарь наблюдателей
+	блок      sync.RWMutex
+}
+
+// НовБезопБулНаблюд -- возвращает новое безопасное булево значение с наблюдателями
+func НовБезопБулНаблюд(ключ string, фнНаблюд func(bool)) ИБезопБулНаблюд {
+	сам := &БезопБулНаблюд{
+		слвНаблюд: map[string]func(bool){},
+	}
+	сам.Зарегать(ключ, фнНаблюд)
+	return сам
+}
+
+// Уст -- устанавливает хранимое значение
+func (сам *БезопБулНаблюд) Уст() {
+	сам.блок.Lock()
+	defer сам.блок.Unlock()
+	сам.знач = true
+	for _, фнНаблюд := range сам.слвНаблюд {
+		фнНаблюд(true)
+	}
+}
+
+// Сброс -- сбрасывает хранимое значение
+func (сам *БезопБулНаблюд) Сброс() {
+	сам.блок.Lock()
+	defer сам.блок.Unlock()
+	сам.знач = false
+	for _, фнНаблюд := range сам.слвНаблюд {
+		фнНаблюд(false)
+	}
+}
+
+// Получ -- возвращает хранимое значение
+func (сам *БезопБулНаблюд) Получ() bool {
+	сам.блок.RLock()
+	defer сам.блок.RUnlock()
+	return сам.знач
+}
+
+// Зарегать -- зарегистрировать наблюдателя
+func (сам *БезопБулНаблюд) Зарегать(ключ string, фнНаблюд func(bool)) {
+	сам.блок.Lock()
+	defer сам.блок.Unlock()
+	Паника(ключ == "", "БезопБулНаблюд.Зарегать(): ключ пустой")
+	Паника(фнНаблюд == nil, "БезопБулНаблюд.Зарегать(): фнНаблюд == nil")
+	сам.слвНаблюд[ключ] = фнНаблюд
+}
+
+// Разрегать -- удалить регистрацию наблюдателя
+func (сам *БезопБулНаблюд) Разрегать(ключ string) {
+	сам.блок.Lock()
+	defer сам.блок.Unlock()
+	delete(сам.слвНаблюд, ключ)
+}

+ 5 - 0
kernel/kernel.go

@@ -7,6 +7,7 @@ import (
 	"wartank/kernel/internal/kernel_serv_http"
 	"wartank/kernel/internal/kernel_store"
 	"wartank/kernel/internal/safe_bool"
+	"wartank/kernel/internal/safe_bool_observer"
 	"wartank/kernel/internal/safe_int"
 	"wartank/kernel/internal/safe_string"
 	. "wartank/kernel/kernel_types"
@@ -24,6 +25,10 @@ func НовБезопБул() ИБезопБул {
 	return safe_bool.НовБезопБул_()
 }
 
+func НовБезопБулНаблюд(ключ string, фнНаблюд func(bool)) ИБезопБулНаблюд {
+	return safe_bool_observer.НовБезопБулНаблюд(ключ, фнНаблюд)
+}
+
 func НовЛог(префикс string) ИЯдроЛог {
 	лог := kernel_log.НовЛоггер(префикс)
 	return лог

+ 15 - 0
kernel/kernel_types/ikernel_safe_bool_observer.go

@@ -0,0 +1,15 @@
+package kernel_types
+
+// ИБезопБулНаблюд -- потокобезопасное булево с наблюдателями
+type ИБезопБулНаблюд interface {
+	// Получ -- возвращает хранимое значение
+	Получ() bool
+	// Уст -- устанавливает хранимое значение
+	Уст()
+	// Сброс -- сбрасывает хранимое значение
+	Сброс()
+	// Зарегать -- зарегистрировать наблюдателя
+	Зарегать(ключ string, фнНаблюд func(bool))
+	// Разрегать -- снять регистрацию наблюдателя
+	Разрегать(ключ string)
+}

+ 1 - 1
pkg/mock/mock_env/mock_env.go

@@ -5,7 +5,7 @@ import (
 	"os"
 	"strings"
 
-	. "wartank/pkg/helpers"
+	. "wartank/kernel/helpers"
 )
 
 // МокОкружение -- объект мок-окружения