Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,9 @@ class LevelSolverService {
(level.gridWidth + level.gridHeight + vine.orderedPath.length + 10)
.clamp(50, 300);

// Create a map for O(1) vine lookup instead of iterating level.vines repeatedly
final vineMap = {for (final v in level.vines) v.id: v};

for (int step = 0; step < maxCheckDistance; step++) {
// Simulate one step of movement
final newPositions = _simulateVineMovementFromPositions(
Expand All @@ -486,7 +489,8 @@ class LevelSolverService {
for (final otherId in activeVineIds) {
if (otherId == vineId) continue;

final otherVine = level.vines.firstWhere((v) => v.id == otherId);
final otherVine = vineMap[otherId];
if (otherVine == null) continue;
for (final cell in otherVine.orderedPath) {
if (cell['x'] == newPos['x'] && cell['y'] == newPos['y']) {
return -(distance +
Expand Down
112 changes: 112 additions & 0 deletions apps/parable-bloom/test/services/level_solver_service_perf_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:parable_bloom/features/game/domain/entities/level_data.dart';
import 'package:parable_bloom/features/game/domain/services/level_solver_service.dart';

void main() {
group('LevelSolverService Performance', () {
late LevelSolverService solver;

setUp(() {
solver = LevelSolverService();
});

test('isVineBlockedInState performance', () {
final vines = <VineData>[];
final activeVineIds = <String>[];

// Create a grid of vines
for (int i = 0; i < 50; i++) {
final id = 'vine_$i';
activeVineIds.add(id);

// Make long vines to increase M
final path = <Map<String, int>>[];
for (int j = 0; j < 20; j++) {
path.add({'x': i, 'y': j});
}

vines.add(VineData(
id: id,
headDirection: 'up',
orderedPath: path,
));
}

final level = LevelData(
id: '1',
name: 'Perf Test Level',
difficulty: 'hard',
gridWidth: 100,
gridHeight: 100,
vines: vines,
maxMoves: 100,
minMoves: 1,
complexity: 'high',
grace: 0,
mask: MaskData(mode: 'none', points: []),
);

final stopwatch = Stopwatch()..start();

// Run it a few times to get a measurable duration (kept small so
// this benchmark stays within CI time budgets).
for (int iter = 0; iter < 10; iter++) {
for (final vineId in activeVineIds) {
solver.isVineBlockedInState(level, vineId, activeVineIds);
}
}

stopwatch.stop();
print('isVineBlockedInState Time: ${stopwatch.elapsedMilliseconds} ms');
});

test('getDistanceToBlocker performance', () {
final vines = <VineData>[];
final activeVineIds = <String>[];

// Create a grid of vines
for (int i = 0; i < 50; i++) {
final id = 'vine_$i';
activeVineIds.add(id);

// Make long vines to increase M
final path = <Map<String, int>>[];
for (int j = 0; j < 20; j++) {
path.add({'x': i, 'y': j});
}

vines.add(VineData(
id: id,
headDirection: 'up',
orderedPath: path,
));
}

final level = LevelData(
id: '1',
name: 'Perf Test Level',
difficulty: 'hard',
gridWidth: 100,
gridHeight: 100,
vines: vines,
maxMoves: 100,
minMoves: 1,
complexity: 'high',
grace: 0,
mask: MaskData(mode: 'none', points: []),
);

final stopwatch = Stopwatch()..start();

// Run it many times to get a measurable duration
for (int iter = 0; iter < 10; iter++) {
for (final vineId in activeVineIds) {
solver.getDistanceToBlocker(level, vineId, activeVineIds);
}
}

stopwatch.stop();
print('getDistanceToBlocker Time: ${stopwatch.elapsedMilliseconds} ms');
});
});
}
Loading