| Total Complexity | 51 |
| Total Lines | 248 |
| Duplicated Lines | 0 % |
| Changes | 0 | ||
Complex classes like osci.dialog.PlanetsOverviewDlg 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
|
|||
| 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
|
|||
| 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 |