feature(BuildCalc) Added reset button, can change micro delay, and can alter timing interval again

This commit is contained in:
2022-04-14 22:28:14 -04:00
parent 4cef578cd0
commit 04c1718259
115 changed files with 1561 additions and 1308 deletions
@@ -10,7 +10,6 @@
@inject ITimingService timingService
@page "/build-calculator"
@using Microsoft.Extensions.Localization
@implements IDisposable
@@ -20,89 +19,93 @@
<AlertComponent Type="@SeverityType.Warning">
<Title>Work In Progress and Not Fully Tested</Title>
<Message>
Currently not considering training queue times. Lacking error toasts for invalid actions. Performance needs to be optimized. Calculations haven't been thoroughly compared against real gameplay. Added a 2 second delay to actions to account for casual micro (will probably tweak later).
Currently not considering training queue times.
</Message>
</AlertComponent>
<ContentDividerComponent></ContentDividerComponent>
<div class="calculatorGrid">
<div style="grid-area: timing;" class="gridItem">
<InfoTooltipComponent InfoText="@locale["Tooltip Timing Info"]">
<TimingComponent></TimingComponent>
</InfoTooltipComponent>
<div class="gridItem" style="grid-area: timing;">
<ButtonComponent OnClick="OnResetClicked">Clear Build Order</ButtonComponent>
<PanelComponent>
<InfoTooltipComponent InfoText="@locale["Tooltip Timing Info"]">
<TimingComponent></TimingComponent>
</InfoTooltipComponent>
</PanelComponent>
</div>
@if (true)
{
<div style="grid-area: chart;" class="gridItem">
<div class="gridItem" style="grid-area: chart;">
<PanelComponent>
<InfoTooltipComponent InfoText="@locale["Tooltip Chart Info"]">
<ChartComponent></ChartComponent>
</InfoTooltipComponent>
</div>
}
<div style="grid-area: filter;" class="gridItem">
<InfoTooltipComponent InfoText="@locale["Tooltip Filter Info"]">
<FilterComponent></FilterComponent>
</InfoTooltipComponent>
</PanelComponent>
</div>
@if (true)
{
<div style="grid-area: view;" class="gridItem">
<div class="gridItem" style="grid-area: filter;">
<PanelComponent>
<InfoTooltipComponent InfoText="@locale["Tooltip Filter Info"]">
<FilterComponent></FilterComponent>
</InfoTooltipComponent>
</PanelComponent>
<PanelComponent>
<InfoTooltipComponent InfoText="@locale["Tooltip Options Info"]">
<OptionsComponent></OptionsComponent>
</InfoTooltipComponent>
</PanelComponent>
</div>
<div class="gridItem" style="grid-area: view;">
<PanelComponent>
<InfoTooltipComponent InfoText="@locale["Tooltip Entity Info"]">
<EntityClickViewComponent/>
</InfoTooltipComponent>
</div>
}
@if (true)
{
<div style="grid-area: bank;" class="gridItem">
</PanelComponent>
</div>
<div class="gridItem" style="grid-area: bank;">
<PanelComponent>
<InfoTooltipComponent InfoText="@locale["Tooltip Bank Info"]">
<BankComponent></BankComponent>
</InfoTooltipComponent>
</div>
}
</PanelComponent>
</div>
@if (true)
{
<div style="grid-area: army;" class="gridItem">
<div class="gridItem" style="grid-area: army;">
<PanelComponent>
<InfoTooltipComponent InfoText="@locale["Tooltip Army Info"]">
<ArmyComponent></ArmyComponent>
</InfoTooltipComponent>
</div>
}
<div class="gridItem gridKeys">
<InfoTooltipComponent InfoText="@locale["Tooltip Hotkey Info"]">
<HotkeyViewerComponent Size="80"></HotkeyViewerComponent>
</InfoTooltipComponent>
</PanelComponent>
</div>
@if (true)
{
<div style="grid-area: highlights;" class="gridItem">
<div class="gridItem gridKeys">
<PanelComponent>
<InfoTooltipComponent InfoText="@locale["Tooltip Hotkey Info"]">
<HotkeyViewerComponent Size="80"></HotkeyViewerComponent>
</InfoTooltipComponent>
</PanelComponent>
</div>
<div class="gridItem" style="grid-area: highlights;">
<PanelComponent>
<InfoTooltipComponent InfoText="@locale["Tooltip Highlights Info"]">
<HighlightsComponent></HighlightsComponent>
</InfoTooltipComponent>
</div>
}
@if (true)
{
<div style="grid-area: buildorder;" class="gridItem">
</PanelComponent>
</div>
<div class="gridItem" style="grid-area: buildorder;">
<PanelComponent>
<InfoTooltipComponent InfoText="@locale["Tooltip BuildOrder Info"]">
<BuildOrderComponent></BuildOrderComponent>
</InfoTooltipComponent>
</div>
}
</PanelComponent>
</div>
</div>
<ContentDividerComponent></ContentDividerComponent>
@@ -135,7 +138,7 @@
<InfoBodyComponent>
<InfoQuestionComponent>
What is CONTROl key for?
What is CONTROL key for?
</InfoQuestionComponent>
<InfoAnswerComponent>
Economy and tech related upgrades for townhalls.
@@ -165,6 +168,12 @@
<style>
.gridItem {
display: flex;
flex-direction: column;
gap: 8px;
}
.calculatorGrid {
display: grid;
gap: 8px;
@@ -178,12 +187,6 @@
'chart chart chart chart';
}
.gridItem {
border: 2px solid var(--paper-border);
padding: 20px;
background-color: var(--paper);
}
.gridKeys {
grid-area: keys;
}
@@ -209,30 +212,35 @@
padding-left: 2px;
padding-right: 2px;
}
.gridItem {
padding: 0px;
border: 0px;
width: 100%;
}
}
</style>
@code {
protected override void OnInitialized()
{
economyService.Calculate(buildOrderService, timingService, 0);
keyService.Subscribe(HandleClick);
}
void IDisposable.Dispose()
{
keyService.Unsubscribe(HandleClick);
}
private void OnResetClicked()
{
toastService.AddToast(new ToastModel(){
SeverityType = SeverityType.Success,
Message = "Build order has been cleared.",
Title = "Reset"});
buildOrderService.Reset();
}
private void HandleClick()
{
var hotkey = keyService.GetHotkey();
@@ -254,16 +262,17 @@
var faction = filterService.GetFactionType();
var immortal = filterService.GetImmortalType();
EntityModel? entity = EntityModel.GetFrom(hotkey!, hotkeyGroup, isHoldSpace, faction, immortal);
var entity = EntityModel.GetFrom(hotkey!, hotkeyGroup, isHoldSpace, faction, immortal);
if (entity == null)
{
return;
}
if (buildOrderService.Add(entity, economyService, toastService))
{
economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval());
}
}
}
@@ -1,6 +1,6 @@
@inject IJSRuntime jsRuntime;
@inject IJSRuntime jsRuntime
@inject IBuildOrderService BuildOrder
@inject IBuildOrderService buildOrder
@implements IDisposable
@@ -35,12 +35,12 @@
protected override void OnInitialized()
{
BuildOrder.Subscribe(OnBuildOrderChanged);
buildOrder.Subscribe(OnBuildOrderChanged);
}
void IDisposable.Dispose()
{
BuildOrder.Unsubscribe(OnBuildOrderChanged);
buildOrder.Unsubscribe(OnBuildOrderChanged);
}
protected override bool ShouldRender()
@@ -57,20 +57,20 @@
jsRuntime.InvokeVoidAsync("console.timeEnd", "ArmyComponent");
#endif
}
void OnBuildOrderChanged()
{
int armyCountWas = 0;
var armyCountWas = 0;
foreach (var army in armyCount)
{
armyCountWas += army.Value;
}
armyCount.Clear();
lastInterval = 0;
var entitiesOverTime = BuildOrder.GetOrders();
var entitiesOverTime = buildOrder.GetOrders();
foreach (var entitiesAtTime in entitiesOverTime)
{
@@ -91,19 +91,18 @@
}
}
//TODO Better
int armyCountIs = 0;
//TODO Better
var armyCountIs = 0;
foreach (var army in armyCount)
{
armyCountIs += army.Value;
}
if (armyCountWas != armyCountIs)
{
StateHasChanged();
StateHasChanged();
}
}
}
@@ -43,7 +43,7 @@
#if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "BankComponent");
#endif
return true;
}
@@ -1,6 +1,5 @@
@inject IJSRuntime jsRuntime;
@inject IBuildOrderService buildOrderService
@implements IDisposable
@@ -29,7 +28,7 @@
#if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "BuildOrderComponent");
#endif
return true;
}
@@ -39,4 +38,5 @@
jsRuntime.InvokeVoidAsync("console.timeEnd", "BuildOrderComponent");
#endif
}
}
@@ -6,7 +6,6 @@
@if (lastRequestedRefreshIndex != requestedRefreshIndex)
{
<LoadingComponent/>
}
else
{
@@ -30,8 +29,8 @@ else
</div>
}
</div>
<style>
.chartsContainer {
position: relative;
@@ -60,8 +59,6 @@ else
<Display>@highestArmyPoint</Display>
</FormDisplayComponent>
</FormLayoutComponent>
}
@code {
@@ -80,7 +77,7 @@ else
private Timer ageTimer = null!;
protected override void OnInitialized()
{
buildOrderService.Subscribe(OnBuilderOrderChanged);
@@ -89,12 +86,13 @@ else
ageTimer.Elapsed += OnAge!;
ageTimer.Enabled = true;
GenerateChart();
}
int lastRequestedRefreshIndex = 0;
void OnAge(object? sender, ElapsedEventArgs elapsedEventArgs)
{
if (requestedRefreshIndex > 0)
@@ -105,14 +103,13 @@ else
requestedRefreshIndex = 0;
lastRequestedRefreshIndex = 0;
}
lastRequestedRefreshIndex = requestedRefreshIndex;
}
ageTimer.Enabled = true;
}
void IDisposable.Dispose()
{
@@ -121,6 +118,7 @@ else
int requestedRefreshIndex = 0;
void OnBuilderOrderChanged()
{
requestedRefreshIndex++;
@@ -133,7 +131,7 @@ else
#if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "ChartComponent");
#endif
return true;
}
@@ -143,7 +141,7 @@ else
jsRuntime.InvokeVoidAsync("console.timeEnd", "ChartComponent");
#endif
}
void GenerateChart()
{
var economyOverTime = economyService.GetOverTime();
@@ -1,9 +1,7 @@
@inject IJSRuntime jsRuntime;
@inject IKeyService keyService
@inject IImmortalSelectionService filterService
@inject IBuildOrderService buildOrderService
@inject IKeyService keyService
@inject IImmortalSelectionService filterService
@inject IBuildOrderService buildOrderService
@implements IDisposable
@@ -68,4 +66,5 @@
StateHasChanged();
}
}
}
@@ -1,4 +1,5 @@
@inject IJSRuntime jsRuntime;
@inject IImmortalSelectionService filterService
<FormLayoutComponent>
<FormSelectComponent OnChange="@OnFactionChanged">
@@ -12,12 +13,12 @@
<FormSelectComponent OnChange="@OnImmortalChanged">
<FormLabelComponent>Immortal</FormLabelComponent>
<ChildContent>
@if (FilterService.GetFactionType() == FactionType.QRath)
@if (filterService.GetFactionType() == FactionType.QRath)
{
<option value="@DataType.IMMORTAL_Orzum" selected>Orzum</option>
<option value="@DataType.IMMORTAL_Ajari">Ajari</option>
}
@if (FilterService.GetFactionType() == FactionType.Aru)
@if (filterService.GetFactionType() == FactionType.Aru)
{
<option value="@DataType.IMMORTAL_Mala" selected>Mala</option>
<option value="@DataType.IMMORTAL_Xol">Xol</option>
@@ -28,17 +29,14 @@
@code {
[Inject]
public IImmortalSelectionService FilterService { get; set; } = default!;
void OnFactionChanged(ChangeEventArgs e)
{
FilterService.SelectFactionType(e.Value!.ToString()!);
filterService.SelectFactionType(e.Value!.ToString()!);
}
void OnImmortalChanged(ChangeEventArgs e)
{
FilterService.SelectImmortalType(e.Value!.ToString()!);
filterService.SelectImmortalType(e.Value!.ToString()!);
}
protected override bool ShouldRender()
@@ -46,7 +44,7 @@
#if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "FilterComponent");
#endif
return true;
}
@@ -56,4 +54,5 @@
jsRuntime.InvokeVoidAsync("console.timeEnd", "FilterComponent");
#endif
}
}
@@ -1,5 +1,7 @@
@inject IJSRuntime jsRuntime;
@inject IEconomyService economyService
@inject IBuildOrderService buildOrderService
@inject ITimingService timingService
@implements IDisposable
@@ -7,7 +9,7 @@
<div>
<div>Requested</div>
@foreach (var ordersAtTime in BuildOrderService.StartedOrders.Reverse())
@foreach (var ordersAtTime in buildOrderService.StartedOrders.Reverse())
{
foreach (var order in ordersAtTime.Value)
{
@@ -26,7 +28,7 @@
<div>
<div>Finished</div>
@foreach (var ordersAtTime in BuildOrderService.CompletedOrders.Reverse())
@foreach (var ordersAtTime in buildOrderService.CompletedOrders.Reverse())
{
foreach (var order in ordersAtTime.Value)
{
@@ -57,25 +59,16 @@
@code {
[Inject]
IEconomyService EconomyService { get; set; } = default!;
[Inject]
IBuildOrderService BuildOrderService { get; set; } = default!;
[Inject]
ITimingService TimingService { get; set; } = default!;
protected override void OnInitialized()
{
EconomyService.Subscribe(StateHasChanged);
BuildOrderService.Subscribe(StateHasChanged);
economyService.Subscribe(StateHasChanged);
buildOrderService.Subscribe(StateHasChanged);
}
void IDisposable.Dispose()
{
EconomyService.Unsubscribe(StateHasChanged);
BuildOrderService.Unsubscribe(StateHasChanged);
economyService.Unsubscribe(StateHasChanged);
buildOrderService.Unsubscribe(StateHasChanged);
}
protected override bool ShouldRender()
@@ -1,8 +1,6 @@
@inject IJSRuntime jsRuntime;
@using System.Diagnostics
@implements IDisposable
@inject IKeyService keyService
@inject IKeyService keyService
@inject IBuildOrderService buildOrderService
@inject IImmortalSelectionService filterService
@@ -57,7 +55,6 @@
@hotkey.KeyText
@foreach (var entity in data.Values)
{
if (InvalidKey(entity, hotkey) || InvalidKeyGroup(entity, hotkey) || InvalidHoldSpace(entity))
{
continue;
@@ -67,7 +64,7 @@
{
continue;
}
if (InvalidVanguard(entity) || InvalidNonVanguard(entity))
{
continue;
@@ -75,7 +72,7 @@
var isVanguard = entity.VanguardAdded() != null;
var style = isVanguard ? "font-weight: bold;" : "";
if (buildOrderService.WillMeetRequirements(entity) == null)
{
style += "color:gray; font-style: italic;";
@@ -138,6 +135,7 @@
}
int completedTimeCount = 0;
void OnBuilderOrderChanged()
{
if (buildOrderService.UniqueCompletedTimes.Count != completedTimeCount)
@@ -146,13 +144,13 @@
StateHasChanged();
}
}
protected override bool ShouldRender()
{
#if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "HotKeyViewerComponent");
#endif
return true;
}
@@ -177,8 +175,8 @@
// Move to Filter Service
bool InvalidVanguard(EntityModel entity)
{
if (entity.VanguardAdded() != null
&& entity.VanguardAdded()?.ImmortalId != filterService.GetImmortalType()
if (entity.VanguardAdded() != null
&& entity.VanguardAdded()?.ImmortalId != filterService.GetImmortalType()
&& filterService.GetImmortalType() != ImmortalType.Any)
{
return true;
@@ -252,11 +250,10 @@
void OnKeyPressed()
{
string controlGroupWas = controlGroup;
string keyWas = key;
var controlGroupWas = controlGroup;
var keyWas = key;
if (keyService.GetAllPressedKeys().Contains("Z"))
{
controlGroup = "Z";
@@ -299,13 +296,11 @@
if (controlGroupWas != controlGroup || keyWas != key)
{
StateHasChanged();
StateHasChanged();
}
}
private void HandleClick()
{
var hotkey = keyService.GetHotkey();
@@ -327,16 +322,17 @@
var faction = filterService.GetFactionType();
var immortal = filterService.GetImmortalType();
EntityModel? entity = EntityModel.GetFrom(hotkey!, hotkeyGroup, isHoldSpace, faction, immortal);
var entity = EntityModel.GetFrom(hotkey!, hotkeyGroup, isHoldSpace, faction, immortal);
if (entity == null)
{
return;
}
if (buildOrderService.Add(entity, economyService, toastService))
{
economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval());
}
}
}
@@ -1,4 +1,4 @@
@inject IKeyService keyService
@inject IKeyService keyService
@inject IJSRuntime jsRuntime;
@@ -13,9 +13,10 @@
</div>
@code {
[Parameter]
public RenderFragment ChildContent { get; set; } = default!;
private void HandleKeyDown(KeyboardEventArgs e)
{
keyService.AddPressedKey(e.Key);
@@ -31,7 +32,7 @@
#if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "InputPanelComponent");
#endif
return true;
}
@@ -41,4 +42,5 @@
jsRuntime.InvokeVoidAsync("console.timeEnd", "InputPanelComponent");
#endif
}
}
@@ -0,0 +1,41 @@
@inject IJSRuntime jsRuntime;
@inject IBuildOrderService buildOrderService
@inject IEconomyService economyService
@inject IToastService toastService
@inject ITimingService timingService
<FormLayoutComponent>
<FormNumberComponent Max="600"
Min="0"
Value="@buildOrderService.BuildingInputDelay"
OnChange="@OnBuildingInputDelayChanged">
<FormLabelComponent>Building Input Delay</FormLabelComponent>
<FormInfoComponent>Add a input delay to constructing buildings for simulating worker movement and player micro.</FormInfoComponent>
</FormNumberComponent>
</FormLayoutComponent>
@code {
void OnBuildingInputDelayChanged(ChangeEventArgs changeEventArgs)
{
buildOrderService.BuildingInputDelay = int.Parse(changeEventArgs.Value!.ToString()!);
}
protected override bool ShouldRender()
{
#if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "TimingComponent");
#endif
return true;
}
protected override void OnAfterRender(bool firstRender)
{
#if DEBUG
jsRuntime.InvokeVoidAsync("console.timeEnd", "TimingComponent");
#endif
}
}
@@ -1,9 +1,10 @@
@inject IJSRuntime jsRuntime;
@inject IJSRuntime jsRuntime
@inject IEconomyService economyService
@inject IBuildOrderService buildOrderService
@implements IDisposable
<Virtualize Items="@EconomyService.GetOverTime()" Context="economyAtSecond" ItemSize="400" OverscanCount="4">
<Virtualize Items="@economyService.GetOverTime()" Context="economyAtSecond" ItemSize="400" OverscanCount="4">
<div style="display: grid; gap: 8px; grid-template-columns: 1fr 1fr;">
<div>
<div>
@@ -27,19 +28,19 @@
<br/>
</div>
<div>
@if (BuildOrderService.StartedOrders.TryGetValue(economyAtSecond.Interval, out var ordersAtTime))
@if (buildOrderService.StartedOrders.TryGetValue(economyAtSecond.Interval, out var ordersAtTime))
{
@foreach (var order in ordersAtTime)
{
<div>
Requested: @order.Info().Name
</div>
}
<div>
Requested: @order.Info().Name
</div>
}
}
@if (BuildOrderService.CompletedOrders.TryGetValue(economyAtSecond.Interval, out var ordersCompletedAtTime))
@if (buildOrderService.CompletedOrders.TryGetValue(economyAtSecond.Interval, out var ordersCompletedAtTime))
{
@foreach (var order in ordersCompletedAtTime)
{
@@ -55,30 +56,24 @@
@code {
[Inject]
IEconomyService EconomyService { get; set; } = default!;
[Inject]
IBuildOrderService BuildOrderService { get; set; } = default!;
protected override void OnInitialized()
{
EconomyService.Subscribe(StateHasChanged);
BuildOrderService.Subscribe(StateHasChanged);
economyService.Subscribe(StateHasChanged);
buildOrderService.Subscribe(StateHasChanged);
}
void IDisposable.Dispose()
{
EconomyService.Unsubscribe(StateHasChanged);
BuildOrderService.Unsubscribe(StateHasChanged);
economyService.Unsubscribe(StateHasChanged);
buildOrderService.Unsubscribe(StateHasChanged);
}
protected override bool ShouldRender()
{
#if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "TimelineComponent");
#endif
return true;
}
@@ -5,11 +5,8 @@
@inject IToastService toastService
@inject ITimingService timingService
<FormLayoutComponent>
<FormNumberComponent ReadOnly="true"
Max="600"
<FormNumberComponent Max="2048"
Min="0"
Value="@timingService.GetTiming()"
OnChange="@OnTimingChanged">
@@ -27,10 +24,17 @@
</FormLayoutComponent>
@code {
void OnTimingChanged(ChangeEventArgs changeEventArgs)
{
timingService.SetTiming(int.Parse(changeEventArgs.Value!.ToString()!));
economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval());
toastService.AddToast(new ToastModel()
{
Title = "Timing Interval",
Message = "Timing interval has changed.",
SeverityType = SeverityType.Success
});
}
void OnNameChanged(ChangeEventArgs changeEventArgs)
@@ -48,13 +52,13 @@
{
buildOrderService.SetNotes(changeEventArgs.Value!.ToString()!);
}
protected override bool ShouldRender()
{
#if DEBUG
jsRuntime.InvokeVoidAsync("console.time", "TimingComponent");
#endif
return true;
}
@@ -65,5 +69,4 @@
#endif
}
}