diff --git a/Changelog b/Changelog index a7d478d..dc588a3 100644 --- a/Changelog +++ b/Changelog @@ -1,8 +1,14 @@ Changelog +v0.7 + - Added an experimental way to clean stale prices in the database. Use it at your own risk, as it has not been debugged yet. + - Suggested price shows which guild it was found in, if possible. + - Reformatted the price table + - Minor improvements to code quality + v0.6 - Removed unnecessary debug information - + v0.5 - Fixed loot window error diff --git a/MathUtils.lua b/MathUtils.lua index 4abc55a..b99681d 100644 --- a/MathUtils.lua +++ b/MathUtils.lua @@ -6,12 +6,8 @@ local MathUtils = {} PriceTracker.mathUtils = MathUtils function MathUtils:GetSortedPriceTable(itemTable) - local prices = {} - for i = 1, #itemTable do - table.insert(prices, math.floor(itemTable[i].purchasePrice / itemTable[i].stackCount)) - end - table.sort(prices) - return prices + table.sort(itemTable, function(a, b) return (a.purchasePrice / a.stackCount) < (b.purchasePrice / b.stackCount) end) + return itemTable end function MathUtils:WeightedAverage(itemTable) @@ -21,27 +17,35 @@ function MathUtils:WeightedAverage(itemTable) sum = sum + itemTable[i].purchasePrice weight = weight + itemTable[i].stackCount end - return math.floor(sum / weight) + item = { + price = math.floor(sun / weight) + } + return item end function MathUtils:Median(itemTable) - local prices = self:GetSortedPriceTable(itemTable) - local index = (#prices + 1) / 2 - if (#prices / 2) == (math.floor(#prices / 2)) then - return math.floor((prices[index] + prices[index + 1]) / 2) + local itemTable = self:GetSortedPriceTable(itemTable) + local index = (#itemTable + 1) / 2 + if (#itemTable / 2) == (math.floor(#itemTable / 2)) then + local item = { + price = math.floor((itemTable[index].price + itemtTable[index + 1]).price / 2) + } + return else - return prices[index] + return itemTable[index] end end function MathUtils:Mode(itemTable) - local prices = self:GetSortedPriceTable(itemTable) - local number = prices[1] - local mode = number local count = 1 + local itemTable = self:GetSortedPriceTable(itemTable) + PriceTracker.itemTable = itemTable + local number = itemTable[1] + local mode = number + local count = 1 local countMode = 1 - for i = 2, #prices do - if prices[i] == number then + for i = 2, #itemTable do + if itemTable[i].price == number.price then count = count + 1 else if count > countMode then @@ -57,22 +61,26 @@ end function MathUtils:Max(itemTable) local price = math.floor(itemTable[1].purchasePrice / itemTable[1].stackCount) - for i = 1, #itemTable do + local item = itemTable[1] + for i = 2, #itemTable do local newPrice = math.floor(itemTable[i].purchasePrice / itemTable[i].stackCount) if newPrice > price then price = newPrice + item = itemTable[i] end end - return price + return item end function MathUtils:Min(itemTable) local price = math.floor(itemTable[1].purchasePrice / itemTable[1].stackCount) - for i = 1, #itemTable do + local item = itemTable[1] + for i = 2, #itemTable do local newPrice = math.floor(itemTable[i].purchasePrice / itemTable[i].stackCount) if newPrice < price then price = newPrice + item = itemTable[i] end end - return price + return item end diff --git a/PriceTracker.lua b/PriceTracker.lua index f6eb9a0..d3abea0 100644 --- a/PriceTracker.lua +++ b/PriceTracker.lua @@ -14,9 +14,7 @@ local PriceTracker = PriceTracker -- Addon initialization function PriceTracker:OnLoad(eventCode, addOnName) - if(addOnName ~= "PriceTracker") then - return - end + if(addOnName ~= "PriceTracker") then return end EVENT_MANAGER:RegisterForEvent("OnSearchResultsReceived", EVENT_TRADING_HOUSE_SEARCH_RESULTS_RECEIVED, function(...) self:OnSearchResultsReceived(...) end) EVENT_MANAGER:RegisterForEvent("OnTradingHouseClosed", EVENT_CLOSE_TRADING_HOUSE, function(...) self:OnTradingHouseClosed(...) end) @@ -43,7 +41,6 @@ function PriceTracker:OnLoad(eventCode, addOnName) self.button:SetWidth(ZO_TradingHouseLeftPaneBrowseItemsCommonQuality:GetWidth()) self.menu:InitAddonMenu(addOnName) - end -- Handle slash commands @@ -57,6 +54,12 @@ function PriceTracker:CommandHandler(text) self.settings.itemList = {} return end + + if text == "clean" then + self:CleanItemList() + return + end + end function PriceTracker:ShowHelp() @@ -64,40 +67,35 @@ function PriceTracker:ShowHelp() d(" ") d("/pt help - Show this help") d("/pt clear - Clear stored price values") + d("pt clean - Remove stale items (experimental)") end function PriceTracker:OnUpdateTooltip(item) - if not item or not item.dataEntry or not item.dataEntry.data or self.selectedItem == item then - return - end - + if not item or not item.dataEntry or not item.dataEntry.data or self.selectedItem == item then return end self.selectedItem = item local stackCount = item.dataEntry.data.stackCount or item.dataEntry.data.stack - if not stackCount then - return - end + if not stackCount then return end local matches = self:GetMatches(item.dataEntry.data.name) - if not matches then - return - end + if not matches then return end - local price = self:SuggestPrice(matches) - if not price then - return - end + local item = self:SuggestPrice(matches) + if not item then return end ZO_Tooltip_AddDivider(ItemTooltip) ItemTooltip:AddLine("Price Tracker", "ZoFontHeader2") local r, g, b = ZO_TOOLTIP_DEFAULT_COLOR:UnpackRGB() - ItemTooltip:AddLine("Suggested Price: |r", "ZoFontGame", r, g, b, TOPLEFT, MODIFY_TEXT_TYPE_NONE, LEFT, false) - ItemTooltip:AddLine(self:FormatTooltipLine("Item price: ", price, stackCount), "ZoFontGame", r, g, b, CENTER, MODIFY_TEXT_TYPE_NONE, CENTER, false) + ItemTooltip:AddLine(self:FormatTooltipLine("Suggested price:", math.floor(item.purchasePrice / item.stackCount)), "ZoFontGame", r, g, b, CENTER, MODIFY_TEXT_TYPE_NONE, CENTER, true) if stackCount > 1 then - ItemTooltip:AddLine(self:FormatTooltipLine("Stack price: ", price * stackCount), "ZoFontGame", r, g, b, CENTER, MODIFY_TEXT_TYPE_NONE, CENTER, false) + ItemTooltip:AddLine(self:FormatTooltipLine("Stack price:", math.floor(item.purchasePrice / item.stackCount * stackCount)), "ZoFontGame", r, g, b, CENTER, MODIFY_TEXT_TYPE_NONE, CENTER, true) end if self.settings.showMinMax then - ItemTooltip:AddLine(self:FormatTooltipLine("Min / Max: ", self.mathUtils:Min(matches) .. " / " .. self.mathUtils:Max(matches)), "ZoFontGame", r, g, b, CENTER, MODIFY_TEXT_TYPE_NONE, CENTER, false) - ItemTooltip:AddLine(self:FormatTooltipLine("Min / Max (stack): ", self.mathUtils:Min(matches) * stackCount .. " / " .. self.mathUtils:Max(matches) * stackCount), "ZoFontGame", r, g, b, CENTER, MODIFY_TEXT_TYPE_NONE, CENTER, false) + local minItem = self.mathUtils:Min(matches) + local maxItem = self.mathUtils:Max(matches) + local minPrice = math.floor(minItem.purchasePrice / minItem.stackCount) + local maxPrice = math.floor(maxItem.purchasePrice / maxItem.stackCount) + ItemTooltip:AddLine(self:FormatTooltipLine("Min (each / stack):", minPrice, minPrice * stackCount, minItem.guildName), "ZoFontGame", r, g, b, CENTER, MODIFY_TEXT_TYPE_NONE, CENTER, true) + ItemTooltip:AddLine(self:FormatTooltipLine("Max (each / stack):", maxPrice, maxPrice * stackCount, maxItem.guildName), "ZoFontGame", r, g, b, CENTER, MODIFY_TEXT_TYPE_NONE, CENTER, true) end if self.settings.showSeen then ItemTooltip:AddLine("Seen " .. #matches .. " times", "ZoFontGame", r, g, b, CENTER, MODIFY_TEXT_TYPE_NONE, CENTER, false) @@ -109,9 +107,7 @@ function PriceTracker:OnHideTooltip() end function PriceTracker:OnScanPrices() - if self.isSearching then - return - end + if self.isSearching then return end self.button:SetEnabled(false) self.isSearching = true @@ -125,9 +121,7 @@ function PriceTracker:OnScanPrices() end function PriceTracker:OnSearchResultsReceived(eventId, guildId, numItemsOnPage, currentPage, hasMorePages) - if not self.isSearching then - return - end + if not self.isSearching then return end for i = 1, numItemsOnPage do self:AddItem(GetTradingHouseSearchResultItemInfo(i)) @@ -161,6 +155,7 @@ function PriceTracker:AddItem(icon, itemName, quality, stackCount, sellerName, t item.stackCount = stackCount item.sellerName = sellerName item.purchasePrice = purchasePrice + item.eachPrice = purchasePrice / stackCount item.guildId = self.currentGuild item.guildName = GetGuildName(item.guildId) @@ -174,24 +169,27 @@ function PriceTracker:AddItem(icon, itemName, quality, stackCount, sellerName, t end end +function PriceTracker:CleanItemList() + local timestamp = GetTimeStamp() + for k, v in pairs(PriceTracker.settings.itemList) do + for itemK, itemV in pairs(v) do + if itemV.expiry > timestamp then + table.remove(v, itemK) + end + end + end +end + function PriceTracker:GetMatches(itemName) local normalizedName = self:NormalizeName(itemName) if not self.settings.itemList or not self.settings.itemList[normalizedName] then return nil end - local index = next(self.settings.itemList[normalizedName]) - if index == nil then - return nil - end - local matches = {} - while index do - table.insert(matches, self.settings.itemList[normalizedName][index]) - index = next(self.settings.itemList[normalizedName], index) + for k, v in pairs(self.settings.itemList[normalizedName]) do + table.insert(matches, v) end - - self.matches = matches return matches end @@ -213,8 +211,18 @@ function PriceTracker:SuggestPrice(matches) return nil end -function PriceTracker:FormatTooltipLine(title, price, stackCount) - return string.format("%-30s %7s%s", title, price, zo_iconFormat(self.icons.gold, 16, 16)) +function PriceTracker:FormatTooltipLine(title, price1, price2, guild) + if price2 then + price1 = price1 .. " / " .. price2 + end + local str + if guild then + str = "%-20.20s (%-10.10s)" + else + str = "%-40.40s %1.1s" + end + str = str .. " %12.12s%s" + return string.format(str, title, guild or "", price1, zo_iconFormat(self.icons.gold, 16, 16)) end function PriceTracker:NormalizeName(name) diff --git a/PriceTrackerMenu.lua b/PriceTrackerMenu.lua index c3c6846..793de94 100644 --- a/PriceTrackerMenu.lua +++ b/PriceTrackerMenu.lua @@ -6,12 +6,11 @@ local PriceTrackerMenu = {} PriceTracker.menu = PriceTrackerMenu PriceTrackerMenu.algorithmTable = { - "Weighted Average", - "Median", - "Most Frequently Used" + "Weighted Average", + "Median", + "Most Frequently Used" } - function PriceTrackerMenu:InitAddonMenu(addOnName) local LAM = LibStub:GetLibrary("LibAddonMenu-1.0") local addOnMenu = LAM:CreateControlPanel("PriceTrackerMenu", addOnName)