9ae7b88b89
Fuse the standalone ship-class designer (Phases 17/18) into a sidebar calculator: live mass/speed/attack/defence/bombing results, a planet build-rate readout, single-target goal-seek, a modernization-cost mode, and auto reach circles on the map for the selected planet. pkg/calc becomes the single source for the new math (no mirroring): extract BombingPower from the engine model and the per-turn ship-production loop from controller.ProduceShip into pkg/calc (engine now delegates), and add inverse goal-seek solvers in pkg/calc/solve.go. Thin-bridge the combat, planet-build, and solver functions through ui/core/calc + ui/wasm and rebuild core.wasm. Remove the standalone designer view/route; the ship-classes table and the view/bottom menus open the calculator via a shared request store. Docs: rewrite ui/PLAN.md Phase 30, adjust Phase 34 (realistic forecast + CAP/COL ownership), add ui/docs/calculator-ux.md, extend calc-bridge.md, fix navigation.md; remove ui/CALCULATOR.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
58 lines
1.5 KiB
Go
58 lines
1.5 KiB
Go
package calc_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
source "galaxy/calc"
|
|
bridge "galaxy/core/calc"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestShipBuildCostParity(t *testing.T) {
|
|
t.Parallel()
|
|
cases := []struct {
|
|
name string
|
|
shipMass, material, resources float64
|
|
}{
|
|
{"material_covers_mass", 5, 10, 0.5},
|
|
{"material_short", 10, 3, 0.5},
|
|
{"no_material", 4, 0, 0.5},
|
|
{"zero_resources_guard", 10, 3, 0},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
want := source.ShipBuildCost(c.shipMass, c.material, c.resources)
|
|
got := bridge.ShipBuildCost(c.shipMass, c.material, c.resources)
|
|
assert.Equal(t, want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestProduceShipsInTurnParity(t *testing.T) {
|
|
t.Parallel()
|
|
cases := []struct {
|
|
name string
|
|
productionAvailable, material, resources, shipMass float64
|
|
}{
|
|
{"ample_material", 100, 100, 10, 1},
|
|
{"farmed_partial", 114, 0, 0.5, 10},
|
|
{"no_production", 0, 50, 10, 5},
|
|
{"zero_ship_mass", 100, 50, 10, 0},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
wantShips, wantMat, wantUsed, wantProg := source.ProduceShipsInTurn(
|
|
c.productionAvailable, c.material, c.resources, c.shipMass)
|
|
gotShips, gotMat, gotUsed, gotProg := bridge.ProduceShipsInTurn(
|
|
c.productionAvailable, c.material, c.resources, c.shipMass)
|
|
assert.Equal(t, wantShips, gotShips)
|
|
assert.Equal(t, wantMat, gotMat)
|
|
assert.Equal(t, wantUsed, gotUsed)
|
|
assert.Equal(t, wantProg, gotProg)
|
|
})
|
|
}
|
|
}
|