Skip to content

Commit

Permalink
feat: move to our own JumpGate type rather than OpenAPI's
Browse files Browse the repository at this point in the history
  • Loading branch information
eseidel committed Feb 18, 2024
1 parent 6c02d41 commit 3acee0c
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 105 deletions.
4 changes: 2 additions & 2 deletions packages/cli/bin/systems_interesting.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ Future<void> command(FileSystem fs, ArgResults argResults) async {
}
logger.info('of ${interestingSystemSymbols.length} interesting systems.');

final reachableJumpGateRecords = jumpGateCache.values.where(
final reachableJumpGates = jumpGateCache.values.where(
(record) => reachableSystems.contains(record.waypointSymbol.system),
);
// These are not necessarily reachable (the jump gate on either side might
// be under construction).
final connectedSystemSymbols = reachableJumpGateRecords
final connectedSystemSymbols = reachableJumpGates
.map((record) => record.connectedSystemSymbols)
.expand((e) => e)
.toSet();
Expand Down
110 changes: 14 additions & 96 deletions packages/cli/lib/cache/jump_gate_cache.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,79 +2,12 @@ import 'package:cli/cache/caches.dart';
import 'package:cli/cache/json_list_store.dart';
import 'package:cli/net/queries.dart';
import 'package:collection/collection.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
import 'package:types/types.dart';

/// A cached JumpGate value.
@immutable
class JumpGateRecord extends Equatable {
/// Creates a new JumpGateRecord.
const JumpGateRecord({
required this.waypointSymbol,
required this.connections,
required this.timestamp,
});

/// Creates a new JumpGateRecord from a JumpGate.
factory JumpGateRecord.fromJumpGate(
WaypointSymbol waypointSymbol,
JumpGate jumpGate,
DateTime now,
) {
return JumpGateRecord(
connections: jumpGate.connections.map(WaypointSymbol.fromString).toSet(),
timestamp: now,
waypointSymbol: waypointSymbol,
);
}

/// Creates a new JumpGateRecord from JSON.
factory JumpGateRecord.fromJson(Map<String, dynamic> json) {
return JumpGateRecord(
connections: (json['connections'] as List<dynamic>)
.map((dynamic e) => e as String)
.map(WaypointSymbol.fromJson)
.toSet(),
timestamp: DateTime.parse(json['timestamp'] as String),
waypointSymbol: WaypointSymbol.fromJson(json['waypointSymbol'] as String),
);
}

/// The waypoint symbol.
final WaypointSymbol waypointSymbol;

/// The last time this record was updated.
final DateTime timestamp;

/// The connections for this jump gate.
final Set<WaypointSymbol> connections;

/// The connected system symbols.
Set<SystemSymbol> get connectedSystemSymbols =>
connections.map((e) => e.system).toSet();

/// Converts this object to JumpGate model object.
JumpGate toJumpGate() => JumpGate(
symbol: waypointSymbol.waypoint,
connections: connections.map((e) => e.toString()).sorted(),
);

@override
List<Object?> get props => [waypointSymbol, timestamp, connections];

/// Converts this object to a JSON encodable object.
Map<String, dynamic> toJson() => <String, dynamic>{
'timestamp': timestamp.toIso8601String(),
'connections': connections.map((e) => e.toJson()).sorted(),
'waypointSymbol': waypointSymbol.toJson(),
};
}

/// A cached of JumpGate connections.
/// Connections are not necessarily functional, you have to check
/// the ConstructionCache to see if they are under construction.
class JumpGateCache extends JsonListStore<JumpGateRecord> {
class JumpGateCache extends JsonListStore<JumpGate> {
/// Creates a new JumpGate cache.
JumpGateCache(
super.records, {
Expand All @@ -87,10 +20,10 @@ class JumpGateCache extends JsonListStore<JumpGateRecord> {
FileSystem fs, {
String path = defaultCacheFilePath,
}) {
final records = JsonListStore.loadRecords<JumpGateRecord>(
final records = JsonListStore.loadRecords<JumpGate>(
fs,
path,
JumpGateRecord.fromJson,
JumpGate.fromJson,
) ??
[];
return JumpGateCache(records, fs: fs, path: path);
Expand All @@ -100,28 +33,28 @@ class JumpGateCache extends JsonListStore<JumpGateRecord> {
static const String defaultCacheFilePath = 'data/jump_gates.json';

/// The JumpGate values.
List<JumpGateRecord> get values => records;
List<JumpGate> get values => records;

/// The number of waypoints in the cache.
int get waypointCount => values.length;

/// Updates a [JumpGate] in the cache.
void updateJumpGate(JumpGateRecord jumpGateRecord) {
void updateJumpGate(JumpGate jumpGate) {
final index = records.indexWhere(
(record) => record.waypointSymbol == jumpGateRecord.waypointSymbol,
(record) => record.waypointSymbol == jumpGate.waypointSymbol,
);

if (index >= 0) {
records[index] = jumpGateRecord;
records[index] = jumpGate;
} else {
records.add(jumpGateRecord);
records.add(jumpGate);
}

save();
}

/// Gets all jump gates for the given system.
Iterable<JumpGateRecord> recordsForSystem(SystemSymbol systemSymbol) {
Iterable<JumpGate> recordsForSystem(SystemSymbol systemSymbol) {
return values
.where((record) => record.waypointSymbol.hasSystem(systemSymbol));
}
Expand All @@ -130,26 +63,14 @@ class JumpGateCache extends JsonListStore<JumpGateRecord> {
Set<WaypointSymbol>? connectionsForSymbol(WaypointSymbol waypointSymbol) =>
recordForSymbol(waypointSymbol)?.connections;

/// Gets the JumpGateRecord for the given waypoint symbol.
JumpGateRecord? recordForSymbol(WaypointSymbol waypointSymbol) =>
/// Gets the JumpGate for the given waypoint symbol.
JumpGate? recordForSymbol(WaypointSymbol waypointSymbol) =>
values.firstWhereOrNull(
(record) => record.waypointSymbol == waypointSymbol,
);

/// Returns the age of the cache for a given waypoint.
Duration? cacheAgeFor(
WaypointSymbol waypointSymbol, {
DateTime Function() getNow = defaultGetNow,
}) {
final record = recordForSymbol(waypointSymbol);
if (record == null) {
return null;
}
return getNow().difference(record.timestamp);
}

/// Gets the JumpGate for the given waypoint symbol.
Future<JumpGateRecord> getOrFetch(
Future<JumpGate> getOrFetch(
Api api,
WaypointSymbol waypointSymbol, {
DateTime Function() getNow = defaultGetNow,
Expand All @@ -159,10 +80,7 @@ class JumpGateCache extends JsonListStore<JumpGateRecord> {
return cached;
}
final jumpGate = await getJumpGate(api, waypointSymbol);

final record =
JumpGateRecord.fromJumpGate(waypointSymbol, jumpGate, getNow());
updateJumpGate(record);
return record;
updateJumpGate(jumpGate);
return jumpGate;
}
}
4 changes: 2 additions & 2 deletions packages/cli/lib/idle_queue.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ class IdleQueue {
/// Queue jump gate connections for fetching.
// TODO(eseidel): Jump gate construction completion should call this.
void queueJumpGateConnections(
JumpGateRecord jumpGateRecord, {
JumpGate JumpGate, {
required int jumpDistance,
}) {
for (final connection in jumpGateRecord.connections) {
for (final connection in JumpGate.connections) {
_queueJumpGate(connection, jumpDistance: jumpDistance);
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/lib/net/queries.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Future<Shipyard> getShipyard(Api api, WaypointSymbol waypointSymbol) async {
Future<JumpGate> getJumpGate(Api api, WaypointSymbol waypointSymbol) async {
final response = await api.systems
.getJumpGate(waypointSymbol.systemString, waypointSymbol.waypoint);
return response!.data;
return JumpGate.fromOpenApi(response!.data);
}

/// Fetches Market for a given Waypoint.
Expand Down
3 changes: 1 addition & 2 deletions packages/cli/test/nav/system_connectivity_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@ void main() {
final fs = MemoryFileSystem.test();
final a = WaypointSymbol.fromString('X-A-A');
final b = WaypointSymbol.fromString('X-B-B');
final now = DateTime(2021);
final constructionSnapshot = _MockConstructionSnapshot();
when(() => constructionSnapshot.isUnderConstruction(a)).thenReturn(false);
final jumpGateCache = JumpGateCache(
[
JumpGateRecord(waypointSymbol: a, connections: {b}, timestamp: now),
JumpGate(waypointSymbol: a, connections: {b}),
],
fs: fs,
);
Expand Down
6 changes: 4 additions & 2 deletions packages/types/lib/api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import 'dart:math';
import 'package:collection/collection.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
import 'package:openapi/api.dart' hide Agent, System, SystemWaypoint, Waypoint;
import 'package:openapi/api.dart'
hide Agent, JumpGate, System, SystemWaypoint, Waypoint;
import 'package:types/mount.dart';

export 'package:openapi/api.dart' hide Agent, System, SystemWaypoint, Waypoint;
export 'package:openapi/api.dart'
hide Agent, JumpGate, System, SystemWaypoint, Waypoint;

/// The default implementation of getNow for production.
/// Used for tests for overriding the current time.
Expand Down
61 changes: 61 additions & 0 deletions packages/types/lib/src/jump_gate.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import 'package:collection/collection.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
import 'package:openapi/api.dart' as openapi;
import 'package:types/types.dart';

/// A cached JumpGate value.
@immutable
class JumpGate extends Equatable {
/// Creates a new JumpGate.
const JumpGate({
required this.waypointSymbol,
required this.connections,
});

/// Creates a new from a JumpGate.
factory JumpGate.fromOpenApi(openapi.JumpGate jumpGate) {
return JumpGate(
waypointSymbol: WaypointSymbol.fromJson(jumpGate.symbol),
connections: jumpGate.connections.map(WaypointSymbol.fromString).toSet(),
);
}

/// Creates a new JumpGate from JSON.
factory JumpGate.fromJson(Map<String, dynamic> json) {
return JumpGate(
connections: (json['connections'] as List<dynamic>)
.map((dynamic e) => e as String)
.map(WaypointSymbol.fromJson)
.toSet(),
waypointSymbol: WaypointSymbol.fromJson(json['waypointSymbol'] as String),
);
}

/// The waypoint symbol.
final WaypointSymbol waypointSymbol;

/// The connections for this jump gate.
final Set<WaypointSymbol> connections;

/// The connected system symbols.
Set<SystemSymbol> get connectedSystemSymbols =>
connections.map((e) => e.system).toSet();

/// Converts this object to an OpenAPI object.
openapi.JumpGate toOpenApi() {
return openapi.JumpGate(
symbol: waypointSymbol.toJson(),
connections: connections.map((e) => e.toJson()).toList(),
);
}

@override
List<Object?> get props => [waypointSymbol, connections];

/// Converts this object to a JSON encodable object.
Map<String, dynamic> toJson() => <String, dynamic>{
'connections': connections.map((e) => e.toJson()).sorted(),
'waypointSymbol': waypointSymbol.toJson(),
};
}
1 change: 1 addition & 0 deletions packages/types/lib/types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export 'mount.dart';
export 'route.dart';
export 'shipyard_listing.dart';
export 'shipyard_price.dart';
export 'src/jump_gate.dart';
export 'survey.dart';
export 'system.dart';
export 'trading.dart';
Expand Down

0 comments on commit 3acee0c

Please sign in to comment.