using System; using System.Collections.Generic; using System.Reflection; using Sandbox.ModAPI.Ingame; using VRage; using VRage.Game.ModAPI.Ingame; using Xunit; using P=AutoMiningScript.Program; namespace AutoMiningScript.Tests { public class SorterSamplingTests { static readonly BindingFlags Private=BindingFlags.Instance|BindingFlags.NonPublic; static void Call(object target,string name)=>target.GetType().GetMethod(name,Private).Invoke(target,null); static void Put(List items,double amount) { items.Clear();if(amount<=0)return;object value=default(MyInventoryItem); typeof(MyInventoryItem).GetField("Type").SetValue(value,MyItemType.MakeOre("Stone")); typeof(MyInventoryItem).GetField("Amount").SetValue(value,(MyFixedPoint)amount); items.Add((MyInventoryItem)value); } sealed class Rig { public readonly MinerStateTests.MinerRig R=new MinerStateTests.MinerRig(); public readonly List First=new List(),Second=new List(),Port=new List(),Buffer=new List(); public readonly Stub Sorter; public Rig() { R.Task();R.Hardware.InventoryBlocks.Clear(); Add(First);Add(Second);Add(Port); Sorter=Add(Buffer).Set("Enabled",true).Set("DrainAll",true); R.Hardware.SetSampling(true); } Stub Add(List items) where T:class,IMyTerminalBlock { var inventory=new Stub().Set("CurrentMass",(MyFixedPoint)0).Set("CurrentVolume",(MyFixedPoint)0).Set("MaxVolume",(MyFixedPoint)100) .Method("get_ItemCount",a=>items.Count).Method("GetItems",a=>{((List)a[0]).AddRange(items);return null;}); var block=new Stub().Set("CubeGrid",R.Program.Me.CubeGrid).Set("HasInventory",true).Set("InventoryCount",1).Method("GetInventory",a=>inventory.Value); R.Hardware.InventoryBlocks.Add(block.Value);return block; } public void Amounts(double first,double second,double buffer) {Put(First,first);Put(Second,second);Put(Buffer,buffer);} public void Scan(P.FlightState state=P.FlightState.Drilling) {R.Program.Now+=.5;R.Resources.Update(.5,state,0,0);} public void Sample()=>Call(R.Miner,"SampleOre"); public void Baseline()=>Call(R.Miner,"ResetSample"); } [Fact] public void ActualDrillToSorterTransfersPreserveOreAndAllowAConfirmedDiscovery() { var r=new Rig(); // Real miner 7, 2026-09-15: inventory-03 JSONL lines 348/349 and 351/352. // Two drill buffers transfer to central sorter 95026802382736041. r.Amounts(93.481720,424.960224,45.786960);r.Scan(P.FlightState.Align);r.Baseline(); Assert.Equal(564.228904,r.R.Resources.Ores["Stone"],5); r.Amounts(93.481720,0,470.747184);r.Scan(); Assert.Equal(564.228904,r.R.Resources.OreAmount,5);Assert.True(r.R.Resources.SamplingValid); r.Sample();r.Sample();Assert.DoesNotContain(r.R.Sent,p=>p.Kind=="RESULT"); r.Amounts(704.451512,1232.909312,470.747184);r.Scan(); Assert.Equal(2408.108008,r.R.Resources.Ores["Stone"],5);Assert.True(r.R.Resources.SamplingValid); r.Sample();Assert.DoesNotContain(r.R.Sent,p=>p.Kind=="RESULT"); r.Amounts(678.375836,0,1729.732172);r.Scan(); Assert.Equal(2408.108008,r.R.Resources.Ores["Stone"],5);Assert.True(r.R.Resources.SamplingValid); r.Sample();var report=P.JobReport.FromIni(Assert.Single(r.R.Sent,p=>p.Kind=="RESULT").Body); Assert.Equal("Discovery",report.Outcome);Assert.Equal("Stone",report.Ore); Assert.True(r.Sorter.Value.Enabled);Assert.True(r.Sorter.Value.DrainAll); } [Fact] public void ActualLossFromASorterStillInvalidatesAndLatchesTheSample() { var r=new Rig();r.Amounts(10,0,100);r.Scan();r.Baseline(); r.Amounts(10,0,80);r.Scan();Assert.False(r.R.Resources.SamplingValid); r.Amounts(10,0,100);r.Scan();Assert.False(r.R.Resources.SamplingValid); r.Sample();Assert.DoesNotContain(r.R.Sent,p=>p.Kind=="RESULT"); Assert.True((bool)typeof(P.MinerController).GetField("invalidSample",Private).GetValue(r.R.Miner)); r.R.Resources.ResetSampleValidation();r.Scan();Assert.True(r.R.Resources.SamplingValid); } [Fact] public void PreexistingSorterOreIsInTheAlignmentBaselineAndCannotBecomeANewDiscovery() { var r=new Rig();r.Amounts(0,0,100);r.Scan(P.FlightState.Align);r.Baseline(); r.Amounts(100,0,0);r.Scan();Assert.True(r.R.Resources.SamplingValid); r.Sample();r.Sample();Assert.DoesNotContain(r.R.Sent,p=>p.Kind=="RESULT"); Assert.Equal(100,r.R.Resources.Ores["Stone"]); } [Fact] public void AForeignSorterCannotBeCountedAsLocalMinedOre() { var r=new Rig();r.Amounts(0,0,100); r.Sorter.Set("CubeGrid",new Stub().Set("EntityId",999L).Value); r.Scan();Assert.Empty(r.R.Resources.Ores);Assert.False(r.R.Resources.SamplingValid); r.Sample();Assert.DoesNotContain(r.R.Sent,p=>p.Kind=="RESULT"); } } }