Group pieces in the hand.

This commit is contained in:
2024-11-26 15:26:47 -06:00
parent 1ed1ad09af
commit 83dd4cc4a3
4 changed files with 62 additions and 21 deletions

View File

@@ -11,13 +11,15 @@
var position = $"{file}{rank}"; var position = $"{file}{rank}";
var piece = Session?.BoardState.Board[position]; var piece = Session?.BoardState.Board[position];
var isSelected = piece != null && SelectedPosition == position; var isSelected = piece != null && SelectedPosition == position;
<div class="tile" @onclick="OnClickTileInternal(position)" <div class="tile"
@onclick="OnClickTileInternal(position)"
data-position="@(position)" data-position="@(position)"
data-selected="@(isSelected)" data-selected="@(isSelected)"
data-upsidedown="@(piece?.Owner != Perspective)"
style="grid-area: @position"> style="grid-area: @position">
@if (piece != null) @if (piece != null)
{ {
<GamePiece Piece="piece" Perspective="Perspective" /> <GamePiece Piece="piece.WhichPiece" IsPromoted="piece.IsPromoted" />
} }
</div> </div>
} }
@@ -49,13 +51,27 @@
<!-- Side board --> <!-- Side board -->
@if (Session != null && UseSideboard == true) @if (Session != null && UseSideboard == true)
{ {
@* <aside class="side-board PrimaryTheme ThemeVariant--Contrast" style="grid-area: opponent-side-board"> *@
@* @if (opponentHand.Any()) *@
@* { *@
@* @foreach (var piece in opponentHand) *@
@* { *@
@* <div class="tile" *@
@* data-upsidedown="@(piece.Owner != Perspective)"> *@
@* <GamePiece Piece="piece.WhichPiece" IsPromoted="false" /> *@
@* </div> *@
@* } *@
@* } *@
@* </aside> *@
<aside class="side-board PrimaryTheme ThemeVariant--Contrast" style="grid-area: opponent-side-board"> <aside class="side-board PrimaryTheme ThemeVariant--Contrast" style="grid-area: opponent-side-board">
@if (opponentHand.Any()) @if (OpponentHandGrouped.Any())
{ {
@foreach (var piece in opponentHand) @foreach (var (whichPiece, count) in OpponentHandGrouped)
{ {
<div class="tile"> <div class="tile"
<GamePiece Piece="piece" Perspective="Perspective" /> data-upsidedown>
<GamePiece Piece="whichPiece" IsPromoted="false" Count="count"/>
</div> </div>
} }
} }
@@ -90,7 +106,7 @@
<div @onclick="OnClickHandInternal(piece)" <div @onclick="OnClickHandInternal(piece)"
class="tile" class="tile"
data-selected="@(piece.WhichPiece == SelectedPieceFromHand)"> data-selected="@(piece.WhichPiece == SelectedPieceFromHand)">
<GamePiece Piece="piece" Perspective="Perspective" /> <GamePiece Piece="piece.WhichPiece" IsPromoted="false" />
</div> </div>
} }
} }
@@ -109,6 +125,7 @@
</article> </article>
@code { @code {
static readonly string[] Files = new[] { "A", "B", "C", "D", "E", "F", "G", "H", "I" }; static readonly string[] Files = new[] { "A", "B", "C", "D", "E", "F", "G", "H", "I" };
/// <summary> /// <summary>
@@ -164,11 +181,17 @@
} }
} }
private Dictionary<WhichPiece, int> OpponentHandGrouped => opponentHand.GroupBy(piece => piece.WhichPiece).ToDictionary(grouping => grouping.Key, grouping => grouping.Count());
private Dictionary<WhichPiece, int> PlayerHandGrouped => userHand.GroupBy(piece => piece.WhichPiece).ToDictionary(grouping => grouping.Key, grouping => grouping.Count());
private bool IsMyTurn => Session?.BoardState.WhoseTurn == Perspective; private bool IsMyTurn => Session?.BoardState.WhoseTurn == Perspective;
private bool IsPlayerInCheck => Session?.BoardState.PlayerInCheck == Perspective; private bool IsPlayerInCheck => Session?.BoardState.PlayerInCheck == Perspective;
private bool IsOpponentInCheck => Session?.BoardState.PlayerInCheck != null && Session.BoardState.PlayerInCheck != Perspective; private bool IsOpponentInCheck => Session?.BoardState.PlayerInCheck != null && Session.BoardState.PlayerInCheck != Perspective;
private bool IsPlayerVictor => Session?.BoardState.Victor == Perspective; private bool IsPlayerVictor => Session?.BoardState.Victor == Perspective;
private bool IsOpponentVictor => Session?.BoardState.Victor != null && Session.BoardState.Victor != Perspective; private bool IsOpponentVictor => Session?.BoardState.Victor != null && Session.BoardState.Victor != Perspective;
private Func<Task> OnClickTileInternal(string position) => () => private Func<Task> OnClickTileInternal(string position) => () =>
{ {
if (IsMyTurn) if (IsMyTurn)
@@ -177,6 +200,7 @@
} }
return Task.CompletedTask; return Task.CompletedTask;
}; };
private Func<Task> OnClickHandInternal(Piece piece) => () => private Func<Task> OnClickHandInternal(Piece piece) => () =>
{ {
if (IsMyTurn) if (IsMyTurn)

View File

@@ -15,6 +15,10 @@
color: beige; color: beige;
} }
.game-board [data-upsidedown] {
transform: rotateZ(180deg);
}
.board { .board {
display: grid; display: grid;
grid-template-areas: grid-template-areas:
@@ -48,7 +52,6 @@
"I9 H9 G9 F9 E9 D9 C9 B9 A9"; "I9 H9 G9 F9 E9 D9 C9 B9 A9";
} }
.tile { .tile {
display: grid; display: grid;
place-content: center; place-content: center;

View File

@@ -1,7 +1,7 @@
@using Shogi.Contracts.Types @using Shogi.Contracts.Types
<div class="game-piece" title="@HtmlTitle" data-upsidedown="@(Piece?.Owner != Perspective)" data-owner="@Piece?.Owner.ToString()"> <div class="game-piece" title="@HtmlTitle">
@switch (Piece?.WhichPiece) @switch (Piece)
{ {
case WhichPiece.Bishop: case WhichPiece.Bishop:
<Bishop IsPromoted="@IsPromoted" /> <Bishop IsPromoted="@IsPromoted" />
@@ -31,18 +31,18 @@
@*render nothing*@ @*render nothing*@
break; break;
} }
@if (Count > 0)
{
<span class="counter">@Count</span>
}
</div> </div>
@code { @code {
[Parameter] [Parameter] public WhichPiece? Piece { get; set; }
public Contracts.Types.Piece? Piece { get; set; } [Parameter] public bool IsPromoted { get; set; }
[Parameter] public int Count { get; set; }
[Parameter] private string HtmlTitle => Piece switch
public WhichPlayer Perspective { get; set; }
private bool IsPromoted => Piece != null && Piece.IsPromoted;
private string HtmlTitle => Piece?.WhichPiece switch
{ {
WhichPiece.Bishop => "Bishop", WhichPiece.Bishop => "Bishop",
WhichPiece.GoldGeneral => "Gold General", WhichPiece.GoldGeneral => "Gold General",

View File

@@ -3,9 +3,23 @@
height: auto; height: auto;
} }
[data-upsidedown] {
transform: rotateZ(180deg);
}
.game-piece { .game-piece {
overflow: hidden; /* Because SVGs have weird sizes. */ overflow: hidden; /* Because SVGs have weird sizes. */
position: relative;
}
.game-piece .counter {
display: grid;
place-content: center;
position: absolute;
top: 0;
left: 0;
padding: 2px;
z-index: 100;
background-color: white;
border-radius: 9px;
border: 1px solid #444;
aspect-ratio: 1 / 1;
width: 15px;
height: 15px;
} }