package calc_test import ( "math" "testing" "galaxy/calc" ) func TestShipBuildCost(t *testing.T) { cases := []struct { name string shipMass float64 material float64 resources float64 want float64 }{ { name: "material exceeds mass: no farming needed", shipMass: 5, material: 10, resources: 0.5, want: 50, // ShipProductionCost(5) = 50; matFarm = 0. }, { name: "material equal to mass: no farming needed", shipMass: 5, material: 5, resources: 0.5, want: 50, }, { name: "material short of mass: farming term added", shipMass: 10, material: 3, resources: 0.5, want: 114, // 100 + (7 / 0.5). }, { name: "no material at all: full mass farmed", shipMass: 4, material: 0, resources: 0.5, want: 48, // 40 + (4 / 0.5). }, { name: "zero resources collapses farming term to zero", shipMass: 10, material: 3, resources: 0, want: 100, // 100 + 0; resources == 0 is a pathological guard. }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { got := calc.ShipBuildCost(tc.shipMass, tc.material, tc.resources) if math.Abs(got-tc.want) > 1e-9 { t.Errorf("ShipBuildCost(%v, %v, %v) = %v, want %v", tc.shipMass, tc.material, tc.resources, got, tc.want) } }) } } func TestProduceShipsInTurn(t *testing.T) { cases := []struct { name string productionAvailable, material, resources, shipMass float64 wantShips uint wantMaterialLeft, wantProductionUsed, wantProgress float64 }{ { name: "ample material: ten ships, no farming", productionAvailable: 100, material: 100, resources: 10, shipMass: 1, wantShips: 10, wantMaterialLeft: 90, wantProductionUsed: 0, wantProgress: 0, }, { name: "no material: partial progress on a farmed ship", productionAvailable: 114, material: 0, resources: 0.5, shipMass: 10, // ShipBuildCost(10,0,0.5) = 100 + 10/0.5 = 120; 114/120 = 0.95. wantShips: 0, wantMaterialLeft: 0, wantProductionUsed: 114, wantProgress: 0.95, }, { name: "no production available leaves the stockpile", productionAvailable: 0, material: 50, resources: 10, shipMass: 5, wantShips: 0, wantMaterialLeft: 50, wantProductionUsed: 0, wantProgress: 0, }, { name: "zero ship mass is guarded against an endless loop", productionAvailable: 100, material: 50, resources: 10, shipMass: 0, wantShips: 0, wantMaterialLeft: 50, wantProductionUsed: 0, wantProgress: 0, }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { ships, materialLeft, productionUsed, progress := calc.ProduceShipsInTurn( tc.productionAvailable, tc.material, tc.resources, tc.shipMass) if ships != tc.wantShips { t.Errorf("ships = %d, want %d", ships, tc.wantShips) } if math.Abs(materialLeft-tc.wantMaterialLeft) > 1e-9 { t.Errorf("materialLeft = %v, want %v", materialLeft, tc.wantMaterialLeft) } if math.Abs(productionUsed-tc.wantProductionUsed) > 1e-9 { t.Errorf("productionUsed = %v, want %v", productionUsed, tc.wantProductionUsed) } if math.Abs(progress-tc.wantProgress) > 1e-9 { t.Errorf("progress = %v, want %v", progress, tc.wantProgress) } }) } }