From 026aebd5addcb4660556f4a30dd2eb6a85c9823f Mon Sep 17 00:00:00 2001 From: 6d486f49 Date: Mon, 1 Jun 2026 11:37:40 -0400 Subject: [PATCH 1/4] Clearing Entity Click View on Clear and other notes --- .../BuildCalculator/BuildCalculatorPage.razor | 8 +- .../Parts/EntityClickViewComponent.razor | 13 +- .../Parts/FactionBorderComponent.razor | 32 ++++ .../Parts/ImmortalBorderComponent.razor | 37 +++++ .../Parts/TutorialHelperComponent.razor | 82 +++++++++++ Playwright/helpers/website.js | 4 +- Playwright/tests/buildCalculator.spec.js | 21 --- docs/.obsidian/workspace.json | 137 ++++-------------- docs/Get AI to Add easy Test Tasks.md | 2 +- docs/Helper Tutorial Info Improvements.md | 30 +++- docs/Make Tests for the Build Calculator.md | 2 +- ... based on Selected Faction and Immortal.md | 17 ++- docs/_Tasks Kanban.base | 10 +- 13 files changed, 248 insertions(+), 147 deletions(-) create mode 100644 IGP/Pages/BuildCalculator/Parts/FactionBorderComponent.razor create mode 100644 IGP/Pages/BuildCalculator/Parts/ImmortalBorderComponent.razor create mode 100644 IGP/Pages/BuildCalculator/Parts/TutorialHelperComponent.razor diff --git a/IGP/Pages/BuildCalculator/BuildCalculatorPage.razor b/IGP/Pages/BuildCalculator/BuildCalculatorPage.razor index 03d8dbb..a6e90e2 100644 --- a/IGP/Pages/BuildCalculator/BuildCalculatorPage.razor +++ b/IGP/Pages/BuildCalculator/BuildCalculatorPage.razor @@ -25,7 +25,9 @@
- + + + @@ -56,7 +58,9 @@
- + + + diff --git a/IGP/Pages/BuildCalculator/Parts/EntityClickViewComponent.razor b/IGP/Pages/BuildCalculator/Parts/EntityClickViewComponent.razor index 584342a..1581c32 100644 --- a/IGP/Pages/BuildCalculator/Parts/EntityClickViewComponent.razor +++ b/IGP/Pages/BuildCalculator/Parts/EntityClickViewComponent.razor @@ -2,6 +2,7 @@ @inject IKeyService KeyService @inject IImmortalSelectionService FilterService @inject IStorageService StorageService +@inject IBuildOrderService BuildOrderService @using Services.Website @implements IDisposable @@ -33,6 +34,7 @@ base.OnInitialized(); KeyService.Subscribe(HandleClick); StorageService.Subscribe(RefreshDefaults); + BuildOrderService.Subscribe(OnBuildOrderServiceChanged); RefreshDefaults(); } @@ -40,11 +42,20 @@ void IDisposable.Dispose() { KeyService.Unsubscribe(HandleClick); - StorageService.Unsubscribe(RefreshDefaults); + BuildOrderService.Unsubscribe(OnBuildOrderServiceChanged); } + void OnBuildOrderServiceChanged() + { + if (BuildOrderService.GetLastRequestInterval() == 0) + { + _entity = null; + StateHasChanged(); + } + } + void RefreshDefaults() { _viewType = StorageService.GetValue(StorageKeys.IsPlainView) ? EntityViewType.Plain : EntityViewType.Detailed; diff --git a/IGP/Pages/BuildCalculator/Parts/FactionBorderComponent.razor b/IGP/Pages/BuildCalculator/Parts/FactionBorderComponent.razor new file mode 100644 index 0000000..a28c318 --- /dev/null +++ b/IGP/Pages/BuildCalculator/Parts/FactionBorderComponent.razor @@ -0,0 +1,32 @@ +@inject IImmortalSelectionService FilterService +@using Model.Entity.Data +@implements IDisposable + + +
+ @ChildContent +
+
+ +@code { + + [Parameter] public RenderFragment? ChildContent { get; set; } + + protected override void OnInitialized() + { + base.OnInitialized(); + FilterService.Subscribe(StateHasChanged); + } + + void IDisposable.Dispose() + { + FilterService.Unsubscribe(StateHasChanged); + } + + string GetBorderStyle() + { + var faction = FilterService.GetFaction(); + var color = faction == DataType.FACTION_Aru ? "#CD5C5C" : "#8EACCD"; + return $"border-top: 4px solid {color}; padding-top: 4px;"; + } +} diff --git a/IGP/Pages/BuildCalculator/Parts/ImmortalBorderComponent.razor b/IGP/Pages/BuildCalculator/Parts/ImmortalBorderComponent.razor new file mode 100644 index 0000000..d65de52 --- /dev/null +++ b/IGP/Pages/BuildCalculator/Parts/ImmortalBorderComponent.razor @@ -0,0 +1,37 @@ +@inject IImmortalSelectionService FilterService +@using Model.Entity.Data +@implements IDisposable + + +
+ @ChildContent +
+
+ +@code { + + [Parameter] public RenderFragment? ChildContent { get; set; } + + protected override void OnInitialized() + { + base.OnInitialized(); + FilterService.Subscribe(StateHasChanged); + } + + void IDisposable.Dispose() + { + FilterService.Unsubscribe(StateHasChanged); + } + + string GetBorderStyle() + { + var immortal = FilterService.GetImmortal(); + var color = "#666666"; + if (immortal == DataType.IMMORTAL_Orzum) color = "#4A6B8A"; + else if (immortal == DataType.IMMORTAL_Ajari) color = "#A3B8CC"; + else if (immortal == DataType.IMMORTAL_Atzlan) color = "#8B7355"; + else if (immortal == DataType.IMMORTAL_Mala) color = "#6B8E23"; + else if (immortal == DataType.IMMORTAL_Xol) color = "#9CA89C"; + return $"border-top: 4px solid {color}; padding-top: 4px;"; + } +} diff --git a/IGP/Pages/BuildCalculator/Parts/TutorialHelperComponent.razor b/IGP/Pages/BuildCalculator/Parts/TutorialHelperComponent.razor new file mode 100644 index 0000000..b863b67 --- /dev/null +++ b/IGP/Pages/BuildCalculator/Parts/TutorialHelperComponent.razor @@ -0,0 +1,82 @@ +@inject IImmortalSelectionService FilterService + +@implements IDisposable + + + + + What is this tool? + + + This is a calculator to determine build timings. Mostly so someone can quickly try out a few build + orders to see if they somewhat make sense. + + + + + + How does it work? + + + The tool calculates every second of game time. So if you attempt to build a Legion Hall as + your first action, the tool will scan every second, until you get to one where the request can be + made. In this case, that is interval 58. +
+
+ If you then build 2 Apostle of Bindings a Soul Foundry and a 3 Absolvers you + should see yourself roughly floating 500 alloy, with barely having any ether. Which means you could + of gotten an Acropolis and a Zentari without hurting your build. +
+
+ Try building Apostle of Bindings before the Legion Hall and see how that changes the + timing of your 3 Absolvers. (Spoiler: + your Absolvers will be built much faster, and you won't be floating so + much alloy. + + ) +
+
+ + + + What is CONTROL key for? + + + Economy and tech related upgrades for townhalls. + + + + + + What is SHIFT key for? + + + Misc building related upgrades. (Omnivores) + + + + + + What is 2 key for? + + + It will be for Pyre camps. Currently not implemented. + + +
+ +@code { + + protected override void OnInitialized() + { + base.OnInitialized(); + FilterService.Subscribe(StateHasChanged); + } + + void IDisposable.Dispose() + { + FilterService.Unsubscribe(StateHasChanged); + } + + +} \ No newline at end of file diff --git a/Playwright/helpers/website.js b/Playwright/helpers/website.js index 18a6092..8f1c795 100644 --- a/Playwright/helpers/website.js +++ b/Playwright/helpers/website.js @@ -11,9 +11,7 @@ class Website { } else { const hook = process.env.TEST_HOOK || ''; this.deploymentType = hook.includes('localhost') ? 'Local' : 'Dev'; - this.baseUrl = this.deploymentType === 'Dev' - ? 'https://calm-mud-04916b210.1.azurestaticapps.net' - : 'https://localhost:7234'; + this.baseUrl = 'https://localhost:7234'; } const BuildCalculatorPage = require('../pages/buildCalculatorPage'); diff --git a/Playwright/tests/buildCalculator.spec.js b/Playwright/tests/buildCalculator.spec.js index 6ce64d3..e8b7025 100644 --- a/Playwright/tests/buildCalculator.spec.js +++ b/Playwright/tests/buildCalculator.spec.js @@ -58,33 +58,12 @@ test.describe('Build Calculator', () => { const calc = website.buildCalculatorPage; await calc.goto(); - const buttons = page.locator('.keyContainer > div > div'); - console.log('Initial Q button text:', await buttons.filter({ hasText: /^Q/ }).first().textContent()); - - // Wait for Blazor re-render to complete by waiting for the button text to stabilize - // (it goes from QAcropolis → empty during re-render → back to QAcropolis) - let tries = 0; - let text = ''; - while (tries < 20) { - await page.waitForTimeout(500); - try { - text = (await buttons.filter({ hasText: /^Q/ }).first().textContent() || '').trim(); - if (text && text.length > 1) break; - } catch { } - tries++; - } - console.log(`After Blazor render (${(tries+1)*0.5}s): Q button text: ${JSON.stringify(text)}`); - await calc.filter.selectFaction("Q'Rath"); await calc.filter.selectImmortal('Orzum'); - await page.waitForTimeout(1000); - - console.log('After filter Q button text:', await buttons.filter({ hasText: /^Q/ }).first().textContent()); expect(await calc.timeline.containsEntity('Acropolis')).toBe(false); await calc.hotkeys.clickKey('Q'); - await page.waitForTimeout(1000); expect(await calc.entityView.getEntityName()).toBe('Acropolis'); expect(await calc.timeline.containsEntity('Acropolis')).toBe(true); diff --git a/docs/.obsidian/workspace.json b/docs/.obsidian/workspace.json index 22ef2b1..f4e8def 100644 --- a/docs/.obsidian/workspace.json +++ b/docs/.obsidian/workspace.json @@ -23,105 +23,7 @@ } }, { - "id": "2389ff9bfbc7c06e", - "type": "leaf", - "state": { - "type": "markdown", - "state": { - "file": "Untitled.md", - "mode": "source", - "source": false - }, - "icon": "lucide-file", - "title": "Untitled" - } - }, - { - "id": "516344d92af043d3", - "type": "leaf", - "state": { - "type": "markdown", - "state": { - "file": "Entity Click View Tests.md", - "mode": "source", - "source": false - }, - "icon": "lucide-file", - "title": "Entity Click View Tests" - } - }, - { - "id": "e080f009e5533348", - "type": "leaf", - "state": { - "type": "markdown", - "state": { - "file": "Hotkey Tests.md", - "mode": "source", - "source": false - }, - "icon": "lucide-file", - "title": "Hotkey Tests" - } - }, - { - "id": "8c62a38928399310", - "type": "leaf", - "state": { - "type": "markdown", - "state": { - "file": "Army Calc UI.md", - "mode": "source", - "source": false - }, - "icon": "lucide-file", - "title": "Army Calc UI" - } - }, - { - "id": "63052cace03ac2f7", - "type": "leaf", - "state": { - "type": "markdown", - "state": { - "file": "Timeline Tests.md", - "mode": "source", - "source": false - }, - "icon": "lucide-file", - "title": "Timeline Tests" - } - }, - { - "id": "b468ed9d43376232", - "type": "leaf", - "state": { - "type": "markdown", - "state": { - "file": "Army Display Split.md", - "mode": "source", - "source": false - }, - "icon": "lucide-file", - "title": "Army Display Split" - } - }, - { - "id": "2c63d9663088f304", - "type": "leaf", - "state": { - "type": "markdown", - "state": { - "file": "Highest Alloy and Ether Tests.md", - "mode": "source", - "source": false - }, - "icon": "lucide-file", - "title": "Highest Alloy and Ether Tests" - } - }, - { - "id": "461430f8c29407ab", + "id": "094e8bbc34e4a833", "type": "leaf", "state": { "type": "markdown", @@ -135,21 +37,35 @@ } }, { - "id": "094e8bbc34e4a833", + "id": "68e1ba2b54081b9a", "type": "leaf", "state": { "type": "markdown", "state": { - "file": "Top Borders in Calculator should change based on Selected Faction and Immortal.md", + "file": "Helper Tutorial Info Improvements.md", "mode": "source", "source": false }, "icon": "lucide-file", - "title": "Top Borders in Calculator should change based on Selected Faction and Immortal" + "title": "Helper Tutorial Info Improvements" + } + }, + { + "id": "b98a69cefb529fc8", + "type": "leaf", + "state": { + "type": "markdown", + "state": { + "file": "Changing Factions and Immortal should clear out build.md", + "mode": "source", + "source": false + }, + "icon": "lucide-file", + "title": "Changing Factions and Immortal should clear out build" } } ], - "currentTab": 9 + "currentTab": 3 } ], "direction": "vertical" @@ -206,8 +122,7 @@ } ], "direction": "horizontal", - "width": 200, - "collapsed": true + "width": 200 }, "right": { "id": "dd7c1dc4bd54d927", @@ -322,27 +237,27 @@ "bases:Create new base": false } }, - "active": "094e8bbc34e4a833", + "active": "b98a69cefb529fc8", "lastOpenFiles": [ "_Tasks Kanban.base", "Helper Tutorial Info Improvements.md", - "Make a Plan to Fully Test the Calculator.md", "Highest Alloy and Ether Tests.md", "Army Display Split.md", "Timeline Tests.md", "Army Calc UI.md", - "Untitled 1.md", "Hotkey Tests.md", - "Add a Timeline Editor.md", - "Worker Income UI and Tests.md", "Entity Click View Tests.md", "Untitled.md", + "Top Borders in Calculator should change based on Selected Faction and Immortal.md", + "Make a Plan to Fully Test the Calculator.md", + "Untitled 1.md", + "Add a Timeline Editor.md", + "Worker Income UI and Tests.md", "More Wait Tests.md", "Build Clear should clear out more stuff.md", "Changing Factions and Immortal should clear out build.md", "Input building delay should have an effect on when a building is built. Tests against 0, 2, 4, 60.md", "Ensure build order gets greyed out past the attack time. Clicking the cancel button will wipe the entire greyed out timeline..md", - "Top Borders in Calculator should change based on Selected Faction and Immortal.md", "Pasted image 20260601093510.png", "Pasted image 20260601093506.png", "Pasted image 20260601083333.png", diff --git a/docs/Get AI to Add easy Test Tasks.md b/docs/Get AI to Add easy Test Tasks.md index c112640..3fc5144 100644 --- a/docs/Get AI to Add easy Test Tasks.md +++ b/docs/Get AI to Add easy Test Tasks.md @@ -1,6 +1,6 @@ --- type: Task -status: AI Agent Work +status: Done category: --- Consider Playwright features we can use to create obvious tests to our test project in the Playwright folder. diff --git a/docs/Helper Tutorial Info Improvements.md b/docs/Helper Tutorial Info Improvements.md index d18b783..61fff6d 100644 --- a/docs/Helper Tutorial Info Improvements.md +++ b/docs/Helper Tutorial Info Improvements.md @@ -8,5 +8,33 @@ category: ![[Pasted image 20260601083333.png]] -- Ensure referenced data is taken from the database. Unit names and costs are currently hard coded. +- Ensure referenced data is taken from the database. Unit names and costs are currently hard coded. - Would be cute to dynamically change the information based on the calculator filter. i.e. when making a build for Aru, we should use the Aru unit names in the help information instead of Q'Rath + + +--- + +The TutorialHelperComponent should change it's information based on the selected Immortal and Faction. + +Currently, it explains a hard coded example of a user playing as Q'Rath and Orzum, and making a Legion Hall, Apostle of Bindings, a Soul Foundry, and 3 Absolvers and a Zentari. + +Obviously, if the the filter has Aru selected for the faction, the user would be making a Ether Maw, Altar of the Worthy, God Heart Upgrade and a Amber Womb. + +For the units, if they have the Immortal of Mala or Atlzan selected, they would be making Masked Hunters. But if they had Xol selected, they would instead be making Bone Stalkers. + +For the units, if they have the Immortal of Atlzan selected, they would be making Resinants. But if they had Mala or Xol selected, they would instead be making Blood Anchors. + +If they have Q'Rath selected, things are as they are. But if they have Ajari selected as the Immortal, they build Sipari instead of Zentari. + +The calculations should be based on the Alloy and Ether costs from the database. + +These variables will be need to be used, and will be taken from hard coded values on the page that matches the associated filter combinations. + +Given the steps can be very different between filter combinations, the exact contents will also need to be changed based on the filters. Note the extra God Heart Upgrade step for Aru. + +This hard coded content will need to be regenerated a a later date to match information currently in the database. But do not worry about implementing that right now. + + + + +--- \ No newline at end of file diff --git a/docs/Make Tests for the Build Calculator.md b/docs/Make Tests for the Build Calculator.md index 68653ff..20884b6 100644 --- a/docs/Make Tests for the Build Calculator.md +++ b/docs/Make Tests for the Build Calculator.md @@ -1,6 +1,6 @@ --- type: Task -status: AI Agent Work +status: Done category: --- diff --git a/docs/Top Borders in Calculator should change based on Selected Faction and Immortal.md b/docs/Top Borders in Calculator should change based on Selected Faction and Immortal.md index aa0b168..711fc70 100644 --- a/docs/Top Borders in Calculator should change based on Selected Faction and Immortal.md +++ b/docs/Top Borders in Calculator should change based on Selected Faction and Immortal.md @@ -1,6 +1,6 @@ --- type: Task -status: Working On +status: AI Agent Work category: - Feature - QA @@ -10,4 +10,19 @@ category: - Top border on the Options component changes based on the selected Faction. Light-gray-blue for Q'Rath, Red for Aru. - Top border on Entity Click View component changes based on the selected Immortal. Ex. Grey-ish-Green for Xol, Green-red for Mala, Brown for Atzlan. Dark-grey-ish-blue for Orzum, Light-ish-blue for Ajari. +--- +Make two new UI component to handle the border display changes based on events given by the FilterService. + +One will listen against events on the GetFaction changes, and one based on the GetImmortal changes. + +These new UI components will be layered on top of FormLayoutComponent. + +The purpose is to change the top border colour based on events, to act as UI feedback. + +One component will cover the FilterComponent for changing the Faction, and one component will cover the EntityClickViewComponent for changing the Immortal. + +Goal is to accomplish: + +- Top border over the FilterComponent component changes based on the selected Faction. Light-gray-blue for Q'Rath, Red for Aru. +- Top border on EntityClickViewComponent changes based on the selected Immortal. Ex. Grey-ish-Green for Xol, Green-red for Mala, Brown for Atzlan. Dark-grey-ish-blue for Orzum, Light-ish-blue for Ajari. diff --git a/docs/_Tasks Kanban.base b/docs/_Tasks Kanban.base index b47150c..411341f 100644 --- a/docs/_Tasks Kanban.base +++ b/docs/_Tasks Kanban.base @@ -45,11 +45,9 @@ views: - Jenkins CI.md - Improve your SEO.md - Create Mobile Calculator UI.md - - Top Borders in Calculator should change based on Selected Faction and Immortal.md - Army Display Split.md - Entity Click View Tests.md - Worker Income UI and Tests.md - - Changing Factions and Immortal should clear out build.md - Ensure build order gets greyed out past the attack time. Clicking the cancel button will wipe the entire greyed out timeline..md - Build Clear should clear out more stuff.md - Army Calc UI.md @@ -57,7 +55,10 @@ views: - Input building delay should have an effect on when a building is built. Tests against 0, 2, 4, 60.md - More Wait Tests.md - Timeline Tests.md - Working On: [] + Working On: + - Helper Tutorial Info Improvements.md + - Changing Factions and Immortal should clear out build.md + - Highest Alloy and Ether Tests.md Backlog: - Fully Test the Build Calculator.md - Add an Ability to Favourite Data.md @@ -72,8 +73,7 @@ views: - Change Ctrl + K Hotkey to something that doesn't conflict with Edge or other browsers.md - Language Support.md AI Agent Work: - - Make Tests for the Build Calculator.md - - Get AI to Add easy Test Tasks.md + - Top Borders in Calculator should change based on Selected Faction and Immortal.md Blocked Backlog: - Nice looking map refrence.md - Auto Build consideration in Calculator.md -- 2.43.0 From dc0395c7d34e2a79f3629c522f6142012e5f8f78 Mon Sep 17 00:00:00 2001 From: 6d486f49 <76097bcc@gmail.com> Date: Mon, 1 Jun 2026 16:52:44 -0400 Subject: [PATCH 2/4] Updating .NET versions --- Components/Components.csproj | 2 +- Model/Model.csproj | 2 +- Services/Services.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Components/Components.csproj b/Components/Components.csproj index 69bdb5b..2e69dd8 100644 --- a/Components/Components.csproj +++ b/Components/Components.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable diff --git a/Model/Model.csproj b/Model/Model.csproj index 2eeee82..0a5dca0 100644 --- a/Model/Model.csproj +++ b/Model/Model.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 diff --git a/Services/Services.csproj b/Services/Services.csproj index 60e573f..a62a0c4 100644 --- a/Services/Services.csproj +++ b/Services/Services.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable -- 2.43.0 From 7da6f554a8a8e893dd3a7ff035c2cf0a07d97c8d Mon Sep 17 00:00:00 2001 From: 6d486f49 Date: Tue, 2 Jun 2026 11:33:46 -0400 Subject: [PATCH 3/4] Faction border code design and colour tweaks --- IGP/App.razor | 9 +++++++++ IGP/Pages/BuildCalculator/BuildCalculatorPage.razor | 1 + .../{ => Cosmetic}/FactionBorderComponent.razor | 5 ++--- .../{ => Cosmetic}/ImmortalBorderComponent.razor | 13 ++++++------- 4 files changed, 18 insertions(+), 10 deletions(-) rename IGP/Pages/BuildCalculator/Parts/{ => Cosmetic}/FactionBorderComponent.razor (75%) rename IGP/Pages/BuildCalculator/Parts/{ => Cosmetic}/ImmortalBorderComponent.razor (60%) diff --git a/IGP/App.razor b/IGP/App.razor index 99cfd6b..0717bce 100644 --- a/IGP/App.razor +++ b/IGP/App.razor @@ -44,6 +44,15 @@ :root { + --faction-aru: #da4e4e; + --immortal-mala: #dc7a29; + --immortal-xol: #87aa87; + --immortal-atzlan: #8B7355; + + --faction-qrath: #8EACCD; + --immortal-orzum: #4A6B8A; + --immortal-ajari: #b4e2e3; + --severity-warning-color: #2a2000; --severity-warning-border-color: #755c13; --severity-error-color: #290102; diff --git a/IGP/Pages/BuildCalculator/BuildCalculatorPage.razor b/IGP/Pages/BuildCalculator/BuildCalculatorPage.razor index a6e90e2..21553c2 100644 --- a/IGP/Pages/BuildCalculator/BuildCalculatorPage.razor +++ b/IGP/Pages/BuildCalculator/BuildCalculatorPage.razor @@ -13,6 +13,7 @@ @inject IDataCollectionService DataCollectionService @page "/build-calculator" +@using IGP.Pages.BuildCalculator.Parts.Cosmetic @using Services.Website @implements IDisposable diff --git a/IGP/Pages/BuildCalculator/Parts/FactionBorderComponent.razor b/IGP/Pages/BuildCalculator/Parts/Cosmetic/FactionBorderComponent.razor similarity index 75% rename from IGP/Pages/BuildCalculator/Parts/FactionBorderComponent.razor rename to IGP/Pages/BuildCalculator/Parts/Cosmetic/FactionBorderComponent.razor index a28c318..f59b103 100644 --- a/IGP/Pages/BuildCalculator/Parts/FactionBorderComponent.razor +++ b/IGP/Pages/BuildCalculator/Parts/Cosmetic/FactionBorderComponent.razor @@ -1,5 +1,4 @@ @inject IImmortalSelectionService FilterService -@using Model.Entity.Data @implements IDisposable @@ -26,7 +25,7 @@ string GetBorderStyle() { var faction = FilterService.GetFaction(); - var color = faction == DataType.FACTION_Aru ? "#CD5C5C" : "#8EACCD"; - return $"border-top: 4px solid {color}; padding-top: 4px;"; + var color = faction == DataType.FACTION_Aru ? "var(--faction-aru)" : "var(--faction-qrath)"; + return $"border-top: 4px solid {color}; padding-top: 14px; margin-top: -12px;"; } } diff --git a/IGP/Pages/BuildCalculator/Parts/ImmortalBorderComponent.razor b/IGP/Pages/BuildCalculator/Parts/Cosmetic/ImmortalBorderComponent.razor similarity index 60% rename from IGP/Pages/BuildCalculator/Parts/ImmortalBorderComponent.razor rename to IGP/Pages/BuildCalculator/Parts/Cosmetic/ImmortalBorderComponent.razor index d65de52..f91b74e 100644 --- a/IGP/Pages/BuildCalculator/Parts/ImmortalBorderComponent.razor +++ b/IGP/Pages/BuildCalculator/Parts/Cosmetic/ImmortalBorderComponent.razor @@ -1,5 +1,4 @@ @inject IImmortalSelectionService FilterService -@using Model.Entity.Data @implements IDisposable @@ -27,11 +26,11 @@ { var immortal = FilterService.GetImmortal(); var color = "#666666"; - if (immortal == DataType.IMMORTAL_Orzum) color = "#4A6B8A"; - else if (immortal == DataType.IMMORTAL_Ajari) color = "#A3B8CC"; - else if (immortal == DataType.IMMORTAL_Atzlan) color = "#8B7355"; - else if (immortal == DataType.IMMORTAL_Mala) color = "#6B8E23"; - else if (immortal == DataType.IMMORTAL_Xol) color = "#9CA89C"; - return $"border-top: 4px solid {color}; padding-top: 4px;"; + if (immortal == DataType.IMMORTAL_Orzum) color = "var(--immortal-orzum)"; + else if (immortal == DataType.IMMORTAL_Ajari) color = "var(--immortal-ajari)"; + else if (immortal == DataType.IMMORTAL_Atzlan) color = "var(--immortal-atzlan)"; + else if (immortal == DataType.IMMORTAL_Mala) color = "var(--immortal-mala)"; + else if (immortal == DataType.IMMORTAL_Xol) color = "var(--immortal-xol)"; + return $"border-top: 4px solid {color}; padding-top: 14px; margin-top: -12px;"; } } -- 2.43.0 From 85834466f12c0ed7baf7dea7cdda411932311281 Mon Sep 17 00:00:00 2001 From: 6d486f49 Date: Tue, 2 Jun 2026 12:12:38 -0400 Subject: [PATCH 4/4] CLI and Publish Tests --- .gitignore | 4 + Dockerfile | 9 + IGP.Calculator.Cli/IGP.Calculator.Cli.csproj | 16 ++ IGP.Calculator.Cli/Program.cs | 158 ++++++++++++++++++ .../Services/NullStorageService.cs | 25 +++ IGP/IGP.sln | 50 ++++++ Model/BuildOrders/BuildOrderModel.cs | 8 +- Services/IServices.cs | 1 + Services/Immortal/BuildOrderService.cs | 7 + docs/.obsidian/workspace.json | 79 ++++----- docs/AI Help Docs/containerize-and-run.md | 62 +++++++ docs/AI Help Docs/publish-and-serve.md | 51 ++++++ docs/Build Calculator CmdLine.md | 7 + .../Pasted image 20260601082954.png | Bin .../Pasted image 20260601083005.png | Bin .../Pasted image 20260601083019.png | Bin .../Pasted image 20260601083030.png | Bin .../Pasted image 20260601083046.png | Bin .../Pasted image 20260601083101.png | Bin .../Pasted image 20260601083113.png | Bin .../Pasted image 20260601083127.png | Bin .../Pasted image 20260601083147.png | Bin .../Pasted image 20260601083206.png | Bin .../Pasted image 20260601083333.png | Bin .../Pasted image 20260601093506.png | Bin .../Pasted image 20260601093510.png | Bin .../Add Co-op objective reference.md | 0 docs/{ => Tasks}/Add a Timeline Editor.md | 0 .../Add an Ability to Favourite Data.md | 0 .../Add some cooldown reference.md | 0 ...ns in Calculator without pressing Space.md | 0 docs/{ => Tasks}/Army Calc UI.md | 0 docs/{ => Tasks}/Army Display Split.md | 0 .../Auto Build consideration in Calculator.md | 0 docs/{ => Tasks}/Basic Build Order Sheet.md | 0 ...Build Clear should clear out more stuff.md | 0 ...'t conflict with Edge or other browsers.md | 0 ...ons and Immortal should clear out build.md | 0 docs/{ => Tasks}/Create Automated Tests.md | 0 .../Create Mobile Calculator UI.md | 0 ...ll wipe the entire greyed out timeline..md | 0 docs/{ => Tasks}/Entity Click View Tests.md | 0 .../Fix Entity Recursion Error - Parent.md | 0 .../Fully Test the Build Calculator.md | 0 .../Get AI to Add easy Test Tasks.md | 0 .../Helper Tutorial Info Improvements.md | 0 .../Highest Alloy and Ether Tests.md | 0 docs/{ => Tasks}/Hotkey Tests.md | 0 docs/{ => Tasks}/Improve your SEO.md | 0 ...ing is built. Tests against 0, 2, 4, 60.md | 0 docs/{ => Tasks}/Jenkins CI.md | 0 docs/{ => Tasks}/Language Support.md | 0 ...amples be based on Database Information.md | 0 .../Make Tests for the Build Calculator.md | 0 ...ake a Plan to Fully Test the Calculator.md | 0 ...uild Calculator and all it's components.md | 0 docs/{ => Tasks}/More Wait Tests.md | 0 docs/{ => Tasks}/Nice looking map refrence.md | 0 docs/{ => Tasks}/Plan Calculator.md | 0 ...rom anywhere in the build calc timeline.md | 0 ... they don't show under production table.md | 0 docs/{ => Tasks}/Timeline Tests.md | 0 ... based on Selected Faction and Immortal.md | 0 ...pdate the Reference Tables with Telerik.md | 0 docs/{ => Tasks}/WebAssembly back to Azure.md | 0 .../{ => Tasks}/Worker Income UI and Tests.md | 0 docs/Untitled 1.md | 5 - docs/Untitled.md | 5 - docs/_Tasks Kanban.base | 3 +- nginx.conf | 27 +++ serve_publish.cjs | 48 ++++++ 71 files changed, 511 insertions(+), 54 deletions(-) create mode 100644 Dockerfile create mode 100644 IGP.Calculator.Cli/IGP.Calculator.Cli.csproj create mode 100644 IGP.Calculator.Cli/Program.cs create mode 100644 IGP.Calculator.Cli/Services/NullStorageService.cs create mode 100644 docs/AI Help Docs/containerize-and-run.md create mode 100644 docs/AI Help Docs/publish-and-serve.md create mode 100644 docs/Build Calculator CmdLine.md rename docs/{ => Images}/Pasted image 20260601082954.png (100%) rename docs/{ => Images}/Pasted image 20260601083005.png (100%) rename docs/{ => Images}/Pasted image 20260601083019.png (100%) rename docs/{ => Images}/Pasted image 20260601083030.png (100%) rename docs/{ => Images}/Pasted image 20260601083046.png (100%) rename docs/{ => Images}/Pasted image 20260601083101.png (100%) rename docs/{ => Images}/Pasted image 20260601083113.png (100%) rename docs/{ => Images}/Pasted image 20260601083127.png (100%) rename docs/{ => Images}/Pasted image 20260601083147.png (100%) rename docs/{ => Images}/Pasted image 20260601083206.png (100%) rename docs/{ => Images}/Pasted image 20260601083333.png (100%) rename docs/{ => Images}/Pasted image 20260601093506.png (100%) rename docs/{ => Images}/Pasted image 20260601093510.png (100%) rename docs/{ => Tasks}/Add Co-op objective reference.md (100%) rename docs/{ => Tasks}/Add a Timeline Editor.md (100%) rename docs/{ => Tasks}/Add an Ability to Favourite Data.md (100%) rename docs/{ => Tasks}/Add some cooldown reference.md (100%) rename docs/{ => Tasks}/Allow to Always see Advanced Options in Calculator without pressing Space.md (100%) rename docs/{ => Tasks}/Army Calc UI.md (100%) rename docs/{ => Tasks}/Army Display Split.md (100%) rename docs/{ => Tasks}/Auto Build consideration in Calculator.md (100%) rename docs/{ => Tasks}/Basic Build Order Sheet.md (100%) rename docs/{ => Tasks}/Build Clear should clear out more stuff.md (100%) rename docs/{ => Tasks}/Change Ctrl + K Hotkey to something that doesn't conflict with Edge or other browsers.md (100%) rename docs/{ => Tasks}/Changing Factions and Immortal should clear out build.md (100%) rename docs/{ => Tasks}/Create Automated Tests.md (100%) rename docs/{ => Tasks}/Create Mobile Calculator UI.md (100%) rename docs/{ => Tasks}/Ensure build order gets greyed out past the attack time. Clicking the cancel button will wipe the entire greyed out timeline..md (100%) rename docs/{ => Tasks}/Entity Click View Tests.md (100%) rename docs/{ => Tasks}/Fix Entity Recursion Error - Parent.md (100%) rename docs/{ => Tasks}/Fully Test the Build Calculator.md (100%) rename docs/{ => Tasks}/Get AI to Add easy Test Tasks.md (100%) rename docs/{ => Tasks}/Helper Tutorial Info Improvements.md (100%) rename docs/{ => Tasks}/Highest Alloy and Ether Tests.md (100%) rename docs/{ => Tasks}/Hotkey Tests.md (100%) rename docs/{ => Tasks}/Improve your SEO.md (100%) rename docs/{ => Tasks}/Input building delay should have an effect on when a building is built. Tests against 0, 2, 4, 60.md (100%) rename docs/{ => Tasks}/Jenkins CI.md (100%) rename docs/{ => Tasks}/Language Support.md (100%) rename docs/{ => Tasks}/Make Examples be based on Database Information.md (100%) rename docs/{ => Tasks}/Make Tests for the Build Calculator.md (100%) rename docs/{ => Tasks}/Make a Plan to Fully Test the Calculator.md (100%) rename docs/{ => Tasks}/Make page object pattern structure for the Build Calculator and all it's components.md (100%) rename docs/{ => Tasks}/More Wait Tests.md (100%) rename docs/{ => Tasks}/Nice looking map refrence.md (100%) rename docs/{ => Tasks}/Plan Calculator.md (100%) rename docs/{ => Tasks}/Remove Items from anywhere in the build calc timeline.md (100%) rename docs/{ => Tasks}/Spells are currently a production item in data. Make the a ability item so they don't show under production table.md (100%) rename docs/{ => Tasks}/Timeline Tests.md (100%) rename docs/{ => Tasks}/Top Borders in Calculator should change based on Selected Faction and Immortal.md (100%) rename docs/{ => Tasks}/Update the Reference Tables with Telerik.md (100%) rename docs/{ => Tasks}/WebAssembly back to Azure.md (100%) rename docs/{ => Tasks}/Worker Income UI and Tests.md (100%) delete mode 100644 docs/Untitled 1.md delete mode 100644 docs/Untitled.md create mode 100644 nginx.conf create mode 100644 serve_publish.cjs diff --git a/.gitignore b/.gitignore index 39bdb4e..6303abf 100644 --- a/.gitignore +++ b/.gitignore @@ -137,6 +137,7 @@ DocProject/Help/html # Click-Once directory publish/ +publish_release/ # Publish Web Output *.[Pp]ublish.xml @@ -264,3 +265,6 @@ __pycache__/ **/.vs/ .DS_Store + + +publish_release/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e6f79af --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +WORKDIR /src +COPY . . +RUN dotnet publish IGP/IGP.csproj -c Release -o /app/publish + +FROM nginx:alpine AS final +WORKDIR /usr/share/nginx/html +COPY --from=build /app/publish/wwwroot ./ +COPY nginx.conf /etc/nginx/nginx.conf diff --git a/IGP.Calculator.Cli/IGP.Calculator.Cli.csproj b/IGP.Calculator.Cli/IGP.Calculator.Cli.csproj new file mode 100644 index 0000000..9d19ccd --- /dev/null +++ b/IGP.Calculator.Cli/IGP.Calculator.Cli.csproj @@ -0,0 +1,16 @@ + + + + Exe + net10.0 + enable + enable + IGP.Calculator.Cli + + + + + + + + diff --git a/IGP.Calculator.Cli/Program.cs b/IGP.Calculator.Cli/Program.cs new file mode 100644 index 0000000..6f0d493 --- /dev/null +++ b/IGP.Calculator.Cli/Program.cs @@ -0,0 +1,158 @@ +using Model.Entity; +using Model.Entity.Data; +using Services; +using Services.Immortal; +using Services.Website; +using IGP.Calculator.Cli.Services; + +var faction = DataType.FACTION_QRath; +var immortal = DataType.IMMORTAL_Orzum; +var attackTime = 1500; +var entityNames = new List(); + +for (var i = 0; i < args.Length; i++) +{ + switch (args[i].ToLower()) + { + case "--faction" when i + 1 < args.Length: + var f = args[++i].ToLower(); + faction = f switch + { + "qrath" => DataType.FACTION_QRath, + "aru" => DataType.FACTION_Aru, + _ => throw new Exception($"Unknown faction '{args[i]}'. Use QRath or Aru.") + }; + immortal = f switch + { + "qrath" => DataType.IMMORTAL_Orzum, + "aru" => DataType.IMMORTAL_Mala, + _ => immortal + }; + break; + case "--immortal" when i + 1 < args.Length: + var im = args[++i]; + immortal = im switch + { + nameof(DataType.IMMORTAL_Orzum) => DataType.IMMORTAL_Orzum, + nameof(DataType.IMMORTAL_Ajari) => DataType.IMMORTAL_Ajari, + nameof(DataType.IMMORTAL_Atzlan) => DataType.IMMORTAL_Atzlan, + nameof(DataType.IMMORTAL_Mala) => DataType.IMMORTAL_Mala, + nameof(DataType.IMMORTAL_Xol) => DataType.IMMORTAL_Xol, + _ => throw new Exception($"Unknown immortal '{im}'.") + }; + break; + case "--attack-time" or "-a" when i + 1 < args.Length: + attackTime = int.Parse(args[++i]); + break; + default: + entityNames.Add(args[i]); + break; + } +} + +var toastService = new ToastService(); +var storageService = new NullStorageService(); +var timingService = new TimingService(storageService); +timingService.SetAttackTime(attackTime); +var buildOrderService = new BuildOrderService(toastService, timingService); +var economyService = new EconomyService(); + +buildOrderService.Reset(faction); +economyService.Calculate(buildOrderService, timingService, 0); + +Console.WriteLine($"Faction: {(faction == DataType.FACTION_QRath ? "Q'Rath" : "Aru")}"); +Console.WriteLine($"Immortal: {immortal.Replace("IMMORTAL_", "")}"); +Console.WriteLine($"Attack Time: {attackTime}s"); +Console.WriteLine(new string('-', 50)); + +foreach (var name in entityNames) +{ + if (name.StartsWith("wait ", StringComparison.OrdinalIgnoreCase)) + { + var seconds = int.Parse(name[5..]); + buildOrderService.AddWait(seconds); + economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval()); + Console.WriteLine($" Wait {seconds}s -> now at interval {buildOrderService.GetLastRequestInterval()}"); + continue; + } + + if (name.StartsWith("waitto ", StringComparison.OrdinalIgnoreCase)) + { + var interval = int.Parse(name[7..]); + buildOrderService.AddWaitTo(interval); + economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval()); + Console.WriteLine($" Wait to {interval}s -> now at interval {buildOrderService.GetLastRequestInterval()}"); + continue; + } + + var entity = FindEntity(name, faction, immortal); + if (entity == null) + { + Console.WriteLine($" ERROR: '{name}' not found for this faction/immortal."); + continue; + } + + var beforeInterval = buildOrderService.GetLastRequestInterval(); + var added = buildOrderService.Add(entity, economyService); + if (added) + { + economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval()); + var startedAt = buildOrderService.GetLastRequestInterval(); + var production = entity.Production(); + var completedAt = production != null ? startedAt + production.BuildTime : startedAt; + var cost = production != null + ? $" [{production.Alloy}a/{production.Ether}e/{production.Pyre}p, {production.BuildTime}s]" + : ""; + Console.WriteLine($" {entity.GetName(),-25} start={startedAt,4}s done={completedAt,4}s{cost}"); + } + else + { + Console.WriteLine($" ERROR: Could not add '{name}'."); + var toasts = toastService.GetToasts(); + if (toasts.Count > 0) + { + var lastToast = toasts[0]; + Console.WriteLine($" Reason: {lastToast.Title} - {lastToast.Message}"); + } + } +} + +Console.WriteLine(new string('-', 50)); + +var lastInterval = buildOrderService.GetLastRequestInterval(); +var finalEconomy = economyService.GetEconomy(timingService.GetAttackTime()); +var lastEconomy = economyService.GetEconomy(lastInterval); + +Console.WriteLine($"Army Attacking At: {timingService.GetAttackTime()}s"); +Console.WriteLine($""); +Console.WriteLine($"At attack time ({timingService.GetAttackTime()}s):"); +Console.WriteLine($" Alloy: {finalEconomy.Alloy,10:F1}"); +Console.WriteLine($" Ether: {finalEconomy.Ether,10:F1}"); +Console.WriteLine($" Pyre: {finalEconomy.Pyre,10:F1}"); +Console.WriteLine($""); +Console.WriteLine($"At last build action ({lastInterval}s):"); +Console.WriteLine($" Alloy: {lastEconomy.Alloy,10:F1}"); +Console.WriteLine($" Ether: {lastEconomy.Ether,10:F1}"); +Console.WriteLine($" Pyre: {lastEconomy.Pyre,10:F1}"); + +static EntityModel? FindEntity(string name, string faction, string immortal) +{ + var candidates = EntityModel.GetList() + .Where(e => e.Info()?.Name?.Equals(name, StringComparison.OrdinalIgnoreCase) == true) + .Where(e => e.Faction()?.Faction == faction) + .ToList(); + + if (candidates.Count == 0) + candidates = EntityModel.GetList() + .Where(e => e.Info()?.Name?.Equals(name, StringComparison.OrdinalIgnoreCase) == true) + .Where(e => e.Faction() == null || e.Faction()!.Faction == DataType.FACTION_Neutral) + .ToList(); + + if (candidates.Count == 0) return null; + if (candidates.Count == 1) return candidates[0]; + + var vanguardMatch = candidates.FirstOrDefault(e => e.VanguardAdded()?.ImmortalId == immortal); + if (vanguardMatch != null) return vanguardMatch; + + return candidates.FirstOrDefault(e => e.VanguardAdded() == null); +} diff --git a/IGP.Calculator.Cli/Services/NullStorageService.cs b/IGP.Calculator.Cli/Services/NullStorageService.cs new file mode 100644 index 0000000..76a4115 --- /dev/null +++ b/IGP.Calculator.Cli/Services/NullStorageService.cs @@ -0,0 +1,25 @@ +using Services; + +namespace IGP.Calculator.Cli.Services; + +public class NullStorageService : IStorageService +{ + private readonly Dictionary _store = new(); + + public void Subscribe(Action action) { } + public void Unsubscribe(Action action) { } + + public T GetValue(string forKey) + { + if (_store.TryGetValue(forKey, out var value) && value is T typed) + return typed; + return default!; + } + + public void SetValue(string key, T value) + { + _store[key] = value; + } + + public Task Load() => Task.CompletedTask; +} diff --git a/IGP/IGP.sln b/IGP/IGP.sln index b2b93e6..8694309 100644 --- a/IGP/IGP.sln +++ b/IGP/IGP.sln @@ -11,28 +11,78 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Components", "..\Components EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Services", "..\Services\Services.csproj", "{621178C8-4E8B-478E-80E5-7478F0E7B67E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IGP.Calculator.Cli", "..\IGP.Calculator.Cli\IGP.Calculator.Cli.csproj", "{9AA71488-E2F5-43C0-8E40-43E72DB2E3CC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {172D35E4-8E7B-40D1-96D6-BE2A2043CFCA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {172D35E4-8E7B-40D1-96D6-BE2A2043CFCA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {172D35E4-8E7B-40D1-96D6-BE2A2043CFCA}.Debug|x64.ActiveCfg = Debug|Any CPU + {172D35E4-8E7B-40D1-96D6-BE2A2043CFCA}.Debug|x64.Build.0 = Debug|Any CPU + {172D35E4-8E7B-40D1-96D6-BE2A2043CFCA}.Debug|x86.ActiveCfg = Debug|Any CPU + {172D35E4-8E7B-40D1-96D6-BE2A2043CFCA}.Debug|x86.Build.0 = Debug|Any CPU {172D35E4-8E7B-40D1-96D6-BE2A2043CFCA}.Release|Any CPU.ActiveCfg = Release|Any CPU {172D35E4-8E7B-40D1-96D6-BE2A2043CFCA}.Release|Any CPU.Build.0 = Release|Any CPU + {172D35E4-8E7B-40D1-96D6-BE2A2043CFCA}.Release|x64.ActiveCfg = Release|Any CPU + {172D35E4-8E7B-40D1-96D6-BE2A2043CFCA}.Release|x64.Build.0 = Release|Any CPU + {172D35E4-8E7B-40D1-96D6-BE2A2043CFCA}.Release|x86.ActiveCfg = Release|Any CPU + {172D35E4-8E7B-40D1-96D6-BE2A2043CFCA}.Release|x86.Build.0 = Release|Any CPU {77395F7A-BE93-470C-9F10-F48FFA445B63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {77395F7A-BE93-470C-9F10-F48FFA445B63}.Debug|Any CPU.Build.0 = Debug|Any CPU + {77395F7A-BE93-470C-9F10-F48FFA445B63}.Debug|x64.ActiveCfg = Debug|Any CPU + {77395F7A-BE93-470C-9F10-F48FFA445B63}.Debug|x64.Build.0 = Debug|Any CPU + {77395F7A-BE93-470C-9F10-F48FFA445B63}.Debug|x86.ActiveCfg = Debug|Any CPU + {77395F7A-BE93-470C-9F10-F48FFA445B63}.Debug|x86.Build.0 = Debug|Any CPU {77395F7A-BE93-470C-9F10-F48FFA445B63}.Release|Any CPU.ActiveCfg = Release|Any CPU {77395F7A-BE93-470C-9F10-F48FFA445B63}.Release|Any CPU.Build.0 = Release|Any CPU + {77395F7A-BE93-470C-9F10-F48FFA445B63}.Release|x64.ActiveCfg = Release|Any CPU + {77395F7A-BE93-470C-9F10-F48FFA445B63}.Release|x64.Build.0 = Release|Any CPU + {77395F7A-BE93-470C-9F10-F48FFA445B63}.Release|x86.ActiveCfg = Release|Any CPU + {77395F7A-BE93-470C-9F10-F48FFA445B63}.Release|x86.Build.0 = Release|Any CPU {0419E7CD-0971-4A56-A61F-C090DF60FAF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0419E7CD-0971-4A56-A61F-C090DF60FAF6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0419E7CD-0971-4A56-A61F-C090DF60FAF6}.Debug|x64.ActiveCfg = Debug|Any CPU + {0419E7CD-0971-4A56-A61F-C090DF60FAF6}.Debug|x64.Build.0 = Debug|Any CPU + {0419E7CD-0971-4A56-A61F-C090DF60FAF6}.Debug|x86.ActiveCfg = Debug|Any CPU + {0419E7CD-0971-4A56-A61F-C090DF60FAF6}.Debug|x86.Build.0 = Debug|Any CPU {0419E7CD-0971-4A56-A61F-C090DF60FAF6}.Release|Any CPU.ActiveCfg = Release|Any CPU {0419E7CD-0971-4A56-A61F-C090DF60FAF6}.Release|Any CPU.Build.0 = Release|Any CPU + {0419E7CD-0971-4A56-A61F-C090DF60FAF6}.Release|x64.ActiveCfg = Release|Any CPU + {0419E7CD-0971-4A56-A61F-C090DF60FAF6}.Release|x64.Build.0 = Release|Any CPU + {0419E7CD-0971-4A56-A61F-C090DF60FAF6}.Release|x86.ActiveCfg = Release|Any CPU + {0419E7CD-0971-4A56-A61F-C090DF60FAF6}.Release|x86.Build.0 = Release|Any CPU {621178C8-4E8B-478E-80E5-7478F0E7B67E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {621178C8-4E8B-478E-80E5-7478F0E7B67E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {621178C8-4E8B-478E-80E5-7478F0E7B67E}.Debug|x64.ActiveCfg = Debug|Any CPU + {621178C8-4E8B-478E-80E5-7478F0E7B67E}.Debug|x64.Build.0 = Debug|Any CPU + {621178C8-4E8B-478E-80E5-7478F0E7B67E}.Debug|x86.ActiveCfg = Debug|Any CPU + {621178C8-4E8B-478E-80E5-7478F0E7B67E}.Debug|x86.Build.0 = Debug|Any CPU {621178C8-4E8B-478E-80E5-7478F0E7B67E}.Release|Any CPU.ActiveCfg = Release|Any CPU {621178C8-4E8B-478E-80E5-7478F0E7B67E}.Release|Any CPU.Build.0 = Release|Any CPU + {621178C8-4E8B-478E-80E5-7478F0E7B67E}.Release|x64.ActiveCfg = Release|Any CPU + {621178C8-4E8B-478E-80E5-7478F0E7B67E}.Release|x64.Build.0 = Release|Any CPU + {621178C8-4E8B-478E-80E5-7478F0E7B67E}.Release|x86.ActiveCfg = Release|Any CPU + {621178C8-4E8B-478E-80E5-7478F0E7B67E}.Release|x86.Build.0 = Release|Any CPU + {9AA71488-E2F5-43C0-8E40-43E72DB2E3CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9AA71488-E2F5-43C0-8E40-43E72DB2E3CC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9AA71488-E2F5-43C0-8E40-43E72DB2E3CC}.Debug|x64.ActiveCfg = Debug|Any CPU + {9AA71488-E2F5-43C0-8E40-43E72DB2E3CC}.Debug|x64.Build.0 = Debug|Any CPU + {9AA71488-E2F5-43C0-8E40-43E72DB2E3CC}.Debug|x86.ActiveCfg = Debug|Any CPU + {9AA71488-E2F5-43C0-8E40-43E72DB2E3CC}.Debug|x86.Build.0 = Debug|Any CPU + {9AA71488-E2F5-43C0-8E40-43E72DB2E3CC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9AA71488-E2F5-43C0-8E40-43E72DB2E3CC}.Release|Any CPU.Build.0 = Release|Any CPU + {9AA71488-E2F5-43C0-8E40-43E72DB2E3CC}.Release|x64.ActiveCfg = Release|Any CPU + {9AA71488-E2F5-43C0-8E40-43E72DB2E3CC}.Release|x64.Build.0 = Release|Any CPU + {9AA71488-E2F5-43C0-8E40-43E72DB2E3CC}.Release|x86.ActiveCfg = Release|Any CPU + {9AA71488-E2F5-43C0-8E40-43E72DB2E3CC}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Model/BuildOrders/BuildOrderModel.cs b/Model/BuildOrders/BuildOrderModel.cs index f147f15..d76838d 100644 --- a/Model/BuildOrders/BuildOrderModel.cs +++ b/Model/BuildOrders/BuildOrderModel.cs @@ -48,7 +48,7 @@ public class BuildOrderModel new List { EntityModel.Get(DataType.STARTING_Bastion), - EntityModel.Get(DataType.STARTING_TownHall_Aru) + EntityModel.Get(factionStartingTownHall) } } }; @@ -59,7 +59,7 @@ public class BuildOrderModel new List { EntityModel.Get(DataType.STARTING_Bastion), - EntityModel.Get(DataType.STARTING_TownHall_Aru) + EntityModel.Get(factionStartingTownHall) } } }; @@ -69,7 +69,7 @@ public class BuildOrderModel DataType.STARTING_Bastion, 0 }, { - DataType.STARTING_TownHall_Aru, 0 + factionStartingTownHall, 0 } }; UniqueCompletedCount = new Dictionary @@ -78,7 +78,7 @@ public class BuildOrderModel DataType.STARTING_Bastion, 1 }, { - DataType.STARTING_TownHall_Aru, 1 + factionStartingTownHall, 1 } }; SupplyCountTimes = new Dictionary diff --git a/Services/IServices.cs b/Services/IServices.cs index 2e679a1..72c9a40 100644 --- a/Services/IServices.cs +++ b/Services/IServices.cs @@ -291,6 +291,7 @@ public interface IBuildOrderService public void RemoveLast(); public void Reset(); + public void Reset(string faction); public int GetLastRequestInterval(); public string BuildOrderAsYaml(); diff --git a/Services/Immortal/BuildOrderService.cs b/Services/Immortal/BuildOrderService.cs index e884ae8..4be1a93 100644 --- a/Services/Immortal/BuildOrderService.cs +++ b/Services/Immortal/BuildOrderService.cs @@ -341,6 +341,13 @@ public class BuildOrderService : IBuildOrderService NotifyDataChanged(); } + public void Reset(string faction) + { + _lastInterval = 0; + _buildOrder.Initialize(faction); + NotifyDataChanged(); + } + public int? WillMeetTrainingQueue(EntityModel entity) { var supply = entity.Supply(); diff --git a/docs/.obsidian/workspace.json b/docs/.obsidian/workspace.json index f4e8def..14d6326 100644 --- a/docs/.obsidian/workspace.json +++ b/docs/.obsidian/workspace.json @@ -56,12 +56,12 @@ "state": { "type": "markdown", "state": { - "file": "Changing Factions and Immortal should clear out build.md", + "file": "Build Calculator CmdLine.md", "mode": "source", "source": false }, "icon": "lucide-file", - "title": "Changing Factions and Immortal should clear out build" + "title": "Build Calculator CmdLine" } } ], @@ -122,7 +122,7 @@ } ], "direction": "horizontal", - "width": 200 + "width": 508.5 }, "right": { "id": "dd7c1dc4bd54d927", @@ -240,41 +240,44 @@ "active": "b98a69cefb529fc8", "lastOpenFiles": [ "_Tasks Kanban.base", - "Helper Tutorial Info Improvements.md", - "Highest Alloy and Ether Tests.md", - "Army Display Split.md", - "Timeline Tests.md", - "Army Calc UI.md", - "Hotkey Tests.md", - "Entity Click View Tests.md", - "Untitled.md", - "Top Borders in Calculator should change based on Selected Faction and Immortal.md", - "Make a Plan to Fully Test the Calculator.md", - "Untitled 1.md", - "Add a Timeline Editor.md", - "Worker Income UI and Tests.md", - "More Wait Tests.md", - "Build Clear should clear out more stuff.md", - "Changing Factions and Immortal should clear out build.md", - "Input building delay should have an effect on when a building is built. Tests against 0, 2, 4, 60.md", - "Ensure build order gets greyed out past the attack time. Clicking the cancel button will wipe the entire greyed out timeline..md", - "Pasted image 20260601093510.png", - "Pasted image 20260601093506.png", - "Pasted image 20260601083333.png", - "Pasted image 20260601083206.png", - "Pasted image 20260601083147.png", - "Pasted image 20260601083127.png", - "Pasted image 20260601083113.png", - "Pasted image 20260601083101.png", - "Pasted image 20260601083046.png", - "Pasted image 20260601083030.png", - "Jenkins CI.md", - "AI Gen Docs/test-network-resilience.md", - "Add some cooldown reference.md", - "Add Co-op objective reference.md", - "Add an Ability to Favourite Data.md", - "AI Gen Docs/test-toast-timing-interactions.md", - "AI Gen Docs/test-visual-regression.md", + "Build Calculator CmdLine.md", + "AI Help Docs/containerize-and-run.md", + "AI Help Docs/publish-and-serve.md", + "AI Gen Docs/test-multi-context-entity-comparison.md", + "AI Gen Docs/services.md", + "AI Gen Docs/recommendations.md", + "AI Gen Docs/development.md", + "AI Gen Docs/architecture.md", + "Images/Pasted image 20260601083005.png", + "Images/Pasted image 20260601082954.png", + "Tasks/Plan Calculator.md", + "Tasks/Remove Items from anywhere in the build calc timeline.md", + "Tasks/Top Borders in Calculator should change based on Selected Faction and Immortal.md", + "Tasks/Update the Reference Tables with Telerik.md", + "Tasks/Worker Income UI and Tests.md", + "Tasks/WebAssembly back to Azure.md", + "Tasks/Spells are currently a production item in data. Make the a ability item so they don't show under production table.md", + "Tasks/Nice looking map refrence.md", + "Tasks/Add an Ability to Favourite Data.md", + "Tasks/Add a Timeline Editor.md", + "Tasks/Add Co-op objective reference.md", + "Tasks/Entity Click View Tests.md", + "Tasks/Make a Plan to Fully Test the Calculator.md", + "Tasks/Make page object pattern structure for the Build Calculator and all it's components.md", + "Tasks/More Wait Tests.md", + "Images/Pasted image 20260601093510.png", + "Tasks/Timeline Tests.md", + "Tasks/Make Tests for the Build Calculator.md", + "Images", + "Images/Pasted image 20260601083019.png", + "Images/Pasted image 20260601083046.png", + "Images/Pasted image 20260601083101.png", + "Images/Pasted image 20260601083113.png", + "Tasks", + "AI Help Docs", + "Images/Pasted image 20260601093506.png", + "Images/Pasted image 20260601083333.png", + "Images/Pasted image 20260601083206.png", "AI Gen Docs", "AI Gen Tasks" ] diff --git a/docs/AI Help Docs/containerize-and-run.md b/docs/AI Help Docs/containerize-and-run.md new file mode 100644 index 0000000..7ba1a38 --- /dev/null +++ b/docs/AI Help Docs/containerize-and-run.md @@ -0,0 +1,62 @@ +# Containerizing the IGP App with Docker + +## Steps Performed + +### 1. Created a Multi‑Stage Dockerfile (`Dockerfile`) + +Two stages: + +| Stage | Image | Purpose | +|---|---|---| +| `build` | `mcr.microsoft.com/dotnet/sdk:10.0` | Restores dependencies, builds, and publishes the Blazor WASM app | +| `final` | `nginx:alpine` | Copies the published `wwwroot/` output and a custom `nginx.conf` that serves it | + +### 2. Created a Custom nginx Config (`nginx.conf`) + +- Listens on port **8887** (not the default 80) so it doesn't conflict with other containers. +- Adds Blazor‑required MIME types: `application/wasm` (`.wasm`), `application/octet-stream` (`.dll`, `.blat`, `.dat`, `.webcil`). +- Enables `gzip_static` so pre‑compressed `.gz` variants are served automatically. +- Implements SPA fallback: `try_files $uri $uri/ /index.html` for client‑side routing. + +### 3. Built the Image + +``` +docker build -t igp-app:latest -f Dockerfile . +``` + +Result: `docker.io/library/igp-app:latest` + +### 4. Ran the Container + +``` +docker run -d --name igp-app -p 8887:8887 igp-app:latest +``` + +The container is now serving at **http://localhost:8887**. + +### 5. Verified + +- `docker ps` shows the container `Up` and port mapping `0.0.0.0:8887->8887/tcp`. +- `curl http://localhost:8887/` returns HTTP `200`. + +## Files + +| File | Purpose | +|---|---| +| `Dockerfile` | Multi‑stage build: .NET SDK → publish → nginx | +| `nginx.conf` | nginx config with Blazor MIME types, gzip, SPA fallback, port 8887 | + +## How to Stop + +``` +docker stop igp-app +docker rm igp-app +``` + +## How to Rebuild + +``` +docker build -t igp-app:latest -f Dockerfile . +docker rm -f igp-app +docker run -d --name igp-app -p 8887:8887 igp-app:latest +``` diff --git a/docs/AI Help Docs/publish-and-serve.md b/docs/AI Help Docs/publish-and-serve.md new file mode 100644 index 0000000..ff35ad1 --- /dev/null +++ b/docs/AI Help Docs/publish-and-serve.md @@ -0,0 +1,51 @@ +# Publishing and Serving the IGP App Locally + +## Steps Performed + +### 1. Publish the Blazor WebAssembly App + +Ran `dotnet publish` targeting Release configuration, outputting to `publish_release/`: + +``` +dotnet publish .\IGP\IGP.csproj -c Release -o .\publish_release +``` + +This produced a standard Blazor WASM publish layout: +- `publish_release/wwwroot/` — static assets (HTML, CSS, JS, WASM, DLLs) +- `publish_release/dotnet.js` — .NET runtime loader +- `publish_release/web.config` — IIS configuration + +### 2. Serve the Published Files on Port 8777 + +Wrote a small Node.js static file server (`serve_publish.cjs`) that: + +- Serves files from `publish_release/wwwroot/` +- Maps correct MIME types for `.wasm` ( `application/wasm` ), `.dll` ( `application/octet-stream` ), `.js` ( `application/javascript` ), `.br`, `.gz` +- Implements SPA fallback: non-file routes serve `index.html` so Blazor's client-side routing works on refresh + +``` +node serve_publish.cjs +``` + +Server is now running at **http://localhost:8777**. + +### 3. Verify + +- `netstat -ano | findstr ":8777"` confirms the process is LISTENING +- `curl -s -o NUL -w "%{http_code}" http://localhost:8777/` returns `200` + +## How to Stop + +Find the process and kill it: + +``` +netstat -ano | findstr ":8777.*LISTENING" +Stop-Process -Id +``` + +## Files + +| File | Purpose | +|---|---| +| `publish_release/wwwroot/` | Published static output | +| `serve_publish.cjs` | Simple Node.js HTTP server with Blazor MIME support | diff --git a/docs/Build Calculator CmdLine.md b/docs/Build Calculator CmdLine.md new file mode 100644 index 0000000..6ae92ba --- /dev/null +++ b/docs/Build Calculator CmdLine.md @@ -0,0 +1,7 @@ +I want you to analyze the BuildCalculator and the services it uses to function. + +Make a cmdline console app with C#, that will allow you to hand in a build order list and have the tool return the Army Attacking At and the displayed Alloy and Ether at the current time interval. + +Try to share the service project. Add new logic where you have to, to make this console specification work. + +Give me example text you would pass in to the console to make a build order that let's say, builds a Legion Hall with two Zentari. \ No newline at end of file diff --git a/docs/Pasted image 20260601082954.png b/docs/Images/Pasted image 20260601082954.png similarity index 100% rename from docs/Pasted image 20260601082954.png rename to docs/Images/Pasted image 20260601082954.png diff --git a/docs/Pasted image 20260601083005.png b/docs/Images/Pasted image 20260601083005.png similarity index 100% rename from docs/Pasted image 20260601083005.png rename to docs/Images/Pasted image 20260601083005.png diff --git a/docs/Pasted image 20260601083019.png b/docs/Images/Pasted image 20260601083019.png similarity index 100% rename from docs/Pasted image 20260601083019.png rename to docs/Images/Pasted image 20260601083019.png diff --git a/docs/Pasted image 20260601083030.png b/docs/Images/Pasted image 20260601083030.png similarity index 100% rename from docs/Pasted image 20260601083030.png rename to docs/Images/Pasted image 20260601083030.png diff --git a/docs/Pasted image 20260601083046.png b/docs/Images/Pasted image 20260601083046.png similarity index 100% rename from docs/Pasted image 20260601083046.png rename to docs/Images/Pasted image 20260601083046.png diff --git a/docs/Pasted image 20260601083101.png b/docs/Images/Pasted image 20260601083101.png similarity index 100% rename from docs/Pasted image 20260601083101.png rename to docs/Images/Pasted image 20260601083101.png diff --git a/docs/Pasted image 20260601083113.png b/docs/Images/Pasted image 20260601083113.png similarity index 100% rename from docs/Pasted image 20260601083113.png rename to docs/Images/Pasted image 20260601083113.png diff --git a/docs/Pasted image 20260601083127.png b/docs/Images/Pasted image 20260601083127.png similarity index 100% rename from docs/Pasted image 20260601083127.png rename to docs/Images/Pasted image 20260601083127.png diff --git a/docs/Pasted image 20260601083147.png b/docs/Images/Pasted image 20260601083147.png similarity index 100% rename from docs/Pasted image 20260601083147.png rename to docs/Images/Pasted image 20260601083147.png diff --git a/docs/Pasted image 20260601083206.png b/docs/Images/Pasted image 20260601083206.png similarity index 100% rename from docs/Pasted image 20260601083206.png rename to docs/Images/Pasted image 20260601083206.png diff --git a/docs/Pasted image 20260601083333.png b/docs/Images/Pasted image 20260601083333.png similarity index 100% rename from docs/Pasted image 20260601083333.png rename to docs/Images/Pasted image 20260601083333.png diff --git a/docs/Pasted image 20260601093506.png b/docs/Images/Pasted image 20260601093506.png similarity index 100% rename from docs/Pasted image 20260601093506.png rename to docs/Images/Pasted image 20260601093506.png diff --git a/docs/Pasted image 20260601093510.png b/docs/Images/Pasted image 20260601093510.png similarity index 100% rename from docs/Pasted image 20260601093510.png rename to docs/Images/Pasted image 20260601093510.png diff --git a/docs/Add Co-op objective reference.md b/docs/Tasks/Add Co-op objective reference.md similarity index 100% rename from docs/Add Co-op objective reference.md rename to docs/Tasks/Add Co-op objective reference.md diff --git a/docs/Add a Timeline Editor.md b/docs/Tasks/Add a Timeline Editor.md similarity index 100% rename from docs/Add a Timeline Editor.md rename to docs/Tasks/Add a Timeline Editor.md diff --git a/docs/Add an Ability to Favourite Data.md b/docs/Tasks/Add an Ability to Favourite Data.md similarity index 100% rename from docs/Add an Ability to Favourite Data.md rename to docs/Tasks/Add an Ability to Favourite Data.md diff --git a/docs/Add some cooldown reference.md b/docs/Tasks/Add some cooldown reference.md similarity index 100% rename from docs/Add some cooldown reference.md rename to docs/Tasks/Add some cooldown reference.md diff --git a/docs/Allow to Always see Advanced Options in Calculator without pressing Space.md b/docs/Tasks/Allow to Always see Advanced Options in Calculator without pressing Space.md similarity index 100% rename from docs/Allow to Always see Advanced Options in Calculator without pressing Space.md rename to docs/Tasks/Allow to Always see Advanced Options in Calculator without pressing Space.md diff --git a/docs/Army Calc UI.md b/docs/Tasks/Army Calc UI.md similarity index 100% rename from docs/Army Calc UI.md rename to docs/Tasks/Army Calc UI.md diff --git a/docs/Army Display Split.md b/docs/Tasks/Army Display Split.md similarity index 100% rename from docs/Army Display Split.md rename to docs/Tasks/Army Display Split.md diff --git a/docs/Auto Build consideration in Calculator.md b/docs/Tasks/Auto Build consideration in Calculator.md similarity index 100% rename from docs/Auto Build consideration in Calculator.md rename to docs/Tasks/Auto Build consideration in Calculator.md diff --git a/docs/Basic Build Order Sheet.md b/docs/Tasks/Basic Build Order Sheet.md similarity index 100% rename from docs/Basic Build Order Sheet.md rename to docs/Tasks/Basic Build Order Sheet.md diff --git a/docs/Build Clear should clear out more stuff.md b/docs/Tasks/Build Clear should clear out more stuff.md similarity index 100% rename from docs/Build Clear should clear out more stuff.md rename to docs/Tasks/Build Clear should clear out more stuff.md diff --git a/docs/Change Ctrl + K Hotkey to something that doesn't conflict with Edge or other browsers.md b/docs/Tasks/Change Ctrl + K Hotkey to something that doesn't conflict with Edge or other browsers.md similarity index 100% rename from docs/Change Ctrl + K Hotkey to something that doesn't conflict with Edge or other browsers.md rename to docs/Tasks/Change Ctrl + K Hotkey to something that doesn't conflict with Edge or other browsers.md diff --git a/docs/Changing Factions and Immortal should clear out build.md b/docs/Tasks/Changing Factions and Immortal should clear out build.md similarity index 100% rename from docs/Changing Factions and Immortal should clear out build.md rename to docs/Tasks/Changing Factions and Immortal should clear out build.md diff --git a/docs/Create Automated Tests.md b/docs/Tasks/Create Automated Tests.md similarity index 100% rename from docs/Create Automated Tests.md rename to docs/Tasks/Create Automated Tests.md diff --git a/docs/Create Mobile Calculator UI.md b/docs/Tasks/Create Mobile Calculator UI.md similarity index 100% rename from docs/Create Mobile Calculator UI.md rename to docs/Tasks/Create Mobile Calculator UI.md diff --git a/docs/Ensure build order gets greyed out past the attack time. Clicking the cancel button will wipe the entire greyed out timeline..md b/docs/Tasks/Ensure build order gets greyed out past the attack time. Clicking the cancel button will wipe the entire greyed out timeline..md similarity index 100% rename from docs/Ensure build order gets greyed out past the attack time. Clicking the cancel button will wipe the entire greyed out timeline..md rename to docs/Tasks/Ensure build order gets greyed out past the attack time. Clicking the cancel button will wipe the entire greyed out timeline..md diff --git a/docs/Entity Click View Tests.md b/docs/Tasks/Entity Click View Tests.md similarity index 100% rename from docs/Entity Click View Tests.md rename to docs/Tasks/Entity Click View Tests.md diff --git a/docs/Fix Entity Recursion Error - Parent.md b/docs/Tasks/Fix Entity Recursion Error - Parent.md similarity index 100% rename from docs/Fix Entity Recursion Error - Parent.md rename to docs/Tasks/Fix Entity Recursion Error - Parent.md diff --git a/docs/Fully Test the Build Calculator.md b/docs/Tasks/Fully Test the Build Calculator.md similarity index 100% rename from docs/Fully Test the Build Calculator.md rename to docs/Tasks/Fully Test the Build Calculator.md diff --git a/docs/Get AI to Add easy Test Tasks.md b/docs/Tasks/Get AI to Add easy Test Tasks.md similarity index 100% rename from docs/Get AI to Add easy Test Tasks.md rename to docs/Tasks/Get AI to Add easy Test Tasks.md diff --git a/docs/Helper Tutorial Info Improvements.md b/docs/Tasks/Helper Tutorial Info Improvements.md similarity index 100% rename from docs/Helper Tutorial Info Improvements.md rename to docs/Tasks/Helper Tutorial Info Improvements.md diff --git a/docs/Highest Alloy and Ether Tests.md b/docs/Tasks/Highest Alloy and Ether Tests.md similarity index 100% rename from docs/Highest Alloy and Ether Tests.md rename to docs/Tasks/Highest Alloy and Ether Tests.md diff --git a/docs/Hotkey Tests.md b/docs/Tasks/Hotkey Tests.md similarity index 100% rename from docs/Hotkey Tests.md rename to docs/Tasks/Hotkey Tests.md diff --git a/docs/Improve your SEO.md b/docs/Tasks/Improve your SEO.md similarity index 100% rename from docs/Improve your SEO.md rename to docs/Tasks/Improve your SEO.md diff --git a/docs/Input building delay should have an effect on when a building is built. Tests against 0, 2, 4, 60.md b/docs/Tasks/Input building delay should have an effect on when a building is built. Tests against 0, 2, 4, 60.md similarity index 100% rename from docs/Input building delay should have an effect on when a building is built. Tests against 0, 2, 4, 60.md rename to docs/Tasks/Input building delay should have an effect on when a building is built. Tests against 0, 2, 4, 60.md diff --git a/docs/Jenkins CI.md b/docs/Tasks/Jenkins CI.md similarity index 100% rename from docs/Jenkins CI.md rename to docs/Tasks/Jenkins CI.md diff --git a/docs/Language Support.md b/docs/Tasks/Language Support.md similarity index 100% rename from docs/Language Support.md rename to docs/Tasks/Language Support.md diff --git a/docs/Make Examples be based on Database Information.md b/docs/Tasks/Make Examples be based on Database Information.md similarity index 100% rename from docs/Make Examples be based on Database Information.md rename to docs/Tasks/Make Examples be based on Database Information.md diff --git a/docs/Make Tests for the Build Calculator.md b/docs/Tasks/Make Tests for the Build Calculator.md similarity index 100% rename from docs/Make Tests for the Build Calculator.md rename to docs/Tasks/Make Tests for the Build Calculator.md diff --git a/docs/Make a Plan to Fully Test the Calculator.md b/docs/Tasks/Make a Plan to Fully Test the Calculator.md similarity index 100% rename from docs/Make a Plan to Fully Test the Calculator.md rename to docs/Tasks/Make a Plan to Fully Test the Calculator.md diff --git a/docs/Make page object pattern structure for the Build Calculator and all it's components.md b/docs/Tasks/Make page object pattern structure for the Build Calculator and all it's components.md similarity index 100% rename from docs/Make page object pattern structure for the Build Calculator and all it's components.md rename to docs/Tasks/Make page object pattern structure for the Build Calculator and all it's components.md diff --git a/docs/More Wait Tests.md b/docs/Tasks/More Wait Tests.md similarity index 100% rename from docs/More Wait Tests.md rename to docs/Tasks/More Wait Tests.md diff --git a/docs/Nice looking map refrence.md b/docs/Tasks/Nice looking map refrence.md similarity index 100% rename from docs/Nice looking map refrence.md rename to docs/Tasks/Nice looking map refrence.md diff --git a/docs/Plan Calculator.md b/docs/Tasks/Plan Calculator.md similarity index 100% rename from docs/Plan Calculator.md rename to docs/Tasks/Plan Calculator.md diff --git a/docs/Remove Items from anywhere in the build calc timeline.md b/docs/Tasks/Remove Items from anywhere in the build calc timeline.md similarity index 100% rename from docs/Remove Items from anywhere in the build calc timeline.md rename to docs/Tasks/Remove Items from anywhere in the build calc timeline.md diff --git a/docs/Spells are currently a production item in data. Make the a ability item so they don't show under production table.md b/docs/Tasks/Spells are currently a production item in data. Make the a ability item so they don't show under production table.md similarity index 100% rename from docs/Spells are currently a production item in data. Make the a ability item so they don't show under production table.md rename to docs/Tasks/Spells are currently a production item in data. Make the a ability item so they don't show under production table.md diff --git a/docs/Timeline Tests.md b/docs/Tasks/Timeline Tests.md similarity index 100% rename from docs/Timeline Tests.md rename to docs/Tasks/Timeline Tests.md diff --git a/docs/Top Borders in Calculator should change based on Selected Faction and Immortal.md b/docs/Tasks/Top Borders in Calculator should change based on Selected Faction and Immortal.md similarity index 100% rename from docs/Top Borders in Calculator should change based on Selected Faction and Immortal.md rename to docs/Tasks/Top Borders in Calculator should change based on Selected Faction and Immortal.md diff --git a/docs/Update the Reference Tables with Telerik.md b/docs/Tasks/Update the Reference Tables with Telerik.md similarity index 100% rename from docs/Update the Reference Tables with Telerik.md rename to docs/Tasks/Update the Reference Tables with Telerik.md diff --git a/docs/WebAssembly back to Azure.md b/docs/Tasks/WebAssembly back to Azure.md similarity index 100% rename from docs/WebAssembly back to Azure.md rename to docs/Tasks/WebAssembly back to Azure.md diff --git a/docs/Worker Income UI and Tests.md b/docs/Tasks/Worker Income UI and Tests.md similarity index 100% rename from docs/Worker Income UI and Tests.md rename to docs/Tasks/Worker Income UI and Tests.md diff --git a/docs/Untitled 1.md b/docs/Untitled 1.md deleted file mode 100644 index cac4e10..0000000 --- a/docs/Untitled 1.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Task -status: -category: ---- diff --git a/docs/Untitled.md b/docs/Untitled.md deleted file mode 100644 index cac4e10..0000000 --- a/docs/Untitled.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Task -status: -category: ---- diff --git a/docs/_Tasks Kanban.base b/docs/_Tasks Kanban.base index 411341f..3dfaf9c 100644 --- a/docs/_Tasks Kanban.base +++ b/docs/_Tasks Kanban.base @@ -23,7 +23,6 @@ views: - Done - AI Agent Work - AI Gen TODO - - Uncategorized cardOrders: file.file: Untitled.base: [] @@ -56,8 +55,8 @@ views: - More Wait Tests.md - Timeline Tests.md Working On: - - Helper Tutorial Info Improvements.md - Changing Factions and Immortal should clear out build.md + - Helper Tutorial Info Improvements.md - Highest Alloy and Ether Tests.md Backlog: - Fully Test the Build Calculator.md diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..b2abc29 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,27 @@ +events { } + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + types { + application/wasm wasm; + application/octet-stream dll blat dat webcil; + application/gzip gz; + } + + server { + listen 8887; + server_name localhost; + + root /usr/share/nginx/html; + index index.html; + + gzip_static on; + gzip_types application/wasm application/octet-stream application/json text/html text/css application/javascript; + + location / { + try_files $uri $uri/ /index.html; + } + } +} diff --git a/serve_publish.cjs b/serve_publish.cjs new file mode 100644 index 0000000..c1c1c53 --- /dev/null +++ b/serve_publish.cjs @@ -0,0 +1,48 @@ +const http = require('http'); +const fs = require('fs'); +const path = require('path'); + +const PORT = 8777; +const ROOT = path.join(__dirname, 'publish_release', 'wwwroot'); + +const MIME = { + '.html': 'text/html', + '.js': 'application/javascript', + '.wasm': 'application/wasm', + '.dll': 'application/octet-stream', + '.css': 'text/css', + '.png': 'image/png', + '.jpg': 'image/jpeg', + '.svg': 'image/svg+xml', + '.ico': 'image/x-icon', + '.json': 'application/json', + '.br': 'application/octet-stream', + '.gz': 'application/gzip', +}; + +const server = http.createServer((req, res) => { + let filePath = path.join(ROOT, req.url === '/' ? 'index.html' : req.url); + const ext = path.extname(filePath); + + fs.readFile(filePath, (err, data) => { + if (err) { + // SPA fallback: serve index.html for non-file routes + fs.readFile(path.join(ROOT, 'index.html'), (err2, data2) => { + if (err2) { + res.writeHead(404); + res.end('Not found'); + return; + } + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end(data2); + }); + return; + } + res.writeHead(200, { 'Content-Type': MIME[ext] || 'application/octet-stream' }); + res.end(data); + }); +}); + +server.listen(PORT, () => { + console.log(`Serving IGP publish on http://localhost:${PORT}`); +}); -- 2.43.0