AuctioneerSuite/Auc-Stat-Purchased/StatPurchased.lua
2026-04-13 17:48:13 -04:00

668 lines
25 KiB
Lua

--[[
Auctioneer - StatPurchased
Version: 5.7.4568 (KillerKoala)
Revision: $Id: StatPurchased.lua 4840 2010-08-04 21:44:00Z Nechckn $
URL: http://auctioneeraddon.com/
This is an addon for World of Warcraft that adds statistical history to the auction data that is collected
when the auction is scanned, so that you can easily determine what price
you will be able to sell an item for at auction or at a vendor whenever you
mouse-over an item in the game
License:
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program(see GPL.txt); if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Note:
This AddOn's source code is specifically designed to work with
World of Warcraft's interpreted AddOn system.
You have an implicit license to use this AddOn with these facilities
since that is its designated purpose as per:
http://www.fsf.org/licensing/licenses/gpl-faq.html#InterpreterIncompat
--]]
if not AucAdvanced then return end
local libType, libName = "Stat", "Purchased"
local lib,parent,private = AucAdvanced.NewModule(libType, libName)
if not lib then return end
-- AucAdvanced locals
local aucPrint,decode,_,_,replicate,empty,get,set,default,debugPrint,fill, _TRANS = AucAdvanced.GetModuleLocals()
local Const = AucAdvanced.Const
local GetFaction = AucAdvanced.GetFaction
-- globals -> locals
local assert = assert
local tinsert = tinsert
local sqrt = sqrt
local select,ipairs,pairs,unpack,type,wipe = select,ipairs,pairs,unpack,type,wipe
local tonumber = tonumber
local strsplit = strsplit
local time = time
local concat = table.concat
local strmatch = strmatch
-- Internal variables
local SPRealmData
local pricecache = setmetatable({}, {__mode="v"})
function private.ClearCache()
wipe(pricecache)
end
function lib.CommandHandler(command, ...)
local serverKey = GetFaction()
local _,_,keyText = AucAdvanced.SplitServerKey(serverKey)
if (command == "help") then
aucPrint(_TRANS('PURC_Help_SlashHelp1') )--Help for Auctioneer - Purchased
local line = AucAdvanced.Config.GetCommandLead(libType, libName)
aucPrint(line, "help}} - ".._TRANS('PURC_Help_SlashHelp2') ) --this Purchased help
aucPrint(line, "clear}} - ".._TRANS('PURC_Help_SlashHelp3'):format(keyText) ) --clear current {{%s}} Purchased price database
aucPrint(line, "push}} - ".._TRANS('PURC_Help_SlashHelp4'):format(keyText) ) --force the {{%s}} Purchased daily stats to archive (start a new day)
elseif (command == _TRANS('clear') ) then
lib.ClearData(serverKey)
elseif (command == _TRANS('push') ) then
aucPrint(_TRANS('PURC_Help_SlashHelp5'):format(keyText) ) --Archiving {{%s}} daily stats and starting a new day
private.PushStats(serverKey)
end
end
function lib.Processor(callbackType, ...)
if (callbackType == "tooltip") then
private.ProcessTooltip(...)
elseif (callbackType == "config") then
--Called when you should build your Configator tab.
private.SetupConfigGui(...)
elseif callbackType == "scanstats" then
private.ClearCache()
end
end
lib.Processors = {}
function lib.Processors.tooltip(callbackType, ...)
private.ProcessTooltip(...)
end
function lib.Processors.config(callbackType, ...)
--Called when you should build your Configator tab.
private.SetupConfigGui(...)
end
function lib.Processors.scanstats(callbackType, ...)
private.ClearCache()
end
lib.ScanProcessors = {}
function lib.ScanProcessors.delete(operation, itemData, oldData)
local price
local auctionmaxtime = Const.AucMinTimes[itemData.timeLeft] or 86400
if (time() - itemData.seenTime <= auctionmaxtime) then
-- Auction deleted earlier than expected expiry time
local buy = itemData.buyoutPrice
if buy and buy > 0 then
-- assume bought out
price = buy
end
--[[ disabled code
-- bid detection code temporarily disabled
-- assumed bids should probably not be treated the same as assumed buyouts with respect to market price
-- needs further development
else -- Auction deleted later than earliest expected expiry time
local bid = itemData.curBid
if bid and bid > 0 then
-- assume won on last bid we saw
price = bid
end
-- end disabled code]]
end
if not price then return end
price = price / itemData.stackSize
local pricedata = private.GetPriceData(GetFaction())
local itemType, itemId, property, factor = decode(itemData.link)
if (factor ~= 0) then property = property.."x"..factor end
if not pricedata.daily[itemId] then pricedata.daily[itemId] = "" end
local stats = private.UnpackStats(pricedata.daily[itemId])
if not stats[property] then stats[property] = { 0, 0 } end
stats[property][1] = stats[property][1] + price
stats[property][2] = stats[property][2] + 1
pricedata.daily[itemId] = private.PackStats(stats)
end
-- Determines the sample estimated standard deviation based on the deviation
-- of the daily, 3day, 7day, and 14day averages. This is not technically
-- correct because they are not independent samples (the 7 day average
-- includes data from the 3 day and daily averages, for example). Still
-- it provides a good estimation in the presence of lack of data. If you
-- want to discuss the math behind this estimation, find Shirik
-- @param hyperlink The item to look up
-- @param serverKey The realm-faction key from which to look up the data
-- @return The estimated population mean
-- @return The estimated population standard deviation
-- @return The number of views found to base the standard deviation upon
local dataset = {}
function private.EstimateStandardDeviation(hyperlink, serverKey)
local dayAverage, avg3, avg7, avg14, _, dayTotal, dayCount, seenDays, seenCount = lib.GetPrice(hyperlink, serverKey)
if not seenDays then return end
local count = 0
if dayAverage then --[[dayAverage should never be nil at this point. It may be 0 if item has not been seen today - does that mess up the stats?]]
count = count + 1
dataset[count] = dayAverage
end
if seenDays >= 3 then
count = count + 1
dataset[count] = avg3
if seenDays >= 7 then
count = count + 1
dataset[count] = avg7
if seenDays >= 14 then
count = count + 1
dataset[count] = avg14
end
end
end
if count == 0 then -- No data
aucPrint(_TRANS('PURC_Interface_WarningPurchasedEmpty'):format(hyperlink) )--Warning: Purchased dataset for %s is empty.
return
end
local mean = 0
for i=1,count do
mean = mean + dataset[count]
end
mean = mean / count
local variance = 0
for i=1,count do
variance = variance + (mean - dataset[count])^2
end
return mean, sqrt(variance), count
end
local bellCurve = AucAdvanced.API.GenerateBellCurve();
-- Gets the PDF curve for a given item. This curve indicates
-- the probability of an item's mean price. Uses an estimation
-- of the normally distributed bell curve by performing
-- calculations on the daily, 3-day, 7-day, and 14-day averages
-- stored by SIMP
-- @param hyperlink The item to generate the PDF curve for
-- @param serverKey The realm-faction key from which to look up the data
-- @return The PDF for the requested item, or nil if no data is available
-- @return The lower limit of meaningful data for the PDF (determined
-- as the mean minus 5 standard deviations)
-- @return The upper limit of meaningful data for the PDF (determined
-- as the mean plus 5 standard deviations)
function lib.GetItemPDF(hyperlink, serverKey)
-- TODO: This is an estimate. Can we touch this up later? Especially the stddev==0 case
if not get("stat.purchased.enable") then return end --disable purchased if desired
-- Calculate the SE estimated standard deviation & mean
local mean, stddev, count = private.EstimateStandardDeviation(hyperlink, serverKey)
if stddev ~= stddev or mean ~= mean or not mean or mean == 0 then
return ; -- No available data or cannot estimate
end
if not count or count == 0 then
aucPrint(mean)
aucPrint(stddev)
aucPrint(count)
aucPrint(_TRANS('PURC_Interface_CountBroken') ..hyperlink)--count broken! for
count = 1
end
-- If the standard deviation is zero, we'll have some issues, so we'll estimate it by saying
-- the std dev is 100% of the mean divided by square root of number of views
if stddev == 0 then stddev = mean / sqrt(count); end
-- Calculate the lower and upper bounds as +/- 3 standard deviations
local lower, upper = mean - 3*stddev, mean + 3*stddev;
bellCurve:SetParameters(mean, stddev);
return bellCurve, lower, upper;
end
function lib.GetPrice(hyperlink, serverKey)
if not get("stat.purchased.enable") then return end --disable purchased if desired
serverKey = serverKey or GetFaction()
local data = private.GetPriceData(serverKey)
local linkType,itemId,property,factor = decode(hyperlink)
if (linkType ~= "item") then return end
if (factor ~= 0) then property = property.."x"..factor end
local cachesig = serverKey..itemId..":"..property
if pricecache[cachesig] then
local dayAverage, avg3, avg7, avg14, dayTotal, dayCount, seenDays, seenCount = unpack(pricecache[cachesig], 1, 8)
return dayAverage, avg3, avg7, avg14, false, dayTotal, dayCount, seenDays, seenCount
end
local dayTotal, dayCount, dayAverage = 0,0,0
local seenDays, seenCount, avg3, avg7, avg14 = 0,0,0,0,0
if data.daily[itemId] then
local stats = private.UnpackStats(data.daily[itemId])
if stats[property] then
dayTotal, dayCount = unpack(stats[property])
dayAverage = dayTotal/dayCount
end
end
if data.means[itemId] then
local stats = private.UnpackStats(data.means[itemId])
if stats[property] then
seenDays, seenCount, avg3, avg7, avg14 = unpack(stats[property])
end
end
pricecache[cachesig] = {dayAverage, avg3, avg7, avg14, dayTotal, dayCount, seenDays, seenCount}
return dayAverage, avg3, avg7, avg14, false, dayTotal, dayCount, seenDays, seenCount
end
function lib.GetPriceColumns()
return "Daily Avg", "3 Day Avg", "7 Day Avg", "14 Day Avg", false, "Daily Total", "Daily Count", "Seen Days", "Seen Count"
end
local pricearray={} -- used to return stuff in
function lib.GetPriceArray(hyperlink, serverKey)
if not get("stat.purchased.enable") then return end --disable purchased if desired
wipe(pricearray)
-- Get our statistics
local dayAverage, avg3, avg7, avg14, _, dayTotal, dayCount, seenDays, seenCount = lib.GetPrice(hyperlink, serverKey)
-- pricearray.price and pricearray.seen are the ones that most algorithms will look for
pricearray.seen = seenCount
if not get("stat.purchased.reportsafe") then
pricearray.price = avg3 or dayAverage
else
-- Safe mode: prefer longer-running averages for low-volume items
if seenCount>100 and seenCount > seenDays*10 then
pricearray.price = avg3 or dayAverage
-- aucPrint(hyperlink..": seen "..seenCount.." over "..seenDays.. "days. going with avg3")
else
local a3 = avg3 or dayAverage
local a7 = avg7 or a3
local a14 = avg14 or a7
if seenCount >= seenDays*7 then
pricearray.price = (a3+a7)/2
-- aucPrint(hyperlink..": seen "..seenCount.." over "..seenDays.. "days. going with avg(a3,a7)")
else
local mix3 = seenCount / (seenDays*7*2) -- 0.07 for 1/1, 0.5 for 7/1
local mix14 = 0.5-mix3
local mix7 = 1-mix3-mix14 -- actually always==0.5 :-)
pricearray.price = a3*mix3 + a7*mix7 + a14*mix14
-- aucPrint(hyperlink..": seen "..seenCount.." over "..seenDays.. "days. mix3="..mix3.." mix7="..mix7.." mix14="..mix14)
end
end
end
-- This is additional data
pricearray.avgday = dayAverage
pricearray.avg3 = avg3
pricearray.avg7 = avg7
pricearray.avg14 = avg14
pricearray.daytotal = dayTotal
pricearray.daycount = dayCount
pricearray.seendays = seenDays
return pricearray
end
function lib.OnLoad(addon)
if SPRealmData then return end
-- set defaults
default("stat.purchased.tooltip", false)
default("stat.purchased.avg3", false)
default("stat.purchased.avg7", false)
default("stat.purchased.avg14", false)
default("stat.purchased.quantmul", true)
default("stat.purchased.enable", true)
default("stat.purchased.reportsafe", false)
private.InitData()
end
function private.SetupConfigGui(gui)
local id = gui:AddTab(lib.libName, lib.libType.." Modules")
--gui:MakeScrollable(id)
gui:AddHelp(id, "what purchased stats",
_TRANS('PURC_Help_WhatPurchasedStats') ,--What are purchased stats?
_TRANS('PURC_Help_WhatPurchasedStatsAnswer') )--Purchased stats are the numbers that are generated by the Purchased module, the Purchased module attempts to determine if an auction was bought out or purchased on a bid. It also calculates a Moving Average (3/7/14).
--all options in here will be duplicated in the tooltip frame
function private.addTooltipControls(id)
gui:AddHelp(id, "what moving day average purchased",
_TRANS('PURC_Help_WhatMovingAverage') ,--What does 'moving average' mean?
_TRANS('PURC_Help_WhatMovingAverageAnswer') )--'Moving average means that it places more value on yesterday\'s moving average than today\'s average. The determined amount is then used for tomorrow\'s moving average calculation.
gui:AddHelp(id, "how day average calculated purchased",
_TRANS('PURC_Help_HowMovingAverage') ,--How is the moving day averages calculated exactly?
_TRANS('PURC_Help_HowMovingAverageAnswer') )--Todays Moving Average is ((X-1)*YesterdaysMovingAverage + TodaysAverage) / X, where X is the number of days (3,7, or 14).
gui:AddHelp(id, "no day saved purchased",
_TRANS('PURC_Help_DayAverage') ,--So you aren\'t saving a day-to-day average?
_TRANS('PURC_Help_DayAverageAnswer') )--No, that would not only take up space, but heavy calculations on each auction house scan.
gui:AddHelp(id, "why multiply stack size stddev",
_TRANS('PURC_Help_MultiplyStack') ,--Why have the option to multiply stack size?
_TRANS('PURC_Help_MultiplyStackAnswer') )--The original Stat-Purchased multiplied by the stack size of the item, but some like dealing on a per-item basis.
gui:AddHelp(id, "report safe safer price prices value low volume item items",
_TRANS('PURC_Help_SaferPrices') ,--How are the \'safer\' prices computed?
_TRANS('PURC_Help_SaferPricesAnswer') )--For anything seen more than 100 times and selling more than 10 items per day (on average), we simply use the 3 day average.\n\nFor others, we value the 7-day average at 50%, and the 3- and 14-day averages at between 0--50% and 50--0%, respectively, depending on how many are seen per day (between 1 and 7).
gui:AddControl(id, "Header", 0, libName.." options")
gui:AddControl(id, "Note", 0, 1, nil, nil, " ")
gui:AddControl(id, "Checkbox", 0, 1, "stat.purchased.enable", _TRANS('PURC_Interface_EnablePurchasedStats') )--Enable Purchased Stats
gui:AddTip(id, _TRANS('PURC_HelpTooltip_EnablePurchasedStats') )--Allow Stat Purchased to gather and return price data
gui:AddControl(id, "Note", 0, 1, nil, nil, " ")
gui:AddControl(id, "Checkbox", 0, 4, "stat.purchased.tooltip", _TRANS('PURC_Interface_ShowPurchased') )--Show purchased stats in the tooltips?
gui:AddTip(id, _TRANS('PURC_HelpTooltip_ShowPurchased') )--Toggle display of stats from the Purchased module on or off
gui:AddControl(id, "Checkbox", 0, 6, "stat.purchased.avg3", _TRANS('PURC_Interface_Toggle3Day') )--Display Moving 3 Day Average
gui:AddTip(id, _TRANS('PURC_HelpTooltip_Toggle3Day') )--Toggle display of 3-Day average from the Purchased module on or off
gui:AddControl(id, "Checkbox", 0, 6, "stat.purchased.avg7", _TRANS('PURC_Interface_Toggle7Day') )--Display Moving 7 Day Average
gui:AddTip(id, _TRANS('PURC_HelpTooltip_Toggle7Day') )--Toggle display of 7-Day average from the Purchased module on or off
gui:AddControl(id, "Checkbox", 0, 6, "stat.purchased.avg14", _TRANS('PURC_Interface_Toggle14Day') )--Display Moving 14 Day Average
gui:AddTip(id, _TRANS('PURC_HelpTooltip_Toggle14Day') )--Toggle display of 14-Day average from the Purchased module on or off
gui:AddControl(id, "Note", 0, 1, nil, nil, " ")
gui:AddControl(id, "Checkbox", 0, 4, "stat.purchased.reportsafe", _TRANS('PURC_Interface_ReportSaferPrices') )--Report safer prices for low volume items
gui:AddTip(id, _TRANS('PURC_HelpTooltip_ReportSaferPrices') )--Returns longer averages (7-day, or even 14-day) for low-volume items
gui:AddControl(id, "Checkbox", 0, 4, "stat.purchased.quantmul", _TRANS('PURC_Interface_MultiplyStack') )--Multiply by Stack Size
gui:AddTip(id, _TRANS('PURC_HelpTooltip_MultiplyStack') )--Multiplies by current Stack Size if on
gui:AddControl(id, "Note", 0, 1, nil, nil, " ")
end
--This is the Tooltip tab provided by aucadvnced so all tooltip configuration is in one place
local tooltipID = AucAdvanced.Settings.Gui.tooltipID
--now we create a duplicate of these in the tooltip frame
private.addTooltipControls(id)
if tooltipID then private.addTooltipControls(tooltipID) end
end
--[[ Local functions ]]--
function private.ProcessTooltip(tooltip, name, hyperlink, quality, quantity, cost)
if not get("stat.purchased.tooltip") then return end
if not quantity or quantity < 1 then quantity = 1 end
if not get("stat.purchased.quantmul") then quantity = 1 end
local dayAverage, avg3, avg7, avg14, _, dayTotal, dayCount, seenDays, seenCount = lib.GetPrice(hyperlink)
if (not dayAverage) then return end
if (seenDays + dayCount > 0) then
tooltip:AddLine(_TRANS('PURC_Tooltip_PurchasedPrices'))--Purchased prices:
if (seenDays > 0) then
if (dayCount>0) then seenDays = seenDays + 1 end
tooltip:AddLine(" ".._TRANS('PURC_Tooltip_SeenNumberDays'):format(seenCount+dayCount, seenDays) )--Seen {{%s}} over {{%s}} days:
end
if (seenDays > 6) and get("stat.purchased.avg14") then
tooltip:AddLine(" ".._TRANS('PURC_Tooltip_14DayAverage'), avg14*quantity)-- 14 day average
end
if (seenDays > 2) and get("stat.purchased.avg7") then
tooltip:AddLine(" ".._TRANS('PURC_Tooltip_7DayAverage'), avg7*quantity)-- 7 day average
end
if (seenDays > 0) and get("stat.purchased.avg3") then
tooltip:AddLine(" ".._TRANS('PURC_Tooltip_3DayAverage'), avg3*quantity)-- 3 day average
end
if (dayCount > 0) then
tooltip:AddLine(" ".._TRANS('PURC_Tooltip_SeenToday'):format(dayCount), dayAverage*quantity)--Seen {{%s}} today
end
end
end
-- This is a function which migrates the data from a daily average to the
-- Exponential Moving Averages over the 3, 7 and 14 day ranges.
function private.PushStats(serverKey)
local dailyAvg
local data = private.GetPriceData(serverKey)
local pdata, fdata
for itemId, stats in pairs(data.daily) do
if (itemId ~= "created") then
pdata = private.UnpackStats(stats)
fdata = private.UnpackStats(data.means[itemId] or "")
for property, info in pairs(pdata) do
dailyAvg = info[1] / info[2]
if not fdata[property] then
fdata[property] = {
1,
info[2],
("%0.01f"):format(dailyAvg),
("%0.01f"):format(dailyAvg),
("%0.01f"):format(dailyAvg),
}
else
fdata[property][1] = fdata[property][1] + 1
fdata[property][2] = fdata[property][2] + info[2]
fdata[property][3] = ("%0.01f"):format(((fdata[property][3] * 2) + dailyAvg)/3)
fdata[property][4] = ("%0.01f"):format(((fdata[property][4] * 6) + dailyAvg)/7)
fdata[property][5] = ("%0.01f"):format(((fdata[property][5] * 13) + dailyAvg)/14)
end
end
data.means[itemId] = private.PackStats(fdata)
end
end
data.daily = { created = time() }
private.ClearCache()
end
function private.UnpackStatIter(data, ...)
local c = select("#", ...)
local v
for i = 1, c do
v = select(i, ...)
local property, info = strsplit(":", v)
property = tonumber(property) or property
if (property and info) then
data[property] = { strsplit(";", info) }
local item
for i=1, #data[property] do
item = data[property][i]
data[property][i] = tonumber(item) or item
end
end
end
end
function private.UnpackStats(dataItem)
local data = {}
private.UnpackStatIter(data, strsplit(",", dataItem))
return data
end
local tmp={}
function private.PackStats(data)
local n=0
for property, info in pairs(data) do
tmp[n+1]=property
tmp[n+2]=":"
tmp[n+3]=concat(info, ";")
tmp[n+4]=","
n=n+4
end
return concat(tmp, "", 1, n-1) -- n-1 to skip last ","
end
-- The following Functions are the routines used to access the permanent store data
function private.UpgradeDb()
private.UpgradeDb = nil
if type(AucAdvancedStatPurchasedData) == "table" and AucAdvancedStatPurchasedData.Version == "2.0" then return end
local newSave = { Version = "2.0", RealmData = {} }
if type(AucAdvancedStatPurchasedData) == "table" and AucAdvancedStatPurchasedData.Version == "1.0" then
-- convert from type "1.0" database to type "2.0"
for realm, realmData in pairs (AucAdvancedStatPurchasedData.RealmData) do
if type(realm) == "string" and type(realmData) == "table" then
for faction, data in pairs (realmData) do
if type(faction) == "string" and type(data) == "table" and strmatch(faction, "^%u%l+$") then
-- looks like a valid realm/faction combination
local serverKey = realm.."-"..faction
local stats = data.stats
if type(stats) == "table" then
if type(data.means) ~= "table" then
data.means = {}
end
if type(data.daily) ~= "table" then
data.daily = { created = time () }
elseif type(data.daily.created) ~= "number" then
data.daily.created = time ()
end
newSave.RealmData[serverKey] = stats
end
end
end
end
end
end
AucAdvancedStatPurchasedData = newSave
end
function lib.ClearData(serverKey)
serverKey = serverKey or GetFaction()
if AucAdvanced.API.IsKeyword(serverKey, "ALL") then
wipe(SPRealmData)
private.ClearCache()
aucPrint(_TRANS('PURC_Interface_ClearingPurchased').." {{".._TRANS("ADV_Interface_AllRealms").."}}") --Clearing Purchased stats for // All realms
elseif SPRealmData[serverKey] then
local _,_,keyText = AucAdvanced.SplitServerKey(serverKey)
SPRealmData[serverKey] = nil
private.ClearCache()
aucPrint(_TRANS('PURC_Interface_ClearingPurchased').." {{"..keyText.."}}")--Clearing Purchased stats for
end
end
function lib.ClearItem(hyperlink, serverKey)
local linkType,itemID,property,factor = decode(hyperlink)
if (linkType ~= "item") then return end
if (factor and factor ~= 0) then property = property.."x"..factor end
serverKey = serverKey or GetFaction ()
local data = private.GetPriceData(serverKey)
local cleareditem = false
if data.daily[itemID] then
local stats = private.UnpackStats (data.daily[itemID])
if stats[property] then
stats[property] = nil
cleareditem = true
data.daily[itemID] = private.PackStats (stats)
end
end
if data.means[itemID] then
local stats = private.UnpackStats (data.means[itemID])
if stats[property] then
stats[property] = nil
cleareditem = true
data.means[itemID] = private.PackStats (stats)
end
end
if cleareditem then
local _, _, keyText = AucAdvanced.SplitServerKey(serverKey)
aucPrint(_TRANS('PURC_Interface_ClearingPurchasedLink'):format(hyperlink, keyText) )--Stat - Purchased: clearing data for {{%s}} for {{%s}}
private.ClearCache()
end
end
function private.GetPriceData(serverKey)
local data = SPRealmData[serverKey]
if not data then
if not AucAdvanced.SplitServerKey(serverKey) then
error("Invalid serverKey passed to Stat-Purchased")
end
data = {means = {}, daily = {created = time()}}
SPRealmData[serverKey] = data
end
return data
end
function private.InitData()
private.InitData = nil
-- Load Data
private.UpgradeDb()
SPRealmData = AucAdvancedStatPurchasedData.RealmData
if not SPRealmData then
SPRealmData = {} -- dummy table to avoid errors in future events; data will not be saved
error("Error loading or creating Stat-Purchased database")
end
-- Data maintenance
for serverKey, data in pairs(SPRealmData) do
if type(serverKey) ~= "string" or not strmatch(serverKey, ".%-%u%l") then
-- not a valid serverKey - remove it
SPRealmData[serverKey] = nil
else
-- lots of checks to make sure we ONLY have valid data in this table
for key, _ in pairs (data) do
if key ~= "means" and key ~= "daily" then
data[key] = nil
end
end
if type(data.means) == "table" then
for id, packed in pairs(data.means) do
if type(id) ~= "number" or type(packed) ~= "string" then
data.means[id] = nil
end
end
else
data.means = {}
end
if type(data.daily) == "table" then
for id, packed in pairs(data.daily) do
if id ~= "created" and (type(id) ~= "number" or type(packed) ~= "string") then
data.daily[id] = nil
end
end
if type(data.daily.created) ~= "number" then
data.daily.created = time()
end
else
data.daily = {created = time()}
end
if time() - data.daily.created > 3600*16 then
-- This data is more than 16 hours old, we classify this as "yesterday's data"
private.PushStats(serverKey)
end
end
end
end
AucAdvanced.RegisterRevision("$URL: http://svn.norganna.org/auctioneer/branches/5.9/Auc-Stat-Purchased/StatPurchased.lua $", "$Rev: 4840 $")