-- $Revision: 206 $
-- Cauldron queue management functions
local L = LibStub("AceLocale-3.0"):GetLocale("Cauldron")
CauldronQueue = {};
--[[
The following table describes a queue item in the "main" and "intermediate"
sections of the queue:
queueItem = {
["name"] = "<name of skill>",
["icon"] = "<icon path>",
["tradeskill"] = "<name of tradeskill>",
["amount"] = <amount>,
["priority"] = <priority>,
["link"] = "<link>",
};
The following table describes a reagent needed by items in the queue.
reagent = {
["name"] = "<name of item>",
["icon"] = "<icon path>",
["amount"] = <amount>,
["tradeskill"] = "<tradeskill that caused this reagent to be listed>",
["link"] = "<link>",
};
--]]
function CauldronQueue:NewQueue()
local queue = {
["main"] = {},
["intermediate"] = {},
["reagents"] = {},
};
return queue;
end
function CauldronQueue:NewItem(name, icon, amount, priority, tradeskill, link, spell)
local queueItem = {
["name"] = name or "",
["icon"] = icon or "",
["tradeskill"] = tradeskill or "",
["link"] = link,
["amount"] = amount or 1,
["priority"] = priority or 0,
["spell"] = spell,
};
return queueItem;
end
function CauldronQueue:NewReagent(name, icon, amount, tradeskill, link)
local reagent = {
["name"] = name or "",
["icon"] = icon or "",
["amount"] = amount or 1,
["tradeskill"] = tradeskill,
["link"] = link,
};
return reagent;
end
function CauldronQueue:GetItems(queue)
-- sanity checks
if not queue then
Cauldron:error("GetItems: No queue found!");
return nil;
end
local items = {};
for _, item in pairs(queue.main) do
if item.amount > 0 then
table.insert(items, item);
end
end
-- sort the list
table.sort(items, function(r1, r2) return r2.priority < r1.priority; end);
return items;
end
function CauldronQueue:GetIntermediates(queue)
-- sanity checks
if not queue then
Cauldron:error("GetIntermediates: No queue found!");
return nil;
end
local items = {};
for _, item in pairs(queue.intermediate) do
-- if tradeskill then
-- if tradeskill == item.tradeskill then
-- table.insert(items, item);
-- end
-- else
local t = CopyTable(item);
local skillInfo = Cauldron:GetSkillInfo(t.tradeskill, t.name);
if skillInfo and (skillInfo.available > 0) then
-- increase the priority of items that can be crafted, so that they appear at the top of the list
t.priority = t.priority + 1000;
end
table.insert(items, t);
-- end
end
-- sort the list
table.sort(items, function(r1, r2) return r2.priority < r1.priority; end);
return items;
end
function CauldronQueue:GetReagents(queue)
-- sanity checks
if not queue then
Cauldron:error("GetReagents: No queue found!");
return nil;
end
local items = {};
for _, item in pairs(queue.reagents) do
-- if tradeskill then
-- if tradeskill == item.tradeskill then
-- table.insert(items, item);
-- end
-- else
table.insert(items, item);
-- end
end
return items;
end
function CauldronQueue:AddItem(queue, skillInfo, amount, suppressCalc)
-- sanity checks
if not queue then
Cauldron:error("AddItem: No queue found!");
return;
end
if not queue.main then
queue.main = {};
end
-- look for the item in the "main" section
local item = queue.main[skillInfo.name];
if item then
-- it's there, so increase the amount
item.amount = item.amount + amount;
else
-- it's not there, so create a new instance
Cauldron:debug("AddItem: recipeLink="..tostring(skillInfo.recipeLink));
queue.main[skillInfo.name] = CauldronQueue:NewItem(skillInfo.name, skillInfo.icon, amount, nil, skillInfo.tradeskill, skillInfo.itemLink, Cauldron:GetSpellNameFromLink(skillInfo.recipeLink));
end
if not suppressCalc then
CauldronQueue:CalculateAllRequiredItems(queue);
end
end
function CauldronQueue:CalculateAllRequiredItems(queue)
-- sanity checks
if not queue then
Cauldron:error("CalculateAllRequiredItems: No queue found!");
-- Cauldron:Print(debugstack(1));
return;
end
-- reset the intermediate and reagent lists
queue.intermediate = {};
queue.reagents = {};
-- iterate over the queued items
for name, queueInfo in pairs(queue.main) do
local skillInfo = Cauldron:GetSkillInfo(queueInfo.tradeskill, queueInfo.name);
CauldronQueue:CalculateRequiredItems(queue, skillInfo, queueInfo.amount, queueInfo.priority);
end
end
function CauldronQueue:CalculateRequiredItems(queue, skillInfo, amount, priority)
-- sanity checks
if not queue then
Cauldron:error("CalculateRequiredItems: No queue found!");
return;
end
-- get the intermediates and reagents for the item
local intermediates, reagents = Cauldron:GetRequiredItems(skillInfo, amount);
-- check the intermediate list; if the item is available somewhere (inventory, bank, alt, etc.)
-- then move it to the reagent list; otherwise, update the intermediate list in the queue
-- update the intermediate and reagent lists
for i, reagent in ipairs(intermediates) do
local count = Cauldron:ReagentCount(reagent.name);
if count.has >= reagent.numRequired then
-- add the item to the reagent list if the character has all the required amount
table.insert(reagents, reagent);
else
local amount = reagent.numRequired;
-- if the character has some, add that amount to the reagent list
if count.has > 0 then
-- create a reagent copy of the item
local newItem = CopyTable(reagent);
newItem.numRequired = count.has;
table.insert(reagents, newItem);
-- adjust item count to how many need to be crafted
amount = reagent.numRequired - count.has;
end
-- add the remaining amount to the intermediate list
if amount > 0 then
-- adjust the amount if the item produces more than one per execution
local intSkillInfo = Cauldron:GetSkillInfoForItem(reagent.name);
if intSkillInfo then
if intSkillInfo.minMade > 1 then
-- we ignore maxMade, since if it is greater than minMade, then the amount
-- produced is variable, so we err on the side of caution and account for
-- only ever making the minimum possible; besides, each execution of the
-- skill will cause the reagent list to be reassessed, so producing more
-- will be handled appropriately
amount = math.ceil(amount / intSkillInfo.minMade);
end
end
CauldronQueue:AddIntermediate(queue, reagent, amount, priority);
-- add the intermediate's reagents also
CauldronQueue:CalculateRequiredItems(queue, intSkillInfo, amount, priority);
end
end
end
for i, reagent in ipairs(reagents) do
local v = CauldronQueue:AddReagent(queue, reagent, reagent.numRequired, skillInfo.tradeskill, reagent.link);
if not v then
Cauldron:error("Failed to add reagent to queue; marking recipe for rescan: "..skillInfo.name);
Cauldron:MarkRecipeForRescan(Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[tradeskill], skillInfo.name);
end
end
end
function CauldronQueue:AddIntermediate(queue, reagent, amount, priority)
-- sanity checks
if not queue then
Cauldron:error("AddIntermediate: No queue found!");
return false;
end
amount = math.max(0, tonumber(amount) or 0);
if not queue.intermediate then
queue.intermediate = {};
end
-- look for the item in the "intermediate" section
local item = queue.intermediate[reagent.name];
if item then
-- it's there, so increase the amount
item.amount = item.amount + amount;
else
-- it's not there, so create a new instance
if reagent.name then
local skillInfo = Cauldron:GetSkillInfoForItem(reagent.name);
if skillInfo then
local newItem = CauldronQueue:NewItem(reagent.name, reagent.icon, amount, nil, skillInfo.tradeskill, reagent.link, Cauldron:GetNameFromLink(skillInfo.recipeLink));
newItem.priority = priority or 0;
queue.intermediate[reagent.name] = newItem;
else
Cauldron:error("AddIntermediate: no skill info found for reagent: "..reagent.name);
return false;
end
else
-- this shouldn't occur unless there's something wrong with the reagent info, but if it does, the user can report this error
Cauldron:error("AddIntermediate: reagent.name is nil! Please report this. (skillIndex: "..reagent.skillIndex..", index: "..reagent.index..")");
return false;
end
end
return true;
end
function CauldronQueue:AddReagent(queue, reagent, amount, tradeskill)
-- sanity checks
if not queue then
Cauldron:error("AddReagent: No queue found!");
return false;
end
amount = math.max(1, tonumber(amount) or 1);
if not queue.reagents then
queue.reagents = {};
end
-- look for the item in the "reagents" section
local item = queue.reagents[reagent.name];
if item then
-- it's there, so increase the amount
item.amount = (tonumber(item.amount) or 0) + amount;
else
-- it's not there, so create a new instance
if reagent.name then
queue.reagents[reagent.name] = CauldronQueue:NewReagent(reagent.name, reagent.icon, amount, tradeskill, reagent.link);
else
-- this shouldn't occur unless there's something wrong with the reagent info, but if it does, the user can report this error
Cauldron:error("AddReagent: reagent.name is nil!");
return false;
end
end
return true;
end
function CauldronQueue:AdjustItemCount(queue, name, delta)
-- sanity checks
if not queue then
Cauldron:error("AdjustItemCount: No queue found!");
return;
end
local item = queue.main[name];
--[[
for qName, qInfo in pairs(queue.main) do
local qItem = Cauldron:GetNameFromLink(qInfo.link);
if name == qItem then
item = qInfo;
break;
end
end
--]]
-- check for a mapped item, like "perfect" gem cuts, etc.
--[[ TODO
if not item then
local map = Cauldron.vars.results[Cauldron:GetIdFromLink()];
end
--]]
Cauldron:debug("AdjustItemCount: item="..tostring(item));
if item then
Cauldron:debug("AdjustItemCount: item.amount="..item.amount);
item.amount = item.amount + delta;
Cauldron:debug("AdjustItemCount: item.amount(delta)="..item.amount);
if item.amount < 1 then
Cauldron:debug("AdjustItemCount: remove item: "..name);
queue.main[name] = nil;
end
end
Cauldron:debug("AdjustItemCount: calculate required items");
CauldronQueue:CalculateAllRequiredItems(queue);
end
function CauldronQueue:RemoveItem(queue, itemName)
Cauldron:debug("RemoveItem enter");
-- sanity checks
if (not queue) and (not itemName) then
Cauldron:error("RemoveItem: No queue or item name found!");
return;
end
if queue.main[itemName] then
queue.main[itemName] = nil;
CauldronQueue:CalculateAllRequiredItems(queue);
end
Cauldron:debug("RemoveItem exit");
end
function CauldronQueue:IncreasePriority(queue, itemName, top)
Cauldron:debug("IncreasePriority enter");
-- sanity checks
if (not queue) and (not itemName) then
Cauldron:error("IncreasePriority: No queue or item name found!");
return;
end
local item = queue.main[itemName];
if item then
local priority = item.priority + 1;
local highest = 0;
if top then
for _, info in pairs(queue.main) do
if info.priority > highest then
highest = info.priority;
end
end
priority = highest + 1;
end
item.priority = priority;
end
Cauldron:debug("IncreasePriority exit");
end
function CauldronQueue:DecreasePriority(queue, itemName, bottom)
Cauldron:debug("DecreasePriority enter");
-- sanity checks
if (not queue) and (not itemName) then
Cauldron:error("DecreasePriority: No queue or item name found!");
return;
end
local item = queue.main[itemName];
if item then
local priority = item.priority - 1;
local lowest = 0;
if top then
for _, info in pairs(queue.main) do
if info.priority < lowest then
lowest = info.priority;
end
end
priority = lowest - 1;
end
item.priority = priority;
end
Cauldron:debug("DecreasePriority exit");
end
function CauldronQueue:ClearQueue(queue)
Cauldron:debug("ClearQueue enter");
-- sanity checks
if not queue then
Cauldron:error("ClearQueue: No queue found!");
return;
end
--[[
if tradeskill then
Cauldron:debug("ClearQueue: clearing tradeskill: "..tradeskill);
-- set aside the current main queue
Cauldron:debug("ClearQueue: set aside main table");
local main = queue.main;
-- clear out the tables
Cauldron:debug("ClearQueue: clear out tables");
queue.main = {};
-- iterate over the items and re-add the ones not for the specified tradeskill
Cauldron:debug("ClearQueue: iterate over items");
for i, item in ipairs(main) do
Cauldron:debug("ClearQueue: item: "..i);
if item.tradeskill ~= tradeskill then
-- get the skill for the item
Cauldron:debug("ClearQueue: item.tradeskill: "..item.tradeskill);
local skillInfo = Cauldron:GetSkillInfo(item.tradeskill, item.name);
-- recalculate
Cauldron:debug("ClearQueue: recalculate");
CauldronQueue:AddItem(queue, skillInfo, item.amount, true);
end
end
CauldronQueue:CalculateAllRequiredItems(queue);
else
--]]
queue.main = {};
queue.intermediate = {};
queue.reagents = {};
Cauldron:debug("ClearQueue exit");
end
function CauldronQueue:GetIntermediateItem(queue, itemName)
-- sanity checks
if not queue then
Cauldron:error("GetIntermediateItem: No queue found!");
return nil;
end
return queue.intermediate[itemName];
end
function CauldronQueue:GetReagentItem(queue, itemName)
-- sanity checks
if not queue then
Cauldron:error("GetReagentItem: No queue found!");
return nil;
end
return queue.reagents[itemName];
end