Go to Page... |
Thread Tools | Display Modes |
08-05-05, 01:19 PM | #1 |
Table.sort and other issues for HealTracker
I'm in the process of polishing up a healer-side heal tracker, so you can track your efficiency and your overhealing percentage. I do this by grabbing the events for periodic and regular heals, and checking the health of the target of the heal. Right now its kinda clunky but its working. Essentially it gives you a short listing of your top 5 or 10 heal targets (by total amount) and gives you an efficiency rating on that user. You can then mouseover the user to get detailed information about each spell you've cast.
I've got two problem I'm trying to work out to keep the code as efficient as possible. Table structure looks like: table["Player"].total table["Player"].actual table["Player"]["Spell"].total table["Player"]["Spell"].actual table["Player"]["Spell"].casts table["Player"]["Spell"].crits I give detailed stats about each individual spell, so you can gauge your efficiency on each type of heal. Since the table is keyed, I wasn't able to get it sorted based upon the interior elements, so to cut down on the sort time and memory, I'm building an external table of the keys, and sorting that based upon the info we have. For example: {"Sagart", "Dewin", "Satrina"} function (a,b) return healStats.a.total > healStats.b.total end) And that seems to sort the table well, without too many lookups, but I'm wondering if I'm missing something that could make this easier. The second issue I'm concerned about is the clunky method to lookup the health of the current target. Code:
function HealTracker_GetActual(unitName, amount) local unitID = nil if unitName == "you" then unitID = "player" end for i, trialUnit in { "party1", "party2", "party3", "party4" } do if ( unitName == UnitName(trialUnit) ) then unitID = trialUnit end end for i=1,40,1 do local trialUnit = "raid"..i; if ( unitName == UnitName(trialUnit) ) then unitID = trialUnit end end if not unitID then return nil end local missinghp = UnitHealthMax(unitID) - UnitHealth(unitID); local healState = amount - missinghp; if healState > 0 then return missinghp else return amount end end Thanks! |
|
08-05-05, 03:33 PM | #2 |
The code you have is really not bad. (Yeah, I know, glowing praise. Seriously though, unless the code is in a tight loop or OnUpdate it probably won't make much performance difference.)
The sort problem can be solved without making a table of keys -- just make another table from the contents of the keyed table. When you assign a table to a variable, Lua doesn't copy the table; it just shares the original table. If you know what a pointer is, what you want to do is create two tables that contain pointers to the same player info. One table is indexed by player name. The other table is sorted by index. Maybe this example will help: Code:
local player = { } player["foo"] = { name = "foo", total = 10, actual = 17 } player["bar"] = { name = "bar", total = 7, actual = 47 } player["goo"] = { name = "goo", total = 12, actual = 5 } local sorted_player = { } for k, v in player do table.insert(sorted_player, v) end table.sort(sorted_player, function(x, y) return x.total > y.total end) for i=1,3 do print(sorted_player[i].name, sorted_player[i].total) end One thing you might think is ugly is my replacing your "partyN" loop with a numeric loop. Surprisingly the "party"..i does not generate garbage, but the { "party1", ... } does. Lua has shared (or interned) strings. This means that every time it builds a string, it looks up the string in a master dictionary to see if the string already exists. If it does, then the new string is thrown away and the old string is re-used. Lua doesn't do this for tables though. In your original code, the party table is re-created (and thrown away) every time. Here's my implementation of HealTracker_GetActual: Code:
local unit_name_to_id = { } function HealTracker_GetActual(unit_name, amount) local unit_id = unit_name_to_id[unit_name] if not unit_id then if unit_name == "you" then unit_id = "player" else for i=1, 4 do local trialUnit = "party"..i if unit_name == UnitName(trialUnit) then unit_id = trialUnit break end end if not unit_id then for i=1, 40 do local trialUnit = "raid"..i if unit_name == UnitName(trialUnit) then unit_id = trialUnit break end end end end unit_name_to_id[unit_name] = unit_id end if not unit_id then return nil end local missinghp = UnitHealthMax(unit_id) - UnitHealth(unit_id) local healState = amount - missinghp if healState > 0 then return missinghp else return amount end end |
|
08-09-05, 07:39 AM | #3 |
Thanks for the response LJ... Yes I am the same Cladhaire that is taking over development of WatchDog.. and if your'e the one who posted a while ago in the WoW forums about efficiency of the parsing algorithm, then I've been looking for you :P
Vika has been called away by the miliary and at this point his account is cancelled and has no plans to return. He's passed full control of the mod over to me (which is a scary thing) but asked me to keep in the main spirit of what he was trying to accomplish. I'm working on some siginifigant rewrite right now, particularly in the loading/saving of the savedvariables, which may no longer be an issue with per-add-on files. |
|
WoWInterface » Developer Discussions » General Authoring Discussion » Table.sort and other issues for HealTracker |
«
Previous Thread
|
Next Thread
»
|
Display Modes |
Linear Mode |
Switch to Hybrid Mode |
Switch to Threaded Mode |
|
|