-- Licence: MIT Licence -- Some code from the luatz project (MIT Licence) -- Configuration ========== local dateformat = "%Y-%m-%d, %H:%M" local dateformat_log = "%Y-%m-%d, %H:%M:%S" local Colour_Not_Complete = "#FFB67D" local Colour_Complete = "#000000" local Colour_Heading_Complete = "#58FA58" dofile "en.lua" -- default english translations -- ======================== require( "iuplua" ) require( "iupluacontrols" ) dofile "../../SavedVariables/History.lua" --os.execute( "md ..\\..\\SavedVariables\\History_Bak" ) -- fails silently if already exists. --os.execute("copy ..\\..\\SavedVariables\\History.lua ..\\..\\SavedVariables\\History_Bak\\History.lua") --[[ -- ============== Setup storage for old characters. archivef = io.open("../../SavedVariables/History.Archive", "r") if archivef ==nil then --create empty file archivef = io.open("../../SavedVariables/History.Archive", "w") archivef:write("Archive = {} \n") end archivef:close() dofile "../../SavedVariables/History.Archive" -- newf = assert(io.open("../../SavedVariables/History.new", "w")) -- ============== --]] function dump(o) if type(o) == 'table' then local s = '{ ' for k,v in pairs(o) do if type(k) ~= 'number' then k = '"'..k..'"' end s = s .. '['..k..'] = ' .. dump(v) .. ',' end return s .. '} ' else return tostring(o) end end -- Minimally effective quoting function quote(astring) return '"' .. string.gsub(astring,"%'", "\\'") .. '"' end function write_saved(o) local escaped if type(o) == 'table' then local s = '{\n' for k,v in pairs(o) do if type(k) ~= 'number' then k = '"'..k..'"' end s = s .. '['..k..'] = ' .. write_saved(v) .. ',\n' end return s .. '}\n' elseif type(o) == 'string' then return quote(o) else return tostring(o) end end accounts = {} accounts_list = {} -- String list for selection dialog naccounts = 0 for i,_ in pairs(History_SV["Default"]) do accounts[i] = {} accounts[i].names = {} -- intermediate table for sorting. WIP. Array formatted. accounts[i].name = {} naccounts = naccounts +1 table.insert(accounts_list, i) end function write_data() newf = assert(io.open("../../SavedVariables/History.new", "w")) newf:write("History_SV=" .. write_saved(History_SV)) newf:close() end --Dump it back out -- newf:write("History_SV=" .. write_saved(History_SV)) -- newf:close() -- Load up .names, as a first run through. It's a sortable array. -- This is used as an indirection to control presentation order for acc,_ in pairs (accounts) do for char, _ in pairs(History_SV["Default"][acc]["$AccountWide"]["data"]) do table.insert (accounts[acc].names, char) accounts[acc].name[char] = {} -- stub table to hold char data end end function print_old() for i,j in pairs (History_SV["Default"][myaccount]["$AccountWide"]["old"]) do print (i .. " .. " .. dump(j)) end end -- set up some static data lbl_Status_bar = iup.label{title=L.Welcome, expand = "HORIZONTAL"} btn_archive = iup.button{title="Archive", FGCOLOR = "#FF0000"} --[[ ========================================== Iterate over all accounts and chars creating display items --]] for acc,_ in pairs (accounts) do -- ==== Accountwide Data -- Setup Log data accounts[acc].logtabs =iup.tabs{} -- Log Display table presentation accounts[acc].logtable = {} accounts[acc].logtable=iup.matrix{numcol=2, numcol_visible=2, numlin=0,numlin_visible=8} accounts[acc].logtable:setcell(0,0, L.TStamp) iup.SetAttribute(accounts[acc].logtable, "ALIGNMENT0", "ACENTER") iup.SetAttribute(accounts[acc].logtable, "ALIGNMENT2", "ALEFT") iup.SetAttribute(accounts[acc].logtable, "WIDTH0", 80) iup.SetAttribute(accounts[acc].logtable, "WIDTH1", 100) iup.SetAttribute(accounts[acc].logtable, "WIDTH2", 300) iup.SetAttribute(accounts[acc].logtable, "READONLY", "YES") -- Load log data local Line=0 local TimeStr = "" accounts[acc].logtable.numlin = Line for i,j in ipairs (History_SV["Default"][acc]["$AccountWide"]["log"]) do Line= Line +1 accounts[acc].logtable.numlin = Line TimeStr = os.date(dateformat_log,j["TimeStamp"]) accounts[acc].logtable:setcell( Line,0, TimeStr) if j["Char"] ~= nil then accounts[acc].logtable:setcell( Line,1, j["Char"]) end accounts[acc].logtable:setcell( Line,2, j["text"]) end -- Setup Log Display accounts[acc].log_tab=iup.vbox { ["tabtitle"] =L.LogTab, accounts[acc].logtable, iup.fill{} } accounts[acc].tabs =iup.tabs{} -- Top level of Tabs, Character Info in Here -- ==== END Accountwide Data -- Creates boxes, stage from names to allow optional sorting in future. for _,char in ipairs(accounts[acc].names) do accounts[acc].name[char] = {} local thischar = History_SV["Default"][acc]["$AccountWide"]["data"][char] -- shorter reference -- Pull in some char data for processing -- == Gender if thischar.Gender =="M" then accounts[acc].name[char].gender = L.Male elseif thischar.Gender == "F" then accounts[acc].name[char].gender = L.Female end -- ==Level local level = thischar.level accounts[acc].name[char].level = level if (level <=50) then accounts[acc].name[char].levelstr = tostring(level) else accounts[acc].name[char].levelstr = "V" .. tostring(level -50) end -- == Cumulative TimePlayed accounts[acc].name[char].timeplayed = math.floor(thischar.levels[level].time/60) -- Generate the leveling box. ============================ local leveling_box = {} accounts[acc].name[char].leveling_box = iup.matrix {numcol=6, numcol_visible=6, widthdef=60} accounts[acc].name[char].leveling_box:setcell(0,1, L.Level) accounts[acc].name[char].leveling_box:setcell(0,2, L.PTime) accounts[acc].name[char].leveling_box:setcell(0,3, L.Start) accounts[acc].name[char].leveling_box:setcell(0,4, L.Deaths) accounts[acc].name[char].leveling_box:setcell(0,5, L.APts) accounts[acc].name[char].leveling_box:setcell(0,6, L.Location) iup.SetAttribute(accounts[acc].name[char].leveling_box, "WIDTH6", "100") iup.SetAttribute(accounts[acc].name[char].leveling_box, "READONLY", "YES") -- levels as stored are unsorted, so create a level table which is sorted, local levels = {} for i,_ in pairs(thischar.levels) do table.insert(levels, i) end table.sort(levels) for i,j in ipairs(levels) do -- traverse in sorted order local timelevel = math.floor(thischar.levels[j].time) accounts[acc].name[char].leveling_box.numlin = i accounts[acc].name[char].leveling_box:setcell(i,1, j) accounts[acc].name[char].leveling_box:setcell(i,2, math.floor(timelevel/60)) accounts[acc].name[char].leveling_box:setcell(i,3, os.date("%Y-%m-%d",thischar.levels[j].begin)) accounts[acc].name[char].leveling_box:setcell(i,4, thischar.levels[j].deaths) accounts[acc].name[char].leveling_box:setcell(i,5, thischar.levels[j].Ach_Points) -- Do we have map name for this level? if thischar.levels[j].map ~= nil then accounts[acc].name[char].leveling_box:setcell(i,6, thischar.levels[j].map) end end -- Create Grp Dungeon Achievements Box========================= accounts[acc].name[char].Grp_box = {} accounts[acc].name[char].Grp_box = iup.matrix {numcol=4, numcol_visible=4, numlin=5, widthdef=90} --Set Column titles for i=1, 4 do accounts[acc].name[char].Grp_box:setcell(0,i, Area_names[i].medium) end --set lines accounts[acc].name[char].Grp_box:setcell(0,0, L.Level) accounts[acc].name[char].Grp_box:setcell(1,0, "10+") accounts[acc].name[char].Grp_box:setcell(2,0, "17+") accounts[acc].name[char].Grp_box:setcell(3,0, "24+") accounts[acc].name[char].Grp_box:setcell(4,0, "31+") accounts[acc].name[char].Grp_box:setcell(5,0, "38+") iup.SetAttribute(accounts[acc].name[char].Grp_box, "READONLY", "YES") -- set all text to red iup.SetAttribute(accounts[acc].name[char].Grp_box, "FGCOLOR*:1", Colour_Not_Complete) iup.SetAttribute(accounts[acc].name[char].Grp_box, "FGCOLOR*:2", Colour_Not_Complete) iup.SetAttribute(accounts[acc].name[char].Grp_box, "FGCOLOR*:3", Colour_Not_Complete) iup.SetAttribute(accounts[acc].name[char].Grp_box, "FGCOLOR*:4", Colour_Not_Complete) -- set text to black if achievement found. for id,_ in pairs (grp_dat) do local colour if thischar.ach[id] ~= nil then colour = "FGCOLOR" .. grp_dat[id].L .. ":" .. grp_dat[id].C iup.SetAttribute(accounts[acc].name[char].Grp_box, colour, Colour_Complete) end end --Set background of heading if all done if thischar.ach[1073] ~= nil then --EP Vanquisher iup.SetAttribute(accounts[acc].name[char].Grp_box, "BGCOLOR0:1", Colour_Heading_Complete) end if thischar.ach[1074] ~= nil then --DC Vanquisher iup.SetAttribute(accounts[acc].name[char].Grp_box, "BGCOLOR0:2", Colour_Heading_Complete) end if thischar.ach[1075] ~= nil then --AD Vanquisher iup.SetAttribute(accounts[acc].name[char].Grp_box, "BGCOLOR0:3", Colour_Heading_Complete) end for id,_ in pairs (grp_dat) do accounts[acc].name[char].Grp_box:setcell(grp_dat[id].L,grp_dat[id].C,grp_dat[id].name) end accounts[acc].name[char].Grp_box.Redraw= "ALL" -- Create Pub Dungeon Achievements Box========================== accounts[acc].name[char].Pub_box = iup.matrix {numcol=4, numcol_visible=4, numlin=5, widthdef=90} for i=1, 4 do -- Load text accounts[acc].name[char].Pub_box:setcell(0,i, Area_names[i].medium) end accounts[acc].name[char].Pub_box:setcell(0,0, L.Level) accounts[acc].name[char].Pub_box:setcell(1,0, "12-15") accounts[acc].name[char].Pub_box:setcell(2,0, "20-23") accounts[acc].name[char].Pub_box:setcell(3,0, "35-36") accounts[acc].name[char].Pub_box:setcell(4,0, "40-43") accounts[acc].name[char].Pub_box:setcell(5,0, "47-50") iup.SetAttribute(accounts[acc].name[char].Pub_box, "READONLY", "YES") iup.SetAttribute(accounts[acc].name[char].Pub_box, "FGCOLOR*:1", Colour_Not_Complete) iup.SetAttribute(accounts[acc].name[char].Pub_box, "FGCOLOR*:2", Colour_Not_Complete) iup.SetAttribute(accounts[acc].name[char].Pub_box, "FGCOLOR*:3", Colour_Not_Complete) iup.SetAttribute(accounts[acc].name[char].Pub_box, "FGCOLOR*:4", Colour_Not_Complete) for id,_ in pairs (pub_dat) do if thischar.ach[id] ~= nil then local colour = "FGCOLOR" .. pub_dat[id].L .. ":" .. pub_dat[id].C iup.SetAttribute(accounts[acc].name[char].Pub_box, colour, Colour_Complete) end end if thischar.ach[1068] ~= nil then --EP Conqueror iup.SetAttribute(accounts[acc].name[char].Pub_box, "BGCOLOR0:1", Colour_Heading_Complete) end if thischar.ach[1070] ~= nil then --DC Conqueror iup.SetAttribute(accounts[acc].name[char].Pub_box, "BGCOLOR0:2", Colour_Heading_Complete) end if thischar.ach[1069] ~= nil then --AD Conqueror iup.SetAttribute(accounts[acc].name[char].Pub_box, "BGCOLOR0:3", Colour_Heading_Complete) end for id,_ in pairs (pub_dat) do -- Load text accounts[acc].name[char].Pub_box:setcell(pub_dat[id].L,pub_dat[id].C,pub_dat[id].name) end accounts[acc].name[char].Pub_box.Redraw= "ALL" -- Create Vet Dungeon Achievements Box========================== accounts[acc].name[char].Vet_box= iup.matrix {numcol=5, numcol_visible=5, numlin=5, widthdef=110} for i=1, 5 do -- Load headings accounts[acc].name[char].Vet_box:setcell(0,i, Area_names[i].medium) end iup.SetAttribute(accounts[acc].name[char].Vet_box, "READONLY", "YES") iup.SetAttribute(accounts[acc].name[char].Vet_box, "FGCOLOR*:1", Colour_Not_Complete) iup.SetAttribute(accounts[acc].name[char].Vet_box, "FGCOLOR*:2", Colour_Not_Complete) iup.SetAttribute(accounts[acc].name[char].Vet_box, "FGCOLOR*:3", Colour_Not_Complete) iup.SetAttribute(accounts[acc].name[char].Vet_box, "FGCOLOR*:4", Colour_Not_Complete) iup.SetAttribute(accounts[acc].name[char].Vet_box, "FGCOLOR*:5", Colour_Not_Complete) -- Need to keep track of multiple achievements in Vet dungeons. Index them by dungeon LineColumn. Vet_Info={} for id,_ in pairs (vet_dat) do -- Load Dungeons Info LC is the Dungeon Identifier local L = vet_dat[id].L local C = vet_dat[id].C Vet_Info[L..C] = {count = 0} accounts[acc].name[char].Vet_box:setcell(L,C,vet_dat[id].name .. " (0)") end for id,_ in pairs (vet_dat) do -- For Achievements we have.. if thischar.ach[id] ~= nil then local L = vet_dat[id].L local C = vet_dat[id].C --Set colour of LC local colour = "FGCOLOR" .. L .. ":" .. C iup.SetAttribute(accounts[acc].name[char].Vet_box, colour, Colour_Complete) -- Increment count and display Vet_Info[L..C].count = Vet_Info[L..C].count+1 accounts[acc].name[char].Vet_box:setcell(L,C,vet_dat[id].name .. " (" .. Vet_Info[L..C].count ..")") end end if thischar.ach[1159] ~= nil then -- Coh All special. iup.SetAttribute(accounts[acc].name[char].Vet_box, "FGCOLOR3:3", Colour_Heading_Complete) end if thischar.ach[1139] ~= nil then -- Craglorn all special. iup.SetAttribute(accounts[acc].name[char].Vet_box, "BGCOLOR0:5", Colour_Heading_Complete) end accounts[acc].name[char].Vet_box.Redraw= "ALL" -- Create Locations Box============================================== accounts[acc].name[char].Map_box= iup.matrix {numcol=6, numcol_visible=6, numlin=0, widthdef=70} accounts[acc].name[char].Map_box:setcell(0,0, L.Location) accounts[acc].name[char].Map_box:setcell(0,1, L.Visits) accounts[acc].name[char].Map_box:setcell(0,2, L.FirstVisited) accounts[acc].name[char].Map_box:setcell(0,3, L.FirstLevel) accounts[acc].name[char].Map_box:setcell(0,4, L.TimesLeveled) accounts[acc].name[char].Map_box:setcell(0,5, L.FirstDeath) accounts[acc].name[char].Map_box:setcell(0,6, L.Deaths) iup.SetAttribute(accounts[acc].name[char].Map_box, "READONLY", "YES") iup.SetAttribute(accounts[acc].name[char].Map_box, "ALIGNMENT0", "ALEFT") iup.SetAttribute(accounts[acc].name[char].Map_box, "WIDTH0", "100") iup.SetAttribute(accounts[acc].name[char].Map_box, "WIDTH1", "40") iup.SetAttribute(accounts[acc].name[char].Map_box, "WIDTH4", "55") iup.SetAttribute(accounts[acc].name[char].Map_box, "WIDTH6", "40") local map_names = {} for map,_ in pairs(thischar.maps) do table.insert(map_names,map) end table.sort(map_names) local Line =1 for _, map in ipairs(map_names) do accounts[acc].name[char].Map_box.numlin = Line accounts[acc].name[char].Map_box:setcell( Line,0, map) if thischar.maps[map].visit ~= nil then accounts[acc].name[char].Map_box:setcell( Line,1, thischar.maps[map].visit) end if thischar.maps[map].firstvisitdate ~= nil then local firstvisit = os.date(dateformat,thischar.maps[map].firstvisitdate) accounts[acc].name[char].Map_box:setcell( Line,2, firstvisit) end if thischar.maps[map].firstlevel ~= nil then accounts[acc].name[char].Map_box:setcell( Line,3, thischar.maps[map].firstlevel) end if thischar.maps[map].timeslevel ~= nil then accounts[acc].name[char].Map_box:setcell( Line,4, thischar.maps[map].timeslevel) end if thischar.maps[map].firstdeathlevel ~= nil then accounts[acc].name[char].Map_box:setcell( Line,5, thischar.maps[map].firstdeathlevel) end if thischar.maps[map].deaths ~= nil then accounts[acc].name[char].Map_box:setcell( Line,6, thischar.maps[map].deaths ) end Line= Line +1 end -- ==================================== -- == Prepare for the user display tabs accounts[acc].name[char].tab = iup.vbox{ ["tabtitle"] = char, -- This vbox will be a tab and the tab text is this iup.hbox{ --Top Information bar Alignment = "ACENTER", iup.label{title=accounts[acc].name[char].gender, FONT="Times,BOLD,10"}, iup.label{title=thischar.Race .." / ".. thischar.Class, PADDING="10X0", FONT="Times,BOLD,10"}, iup.label{title=thischar.Alliance, PADDING="10X0"}, iup.label{title=L.Level .. ": ".. accounts[acc].name[char].levelstr, PADDING="10X0"}, iup.label{title=L.Created .. os.date(dateformat,thischar.Created), PADDING="10X0"}, iup.label{title=L.LLog .. os.date(dateformat,thischar.LoginTime), PADDING="10X0"}, iup.label{title=L.TPlayed .. accounts[acc].name[char].timeplayed .." " .. L.Hrs}, iup.fill{} }, iup.label{SEPARATOR="HORIZONTAL"}, iup.vbox { --Data tabs for Char iup.tabs { iup.vbox { ["tabtitle"] =L.GrpDungeon, iup.label{title=L.GrpLab,expand="HORIZONTAL"}, accounts[acc].name[char].Grp_box, iup.fill{} }, iup.vbox { ["tabtitle"] =L.PubDungeon, iup.label{title=L.PubLab,expand="HORIZONTAL"}, accounts[acc].name[char].Pub_box, iup.fill{} }, iup.vbox { ["tabtitle"] =L.VetDungeon, iup.label{title=L.VetLab,expand="HORIZONTAL"}, accounts[acc].name[char].Vet_box, iup.fill{} }, iup.vbox { ["tabtitle"] =L.Leveling, -- iup.label{title="LevLabel",expand="HORIZONTAL"}, accounts[acc].name[char].leveling_box, iup.fill{} }, iup.vbox { ["tabtitle"] =L.Locations, -- iup.label{title="LevLabel",expand="HORIZONTAL"}, accounts[acc].name[char].Map_box, iup.fill{} }, }, -- end of tabs for dungeons }, } -- end of tabs for characters vbox iup.Append(accounts[acc].tabs,accounts[acc].name[char].tab) local panel =(#accounts[acc].names * 90) if panel < 680 then panel = 680 elseif panel >950 then panel = 950 end accounts[acc].panelsize = tostring(panel) .. "x250" end -- Chars -- Add to end of Characters iup.Append(accounts[acc].tabs, accounts[acc].log_tab) end -- Accounts --print_old() function select_account() local selected if naccounts > 1 then selected = iup.ListDialog (1, L.SelectA, 2, --Size accounts_list, 1, --Initial 1,naccounts --MaxCol MaxLine ) if selected <0 then return nil -- Cancelled else return accounts_list[selected+1] end else return accounts_list[1] -- only 1 account, no need for Dialog end end -- Create dialog to choose account myaccount=select_account() if myaccount ~=nil then -- Create dialog if not canceled dlg = iup.dialog{iup.vbox{accounts[myaccount].tabs, iup.hbox{lbl_Status_bar, -- Bottom Status bar. iup.fill{}, }, margin="5x5", }, title=L.title .. myaccount, size=accounts[myaccount].panelsize } -- Shows dialog in the center of the screen dlg:showxy(iup.CENTER, iup.CENTER) if (iup.MainLoopLevel()==0) then iup.MainLoop() end end