Skip to content

Commit

Permalink
Move to MineJob
Browse files Browse the repository at this point in the history
Prompted me to test more of advanceMinerBehavior
  • Loading branch information
eseidel committed Jul 30, 2023
1 parent 9a86cab commit 1ea5313
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 85 deletions.
13 changes: 7 additions & 6 deletions packages/cli/lib/behavior/buy_ship.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,16 @@ Future<PurchaseShip201ResponseData> doBuyShipJob(
disable: DisableBehavior.allShips,
);
final maxMedianMultiplier = maxMedianShipPriceMultipler;
final maxPrice = medianPrice * maxMedianMultiplier;
final maxPrice = (medianPrice * maxMedianMultiplier).round();

// We should only try to buy new ships if we have enough money to keep
// our traders trading.
final budget = agentCache.agent.credits - minimumCreditsForTrading;
final credits = budget;
jobAssert(
credits >= maxPrice,
'Can not buy $shipType, budget $credits < max price $maxPrice.',
'Can not buy $shipType, budget ${creditsString(credits)} '
'< max price ${creditsString(maxPrice)}.',
const Duration(minutes: 10),
disable: DisableBehavior.allShips,
);
Expand All @@ -66,7 +67,7 @@ Future<PurchaseShip201ResponseData> doBuyShipJob(
jobAssert(
recentPrice <= maxPrice,
'Failed to buy $shipType at $shipyardSymbol, '
'$recentPriceString > max price $maxPrice.',
'$recentPriceString > max price ${creditsString(maxPrice)}.',
const Duration(minutes: 10),
);

Expand Down Expand Up @@ -196,9 +197,9 @@ Future<DateTime?> advanceBuyShip(
final maxPrice = (medianPrice * maxMedianMultipler).toInt();
jobAssert(
recentPrice <= maxPrice,
'Failed to buy $shipType at ${currentWaypoint.symbol}, '
'$recentPriceString > max price $maxPrice.',
const Duration(minutes: 30),
'Failed to buy $shipType at $shipyardSymbol, '
'$recentPriceString > max price ${creditsString(maxPrice)}.',
const Duration(minutes: 10),
);

// Do we need to catch exceptions about insufficient credits?
Expand Down
14 changes: 5 additions & 9 deletions packages/cli/lib/behavior/central_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:math';
import 'package:cli/behavior/behavior.dart';
import 'package:cli/behavior/buy_ship.dart';
import 'package:cli/behavior/deliver.dart';
import 'package:cli/behavior/miner.dart';
import 'package:cli/cache/caches.dart';
import 'package:cli/logger.dart';
import 'package:cli/market_scan.dart';
Expand Down Expand Up @@ -1098,23 +1099,18 @@ class CentralCommand {
return 0.9;
}

/// Returns the symbol of the nearest mine to the given [ship].
// This should probably return a "mining plan" instead, which includes
// what type of mining this is, where the mine is, where the markets are?
WaypointSymbol? mineSymbolForShip(
/// Returns the mining plan for the given [ship].
MineJob mineJobForShip(
SystemsCache systemsCache,
AgentCache agentCache,
Ship ship,
) {
final hq = agentCache.agent.headquartersSymbol;
final hqSystemSymbol = hq.systemSymbol;
final systemSymbol = hqSystemSymbol;
// final systemSymbol = ship.systemSymbol;
// Return the nearest mine to the ship for now?
final systemWaypoints = systemsCache.waypointsInSystem(systemSymbol);
return systemWaypoints
.firstWhereOrNull((w) => w.canBeMined)
?.waypointSymbol;
final mine = systemWaypoints.firstWhere((w) => w.canBeMined).waypointSymbol;
return MineJob(mine: mine, market: mine);
// If the ship is in a system without a mine go to the HQ?

// final mine = await nearestMineWithGoodMining(
Expand Down
39 changes: 18 additions & 21 deletions packages/cli/lib/behavior/miner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,18 @@ int maxExtractedUnits(Ship ship) {
return min(laserStrength + variance, ship.cargo.capacity);
}

/// Extract resources from a mine.
class MineJob {
/// Create a new mine job.
MineJob({required this.mine, required this.market});

/// The mine to extract from.
final WaypointSymbol mine;

/// The market to sell to.
final WaypointSymbol market;
}

/// Apply the miner behavior to the ship.
Future<DateTime?> advanceMiner(
Api api,
Expand Down Expand Up @@ -249,11 +261,11 @@ Future<DateTime?> advanceMiner(
);
}

final mineSymbol = assertNotNull(
centralCommand.mineSymbolForShip(caches.systems, caches.agent, ship),
'No desired mine for ship.',
const Duration(hours: 1),
);
final mineJob =
centralCommand.mineJobForShip(caches.systems, caches.agent, ship);
final mineSymbol = mineJob.mine;
final marketSymbol = mineJob.market;

if (ship.waypointSymbol != mineSymbol) {
return beingNewRouteAndLog(
api,
Expand All @@ -272,21 +284,6 @@ Future<DateTime?> advanceMiner(
const Duration(hours: 1),
);

// This is wrong, we don't know if this market will be able to sell
// the goods we can mine.
final nearestMarket = await nearestWaypointWithMarket(
caches.waypoints,
currentWaypoint,
);
if (nearestMarket == null) {
centralCommand.disableBehaviorForShip(
ship,
'No nearby market for ${waypointDescription(currentWaypoint)}.',
const Duration(hours: 1),
);
return null;
}

// Both surveying and mining require being undocked.
await undockIfNeeded(api, caches.ships, ship);

Expand All @@ -295,7 +292,7 @@ Future<DateTime?> advanceMiner(
caches.marketPrices,
caches.surveys,
surveyWaypointSymbol: currentWaypoint.waypointSymbol,
nearbyMarketSymbol: nearestMarket.waypointSymbol,
nearbyMarketSymbol: marketSymbol,
minimumSurveys: centralCommand.minimumSurveys,
percentileThreshold: centralCommand.surveyPercentileThreshold,
);
Expand Down
13 changes: 3 additions & 10 deletions packages/cli/lib/behavior/surveyor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,9 @@ Future<DateTime?> advanceSurveyor(
}) async {
final currentWaypoint = await caches.waypoints.waypoint(ship.waypointSymbol);

final mineSymbol =
centralCommand.mineSymbolForShip(caches.systems, caches.agent, ship);
if (mineSymbol == null) {
centralCommand.disableBehaviorForShip(
ship,
'No desired mine for ship.',
const Duration(hours: 1),
);
return null;
}
final mineJob =
centralCommand.mineJobForShip(caches.systems, caches.agent, ship);
final mineSymbol = mineJob.mine;
if (ship.waypointSymbol != mineSymbol) {
return beingNewRouteAndLog(
api,
Expand Down
96 changes: 59 additions & 37 deletions packages/cli/test/behavior/miner_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,39 @@ import 'package:cli/logger.dart';
import 'package:mocktail/mocktail.dart';
import 'package:test/test.dart';

class _MockBehaviorState extends Mock implements BehaviorState {}

class _MockShipNav extends Mock implements ShipNav {}
class _MockAgentCache extends Mock implements AgentCache {}

class _MockApi extends Mock implements Api {}

class _MockAgentCache extends Mock implements AgentCache {}
class _MockBehaviorState extends Mock implements BehaviorState {}

class _MockShip extends Mock implements Ship {}
class _MockCaches extends Mock implements Caches {}

class _MockSystemsCache extends Mock implements SystemsCache {}
class _MockCentralCommand extends Mock implements CentralCommand {}

class _MockMarketCache extends Mock implements MarketCache {}
class _MockLogger extends Mock implements Logger {}

class _MockTransactionLog extends Mock implements TransactionLog {}
class _MockMarketCache extends Mock implements MarketCache {}

class _MockMarketPrices extends Mock implements MarketPrices {}

class _MockShip extends Mock implements Ship {}

class _MockShipCache extends Mock implements ShipCache {}

class _MockShipNav extends Mock implements ShipNav {}

class _MockSurveyData extends Mock implements SurveyData {}

class _MockWaypointCache extends Mock implements WaypointCache {}
class _MockSystemsCache extends Mock implements SystemsCache {}

class _MockWaypoint extends Mock implements Waypoint {}
class _MockTransactionLog extends Mock implements TransactionLog {}

class _MockLogger extends Mock implements Logger {}
class _MockWaypoint extends Mock implements Waypoint {}

class _MockCentralCommand extends Mock implements CentralCommand {}
class _MockWaypointCache extends Mock implements WaypointCache {}

class _MockCaches extends Mock implements Caches {}
class _MockFleetApi extends Mock implements FleetApi {}

void main() {
test('surveyWorthMining with no surveys', () async {
Expand Down Expand Up @@ -193,16 +197,17 @@ void main() {

final now = DateTime(2021);
DateTime getNow() => now;
when(() => ship.symbol).thenReturn('S');
const shipSymbol = ShipSymbol('S', 1);
when(() => ship.symbol).thenReturn(shipSymbol.symbol);
when(() => ship.nav).thenReturn(shipNav);
when(() => shipNav.status).thenReturn(ShipNavStatus.IN_ORBIT);
final symbol = WaypointSymbol.fromString('S-A-W');
when(() => shipNav.waypointSymbol).thenReturn(symbol.waypoint);
when(() => shipNav.systemSymbol).thenReturn(symbol.system);
when(() => ship.mounts).thenReturn([]);

when(() => centralCommand.mineSymbolForShip(systemsCache, agentCache, ship))
.thenReturn(symbol);
when(() => centralCommand.mineJobForShip(systemsCache, agentCache, ship))
.thenReturn(MineJob(mine: symbol, market: symbol));

final waypoint = _MockWaypoint();
when(() => waypoint.symbol).thenReturn(symbol.waypoint);
Expand All @@ -213,32 +218,49 @@ void main() {
registerFallbackValue(symbol);
when(() => waypointCache.waypoint(any()))
.thenAnswer((_) => Future.value(waypoint));
registerFallbackValue(symbol.systemSymbol);
when(
() => waypointCache.waypointsInJumpRadius(
startSystem: any(named: 'startSystem'),
maxJumps: any(named: 'maxJumps'),
),
).thenAnswer((_) => Stream.fromIterable([waypoint]));

when(
() => systemsCache.systemSymbolsInJumpRadius(
startSystem: any(named: 'startSystem'),
maxJumps: any(named: 'maxJumps'),
),
).thenReturn([(symbol.systemSymbol, 0)]);

when(
() => waypointCache.waypointsInSystem(any()),
).thenAnswer((_) => Future.value([waypoint]));

when(() => marketCache.marketsInSystem(any()))
.thenAnswer((_) => Stream.fromIterable([]));
final shipCache = _MockShipCache();
when(() => shipCache.ships).thenReturn([ship]);
when(() => caches.ships).thenReturn(shipCache);

final shipCargo = ShipCargo(capacity: 60, units: 0);
when(() => ship.cargo).thenReturn(shipCargo);
final state = _MockBehaviorState();

when(() => centralCommand.minimumSurveys).thenReturn(10);
when(() => centralCommand.surveyPercentileThreshold).thenReturn(0.9);
when(() => surveyData.recentSurveysAtWaypoint(symbol, count: 100))
.thenReturn([]);

final fleetApi = _MockFleetApi();
when(() => api.fleet).thenReturn(fleetApi);
when(
() => fleetApi.extractResources(
shipSymbol.symbol,
),
).thenAnswer(
(_) => Future.value(
ExtractResources201Response(
data: ExtractResources201ResponseData(
cooldown: Cooldown(
shipSymbol: shipSymbol.symbol,
remainingSeconds: 0,
expiration: now,
totalSeconds: 0,
),
extraction: Extraction(
shipSymbol: shipSymbol.symbol,
yield_: ExtractionYield(
symbol: TradeSymbol.DIAMONDS,
units: 10,
),
),
cargo: shipCargo,
),
),
),
);

final logger = _MockLogger();
final waitUntil = await runWithLogger(
logger,
Expand All @@ -251,7 +273,7 @@ void main() {
getNow: getNow,
),
);
expect(waitUntil, isNull);
expect(waitUntil, DateTime(2021));
});

test('maxExtractedUnits', () {
Expand Down
5 changes: 3 additions & 2 deletions packages/cli/test/behavior/surveyor_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:cli/behavior/behavior.dart';
import 'package:cli/behavior/central_command.dart';
import 'package:cli/behavior/miner.dart';
import 'package:cli/behavior/surveyor.dart';
import 'package:cli/cache/caches.dart';
import 'package:cli/logger.dart';
Expand Down Expand Up @@ -71,8 +72,8 @@ void main() {
)
]);

when(() => centralCommand.mineSymbolForShip(systemsCache, agentCache, ship))
.thenReturn(symbol);
when(() => centralCommand.mineJobForShip(systemsCache, agentCache, ship))
.thenReturn(MineJob(mine: symbol, market: symbol));

final waypoint = _MockWaypoint();
when(() => waypoint.symbol).thenReturn(symbol.waypoint);
Expand Down

0 comments on commit 1ea5313

Please sign in to comment.