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

PlanetsOverviewDlg._shallShow()   F

Complexity

Conditions 17

Size

Total Lines 17
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 17
eloc 17
nop 3
dl 0
loc 17
rs 1.8
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like osci.dialog.PlanetsOverviewDlg.PlanetsOverviewDlg._shallShow() 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
21
import pygameui as ui
22
from osci.StarMapWidget import StarMapWidget
23
from osci import gdata, res, client, sequip
24
import ige.ospace.Const as Const
25
from ige.ospace import ShipUtils, Rules
26
from ige import GameException
27
import math
28
29
class PlanetsOverviewDlg:
30
31
    def __init__(self, app):
32
        self.app = app
33
        self.showMine = 1
34
        self.showColonizable = 0
35
        self.showOtherPlayers = 0
36
        self.showUncolonizable = 0
37
        self.createUI()
38
39
    def display(self):
40
        self.show()
41
        self.win.show()
42
        # register for updates
43
        if self not in gdata.updateDlgs:
44
            gdata.updateDlgs.append(self)
45
46
    def hide(self):
47
        self.win.setStatus(_("Ready."))
48
        self.win.hide()
49
        # unregister updates
50
        if self in gdata.updateDlgs:
51
            gdata.updateDlgs.remove(self)
52
53
    def update(self):
54
        self.show()
55
56
    def _shallShow(self, planet, player):
57
        ok = 0
58
        if hasattr(planet, 'owner'):
59
            if self.showMine and planet.owner == player.oid:
60
                ok = 1
61
            elif self.showOtherPlayers and planet.owner != Const.OID_NONE and planet.owner != player.oid:
62
                ok = 1
63
            elif self.showColonizable and planet.owner == Const.OID_NONE and planet.plType not in ('G', 'A'):
64
                ok = 1
65
            elif self.showUncolonizable and planet.plType in ('G', 'A'):
66
                ok = 1
67
        elif hasattr(planet, 'plType'):
68
            if self.showColonizable and planet.plType not in ('G', 'A'):
69
                ok = 1
70
            if self.showUncolonizable and planet.plType in ('G', 'A'):
71
                ok = 1
72
        return ok == 1
73
74
    def _getTaskProd(self, task, tech, planetID):
75
        anotherPlanet = Rules.buildOnAnotherPlanetMod if task.targetID != planetID else 1
76
77
        prodFirst = tech.buildProd * anotherPlanet - task.currProd
78
        prodNext = (task.quantity - 1) * tech.buildProd * anotherPlanet
79
        return prodFirst, prodNext
80
81
    def _processProdQueue(self, planet):
82
        player = client.getPlayer()
83
84
        if planet.prodQueue and planet.effProdProd > 0:
85
            index = 0
86
            totalProd = 0
87
            for task in planet.prodQueue:
88
                if task.isShip:
89
                    tech = player.shipDesigns[task.techID]
90
                else:
91
                    tech = client.getFullTechInfo(task.techID)
92
                if index == 0:
93
                    constrInfo = tech.name
94
                prodFirst, prodNext = self._getTaskProd(task, tech, planet.oid)
95
                if index == 0:
96
                    etc = math.ceil(float(prodFirst) / planet.effProdProd)
97
                totalProd += prodFirst + prodNext
98
                index += 1
99
            etc = res.formatTime(etc)
1 ignored issue
show
introduced by
The variable etc does not seem to be defined for all execution paths.
Loading history...
100
            totalEtc = res.formatTime(math.ceil(float(totalProd) / planet.effProdProd))
101
        elif planet.prodQueue:
102
            task = planet.prodQueue[0]
103
            if task.isShip:
104
                tech = player.shipDesigns[task.techID]
105
            else:
106
                tech = client.getTechInfo(task.techID)
107
            constrInfo = tech.name
108
            etc = _('N/A')
109
            totalEtc = _("N/A")
110
        else:
111
            constrInfo = _("-")
112
            etc = "-"
113
            totalEtc = _("-")
114
        return constrInfo, etc, totalEtc
1 ignored issue
show
introduced by
The variable constrInfo does not seem to be defined for all execution paths.
Loading history...
115
116
117
    def show(self):
118
        player = client.getPlayer()
119
120
        items = []
121
        for planetID in client.db.keys():
122
            planet = client.get(planetID, noUpdate=1)
123
            # skip non-planets
124
            if not hasattr(planet, "type") or planet.type != Const.T_PLANET:
125
                continue
126
            if not self._shallShow(planet, player):
127
                continue
128
            # fill in data
129
            ownerID = getattr(planet, 'owner', Const.OID_NONE)
130
            if hasattr(planet, 'owner') and planet.owner == player.oid:
131
                constrInfo, etc, totalEtc = self._processProdQueue(planet)
132
            else:
133
                constrInfo = '?'
134
                etc = '?'
135
                totalEtc = '?'
136
            # used slots
137
            try:
138
                freeSlots = planet.plSlots - len(planet.slots)
139
            except AttributeError:
140
                freeSlots = '?'
141
            # morale
142
            try:
143
                morale = int(planet.morale)
144
            except AttributeError:
145
                morale = "?"
146
147
            plType = gdata.planetTypes[getattr(planet, 'plType', None)]
148
            # list item
149
            item = ui.Item(getattr(planet, 'name', res.getUnknownName()),
150
                           tPlType=_(plType),
151
                           tPlBio=getattr(planet, 'plBio', '?'),
152
                           tPlMin=getattr(planet, 'plMin', '?'),
153
                           tPlEn=getattr(planet, 'plEn', '?'),
154
                           tChangeBio=getattr(planet, 'changeBio', '?'),
155
                           tChangeEn=getattr(planet, 'changeEn', '?'),
156
                           tETC=etc,
157
                           tTotalETC=totalEtc,
158
                           tConstrInfo=constrInfo,
159
                           tFree=freeSlots,
160
                           tMorale=morale,
161
                           tSpace=getattr(planet, 'plSlots', '?'),
162
                           tDiam=getattr(planet, 'plDiameter', 0) / 1000,
163
                           tProd=getattr(planet, 'effProdProd', '?'),
164
                           tSci=getattr(planet, 'effProdSci', '?'),
165
                           tPlanetID=planetID,
166
                           foreground=res.getPlayerColor(ownerID))
167
            items.append(item)
168
        self.win.vPlanets.items = items
169
        self.win.vPlanets.itemsChanged()
170
        # buttons
171
        self.win.vMine.pressed = self.showMine
172
        self.win.vOtherPlayers = self.showOtherPlayers
173
        self.win.vColonizable = self.showColonizable
174
        self.win.vUncolonizable = self.showUncolonizable
175
176
    def onSelectPlanet(self, widget, action, data):
177
        item = self.win.vPlanets.selection[0]
178
        planet = client.get(item.tPlanetID, noUpdate=1)
179
        if hasattr(planet, "owner") and planet.owner == client.getPlayerID():
180
            # show dialog
181
            gdata.mainGameDlg.onSelectMapObj(None, None, item.tPlanetID)
182
        else:
183
            # center on map
184
            if hasattr(planet, "x"):
185
                gdata.mainGameDlg.win.vStarMap.highlightPos = (planet.x, planet.y)
186
                gdata.mainGameDlg.win.vStarMap.setPos(planet.x, planet.y)
187
                self.hide()
188
                return
189
            self.win.setStatus(_("Cannot show location"))
190
191
    def onShowLocation(self, widget, action, data):
192
        item = self.win.vPlanets.selection[0]
193
        planet = client.get(item.tPlanetID, noUpdate=1)
194
        # center on map
195
        if hasattr(planet, "x"):
196
            gdata.mainGameDlg.win.vStarMap.highlightPos = (planet.x, planet.y)
197
            gdata.mainGameDlg.win.vStarMap.setPos(planet.x, planet.y)
198
            self.hide()
199
            return
200
        self.win.setStatus(_("Cannot show location"))
201
202
    def onToggleCondition(self, widget, action, data):
203
        setattr(self, widget.data, not getattr(self, widget.data))
204
        self.update()
205
206
    def onClose(self, widget, action, data):
207
        self.hide()
208
209
    def createUI(self):
210
        w, h = gdata.scrnSize
211
        self.win = ui.Window(self.app,
212
                             modal=1,
213
                             escKeyClose=1,
214
                             titleOnly=w == 800 and h == 600,
215
                             movable=0,
216
                             title=_('Planets Overview'),
217
                             rect=ui.Rect((w - 800 - 4 * (w != 800)) / 2, (h - 600 - 4 * (h != 600)) / 2, 800 + 4 * (w != 800), 580 + 4 * (h != 600)),
218
                             layoutManager=ui.SimpleGridLM())
219
        self.win.subscribeAction('*', self)
220
        # playets listbox
221
        ui.Listbox(self.win, layout=(0, 0, 40, 26), id='vPlanets',
222
                   columns=[(_('Planet'), 'text', 6, ui.ALIGN_W),
223
                   (_('Type'), 'tPlType', 3.5, ui.ALIGN_W),
224
                   (_('Env'), 'tPlBio', 1.5, ui.ALIGN_E),
225
                   (_('Min'), 'tPlMin', 1.5, ui.ALIGN_E),
226
                   (_('En'), 'tPlEn', 1.5, ui.ALIGN_E),
227
                   (_('Bio+-'), 'tChangeBio', 2.0, ui.ALIGN_E),
228
                   (_('En+-'), 'tChangeEn', 2.0, ui.ALIGN_E),
229
                   (_('Free'), 'tFree', 2.0, ui.ALIGN_E),
230
                   (_('Sl.'), 'tSpace', 1.5, ui.ALIGN_E),
231
                   (_('D.'), 'tDiam', 1.5, ui.ALIGN_E),
232
                   (_('Mrl'), 'tMorale', 2, ui.ALIGN_E),
233
                   (_('CP'), 'tProd', 2, ui.ALIGN_E),
234
                   (_('RP'), 'tSci', 2, ui.ALIGN_E),
235
                   (_('ETC'), 'tETC', 2.5, ui.ALIGN_E),
236
                   (_('Tot.ETC'), 'tTotalETC', 2.5, ui.ALIGN_E),
237
                   (_('Constructing'), 'tConstrInfo', 7.0, ui.ALIGN_W)],
238
                   columnLabels=1, action='onSelectPlanet', rmbAction="onShowLocation")
239
        ui.Button(self.win, layout=(0, 26, 5, 1), text=_('My planets'), id="vMine",
240
                  toggle=1, action="onToggleCondition", data="showMine")
241
        ui.Button(self.win, layout=(5, 26, 5, 1), text=_('Other cmdrs'), id="vOtherPlayers",
242
                  toggle=1, action="onToggleCondition", data="showOtherPlayers")
243
        ui.Button(self.win, layout=(10, 26, 5, 1), text=_('Colonizable'), id="vColonizable",
244
                  toggle=1, action="onToggleCondition", data="showColonizable")
245
        ui.Button(self.win, layout=(15, 26, 5, 1), text=_('Uncolonizable'), id="vUncolonizable",
246
                  toggle=1, action="onToggleCondition", data="showUncolonizable")
247
        # status bar + submit/cancel
248
        ui.TitleButton(self.win, layout=(35, 27, 5, 1), text=_('Close'), action='onClose')
249
        ui.Title(self.win, id='vStatusBar', layout=(0, 27, 35, 1), align=ui.ALIGN_W)
250