package main import "testing" func TestNewWayfarerShipInitialState(t *testing.T) { start := WayfarerSystemID{Galaxy: 0, Index: 0} s := NewWayfarerShip(start) if s.Credits != 1000 { t.Errorf("ожидался стартовый капитал 1000, получено %v", s.Credits) } if s.CurrentSystem != start { t.Errorf("корабль должен был начать в стартовой системе") } if !s.Visited[start] { t.Errorf("стартовая система должна была отметиться как посещённая") } if s.CargoUsed() != 0 || s.CargoFree() != s.CargoCapacity { t.Errorf("трюм новой партии должен быть пуст") } } func TestBuyAndSellCommodity(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) before := s.Credits if err := s.BuyCommodity(0, 5, 10); err != nil { t.Fatalf("неожиданная ошибка покупки: %v", err) } if s.Cargo[0] != 5 { t.Errorf("ожидалось 5 единиц товара в трюме, получено %d", s.Cargo[0]) } if s.Credits != before-50 { t.Errorf("ожидалось списание 50 кредитов, получено %v (было %v)", s.Credits, before) } if err := s.SellCommodity(0, 5, 8); err != nil { t.Fatalf("неожиданная ошибка продажи: %v", err) } if s.Cargo[0] != 0 { t.Errorf("трюм должен был опустеть после продажи всего") } if s.Credits != before-50+40 { t.Errorf("ожидалось начисление 40 кредитов от продажи, получено %v", s.Credits) } } func TestBuyCommodityInsufficientFunds(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) s.Credits = 5 if err := s.BuyCommodity(0, 10, 10); err != errWayfarerInsufficientFunds { t.Errorf("ожидалась ошибка нехватки средств, получено: %v", err) } } func TestBuyCommodityCargoFull(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) s.Credits = 1_000_000 if err := s.BuyCommodity(0, s.CargoCapacity+1, 1); err != errWayfarerCargoFull { t.Errorf("ожидалась ошибка переполнения трюма, получено: %v", err) } } func TestSellCommodityNotEnoughInCargo(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) if err := s.SellCommodity(0, 1, 10); err != errWayfarerNoCargo { t.Errorf("ожидалась ошибка нехватки товара в трюме, получено: %v", err) } } func TestBuyCommodityTracksAverageCostBasis(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) s.Credits = 1_000_000 if err := s.BuyCommodity(0, 10, 20); err != nil { t.Fatalf("неожиданная ошибка: %v", err) } if s.CargoCostBasis[0] != 20 { t.Errorf("после первой покупки средняя цена должна быть 20, получено %v", s.CargoCostBasis[0]) } // вторая партия по другой цене — средняя должна пересчитаться // как взвешенное среднее: (10*20 + 10*40) / 20 = 30 if err := s.BuyCommodity(0, 10, 40); err != nil { t.Fatalf("неожиданная ошибка: %v", err) } if s.CargoCostBasis[0] != 30 { t.Errorf("ожидалась средняя цена 30 после второй закупки, получено %v", s.CargoCostBasis[0]) } } func TestSellCommodityResetsCostBasisWhenCargoEmpty(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) s.Credits = 1_000_000 s.BuyCommodity(0, 5, 20) if err := s.SellCommodity(0, 3, 25); err != nil { t.Fatalf("неожиданная ошибка: %v", err) } if s.CargoCostBasis[0] != 20 { t.Errorf("частичная продажа не должна менять среднюю цену оставшегося груза, получено %v", s.CargoCostBasis[0]) } if err := s.SellCommodity(0, 2, 25); err != nil { t.Fatalf("неожиданная ошибка: %v", err) } if s.CargoCostBasis[0] != 0 { t.Errorf("после полной продажи средняя цена должна была сброситься в 0, получено %v", s.CargoCostBasis[0]) } } func TestRefuelClampsAtCapacity(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) s.Fuel = s.FuelCapacity - 1 s.Credits = 1_000_000 if err := s.Refuel(100, 1); err != nil { t.Fatalf("неожиданная ошибка дозаправки: %v", err) } if s.Fuel != s.FuelCapacity { t.Errorf("топливо должно было ограничиться ёмкостью бака, получено %v", s.Fuel) } } func TestRepairClampsAtMaxHull(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) s.Hull = s.MaxHull - 1 s.Credits = 1_000_000 if err := s.Repair(100, 1); err != nil { t.Fatalf("неожиданная ошибка ремонта: %v", err) } if s.Hull != s.MaxHull { t.Errorf("прочность должна была ограничиться максимумом, получено %d", s.Hull) } } func TestJumpToConsumesFuelByDistance(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{Galaxy: 0, Index: 0}) target := WayfarerSystemID{Galaxy: 0, Index: 1} before := s.Fuel if err := s.JumpTo(target); err != nil { t.Fatalf("неожиданная ошибка прыжка: %v", err) } if s.Fuel >= before { t.Errorf("топливо должно было уменьшиться после прыжка") } if s.CurrentSystem != target { t.Errorf("корабль должен был оказаться в целевой системе") } if !s.Visited[target] { t.Errorf("целевая система должна была отметиться как посещённая") } } func TestJumpToSameSystemFails(t *testing.T) { start := WayfarerSystemID{Galaxy: 0, Index: 0} s := NewWayfarerShip(start) if err := s.JumpTo(start); err != errWayfarerSameSystem { t.Errorf("ожидалась ошибка прыжка в ту же систему, получено: %v", err) } } func TestJumpToOutOfRangeFails(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{Galaxy: 0, Index: 0}) s.Fuel = 0.0001 far := WayfarerSystemID{Galaxy: 0, Index: 1} err := s.JumpTo(far) if err != errWayfarerOutOfRange { far = WayfarerSystemID{Galaxy: 0, Index: 50} s2 := NewWayfarerShip(WayfarerSystemID{Galaxy: 0, Index: 0}) s2.Fuel = 0.0001 if err2 := s2.JumpTo(far); err2 != errWayfarerOutOfRange { t.Fatalf("ожидалась ошибка нехватки топлива, получено: %v (и %v)", err, err2) } } } func TestPilotRatingIncreasesWithKills(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) initial := s.PilotRating() s.Kills = 500 if s.PilotRating() == initial { t.Errorf("рейтинг должен был вырасти после 500 побед") } } func TestNetWorthIncludesCargoValue(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) baseline := s.NetWorth() s.Cargo[0] = 10 if s.NetWorth() <= baseline { t.Errorf("состояние должно было вырасти с добавлением груза в трюм") } }