vanilla-wow-addons – Rev 1
?pathlinks?
--[[
Auctioneer Addon for World of Warcraft(tm).
Version: 3.9.0.1000 (Kangaroo)
Revision: $Id: AucStatistic.lua 972 2006-08-22 19:05:01Z mentalpower $
Auctioneer statistical functions.
Functions to calculate various forms of statistics from the auction data.
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.
]]
--Local function prototypes
local subtractPercent, addPercent, percentLessThan, getLowest, getMedian, getPercentile, getMeans, getItemSnapshotMedianBuyout, getItemHistoricalMedianBuyout, getUsableMedian, getCurrentBid, isBadResaleChoice, profitComparisonSort, roundDownTo95, findLowestAuctions, buildLowestCache, doLow, doMedian, doHSP, getBidBasedSellablePrice, getMarketPrice, getHSP, determinePrice, setScanLength, setScanAge, getScanLength, getScanAge
-- Subtracts/Adds given percentage from/to a value
function subtractPercent(value, percentLess) --function subtractPercent(value, percentLess)
return math.floor(value * ((100 - percentLess)/100));
end
function addPercent(value, percentMore)
return math.floor(value * ((100 + percentMore)/100));
end
-- returns the integer representation of the percent less value2 is from value1
-- example: value1=10, value2=7, percentLess=30
function percentLessThan(value1, value2)
if Auctioneer.Util.NullSafe(value1) > 0 and Auctioneer.Util.NullSafe(value2) < Auctioneer.Util.NullSafe(value1) then
return 100 - math.floor((100 * Auctioneer.Util.NullSafe(value2))/Auctioneer.Util.NullSafe(value1));
else
return 0;
end
end
function getLowest(valuesTable)
if (not valuesTable or table.getn(valuesTable) == 0) then
return nil, nil;
end
local tableSize = table.getn(valuesTable);
local lowest = tonumber(valuesTable[1]) or 0;
local second = nil
if (tableSize > 1) then
for i=2, tableSize do
second = tonumber(valuesTable[i]) or 0;
if (second > lowest) then
return lowest, second;
end
end
end
return lowest, nil;
end
-- Returns the median value of a given table one-dimentional table
function getMedian(valuesTable)
return getPercentile(valuesTable, 0.5)
end
-- Return weighted average percentile such that returned value
-- is larger than or equal to (100*pct)% of the table values
-- 0 <= pct <= 1
function getPercentile(valuesTable, pct)
if (type(valuesTable) ~= "table") or (not tonumber(pct)) then
return nil -- make valuesTable a required table argument
end
pct = math.min(math.max(pct, 0), 1) -- Make sure 0 <= pct <= 1
local _percentile = function(sortedTable, p, first, last)
local f = (last - first) * p + first
local i1, i2 = math.floor(f), math.ceil(f)
f = f - i1
return sortedTable[i1] * (1 - f) + sortedTable[i2] * f
end
local tableSize = table.getn(valuesTable) or 0
if (tableSize == 0) then
return 0, 0; -- if there is an empty table, returns median = 0, count = 0
elseif (tableSize == 1) then
return tonumber(valuesTable[1]), 1
end
-- The following calculations require a sorted table
table.sort(valuesTable)
-- Skip IQR calculations if table is too small to have outliers
if tableSize <= 4 then
return _percentile(valuesTable, pct, 1, tableSize), tableSize
end
-- REWORK by Karavirs to use IQR*1.5 to ignore outliers
-- q1 is median 1st quartile q2 is median of set q3 is median of 3rd quartile iqr is q3 - q1
local q1 = _percentile(valuesTable, 0.25, 1, tableSize)
local q3 = _percentile(valuesTable, 0.75, 1, tableSize)
assert(q3 >= q1)
local iqr = (q3 - q1) * 1.5
local iqlow, iqhigh = q1 - iqr, q3 + iqr
-- Find first and last index to include in median calculation
local first, last = 1, tableSize
-- Skip low outliers
while valuesTable[first] < iqlow do
first = first + 1
end
-- Skip high outliers
while valuesTable[last] > iqhigh do
last = last - 1
end
assert(last >= first)
return _percentile(valuesTable, pct, first, last), last - first + 1
end
-- Return all of the averages for an item
-- Returns: avgMin,avgBuy,avgBid,bidPct,buyPct,avgQty,aCount
function getMeans(itemKey, from)
local auctionPriceItem = Auctioneer.Core.GetAuctionPriceItem(itemKey, from);
if (not auctionPriceItem.data) then
EnhTooltip.DebugPrint("Error, GetAuctionPriceItem", itemKey, from, "returns", auctionPriceItem);
end
local aCount,minCount,minPrice,bidCount,bidPrice,buyCount,buyPrice = Auctioneer.Core.GetAuctionPrices(auctionPriceItem.data);
local avgMin,avgBuy,avgBid,bidPct,buyPct,avgQty;
if aCount > 0 then
avgQty = math.floor(minCount / aCount);
avgMin = math.floor(minPrice / minCount);
bidPct = math.floor(bidCount / minCount * 100);
buyPct = math.floor(buyCount / minCount * 100);
avgBid = 0;
if (bidCount > 0) then
avgBid = math.floor(bidPrice / bidCount);
end
avgBuy = 0;
if (buyCount > 0) then
avgBuy = math.floor(buyPrice / buyCount);
end
end
return avgMin,avgBuy,avgBid,bidPct,buyPct,avgQty,aCount;
end
-- Returns the current snapshot median for an item
function getItemSnapshotMedianBuyout(itemKey, auctKey, buyoutPrices)
if (not auctKey) then auctKey = Auctioneer.Util.GetAuctionKey() end
local stat, count;
if (AuctionConfig.stats and AuctionConfig.stats.snapmed and AuctionConfig.stats.snapmed[auctKey]) then
stat = AuctionConfig.stats.snapmed[auctKey][itemKey];
count = AuctionConfig.stats.snapcount[auctKey][itemKey];
end
if (not stat) or (not count) then
if (not buyoutPrices) then
local sbuy = Auctioneer.Core.GetSnapshotInfo(auctKey, itemKey);
if (sbuy) then
buyoutPrices = sbuy.buyoutPrices;
end
end
if (buyoutPrices) then
stat, count = getMedian(buyoutPrices);
else
stat, count = 0, 0;
end
-- save median to the savedvariablesfile
Auctioneer.Storage.SetSnapMed(auctKey, itemKey, stat, count)
end
return stat, count;
end
-- Returns the historical median for an item
function getItemHistoricalMedianBuyout(itemKey, auctKey, buyoutHistoryTable)
if (not auctKey) then auctKey = Auctioneer.Util.GetAuctionKey() end
local stat, count;
if (AuctionConfig.stats and AuctionConfig.stats.histmed and AuctionConfig.stats.histmed[auctKey]) then
stat = AuctionConfig.stats.histmed[auctKey][itemKey];
count = AuctionConfig.stats.histcount[auctKey][itemKey];
end
if (not stat) or (not count) then
if (not buyoutHistoryTable) then
buyoutHistoryTable = Auctioneer.Core.GetAuctionBuyoutHistory(itemKey, auctKey);
end
if (buyoutHistoryTable) then
stat, count = getMedian(buyoutHistoryTable);
else
stat, count = 0, 0;
end
-- save median to the savedvariablesfile
Auctioneer.Storage.SetHistMed(auctKey, itemKey, stat, count);
end
return stat, count;
end
-- this function returns the most accurate median possible,
-- if an accurate median cannot be obtained based on min seen counts then nil is returned
function getUsableMedian(itemKey, realm, buyoutPrices)
if not realm then
realm = Auctioneer.Util.GetAuctionKey();
end
--get snapshot median
local snapshotMedian, snapCount = getItemSnapshotMedianBuyout(itemKey, realm, buyoutPrices)
--get history median
local historyMedian, histCount = getItemHistoricalMedianBuyout(itemKey, realm);
local median, count
if (histCount >= Auctioneer.Core.Constants.MinBuyoutSeenCount) then
median, count = historyMedian, histCount;
end
if (snapCount >= Auctioneer.Core.Constants.MinBuyoutSeenCount) then
if (histCount < snapCount) then
-- History median isn't shown in tooltip if histCount < snapCount so use snap median in this case
median, count = snapshotMedian, snapCount;
elseif (snapshotMedian < 1.2 * historyMedian) then
median, count = snapshotMedian, snapCount;
end
end
return median, count;
end
-- Returns the current bid on an auction
function getCurrentBid(auctionSignature)
local x,x,x, x, x,min,x,_ = Auctioneer.Core.GetItemSignature(auctionSignature);
local auctKey = Auctioneer.Util.GetAuctionKey();
local itemCat = Auctioneer.Util.GetCatForSig(auctionSignature);
local snap = Auctioneer.Core.GetSnapshot(auctKey, itemCat, auctionSignature);
if (not snap) then return 0 end
local currentBid = tonumber(snap.bidamount) or 0;
if currentBid == 0 then currentBid = min end
return currentBid;
end
-- This filter will return true if an auction is a bad choice for reselling
function isBadResaleChoice(auctSig, auctKey)
if (not auctKey) then auctKey = Auctioneer.Util.GetAuctionKey() end
local isBadChoice = false;
local id,rprop,enchant, name, count,min,buyout,uniq = Auctioneer.Core.GetItemSignature(auctSig);
local itemKey = id..":"..rprop..":"..enchant;
local itemCat = Auctioneer.Util.GetCatForKey(itemKey);
local auctionItem = Auctioneer.Core.GetSnapshot(auctKey, itemCat, auctSig);
local auctionPriceItem = Auctioneer.Core.GetAuctionPriceItem(itemKey, auctKey);
local aCount,minCount,minPrice,bidCount,bidPrice,buyCount,buyPrice = Auctioneer.Core.GetAuctionPrices(auctionPriceItem.data);
local bidPercent = math.floor(bidCount / minCount * 100);
if (auctionItem) then
local itemLevel = tonumber(auctionItem.level);
local itemQuality = tonumber(auctionItem.quality);
-- bad choice conditions
if Auctioneer.Core.Constants.BidBasedCategories[auctionItem.category] and bidPercent < Auctioneer.Core.Constants.MinBidPercent then
isBadChoice = true; -- bidbased items should have a minimum bid percent
elseif (itemLevel >= 50 and itemQuality == Auctioneer.Core.Constants.Quality.Uncommon and bidPercent < Auctioneer.Core.Constants.MinBidPercent) then
isBadChoice = true; -- level 50 and greater greens that do not have bids do not sell well
elseif auctionItem.owner == UnitName("player") or auctionItem.highBidder then
isBadChoice = true; -- don't display auctions that we own, or are high bidder on
elseif itemQuality == Auctioneer.Core.Constants.Quality.Poor then
isBadChoice = true; -- gray items are never a good choice
end
end
return isBadChoice;
end
-- method to pass to table.sort() that sorts auctions by profit descending
function profitComparisonSort(a, b)
local aid,arprop,aenchant, aName, aCount, x, aBuyout, x = Auctioneer.Core.GetItemSignature(a.signature);
local bid,brprop,benchant, bName, bCount, x, bBuyout, x = Auctioneer.Core.GetItemSignature(b.signature);
local aItemKey = aid .. ":" .. arprop..":"..aenchant;
local bItemKey = bid .. ":" .. brprop..":"..benchant;
local realm = Auctioneer.Util.GetAuctionKey()
local aProfit = (getHSP(aItemKey, realm) * aCount) - aBuyout;
local bProfit = (getHSP(bItemKey, realm) * bCount) - bBuyout;
return (aProfit > bProfit)
end
-- this function takes copper and rounds to 5 silver below the the nearest gold if it is less than 15 silver above of an even gold
-- example: this function changes 1g9s to 95s
-- example: 1.5g will be unchanged and remain 1.5g
function roundDownTo95(copper)
local g,s,c = EnhTooltip.GetGSC(copper);
if g > 0 and s < 10 then
return (copper - ((s + 5) * 100)); -- subtract enough copper to round to 95 silver
end
return copper;
end
-- given an item name, find the lowest price for that item in the current AHSnapshot
-- if the item does not exist in the snapshot or the snapshot does not exist
-- a nil is returned.
function findLowestAuctions(itemKey, auctKey)
local itemID, itemRand, enchant = Auctioneer.Util.BreakItemKey(itemKey);
if (itemID == nil) then return nil; end
if (not auctKey) then
auctKey = Auctioneer.Util.GetAuctionKey();
end
if not (Auctioneer_Lowests and Auctioneer_Lowests[auctKey]) then buildLowestCache(auctKey) end
local lowKey = itemID..":"..itemRand;
local itemCat = nil;
local lowSig = nil;
local nextSig = nil;
local lowestPrice = 0;
local nextLowest = 0;
local lows = Auctioneer_Lowests[auctKey][lowKey];
if (lows) then
lowSig = lows.lowSig;
nextSig = lows.nextSig;
lowestPrice = lows.lowestPrice or 0;
nextLowest = lows.nextLowest or 0;
itemCat = lows.cat;
end
return lowSig, lowestPrice, nextSig, nextLowest, itemCat;
end
function buildLowestCache(auctKey)
if (Auctioneer_Lowests == nil) then Auctioneer_Lowests = {}; end
Auctioneer_Lowests[auctKey] = {}
local id, rprop, enchant, name, count, min, buyout, uniq, lowKey, priceForOne, lowests;
if (AuctionConfig and AuctionConfig.snap and AuctionConfig.snap[auctKey]) then
for itemCat, cData in pairs(AuctionConfig.snap[auctKey]) do
for sig, sData in pairs(cData) do
id,rprop,enchant, name, count,min,buyout,uniq = Auctioneer.Core.GetItemSignature(sig);
lowKey = id..":"..rprop;
if (not Auctioneer_Lowests[auctKey][lowKey]) then Auctioneer_Lowests[auctKey][lowKey] = {cat = itemCat} end
lowests = Auctioneer_Lowests[auctKey][lowKey]
if (Auctioneer.Util.NullSafe(buyout) > 0) then
priceForOne = Auctioneer.Util.PriceForOne(buyout, count)
if (lowests.lowestPrice == nil) or (priceForOne < lowests.lowestPrice) then
lowests.lowestPrice, lowests.nextLowest = priceForOne, lowests.lowestPrice
lowests.lowSig, lowests.nextSig = sig, lowests.lowSig
elseif (lowests.nextLowest == nil) or (priceForOne < lowests.nextLowest) then
lowests.nextLowest = priceForOne
lowests.nextSig = sig
end
end
end
end
end
end
-- execute the '/auctioneer low <itemName>' that returns the auction for an item with the lowest buyout
function doLow(link)
local auctKey = Auctioneer.Util.GetAuctionKey();
local items = Auctioneer.Util.GetItems(link);
local itemLinks = Auctioneer.Util.GetItemHyperlinks(link);
if (items) then
for pos,itemKey in pairs(items) do
local auctionSignature = findLowestAuctions(itemKey);
if (not auctionSignature) then
Auctioneer.Util.ChatPrint(string.format(_AUCT('FrmtNoauct'), itemLinks[pos]));
else
local itemCat = Auctioneer.Util.GetCatForKey(itemKey);
local auction = Auctioneer.Core.GetSnapshot(auctKey, itemCat, auctionSignature);
local x,x,x, x, count, x, buyout, x = Auctioneer.Core.GetItemSignature(auctionSignature);
Auctioneer.Util.ChatPrint(string.format(_AUCT('FrmtLowLine'), Auctioneer.Util.ColorTextWhite(count.."x")..auction.itemLink, EnhTooltip.GetTextGSC(buyout), Auctioneer.Util.ColorTextWhite(auction.owner), EnhTooltip.GetTextGSC(buyout / count), Auctioneer.Util.ColorTextWhite(percentLessThan(getUsableMedian(itemKey), buyout / count).."%")));
end
end
end
end
function doMedian(link)
local items = Auctioneer.Util.GetItems(link);
local itemLinks = Auctioneer.Util.GetItemHyperlinks(link);
if (items) then
for pos,itemKey in pairs(items) do
local median, count = getUsableMedian(itemKey);
if (not median) then
Auctioneer.Util.ChatPrint(string.format(_AUCT('FrmtMedianNoauct'), Auctioneer.Util.ColorTextWhite(itemName)));
else
if (not count) then count = 0 end
Auctioneer.Util.ChatPrint(string.format(_AUCT('FrmtMedianLine'), count, Auctioneer.Util.ColorTextWhite(itemName), EnhTooltip.GetTextGSC(median)));
end
end
end
end
function doHSP(link)
local items = Auctioneer.Util.GetItems(link);
local itemLinks = Auctioneer.Util.GetItemHyperlinks(link);
if (items) then
for pos,itemKey in pairs(items) do
local highestSellablePrice = getHSP(itemKey, Auctioneer.Util.GetAuctionKey());
Auctioneer.Util.ChatPrint(string.format(_AUCT('FrmtHspLine'), itemLinks[pos], EnhTooltip.GetTextGSC(Auctioneer.Util.NilSafeString(highestSellablePrice))));
end
end
end
function getBidBasedSellablePrice(itemKey,realm, avgMin,avgBuy,avgBid,bidPct,buyPct,avgQty,seenCount)
-- We can pass these values along if we have them.
if (seenCount == nil) then
avgMin,avgBuy,avgBid,bidPct,buyPct,avgQty,seenCount = getMeans(itemKey, realm);
end
local bidBasedSellPrice = 0;
local typicalBuyout = 0;
local medianBuyout = getUsableMedian(itemKey, realm);
if medianBuyout and avgBuy then
typicalBuyout = math.min(avgBuy, medianBuyout);
elseif medianBuyout then
typicalBuyout = medianBuyout;
else
typicalBuyout = avgBuy or 0;
end
if (avgBid) then
bidBasedSellPrice = math.floor((3*typicalBuyout + avgBid) / 4);
else
bidBasedSellPrice = typicalBuyout;
end
return bidBasedSellPrice;
end
-- returns the best market price - 0, if no market price could be calculated
function getMarketPrice(itemKey, realm, buyoutValues)
-- make sure to call this function with valid parameters! No check is being performed!
local buyoutMedian = Auctioneer.Util.NullSafe(getUsableMedian(itemKey, realm, buyoutValues))
local avgMin, avgBuy, avgBid, bidPct, buyPct, avgQty, meanCount = getMeans(itemKey, realm)
local commonBuyout = 0
-- assign the best common buyout
if buyoutMedian > 0 then
commonBuyout = buyoutMedian
elseif meanCount and meanCount > 0 then
-- if a usable median does not exist, use the average buyout instead
commonBuyout = avgBuy;
end
local playerMade, skill, level = Auctioneer.Core.IsPlayerMade(itemKey);
if Auctioneer.Core.Constants.BidBasedCategories[Auctioneer.Core.GetItemCategory(itemKey)] and not (playerMade and level < 250 and commonBuyout < 100000) then
-- returns bibasedSellablePrice for bidbaseditems, playermade items or if the buyoutprice is not present or less than 10g
return getBidBasedSellablePrice(itemKey,realm, avgMin,avgBuy,avgBid,bidPct,buyPct,avgQty,seenCount)
end
-- returns buyoutMedian, if present - returns avgBuy otherwise, if meanCount > 0 - returns 0 otherwise
return commonBuyout
end
-- Returns market information relating to the HighestSellablePrice for one of the given items.
-- If you use cached data it may be affected by buying/selling items.
HSPCOUNT = 0; CACHECOUNT = 0;
function getHSP(itemKey, realm, buyoutValues, itemCat)
if (itemKey == nil) then -- make itemKey a required parameter
EnhTooltip.DebugPrint("ERROR: Calling Auctioneer.Statistic.GetHSP(itemKey, realm) - Function requires valid itemKey.");
return nil;
end
if (realm == nil) then
EnhTooltip.DebugPrint("WARNING: Auctioneer.Statistic.GetHSP(itemKey, realm) - Defaulting to player realm.");
EnhTooltip.DebugPrint("This is only some debugging code. THIS IS NO BUG!");
realm = Auctioneer.Util.GetAuctionKey();
end
if (not Auctioneer_HSPCache) then Auctioneer_HSPCache = {}; end
CACHECOUNT = CACHECOUNT + 1;
if (not Auctioneer_HSPCache[realm]) then Auctioneer_HSPCache[realm] = {} end
local cached = Auctioneer_HSPCache[realm][itemKey];
if (cached) then
local cache = Auctioneer.Util.Split(cached, ";");
return tonumber(cache[1]), tonumber(cache[2]), tonumber(cache[3]), cache[4], tonumber(cache[5]), cache[6];
end
HSPCOUNT = HSPCOUNT + 1;
local highestSellablePrice = 0;
local warn = _AUCT('FrmtWarnNodata');
EnhTooltip.DebugPrint("Getting HSP, calling GetMarketPrice", itemKey, realm);
if (not buyoutValues) then
local sbuy = Auctioneer.Core.GetSnapshotInfo(realm, itemKey);
if sbuy then
buyoutValues = sbuy.buyoutPrices;
end
end
local marketPrice = getMarketPrice(itemKey, realm, buyoutValues);
-- Get our user-set pricing parameters
local lowestAllowedPercentBelowMarket = tonumber(Auctioneer.Command.GetFilterVal('pct-maxless'));
local discountLowPercent = tonumber(Auctioneer.Command.GetFilterVal('pct-underlow'));
local discountMarketPercent = tonumber(Auctioneer.Command.GetFilterVal('pct-undermkt'));
local discountNoCompetitionPercent = tonumber(Auctioneer.Command.GetFilterVal('pct-nocomp'));
local vendorSellMarkupPercent = tonumber(Auctioneer.Command.GetFilterVal('pct-markup'));
local x, histCount = getUsableMedian(itemKey, realm, buyoutValues);
histCount = Auctioneer.Util.NullSafe(histCount);
local id = Auctioneer.Util.BreakItemKey(itemKey);
-- Get the snapshot sigs of the two lowest auctions
local currentLowestSig = nil;
local currentLowestBuyout = nil;
local currentLowestCount = nil;
local nextLowestSig = nil;
local nextLowestBuyout = nil;
local nextLowestCount = nil;
local lowSig, lowPrice, nextSig, nextPrice, itemCat = findLowestAuctions(itemKey, realm);
if lowSig then
currentLowestSig = lowSig;
currentLowestBuyout = lowPrice;
nextLowestSig = nextSig;
nextLowestBuyout = nextPrice;
end
if (not itemCat) then itemCat = Auctioneer.Util.GetCatForKey(itemKey) end
local hsp, market, warn = determinePrice(id, realm, marketPrice, currentLowestBuyout, currentLowestSig, lowestAllowedPercentBelowMarket, discountLowPercent, discountMarketPercent, discountNoCompetitionPercent, vendorSellMarkupPercent, itemCat);
local nexthsp, x, nextwarn = determinePrice(id, realm, marketPrice, nextLowestBuyout, nextLowestSig, lowestAllowedPercentBelowMarket, discountLowPercent, discountMarketPercent, discountNoCompetitionPercent, vendorSellMarkupPercent, itemCat);
if (not hsp) then
EnhTooltip.DebugPrint("Unable to calc HSP for",id, realm, marketPrice, currentLowestBuyout, currentLowestSig);
hsp = 0;
warn = "";
end
if (not nexthsp) then nexthsp = 0; nextwarn = ""; end
EnhTooltip.DebugPrint("Auction data: ", hsp, histCount, market, warn, nexthsp, nextwarn);
local cache = string.format("%d;%d;%d;%s;%d;%s", hsp,histCount,market,warn, nexthsp,nextwarn);
Auctioneer_HSPCache[realm][itemKey] = cache;
return hsp, histCount, market, warn, nexthsp, nextwarn;
end
function determinePrice(id, realm, marketPrice, currentLowestBuyout, currentLowestSig, lowestAllowedPercentBelowMarket, discountLowPercent, discountMarketPercent, discountNoCompetitionPercent, vendorSellMarkupPercent, itemCat)
local warn, highestSellablePrice, lowestBuyoutPriceAllowed;
if marketPrice and marketPrice > 0 then
if currentLowestBuyout and currentLowestBuyout > 0 then
lowestBuyoutPriceAllowed = subtractPercent(marketPrice, lowestAllowedPercentBelowMarket);
if (not itemCat) then itemCat = Auctioneer.Util.GetCatForSig(currentLowestSig) end
-- since we don't want to decode the full data unless there's a chance it belongs to the player
-- do a substring search for the players name first.
-- For some reason AuctionConfig.snap[realm][itemCat][currentLowestSig] sometimes doesn't
-- exist, even if currentLowestBuyout is set. Added a check for this as a workaround, but
-- the real cause should probably be tracked down - Thorarin
local snap;
if (AuctionConfig.snap[realm][itemCat][currentLowestSig] and string.find(AuctionConfig.snap[realm][itemCat][currentLowestSig], UnitName("player"), 1, true)) then
snap = Auctioneer.Core.GetSnapshot(realm, itemCat, currentLowestSig);
end
if snap and snap.owner == UnitName("player") then
highestSellablePrice = currentLowestBuyout; -- If I am the lowest seller use same low price
warn = _AUCT('FrmtWarnMyprice');
elseif (currentLowestBuyout < lowestBuyoutPriceAllowed) then
highestSellablePrice = subtractPercent(marketPrice, discountMarketPercent);
warn = _AUCT('FrmtWarnToolow');
else
if (currentLowestBuyout > marketPrice) then
highestSellablePrice = subtractPercent(marketPrice, discountNoCompetitionPercent);
warn = _AUCT('FrmtWarnAbovemkt');
end
-- Account for negative discountNoCompetitionPercent values
if (currentLowestBuyout <= marketPrice or highestSellablePrice >= currentLowestBuyout) then
-- set highest price to "Discount low"
highestSellablePrice = subtractPercent(currentLowestBuyout, discountLowPercent);
warn = string.format(_AUCT('FrmtWarnUndercut'), discountLowPercent);
end
end
else -- no low buyout, use discount no competition
-- set highest price to "Discount no competition"
highestSellablePrice = subtractPercent(marketPrice, discountNoCompetitionPercent);
warn = _AUCT('FrmtWarnNocomp');
end
else -- no market
-- Note: urentLowestBuyout is nil, incase the realm is not the current player's realm
if currentLowestBuyout and currentLowestBuyout > 0 then
-- set highest price to "Discount low"
EnhTooltip.DebugPrint("Discount low case 2");
highestSellablePrice = subtractPercent(currentLowestBuyout, discountLowPercent);
warn = string.format(_AUCT('FrmtWarnUndercut'), discountLowPercent);
else
local baseData;
if (Informant) then baseData = Informant.GetItem(id) end
if (baseData and baseData.sell) then
-- use vendor prices if no auction data available
local vendorSell = Auctioneer.Util.NullSafe(baseData.sell); -- use vendor prices
highestSellablePrice = addPercent(vendorSell, vendorSellMarkupPercent);
warn = string.format(_AUCT('FrmtWarnMarkup'), vendorSellMarkupPercent);
end
end
end
return highestSellablePrice, marketPrice, warn;
end
-------------------------------------------------------------------------------
-- Scan Statistic Functions
-------------------------------------------------------------------------------
function setScanLength(startTime, endTime)
--Make both parameters required ones and make sure they're numbers
if (not (tonumber(startTime) and tonumber(endTime))) then
return
end
--Initialize our data structure
if (not AuctionConfig.scanStats) then
AuctionConfig.scanStats = {}
end
AuctionConfig.scanStats.lastScanLength = (endTime - startTime)
end
function setScanAge(endTime)
--Make our parameter a required one and make sure its a number
endTime = tonumber(endTime)
if (not endTime) then
return
end
--Initialize our data structure
if (not AuctionConfig.scanStats) then
AuctionConfig.scanStats = {}
end
AuctionConfig.scanStats.lastScanAge = endTime
end
function getScanLength()
if (AuctionConfig and AuctionConfig.scanStats) then
return AuctionConfig.scanStats.lastScanLength
end
end
function getScanAge()
if (AuctionConfig and AuctionConfig.scanStats and tonumber(AuctionConfig.scanStats.lastScanAge)) then
return time() - AuctionConfig.scanStats.lastScanAge
end
end
Auctioneer.Statistic = {
SubtractPercent = subtractPercent,
AddPercent = addPercent,
PercentLessThan = percentLessThan,
GetLowest = getLowest,
GetMedian = getMedian,
GetPercentile = getPercentile,
GetMeans = getMeans,
GetItemSnapshotMedianBuyout = getItemSnapshotMedianBuyout,
GetSnapMedian = getItemSnapshotMedianBuyout,
GetItemHistoricalMedianBuyout = getItemHistoricalMedianBuyout,
GetHistMedian = getItemHistoricalMedianBuyout,
GetUsableMedian = getUsableMedian,
GetCurrentBid = getCurrentBid,
IsBadResaleChoice = isBadResaleChoice,
ProfitComparisonSort = profitComparisonSort,
RoundDownTo95 = roundDownTo95,
FindLowestAuctions = findLowestAuctions,
BuildLowestCache = buildLowestCache,
DoLow = doLow,
DoMedian = doMedian,
DoHSP = doHSP,
GetBidBasedSellablePrice = getBidBasedSellablePrice,
GetMarketPrice = getMarketPrice,
GetHSP = getHSP,
DeterminePrice = determinePrice,
SetScanLength = setScanLength,
SetScanAge = setScanAge,
GetScanLength = getScanLength,
GetScanAge = getScanAge,
}