Selaa lähdekoodia

d02 Переделка под правильную структуру

SVI 3 vuotta sitten
vanhempi
commit
18c48598d9

+ 25 - 18
pkg/components/section/count_time/count_time.go

@@ -4,6 +4,7 @@
 package count_time
 
 import (
+	"context"
 	"fmt"
 	// "log"
 	"sync"
@@ -16,36 +17,41 @@ import (
 )
 
 const (
-	iSleep = time.Millisecond * 100
+	sleepInterval = time.Millisecond * 100 // Малый интервал сна в 100 мсек
 )
 
-// CountTime -- счётчик обратного времени
+// CountTime -- счётчик обратного времени для игровой зоны (анга, база, битва и т.п.)
 type CountTime struct {
-	bot    types.IBot
+	zone   types.IZone
 	val    *safeint.SafeInt
 	parser *parsetime.ParseTime
 
-	chTick     chan int
+	chTick     chan int           // Канал секундных интервалов сна
 	chCall     chan int           // Канал для отправки сигналов
 	isWork     *safebool.SafeBool // Признак работы
 	timeTarget *safeint.SafeInt   // Целевое время срабатывания
+	ctx        context.Context    // Контекст для счётчика времени
+	fnCancel   func()             // Функция отмены контекста для счётчика времени
 
 	block sync.RWMutex
 }
 
 // NewCountTime -- возвращает новый *CountTime
-func NewCountTime(bot types.IBot) *CountTime {
-	if bot == nil {
-		panic("NewCountTime(): IBot == nil")
+func NewCountTime(zone types.IZone) *CountTime {
+	if zone == nil {
+		panic("NewCountTime(): IZone == nil")
 	}
+	ctx, fnCancel := context.WithCancel(zone.Ctx())
 	sf := &CountTime{
-		bot:        bot,
+		zone:       zone,
 		val:        safeint.NewSafeInt(),
 		chTick:     make(chan int, 3),
 		chCall:     make(chan int, 2),
 		isWork:     safebool.NewSafeBool(),
 		parser:     parsetime.NewParseTime(),
 		timeTarget: safeint.NewSafeInt(),
+		ctx:        ctx,
+		fnCancel:   fnCancel,
 	}
 	sf.isWork.Set()
 	go sf.makeTick()
@@ -59,27 +65,28 @@ func (sf *CountTime) makeTick() {
 		if !sf.isWork.Get() {
 			return
 		}
+		sf.fnCancel()
 		sf.isWork.Reset()
 		close(sf.chTick)
 		// log._rintf("CountTime.makeTick(): работа завершена")
 	}()
-	countSleep := time.Duration(0)
+	countSleep := 0 // Счётчик сна (10 периодов -- 1 секунда)
 	for {
 		select {
-		case <-sf.bot.Ctx().Done(): // Отмена контекста бота
-			// log._rintf("CountTime.makeTick(): глобальная отмена контекста\n")
+		case <-sf.ctx.Done(): // Отмена контекста бота
+			// log._rintf("CountTime.makeTick(): отмена контекста бота\n")
 			return
 		default:
 			if !sf.isWork.Get() {
 				return
 			}
 
-			if countSleep >= time.Second {
+			if countSleep >= 10 {
 				sf.chTick <- 1
 				countSleep = 0
 			}
-			countSleep += iSleep
-			time.Sleep(iSleep)
+			countSleep++
+			time.Sleep(sleepInterval)
 		}
 	}
 }
@@ -94,13 +101,13 @@ func (sf *CountTime) run() {
 			sf.Set(val)
 			continue
 		}
-		sf.chCall <- 1
-		continue
+		close(sf.chCall)
+		sf.fnCancel()
+		return
 	}
-	close(sf.chCall)
 }
 
-// Stop -- останавливает работу чяётчика
+// Stop -- останавливает работу cчётчика
 func (sf *CountTime) Stop() {
 	sf.isWork.Reset()
 }

+ 6 - 6
pkg/components/section/count_time/count_time_test.go

@@ -16,7 +16,7 @@ import (
 type tester struct {
 	t      *testing.T
 	app    *mockapp.MockApp
-	bot    types.IBot
+	zone   types.IZone
 	ct     *CountTime
 	err    error
 	isCall *safebool.SafeBool // Признак обратного вызова
@@ -44,7 +44,7 @@ func TestCountTime(t *testing.T) {
 // Оменяет работу таймера
 func (sf *tester) cancel() {
 	sf.t.Logf("=cancel=\n")
-	ct := NewCountTime(sf.bot)
+	ct := NewCountTime(sf.zone)
 	for len(ct.chTick) > 0 {
 		<-ct.chTick
 	}
@@ -54,7 +54,7 @@ func (sf *tester) cancel() {
 
 // Проверяет обработчик тика
 func (sf *tester) checkTick() {
-	ct := NewCountTime(sf.bot)
+	ct := NewCountTime(sf.zone)
 	{ // Секундный тик
 		ct.Parse("00:00:08")
 		time.Sleep(time.Second * 1)
@@ -109,7 +109,7 @@ func (sf *tester) setStrBad1(strBad string) {
 // Устанавливает строковое значение времени
 func (sf *tester) setStr() {
 	go sf.call()
-	ct := NewCountTime(sf.bot)
+	ct := NewCountTime(sf.zone)
 	{ // BAD-1 пустая строка
 		if sf.err = ct.Parse(""); sf.err == nil {
 			sf.t.Errorf("setStr(): BAD-1 err==nil")
@@ -163,7 +163,7 @@ func (sf *tester) setStr() {
 // Устанавливает число секунд для отсчёта
 func (sf *tester) setInt() {
 	go sf.call()
-	ct := NewCountTime(sf.bot)
+	ct := NewCountTime(sf.zone)
 	{ // Bad-1 Отрицательное число
 		if sf.err = ct.Set(-1); sf.err == nil {
 			sf.t.Errorf("setInt(): BAD-1 err==nil")
@@ -242,7 +242,7 @@ func (sf *tester) createGood1() {
 			sf.t.Errorf("createGood1(): panic=%v", _panic)
 		}
 	}()
-	ct := NewCountTime(sf.bot)
+	ct := NewCountTime(sf.zone)
 	if ct == nil {
 		sf.t.Errorf("createGood1(): countTime==nil")
 	}

+ 18 - 8
pkg/components/section/section.go

@@ -1,4 +1,4 @@
-// package section -- типовая секция работы части игры (банк, арсеал и т.п.)
+// package section -- типовая секция работы части игры (банк, арсенал и т.п.)
 package section
 
 import (
@@ -8,16 +8,13 @@ import (
 	"wartank/pkg/components/lst_string"
 	"wartank/pkg/components/section/count_time"
 	"wartank/pkg/components/section/section_mode"
+	"wartank/pkg/components/section/zone"
 	"wartank/pkg/types"
 )
 
-/*
-	Базовый объект игры -- секция.
-	Основа множества зданий игры.
-*/
-
 // Section -- секция игры
 type Section struct {
+	*zone.Zone
 	countDown types.ICountTime      // Обратный отсчёт до окончания работы режима
 	mode      types.IMode           // Объект режима работы
 	lstString *lst_string.LstString // Список строк из сети для анализа секции
@@ -26,11 +23,15 @@ type Section struct {
 // NewSection -- возвращает новую секцию игры
 func NewSection(bot types.IBot, strControl string) (*Section, error) {
 	log.Printf("NewSection(): strControl=%q\n", strControl)
+	zone, err := zone.NewZone(bot)
+	if err != nil {
+		return nil, fmt.Errorf("NewSection(): in create IZone, err=\n\t%w", err)
+	}
 	sf := &Section{
-		countDown: count_time.NewCountTime(bot),
+		Zone:      zone,
+		countDown: count_time.NewCountTime(zone),
 		mode:      section_mode.NewSectionMode(),
 	}
-	var err error
 	sf.lstString, err = lst_string.NewLstString(strControl)
 	if err != nil {
 		return nil, fmt.Errorf("NewSection(): in create *LstString, err=\n\t%w", err)
@@ -51,6 +52,15 @@ func (sf *Section) GetLst() []string {
 	return sf.lstString.Get()
 }
 
+// SetCountDown -- устанавливает новое значение обратного счётчика времени
+func (sf *Section) SetCountDown(sec int) error {
+	sf.countDown = count_time.NewCountTime(sf)
+	if err := sf.countDown.Set(sec); err != nil {
+		return fmt.Errorf("Section.SetCountDown(): err=\n\t%w", err)
+	}
+	return nil
+}
+
 // CountDown -- объект оставшегося времени
 func (sf *Section) CountDown() types.ICountTime {
 	return sf.countDown

+ 45 - 0
pkg/components/section/zone/zone.go

@@ -0,0 +1,45 @@
+// package zone -- игровая зона (ангар, база, бан, битва и т.п.)
+package zone
+
+import (
+	"context"
+	"fmt"
+	"wartank/pkg/types"
+)
+
+// Zone -- игровая зона (ангар, база, бан, битва и т.п.)
+type Zone struct {
+	bot      types.IBot
+	ctx      context.Context
+	fnCancel func()
+}
+
+// NewZone -- возвращает новую игровую зону
+func NewZone(bot types.IBot) (*Zone, error) {
+	if bot == nil {
+		return nil, fmt.Errorf("NewZone(): IBot==nil")
+	}
+	ctx, fnCancel := context.WithCancel(bot.Ctx())
+	sf := &Zone{
+		bot:      bot,
+		ctx:      ctx,
+		fnCancel: fnCancel,
+	}
+	_ = types.IZone(sf)
+	return sf, nil
+}
+
+// Ctx -- возвращает контекст игровой зоны
+func (sf *Zone) Ctx() context.Context {
+	return sf.ctx
+}
+
+// CancelZone -- отменяет контекст игровой зоны
+func (sf *Zone) CancelZone() {
+	sf.fnCancel()
+}
+
+// Bot -- возвращает бота игровой зоны
+func (sf *Zone) Bot() types.IBot {
+	return sf.bot
+}

+ 39 - 48
pkg/components/sectionnet/netclient/netclient.go

@@ -4,9 +4,6 @@ import (
 	"context"
 	"fmt"
 	"io"
-	"log"
-
-	// "log"
 	"net/http"
 	"strings"
 	"sync"
@@ -28,37 +25,33 @@ type response struct {
 
 // NetClient -- объект сетевого соединения
 type NetClient struct {
-	server   types.IServer
-	conn     *http.Client
-	stat     *netstat.NetStat
-	ctx      context.Context
-	chRes    chan *response // Канал ответа от http-клиента
-	fnCancel func()         // Отмена контекста приложения
-	block    sync.Mutex
+	botNet types.IBotNet
+	conn   *http.Client
+	stat   *netstat.NetStat
+	chRes  chan *response // Канал ответа от http-клиента
+	block  sync.Mutex
 }
 
 // NewNetClient -- возвращает сетевого клиента
-func NewNetClient(server types.IServer, bot types.IBot) *NetClient {
+func NewNetClient(botNet types.IBotNet) *NetClient {
 	sf := &NetClient{
-		server:   server,
-		conn:     bot.BotNet().Conn(),
-		stat:     netstat.NewNetStat(server),
-		chRes:    make(chan *response, 2),
-		ctx:      context.Background(),
-		fnCancel: server.CancelApp,
+		botNet: botNet,
+		conn:   botNet.Conn(),
+		stat:   netstat.NewNetStat(botNet),
+		chRes:  make(chan *response, 2),
 	}
 	return sf
 }
 
-// Теневая функция на блокировку
+// Get -- выполняет безопасный GET-запрос в сеть
 func (sf *NetClient) Get(strLink string) (lstString []string, err error) {
 	sf.block.Lock()
 	defer sf.block.Unlock()
-	ctxCancel, fnCancel := context.WithTimeout(sf.ctx, time.Second*7)
-	defer func() {
-		fnCancel()
+	ctxCancel, fnCancel := context.WithTimeout(sf.botNet.Ctx(), time.Second*7)
+	defer fnCancel()
+	defer func() { // Возможный перехват паники
 		if _panic := recover(); _panic != nil {
-			err = fmt.Errorf("NetClient.get(): перехвачена паника для URL(%v), panic=%v", strLink, _panic)
+			err = fmt.Errorf("NetClient.Get().defer(): перехвачена паника для URL(%v), panic=%v", strLink, _panic)
 			lstString = nil
 			time.Sleep(time.Millisecond * 250) // Чтобы не насиловать не работающую сеть
 		}
@@ -67,7 +60,7 @@ func (sf *NetClient) Get(strLink string) (lstString []string, err error) {
 	select {
 	case <-ctxCancel.Done(): // Таймаут по ожиданию
 		err = fmt.Errorf("NetClient.get(): таймаут ожидания ответа")
-		sf.fnCancel()
+		sf.botNet.CancelBotNet()
 		return nil, err
 	case resp := <-sf.chRes: // Получен ответ
 		if resp.err != nil {
@@ -79,34 +72,36 @@ func (sf *NetClient) Get(strLink string) (lstString []string, err error) {
 
 // Внутренний вызов для сокрытия под общей блокировкой
 func (sf *NetClient) get(strLink string) {
+	resp := &response{}
+	defer func() {
+		if resp.err != nil {
+			sf.stat.IncErr()
+		}
+	}()
 	req, err := http.NewRequest("GET", strLink, nil)
 	if err != nil {
-		log.Fatalln(err)
+		resp.err = fmt.Errorf("NetClient.get(): при создании запроса, err=\n\t%w", err)
+		return
 	}
-	req.Header.Set("User-Agent", "Mozilla Firefox 86.0")
+	req.Header.Set("User-Agent", "Mozilla Firefox 94.1")
 	httpResp, err := sf.conn.Do(req)
-	resp := &response{}
 	if err != nil {
-		resp.err = fmt.Errorf("NetClient.get().fnGet(): при выполнении GET-запроса, err=\n\t%w", err)
-		sf.stat.AddByte(-1) // Фиксируем ошибку
+		resp.err = fmt.Errorf("NetClient.get(): при выполнении GET-запроса, err=\n\t%w", err)
 		return
 	}
-	defer sf.endGet(strLink, httpResp, resp)
+	defer sf.closeGetBody(strLink, httpResp, resp)
 
 	if httpResp.StatusCode != http.StatusOK {
-		resp.err = fmt.Errorf("NetClient.get().fnGet(): code=%v, status=%v", httpResp.StatusCode, httpResp.Status)
-		sf.stat.AddByte(-1) // Фиксируем ошибку
+		resp.err = fmt.Errorf("NetClient.get(): code=%v, status=%v", httpResp.StatusCode, httpResp.Status)
 		return
 	}
 	binData, err := io.ReadAll(httpResp.Body)
 	if err != nil {
-		resp.err = fmt.Errorf("NetClient.get().fnGet(): при чтении тела ответа, err=\n\t%w", err)
-		sf.stat.AddByte(-1) // Фиксируем ошибку
+		resp.err = fmt.Errorf("NetClient.get(): при чтении тела ответа, err=\n\t%w", err)
 		return
 	}
 	if len(binData) == 0 {
-		resp.err = fmt.Errorf("NetClient.get().fnGet(): пустое тело ответа, err=\n\t%w", err)
-		sf.stat.AddByte(-1) // Фиксируем ошибку
+		resp.err = fmt.Errorf("NetClient.get(): пустое тело ответа, err=\n\t%w", err)
 		return
 	}
 	lenData := len(binData) + len(strLink)
@@ -114,32 +109,28 @@ func (sf *NetClient) get(strLink string) {
 
 	lstString := strings.Split(string(binData), "\n")
 	if len(lstString) == 0 {
-		resp.err = fmt.Errorf("NetClient.get().fnGet(): lstString is empty")
-		sf.stat.AddByte(-1) // Фиксируем ошибку
+		resp.err = fmt.Errorf("NetClient.get(): lstString is empty")
 		return
 	}
 	resp.lstString = lstString
 }
 
-// Вызывается по завершению вызова
-func (sf *NetClient) endGet(strLink string, httpResp *http.Response, resp *response) {
+// Вызывается по завершению вызова, закрывает тело запроса
+func (sf *NetClient) closeGetBody(strLink string, httpResp *http.Response, resp *response) {
 	defer func() {
 		if _panic := recover(); _panic != nil {
-			// log._rintf("NetClient.sndGet(): strLink='%v', panic=%v\n", strLink, _panic)
-			sf.fnCancel()
+			// log._rintf("NetClient.closeGetBody(): strLink='%v', panic=%v\n", strLink, _panic)
+			sf.botNet.CancelBotNet()
 		}
 	}()
 	err := httpResp.Body.Close()
 	if err != nil {
-		switch resp.err == nil {
-		case true:
-			resp.err = fmt.Errorf("NetClient.get().fnGet(): ошибка при закрытии запроса URL(%v), err=\n\t%w", strLink, err)
-		case false:
-			resp.err = fmt.Errorf("NetClient.get().fnGet(): ошибка при закрытии запроса URL(%v), err=\n\t%v\n\toldErr=\n\t%w", strLink, err, resp.err)
+		_err := fmt.Errorf("NetClient.closeGetBody(): ошибка при закрытии запроса URL(%q), err=\n\t%w", strLink, err)
+		if resp.err != nil { // Есть и ошибка в закрытии тела запроса и внутренняя
+			resp.err = fmt.Errorf("NetClient.closeGetBody(): двойная ошибка при закрытии запроса URL(%q), err=\n\t%w\n\tinternal err=\n\t%w", strLink, _err, resp.err)
 		}
 		resp.lstString = nil
-
-		sf.stat.AddByte(-1) // Отметим ошибку закрытия клиента
+		sf.stat.IncErr()
 	}
 	sf.chRes <- resp
 }

+ 37 - 30
pkg/components/sectionnet/netstat/netstat.go

@@ -1,8 +1,7 @@
 package netstat
 
 import (
-	// "log"
-	// "log"
+	"log"
 	"sync"
 	"time"
 
@@ -15,20 +14,20 @@ import (
 
 // NetStat -- статистика сетевого соединения
 type NetStat struct {
-	server       types.IServer
-	countByte    int      // Счётчик переданных/полученных байтов
-	totalByte    int      // Сколько всего байт передано вообще
-	totalMinut   int      // Сколько всего минут работала передача
-	countRequest int      // Число запросов
-	countErr     int      // Число зафиксированных ошибок
-	chTick       chan int // Сигналы времени
-	block        sync.Mutex
+	botNet               types.IBotNet
+	countByteInterval    int      // Счётчик байтов в текущем интервале
+	totalByte            int      // Сколько всего байт передано
+	totalMinut           int      // Сколько всего минут работала передача
+	countRequestInterval int      // Число запросов
+	countErr             int      // Число зафиксированных ошибок
+	chTick               chan int // Сигналы времени 1 раз в 5 минут
+	block                sync.Mutex
 }
 
 // NewNetStat -- возвращает новый *NetStat
-func NewNetStat(server types.IServer) *NetStat {
+func NewNetStat(botNet types.IBotNet) *NetStat {
 	sf := &NetStat{
-		server: server,
+		botNet: botNet,
 		chTick: make(chan int, 2),
 	}
 	go sf.run()
@@ -36,16 +35,15 @@ func NewNetStat(server types.IServer) *NetStat {
 	return sf
 }
 
-// Тикер меток времени
+// Тикер меток времени 1 раз в 5 минут
 func (sf *NetStat) makeTick() {
 	defer close(sf.chTick)
 	for {
 		select {
-		case <-sf.server.Done():
+		case <-sf.botNet.Ctx().Done():
 			return
 		default:
 			time.Sleep(time.Second * 5 * 60)
-			sf.totalMinut += 5
 			sf.chTick <- 1
 		}
 	}
@@ -53,32 +51,41 @@ func (sf *NetStat) makeTick() {
 
 // Главный цикл работы статистики
 func (sf *NetStat) run() {
+	fnCalc := func() {
+		sf.block.Lock()
+		defer sf.block.Unlock()
+		sf.totalMinut += 5
+		mbyte := float32(sf.totalByte) / float32(sf.totalMinut*60) * (3600 * 24 * 30.5) / (1024 * 1024)
+		log.Printf("INFO NetStat.run().fnCalc(): запросы=%0.2f/сек\tтраф0=%0.2f бит/сек\tтраф1=%0.2f МБ/мес\tошибки=%v\n",
+			float32(sf.countRequestInterval)/300,
+			float32(sf.countByteInterval*8)/300,
+			mbyte,
+			sf.countErr)
+		sf.countByteInterval = 0
+		sf.countRequestInterval = 0
+	}
 	for range sf.chTick {
 		select {
-		case <-sf.server.Done():
+		case <-sf.botNet.Ctx().Done():
 			return
 		case <-sf.chTick:
-			sf.block.Lock()
-			// mbyte := float32(sf.totalByte) / float32(sf.totalMinut*60) * (3600 * 24 * 30.5) / (1024 * 1024)
-			// log._rintf("INFO NetStat.run(): запросы=%0.2f/сек\tтраф0=%0.2f бит/сек\tтраф1=%0.2f МБ/мес\tошибки=%v\n",
-			// float32(sf.countRequest)/300, float32(sf.countByte*8)/300, mbyte, sf.countErr)
-			sf.countByte = 0
-			sf.countRequest = 0
-			sf.block.Unlock()
+			fnCalc()
 		}
 	}
 }
 
+// IncErr -- добавляет ошибку в статистику
+func (sf *NetStat) IncErr() {
+	sf.block.Lock()
+	defer sf.block.Unlock()
+	sf.countErr++
+}
+
 // AddByte -- увеличивает счётчик запросов и байтов на передачу/приём
 func (sf *NetStat) AddByte(val int) {
 	sf.block.Lock()
 	defer sf.block.Unlock()
-	if val < 0 {
-		// log._rintf("ERRO NatStat.AddByte(): val(%v)<0\n", val)
-		sf.countErr++
-		return
-	}
-	sf.countByte += val
+	sf.countByteInterval += val
 	sf.totalByte += val
-	sf.countRequest++
+	sf.countRequestInterval++
 }

+ 5 - 12
pkg/components/sectionnet/sectionnet.go

@@ -25,29 +25,22 @@ type SectionNet struct {
 }
 
 // NewSectionNet -- возвращает новый *SectionNet
-func NewSectionNet(bot types.IBot, section types.ISection, strUrl string) *SectionNet {
+func NewSectionNet(section types.ISection, strUrl string) (*SectionNet, error) {
 	log.Printf("NewSectionNet(): url=%q\n", strUrl)
 	{ // Предусловия
-		if bot == nil {
-			panic("NewSectionNet(): IServBot == nil")
-		}
 		if section == nil {
-			panic("NewSectionNet(): ISection == nil")
+			return nil, fmt.Errorf("NewSectionNet(): ISection == nil")
 		}
 		if strUrl == "" {
-			panic("NewSectionNet(): strUrl is empty")
+			return nil, fmt.Errorf("NewSectionNet(): strUrl is empty")
 		}
 	}
 	sf := &SectionNet{
 		section: section,
 		strUrl:  strUrl,
-		client:  bot.BotNet().Net(),
+		client:  section.Bot().BotNet().Net(),
 	}
-	return sf
-}
-
-func (sf *SectionNet) Run() {
-
+	return sf, nil
 }
 
 // Обновляет список строк

+ 0 - 2
pkg/types/iangar.go

@@ -33,6 +33,4 @@ type IAngar interface {
 	Base() IBase
 	// Missions -- возвращает объект миссий
 	Missions() IMissions
-	// Make -- создаёт компоненты ангара
-	Make() error
 }

+ 0 - 2
pkg/types/ibot.go

@@ -24,8 +24,6 @@ type IBot interface {
 	IsAutoGame() bool
 	// IsRun -- признак, что бот работает
 	IsRun() bool
-	// Make -- создаёт компоненты бота
-	Make() error
 	// Server -- возвращает ссылку на объект сервера
 	Server() IServer
 	// Ctx -- возвращает контекст бота

+ 10 - 2
pkg/types/ibot_net.go

@@ -1,6 +1,7 @@
 package types
 
 import (
+	"context"
 	"net/http"
 
 	"wartank/pkg/components/safebool"
@@ -14,9 +15,16 @@ import (
 type IBotNet interface {
 	// IsOnline -- возвращает признак подключенности к интернету
 	IsOnline() *safebool.SafeBool
+	// Conn -- возвращает объект сетевого подключения
 	Conn() *http.Client
+	// Cookie -- возвращает объект кукисов
 	Cookie() IBotCookie
+	// Net -- возвращает сетевой клиент бота
 	Net() INetClient
-	// Login -- пытается зайти по сети
-	Login() error
+	// Ctx -- контекст сетевого клиента
+	Ctx() context.Context
+	// CancelBotNet -- вызывает отмену котекста сетевого клиента бота
+	CancelBotNet()
+	// Bot -- возвращает ссылку на бота
+	Bot() IBot
 }

+ 1 - 0
pkg/types/isection.go

@@ -6,6 +6,7 @@ package types
 
 // ISection -- интерфейс базового типа любой секции игры
 type ISection interface {
+	IZone
 	// Update -- обновляет строки секции
 	Update(lstString []string) error
 	// GetLst -- возвращает список строк секции

+ 4 - 4
pkg/types/istatparam.go

@@ -6,10 +6,10 @@ package types
 
 // IStatParam -- интерфейс к праметру
 type IStatParam interface {
-	// Get -- возвращает хранимый параметр
-	Get() int
-	// Set -- устанавливает хранимый параметр
-	Set(val int)
+	// Val -- возвращает хранимый параметр
+	Val() int
+	// SetVal -- устанавливает хранимый параметр
+	SetVal(val int)
 	// Name -- возвращает имя параметра
 	Name() string
 	// SetName -- устанавливает имя параметра

+ 0 - 14
pkg/types/iterm_win.go

@@ -1,14 +0,0 @@
-package types
-
-import (
-	"wartank/pkg/alias"
-
-	tea "github.com/charmbracelet/bubbletea"
-)
-
-// ITermWin -- терминальное окно для показа
-type ITermWin interface {
-	tea.Model
-	// Name -- имя окна
-	Name() alias.AWinName
-}

+ 13 - 0
pkg/types/izone.go

@@ -0,0 +1,13 @@
+package types
+
+import "context"
+
+// IZone -- игровая зона (ангар, база, битва и т.п.)
+type IZone interface {
+	// Bot -- возвращает бота игровой зоны
+	Bot() IBot
+	// Ctx -- контекст игровой зоны
+	Ctx() context.Context
+	// CancelZone -- отмена контекста игровой зоны
+	CancelZone()
+}