diff --git a/stat_average.lua b/stat_average.lua index b4845ad..629ccbb 100644 --- a/stat_average.lua +++ b/stat_average.lua @@ -1,4 +1,4 @@ -private, public = {}, {} +local private, public = {}, {} Aux.stat_average = public private.PUSH_INTERVAL = 57600 @@ -19,171 +19,60 @@ function private.process_auction(auction_info) end local item_record = private.load_data()[get_item_key(auction_info)] or { - auction_count = 0, - unit_count = 0, + daily_auction_count = 0, + daily_unit_count = 0, accumulated_buyout_price = 0, + seen_days = 0, + EMA3 = 0, + EMA7 = 0, + EMA14 = 0, + average_min_buyout = 0, } - - item_record.auction_count = item_record.auction_count + 1 - item_record.unit_count = item_record.unit_count + auction_info.count + item_record.daily_auction_count = item_record.daily_auction_count + 1 + item_record.daily_unit_count = item_record.daily_unit_count + auction_info.count item_record.accumulated_buyout_price = item_record.accumulated_buyout_price + auction_info.buyout_price - - - --[[ data = { - [1] = total buyout, - [2] = seen count, - [3] = today's minimum buyout, - [4] = auctions count, (only recorded if different from seen count) - }--]] - - - if data0 then - local aucs = data0[4] - if aucs then - data0[4] = aucs + 1 - elseif stack > 1 then - -- no recorded auctions count, so auctions count must have been equal to seen count up to this point - data0[4] = data0[2] + 1 - end - local mbo = data0[3] - if mbo == 0 or buyoutper < mbo then - data0[3] = buyoutper - end - data0[2] = data0[2] + stack - data0[1] = data0[1] + buyout - end - - if dataP then - local aucs = dataP[4] - if aucs then - dataP[4] = aucs + 1 - elseif stack > 1 then - -- no recorded auctions count, so auctions count must have been equal to seen count up to this point - dataP[4] = dataP[2] + 1 - end - local mbo = dataP[3] - if mbo == 0 or buyoutper < mbo then - dataP[3] = buyoutper - end - dataP[2] = dataP[2] + stack - dataP[1] = dataP[1] + buyout - end - - private.WriteItemData(serverKey, storeID, storeProperty) + item_record.daily_min_buyout_price = item_record.daily_min_buyout_price and min(item_record.daily_min_buyout_price, auction_info.buyout_price / auction_info.count) or auction_info.buyout_price / auction_info.count end function private.push_data() - local realmdata = SSRealmData[serverKey] - if not realmdata then return end - local daily, means = realmdata.daily, realmdata.means - local lookupmeansdata, lookupmeansindex = {}, {} + local data = private.load_data() - for storeID, itemstring in pairs(daily) do - -- find the means data for this storeID, and build lookup tables to help cross-index - -- we leave the last (DATA_DIVIDER) level of the data as strings for now; later we will fully unpack only the ones we need - local itemstoremeans - if means[storeID] then - itemstoremeans = {strsplit(ITEM_DIVIDER, means[storeID])} - else - itemstoremeans = {} - end - for index, propertystring in ipairs(itemstoremeans) do - local prop, datastringmeans = strsplit(PROPERTY_DIVIDER, propertystring) - lookupmeansdata[prop] = datastringmeans - lookupmeansindex[prop] = index -- remember where we got datastringmeans from, so we can put the revised datastring back in the same place - end + for item_key, item_record in pairs(data) do - local itemsdaily = {strsplit(ITEM_DIVIDER, itemstring)} - for index, propertystring in ipairs(itemsdaily) do - -- extract daily data entries for this itemID & property - local prop, datastringdaily = strsplit(PROPERTY_DIVIDER, propertystring) - local dailybuy, dailyseen, dailymbo, dailyauctions = strsplit(DATA_DIVIDER, datastringdaily) - dailybuy, dailyseen, dailymbo, dailyauctions = tonumber(dailybuy), tonumber(dailyseen), tonumber(dailymbo), tonumber(dailyauctions) - local dailyavg = dailybuy - -- dailyseen may be 0 for certain unusual items which do not modify property "0" - -- our database format requires that there must always be a property "0" (which must always be at index 1) - -- if no items of that base type with property "0" were seen today, the entry will be empty (all 0) - if dailyseen > 0 then - dailyavg = dailyavg / dailyseen - end + if item_record.daily_auction_count > 0 then + + local daily_average = item_record.daily_accumulated_buyout / item_record.daily_unit_count - -- look for existing means data for this property - local datastringmeans = lookupmeansdata[prop] - if datastringmeans then - if dailyseen > 0 then - datameans = {strsplit(DATA_DIVIDER, datastringmeans)} -- seendays, seencount, EMA3, EMA7, EMA14, avgminbuy [, seenauctions] - for k, v in ipairs(datameans) do - datameans[k] = tonumber(v) - end - - -- update means data for this entry - local seendays = datameans[1] - local newseendays = seendays + 1 - datameans[1] = newseendays - datameans[2] = datameans[2] + dailyseen - local seenauctions = datameans[7] - if seenauctions then - datameans[7] = seenauctions + (dailyauctions or dailyseen) - else - datameans[7] = dailyauctions -- may be nil - end - - if seendays < 3 then - -- for first 3 days perform plain average insead of EMAs - datameans[3] = numberformat((datameans[3] * seendays + dailyavg) / newseendays) -- EMA3 - datameans[6] = numberformat((datameans[6] * seendays + dailymbo) / newseendays) -- average minimum buyout - if newseendays == 3 then - -- this is the third day, prep other EMAs for next time - datameans[4] = datameans[3] - datameans[5] = datameans[3] - end - else - -- do normal EMA calculations - datameans[3] = numberformat((datameans[3] * 2 + dailyavg) / 3) -- EMA3 - datameans[4] = numberformat((datameans[4] * 6 + dailyavg) / 7) -- EMA7 - datameans[5] = numberformat((datameans[5] * 13 + dailyavg) / 14) -- EMA14 - - local avgmbo = datameans[6] -- average minimum buyout - if avgmbo < 1 then - datameans[6] = dailymbo - else - if dailymbo >= 1 then - if avgmbo < dailymbo then - if (avgmbo*10/dailymbo) < 9 then - datameans[6] = numberformat((avgmbo+dailymbo)/2) - else - datameans[6] = numberformat((avgmbo*7+dailymbo)/8) - end - else - if (dailymbo*10/avgmbo) < 9 then - datameans[6] = numberformat((avgmbo+dailymbo)/2) - else - datameans[6] = numberformat((avgmbo*7+dailymbo)/8) - end - end - end - end - end - itemstoremeans[lookupmeansindex[prop]] = prop..PROPERTY_DIVIDER..tconcat(datameans, DATA_DIVIDER) - end + if item_record.seen_days < 3 then + -- for first 3 days perform plain average instead of EMAs + item_record.EMA3 = (item_record.EMA3 * item_record.seen_days + daily_average) / (item_record.seen_days + 1) + item_record.average_min_buyout = (item_record.average_min_buyout * item_record.seen_days + item_record.daily_min_buyout) / (item_record.seen_days + 1) + item_record.EMA7 = item_record.EMA3 + item_record.EMA14 = item_record.EMA3 else - -- this property has not been seen before, create a new entry for it - -- we don't need to use an intermediate table, we can build the datastring directly - -- there is no need to update lookupmeansdata[prop] or lookupmeansindex[prop], as each prop should only occur once for each storeID - if dailyauctions then - tinsert(itemstoremeans, newstringtemplate7:format(prop, dailyseen, dailyavg, dailymbo, dailyauctions)) -- represents data table with 7 entries + -- do normal EMA calculations + item_record.EMA3 = (item_record.EMA3 * 2 + daily_average) / 3) + item_record.EMA7 = (item_record.EMA7 * 6 + daily_average) / 7) + item_record.EMA14 = (item_record.EMA14 * 13 + daily_average) / 14) + + if item_record.daily_min_buyout / item_record.average_min_buyout < 0.9 then + item_record.average_min_buyout = (item_record.average_min_buyout + item_record.daily_min_buyout) / 2 else - tinsert(itemstoremeans, newstringtemplate6:format(prop, dailyseen, dailyavg, dailymbo)) -- represents data table with 6 entries (missing seenauctions) + item_record.average_min_buyout = (item_record.average_min_buyout * 7 + item_record.daily_min_buyout) / 8 end end + + item_record.count = item_record.unit_count + item_record.daily_unit_count + item_record.count = item_record.auction_count + item_record.daily_auction_count + item_record.seen_days = item_record.seen_days + 1 + + item_record.daily_auction_count = 0 + item_record.daily_unit_count = 0 + item_record.daily_min_buyout = nil + item_record.daily_accumulated_buyout = 0 end - - means[storeID] = tconcat(itemstoremeans, ITEM_DIVIDER) - wipe(lookupmeansdata) - wipe(lookupmeansindex) end realmdata.dailypush = time() + PUSHTIME - wipe(daily) end