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<MyInventoryItem> 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<MyInventoryItem> First=new List<MyInventoryItem>(),Second=new List<MyInventoryItem>(),Port=new List<MyInventoryItem>(),Buffer=new List<MyInventoryItem>();
public readonly Stub<IMyConveyorSorter> Sorter;
public Rig()
{
R.Task();R.Hardware.InventoryBlocks.Clear();
Add<IMyShipDrill>(First);Add<IMyShipDrill>(Second);Add<IMyShipConnector>(Port);
Sorter=Add<IMyConveyorSorter>(Buffer).Set("Enabled",true).Set("DrainAll",true);
R.Hardware.SetSampling(true);
}
Stub<T> Add<T>(List<MyInventoryItem> items) where T:class,IMyTerminalBlock
{
var inventory=new Stub<IMyInventory>().Set("CurrentMass",(MyFixedPoint)0).Set("CurrentVolume",(MyFixedPoint)0).Set("MaxVolume",(MyFixedPoint)100)
.Method("get_ItemCount",a=>items.Count).Method("GetItems",a=>{((List<MyInventoryItem>)a[0]).AddRange(items);return null;});
var block=new Stub<T>().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<IMyCubeGrid>().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");
}
}
}
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<MyInventoryItem> 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<MyInventoryItem> First=new List<MyInventoryItem>(),Second=new List<MyInventoryItem>(),Port=new List<MyInventoryItem>(),Buffer=new List<MyInventoryItem>();
public readonly Stub<IMyConveyorSorter> Sorter;
public Rig()
{
R.Task();R.Hardware.InventoryBlocks.Clear();
Add<IMyShipDrill>(First);Add<IMyShipDrill>(Second);Add<IMyShipConnector>(Port);
Sorter=Add<IMyConveyorSorter>(Buffer).Set("Enabled",true).Set("DrainAll",true);
R.Hardware.SetSampling(true);
}
Stub<T> Add<T>(List<MyInventoryItem> items) where T:class,IMyTerminalBlock
{
var inventory=new Stub<IMyInventory>().Set("CurrentMass",(MyFixedPoint)0).Set("CurrentVolume",(MyFixedPoint)0).Set("MaxVolume",(MyFixedPoint)100)
.Method("get_ItemCount",a=>items.Count).Method("GetItems",a=>{((List<MyInventoryItem>)a[0]).AddRange(items);return null;});
var block=new Stub<T>().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<IMyCubeGrid>().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");
}
}
}