diff mleqdkp.lua @ 1:822b6ca3ef89

Import of 2.15, moving to wowace svn.
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Sat, 16 Apr 2011 06:03:29 +0000
parents
children 67b8537e8432
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mleqdkp.lua	Sat Apr 16 06:03:29 2011 +0000
@@ -0,0 +1,350 @@
+if UnitName"player" ~= "Farmbuyer" then return end
+local addon = select(2,...)
+
+-- 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).
+local state = {}
+local tag_lookup_handlers = {}
+local do_tag_lookup_handler
+
+
+--[[
+This is taken from 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.
+
+Case of tag names shouldn't matter, but is preserved here from CT_RaidTracker
+code for comparison of generated output.
+
+There is some waste adding newlines between elements here only to strip them
+out later, but it's worth the extra cycles for debugging and verification.
+
+$TIMESTAMP,$ENDTIME MM/DD/YY HH:mm:ss except we don't have seconds available
+$REALM              GetRealmName()
+$ZONE               raw name, not snarky
+$RAIDNOTE           arbitrary text for the raid event
+$PHAT_LEWTS         all accumulated loot entries
+]]
+local XML = ([====[
+<RaidInfo>
+<Version>1.4</Version>  {In live output, this is missing due to scoping bug in ct_raidtracker.lua:3471}
+<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}
+<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.}}
+
+<BossKills>
+  $BOSS_KILLS
+</BossKills>
+
+{<Wipes>  bleh}
+{<NextBoss>Baron Steamroller</NextBoss>  {only one "next boss" for the whole raid event?  huh?}}
+
+<note><![CDATA[$RAIDNOTE - Zone: $ZONE]]></note>
+
+{<Join>...</Join><Leave>...</Leave>   {specific timestamps per player. meh.}}
+
+<Loot>
+  $PHAT_LEWTS
+</Loot>
+</RaidInfo>]====]):gsub('%b{}', "")
+
+--[[
+See the loot markup, next block.
+]]
+local boss_kills_xml = ([====[
+  <key$N>
+    <name>$BOSS_NAME</name>
+    <time>$BOSS_TIME</time>
+    <attendees></attendees>   {this is actually empty in the working example...}
+    <difficulty>$DIFFICULTY</difficulty>
+  </key$N>
+]====]):gsub('%b{}', "")
+
+local function boss_kills_tag_lookup (tag)
+	if tag == 'N' then
+		return tostring(state.key)
+	elseif tag == 'BOSS_NAME' then
+		return state.entry.bosskill
+	elseif tag == 'BOSS_TIME' then
+		return do_tag_lookup_handler (state.index, state.entry, 'TIME')
+	else
+		return do_tag_lookup_handler (state.index, state.entry, tag) or 'NYI'
+	end
+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:"
+$ICON               Last component of texture path?
+$CLASS,$SUBCLASS    ItemType
+$COLOR              GetItemQualityColor, full 8-digit string
+$COUNT,$BOSS,$ZONE,
+  $PLAYER           all self-explanatory
+$COSTS              in DKP points... hmmm
+$ITEMNOTE           take the notes field for this one
+$TIME               another formatted timestamp
+]]
+local phat_lewt_xml = ([====[
+  <key$N>
+$LEWT_GRUNTWORK
+    <zone>$ZONE</zone>   {may be optional}
+    <difficulty>$DIFFICULTY</difficulty>   {this scales badly in places like ICC.  may be optional?}
+    <Note><![CDATA[$ITEMNOTE - Zone: $ZONE - Boss: $BOSS - $COSTS DKP]]></Note> {zone can be followed by difficulty}
+  </key$N>
+]====]):gsub('%b{}', "")
+
+local function phat_lewt_tag_lookup (tag)
+	if tag == 'N' then
+		return tostring(state.key)
+	elseif tag == 'COSTS'
+		then return '1'
+	else
+		return do_tag_lookup_handler (state.index, state.entry, tag) or 'NYI'
+	end
+end
+
+do
+	local gruntwork_tags = {
+		"ItemName", "ItemID", "Icon", "Class", "SubClass", "Color", "Count",
+		"Player", "Costs", "Boss", "Time",
+	}
+	for i,tag in ipairs(gruntwork_tags) do
+		gruntwork_tags[i] = ("    <%s>$%s</%s>"):format(tag,tag:upper(),tag)
+	end
+	phat_lewt_xml = phat_lewt_xml:gsub('$LEWT_GRUNTWORK', table.concat(gruntwork_tags,'\n'))
+end
+
+
+local function format_EQDKP_timestamp (day_entry, time_entry)
+	--assert(day_entry.kind == 'time', day_entry.kind .. " passed to MLEQDKP timestamp")
+	return addon:format_timestamp ("$M/$D/$Y $h:$m:00", day_entry, time_entry)
+end
+
+
+-- Look up tag strings for a particular item, given index and entry table.
+tag_lookup_handlers.ITEMNAME =
+	function (i, e)
+		return e.itemname
+	end
+
+tag_lookup_handlers.ITEMID =
+	function (i, e)
+		return e.itemlink:match("^|c%x+|H(item[%d:]+)|h%[")
+	end
+
+tag_lookup_handlers.ICON =
+	function (i, e)
+		local str = e.itexture
+		repeat
+			local s = str:find('\\')
+			if s then str = str:sub(s+1) end
+		until not s
+		return str
+	end
+
+tag_lookup_handlers.CLASS =
+	function (i, e)
+		return state.class
+	end
+
+tag_lookup_handlers.SUBCLASS =
+	function (i, e)
+		return state.subclass
+	end
+
+tag_lookup_handlers.COLOR =
+	function (i, e)
+		local q = select(4, GetItemQualityColor(e.quality))
+		return q:sub(3)  -- skip leading |c
+	end
+
+tag_lookup_handlers.COUNT =
+	function (i, e)
+		return e.count and e.count:sub(2) or "1"   -- skip the leading "x"
+	end
+
+-- maybe combine these next two
+tag_lookup_handlers.BOSS =
+	function (i, e)
+		while i > 0 and state.loot[i].kind ~= 'boss' do
+			i = i - 1
+		end
+		if i == 0 then return "No Boss Entry Found, Unknown Boss" end
+		return state.loot[i].bosskill
+	end
+
+tag_lookup_handlers.ZONE =
+	function (i, e)
+		while i > 0 and state.loot[i].kind ~= 'boss' do
+			i = i - 1
+		end
+		if i == 0 then return "No Boss Entry Found, Unknown Zone" end
+		return state.loot[i].instance
+	end
+
+tag_lookup_handlers.DIFFICULTY =
+	function (i, e)
+		local tag = tag_lookup_handlers.ZONE(i,e)
+		local N,h = tag:match("%((%d+)(h?)%)")
+		if not N then return "1" end -- maybe signal an error instead?
+		N = tonumber(N)
+		N = ( (N==10) and 1 or 2 ) + ( (h=='h') and 2 or 0 )
+		return tostring(N)
+	end
+
+tag_lookup_handlers.PLAYER =
+	function (i, e)
+		return state.player
+	end
+
+tag_lookup_handlers.ITEMNOTE =
+	function (i, e)
+		return state.itemnote
+	end
+
+tag_lookup_handlers.TIME =
+	function (i, e)
+		local ti,tl = addon:find_previous_time_entry(i)
+		return format_EQDKP_timestamp(tl,e)
+	end
+
+
+function do_tag_lookup_handler (index, entry, tag)
+	local h = tag_lookup_handlers[tag]
+	if h then
+		return h(index,entry)
+	else
+		error(("MLDKP tag lookup (index %d) on tag %s with no handler"):format(index,tag))
+	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
+	-- here is regenerating it from scratch each time.
+	generated[ttype] = nil
+
+	local _
+	local text = XML
+	state.loot = loot
+
+	-- TIMESTAMPs
+	do
+		local f,l  -- first and last timestamps in the table
+		for i = 1, #loot do
+			if loot[i].kind == 'time' then
+				f = format_EQDKP_timestamp(loot[i])
+				break
+			end
+		end
+		_,l = addon:find_previous_time_entry(#loot)  -- latest timestamp
+		l = format_EQDKP_timestamp(l,loot[#loot])
+		text = text:gsub('$TIMESTAMP', f):gsub('$ENDTIME', l)
+	end
+
+	-- Loot
+	do
+		local all_lewts = {}
+		local lewt_template = phat_lewt_xml
+
+		state.key = 1
+		for i,e in addon:filtered_loot_iter('loot') do
+			state.index, state.entry = i, e
+			-- no sense doing repeated getiteminfo calls
+			state.class, state.subclass = select(6, GetItemInfo(e.id))
+
+			-- similar logic as text_tabs.lua:
+			-- assuming nobody names a toon "offspec" or "gvault"
+			local P, N
+			local disp = e.disposition or e.person
+			if disp == 'offspec' then
+				P,N = e.person, "offspec"
+			elseif disp == 'gvault' then
+				P,N = "guild vault", e.person
+			else
+				P,N = disp, ""
+			end
+			if e.extratext_byhand then
+				N = N .. " -- " .. e.extratext
+			end
+			state.player, state.itemnote = P, N
+
+			all_lewts[#all_lewts+1] = lewt_template:gsub('%$([%w_]+)',
+				phat_lewt_tag_lookup)
+			state.key = state.key + 1
+		end
+
+		text = text:gsub('$PHAT_LEWTS', table.concat(all_lewts, '\n'))
+	end
+
+	-- Bosses
+	do
+		local all_bosses = {}
+		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...
+				state.index, state.entry = i, e
+				all_bosses[#all_bosses+1] = boss_template:gsub('%$([%w_]+)',
+					boss_kills_tag_lookup)
+				state.key = state.key + 1
+			end
+		end
+
+		text = text:gsub('$BOSS_KILLS', table.concat(all_bosses, '\n'))
+	end
+
+	-- In addition to doing the top-level zone, this will also catch any
+	-- leftover $ZONE tags.  There could be multiple places in the raid, so
+	-- we default to the first one we saw.
+	do
+		local iter = addon:filtered_loot_iter()  -- HACK
+		local first_boss = iter('boss',0)
+		local zone = first_boss and loot[first_boss].instance or "Unknown"
+		text = text:gsub('$ZONE', zone)
+	end
+
+	-- Misc
+	text = text:gsub('$REALM', (GetRealmName()))
+	--text = text:gsub('$DIFFICULTY', )
+	text = text:gsub('$RAIDNOTE', "")
+
+	cache[#cache+1] = "Formatted version (scroll down for unformatted):"
+	cache[#cache+1] = "==========================="
+	cache[#cache+1] = text
+	cache[#cache+1] = '\n'
+
+	cache[#cache+1] = "Unformatted version:"
+	cache[#cache+1] = "==========================="
+	text = text:gsub('>%s+<', "><")
+	cache[#cache+1] = text
+	cache[#cache+1] = '\n'
+
+	wipe(state)
+	return true
+end
+
+local function specials (_, editbox, container, mkbutton)
+	local hl = mkbutton("Highlight",
+		[[Highlight the unformatted copy for copy-and-pasting.]])
+	hl:SetFullWidth(true)
+	hl:SetCallback("OnClick", function(_hl)
+		local txt = editbox:GetText()
+		local _,start = txt:find("Unformatted version:\n=+\n")
+		local _,finish = txt:find("</RaidInfo>", start)
+		editbox.editBox:HighlightText(start,finish)
+		editbox.editBox:SetCursorPosition(start)
+	end)
+	container:AddChild(hl)
+end
+
+addon:register_text_generator ("mleqdkp", [[ML/EQ-DKP]], [[MLdkp 1.1 EQDKP format]], generator, specials)
+
+-- vim:noet