From c42a03e655a387faa8fe16e710b54f0c248b762a Mon Sep 17 00:00:00 2001 From: AssisrMatheus Date: Tue, 24 Sep 2019 20:13:33 -0300 Subject: [PATCH] :zap: #33: Improved performance when get linked info by memoizing its result --- src/components/TodoChecklister.lua | 86 ++++++++++++++++++------------ src/init.lua | 7 +-- src/utils/functionUtils.lua | 40 ++++++++++++++ src/utils/utils.xml | 1 + 4 files changed, 97 insertions(+), 37 deletions(-) create mode 100644 src/utils/functionUtils.lua diff --git a/src/components/TodoChecklister.lua b/src/components/TodoChecklister.lua index 1ba8cf1..ad330bc 100644 --- a/src/components/TodoChecklister.lua +++ b/src/components/TodoChecklister.lua @@ -12,6 +12,8 @@ local ResponsiveFrame = TodoAddon.ResponsiveFrame local TableUtils = TodoAddon.TableUtils ---@class TodoList local TodoList = TodoAddon.TodoList +---@class FunctionUtils +local FunctionUtils = TodoAddon.FunctionUtils -------------------------------------- -- Declarations @@ -38,6 +40,7 @@ function TodoChecklisterFrame:AddItem(text) else TodoList:UpdateItem(self.selectedItem, {text = text}) end + self.memoizationId = self.memoizationId + 1 self:ClearSelected() self:OnUpdate() end @@ -68,6 +71,7 @@ function TodoChecklisterFrame:RemoveItemWithIndex(indexToRemove) self.selectedItem = indexToSelect end + self.memoizationId = self.memoizationId + 1 self:OnUpdate() end end @@ -104,6 +108,7 @@ function TodoChecklisterFrame:Move(fromIndex, toIndex, fromChat) self.selectedItem = TodoList:GetIndexByItem(selectedItem) end + self.memoizationId = self.memoizationId + 1 self:OnUpdate() end end @@ -115,6 +120,7 @@ function TodoChecklisterFrame:CheckItemWithIndex(indexToCheck) if (indexToCheck and type(indexToCheck) == "number" and indexToCheck > 0) then local item = TodoList:GetItems()[indexToCheck] TodoList:UpdateItem(indexToCheck, {isChecked = (not item.isChecked)}) + self.memoizationId = self.memoizationId + 1 self:OnUpdate() if (Settings:PlayFanfare() and @@ -155,6 +161,7 @@ function TodoChecklisterFrame:SelectItem(todoItem, buttonFrame) self:ClearSelected() end + self.memoizationId = self.memoizationId + 1 self:OnUpdate() end @@ -214,40 +221,46 @@ function TodoChecklisterFrame:PaintItem(frame, todoItem, index) frame.TodoContent:SetWidth(TodoItemsScrollFrame:GetWidth() - frame.RemoveButton:GetWidth() - 23) if (self.displayLinked) then - -- Startup regex process by storing string values - local finalString = "" - local remainingString = todoItem.text - - -- If the remaining string still has linked items - while (remainingString and not (not GetItemInfo(remainingString))) do - -- Find the linked item position - local st, en = string.find(remainingString, "|Hitem:.-|r") - - if (en) then - -- Set the final string to: - finalString = - table.concat { - finalString, -- Current final string - remainingString:sub(1, en), -- Current string until now - "(", - GetItemCount(remainingString), -- Amount from bag - ") " - } - - -- Remove the current linked item from the remaining string to continue the process - remainingString = remainingString:sub(en + 1) - else - remainingString = "" - end - end - - -- If the final string has been set - if (string.len(finalString) > 0) then - frame.TodoContent.FontText:SetText(finalString .. remainingString) - else - -- If not, the string doesn't have links - frame.TodoContent.FontText:SetText(todoItem.text) - end + FunctionUtils:Memoize( + function() + -- Startup regex process by storing string values + local finalString = "" + local remainingString = todoItem.text + + -- If the remaining string still has linked items + while (remainingString and not (not GetItemInfo(remainingString))) do + -- Find the linked item position + local st, en = string.find(remainingString, "|Hitem:.-|r") + + if (en) then + -- Set the final string to: + finalString = + table.concat { + finalString, -- Current final string + remainingString:sub(1, en), -- Current string until now + "(", + GetItemCount(remainingString), -- Amount from bag + ") " + } + + -- Remove the current linked item from the remaining string to continue the process + remainingString = remainingString:sub(en + 1) + else + remainingString = "" + end + end + + -- If the final string has been set + if (string.len(finalString) > 0) then + frame.TodoContent.FontText:SetText(finalString .. remainingString) + else + -- If not, the string doesn't have links + frame.TodoContent.FontText:SetText(todoItem.text) + end + end, + todoItem.id .. self.memoizationId, + todoItem.id .. "Count" + ) else frame.TodoContent.FontText:SetText(todoItem.text) end @@ -489,11 +502,16 @@ end function TodoChecklisterFrame:Init() -- Creates the addon frame local frame = CreateFrame("Frame", "TodoChecklister", UIParent, "TodoChecklisterTemplate") + + -- Store a value to be used as a memoization id + self.memoizationId = 0 + frame:RegisterEvent("BAG_UPDATE_DELAYED") frame:HookScript( "OnEvent", function(frame, event) if (event == "BAG_UPDATE_DELAYED") then + self.memoizationId = self.memoizationId + 1 self:OnUpdate() end end diff --git a/src/init.lua b/src/init.lua index 63bd8e5..6ee257e 100644 --- a/src/init.lua +++ b/src/init.lua @@ -25,13 +25,14 @@ local MinimapIcon = TodoAddon.MinimapIcon -------------------------------------- -- Init keybindings -------------------------------------- -BINDING_HEADER_TC_HEADER = "TodoChecklister" +BINDING_HEADER_TC_HEADER = addonName BINDING_NAME_TC_TOGGLE_FRAME = "Toggle log visibility" -- Export the method TodoChecklisterFrame:Toggle to a global function -- so that it can be called from a keybind -GLOBAL_TodoChecklisterFrameToggle = function () TodoChecklisterFrame:Toggle() end - +GLOBAL_TodoChecklisterFrameToggle = function() + TodoChecklisterFrame:Toggle() +end -------------------------------------- -- Initialization diff --git a/src/utils/functionUtils.lua b/src/utils/functionUtils.lua new file mode 100644 index 0000000..124bd66 --- /dev/null +++ b/src/utils/functionUtils.lua @@ -0,0 +1,40 @@ +-------------------------------------- +-- Imports +-------------------------------------- +---@class TodoAddon +local TodoAddon = select(2, ...) + +-------------------------------------- +-- Declarations +-------------------------------------- +TodoAddon.FunctionUtils = {} + +---@class FunctionUtils +local FunctionUtils = TodoAddon.FunctionUtils + +local memoizedValues = {} + +-------------------------------------- +-- TableUtils functions +-------------------------------------- + +--- +---Calls a function once and store its key value, if the function gets called again but the parameters haven't changed. +---Instead of calling it again, it just return the previously calculated value +---@generic T +---@param execution fun(): T @A complex function that you want to Memoize +---@param comparator any @The value used to decide wether or not the function should be called again +---@param name string @A unique name for this memoization +---@return T @The returned value from the executed function +function FunctionUtils:Memoize(execution, comparator, name) + if (memoizedValues[name] and memoizedValues[name].comparator == comparator) then + return memoizedValues[name].result + end + + memoizedValues[name] = { + result = execution(), + comparator = comparator + } + + return memoizedValues[name].result +end diff --git a/src/utils/utils.xml b/src/utils/utils.xml index 7024dbc..7dd8981 100644 --- a/src/utils/utils.xml +++ b/src/utils/utils.xml @@ -1,5 +1,6 @@ +