diff --git a/IGP/Pages/BuildCalculator/BuildCalculatorPage.razor b/IGP/Pages/BuildCalculator/BuildCalculatorPage.razor index 36a13fa..8990009 100644 --- a/IGP/Pages/BuildCalculator/BuildCalculatorPage.razor +++ b/IGP/Pages/BuildCalculator/BuildCalculatorPage.razor @@ -1,7 +1,4 @@ -@using Microsoft.Extensions.Localization -@implements IDisposable - -@layout PageLayout +@layout PageLayout @inject IStringLocalizer locale @@ -13,6 +10,9 @@ @inject ITimingService timingService @page "/build-calculator" +@using Microsoft.Extensions.Localization + +@implements IDisposable Build Calculator @@ -30,7 +30,7 @@
- + @@ -52,27 +52,32 @@
+ @if (true) + { +
+ + + +
+ } -
- - - -
- - -
- - - -
- - -
- - - -
+ @if (true) + { +
+ + + +
+ } + @if (true) + { +
+ + + +
+ }
@@ -82,25 +87,22 @@
- - @if (false) + @if (true) { -
- +
+ + + +
+ } + @if (true) + { +
+ + +
} - -
- - - -
- -
- - - -
@@ -218,29 +220,19 @@ @code { - protected override void OnInitialized() { - keyService.Subscribe(HandleClick); - filterService.Subscribe(StateHasChanged); - economyService.Subscribe(StateHasChanged); - timingService.Subscribe(HandleTimingChanged); economyService.Calculate(buildOrderService, timingService, 0); + + keyService.Subscribe(HandleClick); } - + void IDisposable.Dispose() { keyService.Unsubscribe(HandleClick); - filterService.Unsubscribe(StateHasChanged); - timingService.Unsubscribe(StateHasChanged); - economyService.Unsubscribe(StateHasChanged); - } - - private void HandleTimingChanged() - { - economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval()); } + private void HandleClick() { var hotkey = keyService.GetHotkey(); @@ -254,7 +246,6 @@ { buildOrderService.RemoveLast(); economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval()); - StateHasChanged(); return; } @@ -275,5 +266,4 @@ economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval()); } } - } \ No newline at end of file diff --git a/IGP/Pages/BuildCalculator/Parts/ArmyComponent.razor b/IGP/Pages/BuildCalculator/Parts/ArmyComponent.razor index 77445eb..2a7349b 100644 --- a/IGP/Pages/BuildCalculator/Parts/ArmyComponent.razor +++ b/IGP/Pages/BuildCalculator/Parts/ArmyComponent.razor @@ -1,4 +1,8 @@ -@implements IDisposable +@inject IJSRuntime jsRuntime; + +@inject IBuildOrderService BuildOrder + +@implements IDisposable @@ -22,8 +26,6 @@ @code { - [Inject] - public IBuildOrderService BuildOrder { get; set; } = default!; private int lastInterval; @@ -41,8 +43,29 @@ BuildOrder.Unsubscribe(OnBuildOrderChanged); } + protected override bool ShouldRender() + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.time", "ArmyComponent"); +#endif + return true; + } + + protected override void OnAfterRender(bool firstRender) + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.timeEnd", "ArmyComponent"); +#endif + } + void OnBuildOrderChanged() { + int armyCountWas = 0; + foreach (var army in armyCount) + { + armyCountWas += army.Value; + } + armyCount.Clear(); lastInterval = 0; @@ -68,7 +91,19 @@ } } - StateHasChanged(); + //TODO Better + int armyCountIs = 0; + foreach (var army in armyCount) + { + armyCountIs += army.Value; + } + + + if (armyCountWas != armyCountIs) + { + StateHasChanged(); + } + } } \ No newline at end of file diff --git a/IGP/Pages/BuildCalculator/Parts/BankComponent.razor b/IGP/Pages/BuildCalculator/Parts/BankComponent.razor index 84aa0c9..40c8c64 100644 --- a/IGP/Pages/BuildCalculator/Parts/BankComponent.razor +++ b/IGP/Pages/BuildCalculator/Parts/BankComponent.razor @@ -1,4 +1,9 @@ -@implements IDisposable +@inject IJSRuntime jsRuntime; + +@inject IEconomyService economyService + + +@implements IDisposable @@ -10,11 +15,6 @@ @economy.Ether - - - @economy.Pyre - - @supplyTaken / @supplyGranted (@(supplyGranted / 16)@(extraBuildings > 0 ? "+" + extraBuildings : "")) @@ -36,13 +36,27 @@ protected override void OnInitialized() { BuildOrderService.Subscribe(OnBuildOrderChanged); - EconomyService.Subscribe(OnBuildOrderChanged); + } + + protected override bool ShouldRender() + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.time", "BankComponent"); +#endif + + return true; + } + + protected override void OnAfterRender(bool firstRender) + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.timeEnd", "BankComponent"); +#endif } void IDisposable.Dispose() { BuildOrderService.Unsubscribe(OnBuildOrderChanged); - EconomyService.Subscribe(OnBuildOrderChanged); } void OnBuildOrderChanged() diff --git a/IGP/Pages/BuildCalculator/Parts/BuildOrderComponent.razor b/IGP/Pages/BuildCalculator/Parts/BuildOrderComponent.razor index 2241d86..8d0c7f2 100644 --- a/IGP/Pages/BuildCalculator/Parts/BuildOrderComponent.razor +++ b/IGP/Pages/BuildCalculator/Parts/BuildOrderComponent.razor @@ -1,4 +1,7 @@ -@inject IBuildOrderService buildOrderService +@inject IJSRuntime jsRuntime; + + +@inject IBuildOrderService buildOrderService @implements IDisposable @@ -21,4 +24,19 @@ buildOrderService.Unsubscribe(StateHasChanged); } + protected override bool ShouldRender() + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.time", "BuildOrderComponent"); +#endif + + return true; + } + + protected override void OnAfterRender(bool firstRender) + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.timeEnd", "BuildOrderComponent"); +#endif + } } \ No newline at end of file diff --git a/IGP/Pages/BuildCalculator/Parts/ChartComponent.razor b/IGP/Pages/BuildCalculator/Parts/ChartComponent.razor index b0068e4..daa68c0 100644 --- a/IGP/Pages/BuildCalculator/Parts/ChartComponent.razor +++ b/IGP/Pages/BuildCalculator/Parts/ChartComponent.razor @@ -1,27 +1,38 @@ -@implements IDisposable - -
- @foreach (var chart in charts) - { -
-
- @foreach (var point in chart.Points) - { -
+ @foreach (var chart in charts) + { +
+
+ @foreach (var point in chart.Points) + { +
-
+
+
-
- } + } +
-
- } -
- - - - - @highestAlloyPoint - - - @highestEtherPoint - - - + + + @highestAlloyPoint + + @highestEtherPoint - - - @highestArmyPoint - - - + + + @highestEtherPoint + + + + @highestArmyPoint + + -@code { - [Inject] - IEconomyService EconomyService { get; set; } = default!; +} - [Inject] - IBuildOrderService BuildOrderService { get; set; } = default!; +@code { private readonly int width = 250; @@ -70,23 +78,75 @@ float highestPyrePoint; float highestArmyPoint; + private Timer ageTimer = null!; + + protected override void OnInitialized() { - EconomyService.Subscribe(GenerateChart); - BuildOrderService.Subscribe(GenerateChart); + buildOrderService.Subscribe(OnBuilderOrderChanged); + + ageTimer = new Timer(3000); + ageTimer.Elapsed += OnAge!; + ageTimer.Enabled = true; + GenerateChart(); } + + int lastRequestedRefreshIndex = 0; + void OnAge(object? sender, ElapsedEventArgs elapsedEventArgs) + { + if (requestedRefreshIndex > 0) + { + if (requestedRefreshIndex == lastRequestedRefreshIndex) + { + GenerateChart(); + requestedRefreshIndex = 0; + lastRequestedRefreshIndex = 0; + } + + lastRequestedRefreshIndex = requestedRefreshIndex; + } + + ageTimer.Enabled = true; + } + + + void IDisposable.Dispose() { - EconomyService.Unsubscribe(GenerateChart); - BuildOrderService.Unsubscribe(GenerateChart); + buildOrderService.Unsubscribe(OnBuilderOrderChanged); } + + int requestedRefreshIndex = 0; + void OnBuilderOrderChanged() + { + requestedRefreshIndex++; + StateHasChanged(); + } + + + protected override bool ShouldRender() + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.time", "ChartComponent"); +#endif + + return true; + } + + protected override void OnAfterRender(bool firstRender) + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.timeEnd", "ChartComponent"); +#endif + } + void GenerateChart() { - var economyOverTime = EconomyService.GetOverTime(); + var economyOverTime = economyService.GetOverTime(); charts.Clear(); @@ -127,7 +187,7 @@ for (var interval = 0; interval < economyOverTime.Count(); interval++) { - var army = from unit in BuildOrderService.GetCompletedBefore(interval) + var army = from unit in buildOrderService.GetCompletedBefore(interval) where unit.EntityType == EntityType.Army select unit; diff --git a/IGP/Pages/BuildCalculator/Parts/EntityClickViewComponent.razor b/IGP/Pages/BuildCalculator/Parts/EntityClickViewComponent.razor index d49386a..4912745 100644 --- a/IGP/Pages/BuildCalculator/Parts/EntityClickViewComponent.razor +++ b/IGP/Pages/BuildCalculator/Parts/EntityClickViewComponent.razor @@ -1,4 +1,11 @@ -@implements IDisposable +@inject IJSRuntime jsRuntime; + + + @inject IKeyService keyService + @inject IImmortalSelectionService filterService + @inject IBuildOrderService buildOrderService + +@implements IDisposable @if (entity != null) { @@ -20,48 +27,45 @@ private EntityModel? entity = default!; private string viewType = "Detailed"; - [Inject] - IKeyService KeyService { get; set; } = default!; - - [Inject] - IImmortalSelectionService FilterService { get; set; } = default!; - - [Inject] - IBuildOrderService BuildOrderService { get; set; } = default!; - protected override void OnInitialized() { - KeyService.Subscribe(HandleClick); - BuildOrderService.Subscribe(OnBuildOrderChanged); + keyService.Subscribe(HandleClick); } void IDisposable.Dispose() { - KeyService.Unsubscribe(HandleClick); - BuildOrderService.Unsubscribe(OnBuildOrderChanged); + keyService.Unsubscribe(HandleClick); } + protected override bool ShouldRender() + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.time", "EntityClickViewComponent"); +#endif + return true; + } - protected void HandleClick() + protected override void OnAfterRender(bool firstRender) { - var hotkey = KeyService.GetHotkey(); - var hotkeyGroup = KeyService.GetHotkeyGroup(); - var isHoldSpace = KeyService.IsHoldingSpace(); - var faction = FilterService.GetFactionType(); - var immortal = FilterService.GetImmortalType(); +#if DEBUG + jsRuntime.InvokeVoidAsync("console.timeEnd", "EntityClickViewComponent"); +#endif + } + + private void HandleClick() + { + var hotkey = keyService.GetHotkey(); + var hotkeyGroup = keyService.GetHotkeyGroup(); + var isHoldSpace = keyService.IsHoldingSpace(); + var faction = filterService.GetFactionType(); + var immortal = filterService.GetImmortalType(); var foundEntity = EntityModel.GetFrom(hotkey!, hotkeyGroup, isHoldSpace, faction, immortal); - if (foundEntity != null) + if (foundEntity != null && entity != foundEntity) { entity = foundEntity; StateHasChanged(); } } - - void OnBuildOrderChanged() - { - StateHasChanged(); - } - } \ No newline at end of file diff --git a/IGP/Pages/BuildCalculator/Parts/FilterComponent.razor b/IGP/Pages/BuildCalculator/Parts/FilterComponent.razor index ae229e7..e1a4d21 100644 --- a/IGP/Pages/BuildCalculator/Parts/FilterComponent.razor +++ b/IGP/Pages/BuildCalculator/Parts/FilterComponent.razor @@ -1,4 +1,6 @@ - +@inject IJSRuntime jsRuntime; + + Faction @@ -39,4 +41,19 @@ FilterService.SelectImmortalType(e.Value!.ToString()!); } + protected override bool ShouldRender() + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.time", "FilterComponent"); +#endif + + return true; + } + + protected override void OnAfterRender(bool firstRender) + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.timeEnd", "FilterComponent"); +#endif + } } \ No newline at end of file diff --git a/IGP/Pages/BuildCalculator/Parts/HighlightsComponent.razor b/IGP/Pages/BuildCalculator/Parts/HighlightsComponent.razor index aef1294..d2437cd 100644 --- a/IGP/Pages/BuildCalculator/Parts/HighlightsComponent.razor +++ b/IGP/Pages/BuildCalculator/Parts/HighlightsComponent.razor @@ -1,40 +1,37 @@ -@implements IDisposable +@inject IJSRuntime jsRuntime; + + +@implements IDisposable
Requested
- - @for (var i = TimingService.GetTiming() - 1; i >= 0; i--) - { - @foreach (var order in BuildOrderService.GetOrdersAt(i)) - { - if (order.EntityType == EntityType.Worker) - { - continue; + + @foreach (var ordersAtTime in BuildOrderService.StartedOrders.Reverse()) { + foreach (var order in ordersAtTime.Value) + { +
+ + @ordersAtTime.Key | T @Interval.ToTime(ordersAtTime.Key) +
+
+ @order.Info().Name +
+
+ } } -
- @i | T @Interval.ToTime(i) -
-
- @order.Info().Name -
-
- } - } +
Finished
- - @for (var i = TimingService.GetTiming() - 1; i >= 0; i--) + + @foreach (var ordersAtTime in BuildOrderService.CompletedOrders.Reverse()) { - @foreach (var order in BuildOrderService.GetCompletedAt(i)) + foreach (var order in ordersAtTime.Value) { - if (order.EntityType == EntityType.Worker) - { - continue; - }
- @i | T @Interval.ToTime(i) + + @ordersAtTime.Key | T @Interval.ToTime(ordersAtTime.Key)
@order.Info().Name @@ -79,5 +76,21 @@ EconomyService.Unsubscribe(StateHasChanged); BuildOrderService.Unsubscribe(StateHasChanged); } + + protected override bool ShouldRender() + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.time", "HighlightsComponent"); +#endif + + return true; + } + + protected override void OnAfterRender(bool firstRender) + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.timeEnd", "HighlightsComponent"); +#endif + } } \ No newline at end of file diff --git a/IGP/Pages/BuildCalculator/Parts/HotkeyViewerComponent.razor b/IGP/Pages/BuildCalculator/Parts/HotkeyViewerComponent.razor index 8b3feb2..204b29a 100644 --- a/IGP/Pages/BuildCalculator/Parts/HotkeyViewerComponent.razor +++ b/IGP/Pages/BuildCalculator/Parts/HotkeyViewerComponent.razor @@ -1,4 +1,14 @@ -@implements IDisposable +@inject IJSRuntime jsRuntime; + +@implements IDisposable +@inject IKeyService keyService +@inject IBuildOrderService buildOrderService +@inject IImmortalSelectionService filterService + +@inject IEconomyService economyService +@inject ITimingService timingService +@inject IToastService toastService +
@@ -9,7 +19,7 @@ continue; } - var color = hotkey.KeyText.Equals("SPACE") && KeyService.IsHoldingSpace() || KeyService.GetAllPressedKeys().Contains(hotkey.KeyText) + var color = hotkey.KeyText.Equals("SPACE") && keyService.IsHoldingSpace() || keyService.GetAllPressedKeys().Contains(hotkey.KeyText) ? "#0a0f12" : hotkey.GetColor(); var x = hotkey.PositionX * Size; @@ -25,7 +35,7 @@ border = "5px solid green"; } - if (hotkey.KeyText.Equals("SPACE") && KeyService.IsHoldingSpace()) + if (hotkey.KeyText.Equals("SPACE") && keyService.IsHoldingSpace()) { border = "5px solid green"; } @@ -37,7 +47,7 @@ width: 0px; height: 0px;"> -
{ if (hotkey.KeyText.Equals(HotKeyType.SPACE.ToString())) { if (keyService.IsHoldingSpace()) { keyService.RemovePressedKey(hotkey.KeyText); } else { keyService.AddPressedKey(hotkey.KeyText); } } else { keyService.AddPressedKey(hotkey.KeyText); keyService.RemovePressedKey(hotkey.KeyText); }}" style="background-color:@color; border: @border; width: @Size.ToString()px; height: @Size.ToString()px; @@ -46,7 +56,7 @@ @hotkey.KeyText @foreach (var entity in data.Values) { - if (!BuildOrderService.MeetsRequirements(entity, 9000)) + if (buildOrderService.WillMeetRequirements(entity) == null) { continue; } @@ -97,15 +107,6 @@ [Parameter] public int Size { get; set; } = 100; - [Inject] - public IKeyService KeyService { get; set; } = default!; - - [Inject] - public IBuildOrderService BuildOrderService { get; set; } = default!; - - [Inject] - public IImmortalSelectionService FilterService { get; set; } = default!; - readonly Dictionary data = EntityModel.GetDictionary(); readonly List hotkeys = HotkeyModel.GetAll(); @@ -116,20 +117,48 @@ { base.OnInitialized(); - KeyService.Subscribe(OnKeyPressed); - FilterService.Subscribe(StateHasChanged); + keyService.Subscribe(OnKeyPressed); + filterService.Subscribe(StateHasChanged); + buildOrderService.Subscribe(OnBuilderOrderChanged); } void IDisposable.Dispose() { - KeyService.Unsubscribe(OnKeyPressed); - FilterService.Unsubscribe(StateHasChanged); + keyService.Unsubscribe(OnKeyPressed); + filterService.Unsubscribe(StateHasChanged); + buildOrderService.Unsubscribe(OnBuilderOrderChanged); + } + + int completedTimeCount = 0; + void OnBuilderOrderChanged() + { + if (buildOrderService.UniqueCompletedTimes.Count != completedTimeCount) + { + completedTimeCount = buildOrderService.UniqueCompletedTimes.Count; + StateHasChanged(); + } + } + + protected override bool ShouldRender() + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.time", "HotKeyViewerComponent"); +#endif + + return true; + } + + protected override void OnAfterRender(bool firstRender) + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.timeEnd", "HotKeyViewerComponent"); +#endif } // Move to Filter Service bool InvalidFaction(EntityModel entity) { - if (entity.Faction() != null && entity.Faction()?.Faction != FilterService.GetFactionType() && FilterService.GetFactionType() != FactionType.Any) + if (entity.Faction() != null && entity.Faction()?.Faction != filterService.GetFactionType() && filterService.GetFactionType() != FactionType.Any) { return true; } @@ -140,7 +169,7 @@ // Move to Filter Service bool InvalidVanguard(EntityModel entity) { - if (entity.VanguardAdded() != null && entity.VanguardAdded()?.ImmortalId != FilterService.GetImmortalType() && FilterService.GetImmortalType() != ImmortalType.Any) + if (entity.VanguardAdded() != null && entity.VanguardAdded()?.ImmortalId != filterService.GetImmortalType() && filterService.GetImmortalType() != ImmortalType.Any) { return true; } @@ -156,7 +185,7 @@ var isReplaced = false; foreach (var replaced in entity.Replaceds()) { - if (FilterService.GetImmortalType() == replaced.ImmortalId) + if (filterService.GetImmortalType() == replaced.ImmortalId) { isReplaced = true; break; @@ -171,11 +200,6 @@ return false; } - bool InvalidRequirements(EntityModel entity) - { - return !BuildOrderService.MeetsRequirements(entity, 9000); - } - bool InvalidKey(EntityModel entity, HotkeyModel key) { if (entity.Hotkey()?.Hotkey == key.KeyText) @@ -215,7 +239,7 @@ bool InvalidHoldSpace(EntityModel entity) { - if (entity.Hotkey()?.HoldSpace == KeyService.IsHoldingSpace()) + if (entity.Hotkey()?.HoldSpace == keyService.IsHoldingSpace()) { return false; } @@ -224,47 +248,93 @@ void OnKeyPressed() { - if (KeyService.GetAllPressedKeys().Contains("Z")) + + string controlGroupWas = _controlGroup; + string keyWas = _key; + + + if (keyService.GetAllPressedKeys().Contains("Z")) { _controlGroup = "Z"; } - if (KeyService.GetAllPressedKeys().Contains("TAB")) + if (keyService.GetAllPressedKeys().Contains("TAB")) { _controlGroup = "TAB"; } - if (KeyService.GetAllPressedKeys().Contains("C")) + if (keyService.GetAllPressedKeys().Contains("C")) { _controlGroup = "C"; } - if (KeyService.GetAllPressedKeys().Contains("D")) + if (keyService.GetAllPressedKeys().Contains("D")) { _controlGroup = "D"; } - if (KeyService.GetAllPressedKeys().Contains("1")) + if (keyService.GetAllPressedKeys().Contains("1")) { _controlGroup = "1"; } //TODO This could be better. Duplicated code - if (KeyService.GetAllPressedKeys().Contains("2")) + if (keyService.GetAllPressedKeys().Contains("2")) { _controlGroup = "2"; } - if (KeyService.GetAllPressedKeys().Contains("SHIFT")) + if (keyService.GetAllPressedKeys().Contains("SHIFT")) { _controlGroup = "SHIFT"; } - if (KeyService.GetAllPressedKeys().Contains("CONTROL")) + if (keyService.GetAllPressedKeys().Contains("CONTROL")) { _controlGroup = "CONTROL"; } - if (KeyService.GetAllPressedKeys().Count > 0) + if (keyService.GetAllPressedKeys().Count > 0) { - _key = KeyService.GetAllPressedKeys().First(); + _key = keyService.GetAllPressedKeys().First(); } - StateHasChanged(); +// HandleClick(); + + if (controlGroupWas != _controlGroup || keyWas != _key) + { + + StateHasChanged(); + } + } + + + private void HandleClick() + { + var hotkey = keyService.GetHotkey(); + + if (hotkey == "") + { + return; + } + + if (hotkey == "`") + { + buildOrderService.RemoveLast(); + economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval()); + return; + } + + var hotkeyGroup = keyService.GetHotkeyGroup(); + var isHoldSpace = keyService.IsHoldingSpace(); + var faction = filterService.GetFactionType(); + var immortal = filterService.GetImmortalType(); + EntityModel? entity = EntityModel.GetFrom(hotkey!, hotkeyGroup, isHoldSpace, faction, immortal); + + if (entity == null) + { + return; + } + + if (buildOrderService.Add(entity, economyService, toastService)) + { + economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval()); + } + } } \ No newline at end of file diff --git a/IGP/Pages/BuildCalculator/Parts/InputPanelComponent.razor b/IGP/Pages/BuildCalculator/Parts/InputPanelComponent.razor index 5b856a3..086da80 100644 --- a/IGP/Pages/BuildCalculator/Parts/InputPanelComponent.razor +++ b/IGP/Pages/BuildCalculator/Parts/InputPanelComponent.razor @@ -1,4 +1,9 @@ -
@code { - [Parameter] public RenderFragment ChildContent { get; set; } = default!; - - [Inject] - public IKeyService KeyService { get; set; } = default!; - + private void HandleKeyDown(KeyboardEventArgs e) { - KeyService.AddPressedKey(e.Key); + keyService.AddPressedKey(e.Key); } private void HandleKeyUp(KeyboardEventArgs e) { - KeyService.RemovePressedKey(e.Key); + keyService.RemovePressedKey(e.Key); } + protected override bool ShouldRender() + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.time", "InputPanelComponent"); +#endif + + return true; + } + + protected override void OnAfterRender(bool firstRender) + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.timeEnd", "InputPanelComponent"); +#endif + } } \ No newline at end of file diff --git a/IGP/Pages/BuildCalculator/Parts/TimelineComponent.razor b/IGP/Pages/BuildCalculator/Parts/TimelineComponent.razor index 97ae903..fde5be4 100644 --- a/IGP/Pages/BuildCalculator/Parts/TimelineComponent.razor +++ b/IGP/Pages/BuildCalculator/Parts/TimelineComponent.razor @@ -1,4 +1,7 @@ -@implements IDisposable +@inject IJSRuntime jsRuntime; + + +@implements IDisposable
@@ -24,17 +27,26 @@
- @foreach (var order in BuildOrderService.GetOrdersAt(economyAtSecond.Interval)) + + @if (BuildOrderService.StartedOrders.TryGetValue(economyAtSecond.Interval, out var ordersAtTime)) { -
- Requested: @order.Info().Name -
+ @foreach (var order in ordersAtTime) + { +
+ Requested: @order.Info().Name +
+} } - @foreach (var order in BuildOrderService.GetCompletedAt(economyAtSecond.Interval)) + + + @if (BuildOrderService.CompletedOrders.TryGetValue(economyAtSecond.Interval, out var ordersCompletedAtTime)) { -
- New: @order.Info().Name -
+ @foreach (var order in ordersCompletedAtTime) + { +
+ New: @order.Info().Name +
+ } }
@@ -60,5 +72,21 @@ EconomyService.Unsubscribe(StateHasChanged); BuildOrderService.Unsubscribe(StateHasChanged); } + + protected override bool ShouldRender() + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.time", "TimelineComponent"); +#endif + + return true; + } + + protected override void OnAfterRender(bool firstRender) + { +#if DEBUG + jsRuntime.InvokeVoidAsync("console.timeEnd", "TimelineComponent"); +#endif + } } \ No newline at end of file diff --git a/IGP/Pages/BuildCalculator/Parts/TimingComponent.razor b/IGP/Pages/BuildCalculator/Parts/TimingComponent.razor index 86d59ff..25d7227 100644 --- a/IGP/Pages/BuildCalculator/Parts/TimingComponent.razor +++ b/IGP/Pages/BuildCalculator/Parts/TimingComponent.razor @@ -1,55 +1,69 @@ - +@inject IJSRuntime jsRuntime; + +@inject IBuildOrderService buildOrderService +@inject IEconomyService economyService +@inject IToastService toastService +@inject ITimingService timingService + + + + Timing interval Altering the time interval is currently disabled. - + - + @code { - - [Inject] - public ITimingService TimingService { get; set; } = default!; - - [Inject] - public IBuildOrderService BuildOrderService { get; set; } = default!; - - void OnTimingChanged(ChangeEventArgs changeEventArgs) { - TimingService.SetTiming(int.Parse(changeEventArgs.Value!.ToString()!)); - } - - void OnTimingChanged(int value) - { - TimingService.SetTiming(value); + timingService.SetTiming(int.Parse(changeEventArgs.Value!.ToString()!)); + economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval()); } void OnNameChanged(ChangeEventArgs changeEventArgs) { - BuildOrderService.SetName(changeEventArgs.Value!.ToString()!); + buildOrderService.SetName(changeEventArgs.Value!.ToString()!); } void OnColorChanged(ChangeEventArgs changeEventArgs) { - BuildOrderService.SetColor(changeEventArgs.Value!.ToString()!); + buildOrderService.SetColor(changeEventArgs.Value!.ToString()!); } void OnNotesChanged(ChangeEventArgs changeEventArgs) { - BuildOrderService.SetNotes(changeEventArgs.Value!.ToString()!); + buildOrderService.SetNotes(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 + } + + } \ No newline at end of file diff --git a/IGP/Program.cs b/IGP/Program.cs index 611e216..780c7be 100644 --- a/IGP/Program.cs +++ b/IGP/Program.cs @@ -29,7 +29,6 @@ builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); -builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); diff --git a/Model/BuildOrders/BuildOrderModel.cs b/Model/BuildOrders/BuildOrderModel.cs index 6d198d2..1ff60cf 100644 --- a/Model/BuildOrders/BuildOrderModel.cs +++ b/Model/BuildOrders/BuildOrderModel.cs @@ -9,6 +9,8 @@ public class BuildOrderModel { public string Name { get; set; } = ""; public string Color { get; set; } = "red"; + + public int CurrentSupplyUsed { get; set; } = 0; public Dictionary> StartedOrders { get; set; } = new() { @@ -33,28 +35,28 @@ public class BuildOrderModel } } }; + + public Dictionary UniqueCompletedTimes { get; set; } = new() + { + { + DataType.STARTING_Bastion, 0 + } + }; + + + + public Dictionary SupplyCountTimes { get; set; } = new() + { + { + 0, 0 + } + }; public string Notes { get; set; } = @""; public List BuildTypes { get; set; } = new(); - public List GetOrdersAt(int interval) - { - return (from ordersAtTime in StartedOrders - from orders in ordersAtTime.Value - where ordersAtTime.Key == interval - select orders).ToList(); - } - - public List GetCompletedAt(int interval) - { - return (from ordersAtTime in StartedOrders - from orders in ordersAtTime.Value - where ordersAtTime.Key + (orders.Production() == null ? 0 : orders.Production().BuildTime) == interval - select orders).ToList(); - } - public List GetCompletedBefore(int interval) { return (from ordersAtTime in StartedOrders diff --git a/Model/Economy/EconomyOverTimeModel.cs b/Model/Economy/EconomyOverTimeModel.cs index c7bfcf7..fda9467 100644 --- a/Model/Economy/EconomyOverTimeModel.cs +++ b/Model/Economy/EconomyOverTimeModel.cs @@ -99,8 +99,8 @@ public class EconomyOverTimeModel } // Remove Funds from Build Order - var ordersAtTime = buildOrder.GetOrdersAt(interval); - + if (buildOrder.StartedOrders.TryGetValue(interval, out var ordersAtTime)) + { foreach (var order in ordersAtTime) { var foundEntity = EntityModel.GetDictionary()[order.DataType]; @@ -115,16 +115,20 @@ public class EconomyOverTimeModel if (production.RequiresWorker) economyAtSecond.BusyWorkerCount += 1; } } + + } // Handle new entities - var completedAtInterval = buildOrder.GetCompletedAt(interval); - foreach (var newEntity in completedAtInterval) + if (buildOrder.StartedOrders.TryGetValue(interval, out var ordersCompletedAtTime)) { - var harvest = newEntity; - if (harvest != null) economyAtSecond.Harvesters.Add(harvest); + foreach (var newEntity in ordersCompletedAtTime) + { + var harvest = newEntity; + if (harvest != null) economyAtSecond.Harvesters.Add(harvest); - var production = newEntity.Production(); - if (production != null && production.RequiresWorker) economyAtSecond.BusyWorkerCount -= 1; + var production = newEntity.Production(); + if (production != null && production.RequiresWorker) economyAtSecond.BusyWorkerCount -= 1; + } } } } diff --git a/Model/Entity/Data/DATA.cs b/Model/Entity/Data/DATA.cs index 4998cc4..641c442 100644 --- a/Model/Entity/Data/DATA.cs +++ b/Model/Entity/Data/DATA.cs @@ -1435,10 +1435,7 @@ public class DATA .AddPart(new EntityHotkeyModel { Hotkey = "Q", HotkeyGroup = "TAB" }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityProductionModel { Alloy = 100, Ether = 100, BuildTime = 100 }) - .AddPart(new EntityRequirementModel - { - Requirement = RequirementType.Production_Building - }) + }, { @@ -1465,10 +1462,7 @@ public class DATA .AddPart(new EntityHotkeyModel { Hotkey = "Q", HotkeyGroup = "TAB", HoldSpace = true}) .AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityProductionModel { Alloy = 100, Ether = 100, BuildTime = 43 }) - .AddPart(new EntityRequirementModel - { - Requirement = RequirementType.Production_Building - }) + }, { @@ -1482,10 +1476,7 @@ public class DATA .AddPart(new EntityHotkeyModel { Hotkey = "Q", HotkeyGroup = "TAB" }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityProductionModel { Alloy = 50, Ether = 100, BuildTime = 60 }) - .AddPart(new EntityRequirementModel - { - Requirement = RequirementType.Production_Building - }) + }, { DataType.UPGRADE_RelicOfTheWrathfulGaze, @@ -1512,7 +1503,7 @@ public class DATA .AddPart(new EntityHotkeyModel { Hotkey = "W", HotkeyGroup = "TAB" }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityProductionModel { Alloy = 50, Ether = 75, BuildTime = 55 }) - .AddPart(new EntityRequirementModel { Requirement = RequirementType.Production_Building }) + .AddPart(new EntityRequirementModel { Id = DataType.BUILDING_Reliquary, Requirement = RequirementType.Production_Building }) }, { DataType.UPGRADE_ZephyrRange, @@ -1525,7 +1516,7 @@ public class DATA .AddPart(new EntityHotkeyModel { Hotkey = "E", HotkeyGroup = "TAB" }) .AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityProductionModel { Alloy = 150, Ether = 100, BuildTime = 43 }) - .AddPart(new EntityRequirementModel { Requirement = RequirementType.Production_Building }) + .AddPart(new EntityRequirementModel { Id = DataType.UPGRADE_ZephyrRange, Requirement = RequirementType.Production_Building }) .AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_WindStep }) .AddPart(new EntityIdUpgradeModel { Id = DataType.UPGRADE_ZephyrRange }) }, @@ -1559,6 +1550,7 @@ public class DATA .AddPart(new EntityProductionModel { Alloy = 100, Ether = 100, BuildTime = 43 }) .AddPart(new EntityRequirementModel { + Id = DataType.BUILDING_EyeOfAros, Requirement = RequirementType.Production_Building }) }, @@ -2632,7 +2624,7 @@ public class DATA .AddPart(new EntityFactionModel { Faction = FactionType.Aru }) .AddPart(new EntityProductionModel { Alloy = 100, BuildTime = 25 }) .AddPart(new EntitySupplyModel { Takes = 6 }) - .AddPart(new EntityRequirementModel { Requirement = RequirementType.Morph }) + .AddPart(new EntityRequirementModel { Id = DataType.UNIT_RedSeer, Requirement = RequirementType.Morph }) .AddPart(new EntityVitalityModel { Health = 200, DefenseLayer = 60, Armor = ArmorType.Heavy }) .AddPart(new EntityMovementModel { Speed = 210, Movement = MovementType.Ground }) .AddPart(new EntityWeaponModel @@ -2853,6 +2845,7 @@ public class DATA .AddPart(new EntityFactionModel { Faction = FactionType.QRath }) .AddPart(new EntityRequirementModel { + Id = DataType.BUILDING_Acropolis, Requirement = RequirementType.Morph }) .AddPart(new EntityProductionModel { Alloy = 75, BuildTime = 20, RequiresWorker = false }) @@ -3245,7 +3238,9 @@ public class DATA .AddPart(new EntityInfoModel { Name = "Omnivore", Descriptive = DescriptiveType.Upgrade }) .AddPart(new EntityHotkeyModel { Hotkey = "Q", HotkeyGroup = "SHIFT" }) .AddPart(new EntityFactionModel { Faction = FactionType.Aru }) - .AddPart(new EntityRequirementModel { Requirement = RequirementType.Morph }) + .AddPart(new EntityRequirementModel { + Id = DataType.DEFENSE_Aerovore, + Requirement = RequirementType.Morph }) .AddPart(new EntityProductionModel { Alloy = 50, BuildTime = 18, RequiresWorker = false }) .AddPart(new EntityVitalityModel { Health = 400, DefenseLayer = 50, Armor = ArmorType.Heavy, IsStructure = true }) diff --git a/Model/Entity/EntityModel.cs b/Model/Entity/EntityModel.cs index 8096fbb..bf8b3e9 100644 --- a/Model/Entity/EntityModel.cs +++ b/Model/Entity/EntityModel.cs @@ -165,7 +165,7 @@ public class EntityModel } - public EntitySupplyModel Supply() + public EntitySupplyModel? Supply() { return ((EntitySupplyModel)EntityParts.Find(x => x.GetType() == typeof(EntitySupplyModel))!)!; } diff --git a/Services/IServices.cs b/Services/IServices.cs index 67a9877..29e3b09 100644 --- a/Services/IServices.cs +++ b/Services/IServices.cs @@ -244,18 +244,15 @@ public interface IMemoryTesterService { public void Unsubscribe(MemoryAction memoryAction); } -public interface IGameLogicService -{ - public bool Add(EntityModel entity, int atInterval); - public int MeetsRequirements(EntityModel entity, int interval); - public int MeetsAlloy(EntityModel entity, int interval); - public int MeetsEther(EntityModel entity, int interval); - public int MeetsPyre(EntityModel entity, int interval); - public int MeetsSupply(EntityModel entity, int interval); - public int MeetsTrainingQueue(EntityModel entity, int interval); -} - public interface IBuildOrderService { + + public Dictionary> StartedOrders { get; } + public Dictionary> CompletedOrders { get; } + public Dictionary UniqueCompletedTimes { get; } + + public Dictionary SupplyCountTimes { get; } + + public bool Add(EntityModel entity, IEconomyService withEconomy, IToastService toastService); public void Add(EntityModel entity, int atInterval); @@ -268,10 +265,9 @@ public interface IBuildOrderService { public void SetColor(string Color); public string GetColor(); - public bool MeetsRequirements(EntityModel entity, int interval); + public int? WillMeetRequirements(EntityModel entity); + public int? WillMeetSupply(EntityModel entity); public Dictionary> GetOrders(); - public List GetOrdersAt(int interval); - public List GetCompletedAt(int interval); public List GetCompletedBefore(int interval); public List GetHarvestersCompletedBefore(int interval); diff --git a/Services/Immortal/BuildOrderService.cs b/Services/Immortal/BuildOrderService.cs index d8f731e..b81fad3 100644 --- a/Services/Immortal/BuildOrderService.cs +++ b/Services/Immortal/BuildOrderService.cs @@ -3,6 +3,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using Model.BuildOrders; using Model.Entity; +using Model.Entity.Data; using Model.Feedback; using Model.Types; using YamlDotNet.Serialization; @@ -15,6 +16,11 @@ public class BuildOrderService : IBuildOrderService private readonly int HumanMicro = 2; private int lastInterval; + public Dictionary> StartedOrders => buildOrder.StartedOrders; + public Dictionary> CompletedOrders => buildOrder.CompletedOrders; + public Dictionary UniqueCompletedTimes => buildOrder.UniqueCompletedTimes; + public Dictionary SupplyCountTimes => buildOrder.SupplyCountTimes; + public int GetLastRequestInterval() { return lastInterval; @@ -38,111 +44,123 @@ public class BuildOrderService : IBuildOrderService public void Add(EntityModel entity, int atInterval) { if (!buildOrder.StartedOrders.ContainsKey(atInterval)) - { - buildOrder.StartedOrders.Add(atInterval, new List { }); - } + buildOrder.StartedOrders.Add(atInterval, new List()); var production = entity.Production(); var completedTime = atInterval; - if (production != null) - { - completedTime += production.BuildTime; - } - - if (!buildOrder.CompletedOrders.ContainsKey(atInterval)) - { - buildOrder.CompletedOrders.Add(completedTime, new List { }); - } + if (production != null) completedTime += production.BuildTime; + + if (!buildOrder.CompletedOrders.ContainsKey(completedTime)) + buildOrder.CompletedOrders.Add(completedTime, new List()); + + var supply = entity.Supply(); + buildOrder.StartedOrders[atInterval].Add(entity.Clone()); buildOrder.CompletedOrders[completedTime].Add(entity.Clone()); - + + if (!buildOrder.UniqueCompletedTimes.ContainsKey(entity.DataType)) + buildOrder.UniqueCompletedTimes.Add(entity.DataType, atInterval); + + if (supply != null) + { + if (!supply.Takes.Equals(0)) buildOrder.CurrentSupplyUsed += supply.Takes; + if (!supply.Grants.Equals(0)) + buildOrder.SupplyCountTimes.Add(buildOrder.SupplyCountTimes.Last().Key + supply.Grants, completedTime); + } + + if (atInterval > lastInterval) lastInterval = atInterval; + + NotifyDataChanged(); } - public bool Add(EntityModel entity, IEconomyService withEconomy, IToastService withToasts) + + public int? WillMeetRequirements(EntityModel entity) { - var production = entity.Production(); + var requirements = entity.Requirements(); + + if (requirements.Count == 0) return 0; - if (production != null) + var metTime = 0; + foreach (var requiredEntity in requirements) { - for (var interval = lastInterval; interval < withEconomy.GetOverTime().Count; interval++) + if (buildOrder.UniqueCompletedTimes.TryGetValue(requiredEntity.Id, out var completedTime)) { - var economyAtSecond = withEconomy.GetOverTime()[interval]; - if (economyAtSecond.Alloy >= production.Alloy && economyAtSecond.Ether >= production.Ether && - economyAtSecond.Pyre >= production.Pyre) - { - if (!MeetsSupply(entity)) - { - withToasts.AddToast(new ToastModel - { - Title = "Supply Cap Reached", Message = "Build more supply!", - SeverityType = SeverityType.Error - }); - return false; - } - - if (!MeetsRequirements(entity, interval)) continue; - - //Account for human Micro delay - interval += HumanMicro; - - if (!buildOrder.StartedOrders.ContainsKey(interval)) - buildOrder.StartedOrders.Add(interval, new List { entity.Clone() }); - else - buildOrder.StartedOrders[interval].Add(entity.Clone()); - - lastInterval = interval; - - NotifyDataChanged(); - return true; - } - - if (interval + 1 == withEconomy.GetOverTime().Count) - { - if (economyAtSecond.Ether < production.Ether) - withToasts.AddToast(new ToastModel - { - Title = "Not Enough Ether", Message = "Build more ether extractors!", - SeverityType = SeverityType.Error - }); - } + if (completedTime > metTime) metTime = completedTime; + } + else + { + return null; } - } - else - { - Add(entity, 0); - NotifyDataChanged(); - return true; } - return false; + return metTime; } - public void RemoveLast() + public int? WillMeetSupply(EntityModel entity) + { + var supply = entity.Supply(); + + if (supply == null || supply.Takes.Equals(0)) return 0; + + foreach (var supplyAtTime in buildOrder.SupplyCountTimes) + if (supply.Takes + buildOrder.CurrentSupplyUsed < supplyAtTime.Key) + return supplyAtTime.Value; + + return null; + } + + + public bool Add(EntityModel entity, IEconomyService withEconomy, IToastService withToasts) { - EntityModel entityRemoved = null!; + var atInterval = lastInterval; + + if (!HandleSupply(entity, withToasts, ref atInterval)) return false; + if (!HandleRequirements(entity, withToasts, ref atInterval)) return false; + if (!HandleEconomy(entity, withEconomy, withToasts, ref atInterval)) return false; + + Add(entity, atInterval); + return true; + } + public void RemoveLast() + { + if (buildOrder.StartedOrders.Keys.Count > 1) { - var last = buildOrder.StartedOrders.Keys.Last(); + var lastStarted = buildOrder.StartedOrders.Keys.Last(); + var lastCompleted = buildOrder.CompletedOrders.Keys.Last(); + + EntityModel entityRemoved = default!; - if (buildOrder.StartedOrders[last].Count > 0) + if (buildOrder.StartedOrders[lastStarted].Count > 0) { - entityRemoved = buildOrder.StartedOrders[last].Last(); - buildOrder.StartedOrders[last].Remove(buildOrder.StartedOrders[last].Last()); + entityRemoved = buildOrder.StartedOrders[lastStarted].Last(); + buildOrder.StartedOrders[lastStarted].Remove(buildOrder.StartedOrders[lastStarted].Last()); + buildOrder.CompletedOrders[lastCompleted].Remove(buildOrder.CompletedOrders[lastCompleted].Last()); } - if (buildOrder.StartedOrders[last].Count == 0) buildOrder.StartedOrders.Remove(last); + if (buildOrder.StartedOrders[lastStarted].Count == 0) buildOrder.StartedOrders.Remove(lastStarted); + if (buildOrder.CompletedOrders[lastCompleted].Count == 0) buildOrder.CompletedOrders.Remove(lastCompleted); if (buildOrder.StartedOrders.Keys.Count > 0) - lastInterval = buildOrder.StartedOrders.Keys.Last() + 1; + lastInterval = buildOrder.StartedOrders.Keys.Last(); else - lastInterval = 1; - - if (entityRemoved?.Info()?.Descriptive == DescriptiveType.Worker) + lastInterval = 0; + + if (entityRemoved.Supply()?.Grants > 0) + SupplyCountTimes.Remove(SupplyCountTimes.Last().Key); + + if (entityRemoved.Supply()?.Takes > 0) + buildOrder.CurrentSupplyUsed -= entityRemoved.Supply()!.Takes; + + if (UniqueCompletedTimes[entityRemoved!.DataType].Equals(lastInterval + entityRemoved.Production()!.BuildTime)) + UniqueCompletedTimes.Remove(entityRemoved.DataType); + + if (entityRemoved.Info().Descriptive == DescriptiveType.Worker) { RemoveLast(); return; @@ -172,28 +190,9 @@ public class BuildOrderService : IBuildOrderService return buildOrderText; } - public List GetOrdersAt(int interval) - { - if (!buildOrder.StartedOrders.ContainsKey(interval)) - { - return new List(); - } - - return buildOrder.StartedOrders[interval].ToList(); - } - - public List GetCompletedAt(int interval) - { - if (!buildOrder.CompletedOrders.ContainsKey(interval)) - { - return new List(); - } - - return buildOrder.CompletedOrders[interval].ToList(); - } public List GetCompletedBefore(int interval) - { + { return (from ordersAtTime in buildOrder.StartedOrders from orders in ordersAtTime.Value where ordersAtTime.Key + (orders.Production() == null ? 0 : orders.Production().BuildTime) <= interval @@ -209,52 +208,10 @@ public class BuildOrderService : IBuildOrderService select orders).ToList(); } - public bool MeetsRequirements(EntityModel entity, int requestedInterval) - { - var requirements = entity.Requirements(); - if (requirements.Count == 0) return true; - - foreach (var requirement in requirements) - if (requirement.Requirement == RequirementType.Morph) - { - var entitiesNeeded = from entitiesAtInterval in buildOrder.StartedOrders - from requiredEntity in entitiesAtInterval.Value - where requestedInterval > entitiesAtInterval.Key + - (requiredEntity.Production() == null ? 0 : requiredEntity.Production().BuildTime) - where requiredEntity.DataType == requirement.Id - select requiredEntity; - - var entitiesAlreadyMorphed = from entitiesAtInterval in buildOrder.StartedOrders - from existingEntity in entitiesAtInterval.Value - where existingEntity.DataType == entity.DataType - select existingEntity; - - if (entitiesAlreadyMorphed.Count() >= entitiesNeeded.Count()) - return false; - } - else - { - var entitiesNeeded = from entitiesAtInterval in buildOrder.StartedOrders - from requiredEntity in entitiesAtInterval.Value - where requestedInterval > entitiesAtInterval.Key + - (requiredEntity.Production() == null ? 0 : requiredEntity.Production().BuildTime) - where requiredEntity.DataType == requirement.Id - select requiredEntity; - - if (!entitiesNeeded.Any()) return false; - - - if (entitiesNeeded.Any() == false) - return false; - } - - return true; - } - - public void SetName(string Name) + public void SetName(string name) { - buildOrder.Name = Name; + buildOrder.Name = name; NotifyDataChanged(); } @@ -263,9 +220,9 @@ public class BuildOrderService : IBuildOrderService return buildOrder.Name; } - public void SetNotes(string Notes) + public void SetNotes(string notes) { - buildOrder.Notes = Notes; + buildOrder.Notes = notes; NotifyDataChanged(); } @@ -285,37 +242,90 @@ public class BuildOrderService : IBuildOrderService return buildOrder.Color; } - private event Action OnChange = null!; - - private void NotifyDataChanged() + private bool HandleEconomy(EntityModel entity, IEconomyService withEconomy, IToastService withToasts, + ref int atInterval) { - OnChange?.Invoke(); + var production = entity.Production(); + + if (production == null) return true; + + for (var interval = atInterval; interval < withEconomy.GetOverTime().Count; interval++) + { + var economyAtSecond = withEconomy.GetOverTime()[interval]; + if (economyAtSecond.Alloy >= production.Alloy && economyAtSecond.Ether >= production.Ether && + economyAtSecond.Pyre >= production.Pyre) + { + atInterval = interval; + + if (entity.EntityType != EntityType.Army) + { + atInterval += HumanMicro; + } + + + return true; + } + } + + if (withEconomy.GetOverTime().Last().Ether < production.Ether) + withToasts.AddToast(new ToastModel + { + Title = "Not Enough Ether", Message = "Build more ether extractors!", + SeverityType = SeverityType.Error + }); + + if (withEconomy.GetOverTime().Last().Alloy < production.Alloy) + withToasts.AddToast(new ToastModel + { + Title = "Not Enough Alloy", Message = "Build more bases!", + SeverityType = SeverityType.Error + }); + + return false; } - public bool MeetsSupply(EntityModel entity) + private bool HandleSupply(EntityModel entity, IToastService withToasts, ref int atInterval) { - var supply = entity.Supply(); - if (supply == null || supply.Takes == 0) return true; + var minSupplyInterval = WillMeetSupply(entity); + if (minSupplyInterval == null) + { + withToasts.AddToast(new ToastModel + { + Title = "Supply Cap Reached", Message = "Build more supply!", + SeverityType = SeverityType.Error + }); + return false; + } + + if (minSupplyInterval > atInterval) atInterval = (int)minSupplyInterval; - var supplyTakenTotal = 0; - var supplyTakens = from entitiesAtInterval in buildOrder.StartedOrders - from supplyTakingEntity in entitiesAtInterval.Value - where supplyTakingEntity.Supply()?.Takes > 0 - select supplyTakingEntity.Supply().Takes; - foreach (var supplyTaken in supplyTakens) supplyTakenTotal += supplyTaken; + return true; + } - var supplyGrantedTotal = 0; - var supplyGranteds = from entitiesAtInterval in buildOrder.StartedOrders - from supplyGrantingEntity in entitiesAtInterval.Value - where supplyGrantingEntity.Supply()?.Grants > 0 - select supplyGrantingEntity.Supply().Grants; - foreach (var supplyGranted in supplyGranteds) supplyGrantedTotal += supplyGranted; + private bool HandleRequirements(EntityModel entity, IToastService withToasts, ref int atInterval) + { + var minRequirementInterval = WillMeetRequirements(entity); + if (minRequirementInterval == null) + { + withToasts.AddToast(new ToastModel + { + Title = "Missing Requirements", Message = "You don't have what's needed for this unit.", + SeverityType = SeverityType.Error + }); - if (supplyGrantedTotal > 160) supplyGrantedTotal = 160; + return false; + } - if (supplyTakenTotal + supply.Takes > supplyGrantedTotal) return false; + if (minRequirementInterval > atInterval) atInterval = (int)minRequirementInterval; return true; } + + private event Action OnChange = null!; + + private void NotifyDataChanged() + { + OnChange?.Invoke(); + } } \ No newline at end of file diff --git a/Services/Immortal/EconomyService.cs b/Services/Immortal/EconomyService.cs index aa974c8..c4aae79 100644 --- a/Services/Immortal/EconomyService.cs +++ b/Services/Immortal/EconomyService.cs @@ -7,16 +7,20 @@ namespace Services.Immortal; public class EconomyService : IEconomyService { private List _economyOverTime = null!; + + private event Action OnChange = null!; + + public List GetOverTime() { return _economyOverTime; } public void Subscribe(Action action) { - onChange += action; + OnChange += action; } public void Unsubscribe(Action action) { - onChange -= action; + OnChange -= action; } public void Calculate(IBuildOrderService buildOrder, ITimingService timing, int fromInterval) { @@ -35,9 +39,11 @@ public class EconomyService : IEconomyService { while (_economyOverTime.Count < timing.GetTiming()) _economyOverTime.Add(new EconomyModel { Interval = _economyOverTime.Count - 1 }); - for (var interval = fromInterval; interval < timing.GetTiming(); interval++) { + for (var interval = fromInterval; interval < timing.GetTiming(); interval++) + { var economyAtSecond = _economyOverTime[interval]; - if (interval > 0) { + if (interval > 0) + { economyAtSecond.Alloy = _economyOverTime[interval - 1].Alloy; economyAtSecond.Ether = _economyOverTime[interval - 1].Ether; economyAtSecond.Pyre = _economyOverTime[interval - 1].Pyre; @@ -62,10 +68,12 @@ public class EconomyService : IEconomyService { economyAtSecond.Pyre += 1; // Add funds - foreach (var entity in economyAtSecond.Harvesters) { + foreach (var entity in economyAtSecond.Harvesters) + { var harvester = entity.Harvest(); if (harvester.RequiresWorker) - if (harvester.Resource == ResourceType.Alloy) { + if (harvester.Resource == ResourceType.Alloy) + { var usedWorkers = Math.Min(harvester.Slots, freeWorkers); economyAtSecond.Alloy += harvester.HarvestedPerInterval * usedWorkers; freeWorkers -= usedWorkers; @@ -73,7 +81,8 @@ public class EconomyService : IEconomyService { if (usedWorkers < harvester.Slots) workersNeeded += 1; } - if (harvester.RequiresWorker == false) { + if (harvester.RequiresWorker == false) + { if (harvester.Resource == ResourceType.Ether) economyAtSecond.Ether += harvester.HarvestedPerInterval * harvester.Slots; @@ -85,46 +94,57 @@ public class EconomyService : IEconomyService { // Create new worker if (economyAtSecond.CreatingWorkerCount > 0) for (var i = 0; i < economyAtSecond.CreatingWorkerDelays.Count; i++) - if (economyAtSecond.CreatingWorkerDelays[i] > 0) { - if (economyAtSecond.Alloy > 2.5f) { + if (economyAtSecond.CreatingWorkerDelays[i] > 0) + { + if (economyAtSecond.Alloy > 2.5f) + { economyAtSecond.Alloy -= 2.5f; economyAtSecond.CreatingWorkerDelays[i]--; } } - else { + else + { economyAtSecond.CreatingWorkerCount -= 1; economyAtSecond.WorkerCount += 1; economyAtSecond.CreatingWorkerDelays.Remove(i); i--; } - if (workersNeeded > economyAtSecond.CreatingWorkerCount) { + if (workersNeeded > economyAtSecond.CreatingWorkerCount) + { economyAtSecond.CreatingWorkerCount += 1; economyAtSecond.CreatingWorkerDelays.Add(50); } // Remove Funds from Build Order - var ordersAtTime = buildOrder.GetOrdersAt(interval); - foreach (var order in ordersAtTime) { - var foundEntity = EntityModel.GetDictionary()[order.DataType]; - var production = foundEntity.Production(); + if (buildOrder.StartedOrders.TryGetValue(interval, out var ordersAtTime)) + { - if (production != null) { - economyAtSecond.Alloy -= production.Alloy; - economyAtSecond.Ether -= production.Ether; - economyAtSecond.Pyre -= production.Pyre; - var finishedAt = interval + production.BuildTime; + foreach (var order in ordersAtTime) + { + var foundEntity = EntityModel.GetDictionary()[order.DataType]; + var production = foundEntity.Production(); - if (production.RequiresWorker) economyAtSecond.BusyWorkerCount += 1; + if (production != null) + { + economyAtSecond.Alloy -= production.Alloy; + economyAtSecond.Ether -= production.Ether; + economyAtSecond.Pyre -= production.Pyre; + var finishedAt = interval + production.BuildTime; - if (production.ConsumesWorker) economyAtSecond.WorkerCount -= 1; + if (production.RequiresWorker) economyAtSecond.BusyWorkerCount += 1; + + if (production.ConsumesWorker) economyAtSecond.WorkerCount -= 1; + } } } // Handle new entities - var completedAtInterval = buildOrder.GetCompletedAt(interval); - foreach (var newEntity in completedAtInterval) { + if (buildOrder.CompletedOrders.TryGetValue(interval, out var completedAtInterval)) + { + foreach (var newEntity in completedAtInterval) + { var harvest = newEntity; if (harvest != null) economyAtSecond.Harvesters.Add(harvest); @@ -132,6 +152,7 @@ public class EconomyService : IEconomyService { if (production != null && production.RequiresWorker) economyAtSecond.BusyWorkerCount -= 1; } } + } NotifyDataChanged(); } @@ -141,13 +162,7 @@ public class EconomyService : IEconomyService { return _economyOverTime[atInterval]; } - private event Action onChange = null!; - private void NotifyDataChanged() { - onChange?.Invoke(); - } - - public Action OnChange() { - return onChange; + OnChange?.Invoke(); } } \ No newline at end of file diff --git a/Services/Immortal/GameLogicService.cs b/Services/Immortal/GameLogicService.cs deleted file mode 100644 index 8c7da30..0000000 --- a/Services/Immortal/GameLogicService.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Model.Entity; -using Model.Types; - -namespace Services.Immortal; - -public class GameLogicService : IGameLogicService -{ - private ITimingService timingService; - private IEconomyService economyService; - private IBuildOrderService buildOrderService; - - public GameLogicService(ITimingService timingService, IEconomyService economyService, IBuildOrderService buildOrderService) - { - this.timingService = timingService; - this.economyService = economyService; - this.buildOrderService = buildOrderService; - } - - public bool Add(EntityModel entity, int atInterval) - { - throw new NotImplementedException(); - } - - public int MeetsRequirements(EntityModel entity, int interval) - { - var buildOrders = buildOrderService.GetCompletedBefore(interval); - - - - - return -1; - } - - public int MeetsAlloy(EntityModel entity, int interval) - { - throw new NotImplementedException(); - } - - public int MeetsEther(EntityModel entity, int interval) - { - throw new NotImplementedException(); - } - - public int MeetsPyre(EntityModel entity, int interval) - { - throw new NotImplementedException(); - } - - public int MeetsSupply(EntityModel entity, int interval) - { - throw new NotImplementedException(); - } - - public int MeetsTrainingQueue(EntityModel entity, int interval) - { - throw new NotImplementedException(); - } -} \ No newline at end of file diff --git a/Services/Immortal/TimingService.cs b/Services/Immortal/TimingService.cs index 01cd105..4ee7884 100644 --- a/Services/Immortal/TimingService.cs +++ b/Services/Immortal/TimingService.cs @@ -1,7 +1,7 @@ namespace Services.Immortal; public class TimingService : ITimingService { - private int _timing = 360; + private int _timing = 1500; public void Subscribe(Action? action) { _onChange += action;