Migre le projet vers Blazor WebAssembly en .NET 10
This commit is contained in:
604
ChessCubing.App/Pages/ChronoPage.razor
Normal file
604
ChessCubing.App/Pages/ChronoPage.razor
Normal file
@@ -0,0 +1,604 @@
|
||||
@page "/chrono"
|
||||
@page "/chrono.html"
|
||||
@implements IAsyncDisposable
|
||||
@inject MatchStore Store
|
||||
@inject NavigationManager Navigation
|
||||
|
||||
<PageTitle>ChessCubing Arena | Phase Chrono</PageTitle>
|
||||
<PageBody Page="chrono" BodyClass="@ChronoBodyClass" />
|
||||
|
||||
@{
|
||||
var summary = Match is null ? null : BuildSummary();
|
||||
var blackZone = Match is null ? null : BuildZone(MatchEngine.ColorBlack);
|
||||
var whiteZone = Match is null ? null : BuildZone(MatchEngine.ColorWhite);
|
||||
}
|
||||
|
||||
@if (!_ready)
|
||||
{
|
||||
<main class="phase-shell chrono-stage">
|
||||
<div class="panel" style="padding: 1.5rem;">Chargement de la phase chrono...</div>
|
||||
</main>
|
||||
}
|
||||
else if (Match is not null && summary is not null && blackZone is not null && whiteZone is not null)
|
||||
{
|
||||
<main class="phase-shell chrono-stage">
|
||||
<header class="phase-header">
|
||||
<a class="brand-link brand-link-logo" href="application.html" aria-label="Retour a l'application">
|
||||
<img class="brand-link-icon" src="logo.png" alt="Icone ChessCubing" />
|
||||
<img class="brand-link-mark" src="transparent.png" alt="Logo ChessCubing" />
|
||||
</a>
|
||||
<div class="phase-title">
|
||||
<p class="eyebrow">Phase chrono</p>
|
||||
<h1 id="chronoTitle">@summary.Title</h1>
|
||||
<p id="chronoSubtitle" class="phase-subtitle">@summary.Subtitle</p>
|
||||
</div>
|
||||
<button class="button ghost small utility-button" id="openArbiterButton" type="button" @onclick="OpenArbiterModal">
|
||||
Arbitre
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<section class="status-strip">
|
||||
<article class="status-card">
|
||||
<span id="blockTimerLabel">Temps Block</span>
|
||||
<strong id="blockTimer">@summary.BlockTimer</strong>
|
||||
</article>
|
||||
<article class="status-card" id="moveTimerCard" hidden="@summary.HideMoveTimer">
|
||||
<span>Temps coup</span>
|
||||
<strong id="moveTimer">@summary.MoveTimer</strong>
|
||||
</article>
|
||||
<article class="status-card wide">
|
||||
<span id="chronoCenterLabel">@summary.CenterLabel</span>
|
||||
<strong id="chronoCenterValue">@summary.CenterValue</strong>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="faceoff-board">
|
||||
<article class="player-zone opponent-zone @(blackZone.ActiveZone ? "active-zone" : string.Empty) @(blackZone.HasPlayerClock ? "has-player-clock" : string.Empty)" id="blackZone">
|
||||
<div class="zone-inner mirrored-mobile">
|
||||
<div class="zone-head">
|
||||
<div>
|
||||
<span class="seat-tag dark-seat">Noir</span>
|
||||
<h2 id="blackNameChrono">@blackZone.Name</h2>
|
||||
</div>
|
||||
<div class="zone-stats">
|
||||
<strong id="blackMovesChrono">@blackZone.Moves</strong>
|
||||
<span class="player-clock @(blackZone.NegativeClock ? "negative-clock" : string.Empty) @(blackZone.ActiveClock ? "active-clock" : string.Empty)" id="blackClockChrono">@blackZone.Clock</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="zone-button dark-button @(blackZone.ActiveTurn ? "active-turn" : string.Empty)" id="blackMoveButton" type="button" disabled="@blackZone.Disabled" @onclick="() => HandleChronoTapAsync(MatchEngine.ColorBlack)">
|
||||
@blackZone.ButtonText
|
||||
</button>
|
||||
|
||||
<p class="zone-foot" id="blackHintChrono">@blackZone.Hint</p>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="phase-spine">
|
||||
<div class="spine-card">
|
||||
<p class="micro-label" id="spineLabel">@summary.SpineLabel</p>
|
||||
<strong id="spineHeadline">@summary.SpineHeadline</strong>
|
||||
<p id="spineText">@summary.SpineText</p>
|
||||
</div>
|
||||
|
||||
<button class="button primary spine-button" id="primaryChronoButton" type="button" @onclick="HandlePrimaryActionAsync">
|
||||
@summary.PrimaryButtonText
|
||||
</button>
|
||||
</article>
|
||||
|
||||
<article class="player-zone @(whiteZone.ActiveZone ? "active-zone" : string.Empty) @(whiteZone.HasPlayerClock ? "has-player-clock" : string.Empty)" id="whiteZone">
|
||||
<div class="zone-inner">
|
||||
<div class="zone-head">
|
||||
<div>
|
||||
<span class="seat-tag light-seat">Blanc</span>
|
||||
<h2 id="whiteNameChrono">@whiteZone.Name</h2>
|
||||
</div>
|
||||
<div class="zone-stats">
|
||||
<strong id="whiteMovesChrono">@whiteZone.Moves</strong>
|
||||
<span class="player-clock @(whiteZone.NegativeClock ? "negative-clock" : string.Empty) @(whiteZone.ActiveClock ? "active-clock" : string.Empty)" id="whiteClockChrono">@whiteZone.Clock</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="zone-button light-button @(whiteZone.ActiveTurn ? "active-turn" : string.Empty)" id="whiteMoveButton" type="button" disabled="@whiteZone.Disabled" @onclick="() => HandleChronoTapAsync(MatchEngine.ColorWhite)">
|
||||
@whiteZone.ButtonText
|
||||
</button>
|
||||
|
||||
<p class="zone-foot" id="whiteHintChrono">@whiteZone.Hint</p>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<section class="modal @(ShowArbiterModal ? string.Empty : "hidden")" id="arbiterModal" aria-hidden="@BoolString(!ShowArbiterModal)">
|
||||
<div class="modal-backdrop" @onclick="CloseArbiterModal"></div>
|
||||
<div class="modal-card">
|
||||
<div class="modal-head">
|
||||
<div>
|
||||
<p class="eyebrow">Outils arbitre</p>
|
||||
<h2>Controles avances</h2>
|
||||
</div>
|
||||
<button class="button ghost small" id="closeArbiterButton" type="button" @onclick="CloseArbiterModal">Fermer</button>
|
||||
</div>
|
||||
|
||||
<p class="section-copy" id="arbiterStatus">@summary.ArbiterStatus</p>
|
||||
|
||||
<div class="modal-actions">
|
||||
<button class="button secondary" id="arbiterPauseButton" type="button" @onclick="TogglePauseAsync">
|
||||
Pause / reprise
|
||||
</button>
|
||||
<button class="button secondary" id="arbiterCloseBlockButton" type="button" @onclick="CloseBlockAsync">
|
||||
Passer au cube
|
||||
</button>
|
||||
<button class="button secondary" id="arbiterTimeoutButton" type="button" hidden="@summary.HideMoveTimer" disabled="@summary.HideMoveTimer" @onclick="TimeoutMoveAsync">
|
||||
@summary.TimeoutButtonText
|
||||
</button>
|
||||
<button class="button secondary" id="arbiterSwitchTurnButton" type="button" @onclick="SwitchTurnAsync">
|
||||
Corriger le trait
|
||||
</button>
|
||||
<button class="button ghost" id="arbiterWhiteWinButton" type="button" @onclick="() => SetResultAsync(MatchEngine.ColorWhite)">
|
||||
Blanc gagne
|
||||
</button>
|
||||
<button class="button ghost" id="arbiterBlackWinButton" type="button" @onclick="() => SetResultAsync(MatchEngine.ColorBlack)">
|
||||
Noir gagne
|
||||
</button>
|
||||
<button class="button ghost danger" id="arbiterStopButton" type="button" @onclick='() => SetResultAsync("stopped")'>
|
||||
Abandon / arret
|
||||
</button>
|
||||
<button class="button ghost" id="arbiterResetButton" type="button" @onclick="ResetMatchAsync">
|
||||
Reinitialiser le match
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
}
|
||||
|
||||
@code {
|
||||
private CancellationTokenSource? _tickerCancellation;
|
||||
private bool _ready;
|
||||
private bool ShowArbiterModal;
|
||||
|
||||
private MatchState? Match => Store.Current;
|
||||
|
||||
private string ChronoBodyClass =>
|
||||
Match is not null && MatchEngine.IsTimeMode(Match)
|
||||
? "phase-body time-mode"
|
||||
: "phase-body";
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (!firstRender)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await Store.EnsureLoadedAsync();
|
||||
_ready = true;
|
||||
|
||||
if (Match is null)
|
||||
{
|
||||
Navigation.NavigateTo("/application.html", replace: true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(Match.Result) && Match.Phase == MatchEngine.PhaseCube)
|
||||
{
|
||||
await Store.SaveAsync();
|
||||
Navigation.NavigateTo("/cube.html", replace: true);
|
||||
return;
|
||||
}
|
||||
|
||||
_tickerCancellation = new CancellationTokenSource();
|
||||
_ = RunTickerAsync(_tickerCancellation.Token);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (_tickerCancellation is not null)
|
||||
{
|
||||
_tickerCancellation.Cancel();
|
||||
_tickerCancellation.Dispose();
|
||||
}
|
||||
|
||||
await Store.FlushIfDueAsync(0);
|
||||
}
|
||||
|
||||
private async Task RunTickerAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var timer = new PeriodicTimer(TimeSpan.FromMilliseconds(100));
|
||||
while (await timer.WaitForNextTickAsync(cancellationToken))
|
||||
{
|
||||
var match = Match;
|
||||
if (match is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (MatchEngine.SyncRunningState(match))
|
||||
{
|
||||
Store.MarkDirty();
|
||||
}
|
||||
|
||||
await Store.FlushIfDueAsync();
|
||||
|
||||
if (string.IsNullOrEmpty(match.Result) && match.Phase == MatchEngine.PhaseCube)
|
||||
{
|
||||
await Store.SaveAsync();
|
||||
await InvokeAsync(() => Navigation.NavigateTo("/cube.html", replace: true));
|
||||
return;
|
||||
}
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenArbiterModal()
|
||||
=> ShowArbiterModal = true;
|
||||
|
||||
private void CloseArbiterModal()
|
||||
=> ShowArbiterModal = false;
|
||||
|
||||
private async Task HandleChronoTapAsync(string color)
|
||||
{
|
||||
var match = Match;
|
||||
if (match is null || !string.IsNullOrEmpty(match.Result) || match.Phase != MatchEngine.PhaseBlock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MatchEngine.SyncRunningState(match);
|
||||
if (!match.Running || match.CurrentTurn != color)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (match.DoubleCoup.Step == 1)
|
||||
{
|
||||
MatchEngine.RegisterFreeDoubleMove(match);
|
||||
}
|
||||
else
|
||||
{
|
||||
MatchEngine.RegisterCountedMove(match, match.DoubleCoup.Step == 2 ? "double" : "standard");
|
||||
}
|
||||
|
||||
await PersistAndRouteAsync();
|
||||
}
|
||||
|
||||
private async Task HandlePrimaryActionAsync()
|
||||
{
|
||||
var match = Match;
|
||||
if (match is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MatchEngine.SyncRunningState(match);
|
||||
if (!string.IsNullOrEmpty(match.Result))
|
||||
{
|
||||
Navigation.NavigateTo("/application.html");
|
||||
return;
|
||||
}
|
||||
|
||||
if (match.Phase != MatchEngine.PhaseBlock)
|
||||
{
|
||||
await Store.SaveAsync();
|
||||
Navigation.NavigateTo("/cube.html", replace: true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (match.Running)
|
||||
{
|
||||
MatchEngine.PauseBlock(match);
|
||||
}
|
||||
else
|
||||
{
|
||||
MatchEngine.StartBlock(match);
|
||||
}
|
||||
|
||||
await PersistAndRouteAsync();
|
||||
}
|
||||
|
||||
private async Task TogglePauseAsync()
|
||||
{
|
||||
var match = Match;
|
||||
if (match is null || !string.IsNullOrEmpty(match.Result) || match.Phase != MatchEngine.PhaseBlock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MatchEngine.SyncRunningState(match);
|
||||
if (match.Running)
|
||||
{
|
||||
MatchEngine.PauseBlock(match);
|
||||
}
|
||||
else
|
||||
{
|
||||
MatchEngine.StartBlock(match);
|
||||
}
|
||||
|
||||
await PersistAndRouteAsync();
|
||||
}
|
||||
|
||||
private async Task CloseBlockAsync()
|
||||
{
|
||||
var match = Match;
|
||||
if (match is null || !string.IsNullOrEmpty(match.Result) || match.Phase != MatchEngine.PhaseBlock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MatchEngine.SyncRunningState(match);
|
||||
MatchEngine.RequestBlockClosure(match, $"Cloture manuelle {MatchEngine.GetBlockGenitivePhrase(match)} demandee par l'arbitre.");
|
||||
await PersistAndRouteAsync();
|
||||
}
|
||||
|
||||
private async Task TimeoutMoveAsync()
|
||||
{
|
||||
var match = Match;
|
||||
if (match is null || !string.IsNullOrEmpty(match.Result) || match.Phase != MatchEngine.PhaseBlock || !MatchEngine.UsesMoveLimit(match))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MatchEngine.SyncRunningState(match);
|
||||
MatchEngine.RegisterMoveTimeout(match, false);
|
||||
await PersistAndRouteAsync();
|
||||
}
|
||||
|
||||
private async Task SwitchTurnAsync()
|
||||
{
|
||||
var match = Match;
|
||||
if (match is null || !string.IsNullOrEmpty(match.Result) || match.Phase != MatchEngine.PhaseBlock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MatchEngine.SyncRunningState(match);
|
||||
match.CurrentTurn = MatchEngine.OpponentOf(match.CurrentTurn);
|
||||
if (MatchEngine.UsesMoveLimit(match))
|
||||
{
|
||||
match.MoveRemainingMs = MatchEngine.GetMoveLimitMs(match);
|
||||
}
|
||||
|
||||
MatchEngine.LogEvent(match, "Trait corrige manuellement par l'arbitre.");
|
||||
await PersistAndRouteAsync();
|
||||
}
|
||||
|
||||
private async Task SetResultAsync(string result)
|
||||
{
|
||||
var match = Match;
|
||||
if (match is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MatchEngine.SyncRunningState(match);
|
||||
MatchEngine.SetResult(match, result);
|
||||
await PersistAndRouteAsync();
|
||||
}
|
||||
|
||||
private async Task ResetMatchAsync()
|
||||
{
|
||||
await Store.ClearAsync();
|
||||
Navigation.NavigateTo("/application.html", replace: true);
|
||||
}
|
||||
|
||||
private async Task PersistAndRouteAsync()
|
||||
{
|
||||
Store.MarkDirty();
|
||||
await Store.SaveAsync();
|
||||
|
||||
if (Match is not null && string.IsNullOrEmpty(Match.Result) && Match.Phase == MatchEngine.PhaseCube)
|
||||
{
|
||||
Navigation.NavigateTo("/cube.html", replace: true);
|
||||
return;
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private ChronoSummaryView BuildSummary()
|
||||
{
|
||||
var match = Match!;
|
||||
var blockHeading = MatchEngine.FormatBlockHeading(match, match.BlockNumber);
|
||||
var subtitle = $"{blockHeading} - {MatchEngine.Modes[match.Config.Mode].Label} - {MatchEngine.RenderModeContext(match)}";
|
||||
var hideMoveTimer = MatchEngine.IsTimeMode(match);
|
||||
var timeoutButtonText = $"Depassement {MatchEngine.FormatClock(MatchEngine.GetMoveLimitMs(match))}";
|
||||
|
||||
if (!string.IsNullOrEmpty(match.Result))
|
||||
{
|
||||
return new ChronoSummaryView(
|
||||
match.Config.MatchLabel,
|
||||
subtitle,
|
||||
MatchEngine.FormatClock(match.BlockRemainingMs),
|
||||
hideMoveTimer ? "--:--" : MatchEngine.FormatClock(match.MoveRemainingMs),
|
||||
"Resultat",
|
||||
MatchEngine.ResultText(match),
|
||||
"Termine",
|
||||
MatchEngine.ResultText(match),
|
||||
"Retournez a la configuration pour lancer une nouvelle rencontre.",
|
||||
"Retour a l'accueil",
|
||||
"Le match est termine. Vous pouvez revenir a l'accueil ou reinitialiser.",
|
||||
hideMoveTimer,
|
||||
timeoutButtonText);
|
||||
}
|
||||
|
||||
if (match.Running)
|
||||
{
|
||||
return new ChronoSummaryView(
|
||||
match.Config.MatchLabel,
|
||||
subtitle,
|
||||
MatchEngine.FormatClock(match.BlockRemainingMs),
|
||||
hideMoveTimer ? "--:--" : MatchEngine.FormatClock(match.MoveRemainingMs),
|
||||
"Trait",
|
||||
MatchEngine.PlayerName(match, match.CurrentTurn),
|
||||
"Chrono en cours",
|
||||
$"{blockHeading} actif",
|
||||
"Chaque joueur tape sur sa grande zone quand son coup est termine. La page cube s'ouvrira automatiquement a la fin de la phase chess.",
|
||||
"Pause arbitre",
|
||||
$"{blockHeading} en cours. Joueur au trait : {MatchEngine.PlayerName(match, match.CurrentTurn)}.",
|
||||
hideMoveTimer,
|
||||
timeoutButtonText);
|
||||
}
|
||||
|
||||
return new ChronoSummaryView(
|
||||
match.Config.MatchLabel,
|
||||
subtitle,
|
||||
MatchEngine.FormatClock(match.BlockRemainingMs),
|
||||
hideMoveTimer ? "--:--" : MatchEngine.FormatClock(match.MoveRemainingMs),
|
||||
"Trait",
|
||||
MatchEngine.PlayerName(match, match.CurrentTurn),
|
||||
MatchEngine.IsTimeMode(match) ? "Etat du Block" : "Pret",
|
||||
blockHeading,
|
||||
"Demarrez le Block, puis laissez uniquement les deux grandes zones aux joueurs. La page cube prendra automatiquement le relais.",
|
||||
"Demarrer le Block",
|
||||
$"{blockHeading} pret. {MatchEngine.PlayerName(match, match.CurrentTurn)} commencera.",
|
||||
hideMoveTimer,
|
||||
timeoutButtonText);
|
||||
}
|
||||
|
||||
private ChronoZoneView BuildZone(string color)
|
||||
{
|
||||
var match = Match!;
|
||||
var active = match.CurrentTurn == color;
|
||||
var clockValue = match.Clocks is not null
|
||||
? color == MatchEngine.ColorWhite ? match.Clocks.White : match.Clocks.Black
|
||||
: 0;
|
||||
|
||||
var clockText = match.Clocks is not null
|
||||
? MatchEngine.FormatSignedClock(clockValue)
|
||||
: $"Dernier cube {MatchEngine.RenderLastCube(match, color)}";
|
||||
|
||||
if (!string.IsNullOrEmpty(match.Result))
|
||||
{
|
||||
return new ChronoZoneView(
|
||||
MatchEngine.PlayerName(match, color),
|
||||
$"{(color == MatchEngine.ColorWhite ? match.Moves.White : match.Moves.Black)} / {match.Quota}",
|
||||
clockText,
|
||||
MatchEngine.ResultText(match),
|
||||
"Le match est termine.",
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
match.Clocks is not null,
|
||||
match.Clocks is not null && clockValue < 0,
|
||||
false);
|
||||
}
|
||||
|
||||
if (!match.Running)
|
||||
{
|
||||
return new ChronoZoneView(
|
||||
MatchEngine.PlayerName(match, color),
|
||||
$"{(color == MatchEngine.ColorWhite ? match.Moves.White : match.Moves.Black)} / {match.Quota}",
|
||||
clockText,
|
||||
"Block en pause",
|
||||
active
|
||||
? $"{MatchEngine.GetBlockPhrase(match)} n'a pas encore demarre ou a ete mis en pause."
|
||||
: $"{MatchEngine.PlayerName(match, match.CurrentTurn)} reprendra au demarrage.",
|
||||
true,
|
||||
false,
|
||||
active,
|
||||
match.Clocks is not null,
|
||||
match.Clocks is not null && clockValue < 0,
|
||||
false);
|
||||
}
|
||||
|
||||
if (!active)
|
||||
{
|
||||
return new ChronoZoneView(
|
||||
MatchEngine.PlayerName(match, color),
|
||||
$"{(color == MatchEngine.ColorWhite ? match.Moves.White : match.Moves.Black)} / {match.Quota}",
|
||||
clockText,
|
||||
"Attends",
|
||||
$"{MatchEngine.PlayerName(match, match.CurrentTurn)} est en train de jouer.",
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
match.Clocks is not null,
|
||||
match.Clocks is not null && clockValue < 0,
|
||||
false);
|
||||
}
|
||||
|
||||
if (match.DoubleCoup.Step == 1)
|
||||
{
|
||||
return new ChronoZoneView(
|
||||
MatchEngine.PlayerName(match, color),
|
||||
$"{(color == MatchEngine.ColorWhite ? match.Moves.White : match.Moves.Black)} / {match.Quota}",
|
||||
clockText,
|
||||
"1er coup gratuit",
|
||||
"Ce coup ne compte pas et ne doit pas donner echec.",
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
match.Clocks is not null,
|
||||
match.Clocks is not null && clockValue < 0,
|
||||
match.Clocks is not null);
|
||||
}
|
||||
|
||||
if (match.DoubleCoup.Step == 2)
|
||||
{
|
||||
return new ChronoZoneView(
|
||||
MatchEngine.PlayerName(match, color),
|
||||
$"{(color == MatchEngine.ColorWhite ? match.Moves.White : match.Moves.Black)} / {match.Quota}",
|
||||
clockText,
|
||||
"2e coup du double",
|
||||
"Ce coup compte dans le quota et l'echec redevient autorise.",
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
match.Clocks is not null,
|
||||
match.Clocks is not null && clockValue < 0,
|
||||
match.Clocks is not null);
|
||||
}
|
||||
|
||||
return new ChronoZoneView(
|
||||
MatchEngine.PlayerName(match, color),
|
||||
$"{(color == MatchEngine.ColorWhite ? match.Moves.White : match.Moves.Black)} / {match.Quota}",
|
||||
clockText,
|
||||
"J'ai fini mon coup",
|
||||
"Tape des que ton coup est joue sur l'echiquier.",
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
match.Clocks is not null,
|
||||
match.Clocks is not null && clockValue < 0,
|
||||
match.Clocks is not null);
|
||||
}
|
||||
|
||||
private static string BoolString(bool value)
|
||||
=> value ? "true" : "false";
|
||||
|
||||
private sealed record ChronoSummaryView(
|
||||
string Title,
|
||||
string Subtitle,
|
||||
string BlockTimer,
|
||||
string MoveTimer,
|
||||
string CenterLabel,
|
||||
string CenterValue,
|
||||
string SpineLabel,
|
||||
string SpineHeadline,
|
||||
string SpineText,
|
||||
string PrimaryButtonText,
|
||||
string ArbiterStatus,
|
||||
bool HideMoveTimer,
|
||||
string TimeoutButtonText);
|
||||
|
||||
private sealed record ChronoZoneView(
|
||||
string Name,
|
||||
string Moves,
|
||||
string Clock,
|
||||
string ButtonText,
|
||||
string Hint,
|
||||
bool Disabled,
|
||||
bool ActiveTurn,
|
||||
bool ActiveZone,
|
||||
bool HasPlayerClock,
|
||||
bool NegativeClock,
|
||||
bool ActiveClock);
|
||||
}
|
||||
Reference in New Issue
Block a user