...
This commit is contained in:
@@ -76,6 +76,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Components\Components.csproj"/>
|
<ProjectReference Include="..\Components\Components.csproj"/>
|
||||||
<ProjectReference Include="..\Model\Model.csproj"/>
|
<ProjectReference Include="..\Model\Model.csproj"/>
|
||||||
|
<ProjectReference Include="..\Pages\Pages.csproj"/>
|
||||||
<ProjectReference Include="..\Services\Services.csproj"/>
|
<ProjectReference Include="..\Services\Services.csproj"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
<a href="@Href" class="contentHighlight">
|
|
||||||
<div class="contentHighlightTitle">
|
|
||||||
@Title
|
|
||||||
</div>
|
|
||||||
<img width="268px" height="161px" src="@ImageHref" class="contentHighlightImage" alt="@Title"/>
|
|
||||||
<div class="contentHighlightCallToAction">
|
|
||||||
@Description
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.contentHighlight {
|
|
||||||
background-color: var(--paper);
|
|
||||||
border: 1px solid var(--paper-border);
|
|
||||||
border-radius: 2px;
|
|
||||||
padding-left: 12px;
|
|
||||||
padding-right: 12px;
|
|
||||||
padding-top: 24px;
|
|
||||||
padding-bottom: 24px;
|
|
||||||
color: white;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 12px;
|
|
||||||
text-align: center;
|
|
||||||
margin-left: 12px;
|
|
||||||
margin-right: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contentHighlight:hover {
|
|
||||||
background-color: var(--paper-hover);
|
|
||||||
border-color: var(--paper-border-hover);
|
|
||||||
text-decoration: none;
|
|
||||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.6);
|
|
||||||
transform: translateY(-2px) scale(1.01);
|
|
||||||
}
|
|
||||||
|
|
||||||
.contentHighlightTitle {
|
|
||||||
font-weight: 800;
|
|
||||||
font-size: 1.3rem;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contentHighlightImage {
|
|
||||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
|
||||||
box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.5);
|
|
||||||
width: calc(100% - 32px);
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
margin-top: 12px;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contentHighlightCallToAction {
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
margin: auto;
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Parameter] public string Href { get; set; } = default!;
|
|
||||||
|
|
||||||
[Parameter] public string Title { get; set; } = default!;
|
|
||||||
|
|
||||||
[Parameter] public string Description { get; set; } = default!;
|
|
||||||
|
|
||||||
[Parameter] public string ImageHref { get; set; } = default!;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
<LayoutMediumContentComponent>
|
|
||||||
<PaperComponent>
|
|
||||||
<div class="mainContainer">
|
|
||||||
<div class="mainTitle">
|
|
||||||
IGP Fan Reference
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Refer to various aspects of "IMMORTAL: Gates of Pyre" from this external reference!
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</PaperComponent>
|
|
||||||
<ContentDividerComponent></ContentDividerComponent>
|
|
||||||
<PaperComponent>
|
|
||||||
<div class="heroesContainer">
|
|
||||||
<ContentHighlightComponent Title="Build Calculator"
|
|
||||||
Description="Make a build!"
|
|
||||||
Href="https://igpfanreference.ca/build-calculator"
|
|
||||||
ImageHref="image/hero/Build.png"/>
|
|
||||||
<ContentHighlightComponent Title="Database"
|
|
||||||
Description="Review the units!"
|
|
||||||
Href="https://igpfanreference.ca/database"
|
|
||||||
ImageHref="image/hero/Database.png"/>
|
|
||||||
</div>
|
|
||||||
</PaperComponent>
|
|
||||||
</LayoutMediumContentComponent>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.mainContainer {
|
|
||||||
padding-bottom: 32px;
|
|
||||||
}
|
|
||||||
.mainTitle {
|
|
||||||
font-size: 2.2rem;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.heroesContainer {
|
|
||||||
display: grid;
|
|
||||||
gap: 64px;
|
|
||||||
justify-content: center;
|
|
||||||
margin: auto;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
}
|
|
||||||
@@media only screen and (max-width: 1025px) {
|
|
||||||
.heroesContainer {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -5,7 +5,9 @@
|
|||||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||||
@using Microsoft.JSInterop
|
@using Microsoft.JSInterop
|
||||||
@using Device
|
@using Device
|
||||||
@using Device.Pages
|
@using IGP.Pages
|
||||||
|
@using IGP.Pages.Home
|
||||||
|
@using IGP.Pages.Home.Parts
|
||||||
|
|
||||||
@using Components.Display
|
@using Components.Display
|
||||||
@using Components.Feedback
|
@using Components.Feedback
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "API", "API\API.csproj", "{6
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Device", "Device\Device.csproj", "{FF07C814-9757-48B5-8450-CFA4958EC42D}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Device", "Device\Device.csproj", "{FF07C814-9757-48B5-8450-CFA4958EC42D}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pages", "Pages\Pages.csproj", "{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -125,6 +127,18 @@ Global
|
|||||||
{FF07C814-9757-48B5-8450-CFA4958EC42D}.Release|x64.Build.0 = Release|Any CPU
|
{FF07C814-9757-48B5-8450-CFA4958EC42D}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{FF07C814-9757-48B5-8450-CFA4958EC42D}.Release|x86.ActiveCfg = Release|Any CPU
|
{FF07C814-9757-48B5-8450-CFA4958EC42D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{FF07C814-9757-48B5-8450-CFA4958EC42D}.Release|x86.Build.0 = Release|Any CPU
|
{FF07C814-9757-48B5-8450-CFA4958EC42D}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ public class WebsiteData
|
|||||||
* Flag for content generated by the AI. Can contain UI that makes no sense, or more importantly,
|
* Flag for content generated by the AI. Can contain UI that makes no sense, or more importantly,
|
||||||
* game data that is not real. Fun to look at, but needs to be thoroughly vetted before it can ever go live.
|
* game data that is not real. Fun to look at, but needs to be thoroughly vetted before it can ever go live.
|
||||||
*/
|
*/
|
||||||
public static bool allowSlopData { get; set; } = false;
|
public static bool allowSlopData { get; set; } = true;
|
||||||
|
|
||||||
private static bool IsPageAllowed(WebPageModel page)
|
private static bool IsPageAllowed(WebPageModel page)
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@
|
|||||||
<Found Context="routeData">
|
<Found Context="routeData">
|
||||||
@if (isLoaded)
|
@if (isLoaded)
|
||||||
{
|
{
|
||||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
|
<RouteView RouteData="@routeData" DefaultLayout="@typeof(PageLayout)"/>
|
||||||
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
|
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
|
||||||
}
|
}
|
||||||
</Found>
|
</Found>
|
||||||
|
|||||||
Generated
-114
@@ -1,114 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
// <auto-generated>
|
|
||||||
// This code was generated by a tool.
|
|
||||||
//
|
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
|
||||||
// the code is regenerated.
|
|
||||||
// </auto-generated>
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace IGP {
|
|
||||||
using System;
|
|
||||||
|
|
||||||
|
|
||||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
|
||||||
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
|
||||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
|
||||||
internal class Localizations {
|
|
||||||
|
|
||||||
private static System.Resources.ResourceManager resourceMan;
|
|
||||||
|
|
||||||
private static System.Globalization.CultureInfo resourceCulture;
|
|
||||||
|
|
||||||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
|
||||||
internal Localizations() {
|
|
||||||
}
|
|
||||||
|
|
||||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
|
|
||||||
internal static System.Resources.ResourceManager ResourceManager {
|
|
||||||
get {
|
|
||||||
if (object.Equals(null, resourceMan)) {
|
|
||||||
System.Resources.ResourceManager temp = new System.Resources.ResourceManager("IGP.Localizations", typeof(Localizations).Assembly);
|
|
||||||
resourceMan = temp;
|
|
||||||
}
|
|
||||||
return resourceMan;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
|
|
||||||
internal static System.Globalization.CultureInfo Culture {
|
|
||||||
get {
|
|
||||||
return resourceCulture;
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
resourceCulture = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string Greeting {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("Greeting", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string Tooltip_Chart_Info {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("Tooltip Chart Info", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string Tooltip_Filter_Info {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("Tooltip Filter Info", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string Tooltip_Entity_Info {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("Tooltip Entity Info", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string Tooltip_Bank_Info {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("Tooltip Bank Info", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string Tooltip_Army_Info {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("Tooltip Army Info", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string Tooltip_Highlights_Info {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("Tooltip Highlights Info", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string Tooltip_BuildOrder_Info {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("Tooltip BuildOrder Info", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string Tooltip_Timing_Info {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("Tooltip Timing Info", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string Tooltip_Hotkey_Info {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("Tooltip Hotkey Info", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string Tooltip_Options_Info {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("Tooltip Options Info", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<root>
|
|
||||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
|
|
||||||
id="root"
|
|
||||||
xmlns="">
|
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
|
||||||
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:schema>
|
|
||||||
<resheader name="resmimetype">
|
|
||||||
<value>text/microsoft-resx</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="version">
|
|
||||||
<value>1.3</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="reader">
|
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
|
||||||
PublicKeyToken=b77a5c561934e089
|
|
||||||
</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="writer">
|
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
|
|
||||||
PublicKeyToken=b77a5c561934e089
|
|
||||||
</value>
|
|
||||||
</resheader>
|
|
||||||
<data name="Greeting" xml:space="preserve">
|
|
||||||
<value>Hello</value>
|
|
||||||
</data>
|
|
||||||
|
|
||||||
<data name="Tooltip Chart Info" xml:space="preserve">
|
|
||||||
<value>Shows economy at each game interval. Use to determine if spending additional resources on harvesters will help or hinder overall timing attack.</value>
|
|
||||||
</data>
|
|
||||||
|
|
||||||
<data name="Tooltip Filter Info" xml:space="preserve">
|
|
||||||
<value>Select build details, such as Faction and Immortal.
|
|
||||||
|
|
||||||
Affects entities you can build.</value>
|
|
||||||
</data>
|
|
||||||
<data name="Tooltip Entity Info" xml:space="preserve">
|
|
||||||
<value>Summary of the entity you just selected.</value>
|
|
||||||
</data>
|
|
||||||
<data name="Tooltip Bank Info" xml:space="preserve">
|
|
||||||
<value>Bank at time of last requested action. Use this section to determine if your build is floating too much alloy or ether.</value>
|
|
||||||
</data>
|
|
||||||
<data name="Tooltip Army Info" xml:space="preserve">
|
|
||||||
<value>Overview of current army, and when it will be ready to begin an attack.</value>
|
|
||||||
</data>
|
|
||||||
<data name="Tooltip Highlights Info" xml:space="preserve">
|
|
||||||
<value>Timeline highlights of your build order. Shows when you start a new action and when the action is done.</value>
|
|
||||||
</data>
|
|
||||||
<data name="Tooltip BuildOrder Info" xml:space="preserve">
|
|
||||||
<value>Some raw JSON data to represent your build order.</value>
|
|
||||||
</data>
|
|
||||||
<data name="Tooltip Timing Info" xml:space="preserve">
|
|
||||||
<value>Enter build details.</value>
|
|
||||||
</data>
|
|
||||||
<data name="Tooltip Hotkey Info" xml:space="preserve">
|
|
||||||
<value>Click on the desired entity to build it. <i>You cannot build entities you cannot afford, construct an ether extractor before spending ether.</i>
|
|
||||||
|
|
||||||
You can also use the default Immortal hotkeys, but the above hotkey UI must have focus for this to work. <i>I.e. click on it if hotkeys aren't working, and a white border should appear after key input to indicate focus.</i>
|
|
||||||
|
|
||||||
Additionally, more entities will appear as you build the required technology. You can click or press ` to remove the last made entity. <i>But you cannot remove the starting entities at interval 0.</i></value>
|
|
||||||
</data>
|
|
||||||
<data name="Tooltip Options Info" xml:space="preserve">
|
|
||||||
<value>Misc calculator controls.</value>
|
|
||||||
</data>
|
|
||||||
</root>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
@layout PageLayout
|
|
||||||
|
|
||||||
@inherits BasePage
|
|
||||||
|
|
||||||
@inject IDataCollectionService DataCollectionService
|
|
||||||
|
|
||||||
|
|
||||||
@page "/about"
|
|
||||||
|
|
||||||
<LayoutMediumContentComponent>
|
|
||||||
<WebsiteTitleComponent>About</WebsiteTitleComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
What is this website for?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
This is just a "yet another third-party tool" website for a video game. If you played a game like Path
|
|
||||||
of Exile, you are probably already used to seeing a bunch of said tools.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
So what is <i>this</i> specific tool for?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
Ideally, this website will be a casual reference, for getting started with understanding the themes and
|
|
||||||
game patterns of IMMORTAL: Gates of Pyre. That said, this tool is currently not near to achieving said
|
|
||||||
goal. In the meantime, you can check out the simple calculator and database tools on this website.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
The game hasn't even been released. Isn't it a bit early for publishing community tools?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
Maybe 🙂
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
Any disclaimers?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
This website has no association with "SunSpear Games." Beyond that, any game data displayed on this
|
|
||||||
website for "IMMORTAL: Gates of Pyre" may be inaccurate due to my own human error and time limitations.
|
|
||||||
Use with caution.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
</PaperComponent>
|
|
||||||
</LayoutMediumContentComponent>
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
@using Services.Website
|
|
||||||
@inject IDataCollectionService DataCollectionService
|
|
||||||
@inject NavigationManager NavigationManager
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
|
|
||||||
CollectLoadedPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CollectLoadedPage()
|
|
||||||
{
|
|
||||||
var skipBaseUri = NavigationManager.Uri.Substring(NavigationManager.BaseUri.Length,
|
|
||||||
NavigationManager.Uri.Length - NavigationManager.BaseUri.Length);
|
|
||||||
|
|
||||||
var splitData = skipBaseUri.Split("/");
|
|
||||||
|
|
||||||
var rootUrl = splitData.First();
|
|
||||||
if (rootUrl.Trim().Equals(""))
|
|
||||||
{
|
|
||||||
rootUrl = "home";
|
|
||||||
}
|
|
||||||
|
|
||||||
var eventData = new Dictionary<string, string> { { "page", rootUrl } };
|
|
||||||
if (splitData.Length > 1)
|
|
||||||
{
|
|
||||||
eventData["inner-page"] = splitData.Last();
|
|
||||||
}
|
|
||||||
|
|
||||||
DataCollectionService.SendEvent(DataCollectionKeys.PageInitialized, eventData);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,296 +0,0 @@
|
|||||||
@layout PageLayout
|
|
||||||
|
|
||||||
@inherits BasePage
|
|
||||||
|
|
||||||
@inject IStringLocalizer<Localizations> Locale
|
|
||||||
|
|
||||||
@inject IKeyService KeyService
|
|
||||||
@inject IImmortalSelectionService FilterService
|
|
||||||
@inject IBuildOrderService BuildOrderService
|
|
||||||
@inject IEconomyService EconomyService
|
|
||||||
@inject IToastService ToastService
|
|
||||||
@inject ITimingService TimingService
|
|
||||||
@inject IDataCollectionService DataCollectionService
|
|
||||||
|
|
||||||
@page "/build-calculator"
|
|
||||||
@using IGP.Pages.BuildCalculator.Parts.Cosmetic
|
|
||||||
@using Services.Website
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
<LayoutLargeContentComponent>
|
|
||||||
<WebsiteTitleComponent>Build Calculator</WebsiteTitleComponent>
|
|
||||||
|
|
||||||
<ContentDividerComponent></ContentDividerComponent>
|
|
||||||
|
|
||||||
<div class="calculatorGrid">
|
|
||||||
<div class="gridItem" style="grid-area: timing;">
|
|
||||||
<PanelComponent>
|
|
||||||
<InfoTooltipComponent InfoText="@Locale["Tooltip Filter Info"]">
|
|
||||||
<FactionBorderComponent>
|
|
||||||
<FilterComponent></FilterComponent>
|
|
||||||
</FactionBorderComponent>
|
|
||||||
</InfoTooltipComponent>
|
|
||||||
</PanelComponent>
|
|
||||||
|
|
||||||
<ButtonComponent MyButtonType="MyButtonType.Secondary" OnClick="OnResetClicked">Clear Build Order
|
|
||||||
</ButtonComponent>
|
|
||||||
<PanelComponent>
|
|
||||||
<InfoTooltipComponent InfoText="@Locale["Tooltip Timing Info"]">
|
|
||||||
<TimingComponent></TimingComponent>
|
|
||||||
</InfoTooltipComponent>
|
|
||||||
</PanelComponent>
|
|
||||||
|
|
||||||
<PanelComponent>
|
|
||||||
<InfoTooltipComponent InfoText="@Locale["Tooltip Options Info"]">
|
|
||||||
<OptionsComponent></OptionsComponent>
|
|
||||||
</InfoTooltipComponent>
|
|
||||||
</PanelComponent>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="gridItem" style="grid-area: chart;">
|
|
||||||
<PanelComponent>
|
|
||||||
<InfoTooltipComponent InfoText="@Locale["Tooltip Chart Info"]">
|
|
||||||
<BuildChartComponent></BuildChartComponent>
|
|
||||||
</InfoTooltipComponent>
|
|
||||||
</PanelComponent>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gridItem" style="grid-area: view;">
|
|
||||||
<PanelComponent>
|
|
||||||
<InfoTooltipComponent InfoText="@Locale["Tooltip Entity Info"]">
|
|
||||||
<ImmortalBorderComponent>
|
|
||||||
<EntityClickViewComponent/>
|
|
||||||
</ImmortalBorderComponent>
|
|
||||||
</InfoTooltipComponent>
|
|
||||||
|
|
||||||
</PanelComponent>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gridItem" style="grid-area: bank;">
|
|
||||||
<PanelComponent>
|
|
||||||
<InfoTooltipComponent InfoText="@Locale["Tooltip Bank Info"]">
|
|
||||||
<BankComponent></BankComponent>
|
|
||||||
</InfoTooltipComponent>
|
|
||||||
</PanelComponent>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gridItem" style="grid-area: army;">
|
|
||||||
<PanelComponent>
|
|
||||||
<InfoTooltipComponent InfoText="@Locale["Tooltip Army Info"]">
|
|
||||||
<ArmyComponent></ArmyComponent>
|
|
||||||
</InfoTooltipComponent>
|
|
||||||
</PanelComponent>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gridItem gridKeys">
|
|
||||||
<PanelComponent>
|
|
||||||
<InfoTooltipComponent InfoText="@Locale["Tooltip Hotkey Info"]">
|
|
||||||
<HotkeyViewerComponent Size="80"></HotkeyViewerComponent>
|
|
||||||
</InfoTooltipComponent>
|
|
||||||
</PanelComponent>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gridItem" style="grid-area: highlights;">
|
|
||||||
<PanelComponent>
|
|
||||||
<InfoTooltipComponent InfoText="@Locale["Tooltip Highlights Info"]">
|
|
||||||
<HighlightsComponent></HighlightsComponent>
|
|
||||||
</InfoTooltipComponent>
|
|
||||||
</PanelComponent>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gridItem" style="grid-area: buildorder;">
|
|
||||||
<PanelComponent>
|
|
||||||
<InfoTooltipComponent InfoText="@Locale["Tooltip BuildOrder Info"]">
|
|
||||||
<BuildOrderComponent></BuildOrderComponent>
|
|
||||||
</InfoTooltipComponent>
|
|
||||||
</PanelComponent>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ContentDividerComponent></ContentDividerComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
What is this tool?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
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.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
How does it work?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
The tool calculates every second of game time. So if you attempt to build a <b>Legion Hall</b> 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.
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
If you then build 2 <b>Apostle of Bindings</b> a <b>Soul Foundry</b> and a 3 <b>Absolvers</b> you
|
|
||||||
should see yourself roughly floating 500 alloy, with barely having any ether. Which means you could
|
|
||||||
of gotten an <b>Acropolis</b> and a <b>Zentari</b> without hurting your build.
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
Try building <b>Apostle of Bindings</b> before the <b>Legion Hall</b> and see how that changes the
|
|
||||||
timing of your 3 <b>Absolvers</b>. (Spoiler:
|
|
||||||
<SpoilerTextComponent> your <b>Absolvers</b> will be built much faster, and you won't be floating so
|
|
||||||
much alloy.
|
|
||||||
</SpoilerTextComponent>
|
|
||||||
)
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
What is CONTROL key for?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
Economy and tech related upgrades for townhalls.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
What is SHIFT key for?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
Misc building related upgrades. (Omnivores)
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
What is 2 key for?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
It will be for Pyre camps. Currently not implemented.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
</PaperComponent>
|
|
||||||
</LayoutLargeContentComponent>
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.gridItem {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.calculatorGrid {
|
|
||||||
display: grid;
|
|
||||||
gap: 8px;
|
|
||||||
max-width: 90vw;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
|
||||||
grid-template-rows: 600px 400px 450px;
|
|
||||||
grid-template-areas:
|
|
||||||
'timing view view view'
|
|
||||||
'timing bank army army'
|
|
||||||
'keys keys highlights buildorder'
|
|
||||||
'chart chart chart chart';
|
|
||||||
}
|
|
||||||
|
|
||||||
.gridKeys {
|
|
||||||
grid-area: keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media only screen and (max-width: 1025px) {
|
|
||||||
.gridKeys {
|
|
||||||
background-color: #282A30;
|
|
||||||
}
|
|
||||||
|
|
||||||
.calculatorGrid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
grid-template-rows: auto;
|
|
||||||
grid-template-areas:
|
|
||||||
'timing'
|
|
||||||
'view'
|
|
||||||
'keys'
|
|
||||||
'bank'
|
|
||||||
'army'
|
|
||||||
'highlights'
|
|
||||||
'buildorder'
|
|
||||||
'chart';
|
|
||||||
padding-left: 2px;
|
|
||||||
padding-right: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
|
|
||||||
EconomyService.Calculate(BuildOrderService, TimingService, 0);
|
|
||||||
|
|
||||||
KeyService.Subscribe(HandleClick);
|
|
||||||
|
|
||||||
DataCollectionService.SendEvent(
|
|
||||||
DataCollectionKeys.PageInitialized,
|
|
||||||
new Dictionary<string, string> { { "page", "build-calculator" } }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
KeyService.Unsubscribe(HandleClick);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnResetClicked()
|
|
||||||
{
|
|
||||||
ToastService.AddToast(new ToastModel
|
|
||||||
{
|
|
||||||
SeverityType = SeverityType.Success,
|
|
||||||
Message = "Build order has been cleared.",
|
|
||||||
Title = "Reset"
|
|
||||||
});
|
|
||||||
|
|
||||||
BuildOrderService.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void HandleClick()
|
|
||||||
{
|
|
||||||
var hotkey = KeyService.GetHotkey();
|
|
||||||
|
|
||||||
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.GetFaction();
|
|
||||||
var immortal = FilterService.GetImmortal();
|
|
||||||
|
|
||||||
var entity = EntityModel.GetFrom(hotkey!, hotkeyGroup, isHoldSpace, faction, immortal);
|
|
||||||
|
|
||||||
if (entity == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BuildOrderService.Add(entity, EconomyService))
|
|
||||||
{
|
|
||||||
EconomyService.Calculate(BuildOrderService, TimingService, BuildOrderService.GetLastRequestInterval());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
@inject IJSRuntime jsRuntime
|
|
||||||
|
|
||||||
@inject IBuildOrderService buildOrder
|
|
||||||
@inject ITimingService timingService
|
|
||||||
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
<div class="armyView">
|
|
||||||
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<div style="display: flex; gap: 24px;">
|
|
||||||
<FormDisplayComponent Label="Army Completed At">
|
|
||||||
<Display>@lastInterval | T @Interval.ToTime(lastInterval)</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
<FormDisplayComponent Label="Army Attacking At">
|
|
||||||
<Display>@(lastInterval + timingService.GetTravelTime()) |
|
|
||||||
T @Interval.ToTime(lastInterval + timingService.GetTravelTime())</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
</div>
|
|
||||||
<FormDisplayComponent Label="Army units built">
|
|
||||||
<Display>
|
|
||||||
<div class="armyCardsContainer">
|
|
||||||
@foreach (var unit in armyCount)
|
|
||||||
{
|
|
||||||
<div class="armyCard">
|
|
||||||
<div class="armyCountPosition">
|
|
||||||
<div class="armyCount">@unit.Value.ToString()x</div>
|
|
||||||
</div>
|
|
||||||
<div>@unit.Key</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.armyView {
|
|
||||||
overflow-y: scroll;
|
|
||||||
width: 100%;
|
|
||||||
overflow-x: hidden;
|
|
||||||
height: 350px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.armyCardsContainer {
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
gap: 16px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.armyCard {
|
|
||||||
width: 100px;
|
|
||||||
height: 80px;
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.armyCountPosition {
|
|
||||||
height: 0;
|
|
||||||
top: -20px;
|
|
||||||
left: -16px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.armyCount {
|
|
||||||
font-weight: bolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private int lastInterval;
|
|
||||||
|
|
||||||
readonly Dictionary<string, int> armyCount = new();
|
|
||||||
|
|
||||||
List<EntityModel> army = new();
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
buildOrder.Subscribe(OnBuildOrderChanged);
|
|
||||||
timingService.Subscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
buildOrder.Unsubscribe(OnBuildOrderChanged);
|
|
||||||
timingService.Unsubscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
var armyCountWas = 0;
|
|
||||||
foreach (var army in armyCount)
|
|
||||||
{
|
|
||||||
armyCountWas += army.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
armyCount.Clear();
|
|
||||||
|
|
||||||
lastInterval = 0;
|
|
||||||
|
|
||||||
var entitiesOverTime = buildOrder.GetOrders();
|
|
||||||
|
|
||||||
foreach (var entitiesAtTime in entitiesOverTime)
|
|
||||||
{
|
|
||||||
foreach (var entity in entitiesAtTime.Value)
|
|
||||||
{
|
|
||||||
if (entity.EntityType == EntityType.Army)
|
|
||||||
{
|
|
||||||
if (!armyCount.TryAdd(entity.Info().Name, 1))
|
|
||||||
{
|
|
||||||
armyCount[entity.Info().Name]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity.Production() != null && entity.Production().BuildTime + entitiesAtTime.Key > lastInterval)
|
|
||||||
{
|
|
||||||
lastInterval = entity.Production().BuildTime + entitiesAtTime.Key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO Better
|
|
||||||
var armyCountIs = 0;
|
|
||||||
foreach (var army in armyCount)
|
|
||||||
{
|
|
||||||
armyCountIs += army.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (armyCountWas != armyCountIs)
|
|
||||||
{
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
@inject IJSRuntime jsRuntime;
|
|
||||||
|
|
||||||
@inject IEconomyService economyService
|
|
||||||
|
|
||||||
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
<div class="bankContainer">
|
|
||||||
<FormDisplayComponent Label="Time">
|
|
||||||
<Display>@(BuildOrderService.GetLastRequestInterval() + 1) |
|
|
||||||
T @Interval.ToTime(BuildOrderService.GetLastRequestInterval() + 1)</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
<div class="bankRow">
|
|
||||||
<FormDisplayComponent Label="Alloy">
|
|
||||||
<Display>@_economy.Alloy +@_economy.AlloyIncome</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
<FormDisplayComponent Label="Ether">
|
|
||||||
<Display>@Math.Round(_economy.Ether) +@Math.Round(_economy.EtherIncome)</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
</div>
|
|
||||||
<div class="bankRow">
|
|
||||||
<FormDisplayComponent Label="Pyre">
|
|
||||||
<Display>@_economy.Pyre</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
<FormDisplayComponent Label="Supply">
|
|
||||||
<Display>@_supplyTaken / @_supplyGranted (@(_supplyGranted / 16)@(_extraBuildings > 0 ? "+" + _extraBuildings : ""))</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div class="workerText">Workers</div>
|
|
||||||
<div class="bankRow">
|
|
||||||
<FormDisplayComponent Label="Current">
|
|
||||||
<Display>@_economy.WorkerCount</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
<FormDisplayComponent Label="Busy">
|
|
||||||
<Display>@_economy.BusyWorkerCount</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
<FormDisplayComponent Label="Creating">
|
|
||||||
<Display>@_economy.CreatingWorkerCount</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.bankContainer {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.workerText {
|
|
||||||
margin-bottom: -2px;
|
|
||||||
font-size: 0.8em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bankRow {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Inject] IBuildOrderService BuildOrderService { get; set; } = default!;
|
|
||||||
|
|
||||||
[Inject] IEconomyService EconomyService { get; set; } = default!;
|
|
||||||
|
|
||||||
EconomyModel _economy = new();
|
|
||||||
int _supplyGranted;
|
|
||||||
int _supplyTaken;
|
|
||||||
int _extraBuildings;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
BuildOrderService.Subscribe(OnBuildOrderChanged);
|
|
||||||
|
|
||||||
|
|
||||||
_economy = EconomyService.GetEconomy(BuildOrderService.GetLastRequestInterval() + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnBuildOrderChanged()
|
|
||||||
{
|
|
||||||
_economy = EconomyService.GetEconomy(BuildOrderService.GetLastRequestInterval() + 1);
|
|
||||||
|
|
||||||
var ordersOverTime = BuildOrderService.GetOrders();
|
|
||||||
|
|
||||||
_supplyTaken = (from ordersAtInterval in ordersOverTime
|
|
||||||
from order in ordersAtInterval.Value
|
|
||||||
where order.Supply() != null
|
|
||||||
where order.Supply().Takes > 0
|
|
||||||
select order.Supply().Takes).Sum();
|
|
||||||
|
|
||||||
_supplyGranted = (from ordersAtInterval in ordersOverTime
|
|
||||||
from order in ordersAtInterval.Value
|
|
||||||
where order.Supply() != null
|
|
||||||
where order.Supply().Grants > 0
|
|
||||||
select order.Supply().Grants).Sum();
|
|
||||||
|
|
||||||
_extraBuildings = 0;
|
|
||||||
if (_supplyGranted > 160)
|
|
||||||
{
|
|
||||||
_extraBuildings = (_supplyGranted - 160) / 16;
|
|
||||||
_supplyGranted = 160;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,331 +0,0 @@
|
|||||||
@inject IEconomyService EconomyService
|
|
||||||
@inject IBuildOrderService BuildOrderService
|
|
||||||
@inject ITimingService TimingService
|
|
||||||
@inject IJSRuntime JsRuntime;
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
@if (lastRequestedRefreshIndex != requestedRefreshIndex)
|
|
||||||
{
|
|
||||||
<LoadingComponent/>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<div class="chartsContainer">
|
|
||||||
@foreach (var chart in charts)
|
|
||||||
{
|
|
||||||
var takenPixels = new Dictionary<int, bool>();
|
|
||||||
|
|
||||||
<div style="width: @chart.IntervalDisplayMax.ToString()px; height: @chart.ValueDisplayMax.ToString()px">
|
|
||||||
<div
|
|
||||||
style="position: relative; border: 2px solid gray; border-radius:2px; width: @chart.IntervalDisplayMax.ToString()px; height: @chart.ValueDisplayMax.ToString()px">
|
|
||||||
@foreach (var point in chart.Points)
|
|
||||||
{
|
|
||||||
var x = int.Parse(point.GetInterval(chart.HighestIntervalPoint, chart.IntervalDisplayMax));
|
|
||||||
if (takenPixels.ContainsKey(x)) continue;
|
|
||||||
|
|
||||||
takenPixels.Add(x, true);
|
|
||||||
|
|
||||||
<div style="position: absolute;
|
|
||||||
bottom:@point.GetValue(chart.HighestValuePoint, chart.ValueDisplayMax)px;
|
|
||||||
left:@point.GetInterval(chart.HighestIntervalPoint, chart.IntervalDisplayMax)px;
|
|
||||||
width: 0px;
|
|
||||||
height: 0px;">
|
|
||||||
<div
|
|
||||||
style="width:1px; height: 1px; border-top-right-radius:10px; border-top-left-radius:10px; border: 2px solid @chart.ChartColor; background-color:@chart.ChartColor">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.chartsContainer {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
gap: 20px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<FormDisplayComponent Label="Highest Alloy">
|
|
||||||
<Display>@highestAlloyPoint</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
<FormDisplayComponent Label="Highest Ether">
|
|
||||||
<Display>@highestEtherPoint</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
<DevOnlyComponent>
|
|
||||||
<FormDisplayComponent Label="Highest Pyre">
|
|
||||||
<Display>@highestEtherPoint</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
</DevOnlyComponent>
|
|
||||||
<FormDisplayComponent Label="Highest Army">
|
|
||||||
<Display>@highestArmyPoint</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
}
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
private readonly int width = 250;
|
|
||||||
|
|
||||||
List<int> valueList = new();
|
|
||||||
|
|
||||||
readonly List<ChartModel> charts = new();
|
|
||||||
|
|
||||||
|
|
||||||
float highestAlloyPoint;
|
|
||||||
float highestEtherPoint;
|
|
||||||
float highestPyrePoint;
|
|
||||||
float highestArmyPoint;
|
|
||||||
|
|
||||||
private Timer ageTimer = null!;
|
|
||||||
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
BuildOrderService.Subscribe(OnBuilderOrderChanged);
|
|
||||||
TimingService.Subscribe(OnBuilderOrderChanged);
|
|
||||||
|
|
||||||
ageTimer = new Timer(1000);
|
|
||||||
ageTimer.Elapsed += OnAge!;
|
|
||||||
ageTimer.Enabled = true;
|
|
||||||
|
|
||||||
|
|
||||||
GenerateChart();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int lastRequestedRefreshIndex;
|
|
||||||
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
BuildOrderService.Unsubscribe(OnBuilderOrderChanged);
|
|
||||||
TimingService.Unsubscribe(OnBuilderOrderChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int requestedRefreshIndex;
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
charts.Clear();
|
|
||||||
|
|
||||||
var alloyChart = new ChartModel
|
|
||||||
{
|
|
||||||
IntervalDisplayMax = width,
|
|
||||||
ValueDisplayMax = 100,
|
|
||||||
ChartColor = "Cyan"
|
|
||||||
};
|
|
||||||
var etherChart = new ChartModel
|
|
||||||
{
|
|
||||||
Offset = width,
|
|
||||||
IntervalDisplayMax = width,
|
|
||||||
ValueDisplayMax = 100,
|
|
||||||
ChartColor = "LightGreen"
|
|
||||||
};
|
|
||||||
|
|
||||||
var pyreChart = new ChartModel
|
|
||||||
{
|
|
||||||
Offset = width * 2,
|
|
||||||
IntervalDisplayMax = width,
|
|
||||||
ValueDisplayMax = 100,
|
|
||||||
ChartColor = "Red"
|
|
||||||
};
|
|
||||||
|
|
||||||
var armyChart = new ChartModel
|
|
||||||
{
|
|
||||||
Offset = width * 3,
|
|
||||||
IntervalDisplayMax = width,
|
|
||||||
ValueDisplayMax = 100,
|
|
||||||
ChartColor = "White"
|
|
||||||
};
|
|
||||||
|
|
||||||
highestAlloyPoint = 0;
|
|
||||||
highestEtherPoint = 0;
|
|
||||||
highestPyrePoint = 0;
|
|
||||||
highestArmyPoint = 0;
|
|
||||||
|
|
||||||
for (var interval = 0; interval < economyOverTime.Count(); interval++)
|
|
||||||
{
|
|
||||||
var army = from unit in BuildOrderService.GetCompletedBefore(interval)
|
|
||||||
where unit.EntityType == EntityType.Army
|
|
||||||
select unit;
|
|
||||||
|
|
||||||
var armyValue = 0;
|
|
||||||
foreach (var unit in army)
|
|
||||||
{
|
|
||||||
armyValue += unit.Production().Alloy + unit.Production().Ether;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
highestArmyPoint = Math.Max(highestArmyPoint, armyValue);
|
|
||||||
|
|
||||||
armyChart.Points.Add(new PointModel { Interval = interval, Value = armyValue });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (var interval = 0; interval < economyOverTime.Count(); interval++)
|
|
||||||
{
|
|
||||||
var alloyPoint = new PointModel { Interval = interval };
|
|
||||||
var etherPoint = new PointModel { Interval = interval };
|
|
||||||
var pyrePoint = new PointModel { Interval = interval };
|
|
||||||
|
|
||||||
var economyAtSecond = economyOverTime[interval];
|
|
||||||
|
|
||||||
var alloyWorkerHarvesters = from harvester in economyAtSecond.HarvestPoints
|
|
||||||
where harvester.Harvest() != null
|
|
||||||
where harvester.Harvest().RequiresWorker
|
|
||||||
where harvester.Harvest().Resource == ResourceType.Alloy
|
|
||||||
select harvester;
|
|
||||||
|
|
||||||
var alloyAutomaticHarvesters = from harvester in economyAtSecond.HarvestPoints
|
|
||||||
where harvester.Harvest() != null
|
|
||||||
where !harvester.Harvest().RequiresWorker
|
|
||||||
where harvester.Harvest().Resource == ResourceType.Alloy
|
|
||||||
select harvester;
|
|
||||||
|
|
||||||
var etherAutomaticHarvesters = from harvester in economyAtSecond.HarvestPoints
|
|
||||||
where harvester.Harvest() != null
|
|
||||||
where !harvester.Harvest().RequiresWorker
|
|
||||||
where harvester.Harvest().Resource == ResourceType.Ether
|
|
||||||
select harvester;
|
|
||||||
|
|
||||||
float autoAlloy = 0;
|
|
||||||
float workerSlots = 0;
|
|
||||||
float workerAlloy = 0;
|
|
||||||
float autoEther = 0;
|
|
||||||
|
|
||||||
float economySpending = 0;
|
|
||||||
|
|
||||||
foreach (var alloyAutoHarvester in alloyAutomaticHarvesters)
|
|
||||||
{
|
|
||||||
autoAlloy += alloyAutoHarvester.Harvest().Slots * alloyAutoHarvester.Harvest().HarvestedPerInterval;
|
|
||||||
var production = alloyAutoHarvester.Production();
|
|
||||||
if (production != null)
|
|
||||||
{
|
|
||||||
economySpending += production.Alloy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var alloyWorkerHarvester in alloyWorkerHarvesters)
|
|
||||||
{
|
|
||||||
workerSlots += alloyWorkerHarvester.Harvest().Slots;
|
|
||||||
var production = alloyWorkerHarvester.Production();
|
|
||||||
if (production != null)
|
|
||||||
{
|
|
||||||
economySpending += production.Alloy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var etherWorkerHarvester in etherAutomaticHarvesters)
|
|
||||||
{
|
|
||||||
autoEther += etherWorkerHarvester.Harvest().Slots * etherWorkerHarvester.Harvest().HarvestedPerInterval;
|
|
||||||
var production = etherWorkerHarvester.Production();
|
|
||||||
if (production != null)
|
|
||||||
{
|
|
||||||
economySpending += production.Alloy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
economySpending += (economyAtSecond.WorkerCount - 6) * 50;
|
|
||||||
|
|
||||||
workerAlloy = Math.Min(economyAtSecond.WorkerCount - economyAtSecond.BusyWorkerCount, workerSlots);
|
|
||||||
|
|
||||||
|
|
||||||
alloyPoint.TempValue = workerAlloy + autoAlloy;
|
|
||||||
etherPoint.Value = autoEther;
|
|
||||||
|
|
||||||
|
|
||||||
if (interval > 0)
|
|
||||||
{
|
|
||||||
alloyPoint.TempValue += alloyChart.Points.Last().TempValue;
|
|
||||||
etherPoint.Value += etherChart.Points.Last().Value;
|
|
||||||
pyrePoint.Value = pyreChart.Points.Last().Value + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
alloyPoint.Value = alloyPoint.TempValue - economySpending;
|
|
||||||
|
|
||||||
highestAlloyPoint = Math.Max(highestAlloyPoint, alloyPoint.Value);
|
|
||||||
highestEtherPoint = Math.Max(highestEtherPoint, etherPoint.Value);
|
|
||||||
|
|
||||||
alloyChart.Points.Add(alloyPoint);
|
|
||||||
etherChart.Points.Add(etherPoint);
|
|
||||||
pyreChart.Points.Add(pyrePoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
alloyChart.HighestValuePoint = (int)Math.Max(highestAlloyPoint, 5000.0f);
|
|
||||||
etherChart.HighestValuePoint = (int)Math.Max(highestEtherPoint, 2000.0f);
|
|
||||||
pyreChart.HighestValuePoint = (int)Math.Max(highestPyrePoint, 2000.0f);
|
|
||||||
|
|
||||||
alloyChart.HighestIntervalPoint = economyOverTime.Count();
|
|
||||||
etherChart.HighestIntervalPoint = economyOverTime.Count();
|
|
||||||
pyreChart.HighestIntervalPoint = economyOverTime.Count();
|
|
||||||
|
|
||||||
armyChart.HighestValuePoint = (int)Math.Max(highestArmyPoint, 2000.0f);
|
|
||||||
armyChart.HighestIntervalPoint = economyOverTime.Count();
|
|
||||||
|
|
||||||
|
|
||||||
charts.Add(alloyChart);
|
|
||||||
charts.Add(etherChart);
|
|
||||||
|
|
||||||
|
|
||||||
//TODO WIP
|
|
||||||
//charts.Add(pyreChart);
|
|
||||||
|
|
||||||
charts.Add(armyChart);
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
@inject IJSRuntime jsRuntime;
|
|
||||||
|
|
||||||
@inject IBuildOrderService buildOrderService
|
|
||||||
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
<FormLayoutComponent>
|
|
||||||
|
|
||||||
</FormLayoutComponent>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* // TODO: Make this more elegant, and useful. Also, it currently doesn't clear properly
|
|
||||||
* <FormTextAreaComponent Label="JSON Data"
|
|
||||||
* Rows="14"
|
|
||||||
* Value="@buildOrderService.AsJson()">
|
|
||||||
* </FormTextAreaComponent>
|
|
||||||
*/
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
buildOrderService.Subscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
@inject IImmortalSelectionService FilterService
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<div style="@GetBorderStyle()">
|
|
||||||
@ChildContent
|
|
||||||
</div>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
|
|
||||||
@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 ? "var(--faction-aru)" : "var(--faction-qrath)";
|
|
||||||
return $"border-top: 4px solid {color}; padding-top: 14px; margin-top: -12px;";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
@inject IImmortalSelectionService FilterService
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<div style="@GetBorderStyle()">
|
|
||||||
@ChildContent
|
|
||||||
</div>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
|
|
||||||
@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 = "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;";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
@inject IJSRuntime JsRuntime
|
|
||||||
@inject IKeyService KeyService
|
|
||||||
@inject IImmortalSelectionService FilterService
|
|
||||||
@inject IStorageService StorageService
|
|
||||||
@inject IBuildOrderService BuildOrderService
|
|
||||||
@using Services.Website
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
@if (_entity != null)
|
|
||||||
{
|
|
||||||
<div class="entityClickView">
|
|
||||||
<CascadingValue Value="_entity">
|
|
||||||
<CascadingValue Value="@_viewType">
|
|
||||||
<EntityViewComponent></EntityViewComponent>
|
|
||||||
</CascadingValue>
|
|
||||||
</CascadingValue>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<style>
|
|
||||||
.entityClickView {
|
|
||||||
overflow-y: scroll;
|
|
||||||
width: 100%;
|
|
||||||
overflow-x: hidden;
|
|
||||||
height: 550px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private EntityModel? _entity;
|
|
||||||
private string _viewType = EntityViewType.Detailed;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
KeyService.Subscribe(HandleClick);
|
|
||||||
StorageService.Subscribe(RefreshDefaults);
|
|
||||||
BuildOrderService.Subscribe(OnBuildOrderServiceChanged);
|
|
||||||
|
|
||||||
RefreshDefaults();
|
|
||||||
}
|
|
||||||
|
|
||||||
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<bool>(StorageKeys.IsPlainView) ? EntityViewType.Plain : EntityViewType.Detailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleClick()
|
|
||||||
{
|
|
||||||
var hotkey = KeyService.GetHotkey();
|
|
||||||
var hotkeyGroup = KeyService.GetHotkeyGroup();
|
|
||||||
var isHoldSpace = KeyService.IsHoldingSpace();
|
|
||||||
var faction = FilterService.GetFaction();
|
|
||||||
var immortal = FilterService.GetImmortal();
|
|
||||||
|
|
||||||
var foundEntity = EntityModel.GetFrom(hotkey!, hotkeyGroup, isHoldSpace, faction, immortal);
|
|
||||||
|
|
||||||
if (foundEntity != null && _entity != foundEntity)
|
|
||||||
{
|
|
||||||
_entity = foundEntity;
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
@inject IJSRuntime JsRuntime;
|
|
||||||
@inject IImmortalSelectionService FilterService
|
|
||||||
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<FormSelectComponent OnChange="@OnFactionChanged">
|
|
||||||
<FormLabelComponent>Faction</FormLabelComponent>
|
|
||||||
<ChildContent>
|
|
||||||
<option value="@DataType.FACTION_Aru"
|
|
||||||
selected="@(FilterService.GetFaction().Equals(DataType.FACTION_Aru))">
|
|
||||||
Aru
|
|
||||||
</option>
|
|
||||||
<option value="@DataType.FACTION_QRath"
|
|
||||||
selected="@(FilterService.GetFaction().Equals(DataType.FACTION_QRath))">
|
|
||||||
Q'Rath
|
|
||||||
</option>
|
|
||||||
</ChildContent>
|
|
||||||
</FormSelectComponent>
|
|
||||||
|
|
||||||
<FormSelectComponent OnChange="@OnImmortalChanged">
|
|
||||||
<FormLabelComponent>Immortal</FormLabelComponent>
|
|
||||||
<ChildContent>
|
|
||||||
@if (FilterService.GetFaction() == DataType.FACTION_QRath)
|
|
||||||
{
|
|
||||||
<option value="@DataType.IMMORTAL_Orzum"
|
|
||||||
selected="@(FilterService.GetImmortal().Equals(DataType.IMMORTAL_Orzum))">
|
|
||||||
Orzum
|
|
||||||
</option>
|
|
||||||
<option value="@DataType.IMMORTAL_Ajari"
|
|
||||||
selected="@(FilterService.GetImmortal().Equals(DataType.IMMORTAL_Ajari))">
|
|
||||||
Ajari
|
|
||||||
</option>
|
|
||||||
}
|
|
||||||
@if (FilterService.GetFaction() == DataType.FACTION_Aru)
|
|
||||||
{
|
|
||||||
<option value="@DataType.IMMORTAL_Atzlan"
|
|
||||||
selected="@(FilterService.GetImmortal().Equals(DataType.IMMORTAL_Atzlan))">
|
|
||||||
Atzlan
|
|
||||||
</option>
|
|
||||||
<option value="@DataType.IMMORTAL_Mala"
|
|
||||||
selected="@(FilterService.GetImmortal().Equals(DataType.IMMORTAL_Mala))">
|
|
||||||
Mala
|
|
||||||
</option>
|
|
||||||
<option value="@DataType.IMMORTAL_Xol"
|
|
||||||
selected="@(FilterService.GetImmortal().Equals(DataType.IMMORTAL_Xol))">
|
|
||||||
Xol
|
|
||||||
</option>
|
|
||||||
}
|
|
||||||
</ChildContent>
|
|
||||||
</FormSelectComponent>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
void OnFactionChanged(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
FilterService.SelectFaction(e.Value!.ToString()!);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnImmortalChanged(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
FilterService.SelectImmortal(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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
@inject IJSRuntime jsRuntime;
|
|
||||||
@inject IEconomyService economyService
|
|
||||||
@inject IBuildOrderService buildOrderService
|
|
||||||
@inject ITimingService timingService
|
|
||||||
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
<div class="highlightsContainer">
|
|
||||||
<div>
|
|
||||||
<div>Requested</div>
|
|
||||||
|
|
||||||
@foreach (var ordersAtTime in buildOrderService.StartedOrders.Reverse())
|
|
||||||
{
|
|
||||||
foreach (var order in ordersAtTime.Value)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
@ordersAtTime.Key | T @Interval.ToTime(ordersAtTime.Key)
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
@order.Info().Name
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div>Finished</div>
|
|
||||||
|
|
||||||
@foreach (var ordersAtTime in buildOrderService.CompletedOrders.Reverse())
|
|
||||||
{
|
|
||||||
foreach (var order in ordersAtTime.Value)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
|
|
||||||
@ordersAtTime.Key | T @Interval.ToTime(ordersAtTime.Key)
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
@order.Info().Name
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.highlightsContainer {
|
|
||||||
overflow-y: scroll;
|
|
||||||
overflow-x: hidden;
|
|
||||||
height: 400px;
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
gap: 4px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
economyService.Subscribe(StateHasChanged);
|
|
||||||
buildOrderService.Subscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,400 +0,0 @@
|
|||||||
@inject IJSRuntime JsRuntime;
|
|
||||||
@using Services.Website
|
|
||||||
@implements IDisposable
|
|
||||||
@inject IKeyService KeyService
|
|
||||||
@inject IBuildOrderService BuildOrderService
|
|
||||||
@inject IImmortalSelectionService FilterService
|
|
||||||
|
|
||||||
@inject IEconomyService EconomyService
|
|
||||||
@inject ITimingService TimingService
|
|
||||||
@inject IToastService ToastService
|
|
||||||
@inject IDataCollectionService DataCollectionService
|
|
||||||
|
|
||||||
|
|
||||||
<InputPanelComponent>
|
|
||||||
<div class="keyContainer">
|
|
||||||
@foreach (var hotkey in hotkeys)
|
|
||||||
{
|
|
||||||
if (hotkey.IsHidden)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var color = (hotkey.KeyText.Equals("SPACE") && KeyService.IsHoldingSpace()) || KeyService.GetAllPressedKeys().Contains(hotkey.KeyText)
|
|
||||||
? hotkey.GetColor()
|
|
||||||
: hotkey.GetColor();
|
|
||||||
|
|
||||||
var x = hotkey.PositionX * Size;
|
|
||||||
var y = hotkey.PositionY * Size + (hotkey.PositionY == 0 ? 5 : -50);
|
|
||||||
|
|
||||||
var width = Size * hotkey.Width;
|
|
||||||
var height = hotkey.PositionY == 0 ? 50 : Size;
|
|
||||||
|
|
||||||
var borderRadius = hotkey.PositionY == 0 ? 12 : 0;
|
|
||||||
|
|
||||||
var border = "1px solid black";
|
|
||||||
if (hotkey.KeyText.Equals(key))
|
|
||||||
{
|
|
||||||
border = "5px solid black";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hotkey.KeyText.Equals(controlGroup))
|
|
||||||
{
|
|
||||||
color = "#257525";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hotkey.KeyText.Equals("SPACE") && KeyService.IsHoldingSpace())
|
|
||||||
{
|
|
||||||
border = "5px solid green";
|
|
||||||
}
|
|
||||||
|
|
||||||
var keyText = hotkey.KeyText.Equals("CAPSLOCK") ? "Caps"
|
|
||||||
: hotkey.KeyText.Equals("CONTROL") ? "Ctrl"
|
|
||||||
: hotkey.KeyText.Equals("SHIFT") ? "Shift"
|
|
||||||
: hotkey.KeyText.Equals("X") ? "X"
|
|
||||||
: hotkey.KeyText.Equals("SPACE") ? "Space" : hotkey.KeyText;
|
|
||||||
|
|
||||||
|
|
||||||
var controlStyle = $"background-color:{color}; " +
|
|
||||||
$"width: {width}px; " +
|
|
||||||
"border-top: 1px solid black; " +
|
|
||||||
"border-left: 1px solid black; " +
|
|
||||||
"border-right: 1px solid black; " +
|
|
||||||
$"border-top-left-radius: {borderRadius}px; " +
|
|
||||||
$"border-top-right-radius: {borderRadius}px; " +
|
|
||||||
"overflow: hidden; " +
|
|
||||||
"text-align: center;";
|
|
||||||
|
|
||||||
var keyStyle = $"background-color:{color}; " +
|
|
||||||
$"border: {border}; " +
|
|
||||||
$"width: {width}px; " +
|
|
||||||
$"height: {height}px; " +
|
|
||||||
"overflow: hidden; " +
|
|
||||||
"padding: 4px;";
|
|
||||||
|
|
||||||
var usedStyle = hotkey.PositionY == 0 ? controlStyle : keyStyle;
|
|
||||||
|
|
||||||
<div style="position:relative;
|
|
||||||
cursor:pointer;
|
|
||||||
top:@y.ToString()px;
|
|
||||||
left:@x.ToString()px;
|
|
||||||
width: 0px;
|
|
||||||
height: 0px;">
|
|
||||||
|
|
||||||
<div @onclick="e => ButtonClicked(e, hotkey)" style="@usedStyle">
|
|
||||||
@keyText
|
|
||||||
@foreach (var entity in data.Values)
|
|
||||||
{
|
|
||||||
if (InvalidKey(entity, hotkey) || InvalidKeyGroup(entity, hotkey) || InvalidHoldSpace(entity))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (InvalidFaction(entity))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (InvalidVanguard(entity) || InvalidNonVanguard(entity))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var isVanguard = entity.VanguardAdded() != null;
|
|
||||||
var style = isVanguard ? "font-weight: bold;" : "";
|
|
||||||
|
|
||||||
if (BuildOrderService.WillMeetRequirements(entity) == null)
|
|
||||||
{
|
|
||||||
style += "color:gray; font-style: italic;";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
<div style="@style">@entity.Info()?.Name</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</InputPanelComponent>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.keyContainer {
|
|
||||||
width: 400px;
|
|
||||||
max-width: 95vw;
|
|
||||||
height: 350px;
|
|
||||||
outline: 3px solid black;
|
|
||||||
border-radius: 8px;
|
|
||||||
background-color: #282A30;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media only screen and (max-width: 1025px) {
|
|
||||||
.keyContainer {
|
|
||||||
transform: scale(0.85) translateX(-20px);
|
|
||||||
background-color: transparent;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Parameter] public int Size { get; set; } = 100;
|
|
||||||
|
|
||||||
readonly Dictionary<string, EntityModel> data = EntityModel.GetDictionary();
|
|
||||||
readonly List<HotkeyModel> hotkeys = HotkeyModel.GetAll();
|
|
||||||
|
|
||||||
private string controlGroup = "C";
|
|
||||||
private string key = "";
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
|
|
||||||
KeyService.Subscribe(OnKeyPressed);
|
|
||||||
FilterService.Subscribe(StateHasChanged);
|
|
||||||
BuildOrderService.Subscribe(OnBuilderOrderChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
KeyService.Unsubscribe(OnKeyPressed);
|
|
||||||
FilterService.Unsubscribe(StateHasChanged);
|
|
||||||
BuildOrderService.Unsubscribe(OnBuilderOrderChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
int completedTimeCount;
|
|
||||||
|
|
||||||
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.GetFaction() && FilterService.GetFaction() != DataType.Any)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move to Filter Service
|
|
||||||
bool InvalidVanguard(EntityModel entity)
|
|
||||||
{
|
|
||||||
if (entity.VanguardAdded() != null
|
|
||||||
&& entity.VanguardAdded()?.ImmortalId != FilterService.GetImmortal()
|
|
||||||
&& FilterService.GetImmortal() != DataType.Any)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move to Filter Service
|
|
||||||
bool InvalidNonVanguard(EntityModel entity)
|
|
||||||
{
|
|
||||||
if (entity.Replaceds().Count > 0)
|
|
||||||
{
|
|
||||||
foreach (var replaced in entity.Replaceds())
|
|
||||||
{
|
|
||||||
if (FilterService.GetImmortal() == replaced.ImmortalId)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InvalidKey(EntityModel entity, HotkeyModel key)
|
|
||||||
{
|
|
||||||
if (entity.Hotkey()?.Hotkey == key.KeyText)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InvalidKeyGroup(EntityModel entity, HotkeyModel key)
|
|
||||||
{
|
|
||||||
if (entity.Hotkey()?.HotkeyGroup == controlGroup)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InvalidKey(EntityModel entity)
|
|
||||||
{
|
|
||||||
if (entity.Hotkey()?.Hotkey == key)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InvalidKeyGroup(EntityModel entity)
|
|
||||||
{
|
|
||||||
if (entity.Hotkey()?.HotkeyGroup == controlGroup)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InvalidHoldSpace(EntityModel entity)
|
|
||||||
{
|
|
||||||
if (entity.Hotkey()?.HoldSpace == KeyService.IsHoldingSpace())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnKeyPressed()
|
|
||||||
{
|
|
||||||
var controlGroupWas = controlGroup;
|
|
||||||
var keyWas = key;
|
|
||||||
|
|
||||||
if (KeyService.GetAllPressedKeys().Contains("Z"))
|
|
||||||
{
|
|
||||||
controlGroup = "Z";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (KeyService.GetAllPressedKeys().Contains("X"))
|
|
||||||
{
|
|
||||||
controlGroup = "X";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (KeyService.GetAllPressedKeys().Contains("C"))
|
|
||||||
{
|
|
||||||
controlGroup = "C";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (KeyService.GetAllPressedKeys().Contains("D"))
|
|
||||||
{
|
|
||||||
controlGroup = "D";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (KeyService.GetAllPressedKeys().Contains("V"))
|
|
||||||
{
|
|
||||||
controlGroup = "V";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (KeyService.GetAllPressedKeys().Contains("ALT"))
|
|
||||||
{
|
|
||||||
controlGroup = "ALT";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (KeyService.GetAllPressedKeys().Contains("SHIFT"))
|
|
||||||
{
|
|
||||||
controlGroup = "SHIFT";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (KeyService.GetAllPressedKeys().Contains("CONTROL"))
|
|
||||||
{
|
|
||||||
controlGroup = "CONTROL";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (KeyService.GetAllPressedKeys().Count > 0)
|
|
||||||
{
|
|
||||||
key = KeyService.GetAllPressedKeys().First();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (controlGroupWas != controlGroup || keyWas != key)
|
|
||||||
{
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void HandleClick()
|
|
||||||
{
|
|
||||||
var hotkey = KeyService.GetHotkey();
|
|
||||||
|
|
||||||
if (hotkey is "`")
|
|
||||||
HandleCancelEntity();
|
|
||||||
|
|
||||||
if (EntityFromKey(hotkey, out var entity))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (BuildOrderService.Add(entity!, EconomyService))
|
|
||||||
EconomyService.Calculate(BuildOrderService, TimingService, BuildOrderService.GetLastRequestInterval());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleCancelEntity()
|
|
||||||
{
|
|
||||||
BuildOrderService.RemoveLast();
|
|
||||||
EconomyService.Calculate(BuildOrderService, TimingService, BuildOrderService.GetLastRequestInterval());
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool EntityFromKey(string? hotkey, out EntityModel? entity)
|
|
||||||
{
|
|
||||||
var hotkeyGroup = KeyService.GetHotkeyGroup();
|
|
||||||
var isHoldSpace = KeyService.IsHoldingSpace();
|
|
||||||
var faction = FilterService.GetFaction();
|
|
||||||
var immortal = FilterService.GetImmortal();
|
|
||||||
|
|
||||||
entity = EntityModel.GetFrom(hotkey!, hotkeyGroup, isHoldSpace, faction, immortal);
|
|
||||||
|
|
||||||
return entity == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ButtonClicked(MouseEventArgs mouseEventArgs, HotkeyModel hotkey)
|
|
||||||
{
|
|
||||||
DataCollectionService.SendEvent(
|
|
||||||
DataCollectionKeys.BuildCalcInput,
|
|
||||||
new Dictionary<string, string> { { "key", hotkey.KeyText.ToLower() }, { "input-source", "mouse" } }
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
@using Services.Website
|
|
||||||
@inject IKeyService KeyService
|
|
||||||
|
|
||||||
@inject IDataCollectionService DataCollectionService
|
|
||||||
@inject IJSRuntime JsRuntime
|
|
||||||
|
|
||||||
|
|
||||||
<div tabindex="0"
|
|
||||||
style="margin: auto;"
|
|
||||||
@onkeydown="HandleKeyDown"
|
|
||||||
@onkeyup="HandleKeyUp"
|
|
||||||
@onkeydown:preventDefault="true"
|
|
||||||
@onkeydown:stopPropagation="true">
|
|
||||||
@ChildContent
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Parameter] public RenderFragment ChildContent { get; set; } = default!;
|
|
||||||
|
|
||||||
private void HandleKeyDown(KeyboardEventArgs e)
|
|
||||||
{
|
|
||||||
DataCollectionService.SendEvent(
|
|
||||||
DataCollectionKeys.BuildCalcInput,
|
|
||||||
new Dictionary<string, string> { { "key", e.Key.ToLower() }, { "input-source", "keyboard" } }
|
|
||||||
);
|
|
||||||
|
|
||||||
KeyService.AddPressedKey(e.Key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleKeyUp(KeyboardEventArgs e)
|
|
||||||
{
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
@inject IJSRuntime JsRuntime;
|
|
||||||
|
|
||||||
@inject IBuildOrderService BuildOrderService
|
|
||||||
@inject IEconomyService EconomyService
|
|
||||||
@inject IToastService ToastService
|
|
||||||
@inject ITimingService TimingService
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<FormNumberComponent Max="600"
|
|
||||||
Min="0"
|
|
||||||
Value="BuildDelay"
|
|
||||||
OnChange="@OnBuildingInputDelayChanged">
|
|
||||||
<FormLabelComponent>Building Input Delay</FormLabelComponent>
|
|
||||||
<FormInfoComponent>Add a input delay to constructing buildings for simulating worker movement and player
|
|
||||||
micro.
|
|
||||||
</FormInfoComponent>
|
|
||||||
</FormNumberComponent>
|
|
||||||
<div class="optionRow">
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<FormNumberComponent Max="600"
|
|
||||||
Min="1"
|
|
||||||
Value="WaitTime"
|
|
||||||
OnChange="@OnWaitTimeChanged">
|
|
||||||
<FormLabelComponent>Wait Time</FormLabelComponent>
|
|
||||||
</FormNumberComponent>
|
|
||||||
<ButtonComponent OnClick="OnWaitClicked">Add Wait</ButtonComponent>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<FormNumberComponent Max="2048"
|
|
||||||
Min="1"
|
|
||||||
Value="WaitTo"
|
|
||||||
OnChange="@OnWaitToChanged">
|
|
||||||
<FormLabelComponent>Wait To</FormLabelComponent>
|
|
||||||
</FormNumberComponent>
|
|
||||||
<ButtonComponent OnClick="OnWaitToClicked">Add Wait</ButtonComponent>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
</div>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.optionRow {
|
|
||||||
display: flex;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private int BuildDelay { get; set; } = 2;
|
|
||||||
private int WaitTime { get; set; } = 30;
|
|
||||||
private int WaitTo { get; set; } = 30;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
TimingService.Subscribe(RefreshDefaults);
|
|
||||||
|
|
||||||
RefreshDefaults();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
TimingService.Unsubscribe(RefreshDefaults);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RefreshDefaults()
|
|
||||||
{
|
|
||||||
BuildDelay = TimingService.BuildingInputDelay;
|
|
||||||
WaitTime = TimingService.WaitTime;
|
|
||||||
WaitTo = TimingService.WaitTo;
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnBuildingInputDelayChanged(ChangeEventArgs changeEventArgs)
|
|
||||||
{
|
|
||||||
TimingService.BuildingInputDelay = int.Parse(changeEventArgs.Value!.ToString()!);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnWaitTimeChanged(ChangeEventArgs changeEventArgs)
|
|
||||||
{
|
|
||||||
TimingService.WaitTime = (int)changeEventArgs.Value!;
|
|
||||||
WaitTime = (int)changeEventArgs.Value!;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnWaitToChanged(ChangeEventArgs changeEventArgs)
|
|
||||||
{
|
|
||||||
TimingService.WaitTo = (int)changeEventArgs.Value!;
|
|
||||||
WaitTo = (int)changeEventArgs.Value!;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnWaitClicked()
|
|
||||||
{
|
|
||||||
if (BuildOrderService.AddWait(WaitTime))
|
|
||||||
{
|
|
||||||
EconomyService.Calculate(BuildOrderService, TimingService, BuildOrderService.GetLastRequestInterval());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnWaitToClicked()
|
|
||||||
{
|
|
||||||
if (BuildOrderService.AddWaitTo(WaitTo))
|
|
||||||
{
|
|
||||||
EconomyService.Calculate(BuildOrderService, TimingService, BuildOrderService.GetLastRequestInterval());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool ShouldRender()
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
JsRuntime.InvokeVoidAsync("console.time", "TimingComponent");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnAfterRender(bool firstRender)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
JsRuntime.InvokeVoidAsync("console.timeEnd", "TimingComponent");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
@inject IJSRuntime jsRuntime
|
|
||||||
@inject IEconomyService economyService
|
|
||||||
@inject IBuildOrderService buildOrderService
|
|
||||||
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
<Virtualize Items="@economyService.GetOverTime()" Context="economyAtSecond" ItemSize="400" OverscanCount="4">
|
|
||||||
<div style="display: grid; gap: 8px; grid-template-columns: 1fr 1fr;">
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
@economyAtSecond.Interval
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
T @Interval.ToTime(economyAtSecond.Interval) | A @economyAtSecond.Alloy | E @economyAtSecond.Ether
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Worker Count: @(economyAtSecond.WorkerCount)
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Free Worker Count: @(economyAtSecond.WorkerCount - economyAtSecond.BusyWorkerCount)
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Busy Worker Count: @economyAtSecond.BusyWorkerCount
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Creating Worker Count: @economyAtSecond.CreatingWorkerCount
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
|
|
||||||
@if (buildOrderService.StartedOrders.TryGetValue(economyAtSecond.Interval, out var ordersAtTime))
|
|
||||||
{
|
|
||||||
@foreach (var order in ordersAtTime)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
Requested: @order.Info().Name
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@if (buildOrderService.CompletedOrders.TryGetValue(economyAtSecond.Interval, out var ordersCompletedAtTime))
|
|
||||||
{
|
|
||||||
@foreach (var order in ordersCompletedAtTime)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
New: @order.Info().Name
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Virtualize>
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
economyService.Subscribe(StateHasChanged);
|
|
||||||
buildOrderService.Subscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
@inject IJSRuntime jsRuntime;
|
|
||||||
|
|
||||||
@inject IBuildOrderService buildOrderService
|
|
||||||
@inject IEconomyService economyService
|
|
||||||
@inject IToastService toastService
|
|
||||||
@inject ITimingService timingService
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<FormNumberComponent Max="2048"
|
|
||||||
Min="0"
|
|
||||||
Value="@timingService.GetAttackTime()"
|
|
||||||
OnChange="@OnAttackTimeChanged">
|
|
||||||
<FormLabelComponent>Attack Time</FormLabelComponent>
|
|
||||||
<FormInfoComponent>
|
|
||||||
<i>  T @Interval.ToTime(timingService.GetAttackTime())</i>
|
|
||||||
</FormInfoComponent>
|
|
||||||
</FormNumberComponent>
|
|
||||||
|
|
||||||
<FormNumberComponent Max="2048"
|
|
||||||
Min="0"
|
|
||||||
Value="@timingService.GetTravelTime()"
|
|
||||||
OnChange="@OnTravelTimeChanged">
|
|
||||||
<FormLabelComponent>Travel Time</FormLabelComponent>
|
|
||||||
<FormInfoComponent>
|
|
||||||
<i>  T @Interval.ToTime(timingService.GetTravelTime())</i>
|
|
||||||
</FormInfoComponent>
|
|
||||||
</FormNumberComponent>
|
|
||||||
|
|
||||||
</FormLayoutComponent>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
timingService.Subscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
timingService.Unsubscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnAttackTimeChanged(ChangeEventArgs changeEventArgs)
|
|
||||||
{
|
|
||||||
timingService.SetAttackTime(int.Parse(changeEventArgs.Value!.ToString()!));
|
|
||||||
economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval());
|
|
||||||
toastService.AddToast(new ToastModel
|
|
||||||
{
|
|
||||||
Title = "Attack Time",
|
|
||||||
Message = "Attack Time has changed.",
|
|
||||||
SeverityType = SeverityType.Success
|
|
||||||
});
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnTravelTimeChanged(ChangeEventArgs changeEventArgs)
|
|
||||||
{
|
|
||||||
timingService.SetTravelTime(int.Parse(changeEventArgs.Value!.ToString()!));
|
|
||||||
economyService.Calculate(buildOrderService, timingService, buildOrderService.GetLastRequestInterval());
|
|
||||||
toastService.AddToast(new ToastModel
|
|
||||||
{
|
|
||||||
Title = "Travel Time",
|
|
||||||
Message = "Travel Time has changed.",
|
|
||||||
SeverityType = SeverityType.Success
|
|
||||||
});
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnNameChanged(ChangeEventArgs changeEventArgs)
|
|
||||||
{
|
|
||||||
buildOrderService.SetName(changeEventArgs.Value!.ToString()!);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnColorChanged(ChangeEventArgs changeEventArgs)
|
|
||||||
{
|
|
||||||
buildOrderService.DeprecatedSetColor(changeEventArgs.Value!.ToString()!);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OnNotesChanged(ChangeEventArgs changeEventArgs)
|
|
||||||
{
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
@inject IImmortalSelectionService FilterService
|
|
||||||
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
What is this tool?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
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.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
How does it work?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
The tool calculates every second of game time. So if you attempt to build a <b>Legion Hall</b> 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.
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
If you then build 2 <b>Apostle of Bindings</b> a <b>Soul Foundry</b> and a 3 <b>Absolvers</b> you
|
|
||||||
should see yourself roughly floating 500 alloy, with barely having any ether. Which means you could
|
|
||||||
of gotten an <b>Acropolis</b> and a <b>Zentari</b> without hurting your build.
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
Try building <b>Apostle of Bindings</b> before the <b>Legion Hall</b> and see how that changes the
|
|
||||||
timing of your 3 <b>Absolvers</b>. (Spoiler:
|
|
||||||
<SpoilerTextComponent> your <b>Absolvers</b> will be built much faster, and you won't be floating so
|
|
||||||
much alloy.
|
|
||||||
</SpoilerTextComponent>
|
|
||||||
)
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
What is CONTROL key for?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
Economy and tech related upgrades for townhalls.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
What is SHIFT key for?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
Misc building related upgrades. (Omnivores)
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
What is 2 key for?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
It will be for Pyre camps. Currently not implemented.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
FilterService.Subscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
FilterService.Unsubscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
@layout PageLayout
|
|
||||||
|
|
||||||
@inject IDataCollectionService DataCollectionService
|
|
||||||
@inherits BasePage
|
|
||||||
|
|
||||||
@page "/contact"
|
|
||||||
|
|
||||||
<LayoutMediumContentComponent>
|
|
||||||
<WebsiteTitleComponent>Contact</WebsiteTitleComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
How do I contact you for feature requests and bug reports?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
You can message me at <b>JonathanMcCaffrey#3544</b> on my <a href="https://discord.gg/uMq8bMGeeN"
|
|
||||||
target="_blank">Discord</a> channel.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
</PaperComponent>
|
|
||||||
</LayoutMediumContentComponent>
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
@page "/data-collection"
|
|
||||||
|
|
||||||
@inject IDataCollectionService DataCollectionService
|
|
||||||
@inherits BasePage
|
|
||||||
|
|
||||||
@layout PageLayout
|
|
||||||
|
|
||||||
|
|
||||||
<LayoutMediumContentComponent>
|
|
||||||
<AlertComponent>
|
|
||||||
<Title>Not Implemented</Title>
|
|
||||||
<Message></Message>
|
|
||||||
</AlertComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
TODO
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
<ContentDividerComponent/>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
|
|
||||||
</PaperComponent>
|
|
||||||
</LayoutMediumContentComponent>
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
@layout PageLayout
|
|
||||||
@using IGP.Pages.DataTables.Parts
|
|
||||||
@inherits BasePage
|
|
||||||
|
|
||||||
@page "/data-tables"
|
|
||||||
|
|
||||||
<LayoutLargeContentComponent>
|
|
||||||
<WebsiteTitleComponent>Data Tables</WebsiteTitleComponent>
|
|
||||||
<MudTabs Elevation="2">
|
|
||||||
<MudTabPanel Text="Attacks">
|
|
||||||
<WeaponTable/>
|
|
||||||
</MudTabPanel>
|
|
||||||
<MudTabPanel Text="Production">
|
|
||||||
<ProductionTable/>
|
|
||||||
</MudTabPanel>
|
|
||||||
<MudTabPanel Text="Health">
|
|
||||||
<VitalityTable/>
|
|
||||||
</MudTabPanel>
|
|
||||||
<MudTabPanel Text="Movement">
|
|
||||||
<MovementTable/>
|
|
||||||
</MudTabPanel>
|
|
||||||
</MudTabs>
|
|
||||||
|
|
||||||
<ContentDividerComponent></ContentDividerComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
What is this tool?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
This tool is a data table of all information belonging to a type of data. Such as viewing all weapons,
|
|
||||||
so one can easily sort and see what weapon attack has the highest range, and what faction and unit that
|
|
||||||
attack belongs to.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
</PaperComponent>
|
|
||||||
</LayoutLargeContentComponent>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
<MudDataGrid T="EntityMovementModel" Items="@_data"
|
|
||||||
SortMode="SortMode.Multiple"
|
|
||||||
Filterable="true"
|
|
||||||
Hideable="true">
|
|
||||||
<Columns>
|
|
||||||
<PropertyColumn Property="x => x.Parent.GetName()" Title="Entity"/>
|
|
||||||
<PropertyColumn Property="x => x.Movement"/>
|
|
||||||
<PropertyColumn Property="x => x.Speed"/>
|
|
||||||
<PropertyColumn Property="x => x.Parent.GetFaction()" Title="Faction"/>
|
|
||||||
<PropertyColumn Property="x => x.Parent.GetImmortal()" Title="Immortal"/>
|
|
||||||
</Columns>
|
|
||||||
</MudDataGrid>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
readonly IEnumerable<EntityMovementModel> _data = EntityData.Get()
|
|
||||||
.SelectMany(e => e.Value.EntityParts)
|
|
||||||
.OfType<EntityMovementModel>()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
<MudDataGrid T="EntityProductionModel" Items="@data"
|
|
||||||
SortMode="SortMode.Multiple"
|
|
||||||
Filterable="true"
|
|
||||||
Hideable="true">
|
|
||||||
<Columns>
|
|
||||||
<PropertyColumn Property="x => x.Parent.GetName()" Title="Entity"/>
|
|
||||||
<PropertyColumn Property="x => x.Alloy"/>
|
|
||||||
<PropertyColumn Property="x => x.BuildTime"/>
|
|
||||||
<PropertyColumn Property="x => x.Ether"/>
|
|
||||||
<PropertyColumn Property="x => x.Parent.GetFaction()" Title="Faction"/>
|
|
||||||
<PropertyColumn Property="x => x.Parent.GetImmortal()" Title="Immortal"/>
|
|
||||||
</Columns>
|
|
||||||
</MudDataGrid>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
readonly IEnumerable<EntityProductionModel> data = EntityData.Get()
|
|
||||||
.SelectMany(e => e.Value.EntityParts)
|
|
||||||
.OfType<EntityProductionModel>()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<MudDataGrid T="EntityVitalityModel" Items="@_data"
|
|
||||||
SortMode="SortMode.Multiple"
|
|
||||||
Filterable="true"
|
|
||||||
Hideable="true">
|
|
||||||
<Columns>
|
|
||||||
<PropertyColumn Property="x => x.Parent.GetName()" Title="Entity"/>
|
|
||||||
<PropertyColumn Property="x => x.Health"/>
|
|
||||||
<PropertyColumn Property="x => x.Armor"/>
|
|
||||||
<PropertyColumn Property="x => x.Defense"/>
|
|
||||||
<PropertyColumn Property="x => x.DefenseLayer"/>
|
|
||||||
<PropertyColumn Property="x => x.IsStructure"/>
|
|
||||||
<PropertyColumn Property="x => x.IsEtheric"/>
|
|
||||||
<PropertyColumn Property="x => x.Parent.GetFaction()" Title="Faction"/>
|
|
||||||
<PropertyColumn Property="x => x.Parent.GetImmortal()" Title="Immortal"/>
|
|
||||||
</Columns>
|
|
||||||
</MudDataGrid>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
readonly IEnumerable<EntityVitalityModel> _data = EntityData.Get()
|
|
||||||
.SelectMany(e => e.Value.EntityParts)
|
|
||||||
.OfType<EntityVitalityModel>()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
<MudDataGrid T="EntityWeaponModel" Items="@_data"
|
|
||||||
SortMode="SortMode.Multiple"
|
|
||||||
Filterable="true"
|
|
||||||
Hideable="true">
|
|
||||||
<Columns>
|
|
||||||
<PropertyColumn Property="x => x.Parent.GetName()" Title="Entity"/>
|
|
||||||
<PropertyColumn Property="x => x.Range" Title="Range"/>
|
|
||||||
<PropertyColumn Property="x => x.Targets" Title="Targets"/>
|
|
||||||
<PropertyColumn Property="x => x.Damage" Title="Damage"/>
|
|
||||||
<PropertyColumn Property="x => x.AttacksPerSecond" Title="Attacks Per Second"/>
|
|
||||||
<PropertyColumn Property="x => x.DamagePerSecond()" Title="DPS"/>
|
|
||||||
<PropertyColumn Property="x => x.HasSplash" Title="Has Splash"/>
|
|
||||||
<PropertyColumn Property="x => x.DamagePerSecondLight()" Title="DPS (Light)"/>
|
|
||||||
<PropertyColumn Property="x => x.DamagePerSecondMedium()" Title="DPS (Medium)"/>
|
|
||||||
<PropertyColumn Property="x => x.DamagePerSecondHeavy()" Title="DPS (Heavy)"/>
|
|
||||||
<PropertyColumn Property="x => x.Parent.GetFaction()" Title="Faction"/>
|
|
||||||
<PropertyColumn Property="x => x.Parent.GetImmortal()" Title="Immortal"/>
|
|
||||||
</Columns>
|
|
||||||
<PagerContent>
|
|
||||||
<MudDataGridPager T="EntityWeaponModel"/>
|
|
||||||
</PagerContent>
|
|
||||||
</MudDataGrid>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
readonly IEnumerable<EntityWeaponModel> _data = EntityData.Get()
|
|
||||||
.SelectMany(e => e.Value.EntityParts)
|
|
||||||
.OfType<EntityWeaponModel>()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,261 +0,0 @@
|
|||||||
@layout PageLayout
|
|
||||||
@inherits BasePage
|
|
||||||
@page "/database"
|
|
||||||
@using Model
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
@inject IEntityDisplayService EntityDisplayService
|
|
||||||
|
|
||||||
|
|
||||||
<LayoutLargeContentComponent>
|
|
||||||
<WebsiteTitleComponent>Database</WebsiteTitleComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<FormDisplayComponent Label="Patch">
|
|
||||||
<Display>
|
|
||||||
Game Patch: @Variables.GamePatch
|
|
||||||
</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
<div style="margin-left: 8px">
|
|
||||||
<ButtonGroupComponent OnClick="choice => { EntityDisplayService.SetDisplayType(choice); }"
|
|
||||||
Choice="@EntityDisplayService.GetDisplayType()"
|
|
||||||
Choices="@EntityDisplayService.DefaultChoices()"></ButtonGroupComponent>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<EntityFilterComponent></EntityFilterComponent>
|
|
||||||
|
|
||||||
@if (searches != null)
|
|
||||||
{
|
|
||||||
<div class="databaseItems">
|
|
||||||
@foreach (var entity in searches)
|
|
||||||
{
|
|
||||||
<CascadingValue Value="entity">
|
|
||||||
<CascadingValue Value="@EntityDisplayService.GetDisplayType()">
|
|
||||||
<EntityViewComponent></EntityViewComponent>
|
|
||||||
</CascadingValue>
|
|
||||||
</CascadingValue>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
|
|
||||||
<ContentDividerComponent></ContentDividerComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
What is this tool?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
This is a reference database. Mostly so unit stats can be reviewed outside of the game, IMMORTAL: Gates
|
|
||||||
of Pyre.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
Is this database complete?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
No. A lot of content is missing, that needs to be manually transfered from screenshots of IMMORTAL:
|
|
||||||
Gates of Pyre. This will happen slowly over-time.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
Is this database updated to the latest version?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
Maybe. Check this <b>@Variables.GamePatch</b> version number, and compare it to the
|
|
||||||
number on discord, in the <b>#game-updates</b> channel. That should give a general sense of how out of
|
|
||||||
date the data is.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
This database has some errors in it.
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
Yup. The content is being transferred by hand, so some mistakes are expected.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
</PaperComponent>
|
|
||||||
</LayoutLargeContentComponent>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.databaseItems {
|
|
||||||
height: 900px;
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
background-color: var(--background);
|
|
||||||
gap: 4px;
|
|
||||||
border-top: 4px solid var(--accent);
|
|
||||||
border-bottom: 4px solid var(--accent);
|
|
||||||
padding: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.databaseInfoContainer {
|
|
||||||
display: flex;
|
|
||||||
gap: 24px;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Inject] public IEntityFilterService EntityFilterService { get; set; } = default!;
|
|
||||||
|
|
||||||
readonly List<EntityModel> defaults = (from entity in EntityModel.GetList()
|
|
||||||
where !entity.IsSpeculative
|
|
||||||
select entity).ToList();
|
|
||||||
|
|
||||||
List<EntityModel> factions = default!;
|
|
||||||
List<EntityModel> immortals = default!;
|
|
||||||
List<EntityModel> entities = default!;
|
|
||||||
List<EntityModel> searches = default!;
|
|
||||||
|
|
||||||
|
|
||||||
string selectedFactionType = DataType.Any;
|
|
||||||
string selectedImmortalType = DataType.Any;
|
|
||||||
string selectedEntityType = EntityType.Army;
|
|
||||||
string searchText = "";
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
RefreshFactionSearch();
|
|
||||||
|
|
||||||
EntityFilterService.Subscribe(OnChange);
|
|
||||||
EntityDisplayService.Subscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
EntityFilterService.Unsubscribe(OnChange);
|
|
||||||
EntityDisplayService.Unsubscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnChange(EntityFilterEvent filterEntityEvent)
|
|
||||||
{
|
|
||||||
if (filterEntityEvent == EntityFilterEvent.OnRefreshFaction)
|
|
||||||
{
|
|
||||||
RefreshFactionSearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterEntityEvent == EntityFilterEvent.OnRefreshImmortal)
|
|
||||||
{
|
|
||||||
RefreshImmortalSearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filterEntityEvent == EntityFilterEvent.OnRefreshEntity)
|
|
||||||
{
|
|
||||||
RefreshEntitySearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filterEntityEvent == EntityFilterEvent.OnRefreshSearch)
|
|
||||||
{
|
|
||||||
RefreshTextSearch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RefreshFactionSearch()
|
|
||||||
{
|
|
||||||
selectedFactionType = EntityFilterService.GetFactionType();
|
|
||||||
|
|
||||||
if (selectedFactionType == DataType.Any)
|
|
||||||
{
|
|
||||||
factions = defaults.ToList();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
factions = (from entity in defaults
|
|
||||||
where entity.Faction() != null && entity.Faction().Faction == selectedFactionType
|
|
||||||
select entity).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
RefreshImmortalSearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OnImmortalChanged(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
selectedImmortalType = e.Value!.ToString()!;
|
|
||||||
RefreshImmortalSearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RefreshImmortalSearch()
|
|
||||||
{
|
|
||||||
selectedImmortalType = EntityFilterService.GetImmortalType();
|
|
||||||
|
|
||||||
if (selectedImmortalType == DataType.Any)
|
|
||||||
{
|
|
||||||
immortals = factions.ToList();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
immortals = (from entity in factions
|
|
||||||
where entity.VanguardAdded() == null || entity.VanguardAdded().ImmortalId == selectedImmortalType
|
|
||||||
select entity).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
RefreshEntitySearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnEntityChanged(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
selectedEntityType = e.Value!.ToString()!;
|
|
||||||
RefreshEntitySearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RefreshEntitySearch()
|
|
||||||
{
|
|
||||||
selectedEntityType = EntityFilterService.GetEntityType();
|
|
||||||
|
|
||||||
if (selectedEntityType == EntityType.Any)
|
|
||||||
{
|
|
||||||
entities = immortals.ToList();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
entities = (from entity in immortals
|
|
||||||
where entity.EntityType == selectedEntityType
|
|
||||||
select entity).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
RefreshTextSearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnSearchTextChanged(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
searchText = e.Value!.ToString()!;
|
|
||||||
RefreshTextSearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RefreshTextSearch()
|
|
||||||
{
|
|
||||||
searchText = EntityFilterService.GetSearchText();
|
|
||||||
|
|
||||||
if (searchText.Trim() == "")
|
|
||||||
{
|
|
||||||
searches = entities.ToList();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
searches = (from entity in entities
|
|
||||||
where entity.Info().Name.ToLower().Contains(searchText.ToLower())
|
|
||||||
select entity).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
@layout PageLayout
|
|
||||||
|
|
||||||
@inherits BasePage
|
|
||||||
|
|
||||||
@page "/database/{text}"
|
|
||||||
|
|
||||||
@inject IEntityDisplayService EntityDisplayService
|
|
||||||
@using Model
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
|
|
||||||
<LayoutLargeContentComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<FormDisplayComponent Label="Patch">
|
|
||||||
<Display>
|
|
||||||
Game Patch: @Variables.GamePatch
|
|
||||||
</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
<div style="margin-left: 8px">
|
|
||||||
<ButtonGroupComponent OnClick="choice => { EntityDisplayService.SetDisplayType(choice); }"
|
|
||||||
Choice="@EntityDisplayService.GetDisplayType()"
|
|
||||||
Choices="@EntityDisplayService.DefaultChoices()"></ButtonGroupComponent>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
@if (Text!.Trim().ToLower().Equals("walter"))
|
|
||||||
{
|
|
||||||
<PaperComponent>
|
|
||||||
<CodeComponent>
|
|
||||||
Unhandled Exception: EXCEPTION_MEMORY_SIZE_VIOLATION
|
|
||||||
UNIT_WALTER too powerful to be displayed.
|
|
||||||
|
|
||||||
This SHOULD NEVER HAPPEN!
|
|
||||||
</CodeComponent>
|
|
||||||
</PaperComponent>
|
|
||||||
}
|
|
||||||
else if (_entity == null)
|
|
||||||
{
|
|
||||||
<PaperComponent>
|
|
||||||
<div>Invalid entity name entered: <span id="invalidSearch">@Text</span></div>
|
|
||||||
<div>No such entity. Did you mean <b>"<span id="validSearch">Throne</span>"</b>?</div>
|
|
||||||
</PaperComponent>
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<PaperComponent>
|
|
||||||
<CascadingValue Value="_entity">
|
|
||||||
<CascadingValue Value="@EntityDisplayService.GetDisplayType()">
|
|
||||||
|
|
||||||
<EntityViewComponent></EntityViewComponent>
|
|
||||||
</CascadingValue>
|
|
||||||
</CascadingValue>
|
|
||||||
|
|
||||||
</PaperComponent>
|
|
||||||
}
|
|
||||||
|
|
||||||
</LayoutLargeContentComponent>
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Parameter] public string? Text { get; set; }
|
|
||||||
|
|
||||||
private EntityModel? _entity;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
EntityDisplayService.Subscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
|
||||||
{
|
|
||||||
base.OnParametersSet();
|
|
||||||
base.OnInitialized();
|
|
||||||
|
|
||||||
FocusEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FocusEntity()
|
|
||||||
{
|
|
||||||
foreach (var e in EntityData.Get().Values)
|
|
||||||
{
|
|
||||||
if (e.Info().Name.ToLower().Equals(Text!.ToLower()))
|
|
||||||
{
|
|
||||||
_entity = e;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
EntityDisplayService.Unsubscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
@if (Entity != null)
|
|
||||||
{
|
|
||||||
var isVanguard = Entity.VanguardAdded() != null ? " vanguard" : "";
|
|
||||||
|
|
||||||
<div id="@Entity.EntityType.ToLower()-@Entity.Info().Name.ToLower()" class="entitiesContainer @isVanguard">
|
|
||||||
<EntityHeaderComponent></EntityHeaderComponent>
|
|
||||||
<div class="entityPartsContainer">
|
|
||||||
<EntityVanguardAddedComponent></EntityVanguardAddedComponent>
|
|
||||||
<EntityInfoComponent></EntityInfoComponent>
|
|
||||||
<EntityVanguardsComponent></EntityVanguardsComponent>
|
|
||||||
<EntityProductionComponent></EntityProductionComponent>
|
|
||||||
<EntityStatsComponent></EntityStatsComponent>
|
|
||||||
<EntityMechanicsComponent></EntityMechanicsComponent>
|
|
||||||
<EntityPassivesComponent></EntityPassivesComponent>
|
|
||||||
<EntityPyreSpellsComponent></EntityPyreSpellsComponent>
|
|
||||||
<EntityUpgradesComponent></EntityUpgradesComponent>
|
|
||||||
<EntityWeaponsComponent></EntityWeaponsComponent>
|
|
||||||
<EntityAbilitiesComponent></EntityAbilitiesComponent>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.entitiesContainer {
|
|
||||||
margin-bottom: 12px;
|
|
||||||
width: 100%;
|
|
||||||
overflow-y: auto;
|
|
||||||
overflow-x: hidden;
|
|
||||||
padding: 30px;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.entityPartsContainer {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media only screen and (max-width: 1025px) {
|
|
||||||
.entitiesContainer {
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[CascadingParameter] public EntityModel? Entity { get; set; }
|
|
||||||
|
|
||||||
[CascadingParameter] public string? StyleType { get; set; }
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
@if (Entity!.IdAbilities().Count > 0)
|
|
||||||
{
|
|
||||||
@if (StyleType.Equals("Plain"))
|
|
||||||
{
|
|
||||||
@foreach (var idAbility in Entity.IdAbilities())
|
|
||||||
{
|
|
||||||
var spell = EntityModel.Get(idAbility.Id);
|
|
||||||
|
|
||||||
var info = spell.Info();
|
|
||||||
var production = spell.Production();
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<b>Ability Name:</b> @spell.Info().Name
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>- Description:</b> @((MarkupString)info.Description)
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (!info.Notes.Trim().Equals(""))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>- Notes:</b> @((MarkupString)info.Notes)
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div>
|
|
||||||
@if (production != null)
|
|
||||||
{
|
|
||||||
if (production.Energy != 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>- Energy: </b> @production.Energy
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (!production.DefensiveLayer.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>- Shields:</b> @production.DefensiveLayer
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
if (production.BuildTime != 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>- BuildTime: </b> @production.BuildTime
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
if (production.Cooldown != 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>- Cooldown: </b> @production.Cooldown
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<EntityDisplayComponent Title="Abilities">
|
|
||||||
@foreach (var idAbility in Entity.IdAbilities())
|
|
||||||
{
|
|
||||||
var spell = EntityModel.Get(idAbility.Id);
|
|
||||||
|
|
||||||
var info = spell.Info();
|
|
||||||
var production = spell.Production();
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<b>Name:</b>
|
|
||||||
<EntityLabelComponent EntityId="@spell.DataType"/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>Description:</b> @((MarkupString)info.Description)
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (!info.Notes.Trim().Equals(""))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Notes:</b> @((MarkupString)info.Notes)
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div>
|
|
||||||
@if (production != null)
|
|
||||||
{
|
|
||||||
if (production.Energy != 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b> Energy: </b> @production.Energy
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (!production.DefensiveLayer.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Shields:</b> @production.DefensiveLayer
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
if (production.BuildTime != 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b> BuildTime: </b> @production.BuildTime
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
if (production.Cooldown != 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b> Cooldown: </b> @production.Cooldown
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</EntityDisplayComponent>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[CascadingParameter] public EntityModel? Entity { get; set; }
|
|
||||||
|
|
||||||
[CascadingParameter] public string StyleType { get; set; } = "Detailed";
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
@if (StyleType.Equals("Plain"))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b id="entityName">@Entity?.Info().Name</b>
|
|
||||||
@if (Entity?.Info().Descriptive != DescriptiveType.None)
|
|
||||||
{
|
|
||||||
<span>, @Entity?.Info().Descriptive.Replace("_", " ")</span>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<div class="entityHeader">
|
|
||||||
<div id="entityName" class="entityHeaderText">
|
|
||||||
@Entity?.Info().Name
|
|
||||||
</div>
|
|
||||||
<div style="font-size:1.4rem;">
|
|
||||||
<b>@Entity?.EntityType.Replace("_", " ")</b>
|
|
||||||
@if (Entity?.Info().Descriptive != DescriptiveType.None)
|
|
||||||
{
|
|
||||||
<span>
|
|
||||||
<b>:</b> @Entity!.Info().Descriptive.Replace("_", " ")
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div>
|
|
||||||
@if (Entity.Info().FlavorText != "")
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<i> @((MarkupString)Entity.Info().FlavorText)</i>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.entityHeader {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 4px;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-bottom: 22px;
|
|
||||||
width: 100%;
|
|
||||||
margin-left: -6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.entityHeaderText {
|
|
||||||
font-size: 2rem;
|
|
||||||
font-weight: 900;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media only screen and (max-width: 1025px) {
|
|
||||||
.entityHeader {
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: normal;
|
|
||||||
margin-left: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
}
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[CascadingParameter] public EntityModel? Entity { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
[CascadingParameter] public string StyleType { get; set; } = "Detailed";
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
@inject IGlossaryService glossaryService
|
|
||||||
|
|
||||||
@if (StyleType.Equals("Plain"))
|
|
||||||
{
|
|
||||||
@if (Entity!.Info().Description != "")
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Description:</b> @((MarkupString)glossaryService.LinkifyText(Entity.Info().Description))
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (Entity.Info().Notes != "")
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Notes:</b> @((MarkupString)glossaryService.LinkifyText(Entity.Info().Notes))
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (Entity.Info().FlavorText != "")
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<i>@((MarkupString)glossaryService.LinkifyText(Entity.Info().FlavorText))</i>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="infoDisplayContainer">
|
|
||||||
<div>
|
|
||||||
@if (Entity.Faction() != null)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Faction:</b> @EntityData.Get()[Entity.Faction().Faction].Info().Name
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (Entity.Tier() != null)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Tier:</b> @Entity.Tier().Tier
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (Entity.Hotkey() != null)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<b>Hotkey Group:</b> @Entity.Hotkey().HotkeyGroup
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>Hotkey:</b> @Entity.Hotkey().Hotkey
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>Hold Space:</b> @(Entity.Hotkey().HoldSpace ? "Yes" : "No")
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<EntityDisplayComponent Title="Info">
|
|
||||||
@if (Entity!.Info().Description != "")
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Description:</b> @((MarkupString)glossaryService.LinkifyText(Entity.Info().Description))
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (Entity.Info().Notes != "")
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Notes:</b> @((MarkupString)glossaryService.LinkifyText(Entity.Info().Notes))
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="infoDisplayContainer">
|
|
||||||
<div>
|
|
||||||
@if (Entity.Faction() != null)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Faction:</b> @EntityData.Get()[Entity.Faction().Faction].Info().Name
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (Entity.Tier() != null)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Tier:</b> @Entity.Tier().Tier
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (Entity.Hotkey() != null)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<b>Hotkey Group:</b> @Entity.Hotkey().HotkeyGroup
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>Hotkey:</b> @Entity.Hotkey().Hotkey
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>Hold Space:</b> @(Entity.Hotkey().HoldSpace ? "Yes" : "No")
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</EntityDisplayComponent>
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.infoDisplayContainer {
|
|
||||||
display: flex;
|
|
||||||
gap: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media only screen and (max-width: 1025px) {
|
|
||||||
.infoDisplayContainer {
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[CascadingParameter] public EntityModel? Entity { get; set; }
|
|
||||||
|
|
||||||
[CascadingParameter] public string StyleType { get; set; } = "Detailed";
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
@if (Entity!.Mechanics().Count > 0)
|
|
||||||
{
|
|
||||||
<EntityDisplayComponent Title="Mechanics">
|
|
||||||
<div>
|
|
||||||
@foreach (var data in Entity.Mechanics())
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<span>
|
|
||||||
<b>Name:</b> @data.Name
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>Description:</b> @data.Description
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</EntityDisplayComponent>
|
|
||||||
}
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[CascadingParameter] public EntityModel? Entity { get; set; }
|
|
||||||
|
|
||||||
[CascadingParameter] public string StyleType { get; set; } = "Detailed";
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
@if (Entity!.IdPassives().Count > 0)
|
|
||||||
{
|
|
||||||
@if (StyleType.Equals("Plain"))
|
|
||||||
{
|
|
||||||
@foreach (var idPassive in Entity.IdPassives())
|
|
||||||
{
|
|
||||||
var passive = EntityModel.Get(idPassive.Id);
|
|
||||||
|
|
||||||
var info = passive.Info();
|
|
||||||
|
|
||||||
var production = passive.Production();
|
|
||||||
|
|
||||||
var requirements = passive.Requirements();
|
|
||||||
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<b>Passive Name:</b> @info.Name
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>- Description:</b> @((MarkupString)info.Description)
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (!info.Notes.Trim().Equals(""))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>- Notes:</b> @((MarkupString)info.Notes)
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (production != null)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
@if (production.Pyre != 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>- Pyre:</b> @production.Pyre
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (production.Cooldown != 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>- Cooldown:</b> @production.Cooldown.ToString()s
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (requirements.Count > 0)
|
|
||||||
{
|
|
||||||
@foreach (var requirement in requirements)
|
|
||||||
{
|
|
||||||
var requirementModel = EntityData.Get()[requirement.Id];
|
|
||||||
<div>
|
|
||||||
<span>
|
|
||||||
<b>- @requirement.Requirement.Replace("_", " "):</b> @requirementModel.Info().Name
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<EntityDisplayComponent Title="Passives">
|
|
||||||
@foreach (var idPassive in Entity.IdPassives())
|
|
||||||
{
|
|
||||||
var passive = EntityModel.Get(idPassive.Id);
|
|
||||||
|
|
||||||
var info = passive.Info();
|
|
||||||
|
|
||||||
var production = passive.Production();
|
|
||||||
|
|
||||||
var requirements = passive.Requirements();
|
|
||||||
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<b>Name:</b>
|
|
||||||
<EntityLabelComponent EntityId="@passive.DataType"/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>Description:</b> @((MarkupString)info.Description)
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (!info.Notes.Trim().Equals(""))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Notes:</b> @((MarkupString)info.Notes)
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@if (requirements.Count > 0)
|
|
||||||
{
|
|
||||||
@foreach (var requirement in requirements)
|
|
||||||
{
|
|
||||||
var requirementModel = EntityData.Get()[requirement.Id];
|
|
||||||
<div>
|
|
||||||
<span>
|
|
||||||
<b>@requirement.Requirement.Replace("_", " "):</b> @requirementModel.Info().Name
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (production != null)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
@if (production.Pyre != 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Pyre:</b> @production.Pyre
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (production.Cooldown != 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Cooldown:</b> @production.Cooldown.ToString()s
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</EntityDisplayComponent>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[CascadingParameter] public EntityModel? Entity { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
[CascadingParameter] public string StyleType { get; set; } = "Detailed";
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,225 +0,0 @@
|
|||||||
@if (Production != null || Supply != null || Requirements.Count > 0)
|
|
||||||
{
|
|
||||||
@if (StyleType.Equals("Plain"))
|
|
||||||
{
|
|
||||||
@if (Requirements.Count() > 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
@foreach (var requirement in Requirements)
|
|
||||||
{
|
|
||||||
var requirementModel = EntityData.Get()[requirement.Id];
|
|
||||||
<div>
|
|
||||||
|
|
||||||
<span>
|
|
||||||
<b>@requirement.Requirement.Replace("_", " "):</b> @requirementModel.Info().Name
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (Production != null && (!Production.Alloy.Equals(0)
|
|
||||||
|| !Production.Ether.Equals(0)
|
|
||||||
|| !Production.BuildTime.Equals(0)
|
|
||||||
|| !Production.Cooldown.Equals(0)))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
@if (!Production.Alloy.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Alloy:</b> @Production.Alloy
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (!Production.Ether.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Ether:</b> @Production.Ether
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (!Production.Pyre.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Pyre:</b> @Production.Pyre
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (!Production.Pyre.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Shields:</b> @Production.DefensiveLayer
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (!Production.BuildTime.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Build Time:</b> @Production.BuildTime.ToString()s
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (!Production.Energy.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Energy:</b> @Production.Energy
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@if (!Production.Cooldown.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Cooldown:</b> @Production.Cooldown.ToString()s
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (Supply != null)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
@if (!Supply.Grants.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Grants:</b> @Supply.Grants
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (!Supply.Takes.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Takes:</b> @Supply.Takes Supply
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<EntityDisplayComponent Title="Production">
|
|
||||||
<div class="ProductionContainer">
|
|
||||||
@if (Requirements.Count() > 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
@foreach (var requirement in Requirements)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
|
|
||||||
<span>
|
|
||||||
<b>@requirement.Requirement.Replace("_", " "):</b> <EntityLabelComponent
|
|
||||||
EntityId="@requirement.Id"/>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (Production != null && (!Production.Alloy.Equals(0)
|
|
||||||
|| !Production.Ether.Equals(0)
|
|
||||||
|| !Production.BuildTime.Equals(0)
|
|
||||||
|| !Production.Cooldown.Equals(0)))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
@if (!Production.Alloy.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Alloy:</b> @Production.Alloy
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (!Production.Ether.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Ether:</b> @Production.Ether
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (!Production.Pyre.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Pyre:</b> @Production.Pyre
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (!Production.DefensiveLayer.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Shields:</b> @Production.DefensiveLayer
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (!Production.BuildTime.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Build Time:</b> @Production.BuildTime.ToString()s
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (!Production.Energy.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Energy:</b> @Production.Energy
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@if (!Production.Cooldown.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Cooldown:</b> @Production.Cooldown.ToString()s
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (Supply != null)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
@if (!Supply.Grants.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Grants:</b> @Supply.Grants
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (!Supply.Takes.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Takes:</b> @Supply.Takes Supply
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</EntityDisplayComponent>
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.ProductionContainer {
|
|
||||||
display: flex;
|
|
||||||
gap: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media only screen and (max-width: 1025px) {
|
|
||||||
.ProductionContainer {
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[CascadingParameter] public EntityModel? Entity { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
[CascadingParameter] public string StyleType { get; set; } = "Detailed";
|
|
||||||
|
|
||||||
|
|
||||||
private EntityProductionModel Production => Entity!.Production();
|
|
||||||
private List<EntityRequirementModel> Requirements => Entity!.Requirements();
|
|
||||||
private EntitySupplyModel Supply => Entity!.Supply();
|
|
||||||
|
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
|
||||||
{
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
@if (Entity!.IdPyreSpells().Count > 0)
|
|
||||||
{
|
|
||||||
@if (StyleType.Equals("Plain"))
|
|
||||||
{
|
|
||||||
@foreach (var pyreSpell in Entity.IdPyreSpells())
|
|
||||||
{
|
|
||||||
var spell = EntityModel.Get(pyreSpell.Id);
|
|
||||||
|
|
||||||
var info = spell.Info();
|
|
||||||
var production = spell.Production();
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<b>Spell Name:</b> @spell.Info().Name
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>- Description:</b> @((MarkupString)info.Description)
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
@if (production != null)
|
|
||||||
{
|
|
||||||
if (production.Pyre != 0)
|
|
||||||
{
|
|
||||||
<b>- Pyre: </b>
|
|
||||||
@production.Pyre
|
|
||||||
}
|
|
||||||
|
|
||||||
if (production.BuildTime != 0)
|
|
||||||
{
|
|
||||||
<b>- BuildTime: </b>
|
|
||||||
@production.BuildTime
|
|
||||||
}
|
|
||||||
|
|
||||||
if (production.Cooldown != 0)
|
|
||||||
{
|
|
||||||
<b>- Cooldown: </b>
|
|
||||||
@production.Cooldown
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<EntityDisplayComponent Title="Pyre Spells">
|
|
||||||
@foreach (var pyreSpell in Entity.IdPyreSpells())
|
|
||||||
{
|
|
||||||
var spell = EntityModel.Get(pyreSpell.Id);
|
|
||||||
|
|
||||||
var info = spell.Info();
|
|
||||||
var production = spell.Production();
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<b>Name:</b>
|
|
||||||
<EntityLabelComponent EntityId="@spell.DataType"/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>Description:</b> @((MarkupString)info.Description)
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
@if (production != null)
|
|
||||||
{
|
|
||||||
if (production.Pyre != 0)
|
|
||||||
{
|
|
||||||
<b> Pyre: </b>
|
|
||||||
@production.Pyre
|
|
||||||
}
|
|
||||||
|
|
||||||
if (production.BuildTime != 0)
|
|
||||||
{
|
|
||||||
<b> BuildTime: </b>
|
|
||||||
@production.BuildTime
|
|
||||||
}
|
|
||||||
|
|
||||||
if (production.Cooldown != 0)
|
|
||||||
{
|
|
||||||
<b> Cooldown: </b>
|
|
||||||
@production.Cooldown
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</EntityDisplayComponent>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[CascadingParameter] public EntityModel? Entity { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
[CascadingParameter] public string StyleType { get; set; } = "Detailed";
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,180 +0,0 @@
|
|||||||
@if (Vitality != null || Movement != null)
|
|
||||||
{
|
|
||||||
@if (StyleType.Equals("Plain"))
|
|
||||||
{
|
|
||||||
@if (Vitality != null)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
@if (!Vitality.DefenseLayer.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Shield:</b> @Vitality.DefenseLayer
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (!Vitality.Health.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Health:</b> <span id="entityHealth">@Vitality.Health</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (!Vitality.Energy.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Energy:</b> @Vitality.Energy
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (!Vitality.Lasts.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Lasts:</b> @Vitality.Lasts.ToString()s
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (Vitality.Armor != "")
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Armor:</b> @Vitality.Armor
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (Vitality.IsEtheric)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b> + Etheric</b>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (Vitality.IsStructure)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b> + Structure</b>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@if (Movement != null)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
@if (!Movement.Speed.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Speed:</b> @Movement.Speed
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Speed:</b> Immobile
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<div>
|
|
||||||
<b>Move Type:</b> @Movement.Movement
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<EntityDisplayComponent Title="Stats">
|
|
||||||
<div class="statContainer">
|
|
||||||
@if (Vitality != null)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
@if (!Vitality.DefenseLayer.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Shield:</b> @Vitality.DefenseLayer
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (!Vitality.Health.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Health:</b> <span id="entityHealth">@Vitality.Health</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (!Vitality.Energy.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Energy:</b> @Vitality.Energy
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (!Vitality.Lasts.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Lasts:</b> @Vitality.Lasts.ToString()s
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (Vitality.Armor != "")
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Armor:</b> @Vitality.Armor
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (Vitality.IsEtheric)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b> + Etheric</b>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (Vitality.IsStructure)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b> + Structure</b>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@if (Movement != null)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
@if (!Movement.Speed.Equals(0))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Speed:</b> @Movement.Speed
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Speed:</b> Immobile
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<div>
|
|
||||||
<b>Move Type:</b> @Movement.Movement
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</EntityDisplayComponent>
|
|
||||||
<style>
|
|
||||||
.statContainer {
|
|
||||||
display: flex;
|
|
||||||
gap: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media only screen and (max-width: 1025px) {
|
|
||||||
.statContainer {
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[CascadingParameter] public EntityModel? Entity { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
[CascadingParameter] public string StyleType { get; set; } = "Detailed";
|
|
||||||
|
|
||||||
|
|
||||||
private EntityVitalityModel Vitality => Entity!.Vitality();
|
|
||||||
private EntityMovementModel Movement => Entity!.Movement();
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
@if (Entity!.IdUpgrades().Count > 0)
|
|
||||||
{
|
|
||||||
@if (StyleType.Equals("Plain"))
|
|
||||||
{
|
|
||||||
@foreach (var upgradeId in Entity.IdUpgrades())
|
|
||||||
{
|
|
||||||
var entity = EntityModel.Get(upgradeId.Id);
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<b>Upgrade Name:</b> @entity.Info().Name
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>- Description:</b> @entity.Info().Description
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<EntityDisplayComponent Title="Upgrades">
|
|
||||||
<div class="upgradesContainer">
|
|
||||||
@foreach (var upgradeId in Entity.IdUpgrades())
|
|
||||||
{
|
|
||||||
var entity = EntityModel.Get(upgradeId.Id);
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<b>Name:</b>
|
|
||||||
<EntityLabelComponent EntityId="@entity.DataType"/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>Description:</b> @entity.Info().Description
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</EntityDisplayComponent>
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.upgradesContainer {
|
|
||||||
display: flex;
|
|
||||||
gap: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media only screen and (max-width: 1025px) {
|
|
||||||
.upgradesContainer {
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[CascadingParameter] public EntityModel? Entity { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
[CascadingParameter] public string StyleType { get; set; } = "Detailed";
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
@if (Vanguard != null)
|
|
||||||
{
|
|
||||||
var immortalId = Vanguard.ImmortalId;
|
|
||||||
var immortal = EntityData.Get()[immortalId];
|
|
||||||
|
|
||||||
var replaced = EntityData.Get()[Vanguard.ReplaceId];
|
|
||||||
|
|
||||||
@if (StyleType.Equals("Plain"))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Immortal:</b> @immortal.Info().Name
|
|
||||||
</div>
|
|
||||||
@if (!Vanguard.ReplaceId.Equals(""))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Replaces:</b> @replaced.Info().Name
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<EntityDisplayComponent Title="Vanguard">
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<b>Immortal:</b>
|
|
||||||
<EntityLabelComponent EntityId="@immortal.DataType"/>
|
|
||||||
</div>
|
|
||||||
@if (!Vanguard.ReplaceId.Equals(""))
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>Replaces:</b>
|
|
||||||
<EntityLabelComponent EntityId="@Vanguard.ReplaceId"></EntityLabelComponent>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</EntityDisplayComponent>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[CascadingParameter] public EntityModel? Entity { get; set; }
|
|
||||||
|
|
||||||
private EntityVanguardAddedModel? Vanguard => Entity?.VanguardAdded();
|
|
||||||
|
|
||||||
[CascadingParameter] public string StyleType { get; set; } = "Detailed";
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
@if (Entity!.IdVanguards().Count > 0)
|
|
||||||
{
|
|
||||||
@if (StyleType.Equals("Plain"))
|
|
||||||
{
|
|
||||||
@foreach (var data in Entity.IdVanguards())
|
|
||||||
{
|
|
||||||
var entity = EntityModel.Get(data.Id);
|
|
||||||
|
|
||||||
var requirements = entity.Requirements();
|
|
||||||
var vanguardAdded = entity.VanguardAdded();
|
|
||||||
var replaced = EntityData.Get()[vanguardAdded.ReplaceId];
|
|
||||||
var immortal = EntityData.Get()[vanguardAdded.ImmortalId];
|
|
||||||
|
|
||||||
|
|
||||||
var productionBuilding = (from building in requirements
|
|
||||||
where building.Requirement == RequirementType.Production_Building
|
|
||||||
select building).First().Id;
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<b>Name:</b> @entity.Info().Name
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>- Replaces:</b> @replaced.Info().Name
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>- Built From:</b> @immortal.Info().Name
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<EntityDisplayComponent Title="Vanguards">
|
|
||||||
@foreach (var data in Entity.IdVanguards())
|
|
||||||
{
|
|
||||||
var entity = EntityModel.Get(data.Id);
|
|
||||||
|
|
||||||
var requirements = entity.Requirements();
|
|
||||||
var vanguard = entity.VanguardAdded();
|
|
||||||
var productionBuilding = (from building in requirements
|
|
||||||
where building.Requirement == RequirementType.Production_Building
|
|
||||||
select building).First().Id;
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<b>Name:</b>
|
|
||||||
<EntityLabelComponent EntityId="@entity.DataType"/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>Replaces:</b>
|
|
||||||
<EntityLabelComponent EntityId="@vanguard.ReplaceId"/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>Built From:</b>
|
|
||||||
<EntityLabelComponent EntityId="@productionBuilding"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</EntityDisplayComponent>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[CascadingParameter] public EntityModel? Entity { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
[CascadingParameter] public string StyleType { get; set; } = "Detailed";
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,263 +0,0 @@
|
|||||||
@inject IStorageService StorageService
|
|
||||||
@using Services.Website
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
@if (Entity!.Weapons().Count > 0)
|
|
||||||
{
|
|
||||||
@if (StyleType.Equals("Plain"))
|
|
||||||
{
|
|
||||||
var index = 0;
|
|
||||||
|
|
||||||
foreach (var data in Entity.Weapons())
|
|
||||||
{
|
|
||||||
index++;
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<div class="damageContainer">
|
|
||||||
<div>
|
|
||||||
<b>Weapon @index</b>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<b>- Damage:</b> @data.Damage
|
|
||||||
</div>
|
|
||||||
@if (data.LightDamage != 0)
|
|
||||||
{
|
|
||||||
<div class="alternateDamage">
|
|
||||||
<i>- vs Light: @data.LightDamage</i>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (data.MediumDamage != 0)
|
|
||||||
{
|
|
||||||
<div class="alternateDamage">
|
|
||||||
<i>- vs Medium: @data.MediumDamage</i>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (data.HeavyDamage != 0)
|
|
||||||
{
|
|
||||||
<div class="alternateDamage">
|
|
||||||
<i>- vs Heavy: @data.HeavyDamage</i>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (data.EthericDamageBonus != 0)
|
|
||||||
{
|
|
||||||
<div class="alternateDamage">
|
|
||||||
<i>- vs Etheric +@data.EthericDamageBonus</i>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (data.StructureDamageBonus != 0)
|
|
||||||
{
|
|
||||||
<div class="alternateDamage">
|
|
||||||
<i>- vs Structure: +@data.StructureDamageBonus</i>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>- Range:</b> @data.Range
|
|
||||||
</div>
|
|
||||||
@if (data.SecondsBetweenAttacks > 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>- AttacksPerSecond:</b> @(1 / data.SecondsBetweenAttacks)
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
- (or <b>SecondsBetweenAttacks:</b> @data.SecondsBetweenAttacks)
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else if (data.AttacksPerSecond > 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>- AttacksPerSecond:</b> @data.AttacksPerSecond
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
- (or <b>SecondsBetweenAttacks:</b> @(1 / data.AttacksPerSecond))
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<b>- Targets:</b> @data.Targets
|
|
||||||
</div>
|
|
||||||
@if (data.AttacksPerSecond != 0)
|
|
||||||
{
|
|
||||||
<span>
|
|
||||||
<b>- DPS:</b> @(Math.Round(data.Damage * data.AttacksPerSecond))
|
|
||||||
</span>
|
|
||||||
@if (data.LightDamage != 0)
|
|
||||||
{
|
|
||||||
<span>
|
|
||||||
<i>- Light DPS: @(Math.Round(data.LightDamage * data.AttacksPerSecond))</i>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (data.MediumDamage != 0)
|
|
||||||
{
|
|
||||||
<span>
|
|
||||||
<i>- Medium DPS: @(Math.Round(data.MediumDamage * data.AttacksPerSecond))</i>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (data.HeavyDamage != 0)
|
|
||||||
{
|
|
||||||
<span>
|
|
||||||
<i>- Heavy DPS: @(Math.Round(data.HeavyDamage * data.AttacksPerSecond))</i>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<EntityDisplayComponent Title="Weapons">
|
|
||||||
<div class="weaponsContainer">
|
|
||||||
@foreach (var data in Entity.Weapons())
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<div class="damageContainer">
|
|
||||||
<div>
|
|
||||||
<b>Damage:</b> @data.Damage
|
|
||||||
</div>
|
|
||||||
@if (data.LightDamage != 0)
|
|
||||||
{
|
|
||||||
<div class="alternateDamage">
|
|
||||||
<i>vs Light: @data.LightDamage</i>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (data.MediumDamage != 0)
|
|
||||||
{
|
|
||||||
<div class="alternateDamage">
|
|
||||||
<i>vs Medium: @data.MediumDamage</i>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (data.HeavyDamage != 0)
|
|
||||||
{
|
|
||||||
<div class="alternateDamage">
|
|
||||||
<i>vs Heavy: @data.HeavyDamage</i>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (data.EthericDamageBonus != 0)
|
|
||||||
{
|
|
||||||
<div class="alternateDamage">
|
|
||||||
<i>vs Etheric +@data.EthericDamageBonus</i>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (data.StructureDamageBonus != 0)
|
|
||||||
{
|
|
||||||
<div class="alternateDamage">
|
|
||||||
<i>vs Structure: +@data.StructureDamageBonus</i>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>Range:</b> @data.Range
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (data.SecondsBetweenAttacks > 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>AttacksPerSecond:</b> @(1 / data.SecondsBetweenAttacks)
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
(or <b>SecondsBetweenAttacks:</b> @data.SecondsBetweenAttacks)
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else if (data.AttacksPerSecond > 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>AttacksPerSecond:</b> @data.AttacksPerSecond
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
(or <b>SecondsBetweenAttacks:</b> @(1 / data.AttacksPerSecond))
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<b>Targets:</b> @data.Targets
|
|
||||||
</div>
|
|
||||||
@if (data.AttacksPerSecond != 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<b>DPS:</b> @(Math.Round(data.Damage * data.AttacksPerSecond))
|
|
||||||
</div>
|
|
||||||
@if (data.LightDamage != 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<i>Light DPS: @(Math.Round(data.LightDamage * data.AttacksPerSecond))</i>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (data.MediumDamage != 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<i>Medium DPS: @(Math.Round(data.MediumDamage * data.AttacksPerSecond))</i>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (data.HeavyDamage != 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<i>Heavy DPS: @(Math.Round(data.HeavyDamage * data.AttacksPerSecond))</i>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</EntityDisplayComponent>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.weaponsContainer {
|
|
||||||
display: flex;
|
|
||||||
gap: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media only screen and (max-width: 1025px) {
|
|
||||||
.weaponsContainer {
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.alternateDamage {
|
|
||||||
margin-left: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.damageContainer {
|
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[CascadingParameter] public EntityModel? Entity { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
[CascadingParameter] public string StyleType { get; set; } = "Detailed";
|
|
||||||
|
|
||||||
private bool _isDynamicFormatting;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
StorageService.Subscribe(RefreshDefaults);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void RefreshDefaults()
|
|
||||||
{
|
|
||||||
_isDynamicFormatting = StorageService.GetValue<bool>(StorageKeys.IsDynamicFormatting);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
StorageService.Unsubscribe(RefreshDefaults);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,264 +0,0 @@
|
|||||||
<div class="desktopFilters">
|
|
||||||
<div class="desktopFiltersContainer">
|
|
||||||
<div class="filtersContainer">
|
|
||||||
<div class="filterContainer">
|
|
||||||
@foreach (var choice in EntityFilterService.GetFactionChoices())
|
|
||||||
{
|
|
||||||
var styleClass = "";
|
|
||||||
if (choice.Equals(EntityFilterService.GetFactionType()))
|
|
||||||
{
|
|
||||||
styleClass = "selected";
|
|
||||||
}
|
|
||||||
|
|
||||||
<button @onclick="@(e => OnChangeFaction(choice))"
|
|
||||||
class="choiceButton @styleClass">
|
|
||||||
@(choice == DataType.Any
|
|
||||||
? DataType.Any
|
|
||||||
: EntityData.Get()[choice].Info().Name)
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (EntityFilterService.GetFactionType() != "Any" && EntityFilterService.GetFactionType() != "None")
|
|
||||||
{
|
|
||||||
<div class="filterContainer">
|
|
||||||
@foreach (var choice in EntityFilterService.GetImmortalChoices())
|
|
||||||
{
|
|
||||||
var name = EntityData.Get()[choice].Info().Name;
|
|
||||||
|
|
||||||
var styleClass = "";
|
|
||||||
if (choice.Equals(EntityFilterService.GetImmortalType()))
|
|
||||||
{
|
|
||||||
styleClass = "selected";
|
|
||||||
}
|
|
||||||
|
|
||||||
<button class="choiceButton @styleClass"
|
|
||||||
@onclick="@(e => OnChangeImmortal(choice))">@name</button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div class="filterContainer">
|
|
||||||
@foreach (var choice in EntityFilterService.GetEntityChoices())
|
|
||||||
{
|
|
||||||
var styleClass = "";
|
|
||||||
if (choice.Equals(EntityFilterService.GetEntityType()))
|
|
||||||
{
|
|
||||||
styleClass = "selected";
|
|
||||||
}
|
|
||||||
|
|
||||||
<button class="choiceButton @styleClass"
|
|
||||||
@onclick="@(e => OnChangeEntity(choice))">@choice.Replace("_", " ")</button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<FormTextComponent Id="filterName" Label="Filter Name" Placeholder="Throne..."
|
|
||||||
OnChange="@(e => EntityFilterService.EnterSearchText(e.Value!.ToString()!))"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mobileFilters">
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<FormSelectComponent OnChange="@OnFactionChanged">
|
|
||||||
<FormLabelComponent>Faction</FormLabelComponent>
|
|
||||||
<ChildContent>
|
|
||||||
<option value="@DataType.Any" selected>Any</option>
|
|
||||||
<option value="@DataType.FACTION_Aru">Aru</option>
|
|
||||||
<option value="@DataType.FACTION_QRath">Q'Rath</option>
|
|
||||||
</ChildContent>
|
|
||||||
</FormSelectComponent>
|
|
||||||
|
|
||||||
<FormSelectComponent OnChange="@OnImmortalChanged">
|
|
||||||
<FormLabelComponent>Immortal</FormLabelComponent>
|
|
||||||
<ChildContent>
|
|
||||||
<option value="@DataType.Any" selected>Any</option>
|
|
||||||
<option value="@DataType.IMMORTAL_Atzlan">Atzlan</option>
|
|
||||||
<option value="@DataType.IMMORTAL_Mala">Mala</option>
|
|
||||||
<option value="@DataType.IMMORTAL_Xol">Xol</option>
|
|
||||||
<option value="@DataType.IMMORTAL_Orzum">Orzum</option>
|
|
||||||
<option value="@DataType.IMMORTAL_Ajari">Ajari</option>
|
|
||||||
</ChildContent>
|
|
||||||
</FormSelectComponent>
|
|
||||||
|
|
||||||
<FormSelectComponent OnChange="@OnEntityChanged">
|
|
||||||
<FormLabelComponent>Entity</FormLabelComponent>
|
|
||||||
<ChildContent>
|
|
||||||
<option value="@EntityType.Any">Any</option>
|
|
||||||
<option value="@EntityType.Ability">Ability</option>
|
|
||||||
<option value="@EntityType.Army" selected>Army</option>
|
|
||||||
<option value="@EntityType.Building">Building</option>
|
|
||||||
<option value="@EntityType.Building_Upgrade">Building Upgrade</option>
|
|
||||||
<option value="@EntityType.Command">Command</option>
|
|
||||||
<option value="@EntityType.Faction">Faction</option>
|
|
||||||
<option value="@EntityType.Immortal">Immortal</option>
|
|
||||||
<option value="@EntityType.Pyre_Spell">Spell</option>
|
|
||||||
<option value="@EntityType.Passive">Passive</option>
|
|
||||||
<option value="@EntityType.Tech">Tech</option>
|
|
||||||
<option value="@EntityType.Worker">Worker</option>
|
|
||||||
</ChildContent>
|
|
||||||
</FormSelectComponent>
|
|
||||||
|
|
||||||
|
|
||||||
<FormTextComponent Id="filterName" Label="Filter Name" Placeholder="Throne..." OnChange="OnSearchTextChanged"/>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
.desktopFilters {
|
|
||||||
display: flex;
|
|
||||||
gap: 12px;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
justify-items: flex-start;
|
|
||||||
top: 50px;
|
|
||||||
padding: 12px;
|
|
||||||
width: 100%;
|
|
||||||
left: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.desktopFiltersContainer {
|
|
||||||
width: 75%;
|
|
||||||
min-width: 1000px;
|
|
||||||
margin: auto;
|
|
||||||
display: flex;
|
|
||||||
gap: 16px;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
justify-items: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filtersContainer {
|
|
||||||
display: flex;
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filterContainer {
|
|
||||||
display: flex;
|
|
||||||
background-color: var(--background);
|
|
||||||
gap: 2px;
|
|
||||||
margin-right: auto;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.choiceButton {
|
|
||||||
background-color: var(--primary);
|
|
||||||
color: white;
|
|
||||||
padding: 12px;
|
|
||||||
border: 1px solid var(--primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.choiceButton:hover {
|
|
||||||
background-color: var(--primary-hover);
|
|
||||||
border-color: var(--primary-border-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.selected {
|
|
||||||
background-color: var(--secondary);
|
|
||||||
color: white;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.selected:hover {
|
|
||||||
background-color: var(--secondary-hover);
|
|
||||||
border-color: var(--secondary-border-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.filterContainer .choiceButton:first-child {
|
|
||||||
border-top-left-radius: 8px;
|
|
||||||
border-bottom-left-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.filterContainer .choiceButton:last-child {
|
|
||||||
border-top-right-radius: 8px;
|
|
||||||
border-bottom-right-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media only screen and (max-width: 1025px) {
|
|
||||||
.desktopNavContainer {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media only screen and (max-width: 480px) {
|
|
||||||
.filtersContainer {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filterContainer {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobileFilters {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media only screen and (max-width: 1024px) {
|
|
||||||
.mobileFilters {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.desktopFilters {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.desktopSpacer {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Inject] public IEntityFilterService EntityFilterService { get; set; } = default!;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnChangeFaction(string clickedFaction)
|
|
||||||
{
|
|
||||||
EntityFilterService.SelectFactionType(clickedFaction);
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnChangeImmortal(string clickedImmortal)
|
|
||||||
{
|
|
||||||
EntityFilterService.SelectImmortalType(clickedImmortal);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnChangeEntity(string clickedEntity)
|
|
||||||
{
|
|
||||||
EntityFilterService.SelectEntityType(clickedEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnFactionChanged(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
EntityFilterService.SelectFactionType(e.Value!.ToString()!);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnImmortalChanged(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
EntityFilterService.SelectImmortalType(e.Value!.ToString()!);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OnEntityChanged(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
EntityFilterService.SelectEntityType(e.Value!.ToString()!);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OnSearchTextChanged(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
EntityFilterService.EnterSearchText(e.Value!.ToString()!);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
|
|
||||||
.desktopFilters {
|
|
||||||
display: flex;
|
|
||||||
gap: 12px;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
justify-items: flex-start;
|
|
||||||
top: 50px;
|
|
||||||
padding: 12px;
|
|
||||||
width: 100%;
|
|
||||||
left: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.desktopFiltersContainer {
|
|
||||||
width: 75%;
|
|
||||||
min-width: 1000px;
|
|
||||||
margin: auto;
|
|
||||||
display: flex;
|
|
||||||
gap: 16px;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
justify-items: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filtersContainer {
|
|
||||||
display: flex;
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filterContainer {
|
|
||||||
display: flex;
|
|
||||||
background-color: var(--background);
|
|
||||||
gap: 2px;
|
|
||||||
margin-right: auto;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.choiceButton {
|
|
||||||
background-color: var(--primary);
|
|
||||||
color: white;
|
|
||||||
padding: 12px;
|
|
||||||
border: 1px solid var(--primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.choiceButton:hover {
|
|
||||||
background-color: var(--primary-hover);
|
|
||||||
border-color: var(--primary-border-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.selected {
|
|
||||||
background-color: var(--secondary);
|
|
||||||
color: white;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.selected:hover {
|
|
||||||
background-color: var(--secondary-hover);
|
|
||||||
border-color: var(--secondary-border-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.filterContainer .choiceButton:first-child {
|
|
||||||
border-top-left-radius: 8px;
|
|
||||||
border-bottom-left-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.filterContainer .choiceButton:last-child {
|
|
||||||
border-top-right-radius: 8px;
|
|
||||||
border-bottom-right-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 1025px) {
|
|
||||||
.desktopNavContainer {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 480px) {
|
|
||||||
.filtersContainer {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filterContainer {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobileFilters {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 1024px) {
|
|
||||||
.mobileFilters {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.desktopFilters {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.desktopSpacer {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
@page "/economy-comparison"
|
|
||||||
|
|
||||||
@inherits BasePage
|
|
||||||
|
|
||||||
@implements IDisposable
|
|
||||||
@inject IEconomyComparisonService EconomyComparisonService
|
|
||||||
@layout PageLayout
|
|
||||||
|
|
||||||
<LayoutMediumContentComponent>
|
|
||||||
<WebsiteTitleComponent>Economy Comparision</WebsiteTitleComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<div>You</div>
|
|
||||||
<EconomyInputComponent ForPlayer="0"/>
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<div>Them</div>
|
|
||||||
<EconomyInputComponent ForPlayer="1"/>
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<EconomyDifferenceComponent/>
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<ChartComponent/>
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
<ContentDividerComponent/>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
What is this tool for?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
Compare two economies together to determine best attack timing windows.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
</PaperComponent>
|
|
||||||
</LayoutMediumContentComponent>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
EconomyComparisonService.Subscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
EconomyComparisonService.Unsubscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,200 +0,0 @@
|
|||||||
@inject IEconomyComparisonService economyComparisonService
|
|
||||||
@inject IJSRuntime jsRuntime;
|
|
||||||
@using Model.BuildOrders
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
<div class="chartsContainer">
|
|
||||||
|
|
||||||
@{
|
|
||||||
var index = 0;
|
|
||||||
}
|
|
||||||
@foreach (var chart in charts)
|
|
||||||
{
|
|
||||||
index++;
|
|
||||||
|
|
||||||
<div style="width: 0; height: @chart.ValueDisplayMax.ToString()px">
|
|
||||||
<div
|
|
||||||
style="left: calc(-@width.ToString()px / 2); position: relative; border: 2px solid gray; border-radius:2px; width: @chart.IntervalDisplayMax.ToString()px; height: @chart.ValueDisplayMax.ToString()px">
|
|
||||||
@foreach (var point in chart.Points)
|
|
||||||
{
|
|
||||||
var xCoord = point.GetInterval(chart.HighestIntervalPoint, chart.IntervalDisplayMax);
|
|
||||||
|
|
||||||
var show = int.Parse(xCoord) / 6 % 2;
|
|
||||||
var player = index - 1;
|
|
||||||
|
|
||||||
if (show == player)
|
|
||||||
{
|
|
||||||
<div style="position: absolute;
|
|
||||||
bottom:@point.GetValue(highestAlloyPoint, chart.ValueDisplayMax)px;
|
|
||||||
left:@point.GetInterval(chart.HighestIntervalPoint, chart.IntervalDisplayMax)px;
|
|
||||||
width: 0px;
|
|
||||||
height: 0px;">
|
|
||||||
<div
|
|
||||||
style="width:1px; height: 1px; border-top-right-radius:10px; border-top-left-radius:10px; border: 2px solid @chart.ChartColor; background-color:@chart.ChartColor">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.chartsContainer {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
private readonly int width = 800;
|
|
||||||
private readonly int height = 700;
|
|
||||||
|
|
||||||
private List<ChartModel> charts = new();
|
|
||||||
|
|
||||||
|
|
||||||
float highestAlloyPoint;
|
|
||||||
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
economyComparisonService.Subscribe(OnBuilderOrderChanged);
|
|
||||||
|
|
||||||
OnBuilderOrderChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int lastRequestedRefreshIndex;
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
economyComparisonService.Unsubscribe(OnBuilderOrderChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OnBuilderOrderChanged()
|
|
||||||
{
|
|
||||||
charts = new List<ChartModel>();
|
|
||||||
var index = 0;
|
|
||||||
|
|
||||||
|
|
||||||
highestAlloyPoint = 0;
|
|
||||||
|
|
||||||
foreach (var buildToCompare in economyComparisonService.BuildsToCompare)
|
|
||||||
{
|
|
||||||
GenerateChart(index++, buildToCompare);
|
|
||||||
}
|
|
||||||
|
|
||||||
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(int index, BuildToCompareModel buildToCompareModel)
|
|
||||||
{
|
|
||||||
var economyOverTime = buildToCompareModel.EconomyOverTimeModel;
|
|
||||||
|
|
||||||
|
|
||||||
var alloyChart = new ChartModel
|
|
||||||
{
|
|
||||||
IntervalDisplayMax = width,
|
|
||||||
ValueDisplayMax = height,
|
|
||||||
ChartColor = buildToCompareModel.ChartColor
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
for (var interval = 0; interval < economyOverTime.Count(); interval++)
|
|
||||||
{
|
|
||||||
var alloyPoint = new PointModel { Interval = interval };
|
|
||||||
|
|
||||||
var economyAtSecond = economyOverTime[interval];
|
|
||||||
|
|
||||||
var alloyWorkerHarvesters = from harvester in economyAtSecond.HarvestPoints
|
|
||||||
where harvester.Harvest() != null
|
|
||||||
where harvester.Harvest().RequiresWorker
|
|
||||||
where harvester.Harvest().Resource == ResourceType.Alloy
|
|
||||||
select harvester;
|
|
||||||
|
|
||||||
var alloyAutomaticHarvesters = from harvester in economyAtSecond.HarvestPoints
|
|
||||||
where harvester.Harvest() != null
|
|
||||||
where !harvester.Harvest().RequiresWorker
|
|
||||||
where harvester.Harvest().Resource == ResourceType.Alloy
|
|
||||||
select harvester;
|
|
||||||
|
|
||||||
|
|
||||||
float autoAlloy = 0;
|
|
||||||
float workerSlots = 0;
|
|
||||||
float workerAlloy = 0;
|
|
||||||
|
|
||||||
float economySpending = 0;
|
|
||||||
|
|
||||||
foreach (var alloyAutoHarvester in alloyAutomaticHarvesters)
|
|
||||||
{
|
|
||||||
autoAlloy += alloyAutoHarvester.Harvest().Slots * alloyAutoHarvester.Harvest().HarvestedPerInterval;
|
|
||||||
var production = alloyAutoHarvester.Production();
|
|
||||||
if (production != null)
|
|
||||||
{
|
|
||||||
economySpending += production.Alloy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var alloyWorkerHarvester in alloyWorkerHarvesters)
|
|
||||||
{
|
|
||||||
workerSlots += alloyWorkerHarvester.Harvest().Slots;
|
|
||||||
var production = alloyWorkerHarvester.Production();
|
|
||||||
if (production != null)
|
|
||||||
{
|
|
||||||
economySpending += production.Alloy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
economySpending += (economyAtSecond.WorkerCount - 6) * 50;
|
|
||||||
|
|
||||||
workerAlloy = Math.Min(economyAtSecond.WorkerCount - economyAtSecond.BusyWorkerCount, workerSlots);
|
|
||||||
|
|
||||||
|
|
||||||
alloyPoint.TempValue = workerAlloy + autoAlloy;
|
|
||||||
|
|
||||||
|
|
||||||
if (interval > 0)
|
|
||||||
{
|
|
||||||
alloyPoint.TempValue += alloyChart.Points.Last().TempValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
alloyPoint.Value = alloyPoint.TempValue - economySpending;
|
|
||||||
|
|
||||||
highestAlloyPoint = Math.Max(highestAlloyPoint, alloyPoint.Value);
|
|
||||||
|
|
||||||
alloyChart.Points.Add(alloyPoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
alloyChart.HighestValuePoint = highestAlloyPoint;
|
|
||||||
|
|
||||||
alloyChart.HighestIntervalPoint = economyOverTime.Count();
|
|
||||||
|
|
||||||
charts.Add(alloyChart);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
@inject IEconomyComparisonService economyComparisonService
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
<div class="differences">
|
|
||||||
<div class="differenceContainer">
|
|
||||||
<div class="differenceTitle">
|
|
||||||
Starting Advantage
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
At Time: @StartingAdvantageAtTime | T @Interval.ToTime(StartingAdvantageAtTime)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="differenceContainer">
|
|
||||||
<div class="differenceTitle">
|
|
||||||
Peak Advantage
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
By Alloy: @PeakAdvantageByAlloy
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
At Time: @PeakAdvantageAtTime | T @Interval.ToTime(PeakAdvantageAtTime)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="differenceContainer">
|
|
||||||
<div class="differenceTitle">
|
|
||||||
Worsening Time
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
At Time: @WorseningTime | T @Interval.ToTime(WorseningTime)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="differenceContainer">
|
|
||||||
<div class="differenceTitle">
|
|
||||||
Miracle Time
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
At Time: @MiracleTime | T @Interval.ToTime(MiracleTime)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.differences {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 12px;
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.differenceTitle {
|
|
||||||
font-size: 1.2em;
|
|
||||||
font-weight: 800;
|
|
||||||
}
|
|
||||||
|
|
||||||
.differenceContainer {
|
|
||||||
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private int StartingAdvantageAtTime;
|
|
||||||
|
|
||||||
private int PeakAdvantageByAlloy;
|
|
||||||
private int PeakAdvantageAtTime;
|
|
||||||
|
|
||||||
private int WorseningTime;
|
|
||||||
private int MiracleTime;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
economyComparisonService.Subscribe(CalculateDifferences);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
economyComparisonService.Unsubscribe(CalculateDifferences);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CalculateDifferences()
|
|
||||||
{
|
|
||||||
PeakAdvantageByAlloy = 0;
|
|
||||||
StartingAdvantageAtTime = 0;
|
|
||||||
WorseningTime = 0;
|
|
||||||
MiracleTime = 0;
|
|
||||||
|
|
||||||
for (var interval = 0; interval < economyComparisonService.BuildsToCompare[0].EconomyOverTimeModel.Count; interval++)
|
|
||||||
{
|
|
||||||
var yourEconomy = economyComparisonService.BuildsToCompare[0].EconomyOverTimeModel[interval];
|
|
||||||
var theirEconomy = economyComparisonService.BuildsToCompare[1].EconomyOverTimeModel[interval];
|
|
||||||
|
|
||||||
var deltaEconomy = yourEconomy.Alloy - theirEconomy.Alloy;
|
|
||||||
if (deltaEconomy >= 0)
|
|
||||||
{
|
|
||||||
if (deltaEconomy > PeakAdvantageByAlloy)
|
|
||||||
{
|
|
||||||
if (StartingAdvantageAtTime == 0)
|
|
||||||
{
|
|
||||||
StartingAdvantageAtTime = interval;
|
|
||||||
}
|
|
||||||
|
|
||||||
PeakAdvantageByAlloy = (int)deltaEconomy;
|
|
||||||
PeakAdvantageAtTime = interval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (PeakAdvantageByAlloy > 0 && WorseningTime == 0)
|
|
||||||
{
|
|
||||||
WorseningTime = interval;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deltaEconomy < -1000 && MiracleTime == 0)
|
|
||||||
{
|
|
||||||
MiracleTime = interval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
@inject IEconomyComparisonService economyComparisonService
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<FormSelectComponent OnChange="@OnFactionChanged">
|
|
||||||
<FormLabelComponent>Faction</FormLabelComponent>
|
|
||||||
<ChildContent>
|
|
||||||
<option value="@DataType.FACTION_Aru" selected="@IsSelected(DataType.FACTION_Aru)">Aru</option>
|
|
||||||
<option value="@DataType.FACTION_QRath" selected="@IsSelected(DataType.FACTION_QRath)">Q'Rath</option>
|
|
||||||
</ChildContent>
|
|
||||||
</FormSelectComponent>
|
|
||||||
<ContentDividerComponent/>
|
|
||||||
<FormNumberComponent Value="@TownHallCount" OnChange="ChangeTownHallNumber">
|
|
||||||
<FormLabelComponent>Number of TownHall Expansions</FormLabelComponent>
|
|
||||||
</FormNumberComponent>
|
|
||||||
<ContentDividerComponent/>
|
|
||||||
|
|
||||||
@{
|
|
||||||
var index = 0;
|
|
||||||
}
|
|
||||||
@foreach (var timing in TownHallTimings)
|
|
||||||
{
|
|
||||||
index++;
|
|
||||||
|
|
||||||
<FormNumberComponent Value="@timing" OnChange="e => ChangeBuildTime(e, index - 1)">
|
|
||||||
<FormLabelComponent>
|
|
||||||
TownHall build time
|
|
||||||
</FormLabelComponent>
|
|
||||||
</FormNumberComponent>
|
|
||||||
}
|
|
||||||
<ContentDividerComponent/>
|
|
||||||
<FormTextComponent Label="Chart Color" Value="@ChartColor" OnChange="ChangeColor"/>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Parameter] public int ForPlayer { get; set; }
|
|
||||||
|
|
||||||
private int TownHallCount => economyComparisonService.GetTownHallCount(ForPlayer);
|
|
||||||
private string ChartColor => economyComparisonService.GetColor(ForPlayer);
|
|
||||||
private string Faction => economyComparisonService.GetFaction(ForPlayer);
|
|
||||||
private List<int> TownHallTimings => economyComparisonService.GetTownHallBuildTimes(ForPlayer);
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
economyComparisonService.Subscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
economyComparisonService.Unsubscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFactionChanged(ChangeEventArgs obj)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsSelected(string factionType)
|
|
||||||
{
|
|
||||||
return Faction.Equals(factionType);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ChangeColor(ChangeEventArgs obj)
|
|
||||||
{
|
|
||||||
economyComparisonService.ChangeColor(ForPlayer, obj.Value!.ToString()!);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ChangeTownHallNumber(ChangeEventArgs obj)
|
|
||||||
{
|
|
||||||
economyComparisonService.ChangeNumberOfTownHalls(ForPlayer, (int)obj.Value!);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ChangeBuildTime(ChangeEventArgs obj, int index)
|
|
||||||
{
|
|
||||||
economyComparisonService.ChangeTownHallTiming(ForPlayer, index, (int)obj.Value!);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
@layout PageLayout
|
|
||||||
@inject IGlossaryService glossaryService
|
|
||||||
@inject IGlossaryDialogService glossaryDialogService
|
|
||||||
@inject NavigationManager NavigationManager
|
|
||||||
|
|
||||||
@page "/glossary/{TermId}"
|
|
||||||
|
|
||||||
<LayoutMediumContentComponent>
|
|
||||||
@if (term != null)
|
|
||||||
{
|
|
||||||
<WebsiteTitleComponent>@term.Term</WebsiteTitleComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<div class="detailCategory">@term.Category</div>
|
|
||||||
<div class="detailDefinition">@((MarkupString)RenderMarkdown(term.LongDefinition))</div>
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
@if (term.RelatedEntityIds.Count > 0)
|
|
||||||
{
|
|
||||||
<PaperComponent>
|
|
||||||
<div class="detailSectionTitle">Related Entities</div>
|
|
||||||
<div class="detailRelatedList">
|
|
||||||
@foreach (var entityId in term.RelatedEntityIds)
|
|
||||||
{
|
|
||||||
<EntityLabelComponent EntityId="@entityId"/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</PaperComponent>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (term.RelatedTermIds.Count > 0)
|
|
||||||
{
|
|
||||||
<PaperComponent>
|
|
||||||
<div class="detailSectionTitle">Related Terms</div>
|
|
||||||
<div class="detailRelatedList">
|
|
||||||
@foreach (var relatedId in term.RelatedTermIds)
|
|
||||||
{
|
|
||||||
<GlossaryLabelComponent TermId="@relatedId"/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</PaperComponent>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<WebsiteTitleComponent>Term not found</WebsiteTitleComponent>
|
|
||||||
<PaperComponent>
|
|
||||||
<p>The glossary term you're looking for doesn't exist.</p>
|
|
||||||
</PaperComponent>
|
|
||||||
}
|
|
||||||
</LayoutMediumContentComponent>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.detailCategory {
|
|
||||||
font-size: 0.85rem;
|
|
||||||
opacity: 0.7;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.detailDefinition {
|
|
||||||
line-height: 1.6;
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.detailDefinition p {
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.detailSectionTitle {
|
|
||||||
font-weight: 800;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.detailRelatedList {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Parameter] public string TermId { get; set; } = "";
|
|
||||||
|
|
||||||
private GlossaryTermModel? term;
|
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
|
||||||
{
|
|
||||||
term = glossaryService.GetTerm(TermId);
|
|
||||||
}
|
|
||||||
|
|
||||||
string RenderMarkdown(string text)
|
|
||||||
{
|
|
||||||
return Markdown.ToHtml(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
@layout PageLayout
|
|
||||||
@inherits BasePage
|
|
||||||
@inject IGlossaryService glossaryService
|
|
||||||
@inject IGlossaryDialogService glossaryDialogService
|
|
||||||
|
|
||||||
@page "/glossary"
|
|
||||||
|
|
||||||
<LayoutLargeContentComponent>
|
|
||||||
<WebsiteTitleComponent>Glossary</WebsiteTitleComponent>
|
|
||||||
|
|
||||||
<div class="glossaryControls">
|
|
||||||
<input class="glossarySearch" @bind="searchText" @bind:after="OnSearchChanged" placeholder="Search terms..."/>
|
|
||||||
<div class="glossaryCategories">
|
|
||||||
<button class="glossaryCategory @(selectedCategory == null ? "active" : "")"
|
|
||||||
@onclick="() => SelectCategory(null)">All
|
|
||||||
</button>
|
|
||||||
@foreach (var cat in categories)
|
|
||||||
{
|
|
||||||
<button class="glossaryCategory @(selectedCategory == cat ? "active" : "")"
|
|
||||||
@onclick="() => SelectCategory(cat)">@cat</button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="glossaryGrid">
|
|
||||||
@foreach (var term in filteredTerms)
|
|
||||||
{
|
|
||||||
<PaperComponent>
|
|
||||||
<div class="glossaryCard" @onclick="() => glossaryDialogService.AddDialog(term.Id)">
|
|
||||||
<div class="glossaryCardHeader">
|
|
||||||
<span class="glossaryCardTerm">@term.Term</span>
|
|
||||||
<span class="glossaryCardCategory">@term.Category</span>
|
|
||||||
</div>
|
|
||||||
<div class="glossaryCardBody">@term.ShortDefinition</div>
|
|
||||||
</div>
|
|
||||||
</PaperComponent>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</LayoutLargeContentComponent>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.glossaryControls {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 12px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossarySearch {
|
|
||||||
padding: 10px 16px;
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 2px solid var(--primary-border);
|
|
||||||
background-color: var(--primary);
|
|
||||||
color: white;
|
|
||||||
font-size: 1rem;
|
|
||||||
font-family: inherit;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 500px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossarySearch::placeholder {
|
|
||||||
color: rgba(255, 255, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossaryCategories {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossaryCategory {
|
|
||||||
padding: 6px 14px;
|
|
||||||
border-radius: 16px;
|
|
||||||
border: 2px solid var(--primary-border);
|
|
||||||
background-color: var(--primary);
|
|
||||||
color: white;
|
|
||||||
cursor: pointer;
|
|
||||||
font-family: inherit;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossaryCategory.active {
|
|
||||||
background-color: var(--primary-hover);
|
|
||||||
border-color: var(--primary-border-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossaryCategory:hover {
|
|
||||||
background-color: var(--primary-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossaryGrid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossaryCard {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossaryCardHeader {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossaryCardTerm {
|
|
||||||
font-weight: 800;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossaryCardCategory {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossaryCardBody {
|
|
||||||
font-size: 0.9rem;
|
|
||||||
line-height: 1.4;
|
|
||||||
opacity: 0.9;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media only screen and (max-width: 1025px) {
|
|
||||||
.glossaryGrid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private string searchText = "";
|
|
||||||
private string? selectedCategory;
|
|
||||||
private List<string> categories = new();
|
|
||||||
private List<GlossaryTermModel> allTerms = new();
|
|
||||||
private List<GlossaryTermModel> filteredTerms = new();
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
allTerms = glossaryService.GetAllTerms();
|
|
||||||
categories = glossaryService.GetCategories();
|
|
||||||
ApplyFilter();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnSearchChanged()
|
|
||||||
{
|
|
||||||
ApplyFilter();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SelectCategory(string? category)
|
|
||||||
{
|
|
||||||
selectedCategory = category;
|
|
||||||
ApplyFilter();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ApplyFilter()
|
|
||||||
{
|
|
||||||
var query = allTerms.AsEnumerable();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(searchText))
|
|
||||||
{
|
|
||||||
query = query.Where(t =>
|
|
||||||
t.Term.Contains(searchText, StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
t.ShortDefinition.Contains(searchText, StringComparison.OrdinalIgnoreCase));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedCategory != null)
|
|
||||||
{
|
|
||||||
query = query.Where(t =>
|
|
||||||
t.Category.Equals(selectedCategory, StringComparison.OrdinalIgnoreCase));
|
|
||||||
}
|
|
||||||
|
|
||||||
filteredTerms = query.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,393 +0,0 @@
|
|||||||
@layout PageLayout
|
|
||||||
|
|
||||||
@inject IDataCollectionService DataCollectionService
|
|
||||||
@using Model
|
|
||||||
@inherits BasePage
|
|
||||||
|
|
||||||
@page "/harass-calculator"
|
|
||||||
|
|
||||||
<LayoutMediumContentComponent>
|
|
||||||
<WebsiteTitleComponent>Harass Calculator</WebsiteTitleComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
Credit to Zard for deriving the formula.
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<LayoutRowComponent>
|
|
||||||
<LayoutColumnComponent>
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<FormDisplayComponent Label="Cost of worker">
|
|
||||||
<Display>@CostOfWorker</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
|
|
||||||
<FormDisplayComponent Label="Alloy mined per second by worker">
|
|
||||||
<Display>@AlloyMinedPerSecondByWorker</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
|
|
||||||
<FormDisplayComponent Label="Time to produce worker">
|
|
||||||
<Display>@TimeToProduceWorker</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
</LayoutColumnComponent>
|
|
||||||
|
|
||||||
<LayoutColumnComponent>
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<FormNumberComponent Min="1"
|
|
||||||
Id="numberOfWorkersLostToHarass"
|
|
||||||
Value="@((int)NumberOfWorkersLostToHarass)"
|
|
||||||
OnChange="@(e =>
|
|
||||||
{
|
|
||||||
NumberOfWorkersLostToHarass = int.Parse(e.Value!.ToString()!);
|
|
||||||
Calculate();
|
|
||||||
})">
|
|
||||||
<FormLabelComponent>Number of workers lost to harass</FormLabelComponent>
|
|
||||||
</FormNumberComponent>
|
|
||||||
|
|
||||||
<FormNumberComponent Min="1"
|
|
||||||
Id="numberOfTownHallsExisting"
|
|
||||||
Value="@((int)NumberOfTownHallsExisting)"
|
|
||||||
OnChange="OnTownHallsChanged">
|
|
||||||
<FormLabelComponent>Number of townhalls you have</FormLabelComponent>
|
|
||||||
</FormNumberComponent>
|
|
||||||
|
|
||||||
<div id="numberOfTownHallTravelTimes">
|
|
||||||
@{
|
|
||||||
var index = 0;
|
|
||||||
}
|
|
||||||
@foreach (var travelTime in TravelTimes)
|
|
||||||
{
|
|
||||||
index++;
|
|
||||||
if (index == 1)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var id = $"numberOfTownHallsExisting_{index}";
|
|
||||||
<FormNumberComponent Min="0"
|
|
||||||
Id="@id"
|
|
||||||
Value="@((int)travelTime.Value)"
|
|
||||||
OnChange="e => { OnTownHallTravelTimeChanged(e, travelTime); }">
|
|
||||||
<FormLabelComponent>Worker travel time from other
|
|
||||||
base @(travelTime.Index + 1)</FormLabelComponent>
|
|
||||||
</FormNumberComponent>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<FormDisplayComponent Label="Total alloy lost">
|
|
||||||
<Display>
|
|
||||||
<div style="font-size: 1.5rem; font-weight: 800;">
|
|
||||||
<span id="totalAlloyHarassment">
|
|
||||||
@TotalAlloyHarassment
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
|
|
||||||
|
|
||||||
</FormLayoutComponent>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
(<b>Worker replacement costs:</b> <span id="workerReplacementCost">@WorkerReplacementCost()</span>)
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
(<b>Delayed mining time:</b> <span id="delayedMiningCost">@DelayedMiningCost()</span>)
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
(<b>Average travel time:</b> <span id="getAverageTravelTime">@GetAverageTravelTime()</span>)
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</LayoutColumnComponent>
|
|
||||||
</LayoutRowComponent>
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
<ContentDividerComponent></ContentDividerComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
What is this tool?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
The Harass Calculator allows you to calculate damage done to an enemy alloy line. For example, if you
|
|
||||||
were to attack with Ichors, and kill 6 enemy workers, you can set the
|
|
||||||
<b>
|
|
||||||
Number of workers lost to
|
|
||||||
harass
|
|
||||||
</b> to 6. This would determine a loss of <span id="exampleTotalAlloyLoss">@ExampleTotalAlloyLoss</span>
|
|
||||||
alloy. Quite
|
|
||||||
the large number.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
What can I learn from this?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
Well, let's assume you lost a full alloy line of workers, and have to take that
|
|
||||||
@ExampleTotalAlloyLoss alloy cost (<span id="exampleWorkerCost">@ExampleWorkerCost</span>
|
|
||||||
to rebuy the workers, and <span id="exampleMiningTimeCost">@ExampleMiningTimeCost</span> in lost mining
|
|
||||||
time.)
|
|
||||||
<br/><br/>
|
|
||||||
If you were to set the <b>Number of townhalls you have</b> to 2, the calculator will consider worker
|
|
||||||
transfer micro. Allowing you to cut the total cost by roughly
|
|
||||||
<span id="exampleTotalAlloyLossDifference">@ExampleTotalAlloyLossDifference</span> alloy. However, that
|
|
||||||
number isn't
|
|
||||||
entirely accurate, you are also going to have to bump up the <b>Worker travel time to alloy</b> to
|
|
||||||
account for the time it takes the transferred workers to arrive at the decimated alloy line.
|
|
||||||
<br/><br/>
|
|
||||||
Let's say it takes 10 seconds for workers to transfer from your second base. Let's enter that for the
|
|
||||||
second base travel time for the more accurate loss of
|
|
||||||
<span
|
|
||||||
id="exampleTotalAlloyLossAccurate">
|
|
||||||
@ExampleTotalAlloyLossAccurate
|
|
||||||
</span> alloy
|
|
||||||
(saving you <span
|
|
||||||
id="exampleTotalAlloyLossAccurateDifference">@ExampleTotalAlloyLossAccurateDifference</span> alloy.)
|
|
||||||
<i>
|
|
||||||
Which is
|
|
||||||
much better than not transferring workers!
|
|
||||||
</i>
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
Can I see the formula for the calculation?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
The Harass Calculator is based on the following calculation.
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<div class="mathContainer">
|
|
||||||
<div> =c*m+r*g*(t+l) +</div>
|
|
||||||
|
|
||||||
<MathLoopSumComponent>
|
|
||||||
<LoopStart><i>x</i> =1</LoopStart>
|
|
||||||
<LoopEnd>
|
|
||||||
⌊
|
|
||||||
<MathDivisionComponent>
|
|
||||||
<Dividee>m</Dividee>
|
|
||||||
<Divider>a</Divider>
|
|
||||||
</MathDivisionComponent>
|
|
||||||
⌋
|
|
||||||
</LoopEnd>
|
|
||||||
<IndexSymbol>
|
|
||||||
<i>x</i>
|
|
||||||
</IndexSymbol>
|
|
||||||
</MathLoopSumComponent>
|
|
||||||
|
|
||||||
<div style="width: 132px">g*<i>x</i>*(t+l)</div>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div style="font-family:monospace;">
|
|
||||||
<div>c is CostOfWorker</div>
|
|
||||||
<div>m is NumberOfWorkersLostToHarass, <i>m for [M]otes</i></div>
|
|
||||||
<div>a is NumberOfTownHallsExisting, <i>a for [A]cropolis</i></div>
|
|
||||||
<div>r is m mod a is LeftOverWorkersToProduceCount()</div>
|
|
||||||
<div>g is AlloyMinedPerSecondByWorker</div>
|
|
||||||
<div>t is TimeToProduceWorker</div>
|
|
||||||
<div>l is TravelTime</div>
|
|
||||||
<div><i>x</i> is workerProductionIndex</div>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
This logic has since been changed slightly to allow client to enter different travel times per base.
|
|
||||||
<br/>
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
Can I see the code for the calculation?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
<br/>
|
|
||||||
<LinkButtonComponent
|
|
||||||
Href="https://git.jonathanmccaffrey.ca/JonathanMcCaffrey/IGP-Fan-Reference/src/branch/main/IGP/Pages/HarassCalculatorPage.razor#L226">
|
|
||||||
View Here
|
|
||||||
</LinkButtonComponent>
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
|
|
||||||
</LayoutMediumContentComponent>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.mathContainer {
|
|
||||||
font-family: monospace;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: flex-start;
|
|
||||||
border: 1px black solid;
|
|
||||||
padding: 32px;
|
|
||||||
background-color: #1A1B1E
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media only screen and (max-width: 1025px) {
|
|
||||||
.mathContainer {
|
|
||||||
padding-left: 2px;
|
|
||||||
padding-right: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
// Example calcs
|
|
||||||
float ExampleTotalAlloyLoss => Calculate(
|
|
||||||
WorkerReplacementCost(6),
|
|
||||||
SimultaneousProductionFloor(1, 6),
|
|
||||||
6,
|
|
||||||
new List<float> { 0 });
|
|
||||||
|
|
||||||
float ExampleWorkerCost => WorkerReplacementCost(6);
|
|
||||||
|
|
||||||
float ExampleMiningTimeCost => ExampleTotalAlloyLoss - ExampleWorkerCost;
|
|
||||||
|
|
||||||
float ExampleTotalAlloyLossDifference => ExampleTotalAlloyLoss - Calculate(
|
|
||||||
WorkerReplacementCost(6),
|
|
||||||
SimultaneousProductionFloor(2, 6),
|
|
||||||
6,
|
|
||||||
new List<float> { 0, 0 });
|
|
||||||
|
|
||||||
float ExampleTotalAlloyLossAccurate => Calculate(
|
|
||||||
WorkerReplacementCost(6),
|
|
||||||
SimultaneousProductionFloor(2, 6),
|
|
||||||
6,
|
|
||||||
new List<float> { 0, 10 });
|
|
||||||
|
|
||||||
float ExampleTotalAlloyLossAccurateDifference => ExampleTotalAlloyLoss - ExampleTotalAlloyLossAccurate;
|
|
||||||
|
|
||||||
float TotalAlloyHarassment;
|
|
||||||
|
|
||||||
readonly float CostOfWorker = 50;
|
|
||||||
readonly float AlloyMinedPerSecondByWorker = 1;
|
|
||||||
readonly float TimeToProduceWorker = 20;
|
|
||||||
float NumberOfWorkersLostToHarass = 1;
|
|
||||||
float NumberOfTownHallsExisting = 1;
|
|
||||||
|
|
||||||
float GetAverageTravelTime()
|
|
||||||
{
|
|
||||||
if (TravelTimes.Count == 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float sum = 0;
|
|
||||||
|
|
||||||
foreach (var travelTime in TravelTimes)
|
|
||||||
{
|
|
||||||
sum += travelTime.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sum / NumberOfTownHallsExisting;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
float SimultaneousProductionFloor()
|
|
||||||
{
|
|
||||||
if (NumberOfTownHallsExisting <= 0 || NumberOfWorkersLostToHarass <= 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NumberOfWorkersLostToHarass / Math.Min(NumberOfTownHallsExisting, NumberOfWorkersLostToHarass);
|
|
||||||
}
|
|
||||||
|
|
||||||
float SimultaneousProductionFloor(float existingTownHalls, float numberOfWorkersLost)
|
|
||||||
{
|
|
||||||
if (existingTownHalls <= 0 || numberOfWorkersLost <= 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return numberOfWorkersLost / Math.Min(existingTownHalls, numberOfWorkersLost);
|
|
||||||
}
|
|
||||||
|
|
||||||
float WorkerReplacementCost()
|
|
||||||
{
|
|
||||||
return CostOfWorker * NumberOfWorkersLostToHarass;
|
|
||||||
}
|
|
||||||
|
|
||||||
float WorkerReplacementCost(int numberOfWorkersLostToHarass)
|
|
||||||
{
|
|
||||||
return CostOfWorker * numberOfWorkersLostToHarass;
|
|
||||||
}
|
|
||||||
|
|
||||||
float DelayedMiningCost()
|
|
||||||
{
|
|
||||||
return TotalAlloyHarassment - WorkerReplacementCost();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Calculate()
|
|
||||||
{
|
|
||||||
TotalAlloyHarassment = Calculate(WorkerReplacementCost(),
|
|
||||||
SimultaneousProductionFloor(),
|
|
||||||
NumberOfWorkersLostToHarass,
|
|
||||||
TravelTimes.Select(x => x.Value).ToList(),
|
|
||||||
TimeToProduceWorker,
|
|
||||||
AlloyMinedPerSecondByWorker);
|
|
||||||
}
|
|
||||||
|
|
||||||
float Calculate(float workerReplacementCost,
|
|
||||||
float simultaneousProductionFloor,
|
|
||||||
float numberOfWorkersLostToHarass,
|
|
||||||
IList<float> travelTimes,
|
|
||||||
float timeToProduceWorker = 20,
|
|
||||||
float alloyMinedPerSecondByWorker = 1)
|
|
||||||
{
|
|
||||||
var totalAlloyHarassment = workerReplacementCost;
|
|
||||||
|
|
||||||
for (var workerProductionIndex = 0; workerProductionIndex < simultaneousProductionFloor; workerProductionIndex++)
|
|
||||||
{
|
|
||||||
totalAlloyHarassment += alloyMinedPerSecondByWorker * timeToProduceWorker * (workerProductionIndex + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
var remainder = (int)(numberOfWorkersLostToHarass % simultaneousProductionFloor);
|
|
||||||
for (var remainderIndex = 0; remainderIndex < remainder; remainderIndex++)
|
|
||||||
{
|
|
||||||
totalAlloyHarassment += alloyMinedPerSecondByWorker * timeToProduceWorker * (simultaneousProductionFloor + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var travelTimeIndex = 0; travelTimeIndex < numberOfWorkersLostToHarass; travelTimeIndex++)
|
|
||||||
{
|
|
||||||
var townHallIndex = travelTimeIndex % travelTimes.Count;
|
|
||||||
totalAlloyHarassment += alloyMinedPerSecondByWorker * travelTimes[townHallIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalAlloyHarassment;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
Calculate();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public List<TravelTime> TravelTimes { get; set; } = new() { new TravelTime(0, 0) };
|
|
||||||
|
|
||||||
private void OnTownHallsChanged(ChangeEventArgs obj)
|
|
||||||
{
|
|
||||||
NumberOfTownHallsExisting = int.Parse(obj.Value!.ToString()!);
|
|
||||||
|
|
||||||
while (TravelTimes.Count > NumberOfTownHallsExisting)
|
|
||||||
TravelTimes.Remove(TravelTimes.Last());
|
|
||||||
|
|
||||||
while (TravelTimes.Count < NumberOfTownHallsExisting)
|
|
||||||
TravelTimes.Add(new TravelTime(TravelTimes.Count, 10 * TravelTimes.Count));
|
|
||||||
Calculate();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTownHallTravelTimeChanged(ChangeEventArgs obj, TravelTime travelTime)
|
|
||||||
{
|
|
||||||
travelTime.Value = (int)obj.Value!;
|
|
||||||
|
|
||||||
Calculate();
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
@layout PageLayout;
|
|
||||||
|
|
||||||
@inherits BasePage
|
|
||||||
|
|
||||||
@page "/immortal-home"
|
|
||||||
|
|
||||||
<LayoutMediumContentComponent>
|
|
||||||
<PaperComponent>
|
|
||||||
<div class="mainContainer">
|
|
||||||
<div class="mainTitle">
|
|
||||||
Fan Reference
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
Refer to various aspects of "IMMORTAL: Gates of Pyre" from this external reference!
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
<ContentDividerComponent></ContentDividerComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<div class="heroesContainer">
|
|
||||||
|
|
||||||
<ContentHighlightComponent Title="Build Calculator"
|
|
||||||
Description="Make a build!"
|
|
||||||
Href="/build-calculator"
|
|
||||||
ImageHref="image/hero/Build.png"/>
|
|
||||||
|
|
||||||
<ContentHighlightComponent Title="Database"
|
|
||||||
Description="Review the units!"
|
|
||||||
Href="/database"
|
|
||||||
ImageHref="image/hero/Database.png"/>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
</LayoutMediumContentComponent>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.mainContainer {
|
|
||||||
padding-bottom: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mainTitle {
|
|
||||||
font-size: 2.2rem;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.heroesContainer {
|
|
||||||
display: grid;
|
|
||||||
gap: 64px;
|
|
||||||
justify-content: center;
|
|
||||||
margin: auto;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@media only screen and (max-width: 1025px) {
|
|
||||||
.heroesContainer {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
<NavLink Href="@Href" class="contentHighlight">
|
|
||||||
<div class="contentHighlightTitle">
|
|
||||||
@Title
|
|
||||||
</div>
|
|
||||||
<img width="268px" height="161px" src="@ImageHref" class="contentHighlightImage" alt="@Title"/>
|
|
||||||
<div class="contentHighlightCallToAction">
|
|
||||||
@Description
|
|
||||||
</div>
|
|
||||||
</NavLink>
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.contentHighlight {
|
|
||||||
background-color: var(--paper);
|
|
||||||
border: 1px solid var(--paper-border);
|
|
||||||
border-radius: 2px;
|
|
||||||
padding-left: 12px;
|
|
||||||
padding-right: 12px;
|
|
||||||
padding-top: 24px;
|
|
||||||
padding-bottom: 24px;
|
|
||||||
color: white;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 12px;
|
|
||||||
text-align: center;
|
|
||||||
margin-left: 12px;
|
|
||||||
margin-right: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contentHighlight:hover {
|
|
||||||
background-color: var(--paper-hover);
|
|
||||||
border-color: var(--paper-border-hover);
|
|
||||||
text-decoration: none;
|
|
||||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.6);
|
|
||||||
transform: translateY(-2px) scale(1.01);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.contentHighlightTitle {
|
|
||||||
font-weight: 800;
|
|
||||||
font-size: 1.3rem;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contentHighlightImage {
|
|
||||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
|
||||||
box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.5);
|
|
||||||
width: calc(100% - 32px);
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
margin-top: 12px;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contentHighlightCallToAction {
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
margin: auto;
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Parameter] public string Href { get; set; } = default!;
|
|
||||||
|
|
||||||
[Parameter] public string Title { get; set; } = default!;
|
|
||||||
|
|
||||||
[Parameter] public string Description { get; set; } = default!;
|
|
||||||
|
|
||||||
[Parameter] public string ImageHref { get; set; } = default!;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
@layout PageLayout
|
|
||||||
|
|
||||||
@inherits BasePage
|
|
||||||
|
|
||||||
@page "/memory-tester"
|
|
||||||
|
|
||||||
<LayoutMediumContentComponent>
|
|
||||||
<WebsiteTitleComponent>Memory Tester</WebsiteTitleComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<UnitMemoryManager></UnitMemoryManager>
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
<ContentDividerComponent></ContentDividerComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
What is this tool?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
A tool to test your memory of unit stats. Look at the first unit given, and fill in the remaining stats
|
|
||||||
based on how they should compare.
|
|
||||||
|
|
||||||
<br/><br/>
|
|
||||||
For example, if the first unit you see is the Masked Hunter of range 400, do you remember the range of
|
|
||||||
the Scepter? Are they the same? Does the Scepter have double the range of the Masked Hunter? Less range
|
|
||||||
than it? Well, enter your guess and submit!
|
|
||||||
<SpoilerTextComponent>The range is 200 longer, so if you remember that, you know you are going to need
|
|
||||||
more than Masked Hunters to deal with hard to reach enemy Scepters.
|
|
||||||
</SpoilerTextComponent>
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>
|
|
||||||
Why is this tool here?
|
|
||||||
</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
It was just a tool to quickly develop for fun when I didn't want to cover something larger on the
|
|
||||||
02/27/2022 live coding stream.
|
|
||||||
<br/><br/>
|
|
||||||
It may get expanded upon later.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
</LayoutMediumContentComponent>
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
@implements IDisposable;
|
|
||||||
@inject IMemoryTesterService MemoryTesterService;
|
|
||||||
|
|
||||||
<div class="unitMemoryContainer@(isCorrect ? " correct" : isWrong ? "wrong" : "")">
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<FormDisplayComponent Label="Name">
|
|
||||||
<Display>@EntityMemory.Name</Display>
|
|
||||||
</FormDisplayComponent>
|
|
||||||
|
|
||||||
@foreach (var question in questions)
|
|
||||||
{
|
|
||||||
var questionWrong = hasBeenSubmitted && !question.IsRevealed && question.Guess != question.Answer;
|
|
||||||
|
|
||||||
<FormGuessComponent IsSubmitted="hasBeenSubmitted"
|
|
||||||
OnChange="answerEventArgs => OnAnswerEntered(answerEventArgs, question)"
|
|
||||||
MemoryQuestion="question"/>
|
|
||||||
|
|
||||||
@if (questionWrong)
|
|
||||||
{
|
|
||||||
<div class="wrongAnswer">The correct answer was @question.Answer</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</FormLayoutComponent>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.unitMemoryContainer {
|
|
||||||
}
|
|
||||||
|
|
||||||
.unitMemoryContainer.correct {
|
|
||||||
border-color: green;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.unitMemoryContainer.wrong {
|
|
||||||
border-color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wrongAnswer {
|
|
||||||
padding: 12px;
|
|
||||||
color: #ff2525;
|
|
||||||
font-weight: 700;
|
|
||||||
background-color: rgba(0, 0, 0, 0.4);
|
|
||||||
padding: 8px;
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Parameter] public MemoryEntityModel EntityMemory { get; set; } = default!;
|
|
||||||
|
|
||||||
private List<MemoryQuestionModel> questions { get; set; } = default!;
|
|
||||||
|
|
||||||
private bool hasBeenSubmitted;
|
|
||||||
private bool isCorrect;
|
|
||||||
private bool isWrong;
|
|
||||||
|
|
||||||
public int Guess { get; set; }
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
MemoryTesterService.Subscribe(OnMemoryEvent);
|
|
||||||
|
|
||||||
OnRefresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
MemoryTesterService.Unsubscribe(OnMemoryEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnMemoryEvent(MemoryTesterEvent memoryTesterEvent)
|
|
||||||
{
|
|
||||||
if (memoryTesterEvent == MemoryTesterEvent.OnVerify)
|
|
||||||
{
|
|
||||||
OnVerify();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memoryTesterEvent == MemoryTesterEvent.OnRefresh)
|
|
||||||
{
|
|
||||||
OnRefresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void OnAnswerEntered(AnswerEventArgs answerEventArgs, MemoryQuestionModel question)
|
|
||||||
{
|
|
||||||
question.Guess = answerEventArgs.Guess;
|
|
||||||
|
|
||||||
MemoryTesterService.Update(question);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnVerify()
|
|
||||||
{
|
|
||||||
hasBeenSubmitted = true;
|
|
||||||
|
|
||||||
isCorrect = true;
|
|
||||||
|
|
||||||
foreach (var question in questions)
|
|
||||||
{
|
|
||||||
if (question.Answer != question.Guess)
|
|
||||||
{
|
|
||||||
isCorrect = false;
|
|
||||||
isWrong = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnRefresh()
|
|
||||||
{
|
|
||||||
hasBeenSubmitted = false;
|
|
||||||
isCorrect = false;
|
|
||||||
isWrong = false;
|
|
||||||
|
|
||||||
questions = (from question in MemoryTesterService.GetQuestions()
|
|
||||||
where question.MemoryEntityModelId == EntityMemory.Id
|
|
||||||
select question).ToList();
|
|
||||||
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
@implements IDisposable;
|
|
||||||
|
|
||||||
@inject IMemoryTesterService MemoryTesterService;
|
|
||||||
|
|
||||||
<div class="quizContainer">
|
|
||||||
<div class="quizListContainer">
|
|
||||||
@if (entities != null && questions != null)
|
|
||||||
{
|
|
||||||
@foreach (var entityMemory in entities)
|
|
||||||
{
|
|
||||||
<UnitMemory EntityMemory="entityMemory"></UnitMemory>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="quizButtons">
|
|
||||||
<ButtonComponent MyButtonType="MyButtonType.Secondary" OnClick="OnRefreshQuiz">Refresh</ButtonComponent>
|
|
||||||
<ButtonComponent MyButtonType="MyButtonType.Primary" OnClick="OnSubmitQuiz">Submit</ButtonComponent>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.quizContainer {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 16px;
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quizListContainer {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media (min-width: @SupportedWebSizes.Tablet) {
|
|
||||||
.quizContainer {
|
|
||||||
}
|
|
||||||
|
|
||||||
.quizButtons {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 16px;
|
|
||||||
justify-content: flex-end;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quizListContainer {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media (min-width: @SupportedWebSizes.Desktop) {
|
|
||||||
.quizListContainer {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private List<MemoryEntityModel> entities = null!;
|
|
||||||
private List<MemoryQuestionModel> questions = null!;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
MemoryTesterService.Subscribe(OnMemoryEvent);
|
|
||||||
|
|
||||||
MemoryTesterService.GenerateQuiz();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
MemoryTesterService.Unsubscribe(OnMemoryEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnMemoryEvent(MemoryTesterEvent memoryTesterEvent)
|
|
||||||
{
|
|
||||||
if (memoryTesterEvent == MemoryTesterEvent.OnVerify)
|
|
||||||
{
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memoryTesterEvent == MemoryTesterEvent.OnRefresh)
|
|
||||||
{
|
|
||||||
entities = MemoryTesterService.GetEntities();
|
|
||||||
questions = MemoryTesterService.GetQuestions();
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnSubmitQuiz(EventArgs eventArgs)
|
|
||||||
{
|
|
||||||
MemoryTesterService.Verify();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnRefreshQuiz(EventArgs eventArgs)
|
|
||||||
{
|
|
||||||
MemoryTesterService.GenerateQuiz();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
@layout PageLayout
|
|
||||||
|
|
||||||
@inherits BasePage
|
|
||||||
|
|
||||||
@inject INoteService NoteService
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
@inject IDataCollectionService DataCollectionService
|
|
||||||
|
|
||||||
@page "/notes"
|
|
||||||
|
|
||||||
|
|
||||||
@if (!NoteService.IsLoaded())
|
|
||||||
{
|
|
||||||
<LoadingComponent/>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<LayoutMediumContentComponent>
|
|
||||||
|
|
||||||
<WebsiteTitleComponent>Notes</WebsiteTitleComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
@foreach (var noteSection in NoteService.NoteSectionModels)
|
|
||||||
{
|
|
||||||
<div class="noteSectionContainer">
|
|
||||||
<div class="noteSectionTitle">@noteSection.Name</div>
|
|
||||||
<div class="noteContentContainer">
|
|
||||||
@foreach (var noteContent in noteSection.NoteContentModels)
|
|
||||||
{
|
|
||||||
<NavLink class="noteContentLink" href="@noteContent.GetNoteLink()">
|
|
||||||
<div class="noteContentName">@noteContent.Name</div>
|
|
||||||
<div class="noteContentDescription">@noteContent.Description</div>
|
|
||||||
</NavLink>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</PaperComponent>
|
|
||||||
</LayoutMediumContentComponent>
|
|
||||||
}
|
|
||||||
<style>
|
|
||||||
.noteSectionContainer {
|
|
||||||
width: 100%;
|
|
||||||
padding-left: 8px;
|
|
||||||
padding-right: 8px;
|
|
||||||
padding-top: 8px;
|
|
||||||
padding-bottom: 64px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noteSectionTitle {
|
|
||||||
font-size: 3rem;
|
|
||||||
font-weight: bold;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noteContentContainer {
|
|
||||||
display: grid;
|
|
||||||
gap: 12px;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@media only screen and (max-width: 1025px) {
|
|
||||||
.noteContentContainer {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.noteContentName {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1.6rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noteContentDescription {
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.noteContentLink {
|
|
||||||
background-color: var(--paper);
|
|
||||||
border: 1px solid var(--paper-border);
|
|
||||||
border-radius: 2px;
|
|
||||||
padding-left: 12px;
|
|
||||||
padding-right: 12px;
|
|
||||||
padding-top: 24px;
|
|
||||||
padding-bottom: 24px;
|
|
||||||
color: white;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 12px;
|
|
||||||
text-align: center;
|
|
||||||
margin-left: 12px;
|
|
||||||
margin-right: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.noteContentLink:hover {
|
|
||||||
background-color: var(--paper-hover);
|
|
||||||
border-color: var(--paper-border-hover);
|
|
||||||
text-decoration: none;
|
|
||||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.6);
|
|
||||||
transform: translateY(-2px) scale(1.01);
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Parameter] public string? Href1 { get; set; }
|
|
||||||
|
|
||||||
[Parameter] public string? Href2 { get; set; }
|
|
||||||
|
|
||||||
[Parameter] public string? Href3 { get; set; }
|
|
||||||
|
|
||||||
[Parameter] public string? Href4 { get; set; }
|
|
||||||
|
|
||||||
[Parameter] public string? Href5 { get; set; }
|
|
||||||
|
|
||||||
private string Href => Href5 ?? Href4 ?? Href3 ?? Href2 ?? Href1 ?? "";
|
|
||||||
|
|
||||||
string selectedSection = "All";
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
NoteService.Subscribe(StateHasChanged);
|
|
||||||
|
|
||||||
NoteService.Load();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
NoteService.Unsubscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OnSectionChanged(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
selectedSection = e.Value!.ToString()!;
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
@layout PageLayout
|
|
||||||
|
|
||||||
@inherits BasePage
|
|
||||||
|
|
||||||
@inject INoteService NoteService
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
@inject IDataCollectionService DataCollectionService
|
|
||||||
|
|
||||||
@page "/notes/{href1}/{href2?}/{href3?}/{href4?}/{href5?}"
|
|
||||||
|
|
||||||
|
|
||||||
@if (!NoteService.IsLoaded())
|
|
||||||
{
|
|
||||||
<LoadingComponent/>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<LayoutWithSidebarComponent>
|
|
||||||
<Sidebar>
|
|
||||||
<NoteNavComponent
|
|
||||||
Connections="NoteService.NoteConnectionModels"
|
|
||||||
Notes="NoteService.NoteContentModels"/>
|
|
||||||
</Sidebar>
|
|
||||||
<Content>
|
|
||||||
<PaperComponent>
|
|
||||||
@foreach (var note in NoteService.NoteContentModels)
|
|
||||||
{
|
|
||||||
if (!note.Href.Equals(Href))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
<NoteComponent NoteContentModel="note"/>
|
|
||||||
}
|
|
||||||
</PaperComponent>
|
|
||||||
</Content>
|
|
||||||
</LayoutWithSidebarComponent>
|
|
||||||
}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
pre code {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
display: block;
|
|
||||||
font-size: 2em;
|
|
||||||
margin-top: 0.67em;
|
|
||||||
margin-bottom: 0.67em;
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 0;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
display: block;
|
|
||||||
font-size: 1.5em;
|
|
||||||
margin-top: 0.83em;
|
|
||||||
margin-bottom: 0.83em;
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 0;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
display: list-item;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
display: block;
|
|
||||||
margin-top: 1em;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
display: block;
|
|
||||||
list-style-type: disc;
|
|
||||||
margin-top: 1em;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 0;
|
|
||||||
padding-left: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
background: black;
|
|
||||||
padding: 2px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Parameter] public string? Href1 { get; set; }
|
|
||||||
|
|
||||||
[Parameter] public string? Href2 { get; set; }
|
|
||||||
|
|
||||||
[Parameter] public string? Href3 { get; set; }
|
|
||||||
|
|
||||||
[Parameter] public string? Href4 { get; set; }
|
|
||||||
|
|
||||||
[Parameter] public string? Href5 { get; set; }
|
|
||||||
|
|
||||||
private string Href => Href5 ?? Href4 ?? Href3 ?? Href2 ?? Href1 ?? "";
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
NoteService.Subscribe(StateHasChanged);
|
|
||||||
|
|
||||||
NoteService.Load();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
NoteService.Unsubscribe(StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
@inject HttpClient httpClient
|
|
||||||
|
|
||||||
@if (content == null)
|
|
||||||
{
|
|
||||||
<LoadingComponent/>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<div class="note">
|
|
||||||
<div class="noteHeader">
|
|
||||||
<h1 class="noteTitle">@noteFrontMatter.Title</h1>
|
|
||||||
<div class="noteDates">
|
|
||||||
<div class="noteDateUpdated"><b>Updated</b>: @noteFrontMatter.UpdatedDate.ToString("MM/dd/yyyy")</div>
|
|
||||||
<div class="noteDateCreated"><b>Created</b>: @noteFrontMatter.CreatedDate.ToString("MM/dd/yyyy")</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="noteContent">@((MarkupString)Markdown.ToHtml(content, Pipeline))</div>
|
|
||||||
<div class="noteFooter">
|
|
||||||
<LinkButtonComponent Href="@GitUrl">
|
|
||||||
Edit on GitHub <i class="fa-brands fa-github" style="font-size: 24px; margin-left: 5px;"></i>
|
|
||||||
</LinkButtonComponent>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.noteTitle {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noteHeader {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noteDates {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.noteFooter {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Parameter] public NoteContentModel NoteContentModel { get; set; } = default!;
|
|
||||||
|
|
||||||
NoteFrontMatterModel noteFrontMatter = null!;
|
|
||||||
private string? content;
|
|
||||||
|
|
||||||
private string Filepath => $"content/notes/{NoteContentModel.Content}.md";
|
|
||||||
private string GitUrl => $"{Project.GitResourcesUrl}/{Filepath}";
|
|
||||||
private MarkdownPipeline Pipeline => MarkdownFiles.Pipeline;
|
|
||||||
|
|
||||||
private async Task<NoteFrontMatterModel> LoadContent()
|
|
||||||
{
|
|
||||||
content = await MarkdownFiles.LoadMarkdown(httpClient, Filepath);
|
|
||||||
|
|
||||||
return noteFrontMatter =
|
|
||||||
await MarkdownFiles.LoadFrontMatter<NoteFrontMatterModel>(httpClient, Filepath);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
|
||||||
{
|
|
||||||
await LoadContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
await LoadContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
@if (Note!.NoteContentModels.Count > 0)
|
|
||||||
{
|
|
||||||
<div class="noteInnerNavContainer">
|
|
||||||
@foreach (var innerNote in Note.NoteContentModels)
|
|
||||||
{
|
|
||||||
var linkStyle = $"noteInnerNavButton inner_{Layers}";
|
|
||||||
<NavLink class="@linkStyle" href="@innerNote.GetNoteLink()">@innerNote.Name</NavLink>
|
|
||||||
<NoteInnerNavComponent Note="@innerNote" Layers="@IncrementLayers()"/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
.noteInnerNavContainer {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noteInnerNavButton a {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noteInnerNavButton a:hover {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noteInnerNavButton {
|
|
||||||
padding: 8px;
|
|
||||||
margin-left: 8px;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noteInnerNavButton:hover {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.inner_1 {
|
|
||||||
margin-left: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inner_2 {
|
|
||||||
margin-left: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inner_3 {
|
|
||||||
margin-left: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Parameter] public NoteContentModel? Note { get; set; }
|
|
||||||
|
|
||||||
[Parameter] public int Layers { get; set; } = 1;
|
|
||||||
|
|
||||||
public int IncrementLayers()
|
|
||||||
{
|
|
||||||
return Layers + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private string GetLink(NoteContentModel note)
|
|
||||||
{
|
|
||||||
return $"notes/{note.Href}";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
<div class="noteNavContainer">
|
|
||||||
@foreach (var note in Notes)
|
|
||||||
{
|
|
||||||
if (note.Parent == null)
|
|
||||||
{
|
|
||||||
<NavLink class="noteNavButton" href="@note.GetNoteLink()">@note.Name</NavLink>
|
|
||||||
<NoteInnerNavComponent Note="@note"/>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.noteNavContainer {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noteNavButton a {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noteNavButton a:hover {
|
|
||||||
color: white;
|
|
||||||
background-color: var(--primary-hover);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.noteNavButton {
|
|
||||||
padding: 8px;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Parameter] public List<NoteContentModel> Notes { get; set; } = default!;
|
|
||||||
|
|
||||||
[Parameter] public List<NoteConnectionModel> Connections { get; set; } = default!;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
@page "/permissions"
|
|
||||||
|
|
||||||
@inject IPermissionService PermissionService
|
|
||||||
@layout PageLayout
|
|
||||||
|
|
||||||
@inject IMyDialogService MyDialogService
|
|
||||||
|
|
||||||
@inherits BasePage
|
|
||||||
@using Services.Website
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
|
|
||||||
<LayoutMediumContentComponent>
|
|
||||||
<PaperComponent>
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<FormToggleComponent
|
|
||||||
Label="Storage Enabled"
|
|
||||||
Info="Is storage enabled?"
|
|
||||||
Value="_storageEnabled"
|
|
||||||
OnChange="StoragePermissionChanged"/>
|
|
||||||
|
|
||||||
<FormToggleComponent
|
|
||||||
Label="Data Collection Enabled"
|
|
||||||
Info="Is data collection enabled?"
|
|
||||||
Value="_dataCollectionEnabled"
|
|
||||||
OnChange="DataCollectionPermissionChanged"/>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
<ContentDividerComponent/>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>What's this page?</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>This page has options to enable and disable certain permissions settings. Such as
|
|
||||||
Storage and Data Collection.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>What does this website store?</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>This website usages storage to track user defined default on the Storage page.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>Why would I enable storage?</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>Enable storage if you want to website to remeber past settings whenever you visit the
|
|
||||||
website on the same web browser.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>What data does this website collect?</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
This website usages Google Analytics to collect data on usage of this website.
|
|
||||||
<br/><br/>
|
|
||||||
Items include: if people use keyboard or mouse in build calculator, what pages people visit, and other
|
|
||||||
usages.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>Why would I enable data collection?</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>Enable data tracking if you want the website maintainer to know how your using the
|
|
||||||
website.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
</PaperComponent>
|
|
||||||
</LayoutMediumContentComponent>
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private bool _storageEnabled;
|
|
||||||
private bool _dataCollectionEnabled;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
PermissionService.Subscribe(Update);
|
|
||||||
|
|
||||||
Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Update()
|
|
||||||
{
|
|
||||||
_storageEnabled = PermissionService.GetIsStorageEnabled();
|
|
||||||
_dataCollectionEnabled = PermissionService.GetIsDataCollectionEnabled();
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
PermissionService.Unsubscribe(Update);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StoragePermissionChanged(ChangeEventArgs obj)
|
|
||||||
{
|
|
||||||
PermissionService.SetIsStorageEnabled(!PermissionService.GetIsStorageEnabled());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void DataCollectionPermissionChanged(ChangeEventArgs obj)
|
|
||||||
{
|
|
||||||
void OnDataCollectionConfirmClicked(MouseEventArgs mouseEventArgs)
|
|
||||||
{
|
|
||||||
PermissionService.SetIsDataCollectionEnabled(!PermissionService.GetIsDataCollectionEnabled());
|
|
||||||
MyDialogService.Hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnDataCollectionCancelClicked(MouseEventArgs mouseEventArgs)
|
|
||||||
{
|
|
||||||
MyDialogService.Hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_storageEnabled && !PermissionService.GetIsDataCollectionEnabled())
|
|
||||||
{
|
|
||||||
MyDialogService.Show(new DialogContents
|
|
||||||
{
|
|
||||||
Title = "Permission Request",
|
|
||||||
Message = "Are you sure you want to enable data collection? This feature is implemented with Google Analytics, and your data will be used to gauge interests, find bugs, and optimize updates in IGP Fan Reference.",
|
|
||||||
OnConfirm = new EventCallback<EventArgs>(this, OnDataCollectionConfirmClicked),
|
|
||||||
OnCancel = new EventCallback<EventArgs>(this, OnDataCollectionCancelClicked),
|
|
||||||
ConfirmButtonLabel = "Enable Data Collection"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PermissionService.SetIsDataCollectionEnabled(!PermissionService.GetIsDataCollectionEnabled());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
@inherits BasePage
|
|
||||||
|
|
||||||
@page "/raw-database"
|
|
||||||
|
|
||||||
<div class="page">
|
|
||||||
<AlertComponent>
|
|
||||||
<Title>Placeholders and Speculative</Title>
|
|
||||||
<Message>The data I am using contains placeholders and speculation on future mechanics. Ignore said data when
|
|
||||||
using this JSON.
|
|
||||||
</Message>
|
|
||||||
</AlertComponent>
|
|
||||||
<CodeComponent>
|
|
||||||
@EntityData.AsJson()
|
|
||||||
</CodeComponent>
|
|
||||||
</div>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
.page {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 16px;
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 1025px) {
|
|
||||||
.page {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 2px;
|
|
||||||
gap: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,248 +0,0 @@
|
|||||||
@page "/storage"
|
|
||||||
|
|
||||||
|
|
||||||
@inherits BasePage
|
|
||||||
@inject IStorageService StorageService
|
|
||||||
@using Services.Website
|
|
||||||
@implements IDisposable
|
|
||||||
@layout PageLayout
|
|
||||||
|
|
||||||
<LayoutMediumContentComponent>
|
|
||||||
@if (!_enabledPermissions)
|
|
||||||
{
|
|
||||||
<AlertComponent Type="@SeverityType.Error">
|
|
||||||
<Title>Storage Disabled</Title>
|
|
||||||
<Message>Enable Storage on the Permissions Page.</Message>
|
|
||||||
</AlertComponent>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<PaperComponent>
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<FormToggleComponent
|
|
||||||
Label="Is Plain View"
|
|
||||||
Info="Should Entity view be in plain text?"
|
|
||||||
Value="@_isEntityPlainView"
|
|
||||||
OnChange="EntityViewChanged"/>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
|
|
||||||
<DevOnlyComponent>
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<FormToggleComponent
|
|
||||||
Label="Is Dynamic Formatting"
|
|
||||||
Info="Should [Attacks Per Second/Seconds Between Attack] match in-game values?"
|
|
||||||
Value="@_isDynamicFormatting"
|
|
||||||
OnChange="DynamicFormattingChanged"/>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
</DevOnlyComponent>
|
|
||||||
|
|
||||||
</PaperComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<FormNumberComponent Max="2048"
|
|
||||||
Min="0"
|
|
||||||
Value="@(_attackTime == null ? 0 : (int)_attackTime)"
|
|
||||||
OnChange="AttackTimeChanged">
|
|
||||||
<FormLabelComponent>Attack Time</FormLabelComponent>
|
|
||||||
<FormInfoComponent>
|
|
||||||
@if (_attackTime != null)
|
|
||||||
{
|
|
||||||
<i>  T @Interval.ToTime((int)_attackTime)</i>
|
|
||||||
}
|
|
||||||
</FormInfoComponent>
|
|
||||||
</FormNumberComponent>
|
|
||||||
|
|
||||||
<FormNumberComponent Max="2048"
|
|
||||||
Min="0"
|
|
||||||
Value="@(_travelTime == null ? 0 : (int)_travelTime)"
|
|
||||||
OnChange="TravelTimeChanged">
|
|
||||||
<FormLabelComponent>Travel Time</FormLabelComponent>
|
|
||||||
<FormInfoComponent>
|
|
||||||
@if (_travelTime != null)
|
|
||||||
{
|
|
||||||
<i>  T @Interval.ToTime((int)_travelTime)</i>
|
|
||||||
}
|
|
||||||
</FormInfoComponent>
|
|
||||||
</FormNumberComponent>
|
|
||||||
|
|
||||||
<FormSelectComponent OnChange="@OnFactionChanged">
|
|
||||||
<FormLabelComponent>Faction</FormLabelComponent>
|
|
||||||
<ChildContent>
|
|
||||||
<option value="@DataType.FACTION_Aru"
|
|
||||||
selected="@(Faction.Equals(DataType.FACTION_Aru))">
|
|
||||||
Aru
|
|
||||||
</option>
|
|
||||||
<option value="@DataType.FACTION_QRath"
|
|
||||||
selected="@(Faction.Equals(DataType.FACTION_QRath))">
|
|
||||||
Q'Rath
|
|
||||||
</option>
|
|
||||||
</ChildContent>
|
|
||||||
</FormSelectComponent>
|
|
||||||
|
|
||||||
<FormSelectComponent OnChange="@OnImmortalChanged">
|
|
||||||
<FormLabelComponent>Immortal</FormLabelComponent>
|
|
||||||
<ChildContent>
|
|
||||||
@if (Faction == DataType.FACTION_QRath)
|
|
||||||
{
|
|
||||||
<option value="@DataType.IMMORTAL_Orzum"
|
|
||||||
selected="@(Immortal.Equals(DataType.IMMORTAL_Orzum))">
|
|
||||||
Orzum
|
|
||||||
</option>
|
|
||||||
<option value="@DataType.IMMORTAL_Ajari"
|
|
||||||
selected="@(Immortal.Equals(DataType.IMMORTAL_Ajari))">
|
|
||||||
Ajari
|
|
||||||
</option>
|
|
||||||
}
|
|
||||||
@if (Faction == DataType.FACTION_Aru)
|
|
||||||
{
|
|
||||||
<option value="@DataType.IMMORTAL_Mala"
|
|
||||||
selected="@(Immortal.Equals(DataType.IMMORTAL_Mala))">
|
|
||||||
Mala
|
|
||||||
</option>
|
|
||||||
<option value="@DataType.IMMORTAL_Xol"
|
|
||||||
selected="@(Immortal.Equals(DataType.IMMORTAL_Xol))">
|
|
||||||
Xol
|
|
||||||
</option>
|
|
||||||
}
|
|
||||||
</ChildContent>
|
|
||||||
</FormSelectComponent>
|
|
||||||
|
|
||||||
|
|
||||||
<FormNumberComponent Max="600"
|
|
||||||
Min="0"
|
|
||||||
Value="@(_buildingInputDelay == null ? 0 : (int)_buildingInputDelay)"
|
|
||||||
OnChange="OnBuildingInputDelayChanged">
|
|
||||||
<FormLabelComponent>Building Input Delay</FormLabelComponent>
|
|
||||||
<FormInfoComponent>Add a input delay to constructing buildings for simulating worker movement and
|
|
||||||
player micro.
|
|
||||||
</FormInfoComponent>
|
|
||||||
</FormNumberComponent>
|
|
||||||
<FormNumberComponent Max="600"
|
|
||||||
Min="1"
|
|
||||||
Value="@(_waitTime == null ? 0 : (int)_waitTime)"
|
|
||||||
OnChange="@OnWaitTimeChanged">
|
|
||||||
<FormLabelComponent>Wait Time</FormLabelComponent>
|
|
||||||
</FormNumberComponent>
|
|
||||||
</FormLayoutComponent>
|
|
||||||
<FormLayoutComponent>
|
|
||||||
<FormNumberComponent Max="2048"
|
|
||||||
Min="1"
|
|
||||||
Value="@(_waitTo == null ? 0 : (int)_waitTo)"
|
|
||||||
OnChange="@OnWaitToChanged">
|
|
||||||
<FormLabelComponent>Wait To</FormLabelComponent>
|
|
||||||
</FormNumberComponent>
|
|
||||||
|
|
||||||
</FormLayoutComponent>
|
|
||||||
</PaperComponent>
|
|
||||||
}
|
|
||||||
|
|
||||||
<ContentDividerComponent/>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
|
|
||||||
</PaperComponent>
|
|
||||||
</LayoutMediumContentComponent>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
bool _enabledPermissions;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
|
|
||||||
_enabledPermissions = StorageService.GetValue<bool>(StorageKeys.EnabledStorage);
|
|
||||||
|
|
||||||
RefreshDefaults();
|
|
||||||
|
|
||||||
StorageService.Subscribe(RefreshDefaults);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
StorageService.Unsubscribe(RefreshDefaults);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int? _attackTime;
|
|
||||||
private int? _travelTime;
|
|
||||||
|
|
||||||
private string? _faction;
|
|
||||||
private string? _immortal;
|
|
||||||
|
|
||||||
private string? Faction => _faction == null ? DataType.FACTION_QRath : _faction;
|
|
||||||
private string? Immortal => _immortal == null ? DataType.IMMORTAL_Orzum : _immortal;
|
|
||||||
|
|
||||||
|
|
||||||
private int? _buildingInputDelay;
|
|
||||||
private int? _waitTime;
|
|
||||||
private int? _waitTo;
|
|
||||||
|
|
||||||
|
|
||||||
void RefreshDefaults()
|
|
||||||
{
|
|
||||||
_isEntityPlainView = StorageService.GetValue<bool>(StorageKeys.IsPlainView);
|
|
||||||
_isDynamicFormatting = StorageService.GetValue<bool>(StorageKeys.IsDynamicFormatting);
|
|
||||||
|
|
||||||
_attackTime = StorageService.GetValue<int?>(StorageKeys.AttackTime);
|
|
||||||
_travelTime = StorageService.GetValue<int?>(StorageKeys.TravelTime);
|
|
||||||
|
|
||||||
|
|
||||||
_faction = StorageService.GetValue<string?>(StorageKeys.SelectedFaction);
|
|
||||||
_immortal = StorageService.GetValue<string?>(StorageKeys.SelectedImmortal);
|
|
||||||
|
|
||||||
_buildingInputDelay = StorageService.GetValue<int?>(StorageKeys.BuildInputDelay);
|
|
||||||
_waitTime = StorageService.GetValue<int?>(StorageKeys.WaitTime);
|
|
||||||
_waitTo = StorageService.GetValue<int?>(StorageKeys.WaitTo);
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _isEntityPlainView;
|
|
||||||
private bool _isDynamicFormatting;
|
|
||||||
|
|
||||||
private void EntityViewChanged(ChangeEventArgs obj)
|
|
||||||
{
|
|
||||||
StorageService.SetValue(StorageKeys.IsPlainView, obj.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DynamicFormattingChanged(ChangeEventArgs obj)
|
|
||||||
{
|
|
||||||
StorageService.SetValue(StorageKeys.IsDynamicFormatting, obj.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AttackTimeChanged(ChangeEventArgs obj)
|
|
||||||
{
|
|
||||||
StorageService.SetValue(StorageKeys.AttackTime, obj.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TravelTimeChanged(ChangeEventArgs obj)
|
|
||||||
{
|
|
||||||
StorageService.SetValue(StorageKeys.TravelTime, obj.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFactionChanged(ChangeEventArgs obj)
|
|
||||||
{
|
|
||||||
StorageService.SetValue(StorageKeys.SelectedFaction, obj.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnImmortalChanged(ChangeEventArgs obj)
|
|
||||||
{
|
|
||||||
StorageService.SetValue(StorageKeys.SelectedImmortal, obj.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnBuildingInputDelayChanged(ChangeEventArgs obj)
|
|
||||||
{
|
|
||||||
StorageService.SetValue(StorageKeys.BuildInputDelay, obj.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnWaitTimeChanged(ChangeEventArgs obj)
|
|
||||||
{
|
|
||||||
StorageService.SetValue(StorageKeys.WaitTime, obj.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnWaitToChanged(ChangeEventArgs obj)
|
|
||||||
{
|
|
||||||
StorageService.SetValue(StorageKeys.WaitTo, obj.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
@page "/streams"
|
|
||||||
|
|
||||||
@inherits BasePage
|
|
||||||
|
|
||||||
@layout PageLayout
|
|
||||||
|
|
||||||
<LayoutMediumContentComponent>
|
|
||||||
<WebsiteTitleComponent>Streams</WebsiteTitleComponent>
|
|
||||||
|
|
||||||
<PaperComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>When and where are you streaming?</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>I stream Sunday updates on <a href="https://www.twitch.tv/jonathanmccaffrey"
|
|
||||||
target="_blank">Twitch</a>.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>What exactly are you streaming?</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
The plan will be sprint planning and general development of this website.
|
|
||||||
|
|
||||||
<br/><br/>
|
|
||||||
Feel free to jump into the stream to ask questions or make feature requests for the website.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>Why should you watch these streams?</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>
|
|
||||||
You shouldn't. By nature of being live coding streams, I think they will have little entertainment and
|
|
||||||
educational value.
|
|
||||||
<br/><br/>
|
|
||||||
The most reason (that comes to mind) is to see a coding day of one software developer. Although please
|
|
||||||
note that I stream content that I think is easy (to look smart), so it's not a "truly random" coding
|
|
||||||
day. For example, you won't find any vods of the five-week sprint where I (figuratively) bash my head
|
|
||||||
against the table trying to get SQL working in Blazor WASM before giving up and moving on.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
<InfoBodyComponent>
|
|
||||||
<InfoQuestionComponent>Anything else I should know?</InfoQuestionComponent>
|
|
||||||
<InfoAnswerComponent>I'll be streaming under the "<a
|
|
||||||
href="https://www.twitch.tv/directory/game/Software%20and%20Game%20Development" target="_blank">Twitch,
|
|
||||||
Software and Game Development</a>" category. If you are looking to see some actual IGP gameplay,
|
|
||||||
there are better and more focused streamers to provide said content. Check out the "<a
|
|
||||||
href="https://www.twitch.tv/directory/game/IMMORTAL%3A%20Gates%20of%20Pyre/videos/all"
|
|
||||||
target="_blank">Twitch, IMMORTAL: Gates of Pyre</a>" category for some examples.
|
|
||||||
</InfoAnswerComponent>
|
|
||||||
</InfoBodyComponent>
|
|
||||||
</PaperComponent>
|
|
||||||
</LayoutMediumContentComponent>
|
|
||||||
@@ -1,223 +0,0 @@
|
|||||||
@layout PageLayout
|
|
||||||
@inherits BasePage
|
|
||||||
@inject TechTreeService techTreeService
|
|
||||||
@inject IEntityDialogService entityDialogService
|
|
||||||
@inject NavigationManager NavigationManager
|
|
||||||
|
|
||||||
@page "/tech-tree"
|
|
||||||
|
|
||||||
<LayoutLargeContentComponent>
|
|
||||||
<WebsiteTitleComponent>Tech Tree</WebsiteTitleComponent>
|
|
||||||
|
|
||||||
<div class="techTreeControls">
|
|
||||||
<div class="techTreeFilters">
|
|
||||||
<span class="techTreeLabel">Faction:</span>
|
|
||||||
<button class="techTreeFilter @(selectedFaction == null ? "active" : "")"
|
|
||||||
@onclick="() => SelectFaction(null)">All
|
|
||||||
</button>
|
|
||||||
@foreach (var faction in factions)
|
|
||||||
{
|
|
||||||
var factionName = GetFactionName(faction);
|
|
||||||
<button class="techTreeFilter @(selectedFaction == faction ? "active" : "")"
|
|
||||||
@onclick="() => SelectFaction(faction)">@factionName</button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="techTreeSearchRow">
|
|
||||||
<input class="techTreeSearch" @bind="searchText" @bind:after="OnSearchChanged"
|
|
||||||
placeholder="Search for an entity..."/>
|
|
||||||
@if (!string.IsNullOrEmpty(highlightEntityId))
|
|
||||||
{
|
|
||||||
<button class="techTreeClearBtn" @onclick="ClearHighlight">Clear Highlight</button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="techTreeLegend">
|
|
||||||
<span class="legendItem"><span class="legendLine" style="background: #2ed573;"></span> Produces</span>
|
|
||||||
<span class="legendItem"><span class="legendLine"
|
|
||||||
style="background: #ffa502; border-top: 3px dashed #ffa502; height: 0;"></span> Requires Building</span>
|
|
||||||
<span class="legendItem"><span class="legendLine"
|
|
||||||
style="background: #a55eea; border-top: 3px dashed #a55eea; height: 0;"></span> Requires Research</span>
|
|
||||||
<span class="legendItem"><span class="legendLine"
|
|
||||||
style="background: #ff6b6b; border-top: 2px dotted #ff6b6b; height: 0;"></span> Morph</span>
|
|
||||||
<span class="legendItem"><span class="legendLine" style="background: #1e90ff;"></span> Upgrade</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (currentGraph != null && currentGraph.Nodes.Count > 0)
|
|
||||||
{
|
|
||||||
<TechTreeGraphComponent Graph="@currentGraph" HighlightEntityId="@highlightEntityId"
|
|
||||||
OnEntitySelected="OnEntitySelected"/>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<PaperComponent>
|
|
||||||
<p>No data available for the selected faction.</p>
|
|
||||||
</PaperComponent>
|
|
||||||
}
|
|
||||||
</LayoutLargeContentComponent>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.techTreeControls {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 12px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.techTreeFilters {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.techTreeLabel {
|
|
||||||
font-weight: 700;
|
|
||||||
margin-right: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.techTreeFilter {
|
|
||||||
padding: 6px 14px;
|
|
||||||
border-radius: 16px;
|
|
||||||
border: 2px solid var(--primary-border);
|
|
||||||
background-color: var(--primary);
|
|
||||||
color: white;
|
|
||||||
cursor: pointer;
|
|
||||||
font-family: inherit;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.techTreeFilter.active {
|
|
||||||
background-color: var(--primary-hover);
|
|
||||||
border-color: var(--primary-border-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.techTreeFilter:hover {
|
|
||||||
background-color: var(--primary-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.techTreeSearchRow {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.techTreeSearch {
|
|
||||||
padding: 10px 16px;
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 2px solid var(--primary-border);
|
|
||||||
background-color: var(--primary);
|
|
||||||
color: white;
|
|
||||||
font-size: 1rem;
|
|
||||||
font-family: inherit;
|
|
||||||
flex: 1;
|
|
||||||
max-width: 400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.techTreeSearch::placeholder {
|
|
||||||
color: rgba(255, 255, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.techTreeClearBtn {
|
|
||||||
padding: 6px 14px;
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 2px solid var(--primary-border);
|
|
||||||
background-color: transparent;
|
|
||||||
color: white;
|
|
||||||
cursor: pointer;
|
|
||||||
font-family: inherit;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.techTreeClearBtn:hover {
|
|
||||||
background-color: var(--primary-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.techTreeLegend {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 16px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
padding: 12px;
|
|
||||||
background-color: var(--paper);
|
|
||||||
border: 2px solid var(--paper-border);
|
|
||||||
border-radius: 8px;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.legendItem {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.legendLine {
|
|
||||||
display: inline-block;
|
|
||||||
width: 24px;
|
|
||||||
height: 3px;
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private TechTreeGraphModel? currentGraph;
|
|
||||||
private List<string> factions = new();
|
|
||||||
private string? selectedFaction;
|
|
||||||
private string searchText = "";
|
|
||||||
private string? highlightEntityId;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
LoadGraph();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadGraph()
|
|
||||||
{
|
|
||||||
currentGraph = techTreeService.BuildGraph(selectedFaction);
|
|
||||||
factions = techTreeService.GetFactions();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SelectFaction(string? faction)
|
|
||||||
{
|
|
||||||
selectedFaction = faction;
|
|
||||||
highlightEntityId = null;
|
|
||||||
LoadGraph();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnSearchChanged()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(searchText))
|
|
||||||
{
|
|
||||||
highlightEntityId = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var found = currentGraph?.Nodes
|
|
||||||
.FirstOrDefault(n => n.Name.Contains(searchText, StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
highlightEntityId = found?.Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClearHighlight()
|
|
||||||
{
|
|
||||||
highlightEntityId = null;
|
|
||||||
searchText = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnEntitySelected(string entityId)
|
|
||||||
{
|
|
||||||
highlightEntityId = entityId;
|
|
||||||
}
|
|
||||||
|
|
||||||
string GetFactionName(string factionId)
|
|
||||||
{
|
|
||||||
var entities = EntityData.Get();
|
|
||||||
return entities.TryGetValue(factionId, out var entity)
|
|
||||||
? entity.Info()?.Name ?? factionId
|
|
||||||
: factionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
namespace IGP.Utils;
|
|
||||||
|
|
||||||
public static class Interval
|
|
||||||
{
|
|
||||||
public static string ToTime(int interval)
|
|
||||||
{
|
|
||||||
return TimeSpan.FromSeconds(interval).ToString(@"mm\:ss");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
using Markdig;
|
|
||||||
using Markdig.Extensions.Yaml;
|
|
||||||
using Markdig.Syntax;
|
|
||||||
using YamlDotNet.Serialization;
|
|
||||||
|
|
||||||
namespace IGP.Utils;
|
|
||||||
|
|
||||||
public static class MarkdownFiles
|
|
||||||
{
|
|
||||||
private static readonly IDeserializer YamlDeserializer =
|
|
||||||
new DeserializerBuilder()
|
|
||||||
.IgnoreUnmatchedProperties()
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
public static readonly MarkdownPipeline Pipeline
|
|
||||||
= new MarkdownPipelineBuilder()
|
|
||||||
.UseYamlFrontMatter()
|
|
||||||
.UseAdvancedExtensions()
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
public static async Task<string> LoadMarkdown(HttpClient httpClient, string filepath)
|
|
||||||
{
|
|
||||||
return await httpClient.GetStringAsync(filepath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<T> LoadFrontMatter<T>(HttpClient httpClient, string filepath)
|
|
||||||
{
|
|
||||||
var markdown = await LoadMarkdown(httpClient, filepath);
|
|
||||||
|
|
||||||
var document = Markdown.Parse(markdown, Pipeline);
|
|
||||||
|
|
||||||
var block = document
|
|
||||||
.Descendants<YamlFrontMatterBlock>()
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
if (block == null)
|
|
||||||
return default!;
|
|
||||||
|
|
||||||
var yaml =
|
|
||||||
block
|
|
||||||
.Lines
|
|
||||||
.Lines
|
|
||||||
.OrderByDescending(x => x.Line)
|
|
||||||
.Select(x => $"{x}\n")
|
|
||||||
.ToList()
|
|
||||||
.Select(x => x.Replace("---", string.Empty))
|
|
||||||
.Where(x => !string.IsNullOrWhiteSpace(x))
|
|
||||||
.Aggregate((s, agg) => agg + s);
|
|
||||||
|
|
||||||
return YamlDeserializer.Deserialize<T>(yaml);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace IGP.Utils;
|
|
||||||
|
|
||||||
public static class Project
|
|
||||||
{
|
|
||||||
public static string GitResourcesUrl =>
|
|
||||||
"https://github.com/JonathanMcCaffrey/IGP-Fan-Reference/blob/develop/IGP/wwwroot/";
|
|
||||||
}
|
|
||||||
+1
-15
@@ -37,26 +37,12 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Components\Components.csproj"/>
|
<ProjectReference Include="..\Components\Components.csproj"/>
|
||||||
<ProjectReference Include="..\Model\Model.csproj"/>
|
<ProjectReference Include="..\Model\Model.csproj"/>
|
||||||
|
<ProjectReference Include="..\Pages\Pages.csproj"/>
|
||||||
<ProjectReference Include="..\Services\Services.csproj"/>
|
<ProjectReference Include="..\Services\Services.csproj"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Pages\DataTables\Parts\"/>
|
|
||||||
<Folder Include="wwwroot\generated"/>
|
<Folder Include="wwwroot\generated"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Update="Localizations.resx">
|
|
||||||
<Generator>ResXFileCodeGenerator</Generator>
|
|
||||||
<LastGenOutput>Localizations.Designer.cs</LastGenOutput>
|
|
||||||
</EmbeddedResource>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Update="Localizations.Designer.cs">
|
|
||||||
<DesignTime>True</DesignTime>
|
|
||||||
<AutoGen>True</AutoGen>
|
|
||||||
<DependentUpon>Example.resx</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
Reference in New Issue
Block a user