Kaynağa Gözat

Add logging

Bastien Sevajol 8 yıl önce
ebeveyn
işleme
a2e6fd5436

+ 15 - 0
sandbox/engulf/behaviour.py Dosyayı Görüntüle

11
         self.subject_id = subject_id
11
         self.subject_id = subject_id
12
         self.density = density
12
         self.density = density
13
 
13
 
14
+    def repr_debug(self) -> str:
15
+        return '{}: subject_id:{}, density:{}'.format(
16
+            self.__class__.__name__,
17
+            self.subject_id,
18
+            self.density,
19
+        )
20
+
14
 
21
 
15
 class GrassSpawn(Event):
22
 class GrassSpawn(Event):
16
     def __init__(self, subject_id, position, density, *args, **kwargs):
23
     def __init__(self, subject_id, position, density, *args, **kwargs):
19
         self.position = position
26
         self.position = position
20
         self.density = density
27
         self.density = density
21
 
28
 
29
+    def repr_debug(self) -> str:
30
+        return '{}: subject_id:{}, position:{}, density:{}'.format(
31
+            self.__class__.__name__,
32
+            self.subject_id,
33
+            self.position,
34
+            self.density,
35
+        )
36
+
22
 
37
 
23
 class GrassSpotablePositionsMechanism(SimulationMechanism):
38
 class GrassSpotablePositionsMechanism(SimulationMechanism):
24
     parallelizable = True
39
     parallelizable = True

+ 21 - 4
sandbox/engulf/run.py Dosyayı Görüntüle

21
 import os
21
 import os
22
 import sys
22
 import sys
23
 
23
 
24
+import logging
25
+
24
 synergine2_ath = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../'))
26
 synergine2_ath = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../'))
25
 sys.path.append(synergine2_ath)
27
 sys.path.append(synergine2_ath)
26
 
28
 
27
 from random import randint, seed
29
 from random import randint, seed
28
 from sandbox.engulf.behaviour import GrassGrownUp, GrassSpawn, GrassSpawnBehaviour
30
 from sandbox.engulf.behaviour import GrassGrownUp, GrassSpawn, GrassSpawnBehaviour
29
 
31
 
32
+from synergine2.config import Config
33
+from synergine2.log import get_default_logger
30
 from sandbox.engulf.subject import Cell, Grass, COLLECTION_GRASS
34
 from sandbox.engulf.subject import Cell, Grass, COLLECTION_GRASS
31
 from synergine2.core import Core
35
 from synergine2.core import Core
32
 from synergine2.cycle import CycleManager
36
 from synergine2.cycle import CycleManager
140
     )
144
     )
141
     simulation.subjects = subjects
145
     simulation.subjects = subjects
142
 
146
 
147
+    config = Config()
148
+    logger = get_default_logger(level=logging.DEBUG)
149
+    logger.debug('HELLO')
143
     core = Core(
150
     core = Core(
151
+        config=config,
152
+        logger=logger,
144
         simulation=simulation,
153
         simulation=simulation,
145
-        cycle_manager=CycleManager(simulation=simulation),
146
-        terminal_manager=TerminalManager([GameTerminal(
147
-            asynchronous=False,
148
-        )]),
154
+        cycle_manager=CycleManager(
155
+            config=config,
156
+            logger=logger,
157
+            simulation=simulation,
158
+        ),
159
+        terminal_manager=TerminalManager(
160
+            config=config,
161
+            logger=logger,
162
+            terminals=[GameTerminal(
163
+                asynchronous=False,
164
+            )]
165
+        ),
149
         cycles_per_seconds=1,
166
         cycles_per_seconds=1,
150
     )
167
     )
151
     core.run()
168
     core.run()

+ 6 - 0
synergine2/base.py Dosyayı Görüntüle

1
+# coding: utf-8
2
+
3
+
4
+class BaseObject(object):
5
+    def repr_debug(self) -> str:
6
+        return type(self).__name__

+ 5 - 0
synergine2/config.py Dosyayı Görüntüle

1
+# coding: utf-8
2
+
3
+
4
+class Config(dict):
5
+    pass

+ 16 - 2
synergine2/core.py Dosyayı Görüntüle

1
 # coding: utf-8
1
 # coding: utf-8
2
 import time
2
 import time
3
+
4
+from synergine2.config import Config
3
 from synergine2.cycle import CycleManager
5
 from synergine2.cycle import CycleManager
6
+from synergine2.log import SynergineLogger
4
 from synergine2.simulation import Simulation
7
 from synergine2.simulation import Simulation
5
 from synergine2.terminals import TerminalManager
8
 from synergine2.terminals import TerminalManager
6
 from synergine2.terminals import TerminalPackage
9
 from synergine2.terminals import TerminalPackage
9
 class Core(object):
12
 class Core(object):
10
     def __init__(
13
     def __init__(
11
         self,
14
         self,
15
+        config: Config,
16
+        logger: SynergineLogger,
12
         simulation: Simulation,
17
         simulation: Simulation,
13
         cycle_manager: CycleManager,
18
         cycle_manager: CycleManager,
14
         terminal_manager: TerminalManager=None,
19
         terminal_manager: TerminalManager=None,
15
         cycles_per_seconds: int=1,
20
         cycles_per_seconds: int=1,
16
     ):
21
     ):
22
+        self.config = config
23
+        self.logger = logger
17
         self.simulation = simulation
24
         self.simulation = simulation
18
         self.cycle_manager = cycle_manager
25
         self.cycle_manager = cycle_manager
19
         self.terminal_manager = terminal_manager or TerminalManager([])
26
         self.terminal_manager = terminal_manager or TerminalManager([])
21
         self._current_cycle_start_time = None
28
         self._current_cycle_start_time = None
22
 
29
 
23
     def run(self):
30
     def run(self):
31
+        self.logger.info('Run core')
24
         try:
32
         try:
25
             self.terminal_manager.start()
33
             self.terminal_manager.start()
26
 
34
 
27
             start_package = TerminalPackage(
35
             start_package = TerminalPackage(
28
                 subjects=self.simulation.subjects,
36
                 subjects=self.simulation.subjects,
29
             )
37
             )
38
+            self.logger.info('Send start package to terminals')
30
             self.terminal_manager.send(start_package)
39
             self.terminal_manager.send(start_package)
31
 
40
 
32
             while True:
41
             while True:
59
         self.terminal_manager.stop()
68
         self.terminal_manager.stop()
60
 
69
 
61
     def _start_cycle(self):
70
     def _start_cycle(self):
62
-        self._current_cycle_start_time = time.time()
71
+        time_ = time.time()
72
+        self.logger.info('Start cycle at time {}'.format(time_))
73
+        self._current_cycle_start_time = time_
63
 
74
 
64
     def _end_cycle(self) -> None:
75
     def _end_cycle(self) -> None:
65
         """
76
         """
66
         Make a sleep if cycle duration take less time of wanted (see
77
         Make a sleep if cycle duration take less time of wanted (see
67
         cycles_per_seconds constructor parameter)
78
         cycles_per_seconds constructor parameter)
68
         """
79
         """
69
-        cycle_duration = time.time() - self._current_cycle_start_time
80
+        time_ = time.time()
81
+        self.logger.info('End of cycle at time {}'.format(time_))
82
+        cycle_duration = time_ - self._current_cycle_start_time
70
         sleep_time = self._loop_delta - cycle_duration
83
         sleep_time = self._loop_delta - cycle_duration
84
+        self.logger.info('Sleep time is {}'.format(sleep_time))
71
         if sleep_time > 0:
85
         if sleep_time > 0:
72
             time.sleep(sleep_time)
86
             time.sleep(sleep_time)

+ 182 - 12
synergine2/cycle.py Dosyayı Görüntüle

1
 # coding: utf-8
1
 # coding: utf-8
2
 import multiprocessing
2
 import multiprocessing
3
 
3
 
4
+from synergine2.config import Config
5
+from synergine2.log import SynergineLogger
4
 from synergine2.processing import ProcessManager
6
 from synergine2.processing import ProcessManager
5
-from synergine2.simulation import Subject, SimulationMechanism, SimulationBehaviour
7
+from synergine2.simulation import SimulationMechanism
8
+from synergine2.simulation import SimulationBehaviour
6
 from synergine2.simulation import Simulation
9
 from synergine2.simulation import Simulation
7
 from synergine2.simulation import SubjectBehaviour
10
 from synergine2.simulation import SubjectBehaviour
8
 from synergine2.simulation import SubjectMechanism
11
 from synergine2.simulation import SubjectMechanism
13
 class CycleManager(object):
16
 class CycleManager(object):
14
     def __init__(
17
     def __init__(
15
             self,
18
             self,
19
+            config: Config,
20
+            logger: SynergineLogger,
16
             simulation: Simulation,
21
             simulation: Simulation,
17
             process_manager: ProcessManager=None,
22
             process_manager: ProcessManager=None,
18
     ):
23
     ):
22
                 chunk_manager=ChunkManager(multiprocessing.cpu_count()),
27
                 chunk_manager=ChunkManager(multiprocessing.cpu_count()),
23
             )
28
             )
24
 
29
 
30
+        self.config = config
31
+        self.logger = logger
25
         self.simulation = simulation
32
         self.simulation = simulation
26
         self.process_manager = process_manager
33
         self.process_manager = process_manager
27
         self.current_cycle = -1
34
         self.current_cycle = -1
34
             self.first_cycle = False
41
             self.first_cycle = False
35
         self.current_cycle += 1
42
         self.current_cycle += 1
36
 
43
 
44
+        self.logger.info('Process cycle {}'.format(self.current_cycle))
45
+
37
         events = []
46
         events = []
38
         # TODO: gestion des behaviours non parallelisables
47
         # TODO: gestion des behaviours non parallelisables
39
         # TODO: Proposer des ordres d'execution
48
         # TODO: Proposer des ordres d'execution
40
         events.extend(self._get_subjects_events())
49
         events.extend(self._get_subjects_events())
41
         events.extend(self._get_simulation_events())
50
         events.extend(self._get_simulation_events())
42
 
51
 
52
+        self.logger.info('Cycle {} generate {} events'.format(
53
+            str(self.current_cycle),
54
+            str(len(events)),
55
+        ))
43
         return events
56
         return events
44
 
57
 
45
     def _get_simulation_events(self) -> [Event]:
58
     def _get_simulation_events(self) -> [Event]:
46
         events = []
59
         events = []
47
         results = {}
60
         results = {}
61
+
62
+        self.logger.info('Process simulation events')
63
+
48
         results_by_processes = self.process_manager.execute_jobs(
64
         results_by_processes = self.process_manager.execute_jobs(
49
             data=self.simulation,
65
             data=self.simulation,
50
             job_maker=self.simulation_computing,
66
             job_maker=self.simulation_computing,
57
                     results.get(behaviour_class),
73
                     results.get(behaviour_class),
58
                 )
74
                 )
59
 
75
 
76
+        self.logger.info('Simulation generate {} behaviours'.format(len(results)))
77
+
60
         # Make events
78
         # Make events
61
         for behaviour_class, behaviour_data in results.items():
79
         for behaviour_class, behaviour_data in results.items():
62
-            events.extend(self.simulation.behaviours[behaviour_class].action(behaviour_data))
80
+            behaviour_events = self.simulation.behaviours[behaviour_class].action(behaviour_data)
81
+            self.logger.info('{} behaviour generate {} events'.format(
82
+                str(behaviour_class),
83
+                str(len(behaviour_events)),
84
+            ))
85
+
86
+            if self.logger.is_debug:
87
+                self.logger.debug('{} behaviour generated events: {}'.format(
88
+                    str(behaviour_class),
89
+                    str([e.repr_debug() for e in behaviour_events]),
90
+                ))
63
 
91
 
92
+            events.extend(behaviour_events)
93
+
94
+        self.logger.info('Simulation behaviours generate {} events'.format(len(events)))
64
         return events
95
         return events
65
 
96
 
66
     def _get_subjects_events(self) -> [Event]:
97
     def _get_subjects_events(self) -> [Event]:
67
         events = []
98
         events = []
99
+        results = {}
100
+
101
+        self.logger.info('Process subjects events')
102
+
68
         results_by_processes = self.process_manager.chunk_and_execute_jobs(
103
         results_by_processes = self.process_manager.chunk_and_execute_jobs(
69
             data=self.simulation.subjects,
104
             data=self.simulation.subjects,
70
             job_maker=self.subjects_computing,
105
             job_maker=self.subjects_computing,
71
         )
106
         )
72
-        results = {}
107
+
73
         for process_results in results_by_processes:
108
         for process_results in results_by_processes:
74
             results.update(process_results)
109
             results.update(process_results)
75
-        for subject in self.simulation.subjects[:]:  # Duplicate list to prevent conflicts with behaviours subjects manipulations
110
+
111
+        # Duplicate list to prevent conflicts with behaviours subjects manipulations
112
+        for subject in self.simulation.subjects[:]:
76
             for behaviour_class, behaviour_data in results.get(subject.id, {}).items():
113
             for behaviour_class, behaviour_data in results.get(subject.id, {}).items():
77
                 # TODO: Ajouter une etape de selection des actions a faire (genre neuronnal)
114
                 # TODO: Ajouter une etape de selection des actions a faire (genre neuronnal)
78
                 # (genre se cacher et fuir son pas compatibles)
115
                 # (genre se cacher et fuir son pas compatibles)
79
-                actions_events = subject.behaviours[behaviour_class].action(behaviour_data)
80
-                events.extend(actions_events)
116
+                behaviour_events = subject.behaviours[behaviour_class].action(behaviour_data)
117
+
118
+                self.logger.info('{} behaviour for subject {} generate {} events'.format(
119
+                    str(behaviour_class),
120
+                    str(subject.id),
121
+                    str(len(behaviour_events)),
122
+                ))
123
+
124
+                if self.logger.is_debug:
125
+                    self.logger.debug('{} behaviour for subject {} generated events: {}'.format(
126
+                        str(behaviour_class),
127
+                        str(subject.id),
128
+                        str([e.repr_debug() for e in behaviour_events]),
129
+                    ))
81
 
130
 
131
+                events.extend(behaviour_events)
132
+
133
+        self.logger.info('Subjects behaviours generate {} events'.format(len(events)))
82
         return events
134
         return events
83
 
135
 
84
     def simulation_computing(
136
     def simulation_computing(
87
             process_number,
139
             process_number,
88
             process_count,
140
             process_count,
89
     ):
141
     ):
142
+        self.logger.info('Simulation computing')
143
+
90
         # TODO: necessaire de passer simulation ?
144
         # TODO: necessaire de passer simulation ?
91
         mechanisms = self.get_mechanisms_to_compute(simulation)
145
         mechanisms = self.get_mechanisms_to_compute(simulation)
92
         mechanisms_data = {}
146
         mechanisms_data = {}
93
         behaviours_data = {}
147
         behaviours_data = {}
94
 
148
 
149
+        self.logger.info('{} mechanisms to compute'.format(str(len(mechanisms))))
150
+        if self.logger.is_debug:
151
+            self.logger.debug('Mechanisms are: {}'.format(
152
+                str([m.repr_debug() for m in mechanisms])
153
+            ))
154
+
95
         for mechanism in mechanisms:
155
         for mechanism in mechanisms:
96
-            mechanisms_data[type(mechanism)] = mechanism.run(
156
+            mechanism_data = mechanism.run(
97
                 process_number=process_number,
157
                 process_number=process_number,
98
                 process_count=process_count,
158
                 process_count=process_count,
99
             )
159
             )
100
 
160
 
101
-        for behaviour in self.get_behaviours_to_compute(simulation):
161
+            if self.logger.is_debug:
162
+                self.logger.debug('{} mechanism product data: {}'.format(
163
+                    type(mechanism).__name__,
164
+                    str(mechanism_data),
165
+                ))
166
+
167
+            mechanisms_data[type(mechanism)] = mechanism_data
168
+
169
+        behaviours = self.get_behaviours_to_compute(simulation)
170
+        self.logger.info('{} behaviours to compute'.format(str(len(behaviours))))
171
+
172
+        if self.logger.is_debug:
173
+            self.logger.debug('Behaviours are: {}'.format(
174
+                str([b.repr_debug() for b in behaviours])
175
+            ))
176
+
177
+        for behaviour in behaviours:
102
             behaviour_data = behaviour.run(mechanisms_data)  # TODO: Behaviours dependencies
178
             behaviour_data = behaviour.run(mechanisms_data)  # TODO: Behaviours dependencies
179
+            if self.logger.is_debug:
180
+                self.logger.debug('{} behaviour produce data: {}'.format(
181
+                    type(behaviour).__name__,
182
+                    behaviour_data,
183
+                ))
184
+
103
             if behaviour_data:
185
             if behaviour_data:
104
                 behaviours_data[type(behaviour)] = behaviour_data
186
                 behaviours_data[type(behaviour)] = behaviour_data
105
 
187
 
112
             process_count=None,
194
             process_count=None,
113
     ):
195
     ):
114
         results = {}
196
         results = {}
197
+        self.logger.info('Subjects computing: {} subjects to compute'.format(str(len(subjects))))
198
+
115
         for subject in subjects:
199
         for subject in subjects:
116
             mechanisms = self.get_mechanisms_to_compute(subject)
200
             mechanisms = self.get_mechanisms_to_compute(subject)
201
+            if not mechanisms:
202
+                break
203
+
204
+            self.logger.info('Subject {}: {} mechanisms'.format(
205
+                str(subject.id),
206
+                str(len(mechanisms)),
207
+            ))
208
+
209
+            if self.logger.is_debug:
210
+                self.logger.info('Subject {}: mechanisms are: {}'.format(
211
+                    str(subject.id),
212
+                    str([m.repr_debug for m in mechanisms])
213
+                ))
214
+
117
             mechanisms_data = {}
215
             mechanisms_data = {}
118
             behaviours_data = {}
216
             behaviours_data = {}
119
 
217
 
120
             for mechanism in mechanisms:
218
             for mechanism in mechanisms:
121
-                mechanisms_data[type(mechanism)] = mechanism.run()
219
+                mechanism_data = mechanism.run()
220
+                if self.logger.is_debug:
221
+                    self.logger.info('Subject {}: {} mechanisms produce data: {}'.format(
222
+                        str(subject.id),
223
+                        type(mechanism).__name__,
224
+                        str(mechanism_data),
225
+                    ))
226
+
227
+                mechanisms_data[type(mechanism)] = mechanism_data
228
+
229
+            if self.logger.is_debug:
230
+                self.logger.info('Subject {}: mechanisms data are: {}'.format(
231
+                    str(subject.id),
232
+                    str(mechanisms_data),
233
+                ))
234
+
235
+            subject_behaviours = self.get_behaviours_to_compute(subject)
236
+
237
+            self.logger.info('Subject {}: have {} behaviours'.format(
238
+                str(subject.id),
239
+                str(len(subject_behaviours)),
240
+            ))
241
+
242
+            for behaviour in subject_behaviours:
243
+                self.logger.info('Subject {}: run {} behaviour'.format(
244
+                    str(subject.id),
245
+                    str(type(behaviour)),
246
+                ))
122
 
247
 
123
-            for behaviour in self.get_behaviours_to_compute(subject):
124
                 # We identify behaviour data with it's class to be able to intersect it after subprocess data collect
248
                 # We identify behaviour data with it's class to be able to intersect it after subprocess data collect
125
                 behaviour_data = behaviour.run(mechanisms_data)  # TODO: Behaviours dependencies
249
                 behaviour_data = behaviour.run(mechanisms_data)  # TODO: Behaviours dependencies
250
+
251
+                if self.logger.is_debug:
252
+                    self.logger.debug('Subject {}: behaviour {} produce data: {}'.format(
253
+                        str(type(behaviour)),
254
+                        str(subject.id),
255
+                        str(behaviour_data),
256
+                    ))
257
+
126
                 if behaviour_data:
258
                 if behaviour_data:
127
                     behaviours_data[type(behaviour)] = behaviour_data
259
                     behaviours_data[type(behaviour)] = behaviour_data
128
 
260
 
157
         simulation_actions = simulation_actions or []
289
         simulation_actions = simulation_actions or []
158
         subject_actions = subject_actions or []
290
         subject_actions = subject_actions or []
159
         events = []
291
         events = []
292
+        self.logger.info('Apply {} simulation_actions and {} subject_actions'.format(
293
+            len(simulation_actions),
294
+            len(subject_actions),
295
+        ))
160
 
296
 
161
         for subject_id, behaviours_and_data in subject_actions:
297
         for subject_id, behaviours_and_data in subject_actions:
162
             subject = self.simulation.subjects.index.get(subject_id)
298
             subject = self.simulation.subjects.index.get(subject_id)
165
                     simulation=self.simulation,
301
                     simulation=self.simulation,
166
                     subject=subject,
302
                     subject=subject,
167
                 )
303
                 )
168
-                events.extend(behaviour.action(behaviour_data))
304
+                self.logger.info('Apply {} behaviour on subject {}'.format(
305
+                    str(behaviour_class),
306
+                    str(subject_id),
307
+                ))
308
+                if self.logger.is_debug:
309
+                    self.logger.debug('{} behaviour data is {}'.format(
310
+                        str(behaviour_class),
311
+                        str(behaviour_data),
312
+                    ))
313
+                behaviour_events = behaviour.action(behaviour_data)
314
+                self.logger.info('{} events from behaviour {} from subject {}'.format(
315
+                    len(behaviour_events),
316
+                    str(behaviour_class),
317
+                    str(subject_id),
318
+                ))
319
+                if self.logger.is_debug:
320
+                    self.logger.debug('Events from behaviour {} from subject {} are: {}'.format(
321
+                        str(behaviour_class),
322
+                        str(subject_id),
323
+                        str([e.repr_debug() for e in behaviour_events])
324
+                    ))
325
+                events.extend(behaviour_events)
169
 
326
 
170
         for behaviour_class, behaviour_data in simulation_actions:
327
         for behaviour_class, behaviour_data in simulation_actions:
171
             behaviour = behaviour_class(
328
             behaviour = behaviour_class(
172
                 simulation=self.simulation,
329
                 simulation=self.simulation,
173
             )
330
             )
174
-            events.extend(behaviour.action(behaviour_data))
175
 
331
 
332
+            self.logger.info('Apply {} simulation behaviour'.format(
333
+                str(behaviour_class),
334
+            ))
335
+
336
+            behaviour_events = behaviour.action(behaviour_data)
337
+            if self.logger.is_debug:
338
+                self.logger.debug('Events from behaviour {} are: {}'.format(
339
+                    str(behaviour_class),
340
+                    str([e.repr_debug() for e in behaviour_events])
341
+                ))
342
+
343
+            events.extend(behaviour_events)
344
+
345
+        self.logger.info('{} events generated'.format(len(events)))
176
         return events
346
         return events

+ 11 - 0
synergine2/exceptions.py Dosyayı Görüntüle

1
+# coding: utf-8
2
+
3
+
4
+class SynergineException(Exception):
5
+    pass
6
+
7
+
8
+class NotYetImplemented(SynergineException):
9
+    """
10
+    Like of NotImplementError. Use it to declare method to implement but only if wanted.
11
+    """

+ 27 - 0
synergine2/log.py Dosyayı Görüntüle

1
+# coding: utf-8
2
+import logging
3
+
4
+import sys
5
+import typing
6
+
7
+
8
+class SynergineLogger(logging.getLoggerClass()):
9
+    @property
10
+    def is_debug(self) -> bool:
11
+        return self.isEnabledFor(logging.DEBUG)
12
+
13
+
14
+def get_default_logger(name: str='synergine', level: int=logging.ERROR) -> SynergineLogger:
15
+    """
16
+    WARNING: Set global logging Logger class to SynergineLogger
17
+    """
18
+    logging.setLoggerClass(SynergineLogger)
19
+    logger = logging.getLogger(name)
20
+    logger = typing.cast(SynergineLogger, logger)
21
+    handler = logging.StreamHandler(sys.stdout)
22
+    formatter = logging.Formatter('%(asctime)s|%(name)s|%(process)d|%(levelname)s: %(message)s')
23
+    handler.setFormatter(formatter)
24
+    logger.addHandler(handler)
25
+    logger.setLevel(level)
26
+
27
+    return logger

+ 21 - 5
synergine2/simulation.py Dosyayı Görüntüle

1
 # coding: utf-8
1
 # coding: utf-8
2
 import collections
2
 import collections
3
 
3
 
4
+from synergine2.base import BaseObject
4
 from synergine2.utils import get_mechanisms_classes
5
 from synergine2.utils import get_mechanisms_classes
5
 
6
 
6
 
7
 
19
 
20
 
20
         self.initialize()
21
         self.initialize()
21
 
22
 
23
+    def __str__(self):
24
+        return self.id
25
+
26
+    def __repr__(self):
27
+        return '{}({})'.format(
28
+            type(self).__name__,
29
+            self.id,
30
+        )
31
+
22
     def initialize(self):
32
     def initialize(self):
23
         for mechanism_class in get_mechanisms_classes(self):
33
         for mechanism_class in get_mechanisms_classes(self):
24
             self.mechanisms[mechanism_class] = mechanism_class(
34
             self.mechanisms[mechanism_class] = mechanism_class(
103
             )
113
             )
104
 
114
 
105
 
115
 
106
-class SubjectMechanism(object):
116
+class SubjectMechanism(BaseObject):
107
     def __init__(
117
     def __init__(
108
             self,
118
             self,
109
             simulation: Simulation,
119
             simulation: Simulation,
116
         raise NotImplementedError()
126
         raise NotImplementedError()
117
 
127
 
118
 
128
 
119
-class SimulationMechanism(object):
129
+class SimulationMechanism(BaseObject):
120
     """If parallelizable behaviour, call """
130
     """If parallelizable behaviour, call """
121
     parallelizable = False
131
     parallelizable = False
122
 
132
 
126
     ):
136
     ):
127
         self.simulation = simulation
137
         self.simulation = simulation
128
 
138
 
139
+    def repr_debug(self) -> str:
140
+        return self.__class__.__name__
141
+
129
     def run(self, process_id: int=None, process_count: int=None):
142
     def run(self, process_id: int=None, process_count: int=None):
130
         raise NotImplementedError()
143
         raise NotImplementedError()
131
 
144
 
132
 
145
 
133
-class Event(object):
146
+class Event(BaseObject):
134
     def __init__(self, *args, **kwargs):
147
     def __init__(self, *args, **kwargs):
135
         pass
148
         pass
136
 
149
 
150
+    def repr_debug(self) -> str:
151
+        return self.__class__.__name__
152
+
137
 
153
 
138
-class SubjectBehaviour(object):
154
+class SubjectBehaviour(BaseObject):
139
     frequency = 1
155
     frequency = 1
140
     use = []
156
     use = []
141
 
157
 
166
         raise NotImplementedError()
182
         raise NotImplementedError()
167
 
183
 
168
 
184
 
169
-class SimulationBehaviour(object):
185
+class SimulationBehaviour(BaseObject):
170
     frequency = 1
186
     frequency = 1
171
     use = []
187
     use = []
172
 
188
 

+ 61 - 5
synergine2/terminals.py Dosyayı Görüntüle

7
 from queue import Empty
7
 from queue import Empty
8
 
8
 
9
 import time
9
 import time
10
+
11
+from synergine2.base import BaseObject
12
+from synergine2.config import Config
13
+from synergine2.log import SynergineLogger
10
 from synergine2.simulation import Subject
14
 from synergine2.simulation import Subject
11
 from synergine2.simulation import Event
15
 from synergine2.simulation import Event
12
 
16
 
13
 STOP_SIGNAL = '__STOP_SIGNAL__'
17
 STOP_SIGNAL = '__STOP_SIGNAL__'
14
 
18
 
15
 
19
 
16
-class TerminalPackage(object):
20
+class TerminalPackage(BaseObject):
17
     def __init__(
21
     def __init__(
18
             self,
22
             self,
19
             subjects: [Subject]=None,
23
             subjects: [Subject]=None,
34
         self.subject_actions = subject_actions or []
38
         self.subject_actions = subject_actions or []
35
         self.is_cycle = is_cycle
39
         self.is_cycle = is_cycle
36
 
40
 
41
+    def repr_debug(self) -> str:
42
+        subjects = self.subjects or []
43
+        return str(dict(
44
+            subjects=subjects,
45
+            add_subjects=[s.id for s in self.add_subjects],
46
+            remove_subjects=[s.id for s in self.remove_subjects],
47
+            events=[e.repr_debug() for e in self.events],
48
+            simulation_actions=['{}: {}'.format(a.__class__.__name__, p) for a, p in self.simulation_actions],
49
+            subject_actions=['{}: {}'.format(a.__class__.__name__, p) for a, p in self.subject_actions],
50
+            is_cycle=self.is_cycle,
51
+        ))
52
+
37
 
53
 
38
 class Terminal(object):
54
 class Terminal(object):
39
     # Default behaviour is to do nothing.
55
     # Default behaviour is to do nothing.
118
 
134
 
119
 
135
 
120
 class TerminalManager(object):
136
 class TerminalManager(object):
121
-    def __init__(self, terminals: [Terminal]):
137
+    def __init__(
138
+        self,
139
+        config: Config,
140
+        logger: SynergineLogger,
141
+        terminals: [Terminal]
142
+    ):
143
+        self.config = config
144
+        self.logger = logger
122
         self.terminals = terminals
145
         self.terminals = terminals
123
         self.outputs_queues = {}
146
         self.outputs_queues = {}
124
         self.inputs_queues = {}
147
         self.inputs_queues = {}
125
 
148
 
126
     def start(self) -> None:
149
     def start(self) -> None:
150
+        self.logger.info('Start terminals')
127
         for terminal in self.terminals:
151
         for terminal in self.terminals:
152
+            # TODO: logs
128
             output_queue = Queue()
153
             output_queue = Queue()
129
             self.outputs_queues[terminal] = output_queue
154
             self.outputs_queues[terminal] = output_queue
130
 
155
 
142
             output_queue.put(STOP_SIGNAL)
167
             output_queue.put(STOP_SIGNAL)
143
 
168
 
144
     def send(self, package: TerminalPackage):
169
     def send(self, package: TerminalPackage):
170
+        self.logger.info('Send package to terminals')
171
+        if self.logger.is_debug:
172
+            self.logger.debug('Send package to terminals: {}'.format(
173
+                str(package.repr_debug()),
174
+            ))
145
         for terminal, output_queue in self.outputs_queues.items():
175
         for terminal, output_queue in self.outputs_queues.items():
176
+            self.logger.info('Send package to terminal {}'.format(terminal.__class__.__name__))
146
             # Terminal maybe don't want all events, so reduce list of event
177
             # Terminal maybe don't want all events, so reduce list of event
147
             # Thirst make a copy to personalize this package
178
             # Thirst make a copy to personalize this package
148
             terminal_adapted_package = copy(package)
179
             terminal_adapted_package = copy(package)
153
                 if not terminal.accept_event(package_event):
184
                 if not terminal.accept_event(package_event):
154
                     terminal_adapted_package.events.remove(package_event)
185
                     terminal_adapted_package.events.remove(package_event)
155
 
186
 
187
+            if self.logger.is_debug:
188
+                self.logger.debug('Send package to terminal {}: {}'.format(
189
+                    terminal.__class__.__name__,
190
+                    terminal_adapted_package.repr_debug(),
191
+                ))
192
+
156
             output_queue.put(terminal_adapted_package)
193
             output_queue.put(terminal_adapted_package)
157
 
194
 
158
     def receive(self) -> [TerminalPackage]:
195
     def receive(self) -> [TerminalPackage]:
196
+        self.logger.info('Receive terminals packages')
159
         packages = []
197
         packages = []
160
         for terminal, input_queue in self.inputs_queues.items():
198
         for terminal, input_queue in self.inputs_queues.items():
199
+            self.logger.info('Receive terminal {} packages ({})'.format(
200
+                terminal.__class__.__name__,
201
+                'sync' if not terminal.asynchronous else 'async'
202
+            ))
161
             # When terminal is synchronous, wait it's cycle package
203
             # When terminal is synchronous, wait it's cycle package
162
             if not terminal.asynchronous:
204
             if not terminal.asynchronous:
163
                 continue_ = True
205
                 continue_ = True
166
                     # In case where terminal send package before end of cycle
208
                     # In case where terminal send package before end of cycle
167
                     # management
209
                     # management
168
                     continue_ = not package.is_cycle
210
                     continue_ = not package.is_cycle
211
+
212
+                    if self.logger.is_debug:
213
+                        self.logger.debug('Receive package from {}: {}'.format(
214
+                            terminal.__class__.__name__,
215
+                            str(package.repr_debug()),
216
+                        ))
217
+
169
                     packages.append(package)
218
                     packages.append(package)
170
             else:
219
             else:
171
                 try:
220
                 try:
172
                     while True:
221
                     while True:
173
-                        packages.append(
174
-                            input_queue.get(block=False, timeout=None),
175
-                        )
222
+                        package = input_queue.get(block=False, timeout=None)
223
+
224
+                        if self.logger.is_debug:
225
+                            self.logger.debug('Receive package from {}: {}'.format(
226
+                                str(terminal),
227
+                                str(package.repr_debug()),
228
+                            ))
229
+
230
+                        packages.append(package)
176
                 except Empty:
231
                 except Empty:
177
                     pass  # Queue is empty
232
                     pass  # Queue is empty
178
 
233
 
234
+        self.logger.info('{} package(s) received'.format(len(packages)))
179
         return packages
235
         return packages