Skip to content

Commit 787f103

Browse files
Fix learn from your mistakes loading again after analysis.
1 parent a14fbd1 commit 787f103

File tree

2 files changed

+60
-17
lines changed

2 files changed

+60
-17
lines changed

lib/src/model/analysis/retro_controller.dart

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -113,21 +113,6 @@ class RetroController extends AsyncNotifier<RetroState> with EngineEvaluationMix
113113
_root = _game.makeTree();
114114

115115
if (_game.serverAnalysis == null) {
116-
await serverAnalysisService.requestAnalysis(options.id);
117-
118-
_serverAnalysisCompleter.future.timeout(
119-
kMaxWaitForServerAnalysis,
120-
onTimeout: () {
121-
_logger.warning(
122-
'Server analysis did not finish within $kMaxWaitForServerAnalysis for game ${options.id}',
123-
);
124-
state = AsyncError(
125-
Exception('Server analysis did not finish within $kMaxWaitForServerAnalysis'),
126-
StackTrace.current,
127-
);
128-
},
129-
);
130-
131116
final retroState = RetroState(
132117
serverAnalysisAvailable: false,
133118
mistakes: const IList.empty(),
@@ -148,9 +133,58 @@ class RetroController extends AsyncNotifier<RetroState> with EngineEvaluationMix
148133

149134
state = AsyncValue.data(retroState);
150135

136+
// Attach listener BEFORE possibly requesting analysis,
137+
// so we don't miss the first progress event.
151138
serverAnalysisService.lastAnalysisEvent.addListener(_listenToServerAnalysisEvents);
152139

153-
return retroState;
140+
// Reuse an already available event immediately if it belongs to this game.
141+
final existingEvent = serverAnalysisService.lastAnalysisEvent.value;
142+
if (existingEvent != null && existingEvent.$1 == options.id) {
143+
ServerAnalysisService.mergeOngoingAnalysis(_root, existingEvent.$2.tree);
144+
145+
final progress =
146+
existingEvent.$2.evals.where((e) => e.hasEval).length / _root.mainline.length;
147+
148+
state = AsyncValue.data(
149+
state.requireValue.copyWith(serverAnalysisProgress: progress),
150+
);
151+
152+
if (existingEvent.$2.isAnalysisComplete) {
153+
if (!_serverAnalysisCompleter.isCompleted) {
154+
_serverAnalysisCompleter.complete();
155+
}
156+
157+
state = AsyncData(await _computeMistakes(options.initialSide));
158+
159+
socketClient.firstConnection.then((_) {
160+
requestEval();
161+
});
162+
163+
return state.requireValue;
164+
}
165+
}
166+
167+
// Only request analysis if this exact game is not already being analyzed.
168+
if (serverAnalysisService.currentAnalysis.value != options.id) {
169+
await serverAnalysisService.requestAnalysis(options.id);
170+
}
171+
172+
unawaited(
173+
_serverAnalysisCompleter.future.timeout(
174+
kMaxWaitForServerAnalysis,
175+
onTimeout: () {
176+
_logger.warning(
177+
'Server analysis did not finish within $kMaxWaitForServerAnalysis for game ${options.id}',
178+
);
179+
state = AsyncError(
180+
Exception('Server analysis did not finish within $kMaxWaitForServerAnalysis'),
181+
StackTrace.current,
182+
);
183+
},
184+
),
185+
);
186+
187+
return state.requireValue;
154188
}
155189

156190
state = AsyncData(await _computeMistakes(options.initialSide));

lib/src/model/analysis/server_analysis_service.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ class ServerAnalysisService {
4949
/// This will return a future that completes when the server analysis is
5050
/// launched (but not when it is finished).
5151
Future<void> requestAnalysis(GameId id, [Side? side]) async {
52+
// If we are already listening for analysis updates of this exact game,
53+
// don't tear everything down and reconnect.
54+
if (_currentAnalysis.value == id &&
55+
_socketSubscription != null &&
56+
_analysisCompleter != null) {
57+
return;
58+
}
59+
5260
_cancelAnalysis();
5361

5462
final uri = Uri(path: '/watch/$id/${side?.name ?? Side.white}/v6');
@@ -95,6 +103,7 @@ class ServerAnalysisService {
95103
// of analyses is reached.
96104
if (e.statusCode == 400) {
97105
debugPrint('Analysis already requested for game $id');
106+
_currentAnalysis.value = id.gameId;
98107
} else {
99108
debugPrint('ServerException requesting server analysis: $e');
100109
_cancelAnalysis();
@@ -199,4 +208,4 @@ class CurrentAnalysis extends Notifier<GameId?> {
199208
state = gameId;
200209
}
201210
}
202-
}
211+
}

0 commit comments

Comments
 (0)