diff --git a/history.lua b/history.lua index d7b2575..2dd5598 100644 --- a/history.lua +++ b/history.lua @@ -4,46 +4,58 @@ Aux.history = public aux_conservative_value = false private.PUSH_INTERVAL = 57600 -private.NEW_RECORD = '####' + +function private.new_record() + return { next_push = time() + private.PUSH_INTERVAL, market_values = {}, max_bids = {} } +end function private.load_data() local dataset = Aux.persistence.load_dataset() - dataset.history = dataset.history or { next_push = time() + private.PUSH_INTERVAL, item_records = {} } + dataset.history = dataset.history or { item_records = {} } return dataset.history end function private.read_record(item_key) local data = private.load_data() - if data.next_push < time() then - data.next_push = time() + private.PUSH_INTERVAL - private.push_data() + local record + if data.item_records[item_key] then + local fields = Aux.persistence.deserialize(data.item_records[item_key], '#') + record = { + -- auction_count = tonumber(record[1]), + -- day_count = tonumber(record[2]), + next_push = tonumber(fields[1]), + daily_max_bid = tonumber(fields[2]), + daily_min_buyout = tonumber(fields[3]), + daily_max_buyout = tonumber(fields[4]), + market_values = Aux.util.map(Aux.persistence.deserialize(fields[5], ';'), function(value) + return tonumber(value) + end), + max_bids = Aux.util.map(Aux.persistence.deserialize(fields[6], ';'), function(value) + return tonumber(value) + end), + } + else + record = private.new_record() end - local fields = Aux.persistence.deserialize(data.item_records[item_key] or private.NEW_RECORD, '#') - return { --- auction_count = tonumber(record[1]), --- day_count = tonumber(record[2]), - daily_max_bid = tonumber(fields[1]), - daily_min_buyout = tonumber(fields[2]), - daily_max_buyout = tonumber(fields[3]), - market_values = Aux.util.map(Aux.persistence.deserialize(fields[4], ';'), function(value) - return tonumber(value) - end), - conservative_market_values = Aux.util.map(Aux.persistence.deserialize(fields[5], ';'), function(value) - return tonumber(value) - end), - } + if record.next_push < time() then + private.push_record(record) + private.write_record(item_key, record) + end + + return record end function private.write_record(item_key, record) local data = private.load_data() data.item_records[item_key] = Aux.persistence.serialize({ + record.next_push or '', record.daily_max_bid or '', record.daily_min_buyout or '', record.daily_max_buyout or '', Aux.persistence.serialize(record.market_values, ';'), - Aux.persistence.serialize(record.conservative_market_values, ';', 'x'), + Aux.persistence.serialize(record.max_bids, ';', 'x'), },'#') end @@ -77,7 +89,7 @@ function public.value(item_key) local past_market_values if aux_conservative_value then - past_market_values = item_record.conservative_market_values + past_market_values = item_record.max_bids else past_market_values = item_record.market_values end @@ -85,7 +97,7 @@ function public.value(item_key) if getn(past_market_values) > 0 then return private.median(past_market_values) elseif aux_conservative_value then - return private.conservative_market_value(item_key) + return item_record.daily_max_bid else return private.market_value(item_key) end @@ -94,25 +106,21 @@ end function private.market_value(item_key) local item_record = private.read_record(item_key) - local buyout_estimate = item_record.daily_min_buyout and min(ceil(item_record.daily_min_buyout * 1.15), item_record.daily_max_buyout) + local estimate - if buyout_estimate and item_record.daily_max_bid then - return max(item_record.daily_max_bid, buyout_estimate) - elseif buyout_estimate then - return buyout_estimate + if item_record.daily_min_buyout and item_record.daily_max_bid then + estimate = max(item_record.daily_min_buyout, item_record.daily_max_bid) + elseif item_record.daily_min_buyout then + estimate = item_record.daily_min_buyout else - return item_record.daily_max_bid + estimate = item_record.daily_max_bid end -end -function private.conservative_market_value(item_key) - local item_record = private.read_record(item_key) - - if item_record.daily_max_bid and item_record.daily_min_buyout then - return min(item_record.daily_max_bid, item_record.daily_min_buyout) - elseif item_record.daily_max_bid then - return item_record.daily_max_bid + if item_record.daily_max_buyout then + estimate = min(ceil(estimate * 1.15), item_record.daily_max_buyout) end + + return estimate end function private.median(list) @@ -130,35 +138,74 @@ function private.median(list) return (sorted_list[floor(middle)] + sorted_list[ceil(middle)]) / 2 end -function private.push_data() - local data = private.load_data() - - for item_key, _ in pairs(data.item_records) do - - local item_record = private.read_record(item_key) - - local market_value = private.market_value(item_key) - if market_value then - tinsert(item_record.market_values, market_value) - while getn(item_record.market_values) > 11 do - tremove(item_record.market_values, 1) - end - end - - local conservative_market_value = private.conservative_market_value(item_key) - if conservative_market_value then - tinsert(item_record.conservative_market_values, conservative_market_value) - while getn(item_record.conservative_market_values) > 11 do - tremove(item_record.conservative_market_values, 1) - end - end - - item_record.daily_max_bid = nil - item_record.daily_min_buyout = nil - item_record.daily_max_buyout = nil - - if market_value or conservative_market_value then - private.write_record(item_key, item_record) +function private.push_record(item_record) + local market_value = private.market_value(item_key) + if market_value then + tinsert(item_record.market_values, market_value) + while getn(item_record.market_values) > 11 do + tremove(item_record.market_values, 1) end end + + if item_record.daily_max_bid then + tinsert(item_record.max_bids, item_record.daily_max_bid) + while getn(item_record.max_bids) > 11 do + tremove(item_record.max_bids, 1) + end + end + + item_record.daily_max_bid = nil + item_record.daily_min_buyout = nil + item_record.daily_max_buyout = nil + item_record.next_push = time() + private.PUSH_INTERVAL +end + +function private.snapshot(data) + local self = {} + + function self.add(signature, duration) + local HOUR = 60 * 60 * 60 + local seconds + if duration == 1 then + seconds = HOUR / 2 + elseif duration == 2 then + seconds = HOUR * 2 + elseif duration == 3 then + seconds = HOUR * 8 + elseif duration == 4 then + seconds = HOUR * 24 + end + data[signature] = time() + seconds + end + + function self.contains(signature) + return data[signature] ~= nil and data[signature] >= time() + end + + function self.compact() + for signature, expiration in pairs(data) do + if expiration < time() then + data[signature] = nil + end + end + end + + function self.signatures() + local signatures = {} + for signature, _ in pairs(data) do + if data[signature] >= time() then + tinsert(signatures, signature) + end + end + return signatures + end + + return self +end + +function public.load_snapshot() + local dataset = public.load_dataset() + dataset.snapshot = dataset.snapshot or {} + local snapshot = private.snapshot(dataset.snapshot) + return snapshot end \ No newline at end of file diff --git a/info.lua b/info.lua index a1f97c2..48455be 100644 --- a/info.lua +++ b/info.lua @@ -198,38 +198,61 @@ end function public.set_shopping_tooltip(slot) local index1, index2 = public.inventory_index(slot) + local tooltips = {} if index1 then - ShoppingTooltip1:SetOwner(GameTooltip, 'ANCHOR_BOTTOMRIGHT') - ShoppingTooltip1:SetInventoryItem('player', index1) - ShoppingTooltip1:SetPoint('TOPLEFT', GameTooltip, 'TOPRIGHT', 0, -10) - - -- for i = TOOLTIP_LENGTH-1,1,-1 do --- for _, side in ipairs({'Left', 'Right'}) do --- getglobal('ShoppingTooltip1Text'..side..(i + 1)):SetWidth(getglobal('ShoppingTooltip1Text'..side..i):GetWidth()) --- getglobal('ShoppingTooltip1Text'..side..(i + 1)):SetText(getglobal('ShoppingTooltip1Text'..side..i):GetText()) --- getglobal('ShoppingTooltip1Text'..side..(i + 1)):SetTextColor(getglobal('ShoppingTooltip1Text'..side..i):GetTextColor()) --- end --- end --- --- ShoppingTooltip1TextLeft1:SetText('Currently Equipped') -- TODO --- ShoppingTooltip1TextLeft1:SetTextColor(0.5, 0.5, 0.5) - - if index2 then - ShoppingTooltip2:SetOwner(ShoppingTooltip1, 'ANCHOR_BOTTOMRIGHT') - ShoppingTooltip2:SetInventoryItem('player', index2) - ShoppingTooltip2:SetPoint('TOPLEFT', ShoppingTooltip1, 'TOPRIGHT') + local tooltip = public.tooltip(function(tt) tt:SetInventoryItem('player', index1) end) + if getn(tooltip) > 0 then + tinsert(tooltips, tooltip) end end + if index2 then + local tooltip = public.tooltip(function(tt) tt:SetInventoryItem('player', index2) end) + if getn(tooltip) > 0 then + tinsert(tooltips, tooltip) + end + end + + if tooltips[1] then + tinsert(tooltips[1], 1, { left_text = 'Currently Equipped', left_color = { 0.5, 0.5, 0.5 } }) + + ShoppingTooltip1:SetOwner(GameTooltip, 'ANCHOR_BOTTOMRIGHT') + public.load_tooltip(ShoppingTooltip1, tooltips[1]) + ShoppingTooltip1:Show() + ShoppingTooltip1:SetPoint('TOPLEFT', GameTooltip, 'TOPRIGHT', 0, -10) + end + + if tooltips[2] then + tinsert(tooltips[2], 1, { left_text = 'Currently Equipped', left_color = { 0.5, 0.5, 0.5 } }) + + ShoppingTooltip2:SetOwner(ShoppingTooltip1, 'ANCHOR_BOTTOMRIGHT') + public.load_tooltip(ShoppingTooltip2, tooltips[2]) + ShoppingTooltip2:Show() + ShoppingTooltip2:SetPoint('TOPLEFT', ShoppingTooltip1, 'TOPRIGHT') + end end function public.tooltip_match(pattern, tooltip) return Aux.util.any(tooltip, function(line) - local left_match = line[1].text and strupper(line[1].text) == strupper(pattern) - local right_match = line[2].text and strupper(line[2].text) == strupper(pattern) + local left_match = line.left.text and strupper(line.left_text) == strupper(pattern) + local right_match = line.left.text and strupper(line.right_text) == strupper(pattern) return left_match or right_match end) end +function public.load_tooltip(frame, tooltip) + for _, line in ipairs(tooltip) do + if line.right_text then + frame:AddDoubleLine(line.left_text, line.right_text, line.left_color[1], line.left_color[2], line.left_color[3], line.right_color[1], line.right_color[2], line.right_color[3]) + else + frame:AddLine(line.left_text, line.left_color[1], line.left_color[2], line.left_color[3], true) + end + end + for i = 1,TOOLTIP_LENGTH do -- TODO why is this needed? + getglobal(frame:GetName()..'TextLeft'..i):SetJustifyH('LEFT') + getglobal(frame:GetName()..'TextRight'..i):SetJustifyH('LEFT') + end +end + function public.tooltip(setter) for i = 1, TOOLTIP_LENGTH do getglobal('AuxInfoTooltipTextLeft'..i):SetText() @@ -242,15 +265,21 @@ function public.tooltip(setter) local tooltip = {} for i = 1, TOOLTIP_LENGTH do - local left, right = {}, {} + + local left_text = getglobal('AuxInfoTooltipTextLeft'..i):GetText() + local left_color = { getglobal('AuxInfoTooltipTextLeft'..i):GetTextColor() } - left.text = getglobal('AuxInfoTooltipTextLeft'..i):GetText() - left.color = { getglobal('AuxInfoTooltipTextLeft'..i):GetTextColor() } - - right.text = getglobal('AuxInfoTooltipTextRight'..i):GetText() - right.color = { getglobal('AuxInfoTooltipTextRight'..i):GetTextColor() } - - tinsert(tooltip, {left or '', right or ''}) + local right_text = getglobal('AuxInfoTooltipTextRight'..i):GetText() + local right_color = { getglobal('AuxInfoTooltipTextRight'..i):GetTextColor() } + + if left_text or right_text then + tinsert(tooltip, { + left_text = left_text, + left_color = left_color, + right_text = right_text, + right_color = right_color, + }) + end end for i = 1, TOOLTIP_LENGTH do @@ -263,8 +292,8 @@ end function private.item_charges(tooltip) for _, line in ipairs(tooltip) do - local _, _, left_charges_string = strfind(line[1].text or '', "^(%d+) Charges") - local _, _, right_charges_string = strfind(line[2].text or '', "^(%d+) Charges$") + local _, _, left_charges_string = strfind(line.left_text or '', '^(%d+) Charges') + local _, _, right_charges_string = strfind(line.right_text or '', '^(%d+) Charges$') local charges = tonumber(left_charges_string) or tonumber(right_charges_string) if charges then return charges diff --git a/scan_util.lua b/scan_util.lua index 62c4822..59e93de 100644 --- a/scan_util.lua +++ b/scan_util.lua @@ -311,7 +311,7 @@ function m.validator(filter) tinsert(stack, not tremove(stack)) elseif op ~= 'TT' then tinsert(stack, Aux.util.any(record.tooltip, function(entry) - return strfind(strupper(entry[1].text or ''), strupper(op), 1, true) or strfind(strupper(entry[2].text or ''), strupper(op), 1, true) + return strfind(strupper(entry.left_text or ''), strupper(op), 1, true) or strfind(strupper(entry.right_text or ''), strupper(op), 1, true) end) and true or false) end end