Passed
Pull Request — master (#291)
by Marek
17:46 queued 10:40
created

NewGlobalTaskDlg._processShips()   F

Complexity

Conditions 16

Size

Total Lines 26
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
eloc 23
nop 1
dl 0
loc 26
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
            items.append(item)
89
        return items
90
91
    def _processShips(self):
92
        items = []
93
        _filterShipSize = Filter.Filter()
94
        _filterShipSize.add((lambda x: x.combatClass == 0) if self.win.vSmall.checked else Filter.false)
95
        _filterShipSize.add((lambda x: x.combatClass == 1) if self.win.vMedium.checked else Filter.false)
96
        _filterShipSize.add((lambda x: x.combatClass == 2) if self.win.vLarge.checked else Filter.false)
97
        _filterShipMilitary = Filter.Filter()
98
        _filterShipMilitary.add((lambda x: x.isMilitary) if self.win.vMilShip.checked else Filter.false)
99
        _filterShipMilitary.add((lambda x: not x.isMilitary) if self.win.vCivShip.checked else Filter.false)
100
101
        player = client.getPlayer()
102
        for designID in player.shipDesigns.keys():
103
            tech = player.shipDesigns[designID]
104
            if not _filterShipSize.OR(tech) or not _filterShipMilitary.OR(tech) or tech.level not in self.showLevels:
105
                continue
106
            if tech.upgradeTo != Const.OID_NONE:
107
                # skip ships that are set to upgrade
108
                continue
109
110
            item = ui.Item(tech.name,
111
                           tLevel=tech.level,
112
                           tProd=tech.buildProd,
113
                           techID=designID,
114
                           tIsShip=1)
115
            items.append(item)
116
        return items
117
118
    def showTechs(self):
119
        # techs
120
        items = []
121
        select = None
122
123
        if self.showOther:
124
            items += self._processProjects()
125
        if self.showShips:
126
            items += self._processShips()
127
128
        # special handling for ships
129
        # sort it by level and then by name
130
        items.sort(key=lambda a: (100 - a.tLevel, a.text))
131
        self.win.vTechs.items = items
132
        self.win.vTechs.itemsChanged()
133
        for item in items:
134
            self.maxTechLevel = max(self.maxTechLevel, item.tLevel)
135
            if item.techID == self.techID:
136
                self.win.vTechs.selectItem(item)
137
        # filter
138
        for i in range(1, 10):
139
            widget = getattr(self.win, 'vLevel%d' % i)
140
            if i in self.showLevels and i <= self.maxTechLevel:
141
                widget.visible = 1
142
                widget.pressed = 1
143
            elif i not in self.showLevels and i <= self.maxTechLevel:
144
                widget.visible = 1
145
                widget.pressed = 0
146
            else:
147
                widget.visible = 0
148
        self.win.vShipsToggle.pressed = self.showShips
149
        self.win.vOtherToggle.pressed = self.showOther
150
        # quantity
151
        self.win.vQuantity.text = str(self.quantity)
152
153 View Code Duplication
    def showSlots(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
154
        # techs
155
        items = []
156
        techs = {}
157
        if self.showStructures:
158
            player = client.getPlayer()
159
            target = client.get(self.targetID, noUpdate=1)
160
            if hasattr(target, 'slots') and target.owner == player.oid:
161
                if len(target.slots) < target.plSlots:
162
                    item = ui.Item(_("Free slot"), techID=0)
163
                    items.append(item)
164
                for struct in target.slots:
165
                    if not struct[Const.STRUCT_IDX_TECHID] in techs:
166
                        techs[struct[Const.STRUCT_IDX_TECHID]] = 1
167
                    else:
168
                        techs[struct[Const.STRUCT_IDX_TECHID]] += 1
169
                for tech in techs.keys():
170
                    techInfo = client.getTechInfo(tech)
171
                    item = ui.Item("%s (%d)" % (techInfo.name, techs[tech]), techID=tech)
172
                    items.append(item)
173
174
        self.win.vTSlots.items = items
175
        self.win.vTSlots.itemsChanged()
176
        self.structToDemolish = Const.OID_NONE
177
178
179
    def onSelectTech(self, widget, action, data):
180
        self.techID = data.techID
181
182
    def onToggleLevel(self, widget, action, data):
183
        i = widget.data
184
        if i in self.showLevels:
185
            self.showLevels.remove(i)
186
        else:
187
            self.showLevels.append(i)
188
        self.update()
189
190
    def onCancel(self, widget, action, data):
191
        self.hide()
192
193
    def onConstruct(self, widget, action, data):
194
        if not self.techID:
195
            self.win.setStatus(_('Select technology to construct.'))
196
            return
197
        try:
198
            self.quantity = int(self.win.vQuantity.text)
199
        except ValueError:
200
            self.win.setStatus(_('Specify quantity (1, 2, 3, ...).'))
201
            return
202
        try:
203
            self.win.setStatus(_('Executing START CONSTRUCTION command...'))
204
            player = client.getPlayer()
205
206
            player.prodQueues[self.queue], player.stratRes = client.cmdProxy.startGlobalConstruction(self.playerID, self.techID, self.quantity, self.techID < 1000, self.win.vReportFin.checked, self.queue)
207
            self.win.setStatus(_('Command has been executed.'))
208
        except GameException, e:
209
            self.win.setStatus(e.args[0])
210
            return
211
        self.hide()
212
        self.caller.update()
213
214
    def onToggleShips(self, widget, action, data):
215
        self.quantity = int(self.win.vQuantity.text)
216
        self.showStructures = 0
217
        self.showShips = 1
218
        self.showOther = 0
219
        self.win.setTagAttr('struct', 'visible', 0)
220
        self.win.setTagAttr('ship', 'visible', 1)
221
        self.update()
222
223
    def onToggleOther(self, widget, action, data):
224
        self.quantity = int(self.win.vQuantity.text)
225
        self.showStructures = 0
226
        self.showShips = 0
227
        self.showOther = 1
228
        self.win.setTagAttr('struct', 'visible', 0)
229
        self.win.setTagAttr('ship', 'visible', 0)
230
        self.update()
231
232
    def onInfo(self, widget, action, data):
233
        if len(self.win.vTechs.selection) == 0:
234
            return
235
        task = self.win.vTechs.selection[0]
236
        if not task.tIsShip:
237
            self.techInfoDlg.display(task.techID)
238
        else:
239
            self.constructionDlg.selectedDesignID = task.techID;
240
            self.constructionDlg.display()
241
242
    def onFilter(self, widget, action, data):
243
        self.update()
244
245
    def createUI(self):
246
        w, h = gdata.scrnSize
247
        cols = 20
248
        rows = 25
249
        dlgWidth = cols * 20 + 4
250
        dlgHeight = rows * 20 + 4
251
        self.win = ui.Window(self.app,
252
                             modal=1,
253
                             escKeyClose=1,
254
                             movable=0,
255
                             title=_('Select new global task'),
256
                             rect=ui.Rect((w - dlgWidth) / 2, (h - dlgHeight) / 2, dlgWidth, dlgHeight),
257
                             layoutManager=ui.SimpleGridLM(),
258
                             tabChange=True)
259
        self.win.subscribeAction('*', self)
260
        ui.Title(self.win, layout=(0, 0, 20, 1), text=_('Technology'),
261
                 align=ui.ALIGN_W, font='normal-bold')
262
        ui.Listbox(self.win, layout=(0, 1, 20, 19), id='vTechs',
263
                   columns=((_('Name'), 'text', 14, ui.ALIGN_W), (_('Lvl'), 'tLevel', 2, ui.ALIGN_E),
264
                   (_('Constr'), 'tProd', 3, ui.ALIGN_E)),
265
                   columnLabels=1, action='onSelectTech')
266
        # filter
267
        ui.Button(self.win, layout=(0, 20, 3, 1), text=_('Ships'), toggle=1,
268
                  id='vShipsToggle', action='onToggleShips')
269
        ui.Button(self.win, layout=(3, 20, 3, 1), text=_('Misc'), toggle=1,
270
                  id='vOtherToggle', action='onToggleOther')
271
        ui.Button(self.win, layout=(6, 20, 1, 1), text=_('1'), id='vLevel1',
272
                  toggle=1, action='onToggleLevel', data=1)
273
        ui.Button(self.win, layout=(7, 20, 1, 1), text=_('2'), id='vLevel2',
274
                  toggle=1, action='onToggleLevel', data=2)
275
        ui.Button(self.win, layout=(8, 20, 1, 1), text=_('3'), id='vLevel3',
276
                  toggle=1, action='onToggleLevel', data=3)
277
        ui.Button(self.win, layout=(9, 20, 1, 1), text=_('4'), id='vLevel4',
278
                  toggle=1, action='onToggleLevel', data=4)
279
        ui.Button(self.win, layout=(10, 20, 1, 1), text=_('5'), id='vLevel5',
280
                  toggle=1, action='onToggleLevel', data=5)
281
        ui.Button(self.win, layout=(11, 20, 1, 1), text=_('6'), id='vLevel6',
282
                  toggle=1, action='onToggleLevel', data=6)
283
        ui.Button(self.win, layout=(12, 20, 1, 1), text=_('7'), id='vLevel7',
284
                  toggle=1, action='onToggleLevel', data=7)
285
        ui.Button(self.win, layout=(13, 20, 1, 1), text=_('8'), id='vLevel8',
286
                  toggle=1, action='onToggleLevel', data=8)
287
        ui.Button(self.win, layout=(14, 20, 1, 1), text=_('9'), id='vLevel9',
288
                  toggle=1, action='onToggleLevel', data=9)
289
        ui.Button(self.win, layout=(15, 20, 4, 1), text=_('Info'), action='onInfo',
290
                  id='vInfo')
291
        # ship types
292
        ui.Check(self.win, layout=(0, 21, 4, 1), text=_('Small'), tags=['ship'],
293
                 id='vSmall', checked=1, align=ui.ALIGN_W, action='onFilter')
294
        ui.Check(self.win, layout=(4, 21, 4, 1), text=_('Medium'), tags=['ship'],
295
                 id='vMedium', checked=1, align=ui.ALIGN_W, action='onFilter')
296
        ui.Check(self.win, layout=(8, 21, 4, 1), text=_('Large'), tags=['ship'],
297
                 id='vLarge', checked=1, align=ui.ALIGN_W, action='onFilter')
298
        ui.Check(self.win, layout=(12, 21, 4, 1), text=_('Civilian'), tags=['ship'],
299
                 id='vCivShip', checked=1, align=ui.ALIGN_W, action='onFilter')
300
        ui.Check(self.win, layout=(16, 21, 4, 1), text=_('Military'), tags=['ship'],
301
                 id='vMilShip', checked=1, align=ui.ALIGN_W, action='onFilter')
302
        # build
303
        ui.Label(self.win, layout=(0, 22, 5, 1), text=_('Quantity'), align=ui.ALIGN_W)
304
        ui.Entry(self.win, layout=(5, 22, 6, 1), id='vQuantity', align=ui.ALIGN_E, orderNo=1)
305
        ui.Check(self.win, layout=(13, 22, 7, 1), id='vReportFin', text=_('Report finalization'))
306
        ui.Title(self.win, layout=(0, 23, 10, 1), id='vStatusBar', align=ui.ALIGN_W)
307
        ui.TitleButton(self.win, layout=(10, 23, 5, 1), text=_('Cancel'), action='onCancel')
308
        ui.TitleButton(self.win, layout=(15, 23, 5, 1), text=_('Construct'), action='onConstruct')
309