""" This file is part of RuneOptimizer. RuneOptimizer is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. RuneOptimizer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RuneOptimizer. If not, see . """ class PanelUnits(wx.Panel): """ The unit list and details Panel. Parameters ---------- selecterId : string ID of the currently selected unit. unitList : wx.ListCtrl Selectable unit list with priorities. filterNameText : wx.TextCtrl Text input to filter units names. filterNameTexts : wx.CheckBox Checkbox to include or exclude units in storage. filterNoRunesCheck : wx.CheckBox Checkbox to include or exclude units without runes. filterNoTeamsCheck : wx.CheckBox Checkbox to include or exclude units in no teams. detailsSizer : wx.BoxSizer Hold the unit detail elements. Hidden until unit selction. nameLabel : wx.StaticText Label for the unit name. statGrid : wx.Grid.grid Table with the unit base and current stats. setLabelList : wx.StaticText[6] Labels with the set of the runes of the selected unit. idLabelList : wx.StaticText[6] Labels with the IDs of the runes of the selected unit. mainLabelList : wx.StaticText[6] Labels with the main stats of the runes of the selected unit. innateLabelList : wx.StaticText[6] Labels with the innates of the runes of the selected unit. statLabelList : wx.StaticText[6][4] Labels with the stats of the runes of the selected unit. Methods ------- populateUnitList(event) Populates the unit list. goToOptimizer(event) Prepares the optimizer panel with the selected unit and redirects. unitSelected(event) Loads a unit info. processResults(jsonData) Processes data obtained from RuneOptimizer. """ selectedId = None unitList = None filterNameText = None filterStorageCheck = None filterNoRunesCheck = None filterNoTeamsCheck = None detailsSizer = None nameLabel = None statGrid = None setLabelList = None idLabelList = None mainLabelList = None innateLabelList = None statLabelList = None def __init__(self, parent, id=wx.ID_ANY): """Initializes the panel. Sets upt all the widgets. Parameters ---------- parent : wx.* Panel parent. id : int, optional ID for the panel (default wx.ID_ANY). """ # Parent constructor wx.Panel.__init__(self, parent=parent, id=id) # Prepare some fonts titleFont = wx.Font( pointSize=14, family=wx.FONTFAMILY_DEFAULT, style=wx.FONTSTYLE_NORMAL, weight=wx.FONTWEIGHT_BOLD ) monospaceFont = wx.Font( pointSize=10, family=wx.FONTFAMILY_TELETYPE, style=wx.FONTSTYLE_NORMAL, weight=wx.FONTWEIGHT_NORMAL ) monospaceFontBold = wx.Font( pointSize=10, family=wx.FONTFAMILY_TELETYPE, style=wx.FONTSTYLE_NORMAL, weight=wx.FONTWEIGHT_BOLD ) monospaceFontItalic = wx.Font( pointSize=10, family=wx.FONTFAMILY_TELETYPE, style=wx.FONTSTYLE_ITALIC, weight=wx.FONTWEIGHT_NORMAL ) # Unit selectable list wx.StaticText( parent=self, id=wx.ID_ANY, label="Name Prio. Sto.", pos=(10, 10), size=(190, 20) ) self.unitList = wx.ListCtrl( parent=self, id=wx.ID_ANY, pos=(10, 30), size=(190, 350), style=wx.LC_REPORT|wx.LC_NO_HEADER ) self.unitList.InsertColumn(0, "Name", width=120) self.unitList.InsertColumn(1, "Prio.", width=40) self.unitList.InsertColumn(2, "Sto.", width=30) self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.unitSelected, self.unitList) # List filters filterBox = wx.StaticBox( parent=self, label="Filters:",id=wx.ID_ANY, pos=(10, 390), size=(190, 150) ) wx.StaticText( parent=filterBox, label="Monster name", pos=(5, 5), size=(180, 20) ) self.filterNameText = wx.TextCtrl( parent=filterBox, id=wx.ID_ANY, value="", pos=(5, 25), size=(177, 20), style=wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB ) self.Bind(wx.EVT_TEXT, self.populateUnitList, self.filterNameText) self.filterStorageCheck = wx.CheckBox( parent=filterBox, id=wx.ID_ANY, label="Monsters in storage", pos=(5, 55), size=(180, 20) ) self.filterStorageCheck.SetValue(True) self.Bind( wx.EVT_CHECKBOX, self.populateUnitList, self.filterStorageCheck ) self.filterNoRunesCheck = wx.CheckBox( parent=filterBox, id=wx.ID_ANY, label="Monsters without runes", pos=(5, 75), size=(180, 20) ) self.filterNoRunesCheck.SetValue(True) self.Bind( wx.EVT_CHECKBOX, self.populateUnitList, self.filterNoRunesCheck ) self.filterNoTeamsCheck = wx.CheckBox( parent=filterBox, id=wx.ID_ANY, label="Monsters not in teams", pos=(5, 95), size=(180, 20) ) self.filterNoTeamsCheck.SetValue(True) self.Bind( wx.EVT_CHECKBOX, self.populateUnitList, self.filterNoTeamsCheck ) self.populateUnitList(None) # Sizer for all the unit details. It will be hidden until a unit is # selected. self.detailsSizer = wx.BoxSizer(wx.VERTICAL) # Unit name self.nameLabel = wx.StaticText( parent=self, label="", pos=(220, 0), size=(120, 100) ) self.detailsSizer.Add(self.nameLabel) self.nameLabel.SetFont(titleFont) # Team list teamBox = wx.StaticBox( parent=self, label="Teams:",id=wx.ID_ANY, pos=(390, 0), size=(145, 200) ) self.detailsSizer.Add(teamBox) self.teamsLabel = wx.StaticText( parent=teamBox, label="", pos=(5, 5), size=(135, 190) ) monospaceFont.PointSize -= 2 self.teamsLabel.SetFont(monospaceFont) monospaceFont.PointSize += 2 optimizeButton = wx.Button( parent=self, id=wx.ID_ANY, pos=(230, 120), size=(120, 50), style=wx.LC_REPORT, label="Optimize" ) self.detailsSizer.Add(optimizeButton) self.Bind(wx.EVT_BUTTON, self.goToOptimizer, optimizeButton) # Stats table self.statGrid = wx.grid.Grid( parent=self, id=wx.ID_ANY, pos=(550, 00), size=(165, 220) ) self.detailsSizer.Add(self.statGrid) self.statGrid.CreateGrid( numRows=10, numCols=2 ) self.statGrid.EnableEditing(False) self.statGrid.SetDefaultCellAlignment( horiz=wx.ALIGN_RIGHT, vert=wx.ALIGN_CENTRE ) self.statGrid.SetDefaultCellFont(monospaceFont) self.statGrid.SetColSize(col=0, width=50) self.statGrid.SetColLabelValue(col=0, value="Base") self.statGrid.SetColSize(col=0, width=50) self.statGrid.SetColLabelValue(col=1, value="Current") self.statGrid.SetRowLabelSize(width=35) self.statGrid.SetColLabelSize(height=20) self.statGrid.SetRowSize(row=0, height=20) self.statGrid.SetRowSize(row=1, height=20) self.statGrid.SetRowSize(row=2, height=20) self.statGrid.SetRowSize(row=3, height=20) self.statGrid.SetRowSize(row=4, height=20) self.statGrid.SetRowSize(row=5, height=20) self.statGrid.SetRowSize(row=6, height=20) self.statGrid.SetRowSize(row=7, height=20) self.statGrid.SetRowSize(row=8, height=20) self.statGrid.SetRowSize(row=9, height=20) self.statGrid.SetRowLabelValue(row=0, value=" HP") self.statGrid.SetRowLabelValue(row=1, value="ATK") self.statGrid.SetRowLabelValue(row=2, value="DEF") self.statGrid.SetRowLabelValue(row=3, value="SPD") self.statGrid.SetRowLabelValue(row=4, value="CRR") self.statGrid.SetRowLabelValue(row=5, value="CRD") self.statGrid.SetRowLabelValue(row=6, value="RES") self.statGrid.SetRowLabelValue(row=7, value="ACC") self.statGrid.SetRowLabelValue(row=8, value="EHP") self.statGrid.SetRowLabelValue(row=9, value="DMG") # Rune list runeBoxList = [ wx.StaticBox( parent=self, label="Slot1:",id=wx.ID_ANY, pos=(390, 225), size=(145, 150) ), wx.StaticBox( parent=self, label="Slot2:",id=wx.ID_ANY, pos=(560, 225), size=(145, 150) ), wx.StaticBox( parent=self, label="Slot3:",id=wx.ID_ANY, pos=(560, 390), size=(145, 150) ), wx.StaticBox( parent=self, label="Slot4:",id=wx.ID_ANY, pos=(390, 390), size=(145, 150) ), wx.StaticBox( parent=self, label="Slot5:",id=wx.ID_ANY, pos=(220, 390), size=(145, 150) ), wx.StaticBox( parent=self, label="Slot6:",id=wx.ID_ANY, pos=(220, 225), size=(145, 150) ) ] for i in range(0, 6): runeBoxList[i].SetFont(monospaceFont) self.detailsSizer.Add(runeBoxList[i]) self.setLabelList = [ wx.StaticText( parent=runeBoxList[0], id=wx.ID_ANY, label="", pos=(0, 0), size=(145, 10) ), wx.StaticText( parent=runeBoxList[1], id=wx.ID_ANY, label="", pos=(0, 0), size=(145, 10) ), wx.StaticText( parent=runeBoxList[2], id=wx.ID_ANY, label="", pos=(0, 0), size=(145, 10) ), wx.StaticText( parent=runeBoxList[3], id=wx.ID_ANY, label="", pos=(0, 0), size=(145, 10) ), wx.StaticText( parent=runeBoxList[4], id=wx.ID_ANY, label="", pos=(0, 0), size=(145, 10) ), wx.StaticText( parent=runeBoxList[5], id=wx.ID_ANY, label="", pos=(0, 0), size=(145, 10) ), ] self.idLabelList = [ wx.StaticText( parent=runeBoxList[0], id=wx.ID_ANY, label="", pos=(0, 15), size=(145, 10) ), wx.StaticText( parent=runeBoxList[1], id=wx.ID_ANY, label="", pos=(0, 15), size=(145, 10) ), wx.StaticText( parent=runeBoxList[2], id=wx.ID_ANY, label="", pos=(0, 15), size=(145, 10) ), wx.StaticText( parent=runeBoxList[3], id=wx.ID_ANY, label="", pos=(0, 15), size=(145, 10) ), wx.StaticText( parent=runeBoxList[4], id=wx.ID_ANY, label="", pos=(0, 15), size=(145, 10) ), wx.StaticText( parent=runeBoxList[5], id=wx.ID_ANY, label="", pos=(0, 15), size=(145, 10) ) ] wx.StaticLine( parent=runeBoxList[0], id=wx.ID_ANY, pos=(0, 30), size=(145, 1), style=wx.LC_REPORT ) wx.StaticLine( parent=runeBoxList[1], id=wx.ID_ANY, pos=(0, 30), size=(145, 1), style=wx.LC_REPORT ) wx.StaticLine( parent=runeBoxList[2], id=wx.ID_ANY, pos=(0, 30), size=(145, 1), style=wx.LC_REPORT ) wx.StaticLine( parent=runeBoxList[3], id=wx.ID_ANY, pos=(0, 30), size=(145, 1), style=wx.LC_REPORT ) wx.StaticLine( parent=runeBoxList[4], id=wx.ID_ANY, pos=(0, 30), size=(145, 1), style=wx.LC_REPORT ) wx.StaticLine( parent=runeBoxList[5], id=wx.ID_ANY, pos=(0, 30), size=(145, 1), style=wx.LC_REPORT ) self.mainLabelList = [ wx.StaticText( parent=runeBoxList[0], id=wx.ID_ANY, label="", pos=(0, 35), size=(145, 10) ), wx.StaticText( parent=runeBoxList[1], id=wx.ID_ANY, label="", pos=(0, 35), size=(145, 10) ), wx.StaticText( parent=runeBoxList[2], id=wx.ID_ANY, label="", pos=(0, 35), size=(145, 10) ), wx.StaticText( parent=runeBoxList[3], id=wx.ID_ANY, label="", pos=(0, 35), size=(145, 10) ), wx.StaticText( parent=runeBoxList[4], id=wx.ID_ANY, label="", pos=(0, 35), size=(145, 10) ), wx.StaticText( parent=runeBoxList[5], id=wx.ID_ANY, label="", pos=(0, 35), size=(145, 10) ) ] for i in range(0, 6): self.mainLabelList[i].SetFont(monospaceFontBold) self.innateLabelList = [ wx.StaticText( parent=runeBoxList[0], id=wx.ID_ANY, label="", pos=(0, 50), size=(145, 10) ), wx.StaticText( parent=runeBoxList[1], id=wx.ID_ANY, label="", pos=(0, 50), size=(145, 10) ), wx.StaticText( parent=runeBoxList[2], id=wx.ID_ANY, label="", pos=(0, 50), size=(145, 10) ), wx.StaticText( parent=runeBoxList[3], id=wx.ID_ANY, label="", pos=(0, 50), size=(145, 10) ), wx.StaticText( parent=runeBoxList[4], id=wx.ID_ANY, label="", pos=(0, 50), size=(145, 10) ), wx.StaticText( parent=runeBoxList[5], id=wx.ID_ANY, label="", pos=(0, 50), size=(145, 10) ) ] for i in range(0, 6): self.innateLabelList[i].SetFont(monospaceFontItalic) self.statLabelList = [ [ wx.StaticText( parent=runeBoxList[0], id=wx.ID_ANY, label="", pos=(0, 70), size=(145, 10) ), wx.StaticText( parent=runeBoxList[0], id=wx.ID_ANY, label="", pos=(0, 85), size=(145, 10) ), wx.StaticText( parent=runeBoxList[0], id=wx.ID_ANY, label="", pos=(0, 100), size=(145, 10) ), wx.StaticText( parent=runeBoxList[0], id=wx.ID_ANY, label="", pos=(0, 115), size=(145, 10) ) ], [ wx.StaticText( parent=runeBoxList[1], id=wx.ID_ANY, label="", pos=(0, 70), size=(145, 10) ), wx.StaticText( parent=runeBoxList[1], id=wx.ID_ANY, label="", pos=(0, 85), size=(145, 10) ), wx.StaticText( parent=runeBoxList[1], id=wx.ID_ANY, label="", pos=(0, 100), size=(145, 10) ), wx.StaticText( parent=runeBoxList[1], id=wx.ID_ANY, label="", pos=(0, 115), size=(145, 10) ) ], [ wx.StaticText( parent=runeBoxList[2], id=wx.ID_ANY, label="", pos=(0, 70), size=(145, 10) ), wx.StaticText( parent=runeBoxList[2], id=wx.ID_ANY, label="", pos=(0, 85), size=(145, 10) ), wx.StaticText( parent=runeBoxList[2], id=wx.ID_ANY, label="", pos=(0, 100), size=(145, 10) ), wx.StaticText( parent=runeBoxList[2], id=wx.ID_ANY, label="", pos=(0, 115), size=(145, 10) ) ], [ wx.StaticText( parent=runeBoxList[3], id=wx.ID_ANY, label="", pos=(0, 70), size=(145, 10) ), wx.StaticText( parent=runeBoxList[3], id=wx.ID_ANY, label="", pos=(0, 85), size=(145, 10) ), wx.StaticText( parent=runeBoxList[3], id=wx.ID_ANY, label="", pos=(0, 100), size=(145, 10) ), wx.StaticText( parent=runeBoxList[3], id=wx.ID_ANY, label="", pos=(0, 115), size=(145, 10) ) ], [ wx.StaticText( parent=runeBoxList[4], id=wx.ID_ANY, label="", pos=(0, 70), size=(145, 10) ), wx.StaticText( parent=runeBoxList[4], id=wx.ID_ANY, label="", pos=(0, 85), size=(145, 10) ), wx.StaticText( parent=runeBoxList[4], id=wx.ID_ANY, label="", pos=(0, 100), size=(145, 10) ), wx.StaticText( parent=runeBoxList[4], id=wx.ID_ANY, label="", pos=(0, 115), size=(145, 10) ) ], [ wx.StaticText( parent=runeBoxList[5], id=wx.ID_ANY, label="", pos=(0, 70), size=(145, 10) ), wx.StaticText( parent=runeBoxList[5], id=wx.ID_ANY, label="", pos=(0, 85), size=(145, 10) ), wx.StaticText( parent=runeBoxList[5], id=wx.ID_ANY, label="", pos=(0, 100), size=(145, 10) ), wx.StaticText( parent=runeBoxList[5], id=wx.ID_ANY, label="", pos=(0, 115), size=(145, 10) ) ] ] # By default, hide all optimization options self.detailsSizer.ShowItems(False) def populateUnitList(self, event=None): """Populates the unit list. Uses the filters. Parameters ---------- event : wx.Event, optional The event that triggered the call (default is None). """ # Get units from db name = self.filterNameText.GetValue() query = """ SELECT id, name, ( SELECT cast(total(teams.priority) as int) FROM teams, units_teams WHERE teams.id = units_teams.team AND units_teams.unit = units.id ) as priority, storage FROM units WHERE name LIKE '%""" + name + """%' """ if self.filterStorageCheck.GetValue() == False: query += " AND storage = 0 " if self.filterNoRunesCheck.GetValue() == False: query += " AND id IN (SELECT DISTINCT unit FROM runes) " if self.filterNoTeamsCheck.GetValue() == False: query += " AND id IN (SELECT DISTINCT unit FROM units_teams) " query += " ORDER BY priority DESC; "; cursor = conn.execute(query) i = 0 self.unitList.DeleteAllItems() for row in cursor: self.unitList.InsertItem(i, row[1]) self.unitList.SetItem(i, 1, str(row[2])) self.unitList.SetItem(i, 2, "") # Items can't hold too much data in Windows, store the first nine # digits and rerieve it from database with LIKE self.unitList.SetItemData(i, int(str(row[0])[0:9])) if (row[3] == 1): self.unitList.SetItem(i, 2, "X") else: self.unitList.SetItem(i, 2, " ") i = i + 1 def goToOptimizer(self, event = None): """Prepares the optimizer panel with the selected unit and redirects. Parameters ---------- event : wx.Event, optional The event that triggered the call (default is None). """ self.GetParent().frameOptimizer.unitId = self.selectedId self.GetParent().frameOptimizer.selectUnit(event=None) self.GetParent().ChangeSelection(2) def unitSelected(self, event): """Loads a unit info and enables optimizaton options. Called when a unit is selected from the list. Parameters ---------- event : wx.Event, optional The event that triggered the call (default is None). """ unitId = \ str(self.unitList.GetItemData(self.unitList.GetFirstSelected())) cursor = conn.execute(""" SELECT base_hp, base_atk, base_def, base_spd, base_crr, base_crd, base_res, base_acc, current_hp, current_atk, current_def, current_spd, current_crr, current_crd, current_res, current_acc, id, name, level FROM units WHERE id LIKE ?; """, (unitId + "%",)) row = cursor.fetchone() unitId = row[16] self.selectedId = row[16] self.selectedId = unitId nameLabelText = "" unitName = row[17][0:15] if len(unitName) > 8: nameLabelText = \ unitName + "\n(Lv." + str(row[18]) + ")\n\n#" + row[16] else: nameLabelText = \ unitName + " (Lv." + str(row[18]) + ")\n\n#" + row[16] self.nameLabel.SetLabel(nameLabelText) self.detailsSizer.ShowItems(True) for i in range(0, 8): value = str(row[i]) if i > 3: value = value + "%" else: value = value + " " self.statGrid.SetCellValue(row=i, col=0, s=value) for i in range(0, 8): value = str(row[8 + i]) if i > 3: value = value + "%" else: value = value + " " self.statGrid.SetCellValue(row=i, col=1, s=value) # Galculate EHP and DMG baseHp = int(self.statGrid.GetCellValue(row=0, col=0)) baseDef = int(self.statGrid.GetCellValue(row=2, col=0).replace("%", "")) baseEhp = math.ceil((((baseDef * 3.5) + 1140) * baseHp) / 1000) self.statGrid.SetCellValue(row=8, col=0, s=str(baseEhp)) #self.minStatSlid[8].SetMin(baseEhp) currentHp = int(self.statGrid.GetCellValue(row=0, col=1)) currentDef = \ int(self.statGrid.GetCellValue(row=2, col=1).replace("%", "")) currentEhp = math.ceil((((currentDef * 3.5) + 1140) * currentHp) / 1000) self.statGrid.SetCellValue(row=8, col=1, s=str(currentEhp)) baseAtk = int(self.statGrid.GetCellValue(row=1, col=0)) baseCrr = int(self.statGrid.GetCellValue(row=4, col=0).replace("%", "")) baseCrd = int(self.statGrid.GetCellValue(row=5, col=0).replace("%", "")) if (baseCrr > 100): # Dont use crit rate over 100 baseCrr = 100 baseDmg = math.ceil( (baseAtk * (100 - baseCrr) / 100) + ((baseAtk + (baseAtk * baseCrd / 100)) * baseCrr / 100) ) self.statGrid.SetCellValue(row=9, col=0, s=str(baseDmg)) currentAtk = int(self.statGrid.GetCellValue(row=1, col=1)) currentCrr = \ int(self.statGrid.GetCellValue(row=4, col=1).replace("%", "")) currentCrd = \ int(self.statGrid.GetCellValue(row=5, col=1).replace("%", "")) if (currentCrr > 100): currentCrr = 100 currentDmg = math.ceil( (currentAtk * (100 - currentCrr) / 100) + # Non-crit (currentAtk * ( currentCrr / 100) * currentCrd / 100) # Crit ) self.statGrid.SetCellValue(row=9, col=1, s=str(currentDmg)) # Get the team list cursorTeams = conn.execute(""" SELECT id, name FROM teams WHERE id IN (SELECT DISTINCT team FROM units_teams WHERE unit = ?) """, (self.selectedId,) ) teamLabelText = "" for row in cursorTeams: teamLabelText += "-" + row[1][0:16].ljust(16, " ") teamLabelText += ("(#" + row[0] + ")").rjust(6) + "\n" self.teamsLabel.SetLabel(teamLabelText) # Populate the runes cursor = conn.execute(""" SELECT runes.id, runes.slot, runes.type, runes.level, units.id, units.name, runes.efficiency, runes.max_efficiency FROM runes LEFT JOIN units ON runes.unit = units.id WHERE runes.unit = ? ORDER BY runes.slot; """, (self.selectedId,)) i = 0 for row in cursor: # Rows are 18 charactes width # First line: Powerup level, ID labelLvId = ("+" + str(row[3])).ljust(3, " ") labelLvId += ("#" + str(row[0])).rjust(15, " ") self.setLabelList[i].SetLabel(labelLvId) # Second line: Set name, efficiency lvlSetEff = set_names[row[2]][0:6].ljust(6, " ") effv = str(("{:.2f}".format(row[6])).rjust(5, " ")) eff = (" Eff:" + str(effv) + "%") lvlSetEff += eff self.idLabelList[i].SetLabel(lvlSetEff) # Get all stats cursorStats = conn.execute(""" SELECT slot, stat, value, grind, enchant FROM rune_stats WHERE rune = """ + row[0] + """ ORDER BY slot; """) j = -1 innateLabel = " " for rowStats in cursorStats: slot = rowStats[0] if rowStats[4] == 1: # if enchanted name = ( stat_names[rowStats[1]] .replace("%", ""). replace(" ", "") + "* " ).rjust(5, " ") else: name = ( stat_names[rowStats[1]] .replace("%", "") .replace(" ", "") + " " ).rjust(5, " ") value = str(rowStats[2]) if rowStats[1] in [2, 4, 6, 9, 10, 11, 23]: value = value + "%" else: value = value + " " value = value.rjust(5) if rowStats[3] > 0: # if grinded value = value + " + " + str(rowStats[3]) if rowStats[1] in [2, 4, 6, 9, 10, 11, 23]: value = value + "%" line = name + value if slot == -1: # main self.mainLabelList[i].SetLabel(line) elif slot == 0: # innate innateLabel = line else: # normal stats self.statLabelList[i][slot - 1].SetLabel(line) self.innateLabelList[i].SetLabel(innateLabel) i = i + 1