PenaltyShootoutHud.razor

HUD panel for a penalty shootout. Draws the sudden death or series heading, both teams' crests and short names, five attempt markers per team filled from the kick history, the current score, the taker's name and the current phase text, with Russian or English labels.

Rough Code
@using Sandbox
@using Sandbox.UI
@using Socer
@using System
@using System.Linq
@inherits Panel
<root class="localized-text">
    <label class="shootout-heading">@(GamePreferences.Russian?Match.ShootoutSuddenDeath?"ДО ПЕРВОГО ПРЕИМУЩЕСТВА":"СЕРИЯ ПЕНАЛЬТИ":Match.ShootoutSuddenDeath?"SUDDEN DEATH":"PENALTY SHOOTOUT")</label>
    @if(Match.ShootoutAttempts.Max()>=5){<label class="shootout-window">@(GamePreferences.Russian?"Попытки":"Attempts") @(Math.Max(1,Match.ShootoutAttempts.Max()-3))–@(Match.ShootoutAttempts.Max()+1)</label>}
    @for(int team=0;team<2;team++)
    {
        int side=team;var results=Match.ShootoutKicks.Where(k=>k.Team==side).ToArray();
        int nextAttempt=Match.ShootoutAttempts.Max()+1;int firstAttempt=Math.Max(0,nextAttempt-5);
        <div class="shootout-team"><img src="@ClubIdentity.Crest(Match.TeamName(side))" /><label class="shootout-team-name">@ClubIdentity.ShortName(Match.TeamName(side))</label><div class="shootout-attempts">@for(int slot=0;slot<5;slot++){int kick=firstAttempt+slot;bool done=kick<results.Length;bool scored=done && results[kick].Scored;<div class="shootout-attempt @(done?scored?"scored":"missed":kick==results.Length && Match.ShootoutTeam==side?"next":"")"><label>@(done?scored?"●":"×":(kick+1).ToString())</label></div>}</div><b>@Match.ShootoutScores[side]</b></div>
    }
    @if(Match.ShootoutTaker>=0){<label class="shootout-kicker">@Match.Players[Match.ShootoutTaker].Profile.Name</label>}
    <label class="shootout-phase">@(GamePreferences.Russian?Match.ShootoutPhase switch{1=>"Игроки готовятся",2=>"Перед ударом",3=>"Разбег",4=>"Удар",_=>Match.ShootoutKicks.LastOrDefault()?.Outcome switch{PenaltyOutcome.Goal=>"Гол!",PenaltyOutcome.Saved=>"Вратарь отбил!",PenaltyOutcome.Post=>"Штанга",PenaltyOutcome.High=>"Выше ворот",_=>"Мимо ворот"}}:Match.ShootoutPhase switch{1=>"Getting ready",2=>"Preparing",3=>"Run-up",4=>"Shot",_=>Match.ShootoutKicks.LastOrDefault()?.Outcome.ToString()??""})</label>
</root>
@code{
    [Parameter] public MatchSimulation Match {get;set;}
    protected override int BuildHash()=>Match==null?0:HashCode.Combine(Match.ShootoutPhase,Match.ShootoutTeam,Match.ShootoutTaker,Match.ShootoutKicks.Count,Match.ShootoutScores[0],Match.ShootoutScores[1],Match.ShootoutAttempts.Max(),GamePreferences.Revision);
}