You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
6.0 KiB
228 lines
6.0 KiB
--- Sorting.lua
|
|
-- Anything used for sorting (it's a mess...)
|
|
local _, addonTable = ...
|
|
|
|
-- Locals
|
|
local Sorting = {}
|
|
|
|
-- Upvalues
|
|
local R = Rarity
|
|
local CONSTANTS = addonTable.constants
|
|
-- Lua APIs
|
|
local type = type
|
|
local pairs = pairs
|
|
local Round = Round
|
|
|
|
local catOrder = {
|
|
[CONSTANTS.ITEM_CATEGORIES.HOLIDAY] = 0,
|
|
[CONSTANTS.ITEM_CATEGORIES.CLASSIC] = 1,
|
|
[CONSTANTS.ITEM_CATEGORIES.TBC] = 2,
|
|
[CONSTANTS.ITEM_CATEGORIES.WOTLK] = 3,
|
|
[CONSTANTS.ITEM_CATEGORIES.CATA] = 4,
|
|
[CONSTANTS.ITEM_CATEGORIES.MOP] = 5,
|
|
[CONSTANTS.ITEM_CATEGORIES.WOD] = 6,
|
|
[CONSTANTS.ITEM_CATEGORIES.LEGION] = 7,
|
|
[CONSTANTS.ITEM_CATEGORIES.BFA] = 8,
|
|
[CONSTANTS.ITEM_CATEGORIES.SHADOWLANDS] = 9,
|
|
[CONSTANTS.ITEM_CATEGORIES.DRAGONFLIGHT] = 10,
|
|
}
|
|
|
|
local function compareCategory(a, b)
|
|
if not a or not b then
|
|
return 0
|
|
end
|
|
if type(a) ~= "table" or type(b) ~= "table" then
|
|
return 0
|
|
end
|
|
if (a.cat or "") == (b.cat or "") then
|
|
return (a.name or "") < (b.name or "")
|
|
end
|
|
return (catOrder[a.cat or 0] or 0) < (catOrder[b.cat or 0] or 0)
|
|
end
|
|
|
|
local function compareDifficulty(a, b)
|
|
if not a or not b then
|
|
return 0
|
|
end
|
|
if type(a) ~= "table" or type(b) ~= "table" then
|
|
return 0
|
|
end
|
|
|
|
local item
|
|
item = a
|
|
local dropChance = Rarity.Statistics.GetRealDropPercentage(item)
|
|
local medianLoots = Round(math.log(1 - 0.5) / math.log(1 - dropChance))
|
|
local median1 = medianLoots
|
|
|
|
item = b
|
|
dropChance = Rarity.Statistics.GetRealDropPercentage(item)
|
|
medianLoots = Round(math.log(1 - 0.5) / math.log(1 - dropChance))
|
|
local median2 = medianLoots
|
|
|
|
return (median1 or 0) < (median2 or 0)
|
|
end
|
|
|
|
local function compareProgress(a, b)
|
|
if not a or not b then
|
|
return 0
|
|
end
|
|
if type(a) ~= "table" or type(b) ~= "table" then
|
|
return 0
|
|
end
|
|
|
|
local item
|
|
item = a
|
|
local dropChance = Rarity.Statistics.GetRealDropPercentage(item)
|
|
local medianLoots = Round(math.log(1 - 0.5) / math.log(1 - dropChance))
|
|
local median1 = medianLoots
|
|
local progress1 = 0
|
|
if item.attempts or 0 > 0 then
|
|
progress1 = 100 * (1 - math.pow(1 - dropChance, item.attempts or 0))
|
|
end
|
|
|
|
item = b
|
|
dropChance = Rarity.Statistics.GetRealDropPercentage(item)
|
|
medianLoots = Round(math.log(1 - 0.5) / math.log(1 - dropChance))
|
|
local median2 = medianLoots
|
|
local progress2 = 0
|
|
if item.attempts or 0 > 0 then
|
|
progress2 = 100 * (1 - math.pow(1 - dropChance, item.attempts or 0))
|
|
end
|
|
|
|
return progress1 > progress2
|
|
end
|
|
|
|
local function compareName(a, b)
|
|
if not a or not b then
|
|
return 0
|
|
end
|
|
if type(a) ~= "table" or type(b) ~= "table" then
|
|
return 0
|
|
end
|
|
return (a.name or "") < (b.name or "")
|
|
end
|
|
|
|
local function compareNum(a, b)
|
|
if not a or not b then
|
|
return 0
|
|
end
|
|
if type(a) ~= "table" or type(b) ~= "table" then
|
|
return 0
|
|
end
|
|
return (a.num or 0) < (b.num or 0)
|
|
end
|
|
|
|
local function compareZone(a, b)
|
|
-- Sort by zone text, unless there are multiple zones. Those go at the bottom, sorted by number of zones.
|
|
-- If the item is in your current zone as well as one or more other zones,
|
|
-- we sort it alphabetically instead of putting it at the bottom.
|
|
if not a or not b then
|
|
return 0
|
|
end
|
|
if type(a) ~= "table" or type(b) ~= "table" then
|
|
return 0
|
|
end
|
|
local zoneInfoA = R.Waypoints:GetZoneInfoForItem(a)
|
|
local zoneInfoB = R.Waypoints:GetZoneInfoForItem(b)
|
|
local zoneTextA, inMyZoneA, zoneColorA, numZonesA =
|
|
zoneInfoA.zoneText, zoneInfoA.inMyZone, zoneInfoA.zoneColor, zoneInfoA.numZones
|
|
local zoneTextB, inMyZoneB, zoneColorB, numZonesB =
|
|
zoneInfoB.zoneText, zoneInfoB.inMyZone, zoneInfoB.zoneColor, zoneInfoB.numZones
|
|
if numZonesA > 1 and inMyZoneA ~= true then
|
|
zoneTextA = "ZZZZZZZZZZZZZZ"
|
|
end
|
|
if numZonesB > 1 and inMyZoneB ~= true then
|
|
zoneTextB = "ZZZZZZZZZZZZZZ"
|
|
end
|
|
if numZonesA < 10 and numZonesA > 1 and inMyZoneA ~= true then
|
|
zoneTextA = zoneTextA .. "0"
|
|
end
|
|
if numZonesB < 10 and numZonesB > 1 and inMyZoneB ~= true then
|
|
zoneTextB = zoneTextB .. "0"
|
|
end
|
|
if numZonesA > 1 and inMyZoneA ~= true then
|
|
zoneTextA = zoneTextA .. numZonesA
|
|
end
|
|
if numZonesB > 1 and inMyZoneB ~= true then
|
|
zoneTextB = zoneTextB .. numZonesB
|
|
end
|
|
return (zoneTextA or "") < (zoneTextB or "")
|
|
end
|
|
|
|
function Sorting:SortGroup(group, method)
|
|
if method == CONSTANTS.SORT_METHODS.SORT_NONE then
|
|
return self:DebugNoOp(group)
|
|
end
|
|
|
|
Rarity.Profiling:StartTimer("SortGroup")
|
|
local sortedGroup = group
|
|
if method == CONSTANTS.SORT_METHODS.SORT_NAME then
|
|
sortedGroup = self:sort(group)
|
|
elseif method == CONSTANTS.SORT_METHODS.SORT_DIFFICULTY then
|
|
sortedGroup = self:sort_difficulty(group)
|
|
elseif method == CONSTANTS.SORT_METHODS.SORT_CATEGORY then
|
|
sortedGroup = self:sort_category(group)
|
|
elseif method == CONSTANTS.SORT_METHODS.SORT_ZONE then
|
|
sortedGroup = self:sort_zone(group)
|
|
elseif method == CONSTANTS.SORT_METHODS.SORT_PROGRESS then
|
|
sortedGroup = self:sort_progress(group)
|
|
end
|
|
Rarity.Profiling:EndTimer("SortGroup")
|
|
|
|
return sortedGroup
|
|
end
|
|
|
|
-- Minimum impact NO OP "sort" (for debugging purposes); introduced since disabling sorting entirely didn't work
|
|
function Sorting:DebugNoOp(t)
|
|
local nt = {}
|
|
local n = 0
|
|
|
|
for k, v in pairs(t) do
|
|
if type(v) == "table" and v.name then
|
|
n = n + 1
|
|
nt[n] = v
|
|
end
|
|
end
|
|
|
|
return nt
|
|
end
|
|
|
|
local function sort_copy_with(t, comparator)
|
|
local nt = {}
|
|
local n = 0
|
|
for _, v in pairs(t) do
|
|
if type(v) == "table" and v.name then
|
|
n = n + 1
|
|
nt[n] = v
|
|
end
|
|
end
|
|
table.sort(nt, comparator)
|
|
return nt
|
|
end
|
|
|
|
function Sorting:sort(t)
|
|
return sort_copy_with(t, compareName)
|
|
end
|
|
|
|
function Sorting.sort2(t)
|
|
return sort_copy_with(t, compareNum)
|
|
end
|
|
|
|
function Sorting:sort_difficulty(t)
|
|
return sort_copy_with(t, compareDifficulty)
|
|
end
|
|
|
|
function Sorting:sort_progress(t)
|
|
return sort_copy_with(t, compareProgress)
|
|
end
|
|
|
|
function Sorting:sort_category(t)
|
|
return sort_copy_with(t, compareCategory)
|
|
end
|
|
|
|
function Sorting:sort_zone(t)
|
|
return sort_copy_with(t, compareZone)
|
|
end
|
|
|
|
Rarity.Utils.Sorting = Sorting
|
|
return Sorting
|
|
|