Add detailed ride diagnostics to match logging
CI / test (push) Successful in 2m26s
Details
CI / test (push) Successful in 2m26s
Details
This commit is contained in:
parent
5a6e96b678
commit
7ad486f382
|
|
@ -109,6 +109,14 @@ public sealed class MatchGrain : IMatchGrain
|
|||
|
||||
_engine.Start(setup.FirstPlayer);
|
||||
RefreshSummary();
|
||||
|
||||
_logger.LogInformation(
|
||||
"Match {MatchId}: created {Seat0} vs {Seat1}, first={FirstPlayer}. {State}",
|
||||
_matchId,
|
||||
_seats[0].PlayerId,
|
||||
_seats[1].PlayerId,
|
||||
setup.FirstPlayer,
|
||||
DescribeTurnState());
|
||||
}
|
||||
|
||||
public string MatchId => _matchId;
|
||||
|
|
@ -172,8 +180,8 @@ public sealed class MatchGrain : IMatchGrain
|
|||
await SendClockAsync(seat, now);
|
||||
|
||||
_logger.LogInformation(
|
||||
"Match {MatchId}: seat {Seat} attached (resume from {Seq}, now {Now}).",
|
||||
_matchId, seat, resumeFromSeq, to);
|
||||
"Match {MatchId}: seat {Seat} attached (resume from {Seq}, now {Now}). {State}",
|
||||
_matchId, seat, resumeFromSeq, to, DescribeTurnState());
|
||||
|
||||
await PersistHeaderAsync();
|
||||
|
||||
|
|
@ -314,6 +322,10 @@ public sealed class MatchGrain : IMatchGrain
|
|||
|
||||
var decisionBefore = _engine.State.ActivePlayer;
|
||||
|
||||
_logger.LogInformation(
|
||||
"Match {MatchId}: seat {Seat} intent {IntentType} ({IntentId}) received. {State}",
|
||||
_matchId, seat, DescribeIntent(intent.Intent), intentId, DescribeTurnState());
|
||||
|
||||
CommandResult result;
|
||||
var commandText = string.Empty;
|
||||
|
||||
|
|
@ -349,6 +361,20 @@ public sealed class MatchGrain : IMatchGrain
|
|||
await SendResultAsync(
|
||||
seat, intentId, record.Accepted, record.Code, record.Reason, record.EventSeq, duplicate: false);
|
||||
|
||||
if (record.Accepted)
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Match {MatchId}: seat {Seat} intent {IntentType} ({IntentId}) accepted. {State}",
|
||||
_matchId, seat, DescribeIntent(intent.Intent), intentId, DescribeTurnState());
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Match {MatchId}: seat {Seat} intent {IntentType} ({IntentId}) rejected {Code}: {Reason}. {State}",
|
||||
_matchId, seat, DescribeIntent(intent.Intent), intentId, record.Code, record.Reason,
|
||||
DescribeTurnState());
|
||||
}
|
||||
|
||||
if (!record.Accepted)
|
||||
return;
|
||||
|
||||
|
|
@ -462,6 +488,10 @@ public sealed class MatchGrain : IMatchGrain
|
|||
IntentRejectCode code,
|
||||
string reason)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Match {MatchId}: seat {Seat} intent {IntentId} rejected before execution {Code}: {Reason}. {State}",
|
||||
_matchId, seat, intentId, code, reason, DescribeTurnState());
|
||||
|
||||
_intents[intentId] = new IntentRecord(false, code, reason, _engine.Events.Count);
|
||||
|
||||
await PersistIntentAsync(new PersistedIntent(
|
||||
|
|
@ -510,6 +540,15 @@ public sealed class MatchGrain : IMatchGrain
|
|||
var from = Math.Max(1, fromSeq);
|
||||
var events = EventProjection.ProjectRange(_engine.Events, seat, from);
|
||||
|
||||
_logger.LogInformation(
|
||||
"Match {MatchId}: events {FromSeq}..{ToSeq} to seat {Seat}: [{EventTypes}]. {State}",
|
||||
_matchId,
|
||||
from,
|
||||
to,
|
||||
seat,
|
||||
string.Join(", ", events.Select(e => e.GetType().Name)),
|
||||
DescribeTurnState());
|
||||
|
||||
_seats[seat].SentSeq = to;
|
||||
|
||||
await SendToSeatAsync(seat, new ServerEvents
|
||||
|
|
@ -524,6 +563,22 @@ public sealed class MatchGrain : IMatchGrain
|
|||
{
|
||||
var to = _engine.Events.Count;
|
||||
var view = MatchProjection.ForViewer(_engine, seat, _matchId, to, BuildClock(now));
|
||||
var legalRides = string.Join(
|
||||
", ",
|
||||
view.LegalIntents.OfType<RideIntent>().Select(i => i.PrintingId));
|
||||
|
||||
_logger.LogInformation(
|
||||
"Match {MatchId}: snapshot to seat {Seat} at seq {Seq}, you={You}, active={Active}, turn={Turn}, phase={Phase}, legal={LegalCount}, rides=[{Rides}]. {State}",
|
||||
_matchId,
|
||||
seat,
|
||||
to,
|
||||
view.You,
|
||||
view.ActivePlayer,
|
||||
view.TurnNumber,
|
||||
view.Phase,
|
||||
view.LegalIntents.Count,
|
||||
legalRides,
|
||||
DescribeTurnState());
|
||||
|
||||
_seats[seat].SentSeq = to;
|
||||
|
||||
|
|
@ -780,6 +835,52 @@ public sealed class MatchGrain : IMatchGrain
|
|||
}
|
||||
}
|
||||
|
||||
private static string DescribeIntent(IntentPayload? intent) =>
|
||||
intent is RideIntent ride
|
||||
? $"Ride({ride.PrintingId})"
|
||||
: intent?.GetType().Name ?? "null";
|
||||
|
||||
/// <summary>
|
||||
/// Diagnostic snapshot for ride issues: active player, phase, vanguard grade,
|
||||
/// hand grades and cards that should be offered for a ride.
|
||||
/// </summary>
|
||||
private string DescribeTurnState()
|
||||
{
|
||||
var state = _engine.State;
|
||||
var active = state.ActivePlayer;
|
||||
var player = state.Players[active];
|
||||
var rideGrade = _engine.VanguardGrade(active);
|
||||
|
||||
var vanguard = player.Vanguard is null
|
||||
? "none"
|
||||
: $"{player.Vanguard.PrintingId}(g{rideGrade})";
|
||||
|
||||
var hand = string.Join(
|
||||
", ",
|
||||
player.Hand.Select(card =>
|
||||
{
|
||||
var grade = state.Catalog.CardOf(card.PrintingId).Grade;
|
||||
return $"{card.PrintingId}(g{grade})";
|
||||
}));
|
||||
|
||||
var rideReady = state.Phase == Phase.Ride
|
||||
? string.Join(
|
||||
", ",
|
||||
player.Hand
|
||||
.Where(card =>
|
||||
{
|
||||
var grade = state.Catalog.CardOf(card.PrintingId).Grade;
|
||||
return grade == rideGrade || grade == rideGrade + 1;
|
||||
})
|
||||
.Select(card => card.PrintingId)
|
||||
.Distinct())
|
||||
: string.Empty;
|
||||
|
||||
return $"active={active} turn={state.TurnNumber} phase={state.Phase} " +
|
||||
$"step={state.Step} vanguard={vanguard} hand=[{hand}] " +
|
||||
$"rideReady=[{rideReady}]";
|
||||
}
|
||||
|
||||
private void RefreshSummary()
|
||||
{
|
||||
_summary = new MatchSummary(
|
||||
|
|
|
|||
Loading…
Reference in New Issue