changeset 19:f560cf82e7d3

Smarter handling of missed item cache entries. Basic persistent logging of debug messages (options panel or /loot debug alsolog) and script to print same.
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Mon, 29 Aug 2011 01:29:13 +0000
parents ca797c0f32d4
children d89aeb6b9f9e
files LibFarmbuyer.lua Ouro_Loot.toc core.lua gui.lua print_log.lua
diffstat 5 files changed, 139 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/LibFarmbuyer.lua	Fri Aug 26 02:52:33 2011 +0000
+++ b/LibFarmbuyer.lua	Mon Aug 29 01:29:13 2011 +0000
@@ -7,22 +7,19 @@
 - author_debug
   Evaluates to true if I'm hacking on something.
 
-- tableprint(t)
+- tableprint(t[,f])
   A single print() call to the contents of T, including nils; strings are
-  cleaned up with respect to embedded '|'/control chars.  If there is a
-  global LIBFARMPRINT function, it is called with the cleaned-up T instead
-  of directly calling print.
+  cleaned up with respect to embedded '|'/control chars.  If a function F is
+  passed, calls that instead of print().  Returns the results of F, or the
+  text string passed to print(), depending on which was used.
 
 - safeprint(...)
-  Same as tableprint() on the argument list.
+  Same as tableprint() on the argument list.  Returns the results of tableprint.
 
 - safeiprint(...)
-  Same as safeprint() but with index numbers inserted.  Ex:
-  safeiprint(a,b,c)  -->  <1>,a,<2>,b,<3>,c
-
-- CHAT(n)
-  Returns a function suitable for assigning to LIBFARMPRINT, directing all
-  output to builtin chat frame N.
+  Same as safeprint() but with <index> numbers inserted.  Returns the results
+  of tableprint.
+  Ex:  safeiprint(a,b,c)  -->  <1>,a,<2>,b,<3>,c
 
 - t = StaticPopup(t)
   Fills out "typical" settings inside T, especially if T contains any kind
@@ -53,7 +50,7 @@
   Ditto for table recycling.
 ]]
 
-local MAJOR, MINOR = "LibFarmbuyer", 11
+local MAJOR, MINOR = "LibFarmbuyer", 12
 assert(LibStub,MAJOR.." requires LibStub")
 local lib = LibStub:NewLibrary(MAJOR, MINOR)
 if not lib then return end
@@ -101,19 +98,13 @@
 --[[
 	safeprint
 ]]
+local tconcat = table.concat
 local function undocontrol(c)
 	return ("\\%.3d"):format(c:byte())
 end
-function lib.CHAT(n)
-	local cf = _G["ChatFrame"..n]
-	return function(t)
-		local msg = table.concat(t,' ', i, tonumber(t.n) or #t)
-		cf:AddMessage(msg)
-	end
-end
 function lib.safeprint(...)
 	local args = { n=select('#',...), ... }
-	lib.tableprint(args)
+	return lib.tableprint(args)
 end
 function lib.safeiprint(...)
 	local args = { n=select('#',...), ... }
@@ -123,17 +114,19 @@
 		last = last - 1
 	end
 	args.n = 2 * args.n
-	lib.tableprint(args)
+	return lib.tableprint(args)
 end
-function lib.tableprint(t)
+function lib.tableprint(t,f)
 	for i = 1, (tonumber(t.n) or #t) do
 		t[i] = tostring(t[i]):gsub('\124','\124\124')
 		                     :gsub('(%c)', undocontrol)
 	end
-	if type(_G.LIBFARMPRINT) == 'function' then
-		return _G.LIBFARMPRINT(t)
+	local msg = tconcat(t,' ', i, tonumber(t.n) or #t)
+	if f then
+		return f(msg)
 	else
-		return print(unpack(t))
+		print(msg)
+		return msg,t
 	end
 end
 
@@ -295,7 +288,7 @@
 	local function CreateDispatcher(argCount)
 		local ARGS = {}
 		for i = 1, argCount do ARGS[i] = "arg"..i end
-		local code = template:gsub("ARGS", table.concat(ARGS, ", "))
+		local code = template:gsub("ARGS", tconcat(ARGS, ", "))
 		return assert(loadstring(code, "LibF/safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
 	end
 
--- a/Ouro_Loot.toc	Fri Aug 26 02:52:33 2011 +0000
+++ b/Ouro_Loot.toc	Mon Aug 29 01:29:13 2011 +0000
@@ -3,7 +3,7 @@
 ## Version: @project-version@
 ## Notes: Raid loot tracking and text generation
 ## Author: Farmbuyer of Kilrogg
-## SavedVariables: OuroLootSV, OuroLootSV_saved, OuroLootSV_opts, OuroLootSV_hist
+## SavedVariables: OuroLootSV, OuroLootSV_saved, OuroLootSV_opts, OuroLootSV_hist, OuroLootSV_log
 ## OptionalDeps: Ace3, DBM-Core, lib-st, LibFarmbuyer
 
 #@no-lib-strip@
--- a/core.lua	Fri Aug 26 02:52:33 2011 +0000
+++ b/core.lua	Mon Aug 29 01:29:13 2011 +0000
@@ -44,6 +44,7 @@
                          -- autoshard:  optional name of disenchanting player, default nil
                          -- threshold:  optional loot threshold, default nil
 OuroLootSV_hist  = nil
+OuroLootSV_log   = {}
 
 
 ------ Constants
@@ -103,14 +104,23 @@
 		flow = false,
 		notraid = false,
 		cache = false,
+		alsolog = false,
 	}
 	function dprint (t,...)
-		if DEBUG_PRINT and debug[t] then return _G.print("<"..t.."> ",...) end
+		if DEBUG_PRINT and debug[t] then
+			local text = flib.safeprint("<"..t.."> ",...)
+			if debug.alsolog then
+				addon:log_with_timestamp(text)
+			end
+		end
 	end
 
 	if author_debug then
 		function pprint(t,...)
-			return _G.print("<<"..t..">> ",...)
+			local text = flib.safeprint("<<"..t..">> ",...)
+			if debug.alsolog then
+				addon:log_with_timestamp(text)
+			end
 		end
 	else
 		pprint = flib.nullfunc
@@ -447,6 +457,7 @@
 		end
 	end end
 	OuroLootSV_hist = self.history_all
+	OuroLootSV_log = #OuroLootSV_log > 0 and OuroLootSV_log or nil
 end
 
 do
@@ -587,16 +598,16 @@
 	-- 'from' and onwards only present if this is triggered by a broadcast
 	function addon:_do_loot (local_override, recipient, itemid, count, from, extratext)
 		local itexture = GetItemIcon(itemid)
-		--local iname, ilink, iquality, _,_,_,_,_,_, itexture = GetItemInfo(itemid)
 		local iname, ilink, iquality = GetItemInfo(itemid)
+		local i
 		if (not iname) or (not itexture) then
+			i = true
 			iname, ilink, iquality, itexture = 
 				UNKNOWN..': '..itemid, 'item:6948', ITEM_QUALITY_COMMON, [[ICONS\INV_Misc_QuestionMark]]
 		end
-		self.dprint('loot',">>_do_loot, R:", recipient, "I:", itemid, "C:", count, "frm:", from, "ex:", extratext, "Q:", iquality)
+		self.dprint('loot',">>_do_loot, R:", recipient, "I:", itemid, "C:", count, "frm:", from, "ex:", extratext, "q:", iquality)
 
-		local i
-		itemid = tonumber(ilink:match("item:(%d+)"))
+		itemid = tonumber(ilink:match("item:(%d+)") or 0)
 		if local_override or ((iquality >= self.threshold) and not opts.itemfilter[itemid]) then
 			if (self.rebroadcast and (not from)) and not local_override then
 				self:broadcast('loot', recipient, itemid, count)
@@ -611,6 +622,7 @@
 						kind		= 'loot',
 						person		= recipient,
 						person_class= select(2,UnitClass(recipient)),
+						cache_miss	= i and true or nil,
 						quality		= iquality,
 						itemname	= iname,
 						id			= itemid,
@@ -622,8 +634,10 @@
 						extratext	= extratext,
 						is_heroic	= self:is_heroic_item(ilink),
 					}
-					self.dprint('loot', "added entry", i)
-					self:_addHistoryEntry(i)
+					self.dprint('loot', "added loot entry", i)
+					if not self.history_suppress then
+						self:_addHistoryEntry(i)
+					end
 					if self.display then
 						self:redisplay()
 						--[[
@@ -747,6 +761,9 @@
 			return self:BuildMainDisplay()
 		end
 
+	elseif cmd == "fixcache" then
+		self:do_item_cache_fixup()
+
 	else
 		if self:OpenMainDisplayToTab(cmd) then
 			return
@@ -852,6 +869,15 @@
 
 
 ------ Behind the scenes routines
+-- Semi-experimental debugging aid.
+do
+	local date = _G.date
+	local log = OuroLootSV_log
+	function addon:log_with_timestamp (msg)
+		tinsert (log, date('%m:%d %H:%M:%S  ')..msg)
+	end
+end
+
 -- Adds indices to traverse the tables in a nice sorted order.
 do
 	local byindex, temp = {}, {}
@@ -996,7 +1022,7 @@
 		if #candidates == 1 then
 			-- (1) or (2)
 			boss.duration = boss.duration or 0
-			addon.dprint('loot', "only one candidate")
+			addon.dprint('loot', "only one boss candidate")
 		else
 			-- (3), should only be one 'cast entry and our local entry
 			if #candidates ~= 2 then
@@ -1011,16 +1037,16 @@
 			for i,c in ipairs(candidates) do
 				if c.duration then
 					boss = c
-					addon.dprint('loot', "fixup found candidate", i, "duration", c.duration)
+					addon.dprint('loot', "fixup found boss candidate", i, "duration", c.duration)
 					break
 				end
 			end
 		end
 		bossi = addon._addLootEntry(boss)
-		--
-		bossi = addon._adjustBossOrder (bossi, g_boss_signpost)
+		-- addon.
+		bossi = addon._adjustBossOrder (bossi, g_boss_signpost) or bossi
 		g_boss_signpost = nil
-		addon.dprint('loot', "added entry", bossi)
+		addon.dprint('loot', "added boss entry", bossi)
 		if boss.reason == 'kill' then
 			addon:_mark_boss_kill (bossi)
 			if opts.chatty_on_kill then
@@ -1049,6 +1075,7 @@
 			else
 				self.recent_boss:add(signature)
 				g_boss_signpost = #g_loot + 1
+				self.dprint('loot', "added boss signpost", g_boss_signpost)
 				-- Possible scenarios:  (1) we don't see a boss event at all (e.g., we're
 				-- outside the instance) and so this only happens once as a non-local event,
 				-- (2) we see a local event first and all non-local events are filtered
@@ -1263,7 +1290,7 @@
 			return
 		end
 		if (type(is)~='number') or (type(should_be)~='number') or (is < should_be) then
-			--pprint('loot', "...the hell? bailing")
+			pprint('loot', is, should_be, "...the hell? bailing")
 			return
 		end
 		if g_loot[should_be].kind == 'time' then
@@ -1282,6 +1309,38 @@
 	end
 end
 
+-- In the rare case of items getting put into the loot table without current
+-- item cache data (which will have arrived by now).
+function addon:do_item_cache_fixup()
+	self:Print("Fixing up missing item cache data...")
+
+	local numfound = 0
+	local borkedpat = '^'..UNKNOWN..': (%S+)'
+
+	for i,e in self:filtered_loot_iter('loot') do
+		if e.cache_miss then
+			local borked_id = e.itemname:match(borkedpat)
+			if borked_id then
+				numfound = numfound + 1
+				-- Best to use the safest and most flexible API here, which is GII and
+				-- its assload of return values.
+				local iname, ilink, iquality, _,_,_,_,_,_, itexture = GetItemInfo(borked_id)
+				if iname then
+					self:Print("    Entry %d patched up with %s.", i, ilink)
+					e.quality = iquality
+					e.itemname = iname
+					e.id = tonumber(ilink:match("item:(%d+)"))
+					e.itemlink = ilink
+					e.itexture = itexture
+					e.cache_miss = nil
+				end
+			end
+		end
+	end
+
+	self:Print("...finished.  Found %d |4entry:entries; with weird data.", numfound)
+end
+
 
 ------ Saved texts
 function addon:check_saved_table(silent_p)
--- a/gui.lua	Fri Aug 26 02:52:33 2011 +0000
+++ b/gui.lua	Mon Aug 29 01:29:13 2011 +0000
@@ -302,7 +302,7 @@
 						ITEM_QUALITY_COLORS[iquality].hex, iname, loot.count or "")
 				else
 					textured = eoi_st_textured_item_format:format ([[ICONS\INV_Misc_QuestionMark]],
-						ITEM_QUALITY_COLORS[ITEM_QUALITY_COMMON].hex, 'UNKNOWN - TRY AGAIN', "")
+						ITEM_QUALITY_COLORS[ITEM_QUALITY_COMMON].hex, 'UNKNOWN - REDISPLAY LATER', "")
 					cache_okay = false
 				end
 				col2.value = textured
@@ -612,8 +612,15 @@
 	local kind = e.kind
 
 	if (kind == 'loot' and column == 1) or (kind == 'history' and column == 2) then
-		if e.itemlink then
-			GameTooltip:SetOwner (cellFrame, "ANCHOR_RIGHT", -20, 0)
+		GameTooltip:SetOwner (cellFrame, "ANCHOR_RIGHT", -20, 0)
+		if e.cache_miss then
+			GameTooltip:ClearLines()
+			GameTooltip:AddLine("Missing Cache Data")
+			GameTooltip:AddLine([[Wait a few seconds, then type]], 0.8, 0.8, 0.8, 1)
+			GameTooltip:AddLine([[/ouroloot fixcache]], 0, 1, 64/255, nil)
+			GameTooltip:AddLine([[and redisplay this window.]], 0.8, 0.8, 0.8, 1)
+			GameTooltip:Show()
+		elseif e.itemlink then
 			GameTooltip:SetHyperlink (e.itemlink)
 		end
 
@@ -1411,9 +1418,19 @@
 		w = GUI:Create("CheckBoxSmallLabel")
 		w:SetFullWidth(true)
 		w:SetType("checkbox")
-		w:SetLabel("master dtoggle")
+		w:SetLabel("debug toggle")
 		w:SetValue(addon.DEBUG_PRINT)
-		w:SetCallback("OnValueChanged", function(_w,event,value) addon.DEBUG_PRINT = value end)
+		w:SetCallback("OnValueChanged", function(_w,event,value)
+			addon.DEBUG_PRINT = value
+			addon:redisplay()
+		end)
+		simple:AddChild(w)
+		w = GUI:Create("CheckBoxSmallLabel")
+		w:SetFullWidth(true)
+		w:SetType("checkbox")
+		w:SetLabel("GOP history mode")
+		w:SetValue(false)
+		w:SetCallback("OnValueChanged", function(_w,event,value) addon.history_suppress = value end)
 		simple:AddChild(w)
 		w = mkbutton("Clear All & Reload",
 			[[No confirmation!  |cffff1010Erases absolutely all> Ouro Loot saved variables and reloads the UI.]])
@@ -1434,6 +1451,8 @@
 			w:SetLabel(d)
 			if d == "notraid" then
 				w:SetDescription("Tick this before enabling to make the addon work outside of raid groups")
+			else
+				w:SetDisabled(not addon.DEBUG_PRINT)
 			end
 			w:SetValue(v)
 			w:SetCallback("OnValueChanged", function(_w,event,value) addon.debug[d] = value end)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/print_log.lua	Mon Aug 29 01:29:13 2011 +0000
@@ -0,0 +1,22 @@
+#!/usr/bin/env lua
+
+if not arg[1] or arg[1] == "" then
+	print"Usage:  lua print_log.lua /path/to/OuroLoot_savedvars.lua"
+	print"Don't forget to delete log table after viewing!"
+	os.exit(1)
+end
+
+dofile(arg[1])
+
+if type(OuroLootSV_log) ~= 'table' then
+	print("Did not find OuroLootSV_log in", arg[1])
+	os.exit(1)
+end
+
+for _,v in ipairs(OuroLootSV_log) do
+	print(v)
+end
+
+os.exit(0)
+
+-- vim:noet ff=unix