Completed
Push — master ( 62163d...101101 )
by Oleksandr
01:13
created

il2fb.parsers.mission.sections.structure_class_by_unit_type()   A

Complexity

Conditions 1

Size

Total Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1
Metric Value
cc 1
dl 0
loc 2
ccs 2
cts 2
cp 1
crap 1
rs 10
1
# -*- coding: utf-8 -*-
2
3 1
from il2fb.commons import UnitTypes
4 1
from il2fb.commons.spatial import Point2D
5 1
from il2fb.commons.structures import BaseStructure
6
7 1
from ..constants import NULL, IS_STATIONARY_AIRCRAFT_RESTORABLE
8 1
from ..converters import (
9
    to_bool, to_skill, to_air_force, to_unit_type, to_belligerent,
10
)
11 1
from . import CollectingParser
12
13
14 1
class StationaryObject(BaseStructure):
15 1
    __slots__ = [
16
        'id', 'belligerent', 'code', 'pos', 'rotation_angle', 'type',
17
    ]
18
19 1
    def __init__(self, id, belligerent, code, pos, rotation_angle, type):
20 1
        self.id = id
21 1
        self.belligerent = belligerent
22 1
        self.code = code
23 1
        self.pos = pos
24 1
        self.rotation_angle = rotation_angle
25 1
        self.type = type
26
27 1
    def __repr__(self):
28 1
        return "<{0} '{1}'>".format(self.__class__.__name__, self.id)
29
30
31 1
class StationaryArtillery(StationaryObject):
32 1
    __slots__ = StationaryObject.__slots__ + [
33
        'awakening_time', 'range', 'skill', 'use_spotter',
34
    ]
35
36 1
    def __init__(self, id, belligerent, code, pos, rotation_angle, type,
37
                 awakening_time, range, skill, use_spotter):
38 1
        super(StationaryArtillery, self).__init__(
39
            id, belligerent, code, pos, rotation_angle, type)
40 1
        self.awakening_time = awakening_time
41 1
        self.range = range
42 1
        self.skill = skill
43 1
        self.use_spotter = use_spotter
44
45
46 1
class StationaryAircraft(StationaryObject):
47 1
    __slots__ = StationaryObject.__slots__ + [
48
        'air_force', 'allows_spawning', 'is_restorable', 'skin',
49
        'show_markings',
50
    ]
51
52 1
    def __init__(self, id, belligerent, code, pos, rotation_angle, type,
53
                 air_force, allows_spawning, is_restorable, skin,
54
                 show_markings):
55 1
        super(StationaryAircraft, self).__init__(
56
            id, belligerent, code, pos, rotation_angle, type)
57 1
        self.air_force = air_force
58 1
        self.allows_spawning = allows_spawning
59 1
        self.is_restorable = is_restorable
60 1
        self.skin = skin
61 1
        self.show_markings = show_markings
62
63
64 1
class StationaryShip(StationaryObject):
65 1
    __slots__ = StationaryObject.__slots__ + [
66
        'awakening_time', 'recharge_time', 'skill',
67
    ]
68
69 1
    def __init__(self, id, belligerent, code, pos, rotation_angle, type,
70
                 awakening_time, recharge_time, skill):
71 1
        super(StationaryShip, self).__init__(
72
            id, belligerent, code, pos, rotation_angle, type)
73 1
        self.awakening_time = awakening_time
74 1
        self.recharge_time = recharge_time
75 1
        self.skill = skill
76
77
78 1
__UNIT_TYPES_MAP = {
79
    UnitTypes.aircraft: StationaryAircraft,
80
    UnitTypes.artillery: StationaryArtillery,
81
    UnitTypes.ship: StationaryShip,
82
}
83
84
85 1
def structure_class_by_unit_type(value):
86 1
    return __UNIT_TYPES_MAP.get(value, StationaryObject)
87
88
89 1
class NStationarySectionParser(CollectingParser):
90
    """
91
    Parses ``NStationary`` section.
92
    View :ref:`detailed description <nstationary-section>`.
93
    """
94
95 1
    def check_section_name(self, section_name):
96 1
        return section_name == "NStationary"
97
98 1
    def __parse_artillery(params):
99
        """
100
        Parse additional options for ``artillery`` type.
101
        """
102 1
        try:
103 1
            awakening_time, the_range, skill, use_spotter = params
104 1
            skill = to_skill(skill)
105 1
            use_spotter = to_bool(use_spotter)
106 1
        except ValueError:
107 1
            try:
108 1
                awakening_time, the_range = params
109 1
            except ValueError:
110 1
                awakening_time, the_range = params[0], 0
111 1
            skill, use_spotter = None, False
112
113 1
        return {
114
            'awakening_time': float(awakening_time),
115
            'range': int(the_range),
116
            'skill': skill,
117
            'use_spotter': use_spotter,
118
        }
119
120 1
    def __parse_aircraft(params):
121
        """
122
        Parse additional options for ``planes`` type.
123
        """
124 1
        try:
125 1
            air_force, allows_spawning__restorable = params[1:3]
126 1
            skin, show_markings = params[4:]
127 1
        except ValueError:
128 1
            air_force, allows_spawning__restorable = None, 0
129 1
            skin, show_markings = params[1:]
130
131 1
        is_restorable = allows_spawning__restorable == IS_STATIONARY_AIRCRAFT_RESTORABLE
132 1
        skin = None if skin == NULL else skin
133
134 1
        return {
135
            'air_force': to_air_force(air_force),
136
            'allows_spawning': to_bool(allows_spawning__restorable),
137
            'is_restorable': is_restorable,
138
            'skin': skin,
139
            'show_markings': to_bool(show_markings),
140
        }
141
142 1
    def __parse_ship(params):
143
        """
144
        Parse additional options for ``ships`` type.
145
        """
146 1
        awakening_time, skill, recharge_time = params[1:]
147 1
        return {
148
            'awakening_time': float(awakening_time),
149
            'recharge_time': float(recharge_time),
150
            'skill': to_skill(skill),
151
        }
152
153 1
    __subparsers = {
154
        UnitTypes.aircraft: __parse_aircraft,
155
        UnitTypes.artillery: __parse_artillery,
156
        UnitTypes.ship: __parse_ship,
157
    }
158
159 1
    def parse_line(self, line):
160 1
        params = line.split()
161
162 1
        oid, object_name, belligerent = params[0], params[1], params[2]
163 1
        pos = params[3:5]
164 1
        rotation_angle = params[5]
165 1
        params = params[6:]
166
167 1
        unit_type = self._get_type(object_name)
168 1
        info = {
169
            'id': oid,
170
            'belligerent': to_belligerent(belligerent),
171
            'code': self._get_code(object_name),
172
            'pos': Point2D(*pos),
173
            'rotation_angle': float(rotation_angle),
174
            'type': unit_type,
175
        }
176
177 1
        subparser = self.__subparsers.get(unit_type)
178 1
        if subparser:
179 1
            info.update(subparser(params))
180
181 1
        structure_class = structure_class_by_unit_type(unit_type)
182 1
        self.data.append(structure_class(**info))
183
184 1
    def _get_type(self, object_name):
185 1
        type_name = self._get_type_name(object_name)
186 1
        try:
187 1
            return to_unit_type(type_name)
188 1
        except:
189
            # Use original string as object's type
190 1
            return type_name
191
192 1
    @staticmethod
193
    def _get_type_name(object_name):
194 1
        if object_name.startswith('ships'):
195 1
            return "ships"
196
        else:
197 1
            start = object_name.index('.') + 1
198 1
            stop = object_name.rindex('.')
199 1
            return object_name[start:stop]
200
201 1
    @staticmethod
202
    def _get_code(code):
203 1
        start = code.index('$') + 1
204 1
        return code[start:]
205
206 1
    def clean(self):
207
        return {'stationary': self.data}
208