Merge branch '54-as-a-user-i-want-to-save-and-load-cell-configurations' into 'master'
Resolve "As a user, I want to save and load cell configurations." Closes #54 See merge request marty.oehme/cellular-automata!17
This commit is contained in:
commit
d79aceeebf
6 changed files with 60 additions and 10 deletions
|
@ -29,8 +29,12 @@ class ControlsComponent {
|
||||||
engine.step();
|
engine.step();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onResetClicked() {
|
void onSaveClicked() {
|
||||||
sim.reset();
|
sim.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onLoadClicked() {
|
||||||
|
sim.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onRandomClicked() {
|
void onRandomClicked() {
|
||||||
|
@ -39,6 +43,6 @@ class ControlsComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
void onClearClicked() {
|
void onClearClicked() {
|
||||||
sim.clear();
|
sim.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<div id="controls">
|
<div id="controls">
|
||||||
<material-button id="reset" (click)="onResetClicked()"><material-icon icon="replay" baseline></material-icon></material-button>
|
<material-button id="save" (click)="onSaveClicked()"><material-icon icon="save" baseline></material-icon></material-button>
|
||||||
|
<material-button id="load" (click)="onLoadClicked()"><material-icon icon="history" baseline></material-icon></material-button>
|
||||||
<material-button id="run" (click)="onStartClicked()">
|
<material-button id="run" (click)="onStartClicked()">
|
||||||
<span [ngSwitch]="engine.isRunning">
|
<span [ngSwitch]="engine.isRunning">
|
||||||
<material-icon *ngSwitchCase="false" icon="play_arrow" baseline></material-icon>
|
<material-icon *ngSwitchCase="false" icon="play_arrow" baseline></material-icon>
|
||||||
|
|
|
@ -9,9 +9,10 @@ class SimulationService {
|
||||||
static final int DEFAULT_GRID_SIZE = 50;
|
static final int DEFAULT_GRID_SIZE = 50;
|
||||||
|
|
||||||
final EngineService _engine;
|
final EngineService _engine;
|
||||||
final Simulation _sim = Simulation(DEFAULT_GRID_SIZE, DEFAULT_GRID_SIZE);
|
final Simulation _sim;
|
||||||
|
|
||||||
SimulationService(this._engine) {
|
SimulationService(this._engine, [Simulation sim])
|
||||||
|
: this._sim = sim ?? Simulation(DEFAULT_GRID_SIZE, DEFAULT_GRID_SIZE) {
|
||||||
_engine.simulation = _sim;
|
_engine.simulation = _sim;
|
||||||
_sim.addRandomPattern(amount: 15, dispersal: 5);
|
_sim.addRandomPattern(amount: 15, dispersal: 5);
|
||||||
}
|
}
|
||||||
|
@ -24,10 +25,6 @@ class SimulationService {
|
||||||
_sim.addRandomPattern();
|
_sim.addRandomPattern();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
|
||||||
_sim.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
Point<int> get gridSize => _sim.gridSize;
|
Point<int> get gridSize => _sim.gridSize;
|
||||||
void set gridSize(Point<int> size) {
|
void set gridSize(Point<int> size) {
|
||||||
_sim.gridSize = size;
|
_sim.gridSize = size;
|
||||||
|
@ -40,4 +37,7 @@ class SimulationService {
|
||||||
void toggleGrid() {
|
void toggleGrid() {
|
||||||
_sim.renderEdges = !_sim.renderEdges;
|
_sim.renderEdges = !_sim.renderEdges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void save() => _sim.saveSnapshot();
|
||||||
|
void load() => _sim.loadSnapshot();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ enum CellPattern { SpaceShip, Blinker }
|
||||||
|
|
||||||
class Simulation {
|
class Simulation {
|
||||||
Grid<bool> map;
|
Grid<bool> map;
|
||||||
|
Grid<bool> _snapshot;
|
||||||
|
|
||||||
RuleSet rules = GameOfLife();
|
RuleSet rules = GameOfLife();
|
||||||
|
|
||||||
bool _dirty = true;
|
bool _dirty = true;
|
||||||
|
@ -151,4 +153,11 @@ class Simulation {
|
||||||
_renderEdges = on;
|
_renderEdges = on;
|
||||||
_dirty = true;
|
_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void saveSnapshot() => _snapshot = Grid.from(map);
|
||||||
|
Grid<bool> loadSnapshot() {
|
||||||
|
map = Grid.from(_snapshot);
|
||||||
|
_dirty = true;
|
||||||
|
return map;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
23
test/service/simulation_service_test.dart
Normal file
23
test/service/simulation_service_test.dart
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import 'package:rules_of_living/service/engine_service.dart';
|
||||||
|
import 'package:rules_of_living/service/simulation_service.dart';
|
||||||
|
import 'package:rules_of_living/src/Simulation.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:mockito/mockito.dart';
|
||||||
|
|
||||||
|
class MockSimulation extends Mock implements Simulation {}
|
||||||
|
|
||||||
|
class MockEngineService extends Mock implements EngineService {}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
SimulationService sut;
|
||||||
|
MockSimulation mockSim = MockSimulation();
|
||||||
|
setUp(() => sut = SimulationService(MockEngineService(), mockSim));
|
||||||
|
test("calling save calls through to Simulation.saveSnapshot", () {
|
||||||
|
sut.save();
|
||||||
|
verify(mockSim.saveSnapshot());
|
||||||
|
});
|
||||||
|
test("calling load calls through to Simulation.loadSnapshot", () {
|
||||||
|
sut.load();
|
||||||
|
verify(mockSim.loadSnapshot());
|
||||||
|
});
|
||||||
|
}
|
|
@ -5,6 +5,8 @@ import 'package:test/test.dart';
|
||||||
|
|
||||||
import 'package:rules_of_living/src/Simulation.dart';
|
import 'package:rules_of_living/src/Simulation.dart';
|
||||||
|
|
||||||
|
class MockGrid extends Mock implements Grid<bool> {}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
Simulation sut;
|
Simulation sut;
|
||||||
setUp(() {
|
setUp(() {
|
||||||
|
@ -34,4 +36,15 @@ void main() {
|
||||||
expect(sut.dirty, true);
|
expect(sut.dirty, true);
|
||||||
}, skip: "can not find a way to set dirty to true first yet");
|
}, skip: "can not find a way to set dirty to true first yet");
|
||||||
});
|
});
|
||||||
|
group("save&load", () {
|
||||||
|
test(
|
||||||
|
"saves a copy of the map which does not change when the actual map changes",
|
||||||
|
() {
|
||||||
|
sut.saveSnapshot();
|
||||||
|
sut.mergeStateChanges({1: true, 2: true});
|
||||||
|
var snapshot = Grid.from(sut.map);
|
||||||
|
|
||||||
|
expect(sut.loadSnapshot(), isNot(equals(snapshot)));
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue