This commit is contained in:
beo3000 2025-11-10 10:36:29 +01:00
parent d80539740d
commit 0b0218824a
13 changed files with 220 additions and 94 deletions

View File

@ -2,6 +2,7 @@
@using KoogleApp.Model.EventMessages
@using KoogleApp.Services
@using KoogleApp.Store.Game
@using KoogleApp.Store.Game.ThrowPanel
@inherits FluxorComponent

View File

@ -3,6 +3,7 @@
@using KoogleApp.Model.EventMessages
@using KoogleApp.Services
@using KoogleApp.Store.Game
@using KoogleApp.Store.Game.ThrowPanel
@inherits FluxorComponent

View File

@ -1,10 +1,11 @@
@using KoogleApp.Model
@using KoogleApp.Store.Game
@using KoogleApp.Store.Game.ThrowPanel
@inherits FluxorComponent
@inject IState<ThrowPanelState> ThrowPanelState
@inject IDispatcher Dispatcher
@if (ThrowPanelState.Value.IsStated)
{
@ -60,6 +61,16 @@
// public ThrowPanelState? PanelState { get; set; }
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
Dispatcher.Dispatch(new LoadStateFromSessionAction());
}
base.OnAfterRender(firstRender);
}
private async Task OnNumberPinStateChanged(ThrowPanelState state)
{
await OnStateChanged.InvokeAsync(state);

View File

@ -8,6 +8,7 @@
@using KoogleApp.Model.EventMessages
@using KoogleApp.Model.Framework
@using KoogleApp.Store.Game
@using KoogleApp.Store.Game.ThrowPanel
@inherits FluxorComponent
@ -255,7 +256,7 @@
Dispatcher.Dispatch(action);
// _throwPanelState = ThrowPanelState.Create();
// await BroadcastThrowPanelState(_throwPanelState);
// await BroadcastThrowPanelStateAction(_throwPanelState);
// await InvokeAsync(StateHasChanged);
}
@ -274,10 +275,10 @@
// private async Task OnThrowPanelStateChanged(ThrowPanelState state)
// {
// await BroadcastThrowPanelState(state);
// await BroadcastThrowPanelStateAction(state);
// }
// private async Task BroadcastThrowPanelState(ThrowPanelState state)
// private async Task BroadcastThrowPanelStateAction(ThrowPanelState state)
// {
// if (hubConnection is not null)
// {

View File

@ -1,12 +1,12 @@
using Fluxor;
using KoogleApp.Model;
using KoogleApp.Services;
using KoogleApp.Store.Game;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using System.Diagnostics;
using KoogleApp.Store.Game.ThrowPanel;
namespace KoogleApp.Hub
{
@ -63,9 +63,9 @@ namespace KoogleApp.Hub
try
{
if (_hubConnection is not null)
{
await _hubConnection.SendAsync("BroadcastThrowPanelState", action.State);
}
{
await _hubConnection.SendAsync("BroadcastThrowPanelState", action.State);
}
//await Clients.Others.SendAsync("ReceiveThrowPanelState", new ThrowPanelState());

View File

@ -0,0 +1,27 @@
using System.Runtime.InteropServices;
using Fluxor;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
namespace KoogleApp.Model
{
[FeatureState]
public record ThrowPanelState(bool IsStated, bool BellValue,
bool Pin1Value, bool Pin2Value, bool Pin3Value, bool Pin4Value, bool Pin5Value, bool Pin6Value, bool Pin7Value, bool Pin8Value, bool Pin9Value,
bool Pin1Disabled, bool Pin2Disabled, bool Pin3Disabled, bool Pin4Disabled, bool Pin5Disabled, bool Pin6Disabled, bool Pin7Disabled, bool Pin8Disabled, bool Pin9Disabled
)
{
// Required for creating initial state
public ThrowPanelState() : this(BellValue:false, IsStated:false,
Pin1Value:false, Pin2Value:false, Pin3Value: false, Pin4Value: false, Pin5Value: false, Pin6Value: false, Pin7Value: false, Pin8Value: false, Pin9Value: false,
Pin1Disabled:false, Pin2Disabled:false, Pin3Disabled: false, Pin4Disabled: false, Pin5Disabled: false, Pin6Disabled: false, Pin7Disabled: false, Pin8Disabled: false, Pin9Disabled: false
)
{ }
}
// Actions
}

View File

@ -22,7 +22,7 @@ namespace KoogleApp.Services
private GameStatusSnapshot _currentData;
private readonly Stack<GameStatusSnapshot> _undoStack;
private readonly Stack<GameStatusSnapshot> _redoStack;
private readonly object _lock = new object();
private readonly Lock _lock = new Lock();
private readonly string _dataFilePath = "appdata.json";
private const int MaxUndoSteps = 50;

View File

@ -15,5 +15,16 @@ namespace KoogleApp.Services
{
await sessionStorage.SetAsync("selectedPlayer", record);
}
public async Task<ThrowPanelState?> GetThrowPanelStateAsync()
{
var result = await sessionStorage.GetAsync<ThrowPanelState>("throwPanelState");
return result.Success ? result.Value : null;
}
public async Task SetThrowPanelStateAsync(ThrowPanelState state)
{
await sessionStorage.SetAsync("throwPanelState", state);
}
}
}

View File

@ -0,0 +1,24 @@
using KoogleApp.Model;
namespace KoogleApp.Store.Game.ThrowPanel
{
public record TogglePinValueAction(bool IsOn, int PinNumber);
public record StartAction(ThrowPanelState State);
public record ConnectToHubAction();
public record ToggleAllPinsAction();
public record ToggleBellAction();
public record UpdatePinStateByNumber(int Number);
public record ReceiveStateFromServer(ThrowPanelState State);
public record LoadStateFromSessionAction();
public record StateLoadedAction(ThrowPanelState? State);
public record BroadcastThrowPanelStateAction(ThrowPanelState State);
}

View File

@ -0,0 +1,103 @@
using Fluxor;
using KoogleApp.Hub;
using KoogleApp.Model;
using KoogleApp.Services;
using System.Text.Json;
namespace KoogleApp.Store.Game.ThrowPanel
{
public class ThrowPanelEffects : IDisposable
{
private readonly ILogger<ThrowPanelEffects> _logger;
private readonly HubConnectionService _sharedModelHub;
private readonly IState<ThrowPanelState> _state;
private readonly SessionStorage _sessionStorage;
private readonly string _dataFilePath = "ThrowPanelState.json";
public ThrowPanelEffects(
ILogger<ThrowPanelEffects> logger,
HubConnectionService sharedModelHub, IState<ThrowPanelState> state,
SessionStorage sessionStorage)
{
_logger = logger;
_sharedModelHub = sharedModelHub;
_state = state;
_sessionStorage = sessionStorage;
}
public void Dispose()
{
//_sharedModelHub?.Dispose();
}
//[EffectMethod(typeof(StartAction))]
[EffectMethod]
public async Task HandleStartAction(StartAction action, IDispatcher dispatcher)
{
dispatcher.Dispatch(new BroadcastThrowPanelStateAction(_state.Value));
}
[EffectMethod]
public async Task HandleConnectToHubAction(ConnectToHubAction action, IDispatcher dispatcher)
{
try
{
await _sharedModelHub.ConnectToHub(dispatcher);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to connect to hub");
//dispatcher.Dispatch(new HubConnectionFailedAction(ex.Message));
}
}
[EffectMethod]
public async Task HandelLoadStateAction(LoadStateFromSessionAction stateFromSessionAction, IDispatcher dispatcher)
{
var state = await _sessionStorage.GetThrowPanelStateAsync();
if (state == null)
{
try
{
if (File.Exists(_dataFilePath))
{
var json = await File.ReadAllTextAsync(_dataFilePath);
state = JsonSerializer.Deserialize<ThrowPanelState>(json);
}
}
catch (Exception e)
{
// TODO error handling
}
}
if (state != null)
{
dispatcher.Dispatch(new StateLoadedAction(state));
}
}
[EffectMethod]
public async Task HandelBroadcastThrowPanelStateAction(BroadcastThrowPanelStateAction action, IDispatcher dispatcher)
{
await _sessionStorage.SetThrowPanelStateAsync(action.State);
try
{
var json = JsonSerializer.Serialize(action.State, new JsonSerializerOptions
{
WriteIndented = true
});
await File.WriteAllTextAsync(_dataFilePath, json);
}
catch (Exception ex)
{
// TODO error handling
}
await _sharedModelHub.HandleStartAction(new StartAction(_state.Value), dispatcher);
}
}
}

View File

@ -1,40 +1,8 @@
using System.Runtime.InteropServices;
using Fluxor;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using Fluxor;
using KoogleApp.Model;
namespace KoogleApp.Store.Game
namespace KoogleApp.Store.Game.ThrowPanel
{
[FeatureState]
public record ThrowPanelState(bool IsStated, bool BellValue,
bool Pin1Value, bool Pin2Value, bool Pin3Value, bool Pin4Value, bool Pin5Value, bool Pin6Value, bool Pin7Value, bool Pin8Value, bool Pin9Value,
bool Pin1Disabled, bool Pin2Disabled, bool Pin3Disabled, bool Pin4Disabled, bool Pin5Disabled, bool Pin6Disabled, bool Pin7Disabled, bool Pin8Disabled, bool Pin9Disabled
)
{
// Required for creating initial state
public ThrowPanelState() : this(BellValue:false, IsStated:false,
Pin1Value:false, Pin2Value:false, Pin3Value: false, Pin4Value: false, Pin5Value: false, Pin6Value: false, Pin7Value: false, Pin8Value: false, Pin9Value: false,
Pin1Disabled:false, Pin2Disabled:false, Pin3Disabled: false, Pin4Disabled: false, Pin5Disabled: false, Pin6Disabled: false, Pin7Disabled: false, Pin8Disabled: false, Pin9Disabled: false
)
{ }
}
// Actions
public record TogglePinValueAction(bool IsOn, int PinNumber);
public record StartAction(ThrowPanelState State);
public record ConnectToHubAction();
public record ToggleAllPinsAction();
public record ToggleBellAction();
public record UpdatePinStateByNumber(int Number);
public record ReceiveStateFromServer(ThrowPanelState State);
// Reducer
public static class ThrowPanelStateReducer
{
@ -148,5 +116,11 @@ namespace KoogleApp.Store.Game
{
return state with { BellValue = !state.BellValue };
}
[ReducerMethod]
public static ThrowPanelState OnLoadState(ThrowPanelState state, StateLoadedAction action)
{
return action.State;
}
}
}
}

View File

@ -1,49 +0,0 @@
using Fluxor;
using KoogleApp.Hub;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.SignalR.Client;
namespace KoogleApp.Store.Game
{
public class ThrowPanelEffects : IDisposable
{
private readonly ILogger<ThrowPanelEffects> _logger;
private readonly HubConnectionService _sharedModelHub;
private readonly IState<ThrowPanelState> _state;
public ThrowPanelEffects(
ILogger<ThrowPanelEffects> logger,
HubConnectionService sharedModelHub, IState<ThrowPanelState> state)
{
_logger = logger;
_sharedModelHub = sharedModelHub;
_state = state;
}
public void Dispose()
{
//_sharedModelHub?.Dispose();
}
//[EffectMethod(typeof(StartAction))]
[EffectMethod]
public async Task HandleStartAction(StartAction action, IDispatcher dispatcher)
{
await _sharedModelHub.HandleStartAction(new StartAction(_state.Value), dispatcher);
}
[EffectMethod]
public async Task HandleConnectToHubAction(ConnectToHubAction action, IDispatcher dispatcher)
{
try
{
await _sharedModelHub.ConnectToHub(dispatcher);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to connect to hub");
//dispatcher.Dispatch(new HubConnectionFailedAction(ex.Message));
}
}
}
}

View File

@ -0,0 +1,22 @@
{
"IsStated": true,
"BellValue": false,
"Pin1Value": false,
"Pin2Value": false,
"Pin3Value": false,
"Pin4Value": false,
"Pin5Value": false,
"Pin6Value": false,
"Pin7Value": false,
"Pin8Value": false,
"Pin9Value": false,
"Pin1Disabled": false,
"Pin2Disabled": false,
"Pin3Disabled": false,
"Pin4Disabled": false,
"Pin5Disabled": false,
"Pin6Disabled": false,
"Pin7Disabled": false,
"Pin8Disabled": false,
"Pin9Disabled": false
}