Compare commits

...

6 Commits

Author SHA1 Message Date
beo3000 a48ca83ffd fix bell, init new state on start and stop 2025-11-10 17:51:40 +01:00
beo3000 0d7a4d9ba5 dev 2025-11-10 16:03:02 +01:00
beo3000 6bebafe402 dev 2025-11-10 11:49:58 +01:00
beo3000 acb9201725 upd bell button 2025-11-10 11:12:05 +01:00
beo3000 b93a7048fd start -> start/stop 2025-11-10 10:44:17 +01:00
beo3000 0b0218824a dev 2025-11-10 10:36:29 +01:00
17 changed files with 455 additions and 241 deletions

View File

@ -1,52 +1,51 @@
@if (!Value)
{
<MudButton OnClick="ToggleClick" Disabled="Disabled">
<MudIcon Class="ma-2" Icon="@Icons.Material.Filled.AddAlert" Color="Color.Dark" Style="font-size: 3rem;" />
</MudButton>
}
else
{
<MudButton OnClick="ToggleClick" Disabled="Disabled">
<MudIcon Class="ma-2" Icon="@Icons.Material.Filled.AddAlert" Color="Color.Tertiary"
Style="font-size: 3rem;"/>
</MudButton>
}
@using KoogleApp.Model
@using KoogleApp.Store.Game.ThrowPanel
<MudSwitch T="bool" Label="" Size="Size.Medium" Disabled="Disabled"
ThumbIcon="@(Value ? Icons.Material.Filled.Done : @Icons.Material.Filled.AddAlert)" ThumbIconColor="@(Value ? Color.Success : Color.Primary)"
@bind-Value="Value"/>
@inherits FluxorComponent
@inject IDispatcher Dispatcher
@inject IState<ThrowPanelState> State
<MudButton OnClick="ToggleClick" Disabled="false">
<MudIcon Class="ma-2" Icon="@Icons.Material.Filled.AddAlert"
Color="@(State.Value.BellValue ? Color.Warning : Color.Primary)"
Style="font-size: 3rem;"/>
</MudButton>
@* <MudSwitch T="bool" Label="" Size="Size.Medium" Disabled="false"
@bind-Value="MudSwitchValue"
ThumbIcon="@(State.Value.BellValue ? Icons.Material.Filled.Done : @Icons.Material.Filled.AddAlert)"
ThumbIconColor="@(State.Value.BellValue ? Color.Success : Color.Primary)" /> *@
@code {
private bool _value;
// private bool _mudSwitchValue;
[Parameter]
public bool Value
// private bool MudSwitchValue
// {
// get => _mudSwitchValue;
// set
// {
// if (_mudSwitchValue == value)
// {
// return;
// }
// _mudSwitchValue = value;
// Dispatcher.Dispatch(new ToggleBellAction());
// }
// }
// protected override void OnAfterRender(bool firstRender)
// {
// base.OnAfterRender(firstRender);
// _mudSwitchValue = State.Value.BellValue;
// }
private void ToggleClick(MouseEventArgs obj)
{
get => _value;
set
{
if (_value == value) return;
_value = value;
InvokeAsync(async () => await ValueChanged.InvokeAsync(value));
InvokeAsync(async () => await OnStateChanged.InvokeAsync(Value));
}
}
[Parameter]
public EventCallback<bool> ValueChanged { get; set; }
[Parameter]
public EventCallback<bool> OnStateChanged { get; set; }
[Parameter]
public bool Disabled { get; set; } = false;
private async Task ToggleClick(MouseEventArgs obj)
{
Value = !Value;
Dispatcher.Dispatch(new ToggleBellAction());
}
}

View File

@ -2,10 +2,10 @@
@using KoogleApp.Model.EventMessages
@using KoogleApp.Services
@using KoogleApp.Store.Game
@using KoogleApp.Store.Game.ThrowPanel
@inherits FluxorComponent
@inject IMyEventAggregator EventAggregator
@inject IState<ThrowPanelState> ThrowPanelState
@inject IDispatcher Dispatcher
@ -25,20 +25,19 @@
<MudItem xs="4">
<MudPaper Class="d-flex align-center justify-center mud-width-full py-0" Style="height: 76px;">
<MudStack Spacing="0" Wrap="Wrap.Wrap">
<MudChip T="string" Color="Color.Dark" Size="Size.Small">in die Vollen</MudChip>
<MudChip T="string" Color="Color.Dark" Size="Size.Small">@(GetThrowModeName(ThrowPanelState.Value.ThrowMode))</MudChip>
<MudChip T="string" Color="Color.Dark" Size="Size.Small">Wurf 1 von 1</MudChip>
</MudStack>
</MudPaper>
</MudItem>
<MudItem xs="4">
<MudPaper Class="d-flex align-center justify-center mud-width-full py-0">
<BellButton
OnStateChanged="OnBellStateChanged" />
<BellButton />
</MudPaper>
</MudItem>
<MudFlexBreak/>
@if (ShowNumbers)
@if (ThrowPanelState.Value.ThrowMode == ThrowMode.Reposition)
{
<MudItem xs="4">
<MudPaper Class="d-flex align-center justify-center mud-width-full py-0">
@ -137,18 +136,6 @@
@code {
// [Parameter]
// public ThrowPanelState? ThrowPanelState { get; set; }
[Parameter]
public EventCallback<ThrowPanelState> OnStateChanged { get; set; }
[Parameter]
public bool ShowNumbers
{
get;
set;
}
[Parameter]
public bool CanSelectPlayer
@ -160,19 +147,24 @@
private void ToggleClick(MouseEventArgs obj)
{
Dispatcher.Dispatch(new ToggleAllPinsAction());
// await EventAggregator.PublishAsync(new PinToggleMessage());
}
private async Task OneClick(int number)
{
Dispatcher.Dispatch(new UpdatePinStateByNumber(number));
// await EventAggregator.PublishAsync(new NumberPanelMessage(number));
Dispatcher.Dispatch(new UpdatePinStateByNumberAction(number));
}
private async Task OnBellStateChanged(bool obj)
private string GetThrowModeName(ThrowMode value)
{
Dispatcher.Dispatch(new ToggleBellAction());
// await OnStateChanged.InvokeAsync(ThrowPanelState);
switch (value)
{
case ThrowMode.Reposition:
return "Abräumen";
case ThrowMode.Decrease:
return "in die Vollen";
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}

View File

@ -4,52 +4,15 @@
<MudItem xs="12" md="6">
<NumberPanel ShowNumbers="ShowNumbers"
CanSelectPlayer="CanSelectPlayers"
OnStateChanged="OnThrowPanelStateChanged"
/>
<NumberPanel/>
</MudItem>
<MudItem xs="12" md="6">
<PinPanel @ref="_pinPanel"
/>
<PinPanel/>
</MudItem>
@code {
// [Parameter]
// public ThrowPanelState? ThrowPanelState { get; set; }
[Parameter]
public EventCallback<ThrowPanelState> OnStateChanged { get; set; }
PinPanel _pinPanel;
NumberPanel _numberPanel;
[Parameter]
public bool ShowNumbers
{
get;
set;
}
[Parameter]
public bool CanSelectPlayers
{
get;
set;
}
// public void UpdatePanelState(ThrowPanelState state)
// {
// _pinPanel.UpdatePanelState(state);
// }
private async Task OnThrowPanelStateChanged(ThrowPanelState arg)
{
await OnStateChanged.InvokeAsync(arg);
}
}

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,21 +1,16 @@
@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)
{
<MudGrid>
<NumberPinPanel @ref="_numberPinPanel"
ShowNumbers="true"
OnStateChanged="OnNumberPinStateChanged"
CanSelectPlayers="true"
/>
<NumberPinPanel />
<MudItem xs="4">
<MudPaper Class="d-flex align-center justify-center mud-width-full py-0">
<MudButton OnClick="SinkLeftClick">
@ -48,7 +43,6 @@
@code {
private NumberPinPanel _numberPinPanel;
[Parameter]
public EventCallback<ThrowEventArgs> OnClick { get; set; }
@ -60,6 +54,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);
@ -95,11 +99,5 @@
}
// public void UpdatePanelState(ThrowPanelState state)
// {
// _numberPinPanel.UpdatePanelState(state);
// }
}

View File

@ -0,0 +1,60 @@
@using KoogleApp.Model
<MudDialog Style="height: 400px; width:600px">
<TitleContent>
<MudText Typo="Typo.h6">
<MudIcon Icon="@Icons.Material.Filled.Favorite" Class="mr-3 mb-n1"/>
Save as favorite?
</MudText>
</TitleContent>
<DialogContent>
<MudSelect T="Tuple<string, ThrowMode>" Label="Modus" @bind-Value="_valueThrowMode" HelperText="Wähle zwischen Abräumen und in die Vollen"
OpenIcon="@Icons.Material.Filled.Mode" AdornmentColor="Color.Primary">
@foreach (var item in _items)
{
<MudSelectItem T="Tuple<string, ThrowMode>" Value="@(item)">@item.Item1</MudSelectItem>
}
</MudSelect>
</DialogContent>
<DialogActions>
<MudButton OnClick="Cancel">Abbrechen</MudButton>
<MudButton Color="Color.Primary" OnClick="Start">Start</MudButton>
</DialogActions>
</MudDialog>
@code {
private List<Tuple<string, ThrowMode>> _items = new List<Tuple<string, ThrowMode>>();
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
_items.Add(new Tuple<string, ThrowMode>("in die Vollen", ThrowMode.Reposition));
_items.Add(new Tuple<string, ThrowMode>("Abräumen", ThrowMode.Decrease));
_valueThrowMode = _items[0];
StateHasChanged();
}
}
[CascadingParameter]
private IMudDialogInstance MudDialog { get; set; }
private Tuple<string, ThrowMode> _valueThrowMode;
[Parameter]
public string Description { get; set; } = "";
private void Cancel() => MudDialog.Cancel();
private void Start()
{
// if (!string.IsNullOrEmpty(Description))
{
// Snackbar.Add("Favorite added", Severity.Success);
MudDialog.Close(DialogResult.Ok(new StartParams(_valueThrowMode.Item2, 3)));
}
}
}

View File

@ -5,9 +5,11 @@
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.SignalR.Client
@using KoogleApp.Components.Controls
@using KoogleApp.Components.Dialogs
@using KoogleApp.Model.EventMessages
@using KoogleApp.Model.Framework
@using KoogleApp.Store.Game
@using KoogleApp.Store.Game.ThrowPanel
@inherits FluxorComponent
@ -21,6 +23,7 @@
@inject IMyEventAggregator EventAggregator
@inject IState<ThrowPanelState> ThrowPanelState
@inject IDispatcher Dispatcher
@inject IDialogService DialogService
@* @inject IGameStatusDataService _dataService; *@
@ -41,10 +44,11 @@
Class="mr-5" OnClick="RedoClick"/>
</MudTooltip>
<MudTooltip Text="Start" Color="Color.Primary" Placement="Placement.Bottom" Arrow="true">
<MudIconButton Icon="@Icons.Material.Filled.Start" Variant="Variant.Filled" Color="Color.Primary"
Disabled="@(ThrowPanelState.Value.IsStated)"
Class="mr-5" OnClick="StartClick"/>
<MudTooltip Text="@(ThrowPanelState.Value.IsStated ? "Stop" : "Start")"
Color="Color.Primary" Placement="Placement.Bottom" Arrow="true">
<MudIconButton Icon="@(ThrowPanelState.Value.IsStated ? Icons.Material.Filled.Stop : Icons.Material.Filled.Start)"
Variant="Variant.Filled" Color="Color.Primary"
Class="mr-5" OnClick="StartStopClick"/>
</MudTooltip>
</MudToolBar>
@ -198,7 +202,7 @@
// await hubConnection.StartAsync();
}
// private async Task OnBoardPanelStateChanged(ThrowPanelState state)
@ -235,27 +239,55 @@
private async Task UndoClick()
{
// if (hubConnection is not null)
// {
// await hubConnection.SendAsync("RequestUndo", _userName);
// }
// if (hubConnection is not null)
// {
// await hubConnection.SendAsync("RequestUndo", _userName);
// }
}
private async Task RedoClick()
{
// if (hubConnection is not null)
// {
// await hubConnection.SendAsync("RequestRedo", _userName);
// }
// if (hubConnection is not null)
// {
// await hubConnection.SendAsync("RequestRedo", _userName);
// }
}
private void StartClick()
private async Task StartStopClick()
{
var action = new StartAction(ThrowPanelState.Value);
Dispatcher.Dispatch(action);
if (!ThrowPanelState.Value.IsStated)
{
var parameters = new DialogParameters<StartGameDialog> { { x => x.Description, "" }};
// parameters.Add<TimeRecordDto>(x => x.Record, Record);
var options = new DialogOptions
{
};
var dialog = await DialogService.ShowAsync<StartGameDialog>("Spiel starten", parameters, options);
var result = await dialog.Result;
var startParams = result.Data as StartParams;
if (!result.Canceled)
{
var action = new StartStopAction(ThrowPanelState.Value, startParams);
Dispatcher.Dispatch(action);
}
}
else
{
var result = await DialogService.ShowMessageBox("Spiel beenden?", "Spiel wirklich abbrechen?", "JA", "NEIN");
if (result.Value)
{
var action = new StartStopAction(ThrowPanelState.Value,null);
Dispatcher.Dispatch(action);
}
}
// _throwPanelState = ThrowPanelState.Create();
// await BroadcastThrowPanelState(_throwPanelState);
// await BroadcastThrowPanelStateAction(_throwPanelState);
// await InvokeAsync(StateHasChanged);
}
@ -274,10 +306,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
{
@ -40,7 +40,7 @@ namespace KoogleApp.Hub
_hubConnection.On<ThrowPanelState>("ReceiveThrowPanelState", state =>
{
dispatcher.Dispatch(new ReceiveStateFromServer(state));
dispatcher.Dispatch(new ReceiveStateFromServerAction(state));
});
// _hubConnection.On<string>("ReceiveTextUpdate", (newText) =>
@ -52,7 +52,7 @@ namespace KoogleApp.Hub
await _hubConnection.StartAsync();
}
public async Task HandleStartAction(StartAction action, IDispatcher dispatcher)
public async Task HandelBroadcastThrowPanelStateAction(BroadcastThrowPanelStateAction action, IDispatcher dispatcher)
{
if (_hubConnection?.State != HubConnectionState.Connected)
{
@ -63,13 +63,13 @@ 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());
//await _hubConnection.InvokeAsync("StartAction", action);
//await _hubConnection.InvokeAsync("StartStopAction", stopAction);
// Der Server wird ActivityAdded an alle Clients senden,
// einschließlich diesem. Dann wird ActivityAddedAction dispatched.
@ -198,7 +198,7 @@ namespace KoogleApp.Hub
{
await Clients.Others.SendAsync("ReceiveThrowPanelState", state);
//await _hubConnection.InvokeAsync("StartAction", action);
//await _hubConnection.InvokeAsync("StartStopAction", action);
// Der Server wird ActivityAdded an alle Clients senden,
// einschließlich diesem. Dann wird ActivityAddedAction dispatched.

View File

@ -0,0 +1,8 @@
namespace KoogleApp.Model
{
public record StartParams(ThrowMode ThrowMode, int ThrowsPerRound)
{
public StartParams() : this(ThrowMode: ThrowMode.Reposition, ThrowsPerRound:3)
{}
}
}

View File

@ -0,0 +1,34 @@
using System.Runtime.InteropServices;
using Fluxor;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
namespace KoogleApp.Model
{
public enum ThrowMode
{
Reposition, // in die Vollen
Decrease // Abräumen
}
[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,
int ThrowsPerRound, int ThrowCounter, ThrowMode ThrowMode)
{
// 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,
ThrowsPerRound : 3, ThrowCounter : 0, ThrowMode : ThrowMode.Reposition
)
{ }
}
// 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 StartStopAction(ThrowPanelState State, StartParams? StartParams);
public record ConnectToHubAction();
public record ToggleAllPinsAction();
public record ToggleBellAction();
public record UpdatePinStateByNumberAction(int Number);
public record ReceiveStateFromServerAction(ThrowPanelState State);
public record LoadStateFromSessionAction();
public record StateLoadedAction(ThrowPanelState? State);
public record BroadcastThrowPanelStateAction(ThrowPanelState State);
}

View File

@ -0,0 +1,128 @@
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(StartStopAction))]
[EffectMethod]
public async Task HandleStartAction(StartStopAction stopAction, IDispatcher dispatcher)
{
dispatcher.Dispatch(new BroadcastThrowPanelStateAction(_state.Value));
}
[EffectMethod]
public async Task HandleToggleAllPinsAction(ToggleAllPinsAction stopAction, IDispatcher dispatcher)
{
dispatcher.Dispatch(new BroadcastThrowPanelStateAction(_state.Value));
}
[EffectMethod]
public async Task HandleTogglePinValueAction(TogglePinValueAction stopAction, IDispatcher dispatcher)
{
dispatcher.Dispatch(new BroadcastThrowPanelStateAction(_state.Value));
}
[EffectMethod]
public async Task HandleUpdatePinStateByNumberAction(UpdatePinStateByNumberAction stopAction, IDispatcher dispatcher)
{
dispatcher.Dispatch(new BroadcastThrowPanelStateAction(_state.Value));
}
[EffectMethod]
public async Task HandleToggleBellAction(ToggleBellAction stopAction, 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.HandelBroadcastThrowPanelStateAction(action, dispatcher);
}
}
}

View File

@ -1,51 +1,19 @@
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
{
[ReducerMethod]
public static ThrowPanelState ReceiveStateFromServer(ThrowPanelState state, ReceiveStateFromServer action)
public static ThrowPanelState OnReceiveStateFromServer(ThrowPanelState state, ReceiveStateFromServerAction action)
{
return action.State;
}
[ReducerMethod]
public static ThrowPanelState OnToggleDevice(ThrowPanelState state, TogglePinValueAction action)
public static ThrowPanelState OnTogglePinValue(ThrowPanelState state, TogglePinValueAction action)
{
switch (action.PinNumber)
{
@ -73,9 +41,23 @@ namespace KoogleApp.Store.Game
}
[ReducerMethod]
public static ThrowPanelState OnStart(ThrowPanelState state, StartAction action)
public static ThrowPanelState OnStartStop(ThrowPanelState state, StartStopAction startStopAction)
{
return state with { IsStated = true };
var newState = new ThrowPanelState();
if (state.IsStated)
{
return newState with { IsStated = false };
}
if (startStopAction.StartParams != null)
return newState with
{
IsStated = !state.IsStated,
ThrowMode = startStopAction.StartParams.ThrowMode,
ThrowsPerRound = startStopAction.StartParams.ThrowsPerRound
};
return state;
}
[ReducerMethod]
@ -102,7 +84,7 @@ namespace KoogleApp.Store.Game
}
[ReducerMethod]
public static ThrowPanelState OnUpdatePinStateByNumber(ThrowPanelState state, UpdatePinStateByNumber action)
public static ThrowPanelState OnUpdatePinStateByNumber(ThrowPanelState state, UpdatePinStateByNumberAction action)
{
var chgCnt = 0;
@ -144,9 +126,15 @@ namespace KoogleApp.Store.Game
}
[ReducerMethod]
public static ThrowPanelState OnUpdatePinStateByNumber(ThrowPanelState state, ToggleBellAction action)
public static ThrowPanelState OnToggleBell(ThrowPanelState state, ToggleBellAction action)
{
return state with { BellValue = !state.BellValue };
}
[ReducerMethod]
public static ThrowPanelState OnStateLoaded(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,25 @@
{
"IsStated": true,
"BellValue": false,
"Pin1Value": true,
"Pin2Value": false,
"Pin3Value": true,
"Pin4Value": false,
"Pin5Value": true,
"Pin6Value": true,
"Pin7Value": false,
"Pin8Value": false,
"Pin9Value": false,
"Pin1Disabled": false,
"Pin2Disabled": false,
"Pin3Disabled": false,
"Pin4Disabled": false,
"Pin5Disabled": false,
"Pin6Disabled": false,
"Pin7Disabled": false,
"Pin8Disabled": false,
"Pin9Disabled": false,
"ThrowsPerRound": 3,
"ThrowCounter": 0,
"ThrowMode": 1
}