Browse Source

state: fill subject

Bastien Sevajol 6 years ago
parent
commit
0889cd17a1
6 changed files with 79 additions and 14 deletions
  1. 4 0
      opencombat/exception.py
  2. 32 6
      opencombat/state.py
  3. 5 5
      opencombat/state.xsd
  4. 25 0
      opencombat/util.py
  5. 4 3
      run.py
  6. 9 0
      tests/test_state.py

+ 4 - 0
opencombat/exception.py View File

19
 
19
 
20
 class StateLoadError(OpenCombatException):
20
 class StateLoadError(OpenCombatException):
21
     pass
21
     pass
22
+
23
+
24
+class NotFoundError(OpenCombatException):
25
+    pass

+ 32 - 6
opencombat/state.py View File

1
 # coding: utf-8
1
 # coding: utf-8
2
-import importlib
3
 import typing
2
 import typing
4
-from _elementtree import Element
5
 
3
 
4
+from _elementtree import Element
6
 from lxml import etree
5
 from lxml import etree
7
 
6
 
8
 from synergine2.config import Config
7
 from synergine2.config import Config
9
 from synergine2.log import get_logger
8
 from synergine2.log import get_logger
10
-from synergine2.simulation import Subject
11
 
9
 
12
 from opencombat.exception import StateLoadError
10
 from opencombat.exception import StateLoadError
13
 from opencombat.simulation.base import TileStrategySimulation
11
 from opencombat.simulation.base import TileStrategySimulation
12
+from opencombat.simulation.subject import TileSubject
14
 from opencombat.util import get_class_from_string_path
13
 from opencombat.util import get_class_from_string_path
14
+from opencombat.util import get_text_xml_element
15
 
15
 
16
 
16
 
17
 class State(object):
17
 class State(object):
23
     ) -> None:
23
     ) -> None:
24
         self._config = config
24
         self._config = config
25
         self._state_root = state_root
25
         self._state_root = state_root
26
-        self._subjects = None  # type: typing.List[Subject]
26
+        self._subjects = None  # type: typing.List[TileSubject]
27
         self._simulation = simulation
27
         self._simulation = simulation
28
 
28
 
29
     @property
29
     @property
30
-    def subjects(self) -> typing.List[Subject]:
30
+    def subjects(self) -> typing.List[TileSubject]:
31
         if self._subjects is None:
31
         if self._subjects is None:
32
             self._subjects = self._get_subjects()
32
             self._subjects = self._get_subjects()
33
 
33
 
34
         return self._subjects
34
         return self._subjects
35
 
35
 
36
-    def _get_subjects(self) -> typing.List[Subject]:
36
+    def _get_subjects(self) -> typing.List[TileSubject]:
37
         subjects = []
37
         subjects = []
38
         subject_elements = self._state_root.find('subjects').findall('subject')
38
         subject_elements = self._state_root.find('subjects').findall('subject')
39
 
39
 
44
                 subject_class_path,
44
                 subject_class_path,
45
             )
45
             )
46
             subject = subject_class(self._config, self._simulation)
46
             subject = subject_class(self._config, self._simulation)
47
+            self._fill_subject(subject, subject_element)
47
 
48
 
48
             # TODO BS 2018-06-13: Fill subject with property
49
             # TODO BS 2018-06-13: Fill subject with property
49
             subjects.append(subject)
50
             subjects.append(subject)
50
 
51
 
51
         return subjects
52
         return subjects
52
 
53
 
54
+    def _fill_subject(
55
+        self,
56
+        subject: TileSubject,
57
+        subject_element: Element,
58
+    ) -> None:
59
+        subject.position = tuple(
60
+            map(
61
+                int,
62
+                get_text_xml_element(subject_element, 'position').split(','),
63
+            ),
64
+        )
65
+        subject.direction = float(
66
+            get_text_xml_element(subject_element, 'direction'),
67
+        )
68
+
69
+        """
70
+        TODO:
71
+
72
+        properties={
73
+                 SELECTION_COLOR_RGB: DE_COLOR,
74
+                 FLAG: FLAG_DE,
75
+                 SIDE: 'AXIS',
76
+             }
77
+        """
78
+
53
 
79
 
54
 class StateLoader(object):
80
 class StateLoader(object):
55
     def __init__(
81
     def __init__(

+ 5 - 5
opencombat/state.xsd View File

52
 
52
 
53
     <xs:complexType name="subjecttype">
53
     <xs:complexType name="subjecttype">
54
         <xs:sequence>
54
         <xs:sequence>
55
-            <xs:element name="type" type="xs:string"/>
56
-            <xs:element name="position" type="positiontype"/>
57
-            <xs:element name="direction" type="directiontype"/>
58
-            <xs:element name="mode" type="modetype"/>
59
-            <xs:element name="side" type="sidetype"/>
55
+            <xs:element name="type" type="xs:string" minOccurs="1" />
56
+            <xs:element name="position" type="positiontype" minOccurs="1"/>
57
+            <xs:element name="direction" type="directiontype" minOccurs="1"/>
58
+            <xs:element name="mode" type="modetype" minOccurs="1"/>
59
+            <xs:element name="side" type="sidetype" minOccurs="1"/>
60
         </xs:sequence>
60
         </xs:sequence>
61
     </xs:complexType>
61
     </xs:complexType>
62
 
62
 

+ 25 - 0
opencombat/util.py View File

1
 # coding: utf-8
1
 # coding: utf-8
2
 import importlib
2
 import importlib
3
 
3
 
4
+from _elementtree import Element
5
+
6
+from opencombat.exception import NotFoundError
7
+
8
+__DEFAULT__ = '__DEFAULT__'
9
+
4
 
10
 
5
 def get_class_from_string_path(config, string_path: str) -> type:
11
 def get_class_from_string_path(config, string_path: str) -> type:
6
     """
12
     """
13
     class_name = string_path.split('.')[-1]
19
     class_name = string_path.split('.')[-1]
14
     module_ = importlib.import_module(module_address)
20
     module_ = importlib.import_module(module_address)
15
     return getattr(module_, class_name)
21
     return getattr(module_, class_name)
22
+
23
+
24
+def get_text_xml_element(
25
+    element: Element,
26
+    search_element_name: str,
27
+    default_value: str = __DEFAULT__,
28
+) -> str:
29
+    found = element.find(search_element_name)
30
+    if found is None:
31
+        if default_value == __DEFAULT__:
32
+            raise NotFoundError(
33
+                'Asked element "{}" not exist in {}'.format(
34
+                    search_element_name,
35
+                    str(element),
36
+                ),
37
+            )
38
+        return default_value
39
+
40
+    return found.text

+ 4 - 3
run.py View File

43
     subjects = TileStrategySubjects(simulation=simulation)
43
     subjects = TileStrategySubjects(simulation=simulation)
44
 
44
 
45
     if state_file_path:
45
     if state_file_path:
46
-        state_loader_builder = StateLoaderBuilder(config)
47
-        state_loader = state_loader_builder.get_state_loader(state_file_path)
48
-        subjects.extend(state_loader.get_subjects())
46
+        state_loader_builder = StateLoaderBuilder(config, simulation)
47
+        state_loader = state_loader_builder.get_state_loader()
48
+        state = state_loader.get_state(state_file_path)
49
+        subjects.extend(state.subjects)
49
 
50
 
50
     # for position in ((10, 2), (11, 3), (11, 4), (12, 5),):
51
     # for position in ((10, 2), (11, 3), (11, 4), (12, 5),):
51
     #     man = ManSubject(
52
     #     man = ManSubject(

+ 9 - 0
tests/test_state.py View File

3
 from synergine2.config import Config
3
 from synergine2.config import Config
4
 
4
 
5
 from opencombat.exception import StateLoadError
5
 from opencombat.exception import StateLoadError
6
+from opencombat.simulation.subject import ManSubject
6
 from opencombat.state import StateLoaderBuilder, StateLoader
7
 from opencombat.state import StateLoaderBuilder, StateLoader
7
 
8
 
8
 
9
 
54
     state_loader,
55
     state_loader,
55
 ):
56
 ):
56
     state = state_loader.get_state('tests/fixtures/state_ok.xml')
57
     state = state_loader.get_state('tests/fixtures/state_ok.xml')
58
+
57
     assert 2 == len(state.subjects)
59
     assert 2 == len(state.subjects)
60
+    assert isinstance(state.subjects[0], ManSubject)
61
+    assert isinstance(state.subjects[1], ManSubject)
62
+
63
+    assert (1, 1) == state.subjects[0].position
64
+    assert (10, 10) == state.subjects[1].position
65
+    assert 90.0 == state.subjects[0].direction
66
+    assert 270.0 == state.subjects[1].direction