Files
aux-addon-ClassicAPI/core/history.lua
T
2024-01-08 16:55:46 +01:00

188 lines
6.4 KiB
Lua

module 'aux.core.history'
--not using acecomm anymore
--[[AuxAddon = AceLibrary("AceAddon-2.0"):new("AceComm-2.0") --im unsure this is done correctly but seems to work lol
local commPrefix = "AuxAddon";
AuxAddon:SetCommPrefix(commPrefix)
function AuxAddon:OnEnable()
--self:RegisterComm(commPrefix, "GROUP", "OnCommReceive"); --for testing purposes, not really useful in real world I think
self:RegisterComm(commPrefix, "GUILD", "OnCommReceive");
--self:RegisterComm(commPrefix, "ZONE", "OnCommReceive");
end ]]--
local T = require 'T'
local aux = require 'aux'
local persistence = require 'aux.util.persistence'
local history_schema = {'tuple', '#', {next_push='number'}, {daily_min_buyout='number'}, {data_points={'list', ';', {'tuple', '@', {value='number'}, {time='number'}}}}}
local value_cache = {}
function aux.handle.LOAD2()
data = aux.faction_data.history
end
do
local next_push = 0
function get_next_push()
if time() > next_push then
local date = date('*t')
date.hour, date.min, date.sec = 24, 0, 0
next_push = time(date)
end
return next_push
end
end
function new_record()
return T.temp-T.map('next_push', get_next_push(), 'data_points', T.acquire())
end
function read_record(item_key)
local record = data[item_key] and persistence.read(history_schema, data[item_key]) or new_record()
if record.next_push <= time() then
push_record(record)
write_record(item_key, record)
end
return record
end
function write_record(item_key, record)
data[item_key] = persistence.write(history_schema, record)
if value_cache[item_key] then
T.release(value_cache[item_key])
value_cache[item_key] = nil
end
end
--pfUI.api.strsplit
local function AuxAddon_strsplit(delimiter, subject)
if not subject then return nil end
local delimiter, fields = delimiter or ":", {}
local pattern = string.format("([^%s]+)", delimiter)
string.gsub(subject, pattern, function(c) fields[table.getn(fields)+1] = c end)
return unpack(fields)
end
--taken from Atlasloot Update announcing code
AUX_data_sharer = CreateFrame("Frame")
AUX_data_sharer:RegisterEvent("CHAT_MSG_CHANNEL")
AUXplayerName = UnitName("player")
AUX_data_sharer:SetScript("OnEvent", function()
if event == "CHAT_MSG_CHANNEL" then
local _,_,source = string.find(arg4,"(%d+)%.")
if source then
_,name = GetChannelName(source)
end
if name == "LFT" then
local msg, item_key, munit_buyout_price = AuxAddon_strsplit(",", arg1) --using , as a seperator because item_key contains a :
if msg == "AuxData" then
if arg2 ~= AUXplayerName then
--print(arg2)
--print(AUXplayerName)
local unit_buyout_price = tonumber (munit_buyout_price)
--print("received data:" .. msg .. "," .. item_key .. "," .. unit_buyout_price); --for testing (print comes from PFUI)
local item_record = read_record(item_key)
if unit_buyout_price > 0 and unit_buyout_price < (item_record.daily_min_buyout or aux.huge) then
item_record.daily_min_buyout = unit_buyout_price
write_record(item_key, item_record)
--print("wrote data"); --for testing (print comes from PFUI)
end
end
end
end
end
end)
local lastMessageTime = 0
local messageCooldown = 0.01 --time between messages in seconds. Arbitrary value to stop people from getting chat restricted when doing full scans. Could probably be lower but that would lead to so much spam, full scan bad
function M.process_auction(auction_record)
local currentTime = GetTime()
local elapsedTime = currentTime - lastMessageTime
local item_record = read_record(auction_record.item_key)
local unit_buyout_price = ceil(auction_record.buyout_price / auction_record.aux_quantity)
local item_key = auction_record.item_key
if unit_buyout_price > 0 and unit_buyout_price < (item_record.daily_min_buyout or aux.huge) then
item_record.daily_min_buyout = unit_buyout_price
write_record(auction_record.item_key, item_record)
--AuxAddon:SendCommMessage("GUILD", item_key, unit_buyout_price) relies on acecomm
if elapsedTime >= messageCooldown then
if GetChannelName("LFT") ~= 0 then
SendChatMessage("AuxData," .. item_key .."," .. unit_buyout_price , "CHANNEL", nil, GetChannelName("LFT"))
end
lastMessageTime = currentTime
end
--print("sent/wrote data"); --for testing
end
end
--[[ function AuxAddon:OnCommReceive(prefix, sender, distribution, item_key, unit_buyout_price) --copied code from process_auction. <- code for when using acecomm
print("received data"); --for testing (print comes from PFUI)
local item_record = read_record(item_key)
if unit_buyout_price > 0 and unit_buyout_price < (item_record.daily_min_buyout or aux.huge) then
item_record.daily_min_buyout = unit_buyout_price
write_record(item_key, item_record)
--print("wrote data"); --for testing (print comes from PFUI)
end
end ]]--
function M.data_points(item_key)
return read_record(item_key).data_points
end
function M.value(item_key)
if not value_cache[item_key] or value_cache[item_key].next_push <= time() then
local item_record, value
item_record = read_record(item_key)
if getn(item_record.data_points) > 0 then
local total_weight, weighted_values = 0, T.temp-T.acquire()
for _, data_point in item_record.data_points do
local weight = .99 ^ aux.round((item_record.data_points[1].time - data_point.time) / (60 * 60 * 24))
total_weight = total_weight + weight
tinsert(weighted_values, T.map('value', data_point.value, 'weight', weight))
end
for _, weighted_value in weighted_values do
weighted_value.weight = weighted_value.weight / total_weight
end
value = weighted_median(weighted_values)
else
value = item_record.daily_min_buyout
end
value_cache[item_key] = T.map('value', value, 'next_push', item_record.next_push)
end
return value_cache[item_key].value
end
function M.market_value(item_key)
return read_record(item_key).daily_min_buyout
end
function weighted_median(list)
sort(list, function(a,b) return a.value < b.value end)
local weight = 0
for _, v in ipairs(list) do
weight = weight + v.weight
if weight >= .5 then
return v.value
end
end
end
function push_record(item_record)
if item_record.daily_min_buyout then
tinsert(item_record.data_points, 1, T.map('value', item_record.daily_min_buyout, 'time', item_record.next_push))
while getn(item_record.data_points) > 11 do
T.release(item_record.data_points[getn(item_record.data_points)])
tremove(item_record.data_points)
end
end
item_record.next_push, item_record.daily_min_buyout = get_next_push(), nil
end