diff --git a/src/Koogle.Application/Games/GameProgress.cs b/src/Koogle.Application/Games/GameProgress.cs
index 53dae84..04c61b5 100644
--- a/src/Koogle.Application/Games/GameProgress.cs
+++ b/src/Koogle.Application/Games/GameProgress.cs
@@ -22,6 +22,7 @@ public record BeforeThrowState(
/// Whether all 9 pins were knocked down.
/// Whether the throw was a gutter (Rinne).
/// Whether all remaining pins are hit (Abgeräumt).
+/// Whether bell was active in this throw.
public record AfterThrowState(
ThrowPanelSnapshot ThrowPanel,
Guid CurrentPlayerId,
@@ -29,7 +30,8 @@ public record AfterThrowState(
bool IsCircle,
bool IsStrike,
bool IsGutter,
- bool IsCleared
+ bool IsCleared,
+ bool IsBell
);
///
@@ -162,11 +164,13 @@ public static class GameProgressExtensions
/// Snapshot before the throw.
/// Current player ID.
/// Whether the throw went into the gutter (from user input).
+ /// Whether the throw activated the bell (from user input).
public static AfterThrowState CreateAfterThrowState(
this ThrowPanelSnapshot afterThrow,
ThrowPanelSnapshot beforeThrow,
Guid playerId,
- bool isGutter = false)
+ bool isGutter = false,
+ bool isBell = false)
{
var pinsKnockedBefore = beforeThrow.PinCount();
var pinsKnockedAfter = afterThrow.PinCount();
@@ -179,7 +183,8 @@ public static class GameProgressExtensions
IsCircle: afterThrow.IsCircle(),
IsStrike: afterThrow.IsStrike(),
IsGutter: isGutter,
- IsCleared: afterThrow.IsCleared()
+ IsCleared: afterThrow.IsCleared(),
+ IsBell: isBell
);
}
}
diff --git a/src/Koogle.Application/Games/Training/TrainingGameLogicService.cs b/src/Koogle.Application/Games/Training/TrainingGameLogicService.cs
index d4df1c9..42ababa 100644
--- a/src/Koogle.Application/Games/Training/TrainingGameLogicService.cs
+++ b/src/Koogle.Application/Games/Training/TrainingGameLogicService.cs
@@ -63,7 +63,7 @@ public class TrainingGameLogicService : IGameLogicService
stats.ClearedCount++;
}
- if (afterThrow.ThrowPanel.BellValue)
+ if (afterThrow.IsBell)
{
stats.BellCount++;
}
diff --git a/src/Koogle.Web/Components/Shared/PlayerStatisticsChart.razor b/src/Koogle.Web/Components/Shared/PlayerStatisticsChart.razor
index e38f585..ccdd229 100644
--- a/src/Koogle.Web/Components/Shared/PlayerStatisticsChart.razor
+++ b/src/Koogle.Web/Components/Shared/PlayerStatisticsChart.razor
@@ -70,6 +70,13 @@ else if (_stats != null)
SeriesType="SeriesType.Bar"
XValue="e => e.Name"
YValue="e => e.TotalCleared" />
+
+
}
}
@@ -88,6 +95,7 @@ else if (_stats != null)
public int TotalStrikes { get; set; }
public int TotalCircles { get; set; }
public int TotalCleared { get; set; }
+ public int TotalBells { get; set; }
}
@@ -111,7 +119,8 @@ else if (_stats != null)
TotalThrows = s.TotalThrows,
TotalStrikes = s.TotalStrikes,
TotalCircles = s.TotalCircles,
- TotalCleared = s.TotalCleared
+ TotalCleared = s.TotalCleared,
+ TotalBells = s.TotalBells
})
);
}
diff --git a/src/Koogle.Web/Store/GameState/GameEffects.cs b/src/Koogle.Web/Store/GameState/GameEffects.cs
index 6b5479d..7895054 100644
--- a/src/Koogle.Web/Store/GameState/GameEffects.cs
+++ b/src/Koogle.Web/Store/GameState/GameEffects.cs
@@ -363,7 +363,8 @@ public class GameEffects
// Create AfterThrowState for game logic with updated counters
var beforeSnapshot = CreateThrowPanelSnapshot(action.BeforeThrowState);
var afterSnapshot = CreateThrowPanelSnapshot(newThrowPanel);
- var afterThrowState = afterSnapshot.CreateAfterThrowState(beforeSnapshot, currentPlayerId.Value, action.IsGutter);
+ var afterThrowState = afterSnapshot.CreateAfterThrowState(beforeSnapshot,
+ currentPlayerId.Value, action.IsGutter, action.AfterThrowState.BellValue);
// Default values
bool shouldRotatePlayer = false;
@@ -440,7 +441,7 @@ public class GameEffects
// Fire expense triggers for special throw events
// Note: Use action.AfterThrowState.BellValue since afterThrowState has BellValue reset to false
- await FireThrowTriggersAsync(state, currentPlayerId.Value, action, afterThrowState, action.AfterThrowState.BellValue, dispatcher);
+ await FireThrowTriggersAsync(state, currentPlayerId.Value, action, afterThrowState, dispatcher);
// Record player statistics (game-type independent)
await RecordPlayerStatisticsAsync(state, currentPlayerId.Value, afterThrowState);
@@ -893,7 +894,6 @@ public class GameEffects
Guid currentPlayerId,
RecordThrowAction action,
AfterThrowState afterThrowState,
- bool bellValue,
IDispatcher dispatcher)
{
// Skip if no day or game context
@@ -991,7 +991,7 @@ public class GameEffects
}
// Check for Bell hit
- if (bellValue)
+ if (afterThrowState.IsBell)
{
var expenses = await _gameEventService.RegisterBellAsync(
currentPlayerId,
@@ -1016,7 +1016,7 @@ public class GameEffects
}
// Trigger GIF playback for special events
- await TriggerGifForEventsAsync(state, gameId, action, afterThrowState, bellValue, dispatcher);
+ await TriggerGifForEventsAsync(state, gameId, action, afterThrowState, dispatcher);
}
catch (Exception ex)
{
@@ -1034,7 +1034,6 @@ public class GameEffects
Guid gameId,
RecordThrowAction action,
AfterThrowState afterThrowState,
- bool bellValue,
IDispatcher dispatcher)
{
var clubId = _clubContext.ClubId;
@@ -1049,7 +1048,7 @@ public class GameEffects
{
triggeredEvent = ThrowEventType.Circle;
}
- else if (bellValue)
+ else if (afterThrowState.IsBell)
{
triggeredEvent = ThrowEventType.Bell;
}
@@ -1188,7 +1187,7 @@ public class GameEffects
afterThrowState.IsGutter,
afterThrowState.IsCircle,
afterThrowState.IsStrike,
- afterThrowState.ThrowPanel.BellValue);
+ afterThrowState.IsBell);
}
catch (Exception ex)
{