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:
Marty 2018-10-19 18:51:50 +00:00
commit d79aceeebf
6 changed files with 60 additions and 10 deletions

View File

@ -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();
} }
} }

View File

@ -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>

View File

@ -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();
} }

View File

@ -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;
}
} }

View 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());
});
}

View File

@ -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)));
});
});
} }