-- Zirco's utilities -- This module should contain no globals as it is intended to be "linked" in to each of Zirco's addons local addonName, addonTable = "Auctionator", AtrNS; local zc = {}; addonTable.zc = zc; ----------------------------------------- function zc.RGBtoHEX (r,g,b) local hex = ""; return string.format ("%02x%02x%02x", r * 255, g * 255, b * 255); end ----------------------------------------- function zc.EnableDisable (elem, b) if (b) then elem:Enable(); else elem:Disable(); end end ----------------------------------------- function zc.ShowHide (elem, b) if (b) then elem:Show(); else elem:Hide(); end end ----------------------------------------- function zc.SetTextIf (elem, b, t1, t2) if (b) then elem:SetText(t1); else elem:SetText(t2); end end ----------------------------------------- function zc.Val (val, ifNilVal) if (val == nil) then return ifNilVal; end return val; end ----------------------------------------- function zc.Min (a, b) if (a == nil) then return b; end if (b == nil) then return a; end return math.min (tonumber (a), tonumber (b)); end ----------------------------------------- function zc.Max (a, b) if (a == nil) then return b; end if (b == nil) then return a; end return math.max (tonumber (a), tonumber (b)); end ----------------------------------------- function zc.If (b, x, y) if (b ~= nil and b ~= false) then return x; end return y; end ----------------------------------------- function zc.PrintKeysSorted (t) local ta = {}; for a,v in pairs (t) do table.insert (ta, a); end table.sort (ta, function (a,b) return (string.lower(a) < string.lower(b)); end); for x = 1, getn(ta) do zc.msg_pink (x.." "..ta[x]); end end ----------------------------------------- function zc.UTF8_Truncate (s, newlen) if (string.len (s) <= newlen) then return s; end local x, c; for x = newlen, 1, -1 do c = string.byte (s, x+1); if (c ~= nil and (c < 128 or c >= 192)) then -- the next byte starts a character, so cut here return string.sub (s, 1, x); end end return string.sub (s, 1, newlen); end ----------------------------------------- function zc.GetArrayElemOrFirst (a, x) if (a and getn(a) > 0) then if (x == nil or x < 1 or x > getn(a)) then x = 1; end return a[x]; end return nil; end ----------------------------------------- function zc.GetArrayElemOrNil (a, x) if (a and getn(a) > 0) then if (x == nil or x < 1 or x > getn(a)) then return nil; end return a[x]; end return nil; end ----------------------------------------- function zc.padstring (s, n, c) while (string.len (s) < n) do s = c..s; end return s; end ----------------------------------------- local encTable = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z", "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z", "0","1","2","3","4","5","6","7","8","9", "-", "_" }; local decTable; ----------------------------------------- local function BuildDecTable() if (decTable == nil) then decTable = {}; local i; for i = 1,64 do decTable[encTable[i]] = i-1; end end end ----------------------------------------- function zc.enc64 (n) if (n == 0) then return encTable[1]; end local k = n; local result = ""; while k > 0 do local x = mod (k, 64); result = encTable[x+1]..result; k = floor (k / 64); end return result; end ----------------------------------------- function zc.dec64 (s) if (s == nil or s == "") then return 0; end BuildDecTable(); local result = 0; local len = string.len (s); local x; for x = 1, len do result = result * 64; result = result + decTable[string.sub(s,x,x)]; end return result; end ----------------------------------------- function ZF (s) BuildDecTable(); local s2 = ""; local n; for n = 1, string.len(s) do local c = string.sub(s, n,n); local x = decTable[c]; if (x == nil) then s2 = s2..c; else if (x < 32) then x = x + 32; else x = x - 32; end; s2 = s2..encTable[x+1]; end end return s2; end ----------------------------------------- function zc.words(str) local t = {} local function helper(word) table.insert(t, word) return "" end local rest = string.gsub (str, "%w+", helper); if (not string.find (rest, "%S")) then if (getn(t) == 1) then return t[1]; end; if (getn(t) == 2) then return t[1],t[2]; end; if (getn(t) == 3) then return t[1],t[2],t[3]; end; if (getn(t) == 4) then return t[1],t[2],t[3],t[4]; end; if (getn(t) == 5) then return t[1],t[2],t[3],t[4],t[5]; end; return t; end end ----------------------------------------- local gDeferredCalls = {}; ----------------------------------------- function zc.AddDeferredCall (seconds, funcname, param1, param2, tag) -- tag is optional. if present used to overwrite prior call with same tag local now = time(); local cfdEntry = {}; cfdEntry.funcname = funcname; cfdEntry.param1 = param1; cfdEntry.param2 = param2; cfdEntry.when = now + seconds; cfdEntry.tag = ""; if (tag) then cfdEntry.tag = tag; for i = 1, getn(gDeferredCalls) do if (gDeferredCalls[i].tag == tag) then gDeferredCalls[i] = cfdEntry; -- overwrite return; end end end table.insert (gDeferredCalls, cfdEntry); end ----------------------------------------- function zc.CheckDeferredCall () local now = time(); local i; for i = 1, getn(gDeferredCalls) do if (gDeferredCalls[i].when < now) then local fcn = getglobal(gDeferredCalls[i].funcname); local p1 = gDeferredCalls[i].param1; local p2 = gDeferredCalls[i].param2; table.remove (gDeferredCalls, i); if (type(fcn) == 'function') then fcn(p1, p2); end return; -- only do one end end end ----------------------------------------- function zc.periodic (elem, name, period, elapsed) local t = elem[name] or 0; t = t + elapsed; if (t > period) then elem[name] = 0; return true; end elem[name] = t; return false; end ----------------------------------------- function zc.tableIsEmpty (t) local n, v; for n, v in pairs (t) do return false; end return true; end ----------------------------------------- function zc.PrintTable (t, indent) if (not indent) then indent = 0; end local x local padding = ""; for x = 1,indent do padding = padding.." "; end zc.msg ("-------"); for n, v in pairs (t) do if (type(v) == "table") then zc.msg (padding..n, "TABLE"); zc.PrintTable(v, indent+1); elseif (type(v) == "userdata") then zc.msg (padding..n, "userdata"); else zc.msg (padding..n, v); end end end ----------------------------------------- function zc.ItemIDfromLink (itemLink) if (itemLink == nil) then return 0,0,0; end -- 1.12 item strings are item:id:enchant:suffix:unique local found, _, itemString = string.find(itemLink, "^|c%x+|H(.+)|h%[.*%]") if (itemString == nil) then found, _, itemString = string.find (itemLink, "(item:[%-%d:]+)"); end if (itemString == nil) then return 0,0,0; end local _, itemId, _, suffixId, uniqueId = Atr_strsplit (":", itemString) return itemId, suffixId or 0, uniqueId or 0; end ----------------------------------------- function zc.BoolToString (b) if (b) then return "true"; end return "false"; end ----------------------------------------- function zc.BoolToNum (b) if (b) then return 1; end return 0; end ----------------------------------------- function zc.NumToBool (n) if (n == 0) then return false; end return true; end ----------------------------------------- function zc.pluralizeIf (word, count) if (count and count == 1) then return word; else return zc.pluralize(word); end end ----------------------------------------- function zc.pluralize (word) return word.."s"; end ----------------------------------------- function zc.round (v) return math.floor (v + 0.5); end ----------------------------------------- function zc.msg_red (...) zc.msg_color (1, 0, 0, unpack(arg)); end function zc.msg_pink (...) zc.msg_color (1, .6, .6, unpack(arg)); end function zc.msg_yellow (...) zc.msg_color (1, 1, 0, unpack(arg)); end ----------------------------------------- function zc.msg_color (r, g, b, ...) local options = {}; options.r = r; options.g = g; options.b = b; zc.msg_ex (options, unpack(arg)); end ----------------------------------------- function zc.msg_str (...) local options = {}; options.str = true; return zc.msg_ex (options, unpack(arg)); end ----------------------------------------- function zc.msg_atr (...) zc.msg_yellow ("|cff00ffff|r", unpack(arg)); end ----------------------------------------- function zc.HSV2RGB (h, s, v) local r, g, b; local hi = mod (math.floor(h/60), 6); local f = h/60 - math.floor(h/60); local p = v * (1-s); local q = v * (1-(f*s)); local t = v * (1-((1-f)*s)); if (hi == 0) then return v, t, p; end if (hi == 1) then return q, v, p; end if (hi == 2) then return p, v, t; end if (hi == 3) then return p, q, v; end if (hi == 4) then return t, p, v; end if (hi == 5) then return v, p, q; end return end ----------------------------------------- function zc.md (...) -- developer trace output: disabled in the 1.12 port end ----------------------------------------- function zc.msg (...) local options = {}; zc.msg_ex (options, unpack(arg)); end ----------------------------------------- function zc.msg_ex (options, ...) if (not DEFAULT_CHAT_FRAME) then return; end local msg = ""; local i; local m; for i = 1, arg.n do local v = arg[i]; if (type(v) == "boolean") then m = zc.BoolToString(v); elseif (type(v) == "table") then m = ""; elseif (v == nil) then m = ""; else m = v; end msg = msg.." "..m; end if (options.str) then return msg; end if (options.r ~= nil) then DEFAULT_CHAT_FRAME:AddMessage (msg, options.r, options.g, options.b); else DEFAULT_CHAT_FRAME:AddMessage (msg); end end ----------------------------------------- function zc.val2gsc (v) local rv = zc.round(v) local g = math.floor (rv/10000); rv = rv - g*10000; local s = math.floor (rv/100); rv = rv - s*100; local c = rv; return g, s, c end ----------------------------------------- function zc.priceToString (val) local gold, silver, copper = zc.val2gsc(val); local st = ""; if (gold ~= 0) then st = gold.."g "; end if (st ~= "") then st = st..format("%02is ", silver); elseif (silver ~= 0) then st = st..silver.."s "; end if (st ~= "") then st = st..format("%02ic", copper); elseif (copper ~= 0) then st = st..copper.."c"; end return st; end ----------------------------------------- local goldicon = "|cffffd100g|r" local silvericon = "|cffc7c7cfs|r" local coppericon = "|cffeda55fc|r" ----------------------------------------- function zc.priceToMoneyString (val, noZeroCoppers) local gold, silver, copper = zc.val2gsc(val); local st = ""; if (gold ~= 0) then st = gold..goldicon.." "; end if (st ~= "") then st = st..format("%02i%s ", silver, silvericon); elseif (silver ~= 0) then st = st..silver..silvericon.." "; end if (noZeroCoppers and copper == 0) then return st; end if (st ~= "") then st = st..format("%02i%s", copper, coppericon); elseif (copper ~= 0) then st = st..copper..coppericon; end return st; end ----------------------------------------- function zc.StringSame (s1, s2) if (s1 == nil and s2 == nil) then return true; end if (s1 == nil or s2 == nil) then return false; end if (s1 == s2) then -- maybe will fix german umlaut problem? return true; end return (string.lower (s1) == string.lower (s2)); end ----------------------------------------- function zc.StringContains (s, sub) if (sub == nil or sub == "") then return false; end local start, stop = string.find (string.lower(s), string.lower(sub), 1, true); return (start ~= nil); end ----------------------------------------- function zc.StringEndsWith (s, sub) if (sub == nil or sub == "") then return false; end local i = string.len(s) - string.len(sub); if (i < 0) then return false; end local sEnd = string.sub (s, i+1); return (string.lower (sEnd) == string.lower (sub)); end ----------------------------------------- function zc.StringStartsWith (s, sub) if (s == nil or sub == nil or sub == "") then return false; end local sublen = string.len (sub); if (string.len (s) < sublen) then return false; end return (string.lower (string.sub(s, 1, sublen)) == string.lower(sub)); end ----------------------------------------- function zc.CopyDeep (src) local result = {}; for n, v in pairs (src) do if (type(v) == "table") then result[n] = zc.CopyDeep(v); else result[n] = v; end end return result; end ----------------------------------------- function zc.printableLink (link) if (link == nil) then return "nil"; end local printable = gsub(link, "\124", "\124\124"); return printable; end ----------------------------------------- function zc.printmem () local cmem = math.floor(collectgarbage ("count")) UpdateAddOnMemoryUsage(); local mem = GetAddOnMemoryUsage("OctoAuctionator"); zc.msg_atr (math.floor(mem).." KB (total LUA: "..cmem.." KB)"); end ----------------------------------------- function zc.printstack (options) return {}; -- needs debugstack(), which the 1.12 client does not have end ----------------------------------------- function zc.tallyAdd (ttable, value) if (ttable[value]) then ttable[value] = ttable[value] + 1; else ttable[value] = 1; end end ----------------------------------------- function zc.tallyPrint (ttable, options) local sortedTable = {}; local total = 0; local n = 1; for value,count in pairs(ttable) do sortedTable[n] = {}; sortedTable[n].value = value; sortedTable[n].count = count; total = total + count; n = n + 1; end if (options.sortByValue and options.sortDesc) then table.sort (sortedTable, function(x,y) return x.value > y.value; end); elseif (options.sortByValue and not options.sortDesc) then table.sort (sortedTable, function(x,y) return x.value < y.value; end); elseif (options.sortDesc) then table.sort (sortedTable, function(x,y) return x.count > y.count; end); else table.sort (sortedTable, function(x,y) return x.count < y.count; end); end for n = 1, getn(sortedTable) do if (not options.printCount or n < options.printCount) then zc.msg_pink (sortedTable[n].count.." "..sortedTable[n].value); end end zc.msg_yellow ("Total: "..total); end