From 2ec84d7b896106cb8592221f3a353dc44a40d4f9 Mon Sep 17 00:00:00 2001 From: Kevin Lyles Date: Sat, 17 Sep 2011 16:33:19 -0500 Subject: [PATCH] Enabled 4 parallel tooltips for item scanning --- ItemScanner.lua | 124 +++++++++++++++++++++++++++++++++++++------------------ ItemScanner.xml | 2 +- 2 files changed, 84 insertions(+), 42 deletions(-) diff --git a/ItemScanner.lua b/ItemScanner.lua index ddee57b..72ffa1e 100644 --- a/ItemScanner.lua +++ b/ItemScanner.lua @@ -1,7 +1,8 @@ local minItem, maxItem, chunkSize = 1, 99999, 20000 local CONSECUTIVE_INVALID_TO_IGNORE = 5 local VALID_DELAY = 0.025 -local INVALID_DELAY = 5 +local INVALID_DELAY = 10 +local NUM_THREADS = 4 local patterns = { "^Design:", @@ -22,21 +23,22 @@ local skippedLines = { "^Collected %(%d/%d%)$", } -local function scanItemLink(link) +local function scanItemLink(link, tooltip, threadNumber) local textL, textR + local tooltipName = tooltip:GetName() -- Populate hidden tooltip - ItemScannerHiddenTooltip:ClearLines() - ItemScannerHiddenTooltip:SetHyperlink(link) + tooltip:ClearLines() + tooltip:SetHyperlink(link) local startTime = GetTime() local isPattern, hasReq = false, false while true do - local numLines = ItemScannerHiddenTooltip:NumLines() + local numLines = tooltip:NumLines() local done = numLines > 1 if done then if not isPattern then - local text = _G["ItemScannerHiddenTooltipTextLeft1"]:GetText() + local text = _G[tooltipName .. "TextLeft1"]:GetText() for _, pattern in ipairs(patterns) do if text:find(pattern) then isPattern = true @@ -46,7 +48,7 @@ local function scanItemLink(link) end -- We can skip the first line because it will only be RETRIEVING_ITEM_INFO if we only have one line for i = 2, numLines do - local text = _G["ItemScannerHiddenTooltipTextLeft" .. i]:GetText() + local text = _G[tooltipName .. "TextLeft" .. i]:GetText() if text:find(RETRIEVING_ITEM_INFO) then done = false break @@ -74,7 +76,7 @@ local function scanItemLink(link) end end - if IS_item_info[link] and #(IS_item_info[link]) >= ItemScannerHiddenTooltip:NumLines() then + if IS_item_info[link] and #(IS_item_info[link]) >= tooltip:NumLines() then return true end @@ -89,9 +91,9 @@ local function scanItemLink(link) harmful = IsHarmfulItem(link), } local numSkipped = 0 - for i = 1, ItemScannerHiddenTooltip:NumLines() do - textL = _G["ItemScannerHiddenTooltipTextLeft" .. i]:GetText() - textR = _G["ItemScannerHiddenTooltipTextRight" .. i]:GetText() + for i = 1, tooltip:NumLines() do + textL = _G[tooltipName .. "TextLeft" .. i]:GetText() + textR = _G[tooltipName .. "TextRight" .. i]:GetText() local skip = false for _, pattern in ipairs(skippedLines) do if textL:find(pattern) then @@ -100,7 +102,7 @@ local function scanItemLink(link) break end end - if not skip and (i ~= ItemScannerHiddenTooltip:NumLines() or (textL ~= " " and textL ~= "" and textR ~= " " and textR ~= "")) then + if not skip and (i ~= tooltip:NumLines() or (textL ~= " " and textL ~= "" and textR ~= " " and textR ~= "")) then IS_item_info[link][i - numSkipped] = { left = textL, right = textR, @@ -112,17 +114,33 @@ local function scanItemLink(link) end local frame = CreateFrame("Frame") +local nextSlot = 1 local function OnUpdate(self) local status, err if self.itemco then - status, err = pcall(self.itemco) - if status == false then - print("ItemScanner: item scan error, aborting.") - self.itemco = nil - IS_status.items.scan_active = false - error(err) - return - elseif err == true then + if nextSlot > #(self.itemco) then + nextSlot = 1 + end + if self.itemco[nextSlot] then + status, err = pcall(self.itemco[nextSlot]) + if status == false then + print("ItemScanner: item scan error, aborting thread " .. nextSlot .. ".") + table.remove(self.itemco, nextSlot) + if #(self.itemco) == 0 then + IS_status.items.scan_active = false + self.itemco = nil + end + error(err) + return + elseif err == true then + table.remove(self.itemco, nextSlot) + if #(self.itemco) == 0 then + self.itemco = nil + end + return + end + nextSlot = nextSlot + 1 + else self.itemco = nil end else @@ -130,20 +148,26 @@ local function OnUpdate(self) end end -local function itemParseCoroutine(start) - local chunkStart, chunkEnd = chunkSize * math.floor(start / chunkSize), chunkSize * math.floor((start + chunkSize) / chunkSize) - 1 - IS_status.items.scan_active = true - IS_status.items.finished = false - coroutine.yield() - local startTime = GetTime() - local roundStartTime = startTime - local numProcessed, roundNumProcessed, valid, roundValid = 0, 0, 0, 0 - print(string.format("ItemScanner: starting scan at item %d", start)) +local startTime, roundStartTime, numProcessed, roundNumProcessed, valid, roundValid, chunkStart, chunkEnd +local function itemParseCoroutine(start, tooltip, threadNumber) + if threadNumber == 1 then + chunkStart, chunkEnd = chunkSize * math.floor(start / chunkSize), chunkSize * math.floor((start + chunkSize) / chunkSize) - 1 + IS_status.items.scan_active = true + IS_status.items.finished = false + coroutine.yield() + startTime = GetTime() + roundStartTime = startTime + IS_status.items.last_scanned = start - 1 + numProcessed, roundNumProcessed, valid, roundValid = 0, 0, 0, 0 + print(string.format("ItemScanner: starting scan at item %d", start)) + else + coroutine.yield() + end local function scan(i, scanningAll) IS_status.items.last_scanned = i local itemStartTime = GetTime() - if scanItemLink("item:" .. i .. ":0:0:0:0:0:0:0:85") then + if scanItemLink("item:" .. i .. ":0:0:0:0:0:0:0:85", tooltip, threadNumber) then if scanningAll then if IS_status.items.invalid[i] ~= false then valid, roundValid = valid + 1, roundValid + 1 @@ -175,15 +199,24 @@ local function itemParseCoroutine(start) end end - for i = start, math.min(chunkEnd, maxItem) do - if not IS_status.items.invalid[i] or (type(IS_status.items.invalid[i]) == "number" and IS_status.items.invalid[i] < CONSECUTIVE_INVALID_TO_IGNORE) then - scan(i, false) - if not IS_status.items.scan_active then + while IS_status.items.scan_active and not IS_status.items.finished do + local i = IS_status.items.last_scanned + if i == nil then + break + end + repeat + i = i + 1 + if i > chunkEnd or i > maxItem then + IS_status.items.finished = true break end + until not IS_status.items.invalid[i] or (type(IS_status.items.invalid[i]) == "number" and IS_status.items.invalid[i] < CONSECUTIVE_INVALID_TO_IGNORE) + if IS_status.items.finished then + break end + scan(i, false) end - IS_status.items.finished = true + local chunkName = chunkStart .. "-" .. chunkEnd while IS_status.items.scan_active do local i = (IS_status.items.last_invalid[chunkName] or chunkStart - 1) @@ -197,11 +230,13 @@ local function itemParseCoroutine(start) scan(i, true) end - local elapsedTime = GetTime() - startTime - if elapsedTime == 0 then - elapsedTime = 0.001 + if threadNumber == 1 then + local elapsedTime = GetTime() - startTime + if elapsedTime == 0 then + elapsedTime = 0.001 + end + print(string.format("ItemScanner: scan stopped at item %d, %d in %.1f sec. (%.2f/min.) (%d valid)", IS_status.items.last_scanned, numProcessed, elapsedTime, numProcessed / elapsedTime * 60, valid)) end - print(string.format("ItemScanner: scan stopped at item %d, %d in %.1f sec. (%.2f/min.) (%d valid)", IS_status.items.last_scanned, numProcessed, elapsedTime, numProcessed / elapsedTime * 60, valid)) return true end @@ -249,8 +284,15 @@ local function commandHandler(msg) return end - frame.itemco = coroutine.wrap(itemParseCoroutine) - frame.itemco(start) + frame.itemco = {} + for i = 1, NUM_THREADS do + local tooltip = _G["ItemScannerHiddenTooltip" .. i] + if not tooltip then + tooltip = CreateFrame("GameTooltip", "ItemScannerHiddenTooltip" .. i, nil, "ItemScannerHiddenTooltip") + end + table.insert(frame.itemco, coroutine.wrap(itemParseCoroutine)) + frame.itemco[i](start + i - 1, tooltip, i) + end frame:SetScript("OnUpdate", OnUpdate) else print("Usage: /is (or /itemscanner ") diff --git a/ItemScanner.xml b/ItemScanner.xml index 0b96ba0..7771c7e 100644 --- a/ItemScanner.xml +++ b/ItemScanner.xml @@ -1,7 +1,7 @@