From 2f745ba3284d22385639e554aaf2e85f1fdd9e68 Mon Sep 17 00:00:00 2001 From: Konstantin Dyachenko Date: Wed, 27 May 2026 04:04:59 +0700 Subject: [PATCH] =?UTF-8?q?=EF=BB=BFfeat(task-0002):=20implement=20state?= =?UTF-8?q?=20controller=20interface=20with=20cancellation=20support=20and?= =?UTF-8?q?=20update=20task=20status?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Refactor BootStatesController to implement IStatesController interface - Move state dictionary creation into constructor, remove static helper method - Add CancellationToken validation before state transitions in StatesController - Track current state presence with _hasCurrentState flag for safety - Update TASK-0002 with Ready status Выполнена задача TASK-0002 и обновлён статус: - Рефакторинг BootStatesController для реализации интерфейса IStatesController - Перемещено создание словаря состояний в конструктор, удалён статический вспомогательный метод - Добавлена валидация CancellationToken перед переходами между состояниями в StatesController - Добавлен флаг _hasCurrentState для отслеживания текущего состояния - Обновлён статус TASK-0002 до Ready --- Agent/Task/TASK-0002.md | 4 +++ .../Boot/States/BootStatesController.cs | 26 ++++++++++--------- .../Common/StateMachine/StatesController.cs | 12 +++++++-- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/Agent/Task/TASK-0002.md b/Agent/Task/TASK-0002.md index 666aed1..6323788 100644 --- a/Agent/Task/TASK-0002.md +++ b/Agent/Task/TASK-0002.md @@ -1,5 +1,9 @@ # TASK-0002: Базовая архитектура Boot Flow +## Статус + +Ready + ## Цель Создать минимальную архитектурную основу для boot flow: сервисный lifecycle, state-контракты и generic state controller. diff --git a/Assets/Scripts/Boot/States/BootStatesController.cs b/Assets/Scripts/Boot/States/BootStatesController.cs index 2a4efd0..30fc49f 100644 --- a/Assets/Scripts/Boot/States/BootStatesController.cs +++ b/Assets/Scripts/Boot/States/BootStatesController.cs @@ -1,29 +1,31 @@ using System.Collections.Generic; +using System.Threading; +using Cysharp.Threading.Tasks; using QuizPleaseTest.Common.StateMachine; namespace QuizPleaseTest.Boot.States { - public class BootStatesController : StatesController + public class BootStatesController : IStatesController { + private readonly StatesController _statesController; + public BootStatesController( SplashState splashState, LoadState loadState, MenuState menuState) - : base(CreateStates(splashState, loadState, menuState)) { + _statesController = new StatesController( + new Dictionary + { + { BootStateCode.Splash, splashState }, + { BootStateCode.Load, loadState }, + { BootStateCode.Menu, menuState } + }); } - private static IReadOnlyDictionary CreateStates( - SplashState splashState, - LoadState loadState, - MenuState menuState) + public UniTask EnterStateAsync(BootStateCode code, CancellationToken ct) { - return new Dictionary - { - { BootStateCode.Splash, splashState }, - { BootStateCode.Load, loadState }, - { BootStateCode.Menu, menuState } - }; + return _statesController.EnterStateAsync(code, ct); } } } diff --git a/Assets/Scripts/Common/StateMachine/StatesController.cs b/Assets/Scripts/Common/StateMachine/StatesController.cs index a76ff93..714d400 100644 --- a/Assets/Scripts/Common/StateMachine/StatesController.cs +++ b/Assets/Scripts/Common/StateMachine/StatesController.cs @@ -9,6 +9,7 @@ namespace QuizPleaseTest.Common.StateMachine { private readonly IReadOnlyDictionary _states; private IState _currentState; + private bool _hasCurrentState; public StatesController(IReadOnlyDictionary states) { @@ -17,18 +18,25 @@ namespace QuizPleaseTest.Common.StateMachine public async UniTask EnterStateAsync(TEnum code, CancellationToken ct) { + ct.ThrowIfCancellationRequested(); + if (!_states.TryGetValue(code, out IState newState)) { throw new InvalidOperationException($"State is not registered: {code}"); } - if (_currentState != null) + if (_hasCurrentState) { await _currentState.ExitAsync(ct); + _currentState = null; + _hasCurrentState = false; } + ct.ThrowIfCancellationRequested(); + + await newState.EnterAsync(ct); _currentState = newState; - await _currentState.EnterAsync(ct); + _hasCurrentState = true; } } }