Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions Satistools.Calculator.Test/CateriumProductsTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using Satistools.Calculator.Graph;
using Satistools.Calculator.Test.SetUp;
using Xunit;
using Xunit.Abstractions;

namespace Satistools.Calculator.Test;

public class CateriumProductsTest : CalcTest
{
public CateriumProductsTest(CalculatorFactory factory, ITestOutputHelper testOutputHelper) : base(factory, testOutputHelper)
{
}

/// <summary>
/// Tests production of Caterium Ingot via alternate: Pure Caterium Ingot.
/// </summary>
[Fact]
public async Task Test_PureCateriumIngot()
{
IProductionCalculator calculator = ServiceProvider.GetRequiredService<IProductionCalculator>();
calculator.AddTargetProduct("Desc_GoldIngot_C", 36f);
calculator.UseAlternateRecipe("Recipe_Alternate_PureCateriumIngot_C");
ProductionGraph graph = await calculator.Calculate();

graph.Count.Should().Be(3);

GraphNode ingot = graph["Desc_GoldIngot_C"];
ingot.Product.TargetAmount.Should().Be(36f);
ingot.BuildingAmount.Should().Be(3f);
ingot.Building!.Id.Should().Be("Build_OilRefinery_C");
ingot.NeededProducts.Should().HaveCount(2);

GraphNode water = graph["Desc_Water_C"];
water.Product.TargetAmount.Should().Be(72f);

GraphNode ore = graph["Desc_OreGold_C"];
ore.Product.TargetAmount.Should().Be(72f);
}
}
173 changes: 173 additions & 0 deletions Satistools.Calculator.Test/IronProductsTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
using System.Linq;
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using Satistools.Calculator.Graph;
using Satistools.Calculator.Test.SetUp;
using Xunit;
using Xunit.Abstractions;

namespace Satistools.Calculator.Test;

public class IronProductsTest : CalcTest
{
public IronProductsTest(CalculatorFactory factory, ITestOutputHelper testOutputHelper) : base(factory, testOutputHelper)
{
}

/// <summary>
/// Tests calculation of basic iron ingot production.
/// </summary>
[Fact]
public async Task Test_IronIngot()
{
IProductionCalculator calculator = ServiceProvider.GetRequiredService<IProductionCalculator>();
calculator.AddTargetProduct("Desc_IronIngot_C", 30f);
ProductionGraph graph = await calculator.Calculate();

graph.Count.Should().Be(2);
GraphNode topNode = graph.First();
topNode.Product.TargetAmount.Should().Be(30f);
topNode.Product.Id.Should().Be("Desc_IronIngot_C");
topNode.NeededProducts.Should().HaveCount(1);
topNode.UsedBy.Should().HaveCount(0);

GraphNode lastNode = graph.Last();
lastNode.Product.TargetAmount.Should().Be(30f);
lastNode.Product.Id.Should().Be("Desc_OreIron_C");
lastNode.UsedBy.Should().HaveCount(1);
lastNode.NeededProducts.Should().HaveCount(0);

NodeRelation oreIsUsed = lastNode.UsedBy.First();
oreIsUsed.UnitsAmount.Should().Be(30f);
}

/// <summary>
/// Test production of bigger amount of iron plate.
/// </summary>
[Fact]
public async Task Test_IronPlate()
{
IProductionCalculator calculator = ServiceProvider.GetRequiredService<IProductionCalculator>();
calculator.AddTargetProduct("Desc_IronPlate_C", 50f);
ProductionGraph graph = await calculator.Calculate();

graph.Count.Should().Be(3);

GraphNode ingot = graph["Desc_IronIngot_C"];
ingot.UsedBy.Should().HaveCount(1);
ingot.NeededProducts.Should().HaveCount(1);
ingot.BuildingAmount.Should().Be(2.5f);

GraphNode plate = graph["Desc_IronPlate_C"];
plate.NeededProducts.Should().HaveCount(1);
plate.BuildingAmount.Should().Be(2.5f);
}

/// <summary>
/// Tests two target products. Iron Plate & Iron Rod.
/// </summary>
[Fact]
public async Task Test_DoubleProduction()
{
IProductionCalculator calculator = ServiceProvider.GetRequiredService<IProductionCalculator>();
calculator.AddTargetProduct("Desc_IronPlate_C", 20f);
calculator.AddTargetProduct("Desc_IronRod_C", 15f);
ProductionGraph graph = await calculator.Calculate();

graph.Count.Should().Be(4);

GraphNode ore = graph["Desc_OreIron_C"];
ore.Product.TargetAmount.Should().Be(45f);

GraphNode ingot = graph["Desc_IronIngot_C"];
ingot.Product.TargetAmount.Should().Be(45f);
ingot.UsedBy.Should().HaveCount(2);
}

/// <summary>
/// Tests production of Reinforced Iron Plate.
/// </summary>
[Fact]
public async Task Test_ReinforcedIronPlate()
{
IProductionCalculator calculator = ServiceProvider.GetRequiredService<IProductionCalculator>();
calculator.AddTargetProduct("Desc_IronPlateReinforced_C", 5f);
ProductionGraph graph = await calculator.Calculate();

graph.Should().HaveCount(6);

GraphNode ore = graph["Desc_OreIron_C"];
ore.Product.TargetAmount.Should().Be(60f);

GraphNode ingot = graph["Desc_IronIngot_C"];
ingot.Product.TargetAmount.Should().Be(60f);
ingot.UsedBy.Should().HaveCount(2);

GraphNode rip = graph["Desc_IronPlateReinforced_C"];
rip.NeededProducts.Should().HaveCount(2);
}

/// <summary>
/// Tests production of all advanced iron products - Rotors, Modular Frames & Reinforced Plates.
/// </summary>
[Fact]
public async Task Test_AdvancedIronProducts()
{
IProductionCalculator calculator = ServiceProvider.GetRequiredService<IProductionCalculator>();
calculator.AddTargetProduct("Desc_IronPlateReinforced_C", 5f);
calculator.AddTargetProduct("Desc_Rotor_C", 4f);
calculator.AddTargetProduct("Desc_ModularFrame_C", 2f);
ProductionGraph graph = await calculator.Calculate();

graph.Should().HaveCount(8);

GraphNode ingot = graph["Desc_IronIngot_C"];
ingot.Product.TargetAmount.Should().Be(153f);
ingot.UsedBy.Should().HaveCount(2);

GraphNode rip = graph["Desc_IronPlateReinforced_C"];
rip.Product.TargetAmount.Should().Be(8);
rip.NeededProducts.Should().HaveCount(2);
rip.UsedBy.Should().HaveCount(1);
}

/// <summary>
/// Just like previous test, but every manufactuerer is producing at 100%.
/// </summary>
[Fact]
public async Task Test_BalancedProduction()
{
IProductionCalculator calculator = ServiceProvider.GetRequiredService<IProductionCalculator>();
calculator.AddTargetProduct("Desc_IronPlateReinforced_C", 7f);
calculator.AddTargetProduct("Desc_Rotor_C", 4f);
calculator.AddTargetProduct("Desc_ModularFrame_C", 2f);
calculator.AddTargetProduct("Desc_IronScrew_C", 20f);
calculator.AddTargetProduct("Desc_IronRod_C", 13f);
calculator.AddTargetProduct("Desc_IronIngot_C", 15f);
ProductionGraph graph = await calculator.Calculate();

graph.Should().HaveCount(8);
graph.Sum(n => n.BuildingAmount).Should().Be(27f);
}

/// <summary>
/// Tests production of rotot via Alternate: Steel Rotor.
/// </summary>
[Fact]
public async Task Test_AlternateSteelRotor()
{
IProductionCalculator calculator = ServiceProvider.GetRequiredService<IProductionCalculator>();
calculator.AddTargetProduct("Desc_Rotor_C", 5f);
calculator.UseAlternateRecipe("Recipe_Alternate_Rotor_C");
ProductionGraph graph = await calculator.Calculate();

graph.Should().HaveCount(8);

GraphNode ironOre = graph["Desc_OreIron_C"];
ironOre.Product.TargetAmount.Should().Be(15f);

GraphNode coal = graph["Desc_Coal_C"];
coal.Product.TargetAmount.Should().Be(15f);
}
}
48 changes: 48 additions & 0 deletions Satistools.Calculator.Test/OilProductsTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using Satistools.Calculator.Graph;
using Satistools.Calculator.Test.SetUp;
using Xunit;
using Xunit.Abstractions;

namespace Satistools.Calculator.Test;

public class OilProductsTest : CalcTest
{
public OilProductsTest(CalculatorFactory factory, ITestOutputHelper testOutputHelper) : base(factory, testOutputHelper)
{
}

/// <summary>
/// Tests production of plastic.
/// </summary>
[Fact]
public async Task Test_PlasticProduction()
{
IProductionCalculator calculator = ServiceProvider.GetRequiredService<IProductionCalculator>();
calculator.AddTargetProduct("Desc_Plastic_C", 20f);
ProductionGraph graph = await calculator.Calculate();

graph.Should().HaveCount(2);

GraphNode plastic = graph["Desc_Plastic_C"];
plastic.Byproduct.Should().NotBeNull();
plastic.Byproduct!.TargetAmount.Should().Be(10f);

GraphNode residue = graph["Desc_HeavyOilResidue_C"]; // We are able to find the node also by byproduct
residue.ProductId.Should().Be(plastic.ProductId);
residue.ByproductId.Should().Be(residue.ByproductId);
}

[Fact]
public async Task Test_PlasticAndFuel()
{
IProductionCalculator calculator = ServiceProvider.GetRequiredService<IProductionCalculator>();
calculator.AddTargetProduct("Desc_Plastic_C", 20f);
calculator.AddTargetProduct("Desc_LiquidFuel_C", 6.66f);
ProductionGraph graph = await calculator.Calculate();

graph.Should().HaveCount(3);
}
}
37 changes: 37 additions & 0 deletions Satistools.Calculator.Test/Satistools.Calculator.Test.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.6.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.5" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="Sagittaras.Model.TestFramework" Version="1.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Satistools.Calculator\Satistools.Calculator.csproj" />
</ItemGroup>

<ItemGroup>
<Content Include="..\FactoryGame.json">
<Link>FactoryGame.json</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

</Project>
12 changes: 12 additions & 0 deletions Satistools.Calculator.Test/SetUp/CalcTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Sagittaras.Model.TestFramework;
using Satistools.GameData;
using Xunit.Abstractions;

namespace Satistools.Calculator.Test.SetUp;

public abstract class CalcTest : UnitTest<CalculatorFactory, GameDataContext>
{
protected CalcTest(CalculatorFactory factory, ITestOutputHelper testOutputHelper) : base(factory, testOutputHelper)
{
}
}
27 changes: 27 additions & 0 deletions Satistools.Calculator.Test/SetUp/CalculatorFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Sagittaras.Model.TestFramework;
using Sagittaras.Repository.Extensions;
using Satistools.Calculator.Extensions;
using Satistools.GameData;
using Satistools.GameData.Items;
using Satistools.GameData.Recipes;

namespace Satistools.Calculator.Test.SetUp;

public class CalculatorFactory : TestFactory
{
protected override void OnConfiguring(ServiceCollection services)
{
services.AddDbContext<GameDataContext>(options =>
{
options.UseInMemoryDatabase(GetConnectionString(Engine.InMemory));
});
services.UseRepositoryPattern(options =>
{
options.AddRepository<IItemRepository, ItemRepository>();
options.AddRepository<IRecipeRepository, RecipeRepository>();
});
services.AddCalculator();
}
}
23 changes: 23 additions & 0 deletions Satistools.Calculator/AnalyseResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Satistools.Calculator.Graph;

namespace Satistools.Calculator;

public readonly struct AnalyseResult
{
public GraphNode ProductNode { get; }
public float ProductAmount { get; }
public IEnumerable<GraphNode> Byproducts { get; } = Array.Empty<GraphNode>();

public AnalyseResult(GraphNode productNode, float productAmount)
{
ProductNode = productNode;
ProductAmount = productAmount;
}

public AnalyseResult(GraphNode productNode, float productAmount, IEnumerable<GraphNode> byproducts)
{
ProductNode = productNode;
ProductAmount = productAmount;
Byproducts = byproducts;
}
}
11 changes: 11 additions & 0 deletions Satistools.Calculator/Extensions/ServiceExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Microsoft.Extensions.DependencyInjection;

namespace Satistools.Calculator.Extensions;

public static class ServiceExtension
{
public static void AddCalculator(this IServiceCollection services)
{
services.AddTransient<IProductionCalculator, ProductionCalculator>();
}
}
Loading