Browse Source

state: fill subject

Bastien Sevajol 5 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,3 +19,7 @@ class WrongMode(OpenCombatException):
19 19
 
20 20
 class StateLoadError(OpenCombatException):
21 21
     pass
22
+
23
+
24
+class NotFoundError(OpenCombatException):
25
+    pass

+ 32 - 6
opencombat/state.py View File

@@ -1,17 +1,17 @@
1 1
 # coding: utf-8
2
-import importlib
3 2
 import typing
4
-from _elementtree import Element
5 3
 
4
+from _elementtree import Element
6 5
 from lxml import etree
7 6
 
8 7
 from synergine2.config import Config
9 8
 from synergine2.log import get_logger
10
-from synergine2.simulation import Subject
11 9
 
12 10
 from opencombat.exception import StateLoadError
13 11
 from opencombat.simulation.base import TileStrategySimulation
12
+from opencombat.simulation.subject import TileSubject
14 13
 from opencombat.util import get_class_from_string_path
14
+from opencombat.util import get_text_xml_element
15 15
 
16 16
 
17 17
 class State(object):
@@ -23,17 +23,17 @@ class State(object):
23 23
     ) -> None:
24 24
         self._config = config
25 25
         self._state_root = state_root
26
-        self._subjects = None  # type: typing.List[Subject]
26
+        self._subjects = None  # type: typing.List[TileSubject]
27 27
         self._simulation = simulation
28 28
 
29 29
     @property
30
-    def subjects(self) -> typing.List[Subject]:
30
+    def subjects(self) -> typing.List[TileSubject]:
31 31
         if self._subjects is None:
32 32
             self._subjects = self._get_subjects()
33 33
 
34 34
         return self._subjects
35 35
 
36
-    def _get_subjects(self) -> typing.List[Subject]:
36
+    def _get_subjects(self) -> typing.List[TileSubject]:
37 37
         subjects = []
38 38
         subject_elements = self._state_root.find('subjects').findall('subject')
39 39
 
@@ -44,12 +44,38 @@ class State(object):
44 44
                 subject_class_path,
45 45
             )
46 46
             subject = subject_class(self._config, self._simulation)
47
+            self._fill_subject(subject, subject_element)
47 48
 
48 49
             # TODO BS 2018-06-13: Fill subject with property
49 50
             subjects.append(subject)
50 51
 
51 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 80
 class StateLoader(object):
55 81
     def __init__(

+ 5 - 5
opencombat/state.xsd View File

@@ -52,11 +52,11 @@
52 52
 
53 53
     <xs:complexType name="subjecttype">
54 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 60
         </xs:sequence>
61 61
     </xs:complexType>
62 62
 

+ 25 - 0
opencombat/util.py View File

@@ -1,6 +1,12 @@
1 1
 # coding: utf-8
2 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 11
 def get_class_from_string_path(config, string_path: str) -> type:
6 12
     """
@@ -13,3 +19,22 @@ def get_class_from_string_path(config, string_path: str) -> type:
13 19
     class_name = string_path.split('.')[-1]
14 20
     module_ = importlib.import_module(module_address)
15 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,9 +43,10 @@ def main(
43 43
     subjects = TileStrategySubjects(simulation=simulation)
44 44
 
45 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 51
     # for position in ((10, 2), (11, 3), (11, 4), (12, 5),):
51 52
     #     man = ManSubject(

+ 9 - 0
tests/test_state.py View File

@@ -3,6 +3,7 @@ import pytest
3 3
 from synergine2.config import Config
4 4
 
5 5
 from opencombat.exception import StateLoadError
6
+from opencombat.simulation.subject import ManSubject
6 7
 from opencombat.state import StateLoaderBuilder, StateLoader
7 8
 
8 9
 
@@ -54,4 +55,12 @@ def test_state__ok__subjects(
54 55
     state_loader,
55 56
 ):
56 57
     state = state_loader.get_state('tests/fixtures/state_ok.xml')
58
+
57 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