Merge branch 'master' of ctpug.org.za:koperkapel
[koperkapel.git] / koperkapel / actors / navigator.py
1 """ A navigable graph of actors. """
2
3
4 class ActorNavigator:
5     """ A navigable graph of actors. """
6
7     def __init__(self):
8         self._actors = {}
9         self._graph = {}
10         self._current_id = None
11
12     @property
13     def current(self):
14         return self._actors.get(self._current_id)
15
16     def connect_pair(self, a1, a2, edge):
17         self._actors[id(a1)] = a1
18         self._actors[id(a2)] = a2
19         if self._current_id is None:
20             self._current_id = id(a1)
21         a1edges = self._graph.setdefault(id(a1), {})
22         a1edges[edge] = id(a2)
23
24     def connect(self, actors, edges, reverse=None, wrap=True):
25         if not edges or not actors:
26             return
27         first, previous, current = None, None, None
28         for actor in actors:
29             previous, current = current, actor
30             if previous is None:
31                 first = current
32                 continue
33             for edge in edges:
34                 self.connect_pair(previous, current, edge)
35         if wrap and first is not current:
36             for edge in edges:
37                 self.connect_pair(current, first, edge)
38         if reverse is not None:
39             self.connect(list(reversed(actors)), reverse)
40
41     def follow(self, edge):
42         future = self._graph.get(self._current_id, {}).get(edge)
43         if future:
44             old, self._current_id = self._current_id, future
45             return self._actors[old], self._actors[future]
46         return None, None