From 355b15a53e09084b324634524fdd56a7fdfe67f3 Mon Sep 17 00:00:00 2001 From: Kevin Lyles Date: Mon, 14 Dec 2009 03:32:14 -0600 Subject: [PATCH] Reworked caching --- WeightsWatcher.lua | 299 +++++++++++++++++++++++++++------------------------- 1 file changed, 157 insertions(+), 142 deletions(-) diff --git a/WeightsWatcher.lua b/WeightsWatcher.lua index 5c1da76..242d327 100644 --- a/WeightsWatcher.lua +++ b/WeightsWatcher.lua @@ -4,10 +4,152 @@ end currentHooks = {} -ww_itemCache = {} -ww_bareItemCache = {} -ww_weightCache = {} -ww_weightIdealCache = {} +ww_bareItemCacheMetatable = { + __index = function(tbl, key) + tbl[key] = {WeightsWatcher:getItemStats(key)} + return tbl[key] + end, +} + +ww_itemCacheMetatable = { + __index = function(tbl, key) + local gemStats, socketBonusActive + local bareLink, gems = splitItemLink(key) + local normalStats, sockets, socketBonusStat = unpack(ww_bareItemCache[bareLink]) + + gemStats = WeightsWatcher:getGemStats(gems) + + -- Removes gems in crafted sockets from consideration + for i = #(sockets) + 1, #(gemStats) do + table.remove(gemStats) + end + + if #(sockets) > 0 then + socketBonusActive = true + for i = 1, #(sockets) do + if not gemStats[i] or not WeightsWatcher:matchesSocket(gemStats[i][1], sockets[i]) then + socketBonusActive = false + break + end + end + else + socketBonusActive = false + end + + tbl[key] = {socketBonusActive, gemStats} + return tbl[key] + end, +} + +ww_weightCacheWeightMetatable = { + __index = function(tbl, key) + local normalStats, socketBonusActive, socketBonusStat, gemStats + local bareLink = splitItemLink(key) + normalStats, _, socketBonusStat = unpack(ww_bareItemCache[bareLink]) + socketBonusActive, gemStats = unpack(ww_itemCache[key]) + + tbl[key] = WeightsWatcher:calculateWeight(normalStats, socketBonusActive, socketBonusStat, gemStats, tbl.weight) + return tbl[key] + end, +} + +ww_weightCacheClassMetatable = { + __index = function(tbl, key) + tbl[key] = setmetatable({}, ww_weightCacheWeightMetatable) + tbl[key].weight = tbl.class[key] + return tbl[key] + end, +} + +ww_weightCacheMetatable = { + __index = function(tbl, key) + tbl[key] = setmetatable({}, ww_weightCacheClassMetatable) + tbl[key].class = ww_vars.weightsList[key] + return tbl[key] + end, +} + +ww_weightIdealCacheWeightMetatable = { + __index = function(tbl, key) + if key == "weight" then + return nil + elseif key == "bestGems" then + local redScore, yellowScore, blueScore, overallScore + local bestGems = {} + + bestGems.Red, redScore = WeightsWatcher:bestGemForSocket("Red", tbl.weight, ww_vars.options.gemQualityLimit) + bestGems.Yellow, yellowScore = WeightsWatcher:bestGemForSocket("Yellow", tbl.weight, ww_vars.options.gemQualityLimit) + bestGems.Blue, blueScore = WeightsWatcher:bestGemForSocket("Blue", tbl.weight, ww_vars.options.gemQualityLimit) + bestGems.Meta = WeightsWatcher:bestGemForSocket("Meta", tbl.weight, ww_vars.options.gemQualityLimit) + bestGems.overall = bestGems.Red + overallScore = redScore + if blueScore > overallScore then + bestGems.overall = bestGems.Blue + overallScore = blueScore + end + if yellowScore > overallScore then + bestGems.overall = bestGems.Yellow + end + tbl.bestGems = bestGems + return bestGems + end + local gemId, gemIdIgnoreSocket, weightVal, weightValIgnoreSockets, bestGems, bestGemsIgnoreSocket + local normalStats, sockets, socketBonusStat = unpack(ww_bareItemCache[key]) + + bestGems = {} + bestGemsIgnoreSocket = {} + for _, color in pairs(sockets) do + gemId = tbl.bestGems[color] + if gemId ~= 0 then + table.insert(bestGems, gemId) + end + if breakSocketColors then + gemIdIgnoreSocket = tbl.bestGems.overall + if gemIdIgnoreSocket ~= 0 then + table.insert(bestGemsIgnoreSocket, gemIdIgnoreSocket) + end + end + end + gemStats = WeightsWatcher:getGemStats(bestGems) + weightVal = WeightsWatcher:calculateWeight(normalStats, true, socketBonusStat, gemStats, tbl.weight) + if breakSocketColors then + gemStatsIgnoreSockets = WeightsWatcher:getGemStats(bestGemsIgnoreSocket) + weightValIgnoreSockets = WeightsWatcher:calculateWeight(normalStats, false, socketBonusStat, gemStatsIgnoreSockets, tbl.weight) + + if weightVal < weightValIgnoreSockets then + weightVal = weightValIgnoreSockets + gemStats = gemStatsIgnoreSockets + end + end + + tbl[key] = { + gemStats = gemStats, + score = weightVal, + } + return tbl[key] + end, +} + +ww_weightIdealCacheClassMetatable = { + __index = function(tbl, key) + tbl[key] = setmetatable({}, ww_weightIdealCacheWeightMetatable) + tbl[key].weight = tbl.class[key] + return tbl[key] + end, +} + +ww_weightIdealCacheMetatable = { + __index = function(tbl, key) + tbl[key] = setmetatable({}, ww_weightIdealCacheClassMetatable) + tbl[key].class = ww_vars.weightsList[key] + return tbl[key] + end, +} + +ww_bareItemCache = setmetatable({}, ww_bareItemCacheMetatable) +ww_itemCache = setmetatable({}, ww_itemCacheMetatable) +ww_weightCache = setmetatable({}, ww_weightCacheMetatable) +ww_weightIdealCache = setmetatable({}, ww_weightIdealCacheMetatable) function WeightsWatcher:OnInitialize() local tempVars @@ -138,145 +280,18 @@ function WeightsWatcher:OnDisable() currentHooks = {} end -function WeightsWatcher:cacheItemStats(link) - -- Stats: normal stats, sockets, socket bonus, gem-given stats, whether the socket bonus is active, ideal gems, ideal gems ignoring socket bonuses - local normalStats, sockets, socketBonusStat, socketBonusActive, gemStats - - _, itemId, _, gemId1, gemId2, gemId3, gemId4, suffixId, uniqueId, linkLevel = strsplit(":", link) +function splitItemLink(link) + local _, itemId, _, gemId1, gemId2, gemId3, gemId4, suffixId, uniqueId, linkLevel = strsplit(":", link) -- Strip color codes linkLevel = strsplit("|", linkLevel) bareLink = strjoin(":", "item", itemId, "0:0:0:0:0", suffixId, uniqueId, linkLevel) - if ww_bareItemCache[bareLink] then - normalStats, sockets, socketBonusStat = unpack(ww_bareItemCache[bareLink]) - else - normalStats, sockets, socketBonusStat = WeightsWatcher:getItemStats(bareLink) - ww_bareItemCache[bareLink] = {normalStats, sockets, socketBonusStat} - end - - if ww_itemCache[link] then - socketBonusActive, gemStats = unpack(ww_itemCache[link]) - else - gemStats = WeightsWatcher:getGemStats({gemId1, gemId2, gemId3, gemId4}) - - -- Removes gems in crafted sockets from consideration - for i = #(sockets) + 1, #(gemStats) do - table.remove(gemStats) - end - - if #(sockets) > 0 then - socketBonusActive = true - for i = 1, #(sockets) do - if not gemStats[i] or not WeightsWatcher:matchesSocket(gemStats[i][1], sockets[i]) then - socketBonusActive = false - break - end - end - else - socketBonusActive = false - end - - ww_itemCache[link] = {socketBonusActive, gemStats} - end - - for _, class in ipairs(ww_charVars.activeWeights) do - if ww_vars.weightsList[class] then - if not ww_weightCache[class] then - ww_weightCache[class] = {} - end - for _, weight in pairs(ww_charVars.activeWeights[class]) do - if ww_vars.weightsList[class][weight] then - if not ww_weightCache[class][weight] then - ww_weightCache[class][weight] = {} - end - if not ww_weightCache[class][weight][link] then - ww_weightCache[class][weight][link] = WeightsWatcher:calculateWeight(normalStats, socketBonusActive, socketBonusStat, gemStats, ww_vars.weightsList[class][weight]) - end - end - end - end - end - - if #(sockets) > 0 then - for _, class in ipairs(ww_charVars.activeWeights) do - if ww_vars.weightsList[class] then - if not ww_weightIdealCache[class] then - ww_weightIdealCache[class] = {} - end - for _, weight in pairs(ww_charVars.activeWeights[class]) do - if ww_vars.weightsList[class][weight] then - local socketBonusWeight = ww_vars.weightsList[class][weight][string.lower(socketBonusStat[1])] - local breakSocketColors = ww_vars.options.breakSocketColors or (not ww_vars.options.neverBreakSocketColors and (not socketBonusWeight or socketBonusWeight <= 0)) - - if not ww_weightIdealCache[class][weight] then - ww_weightIdealCache[class][weight] = {} - end - - if not ww_weightIdealCache[class][weight].bestGems then - local redScore, yellowScore, blueScore, overallScore - local bestGems = {} - - bestGems.Red, redScore = WeightsWatcher:bestGemForSocket("Red", ww_vars.weightsList[class][weight], ww_vars.options.gemQualityLimit) - bestGems.Yellow, yellowScore = WeightsWatcher:bestGemForSocket("Yellow", ww_vars.weightsList[class][weight], ww_vars.options.gemQualityLimit) - bestGems.Blue, blueScore = WeightsWatcher:bestGemForSocket("Blue", ww_vars.weightsList[class][weight], ww_vars.options.gemQualityLimit) - bestGems.Meta = WeightsWatcher:bestGemForSocket("Meta", ww_vars.weightsList[class][weight], ww_vars.options.gemQualityLimit) - bestGems.overall = bestGems.Red - overallScore = redScore - if blueScore > overallScore then - bestGems.overall = bestGems.Blue - overallScore = blueScore - end - if yellowScore > overallScore then - bestGems.overall = bestGems.Yellow - end - ww_weightIdealCache[class][weight].bestGems = bestGems - end - - if not ww_weightIdealCache[class][weight][bareLink] then - local gemId, gemIdIgnoreSocket, weightVal, weightValIgnoreSockets, bestGems, bestGemsIgnoreSocket - - ww_weightIdealCache[class][weight][bareLink] = {} - - bestGems = {} - bestGemsIgnoreSocket = {} - for _, color in pairs(sockets) do - gemId = ww_weightIdealCache[class][weight].bestGems[color] - if gemId ~= 0 then - table.insert(bestGems, gemId) - end - if breakSocketColors then - gemIdIgnoreSocket = ww_weightIdealCache[class][weight].bestGems.overall - if gemIdIgnoreSocket ~= 0 then - table.insert(bestGemsIgnoreSocket, gemIdIgnoreSocket) - end - end - end - gemStats = WeightsWatcher:getGemStats(bestGems) - weightVal = WeightsWatcher:calculateWeight(normalStats, true, socketBonusStat, gemStats, ww_vars.weightsList[class][weight]) - if breakSocketColors then - gemStatsIgnoreSockets = WeightsWatcher:getGemStats(bestGemsIgnoreSocket) - weightValIgnoreSockets = WeightsWatcher:calculateWeight(normalStats, false, socketBonusStat, gemStatsIgnoreSockets, ww_vars.weightsList[class][weight]) - - if weightVal < weightValIgnoreSockets then - weightVal = weightValIgnoreSockets - gemStats = gemStatsIgnoreSockets - end - end - ww_weightIdealCache[class][weight][bareLink].gemStats = gemStats - ww_weightIdealCache[class][weight][bareLink].score = weightVal - end - end - end - end - end - end - - return bareLink + return bareLink, {gemId1, gemId2, gemId3, gemId4} end function WeightsWatcher:displayItemStats(tooltip, ttname) local link, bareLink, itemType, stackSize, sockets, gemStats - local stat, value, string + local stat, value, str local _, playerClass = UnitClass("player") _, link = tooltip:GetItem() @@ -286,7 +301,7 @@ function WeightsWatcher:displayItemStats(tooltip, ttname) _, _, _, _, _, itemType, _, stackSize = GetItemInfo(link) if (IsEquippableItem(link) and itemType ~= "Container" and itemType ~= "Quiver") or (itemType == "Gem" and stackSize == 1) or (itemType == "Consumable") or (itemType == "Recipe") then - bareLink = WeightsWatcher:cacheItemStats(link) + bareLink = splitItemLink(link) if keyDetectors[ww_vars.options.tooltip.showWeights]() then tooltip:AddLine("Current Weights:") @@ -294,11 +309,11 @@ function WeightsWatcher:displayItemStats(tooltip, ttname) if ww_vars.weightsList[class] then for _, weight in pairs(ww_charVars.activeWeights[class]) do if ww_vars.weightsList[class][weight] then - string = " " .. weight + str = " " .. weight if ww_vars.options.tooltip.showClassNames == "Always" or (ww_vars.options.tooltip.showClassNames == "Others" and class ~= playerClass) then - string = string .. " - " .. classNames[class] + str = str .. " - " .. classNames[class] end - tooltip:AddDoubleLine(string, string.format("%.3f", ww_weightCache[class][weight][link])) + tooltip:AddDoubleLine(str, string.format("%.3f", ww_weightCache[class][weight][link])) end end end @@ -313,11 +328,11 @@ function WeightsWatcher:displayItemStats(tooltip, ttname) if ww_vars.weightsList[class] then for _, weight in pairs(ww_charVars.activeWeights[class]) do if ww_vars.weightsList[class][weight] then - string = " " .. weight + str = " " .. weight if ww_vars.options.tooltip.showClassNames == "Always" or (ww_vars.options.tooltip.showClassNames == "Others" and class ~= playerClass) then - string = string .. " - " .. classNames[class] + str = str .. " - " .. classNames[class] end - tooltip:AddDoubleLine(string, string.format("%.3f", ww_weightIdealCache[class][weight][bareLink].score)) + tooltip:AddDoubleLine(str, string.format("%.3f", ww_weightIdealCache[class][weight][bareLink].score)) if keyDetectors[ww_vars.options.tooltip.showIdealGems]() then gemStats = ww_weightIdealCache[class][weight][bareLink].gemStats for _, gem in ipairs(gemStats) do -- 1.7.9.5