Passed
Pull Request — master (#291)
by Marek
07:30
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
        if planet.prodQueue and planet.effProdProd > 0:
84
            index = 0
85
            totalProd = 0
86
            for task in planet.prodQueue:
87
                if task.isShip:
88
                    tech = player.shipDesigns[task.techID]
89
                else:
90
                    tech = client.getFullTechInfo(task.techID)
91
                prodFirst, prodNext = self._getTaskProd(task, tech, planet.oid)
92
                if index == 0:
93
                    constrInfo = tech.name
94
                    etc = math.ceil(float(prodFirst) / planet.effProdProd)
95
                totalProd += prodFirst + prodNext
96
                index += 1
97
            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...
98
            totalEtc = res.formatTime(math.ceil(float(totalProd) / planet.effProdProd))
99
        elif planet.prodQueue:
100
            task = planet.prodQueue[0]
101
            if task.isShip:
102
                tech = player.shipDesigns[task.techID]
103
            else:
104
                tech = client.getTechInfo(task.techID)
105
            constrInfo = tech.name
106
            etc = _('N/A')
107
            totalEtc = _("N/A")
108
        else:
109
            constrInfo = _("-")
110
            etc = "-"
111
            totalEtc = _("-")
112
        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...
113
114
115
    def show(self):
116
        player = client.getPlayer()
117
118
        items = []
119
        for planetID in client.db.keys():
120
            planet = client.get(planetID, noUpdate=1)
121
            # skip non-planets
122
            if not hasattr(planet, "type") or planet.type != Const.T_PLANET:
123
                continue
124
            if not self._shallShow(planet, player):
125
                continue
126
            # fill in data
127
            ownerID = getattr(planet, 'owner', Const.OID_NONE)
128
            if hasattr(planet, 'owner') and planet.owner == player.oid:
129
                constrInfo, etc, totalEtc = self._processProdQueue(planet)
130
            else:
131
                constrInfo = '?'
132
                etc = '?'
133
                totalEtc = '?'
134
            # used slots
135
            try:
136
                freeSlots = planet.plSlots - len(planet.slots)
137
            except AttributeError:
138
                freeSlots = '?'
139
            # morale
140
            try:
141
                morale = int(planet.morale)
142
            except AttributeError:
143
                morale = "?"
144
145
            plType = gdata.planetTypes[getattr(planet, 'plType', None)]
146
            # list item
147
            item = ui.Item(getattr(planet, 'name', res.getUnknownName()),
148
                           tPlType=_(plType),
149
                           tPlBio=getattr(planet, 'plBio', '?'),
150
                           tPlMin=getattr(planet, 'plMin', '?'),
151
                           tPlEn=getattr(planet, 'plEn', '?'),
152
                           tChangeBio=getattr(planet, 'changeBio', '?'),
153
                           tChangeEn=getattr(planet, 'changeEn', '?'),
154
                           tETC=etc,
155
                           tTotalETC=totalEtc,
156
                           tConstrInfo=constrInfo,
157
                           tFree=freeSlots,
158
                           tMorale=morale,
159
                           tSpace=getattr(planet, 'plSlots', '?'),
160
                           tDiam=getattr(planet, 'plDiameter', 0) / 1000,
161
                           tProd=getattr(planet, 'effProdProd', '?'),
162
                           tSci=getattr(planet, 'effProdSci', '?'),
163
                           tPlanetID=planetID,
164
                           foreground=res.getPlayerColor(ownerID))
165
            items.append(item)
166
        self.win.vPlanets.items = items
167
        self.win.vPlanets.itemsChanged()
168
        # buttons
169
        self.win.vMine.pressed = self.showMine
170
        self.win.vOtherPlayers = self.showOtherPlayers
171
        self.win.vColonizable = self.showColonizable
172
        self.win.vUncolonizable = self.showUncolonizable
173
174
    def onSelectPlanet(self, widget, action, data):
175
        item = self.win.vPlanets.selection[0]
176
        planet = client.get(item.tPlanetID, noUpdate=1)
177
        if hasattr(planet, "owner") and planet.owner == client.getPlayerID():
178
            # show dialog
179
            gdata.mainGameDlg.onSelectMapObj(None, None, item.tPlanetID)
180
        else:
181
            # center on map
182
            if hasattr(planet, "x"):
183
                gdata.mainGameDlg.win.vStarMap.highlightPos = (planet.x, planet.y)
184
                gdata.mainGameDlg.win.vStarMap.setPos(planet.x, planet.y)
185
                self.hide()
186
                return
187
            self.win.setStatus(_("Cannot show location"))
188
189
    def onShowLocation(self, widget, action, data):
190
        item = self.win.vPlanets.selection[0]
191
        planet = client.get(item.tPlanetID, noUpdate=1)
192
        # center on map
193
        if hasattr(planet, "x"):
194
            gdata.mainGameDlg.win.vStarMap.highlightPos = (planet.x, planet.y)
195
            gdata.mainGameDlg.win.vStarMap.setPos(planet.x, planet.y)
196
            self.hide()
197
            return
198
        self.win.setStatus(_("Cannot show location"))
199
200
    def onToggleCondition(self, widget, action, data):
201
        setattr(self, widget.data, not getattr(self, widget.data))
202
        self.update()
203
204
    def onClose(self, widget, action, data):
205
        self.hide()
206
207
    def createUI(self):
208
        w, h = gdata.scrnSize
209
        self.win = ui.Window(self.app,
210
                             modal=1,
211
                             escKeyClose=1,
212
                             titleOnly=w == 800 and h == 600,
213
                             movable=0,
214
                             title=_('Planets Overview'),
215
                             rect=ui.Rect((w - 800 - 4 * (w != 800)) / 2, (h - 600 - 4 * (h != 600)) / 2, 800 + 4 * (w != 800), 580 + 4 * (h != 600)),
216
                             layoutManager=ui.SimpleGridLM())
217
        self.win.subscribeAction('*', self)
218
        # playets listbox
219
        ui.Listbox(self.win, layout=(0, 0, 40, 26), id='vPlanets',
220
                   columns=[(_('Planet'), 'text', 6, ui.ALIGN_W),
221
                   (_('Type'), 'tPlType', 3.5, ui.ALIGN_W),
222
                   (_('Env'), 'tPlBio', 1.5, ui.ALIGN_E),
223
                   (_('Min'), 'tPlMin', 1.5, ui.ALIGN_E),
224
                   (_('En'), 'tPlEn', 1.5, ui.ALIGN_E),
225
                   (_('Bio+-'), 'tChangeBio', 2.0, ui.ALIGN_E),
226
                   (_('En+-'), 'tChangeEn', 2.0, ui.ALIGN_E),
227
                   (_('Free'), 'tFree', 2.0, ui.ALIGN_E),
228
                   (_('Sl.'), 'tSpace', 1.5, ui.ALIGN_E),
229
                   (_('D.'), 'tDiam', 1.5, ui.ALIGN_E),
230
                   (_('Mrl'), 'tMorale', 2, ui.ALIGN_E),
231
                   (_('CP'), 'tProd', 2, ui.ALIGN_E),
232
                   (_('RP'), 'tSci', 2, ui.ALIGN_E),
233
                   (_('ETC'), 'tETC', 2.5, ui.ALIGN_E),
234
                   (_('Tot.ETC'), 'tTotalETC', 2.5, ui.ALIGN_E),
235
                   (_('Constructing'), 'tConstrInfo', 7.0, ui.ALIGN_W)],
236
                   columnLabels=1, action='onSelectPlanet', rmbAction="onShowLocation")
237
        ui.Button(self.win, layout=(0, 26, 5, 1), text=_('My planets'), id="vMine",
238
                  toggle=1, action="onToggleCondition", data="showMine")
239
        ui.Button(self.win, layout=(5, 26, 5, 1), text=_('Other cmdrs'), id="vOtherPlayers",
240
                  toggle=1, action="onToggleCondition", data="showOtherPlayers")
241
        ui.Button(self.win, layout=(10, 26, 5, 1), text=_('Colonizable'), id="vColonizable",
242
                  toggle=1, action="onToggleCondition", data="showColonizable")
243
        ui.Button(self.win, layout=(15, 26, 5, 1), text=_('Uncolonizable'), id="vUncolonizable",
244
                  toggle=1, action="onToggleCondition", data="showUncolonizable")
245
        # status bar + submit/cancel
246
        ui.TitleButton(self.win, layout=(35, 27, 5, 1), text=_('Close'), action='onClose')
247
        ui.Title(self.win, id='vStatusBar', layout=(0, 27, 35, 1), align=ui.ALIGN_W)
248