📄 enxutil.lua
字号:
--[[ Enchantrix Addon for World of Warcraft(tm). Version: 3.5.0.0917 (Platypus) Revision: $Id: EnxUtil.lua 878 2006-05-28 16:50:50Z aradan $ General utility functions License: This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program(see GLP.txt); if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.]]-- Global functionslocal isDisenchantablelocal getReagentInfolocal getLinkFromNamelocal getReagentPricelocal getItemTypelocal getItemIdFromSiglocal getItemIdFromLinklocal getSigFromLinklocal getRevisionlocal splitlocal spliteratorlocal chatPrintlocal gcdlocal roundUplocal roundlocal confidenceIntervallocal createProfiler-------------------------- Item functions ---------------------------- Return false if item id can't be disenchantedfunction isDisenchantable(id) if (id) then local _, _, quality, _, _, _, count, equip = GetItemInfo(id) if (not quality) then -- GetItemInfo() failed, item might be disenchantable return true end if (not Enchantrix.Constants.InventoryTypes[equip]) then -- Neither weapon nor armor return false end if (quality and quality < 2) then -- Low quality return false end if (count and count > 1) then -- Stackable item return false end return true end return falseend-- Frontend to GetItemInfo()-- Information for disenchant reagents are kept in a saved variable cachefunction getReagentInfo(id) local cache = EnchantConfig.cache.reagentinfo if type(id) == "string" then local _, _, i = string.find(id, "item:(%d+):") id = i end id = tonumber(id) local sName, sLink, iQuality, iLevel, sType, sSubtype, iStack, sEquip, sTexture = GetItemInfo(id) if id and Enchantrix.Constants.StaticPrices[id] then if sName then cache[id] = sName.."|"..iQuality.."|"..sTexture cache["t"] = sType elseif type(cache[id]) == "string" then local cdata = split(cache[id], "|") sName = cdata[1] iQuality = tonumber(cdata[2]) iLevel = 0 sType = cache["t"] sSubtype = cache["t"] iStack = 10 sEquip = "" sTexture = cdata[3] sLink = "item:"..id..":0:0:0" end end if sName and id then -- Might as well save this name while we have the data EnchantConfig.cache.names[sName] = "item:"..id..":0:0:0" end return sName, sLink, iQuality, iLevel, sType, sSubtype, iStack, sEquip, sTextureendfunction getLinkFromName(name) assert(type(name) == "string") if not EnchantConfig.cache then EnchantConfig.cache = {} end if not EnchantConfig.cache.names then EnchantConfig.cache.names = {} end local link = EnchantConfig.cache.names[name] if link then local n = GetItemInfo(link) if n ~= name then EnchantConfig.cache.names[name] = nil end end if not EnchantConfig.cache.names[name] then for i = 1, Enchantrix.State.MAX_ITEM_ID + 4000 do local n, link = GetItemInfo(i) if n then if n == name then EnchantConfig.cache.names[name] = link break end Enchantrix.State.MAX_ITEM_ID = math.max(Enchantrix.State.MAX_ITEM_ID, i) end end end return EnchantConfig.cache.names[name]end-- Returns HSP, median and static price for reagent-- Auctioneer values are kept in cache for 48h in case Auctioneer isn't loadedfunction getReagentPrice(reagentID) -- reagentID ::= number | hyperlink if type(reagentID) == "string" then local _, _, i = string.find(reagentID, "item:(%d+):") reagentID = i end reagentID = tonumber(reagentID) if not reagentID then return nil end local hsp, median, market market = Enchantrix.Constants.StaticPrices[reagentID] if Enchantrix.State.Auctioneer_Loaded then local itemKey = string.format("%d:0:0", reagentID); local realm = Auctioneer.Util.GetAuctionKey() hsp = Auctioneer.Statistic.GetHSP(itemKey, realm) median = Auctioneer.Statistic.GetUsableMedian(itemKey, realm) end if not EnchantConfig.cache then EnchantConfig.cache = {} end if not EnchantConfig.cache.prices then EnchantConfig.cache.prices = {} end if not EnchantConfig.cache.prices[reagentID] then EnchantConfig.cache.prices[reagentID] = {} end local cache = EnchantConfig.cache.prices[reagentID] if cache.timestamp and time() - cache.timestamp > 172800 then cache = {} end cache.hsp = hsp or cache.hsp cache.median = median or cache.median cache.market = market or cache.market cache.timestamp = time() return cache.hsp, cache.median, cache.marketend-- Return item level (rounded up to nearest 5 levels), quality and type as string,-- e.g. "20:2:Armor" for uncommon level 20 armorfunction getItemType(id) if (id) then local _, _, quality, level, _, _, _, equip = GetItemInfo(id) if (quality and quality >= 2 and level > 0 and Enchantrix.Constants.InventoryTypes[equip]) then return string.format("%d:%d:%s", Enchantrix.Util.RoundUp(level, 5), quality, Enchantrix.Constants.InventoryTypes[equip]) end endend-- Return item id as integerfunction getItemIdFromSig(sig) if type(sig) == "string" then _, _, sig = string.find(sig, "(%d+)") end return tonumber(sig)endfunction getItemIdFromLink(link) return (EnhTooltip.BreakLink(link))endfunction getSigFromLink(link) assert(type(link) == "string") local _, _, id, rand = string.find(link, "item:(%d+):%d+:(%d+):%d+") if id and rand then return id..":0:"..rand endend------------------------------------- General Utility Functions --------------------------------------- Extract the revision number from SVN keyword stringfunction getRevision(str) if not str then return 0 end local _, _, rev = string.find(str, "Revision: (%d+)") return tonumber(rev) or 0endfunction split(str, at) local splut = {}; if (type(str) ~= "string") then return nil end if (not str) then str = "" end if (not at) then table.insert(splut, str) else for n, c in string.gfind(str, '([^%'..at..']*)(%'..at..'?)') do table.insert(splut, n); if (c == '') then break end end end return splut;end-- Iterator version of split()-- for i in spliterator(a, b) do-- is equivalent to-- for _, i in ipairs(split(a, b)) do-- but puts less strain on the garbage collectorfunction spliterator(str, at) local start local found = 0 local done = (type(str) ~= "string") return function() if done then return nil end start = found + 1 found = string.find(str, at, start, true) if not found then found = 0 done = true end return string.sub(str, start, found - 1) endendfunction chatPrint(text, cRed, cGreen, cBlue, cAlpha, holdTime) local frameIndex = Enchantrix.Config.GetFrameIndex(); if (cRed and cGreen and cBlue) then if getglobal("ChatFrame"..frameIndex) then getglobal("ChatFrame"..frameIndex):AddMessage(text, cRed, cGreen, cBlue, cAlpha, holdTime); elseif (DEFAULT_CHAT_FRAME) then DEFAULT_CHAT_FRAME:AddMessage(text, cRed, cGreen, cBlue, cAlpha, holdTime); end else if getglobal("ChatFrame"..frameIndex) then getglobal("ChatFrame"..frameIndex):AddMessage(text, 1.0, 0.5, 0.25); elseif (DEFAULT_CHAT_FRAME) then DEFAULT_CHAT_FRAME:AddMessage(text, 1.0, 0.5, 0.25); end endend-------------------------- Math Functions --------------------------function gcd(a, b) -- Greatest Common Divisor, Euclidean algorithm local m, n = tonumber(a), tonumber(b) or 0 while (n ~= 0) do m, n = n, math.mod(m, n) end return mend-- Round up m to nearest multiple of nfunction roundUp(m, n) return math.ceil(m / n) * nend-- Round m to n digits in given basefunction round(m, n, base, offset) base = base or 10 -- Default to base 10 offset = offset or 0.5 if (n or 0) == 0 then return math.floor(m + offset) end if m == 0 then return 0 elseif m < 0 then return -round(-m, n, base, offset) end -- Get integer and fractional part of n local f = math.floor(n) n, f = f, n - f -- Pre-rounding multiplier is 1 / f local mul = 1 if f > 0.1 then mul = math.floor(1 / f + 0.5) end local d if n > 0 then d = base^(n - math.floor(math.log(m) / math.log(base)) - 1) else d = 1 end if offset >= 1 then return math.ceil(m * d * mul) / (d * mul) else return math.floor(m * d * mul + offset) / (d * mul) endend-- Returns confidence interval for binomial distribution given observed-- probability p, sample size n, and z-valuefunction confidenceInterval(p, n, z) if not z then --[[ z conf 1.282 80% 1.645 90% 1.960 95% 2.326 98% 2.576 99% 3.090 99.8% 3.291 99.9% ]] z = 1.645 end assert(p >= 0 and p <= 1) assert(n > 0) local a = p + z^2 / (2 * n) local b = z * math.sqrt(p * (1 - p) / n + z^2 / (4 * n^2)) local c = 1 + z^2 / n return (a - b) / c, (a + b) / cend----------------------- Debug functions ------------------------- profiler:Start()-- Record start time and memory, set state to runninglocal function _profilerStart(this) this.t = GetTime() this.m = gcinfo() this.r = trueend-- profiler:Stop()-- Record time and memory change, set state to stoppedlocal function _profilerStop(this) this.m = (gcinfo()) - this.m this.t = GetTime() - this.t this.r = falseend-- profiler:DebugPrint()local function _profilerDebugPrint(this) if this.n then EnhTooltip.DebugPrint("Profiler ["..this.n.."]") else EnhTooltip.DebugPrint("Profiler") end if this.r == nil then EnhTooltip.DebugPrint(" Not started") else EnhTooltip.DebugPrint(string.format(" Time: %0.3f s", this:Time())) EnhTooltip.DebugPrint(string.format(" Mem: %0.0f KiB", this:Mem())) if this.r then EnhTooltip.DebugPrint(" Running...") end endend-- time = profiler:Time()-- Return time (in seconds) from Start() [until Stop(), if stopped]local function _profilerTime(this) if this.r == false then return this.t elseif this.r == true then return GetTime() - this.t endend-- mem = profiler:Mem()-- Return memory change (in kilobytes) from Start() [until Stop(), if stopped]local function _profilerMem(this) if this.r == false then return this.m elseif this.r == true then return (gcinfo()) - this.m endend-- profiler = Enchantrix.Util.CreateProfiler("foobar")function createProfiler(name) return { Start = _profilerStart, Stop = _profilerStop, DebugPrint = _profilerDebugPrint, Time = _profilerTime, Mem = _profilerMem, n = name, }endEnchantrix.Util = { Revision = "$Revision: 878 $", IsDisenchantable = isDisenchantable, GetReagentInfo = getReagentInfo, GetLinkFromName = getLinkFromName, GetReagentPrice = getReagentPrice, GetItemType = getItemType, GetItemIdFromSig = getItemIdFromSig, GetItemIdFromLink = getItemIdFromLink, GetSigFromLink = getSigFromLink, SigFromLink = sigFromLink, GetRevision = getRevision, Split = split, Spliterator = spliterator, ChatPrint = chatPrint, GCD = gcd, RoundUp = roundUp, Round = round, ConfidenceInterval = confidenceInterval, CreateProfiler = createProfiler,}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -