139 lines
4.4 KiB
Go
139 lines
4.4 KiB
Go
package agent
|
|
|
|
import (
|
|
"fmt"
|
|
"slices"
|
|
|
|
"git.adyxax.org/adyxax/spacetraders/golang/pkg/model"
|
|
)
|
|
|
|
type TradeGoodNotFoundError struct{}
|
|
|
|
func (err *TradeGoodNotFoundError) Error() string {
|
|
return "trade good not found"
|
|
}
|
|
|
|
func (a *agent) buyTradeGood(ship *model.Ship, tradeGoodToBuy string) error {
|
|
if ship.Cargo.Units == ship.Cargo.Capacity {
|
|
return nil
|
|
}
|
|
// list markets would sell our goods
|
|
markets, err := a.listMarketsInSystem(ship.Nav.SystemSymbol)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to list markets in system %s: %w", ship.Nav.SystemSymbol, err)
|
|
}
|
|
markets = slices.DeleteFunc(markets, func(market model.Market) bool {
|
|
for _, item := range market.Exports {
|
|
if item.Symbol == tradeGoodToBuy {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
})
|
|
if len(markets) == 0 {
|
|
return &TradeGoodNotFoundError{}
|
|
}
|
|
// find the closest place to buy TODO
|
|
waypoint, err := a.client.GetWaypoint(ship.Nav.WaypointSymbol, a.db)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get nav waypoint %s: %w", ship.Nav.WaypointSymbol, err)
|
|
}
|
|
waypoints := make([]model.Waypoint, 0)
|
|
for i := range markets {
|
|
waypoint, err := a.client.GetWaypoint(markets[i].Symbol, a.db)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get waypoint %s: %w", markets[i].Symbol, err)
|
|
}
|
|
waypoints = append(waypoints, *waypoint)
|
|
}
|
|
sortByDistanceFrom(waypoint, waypoints)
|
|
// Go there and refresh our market data
|
|
if err := a.client.Navigate(ship, waypoints[0].Symbol, a.db); err != nil {
|
|
return fmt.Errorf("failed to navigate to %s: %w", waypoints[0].Symbol, err)
|
|
}
|
|
market, err := a.client.GetMarket(waypoints[0].Symbol, a.db)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get market %s: %w", waypoints[0].Symbol, err)
|
|
}
|
|
// Buy until full
|
|
for _, tradeGood := range market.TradeGoods {
|
|
if tradeGood.Type == "EXPORT" && tradeGood.Symbol == tradeGoodToBuy {
|
|
for ship.Cargo.Units < ship.Cargo.Capacity {
|
|
increment := min(ship.Cargo.Capacity-ship.Cargo.Units, tradeGood.TradeVolume)
|
|
if err := a.client.Purchase(ship, tradeGoodToBuy, increment, a.db); err != nil {
|
|
return fmt.Errorf("failed to purchase %d units of %s: %w", increment, tradeGoodToBuy, err)
|
|
}
|
|
}
|
|
break
|
|
}
|
|
}
|
|
return a.buyTradeGood(ship, tradeGoodToBuy)
|
|
}
|
|
|
|
func (a *agent) sellEverythingExcept(ship *model.Ship, keep string) error {
|
|
// First lets see what we need to sell
|
|
cargo := ship.Cargo.Inventory
|
|
cargo = slices.DeleteFunc(cargo, func(inventory model.Inventory) bool {
|
|
return inventory.Symbol == keep
|
|
})
|
|
if len(cargo) == 0 {
|
|
return nil
|
|
}
|
|
// list markets would buy our goods
|
|
markets, err := a.listMarketsInSystem(ship.Nav.SystemSymbol)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to list markets in system %s: %w", ship.Nav.SystemSymbol, err)
|
|
}
|
|
markets = slices.DeleteFunc(markets, func(market model.Market) bool {
|
|
for _, item := range market.Imports {
|
|
for _, cargoItem := range cargo {
|
|
if item.Symbol == cargoItem.Symbol {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
})
|
|
if len(markets) == 0 {
|
|
return nil
|
|
}
|
|
// find the closest place to sell something TODO
|
|
waypoint, err := a.client.GetWaypoint(ship.Nav.WaypointSymbol, a.db)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get nav waypoint %s: %w", ship.Nav.WaypointSymbol, err)
|
|
}
|
|
waypoints := make([]model.Waypoint, 0)
|
|
for i := range markets {
|
|
waypoint, err := a.client.GetWaypoint(markets[i].Symbol, a.db)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get waypoint %s: %w", markets[i].Symbol, err)
|
|
}
|
|
waypoints = append(waypoints, *waypoint)
|
|
}
|
|
sortByDistanceFrom(waypoint, waypoints)
|
|
// Go there and refresh our market data
|
|
if err := a.client.Navigate(ship, waypoints[0].Symbol, a.db); err != nil {
|
|
return fmt.Errorf("failed to navigate to %s: %w", waypoints[0].Symbol, err)
|
|
}
|
|
market, err := a.client.GetMarket(waypoints[0].Symbol, a.db)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get market %s: %w", waypoints[0].Symbol, err)
|
|
}
|
|
// sell everything we can
|
|
for _, cargoItem := range cargo {
|
|
units := cargoItem.Units
|
|
for _, tradeGood := range market.TradeGoods {
|
|
if tradeGood.Type == "IMPORT" && tradeGood.Symbol == cargoItem.Symbol {
|
|
for units > 0 {
|
|
increment := min(units, tradeGood.TradeVolume)
|
|
if err := a.client.Sell(ship, cargoItem.Symbol, increment, a.db); err != nil {
|
|
return fmt.Errorf("failed to sell %d units of %s: %w", units, cargoItem.Symbol, err)
|
|
}
|
|
units = units - increment
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return a.sellEverythingExcept(ship, keep)
|
|
}
|