XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using XFEEDToolBox.Core.Engineering;
using XFEEDToolBox.Core.Presentation;
using XFEExtension.NetCore.XUnit.Attributes;

namespace XFEEDToolBox.Test;

[TestFixture]
public class MaterialWarehouseTests
{
    private static MaterialStock[] Stocks =>
    [
        new("nickel", "Nickel", "Raw", 1, 40, 300),
        new("arsenic", "Arsenic", "Raw", 2, 0, 250),
        new("selenium", "Selenium", "Raw", 4, 150, 150),
        new("conductivecomponents", "Conductive Components", "Manufactured", 1, 81, 300),
        new("chemical", "Chemical Manipulators", "Manufactured", 4, 6, 150),
        new("encoded", "Encoded Data", "Encoded", 5, 20, 100),
        new("unknown", "Unknown Material", "Other", 0, 9, 0)
    ];

    [Test] public void CategoryOwnershipGradeAndQuantityFiltersCombine()
    {
        var result = MaterialWarehouseQuery.Apply(Stocks, new()
        {
            Category = "raw", Ownership = MaterialOwnership.Unowned,
            MinimumGrade = 2, MaximumGrade = 4, MinimumQuantity = 0, MaximumQuantity = 0
        });
        Check.Equal("arsenic", result.Single().Key);
        Check.Equal(6, MaterialWarehouseQuery.Apply(Stocks, new() { Ownership = MaterialOwnership.Owned }).Count);
        Check.Equal(7, MaterialWarehouseQuery.Apply(Stocks, new()).Count);
        Check.Equal(0, MaterialWarehouseQuery.Apply(Stocks, new() { Ownership = MaterialOwnership.Unowned, MinimumQuantity = 1 }).Count);
    }

    [Test] public void SearchIgnoresWhitespaceAndCaseAndMatchesGameKeys()
    {
        Check.Equal("conductivecomponents", MaterialWarehouseQuery.Apply(Stocks, new() { Search = "  COMPONENTS\tconductive  " }).Single().Key);
        Check.Equal("conductivecomponents", MaterialWarehouseQuery.Apply(Stocks, new() { Search = "CONDUCTIVECOMPONENTS" }).Single().Key);
        Check.Equal(Stocks.Length, MaterialWarehouseQuery.Apply(Stocks, new() { Search = "  \t " }).Count);
        Check.Equal(0, MaterialWarehouseQuery.Apply(Stocks, new() { Search = "no such material" }).Count);
    }

    [Test] public void PercentageBoundariesExcludeUnknownCapacity()
    {
        MaterialStock[] rows = [new("quarter", "Quarter", "Raw", 1, 25, 100),
            new("half", "Half", "Raw", 1, 50, 100), new("near", "Near", "Raw", 1, 80, 100),
            new("full", "Full", "Raw", 1, 100, 100), new("unknown", "Unknown", "Other", 0, 0, 0)];
        Check.Equal(0, MaterialWarehouseQuery.Apply(rows, new() { StockLevel = MaterialStockLevel.BelowQuarter }).Count);
        Check.Equal("quarter", MaterialWarehouseQuery.Apply(rows, new() { StockLevel = MaterialStockLevel.BelowHalf }).Single().Key);
        Check.Equal(2, MaterialWarehouseQuery.Apply(rows, new() { StockLevel = MaterialStockLevel.NearlyFull }).Count);
        Check.Equal("full", MaterialWarehouseQuery.Apply(rows, new() { StockLevel = MaterialStockLevel.Full }).Single().Key);
        Check.Equal(3, MaterialWarehouseQuery.Apply(rows, new() { StockLevel = MaterialStockLevel.NotFull }).Count);
        Check.Equal("unknown", MaterialWarehouseQuery.Apply(rows, new() { StockLevel = MaterialStockLevel.UnknownCapacity }).Single().Key);
    }

    [Test] public void QuantitiesGradesAndRatiosSortNumericallyInBothDirections()
    {
        var ascending = MaterialWarehouseQuery.Apply(Stocks, new() { Sort = MaterialSort.Quantity });
        Check.That(ascending.Select(m => m.Owned).SequenceEqual(new[] { 0, 6, 9, 20, 40, 81, 150 }));
        var descending = MaterialWarehouseQuery.Apply(Stocks, new() { Sort = MaterialSort.Quantity, Descending = true });
        Check.That(descending.Select(m => m.Owned).SequenceEqual(new[] { 150, 81, 40, 20, 9, 6, 0 }));
        Check.Equal(5, MaterialWarehouseQuery.Apply(Stocks, new() { Sort = MaterialSort.Grade, Descending = true }).First().Grade);
        var filled = MaterialWarehouseQuery.Apply(Stocks, new() { Sort = MaterialSort.Fill, Descending = true });
        Check.That(filled.Select(m => m.Key).SequenceEqual(new[] { "selenium", "conductivecomponents", "encoded", "nickel", "chemical", "arsenic", "unknown" }));
        foreach (var sort in new[] { MaterialSort.Fill, MaterialSort.RemainingCapacity })
            foreach (var direction in new[] { false, true })
                Check.Equal("unknown", MaterialWarehouseQuery.Apply(Stocks, new() { Sort = sort, Descending = direction }).Last().Key);
        Check.Equal("selenium", MaterialWarehouseQuery.Apply(Stocks, new() { Sort = MaterialSort.RemainingCapacity }).First().Key);
        Check.Equal("nickel", MaterialWarehouseQuery.Apply(Stocks, new() { Sort = MaterialSort.RemainingCapacity, Descending = true }).First().Key);
    }

    [Test] public void DefaultOrderGroupsCategoriesAndKeepsTiesStable()
    {
        var first = MaterialWarehouseQuery.Apply(Stocks, new());
        Check.That(first.Select(m => m.Key).SequenceEqual(new[] { "selenium", "arsenic", "nickel", "chemical", "conductivecomponents", "encoded", "unknown" }));
        var reversed = MaterialWarehouseQuery.Apply(Stocks.Reverse(), new());
        Check.That(first.SequenceEqual(reversed));
        Check.Equal("Arsenic", MaterialWarehouseQuery.Apply(Stocks, new() { Sort = MaterialSort.Name }).First().Name);
        Check.Equal("Unknown Material", MaterialWarehouseQuery.Apply(Stocks, new() { Sort = MaterialSort.Name, Descending = true }).First().Name);
    }

    [Test] public void ChecklistUsesCurrentStockInsteadOfStaleOwnedCounts()
    {
        MaterialNeed[] needs = [new("NICKEL", "Nickel", 30, 0),
            new("conductivecomponents", "Conductive Components", 60, 999),
            new("CONDUCTIVECOMPONENTS", "Conductive Components", 40, 999), new("arsenic", "Arsenic", 0, 0)];
        Check.Equal("conductivecomponents", MaterialWarehouseQuery.Apply(Stocks, new() { Checklist = MaterialChecklistFilter.Missing }, needs).Single().Key);
        Check.Equal("nickel", MaterialWarehouseQuery.Apply(Stocks, new() { Checklist = MaterialChecklistFilter.Ready }, needs).Single().Key);
        Check.Equal(2, MaterialWarehouseQuery.Apply(Stocks, new() { Checklist = MaterialChecklistFilter.Tracked }, needs).Count);
        Check.Equal("conductivecomponents", MaterialWarehouseQuery.Apply(Stocks, new() { Sort = MaterialSort.Shortage, Descending = true }, needs).First().Key);
        Check.Equal(0, MaterialWarehouseQuery.Apply(Stocks, new() { Checklist = MaterialChecklistFilter.Tracked }, []).Count);
    }

    [Test] public void InvalidRangesReturnActionableValidationAndNoResults()
    {
        MaterialWarehouseFilter[] invalid =
        [
            new() { MinimumGrade = 4, MaximumGrade = 2 },
            new() { MinimumQuantity = 50, MaximumQuantity = 10 },
            new() { MinimumQuantity = -1 }, new() { MaximumQuantity = .5 },
            new() { MinimumQuantity = double.PositiveInfinity }
        ];
        foreach (var filter in invalid)
        {
            Check.That(filter.ValidationMessage.Length > 0);
            Check.Equal(0, MaterialWarehouseQuery.Apply(Stocks, filter).Count);
        }
        Check.Equal("", new MaterialWarehouseFilter { MaximumGrade = 3, MinimumQuantity = 0 }.ValidationMessage);
        Check.That(MaterialWarehouseQuery.Apply(Stocks, new() { MaximumGrade = 3 }).All(m => m.Grade is > 0 and <= 3));
    }

    [Test] public void LiveUpdatesReorderExistingRowsAndRemoveNewlyCoveredShortages()
    {
        var live = new LiveCollection<MaterialLiveRow, MaterialStock, string>(m => m.Key, m => new(m));
        MaterialWarehouseFilter filter = new() { Sort = MaterialSort.Quantity, Descending = true };
        live.Apply(MaterialWarehouseQuery.Apply(Stocks, filter));
        var nickel = live.Single(m => m.Key == "nickel");
        var changed = Stocks.Select(m => m.Key == "nickel" ? m with { Owned = 200 } : m).ToArray();
        var delta = live.Apply(MaterialWarehouseQuery.Apply(changed, filter));
        Check.That(ReferenceEquals(nickel, live.First()));
        Check.Equal(200, nickel.Owned); Check.Equal(0, delta.Added + delta.Removed);
        MaterialNeed[] needs = [new("nickel", "Nickel", 100, 0)];
        Check.Equal(1, MaterialWarehouseQuery.Apply(Stocks, new() { Checklist = MaterialChecklistFilter.Missing }, needs).Count);
        Check.Equal(0, MaterialWarehouseQuery.Apply(changed, new() { Checklist = MaterialChecklistFilter.Missing }, needs).Count);
    }
}