fix undo/redo handling
This commit is contained in:
parent
191fb3db3f
commit
03364291aa
|
|
@ -9,10 +9,15 @@ namespace Koogle.Application.DTOs;
|
|||
/// </summary>
|
||||
public record GameStateSerializationDto
|
||||
{
|
||||
/// <summary>
|
||||
/// State of the throw panel before current throw.
|
||||
/// </summary>
|
||||
public ThrowPanelStateDto ThrowPanelBefore { get; init; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Current state of the throw panel.
|
||||
/// </summary>
|
||||
public ThrowPanelStateDto ThrowPanel { get; init; } = new();
|
||||
public ThrowPanelStateDto ThrowPanelAfter { get; init; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Current state of game participants.
|
||||
|
|
@ -120,7 +125,12 @@ public record GameSnapshotDto
|
|||
/// <summary>
|
||||
/// Snapshot of the throw panel state.
|
||||
/// </summary>
|
||||
public ThrowPanelStateDto ThrowPanel { get; init; } = new();
|
||||
public ThrowPanelStateDto ThrowPanelBefore { get; init; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Snapshot of the throw panel state.
|
||||
/// </summary>
|
||||
public ThrowPanelStateDto ThrowPanelAfter { get; init; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Snapshot of the participants state.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,12 @@
|
|||
@inject IState<GameState> GameState
|
||||
@inject IDispatcher Dispatcher
|
||||
|
||||
@* @GameState.Value.ThrowPanelAfter
|
||||
|
||||
<hr/>
|
||||
|
||||
@GameState.Value.ThrowPanelBefore *@
|
||||
|
||||
<div class="game-input-panel">
|
||||
@* Current player display *@
|
||||
<div class="current-player-section">
|
||||
|
|
@ -28,13 +34,13 @@
|
|||
|
||||
@* Pin input area *@
|
||||
<div class="pin-input-section">
|
||||
<PinPanel ThrowPanelState="@GameState.Value.ThrowPanel"
|
||||
<PinPanel ThrowPanelState="@GameState.Value.ThrowPanelAfter"
|
||||
IsInteractive="@IsInteractive"
|
||||
OnPinClicked="HandlePinClick" />
|
||||
</div>
|
||||
|
||||
|
||||
@if (@GameState.Value.ThrowPanel.ThrowMode == ThrowMode.Reposition)
|
||||
@if (@GameState.Value.ThrowPanelAfter.ThrowMode == ThrowMode.Reposition)
|
||||
{
|
||||
@* Number quick-entry *@
|
||||
<div class="number-input-section">
|
||||
|
|
@ -52,7 +58,7 @@
|
|||
|
||||
@* Throw info and controls *@
|
||||
<div class="throw-control-section">
|
||||
<ThrowPanel ThrowPanelState="@GameState.Value.ThrowPanel"
|
||||
<ThrowPanel ThrowPanelState="@GameState.Value.ThrowPanelAfter"
|
||||
IsInteractive="@IsInteractive"
|
||||
OnGutterClicked="HandleGutterClick" />
|
||||
</div>
|
||||
|
|
@ -162,7 +168,7 @@
|
|||
|
||||
private int? _selectedNumber;
|
||||
private bool _hasModifiedPins;
|
||||
private ThrowPanelState? _beforeThrowState;
|
||||
// private ThrowPanelState? _beforeThrowState;
|
||||
private int _lastKnownThrowCounter;
|
||||
|
||||
private bool IsInteractive => GameState.Value.IsGameActive && !GameState.Value.IsLoading;
|
||||
|
|
@ -173,35 +179,46 @@
|
|||
GameState.StateChanged += OnGameStateChanged;
|
||||
// Store initial state for before/after comparison
|
||||
CaptureBeforeThrowState();
|
||||
_lastKnownThrowCounter = GameState.Value.ThrowPanel.TotalThrowCounter;
|
||||
_lastKnownThrowCounter = GameState.Value.ThrowPanelAfter.TotalThrowCounter;
|
||||
}
|
||||
|
||||
private void OnGameStateChanged(object? sender, EventArgs e)
|
||||
{
|
||||
var currentCounter = GameState.Value.ThrowPanel.TotalThrowCounter;
|
||||
var tp = GameState.Value.ThrowPanelAfter;
|
||||
var currentCounter = tp.TotalThrowCounter;
|
||||
|
||||
// Detect external state changes (Undo/Redo/SignalR) by comparing throw counter
|
||||
// If counter changed externally, reset local state and capture new before state
|
||||
// If counter changed externally (went backwards = Undo, or different = external change)
|
||||
if (currentCounter != _lastKnownThrowCounter)
|
||||
{
|
||||
_hasModifiedPins = false;
|
||||
_selectedNumber = null;
|
||||
CaptureBeforeThrowState();
|
||||
|
||||
// // In Reposition mode after Undo, reset pins for clean re-entry
|
||||
// // Counter going backwards indicates Undo
|
||||
// if (currentCounter < _lastKnownThrowCounter &&
|
||||
// tp.ThrowMode == ThrowMode.Reposition)
|
||||
// {
|
||||
// // Reset pins to standing for clean re-entry
|
||||
// Dispatcher.Dispatch(new ResetPinsAction());
|
||||
// }
|
||||
|
||||
_lastKnownThrowCounter = currentCounter;
|
||||
}
|
||||
else if (!_hasModifiedPins)
|
||||
|
||||
// Always capture before state when not actively modifying pins
|
||||
if (!_hasModifiedPins)
|
||||
{
|
||||
// Normal state change (e.g., after throw processed), capture new before state
|
||||
CaptureBeforeThrowState();
|
||||
}
|
||||
|
||||
// Force re-render to update child components (ThrowPanel, PinPanel, etc.)
|
||||
// Force re-render to update child components (ThrowPanelAfter, PinPanel, etc.)
|
||||
InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private void CaptureBeforeThrowState()
|
||||
{
|
||||
_beforeThrowState = GameState.Value.ThrowPanel;
|
||||
// _beforeThrowState = GameState.Value.ThrowPanelAfter;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
@ -217,7 +234,7 @@
|
|||
var currentStatus = GetPinStatus(pinNumber);
|
||||
|
||||
// In Decrease mode, fallen pins cannot be reset to standing
|
||||
if (GameState.Value.ThrowPanel.ThrowMode == ThrowMode.Decrease && currentStatus == PinStatus.Disabled)
|
||||
if (GameState.Value.ThrowPanelAfter.ThrowMode == ThrowMode.Decrease && currentStatus == PinStatus.Disabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -232,7 +249,7 @@
|
|||
private void HandleNumberClick(int number)
|
||||
{
|
||||
// Quick entry: set pins 1-N as fallen, reset as standing
|
||||
var newState = GameState.Value.ThrowPanel.ResetPins();
|
||||
var newState = GameState.Value.ThrowPanelAfter.ResetPins();
|
||||
|
||||
for (int i = 1; i <= 9; i++)
|
||||
{
|
||||
|
|
@ -254,7 +271,7 @@
|
|||
|
||||
private void HandleBellClick()
|
||||
{
|
||||
Dispatcher.Dispatch(new SetBellValueAction(!GameState.Value.ThrowPanel.BellValue));
|
||||
Dispatcher.Dispatch(new SetBellValueAction(!GameState.Value.ThrowPanelAfter.BellValue));
|
||||
}
|
||||
|
||||
private async Task HandleGutterClick(bool isLeft)
|
||||
|
|
@ -273,7 +290,7 @@
|
|||
|
||||
private async Task ConfirmThrow(bool isGutter, bool isLeftGutter)
|
||||
{
|
||||
var currentThrowPanel = GameState.Value.ThrowPanel;
|
||||
var currentThrowPanel = GameState.Value.ThrowPanelAfter;
|
||||
var fallenPins = currentThrowPanel.CountFallenPins();
|
||||
var bellValue = currentThrowPanel.BellValue;
|
||||
|
||||
|
|
@ -288,7 +305,8 @@
|
|||
};
|
||||
|
||||
// Get before state (captured at start of input session)
|
||||
var beforeState = _beforeThrowState ?? currentThrowPanel;
|
||||
// var beforeState = _beforeThrowState ?? currentThrowPanel;
|
||||
var beforeState = GameState.Value.ThrowPanelBefore;
|
||||
|
||||
// Dispatch record throw action - game logic will handle pin reset and player rotation
|
||||
Dispatcher.Dispatch(new RecordThrowAction(beforeState, currentThrowPanel, isGutter, isLeftGutter));
|
||||
|
|
@ -310,15 +328,15 @@
|
|||
|
||||
private PinStatus GetPinStatus(int pinNumber) => pinNumber switch
|
||||
{
|
||||
1 => GameState.Value.ThrowPanel.Pin1,
|
||||
2 => GameState.Value.ThrowPanel.Pin2,
|
||||
3 => GameState.Value.ThrowPanel.Pin3,
|
||||
4 => GameState.Value.ThrowPanel.Pin4,
|
||||
5 => GameState.Value.ThrowPanel.Pin5,
|
||||
6 => GameState.Value.ThrowPanel.Pin6,
|
||||
7 => GameState.Value.ThrowPanel.Pin7,
|
||||
8 => GameState.Value.ThrowPanel.Pin8,
|
||||
9 => GameState.Value.ThrowPanel.Pin9,
|
||||
1 => GameState.Value.ThrowPanelAfter.Pin1,
|
||||
2 => GameState.Value.ThrowPanelAfter.Pin2,
|
||||
3 => GameState.Value.ThrowPanelAfter.Pin3,
|
||||
4 => GameState.Value.ThrowPanelAfter.Pin4,
|
||||
5 => GameState.Value.ThrowPanelAfter.Pin5,
|
||||
6 => GameState.Value.ThrowPanelAfter.Pin6,
|
||||
7 => GameState.Value.ThrowPanelAfter.Pin7,
|
||||
8 => GameState.Value.ThrowPanelAfter.Pin8,
|
||||
9 => GameState.Value.ThrowPanelAfter.Pin9,
|
||||
_ => PinStatus.Standing
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,8 @@ public record LoadActiveGameAction(Guid DayId);
|
|||
public record LoadActiveGameSuccessAction(
|
||||
Guid GameId,
|
||||
string GameTypeName,
|
||||
ThrowPanelState ThrowPanel,
|
||||
ThrowPanelState ThrowPanelBefore,
|
||||
ThrowPanelState ThrowPanelAfter,
|
||||
ParticipantsState Participants,
|
||||
object? GameModel,
|
||||
IReadOnlyList<GameSnapshot> UndoStack,
|
||||
|
|
|
|||
|
|
@ -55,7 +55,13 @@ public class GameEffects
|
|||
{
|
||||
var initialState = new GameStateSerializationDto
|
||||
{
|
||||
ThrowPanel = MapThrowPanelToDto(ThrowPanelState.Initial with
|
||||
ThrowPanelAfter = MapThrowPanelToDto(ThrowPanelState.Initial with
|
||||
{
|
||||
IsStarted = true,
|
||||
ThrowsPerRound = action.ThrowsPerRound,
|
||||
ThrowMode = action.ThrowMode
|
||||
}),
|
||||
ThrowPanelBefore = MapThrowPanelToDto(ThrowPanelState.Initial with
|
||||
{
|
||||
IsStarted = true,
|
||||
ThrowsPerRound = action.ThrowsPerRound,
|
||||
|
|
@ -201,12 +207,14 @@ public class GameEffects
|
|||
return;
|
||||
}
|
||||
|
||||
var throwPanel = MapDtoToThrowPanel(stateDto.ThrowPanel);
|
||||
var throwPanelBefore = MapDtoToThrowPanel(stateDto.ThrowPanelBefore);
|
||||
var throwPanelAfter = MapDtoToThrowPanel(stateDto.ThrowPanelAfter);
|
||||
var participants = MapDtoToParticipants(stateDto.Participants);
|
||||
var undoStack = stateDto.UndoStack
|
||||
.Select(s => new GameSnapshot
|
||||
{
|
||||
ThrowPanel = MapDtoToThrowPanel(s.ThrowPanel),
|
||||
ThrowPanelBefore = MapDtoToThrowPanel(s.ThrowPanelBefore),
|
||||
ThrowPanelAfter = MapDtoToThrowPanel(s.ThrowPanelAfter),
|
||||
Participants = MapDtoToParticipants(s.Participants),
|
||||
GameModel = s.GameModel.HasValue ? (object?)s.GameModel.Value : null
|
||||
})
|
||||
|
|
@ -214,7 +222,8 @@ public class GameEffects
|
|||
var redoStack = stateDto.RedoStack
|
||||
.Select(s => new GameSnapshot
|
||||
{
|
||||
ThrowPanel = MapDtoToThrowPanel(s.ThrowPanel),
|
||||
ThrowPanelBefore = MapDtoToThrowPanel(s.ThrowPanelBefore),
|
||||
ThrowPanelAfter = MapDtoToThrowPanel(s.ThrowPanelAfter),
|
||||
Participants = MapDtoToParticipants(s.Participants),
|
||||
GameModel = s.GameModel.HasValue ? (object?)s.GameModel.Value : null
|
||||
})
|
||||
|
|
@ -232,7 +241,8 @@ public class GameEffects
|
|||
dispatcher.Dispatch(new LoadActiveGameSuccessAction(
|
||||
activeGame.Id,
|
||||
activeGame.GameType,
|
||||
throwPanel,
|
||||
throwPanelBefore,
|
||||
throwPanelAfter,
|
||||
participants,
|
||||
stateDto.GameModel.HasValue ? (object?)stateDto.GameModel.Value : null,
|
||||
undoStack,
|
||||
|
|
@ -467,13 +477,13 @@ public class GameEffects
|
|||
[EffectMethod]
|
||||
public Task HandleUndoThrowSuccess(UndoThrowSuccessAction action, IDispatcher dispatcher)
|
||||
{
|
||||
//var stateAfterReducer = _gameState.Value;
|
||||
//_logger.LogInformation(
|
||||
// "UNDO SUCCESS: State after reducer - pins fallen={Fallen}, total={Total}, UndoStack={UndoCount}, RedoStack={RedoCount}",
|
||||
// stateAfterReducer.ThrowPanel.CountFallenPins(),
|
||||
// stateAfterReducer.ThrowPanel.TotalThrowCounter,
|
||||
// stateAfterReducer.UndoStack.Count,
|
||||
// stateAfterReducer.RedoStack.Count);
|
||||
var stateAfterReducer = _gameState.Value;
|
||||
_logger.LogInformation(
|
||||
"UNDO SUCCESS: State after reducer - pins fallen={Fallen}, total={Total}, UndoStack={UndoCount}, RedoStack={RedoCount}",
|
||||
stateAfterReducer.ThrowPanelAfter.CountFallenPins(),
|
||||
stateAfterReducer.ThrowPanelAfter.TotalThrowCounter,
|
||||
stateAfterReducer.UndoStack.Count,
|
||||
stateAfterReducer.RedoStack.Count);
|
||||
|
||||
// Save after undo as well
|
||||
_saveDebounceTimer?.Dispose();
|
||||
|
|
@ -506,13 +516,13 @@ public class GameEffects
|
|||
_logger.LogInformation(
|
||||
"UNDO: Stack={StackSize}, Current pins fallen={CurrentFallen}, Snapshot pins fallen={SnapshotFallen}, Current total={CurrentTotal}, Snapshot total={SnapshotTotal}",
|
||||
state.UndoStack.Count,
|
||||
state.ThrowPanel.CountFallenPins(),
|
||||
lastSnapshot.ThrowPanel.CountFallenPins(),
|
||||
state.ThrowPanel.TotalThrowCounter,
|
||||
lastSnapshot.ThrowPanel.TotalThrowCounter);
|
||||
state.ThrowPanelAfter.CountFallenPins(),
|
||||
lastSnapshot.ThrowPanelAfter.CountFallenPins(),
|
||||
state.ThrowPanelAfter.TotalThrowCounter,
|
||||
lastSnapshot.ThrowPanelAfter.TotalThrowCounter);
|
||||
|
||||
dispatcher.Dispatch(new UndoThrowSuccessAction(
|
||||
lastSnapshot.ThrowPanel,
|
||||
lastSnapshot.ThrowPanelAfter,
|
||||
lastSnapshot.Participants,
|
||||
lastSnapshot.GameModel));
|
||||
|
||||
|
|
@ -539,10 +549,10 @@ public class GameEffects
|
|||
_logger.LogDebug(
|
||||
"Redoing throw. Stack size before: {StackSize}, Restoring to throw counter: {ThrowCounter}",
|
||||
state.RedoStack.Count,
|
||||
lastSnapshot.ThrowPanel.TotalThrowCounter);
|
||||
lastSnapshot.ThrowPanelAfter.TotalThrowCounter);
|
||||
|
||||
dispatcher.Dispatch(new RedoThrowSuccessAction(
|
||||
lastSnapshot.ThrowPanel,
|
||||
lastSnapshot.ThrowPanelAfter,
|
||||
lastSnapshot.Participants,
|
||||
lastSnapshot.GameModel));
|
||||
|
||||
|
|
@ -617,7 +627,8 @@ public class GameEffects
|
|||
{
|
||||
return new GameStateSerializationDto
|
||||
{
|
||||
ThrowPanel = MapThrowPanelToDto(state.ThrowPanel),
|
||||
ThrowPanelBefore = MapThrowPanelToDto(state.ThrowPanelBefore),
|
||||
ThrowPanelAfter = MapThrowPanelToDto(state.ThrowPanelAfter),
|
||||
Participants = new ParticipantsStateDto
|
||||
{
|
||||
PlayerIds = state.Participants.PlayerIds,
|
||||
|
|
@ -632,7 +643,7 @@ public class GameEffects
|
|||
: null,
|
||||
UndoStack = state.UndoStack.Select(s => new GameSnapshotDto
|
||||
{
|
||||
ThrowPanel = MapThrowPanelToDto(s.ThrowPanel),
|
||||
ThrowPanelAfter = MapThrowPanelToDto(s.ThrowPanelAfter),
|
||||
Participants = new ParticipantsStateDto
|
||||
{
|
||||
PlayerIds = s.Participants.PlayerIds,
|
||||
|
|
@ -645,7 +656,7 @@ public class GameEffects
|
|||
}).ToList(),
|
||||
RedoStack = state.RedoStack.Select(s => new GameSnapshotDto
|
||||
{
|
||||
ThrowPanel = MapThrowPanelToDto(s.ThrowPanel),
|
||||
ThrowPanelAfter = MapThrowPanelToDto(s.ThrowPanelAfter),
|
||||
Participants = new ParticipantsStateDto
|
||||
{
|
||||
PlayerIds = s.Participants.PlayerIds,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using System.Text.Json;
|
|||
using Fluxor;
|
||||
using Koogle.Application.Games;
|
||||
using Koogle.Domain.Enums;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Koogle.Web.Store.GameState;
|
||||
|
||||
|
|
@ -34,7 +35,7 @@ public static class GameReducers
|
|||
IsGameActive = true,
|
||||
ActiveGameId = action.GameId,
|
||||
GameTypeName = action.GameTypeName,
|
||||
ThrowPanel = action.ThrowPanel,
|
||||
ThrowPanelAfter = action.ThrowPanel,
|
||||
Participants = action.Participants,
|
||||
GameModel = action.GameModel,
|
||||
Setup = action.Setup,
|
||||
|
|
@ -76,7 +77,7 @@ public static class GameReducers
|
|||
IsGameActive = false,
|
||||
ActiveGameId = null,
|
||||
GameTypeName = null,
|
||||
ThrowPanel = ThrowPanelState.Initial,
|
||||
ThrowPanelAfter = ThrowPanelState.Initial,
|
||||
Participants = ParticipantsState.Initial,
|
||||
GameModel = null,
|
||||
Setup = null,
|
||||
|
|
@ -119,7 +120,7 @@ public static class GameReducers
|
|||
IsGameActive = true,
|
||||
ActiveGameId = action.GameId,
|
||||
GameTypeName = action.GameTypeName,
|
||||
ThrowPanel = action.ThrowPanel,
|
||||
ThrowPanelAfter = action.ThrowPanelAfter,
|
||||
Participants = action.Participants,
|
||||
GameModel = action.GameModel,
|
||||
Setup = action.Setup,
|
||||
|
|
@ -198,11 +199,17 @@ public static class GameReducers
|
|||
|
||||
var snapshot = new GameSnapshot
|
||||
{
|
||||
ThrowPanel = state.ThrowPanel,
|
||||
ThrowPanelAfter = state.ThrowPanelAfter,
|
||||
Participants = state.Participants,
|
||||
GameModel = clonedGameModel
|
||||
};
|
||||
|
||||
Console.WriteLine($"[OnRecordThrow] Creating snapshot - state.ThrowPanelAfter pins: " +
|
||||
$"[{(int)state.ThrowPanelAfter.Pin1},{(int)state.ThrowPanelAfter.Pin2},{(int)state.ThrowPanelAfter.Pin3}," +
|
||||
$"{(int)state.ThrowPanelAfter.Pin4},{(int)state.ThrowPanelAfter.Pin5},{(int)state.ThrowPanelAfter.Pin6}," +
|
||||
$"{(int)state.ThrowPanelAfter.Pin7},{(int)state.ThrowPanelAfter.Pin8},{(int)state.ThrowPanelAfter.Pin9}] " +
|
||||
$"TotalThrows={state.ThrowPanelAfter.TotalThrowCounter}");
|
||||
|
||||
return state with
|
||||
{
|
||||
UndoStack = state.UndoStack.Add(snapshot),
|
||||
|
|
@ -217,9 +224,15 @@ public static class GameReducers
|
|||
[ReducerMethod]
|
||||
public static GameState OnProcessThrowResult(GameState state, ProcessThrowResultAction action)
|
||||
{
|
||||
Console.WriteLine($"[OnProcessThrowResult] Setting new ThrowPanelAfter pins: " +
|
||||
$"[{(int)action.NewThrowPanelState.Pin1},{(int)action.NewThrowPanelState.Pin2},{(int)action.NewThrowPanelState.Pin3}," +
|
||||
$"{(int)action.NewThrowPanelState.Pin4},{(int)action.NewThrowPanelState.Pin5},{(int)action.NewThrowPanelState.Pin6}," +
|
||||
$"{(int)action.NewThrowPanelState.Pin7},{(int)action.NewThrowPanelState.Pin8},{(int)action.NewThrowPanelState.Pin9}] " +
|
||||
$"TotalThrows={action.NewThrowPanelState.TotalThrowCounter}");
|
||||
|
||||
var newState = state with
|
||||
{
|
||||
ThrowPanel = action.NewThrowPanelState,
|
||||
ThrowPanelAfter = action.NewThrowPanelState,
|
||||
GameModel = action.UpdatedGameModel,
|
||||
IsLoading = false,
|
||||
IsSaving = true
|
||||
|
|
@ -274,7 +287,7 @@ public static class GameReducers
|
|||
public static GameState OnSetPinStatus(GameState state, SetPinStatusAction action)
|
||||
=> state with
|
||||
{
|
||||
ThrowPanel = state.ThrowPanel.SetPin(action.PinNumber, action.Status)
|
||||
ThrowPanelAfter = state.ThrowPanelAfter.SetPin(action.PinNumber, action.Status)
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -284,7 +297,7 @@ public static class GameReducers
|
|||
public static GameState OnResetPins(GameState state)
|
||||
=> state with
|
||||
{
|
||||
ThrowPanel = state.ThrowPanel.ResetPins()
|
||||
ThrowPanelAfter = state.ThrowPanelAfter.ResetPins()
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -294,7 +307,7 @@ public static class GameReducers
|
|||
public static GameState OnSetBellValue(GameState state, SetBellValueAction action)
|
||||
=> state with
|
||||
{
|
||||
ThrowPanel = state.ThrowPanel with { BellValue = action.Value }
|
||||
ThrowPanelAfter = state.ThrowPanelAfter with { BellValue = action.Value }
|
||||
};
|
||||
|
||||
// Player Reducers
|
||||
|
|
@ -327,10 +340,16 @@ public static class GameReducers
|
|||
[ReducerMethod]
|
||||
public static GameState OnUndoThrowSuccess(GameState state, UndoThrowSuccessAction action)
|
||||
{
|
||||
Console.WriteLine($"[OnUndoThrowSuccess] Restoring - action.ThrowPanelAfter pins: " +
|
||||
$"[{(int)action.ThrowPanel.Pin1},{(int)action.ThrowPanel.Pin2},{(int)action.ThrowPanel.Pin3}," +
|
||||
$"{(int)action.ThrowPanel.Pin4},{(int)action.ThrowPanel.Pin5},{(int)action.ThrowPanel.Pin6}," +
|
||||
$"{(int)action.ThrowPanel.Pin7},{(int)action.ThrowPanel.Pin8},{(int)action.ThrowPanel.Pin9}] " +
|
||||
$"TotalThrows={action.ThrowPanel.TotalThrowCounter}");
|
||||
|
||||
// Create snapshot of current state for redo (deep clone GameModel)
|
||||
var currentSnapshot = new GameSnapshot
|
||||
{
|
||||
ThrowPanel = state.ThrowPanel,
|
||||
ThrowPanelAfter = state.ThrowPanelAfter,
|
||||
Participants = state.Participants,
|
||||
GameModel = CloneGameModel(state.GameModel)
|
||||
};
|
||||
|
|
@ -342,7 +361,7 @@ public static class GameReducers
|
|||
|
||||
return state with
|
||||
{
|
||||
ThrowPanel = action.ThrowPanel,
|
||||
ThrowPanelAfter = action.ThrowPanel,
|
||||
Participants = action.Participants,
|
||||
GameModel = action.GameModel,
|
||||
UndoStack = newUndoStack,
|
||||
|
|
@ -372,7 +391,7 @@ public static class GameReducers
|
|||
// Create snapshot of current state for undo (deep clone GameModel)
|
||||
var currentSnapshot = new GameSnapshot
|
||||
{
|
||||
ThrowPanel = state.ThrowPanel,
|
||||
ThrowPanelAfter = state.ThrowPanelAfter,
|
||||
Participants = state.Participants,
|
||||
GameModel = CloneGameModel(state.GameModel)
|
||||
};
|
||||
|
|
@ -384,7 +403,7 @@ public static class GameReducers
|
|||
|
||||
return state with
|
||||
{
|
||||
ThrowPanel = action.ThrowPanel,
|
||||
ThrowPanelAfter = action.ThrowPanel,
|
||||
Participants = action.Participants,
|
||||
GameModel = action.GameModel,
|
||||
UndoStack = state.UndoStack.Add(currentSnapshot),
|
||||
|
|
@ -466,7 +485,7 @@ public static class GameReducers
|
|||
public static GameState OnGameStateUpdatedFromHub(GameState state, GameStateUpdatedFromHubAction action)
|
||||
=> state with
|
||||
{
|
||||
ThrowPanel = action.ThrowPanel,
|
||||
ThrowPanelAfter = action.ThrowPanel,
|
||||
Participants = action.Participants,
|
||||
GameModel = action.GameModel
|
||||
};
|
||||
|
|
@ -481,7 +500,7 @@ public static class GameReducers
|
|||
IsGameActive = false,
|
||||
ActiveGameId = null,
|
||||
GameTypeName = null,
|
||||
ThrowPanel = ThrowPanelState.Initial,
|
||||
ThrowPanelAfter = ThrowPanelState.Initial,
|
||||
Participants = ParticipantsState.Initial,
|
||||
GameModel = null,
|
||||
Setup = null,
|
||||
|
|
|
|||
|
|
@ -31,10 +31,15 @@ public record GameState
|
|||
/// </summary>
|
||||
public Guid? ActiveGameId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// State of the throw panel before the current throw.
|
||||
/// </summary>
|
||||
public ThrowPanelState ThrowPanelBefore { get; init; } = ThrowPanelState.Initial;
|
||||
|
||||
/// <summary>
|
||||
/// Current state of the throw panel.
|
||||
/// </summary>
|
||||
public ThrowPanelState ThrowPanel { get; init; } = ThrowPanelState.Initial;
|
||||
public ThrowPanelState ThrowPanelAfter { get; init; } = ThrowPanelState.Initial;
|
||||
|
||||
/// <summary>
|
||||
/// Current state of game participants.
|
||||
|
|
@ -100,7 +105,7 @@ public record GameState
|
|||
GameTypeName = null,
|
||||
DayId = null,
|
||||
ActiveGameId = null,
|
||||
ThrowPanel = ThrowPanelState.Initial,
|
||||
ThrowPanelAfter = ThrowPanelState.Initial,
|
||||
Participants = ParticipantsState.Initial,
|
||||
GameModel = null,
|
||||
Setup = null,
|
||||
|
|
@ -350,7 +355,12 @@ public record GameSnapshot
|
|||
/// <summary>
|
||||
/// Snapshot of the throw panel state.
|
||||
/// </summary>
|
||||
public ThrowPanelState ThrowPanel { get; init; } = ThrowPanelState.Initial;
|
||||
public ThrowPanelState ThrowPanelBefore { get; init; } = ThrowPanelState.Initial;
|
||||
|
||||
/// <summary>
|
||||
/// Snapshot of the throw panel state.
|
||||
/// </summary>
|
||||
public ThrowPanelState ThrowPanelAfter { get; init; } = ThrowPanelState.Initial;
|
||||
|
||||
/// <summary>
|
||||
/// Snapshot of the participants state.
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
@inject IGameStatusDataService DataService;
|
||||
|
||||
@* @ThrowPanelState.Value *@
|
||||
@* @ThrowPanelAfterAfterState.Value *@
|
||||
|
||||
@switch (_gameView)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue