@page "/keyboard" Keyboard
@foreach (var k in Keys.Take(6)) {
@k.Label @if (k.SkillName != null) { @k.SkillName } @if (k.OnCooldown) {
@k.RemainingSeconds
}
}
@foreach (var k in Keys.Skip(6).Take(5)) {
@k.Label @if (k.SkillName != null) { @k.SkillName } @if (k.OnCooldown) {
@k.RemainingSeconds
}
}
@foreach (var k in Keys.Skip(11).Take(5)) {
@k.Label @if (k.SkillName != null) { @k.SkillName } @if (k.OnCooldown) {
@k.RemainingSeconds
}
}
@foreach (var k in Keys.Skip(16).Take(5)) {
@k.Label @if (k.SkillName != null) { @k.SkillName } @if (k.OnCooldown) {
@k.RemainingSeconds
}
}
@spaceKey.Label @if (spaceKey.SkillName != null) { @spaceKey.SkillName } @if (spaceKey.OnCooldown) {
@spaceKey.RemainingSeconds
}
Shift + Key
@foreach (var k in ShiftKeys.Take(6)) {
@k.Label @if (k.SkillName != null) { @k.SkillName } @if (k.OnCooldown) {
@k.RemainingSeconds
}
}
@foreach (var k in ShiftKeys.Skip(6).Take(5)) {
@k.Label @if (k.SkillName != null) { @k.SkillName } @if (k.OnCooldown) {
@k.RemainingSeconds
}
}
@foreach (var k in ShiftKeys.Skip(11).Take(5)) {
@k.Label @if (k.SkillName != null) { @k.SkillName } @if (k.OnCooldown) {
@k.RemainingSeconds
}
}
@foreach (var k in ShiftKeys.Skip(16).Take(5)) {
@k.Label @if (k.SkillName != null) { @k.SkillName } @if (k.OnCooldown) {
@k.RemainingSeconds
}
}
@shiftSpaceKey.Label @if (shiftSpaceKey.SkillName != null) { @shiftSpaceKey.SkillName } @if (shiftSpaceKey.OnCooldown) {
@shiftSpaceKey.RemainingSeconds
}
@code { private ElementReference containerRef; private List Keys { get; set; } = new(); private List ShiftKeys { get; set; } = new(); private KeyData spaceKey = null!; private KeyData shiftSpaceKey = null!; private string selectedCharacter = "Xavian"; private List Characters = []; public class KeyData { public string Id { get; set; } = ""; public string Label { get; set; } = ""; public string? SkillName { get; set; } public string? Character { get; set; } public double CooldownDuration { get; set; } public double Remaining { get; set; } public bool OnCooldown => Remaining > 0; public double RemainingSeconds => Math.Ceiling(Remaining); public double CooldownFraction => CooldownDuration > 0 ? Math.Min(1, Remaining / CooldownDuration) : 0; public void Tick(double seconds) { if (Remaining > 0) Remaining = Math.Max(0, Remaining - seconds); } public string Tooltip { get { var parts = new List(); if (Character != null) parts.Add(Character); if (SkillName != null) parts.Add(SkillName); if (CooldownDuration > 0) parts.Add($"CD: {CooldownDuration}s"); return parts.Count > 0 ? string.Join(" - ", parts) : Label; } } } protected override void OnInitialized() { Characters = DocsData.All .OfType() .Where(s => s.Character != null) .Select(s => s.Character!) .Distinct() .Order() .ToList(); if (Characters.Count == 0) Characters.Add("Xavian"); RebuildKeyboardData(); } private void RebuildKeyboardData() { var skillByKey = DocsData.All .OfType() .Where(s => !string.IsNullOrEmpty(s.Key) && s.Character == selectedCharacter) .GroupBy(s => s.Key!) .ToDictionary(g => g.Key, g => g.OrderBy(s => string.IsNullOrEmpty(s.CostSwiftReprieval) ? 0 : 1).First()); var actionByKey = DocsData.All .OfType() .Where(k => !string.IsNullOrEmpty(k.Action)) .Select(k => new { Key = Path.GetFileNameWithoutExtension(k.FileName), k.Action }) .GroupBy(x => x.Key) .ToDictionary(g => g.Key, g => g.First().Action!, StringComparer.OrdinalIgnoreCase); var keyLabels = new[] { "1", "2", "3", "4", "5", "6", "Q", "W", "E", "R", "T", "A", "S", "D", "F", "G", "Z", "X", "C", "V", "B" }; Keys = keyLabels.Select(label => { var skill = skillByKey.GetValueOrDefault(label); var action = actionByKey.GetValueOrDefault(label); var skillName = skill != null ? Path.GetFileNameWithoutExtension(skill.FileName) : action; return new KeyData { Id = label.ToLower(), Label = label, SkillName = skillName, Character = skill?.Character, CooldownDuration = ParseCooldown(skill?.Cooldown) }; }).ToList(); var spaceSkill = skillByKey.GetValueOrDefault(" "); var spaceAction = actionByKey.GetValueOrDefault("Space"); spaceKey = new KeyData { Id = "space", Label = "Space", SkillName = spaceSkill != null ? Path.GetFileNameWithoutExtension(spaceSkill.FileName) : spaceAction, Character = spaceSkill?.Character, CooldownDuration = ParseCooldown(spaceSkill?.Cooldown) }; ShiftKeys = keyLabels.Select(label => { var shiftKeyStr = "Shift + " + label; var skill = skillByKey.GetValueOrDefault(shiftKeyStr); var action = actionByKey.GetValueOrDefault(shiftKeyStr); var skillName = skill != null ? Path.GetFileNameWithoutExtension(skill.FileName) : action; return new KeyData { Id = "shift-" + label.ToLower(), Label = "Shift+" + label, SkillName = skillName, Character = skill?.Character, CooldownDuration = ParseCooldown(skill?.Cooldown) }; }).ToList(); var shiftSpaceSkill = skillByKey.GetValueOrDefault("Shift + Space"); var shiftSpaceAction = actionByKey.GetValueOrDefault("Shift + Space"); shiftSpaceKey = new KeyData { Id = "shift-space", Label = "Shift+Space", SkillName = shiftSpaceSkill != null ? Path.GetFileNameWithoutExtension(shiftSpaceSkill.FileName) : shiftSpaceAction, Character = shiftSpaceSkill?.Character, CooldownDuration = ParseCooldown(shiftSpaceSkill?.Cooldown) }; } private static double ParseCooldown(string? cooldown) { if (string.IsNullOrEmpty(cooldown)) return 0; if (double.TryParse(cooldown, out var result)) return result; return 0; } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { await containerRef.FocusAsync(); } } private void HandleKeyDown(KeyboardEventArgs e) { var isShift = e.ShiftKey; var key = e.Key.ToLower(); var allKeys = new List(); allKeys.AddRange(Keys); allKeys.Add(spaceKey); allKeys.AddRange(ShiftKeys); allKeys.Add(shiftSpaceKey); KeyData? target; if (isShift) { if (key == "shift") return; var lookup = "shift-" + (key == " " ? "space" : key); target = allKeys.FirstOrDefault(k => k.Id == lookup); } else { var lookup = key == " " ? "space" : key; target = allKeys.FirstOrDefault(k => k.Id == lookup); } if (target != null) { ActivateKey(target); } } private void ActivateKey(KeyData key) { if (key.OnCooldown) return; if (key.Character == null) return; var duration = key.CooldownDuration > 0 ? key.CooldownDuration : 0.5; key.Remaining = duration; var allKeys = new List(); allKeys.AddRange(Keys); allKeys.Add(spaceKey); allKeys.AddRange(ShiftKeys); allKeys.Add(shiftSpaceKey); foreach (var k in allKeys) { k.Tick(1.5); } } }