From 312ef2eb5792cd145d6829e2abc017dd304c5819 Mon Sep 17 00:00:00 2001 From: Julien Dessaux Date: Wed, 19 Feb 2025 00:19:58 +0100 Subject: [golang] implement trading and contracting --- golang/pkg/agent/contracting.go | 54 +++++++++---- golang/pkg/agent/trading.go | 139 ++++++++++++++++++++++++++++++++ golang/pkg/agent/utils.go | 18 ++++- golang/pkg/agent/visit.go | 12 ++- golang/pkg/api/contracts.go | 53 +++++++++++- golang/pkg/api/ships.go | 68 ++++++++++++++++ golang/pkg/api/systems.go | 50 ++++++++---- golang/pkg/database/markets.go | 42 ++++++++++ golang/pkg/database/sql/001_trading.sql | 2 - golang/pkg/model/contract.go | 2 +- golang/pkg/model/market.go | 10 +++ golang/pkg/model/trade_good.go | 11 +++ 12 files changed, 422 insertions(+), 39 deletions(-) create mode 100644 golang/pkg/agent/trading.go create mode 100644 golang/pkg/database/markets.go create mode 100644 golang/pkg/model/market.go create mode 100644 golang/pkg/model/trade_good.go (limited to 'golang') diff --git a/golang/pkg/agent/contracting.go b/golang/pkg/agent/contracting.go index 6d67d6d..ecd896a 100644 --- a/golang/pkg/agent/contracting.go +++ b/golang/pkg/agent/contracting.go @@ -15,7 +15,7 @@ func (a *agent) autoContracting(ship *model.Ship) { return } for _, contract := range contracts { - if contract.Fullfilled { + if contract.Fulfilled { continue } now := time.Now() @@ -27,11 +27,17 @@ func (a *agent) autoContracting(ship *model.Ship) { } } a.channel <- fmt.Errorf("negotiating new contracts is not implemented yet") - // TODO - //for { - // negotiate - // runContract - //} + for { + contract, err := a.client.NegotiateContract(ship) + if err != nil { + a.channel <- fmt.Errorf("failed to negotiate contract: %w", err) + return + } + if err := a.runContract(contract, ship); err != nil { + a.channel <- fmt.Errorf("failed to run contract %s: %w", contract.Id, err) + return + } + } } func (a *agent) runContract(contract *model.Contract, ship *model.Ship) error { @@ -51,15 +57,33 @@ func (a *agent) runContract(contract *model.Contract, ship *model.Ship) error { } func (a *agent) runProcurement(contract *model.Contract, ship *model.Ship) error { - deliveryCargo := contract.Terms.Deliver[0].TradeSymbol - deliveryWaypoint, err := a.client.GetWaypoint(contract.Terms.Deliver[0].DestinationSymbol, a.db) - if err != nil { - return fmt.Errorf("failed to get delivery waypoint: %w", err) + if contract.Fulfilled { + return nil + } + deliver := contract.Terms.Deliver[0] + // make sure we are not carrying useless stuff + if err := a.sellEverythingExcept(ship, deliver.TradeSymbol); err != nil { + return fmt.Errorf("failed to sell everything except %s for ship %s: %w", deliver.TradeSymbol, ship.Symbol, err) } - for !contract.Fullfilled { - _ = deliveryCargo - _ = deliveryWaypoint - return fmt.Errorf("not implemented") + // procure the desired goods + if ship.Cargo.Units < min(deliver.UnitsRequired-deliver.UnitsFulfilled, ship.Cargo.Capacity) { + if err := a.buyTradeGood(ship, deliver.TradeSymbol); err != nil { + return fmt.Errorf("failed to buy trade good %s with ship %s: %w", deliver.TradeSymbol, ship.Symbol, err) + } + } + // deliver the goods + if err := a.client.Navigate(ship, deliver.DestinationSymbol, a.db); err != nil { + return fmt.Errorf("failed to navigate to %s: %w", deliver.DestinationSymbol, err) + } + if err := a.client.Deliver(contract, ship, a.db); err != nil { + return fmt.Errorf("failed to deliver: %w", err) + } + deliver = contract.Terms.Deliver[0] + if deliver.UnitsRequired == deliver.UnitsFulfilled { + if err := a.client.Fulfill(contract, a.db); err != nil { + return fmt.Errorf("failed to fulfill: %w", err) + } + return nil } - return fmt.Errorf("not implemented") + return a.runProcurement(contract, ship) } diff --git a/golang/pkg/agent/trading.go b/golang/pkg/agent/trading.go new file mode 100644 index 0000000..e84cef4 --- /dev/null +++ b/golang/pkg/agent/trading.go @@ -0,0 +1,139 @@ +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) +} diff --git a/golang/pkg/agent/utils.go b/golang/pkg/agent/utils.go index 274e973..b274f43 100644 --- a/golang/pkg/agent/utils.go +++ b/golang/pkg/agent/utils.go @@ -40,6 +40,22 @@ func (a *agent) listWaypointsInSystemWithTrait(systemSymbol string, trait string return waypoints, nil } +func (a *agent) listMarketsInSystem(systemSymbol string) ([]model.Market, error) { + waypoints, err := a.listWaypointsInSystemWithTrait(systemSymbol, "MARKETPLACE") + if err != nil { + return nil, fmt.Errorf("failed to list waypoints in system %s with trait MARKETPLACE: %w", systemSymbol, err) + } + var markets []model.Market + for i := range waypoints { + market, err := a.client.GetMarket(waypoints[i].Symbol, a.db) + if err != nil { + return nil, fmt.Errorf("failed to get market %s: %w", waypoints[i].Symbol, err) + } + markets = append(markets, *market) + } + return markets, nil +} + func (a *agent) listShipyardsInSystem(systemSymbol string) ([]model.Shipyard, error) { waypoints, err := a.listWaypointsInSystemWithTrait(systemSymbol, "SHIPYARD") if err != nil { @@ -47,7 +63,7 @@ func (a *agent) listShipyardsInSystem(systemSymbol string) ([]model.Shipyard, er } var shipyards []model.Shipyard for i := range waypoints { - shipyard, err := a.client.GetShipyard(&waypoints[i], a.db) + shipyard, err := a.client.GetShipyard(waypoints[i].Symbol, a.db) if err != nil { return nil, fmt.Errorf("failed to get shipyard %s: %w", waypoints[i].Symbol, err) } diff --git a/golang/pkg/agent/visit.go b/golang/pkg/agent/visit.go index 4d79fef..3004553 100644 --- a/golang/pkg/agent/visit.go +++ b/golang/pkg/agent/visit.go @@ -39,9 +39,17 @@ func (a *agent) visitAllShipyards(ship *model.Ship) error { 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) } - if _, err := a.client.GetShipyard(&waypoints[0], a.db); err != nil { + if _, err := a.client.GetShipyard(waypoints[0].Symbol, a.db); err != nil { return fmt.Errorf("failed to get shipyard %s: %w", waypoints[0].Symbol, err) } - // TODO get market data + // If this waypoint is also a marketplace, get its data + for _, trait := range waypoints[0].Traits { + if trait.Symbol == "MARKETPLACE" { + if _, err := a.client.GetMarket(waypoints[0].Symbol, a.db); err != nil { + return fmt.Errorf("failed to get market %s: %w", waypoints[0].Symbol, err) + } + break + } + } return a.visitAllShipyards(ship) } diff --git a/golang/pkg/api/contracts.go b/golang/pkg/api/contracts.go index 573d938..6a9a28a 100644 --- a/golang/pkg/api/contracts.go +++ b/golang/pkg/api/contracts.go @@ -20,16 +20,65 @@ func (c *Client) Accept(contract *model.Contract, db *database.DB) error { } var response acceptResponse if err := c.Send("POST", &uriRef, nil, &response); err != nil { - return fmt.Errorf("failed to accept contract %s: %w", contract.Id, err) + return fmt.Errorf("failed API request: %w", err) } if err := db.SaveAgent(response.Agent); err != nil { - return fmt.Errorf("failed to accept contract %s: %w", contract.Id, err) + return fmt.Errorf("failed to save agent: %w", err) } contract.Accepted = response.Contract.Accepted contract.Terms = response.Contract.Terms return nil } +func (c *Client) Deliver(contract *model.Contract, ship *model.Ship, db *database.DB) error { + deliver := contract.Terms.Deliver[0] + var units int + for _, cargoItem := range ship.Cargo.Inventory { + if cargoItem.Symbol == deliver.TradeSymbol { + units = min(deliver.UnitsRequired-deliver.UnitsFulfilled, cargoItem.Units) + break + } + } + uriRef := url.URL{Path: path.Join("my/contracts", contract.Id, "deliver")} + type deliverRequest struct { + ShipSymbol string `json:"shipSymbol"` + TradeSymbol string `json:"tradeSymbol"` + Units int `json:"units"` + } + type deliverResponse struct { + Cargo *model.Cargo `json:"cargo"` + Contract *model.Contract `json:"contract"` + } + var response deliverResponse + if err := c.Send("POST", &uriRef, deliverRequest{ship.Symbol, deliver.TradeSymbol, units}, &response); err != nil { + return fmt.Errorf("failed API request: %w", err) + } + ship.Cargo = response.Cargo + contract.Terms = response.Contract.Terms + return nil +} + +func (c *Client) Fulfill(contract *model.Contract, db *database.DB) error { + if contract.Fulfilled { + return nil + } + uriRef := url.URL{Path: path.Join("my/contracts", contract.Id, "fulfill")} + type fulfillResponse struct { + Agent *model.Agent `json:"agent"` + Contract *model.Contract `json:"contract"` + } + var response fulfillResponse + if err := c.Send("POST", &uriRef, nil, &response); err != nil { + return fmt.Errorf("failed API request: %w", err) + } + if err := db.SaveAgent(response.Agent); err != nil { + return fmt.Errorf("failed to save agent: %w", err) + } + contract.Fulfilled = response.Contract.Fulfilled + contract.Terms = response.Contract.Terms + return nil +} + func (c *Client) MyContracts() ([]model.Contract, error) { uriRef := url.URL{Path: "my/contracts"} var contracts []model.Contract diff --git a/golang/pkg/api/ships.go b/golang/pkg/api/ships.go index 67a1ebd..21676d1 100644 --- a/golang/pkg/api/ships.go +++ b/golang/pkg/api/ships.go @@ -68,6 +68,18 @@ func (c *Client) Navigate(s *model.Ship, waypointSymbol string, db *database.DB) return nil } +func (c *Client) NegotiateContract(s *model.Ship) (*model.Contract, error) { + uriRef := url.URL{Path: path.Join("my/ships", s.Symbol, "negotiate", "contract")} + type negotiateResponse struct { + Contract *model.Contract `json:"contract"` + } + var response negotiateResponse + if err := c.Send("POST", &uriRef, nil, &response); err != nil { + return nil, fmt.Errorf("failed API request: %w", err) + } + return response.Contract, nil +} + func (c *Client) orbit(s *model.Ship) error { if s.Nav.Status == "IN_ORBIT" { return nil @@ -84,6 +96,34 @@ func (c *Client) orbit(s *model.Ship) error { return nil } +func (c *Client) Purchase(s *model.Ship, cargoItem string, units int, db *database.DB) error { + if err := c.dock(s); err != nil { + return fmt.Errorf("failed to dock: %w", err) + } + uriRef := url.URL{Path: path.Join("my/ships", s.Symbol, "purchase")} + type purchaseRequest struct { + Symbol string `json:"symbol"` + Units int `json:"units"` + } + type purchaseResponse struct { + Agent *model.Agent `json:"agent"` + Cargo *model.Cargo `json:"cargo"` + Transaction *model.Transaction `json:"transaction"` + } + var response purchaseResponse + if err := c.Send("POST", &uriRef, purchaseRequest{cargoItem, units}, &response); err != nil { + return fmt.Errorf("failed API request: %w", err) + } + if err := db.SaveAgent(response.Agent); err != nil { + return fmt.Errorf("failed to save agent: %w", err) + } + s.Cargo = response.Cargo + if err := db.AppendTransaction(response.Transaction); err != nil { + return fmt.Errorf("failed to append transaction: %w", err) + } + return nil +} + func (c *Client) refuel(s *model.Ship, db *database.DB) error { if s.Fuel.Current == s.Fuel.Capacity { return nil @@ -110,3 +150,31 @@ func (c *Client) refuel(s *model.Ship, db *database.DB) error { } return nil } + +func (c *Client) Sell(s *model.Ship, cargoItem string, units int, db *database.DB) error { + if err := c.dock(s); err != nil { + return fmt.Errorf("failed to dock: %w", err) + } + uriRef := url.URL{Path: path.Join("my/ships", s.Symbol, "sell")} + type sellRequest struct { + Symbol string `json:"symbol"` + Units int `json:"units"` + } + type sellResponse struct { + Agent *model.Agent `json:"agent"` + Cargo *model.Cargo `json:"cargo"` + Transaction *model.Transaction `json:"transaction"` + } + var response sellResponse + if err := c.Send("POST", &uriRef, sellRequest{cargoItem, units}, &response); err != nil { + return fmt.Errorf("failed API request: %w", err) + } + if err := db.SaveAgent(response.Agent); err != nil { + return fmt.Errorf("failed to save agent: %w", err) + } + s.Cargo = response.Cargo + if err := db.AppendTransaction(response.Transaction); err != nil { + return fmt.Errorf("failed to append transaction: %w", err) + } + return nil +} diff --git a/golang/pkg/api/systems.go b/golang/pkg/api/systems.go index 840f32e..58770cb 100644 --- a/golang/pkg/api/systems.go +++ b/golang/pkg/api/systems.go @@ -9,28 +9,31 @@ import ( "git.adyxax.org/adyxax/spacetraders/golang/pkg/model" ) -func (c *Client) GetSystem(symbol string, db *database.DB) (*model.System, error) { - if system, err := db.LoadSystem(symbol); err == nil && system != nil { - return system, nil +func (c *Client) GetMarket(waypointSymbol string, db *database.DB) (*model.Market, error) { + if market, err := db.LoadMarket(waypointSymbol); err == nil && market != nil { + // TODO check last updated time + return market, nil } - uriRef := url.URL{Path: path.Join("systems", symbol)} - var system model.System - if err := c.Send("GET", &uriRef, nil, &system); err != nil { + systemSymbol := WaypointSymbolToSystemSymbol(waypointSymbol) + uriRef := url.URL{Path: path.Join("systems", systemSymbol, "waypoints", waypointSymbol, "market")} + var market model.Market + if err := c.Send("GET", &uriRef, nil, &market); err != nil { return nil, fmt.Errorf("failed API request: %w", err) } - if err := db.SaveSystem(&system); err != nil { - return nil, fmt.Errorf("failed to save system %s: %w", system.Symbol, err) + if err := db.SaveMarket(&market); err != nil { + return nil, fmt.Errorf("failed to save market %s: %w", market.Symbol, err) } - return &system, nil + return &market, nil } -func (c *Client) GetShipyard(waypoint *model.Waypoint, db *database.DB) (*model.Shipyard, error) { - if shipyard, err := db.LoadShipyard(waypoint.Symbol); err == nil && shipyard != nil && +func (c *Client) GetShipyard(waypointSymbol string, db *database.DB) (*model.Shipyard, error) { + if shipyard, err := db.LoadShipyard(waypointSymbol); err == nil && shipyard != nil && (shipyard.Ships != nil) { // TODO || !IsThereAShipAtWaypoint(waypoint)) { // TODO check last updated time return shipyard, nil } - uriRef := url.URL{Path: path.Join("systems", waypoint.SystemSymbol, "waypoints", waypoint.Symbol, "shipyard")} + systemSymbol := WaypointSymbolToSystemSymbol(waypointSymbol) + uriRef := url.URL{Path: path.Join("systems", systemSymbol, "waypoints", waypointSymbol, "shipyard")} var shipyard model.Shipyard if err := c.Send("GET", &uriRef, nil, &shipyard); err != nil { return nil, fmt.Errorf("failed API request: %w", err) @@ -41,13 +44,28 @@ func (c *Client) GetShipyard(waypoint *model.Waypoint, db *database.DB) (*model. return &shipyard, nil } -func (c *Client) GetWaypoint(symbol string, db *database.DB) (*model.Waypoint, error) { - if waypoint, err := db.LoadWaypoint(symbol); err == nil && waypoint != nil { +func (c *Client) GetSystem(systemSymbol string, db *database.DB) (*model.System, error) { + if system, err := db.LoadSystem(systemSymbol); err == nil && system != nil { + return system, nil + } + uriRef := url.URL{Path: path.Join("systems", systemSymbol)} + var system model.System + if err := c.Send("GET", &uriRef, nil, &system); err != nil { + return nil, fmt.Errorf("failed API request: %w", err) + } + if err := db.SaveSystem(&system); err != nil { + return nil, fmt.Errorf("failed to save system %s: %w", system.Symbol, err) + } + return &system, nil +} + +func (c *Client) GetWaypoint(waypointSymbol string, db *database.DB) (*model.Waypoint, error) { + if waypoint, err := db.LoadWaypoint(waypointSymbol); err == nil && waypoint != nil { // TODO check last updated time return waypoint, nil } - systemSymbol := WaypointSymbolToSystemSymbol(symbol) - uriRef := url.URL{Path: path.Join("systems", systemSymbol, "waypoints", symbol)} + systemSymbol := WaypointSymbolToSystemSymbol(waypointSymbol) + uriRef := url.URL{Path: path.Join("systems", systemSymbol, "waypoints", waypointSymbol)} var waypoint model.Waypoint if err := c.Send("GET", &uriRef, nil, &waypoint); err != nil { return nil, fmt.Errorf("failed API request: %w", err) diff --git a/golang/pkg/database/markets.go b/golang/pkg/database/markets.go new file mode 100644 index 0000000..11498d2 --- /dev/null +++ b/golang/pkg/database/markets.go @@ -0,0 +1,42 @@ +package database + +import ( + "database/sql" + "encoding/json" + "fmt" + "time" + + "git.adyxax.org/adyxax/spacetraders/golang/pkg/model" +) + +func (db *DB) LoadMarket(symbol string) (*model.Market, error) { + var buf []byte + if err := db.QueryRow(`SELECT data FROM markets WHERE data->>'symbol' = ?;`, symbol).Scan(&buf); err != nil { + return nil, fmt.Errorf("failed to query row: %w", err) + } + var market model.Market + if err := json.Unmarshal(buf, &market); err != nil { + return nil, fmt.Errorf("failed to unmarshal market: %w", err) + } + return &market, nil +} + +func (db *DB) SaveMarket(market *model.Market) error { + data, err := json.Marshal(market) + if err != nil { + return fmt.Errorf("failed to marshal market: %w", err) + } + _, err = db.Exec( + `INSERT INTO markets(data, updated) + VALUES (json(:data), :updated) + ON CONFLICT DO UPDATE SET data = :data, updated = :updated + WHERE data->>'symbol' = :symbol;`, + sql.Named("data", data), + sql.Named("symbol", market.Symbol), + sql.Named("updated", time.Now()), + ) + if err != nil { + return fmt.Errorf("failed to exec: %w", err) + } + return nil +} diff --git a/golang/pkg/database/sql/001_trading.sql b/golang/pkg/database/sql/001_trading.sql index 89dd77c..e218962 100644 --- a/golang/pkg/database/sql/001_trading.sql +++ b/golang/pkg/database/sql/001_trading.sql @@ -4,11 +4,9 @@ CREATE TABLE agents ( ); CREATE TABLE markets ( id INTEGER PRIMARY KEY, - systemSymbol TEXT NOT NULL, data JSON NOT NULL, updated DATE NOT NULL ); -CREATE INDEX markets_systemSymbol on markets (systemSymbol); CREATE UNIQUE INDEX markets_data_symbol on markets(json_extract(data, '$.symbol')); CREATE TABLE shipyards ( id INTEGER PRIMARY KEY, diff --git a/golang/pkg/model/contract.go b/golang/pkg/model/contract.go index 24ed403..9d9c7bd 100644 --- a/golang/pkg/model/contract.go +++ b/golang/pkg/model/contract.go @@ -7,7 +7,7 @@ type Contract struct { DeadlineToAccept time.Time `json:"deadlineToAccept"` Expiration time.Time `json:"expiration"` FactionSymbol string `json:"factionSymbol"` - Fullfilled bool `json:"fulfilled"` + Fulfilled bool `json:"fulfilled"` Id string `json:"id"` Terms *Terms `json:"terms"` Type string `json:"type"` diff --git a/golang/pkg/model/market.go b/golang/pkg/model/market.go new file mode 100644 index 0000000..6c11386 --- /dev/null +++ b/golang/pkg/model/market.go @@ -0,0 +1,10 @@ +package model + +type Market struct { + Exchange []Common `json:"exchange"` + Exports []Common `json:"exports"` + Imports []Common `json:"imports"` + Symbol string `json:"symbol"` + TradeGoods []TradeGood `json:"tradeGoods"` + Transactions []Transaction `json:"transactions"` +} diff --git a/golang/pkg/model/trade_good.go b/golang/pkg/model/trade_good.go new file mode 100644 index 0000000..602f667 --- /dev/null +++ b/golang/pkg/model/trade_good.go @@ -0,0 +1,11 @@ +package model + +type TradeGood struct { + Activity string `json:"activity"` + PurchasePrice int `json:"purchasePrice"` + SellPrice int `json:"sellPrice"` + Supply string `json:"supply"` + Symbol string `json:"symbol"` + TradeVolume int `json:"tradeVolume"` + Type string `json:"type"` +} -- cgit v1.2.3