Passed
Pull Request — master (#291)
by Marek
01:53
created

NewGlobalTaskDlg._processShips()   F

Complexity

Conditions 16

Size

Total Lines 27
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
eloc 23
nop 1
dl 0
loc 27
rs 2.4
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like osci.dialog.NewGlobalTaskDlg.NewGlobalTaskDlg._processShips() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
#
2
#  Copyright 2001 - 2016 Ludek Smid [http://www.ospace.net/]
3
#
4
#  This file is part of Outer Space.
5
#
6
#  Outer Space is free software; you can redistribute it and/or modify
7
#  it under the terms of the GNU General Public License as published by
8
#  the Free Software Foundation; either version 2 of the License, or
9
#  (at your option) any later version.
10
#
11
#  Outer Space is distributed in the hope that it will be useful,
12
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
#  GNU General Public License for more details.
15
#
16
#  You should have received a copy of the GNU General Public License
17
#  along with Outer Space; if not, write to the Free Software
18
#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
#
20
import math
21
22
import pygameui as ui
23
24
from ige import GameException
25
from ige.ospace import Rules
26
import ige.ospace.Const as Const
27
28
from osci import gdata, client, res
29
from TechInfoDlg import TechInfoDlg
30
from ConstructionDlg import ConstructionDlg
31
import Utils
32
import Filter
33
34
class NewGlobalTaskDlg:
35
36
    def __init__(self, app):
37
        self.app = app
38
        self.showShips = 1
39
        self.showOther = 0
40
        self.techID = 0
41
        self.showLevels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 99]
42
        self.techInfoDlg = TechInfoDlg(app)
43
        self.constructionDlg = ConstructionDlg(app)
44
        self.createUI()
45
        self.win.setTagAttr('ship', 'visible', 1)
46
        # set default sorting for technologies
47
        self.win.vTechs.setSort("text")
48
49
    def display(self, caller, queue, structToDemolish = Const.OID_NONE):
50
        if gdata.config.defaults.reportfinalization != None:
51
            val = gdata.config.defaults.reportfinalization
52
            self.win.vReportFin.checked = val == 'yes'
53
54
        self.caller = caller
55
        self.playerID = client.getPlayerID()
56
        self.maxTechLevel = 0
57
        self.quantity = 1
58
        self.queue = queue
59
        self.showTechs()
60
        self.win.show()
61
        gdata.updateDlgs.append(self)
62
63
    def hide(self):
64
        self.win.setStatus(_("Ready."))
65
        if self in gdata.updateDlgs:
66
            gdata.updateDlgs.remove(self)
67
        self.win.hide()
68
69
    def update(self):
70
        if self.win.visible:
71
            if self.showShips:
72
                self.win.vInfo.enabled = Utils.enableConstruction(client)
73
            self.showTechs()
74
75
    def _processProjects(self):
76
        items = []
77
        for techID in client.getPlayer().techs.keys():
78
            tech = client.getTechInfo(techID)
79
80
            if not tech.isProject or tech.globalDisabled or tech.level not in self.showLevels:
81
                continue
82
83
            item = ui.Item(tech.name,
84
                           tLevel=tech.level,
85
                           tProd=tech.buildProd,
86
                           techID=techID,
87
                           tIsShip=0,
88
            )
89
            items.append(item)
90
        return items
91
92
    def _processShips(self):
93
        items = []
94
        _filterShipSize = Filter.Filter()
95
        _filterShipSize.add((lambda x: x.combatClass == 0) if self.win.vSmall.checked else Filter.false)
96
        _filterShipSize.add((lambda x: x.combatClass == 1) if self.win.vMedium.checked else Filter.false)
97
        _filterShipSize.add((lambda x: x.combatClass == 2) if self.win.vLarge.checked else Filter.false)
98
        _filterShipMilitary = Filter.Filter()
99
        _filterShipMilitary.add((lambda x: x.isMilitary) if self.win.vMilShip.checked else Filter.false)
100
        _filterShipMilitary.add((lambda x: not x.isMilitary) if self.win.vCivShip.checked else Filter.false)
101
102
        player = client.getPlayer()
103
        for designID in player.shipDesigns.keys():
104
            tech = player.shipDesigns[designID]
105
            if not _filterShipSize.OR(tech) or not _filterShipMilitary.OR(tech) or tech.level not in self.showLevels:
106
                continue
107
            if tech.upgradeTo != Const.OID_NONE:
108
                # skip ships that are set to upgrade
109
                continue
110
111
            item = ui.Item(tech.name,
112
                           tLevel=tech.level,
113
                           tProd=tech.buildProd,
114
                           techID=designID,
115
                           tIsShip=1,
116
                          )
117
            items.append(item)
118
        return items
119
120
    def showTechs(self):
121
        # techs
122
        items = []
123
        select = None
124
125
        if self.showOther:
126
            items += self._processProjects()
127
        if self.showShips:
128
            items += self._processShips()
129
130
        # special handling for ships
131
        # sort it by level and then by name
132
        items.sort(key=lambda a: (100 - a.tLevel, a.text))
133
        self.win.vTechs.items = items
134
        self.win.vTechs.itemsChanged()
135
        for item in items:
136
            self.maxTechLevel = max(self.maxTechLevel, item.tLevel)
137
            if item.techID == self.techID:
138
                self.win.vTechs.selectItem(item)
139
        # filter
140
        for i in range(1, 10):
141
            widget = getattr(self.win, 'vLevel%d' % i)
142
            if i in self.showLevels and i <= self.maxTechLevel:
143
                widget.visible = 1
144
                widget.pressed = 1
145
            elif i not in self.showLevels and i <= self.maxTechLevel:
146
                widget.visible = 1
147
                widget.pressed = 0
148
            else:
149
                widget.visible = 0
150
        self.win.vShipsToggle.pressed = self.showShips
151
        self.win.vOtherToggle.pressed = self.showOther
152
        # quantity
153
        self.win.vQuantity.text = str(self.quantity)
154
155 View Code Duplication
    def showSlots(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
156
        # techs
157
        items = []
158
        techs = {}
159
        if self.showStructures:
160
            player = client.getPlayer()
161
            target = client.get(self.targetID, noUpdate=1)
162
            if hasattr(target, 'slots') and target.owner == player.oid:
163
                if len(target.slots) < target.plSlots:
164
                    item = ui.Item(_("Free slot"), techID=0)
165
                    items.append(item)
166
                for struct in target.slots:
167
                    if not struct[Const.STRUCT_IDX_TECHID] in techs:
168
                        techs[struct[Const.STRUCT_IDX_TECHID]] = 1
169
                    else:
170
                        techs[struct[Const.STRUCT_IDX_TECHID]] += 1
171
                for tech in techs.keys():
172
                    techInfo = client.getTechInfo(tech)
173
                    item = ui.Item("%s (%d)" % (techInfo.name, techs[tech]), techID=tech)
174
                    items.append(item)
175
176
        self.win.vTSlots.items = items
177
        self.win.vTSlots.itemsChanged()
178
        self.structToDemolish = Const.OID_NONE
179
180
181
    def onSelectTech(self, widget, action, data):
182
        self.techID = data.techID
183
184
    def onToggleLevel(self, widget, action, data):
185
        i = widget.data
186
        if i in self.showLevels:
187
            self.showLevels.remove(i)
188
        else:
189
            self.showLevels.append(i)
190
        self.update()
191
192
    def onCancel(self, widget, action, data):
193
        self.hide()
194
195
    def onConstruct(self, widget, action, data):
196
        if not self.techID:
197
            self.win.setStatus(_('Select technology to construct.'))
198
            return
199
        try:
200
            self.quantity = int(self.win.vQuantity.text)
201
        except ValueError:
202
            self.win.setStatus(_('Specify quantity (1, 2, 3, ...).'))
203
            return
204
        try:
205
            self.win.setStatus(_('Executing START CONSTRUCTION command...'))
206
            player = client.getPlayer()
207
208
            player.prodQueues[self.queue], player.stratRes = client.cmdProxy.startGlobalConstruction(self.playerID, self.techID, self.quantity, self.techID < 1000, self.win.vReportFin.checked, self.queue)
209
            self.win.setStatus(_('Command has been executed.'))
210
        except GameException, e:
211
            self.win.setStatus(e.args[0])
212
            return
213
        self.hide()
214
        self.caller.update()
215
216
    def onToggleShips(self, widget, action, data):
217
        self.quantity = int(self.win.vQuantity.text)
218
        self.showStructures = 0
219
        self.showShips = 1
220
        self.showOther = 0
221
        self.win.setTagAttr('struct', 'visible', 0)
222
        self.win.setTagAttr('ship', 'visible', 1)
223
        self.update()
224
225
    def onToggleOther(self, widget, action, data):
226
        self.quantity = int(self.win.vQuantity.text)
227
        self.showStructures = 0
228
        self.showShips = 0
229
        self.showOther = 1
230
        self.win.setTagAttr('struct', 'visible', 0)
231
        self.win.setTagAttr('ship', 'visible', 0)
232
        self.update()
233
234
    def onInfo(self, widget, action, data):
235
        if len(self.win.vTechs.selection) == 0:
236
            return
237
        task = self.win.vTechs.selection[0]
238
        if not task.tIsShip:
239
            self.techInfoDlg.display(task.techID)
240
        else:
241
            self.constructionDlg.selectedDesignID = task.techID;
242
            self.constructionDlg.display()
243
244
    def onFilter(self, widget, action, data):
245
        self.update()
246
247
    def createUI(self):
248
        w, h = gdata.scrnSize
249
        cols = 20
250
        rows = 25
251
        dlgWidth = cols * 20 + 4
252
        dlgHeight = rows * 20 + 4
253
        self.win = ui.Window(self.app,
254
                             modal=1,
255
                             escKeyClose=1,
256
                             movable=0,
257
                             title=_('Select new global task'),
258
                             rect=ui.Rect((w - dlgWidth) / 2, (h - dlgHeight) / 2, dlgWidth, dlgHeight),
259
                             layoutManager=ui.SimpleGridLM(),
260
                             tabChange=True
261
        )
262
        self.win.subscribeAction('*', self)
263
        ui.Title(self.win, layout=(0, 0, 20, 1), text=_('Technology'),
264
                 align=ui.ALIGN_W, font='normal-bold')
265
        ui.Listbox(self.win, layout=(0, 1, 20, 19), id='vTechs',
266
                   columns=((_('Name'), 'text', 14, ui.ALIGN_W), (_('Lvl'), 'tLevel', 2, ui.ALIGN_E),
267
                   (_('Constr'), 'tProd', 3, ui.ALIGN_E)),
268
                   columnLabels=1, action='onSelectTech')
269
        # filter
270
        ui.Button(self.win, layout=(0, 20, 3, 1), text=_('Ships'), toggle=1,
271
                  id='vShipsToggle', action='onToggleShips')
272
        ui.Button(self.win, layout=(3, 20, 3, 1), text=_('Misc'), toggle=1,
273
                  id='vOtherToggle', action='onToggleOther')
274
        ui.Button(self.win, layout=(6, 20, 1, 1), text=_('1'), id='vLevel1',
275
                  toggle=1, action='onToggleLevel', data=1)
276
        ui.Button(self.win, layout=(7, 20, 1, 1), text=_('2'), id='vLevel2',
277
                  toggle=1, action='onToggleLevel', data=2)
278
        ui.Button(self.win, layout=(8, 20, 1, 1), text=_('3'), id='vLevel3',
279
                  toggle=1, action='onToggleLevel', data=3)
280
        ui.Button(self.win, layout=(9, 20, 1, 1), text=_('4'), id='vLevel4',
281
                  toggle=1, action='onToggleLevel', data=4)
282
        ui.Button(self.win, layout=(10, 20, 1, 1), text=_('5'), id='vLevel5',
283
                  toggle=1, action='onToggleLevel', data=5)
284
        ui.Button(self.win, layout=(11, 20, 1, 1), text=_('6'), id='vLevel6',
285
                  toggle=1, action='onToggleLevel', data=6)
286
        ui.Button(self.win, layout=(12, 20, 1, 1), text=_('7'), id='vLevel7',
287
                  toggle=1, action='onToggleLevel', data=7)
288
        ui.Button(self.win, layout=(13, 20, 1, 1), text=_('8'), id='vLevel8',
289
                  toggle=1, action='onToggleLevel', data=8)
290
        ui.Button(self.win, layout=(14, 20, 1, 1), text=_('9'), id='vLevel9',
291
                  toggle=1, action='onToggleLevel', data=9)
292
        ui.Button(self.win, layout=(15, 20, 4, 1), text=_('Info'), action='onInfo',
293
                  id='vInfo')
294
        # ship types
295
        ui.Check(self.win, layout=(0, 21, 4, 1), text=_('Small'), tags=['ship'],
296
                 id='vSmall', checked=1, align=ui.ALIGN_W, action='onFilter')
297
        ui.Check(self.win, layout=(4, 21, 4, 1), text=_('Medium'), tags=['ship'],
298
                 id='vMedium', checked=1, align=ui.ALIGN_W, action='onFilter')
299
        ui.Check(self.win, layout=(8, 21, 4, 1), text=_('Large'), tags=['ship'],
300
                 id='vLarge', checked=1, align=ui.ALIGN_W, action='onFilter')
301
        ui.Check(self.win, layout=(12, 21, 4, 1), text=_('Civilian'), tags=['ship'],
302
                 id='vCivShip', checked=1, align=ui.ALIGN_W, action='onFilter')
303
        ui.Check(self.win, layout=(16, 21, 4, 1), text=_('Military'), tags=['ship'],
304
                 id='vMilShip', checked=1, align=ui.ALIGN_W, action='onFilter')
305
        # build
306
        ui.Label(self.win, layout=(0, 22, 5, 1), text=_('Quantity'), align=ui.ALIGN_W)
307
        ui.Entry(self.win, layout=(5, 22, 6, 1), id='vQuantity', align=ui.ALIGN_E, orderNo=1)
308
        ui.Check(self.win, layout=(13, 22, 7, 1), id='vReportFin', text=_('Report finalization'))
309
        ui.Title(self.win, layout=(0, 23, 10, 1), id='vStatusBar', align=ui.ALIGN_W)
310
        ui.TitleButton(self.win, layout=(10, 23, 5, 1), text=_('Cancel'), action='onCancel')
311
        ui.TitleButton(self.win, layout=(15, 23, 5, 1), text=_('Construct'), action='onConstruct')
312