-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstate_restore.py
More file actions
92 lines (84 loc) · 3.07 KB
/
Copy pathstate_restore.py
File metadata and controls
92 lines (84 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
from __future__ import annotations
from backend.payload_types import PersistedSimulationSnapshotInput, SparseCellsByIdPayload
from backend.rules import RuleRegistry
from backend.rules.base import AutomatonRule
from backend.simulation.models import (
SimulationStateData,
)
from backend.simulation.topology import SimulationBoard, board_from_cells_by_id, board_from_states
from backend.simulation.transition_planner import plan_restore_transition
class SimulationStateRestorer:
"""Builds normalized mutable simulation state from persisted snapshot payloads."""
def __init__(self, rule_registry: RuleRegistry) -> None:
self.rule_registry = rule_registry
def restore(
self,
payload: PersistedSimulationSnapshotInput,
*,
fallback_state: SimulationStateData,
) -> SimulationStateData:
plan = plan_restore_transition(
payload,
fallback_state=fallback_state,
rule_registry=self.rule_registry,
)
next_board = self._normalize_board(
payload,
geometry=plan.config.geometry,
width=plan.config.width,
height=plan.config.height,
patch_depth=plan.config.patch_depth,
rule=plan.rule,
payload_kind=plan.board_payload_kind,
)
next_config = plan.config.updated(
width=next_board.topology.width,
height=next_board.topology.height,
)
return SimulationStateData(
config=next_config,
running=False,
generation=plan.generation,
rule=plan.rule,
board=next_board,
state_revision=0,
)
def _normalize_board(
self,
payload: PersistedSimulationSnapshotInput,
*,
geometry: str,
width: int,
height: int,
patch_depth: int,
rule: AutomatonRule,
payload_kind: str,
) -> SimulationBoard:
if payload_kind == "cells_by_id":
return board_from_cells_by_id(
geometry,
width,
height,
self._normalize_cells_by_id(payload.get("cells_by_id"), rule),
patch_depth=patch_depth,
)
return board_from_states(geometry, width, height, [], patch_depth=patch_depth)
def _normalize_cells_by_id(
self,
cells_by_id_payload: object,
rule: AutomatonRule,
) -> SparseCellsByIdPayload:
allowed_states = rule.state_values()
normalized: SparseCellsByIdPayload = {}
if not isinstance(cells_by_id_payload, dict):
return normalized
for cell_id, cell_state in cells_by_id_payload.items():
if not isinstance(cell_id, str) or cell_id == "":
continue
try:
normalized_state = int(cell_state)
except (TypeError, ValueError):
normalized_state = 0
if normalized_state in allowed_states and normalized_state != 0:
normalized[cell_id] = normalized_state
return normalized