aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-10-25 17:26:20 +0200
committerLoek Le Blansch <loek@pipeframe.xyz>2024-10-25 17:26:20 +0200
commitb31d7a677481b4a09168c43d203bfd6d7badf577 (patch)
tree13550fa7f33d21aea8a7b03981707db2c08fc9a2
parentc9f5ac8722190efeb58fda1eec9e6160d5204127 (diff)
implement mementos snapshots
-rw-r--r--ArtistData.h11
-rw-r--r--Canvas.cpp23
-rw-r--r--Canvas.h4
-rw-r--r--CanvasData.h11
-rw-r--r--Memento.h13
-rw-r--r--Museum.cpp49
-rw-r--r--Museum.h14
-rw-r--r--People.cpp20
-rw-r--r--People.h4
-rw-r--r--TileData.h11
-rw-r--r--docs/class-diag.puml11
-rw-r--r--readme.md5
12 files changed, 163 insertions, 13 deletions
diff --git a/ArtistData.h b/ArtistData.h
index 1c3c88c..1a75842 100644
--- a/ArtistData.h
+++ b/ArtistData.h
@@ -1,5 +1,7 @@
#pragma once
+#include "Memento.h"
+
struct ArtistData {
float x = 0.0;
float y = 0.0;
@@ -7,3 +9,12 @@ struct ArtistData {
float vy = 0.0;
};
+class ArtistDataMemento : public Memento {
+ friend class People;
+
+public:
+ ArtistDataMemento(const ArtistData & data) : data(data) {}
+private:
+ ArtistData data;
+};
+
diff --git a/Canvas.cpp b/Canvas.cpp
index b7cc8a5..86b5bec 100644
--- a/Canvas.cpp
+++ b/Canvas.cpp
@@ -109,3 +109,26 @@ void Canvas::update_tiles() {
}
}
+Memories Canvas::save() {
+ Memories data;
+ data.push_back(make_unique<CanvasDataMemento>(this->data));
+ for (Tile * tile : this->tiles) {
+ data.push_back(make_unique<TileDataMemento>(tile->data));
+ }
+ return data;
+}
+
+void Canvas::restore(const Memories & memories) {
+ for (const unique_ptr<Memento> & memory : memories) {
+ auto canvas = dynamic_cast<CanvasDataMemento *>(memory.get());
+ if (canvas != nullptr) {
+ this->set_data(canvas->data);
+ }
+
+ auto tile = dynamic_cast<TileDataMemento *>(memory.get());
+ if (tile != nullptr) {
+ this->set_tile(tile->data);
+ }
+ }
+}
+
diff --git a/Canvas.h b/Canvas.h
index b602fb2..294b335 100644
--- a/Canvas.h
+++ b/Canvas.h
@@ -28,6 +28,10 @@ public:
void set_data(CanvasData data);
public:
+ Memories save();
+ void restore(const Memories &);
+
+public:
TileColorFactory tile_color;
TileBehaviorFactory tile_behavior;
diff --git a/CanvasData.h b/CanvasData.h
index d2b0666..69e8c8c 100644
--- a/CanvasData.h
+++ b/CanvasData.h
@@ -1,7 +1,18 @@
#pragma once
+#include "Memento.h"
+
struct CanvasData {
unsigned rows = 0;
unsigned columns = 0;
};
+class CanvasDataMemento : public Memento {
+ friend class Canvas;
+
+public:
+ CanvasDataMemento(const CanvasData & data) : data(data) {}
+private:
+ CanvasData data;
+};
+
diff --git a/Memento.h b/Memento.h
new file mode 100644
index 0000000..0bc6c92
--- /dev/null
+++ b/Memento.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <vector>
+#include <memory>
+
+class Memento {
+public:
+ Memento() = default;
+ virtual ~Memento() = default;
+};
+
+typedef std::vector<std::unique_ptr<Memento>> Memories;
+
diff --git a/Museum.cpp b/Museum.cpp
index 4a12038..d389602 100644
--- a/Museum.cpp
+++ b/Museum.cpp
@@ -20,22 +20,39 @@ void Museum::update() {
this->canvas.update();
this->collision.update();
this->tick++;
+
+ unsigned long long next_snapshot = this->snapshot_ticks;
+ if (!this->history.empty()) next_snapshot += this->history.top().tick;
+ if (next_snapshot > this->tick) return;
+ this->history.push(this->save_snapshot());
+ printf("saved snapshot at tick %llu\n", this->tick);
}
void Museum::skip_forward() {
- this->jump += this->snapshot_ticks;
+ this->jump++;
}
-
void Museum::skip_backward() {
-
+ this->jump--;
}
void Museum::work() {
while (this->working) {
- // immediately process forward jumps, even if paused
+ // immediately process jumps, even if paused
if (this->jump > 0) {
- for (; this->jump != 0; this->jump--)
- this->update();
+ // forward jump
+ for (; this->jump != 0; this->jump--) {
+ printf("jumping forward %u ticks\n", this->snapshot_ticks);
+ for (size_t i = 0; i < this->snapshot_ticks; i++)
+ this->update();
+ }
+ } else if (this->jump < 0) {
+ // backward jump
+ for (; this->jump != 0; this->jump++) {
+ if (this->history.empty()) continue;
+ printf("restoring snapshot from tick %llu\n", this->history.top().tick);
+ this->restore_snapshot(this->history.top());
+ this->history.pop();
+ }
}
// wait with regular update if paused
@@ -48,3 +65,23 @@ void Museum::work() {
}
}
+static void memories_concat(Memories & a, Memories b) {
+ a.insert(a.end(), make_move_iterator(b.begin()), make_move_iterator(b.end()));
+}
+
+Museum::Snapshot Museum::save_snapshot() {
+ Snapshot snapshot = {
+ .tick = this->tick,
+ .memories = {},
+ };
+ memories_concat(snapshot.memories, this->canvas.save());
+ memories_concat(snapshot.memories, this->people.save());
+ return snapshot;
+}
+
+void Museum::restore_snapshot(const Snapshot & snapshot) {
+ this->tick = snapshot.tick;
+ this->canvas.restore(snapshot.memories);
+ this->people.restore(snapshot.memories);
+}
+
diff --git a/Museum.h b/Museum.h
index 27e7915..bc5b590 100644
--- a/Museum.h
+++ b/Museum.h
@@ -2,6 +2,7 @@
#include <thread>
#include <chrono>
+#include <stack>
#include "People.h"
#include "Canvas.h"
@@ -28,7 +29,7 @@ public:
void skip_backward();
private:
- unsigned long jump = 0;
+ int jump = 0;
private:
bool working = true;
@@ -37,7 +38,16 @@ private:
private:
unsigned long long tick = 0;
- static constexpr unsigned snapshot_ticks = 50;
static constexpr std::chrono::milliseconds tick_interval = 15ms;
+
+private:
+ static constexpr unsigned snapshot_ticks = 50;
+ struct Snapshot {
+ unsigned long long tick;
+ Memories memories;
+ };
+ std::stack<Snapshot, std::vector<Snapshot>> history;
+ Snapshot save_snapshot();
+ void restore_snapshot(const Snapshot &);
};
diff --git a/People.cpp b/People.cpp
index 39d44db..d11434d 100644
--- a/People.cpp
+++ b/People.cpp
@@ -1,6 +1,8 @@
#include <algorithm>
+#include <memory>
#include "People.h"
+#include "ArtistData.h"
#include "util.h"
using namespace std;
@@ -50,3 +52,21 @@ void People::update(bool tick) {
}
}
+Memories People::save() {
+ Memories data;
+ for (Artist * artist : this->artists) {
+ data.push_back(make_unique<ArtistDataMemento>(artist->data));
+ }
+ return data;
+}
+
+void People::restore(const Memories & memories) {
+ this->artists.clear();
+ this->artist_count = 0;
+ for (const unique_ptr<Memento> & memory : memories) {
+ auto data = dynamic_cast<ArtistDataMemento *>(memory.get());
+ if (data == nullptr) continue;
+ this->add_artist(data->data);
+ }
+}
+
diff --git a/People.h b/People.h
index 940a6d5..83516c9 100644
--- a/People.h
+++ b/People.h
@@ -22,6 +22,10 @@ public:
void update(bool tick = true);
+public:
+ Memories save();
+ void restore(const Memories &);
+
private:
std::forward_list<Artist *> artists;
size_t artist_count = 0;
diff --git a/TileData.h b/TileData.h
index 87d9003..314466c 100644
--- a/TileData.h
+++ b/TileData.h
@@ -2,9 +2,20 @@
#include <string>
+#include "Memento.h"
+
struct TileData {
unsigned int x = 0;
unsigned int y = 0;
std::string type = "";
};
+class TileDataMemento : public Memento {
+ friend class Canvas;
+
+public:
+ TileDataMemento(const TileData & data) : data(data) {}
+private:
+ TileData data;
+};
+
diff --git a/docs/class-diag.puml b/docs/class-diag.puml
index 9ce43eb..f695ed3 100644
--- a/docs/class-diag.puml
+++ b/docs/class-diag.puml
@@ -111,7 +111,7 @@ rectangle Group_Collisions as "Collisions" <<group>> {
--
- museum : Museum &
}
- class CollisionChecker <<abstract>> {
+ abstract class CollisionChecker {
+ CollisionChecker(Museum &)
+ check() <<pure virtual>>
--
@@ -169,7 +169,7 @@ rectangle Group_Pathfinding as "Pathfinding" <<group>> {
--
- museum : Museum &
}
- class Pathfinder <<abstract>> {
+ abstract class Pathfinder {
+ Pathfinder(Museum &)
+ find_between(const XY &, const XY &) <<pure virtual>
--
@@ -260,6 +260,9 @@ rectangle Group_Model as "Model" <<group>> {
- artist_count : size_t
- museum : Museum &
}
+ interface Memento {
+ }
+ People -r[hidden] Canvas
}
together {
class Tile {
@@ -383,6 +386,10 @@ rectangle Group_Model as "Model" <<group>> {
Tile --> "state" TileBehavior
Tile .[norank].> TileBehaviorFactory
+ Memento <|.[norank]. TileData
+ Memento <|.[norank]. ArtistData
+ Memento <|.[norank]. CanvasData
+
' LAYOUT
Artist -r[hidden] Tile
}
diff --git a/readme.md b/readme.md
index 309abed..42c9aaf 100644
--- a/readme.md
+++ b/readme.md
@@ -1,6 +1,5 @@
# TODO
-DPA:
-
-- state snapshots (memento)
+- update class diagram
+- triple check class diagram