--[[ Auctioneer - StatSimple Version: 5.7.4568 (KillerKoala) Revision: $Id: StatSimple.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", "Simple" local lib,parent,private = AucAdvanced.NewModule(libType, libName) if not lib then return end local aucPrint,decode,_,_,replicate,_,get,set,default,debugPrint,fill, _TRANS = AucAdvanced.GetModuleLocals() local GetFaction = AucAdvanced.GetFaction -- Eliminate some global lookups local select = select local sqrt = sqrt local ipairs = ipairs local unpack = unpack local tinsert = table.insert local assert = assert local tonumber = tonumber local pairs = pairs local type,time,wipe,ceil = type,time,wipe,ceil local concat=table.concat local strsplit,strfind=strsplit,strfind -- GLOBALS: AucAdvancedStatSimpleData -- local reference to our saved stats table local SSRealmData function lib.CommandHandler(command, ...) local serverKey = GetFaction() local _,_,keyText = AucAdvanced.SplitServerKey(serverKey) if (command == "help") then aucPrint(_TRANS('SIMP_Help_SlashHelp1') ) --Help for Auctioneer Advanced - Simple local line = AucAdvanced.Config.GetCommandLead(libType, libName) aucPrint(line, "help}} - ".._TRANS('SIMP_Help_SlashHelp2') ) --this Simple help aucPrint(line, "clear}} - ".._TRANS('SIMP_Help_SlashHelp3'):format(keyText) ) --clear current %s Simple price database aucPrint(line, "push}} - ".._TRANS('SIMP_Help_SlashHelp4'):format(keyText) ) --force the %s Simple daily stats to archive (start a new day) elseif (command == "clear") then lib.ClearData(serverKey) elseif (command == "push") then aucPrint(_TRANS('SIMP_Help_SlashHelp6'):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(...) end end lib.Processors = {} lib.Processors.tooltip = lib.Processor lib.Processors.config = lib.Processor lib.ScanProcessors = {} function lib.ScanProcessors.create(operation, itemData, oldData) if not get("stat.simple.enable") then return end -- This function is responsible for processing and storing the stats after each scan -- Note: itemData gets reused over and over again, so do not make changes to it, or use -- it in places where you rely on it. Make a deep copy of it if you need it after this -- function returns. -- We're only interested in items with buyouts. local buyout = itemData.buyoutPrice if not buyout or buyout == 0 then return end local buyoutper = ceil(buyout/itemData.stackSize) -- In this case, we're only interested in the initial create, other -- Get the signature of this item and find it's stats. local itemType, itemId, property, factor = AucAdvanced.DecodeLink(itemData.link) if (factor ~= 0) then property = property.."x"..factor end local data = private.GetPriceData(GetFaction()) if not data.daily[itemId] then data.daily[itemId] = "" end local stats = private.UnpackStats(data.daily[itemId]) if not stats[property] then stats[property] = { 0, 0 , buyoutper } end if not stats[property][3] then stats[property][3] = buyoutper end stats[property][1] = stats[property][1] + buyout stats[property][2] = stats[property][2] + itemData.stackSize if stats[property][3] > buyoutper then stats[property][3] = buyoutper end data.daily[itemId] = private.PackStats(stats) end local dataset = {} function lib.GetPrice(hyperlink, serverKey) if not get("stat.simple.enable") then return end local linkType,itemId,property,factor = AucAdvanced.DecodeLink(hyperlink) if (linkType ~= "item") then return end if (factor ~= 0) then property = property.."x"..factor end serverKey = serverKey or GetFaction() local data = private.GetPriceData(serverKey) local dayTotal, dayCount, dayAverage, minBuyout = 0,0,0,0 local seenDays, seenCount, avg3, avg7, avg14, avgmins = 0,0,0,0,0,0 -- Stddev calculations for market price local count=0 -- index into dataset[] (living static outside the function) local daysUsed = 0 -- used to keep running track of which daily averages we have if data.daily[itemId] then local stats = private.UnpackStats(data.daily[itemId]) if stats[property] then dayTotal, dayCount, minBuyout = unpack(stats[property]) dayAverage = dayTotal/dayCount if not minBuyout then minBuyout = 0 end -- Stddev calculations for market price count=count+1 dataset[count] = dayAverage daysUsed = 1 end end if data.means[itemId] then local stats = private.UnpackStats(data.means[itemId]) if stats[property] then seenDays, seenCount, avg3, avg7, avg14, avgmins = unpack(stats[property]) if not avgmins then avgmins = 0 end -- Stddev calculations for market price if seenDays >= 3 then for n = 1, 3-daysUsed do count=count+1 dataset[count] = avg3 end daysUsed = 3 end if seenDays >= 7 then for n = 1, 7-daysUsed do count=count+1 dataset[count] = avg7 end daysUsed = 7 end if seenDays >= 14 then for n = 1, 14-daysUsed do count=count+1 dataset[count] = avg14 end daysUsed = 14 end end end local mean = 0 if count > 0 then for n=1,count do mean=mean+dataset[n] end mean = mean/count end local variance = 0 if count == 1 then variance = 0 else for n=1,count do variance = variance + (mean - dataset[n])^2; end variance = sqrt(variance/(count-1)) end return dayAverage, avg3, avg7, avg14, minBuyout, avgmins, false, dayTotal, dayCount, seenDays, seenCount, mean, variance end function lib.GetPriceColumns() return "Daily Avg", "3 Day Avg", "7 Day Avg", "14 Day Avg", "Min BO", "Avg MBO", false, "Daily Total", "Daily Count", "Seen Days", "Seen Count", "Mean", "StdDev" end local array = {} function lib.GetPriceArray(hyperlink, serverKey) if not get("stat.simple.enable") then return end -- Clean out the old array wipe(array) -- Get our statistics local dayAverage, avg3, avg7, avg14, minBuyout, avgmins, _, dayTotal, dayCount, seenDays, seenCount, mean, stddev = lib.GetPrice(hyperlink, serverKey) --if nothing is returned, return nil if not dayCount then return end -- If reportsafe is on use the mean of all 14 day samples. Else use the "traditional" Simple values. if not get("stat.simple.reportsafe") then if (avg3 and seenDays > 3) or dayCount == 0 then array.price = avg3 elseif dayCount > 0 then array.price = dayAverage end else array.price = mean end array.stddev = stddev array.seen = seenCount array.avgday = dayAverage array.avg3 = avg3 array.avg7 = avg7 array.avg14 = avg14 array.mbo = minBuyout array.avgmins = avgmins array.daytotal = dayTotal array.daycount = dayCount array.seendays = seenDays -- Return a temporary array. Data in this array is -- only valid until this function is called again. return array 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.simple.enable") then return end -- Calculate the SE estimated standard deviation & mean local dayAverage, avg3, avg7, avg14, minBuyout, avgmins, _, dayTotal, dayCount, seenDays, seenCount, mean, stddev = lib.GetPrice(hyperlink, serverKey) if seenCount == 0 or stddev ~= stddev or mean ~= mean or not mean or mean == 0 then return ; -- No available data or cannot estimate 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(seenCount); 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.OnLoad(addon) if SSRealmData then return end -- Set defaults default("stat.simple.tooltip", false) default("stat.simple.avg3", false) default("stat.simple.avg7", false) default("stat.simple.avg14", false) default("stat.simple.minbuyout", true) default("stat.simple.avgmins", true) default("stat.simple.quantmul", true) default("stat.simple.enable", true) default("stat.simple.reportsafe", false) -- Load and check data private.InitData() end function lib.ClearItem(hyperlink, serverKey) local linkType, itemID, property, factor = AucAdvanced.DecodeLink(hyperlink) if linkType ~= "item" then return end if (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('SIMP_Help_SlashHelpClearingData'):format(libType, hyperlink, keyText)) --%s - Simple: clearing data for %s for {{%s}} end end function private.SetupConfigGui(gui) local id = gui:AddTab(lib.libName, lib.libType.." Modules" ) gui:AddHelp(id, "what simple stats", _TRANS('SIMP_Help_SimpleStats') ,--What are simple stats? _TRANS('SIMP_Help_SimpleStatsAnswer') )--Simple stats are the numbers that are generated by the Simple module, the Simple module averages all of the prices for items that it sees and provides moving 3, 7, and 14 day averages. It also provides daily minimum buyout along with a running average minimum buyout within 10% variance. --all options in here will be duplicated in the tooltip frame function private.addTooltipControls(id) gui:AddHelp(id, "what moving day average", _TRANS('SIMP_Help_MovingAverage') , --What does \'moving day average\' mean? _TRANS('SIMP_Help_MovingAverageAnswer') --Moving average means that it places more value on yesterday\'s moving averagethan today\'s average. The determined amount is then used for tomorrow\'s moving average calculation. ) gui:AddHelp(id, "how day average calculated", _TRANS('SIMP_Help_HowAveragesCalculated') , --How is the moving day averages calculated exactly? _TRANS('SIMP_Help_HowAveragesCalculatedAnswer') --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", _TRANS('SIMP_Help_NoDaySaved') ,--So you aren't saving a day-to-day average? _TRANS('SIMP_Help_NoDaySavedAnswer') )--No, that would not only take up space, but heavy calculations on each auction house scan, and this is only a simple model. gui:AddHelp(id, "minimum buyout", _TRANS('SIMP_Help_MinimumBuyout') ,--Why do I need to know minimum buyout? _TRANS('SIMP_Help_MinimumBuyoutAnswer')--While some items will sell very well at average within 2 days, others may sell only if it is the lowest price listed. This was an easy calculation to do, so it was put in this module. ) gui:AddHelp(id, "average minimum buyout", _TRANS('SIMP_Help_AverageMinimumBuyout') ,--What's the point in an average minimum buyout? _TRANS('SIMP_Help_AverageMinimumBuyoutAnswer')--This way you know how good a market is dealing. If the MBO (minimum buyout) is bigger than the average MBO, then it\'s usually a good time to sell, and if the average MBO is greater than the MBO, then it\'s a good time to buy. ) gui:AddHelp(id, "average minimum buyout variance", _TRANS('SIMP_Help_MinimumBuyoutVariance') ,--What\'s the \'10% variance\' mentioned earlier for? _TRANS('SIMP_Help_MinimumBuyoutVarianceAnswer')--If the current MBO is inside a 10% range of the running average, the current MBO is averaged in to the running average at 50% (normal). If the current MBO is outside the 10% range, the current MBO will only be averaged in at a 12.5% rate. ) gui:AddHelp(id, "why have variance", _TRANS('SIMP_Help_WhyVariance') ,--What\'s the point of a variance on minimum buyout? _TRANS('SIMP_Help_WhyVarianceAnswer') --Because some people put their items on the market for rediculous price (too low or too high), so this helps keep the average from getting out of hand. ) gui:AddHelp(id, "why multiply stack size simple", _TRANS('SIMP_Help_WhyMultiplyStack') ,--Why have the option to multiply stack size? _TRANS('SIMP_Help_WhyMultiplyStackAnswer') --The original Stat-Simple multiplied by the stack size of the item, but some like dealing on a per-item basis. ) gui:AddControl(id, "Header", 0, _TRANS('SIMP_Interface_SimpleOptions') )--Simple options' gui:AddControl(id, "Note", 0, 1, nil, nil, " ") gui:AddControl(id, "Checkbox", 0, 1, "stat.simple.enable", _TRANS('SIMP_Interface_EnableSimpleStats') )--Enable Simple Stats gui:AddTip(id, _TRANS('SIMP_HelpTooltip_EnableSimpleStats') )--Allow Simple Stats to gather and return price data gui:AddControl(id, "Note", 0, 1, nil, nil, " ") gui:AddControl(id, "Checkbox", 0, 4, "stat.simple.tooltip", _TRANS('SIMP_Interface_Show') )--Show simple stats in the tooltips? gui:AddTip(id, _TRANS('SIMP_HelpTooltip_Show') )--Toggle display of stats from the Simple module on or off gui:AddControl(id, "Checkbox", 0, 6, "stat.simple.avg3", _TRANS('SIMP_Interface_Toggle3Day') )--Display Moving 3 Day Average gui:AddTip(id, _TRANS('SIMP_HelpTooltip_Toggle3Day') )--Toggle display of 3-Day average from the Simple module on or off gui:AddControl(id, "Checkbox", 0, 6, "stat.simple.avg7", _TRANS('SIMP_Interface_Toggle7Day') )--Display Moving 7 Day Average gui:AddTip(id, _TRANS('SIMP_HelpTooltip_Toggle7Day') )--Toggle display of 7-Day average from the Simple module on or off gui:AddControl(id, "Checkbox", 0, 6, "stat.simple.avg14", _TRANS('SIMP_Interface_Toggle14Day') )--Display Moving 14 Day Average gui:AddTip(id,_TRANS( 'SIMP_HelpTooltip_Toggle14Day') )--Toggle display of 14-Day average from the Simple module on or off gui:AddControl(id, "Checkbox", 0, 6, "stat.simple.minbuyout", _TRANS('SIMP_Interface_MinBuyout') )--Display Daily Minimum Buyout gui:AddTip(id, _TRANS('SIMP_HelpTooltip_MinBuyout') )--Toggle display of Minimum Buyout from the Simple module on or offMultiplies by current stack size if on gui:AddControl(id, "Checkbox", 0, 6, "stat.simple.avgmins", _TRANS('SIMP_Interface_MinBuyoutAverage') )--Display Average of Daily Minimum Buyouts gui:AddTip(id,_TRANS( 'SIMP_HelpTooltip_MinBuyoutAverage') )--Toggle display of Minimum Buyout average from the Simple module on or off gui:AddControl(id, "Note", 0, 1, nil, nil, " ") gui:AddControl(id, "Checkbox", 0, 4, "stat.simple.quantmul", _TRANS('SIMP_Interface_MultiplyStack') )--Multiply by stack size gui:AddTip(id, _TRANS('SIMP_HelpTooltip_MultiplyStack') )--Multiplies by current stack size if on gui:AddControl(id, "Checkbox", 0, 4, "stat.simple.reportsafe", _TRANS('SIMP_Interface_LongerAverage') )--Report safer prices for low volume items gui:AddTip(id, _TRANS('SIMP_HelpTooltip_LongerAverage') )--Returns longer averages (7-day, or even 14-day) for low-volume items 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) -- In this function, you are afforded the opportunity to add data to the tooltip should you so -- desire. You are passed a hyperlink, and it's up to you to determine whether or what you should -- display in the tooltip. if not get("stat.simple.tooltip") then return end if not quantity or quantity < 1 then quantity = 1 end if not get("stat.simple.quantmul") then quantity = 1 end local serverKey, realm, faction = GetFaction () -- realm/faction requested for anticipated changes to add cross-faction tooltips local dayAverage, avg3, avg7, avg14, minBuyout, avgmins, _, dayTotal, dayCount, seenDays, seenCount = lib.GetPrice(hyperlink, serverKey) local dispAvg3 = get("stat.simple.avg3") local dispAvg7 = get("stat.simple.avg7") local dispAvg14 = get("stat.simple.avg14") local dispMinB = get("stat.simple.minbuyout") local dispAvgMBO = get("stat.simple.avgmins") if (not dayAverage) then return end if (seenDays + dayCount > 0) then tooltip:AddLine(_TRANS('SIMP_Tooltip_SimplePrices') )--Simple prices: if (seenDays > 0) then if (dayCount>0) then seenDays = seenDays + 1 end tooltip:AddLine(" ".._TRANS('SIMP_Tooltip_SeenNumberDays'):format(seenCount+dayCount, seenDays) ) --Seen {{%s}} over {{%s}} days: end if (seenDays > 6) and dispAvg14 then tooltip:AddLine(" ".._TRANS('SIMP_Tooltip_14DayAverage') , avg14*quantity)-- 14 day average end if (seenDays > 2) and dispAvg7 then tooltip:AddLine(" ".._TRANS('SIMP_Tooltip_7DayAverage') , avg7*quantity) -- 7 day average end if (seenDays > 0) and dispAvg3 then tooltip:AddLine(" ".._TRANS('SIMP_Tooltip_3DayAverage') , avg3*quantity)-- 3 day average end if (seenDays > 0) and (avgmins > 0) and dispAvgMBO then tooltip:AddLine(" ".._TRANS('SIMP_Tooltip_AverageMBO') , avgmins*quantity)-- Average MBO end if (dayCount > 0) then tooltip:AddLine(" ".._TRANS('SIMP_Tooltip_SeenToday'):format(dayCount) , dayAverage*quantity) --Seen {{%s}} today: end if (dayCount > 0) and (minBuyout > 0) and dispMinB then tooltip:AddLine(" ".._TRANS('SIMP_Tooltip_TodaysMBO') , minBuyout*quantity)-- Today's Min BO 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, temp 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 info[3] then info[3] = 0 end if not fdata[property] then fdata[property] = { 1, info[2], ("%0.01f"):format(dailyAvg), ("%0.01f"):format(dailyAvg), ("%0.01f"):format(dailyAvg), ("%0.01f"):format(info[3]) } 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) if not fdata[property][6] then fdata[property][6] = 0 end temp = fdata[property][6] if temp < 1 then fdata[property][6] = info[3] else if info[3] ~= 0 then if temp < info[3] then if (temp*10/info[3]) < 9 then fdata[property][6] = ("%0.01f"):format((temp+info[3])/2) else fdata[property][6] = ("%0.01f"):format((temp*7+info[3])/8) end else if (info[3]*10/temp) < 9 then fdata[property][6] = ("%0.01f"):format((temp+info[3])/2) else fdata[property][6] = ("%0.01f"):format((temp*7+info[3])/8) end end end end end end data.means[itemId] = private.PackStats(fdata) end end data.daily = {created = time()} 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 n=n+1 tmp[n]=property..":"..concat(info, ";") end return concat(tmp,",",1,n) end -- The following Functions are the routines used to access the permanent store data function private.UpgradeDb() private.UpgradeDb = nil if type(AucAdvancedStatSimpleData) == "table" and AucAdvancedStatSimpleData.Version == "2.0" then return end local newSave = {Version = "2.0", RealmData = {}} -- Will only be run once per user account; however must run smoothly every time -- Can afford to perform extra type-checking for safety if type(AucAdvancedStatSimpleData) == "table" and AucAdvancedStatSimpleData.Version == "1.0" then -- perform upgrade from "1.0" to "2.0" for realm, realmData in pairs (AucAdvancedStatSimpleData.RealmData) do if type (realm) == "string" and type (realmData) == "table" then -- valid stats will only be stored in serverKeys which match realm local realmPattern = realm.."%-%u%l" for serverKey, data in pairs (realmData) do if type (serverKey) == "string" and type (data) == "table" and strfind (serverKey, realmPattern) then -- found a valid serverKey -- ensure all required subtables are present 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] = data end end end end end AucAdvancedStatSimpleData = newSave end function lib.ClearData(serverKey) serverKey = serverKey or GetFaction() if AucAdvanced.API.IsKeyword(serverKey, "ALL") then wipe(SSRealmData) aucPrint(_TRANS('SIMP_Interface_ClearingSimple').." {{".._TRANS("ADV_Interface_AllRealms").."}}") --Clearing Simple stats for // All realms elseif SSRealmData[serverKey] then local _,_,keyText = AucAdvanced.SplitServerKey(serverKey) keyText = keyText or tostring(serverKey) -- avoid display error if database entry is not a valid serverKey (due to minor database corruption) SSRealmData[serverKey] = nil aucPrint(_TRANS('SIMP_Interface_ClearingSimple').." {{"..keyText.."}}") --Clearing Simple stats for end end function private.GetPriceData(serverKey) local data = SSRealmData[serverKey] if not data then if not AucAdvanced.SplitServerKey(serverKey) then error("Invalid serverKey passed to Stat-Simple") end data = {means = {}, daily = {created = time ()}} SSRealmData[serverKey] = data end return data end function private.InitData() private.InitData = nil -- Load data private.UpgradeDb() SSRealmData = AucAdvancedStatSimpleData.RealmData if not SSRealmData then SSRealmData = {} -- dummy value to avoid more errors - will not get saved error("Error loading or creating StatSimple database") end -- Note: database errors can occur if user tries to run an older version of StatSimple after the database is upgraded. for serverKey, data in pairs (SSRealmData) do if type(serverKey) ~= "string" or not strfind (serverKey, ".%-%u%l") then -- not a valid serverKey - remove it SSRealmData[serverKey] = nil else -- aggressive checks to strip out any data that is the wrong type 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 -- database maintenance 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-Simple/StatSimple.lua $", "$Rev: 4840 $")