Advertisement
Zerewa

Untitled

Nov 2nd, 2017
182
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 36.79 KB | None | 0 0
  1.  
  2. local addonName, addonTable = ...
  3. local zc = addonTable.zc
  4. local zz = zc.md
  5. local _
  6.  
  7. KM_NULL_STATE   = 0;
  8. KM_PREQUERY     = 1;
  9. KM_INQUERY      = 2;
  10. KM_POSTQUERY    = 3;
  11. KM_ANALYZING    = 4;
  12. KM_SETTINGSORT  = 5;
  13.  
  14. local AUCTION_CLASS_WEAPON       = 1;
  15. local AUCTION_CLASS_ARMOR        = 2;
  16. local AUCTION_CLASS_BATTLEPET    = 11;
  17.  
  18. local gAllScans = {};
  19.  
  20. local BATTLE_PET_ITEMID = 82800
  21.  
  22. local BIGNUM = 999999999999;
  23.  
  24. local ATR_SORTBY_NAME_ASC = 0;
  25. local ATR_SORTBY_NAME_DES = 1;
  26. local ATR_SORTBY_PRICE_ASC = 2;
  27. local ATR_SORTBY_PRICE_DES = 3;
  28.  
  29. gScanHistDayZero = time({year=2010, month=11, day=15, hour=0});     -- never ever change
  30.  
  31. local gNumNilItemLinks
  32.  
  33. -----------------------------------------
  34.  
  35. AtrScan = {};
  36. AtrScan.__index = AtrScan;
  37.  
  38. -----------------------------------------
  39.  
  40. AtrSearch = {};
  41. AtrSearch.__index = AtrSearch;
  42.  
  43. -----------------------------------------
  44.  
  45. local function GetExactMatchText (searchText)
  46.  
  47.     local emtext = nil;
  48.    
  49.     if (zc.StringStartsWith (searchText, "\"") and zc.StringEndsWith (searchText, "\"")) then
  50.         emtext = string.sub (searchText, 2, searchText:len()-1);
  51.     end
  52.  
  53.     return emtext;
  54. end
  55.  
  56. -----------------------------------------
  57.  
  58. function Atr_NewSearch (itemName, IDstring, itemLink, rescanThreshold)
  59.  
  60.     local srch = {};
  61.     setmetatable (srch, AtrSearch);
  62.     srch:Init (itemName, IDstring, itemLink, rescanThreshold);
  63.  
  64.     return srch;
  65. end
  66.  
  67. -----------------------------------------
  68.  
  69. function AtrSearch:Init (searchText, IDstring, itemLink, rescanThreshold)
  70.  
  71.     if (searchText == nil) then
  72.         searchText = ""
  73.     end
  74.  
  75.     self.origSearchText = searchText
  76.    
  77.     self.exactMatchText = nil;
  78.     self.searchText     = searchText
  79.    
  80.     if (IDstring == nil) then
  81.         self.exactMatchText = GetExactMatchText(searchText)
  82.         if (self.exactMatchText) then
  83.             self.searchText = self.exactMatchText
  84.         end
  85.     end    
  86.  
  87.     self.IDstring           = IDstring
  88.     self.processing_state   = KM_NULL_STATE
  89.     self.current_page       = -1
  90.     self.items              = {}
  91.     self.query              = Atr_NewQuery()
  92.     self.sortedScans        = nil
  93.     self.sortHow            = ATR_SORTBY_PRICE_ASC
  94.     self.shopListIndex      = 1
  95.     self.shplist            = Atr_GetShoppingListFromSearchText (self.searchText)
  96.  
  97.     if (Atr_IsCompoundSearch(self.searchText)) then
  98.         _, _, _, _, _, self.minItemLevel, self.maxItemLevel = Atr_ParseCompoundSearch (self.searchText);
  99.     end
  100.    
  101.     if (IDstring) then 
  102.  
  103.         if (rescanThreshold and rescanThreshold > 0) then
  104.             local scan = Atr_FindScan (IDstring, searchText);
  105.             if (scan and (time() - scan.whenScanned) <= rescanThreshold) then
  106.                 self.items[IDstring] = scan;
  107.                 self.items[IDstring]:UpdateItemLink (itemLink);
  108.             end
  109.         end
  110.        
  111.         if (not self.items[IDstring]) then     
  112.             self.items[IDstring] = Atr_FindScanAndInit (IDstring, searchText);
  113.             self.items[IDstring]:UpdateItemLink (itemLink);
  114.         end
  115.        
  116.     end
  117.  
  118.    
  119. end
  120.  
  121. -----------------------------------------
  122.  
  123. function Atr_FindScanAndInit (IDstring, itemName)
  124.  
  125.     return Atr_FindScan (IDstring, itemName, true);
  126. end
  127.  
  128. -----------------------------------------
  129.  
  130. function Atr_FindScan (IDstring, itemName, init)
  131.  
  132.     if (IDstring == nil or IDstring == "" or IDstring == "0") then
  133.         IDstring = "0";
  134.         itemName = "nil";
  135.     end
  136.  
  137.     if (gAllScans[IDstring] == nil and itemName ~= nil) then    -- if no itemName provided then we can't create
  138.         local scn = {};
  139.         setmetatable (scn, AtrScan);
  140.         gAllScans[IDstring] = scn;
  141.         init = true;
  142. --      zz ("creating scan: ", IDstring, itemName);
  143.     end
  144.  
  145.     if (init and gAllScans[IDstring] ~= nil) then
  146. --      zz ("initing scan: ", IDstring, itemName);
  147.        
  148.         gAllScans[IDstring]:Init (IDstring, itemName);
  149.     end
  150.    
  151.     return gAllScans[IDstring];
  152. end
  153.  
  154. -----------------------------------------
  155.  
  156. function Atr_ClearScanCache ()
  157.  
  158.     for a,v in pairs (gAllScans) do
  159.         if (a ~= "0") then
  160.             gAllScans[a] = nil;
  161.         end
  162.     end
  163.  
  164. end
  165.  
  166. -----------------------------------------
  167.  
  168. function AtrScan:Init (IDstring, itemName)
  169.  
  170.     self.IDstring           = IDstring;
  171.    
  172.     if (itemName) then
  173.         self.itemName = itemName;
  174.     end
  175.    
  176.     self.itemLink           = nil;
  177.     self.scanData           = {};
  178.     self.sortedData         = {};
  179.     self.whenScanned        = 0;
  180.     self.lowprice           = BIGNUM;
  181.     self.absoluteBest       = nil;
  182.     self.itemClass          = 0;
  183.     self.itemSubclass       = 0;
  184.     self.itemLevel          = 0;
  185.     self.yourBestPrice      = nil;
  186.     self.yourWorstPrice     = nil;
  187.     self.itemTextColor      = { 1.0, 1.0, 1.0 };
  188.     self.searchText         = nil;
  189.    
  190. end
  191.  
  192.  
  193. -----------------------------------------
  194.  
  195. function AtrScan:UpdateItemLink (itemLink)
  196.  
  197.     if (itemLink and self.itemLink == nil) then
  198.    
  199.         self.itemLink = itemLink;
  200.  
  201.         local _, quality, iLevel, sType, sSubType;
  202.  
  203.         if (zc.IsBattlePetLink (itemLink)) then
  204.            
  205.             local speciesID, level, breedQuality = zc.ParseBattlePetLink (itemLink)
  206.            
  207.             iLevel  = level;
  208.             quality = breedQuality;
  209.            
  210.             self.itemClass      = AUCTION_CLASS_BATTLEPET;
  211.             self.itemSubclass   = 0;
  212.  
  213.         else
  214.             _, _, quality, iLevel, _, sType, sSubType = GetItemInfo(itemLink);
  215.  
  216.             self.itemClass      = Atr_ItemType2AuctionClass (sType);
  217.             self.itemSubclass   = Atr_SubType2AuctionSubclass (self.itemClass, sSubType);  
  218.         end
  219.            
  220.         self.itemQuality    = quality;
  221.         self.itemLevel      = iLevel;
  222.  
  223.         self.itemTextColor = { 0.75, 0.75, 0.75 };
  224.  
  225.         if (quality == 0)   then    self.itemTextColor = { 0.6, 0.6, 0.6 }; end
  226.         if (quality == 1)   then    self.itemTextColor = { 1.0, 1.0, 1.0 }; end
  227.         if (quality == 2)   then    self.itemTextColor = { 0.2, 1.0, 0.0 }; end
  228.         if (quality == 3)   then    self.itemTextColor = { 0.0, 0.5, 1.0 }; end
  229.         if (quality == 4)   then    self.itemTextColor = { 0.7, 0.3, 1.0 }; end
  230.     end
  231.  
  232. end
  233.  
  234.  
  235.  
  236. -----------------------------------------
  237.  
  238. function AtrSearch:NumScans()
  239.  
  240.     if (self.sortedScans) then
  241.         return #self.sortedScans;
  242.     end
  243.  
  244.     local idstr,scn;
  245.     local count = 0;
  246.     for idstr,scn in pairs (self.items) do
  247.         count = count + 1;
  248.     end
  249.  
  250.     return count;
  251. end
  252.  
  253. -----------------------------------------
  254.  
  255. function AtrSearch:NumSortedScans()
  256.  
  257.     if (self.sortedScans) then
  258.         return #self.sortedScans;
  259.     end
  260.  
  261.     return 0;
  262. end
  263.  
  264. -----------------------------------------
  265.  
  266. function AtrSearch:GetFirstScan()
  267.  
  268.     if (self.sortedScans) then
  269.         return self.sortedScans[1];
  270.     end
  271.  
  272.     local idstr,scn;
  273.     for idstr,scn in pairs (self.items) do
  274.         return scn;
  275.     end
  276.    
  277.     return nil
  278. end
  279.  
  280.  
  281. -----------------------------------------
  282.  
  283. function AtrSearch:Start ()
  284.  
  285.     if (self.searchText == "") then
  286.         return;
  287.     end
  288.    
  289.     if (Atr_IsCompoundSearch (self.searchText)) then
  290.            
  291.         local _, itemClass = Atr_ParseCompoundSearch (self.searchText);
  292.    
  293.         if (itemClass == 0) then
  294.             Atr_Error_Display (ZT("The first part of this compound\n\nsearch is not a valid category."));
  295.             return;
  296.         end
  297.  
  298.         self.sortHow = ATR_SORTBY_PRICE_DES;
  299.     end
  300.  
  301.     -- make sure all the matches in the scan db are in memory
  302.    
  303.     local numpulled = 0;
  304.    
  305.     if (self.exactMatchtext == nil and not self.IDstring and not Atr_IsCompoundSearch (self.searchText) and string.len(self.searchText) > 2) then
  306.         local name, info, itemLink;
  307.         for name, info in pairs(gAtr_ScanDB) do
  308.             if (zc.StringContains (name, self.searchText)) then
  309.                 if (type(info) == "table" and info.id) then
  310.                     local itemID, suffixID = strsplit(":", info.id);
  311.                     if (suffixID == nil) then       -- for now; seems problematic for many green "of the" items
  312.                         itemLink = zc.PullItemIntoMemory (itemID, suffixID);
  313.                         numpulled = numpulled + 1;
  314.                     end
  315.                 end
  316.             end
  317.         end
  318.     end
  319.  
  320.     -- make sure all the items in the shopping list are in memory
  321.    
  322.     if (self.shplist) then
  323.         local n
  324.         for n = 1,self.shplist:GetNumItems() do
  325.             local itemname = zc.TrimQuotes(self.shplist:GetNthItemName (n))
  326.             local dbInfo = gAtr_ScanDB[itemname]
  327.             if (dbInfo and dbInfo.id) then
  328.                 zc.PullItemIntoMemory (dbInfo.id);
  329.                 numpulled = numpulled + 1;
  330.             end
  331.         end
  332.     end
  333.  
  334.     gNumNilItemLinks = 0
  335.    
  336.     self.processing_state = KM_SETTINGSORT;
  337.    
  338.     if (Atr_ILevelHist_Init) then
  339.         Atr_ILevelHist_Init()
  340.     end
  341.    
  342.     SortAuctionClearSort ("list");
  343.  
  344.     BrowseName:SetText (self.searchText);       -- not necessary but nice when user switches to Browse tab
  345.  
  346.     self.current_page       = 0;
  347.     self.processing_state   = KM_PREQUERY;
  348.  
  349.     self:Continue();
  350.    
  351. end
  352.  
  353. -----------------------------------------
  354.  
  355. function AtrSearch:Abort ()
  356.  
  357.     if (self.processing_state == KM_NULL_STATE) then
  358.         return;
  359.     end
  360.  
  361.     self.processing_state = KM_NULL_STATE;
  362.     self:Init();
  363. end
  364.  
  365. -----------------------------------------
  366.  
  367. function AtrSearch:CheckForDuplicatePage ()
  368.  
  369.     local isDup = self.query:CheckForDuplicatePage(self.current_page);
  370.  
  371.     if (isDup) then
  372. --      zc.msg_red ("DUPLICATE PAGE FOUND: ", "  current_page: ", self.current_page, "  numDupPages: ", self.query.numDupPages);
  373.  
  374.         self.current_page   = self.current_page - 1;   -- requery the page
  375.        
  376.         self.processing_state = KM_PREQUERY;
  377.     end
  378.        
  379.     return isDup;
  380. end
  381.  
  382.  
  383. -----------------------------------------
  384.  
  385. function AtrSearch:AnalyzeResultsPage()
  386.  
  387.     self.processing_state = KM_ANALYZING;
  388.  
  389.     if (self.query.numDupPages > 50) then    -- hopefully this will never happen but need check to avoid looping
  390.         return true;                         -- done
  391.     end
  392.  
  393.  
  394.     local numBatchAuctions, totalAuctions = Atr_GetNumAuctionItems("list");
  395.  
  396.     if (self.current_page == 1 and totalAuctions > 5000) then -- give Blizz servers a break (100 pages)
  397.         Atr_Error_Display (ZT("Too many results\n\nPlease narrow your search"));
  398.         return true;  -- done
  399.     end
  400.  
  401.     local msg
  402.  
  403.     local slistItemName = Atr_GetShoppingListItem (self)
  404.     if (slistItemName) then
  405.        
  406.         local pageText = "";
  407.         if (self.current_page > 1) then
  408.             pageText = string.format (ZT(": page %d"), self.current_page)
  409.         else
  410.             pageText = "             "
  411.         end
  412.  
  413.         msg = string.format (ZT("Scanning auctions for %s%s"), slistItemName, pageText);
  414.     elseif (totalAuctions >= 50) then
  415.         msg = string.format (ZT("Scanning auctions: page %d"), self.current_page);
  416.     end
  417.  
  418.     if (msg) then
  419.         Atr_SetMessage (msg)
  420.     end
  421.  
  422.     --zz (slistItemName, "current_page: ", self.current_page, "numBatchAuctions: ", numBatchAuctions)
  423.  
  424.     -- analyze
  425.  
  426.     local k, g, f
  427.     local numNilOwners = 0
  428.  
  429.     if (numBatchAuctions > 0) then
  430.  
  431.         local x;
  432.  
  433.         for x = 1, numBatchAuctions do
  434.  
  435.             local name, texture, count, quality, canUse, level, huh, minBid, minIncrement, buyoutPrice, bidAmount, highBidder, bidderFullName, owner, ownerFullName = GetAuctionItemInfo("list", x);
  436.  
  437.             local itemLink = GetAuctionItemLink("list", x);
  438.            
  439.             if (itemLink) then
  440.                 local IDstring = zc.ItemIDStrfromLink (itemLink);
  441.                
  442.                 if (Atr_ILevelHist_Update) then
  443.                     Atr_ILevelHist_Update(itemLink)
  444.                 end
  445.                
  446.                 local OKitemLevel = true
  447.                 if (self.minItemLevel or self.maxItemLevel) then
  448.                     local _, _, _, iLevel, _ = GetItemInfo(itemLink);
  449.                     if ((self.minItemLevel and iLevel < self.minItemLevel) or (self.maxItemLevel and iLevel > self.maxItemLevel)) then
  450.                         OKitemLevel = false
  451.                     end
  452.                 end
  453.                
  454.                 if (OKitemLevel) then
  455.                     if (owner == nil) then
  456.                         numNilOwners = numNilOwners + 1
  457.                     end
  458.  
  459.                     if (self.exactMatchText == nil or zc.StringSame (name, self.exactMatchText)) then
  460.  
  461.                         if (self.items[IDstring] == nil) then
  462.                             self.items[IDstring] = Atr_FindScanAndInit (IDstring, name)
  463.                         end
  464.                        
  465.                         local curpage = (tonumber(self.current_page)-1)
  466.  
  467.                         local scn = self.items[IDstring]
  468.  
  469.                         if (scn) then
  470.                             scn:AddScanItem (count, buyoutPrice, owner, 1, curpage)
  471.                             scn:UpdateItemLink (itemLink)
  472.                         end
  473.                     end
  474.                 end
  475.             else
  476.                 gNumNilItemLinks = gNumNilItemLinks + 1
  477.                 print(itemlink)
  478.             end
  479.         end
  480.     end
  481.    
  482.     local done = (numBatchAuctions < 50);
  483.  
  484.     if (done) then
  485.         if (self.shplist) then
  486.             self.shopListIndex = self.shopListIndex + 1
  487.             local nextSearchItem = Atr_GetShoppingListItem (self)
  488.             if (nextSearchItem) then
  489.                 self.current_page       = 0
  490.                 self.exactMatchText     = nil
  491.                 done = false
  492.             end
  493.         end
  494.     end
  495.  
  496.     if (not done) then
  497.         self.processing_state = KM_PREQUERY;
  498.     end
  499.  
  500.     return done;
  501. end
  502.  
  503. -----------------------------------------
  504.  
  505. function AtrScan:AddScanItem (stackSize, buyoutPrice, owner, numAuctions, curpage)
  506.  
  507.     local sd = {};
  508.     local i;
  509.  
  510.     if (numAuctions == nil) then
  511.         numAuctions = 1;
  512.     end
  513.  
  514.     for i = 1, numAuctions do
  515.         sd["stackSize"]     = stackSize;
  516.         sd["buyoutPrice"]   = buyoutPrice;
  517.         sd["owner"]         = owner;
  518.         sd["pagenum"]       = curpage;
  519.  
  520.         tinsert (self.scanData, sd);
  521.        
  522.         if (buyoutPrice and buyoutPrice > 0) then
  523.             local itemPrice = math.floor (buyoutPrice / stackSize);
  524.  
  525.             self.lowprice = math.min (self.lowprice, itemPrice);
  526.         end
  527.     end
  528.  
  529. end
  530.  
  531.  
  532. -----------------------------------------
  533.  
  534. function AtrScan:SubtractScanItem (stackSize, buyoutPrice)
  535.  
  536.     local sd;
  537.     local i;
  538.  
  539.     for i,sd in ipairs (self.scanData) do
  540.        
  541.         if (sd.stackSize == stackSize and sd.buyoutPrice == buyoutPrice) then
  542.            
  543.             tremove (self.scanData, i);
  544.             return;
  545.         end
  546.     end
  547.  
  548. end
  549.  
  550.  
  551. -----------------------------------------
  552.  
  553. function Atr_IsShoppingListSearch (searchString)
  554.    
  555.     if (searchString == nil) then
  556.         return false;
  557.     end
  558.    
  559.     return zc.StringStartsWith (searchString, "{ ") and zc.StringEndsWith (searchString, " }");
  560. end
  561.  
  562. -----------------------------------------
  563.  
  564. function Atr_GetShoppingListFromSearchText (searchString)
  565.  
  566.     if (Atr_IsShoppingListSearch (searchString)) then
  567.         local len = string.len(searchString);
  568.  
  569.         local shoppingListName = string.sub (searchString, 3, len-2);
  570.        
  571.         return Atr_SList.FindByName (shoppingListName);
  572.     end
  573.    
  574.     return nil
  575. end
  576.  
  577. -----------------------------------------
  578.  
  579. function Atr_GetShoppingListItem (search)
  580.  
  581.     if (search.shplist) then
  582.         return search.shplist:GetNthItemName (search.shopListIndex);
  583.     end
  584.    
  585.     return nil;
  586. end
  587.  
  588. -----------------------------------------
  589.  
  590. function Atr_IsCompoundSearch (searchString)
  591.    
  592.     if (searchString == nil) then
  593.         return false;
  594.     end
  595.    
  596.     return zc.StringContains (searchString, ">") or zc.StringContains (searchString, "/");
  597. end
  598.  
  599. -----------------------------------------
  600.  
  601. local function toItemLevel (s)      -- returns nil if not of the form i72 or i277, etc
  602.  
  603.     if (string.len(s) > 1 and string.sub(s,1,1) == "i") then
  604.         return tonumber (string.sub(s,2))
  605.     end
  606.    
  607.     return nil
  608. end
  609.  
  610. -----------------------------------------
  611.  
  612. function Atr_ParseCompoundSearch (searchString)
  613.  
  614.     local delim = "/";
  615.  
  616.     if (zc.StringContains (searchString, ">")) then
  617.         delim = ">";
  618.     end
  619.  
  620.     local tbl   = { strsplit (delim, searchString) };
  621.    
  622.     local queryString   = "";
  623.     local itemClass     = 0;
  624.     local itemSubclass  = 0;
  625.     local minLevel      = nil;
  626.     local maxLevel      = nil;
  627.     local minItemLevel  = nil;
  628.     local maxItemLevel  = nil;
  629.     local prevWasItemClass;
  630.     local n;
  631.    
  632.     for n = 1,#tbl do
  633.         local s = tbl[n];
  634.  
  635.         local handled = false;
  636.  
  637.    
  638.         if (not handled and tonumber(s)) then
  639.             if (minLevel == nil) then
  640.                 minLevel = tonumber(s);
  641.             elseif (maxLevel == nil) then
  642.                 maxLevel = tonumber(s);
  643.             end
  644.            
  645.             handled = true;
  646.             prevWasItemClass = false;
  647.         end
  648.    
  649.         if (not handled and toItemLevel(s)) then
  650.             if (minItemLevel == nil) then
  651.                 minItemLevel = toItemLevel(s);
  652.             elseif (maxItemLevel == nil) then
  653.                 maxItemLevel = toItemLevel(s);
  654.             end
  655.            
  656.             handled = true;
  657.             prevWasItemClass = false;
  658.         end
  659.        
  660.         if (not handled and prevWasItemClass and itemSubclass == 0) then
  661.             itemSubclass = Atr_SubType2AuctionSubclass (itemClass, s);
  662.             if (itemSubclass > 0) then
  663.                 handled = true;
  664.                 prevWasItemClass = false;
  665.             end
  666.         end
  667.        
  668.         if (not handled and itemClass == 0) then
  669.  
  670.             itemClass = Atr_ItemType2AuctionClass (s);
  671.  
  672.             if (itemClass > 0) then
  673.                 prevWasItemClass = true;
  674.                 handled = true;
  675.             end
  676.         end
  677.        
  678.         if (not handled) then
  679.             queryString = s;
  680.             handled = true;
  681.         end
  682.     end
  683.  
  684.     return queryString, itemClass, itemSubclass, minLevel, maxLevel, minItemLevel, maxItemLevel;
  685. end
  686.  
  687. -----------------------------------------
  688.  
  689. function AtrSearch:Continue()
  690.  
  691.     if (CanSendAuctionQuery()) then
  692.  
  693.         self.processing_state = KM_IN_QUERY;
  694.  
  695.         local queryString;
  696.  
  697.         local itemClass     = 0;
  698.         local itemSubclass  = 0;
  699.         local minLevel      = nil;
  700.         local maxLevel      = nil;
  701.        
  702.         if (Atr_IsCompoundSearch(self.searchText)) then
  703.             queryString, itemClass, itemSubclass, minLevel, maxLevel = Atr_ParseCompoundSearch (self.searchText);
  704.            
  705.         elseif (self.shplist) then
  706.             queryString = Atr_GetShoppingListItem (self)
  707.            
  708.             self.exactMatchText = GetExactMatchText(queryString)
  709.             if (self.exactMatchText) then
  710.                 queryString = self.exactMatchText
  711.             end
  712.            
  713.             -- skip nested shopping lists or compound searches
  714.             while (Atr_IsShoppingListSearch(queryString) or Atr_IsCompoundSearch(queryString)) do
  715.                 zc.md ("Skipping ", queryString);
  716.                 self.shopListIndex = self.shopListIndex + 1
  717.                 queryString = Atr_GetShoppingListItem (self)
  718.                 if (queryString == nil) then
  719.                     break
  720.                 end
  721.             end
  722.            
  723.             if (queryString == nil) then
  724.                 queryString = "?????";
  725.             end
  726.         else
  727.             queryString = self.searchText;
  728.         end
  729.  
  730.         queryString = zc.UTF8_Truncate (queryString,63);    -- attempting to reduce number of disconnects
  731.  
  732.         --zz (queryString, "  page:", self.current_page);
  733.        
  734.         QueryAuctionItems (queryString, minLevel, maxLevel, nil, itemClass, itemSubclass, self.current_page, nil, nil);
  735.  
  736.         self.query_sent_when    = gAtr_ptime;
  737.         self.processing_state   = KM_POSTQUERY;
  738.  
  739.         self.current_page       = self.current_page + 1;
  740.     end
  741.  
  742. end
  743.  
  744. -----------------------------------------
  745.  
  746. local gSortScansBy;
  747.  
  748. -----------------------------------------
  749.  
  750. local function Atr_SortScans (x, y)
  751.  
  752.     if (gSortScansBy == ATR_SORTBY_NAME_ASC) then       return string.lower (x.itemName) < string.lower (y.itemName);   end
  753.     if (gSortScansBy == ATR_SORTBY_NAME_DES) then       return string.lower (x.itemName) > string.lower (y.itemName);   end
  754.  
  755.     local xprice = 0;
  756.     local yprice = 0;
  757.    
  758.     if (x.absoluteBest) then    xprice = zc.round(x.absoluteBest.buyoutPrice/x.absoluteBest.stackSize);     end;
  759.     if (y.absoluteBest) then    yprice = zc.round(y.absoluteBest.buyoutPrice/y.absoluteBest.stackSize);     end;
  760.    
  761.     if (gSortScansBy == ATR_SORTBY_PRICE_ASC) then      return xprice < yprice;     end
  762.     if (gSortScansBy == ATR_SORTBY_PRICE_DES) then      return xprice > yprice;     end
  763.  
  764. end
  765.  
  766. -----------------------------------------
  767.  
  768. function AtrSearch:Finish()
  769.  
  770.     local finishTime = time();
  771.    
  772.     self.processing_state   = KM_NULL_STATE;
  773.     self.current_page       = -1;
  774.     self.query_sent_when    = nil;
  775.  
  776.     -- add scans for items that weren't found (at least for items that are in the scan db)
  777.    
  778.     if (self.exactMatchText == nil and not self.IDstring) then
  779.         if (not Atr_IsCompoundSearch (self.searchText)) then
  780.             local name, info;
  781.             for name, info in pairs(gAtr_ScanDB) do
  782.                 if (zc.StringContains (name, self.searchText)) then
  783.                     if (info.id and self.items[info.id] == nil) then
  784.                         local itemID, suffixID = strsplit(":", info.id);
  785.                         if (suffixID == nil) then       -- for now; seems problematic for many green "of the" items
  786.                             self.items[info.id] = Atr_FindScanAndInit (info.id, name);
  787.                             local itemLink = zc.LinkFromItemID (itemID, suffixID);
  788.                             if (itemLink) then
  789.                                 self.items[info.id]:UpdateItemLink (itemLink)
  790.                             end
  791.                         end
  792.                     end
  793.                 end
  794.             end
  795.         end
  796.     end
  797.    
  798.     -- add scans for items in the shopping list that weren't found
  799.    
  800.     if (self.shplist) then
  801.         local n
  802.         for n = 1,self.shplist:GetNumItems() do
  803.             local itemname = zc.TrimQuotes(self.shplist:GetNthItemName (n))
  804.            
  805.             local dbInfo = gAtr_ScanDB[itemname]
  806.             if (dbInfo and dbInfo.id) then
  807.                 local IDstring = dbInfo.id
  808.                 if (self.items[IDstring] == nil) then
  809.                     self.items[IDstring] = Atr_FindScanAndInit (IDstring, itemname)
  810.                     local itemLink = zc.LinkFromItemID (IDstring);
  811.                     if (itemLink) then
  812.                         self.items[IDstring]:UpdateItemLink (itemLink)
  813.                     end
  814.                 end
  815.             else        -- not in scandb
  816.                 local IDstring = "***"..itemname               
  817.                 self.items[IDstring] = Atr_FindScanAndInit (IDstring, itemname)
  818.             end
  819.         end
  820.     end
  821.  
  822.     -- create an empty scan if there were no matches
  823.    
  824.     self.sortedScans = nil;
  825.    
  826.     if (self:NumScans() == 0) then
  827.  
  828.         local dbInfo = gAtr_ScanDB[self.searchText]
  829.        
  830.         if (dbInfo and dbInfo.id) then  -- so that we see the history tab, etc.
  831.             local IDstring = dbInfo.id;
  832.             self.items[IDstring] = Atr_FindScan (IDstring, self.searchText, true);
  833.         else
  834.             self.items["0"] = Atr_FindScan (nil);
  835.         end
  836.    
  837.     end
  838.    
  839.     -- process the scans
  840.    
  841.     local broadcastInfo = {};
  842.    
  843.     local x = 1;
  844.     self.sortedScans = {};
  845.    
  846.     for IDstring,scn in pairs (self.items) do
  847.    
  848.         self.sortedScans[x] = scn;
  849.         x = x + 1;
  850.        
  851.         scn.whenScanned     = finishTime;
  852.         scn.searchText      = self.searchText;
  853.  
  854.         scn:CondenseAndSort ();
  855.  
  856.         -- update the fullscan DB
  857.  
  858.         if (scn.lowprice < BIGNUM) then
  859.        
  860.             if (scn.itemQuality == nil) then
  861.                 zc.msg_anm ("|cffff0000Error: scn.itemQuality == nil, scn.itemName: ", scn.itemName);
  862.             end
  863.            
  864.             if (scn.itemQuality ~= nil and (scn.itemQuality + 1 >= AUCTIONATOR_SCAN_MINLEVEL or scn.quality == -1)) then        --  battle pets can be UNKNOWN (-1) quality
  865.                                
  866.                 Atr_UpdateScanDBprice       (scn.itemName, scn.lowprice);
  867.                 Atr_UpdateScanDBclassInfo   (scn.itemName, scn.itemClass, scn.itemSubclass);
  868.                 Atr_UpdateScanDBitemID      (scn.itemName, scn.itemLink);
  869.                
  870.                 table.insert (broadcastInfo, {i=scn.IDstring, p=scn.lowprice});
  871.             end
  872.         end
  873.     end
  874.  
  875.     if (gNumNilItemLinks > 0) then
  876.         zc.msg_anm ("Number of nil links found during scan: ", gNumNilItemLinks)
  877.     end
  878.  
  879.     Atr_Broadcast_DBupdated (#broadcastInfo, "partialscan", broadcastInfo);
  880.  
  881.     if (Atr_ILevelHist_Print) then
  882.         Atr_ILevelHist_Print()
  883.     end
  884.    
  885.    
  886.     gSortScansBy = self.sortHow;
  887.     table.sort (self.sortedScans, Atr_SortScans);
  888. end
  889.  
  890. -----------------------------------------
  891.  
  892. function AtrSearch:ClickPriceCol()
  893.  
  894.     if (self.sortHow == ATR_SORTBY_PRICE_ASC) then
  895.         self.sortHow = ATR_SORTBY_PRICE_DES;
  896.     else
  897.         self.sortHow = ATR_SORTBY_PRICE_ASC;
  898.     end
  899.  
  900.     gSortScansBy = self.sortHow;
  901.     table.sort (self.sortedScans, Atr_SortScans);
  902.  
  903. end
  904.  
  905. -----------------------------------------
  906.  
  907. function AtrSearch:ClickNameCol()
  908.  
  909.     if (self.sortHow == ATR_SORTBY_NAME_ASC) then
  910.         self.sortHow = ATR_SORTBY_NAME_DES;
  911.     else
  912.         self.sortHow = ATR_SORTBY_NAME_ASC;
  913.     end
  914.  
  915.     gSortScansBy = self.sortHow;
  916.     table.sort (self.sortedScans, Atr_SortScans);
  917. end
  918.  
  919. -----------------------------------------
  920.  
  921. function AtrSearch:UpdateArrows()
  922.  
  923.     Atr_Col1_Heading_ButtonArrow:Hide();
  924.     Atr_Col3_Heading_ButtonArrow:Hide();
  925.    
  926.     if (self.sortHow == ATR_SORTBY_PRICE_ASC) then
  927.         Atr_Col1_Heading_ButtonArrow:Show();
  928.         Atr_Col1_Heading_ButtonArrow:SetTexCoord(0, 0.5625, 0, 1.0);
  929.     elseif (self.sortHow == ATR_SORTBY_PRICE_DES) then
  930.         Atr_Col1_Heading_ButtonArrow:Show();
  931.         Atr_Col1_Heading_ButtonArrow:SetTexCoord(0, 0.5625, 1.0, 0);
  932.     elseif (self.sortHow == ATR_SORTBY_NAME_ASC) then
  933.         Atr_Col3_Heading_ButtonArrow:Show();
  934.         Atr_Col3_Heading_ButtonArrow:SetTexCoord(0, 0.5625, 0, 1.0);
  935.     elseif (self.sortHow == ATR_SORTBY_NAME_DES) then
  936.         Atr_Col3_Heading_ButtonArrow:Show();
  937.         Atr_Col3_Heading_ButtonArrow:SetTexCoord(0, 0.5625, 1.0, 0);
  938.     end
  939. end
  940.  
  941. -----------------------------------------
  942.  
  943. function Atr_ClearBrowseListings()
  944.    
  945.  
  946.     if (CanSendAuctionQuery()) then
  947.         QueryAuctionItems("xyzzy", 43, 43, 0, 7, 0);
  948.         zz ("Atr_ClearBrowseListings succeeded");
  949.     end
  950.  
  951.  
  952. end
  953.  
  954. -----------------------------------------
  955.  
  956. function Atr_SortAuctionData (x, y)
  957.  
  958.     return x.itemPrice < y.itemPrice;
  959.  
  960. end
  961.  
  962. -----------------------------------------
  963.  
  964. function AtrScan:CondenseAndSort ()
  965.  
  966.     ----- Condense the scan data into a table that has only a single entry per stacksize/price combo
  967.  
  968.     self.sortedData = {};
  969.  
  970.     local i,sd;
  971.     local conddata = {};
  972.  
  973.     for i,sd in ipairs (self.scanData) do
  974.  
  975.         local ownerCode = "x";
  976.         local dataType  = "n";      -- normal
  977.        
  978.         if (sd.owner == UnitName("player")) then
  979.             ownerCode = "y";
  980. --      elseif (Atr_IsMyToon (sd.owner)) then
  981. --          ownerCode = sd.owner;
  982.         end
  983.  
  984.         local key = "_"..sd.stackSize.."_"..sd.buyoutPrice.."_"..ownerCode..dataType;
  985.  
  986.         if (conddata[key]) then
  987.             conddata[key].count     = conddata[key].count + 1;
  988.             conddata[key].minpage   = zc.Min (conddata[key].minpage, sd.pagenum);
  989.             conddata[key].maxpage   = zc.Max (conddata[key].maxpage, sd.pagenum);
  990.         else
  991.             local data = {};
  992.  
  993.             data.stackSize      = sd.stackSize;
  994.             data.buyoutPrice    = sd.buyoutPrice;
  995.             data.itemPrice      = sd.buyoutPrice / sd.stackSize;
  996.             data.minpage        = sd.pagenum;
  997.             data.maxpage        = sd.pagenum;
  998.             data.count          = 1;
  999.             data.type           = dataType;
  1000.             data.yours          = (ownerCode == "y");
  1001.            
  1002.             if (ownerCode ~= "x" and ownerCode ~= "y") then
  1003.                 data.altname = ownerCode;
  1004.             end
  1005.            
  1006.             if (sd.volume) then
  1007.                 data.volume = sd.volume;
  1008.             end
  1009.            
  1010.             conddata[key] = data;
  1011.         end
  1012.  
  1013.     end
  1014.  
  1015.     ----- create a table of these entries
  1016.  
  1017.     local n = 1;
  1018.  
  1019.     local i, v;
  1020.  
  1021.     for i,v in pairs (conddata) do
  1022.         self.sortedData[n] = v;
  1023.         n = n + 1;
  1024.     end
  1025.  
  1026.     -- sort the table by itemPrice
  1027.  
  1028.     table.sort (self.sortedData, Atr_SortAuctionData);
  1029.  
  1030.     -- analyze and store some info about the data
  1031.  
  1032.     self:AnalyzeSortData ();
  1033.  
  1034. end
  1035.  
  1036. -----------------------------------------
  1037.  
  1038. function AtrScan:AnalyzeSortData ()
  1039.  
  1040.     self.absoluteBest           = nil;
  1041.     self.bestPrices             = {};       -- a table with one entry per stacksize that is the cheapest auction for that particular stacksize
  1042.     self.numMatches             = 0;
  1043.     self.numMatchesWithBuyout   = 0;
  1044.     self.hasStack               = false;
  1045.     self.yourBestPrice          = nil;
  1046.     self.yourWorstPrice         = nil;
  1047.  
  1048.     local j, sd;
  1049.  
  1050.     ----- find the best price per stacksize and overall -----
  1051.  
  1052.     for j,sd in ipairs(self.sortedData) do
  1053.  
  1054.         if (sd.type == "n") then
  1055.  
  1056.             self.numMatches = self.numMatches + 1;
  1057.  
  1058.             if (sd.itemPrice > 0) then
  1059.  
  1060.                 self.numMatchesWithBuyout = self.numMatchesWithBuyout + 1;
  1061.  
  1062.                 if (self.bestPrices[sd.stackSize] == nil or self.bestPrices[sd.stackSize].itemPrice >= sd.itemPrice) then
  1063.                     self.bestPrices[sd.stackSize] = sd;
  1064.                 end
  1065.  
  1066.                 if (self.absoluteBest == nil or self.absoluteBest.itemPrice > sd.itemPrice) then
  1067.                     self.absoluteBest = sd;
  1068.                 end
  1069.                
  1070.                 if (sd.yours) then
  1071.                     if (self.yourBestPrice == nil or self.yourBestPrice > sd.itemPrice) then
  1072.                         self.yourBestPrice = sd.itemPrice;
  1073.                     end
  1074.                    
  1075.                     if (self.yourWorstPrice == nil or self.yourWorstPrice < sd.itemPrice) then
  1076.                         self.yourWorstPrice = sd.itemPrice;
  1077.                     end
  1078.                    
  1079.                 end
  1080.             end
  1081.  
  1082.             if (sd.stackSize > 1) then
  1083.                 self.hasStack = true;
  1084.             end
  1085.         end
  1086.     end
  1087. end
  1088.  
  1089. -----------------------------------------
  1090.  
  1091. function AtrScan:FindInSortedData (stackSize, buyoutPrice)
  1092.     local j = 1;
  1093.     for j = 1,#self.sortedData do
  1094.         sd = self.sortedData[j];
  1095.         if (sd.stackSize == stackSize and sd.buyoutPrice == buyoutPrice and sd.yours) then
  1096.             return j;
  1097.         end
  1098.     end
  1099.    
  1100.     return 0;
  1101. end
  1102.  
  1103.  
  1104. -----------------------------------------
  1105.  
  1106. function AtrScan:FindMatchByStackSize (stackSize)
  1107.  
  1108.     local index = nil;
  1109.  
  1110.     local basedata = self.absoluteBest;
  1111.  
  1112.     if (self.bestPrices[stackSize]) then
  1113.         basedata = self.bestPrices[stackSize];
  1114.     end
  1115.  
  1116.     local numrows = #self.sortedData;
  1117.  
  1118.     local n;
  1119.  
  1120.     for n = 1,numrows do
  1121.  
  1122.         local data = self.sortedData[n];
  1123.  
  1124.         if (basedata and data.itemPrice == basedata.itemPrice and data.stackSize == basedata.stackSize and data.yours == basedata.yours) then
  1125.             index = n;
  1126.             break;
  1127.         end
  1128.     end
  1129.  
  1130.     return index;
  1131.    
  1132. end
  1133.  
  1134. -----------------------------------------
  1135.  
  1136. function AtrScan:FindMatchByYours ()
  1137.  
  1138.     local index = nil;
  1139.  
  1140.     local j;
  1141.     for j = 1,#self.sortedData do
  1142.         sd = self.sortedData[j];
  1143.         if (sd.yours) then
  1144.             index = j;
  1145.             break;
  1146.         end
  1147.     end
  1148.  
  1149.     return index;
  1150.  
  1151. end
  1152.  
  1153. -----------------------------------------
  1154.  
  1155. function AtrScan:FindCheapest ()
  1156.  
  1157.     local index = nil;
  1158.  
  1159.     local j;
  1160.     for j = 1,#self.sortedData do
  1161.         sd = self.sortedData[j];
  1162.         if (sd.itemPrice > 0) then
  1163.             index = j;
  1164.             break;
  1165.         end
  1166.     end
  1167.  
  1168.     return index;
  1169.  
  1170. end
  1171.  
  1172.  
  1173. -----------------------------------------
  1174.  
  1175. function AtrScan:GetNumAvailable ()
  1176.  
  1177.     local num = 0;
  1178.  
  1179.     local j, data;
  1180.     for j = 1,#self.sortedData do
  1181.  
  1182.         data = self.sortedData[j];
  1183.         num = num + (data.count * data.stackSize);
  1184.     end
  1185.    
  1186.     return num;
  1187. end
  1188.  
  1189. -----------------------------------------
  1190.  
  1191. function AtrScan:IsNil ()
  1192.  
  1193.     if (self.itemName == nil or self.itemName == "" or self.itemName == "nil") then
  1194.         return true;
  1195.     end
  1196.    
  1197.     return false;
  1198. end
  1199.  
  1200.  
  1201. -----------------------------------------
  1202.  
  1203. function Atr_GetDBsize()
  1204.  
  1205.     local n = 0;
  1206.     local a,v;
  1207.  
  1208.     for a,v in pairs (gAtr_ScanDB) do
  1209.         n = n + 1;
  1210.     end
  1211.    
  1212.     return n;
  1213. end
  1214.  
  1215.  
  1216. -----------------------------------------
  1217.  
  1218. function Atr_UpdateScanDBitemID (itemName, itemLink)
  1219.  
  1220.     if (itemLink == nil) then
  1221.         return;
  1222.     end
  1223.    
  1224.     if (not gAtr_ScanDB[itemName]) then
  1225.         gAtr_ScanDB[itemName] = {};
  1226.     end
  1227.  
  1228.     gAtr_ScanDB[itemName].id = zc.ItemIDStrfromLink (itemLink);
  1229. end
  1230.    
  1231. -----------------------------------------
  1232.  
  1233. function Atr_UpdateScanDBclassInfo (itemName, class, subclass)
  1234.  
  1235.     if (not gAtr_ScanDB[itemName]) then
  1236.         gAtr_ScanDB[itemName] = {};
  1237.     end
  1238.  
  1239.     gAtr_ScanDB[itemName].cc = class;
  1240.     gAtr_ScanDB[itemName].sc = subclass;
  1241.  
  1242. --  zc.md ("Setting class info for:", itemName, "    ", class, subclass);
  1243.  
  1244. end
  1245.  
  1246. -----------------------------------------
  1247.  
  1248. function Atr_UpdateScanDBprice (itemName, currentLowPrice, db)
  1249.  
  1250.     if (currentLowPrice == nil) then
  1251.         zc.msg_badErr ("currentLowPrice in NIL!!!!!!", itemName)
  1252. --      zc.printstack()
  1253.         return
  1254.     end
  1255.  
  1256.     if (type(currentLowPrice) ~= "number") then
  1257.         zc.msg_badErr ("currentLowPrice in not a number !!!!!!", type(currentLowPrice), itemName)
  1258. --      zc.printstack()
  1259.         return
  1260.     end
  1261.  
  1262.     if (db == nil) then
  1263.         db = gAtr_ScanDB;
  1264.     end
  1265.  
  1266.     if (db and type (db) ~= "table") then
  1267.         zc.msg_badErr ("Scanning history database appears to be corrupt")
  1268.         zc.msg_badErr ("db:", db)
  1269.         return nil
  1270.     end
  1271.  
  1272.     if (not db[itemName]) then
  1273.         db[itemName] = {};
  1274.     end
  1275.  
  1276.     db[itemName].mr = currentLowPrice;
  1277.    
  1278.     local daysSinceZero = Atr_GetScanDay_Today();
  1279.  
  1280.     local lowlow  = db[itemName]["L"..daysSinceZero];
  1281.     local highlow = db[itemName]["H"..daysSinceZero];
  1282.  
  1283.     local olow  = lowlow;
  1284.     local ohigh = highlow;
  1285.    
  1286.     if (highlow == nil or currentLowPrice > highlow) then
  1287.         db[itemName]["H"..daysSinceZero] = currentLowPrice;
  1288.         highlow = currentLowPrice;
  1289.     end
  1290.  
  1291.     -- save memory by only saving lowlow when different from highlow
  1292.    
  1293.     local isLowerThanLow        = (lowlow ~= nil and currentLowPrice < lowlow);
  1294.     local isNewAndDifferent     = (lowlow == nil and currentLowPrice < highlow);
  1295.    
  1296.     if (isLowerThanLow or isNewAndDifferent) then
  1297.         db[itemName]["L"..daysSinceZero] = currentLowPrice;
  1298. --      zz (itemName, "currentLowPrice:", currentLowPrice, "highlow:", highlow, "lowlow:", lowlow, "ohigh:", ohigh, "olow:", olow);
  1299.     end
  1300.  
  1301.     if (db[itemName]["po"]) then    -- unmark this item so it isn't purged
  1302.         db[itemName]["po"] = nil;
  1303.     end
  1304. end
  1305.  
  1306. -----------------------------------------
  1307.  
  1308. function Atr_PurgeObsoleteItems ()
  1309.  
  1310.     -- one time removal of old items - called after a full scan
  1311.  
  1312.     local a = 0
  1313.     local b = 0
  1314.     local potentials = 0;
  1315.     local doPurge, mostRecentDay, key, price, name, itemInfo
  1316.    
  1317.     local todayDay  = Atr_GetScanDay_Today()
  1318.    
  1319.     for name, itemInfo in pairs (gAtr_ScanDB) do
  1320.        
  1321.         doPurge = false;
  1322.        
  1323.         if (type(itemInfo) == "table") then
  1324.  
  1325.             mostRecentDay = -1
  1326.  
  1327.             for key, price in pairs (itemInfo) do
  1328.                 char1 = string.sub (key, 1, 1)
  1329.                 if (char1 == "H") then
  1330.                     day = tonumber (string.sub(key, 2))
  1331.                     mostRecentDay   = math.max (day, mostRecentDay)
  1332.                 end
  1333.             end
  1334.  
  1335.             if (itemInfo["po"]) then
  1336.                 potentials = potentials + 1;
  1337.             end
  1338.            
  1339.             if (itemInfo["po"] and todayDay - mostRecentDay > 10) then
  1340.                 doPurge = true;
  1341.             end
  1342.         end
  1343.        
  1344.         if (doPurge) then
  1345.             gAtr_ScanDB[name] = nil
  1346.             a = a + 1
  1347.         end
  1348.        
  1349.         b = b + 1
  1350.     end
  1351.  
  1352. --  zz ("potentials:", potentials);
  1353. --  zz ("purged:", a, "out of", b)
  1354. end
  1355.  
  1356. -----------------------------------------
  1357.  
  1358. function Atr_PrunePostDB()
  1359.  
  1360.     -- remove old items from the posting history database
  1361.  
  1362.     if (AUCTIONATOR_PRICING_HISTORY == nil) then
  1363.         return;
  1364.     end
  1365.  
  1366.     local now = time();
  1367.     local x = 0;
  1368.     local total = 0;
  1369.    
  1370.     local tempDB = {};
  1371.     zc.CopyDeep (tempDB, AUCTIONATOR_PRICING_HISTORY);
  1372.  
  1373.     for itemName, info in pairs(tempDB) do
  1374.  
  1375.         local recentWhen = 0;
  1376.         local tag, hist;
  1377.        
  1378.         for tag, hist in pairs (info) do
  1379.             if (tag ~= "is") then
  1380.                 local when, type, price = ParseHist (tag, hist);
  1381.  
  1382.                 if (when > recentWhen) then
  1383.                     recentWhen  = when;
  1384.                 end
  1385.             end
  1386.         end
  1387.        
  1388.         if (now - recentWhen > 180 * 86400) then
  1389.             AUCTIONATOR_PRICING_HISTORY[itemName] = nil;
  1390.             --zc.md (itemName, "   ", date("%A, %B %d %Y", recentWhen));
  1391.             x = x + 1;
  1392.         end
  1393.        
  1394.         total = total + 1;
  1395.     end
  1396.    
  1397.     collectgarbage  ("collect");
  1398.    
  1399.     if (x > 0) then
  1400.         zc.md (x, "of", total, "items pruned from post DB");
  1401.     end
  1402. end
  1403.  
  1404. -----------------------------------------
  1405.  
  1406. function Atr_MigtrateMaxHistAge()       -- 21 was too much
  1407.  
  1408.     if (AUCTIONATOR_DB_MAXHIST_AGE and AUCTIONATOR_DB_MAXHIST_AGE ~= 21 and AUCTIONATOR_DB_MAXHIST_AGE ~= -1) then
  1409.         zz ("AUCTIONATOR_DB_MAXHIST_AGE:", AUCTIONATOR_DB_MAXHIST_AGE, "AUCTIONATOR_DB_MAXHIST_DAYS:", AUCTIONATOR_DB_MAXHIST_DAYS)
  1410.         AUCTIONATOR_DB_MAXHIST_DAYS = AUCTIONATOR_DB_MAXHIST_AGE;
  1411.     end
  1412.        
  1413.     AUCTIONATOR_DB_MAXHIST_AGE = -1;
  1414. end
  1415.  
  1416. -----------------------------------------
  1417.  
  1418. function Atr_PruneScanDB(verbose)
  1419.  
  1420.     local start = time();
  1421.  
  1422.     collectgarbage  ("collect");
  1423.  
  1424.     local startMem = Atr_GetAuctionatorMemString();
  1425.  
  1426.     local dbCopy = {};
  1427.  
  1428.     local todayDays = Atr_GetScanDay_Today();
  1429.  
  1430.     Atr_MigtrateMaxHistAge();
  1431.  
  1432.     local histCutoff    = todayDays - AUCTIONATOR_DB_MAXHIST_DAYS;
  1433.     local itemCutoff    = todayDays - AUCTIONATOR_DB_MAXITEM_AGE;
  1434.    
  1435.     local x = 0;
  1436.     local h = 0;
  1437.     local y = 0;
  1438.     local z = 0;
  1439.    
  1440.     local key, price, char1, day, doCopy;
  1441.  
  1442.     if (gAtr_ScanDB and type (gAtr_ScanDB) ~= "table") then
  1443.         zc.msg_badErr ("Scanning history database appears to be corrupt")
  1444.         zc.msg_badErr ("gAtr_ScanDB:", gAtr_ScanDB)
  1445.         return
  1446.     end
  1447.    
  1448.     for itemName, info in pairs (gAtr_ScanDB) do
  1449.    
  1450.         local mostRecentDay = -1;
  1451.        
  1452.         -- first pass over item
  1453.        
  1454.         for key, price in pairs (info) do
  1455.             char1 = string.sub (key, 1, 1);
  1456.             if (char1 == "H") then
  1457.                 day = tonumber (string.sub(key, 2));
  1458.                 mostRecentDay   = math.max (day, mostRecentDay);
  1459.             end
  1460.         end
  1461.        
  1462.         -- decide if the item should be retained
  1463.        
  1464.         if (mostRecentDay == -1 or mostRecentDay >= itemCutoff) then
  1465.        
  1466.             dbCopy[itemName] = {};
  1467.             y = y + 1;
  1468.            
  1469.             for key, price in pairs (info) do           -- second pass over item
  1470.                 doCopy = true;
  1471.                
  1472.                 char1 = string.sub (key, 1, 1);
  1473.                 if (char1 == "H" or char1 == "L") then
  1474.                     day = tonumber (string.sub(key, 2));
  1475.                     if (day < histCutoff and day ~= mostRecentDay) then
  1476.                         doCopy = false;
  1477.                         h = h + 1;
  1478.                     end
  1479.                 end
  1480.                
  1481.                 if (doCopy) then
  1482.                     dbCopy[itemName][key] = price;
  1483.                     z = z + 1;
  1484.                 end
  1485.             end
  1486.         else
  1487.             x = x + 1;
  1488.         end
  1489.        
  1490.        
  1491.     end
  1492.  
  1493.     zc.ClearTable (gAtr_ScanDB);
  1494.     zc.CopyDeep (gAtr_ScanDB, dbCopy);
  1495.    
  1496.     dbCopy = nil;
  1497.    
  1498.     collectgarbage  ("collect");
  1499.  
  1500.     if (verbose or Atr_IsDev) then
  1501.         local endMem = Atr_GetAuctionatorMemString();
  1502. --      zc.msg_anm ("Memory usage went from", startMem, "to", endMem);
  1503.     end
  1504.  
  1505. --  zc.md ("Historical prices pruned: ", h, "out of", h+z, "   Items pruned: ", x, "out of", x+y, "   Time taken: ", time() - start);
  1506.    
  1507. end
  1508.  
  1509. -----------------------------------------
  1510.  
  1511. function Atr_BuildSortedScanHistoryList (itemName)
  1512.  
  1513.     local currentPane = Atr_GetCurrentPane();
  1514.    
  1515.     local todayScanDay = Atr_GetScanDay_Today();
  1516.    
  1517.     -- build the sorted history list
  1518.  
  1519.     currentPane.sortedHist = {};
  1520.  
  1521.     if (gAtr_ScanDB[itemName]) then
  1522.         local n = 1;
  1523.         local key, highlowprice, char1, day, when;
  1524.         for key, highlowprice in pairs (gAtr_ScanDB[itemName]) do
  1525.        
  1526.             char1 = string.sub (key, 1, 1);
  1527.        
  1528.             if (char1 == "H") then
  1529.  
  1530.                 day = tonumber (string.sub(key, 2));
  1531.  
  1532.                 when = gScanHistDayZero + (day *86400);
  1533.  
  1534.                 local lowlowprice = gAtr_ScanDB[itemName]["L"..day];
  1535.                 if (lowlowprice == nil) then
  1536.                     lowlowprice = highlowprice;
  1537.                 end
  1538.  
  1539.                 highlowprice = tonumber (highlowprice)
  1540.                 lowlowprice  = tonumber (lowlowprice)
  1541.  
  1542.                 currentPane.sortedHist[n]               = {};
  1543.                 currentPane.sortedHist[n].itemPrice     = zc.round ((highlowprice + lowlowprice) / 2);
  1544.                 currentPane.sortedHist[n].when          = when;
  1545.                 currentPane.sortedHist[n].yours         = true;
  1546.                 currentPane.sortedHist[n].type          = "n";
  1547.  
  1548.                 if (day == todayScanDay) then
  1549.                     currentPane.sortedHist[n].whenText = ZT("Today");
  1550.                 elseif (day == todayScanDay - 1) then
  1551.                     currentPane.sortedHist[n].whenText = ZT("Yesterday");
  1552.                 else
  1553.                     currentPane.sortedHist[n].whenText = date("%A, %B %d", when);
  1554.                 end
  1555.                
  1556.                 n = n + 1;
  1557.             end
  1558.         end
  1559.     end
  1560.  
  1561.     table.sort (currentPane.sortedHist, Atr_SortHistoryData);
  1562.  
  1563.     if (#currentPane.sortedHist > 0) then
  1564.         return currentPane.sortedHist[1].itemPrice;
  1565.     end
  1566.  
  1567. end
  1568.  
  1569. -----------------------------------------
  1570.  
  1571. function Atr_GetScanDay_Today()
  1572.  
  1573.     return (math.floor ((time() - gScanHistDayZero) / (86400)));
  1574.  
  1575. end
  1576.  
  1577. -----------------------------------------
  1578.  
  1579. function Atr_GetNumAuctionItems (which)
  1580.  
  1581.     local numBatchAuctions, totalAuctions = GetNumAuctionItems(which);
  1582.    
  1583.     local returnTotalAuctions = totalAuctions
  1584.    
  1585.     if (totalAuctions > 500000 or totalAuctions < 0) then
  1586.         totalAuctions = numBatchAuctions;
  1587.     end
  1588.    
  1589.     return numBatchAuctions, totalAuctions, returnTotalAuctions
  1590.  
  1591. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement