Mercurial > wow > ouroloot
diff mleqdkp.lua @ 10:67b8537e8432
More work on ML/EQDKP generator and its spawned subprojects.
author | Farmbuyer of US-Kilrogg <farmbuyer@gmail.com> |
---|---|
date | Tue, 28 Jun 2011 07:36:26 +0000 |
parents | 822b6ca3ef89 |
children | 40ff9c63badc |
line wrap: on
line diff
--- a/mleqdkp.lua Fri Jun 17 20:30:46 2011 +0000 +++ b/mleqdkp.lua Tue Jun 28 07:36:26 2011 +0000 @@ -1,5 +1,14 @@ -if UnitName"player" ~= "Farmbuyer" then return end +-- This file is one gigantic exercise in abusing the garbage collector via +-- string manipulation. A real XML-handling library would be cleaner, alas, +-- we can't load third-party .so/.dll inside the WoW client. Life is hard. + local addon = select(2,...) +local pairs, ipairs, tinsert, tremove, tconcat = pairs, ipairs, table.insert, table.remove, table.concat +local tostring, tonumber = tostring, tonumber + +local banner_formatted = "Formatted version (scroll down for unformatted):" +local banner_unformatted = "Unformatted version:" +local banner_sep = "===========================" -- We keep some local state bundled up rather than trying to pass it around -- as paramters (which would have entailed creating a ton of closures). @@ -9,7 +18,7 @@ --[[ -This is taken from CT_RaidTracker 1.7.32, reconstructing the output from +This is based on CT_RaidTracker 1.7.32, reconstructing the output from code inspection. No official format documents are available on the web without downloading and installing the EQDKP webserver package. Bah. @@ -31,22 +40,32 @@ <key>$TIMESTAMP</key> <realm>$REALM</realm> <start>$TIMESTAMP</start> {Same as the key, apparently?} -<end>$ENDTIME</end> {Set by the "end the raid" command in the raid tracker, here just the final entry time} +<end>$ENDTIME</end> {Set by the "end the raid" command in CTRT, here it is just the final entry time} <zone>$ZONE</zone> {may be optional. first one on the list in case of multiple zones?} {<difficulty>$DIFFICULTY</difficulty> {this scales badly in places like ICC. may be optional?}} -{<PlayerInfos>... {guh.}} +<PlayerInfos> + $PLAYER_INFOS +</PlayerInfos> <BossKills> $BOSS_KILLS </BossKills> -{<Wipes> bleh} -{<NextBoss>Baron Steamroller</NextBoss> {only one "next boss" for the whole raid event? huh?}} +<Wipes> + $WIPES +</Wipes> +{<NextBoss>Baron Steamroller</NextBoss> {only one "next boss" for the whole + raid event? presumably where to pick up next time?}} <note><![CDATA[$RAIDNOTE - Zone: $ZONE]]></note> -{<Join>...</Join><Leave>...</Leave> {specific timestamps per player. meh.}} +<Join> + $JOINS +</Join> +<Leave> + $LEAVES +</Leave> <Loot> $PHAT_LEWTS @@ -54,7 +73,7 @@ </RaidInfo>]====]):gsub('%b{}', "") --[[ -See the loot markup, next block. +See the loot markup below. ]] local boss_kills_xml = ([====[ <key$N> @@ -78,9 +97,52 @@ end --[[ +Handles the PlayerInfo, Join, and Leave tags. +]] +local joinleave_xml +local player_info_xml = ([====[ + <key$N> +$PLAYER_GRUNTWORK + </key$N> +]====]):gsub('%b{}', "") + +local function player_info_tag_lookup (tag) + if tag == 'N' then + return tostring(state.key) + elseif tag == 'NAME' then + return state.index + elseif tag == 'TIME' then + return state.time + end + local ltag = tag:lower() + if state.entry[ltag] then + -- handles race, guild, sex, class, level + return state.entry[ltag] + end + return "?" +end + +do + local pi_xml_save = player_info_xml + local gruntwork_tags = { + "name", "race", "guild", "sex", "class", "level" + } + for i,tag in ipairs(gruntwork_tags) do + gruntwork_tags[i] = (" <%s>$%s</%s>"):format(tag,tag:upper(),tag) + end + player_info_xml = player_info_xml:gsub('$PLAYER_GRUNTWORK', table.concat(gruntwork_tags,'\n')) + + -- The join/leave blocks use "player" instead of "name". They don't have a + -- guild tag, but they do have a time tag. + gruntwork_tags[1] = " <player>$NAME</player>" + gruntwork_tags[3] = " <time>$TIME</time>" + joinleave_xml = pi_xml_save:gsub('$PLAYER_GRUNTWORK', table.concat(gruntwork_tags,'\n')) +end + +--[[ $N 1-based loop variable for key element -$ITEMNAME Without The Brackets -$ITEMID Not the ID, actually a full itemstring without the leading "item:" +$ITEMNAME Without The Square Brackets of the Whale +$ITEMID Not the numeric ID, actually a full itemstring without the leading "item:" $ICON Last component of texture path? $CLASS,$SUBCLASS ItemType $COLOR GetItemQualityColor, full 8-digit string @@ -169,7 +231,7 @@ return e.count and e.count:sub(2) or "1" -- skip the leading "x" end --- maybe combine these next two +-- should combine these next two tag_lookup_handlers.BOSS = function (i, e) while i > 0 and state.loot[i].kind ~= 'boss' do @@ -224,6 +286,7 @@ end end + local function generator (ttype, loot, last_printed, generated, cache) -- Because it's XML, generated text is "grown" by shoving more crap into -- the middle instead of appending to the end. Only easy way of doing that @@ -280,25 +343,49 @@ state.key = state.key + 1 end - text = text:gsub('$PHAT_LEWTS', table.concat(all_lewts, '\n')) + text = text:gsub('$PHAT_LEWTS', tconcat(all_lewts, '\n')) end - -- Bosses + -- Player info, join times, leave times do - local all_bosses = {} + local all_players, all_joins, all_leaves = {}, {}, {} + local player_template, joinleave_template = player_info_xml, joinleave_xml + local date = date + + state.key = 1 + if type(loot.raiders) == 'table' then for name,r in pairs(loot.raiders) do + state.index, state.entry = name, r + all_players[#all_players+1] = player_template:gsub('%$([%w_]+)', player_info_tag_lookup) + state.time = date ("%m/%d/%y %H:%M:00", r.join) + all_joins[#all_joins+1] = joinleave_template:gsub('%$([%w_]+)', player_info_tag_lookup) + state.time = date ("%m/%d/%y %H:%M:00", r.leave) + all_leaves[#all_leaves+1] = joinleave_template:gsub('%$([%w_]+)', player_info_tag_lookup) + state.key = state.key + 1 + end end + text = text:gsub('$PLAYER_INFOS', tconcat(all_players, '\n')) + :gsub('$JOINS', tconcat(all_joins, '\n')) + :gsub('$LEAVES', tconcat(all_leaves, '\n')) + end + + -- Bosses and wipes (does anybody really use the latter?) + do + local all_bosses, all_wipes = {}, {} local boss_template = boss_kills_xml state.key = 1 for i,e in addon:filtered_loot_iter('boss') do - if e.reason == 'kill' then -- oh, for a 'continue' statement... + if e.reason == 'kill' then state.index, state.entry = i, e all_bosses[#all_bosses+1] = boss_template:gsub('%$([%w_]+)', boss_kills_tag_lookup) state.key = state.key + 1 + elseif e.reason == 'wipe' then + all_wipes[#all_wipes+1] = ('<Wipe>%d</Wipe>'):format(e.stamp) end end - text = text:gsub('$BOSS_KILLS', table.concat(all_bosses, '\n')) + text = text:gsub('$BOSS_KILLS', tconcat(all_bosses, '\n')) + :gsub('$WIPES', tconcat(all_wipes, '\n')) end -- In addition to doing the top-level zone, this will also catch any @@ -316,13 +403,13 @@ --text = text:gsub('$DIFFICULTY', ) text = text:gsub('$RAIDNOTE', "") - cache[#cache+1] = "Formatted version (scroll down for unformatted):" - cache[#cache+1] = "===========================" + cache[#cache+1] = banner_formatted + cache[#cache+1] = banner_sep cache[#cache+1] = text cache[#cache+1] = '\n' - cache[#cache+1] = "Unformatted version:" - cache[#cache+1] = "===========================" + cache[#cache+1] = banner_unformatted + cache[#cache+1] = banner_sep text = text:gsub('>%s+<', "><") cache[#cache+1] = text cache[#cache+1] = '\n' @@ -332,17 +419,41 @@ end local function specials (_, editbox, container, mkbutton) - local hl = mkbutton("Highlight", + local b = mkbutton("Highlight", [[Highlight the unformatted copy for copy-and-pasting.]]) - hl:SetFullWidth(true) - hl:SetCallback("OnClick", function(_hl) + b:SetFullWidth(true) + b:SetCallback("OnClick", function(_b) + local _,start,finish local txt = editbox:GetText() - local _,start = txt:find("Unformatted version:\n=+\n") - local _,finish = txt:find("</RaidInfo>", start) + _,start = txt:find(banner_unformatted..'\n'..banner_sep..'\n') + _,finish = txt:find("</RaidInfo>", start) editbox.editBox:HighlightText(start,finish) editbox.editBox:SetCursorPosition(start) end) - container:AddChild(hl) + container:AddChild(b) + + local b = mkbutton("Re-Unformat", + [[Regenerate only the unformatted copy at the bottom <*from*> the formatted copy at the top.]]) + b:SetFullWidth(true) + b:SetCallback("OnClick", function(_b) + local _,start,finish + local txt = editbox:GetText() + _,start = txt:find(banner_formatted..'\n'..banner_sep..'\n', --[[init=]]1, --[[plain=]]true) + _,finish = txt:find("</RaidInfo>", start, true) + txt = txt:sub(start+1,finish) + txt = banner_formatted .. '\n' + .. banner_sep .. '\n' + .. txt .. '\n\n\n' + .. banner_unformatted .. '\n' + .. banner_sep .. '\n' + .. txt:gsub('>%s+<', "><") .. '\n' + -- This would normally screw up the cached version, but we're regenerating + -- everything on each new display for this tab anyhow. + editbox.editBox:SetText(txt) + _,start = txt:find(banner_unformatted..'\n'..banner_sep..'\n', --[[init=]]1, --[[plain=]]true) + editbox.editBox:SetCursorPosition(start) + end) + container:AddChild(b) end addon:register_text_generator ("mleqdkp", [[ML/EQ-DKP]], [[MLdkp 1.1 EQDKP format]], generator, specials)