Tech stack stub page and changing project to be just one Web Assembly project for now
This commit is contained in:
@@ -0,0 +1,355 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace WebAssembly.Throwaway;
|
||||
|
||||
public sealed class ResourceAmounts
|
||||
{
|
||||
public int Draft { get; set; }
|
||||
public int Food { get; set; }
|
||||
public int Knowledge { get; set; }
|
||||
public int Industry { get; set; }
|
||||
public int Magic { get; set; }
|
||||
public int Gold { get; set; }
|
||||
public int Imperial { get; set; }
|
||||
public int Stability { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsZero => Draft == 0 && Food == 0 && Knowledge == 0 && Industry == 0 && Magic == 0 && Gold == 0 &&
|
||||
Imperial == 0 && Stability == 0;
|
||||
|
||||
public void Add(ResourceAmounts other)
|
||||
{
|
||||
Draft += other.Draft;
|
||||
Food += other.Food;
|
||||
Knowledge += other.Knowledge;
|
||||
Industry += other.Industry;
|
||||
Magic += other.Magic;
|
||||
Gold += other.Gold;
|
||||
Imperial += other.Imperial;
|
||||
Stability += other.Stability;
|
||||
}
|
||||
|
||||
public void Subtract(ResourceAmounts other)
|
||||
{
|
||||
Draft -= other.Draft;
|
||||
Food -= other.Food;
|
||||
Knowledge -= other.Knowledge;
|
||||
Industry -= other.Industry;
|
||||
Magic -= other.Magic;
|
||||
Gold -= other.Gold;
|
||||
Imperial -= other.Imperial;
|
||||
Stability -= other.Stability;
|
||||
}
|
||||
|
||||
public static ResourceAmounts operator +(ResourceAmounts a, ResourceAmounts b)
|
||||
{
|
||||
return new ResourceAmounts
|
||||
{
|
||||
Draft = a.Draft + b.Draft,
|
||||
Food = a.Food + b.Food,
|
||||
Knowledge = a.Knowledge + b.Knowledge,
|
||||
Industry = a.Industry + b.Industry,
|
||||
Magic = a.Magic + b.Magic,
|
||||
Gold = a.Gold + b.Gold,
|
||||
Imperial = a.Imperial + b.Imperial,
|
||||
Stability = a.Stability + b.Stability
|
||||
};
|
||||
}
|
||||
|
||||
public static ResourceAmounts operator -(ResourceAmounts a, ResourceAmounts b)
|
||||
{
|
||||
return new ResourceAmounts
|
||||
{
|
||||
Draft = a.Draft - b.Draft,
|
||||
Food = a.Food - b.Food,
|
||||
Knowledge = a.Knowledge - b.Knowledge,
|
||||
Industry = a.Industry - b.Industry,
|
||||
Magic = a.Magic - b.Magic,
|
||||
Gold = a.Gold - b.Gold,
|
||||
Imperial = a.Imperial - b.Imperial,
|
||||
Stability = a.Stability - b.Stability
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class BuildingDefinition
|
||||
{
|
||||
public string Id { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string? Description { get; set; }
|
||||
public string? Image { get; set; }
|
||||
public string SourceId { get; set; } = "General";
|
||||
public List<string> RequirementIds { get; set; } = new();
|
||||
public ResourceAmounts Income { get; set; } = new();
|
||||
public ResourceAmounts Upkeep { get; set; } = new();
|
||||
public ResourceAmounts Cost { get; set; } = new();
|
||||
public int BoostPopulation { get; set; }
|
||||
public int BoostForester { get; set; }
|
||||
public int BoostFarm { get; set; }
|
||||
public int BoostQuarry { get; set; }
|
||||
public int BoostGoldMine { get; set; }
|
||||
public int BoostConduit { get; set; }
|
||||
}
|
||||
|
||||
public sealed class BuildOrderEntry
|
||||
{
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
public string ItemId { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public int RequestedTurn { get; set; }
|
||||
public int BuildStartTurn { get; set; }
|
||||
public int BuiltFinishTurn { get; set; }
|
||||
public int IndustryCostRemaining { get; set; }
|
||||
public BuildingDefinition Definition { get; set; } = new();
|
||||
}
|
||||
|
||||
public sealed class ResourceSnapshot
|
||||
{
|
||||
public int Turn { get; set; }
|
||||
public ResourceAmounts Stored { get; set; } = new();
|
||||
public ResourceAmounts TotalIncome { get; set; } = new();
|
||||
public ResourceAmounts TotalUpkeep { get; set; } = new();
|
||||
public string? Notes { get; set; }
|
||||
}
|
||||
|
||||
public sealed class BuildPlanResult
|
||||
{
|
||||
public List<BuildOrderEntry> BuildOrder { get; set; } = new();
|
||||
public List<ResourceSnapshot> ResourceHistory { get; set; } = new();
|
||||
public ResourceAmounts StartingPool { get; set; } = new();
|
||||
}
|
||||
|
||||
public sealed class BuildOrderRequest
|
||||
{
|
||||
public string ItemId { get; init; } = string.Empty;
|
||||
public BuildingDefinition Definition { get; init; } = new();
|
||||
public int RequestedTurn { get; init; }
|
||||
}
|
||||
|
||||
public static class BuildingPlanCalculator
|
||||
{
|
||||
public static BuildPlanResult CalculateBuildPlan(
|
||||
int totalTurns,
|
||||
IEnumerable<BuildOrderRequest> buildRequests,
|
||||
IEnumerable<BuildingDefinition>? startingBuildings = null,
|
||||
ResourceAmounts? startingResources = null)
|
||||
{
|
||||
var activeBuildings = new List<BuildOrderEntry>();
|
||||
var result = new BuildPlanResult
|
||||
{
|
||||
StartingPool = startingResources ?? new ResourceAmounts()
|
||||
};
|
||||
|
||||
var stored = new ResourceAmounts();
|
||||
if (startingResources is not null)
|
||||
stored = new ResourceAmounts
|
||||
{
|
||||
Draft = startingResources.Draft,
|
||||
Food = startingResources.Food,
|
||||
Knowledge = startingResources.Knowledge,
|
||||
Industry = startingResources.Industry,
|
||||
Magic = startingResources.Magic,
|
||||
Gold = startingResources.Gold,
|
||||
Imperial = startingResources.Imperial,
|
||||
Stability = startingResources.Stability
|
||||
};
|
||||
|
||||
if (startingBuildings is not null)
|
||||
foreach (var startingBuilding in startingBuildings)
|
||||
{
|
||||
var entry = new BuildOrderEntry
|
||||
{
|
||||
ItemId = startingBuilding.Id,
|
||||
Name = startingBuilding.Name,
|
||||
RequestedTurn = 1,
|
||||
BuildStartTurn = 1,
|
||||
BuiltFinishTurn = 0,
|
||||
IndustryCostRemaining = 0,
|
||||
Definition = startingBuilding
|
||||
};
|
||||
activeBuildings.Add(entry);
|
||||
result.BuildOrder.Add(entry);
|
||||
}
|
||||
|
||||
var requestsByTurn = buildRequests
|
||||
.OrderBy(r => r.RequestedTurn)
|
||||
.GroupBy(r => r.RequestedTurn)
|
||||
.ToDictionary(g => g.Key, g => g.ToList());
|
||||
|
||||
var projects = new List<BuildOrderEntry>();
|
||||
|
||||
for (var turn = 1; turn <= totalTurns; turn++)
|
||||
{
|
||||
var incomeThisTurn = new ResourceAmounts();
|
||||
var upkeepThisTurn = new ResourceAmounts();
|
||||
|
||||
foreach (var building in activeBuildings)
|
||||
if (building.BuiltFinishTurn == 0 || turn > building.BuiltFinishTurn)
|
||||
{
|
||||
incomeThisTurn.Add(building.Definition.Income);
|
||||
upkeepThisTurn.Add(building.Definition.Upkeep);
|
||||
}
|
||||
|
||||
stored.Add(incomeThisTurn);
|
||||
stored.Subtract(upkeepThisTurn);
|
||||
|
||||
if (requestsByTurn.TryGetValue(turn, out var requests))
|
||||
foreach (var request in requests)
|
||||
{
|
||||
var nextProject = new BuildOrderEntry
|
||||
{
|
||||
ItemId = request.ItemId,
|
||||
Name = request.Definition.Name,
|
||||
RequestedTurn = turn,
|
||||
BuildStartTurn = turn,
|
||||
BuiltFinishTurn = 0,
|
||||
IndustryCostRemaining = request.Definition.Cost.Industry,
|
||||
Definition = request.Definition
|
||||
};
|
||||
|
||||
stored.Subtract(new ResourceAmounts
|
||||
{
|
||||
Draft = request.Definition.Cost.Draft,
|
||||
Food = request.Definition.Cost.Food,
|
||||
Knowledge = request.Definition.Cost.Knowledge,
|
||||
Magic = request.Definition.Cost.Magic,
|
||||
Gold = request.Definition.Cost.Gold,
|
||||
Imperial = request.Definition.Cost.Imperial,
|
||||
Stability = 0
|
||||
});
|
||||
|
||||
projects.Add(nextProject);
|
||||
result.BuildOrder.Add(nextProject);
|
||||
}
|
||||
|
||||
var availableIndustry = incomeThisTurn.Industry;
|
||||
foreach (var project in projects.Where(p => p.BuiltFinishTurn == 0).OrderBy(p => p.RequestedTurn))
|
||||
{
|
||||
if (availableIndustry <= 0 || project.IndustryCostRemaining <= 0) continue;
|
||||
|
||||
var applied = Math.Min(availableIndustry, project.IndustryCostRemaining);
|
||||
project.IndustryCostRemaining -= applied;
|
||||
availableIndustry -= applied;
|
||||
|
||||
if (project.IndustryCostRemaining <= 0)
|
||||
{
|
||||
project.BuiltFinishTurn = turn;
|
||||
activeBuildings.Add(project);
|
||||
}
|
||||
}
|
||||
|
||||
result.ResourceHistory.Add(new ResourceSnapshot
|
||||
{
|
||||
Turn = turn,
|
||||
Stored = new ResourceAmounts
|
||||
{
|
||||
Draft = stored.Draft,
|
||||
Food = stored.Food,
|
||||
Knowledge = stored.Knowledge,
|
||||
Industry = stored.Industry,
|
||||
Magic = stored.Magic,
|
||||
Gold = stored.Gold,
|
||||
Imperial = stored.Imperial,
|
||||
Stability = stored.Stability
|
||||
},
|
||||
TotalIncome = incomeThisTurn,
|
||||
TotalUpkeep = upkeepThisTurn,
|
||||
Notes = null
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IReadOnlyList<BuildingDefinition> GetDefaultStartingBuildings()
|
||||
{
|
||||
return new List<BuildingDefinition>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Id = "town-hall-1",
|
||||
Name = "Town Hall I",
|
||||
Description = "Starting civic center that produces basic resources and morale.",
|
||||
SourceId = "General",
|
||||
Income = new ResourceAmounts
|
||||
{
|
||||
Draft = 20,
|
||||
Food = 30,
|
||||
Industry = 20,
|
||||
Gold = 0,
|
||||
Stability = 10
|
||||
},
|
||||
Upkeep = new ResourceAmounts(),
|
||||
Cost = new ResourceAmounts()
|
||||
},
|
||||
new()
|
||||
{
|
||||
Id = "throne",
|
||||
Name = "Throne",
|
||||
Description = "Royal treasury building that provides steady gold income.",
|
||||
SourceId = "General",
|
||||
Income = new ResourceAmounts
|
||||
{
|
||||
Gold = 120
|
||||
},
|
||||
Upkeep = new ResourceAmounts(),
|
||||
Cost = new ResourceAmounts()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static BuildPlanResult CreateSampleBuildPlan(int totalTurns = 60)
|
||||
{
|
||||
var sampleRequests = new List<BuildOrderRequest>
|
||||
{
|
||||
new()
|
||||
{
|
||||
ItemId = "farm-1",
|
||||
Definition = new BuildingDefinition
|
||||
{
|
||||
Id = "farm-1",
|
||||
Name = "Farm",
|
||||
Description = "Provides food income and supports future growth.",
|
||||
SourceId = "General",
|
||||
Income = new ResourceAmounts { Food = 15 },
|
||||
Upkeep = new ResourceAmounts { Gold = 2 },
|
||||
Cost = new ResourceAmounts { Gold = 80, Industry = 40 }
|
||||
},
|
||||
RequestedTurn = 2
|
||||
},
|
||||
new()
|
||||
{
|
||||
ItemId = "workshop-1",
|
||||
Definition = new BuildingDefinition
|
||||
{
|
||||
Id = "workshop-1",
|
||||
Name = "Workshop",
|
||||
Description = "Improves production and generates industry.",
|
||||
SourceId = "General",
|
||||
Income = new ResourceAmounts { Industry = 20 },
|
||||
Upkeep = new ResourceAmounts { Gold = 4 },
|
||||
Cost = new ResourceAmounts { Gold = 110, Industry = 80 }
|
||||
},
|
||||
RequestedTurn = 5
|
||||
},
|
||||
new()
|
||||
{
|
||||
ItemId = "market-1",
|
||||
Definition = new BuildingDefinition
|
||||
{
|
||||
Id = "market-1",
|
||||
Name = "Market",
|
||||
Description = "Provides ongoing gold income and supports trade.",
|
||||
SourceId = "General",
|
||||
Income = new ResourceAmounts { Gold = 40 },
|
||||
Upkeep = new ResourceAmounts { Gold = 6 },
|
||||
Cost = new ResourceAmounts { Gold = 180, Industry = 100 }
|
||||
},
|
||||
RequestedTurn = 12
|
||||
}
|
||||
};
|
||||
|
||||
return CalculateBuildPlan(totalTurns, sampleRequests, GetDefaultStartingBuildings(),
|
||||
new ResourceAmounts { Gold = 0 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user