diff --git a/packages/cli/bin/contracts.dart b/packages/cli/bin/contracts.dart index 214c215a..b1010722 100644 --- a/packages/cli/bin/contracts.dart +++ b/packages/cli/bin/contracts.dart @@ -1,15 +1,14 @@ import 'package:cli/behavior/trader.dart'; import 'package:cli/cache/contract_snapshot.dart'; -import 'package:cli/cache/market_prices.dart'; import 'package:cli/cli.dart'; import 'package:cli/printing.dart'; -void printContracts( +Future printContracts( + Database db, String label, - List contracts, - MarketPriceSnapshot marketPrices, { + List contracts, { required bool describeContracts, -}) { +}) async { if (contracts.isEmpty) { return; } @@ -21,36 +20,35 @@ void printContracts( for (final contract in contracts) { logger ..info(contractDescription(contract)) - ..info(describeExpectedContractProfit(marketPrices, contract)); + ..info(await describeExpectedContractProfit(db, contract)); } } Future command(FileSystem fs, Database db, ArgResults argResults) async { final printAll = argResults['all'] as bool; final contractSnapshot = await ContractSnapshot.load(db); - final marketPrices = await MarketPriceSnapshot.load(db); - printContracts( + await printContracts( + db, 'completed', contractSnapshot.completedContracts, - marketPrices, describeContracts: printAll, ); - printContracts( + await printContracts( + db, 'expired', contractSnapshot.expiredContracts, - marketPrices, describeContracts: printAll, ); - printContracts( + await printContracts( + db, 'active', contractSnapshot.activeContracts, - marketPrices, describeContracts: true, ); - printContracts( + await printContracts( + db, 'unaccepted', contractSnapshot.unacceptedContracts, - marketPrices, describeContracts: true, ); } diff --git a/packages/cli/lib/behavior/trader.dart b/packages/cli/lib/behavior/trader.dart index 2883d038..5d1bd9bd 100644 --- a/packages/cli/lib/behavior/trader.dart +++ b/packages/cli/lib/behavior/trader.dart @@ -513,16 +513,16 @@ Future return response; } -int? _expectedContractProfit( +Future _expectedContractProfit( + Database db, Contract contract, - MarketPriceSnapshot marketPrices, -) { +) async { // Add up the total expected outlay. final terms = contract.terms; final tradeSymbols = terms.deliver.map((d) => d.tradeSymbolObject).toSet(); final medianPricesBySymbol = {}; for (final tradeSymbol in tradeSymbols) { - final medianPrice = marketPrices.medianPurchasePrice(tradeSymbol); + final medianPrice = await db.medianPurchasePrice(tradeSymbol); if (medianPrice == null) { return null; } @@ -540,11 +540,11 @@ int? _expectedContractProfit( } /// Returns a string describing the expected profit of a contract. -String describeExpectedContractProfit( - MarketPriceSnapshot marketPrices, +Future describeExpectedContractProfit( + Database db, Contract contract, -) { - final profit = _expectedContractProfit(contract, marketPrices); +) async { + final profit = await _expectedContractProfit(db, contract); final profitString = profit == null ? 'unknown' : creditsString(profit); return 'Expected profit: $profitString'; } @@ -567,7 +567,7 @@ Future acceptContractsIfNeeded( ship, shipCache, ); - shipInfo(ship, describeExpectedContractProfit(marketPrices, contract)); + shipInfo(ship, await describeExpectedContractProfit(db, contract)); return null; } final unacceptedContracts = await db.unacceptedContracts(); diff --git a/packages/db/lib/db.dart b/packages/db/lib/db.dart index 4978b400..5f015cec 100644 --- a/packages/db/lib/db.dart +++ b/packages/db/lib/db.dart @@ -413,6 +413,15 @@ class Database { return queryOne(query, marketPriceFromColumnMap); } + Future medianPurchasePrice(TradeSymbol tradeSymbol) async { + final query = medianPurchasePriceQuery(tradeSymbol); + final result = await connection.execute( + pg.Sql.named(query.fmtString), + parameters: query.parameters, + ); + return result[0][0] as int?; + } + /// Get all shipyard prices from the database. Future> allShipyardPrices() async { return queryMany(allShipyardPricesQuery(), shipyardPriceFromColumnMap); diff --git a/packages/db/lib/src/market_price.dart b/packages/db/lib/src/market_price.dart index d2f39f33..95711e33 100644 --- a/packages/db/lib/src/market_price.dart +++ b/packages/db/lib/src/market_price.dart @@ -64,6 +64,17 @@ Query marketPriceQuery(WaypointSymbol waypoint, TradeSymbol trade) => Query( }, ); +/// Query to get the median purchase price for a trade symbol. +Query medianPurchasePriceQuery(TradeSymbol trade) => Query( + ''' + SELECT percentile_disc(0.5) + WITHIN GROUP (ORDER BY purchase_price) + FROM market_price_ + WHERE trade_symbol = @trade; + ''', + parameters: {'trade': trade.toJson()}, + ); + /// Build a market price from a column map. MarketPrice marketPriceFromColumnMap(Map values) { return MarketPrice(