|
@@ -0,0 +1,560 @@
|
|
|
|
|
+#!/usr/bin/env python
|
|
|
|
|
+"""
|
|
|
|
|
+RuneOptimizer GUI.
|
|
|
|
|
+"""
|
|
|
|
|
+
|
|
|
|
|
+import wx
|
|
|
|
|
+import wx.grid
|
|
|
|
|
+import sqlite3
|
|
|
|
|
+import math
|
|
|
|
|
+
|
|
|
|
|
+conn = None
|
|
|
|
|
+
|
|
|
|
|
+stat_names = [
|
|
|
|
|
+ "NULL", "HP ", "HP% ", "ATK ", "ATK%", "DEF ",
|
|
|
|
|
+ "DEF%", "NULL", "SPD ", "CRR ", "CRD ", "RES ", "ACC "
|
|
|
|
|
+]
|
|
|
|
|
+set_names = [
|
|
|
|
|
+ "NULL", "ENERGY", "GUARD", "SWIFT", "BLADE", "RAGE",
|
|
|
|
|
+ "FOCUS", "ENDURE", "FATAL", "NULL", "DESPAIR", "VAMPIRE",
|
|
|
|
|
+ "VIOLENT", "NEMESIS", "WILL", "SHIELD", "REVENGE", "DESTROY",
|
|
|
|
|
+ "FIGHT", "DETERMINATION", "ENHANCE", "ACCURACY", "TOLERANCE"
|
|
|
|
|
+]
|
|
|
|
|
+
|
|
|
|
|
+class RuneOptimizerFrame(wx.Frame):
|
|
|
|
|
+ """
|
|
|
|
|
+ The main frame
|
|
|
|
|
+ """
|
|
|
|
|
+ statGrid = None
|
|
|
|
|
+ runeList = None
|
|
|
|
|
+ minStatSlider = None
|
|
|
|
|
+ minStatText = None
|
|
|
|
|
+
|
|
|
|
|
+ def __init__(self, *args, **kw):
|
|
|
|
|
+ global conn
|
|
|
|
|
+ # ensure the parent's __init__ is called
|
|
|
|
|
+ super(RuneOptimizerFrame, self).__init__(*args, **kw)
|
|
|
|
|
+
|
|
|
|
|
+ # create a panel in the frame
|
|
|
|
|
+ # Sies and pos do nothing here
|
|
|
|
|
+ pnl = wx.Panel(self,pos=(500,10), size=(800,800))
|
|
|
|
|
+
|
|
|
|
|
+ # put some text with a larger bold font on it
|
|
|
|
|
+ st = wx.StaticText(pnl, label="Rune Optimizer")
|
|
|
|
|
+ font = st.GetFont()
|
|
|
|
|
+ font.PointSize += 2
|
|
|
|
|
+ font = font.Bold()
|
|
|
|
|
+ st.SetFont(font)
|
|
|
|
|
+
|
|
|
|
|
+ # and create a sizer to manage the layout of child widgets
|
|
|
|
|
+ sizer = wx.BoxSizer(wx.VERTICAL)
|
|
|
|
|
+ sizer.Add(st, wx.SizerFlags().Border(wx.TOP|wx.LEFT, 25))
|
|
|
|
|
+ pnl.SetSizer(sizer)
|
|
|
|
|
+
|
|
|
|
|
+ # create a menu bar
|
|
|
|
|
+ self.makeMenuBar()
|
|
|
|
|
+
|
|
|
|
|
+ # and a status bar
|
|
|
|
|
+ self.CreateStatusBar()
|
|
|
|
|
+ self.SetStatusText("Status: Updated, no pending changes")
|
|
|
|
|
+
|
|
|
|
|
+ # Show unit list
|
|
|
|
|
+ self.unitList = wx.ListCtrl(parent=pnl, id=-1, pos=(10, 30), size=(190, 650), style=wx.LC_REPORT)
|
|
|
|
|
+ self.unitList.InsertColumn(0, "Name", width=120)
|
|
|
|
|
+ self.unitList.InsertColumn(1, "Prio.", width=40)
|
|
|
|
|
+ self.unitList.InsertColumn(2, "Sto.", width=30)
|
|
|
|
|
+
|
|
|
|
|
+ # Empty item
|
|
|
|
|
+ item = wx.ListItem()
|
|
|
|
|
+ item.SetId(0)
|
|
|
|
|
+ item.SetText("")
|
|
|
|
|
+ item.SetColumn(0)
|
|
|
|
|
+ item = wx.ListItem()
|
|
|
|
|
+ item.SetId(0)
|
|
|
|
|
+ item.SetText("")
|
|
|
|
|
+ item.SetColumn(1)
|
|
|
|
|
+ item = wx.ListItem()
|
|
|
|
|
+ item.SetId(0)
|
|
|
|
|
+ item.SetText("")
|
|
|
|
|
+ item.SetColumn(2)
|
|
|
|
|
+ self.unitList.InsertItem(item)
|
|
|
|
|
+
|
|
|
|
|
+ # Get units from db
|
|
|
|
|
+ cursor = conn.execute("""
|
|
|
|
|
+ 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
|
|
|
|
|
+ FROM units
|
|
|
|
|
+ WHERE
|
|
|
|
|
+ id IN (SELECT DISTINCT unit FROM runes)
|
|
|
|
|
+ ORDER BY priority DESC;
|
|
|
|
|
+ """)
|
|
|
|
|
+ i = 0
|
|
|
|
|
+ for row in cursor:
|
|
|
|
|
+ self.unitList.InsertStringItem(i, row[1])
|
|
|
|
|
+ self.unitList.SetStringItem(i, 1, str(row[2]))
|
|
|
|
|
+ self.unitList.SetStringItem(i, 2, "")
|
|
|
|
|
+ self.unitList.SetItemData(i, int(row[0]))
|
|
|
|
|
+ i = i + 1
|
|
|
|
|
+
|
|
|
|
|
+ self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.unitSelected, self.unitList)
|
|
|
|
|
+
|
|
|
|
|
+ # Stats table
|
|
|
|
|
+ self.statGrid = wx.grid.Grid(parent=pnl, id=-1, pos=(210, 30), size=(165, 220))
|
|
|
|
|
+ self.statGrid.CreateGrid(numRows=10, numCols=2, selmode=wx.grid.Grid.GridSelectionModes.SelectRowsOrColumns)
|
|
|
|
|
+ self.statGrid.SetDefaultCellAlignment(horiz=wx.ALIGN_RIGHT, vert=wx.ALIGN_CENTRE)
|
|
|
|
|
+ monospaceFont = wx.Font(10, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
|
|
|
|
|
+ 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 set list
|
|
|
|
|
+ runeListBox = [
|
|
|
|
|
+ wx.StaticBox(pnl, label="Slot1:",id=-1, pos=(465, 30), size=(80, 115)),
|
|
|
|
|
+ wx.StaticBox(pnl, label="Slot2:",id=-1, pos=(550, 30), size=(80, 115)),
|
|
|
|
|
+ wx.StaticBox(pnl, label="Slot3:",id=-1, pos=(550, 150), size=(80, 115)),
|
|
|
|
|
+ wx.StaticBox(pnl, label="Slot4:",id=-1, pos=(465, 150), size=(80, 115)),
|
|
|
|
|
+ wx.StaticBox(pnl, label="Slot5:",id=-1, pos=(380, 150), size=(80, 115)),
|
|
|
|
|
+ wx.StaticBox(pnl, label="Slot6:",id=-1, pos=(380, 30), size=(80, 115)),
|
|
|
|
|
+ ]
|
|
|
|
|
+ self.runeList = [
|
|
|
|
|
+ wx.StaticText(runeListBox[0], label="",id=-1, pos=(0, 0), size=(80, 115)),
|
|
|
|
|
+ wx.StaticText(runeListBox[1], label="",id=-1, pos=(0, 0), size=(80, 115)),
|
|
|
|
|
+ wx.StaticText(runeListBox[2], label="",id=-1, pos=(0, 0), size=(80, 115)),
|
|
|
|
|
+ wx.StaticText(runeListBox[3], label="",id=-1, pos=(0, 0), size=(80, 115)),
|
|
|
|
|
+ wx.StaticText(runeListBox[4], label="",id=-1, pos=(0, 0), size=(80, 115)),
|
|
|
|
|
+ wx.StaticText(runeListBox[5], label="",id=-1, pos=(0, 0), size=(80, 115)),
|
|
|
|
|
+ ]
|
|
|
|
|
+ monospaceFont.PointSize -= 2
|
|
|
|
|
+ for i in range(0, 6):
|
|
|
|
|
+ runeListBox[i].SetFont(monospaceFont)
|
|
|
|
|
+ monospaceFont.PointSize += 2
|
|
|
|
|
+
|
|
|
|
|
+ # Create an update button:
|
|
|
|
|
+ #btUpdate = wx.Button(parent=pnl, id=-1, label="Update data", pos=(10,10), size=(100,40))
|
|
|
|
|
+ #btOptimize = wx.Button(parent=pnl, id=-1, label="Optimize unit", pos=(10,60), size=(100,40))
|
|
|
|
|
+
|
|
|
|
|
+ # Line to separate optimization parameters
|
|
|
|
|
+ wx.StaticLine(parent=pnl, id=-1, pos=(210, 290), size=(650, 3), style=wx.LC_REPORT)
|
|
|
|
|
+
|
|
|
|
|
+ # Min stats
|
|
|
|
|
+ minStatBox = wx.StaticBox(pnl, label="Min. stats:",id=-1, pos=(220, 300), size=(260, 380))
|
|
|
|
|
+ wx.StaticText(minStatBox, label="HP",id=-1, pos=(0, 5), size=(30, 25))
|
|
|
|
|
+ wx.StaticText(minStatBox, label="ATK",id=-1, pos=(0, 35), size=(30, 25))
|
|
|
|
|
+ wx.StaticText(minStatBox, label="DEF",id=-1, pos=(0, 65), size=(30, 25))
|
|
|
|
|
+ wx.StaticText(minStatBox, label="SPD",id=-1, pos=(0, 95), size=(30, 25))
|
|
|
|
|
+ wx.StaticText(minStatBox, label="CRR",id=-1, pos=(0, 125), size=(30, 25))
|
|
|
|
|
+ wx.StaticText(minStatBox, label="CRD",id=-1, pos=(0, 155), size=(30, 25))
|
|
|
|
|
+ wx.StaticText(minStatBox, label="RES",id=-1, pos=(0, 185), size=(30, 25))
|
|
|
|
|
+ wx.StaticText(minStatBox, label="ACC",id=-1, pos=(0, 215), size=(30, 25))
|
|
|
|
|
+ wx.StaticText(minStatBox, label="EHP",id=-1, pos=(0, 245), size=(30, 25))
|
|
|
|
|
+ wx.StaticText(minStatBox, label="DMG",id=-1, pos=(0, 275), size=(30, 25))
|
|
|
|
|
+ self.minStatSlid = [
|
|
|
|
|
+ wx.Slider(minStatBox, id=-1, pos=(30, 0), size=(150, 30), name="slid0"),
|
|
|
|
|
+ wx.Slider(minStatBox, id=-1, pos=(30, 30), size=(150, 30), name="slid1"),
|
|
|
|
|
+ wx.Slider(minStatBox, id=-1, pos=(30, 60), size=(150, 30), name="slid2"),
|
|
|
|
|
+ wx.Slider(minStatBox, id=-1, pos=(30, 90), size=(150, 30), name="slid3"),
|
|
|
|
|
+ wx.Slider(minStatBox, id=-1, pos=(30, 120), size=(150, 30), name="slid4"),
|
|
|
|
|
+ wx.Slider(minStatBox, id=-1, pos=(30, 150), size=(150, 30), name="slid5"),
|
|
|
|
|
+ wx.Slider(minStatBox, id=-1, pos=(30, 180), size=(150, 30), name="slid6"),
|
|
|
|
|
+ wx.Slider(minStatBox, id=-1, pos=(30, 210), size=(150, 30), name="slid7"),
|
|
|
|
|
+ wx.Slider(minStatBox, id=-1, pos=(30, 240), size=(150, 30), name="slid8"),
|
|
|
|
|
+ wx.Slider(minStatBox, id=-1, pos=(30, 270), size=(150, 30), name="slid9")
|
|
|
|
|
+ ]
|
|
|
|
|
+ for i in range(0, 9):
|
|
|
|
|
+ self.minStatSlid[i].SetMin(0)
|
|
|
|
|
+ self.minStatSlid[i].SetMax(0)
|
|
|
|
|
+ self.minStatSlid[i].SetValue(0)
|
|
|
|
|
+ self.Bind(wx.EVT_SCROLL, self.minStatChangeBySlider, self.minStatSlid[i])
|
|
|
|
|
+ self.minStatText = [
|
|
|
|
|
+ wx.TextCtrl(minStatBox, id=-1, value="", pos=(185, 0), size=(65, 25), style=wx.TE_RIGHT|wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB, name="tx0"),
|
|
|
|
|
+ wx.TextCtrl(minStatBox, id=-1, value="", pos=(185, 30), size=(65, 25), style=wx.TE_RIGHT|wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB, name="tx1"),
|
|
|
|
|
+ wx.TextCtrl(minStatBox, id=-1, value="", pos=(185, 60), size=(65, 25), style=wx.TE_RIGHT|wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB, name="tx2"),
|
|
|
|
|
+ wx.TextCtrl(minStatBox, id=-1, value="", pos=(185, 90), size=(65, 25), style=wx.TE_RIGHT|wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB, name="tx3"),
|
|
|
|
|
+ wx.TextCtrl(minStatBox, id=-1, value="", pos=(185, 120), size=(65, 25), style=wx.TE_RIGHT|wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB, name="tx4"),
|
|
|
|
|
+ wx.TextCtrl(minStatBox, id=-1, value="", pos=(185, 150), size=(65, 25), style=wx.TE_RIGHT|wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB, name="tx5"),
|
|
|
|
|
+ wx.TextCtrl(minStatBox, id=-1, value="", pos=(185, 180), size=(65, 25), style=wx.TE_RIGHT|wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB, name="tx6"),
|
|
|
|
|
+ wx.TextCtrl(minStatBox, id=-1, value="", pos=(185, 210), size=(65, 25), style=wx.TE_RIGHT|wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB, name="tx7"),
|
|
|
|
|
+ wx.TextCtrl(minStatBox, id=-1, value="", pos=(185, 240), size=(65, 25), style=wx.TE_RIGHT|wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB, name="tx8"),
|
|
|
|
|
+ wx.TextCtrl(minStatBox, id=-1, value="", pos=(185, 270), size=(65, 25), style=wx.TE_RIGHT|wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB, name="tx9")
|
|
|
|
|
+ ]
|
|
|
|
|
+ for i in range(0, 9):
|
|
|
|
|
+ self.Bind(wx.EVT_TEXT_ENTER, self.minStatChangeByText, self.minStatText[i])
|
|
|
|
|
+ minStatsReset = wx.Button(parent=minStatBox, id=-1, pos=(10, 300), size=(100, 40), style=wx.LC_REPORT, label="Reset all")
|
|
|
|
|
+ minStatsAdapt = wx.Button(parent=minStatBox, id=-1, pos=(120, 300), size=(100, 40), style=wx.LC_REPORT, label="Adapt all")
|
|
|
|
|
+ # TODO: Add binds
|
|
|
|
|
+
|
|
|
|
|
+ # Rune sets
|
|
|
|
|
+ names = [
|
|
|
|
|
+ "", "ENERGY ", "GUARD ", "SWIFT ", "BLADE ", "RAGE ",
|
|
|
|
|
+ "FOCUS ", "ENDURE ", "FATAL ", "DESPAIR", "VAMPIRE", "VIOLENT",
|
|
|
|
|
+ "NEMESIS", "WILL ", "SHIELD ", "REVENGE", "DESTROY", "FIGHT ",
|
|
|
|
|
+ "DETERMI", "ENHANCE", "ACCURAC", "TOLERAN"
|
|
|
|
|
+ ]
|
|
|
|
|
+ setBox = wx.StaticBox(pnl, label="Rune Sets:",id=-1, pos=(500, 300), size=(330, 65))
|
|
|
|
|
+ self.runeSets = [
|
|
|
|
|
+ wx.Choice(parent=setBox, id=-1, pos=(5, 0), choices=names),
|
|
|
|
|
+ wx.Choice(parent=setBox, id=-1, pos=(110, 0), choices=names),
|
|
|
|
|
+ wx.Choice(parent=setBox, id=-1, pos=(215, 0), choices=names)
|
|
|
|
|
+ ]
|
|
|
|
|
+
|
|
|
|
|
+ # Allowed main stats for even slots
|
|
|
|
|
+ names = [
|
|
|
|
|
+ ["HP ", "HP% ", "ATK ", "ATK%", "DEF ", "DEF%"],
|
|
|
|
|
+ ["SPD ", "CRR ", "CRD ", "RES ", "ACC "]
|
|
|
|
|
+ ]
|
|
|
|
|
+ statBox = wx.StaticBox(pnl, label="Main stats (2, 4, 6):",id=-1, pos=(500, 380), size=(150, 190))
|
|
|
|
|
+ self.stats = [
|
|
|
|
|
+ wx.CheckListBox(parent=statBox, id=-1, pos=(5, 5), size=(70, 155), choices=names[0]),
|
|
|
|
|
+ wx.CheckListBox(parent=statBox, id=-1, pos=(70, 5), size=(70, 155), choices=names[1])
|
|
|
|
|
+ ]
|
|
|
|
|
+
|
|
|
|
|
+ levelBox = wx.StaticBox(pnl, label="Rune Level:",id=-1, pos=(700, 380), size=(100, 65))
|
|
|
|
|
+ self.level = wx.Choice(parent=levelBox, id=-1, pos=(5, 0), choices=["Current", "+ 12", " + 15"])
|
|
|
|
|
+
|
|
|
|
|
+ # Button to start
|
|
|
|
|
+ btOptimize = wx.Button(parent=pnl, id=-1, pos=(700, 480), size=(100, 40), style=wx.LC_REPORT, label="OPTIMIZE")
|
|
|
|
|
+ self.Bind(wx.EVT_BUTTON, self.startOptimization, btOptimize)
|
|
|
|
|
+
|
|
|
|
|
+ def startOptimization(self, event):
|
|
|
|
|
+ # Example call:
|
|
|
|
|
+ # ../RuneOptimizer optimize 7223811472 -l 15 -e rage,blade --stats atk,crr,crd -h 10000 -f 10
|
|
|
|
|
+ command = "RuneOptimizer optimize "
|
|
|
|
|
+ print("StartOptimization...")
|
|
|
|
|
+ unitId = str(self.unitList.GetItemData(self.unitList.GetFirstSelected()))
|
|
|
|
|
+ command += unitId
|
|
|
|
|
+ print(" Unit ID: " + unitId)
|
|
|
|
|
+ level = self.level.GetSelection()
|
|
|
|
|
+ if level == 1:
|
|
|
|
|
+ level = "12"
|
|
|
|
|
+ elif level == 2:
|
|
|
|
|
+ level = "15"
|
|
|
|
|
+ else:
|
|
|
|
|
+ level = "current"
|
|
|
|
|
+ command += (" --level " + level)
|
|
|
|
|
+ print(" Rune level: " + level)
|
|
|
|
|
+ sets = ""
|
|
|
|
|
+ for i in range (0, 2):
|
|
|
|
|
+ selected = self.runeSets[i].GetString(self.runeSets[i].GetSelection()).upper().replace(" ", "");
|
|
|
|
|
+ for j in range(0, 22):
|
|
|
|
|
+ name = set_names[j].upper()
|
|
|
|
|
+ if len(name) > 7:
|
|
|
|
|
+ name = name[0:7]
|
|
|
|
|
+ #print(selected + " - " + name)
|
|
|
|
|
+ if selected == name:
|
|
|
|
|
+ sets += set_names[j].lower() + ","
|
|
|
|
|
+ if len(sets) > 0:
|
|
|
|
|
+ sets = sets[:-1]
|
|
|
|
|
+ # TODO: ELSE ERROR
|
|
|
|
|
+ command += (" --sets " + sets)
|
|
|
|
|
+ stats = ""
|
|
|
|
|
+ selected_stats = self.stats[0].GetCheckedItems() + self.stats[1].GetCheckedItems()
|
|
|
|
|
+ for s in self.stats[0].GetCheckedItems():
|
|
|
|
|
+ if s == 0:
|
|
|
|
|
+ stats += "hpflat,"
|
|
|
|
|
+ elif s == 1:
|
|
|
|
|
+ stats += "hp,"
|
|
|
|
|
+ elif s == 2:
|
|
|
|
|
+ stats += "atkflat,"
|
|
|
|
|
+ elif s == 3:
|
|
|
|
|
+ stats += "atk,"
|
|
|
|
|
+ elif s == 4:
|
|
|
|
|
+ stats += "defflat,"
|
|
|
|
|
+ elif s == 5:
|
|
|
|
|
+ stats += "def,"
|
|
|
|
|
+ for s in self.stats[1].GetCheckedItems():
|
|
|
|
|
+ if s == 0:
|
|
|
|
|
+ stats += "spd,"
|
|
|
|
|
+ elif s == 1:
|
|
|
|
|
+ stats += "crr,"
|
|
|
|
|
+ elif s == 2:
|
|
|
|
|
+ stats += "crd,"
|
|
|
|
|
+ elif s == 3:
|
|
|
|
|
+ stats += "res,"
|
|
|
|
|
+ elif s == 4:
|
|
|
|
|
+ stats += "acc,"
|
|
|
|
|
+ if len(stats) > 0:
|
|
|
|
|
+ stats = stats[:-1]
|
|
|
|
|
+ # TODO: ELSE ERROR
|
|
|
|
|
+ command += (" --stats " + stats)
|
|
|
|
|
+ print(" Main stats: " + stats)
|
|
|
|
|
+
|
|
|
|
|
+ command += (" --min-hp " + str(self.minStatSlid[0].GetValue()))
|
|
|
|
|
+ command += (" --min-atk " + str(self.minStatSlid[1].GetValue()))
|
|
|
|
|
+ command += (" --min-def " + str(self.minStatSlid[2].GetValue()))
|
|
|
|
|
+ command += (" --min-spd " + str(self.minStatSlid[3].GetValue()))
|
|
|
|
|
+ command += (" --min-crr " + str(self.minStatSlid[4].GetValue()))
|
|
|
|
|
+ command += (" --min-crd " + str(self.minStatSlid[5].GetValue()))
|
|
|
|
|
+ command += (" --min-res " + str(self.minStatSlid[6].GetValue()))
|
|
|
|
|
+ command += (" --min-acc " + str(self.minStatSlid[7].GetValue()))
|
|
|
|
|
+ command += (" --min-ehp " + str(self.minStatSlid[8].GetValue()))
|
|
|
|
|
+ command += (" --min-dmg " + str(self.minStatSlid[9].GetValue()))
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ command += (" --gui ")
|
|
|
|
|
+ print("Command: " + command)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ def minStatChangeBySlider(self, event):
|
|
|
|
|
+ slidId = int(event.GetEventObject().GetName().replace("slid", ""))
|
|
|
|
|
+ self.minStatText[slidId].SetValue(str(event.GetEventObject().GetValue()))
|
|
|
|
|
+
|
|
|
|
|
+ def minStatChangeByText(self, event):
|
|
|
|
|
+ textId = int(event.GetEventObject().GetName().replace("tx", ""))
|
|
|
|
|
+ if event.GetEventObject().GetValue().isdigit() == False:
|
|
|
|
|
+ event.GetEventObject().SetValue(str(self.minStatSlid[textId].GetValue()))
|
|
|
|
|
+ value = int(event.GetEventObject().GetValue())
|
|
|
|
|
+ minValue = self.minStatSlid[textId].GetMin()
|
|
|
|
|
+ maxValue = self.minStatSlid[textId].GetMax()
|
|
|
|
|
+ if value < minValue:
|
|
|
|
|
+ value = minValue
|
|
|
|
|
+ event.GetEventObject().SetValue(str(value))
|
|
|
|
|
+ elif value > maxValue:
|
|
|
|
|
+ value = maxValue
|
|
|
|
|
+ event.GetEventObject().SetValue(str(value))
|
|
|
|
|
+ self.minStatSlid[textId].SetValue(value)
|
|
|
|
|
+
|
|
|
|
|
+ def unitSelected(self, event):
|
|
|
|
|
+ id = str(event.GetEventObject().GetItemData(event.GetEventObject().GetFirstSelected()))
|
|
|
|
|
+ print("Current selection:" + id)
|
|
|
|
|
+
|
|
|
|
|
+ # First, set sliders max values
|
|
|
|
|
+ self.minStatSlid[0].SetMax(50000) #HP
|
|
|
|
|
+ self.minStatSlid[1].SetMax(5000) #ATK
|
|
|
|
|
+ self.minStatSlid[2].SetMax(5000) #DEF
|
|
|
|
|
+ self.minStatSlid[3].SetMax(500) #SPD
|
|
|
|
|
+ self.minStatSlid[4].SetMax(100) #CRR
|
|
|
|
|
+ self.minStatSlid[5].SetMax(500) #CRD
|
|
|
|
|
+ self.minStatSlid[6].SetMax(100) #RES
|
|
|
|
|
+ self.minStatSlid[7].SetMax(85) #ACC
|
|
|
|
|
+ self.minStatSlid[8].SetMax(250000) #EHP
|
|
|
|
|
+ self.minStatSlid[9].SetMax(8000) #DMG
|
|
|
|
|
+
|
|
|
|
|
+ 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
|
|
|
|
|
+ FROM units
|
|
|
|
|
+ WHERE
|
|
|
|
|
+ id = """ + id + """;
|
|
|
|
|
+ """)
|
|
|
|
|
+ row = cursor.fetchone()
|
|
|
|
|
+ for i in range(0, 8):
|
|
|
|
|
+ value = str(row[i])
|
|
|
|
|
+ self.minStatSlid[i].SetMin(int(value))
|
|
|
|
|
+ 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])
|
|
|
|
|
+ self.minStatSlid[i].SetValue(int(value))
|
|
|
|
|
+ self.minStatText[i].SetValue(value)
|
|
|
|
|
+ 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))
|
|
|
|
|
+ self.minStatSlid[8].SetValue(currentEhp)
|
|
|
|
|
+ self.minStatText[8].SetValue(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))
|
|
|
|
|
+ self.minStatSlid[9].SetMin(baseDmg)
|
|
|
|
|
+ currentAtk = int(self.statGrid.GetCellValue(row=1, col=1))
|
|
|
|
|
+ currentCrr = int(self.statGrid.GetCellValue(row=4, col=0).replace("%", ""))
|
|
|
|
|
+ currentCrd = int(self.statGrid.GetCellValue(row=5, col=1).replace("%", ""))
|
|
|
|
|
+ if (currentCrr > 100):
|
|
|
|
|
+ # Dont use crit rate over 100
|
|
|
|
|
+ currentCrr = 100
|
|
|
|
|
+ currentDmg = math.ceil((currentAtk * (100 - currentCrr) / 100) + ((currentAtk + (currentAtk * currentCrd / 100)) * currentCrr / 100));
|
|
|
|
|
+ self.statGrid.SetCellValue(row=9, col=1, s=str(currentDmg))
|
|
|
|
|
+ self.minStatSlid[9].SetValue(currentDmg)
|
|
|
|
|
+ self.minStatText[9].SetValue(str(currentDmg))
|
|
|
|
|
+ cursor = conn.execute("""
|
|
|
|
|
+ SELECT
|
|
|
|
|
+ id, slot, type
|
|
|
|
|
+ FROM runes
|
|
|
|
|
+ WHERE
|
|
|
|
|
+ unit = """ + id + """
|
|
|
|
|
+ ORDER BY slot;
|
|
|
|
|
+ """)
|
|
|
|
|
+ i = 0
|
|
|
|
|
+ for row in cursor:
|
|
|
|
|
+ label = ""
|
|
|
|
|
+ label = label + set_names[row[2]] + "\n"
|
|
|
|
|
+ # Get all stats
|
|
|
|
|
+ cursorStats = conn.execute("""
|
|
|
|
|
+ SELECT
|
|
|
|
|
+ slot, stat, value, grind, enchant
|
|
|
|
|
+ FROM rune_stats
|
|
|
|
|
+ WHERE
|
|
|
|
|
+ rune = """ + row[0] + """
|
|
|
|
|
+ ORDER BY slot;
|
|
|
|
|
+ """)
|
|
|
|
|
+ j = -1
|
|
|
|
|
+ for rowStats in cursorStats:
|
|
|
|
|
+ while (j != rowStats[0]):
|
|
|
|
|
+ label = label + "\n"
|
|
|
|
|
+ j = j + 1;
|
|
|
|
|
+ label = label + stat_names[rowStats[1]] + str(rowStats[2]).rjust(4) + ""
|
|
|
|
|
+ if rowStats[3] > 0:
|
|
|
|
|
+ label = label + " +" + str(rowStats[3])
|
|
|
|
|
+ self.runeList[i].SetLabel(label)
|
|
|
|
|
+ i = i + 1
|
|
|
|
|
+
|
|
|
|
|
+ def makeMenuBar(self):
|
|
|
|
|
+ """
|
|
|
|
|
+ A menu bar is composed of menus, which are composed of menu items.
|
|
|
|
|
+ This method builds a set of menus and binds handlers to be called
|
|
|
|
|
+ when the menu item is selected.
|
|
|
|
|
+ """
|
|
|
|
|
+
|
|
|
|
|
+ updateMenu = wx.Menu()
|
|
|
|
|
+ updateJson = updateMenu.Append(
|
|
|
|
|
+ -1,
|
|
|
|
|
+ "&Update from JSON file\tCtrl-J",
|
|
|
|
|
+ "Updates the database from a profile JSON file."
|
|
|
|
|
+ );
|
|
|
|
|
+ updateSwdb = updateMenu.Append(
|
|
|
|
|
+ -1,
|
|
|
|
|
+ "&Update from SWDB\tCtrl-W",
|
|
|
|
|
+ "Updates the database from data retrieved from a SWDB instance."
|
|
|
|
|
+ );
|
|
|
|
|
+ updateSwarfarm = updateMenu.Append(
|
|
|
|
|
+ -1,
|
|
|
|
|
+ "&Update from Sarfarm\tCtrl-F",
|
|
|
|
|
+ "Updates the database from data retrieved from Swarfarm."
|
|
|
|
|
+ );
|
|
|
|
|
+ updateSqlite = updateMenu.Append(
|
|
|
|
|
+ -1,
|
|
|
|
|
+ "&Update from a sqlite database\tCtrl-Q",
|
|
|
|
|
+ "Updates the database from a SWDB sqlite database."
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ # Make a file menu with Hello and Exit items
|
|
|
|
|
+ fileMenu = wx.Menu()
|
|
|
|
|
+ # The "\t..." syntax defines an accelerator key that also triggers
|
|
|
|
|
+ # the same event
|
|
|
|
|
+ aboutItem = fileMenu.Append(wx.ID_ABOUT)
|
|
|
|
|
+ fileMenu.AppendSeparator()
|
|
|
|
|
+ # When using a stock ID we don't need to specify the menu item's
|
|
|
|
|
+ # label
|
|
|
|
|
+ exitItem = fileMenu.Append(wx.ID_EXIT)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ # Make the menu bar and add the two menus to it. The '&' defines
|
|
|
|
|
+ # that the next letter is the "mnemonic" for the menu item. On the
|
|
|
|
|
+ # platforms that support it those letters are underlined and can be
|
|
|
|
|
+ # triggered from the keyboard.
|
|
|
|
|
+ menuBar = wx.MenuBar()
|
|
|
|
|
+ menuBar.Append(fileMenu, "&File")
|
|
|
|
|
+ menuBar.Append(updateMenu, "&Update")
|
|
|
|
|
+
|
|
|
|
|
+ # Give the menu bar to the frame
|
|
|
|
|
+ self.SetMenuBar(menuBar)
|
|
|
|
|
+
|
|
|
|
|
+ # Finally, associate a handler function with the EVT_MENU event for
|
|
|
|
|
+ # each of the menu items. That means that when that menu item is
|
|
|
|
|
+ # activated then the associated handler function will be called.
|
|
|
|
|
+ #self.Bind(wx.EVT_MENU, self.OnHello, helloItem)
|
|
|
|
|
+ self.Bind(wx.EVT_MENU, self.closeApp, exitItem)
|
|
|
|
|
+ self.Bind(wx.EVT_MENU, self.showAbout, aboutItem)
|
|
|
|
|
+ self.Bind(wx.EVT_MENU, self.updateFromJson, updateJson)
|
|
|
|
|
+ self.Bind(wx.EVT_MENU, self.updateFromSwdb, updateSwdb)
|
|
|
|
|
+ self.Bind(wx.EVT_MENU, self.updateFromSwarfarm, updateSwarfarm)
|
|
|
|
|
+ self.Bind(wx.EVT_MENU, self.updateFromSqlite, updateSqlite)
|
|
|
|
|
+
|
|
|
|
|
+ def closeApp(self, event):
|
|
|
|
|
+ """Close the frame, terminating the application."""
|
|
|
|
|
+ self.Close(True)
|
|
|
|
|
+
|
|
|
|
|
+ def showAbout(self, event):
|
|
|
|
|
+ """Display an About Dialog"""
|
|
|
|
|
+ wx.MessageBox("RuneOptimizerAbout", wx.OK | wx.ICON_INFORMATION)
|
|
|
|
|
+
|
|
|
|
|
+ def updateFromJson(self, event):
|
|
|
|
|
+ self.showUnimplemented(wx.EVT_MENU)
|
|
|
|
|
+
|
|
|
|
|
+ def updateFromSwdb(self, event):
|
|
|
|
|
+ self.showUnimplemented()
|
|
|
|
|
+
|
|
|
|
|
+ def updateFromSwarfarm(self, event):
|
|
|
|
|
+ self.showUnimplemented()
|
|
|
|
|
+
|
|
|
|
|
+ def updateFromSqlite(self, event):
|
|
|
|
|
+ self.showUnimplemented()
|
|
|
|
|
+
|
|
|
|
|
+ def showUnimplemented(parent, arg2):
|
|
|
|
|
+ wx.MessageBox(parent=parent, message="This functionality is not yet implemented", caption="Unimplemented")
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+if __name__ == '__main__':
|
|
|
|
|
+ # Connect to the database
|
|
|
|
|
+ conn = sqlite3.connect('../../data.sqlite')
|
|
|
|
|
+ # When this module is run (not imported) then create the app, the
|
|
|
|
|
+ # frame, show it, and start the event loop.
|
|
|
|
|
+ app = wx.App()
|
|
|
|
|
+ frm = RuneOptimizerFrame(None, title='Rune Optimizer', pos=(100, 100), size=(900, 800))
|
|
|
|
|
+ frm.Show()
|
|
|
|
|
+ app.MainLoop()
|