Start of data comparison tables
This commit is contained in:
+5
-1
@@ -1,7 +1,11 @@
|
|||||||
@inject IVariableService VariableService
|
@using IGP.Pages.DataTables
|
||||||
|
@inject IVariableService VariableService
|
||||||
@inject IStorageService StorageService
|
@inject IStorageService StorageService
|
||||||
@inject IPermissionService PermissionService
|
@inject IPermissionService PermissionService
|
||||||
|
|
||||||
|
<DevOnlyComponent>
|
||||||
|
<DataTablesPage/>
|
||||||
|
</DevOnlyComponent>
|
||||||
|
|
||||||
<Router AppAssembly="@typeof(App).Assembly">
|
<Router AppAssembly="@typeof(App).Assembly">
|
||||||
<Found Context="routeData">
|
<Found Context="routeData">
|
||||||
|
|||||||
@@ -1,107 +1,14 @@
|
|||||||
@layout PageLayout
|
@layout PageLayout
|
||||||
|
|
||||||
@inject IDataCollectionService DataCollectionService
|
@using IGP.Pages.DataTables.Parts
|
||||||
@using Model
|
|
||||||
@inherits BasePage
|
@inherits BasePage
|
||||||
|
|
||||||
@page "/data-tables"
|
@page "/data-tables"
|
||||||
|
|
||||||
<LayoutMediumContentComponent>
|
<LayoutMediumContentComponent>
|
||||||
<WebsiteTitleComponent>Comparision Tables</WebsiteTitleComponent>
|
<WebsiteTitleComponent>Data Tables</WebsiteTitleComponent>
|
||||||
|
|
||||||
<PaperComponent>
|
<WeaponTable/>
|
||||||
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>
|
<ContentDividerComponent></ContentDividerComponent>
|
||||||
|
|
||||||
@@ -111,283 +18,20 @@
|
|||||||
What is this tool?
|
What is this tool?
|
||||||
</InfoQuestionComponent>
|
</InfoQuestionComponent>
|
||||||
<InfoAnswerComponent>
|
<InfoAnswerComponent>
|
||||||
The Harass Calculator allows you to calculate damage done to an enemy alloy line. For example, if you
|
Compare data
|
||||||
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>
|
</InfoAnswerComponent>
|
||||||
</InfoBodyComponent>
|
</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>
|
</PaperComponent>
|
||||||
|
|
||||||
|
|
||||||
</LayoutMediumContentComponent>
|
</LayoutMediumContentComponent>
|
||||||
|
|
||||||
<style>
|
<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>
|
</style>
|
||||||
|
|
||||||
@code {
|
@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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
<MudDataGrid Items="@_entityWeapons.Take(4)">
|
<MudDataGrid Items="@_entityWeapons.Take(4)">
|
||||||
<Columns>
|
<Columns>
|
||||||
<PropertyColumn Property="x => x.Range" Title="Nr"/>
|
<PropertyColumn Property="x => x.Range" Title="Range"/>
|
||||||
|
<PropertyColumn Property="x => x.Damage" Title="Damage"/>
|
||||||
|
<PropertyColumn Property="x => x.AttacksPerSecond" Title="Attacks Per Second"/>
|
||||||
</Columns>
|
</Columns>
|
||||||
</MudDataGrid>
|
</MudDataGrid>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Model.Entity.Parts;
|
|||||||
public class EntityWeaponModel : IEntityPartInterface
|
public class EntityWeaponModel : IEntityPartInterface
|
||||||
{
|
{
|
||||||
public int Id { get; set; } = 1;
|
public int Id { get; set; } = 1;
|
||||||
public string EntityModelId { get; set; } = "EntityWeaponModel";
|
public int EntityModelId { get; set; }
|
||||||
public virtual EntityModel EntityModel { get; set; }
|
public virtual EntityModel EntityModel { get; set; }
|
||||||
|
|
||||||
public int Range { get; set; } = 40;
|
public int Range { get; set; } = 40;
|
||||||
|
|||||||
@@ -2,5 +2,4 @@
|
|||||||
|
|
||||||
public class IEntityPartInterface
|
public class IEntityPartInterface
|
||||||
{
|
{
|
||||||
public string EntityModelId { get; set; }
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user