533 lines
20 KiB
Lua
533 lines
20 KiB
Lua
--[[
|
|
Auctioneer - iLevel Standard Deviation Statistics module
|
|
Version: 5.7.4568 (KillerKoala)
|
|
Revision: $Id: iLevel.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", "iLevel"
|
|
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 select,next,pairs,ipairs,type,unpack,wipe = select,next,pairs,ipairs,type,unpack,wipe
|
|
local tonumber,tostring,strsplit,strjoin = tonumber,tostring,strsplit,strjoin
|
|
local floor,abs,max = floor,abs,max
|
|
local concat = table.concat
|
|
local strmatch = strmatch
|
|
|
|
local iTypes = AucAdvanced.Const.InvTypes
|
|
local GetFaction = AucAdvanced.GetFaction
|
|
|
|
local KEEP_NUM_POINTS = 250
|
|
|
|
local ZValues = {.063, .126, .189, .253, .319, .385, .454, .525, .598, .675, .756, .842, .935, 1.037, 1.151, 1.282, 1.441, 1.646, 1.962, 20, 20000}
|
|
|
|
function lib.CommandHandler(command, ...)
|
|
local serverKey = GetFaction()
|
|
local _,_,keyText = AucAdvanced.SplitServerKey(serverKey)
|
|
if (command == "help") then
|
|
aucPrint(_TRANS('ILVL_Help_SlashHelp1') )--Help for Auctioneer Advanced - iLevel
|
|
local line = AucAdvanced.Config.GetCommandLead(libType, libName)
|
|
aucPrint(line, "help}} - ".._TRANS('ILVL_Help_SlashHelp2') ) -- this iLevel help
|
|
aucPrint(line, "clear}} - ".._TRANS('ILVL_Help_SlashHelp3'):format(keyText) ) --clear current %s iLevel price database
|
|
elseif (command ==_TRANS( 'clear') ) then
|
|
lib.ClearData(serverKey)
|
|
end
|
|
end
|
|
|
|
function lib.Processor(callbackType, ...)
|
|
if (callbackType == "tooltip") then
|
|
lib.ProcessTooltip(...)
|
|
elseif (callbackType == "config") then
|
|
if private.SetupConfigGui then -- only call it once
|
|
private.SetupConfigGui(...)
|
|
end
|
|
elseif (callbackType == "scanstats") then
|
|
private.ResetCache()
|
|
private.RepackStats()
|
|
end
|
|
end
|
|
lib.Processors = {}
|
|
function lib.Processors.tooltip(callbackType, ...)
|
|
lib.ProcessTooltip(...)
|
|
end
|
|
function lib.Processors.config(callbackType, ...)
|
|
if private.SetupConfigGui then -- only call it once
|
|
private.SetupConfigGui(...)
|
|
end
|
|
end
|
|
function lib.Processors.scanstats(callbackType, ...)
|
|
private.ResetCache()
|
|
private.RepackStats()
|
|
end
|
|
|
|
|
|
|
|
lib.ScanProcessors = {}
|
|
function lib.ScanProcessors.create(operation, itemData, oldData)
|
|
if not get("stat.ilevel.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
|
|
if (itemData.stackSize > 1) then
|
|
buyout = buyout.."/"..itemData.stackSize
|
|
end
|
|
|
|
-- Get the signature of this item and find it's stats.
|
|
local iLevel, quality, equipPos = itemData.itemLevel, itemData.quality, itemData.equipPos
|
|
if quality < 1 then return end
|
|
if not equipPos then return end
|
|
if equipPos < 1 then return end
|
|
local itemSig = ("%d:%d"):format(equipPos, quality)
|
|
|
|
local serverKey = GetFaction()
|
|
local stats = private.GetUnpackedStats(serverKey, itemSig, true) -- read/write
|
|
if not stats[iLevel] then stats[iLevel] = {} end
|
|
local sz = #stats[iLevel]
|
|
stats[iLevel][sz+1] = buyout
|
|
end
|
|
|
|
local BellCurve = AucAdvanced.API.GenerateBellCurve();
|
|
-----------------------------------------------------------------------------------
|
|
-- The PDF for standard deviation data, standard bell curve
|
|
-----------------------------------------------------------------------------------
|
|
function lib.GetItemPDF(hyperlink, serverKey)
|
|
if not get("stat.ilevel.enable") then return end
|
|
-- Get the data
|
|
local average, mean, _, stddev, variance, count, confidence = lib.GetPrice(hyperlink, serverKey)
|
|
|
|
if not (average and stddev) or average == 0 or stddev == 0 then
|
|
return nil; -- No data, cannot determine pricing
|
|
end
|
|
|
|
local lower, upper = average - 3 * stddev, average + 3 * stddev;
|
|
|
|
-- Build the PDF based on standard deviation & average
|
|
BellCurve:SetParameters(average, stddev);
|
|
return BellCurve, lower, upper; -- This has a __call metamethod so it's ok
|
|
end
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
function private.GetCfromZ(Z)
|
|
--C = 0.05*i
|
|
if (not Z) then
|
|
return .05
|
|
end
|
|
if (Z > 10) then
|
|
return .99
|
|
end
|
|
local i = 1
|
|
while Z > ZValues[i] do
|
|
i = i + 1
|
|
end
|
|
if i == 1 then
|
|
return .05
|
|
else
|
|
i = i - 1 + ((Z - ZValues[i-1]) / (ZValues[i] - ZValues[i-1]))
|
|
return i*0.05
|
|
end
|
|
end
|
|
|
|
local weakmeta = {__mode="kv"}
|
|
local pricecache = setmetatable({}, weakmeta)
|
|
function private.ResetCache()
|
|
wipe(pricecache)
|
|
end
|
|
|
|
local datapoints_price = {} -- used temporarily in .GetPrice() to avoid unpacking strings multiple times
|
|
local datapoints_stack = {}
|
|
|
|
function lib.GetPrice(hyperlink, serverKey)
|
|
if not get("stat.ilevel.enable") then return end
|
|
local itemSig, iLevel = private.GetItemDetail(hyperlink)
|
|
if not itemSig then return end
|
|
if not serverKey then serverKey = GetFaction() end
|
|
|
|
local average, mean, stdev, variance, count, confidence
|
|
|
|
local cacheSig = serverKey..itemSig..";"..iLevel
|
|
if pricecache[cacheSig] then
|
|
average, mean, stdev, variance, count, confidence = unpack(pricecache[cacheSig], 1, 6)
|
|
return average, mean, false, stdev, variance, count, confidence
|
|
end
|
|
|
|
local stats = private.GetUnpackedStats(serverKey, itemSig) -- read only
|
|
if not stats[iLevel] then return end
|
|
|
|
count = #stats[iLevel]
|
|
if (count < 1) then return end
|
|
|
|
local total, number = 0, 0
|
|
for i = 1, count do
|
|
local price, stack = strsplit("/", stats[iLevel][i])
|
|
price = tonumber(price) or 0
|
|
stack = tonumber(stack) or 1
|
|
if (stack < 1) then stack = 1 end
|
|
datapoints_price[i] = price
|
|
datapoints_stack[i] = stack
|
|
total = total + price
|
|
number = number + stack
|
|
end
|
|
mean = total / number
|
|
|
|
if (count < 2) then return 0,0,0, mean, count end
|
|
|
|
variance = 0
|
|
for i = 1, count do
|
|
variance = variance + ((mean - datapoints_price[i]/datapoints_stack[i]) ^ 2);
|
|
end
|
|
|
|
variance = variance / count;
|
|
stdev = variance ^ 0.5
|
|
|
|
local deviation = 1.5 * stdev
|
|
total = 0 -- recomputing with only data within deviation
|
|
number = 0
|
|
|
|
for i = 1, count do
|
|
local price,stack = datapoints_price[i], datapoints_stack[i]
|
|
if abs((price/stack) - mean) < deviation then
|
|
total = total + price
|
|
number = number + stack
|
|
end
|
|
end
|
|
|
|
confidence = .01
|
|
if (number > 0) then -- number<1 will happen if we have e.g. two big clusters: one at 1g and one at 10g
|
|
average = total / number
|
|
confidence = (.15*average)*(number^0.5)/(stdev)
|
|
confidence = private.GetCfromZ(confidence)
|
|
end
|
|
pricecache[cacheSig] = {average, mean, stdev, variance, count, confidence}
|
|
return average, mean, false, stdev, variance, count, confidence
|
|
end
|
|
|
|
function lib.GetPriceColumns()
|
|
return "Average", "Mean", false, "Std Deviation", "Variance", "Count", "Confidence"
|
|
end
|
|
|
|
local array = {}
|
|
function lib.GetPriceArray(hyperlink, serverKey)
|
|
if not get("stat.ilevel.enable") then return end
|
|
-- Clean out the old array
|
|
wipe(array)
|
|
|
|
-- Get our statistics
|
|
local average, mean, _, stdev, variance, count, confidence = lib.GetPrice(hyperlink, serverKey)
|
|
|
|
-- These 3 are the ones that most algorithms will look for
|
|
array.price = average or mean
|
|
array.seen = 0
|
|
array.confidence = confidence
|
|
-- This is additional data
|
|
array.normalized = average
|
|
array.mean = mean
|
|
array.deviation = stdev
|
|
array.variance = variance
|
|
array.processed = count
|
|
|
|
-- Return a temporary array. Data in this array is
|
|
-- only valid until this function is called again.
|
|
return array
|
|
end
|
|
|
|
function private.SetupConfigGui(gui)
|
|
private.SetupConfigGui = nil
|
|
local id = gui:AddTab(lib.libName, lib.libType.." Modules")
|
|
--gui:MakeScrollable(id)
|
|
|
|
gui:AddHelp(id, "what ilevel stats",
|
|
_TRANS('ILVL_Help_WhatIlevelStats') ,--What are ilevel stats?
|
|
_TRANS('ILVL_Help_WhatIlevelStatsAnswer') )--ilevel stats are the numbers that are generated by the iLevel module consisting of a filtered Standard Deviation calculation of item cost.
|
|
|
|
gui:AddHelp(id, "filtered ilevel",
|
|
_TRANS('ILVL_Help_WhatFiltered') ,--What do you mean filtered?
|
|
_TRANS('ILVL_Help_WhatFilteredAnswer') )--Items outside a (1.5*Standard) variance are ignored and assumed to be wrongly priced when calculating the deviation.
|
|
|
|
--all options in here will be duplicated in the tooltip frame
|
|
function private.addTooltipControls(id)
|
|
gui:AddHelp(id, "what standard deviation",
|
|
_TRANS('ILVL_Help_WhatStdDev') ,--What is a Standard Deviation calculation?
|
|
_TRANS('ILVL_Help_WhatStdDevAnswer') )--In short terms, it is a distance to mean average calculation.
|
|
|
|
gui:AddHelp(id, "what normalized",
|
|
_TRANS('ILVL_Help_WhatNormalized') ,--What is the Normalized calculation?
|
|
_TRANS('ILVL_Help_WhatNormalizedAnswer') )--In short terms again, it is the average of those values determined within the standard deviation variance calculation.
|
|
|
|
gui:AddHelp(id, "what confidence",
|
|
_TRANS('ILVL_Help_WhatConfidence') ,--What does confidence mean?
|
|
_TRANS('ILVL_Help_WhatConfidenceAnswer') )--Confidence is a value between 0 and 1 that determines the strength of the calculations (higher the better).
|
|
|
|
gui:AddHelp(id, "why multiply stack size ilevel",
|
|
_TRANS('ILVL_Help_WhyStackSize') ,--Why have the option to multiply by stack size?
|
|
_TRANS('ILVL_Help_WhyStackSizeAnswer') )--The original Stat-ilevel multiplied by the stack size of the item, but some like dealing on a per-item basis.
|
|
|
|
gui:AddControl(id, "Header", 0, _TRANS('ILVL_Interface_IlevelOptions') )--ilevel options
|
|
gui:AddControl(id, "Note", 0, 1, nil, nil, " ")
|
|
gui:AddControl(id, "Checkbox", 0, 1, "stat.ilevel.enable", _TRANS('ILVL_Interface_EnableILevelStats') )--Enable iLevel Stats
|
|
gui:AddTip(id, _TRANS('ILVL_HelpTooltip_EnableILevelStats') )--Allow iLevel to gather and return price data
|
|
gui:AddControl(id, "Note", 0, 1, nil, nil, " ")
|
|
|
|
gui:AddControl(id, "Checkbox", 0, 4, "stat.ilevel.tooltip", _TRANS('ILVL_Interface_ShowiLevel') )--Show iLevel stats in the tooltips?
|
|
gui:AddTip(id, _TRANS('ILVL_HelpTooltip_ShowiLevel') )--Toggle display of stats from the iLevel module on or off
|
|
gui:AddControl(id, "Checkbox", 0, 6, "stat.ilevel.mean", _TRANS('ILVL_Interface_DisplayMean') )--Display Mean
|
|
gui:AddTip(id, _TRANS('ILVL_HelpTooltip_DisplayMean') )--Toggle display of 'Mean' calculation in tooltips on or off
|
|
gui:AddControl(id, "Checkbox", 0, 6, "stat.ilevel.normal", _TRANS('ILVL_Interface_DisplayNormalized') )--Display Normalized'
|
|
gui:AddTip(id, _TRANS('ILVL_HelpTooltip_DisplayNormalized') )--Toggle display of \'Normalized\' calculation in tooltips on or off
|
|
gui:AddControl(id, "Checkbox", 0, 6, "stat.ilevel.stdev", _TRANS('ILVL_Interface_DisplayStdDeviation') )--Display Standard Deviation
|
|
gui:AddTip(id, _TRANS('ILVL_HelpTooltip_DisplayStdDeviation') )--Toggle display of \'Standard Deviation\' calculation in tooltips on or off
|
|
gui:AddControl(id, "Checkbox", 0, 6, "stat.ilevel.confid", _TRANS('ILVL_Interface_DisplayConfidence') )--Display Confidence
|
|
gui:AddTip(id, _TRANS('ILVL_HelpTooltip_DisplayConfidence') )--Toggle display of \'Confidence\' calculation in tooltips on or off
|
|
gui:AddControl(id, "Note", 0, 1, nil, nil, " ")
|
|
gui:AddControl(id, "Checkbox", 0, 4, "stat.ilevel.quantmul", _TRANS('ILVL_Interface_MultiplyStack') )--Multiply by Stack Size
|
|
gui:AddTip(id, _TRANS('ILVL_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 Auctioneer 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
|
|
|
|
function lib.ProcessTooltip(tooltip, name, hyperlink, quality, quantity, cost, ...)
|
|
if not get("stat.ilevel.tooltip") then return end
|
|
|
|
if not quantity or quantity < 1 then quantity = 1 end
|
|
if not get("stat.ilevel.quantmul") then quantity = 1 end
|
|
local average, mean, _, stdev, var, count, confidence = lib.GetPrice(hyperlink)
|
|
|
|
if (mean and mean > 0) then
|
|
tooltip:SetColor(0.3, 0.9, 0.8)
|
|
|
|
tooltip:AddLine(_TRANS('ILVL_Tooltip_iLevelPrices'):format(count) )--iLevel prices (%s points):
|
|
|
|
if get("stat.ilevel.mean") then
|
|
tooltip:AddLine(" ".._TRANS('ILVL_Tooltip_MeanPrice') , mean*quantity)--Mean price
|
|
end
|
|
if (average and average > 0) then
|
|
if get("stat.ilevel.normal") then
|
|
tooltip:AddLine(" ".._TRANS('ILVL_Tooltip_Normalized') , average*quantity)--Normalized
|
|
if (quantity > 1) then
|
|
tooltip:AddLine(" ".._TRANS('ILVL_Tooltip_Individually') , average)--(or individually)
|
|
end
|
|
end
|
|
if get("stat.ilevel.stdev") then
|
|
tooltip:AddLine(" ".._TRANS('ILVL_Tooltip_StdDeviation') , stdev*quantity)--Std Deviation
|
|
if (quantity > 1) then
|
|
tooltip:AddLine(" ".._TRANS('ILVL_Tooltip_Individually') , stdev)--(or individually)
|
|
end
|
|
|
|
end
|
|
if get("stat.ilevel.confid") then
|
|
tooltip:AddLine(" ".._TRANS('ILVL_Tooltip_Confidence'):format((floor(confidence*1000))/1000) )--Confidence: %s
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function lib.OnLoad(addon)
|
|
default("stat.ilevel.tooltip", false)
|
|
default("stat.ilevel.mean", false)
|
|
default("stat.ilevel.normal", false)
|
|
default("stat.ilevel.stdev", true)
|
|
default("stat.ilevel.confid", true)
|
|
default("stat.ilevel.quantmul", true)
|
|
default("stat.ilevel.enable", true)
|
|
if private.InitData then private.InitData() end
|
|
end
|
|
|
|
function lib.OnUnload()
|
|
private.RepackStats()
|
|
end
|
|
|
|
function lib.ClearItem(hyperlink, serverKey)
|
|
local itemSig, iLevel, equipPos, quality = private.GetItemDetail(hyperlink)
|
|
if not itemSig then return end
|
|
|
|
if not serverKey then serverKey = GetFaction() end
|
|
local stats = private.GetUnpackedStats(serverKey, itemSig, true)
|
|
if stats[iLevel] then
|
|
stats[iLevel] = nil
|
|
private.RepackStats()
|
|
private.ResetCache()
|
|
local _, _, keyText = AucAdvanced.SplitServerKey(serverKey)
|
|
aucPrint(_TRANS('ILVL_Interface_ClearingItems'):format(iLevel, quality, equipPos, keyText))--Stat-iLevel: clearing data for iLevel=%d/quality=%d/equip=%d items for {{%s}}
|
|
return
|
|
end
|
|
aucPrint(_TRANS('ILVL_Interface_ItemNotFound') )--Stat-iLevel: item is not in database
|
|
end
|
|
|
|
--[[ Database Management functions ]]--
|
|
|
|
local ILRealmData
|
|
local unpacked, updated = {}, {}
|
|
|
|
function private.InitData()
|
|
private.InitData = nil
|
|
if not AucAdvancedStat_iLevelData then AucAdvancedStat_iLevelData = {} end
|
|
ILRealmData = AucAdvancedStat_iLevelData
|
|
end
|
|
|
|
function lib.ClearData(serverKey)
|
|
serverKey = serverKey or GetFaction()
|
|
private.ResetCache()
|
|
if AucAdvanced.API.IsKeyword(serverKey, "ALL") then
|
|
wipe(ILRealmData)
|
|
wipe(unpacked)
|
|
wipe(updated)
|
|
aucPrint(_TRANS('ILVL_Help_SlashHelp5').." {{".._TRANS("ADV_Interface_AllRealms").."}}") --Clearing iLevel stats for // All realms
|
|
elseif ILRealmData[serverKey] then
|
|
ILRealmData[serverKey] = nil
|
|
unpacked[serverKey] = nil
|
|
-- 'updated' may contain orphaned entries - these will be cleaned up in next RepackStats
|
|
local _, _, keyText = AucAdvanced.SplitServerKey(serverKey)
|
|
aucPrint(_TRANS('ILVL_Help_SlashHelp5').." {{"..keyText.."}}") --Clearing iLevel stats for
|
|
end
|
|
end
|
|
|
|
--[[
|
|
itemSig, iLevel, equipPos, quality = GetItemDetail(hyperlink)
|
|
--]]
|
|
function private.GetItemDetail(hyperlink)
|
|
if type(hyperlink) ~= "string" then return end
|
|
if not hyperlink:match("item:%d") then return end
|
|
|
|
local _,_, quality, iLevel, _,_,_,_, equipPos = GetItemInfo(hyperlink)
|
|
if not quality or quality < 1 then return end
|
|
equipPos = tonumber(iTypes[equipPos])
|
|
if not equipPos or equipPos < 1 then return end
|
|
local itemSig = ("%d:%d"):format(equipPos, quality)
|
|
|
|
return itemSig, iLevel, equipPos, quality
|
|
end
|
|
|
|
--[[
|
|
stats = GetUnpackedStats (serverKey, itemSig, writing)
|
|
Obtain a cached data table for itemSig in serverKey's data.
|
|
Set writing to true if you intend to change the data
|
|
Caution: if you set 'writing' to true, RepackStats() must be called before the end of the session to save the changes
|
|
--]]
|
|
function private.GetUnpackedStats(serverKey, itemSig, writing)
|
|
local stats = unpacked[serverKey] and unpacked[serverKey][itemSig]
|
|
if stats then
|
|
if writing then
|
|
updated[stats] = true
|
|
end
|
|
return stats
|
|
end
|
|
|
|
local realmdata = ILRealmData[serverKey]
|
|
if not realmdata then
|
|
if not AucAdvanced.SplitServerKey(serverKey) then
|
|
error("Invalid serverKey passed to Stat-iLevel")
|
|
end
|
|
realmdata = {}
|
|
ILRealmData[serverKey] = realmdata
|
|
end
|
|
|
|
stats = private.UnpackStats(realmdata, itemSig)
|
|
|
|
if not unpacked[serverKey] then unpacked[serverKey] = {} end
|
|
unpacked[serverKey][itemSig] = stats
|
|
if writing then
|
|
updated[stats] = true
|
|
end
|
|
|
|
return stats
|
|
end
|
|
|
|
--[[
|
|
RepackStats()
|
|
Write any changed tables in the unpacked cache back to ILRealmData
|
|
--]]
|
|
function private.RepackStats()
|
|
if not next(updated) then return end -- bail out if no updated entries
|
|
for serverKey, realmData in pairs(unpacked) do
|
|
for item, stats in pairs(realmData) do
|
|
if updated[stats] then
|
|
local packed = private.PackStats(stats)
|
|
if packed == "" then
|
|
ILRealmData[serverKey][item] = nil -- delete empty entries from the database
|
|
else
|
|
ILRealmData[serverKey][item] = packed
|
|
end
|
|
end
|
|
end
|
|
end
|
|
wipe(updated)
|
|
end
|
|
|
|
--[[ Subfunctions ]]--
|
|
|
|
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
|
|
local t= {strsplit(";", info)}
|
|
for k,v in ipairs(t) do
|
|
t[k] = tonumber(v) or v
|
|
end
|
|
data[property] = t
|
|
end
|
|
end
|
|
end
|
|
function private.UnpackStats(data, item)
|
|
local stats = {}
|
|
if (data and data[item]) then
|
|
private.UnpackStatIter(stats, strsplit(",", data[item]))
|
|
end
|
|
return stats
|
|
end
|
|
local tmp={}
|
|
function private.PackStats(data)
|
|
local ntmp=0
|
|
for property, info in pairs(data) do
|
|
ntmp=ntmp+1
|
|
local n = max(1, #info - KEEP_NUM_POINTS + 1)
|
|
tmp[ntmp] = property..":"..concat(info, ";", n)
|
|
end
|
|
return concat(tmp, ",", 1, ntmp)
|
|
end
|
|
|
|
AucAdvanced.RegisterRevision("$URL: http://svn.norganna.org/auctioneer/branches/5.9/Auc-Stat-iLevel/iLevel.lua $", "$Rev: 4840 $")
|