changeset 0:ec731d2fe6ba

Version 1.2.12.0
author Adam tegen <adam.tegen@gmail.com>
date Tue, 20 May 2014 21:43:23 -0500
parents
children ec3e67868c5c
files AskMrRobot.lua AskMrRobot.toc AskMrRobot.xml AskMrRobotUi.lua Media/AddonExport.tga Media/BiBScreen.tga Media/icon.tga Media/round-edge-big.tga Media/round-edge.tga Media/square-edge.tga config.lua enchants.lua gems.lua libs/CallbackHandler-1.0/CallbackHandler-1.0.lua libs/CallbackHandler-1.0/CallbackHandler-1.0.xml libs/LibDBIcon-1.0/LibDBIcon-1.0.lua libs/LibDataBroker-1.1/LibDataBroker-1.1.lua libs/LibDataBroker-1.1/README.textile libs/LibStub/LibStub.lua libs/LibStub/LibStub.toc libs/LibStub/tests/test.lua libs/LibStub/tests/test2.lua libs/LibStub/tests/test3.lua libs/LibStub/tests/test4.lua sort.lua ui/CombatLogTab.lua ui/Components.lua ui/EnchantLinkText.lua ui/EnchantTab.lua ui/ExportTab.lua ui/GemIcon.lua ui/GemTab.lua ui/HelpTab.lua ui/ImportTab.lua ui/ItemIcon.lua ui/ItemLinkText.lua ui/ItemTooltipFrame.lua ui/JewelPanel.lua ui/ReforgesTab.lua ui/RobotStamp.lua ui/ShoppingListTab.lua ui/SummaryTab.lua wait.lua
diffstat 43 files changed, 13643 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AskMrRobot.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,1245 @@
+local _, AskMrRobot = ...
+
+AskMrRobot.eventListener = CreateFrame("FRAME"); -- Need a frame to respond to events
+AskMrRobot.eventListener:RegisterEvent("ADDON_LOADED"); -- Fired when saved variables are loaded
+AskMrRobot.eventListener:RegisterEvent("ITEM_PUSH");
+AskMrRobot.eventListener:RegisterEvent("DELETE_ITEM_CONFIRM");
+AskMrRobot.eventListener:RegisterEvent("UNIT_INVENTORY_CHANGED");
+AskMrRobot.eventListener:RegisterEvent("BANKFRAME_OPENED");
+AskMrRobot.eventListener:RegisterEvent("BANKFRAME_CLOSED");
+AskMrRobot.eventListener:RegisterEvent("PLAYERBANKSLOTS_CHANGED");
+AskMrRobot.eventListener:RegisterEvent("CHARACTER_POINTS_CHANGED");
+AskMrRobot.eventListener:RegisterEvent("CONFIRM_TALENT_WIPE");
+AskMrRobot.eventListener:RegisterEvent("PLAYER_TALENT_UPDATE");
+AskMrRobot.eventListener:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED");
+AskMrRobot.eventListener:RegisterEvent("PLAYER_LOGOUT"); -- Fired when about to log out
+AskMrRobot.eventListener:RegisterEvent("PLAYER_LEVEL_UP");
+--AskMrRobot.eventListener:RegisterEvent("GET_ITEM_INFO_RECEIVED")
+AskMrRobot.eventListener:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED")
+AskMrRobot.eventListener:RegisterEvent("SOCKET_INFO_UPDATE")
+AskMrRobot.eventListener:RegisterEvent("SOCKET_INFO_CLOSE")
+AskMrRobot.eventListener:RegisterEvent("BAG_UPDATE")
+AskMrRobot.eventListener:RegisterEvent("ITEM_UNLOCKED")
+--AskMrRobot.eventListener:RegisterEvent("PLAYER_REGEN_DISABLED")
+AskMrRobot.eventListener:RegisterEvent("ENCOUNTER_START")
+AskMrRobot.eventListener:RegisterEvent("CHAT_MSG_ADDON")
+AskMrRobot.eventListener:RegisterEvent("UPDATE_INSTANCE_INFO")
+AskMrRobot.eventListener:RegisterEvent("PLAYER_DIFFICULTY_CHANGED")
+
+AskMrRobot.AddonName = ...
+AskMrRobot.ChatPrefix = "_AMR"
+
+local amrLDB
+local icon
+local reforgequeue
+local reforgeFrame = nil
+local LoggingCombat = _G.LoggingCombat
+
+AskMrRobot.itemDiffs = {
+	items = {},    -- slotNum -> nil (no change) or current <item id>, optimized <item id>
+	enchants = {}, -- slotNum -> nil (no change) or current <enchant id>, optimized <enchant id>
+	gems = {},     -- slotNum -> nil (no change) or ?
+	reforges = {}   -- slotNum -> nil (no change) or current <reforge id>, optimized <reforge id>
+}
+
+AskMrRobot.instanceIds = {
+	HeartOfFear = 1009,
+	MogushanVaults = 1008,	
+	SiegeOfOrgrimmar = 1136,
+	TerraceOfEndlessSpring = 996,
+	ThroneOfThunder = 1098
+}
+
+-- upgrade id -> upgrade level
+local upgradeTable = {
+  [0]   =  0,
+  [1]   =  1, -- 1/1 -> 8
+  [373] =  1, -- 1/2 -> 4
+  [374] =  2, -- 2/2 -> 8
+  [375] =  1, -- 1/3 -> 4
+  [376] =  2, -- 2/3 -> 4
+  [377] =  3, -- 3/3 -> 4
+  [378] =  1, -- 1/1 -> 7
+  [379] =  1, -- 1/2 -> 4
+  [380] =  2, -- 2/2 -> 4
+  [445] =  0, -- 0/2 -> 0
+  [446] =  1, -- 1/2 -> 4
+  [447] =  2, -- 2/2 -> 8
+  [451] =  0, -- 0/1 -> 0
+  [452] =  1, -- 1/1 -> 8
+  [453] =  0, -- 0/2 -> 0
+  [454] =  1, -- 1/2 -> 4
+  [455] =  2, -- 2/2 -> 8
+  [456] =  0, -- 0/1 -> 0
+  [457] =  1, -- 1/1 -> 8
+  [458] =  0, -- 0/4 -> 0
+  [459] =  1, -- 1/4 -> 4
+  [460] =  2, -- 2/4 -> 8
+  [461] =  3, -- 3/4 -> 12
+  [462] =  4, -- 4/4 -> 16
+  [465] =  0, -- 0/2 -> 0
+  [466] =  1, -- 1/2 -> 4
+  [467] =  2, -- 2/2 -> 8
+  [468] =  0, -- 0/4 -> 0
+  [469] =  1, -- 1/4 -> 4
+  [470] =  2, -- 2/4 -> 8
+  [471] =  3, -- 3/4 -> 12
+  [472] =  4, -- 4/4 -> 16
+  [476] =  0, -- ? -> 0
+  [479] =  0, -- ? -> 0
+  [491] =  0, -- ? -> 0
+  [492] =  1, -- ? -> 0
+  [493] =  2, -- ? -> 0
+  [494] = 0,
+  [495] = 1,
+  [496] = 2,
+  [497] = 3,
+  [498] = 4,
+  [504] = 3,
+  [505] = 4
+}
+
+local professionIds = {
+    ["None"] = 0,
+    ["Mining"] = 1,
+    ["Skinning"] = 2,
+    ["Herbalism"] = 3,
+    ["Enchanting"] = 4,
+    ["Jewelcrafting"] = 5,
+    ["Engineering"] = 6,
+    ["Blacksmithing"] = 7,
+    ["Leatherworking"] = 8,
+    ["Inscription"] = 9,
+    ["Tailoring"] = 10,
+    ["Alchemy"] = 11,
+    ["Fishing"] = 12,
+    ["Cooking"] = 13,
+    ["First Aid"] = 14,
+    ["Archaeology"] = 15
+}
+
+local raceIds = {
+    ["None"] = 0,
+    ["BloodElf"] = 1,
+    ["Draenei"] = 2,
+    ["Dwarf"] = 3,
+    ["Gnome"] = 4,
+    ["Human"] = 5,
+    ["NightElf"] = 6,
+    ["Orc"] = 7,
+    ["Tauren"] = 8,
+    ["Troll"] = 9,
+    ["Scourge"] = 10,
+    ["Undead"] = 10,
+    ["Goblin"] = 11,
+    ["Worgen"] = 12,
+    ["Pandaren"] = 13
+}
+
+local factionIds = {
+    ["None"] = 0,
+    ["Alliance"] = 1,
+    ["Horde"] = 2
+}
+
+local function OnExport()
+    if (AmrOptions.exportToClient) then
+        AskMrRobot.SaveAll()
+        ReloadUI()
+    else
+        AskMrRobot_ReforgeFrame:Show()
+        AskMrRobot_ReforgeFrame:ShowTab("export")
+    end
+end
+
+function AskMrRobot.eventListener:OnEvent(event, ...)
+	if event == "ADDON_LOADED" then
+        local addon = select(1, ...)
+        if (addon == "AskMrRobot") then
+            print("Loaded Ask Mr. Robot " .. GetAddOnMetadata(AskMrRobot.AddonName, "Version"))
+            
+            -- listen for messages from other AMR addons
+            RegisterAddonMessagePrefix(AskMrRobot.ChatPrefix)
+            
+            AmrRealmName = GetRealmName()
+            AmrCharacterName = UnitName("player")
+
+            if not AmrLogData then AmrLogData = {} end
+			if not AmrLogData._autoLog then AmrLogData._autoLog = {} end
+			if not AmrLogData._autoLog[AskMrRobot.instanceIds.SiegeOfOrgrimmar] then 
+				AmrLogData._autoLog[AskMrRobot.instanceIds.SiegeOfOrgrimmar] = "disabled" 
+			end
+
+            if not AmrIconInfo then AmrIconInfo = {} end
+            if not AmrBankItems then AmrBankItems = {} end
+            if not AmrCurrencies then AmrCurrencies = {} end
+            if not AmrSpecializations then AmrSpecializations = {} end
+            if not AmrOptions then AmrOptions = {} end
+            if not AmrGlyphs then AmrGlyphs = {} end
+            if not AmrTalents then AmrTalents = {} end
+            if not AmrBankItemsAndCounts then AmrBankItemsAndCounts = {} end
+            if not AmrImportString then AmrImportString = "" end
+            if not AmrImportDate then AmrImportDate = "" end
+            if not AmrSendSettings then
+                AmrSendSettings = {
+                    SendGems = true,
+                    SendEnchants = true,
+                    SendEnchantMaterials = true,
+                    SendToType = "a friend",
+                    SendTo = ""
+                }
+            end
+
+            amrLDB = LibStub("LibDataBroker-1.1"):NewDataObject("AskMrRobot", {
+                type = "launcher",
+                text = "Ask Mr. Robot",
+                icon = "Interface\\AddOns\\AskMrRobot\\Media\\icon",
+                OnClick = function()
+
+                    if IsModifiedClick("CHATLINK") then
+                        OnExport()
+                    else
+                        AskMrRobot_ReforgeFrame:Toggle()
+                    end
+                end,
+                OnTooltipShow = function(tt)
+                    tt:AddLine("Ask Mr. Robot", 1, 1, 1);
+                    tt:AddLine(" ");
+                    tt:AddLine("Left Click to open the Ask Mr. Robot window.\n\nShift + Left Click to export your bag and bank data.")
+                end	
+            });
+
+
+            AskMrRobot.AmrUpdateMinimap()
+
+            AskMrRobot_ReforgeFrame = AskMrRobot.AmrUI:new()
+
+            -- remember the import settings between sessions
+            AskMrRobot_ReforgeFrame.summaryTab.importDate = AmrImportDate or ""
+            AskMrRobot_ReforgeFrame.buttons[2]:Click()
+            
+            -- the previous import string is loaded when the UI is first shown, otherwise the game spams events and it lags
+        end
+        
+	elseif event == "ITEM_PUSH" or event == "DELETE_ITEM_CONFIRM" or event == "UNIT_INVENTORY_CHANGED" or event == "SOCKET_INFO_CLOSE" or event == "PLAYER_SPECIALIZATION_CHANGED" or event == "BAG_UPDATE" then
+		if AskMrRobot_ReforgeFrame then
+			AskMrRobot_ReforgeFrame:OnUpdate()
+		end
+		--AskMrRobot.SaveBags();
+		--AskMrRobot.SaveEquiped();
+		--AskMrRonot.GetCurrencies();
+		--AskMrRobot.GetGold();
+	elseif event == "BANKFRAME_OPENED" or event == "PLAYERBANKSLOTS_CHANGED" then 
+		--print("Scanning Bank: " .. event);
+		AskMrRobot.ScanBank();
+	elseif event == "BANKFRAME_CLOSED" then
+		--print("Stop Scanning Bank");
+		--inBank = false;
+	elseif event == "CHARACTER_POINTS_CHANGED" or event == "CONFIRM_TALENT_WIPE" or event == "PLAYER_TALENT_UPDATE" or event == "ACTIVE_TALENT_GROUP_CHANGED" then
+		--AskMrRobot.GetAmrSpecializations();
+		if AskMrRobot_ReforgeFrame then
+			AskMrRobot_ReforgeFrame:OnUpdate()
+		end
+	elseif event == "PLAYER_LEVEL_UP" then
+		--GetLevel();
+	elseif event == "ITEM_UNLOCKED" then
+		AskMrRobot.On_ITEM_UNLOCKED()
+	elseif event == "PLAYER_LOGOUT" then
+		-- doing nothing right now, but leaving this in case we need something here	
+    elseif event == "ENCOUNTER_START" then
+        -- send data about this character when a boss fight starts
+        AskMrRobot.SaveAll()
+        AskMrRobot.ExportToAddonChat(time())
+    elseif event == "CHAT_MSG_ADDON" then
+        local chatPrefix, message = select(1, ...)
+        local isLogging = AskMrRobot_ReforgeFrame.combatLogTab:IsLogging()        
+        if (isLogging and chatPrefix == AskMrRobot.ChatPrefix) then
+            AskMrRobot_ReforgeFrame.combatLogTab:ReadAddonMessage(message)
+        end
+    elseif event == "UPDATE_INSTANCE_INFO" or event == "PLAYER_DIFFICULTY_CHANGED" then
+    	AskMrRobot_ReforgeFrame.combatLogTab:UpdateAutoLogging()
+	end
+ 
+end
+
+AskMrRobot.eventListener:SetScript("OnEvent", AskMrRobot.eventListener.OnEvent);
+
+local function parseItemLink(input)
+	local itemId, enchantId, gemEnchantId1, gemEnchantId2, gemEnchantId3, gemEnchantId4, suffixId, _, _, reforgeId, upgradeId = string.match(input, "^|.-|Hitem:(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(-?%d+):(-?%d+):(-?%d+):(%d+):(%d+)|");
+	local item = {}
+	item.itemId = tonumber(itemId)
+	item.suffixId = tonumber(suffixId)
+	item.enchantId = tonumber(enchantId)
+	item.reforgeId = tonumber(reforgeId)
+	item.upgradeId = tonumber(upgradeId)
+	item.gemEnchantIds = { tonumber(gemEnchantId1), tonumber(gemEnchantId2), tonumber(gemEnchantId3), tonumber(gemEnchantId4) }
+	return item
+end
+
+SLASH_AMR1 = "/amr";
+function SlashCmdList.AMR(msg)
+
+	if msg == 'toggle' then
+		AskMrRobot_ReforgeFrame:Toggle()
+	elseif msg == 'show' then
+		AskMrRobot_ReforgeFrame:Show()
+	elseif msg == 'hide' then
+		AskMrRobot_ReforgeFrame:Hide()
+	elseif msg == 'export' then
+		OnExport()
+	else
+		print('Available AskMrRobot slash commands:\n' ..
+			'  /amr show   -- show the main window\n' ..
+			'  /amr hide   -- hide the main window\n' ..
+			'  /amr toggle -- toggle the main window\n' ..
+			'  /amr export -- export bag and bank data (uses your last selected method and either opens the copy/paste window, or saves and reloads ui)')
+	end
+end
+
+function AskMrRobot.SaveAll()
+	AskMrRobot.ScanBank()
+	AskMrRobot.SaveBags()
+	AskMrRobot.SaveEquiped()
+	AskMrRobot.GetCurrencies()
+	AskMrRobot.GetGold()
+	AskMrRobot.GetAmrSpecializations()
+	AskMrRobot.GetAmrProfessions()
+	AskMrRobot.GetRace()
+	AskMrRobot.GetLevel()
+	AskMrRobot.GetAmrGlyphs()
+	AskMrRobot.GetAmrTalents()
+	--ReloadUI()
+end
+
+local function InitIcon()
+	icon = LibStub("LibDBIcon-1.0");
+	icon:Register("AskMrRobot", amrLDB, AmrIconInfo);	
+end
+
+function AskMrRobot.AmrUpdateMinimap()
+	if (AmrOptions.hideMapIcon) then
+		if (icon) then
+			icon:Hide("AskMrRobot");
+		end
+	else
+		if (not icon) then 
+			InitIcon() 
+		end
+		icon:Show("AskMrRobot");
+	end
+end
+
+local function getToolTipText(tip)
+	return EnumerateTooltipLines_helper(tip:GetRegions())
+end
+
+local bagItems = {}
+local bagItemsWithCount = {}
+
+function AskMrRobot.ScanBag(bagId) 	
+	local numSlots = GetContainerNumSlots(bagId);
+	for slotId = 1, numSlots do
+		local _, itemCount, _, _, _, _, itemLink = GetContainerItemInfo(bagId, slotId);
+		if itemLink ~= nil then
+            local itemData = parseItemLink(itemLink)
+            if itemData.itemId ~= nil then
+                tinsert(bagItems, itemLink);
+                tinsert(bagItemsWithCount, {link = itemLink, count = itemCount})
+            end
+		end
+	end
+end
+
+local BACKPACK_CONTAINER = 0;
+local BANK_CONTAINER = -1;
+
+function AskMrRobot.ScanEquiped()
+	local equipedItems = {};
+	for slotNum = 1, #AskMrRobot.slotIds do
+		local slotId = AskMrRobot.slotIds[slotNum];
+		local itemLink = GetInventoryItemLink("player", slotId);
+		if (itemLink ~= nil) then
+			equipedItems[slotId .. ""] = itemLink;
+		end
+	end
+	return equipedItems
+end
+
+function AskMrRobot.SaveEquiped()
+	AmrEquipedItems = AskMrRobot.ScanEquiped();
+end
+
+function AskMrRobot.ScanBags()
+	bagItems = {}
+	bagItemsWithCount = {}
+
+	AskMrRobot.ScanBag(BACKPACK_CONTAINER); -- backpack
+	
+	for bagId = 1, NUM_BAG_SLOTS do
+		AskMrRobot.ScanBag(bagId);
+	end
+	
+
+	return bagItems, bagItemsWithCount
+end
+
+function AskMrRobot.SaveBags()
+	AmrBagItems, _ = AskMrRobot.ScanBags()
+end
+
+function AskMrRobot.GetGold()
+	AmrGold = GetMoney();
+end
+
+local lastBankBagId = nil;
+local lastBankSlotId = nil;
+local bankItems = {};
+local bankItemsAndCount = {};
+AmrBankItemsAndCounts = {};
+
+local function ScanBankBag(bagId)
+	local numSlots = GetContainerNumSlots(bagId);
+	for slotId = 1, numSlots do
+		local _, itemCount, _, _, _, _, itemLink = GetContainerItemInfo(bagId, slotId);
+		if itemLink ~= nil then
+            local itemData = parseItemLink(itemLink)
+            if itemData.itemId ~= nil then
+                lastBankBagId = bagId;
+                lastBankSlotId = slotId;
+                tinsert(bankItems, itemLink);						
+                tinsert(bankItemsAndCount, {link = itemLink, count = itemCount})
+            end
+		end
+	end
+end
+		
+function AskMrRobot.ScanBank()
+		
+	bankItems = {};
+	bankItemsAndCount = {}
+	
+	ScanBankBag(BANK_CONTAINER);
+	for bagId = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do
+		ScanBankBag(bagId);
+	end
+	
+	-- see if the scan completed before the window closed
+	if lastBankBagId ~= nil then
+		local itemLink = GetContainerItemLink(lastBankBagId, lastBankSlotId);
+		if itemLink ~= nil then --still open
+			AmrBankItems = bankItems;
+			AmrBankItemsAndCounts = bankItemsAndCount
+		end
+	end
+end
+
+local function GetCurrencyAmount(index)
+	local localized_label, amount, icon_file_name = GetCurrencyInfo(index);
+	return amount;
+end
+
+function AskMrRobot.GetCurrencies()
+	local currencies = {};
+	local currencyList = {61, 81, 241, 361, 384, 394, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 416, 515, 614, 615, 676, 679};
+
+	for i, currency in pairs(currencyList) do
+		local amount = GetCurrencyAmount(currency);
+		if amount ~= 0 then
+			currencies[currencyList[i]] = amount;
+		end
+	end
+	AmrCurrencies = currencies;
+end
+
+local function GetAmrSpecialization(specGroup)
+	local spec = GetSpecialization(false, false, specGroup);
+	return spec and GetSpecializationInfo(spec);
+end
+
+function AskMrRobot.GetAmrSpecializations()
+
+	AmrSpecializations = {};
+
+	AmrActiveSpec = GetActiveSpecGroup();
+
+	for group = 1, 2 do
+		AmrSpecializations[group .. ""] = GetAmrSpecialization(group)
+	end
+
+-- Death Knight 
+-- 250 - Blood
+-- 251 - Frost
+-- 252 - Unholy
+-- Druid 
+-- 102 - Balance
+-- 103 - Feral Combat
+-- 104 - Guardian
+-- 105 - Restoration
+-- Hunter 
+-- 253 - Beast Mastery
+-- 254 - Marksmanship
+-- 255 - Survival
+-- Mage 
+-- 62 - Arcane
+-- 63 - Fire
+-- 64 - Frost
+-- Monk 
+-- 268 - Brewmaster
+-- 269 - Windwalker
+-- 270 - Mistweaver
+-- Paladin 
+-- 65 - Holy
+-- 66 - Protection
+-- 70 - Retribution
+-- Priest 
+-- 256 Discipline
+-- 257 Holy
+-- 258 Shadow
+-- Rogue 
+-- 259 - Assassination
+-- 260 - Combat
+-- 261 - Subtlety
+-- Shaman 
+-- 262 - Elemental
+-- 263 - Enhancement
+-- 264 - Restoration
+-- Warlock 
+-- 265 - Affliction
+-- 266 - Demonology
+-- 267 - Destruction
+-- Warrior 
+-- 71 - Arms
+-- 72 - Fury
+-- 73 - Protection
+end
+
+function AskMrRobot.GetAmrProfessions()
+
+	local profMap = {
+		[794] = "Archaeology",
+		[171] = "Alchemy",
+		[164] = "Blacksmithing",
+		[185] = "Cooking",
+		[333] = "Enchanting",
+		[202] = "Engineering",
+		[129] = "First Aid",
+		[356] = "Fishing",
+		[182] = "Herbalism",
+		[773] = "Inscription",
+		[755] = "Jewelcrafting",
+		[165] = "Leatherworking",
+		[186] = "Mining",
+		[393] = "Skinning",
+		[197] = "Tailoring"
+	}
+
+	local prof1, prof2, archaeology, fishing, cooking, firstAid = GetProfessions();
+	AmrProfessions = {};
+	if prof1 then
+		local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(prof1);
+		if profMap[skillLine] ~= nil then
+			AmrProfessions[profMap[skillLine]] = skillLevel;
+		end
+	end
+	if prof2 then
+		local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(prof2);
+		if profMap[skillLine] ~= nil then
+			AmrProfessions[profMap[skillLine]] = skillLevel;
+		end
+	end
+	if archaeology then
+		local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(archaeology);
+		if profMap[skillLine] ~= nil then
+			AmrProfessions[profMap[skillLine]] = skillLevel;
+		end
+	end
+	if fishing then
+		local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(fishing);
+		if profMap[skillLine] ~= nil then
+			AmrProfessions[profMap[skillLine]] = skillLevel;
+		end
+	end
+	if cooking then
+		local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(cooking);
+		if profMap[skillLine] ~= nil then
+			AmrProfessions[profMap[skillLine]] = skillLevel;
+		end
+	end
+	if firstAid then
+		local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(firstAid);
+		if profMap[skillLine] ~= nil then
+			AmrProfessions[profMap[skillLine]] = skillLevel;
+		end
+	end
+end
+
+function AskMrRobot.GetRace()
+	local race, raceEn = UnitRace("player");
+	AmrRace = raceEn;
+	AmrFaction = UnitFactionGroup("player");
+end
+
+function AskMrRobot.GetLevel()
+	AmrLevel = UnitLevel("player");
+end
+
+local SlotNames = {
+   "HeadSlot",
+   "NeckSlot",
+   "ShoulderSlot",
+   "ShirtSlot",
+   "ChestSlot",
+   "WaistSlot",
+   "LegsSlot",
+   "FeetSlot",
+   "WristSlot",
+   "HandsSlot",
+   "Finger0Slot",
+   "Finger1Slot",
+   "Trinket0Slot",
+   "Trinket1Slot",
+   "BackSlot",
+   "MainHandSlot",
+   "SecondaryHandSlot",
+--   "RangedSlot",
+   "TabardSlot",
+}
+
+local function GetAmrTalentsForSpec(spec)	
+    local talentInfo = {}
+    local maxTiers = 6
+    for talent = 1, GetNumTalents() do
+     	local name, texture, tier, column, selected, available = GetTalentInfo(talent, false, spec)
+     	if tier > maxTiers then
+     		maxTiers = tier
+     	end
+     	if selected then
+     		talentInfo[tier] = column
+    	end
+    end
+    
+    local str = ""
+    for i = 1, maxTiers do
+    	if talentInfo[i] then
+    		str = str .. talentInfo[i]
+    	else
+    		str = str .. '0'
+    	end
+    end    	
+
+	return str
+end
+
+function AskMrRobot.GetAmrTalents()
+	AmrTalents = {}
+    for spec = 1, GetNumSpecGroups() do
+    	AmrTalents[spec] = GetAmrTalentsForSpec(spec);
+    end
+end
+
+local function GetAmrGlyphsForSpec(spec)
+	local glyphs = {}
+	for i = 1,  NUM_GLYPH_SLOTS do
+		local _, _, _, glyphSpellID, _, glyphID = GetGlyphSocketInfo(i, spec)
+		if (glyphID) then
+			tinsert(glyphs, glyphSpellID)
+		end
+	end
+	return glyphs;
+end
+
+function AskMrRobot.GetAmrGlyphs()
+	AmrGlyphs = {}
+	for spec = 1, GetNumSpecGroups() do
+		AmrGlyphs[spec] = GetAmrGlyphsForSpec(spec)
+	end
+end
+
+--[[
+local function ItemLinkToExportString(itemLink, slot)
+    local itemData = parseItemLink(itemLink)
+    local ret = {}
+    table.insert(ret, slot)
+    table.insert(ret, itemData.itemId)
+    table.insert(ret, itemData.suffixId)
+    table.insert(ret, itemData.upgradeId)
+    table.insert(ret, itemData.gemEnchantIds[1])
+    table.insert(ret, itemData.gemEnchantIds[2])
+    table.insert(ret, itemData.gemEnchantIds[3])
+    table.insert(ret, itemData.enchantId)
+    table.insert(ret, itemData.reforgeId)
+    return table.concat(ret, ":")
+end
+]]
+
+local function toCompressedNumberList(list)
+    -- ensure the values are numbers, sorted from lowest to highest
+    local nums = {}
+    for i, v in ipairs(list) do
+        table.insert(nums, tonumber(v))
+    end
+    table.sort(nums)
+    
+    local ret = {}
+    local prev = 0
+    for i, v in ipairs(nums) do
+        local diff = v - prev
+        table.insert(ret, diff)
+        prev = v
+    end
+    
+    return table.concat(ret, ",")
+end
+
+-- create a more compact but less readable string
+function AskMrRobot.ExportToCompressedString(includeInventory)
+    local fields = {}
+    
+    -- compressed string uses a fixed order rather than inserting identifiers
+    table.insert(fields, GetAddOnMetadata(AskMrRobot.AddonName, "Version"))
+    table.insert(fields, AmrRealmName)
+    table.insert(fields, AmrCharacterName)
+
+	-- guild name
+	local guildName = GetGuildInfo("player")
+	if guildName == nil then
+		table.insert(fields, "")
+	else
+		table.insert(fields, guildName)
+    end
+
+    -- race, default to pandaren if we can't read it for some reason
+    local raceval = raceIds[AmrRace]
+    if raceval == nil then raceval = 13 end
+    table.insert(fields, raceval)
+    
+    -- faction, default to alliance if we can't read it for some reason
+    raceval = factionIds[AmrFaction]
+    if raceval == nil then raceval = 1 end
+    table.insert(fields, raceval)
+    
+    table.insert(fields, AmrLevel)
+    
+    local profs = {}
+    local noprofs = true
+    for k, v in pairs(AmrProfessions) do
+        local profval = professionIds[k]
+        if profval ~= nil then
+            noprofs = false
+            table.insert(profs, profval .. ":" .. v)
+        end
+    end
+    
+    if noprofs then
+        table.insert(profs, "0:0")
+    end
+    
+    table.insert(fields, table.concat(profs, ","))
+    
+    if (AmrActiveSpec ~= nil) then
+        table.insert(fields, AmrActiveSpec)
+        table.insert(fields, AmrSpecializations[AmrActiveSpec .. ""])
+        table.insert(fields, AmrTalents[AmrActiveSpec])
+        table.insert(fields, toCompressedNumberList(AmrGlyphs[AmrActiveSpec]))
+    else
+        table.insert(fields, "_")
+        table.insert(fields, "_")
+        table.insert(fields, "_")
+        table.insert(fields, "_")
+    end
+    
+    -- convert items to parsed objects, sorted by id
+    local itemObjects = {}
+    for k, v in pairs(AmrEquipedItems) do
+        local itemData = parseItemLink(v)
+        itemData.slot = k
+        table.insert(itemObjects, itemData)
+    end
+    
+    -- if desired, include bank/bag items too
+    if includeInventory then
+        for i, v in ipairs(AmrBagItems) do
+            local itemData = parseItemLink(v)
+            if itemData.itemId ~= nil then
+                table.insert(itemObjects, itemData)
+            end
+        end
+        for i, v in ipairs(AmrBankItems) do
+            local itemData = parseItemLink(v)
+            if itemData.itemId ~= nil then
+                table.insert(itemObjects, itemData)
+            end
+        end
+    end
+    
+    -- sort by item id so we can compress it more easily
+    table.sort(itemObjects, function(a, b) return a.itemId < b.itemId end)
+    
+    -- append to the export string
+    local prevItemId = 0
+    local prevGemId = 0
+    local prevEnchantId = 0
+    for i, itemData in ipairs(itemObjects) do
+    
+        local itemParts = {}
+        
+        table.insert(itemParts, itemData.itemId - prevItemId)
+        prevItemId = itemData.itemId
+        
+        if itemData.slot ~= nil then table.insert(itemParts, "s" .. itemData.slot) end
+        if itemData.suffixId ~= 0 then table.insert(itemParts, "f" .. itemData.suffixId) end
+        if upgradeTable[itemData.upgradeId] ~= 0 then table.insert(itemParts, "u" .. upgradeTable[itemData.upgradeId]) end
+        if itemData.gemEnchantIds[1] ~= 0 then 
+            table.insert(itemParts, "a" .. (itemData.gemEnchantIds[1] - prevGemId))
+            prevGemId = itemData.gemEnchantIds[1]
+        end
+        if itemData.gemEnchantIds[2] ~= 0 then 
+            table.insert(itemParts, "b" .. (itemData.gemEnchantIds[2] - prevGemId))
+            prevGemId = itemData.gemEnchantIds[2]
+        end
+        if itemData.gemEnchantIds[3] ~= 0 then 
+            table.insert(itemParts, "c" .. (itemData.gemEnchantIds[3] - prevGemId))
+            prevGemId = itemData.gemEnchantIds[3]
+        end
+        if itemData.enchantId ~= 0 then 
+            table.insert(itemParts, "e" .. (itemData.enchantId - prevEnchantId))
+            prevEnchantId = itemData.enchantId
+        end
+        if itemData.reforgeId ~= 0 then table.insert(itemParts, "r" .. (itemData.reforgeId - 113)) end
+    
+        table.insert(fields, table.concat(itemParts, ""))
+    end
+    
+    return "$" .. table.concat(fields, ";") .. "$"
+end
+
+function AskMrRobot.ExportToAddonChat(timestamp)
+    local data = AskMrRobot.ExportToCompressedString(false)
+    local msgPrefix = timestamp .. "\n" .. AmrRealmName .. "\n" .. AmrCharacterName .. "\n"
+    
+    -- break the data into 250 character chunks (to deal with the short limit on addon message size)
+    local chunks = {}
+    local i = 1
+    local length = string.len(data)
+    local chunkLen = 249 - string.len(msgPrefix)
+    while (i <= length) do
+        local endpos = math.min(i + chunkLen, length)
+        table.insert(chunks, msgPrefix .. string.sub(data, i, endpos))
+        i = endpos + 1
+    end
+    
+    for i, v in ipairs(chunks) do
+        SendAddonMessage(AskMrRobot.ChatPrefix, v, "RAID")
+    end
+    
+    -- send a completion message
+    SendAddonMessage(AskMrRobot.ChatPrefix, msgPrefix .. "done", "RAID")
+end
+
+-- Create an export string that can be copied to the website
+function AskMrRobot.ExportToString()
+
+    --[[
+    local fields = {}
+    
+    fields["realm"] = AmrRealmName
+    fields["name"] = AmrCharacterName
+    fields["race"] = AmrRace
+    fields["faction"] = AmrFaction
+    fields["level"] = AmrLevel
+    
+    local profs = {}
+    for k, v in pairs(AmrProfessions) do
+        table.insert(profs, k .. ":" .. v)
+    end
+    fields["professions"] = table.concat(profs, ",")
+    
+    if (AmrActiveSpec ~= nil) then
+        fields["activespec"] = AmrActiveSpec
+        fields["spec"] = AmrSpecializations[AmrActiveSpec .. ""]
+        fields["talents"] = AmrTalents[AmrActiveSpec]
+        fields["glyphs"] = table.concat(AmrGlyphs[AmrActiveSpec], ",")
+    end
+    
+    local items = {}
+    for k, v in pairs(AmrEquipedItems) do
+        table.insert(items, ItemLinkToExportString(v, k))
+    end
+    for i, v in ipairs(AmrBagItems) do
+        table.insert(items, ItemLinkToExportString(v, "-1"))
+    end
+    for i, v in ipairs(AmrBankItems) do
+        table.insert(items, ItemLinkToExportString(v, "-1"))
+    end
+    fields["items"] = table.concat(items, "_")
+    
+    local fieldList = {}
+    for k, v in pairs(fields) do
+        table.insert(fieldList, k .. "=" .. v)
+    end
+    ]]
+    
+    --return table.concat(fieldList, ";")
+    
+    return AskMrRobot.ExportToCompressedString(true)
+    --return AskMrRobot.ExportToAddonChat(time())
+end
+
+local function parseGlyphs(input)
+	local glyphs = {}
+	for glyph in string.gmatch(input, "([^,]+)") do
+		tinsert(glyphs, glyph)
+	end
+	table.sort(glyphs)
+	return glyphs
+end
+
+local function parseProfessions(input)
+	local professions = {}
+	for prof, v in string.gmatch(input, "([^:,]+):([^,]+)") do
+		professions[prof] = tonumber(v);
+	end
+	return professions;
+end
+
+local gemColorMapping = {
+	y = 'Yellow',
+	b = 'Blue',
+	r = 'Red',
+	h = 'Hydraulic',
+	p = 'Prismatic',
+	m = 'Meta',
+	c = 'Cogwheel'
+}
+
+local function parseAmrItem(input)
+	local slot, itemId, suffixList, upgradeId, gemColorString, gemEnchantIdString, gemIdString, enchantId, reforgeId = string.match(input, "^(%d+):(%d+):([^:]+):([^:]+):([^:]+):([^:]+):([^:]+):(%d+):(%d+)");
+	-- parse the gem enchant ids out of their comma seperated list
+	local gems = {}
+	for gemEnchantId in string.gmatch(gemEnchantIdString, '(%d+)') do
+		tinsert(gems, {enchantId = tonumber(gemEnchantId), id = 0})
+	end
+	-- make sure we have 4 gem ids
+	for i = #gems + 1, 4 do
+		tinsert(gems, {enchantId = 0, id = 0})
+	end	
+	-- parse the gem ids out of their comma seperated list	
+	local gemIds = {}
+	i = 1
+	for gemId in string.gmatch(gemIdString, '(%d+)') do
+		gems[i].id = tonumber(gemId)
+		i = i + 1
+	end
+	i = 1
+	for gemColor in string.gmatch(gemColorString, '([^,])') do
+		gems[i].color = gemColorMapping[gemColor]
+		i = i + 1
+	end
+
+	-- parse the possible suffixes out of their comma seperated list and put them in a set (number -> bool)
+	local suffixes = {}
+	for suffixId in string.gmatch(suffixList, '(%-?%d+)') do
+		suffixes[tonumber(suffixId)] = true
+	end
+
+	local item = {
+		itemId = tonumber(itemId),
+		suffixes = suffixes,
+		upgradeId = tonumber(upgradeId),
+		gems = gems,
+		enchantId = tonumber(enchantId),
+		reforgeId = tonumber(reforgeId)
+	}
+	return slot, item
+end
+
+
+function AskMrRobot.parseAmr(input)
+	local parsedInput = {}
+	parsedInput.items = {}
+	for k, v in string.gmatch(input, "([^=;]+)=([^;]*)") do
+		if (k == 'item') then
+			local slot, item = parseAmrItem(v);
+			parsedInput.items[AskMrRobot.slotIdToSlotNum[tonumber(slot) + 1]] = item;
+		 elseif (k == 'glyphs') then
+		 	parsedInput.glyphs = parseGlyphs(v)
+	 	 elseif (k == 'professions') then
+	 	 	parsedInput.professions = parseProfessions(v)
+		 else
+		 	parsedInput[k]=v
+		end
+	end
+	return parsedInput
+end
+
+function AskMrRobot.validateRealm(realm)
+	return realm == GetRealmName();
+end
+
+function AskMrRobot.validateCharacterName(characterName)
+	return UnitName("player") == characterName
+end
+
+function AskMrRobot.validateRace(race)
+	local _, raceEn = UnitRace("player")
+	return raceEn == race or (raceEn == "Scourge" and race == "Undead")
+end
+
+function AskMrRobot.validateFaction(faction)
+	return faction == UnitFactionGroup("player")
+end
+
+function AskMrRobot.validateSpec(spec)
+	if spec == 'nil' then 
+		spec = nil
+	end
+	local currentSpec = GetAmrSpecialization(GetActiveSpecGroup())
+	return (not currentSpec and not spec) or tostring(currentSpec) == spec
+end
+
+function AskMrRobot.validateTalents(talents)
+	if talents == nil then
+		talents = ''
+	end
+	return talents == GetAmrTalentsForSpec(GetActiveSpecGroup())
+end
+
+function AskMrRobot.validateGlyphs(glyphs)
+	if (glyphs == nil) then
+		glyphs = {};
+	end
+	local currentGlyphs = GetAmrGlyphsForSpec(GetActiveSpecGroup())
+	table.sort(glyphs, function(a,b) return tostring(a) < tostring(b) end)
+	table.sort(currentGlyphs, function(a,b) return tostring(a) < tostring(b) end)
+
+	if #glyphs ~= #currentGlyphs then
+		return false
+	end
+	for i = 1, #glyphs do
+		if tostring(glyphs[i]) ~= tostring(currentGlyphs[i]) then
+			return false
+		end
+	end
+
+	return true
+end
+
+local function getPrimaryProfessions()
+	local profs = {}
+	local prof1, prof2 = GetProfessions()
+	local profMap = {
+		[794] = "Archaeology",
+		[171] = "Alchemy",
+		[164] = "Blacksmithing",
+		[185] = "Cooking",
+		[333] = "Enchanting",
+		[202] = "Engineering",
+		[129] = "First Aid",
+		[356] = "Fishing",
+		[182] = "Herbalism",
+		[773] = "Inscription",
+		[755] = "Jewelcrafting",
+		[165] = "Leatherworking",
+		[186] = "Mining",
+		[393] = "Skinning",
+		[197] = "Tailoring"
+	}
+
+	if prof1 then
+		local _, _, skillLevel, _, _, _, skillLine = GetProfessionInfo(prof1);
+		if profMap[skillLine] ~= nil then
+			profs[profMap[skillLine]] = skillLevel
+		end
+	end
+	if prof2 then
+		local _, _, skillLevel, _, _, _, skillLine = GetProfessionInfo(prof2);
+		if profMap[skillLine] ~= nil then
+			profs[profMap[skillLine]] = skillLevel
+		end
+	end	
+	return profs;
+end
+
+local professionThresholds = {
+	Leatherworking = 575,
+	Inscription = 600,
+	Alchemy = 50,
+	Enchanting = 550,
+	Jewelcrafting = 550,
+	Blacksmithing = 550,
+	Tailoring = 550
+}
+
+function AskMrRobot.validateProfessions(professions)
+	local currentProfessions = getPrimaryProfessions()
+	if #currentProfessions ~= #professions then
+		return false
+	end
+	for k, v in pairs(professions) do
+		if currentProfessions[k] then
+			local threshold = professionThresholds[k]
+			if not threshold then
+				threshold = 1
+			end
+			-- compare the desired profession against the threshold
+			local desired = v >= threshold
+			-- compare the current profession against the threshold
+			local has = currentProfessions[k] and currentProfessions[k] >= threshold
+			-- if the current value is on the other side of the threshold
+			-- then we don't match
+			if desired ~= has then 
+				return false 
+			end
+		else 
+			return false
+		end
+	end
+	return true
+end
+
+function AskMrRobot.populateItemDiffs(amrItem, itemLink, slotNum)
+	AskMrRobot.itemDiffs.items[slotNum] = nil
+	AskMrRobot.itemDiffs.gems[slotNum] = nil
+	AskMrRobot.itemDiffs.enchants[slotNum] = nil
+	AskMrRobot.itemDiffs.reforges[slotNum] = nil
+
+	local needsUpgrade = false
+	local aSuffix = 0
+	if amrItem then
+		for k,v in pairs(amrItem.suffixes) do
+			aSuffix = k
+		end
+	end
+
+	if itemLink == nil then
+		if amrItem ~= nil then
+			AskMrRobot.itemDiffs.items[slotNum] = {
+				current = nil,
+				optimized = { itemId = amrItem.itemId, upgradeId = amrItem.upgradeId, suffixId = aSuffix },
+				needsUpgrade = false
+			}
+		end
+		return
+	end
+	local item = parseItemLink(itemLink)
+	local isItemBad = false
+
+	if amrItem == nil or item.itemId ~= amrItem.itemId then
+		isItemBad = true
+	else
+		if item.suffixId == 0 then
+			if #amrItem.suffixes > 0 then
+				isItemBad = true
+			end
+		else
+			if not amrItem.suffixes[item.suffixId] then
+				isItemBad = true
+			end
+		end
+		if not isItemBad and upgradeTable[item.upgradeId] ~= upgradeTable[amrItem.upgradeId] then
+			isItemBad = true
+			needsUpgrade = true
+		end
+	end
+
+	if isItemBad then
+		AskMrRobot.itemDiffs.items[slotNum] = {
+			current = item.itemId,
+			optimized = { itemId = amrItem and amrItem.itemId or 0, upgradeId = amrItem and amrItem.upgradeId or 0, suffixId = aSuffix },			
+			needsUpgrade = needsUpgrade
+		}
+		return
+	end
+
+	local badGemCount, gemInfo = AskMrRobot.MatchesGems(itemLink, item.gemEnchantIds, amrItem.gems)
+	if badGemCount > 0 then
+		AskMrRobot.itemDiffs.gems[slotNum] = gemInfo
+	end
+
+	if item.enchantId ~= amrItem.enchantId then
+		AskMrRobot.itemDiffs.enchants[slotNum] = {
+			current = item.enchantId,
+			optimized = amrItem.enchantId
+		}
+	end
+
+	if item.reforgeId ~= amrItem.reforgeId then
+		AskMrRobot.itemDiffs.reforges[slotNum] = {
+			current = item.reforgeId,
+			optimized = amrItem.reforgeId
+		}
+	end
+end
+
+--[[
+function AskMrRobot.StartLogging()
+	if not LoggingCombat() then
+		LoggingCombat(1)
+		print("Started Combat Logging")
+	end
+end
+
+function AskMrRobot.FinishLogging()
+	if LoggingCombat() then
+		LoggingCombat(0)
+		print("Finished Combat Logging")
+	end
+end
+
+-- local difficultyLookup = {
+-- 	DUNGEON_DIFFICULTY1,
+-- 	DUNGEON_DIFFICULTY2,
+-- 	RAID_DIFFICULTY_10PLAYER,
+-- 	RAID_DIFFICULTY_25PLAYER,
+-- 	RAID_DIFFICULTY_10PLAYER_HEROIC,
+-- 	RAID_DIFFICULTY_25PLAYER_HEROIC,
+-- 	RAID_FINDER,
+-- 	CHALLENGE_MODE,
+-- 	RAID_DIFFICULTY_40PLAYER,
+-- 	nil,
+-- 	nil, -- Norm scen
+-- 	nil, -- heroic scen
+-- 	nil,
+-- 	PLAYER_DIFFICULTY4
+-- }
+
+--http://wowpedia.org/InstanceMapID
+local instanceMaps = {
+	HeartOfFear = 1009,
+	MogushanVaults = 1008,	
+	SiegeOfOrgrimmar = 1136,
+	TerraceOfEndlessSpring = 996,
+	ThroneOfThunder = 1098
+}
+
+function AskMrRobot.UpdateLogging()
+
+	-- get the info about the instance
+	--local zone, zonetype, difficultyIndex, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID = GetInstanceInfo()
+	local zone, _, difficultyIndex, _, _, _, _, instanceMapID = GetInstanceInfo()
+	--local difficulty = difficultyIndex
+	-- Unless Blizzard fixes scenarios to not return nil, let's hardcode this into returning "scenario" -Znuff
+	--if zonetype == nil and difficultyIndex == 1 then
+		--zonetype = "scenario"
+	--end
+
+	-- if nothing has changed, then bail
+	--if (not zone) and difficulty == 0 then return end
+	if zone == AskMrRobot.lastzone and difficultyIndex == AskMrRobot.lastdiff then
+	  -- do nothing if the zone hasn't ACTUALLY changed
+	  -- otherwise we may override the user's manual enable/disable
+	  return
+	end
+
+	AskMrRobot.lastzone = zone
+	AskMrRobot.lastdiff = difficultyIndex
+
+	if AmrOptions.autoLog[tonumber(instanceMapID)] then
+		if instanceMapID == instanceMaps.SiegeOfOrgrimmar then
+			AskMrRobot.StartLogging()
+		else
+			AskMrRobot.FinishLogging()
+		end
+	end
+end
+]]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AskMrRobot.toc	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,47 @@
+## Interface: 50400
+## Title: Ask Mr. Robot
+## Author: Team Robot, Inc.
+## Version: 1.2.12.0
+## Notes: Exports/Imports data to/from askmrrobot.com.
+## URL: www.askmrrobot.com
+## DefaultState: Enabled
+## LoadOnDemand: 0
+## SavedVariablesPerCharacter: AmrBagItems,AmrBankItems,AmrEquipedItems,AmrGold,AmrRealmName,AmrCharacterName,AmrIconInfo,AmrCurrencies,AmrProfessions,AmrSpecializations,AmrRace,AmrLevel,AmrFaction,AmrActiveSpec,AmrOptions,AmrGlyphs,AmrTalents,AmrBankItemsAndCounts,AmrImportString,AmrImportDate,AmrSendSettings,AmrLogData
+
+#@no-lib-strip@
+Libs\LibStub\Libstub.lua
+Libs\CallbackHandler-1.0\CallbackHandler-1.0.lua
+#@end-no-lib-strip@
+
+Libs\LibDataBroker-1.1\LibDataBroker-1.1.lua
+
+#@no-lib-strip@
+Libs\LibDBIcon-1.0\LibDBIcon-1.0.lua
+#@end-no-lib-strip@
+
+wait.lua
+sort.lua
+enchants.lua
+gems.lua
+ui\Components.lua
+ui\RobotStamp.lua
+ui\ItemTooltipFrame.lua
+ui\ItemLinkText.lua
+ui\ItemIcon.lua
+ui\GemIcon.lua
+ui\EnchantLinkText.lua
+ui\JewelPanel.lua
+ui\SummaryTab.lua
+ui\GemTab.lua
+ui\EnchantTab.lua
+ui\HelpTab.lua
+ui\ImportTab.lua
+ui\ExportTab.lua
+ui\ReforgesTab.lua
+ui\ShoppingListTab.lua
+ui\CombatLogTab.lua
+AskMrRobotUi.lua
+AskMrRobot.lua
+config.lua
+AskMrRobot.xml
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AskMrRobot.xml	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,9 @@
+<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd">
+  <GameTooltip name="MyScanningTooltip" inherits="GameTooltipTemplate">
+   <Scripts>
+     <Onload>
+       self:SetOwner(WorldFrame, "ANCHOR_NONE");
+     </Onload>
+   </Scripts>
+ </GameTooltip>
+</Ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AskMrRobotUi.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,495 @@
+local _, AskMrRobot = ...
+
+local showImportDetailsError = nil
+local showImportErrorTab = nil
+
+AskMrRobot.AmrUI = AskMrRobot.inheritsFrom(AskMrRobot.Frame)
+
+function AskMrRobot.AmrUI:swapSimilarSlotsIfNeeded(slotName1, slotName2)
+	local slotId1 = GetInventorySlotInfo(slotName1)
+	local slotId2 = GetInventorySlotInfo(slotName2)
+	local slotNum1 = AskMrRobot.slotIdToSlotNum[slotId1]
+	local slotNum2 = AskMrRobot.slotIdToSlotNum[slotId2]
+
+	local itemLink1 = GetInventoryItemLink("player", slotId1)
+	local itemLink2 = GetInventoryItemLink("player", slotId2)
+
+	-- see how bad the items are in the original order
+	AskMrRobot.populateItemDiffs(self.importedItems[slotNum1], itemLink1, slotNum1)
+	AskMrRobot.populateItemDiffs(self.importedItems[slotNum2], itemLink2, slotNum2)
+
+	local badCountOriginalOrder = 0
+	if AskMrRobot.itemDiffs.items[slotNum1] then badCountOriginalOrder = badCountOriginalOrder + 1 end
+	if AskMrRobot.itemDiffs.items[slotNum2] then badCountOriginalOrder = badCountOriginalOrder + 1 end
+
+	-- try the order swapped
+	AskMrRobot.populateItemDiffs(self.importedItems[slotNum1], itemLink2, slotNum1)
+	AskMrRobot.populateItemDiffs(self.importedItems[slotNum2], itemLink1, slotNum2)
+
+	local badCountNewOrder = 0
+	if AskMrRobot.itemDiffs.items[slotNum1] then badCountNewOrder = badCountNewOrder + 1 end
+	if AskMrRobot.itemDiffs.items[slotNum2] then badCountNewOrder = badCountNewOrder + 1 end
+
+	-- if the items were less bad in the new order, swap the imported items
+	if badCountNewOrder < badCountOriginalOrder then
+		local tempItem = self.importedItems[slotNum1]
+		self.importedItems[slotNum1] = self.importedItems[slotNum2]
+		self.importedItems[slotNum2] = tempItem
+	end
+end
+
+function AskMrRobot.AmrUI:displayImportItems()
+	if not self.importedItems then 
+		return false
+	end
+
+	--see if rings or trinkets are swapped, and alter self.importedItems accordingly
+	self:swapSimilarSlotsIfNeeded("Finger0Slot", "Finger1Slot")
+	self:swapSimilarSlotsIfNeeded("Trinket0Slot", "Trinket1Slot")
+
+	for slotNum = 1, #AskMrRobot.slotIds do
+		if AskMrRobot.OptimizationSlots[slotNum] then
+			local slotId = AskMrRobot.slotIds[slotNum]
+			local itemLink = GetInventoryItemLink("player", slotId)
+			AskMrRobot.populateItemDiffs(self.importedItems[slotNum], itemLink, slotNum)
+		end
+	end
+
+	self.summaryTab:showBadItems()
+
+	-- if there are incorrect items equiped, display errors on other tabs
+	if AskMrRobot.itemDiffs and AskMrRobot.itemDiffs.items then
+		for k,v in pairs(AskMrRobot.itemDiffs.items) do
+			if not v.needsUpgrade then
+				self.hasImportError = true
+			end
+		end		
+	end
+
+	if self.hasImportError then
+		showImportDetailsError()
+	else
+		self.gemTab:Update()
+		self.enchantTab:showBadEnchants()
+		self.reforgeTab:Render()
+		self.shoppingTab:Update()
+	end
+end
+
+function AskMrRobot.AmrUI:showImportError(text, ...)
+	self.summaryTab:showImportError(text, ...)
+	if text then
+		self.hasImportError = true		
+		showImportDetailsError()
+	else
+		self.hasImportError = false
+	end
+end
+
+function AskMrRobot.AmrUI:showImportWarning(text, ...)
+	self.summaryTab:showImportWarning(text, ...)
+	self.hasImportError = false
+	if text then
+		showImportDetailsError()
+	end
+end
+
+function AskMrRobot.AmrUI:validateInput(input)
+
+	self.importedItems = nil
+	self.mostlySuccess = false
+
+	local parsed = AskMrRobot.parseAmr(input)
+
+	if not parsed.realm then
+		self:showImportError("Oops, you didn't have proper import text", "Please go back to AskMrRobot.com and grab optimizations for this character")
+	elseif not AskMrRobot.validateCharacterName(parsed.name) then
+		self:showImportError("Oops, you've imported optimizations for " .. parsed.name, "Please go back to AskMrRobot.com and grab optimizations for this character, who is much better looking anyway!")
+	elseif not AskMrRobot.validateRace(parsed.race) then
+		self:showImportError("It looks like your race may have changed, which affects the optimizations.", "Right now, Mr. Robot thinks you are a " .. parsed.race)
+	elseif not AskMrRobot.validateFaction(parsed.faction) then
+		self:showImportError("It looks like your faction may have changed.", "Right now, Mr. Robot thinks you belong to the " .. parsed.faction)
+	elseif not AskMrRobot.validateProfessions(parsed.professions) then
+		self:showImportError("Your professions have changed, which affects the optimizations.", "You will need to make sure your in-game professions match the professions on AskMrRobot.com when importing.")
+	elseif not AskMrRobot.validateSpec(parsed.spec) then
+		if parsed.spec and parsed.spec ~= 'nil' then			
+			local _, specName = GetSpecializationInfoByID(parsed.spec)
+			self:showImportError("WARNING! Please check your character before proceeding:", "Change your spec to " .. specName .. ".")
+		else
+			self:showImportError("WARNING! Please check your character before proceeding:", "AskMrRobot.com did not expect to see a specialization.")
+		end
+		self.mostlySuccess = true
+		self.summaryTab.badRealm = nil
+		self.summaryTab.badTalents = nil
+		self.summaryTab.badGlyphs = nil
+		AmrImportString = input
+	else
+		self.summaryTab.badRealm = not AskMrRobot.validateRealm(parsed.realm) and parsed.realm
+		self.summaryTab.badTalents = not AskMrRobot.validateTalents(parsed.talents)
+		self.summaryTab.badGlyphs = not AskMrRobot.validateGlyphs(parsed.glyphs)
+		self.mostlySuccess = true
+		self:showImportError(nil)
+		AmrImportString = input
+		self.importedItems = parsed.items
+		return self:displayImportItems()
+	end
+	return false
+end
+
+local function createImportDetailsErrorTab(reforgeFrame)
+	local tab = CreateFrame("Frame", nil, reforgeFrame)
+	tab:SetPoint("TOPLEFT")
+	tab:SetPoint("BOTTOMRIGHT")
+	tab:Hide()
+
+	local text = tab:CreateFontString("AmrImportDetailsText1", "ARTWORK", "GameFontNormalLarge")
+	text:SetPoint("TOPLEFT", 0, -5)
+	text:SetText("Help")
+
+	local errorText1 = tab:CreateFontString("AmrImportDetailsText2", "ARTWORK", "GameFontRed")
+	errorText1:SetPoint("TOPLEFT", "AmrImportDetailsText1", "BOTTOMLEFT", 0, -20)
+	errorText1:SetText('You have no optimizations imported. Click the "Import" tab to get started.')
+	errorText1:SetPoint("RIGHT", -10, 0)
+	errorText1:SetWidth(errorText1:GetWidth())
+	errorText1:SetJustifyH("LEFT")
+
+	showImportDetailsError = function()
+		errorText1:SetText("I can't optimize yet. Please go to the summary tab for more information.")
+	end
+
+	showImportErrorTab = function(tabName)
+		if not tabName then
+			tab:Hide()
+		else
+			text:SetText(tabName)
+			tab:Show()
+		end		
+	end
+
+	return tab
+end
+
+function AskMrRobot.AmrUI:createTabButtons()
+	local importTabButton = CreateFrame("Button", "AmrImportTabButton", self, "OptionsListButtonTemplate")
+
+	local buttons = {}
+	self.hasImportError = true
+
+	local function onTabButtonClick(clickedButton, event, ...)
+		showImportErrorTab(nil)
+		for i = 1, #buttons do
+			local button = buttons[i]
+			if clickedButton == button then
+				button.highlight:SetVertexColor(1, 1, 0)
+				button:LockHighlight()
+				if self.hasImportError and button.isImportDetails then
+					showImportErrorTab(button:GetText())
+				elseif button.element then 
+					button.element:Show()
+				end
+			else
+				button.highlight:SetVertexColor(.196, .388, .8)
+				button:UnlockHighlight()
+				if button.element then
+					button.element:Hide()
+				end
+			end
+		end
+	end
+
+	local function createButton(text, spacing, isImportDetails)
+		local lastButton = #buttons
+		local i = lastButton + 1
+		local tabButton = CreateFrame("Button", "AmrTabButton" .. i, self, "OptionsListButtonTemplate")
+		tabButton.isImportDetails = isImportDetails
+		tabButton:SetText(text)
+		tabText = tabButton:GetFontString()
+		tabText:SetPoint("LEFT", 6, 0)
+		if i == 1 then
+			tabButton:SetPoint("TOPLEFT", 2, spacing)
+		else
+			tabButton:SetPoint("TOPLEFT", "AmrTabButton" .. lastButton, "BOTTOMLEFT", 0, spacing)
+		end
+		tabButton:SetWidth(125)
+		tabButton:SetHeight(20)
+		tinsert(buttons, tabButton)
+		tabButton:SetScript("OnClick", onTabButtonClick)
+	end
+
+	createButton("Import", -35, false)
+	createButton("Summary", -20, false)
+	createButton("Gems", 0, true)
+	createButton("Enchants", 0, true)
+	createButton("Reforges", 0, true)
+	createButton("Shopping List", 0, true)
+	createButton("Best in Bags", -20, false)
+    createButton("Combat Log", 0, false)
+	createButton("Help", -20, false)
+
+	return buttons
+end
+
+function AskMrRobot.AmrUI:new()
+	local o = AskMrRobot.Frame:new("AskMrRobot_Dialog", nil, "BasicFrameTemplateWithInset")
+
+	-- use the AmrUI class
+	setmetatable(o, { __index = AskMrRobot.AmrUI })
+
+	o:RegisterForDrag("LeftButton");
+	o:SetWidth(600)
+	o:SetHeight(530)
+	o.InsetBg:SetPoint("TOPLEFT", 125, -24)
+
+	o:SetParent("UIParent")
+	o:SetPoint("CENTER")
+	o:Hide()
+	o:EnableMouse(true)
+	o:EnableKeyboard(true)
+	o.hideOnEscape = 1
+	o:SetMovable(true)
+	o:SetToplevel(true)
+
+	--o:SetScript("OnEscapePressed", function)
+	o:SetScript("OnDragStart", AskMrRobot.AmrUI.OnDragStart)
+	o:SetScript("OnDragStop", AskMrRobot.AmrUI.OnDragStop)
+	o:SetScript("OnHide", AskMrRobot.AmrUI.OnHide)
+	-- make the UI show the first tab when its opened
+	o:SetScript("OnShow", AskMrRobot.AmrUI.OnShow)
+
+	o:RegisterEvent("AUCTION_HOUSE_CLOSED")
+	o:RegisterEvent("AUCTION_HOUSE_SHOW")
+	o:RegisterEvent("FORGE_MASTER_OPENED")
+	o:RegisterEvent("FORGE_MASTER_CLOSED")
+	o:RegisterEvent("SOCKET_INFO_UPDATE")
+	o:RegisterEvent("SOCKET_INFO_CLOSE")
+
+	o:SetScript("OnEvent", function(...)
+		o:OnEvent(...)
+	end)
+
+	tinsert(UISpecialFrames, o:GetName())
+
+	-- title
+	o.TitleText:SetText("Ask Mr. Robot " .. GetAddOnMetadata(AskMrRobot.AddonName, "Version"))
+
+	-- create the tab buttons
+	o.buttons = o:createTabButtons()
+
+	local tabArea = AskMrRobot.Frame:new(nil, o)
+	tabArea:SetPoint("TOPLEFT", 140, -30)
+	tabArea:SetPoint("BOTTOMRIGHT")	
+
+	createImportDetailsErrorTab(tabArea)
+
+	-- create the import tab and associated it with the import tab button
+	o.importTab = AskMrRobot.ImportTab:new(tabArea)
+	o.buttons[1].element = o.importTab	
+	o.importTab.scrollFrame.EditBox:SetScript("OnEscapePressed", function()
+		o:Hide()
+	end)	
+
+	o.importTab.button:SetScript("OnClick", function(...)
+		o.summaryTab.importDate = date()
+		AmrImportDate = o.summaryTab.importDate
+		o:OnUpdate()
+		if o.mostlySuccess then
+			-- save import between sessions
+			AmrImportString = o.importTab.scrollFrame.EditBox:GetText()
+			AmrImportDate = o.summaryTab.importDate
+		end
+		o:ShowTab("summary")
+	end)
+
+	o.summaryTab = AskMrRobot.SummaryTab:new(tabArea)
+	o.buttons[2].element = o.summaryTab
+
+	o.gemTab = AskMrRobot.GemTab:new(nil, tabArea)
+	o.buttons[3].element = o.gemTab
+
+	o.enchantTab = AskMrRobot.EnchantTab:new(tabArea)
+	o.buttons[4].element = o.enchantTab
+
+	o.reforgeTab = AskMrRobot.ReforgesTab:new(tabArea)
+	o.buttons[5].element = o.reforgeTab
+
+	o.shoppingTab = AskMrRobot.ShoppingListTab:new(tabArea)
+	o.buttons[6].element = o.shoppingTab
+
+	o.shoppingTab.sendTo:SetScript("OnEscapePressed", function()
+ 		o:Hide()
+  	end)
+
+	o.exportTab = AskMrRobot.ExportTab:new(tabArea)
+	o.buttons[7].element = o.exportTab
+
+    o.combatLogTab = AskMrRobot.CombatLogTab:new(tabArea)
+    o.buttons[8].element = o.combatLogTab
+    
+	o.helpTab = AskMrRobot.HelpTab:new(tabArea)
+	o.buttons[9].element = o.helpTab
+
+	o.isSocketWindowVisible = false
+	o.isReforgeVisible = false
+	o.isAuctionHouseVisible = false
+
+	--hide the UI	
+	o:Hide()
+
+	o:ShowTab("import")	
+
+    o.initialize = false
+    
+	return o
+end
+
+function AskMrRobot.AmrUI:OnUpdate()
+	local input = self.importTab.scrollFrame.EditBox:GetText()
+	if input and input:len() > 0 then
+		self:validateInput(input)
+	end
+end
+
+function AskMrRobot.AmrUI:OnShow()
+
+    if not self.initialized then
+        -- remember the import settings between sessions
+        self.importTab.scrollFrame.EditBox:SetText(AmrImportString or "")        
+        self.initialized = true
+    end
+    
+	self:OnUpdate()	
+end
+
+function AskMrRobot.AmrUI:OnDragStart()
+	if not self.isLocked then
+		self:StartMoving();
+	end
+end
+
+function AskMrRobot.AmrUI:OnDragStop()
+	self:StopMovingOrSizing()
+end
+
+function AskMrRobot.AmrUI:OnHide()
+	self.visible = false
+	self:StopMovingOrSizing()
+end
+
+function AskMrRobot.AmrUI:ShowReforgeFrame()
+	self.visible = true
+	self:Show()	
+end
+
+function AskMrRobot.AmrUI:Toggle()
+	if self.visible then
+		self:Hide()
+	else
+		self:ShowReforgeFrame()
+	end
+end
+
+local nameToButtonNumber = {
+	import = 1,
+	summary = 2,
+	gems = 3,
+	enchants = 4,
+	reforges = 5,
+	shopping = 6,
+	export = 7,
+    combatLog = 8,
+    help = 9    
+}
+
+function AskMrRobot.AmrUI:ShowTab(tabName)
+	local buttonNumber = nameToButtonNumber[tabName]
+	if buttonNumber then
+		self.buttons[buttonNumber]:Click()
+	end
+end
+
+function AskMrRobot.AmrUI:OnEvent(frame, event, ...)
+	local handler = self["On_" .. event]
+	if handler then
+		handler(self, ...)
+	end
+end
+
+function AskMrRobot.AmrUI:On_AUCTION_HOUSE_SHOW()
+	self.isAuctionHouseVisible = true
+	if self.mostlySuccess then
+		local showTab = self.visible
+		if not AmrOptions.manualShowShop and not self.visible then
+
+			-- show if there is anything to buy
+			if self.shoppingTab:HasStuffToBuy() then
+				self:Show()
+				showTab = true
+			end
+		end
+
+		if showTab then
+			self:ShowTab("shopping")
+		end
+	end	
+end
+
+function AskMrRobot.AmrUI:On_AUCTION_HOUSE_CLOSED()
+	self.isAuctionHouseVisible = false
+	if self.isReforgeVisible then
+		self:ShowTab("reforges")
+	elseif self.isSocketWindowVisible then
+		self:ShowTab("gems")
+	end
+end
+
+function AskMrRobot.AmrUI:On_FORGE_MASTER_OPENED()
+	self.isReforgeVisible = true
+	if self.mostlySuccess then
+		local showTab = self.visible
+		if not AmrOptions.manualShowReforge and not self.visible then
+
+			-- see if there are any reforges to do
+			local reforgeCount = 0
+			for slotNum, badReforge in pairs(AskMrRobot.itemDiffs.reforges) do
+				reforgeCount = reforgeCount + 1
+			end
+
+			if reforgeCount > 0 then
+				self:Show()
+				showTab = true
+			end
+		end
+
+		if showTab then
+			self:ShowTab("reforges")
+		end
+	end
+end
+
+function AskMrRobot.AmrUI:On_FORGE_MASTER_CLOSED()
+	self.isReforgeVisible = false
+	if self.isAuctionHouseVisible then
+		self:ShowTab("shopping")
+	elseif self.isSocketWindowVisible then
+		self:ShowTab("gems")
+	end	
+end
+
+function AskMrRobot.AmrUI:On_SOCKET_INFO_UPDATE()
+	self.isSocketWindowVisible = true
+	if self.mostlySuccess then
+		if not self.visible then
+			self:Show()
+		end
+		self:ShowTab("gems")
+	end
+end
+
+function AskMrRobot.AmrUI:On_SOCKET_INFO_CLOSE()
+	self.isSocketWindowVisible = false
+	if self.isAuctionHouseVisible then
+		self:ShowTab("shopping")
+	elseif self.isReforgeVisible then
+		self:ShowTab("reforges")
+	end
+end
\ No newline at end of file
Binary file Media/AddonExport.tga has changed
Binary file Media/BiBScreen.tga has changed
Binary file Media/icon.tga has changed
Binary file Media/round-edge-big.tga has changed
Binary file Media/round-edge.tga has changed
Binary file Media/square-edge.tga has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,114 @@
+local addonName, AskMrRobot = ...
+
+--if not addon.healthCheck then return end
+local L = AskMrRobot.L
+
+local wow_ver = select(4, GetBuildInfo())
+local wow_500 = wow_ver >= 50000
+local UIPanelButtonTemplate = wow_500 and "UIPanelButtonTemplate" or "UIPanelButtonTemplate2"
+
+local frame = CreateFrame("Frame", nil, InterfaceOptionsFramePanelContainer)
+frame.name = addonName
+frame:Hide()
+
+-- Credits to Ace3, Tekkub, cladhaire and Tuller for some of the widget stuff.
+
+local function newCheckbox(label, tooltipTitle, description, onClick)
+	local check = CreateFrame("CheckButton", "AmrCheck" .. label, frame, "InterfaceOptionsCheckButtonTemplate")
+	check:SetScript("OnClick", function(self)
+		PlaySound(self:GetChecked() and "igMainMenuOptionCheckBoxOn" or "igMainMenuOptionCheckBoxOff")
+		onClick(self, self:GetChecked() and true or false)
+	end)
+	check.label = _G[check:GetName() .. "Text"]
+	check.label:SetText(label)
+	check.tooltipText = tooltipTitle
+	check.tooltipRequirement = description
+	return check
+end
+
+frame:SetScript("OnShow", function(frame)
+	local title = frame:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
+	title:SetPoint("TOPLEFT", 16, -16)
+	title:SetText(addonName)
+
+	local subTitleWrapper = CreateFrame("Frame", nil, frame)
+	subTitleWrapper:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -8)
+	subTitleWrapper:SetPoint("RIGHT", -16, 0)
+	local subtitle = subTitleWrapper:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
+	subtitle:SetPoint("TOPLEFT", subTitleWrapper)
+	subtitle:SetWidth(subTitleWrapper:GetRight() - subTitleWrapper:GetLeft())
+	subtitle:SetJustifyH("LEFT")
+	subtitle:SetNonSpaceWrap(false)
+	subtitle:SetJustifyV("TOP")
+	subtitle:SetText("Mr. Robot's addon can export your item information to his website, and import your optimizations into the game.")
+	subTitleWrapper:SetHeight(subtitle:GetHeight())
+
+	local autoPopup = newCheckbox(
+		"Show minimap icon",
+		"Minimap Icon",
+		"Show the Ask Mr. Robot minimap icon.",
+		function(self, value) 
+			if AmrOptions.hideMapIcon then
+				AmrOptions.hideMapIcon = false
+			else
+				AmrOptions.hideMapIcon = true
+			end
+			AskMrRobot.AmrUpdateMinimap();
+		end
+	)
+	autoPopup:SetChecked(not AmrOptions.hideMapIcon)
+	autoPopup:SetPoint("TOPLEFT", subTitleWrapper, "BOTTOMLEFT", -2, -16)
+
+	local autoReforge = newCheckbox(
+		"Automatically show Mr. Robot's reforge window at the reforger",
+		"Auto-Show Reforges",
+		"When you have suggested reforges left to complete, automatically show Mr. Robot's reforge window when you visit a reforger.",
+		function(self, value) 
+			if AmrOptions.manualShowReforge then
+				AmrOptions.manualShowReforge = false
+			else
+				AmrOptions.manualShowReforge = true
+			end
+		end
+	)
+	autoReforge:SetChecked(not AmrOptions.manualShowReforge)
+	autoReforge:SetPoint("TOPLEFT", subTitleWrapper, "BOTTOMLEFT", -2, -52)
+
+	local autoAh = newCheckbox(
+		"Automatically show Mr. Robot's shopping list at the auction house",
+		"Auto-Show Shopping List",
+		"When your shopping list still has things left to buy, automatically show Mr. Robot's shopping list when you visit the auction house.",
+		function(self, value) 
+			if AmrOptions.manualShowShop then
+				AmrOptions.manualShowShop = false
+			else
+				AmrOptions.manualShowShop = true
+			end
+		end
+	)
+	autoAh:SetChecked(not AmrOptions.manualShowShop)
+	autoAh:SetPoint("TOPLEFT", subTitleWrapper, "BOTTOMLEFT", -2, -88)
+
+	--[[
+	AmrOptions.autoLog = AmrOptions.autoLog or {}
+
+	local autoCombatLog = newCheckbox(
+		"Automatically turn on combat logging for Siege of Orgrimmar",
+		"Automatically Log Siege of Orgrimmar",
+		"When entering Siege of Orgrimmar, combat logging will be turned on.  When leaving Siege of Orgrimmar, combat logging will be turned off.",
+		function(self, value)
+			if AmrOptions.autoLog[1136] then
+				AmrOptions.autoLog[1136] = false
+			else
+				AmrOptions.autoLog[1136] = true
+			end
+		end
+	)
+	autoCombatLog:SetChecked(AmrOptions.autoLog[1136])
+	autoCombatLog:SetPoint("TOPLEFT", subTitleWrapper, "BOTTOMLEFT", -2, -124)
+	]]
+
+	frame:SetScript("OnShow", nil)
+end)
+InterfaceOptions_AddCategory(frame)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/enchants.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,4247 @@
+local _, AskMrRobot = ...
+
+local enchantNames = {
+[-1000]="Belt Buckle",
+[2]="Frostbrand",
+[5]="Flametongue",
+[13]="Sharpened (+3 Damage)",
+[14]="Sharpened (+4 Damage)",
+[15]="8 Armor",
+[16]="16 Armor",
+[17]="24 Armor",
+[18]="32 Armor",
+[19]="Weighted (+2 Damage)",
+[20]="Weighted (+3 Damage)",
+[21]="Weighted (+4 Damage)",
+[24]="+5 Mana",
+[25]="Shadow Oil",
+[26]="Frost Oil",
+[27]="Sundered",
+[28]="+4 All Resistances",
+[30]="Scope (+1 Damage)",
+[31]="+4 Beastslaying",
+[32]="Scope (+2 Damage)",
+[33]="Scope (+3 Damage)",
+[34]="20 Haste",
+[36]="Enchant: Fiery Blaze",
+[37]="Steel Weapon Chain",
+[38]="5 Dodge",
+[39]="Sharpened (+1 Damage)",
+[40]="Sharpened (+2 Damage)",
+[41]="+5 Health",
+[43]="Iron Spike (8-12)",
+[44]="Absorption (10)",
+[63]="Absorption (25)",
+[64]="3 Spirit",
+[65]="+1 All Resistances",
+[66]="1 Stam",
+[67]="+1 Damage",
+[68]="1 Str",
+[69]="2 Str",
+[70]="3 Str",
+[71]="1 Stam",
+[72]="2 Stam",
+[73]="3 Stam",
+[74]="1 Agi",
+[75]="2 Agi",
+[76]="3 Agi",
+[77]="+2 Damage",
+[78]="+3 Damage",
+[79]="1 Int",
+[80]="2 Int",
+[81]="3 Int",
+[82]="1 Spirit",
+[83]="2 Spirit",
+[84]="3 Spirit",
+[85]="3 Armor",
+[86]="8 Armor",
+[87]="12 Armor",
+[89]="16 Armor",
+[90]="4 Agi",
+[91]="5 Agi",
+[92]="6 Agi",
+[93]="7 Agi",
+[94]="4 Int",
+[95]="5 Int",
+[96]="6 Int",
+[97]="7 Int",
+[98]="4 Spirit",
+[99]="5 Spirit",
+[100]="6 Spirit",
+[101]="7 Spirit",
+[102]="4 Stam",
+[103]="5 Stam",
+[104]="6 Stam",
+[105]="7 Stam",
+[106]="4 Str",
+[107]="5 Str",
+[108]="6 Str",
+[109]="7 Str",
+[110]="1 Dodge",
+[111]="2 Dodge",
+[112]="3 Dodge",
+[113]="4 Dodge",
+[114]="5 Dodge",
+[115]="6 Dodge",
+[116]="7 Dodge",
+[117]="+4 Damage",
+[118]="+5 Damage",
+[119]="+6 Damage",
+[120]="+7 Damage",
+[121]="20 Armor",
+[122]="24 Armor",
+[123]="28 Armor",
+[125]="+1 Sword Skill",
+[126]="+2 Sword Skill",
+[127]="+3 Sword Skill",
+[128]="+4 Sword Skill",
+[129]="+5 Sword Skill",
+[130]="+6 Sword Skill",
+[131]="+7 Sword Skill",
+[132]="+1 Two-Handed Sword Skill",
+[133]="+2 Two-Handed Sword Skill",
+[134]="+3 Two-Handed Sword Skill",
+[135]="+4 Two-Handed Sword Skill",
+[136]="+5 Two-Handed Sword Skill",
+[137]="+6 Two-Handed Sword Skill",
+[138]="+7 Two-Handed Sword Skill",
+[139]="+1 Mace Skill",
+[140]="+2 Mace Skill",
+[141]="+3 Mace Skill",
+[142]="+4 Mace Skill",
+[143]="+5 Mace Skill",
+[144]="+6 Mace Skill",
+[145]="+7 Mace Skill",
+[146]="+1 Two-Handed Mace Skill",
+[147]="+2 Two-Handed Mace Skill",
+[148]="+3 Two-Handed Mace Skill",
+[149]="+4 Two-Handed Mace Skill",
+[150]="+5 Two-Handed Mace Skill",
+[151]="+6 Two-Handed Mace Skill",
+[152]="+7 Two-Handed Mace Skill",
+[153]="+1 Axe Skill",
+[154]="+2 Axe Skill",
+[155]="+3 Axe Skill",
+[156]="+4 Axe Skill",
+[157]="+5 Axe Skill",
+[158]="+6 Ase Skill",
+[159]="+7 Axe Skill",
+[160]="+1 Two-Handed Axe Skill",
+[161]="+2 Two-Handed Axe Skill",
+[162]="+3 Two-Handed Axe Skill",
+[163]="+4 Two-Handed Axe Skill",
+[164]="+5 Two-Handed Axe Skill",
+[165]="+6 Two-Handed Axe Skill",
+[166]="+7 Two-Handed Axe Skill",
+[167]="+1 Dagger Skill",
+[168]="+2 Dagger Skill",
+[169]="+3 Dagger Skill",
+[170]="+4 Dagger Skill",
+[171]="+5 Dagger Skill",
+[172]="+6 Dagger Skill",
+[173]="+7 Dagger Skill",
+[174]="+1 Gun Skill",
+[175]="+2 Gun Skill",
+[176]="+3 Gun Skill",
+[177]="+4 Gun Skill",
+[178]="+5 Gun Skill",
+[179]="+6 Gun Skill",
+[180]="+7 Gun Skill",
+[181]="+1 Bow Skill",
+[182]="+2 Bow Skill",
+[183]="+3 Bow Skill",
+[184]="+4 Bow Skill",
+[185]="+5 Bow Skill",
+[186]="+6 Bow Skill",
+[187]="+7 Bow Skill",
+[188]="+2 Beast Slaying",
+[189]="+4 Beast Slaying",
+[190]="+6 Beast Slaying",
+[191]="+8 Beast Slaying",
+[192]="+10 Beast Slaying",
+[193]="+12 Beast Slaying",
+[194]="+14 Beast Slaying",
+[195]="14 Crit",
+[196]="28 Crit",
+[197]="42 Crit",
+[198]="56 Crit",
+[199]="10% On Get Hit: Shadow Bolt (10 Damage)",
+[200]="10% On Get Hit: Shadow Bolt (20 Damage)",
+[201]="10% On Get Hit: Shadow Bolt (30 Damage)",
+[202]="10% On Get Hit: Shadow Bolt (40 Damage)",
+[203]="10% On Get Hit: Shadow Bolt (50 Damage)",
+[204]="10% On Get Hit: Shadow Bolt (60 Damage)",
+[205]="10% On Get Hit: Shadow Bolt (70 Damage)",
+[206]="1 SP",
+[207]="2 SP",
+[208]="4 SP",
+[209]="5 SP",
+[210]="6 SP",
+[211]="7 SP",
+[212]="8 SP",
+[213]="+1 Fire Spell Damage",
+[214]="+3 Fire Spell Damage",
+[215]="+4 Fire Spell Damage",
+[216]="+6 Fire Spell Damage",
+[217]="+7 Fire Spell Damage",
+[218]="+9 Fire Spell Damage",
+[219]="+10 Fire Spell Damage",
+[220]="+1 Nature Spell Damage",
+[221]="+3 Nature Spell Damage",
+[222]="+4 Nature Spell Damage",
+[223]="+6 Nature Spell Damage",
+[224]="+7 Nature Spell Damage",
+[225]="+9 Nature Spell Damage",
+[226]="+10 Nature Spell Damage",
+[227]="+1 Frost Spell Damage",
+[228]="+3 Frost Spell Damage",
+[229]="+4 Frost Spell Damage",
+[230]="+6 Frost Spell Damage",
+[231]="+7 Frost Spell Damage",
+[232]="+9 Frost Spell Damage",
+[233]="+10 Frost Spell Damage",
+[234]="+1 Shadow Spell Damage",
+[235]="+3 Shadow Spell Damage",
+[236]="+4 Shadow Spell Damage",
+[237]="+6 Shadow Spell Damage",
+[238]="+7 Shadow Spell Damage",
+[239]="+9 Shadow Spell Damage",
+[240]="+10 Shadow Spell Damage",
+[241]="+2 Weapon Damage",
+[242]="+15 Health",
+[243]="1 Spirit",
+[244]="4 Int",
+[245]="5 Armor",
+[246]="+20 Mana",
+[247]="1 Agi",
+[248]="1 Str",
+[249]="+2 Beastslaying",
+[250]="+1  Weapon Damage",
+[251]="1 Int",
+[252]="6 Spirit",
+[253]="Absorption (50)",
+[254]="+25 Health",
+[255]="3 Spirit",
+[256]="+5 Fire Resistance",
+[257]="10 Armor",
+[263]="Fishing Lure (+25 Fishing Skill)",
+[264]="Fishing Lure (+50 Fishing Skill)",
+[265]="Fishing Lure (+75 Fishing Skill)",
+[266]="Fishing Lure (+100 Fishing Skill)",
+[283]="Windfury",
+[286]="+2 Weapon Fire Damage",
+[287]="+4 Weapon Fire Damage",
+[288]="+6 Weapon Fire Damage",
+[289]="+8 Weapon Fire Damage",
+[290]="+0 Weapon Fire Damage",
+[291]="+12 Weapon Fire Damage",
+[292]="+14 Weapon Fire Damage",
+[303]="Orb of Fire",
+[343]="8 Agi",
+[344]="32 Armor",
+[345]="40 Armor",
+[346]="36 Armor",
+[347]="44 Armor",
+[348]="48 Armor",
+[349]="9 Agi",
+[350]="8 Int",
+[351]="8 Spirit",
+[352]="8 Str",
+[353]="8 Stam",
+[354]="9 Int",
+[355]="9 Spirit",
+[356]="9 Stam",
+[357]="9 Str",
+[358]="10 Agi",
+[359]="10 Int",
+[360]="10 Spirit",
+[361]="10 Stam",
+[362]="10 Str",
+[363]="11 Agi",
+[364]="11 Int",
+[365]="11 Spirit",
+[366]="11 Stam",
+[367]="11 Str",
+[368]="12 Agi",
+[369]="12 Int",
+[370]="12 Spirit",
+[371]="12 Stam",
+[372]="12 Str",
+[383]="52 Armor",
+[384]="56 Armor",
+[385]="60 Armor",
+[386]="16 Armor",
+[387]="17 Armor",
+[388]="18 Armor",
+[389]="19 Armor",
+[403]="13 Agi",
+[404]="14 Agi",
+[405]="13 Int",
+[406]="14 Int",
+[407]="13 Spirit",
+[408]="14 Spirit",
+[409]="13 Stam",
+[410]="13 Str",
+[411]="14 Stam",
+[412]="14 Str",
+[423]="1 SP",
+[424]="2 SP",
+[425]="Black Temple Dummy",
+[426]="5 SP",
+[427]="6 SP",
+[428]="7 SP",
+[429]="8 SP",
+[430]="9 SP",
+[431]="11 SP",
+[432]="12 SP",
+[433]="+11 Fire Spell Damage",
+[434]="+13 Fire Spell Damage",
+[435]="+14 Fire Spell Damage",
+[436]="70 Crit",
+[437]="+11 Frost Spell Damage",
+[438]="+13 Frost Spell Damage",
+[439]="+14 Frost Spell Damage",
+[440]="9 SP",
+[441]="11 SP",
+[442]="12 SP",
+[443]="+11 Nature Spell Damage",
+[444]="+13 Nature Spell Damage",
+[445]="+14 Nature Spell Damage",
+[446]="+11 Shadow Spell Damage",
+[447]="+13 Shadow Spell Damage",
+[448]="+14 Shadow Spell Damage",
+[463]="Mithril Spike (16-20)",
+[464]="+4% Mount Speed",
+[483]="Sharpened (+6 Damage)",
+[484]="Weighted (+6 Damage)",
+[583]="1 Agi, 1 Spirit",
+[584]="1 Agi, 1 Int",
+[585]="1 Agi, 1 Stam",
+[586]="1 Agi, 1 Str",
+[587]="1 Int, 1 Spirit",
+[588]="1 Int, 1 Stam",
+[589]="1 Int, 1 Str",
+[590]="1 Stam, 1 Spirit",
+[591]="1 Str, 1 Spirit",
+[592]="1 Stam, 1 Str",
+[663]="Scope (+5 Damage)",
+[664]="Scope (+7 Damage)",
+[684]="15 Str",
+[723]="3 Int",
+[724]="3 Stam",
+[743]="+2 Stealth",
+[744]="20 Armor",
+[763]="+5 Shield Block",
+[783]="10 Armor",
+[803]="Fiery Weapon",
+[804]="+10 Shadow Resistance",
+[805]="+4 Weapon Damage",
+[823]="3 Str",
+[843]="+30 Mana",
+[844]="+2 Mining",
+[845]="+2 Herbalism",
+[846]="+5 Fishing",
+[847]="1 Str, 1 Agi, 1 Stam, 1 Int, 1 Spirit",
+[848]="30 Armor",
+[849]="3 Agi",
+[850]="+35 Health",
+[851]="5 Spirit",
+[852]="5 Stam",
+[853]="+6 Beastslaying",
+[854]="+6 Elemental Slayer",
+[855]="+5 Fire Resistance",
+[856]="5 Str",
+[857]="+50 Mana",
+[863]="10 Parry",
+[864]="+4 Weapon Damage",
+[865]="+5 Skinning",
+[866]="2 Str, 2 Agi, 2 Stam, 2 Int, 2 Spirit",
+[883]="15 Agi",
+[884]="50 Armor",
+[903]="+3 All Resistances",
+[904]="5 Agi",
+[905]="5 Int",
+[906]="+5 Mining",
+[907]="7 Spirit",
+[908]="+50 Health",
+[909]="+5 Herbalism",
+[910]="8 Agi, 8 Dodge",
+[911]=", Run Speed",
+[912]="Demonslaying",
+[913]="+65 Mana",
+[923]="5 Dodge",
+[924]="2 Dodge",
+[925]="3 Dodge",
+[926]="+8 Frost Resistance",
+[927]="7 Str",
+[928]="3 Str, 3 Agi, 3 Stam, 3 Int, 3 Spirit",
+[929]="7 Stam",
+[930]="+2% Mount Speed",
+[931]="10 Haste",
+[943]="+3 Weapon Damage",
+[963]="+7 Weapon Damage",
+[983]="16 Agi",
+[1003]="Venomhide Poison",
+[1043]="16 Str",
+[1044]="17 Str",
+[1045]="18 Str",
+[1046]="19 Str",
+[1047]="20 Str",
+[1048]="21 Str",
+[1049]="22 Str",
+[1050]="23 Str",
+[1051]="24 Str",
+[1052]="25 Str",
+[1053]="26 Str",
+[1054]="27 Str",
+[1055]="28 Str",
+[1056]="29 Str",
+[1057]="30 Str",
+[1058]="31 Str",
+[1059]="32 Str",
+[1060]="33 Str",
+[1061]="34 Str",
+[1062]="35 Str",
+[1063]="36 Str",
+[1064]="37 Str",
+[1065]="38 Str",
+[1066]="39 Str",
+[1067]="40 Str",
+[1068]="15 Stam",
+[1069]="16 Stam",
+[1070]="17 Stam",
+[1071]="18 Stam",
+[1072]="19 Stam",
+[1073]="20 Stam",
+[1074]="21 Stam",
+[1075]="22 Stam",
+[1076]="23 Stam",
+[1077]="24 Stam",
+[1078]="25 Stam",
+[1079]="26 Stam",
+[1080]="27 Stam",
+[1081]="28 Stam",
+[1082]="29 Stam",
+[1083]="30 Stam",
+[1084]="31 Stam",
+[1085]="32 Stam",
+[1086]="33 Stam",
+[1087]="34 Stam",
+[1088]="35 Stam",
+[1089]="36 Stam",
+[1090]="37 Stam",
+[1091]="38 Stam",
+[1092]="39 Stam",
+[1093]="40 Stam",
+[1094]="17 Agi",
+[1095]="18 Agi",
+[1096]="19 Agi",
+[1097]="20 Agi",
+[1098]="21 Agi",
+[1099]="22 Agi",
+[1100]="23 Agi",
+[1101]="24 Agi",
+[1102]="25 Agi",
+[1103]="26 Agi",
+[1104]="27 Agi",
+[1105]="28 Agi",
+[1106]="29 Agi",
+[1107]="30 Agi",
+[1108]="31 Agi",
+[1109]="32 Agi",
+[1110]="33 Agi",
+[1111]="34 Agi",
+[1112]="35 Agi",
+[1113]="36 Agi",
+[1114]="37 Agi",
+[1115]="38 Agi",
+[1116]="39 Agi",
+[1117]="40 Agi",
+[1118]="15 Int",
+[1119]="16 Int",
+[1120]="17 Int",
+[1121]="18 Int",
+[1122]="19 Int",
+[1123]="20 Int",
+[1124]="21 Int",
+[1125]="22 Int",
+[1126]="23 Int",
+[1127]="24 Int",
+[1128]="25 Int",
+[1129]="26 Int",
+[1130]="27 Int",
+[1131]="28 Int",
+[1132]="29 Int",
+[1133]="30 Int",
+[1134]="31 Int",
+[1135]="32 Int",
+[1136]="33 Int",
+[1137]="34 Int",
+[1138]="35 Int",
+[1139]="36 Int",
+[1140]="37 Int",
+[1141]="38 Int",
+[1142]="39 Int",
+[1143]="40 Int",
+[1144]="15 Spirit",
+[1145]="16 Spirit",
+[1146]="17 Spirit",
+[1147]="18 Spirit",
+[1148]="19 Spirit",
+[1149]="20 Spirit",
+[1150]="21 Spirit",
+[1151]="22 Spirit",
+[1152]="23 Spirit",
+[1153]="24 Spirit",
+[1154]="25 Spirit",
+[1155]="26 Spirit",
+[1156]="27 Spirit",
+[1157]="28 Spirit",
+[1158]="29 Spirit",
+[1159]="30 Spirit",
+[1160]="31 Spirit",
+[1161]="32 Spirit",
+[1162]="33 Spirit",
+[1163]="34 Spirit",
+[1164]="36 Spirit",
+[1165]="37 Spirit",
+[1166]="38 Spirit",
+[1167]="39 Spirit",
+[1168]="40 Spirit",
+[1183]="35 Spirit",
+[1203]="41 Str",
+[1204]="42 Str",
+[1205]="43 Str",
+[1206]="44 Str",
+[1207]="45 Str",
+[1208]="46 Str",
+[1209]="41 Stam",
+[1210]="42 Stam",
+[1211]="43 Stam",
+[1212]="44 Stam",
+[1213]="45 Stam",
+[1214]="46 Stam",
+[1215]="41 Agi",
+[1216]="42 Agi",
+[1217]="43 Agi",
+[1218]="44 Agi",
+[1219]="45 Agi",
+[1220]="46 Agi",
+[1221]="41 Int",
+[1222]="42 Int",
+[1223]="43 Int",
+[1224]="44 Int",
+[1225]="45 Int",
+[1226]="46 Int",
+[1227]="41 Spirit",
+[1228]="42 Spirit",
+[1229]="43 Spirit",
+[1230]="44 Spirit",
+[1231]="45 Spirit",
+[1232]="46 Spirit",
+[1243]="+1 Arcane Resistance",
+[1244]="+2 Arcane Resistance",
+[1245]="+3 Arcane Resistance",
+[1246]="+4 Arcane Resistance",
+[1247]="+5 Arcane Resistance",
+[1248]="+6 Arcane Resistance",
+[1249]="+7 Arcane Resistance",
+[1250]="+8 Arcane Resistance",
+[1251]="+9 Arcane Resistance",
+[1252]="+10 Arcane Resistance",
+[1253]="+11 Arcane Resistance",
+[1254]="+12 Arcane Resistance",
+[1255]="+13 Arcane Resistance",
+[1256]="+14 Arcane Resistance",
+[1257]="+15 Arcane Resistance",
+[1258]="+16 Arcane Resistance",
+[1259]="+17 Arcane Resistance",
+[1260]="+18 Arcane Resistance",
+[1261]="+19 Arcane Resistance",
+[1262]="+20 Arcane Resistance",
+[1263]="+21 Arcane Resistance",
+[1264]="+22 Arcane Resistance",
+[1265]="+23 Arcane Resistance",
+[1266]="+24 Arcane Resistance",
+[1267]="+25 Arcane Resistance",
+[1268]="+26 Arcane Resistance",
+[1269]="+27 Arcane Resistance",
+[1270]="+28 Arcane Resistance",
+[1271]="+29 Arcane Resistance",
+[1272]="+30 Arcane Resistance",
+[1273]="+31 Arcane Resistance",
+[1274]="+32 Arcane Resistance",
+[1275]="+33 Arcane Resistance",
+[1276]="+34 Arcane Resistance",
+[1277]="+35 Arcane Resistance",
+[1278]="+36 Arcane Resistance",
+[1279]="+37 Arcane Resistance",
+[1280]="+38 Arcane Resistance",
+[1281]="+39 Arcane Resistance",
+[1282]="+40 Arcane Resistance",
+[1283]="+41 Arcane Resistance",
+[1284]="+42 Arcane Resistance",
+[1285]="+43 Arcane Resistance",
+[1286]="+44 Arcane Resistance",
+[1287]="+45 Arcane Resistance",
+[1288]="+46 Arcane Resistance",
+[1289]="+1 Frost Resistance",
+[1290]="+2 Frost Resistance",
+[1291]="+3 Frost Resistance",
+[1292]="+4 Frost Resistance",
+[1293]="+5 Frost Resistance",
+[1294]="+6 Frost Resistance",
+[1295]="+7 Frost Resistance",
+[1296]="+8 Frost Resistance",
+[1297]="+9 Frost Resistance",
+[1298]="+10 Frost Resistance",
+[1299]="+11 Frost Resistance",
+[1300]="+12 Frost Resistance",
+[1301]="+13 Frost Resistance",
+[1302]="+14 Frost Resistance",
+[1303]="+15 Frost Resistance",
+[1304]="+16 Frost Resistance",
+[1305]="+17 Frost Resistance",
+[1306]="+18 Frost Resistance",
+[1307]="+19 Frost Resistance",
+[1308]="+20 Frost Resistance",
+[1309]="+21 Frost Resistance",
+[1310]="+22 Frost Resistance",
+[1311]="+23 Frost Resistance",
+[1312]="+24 Frost Resistance",
+[1313]="+25 Frost Resistance",
+[1314]="+26 Frost Resistance",
+[1315]="+27 Frost Resistance",
+[1316]="+28 Frost Resistance",
+[1317]="+29 Frost Resistance",
+[1318]="+30 Frost Resistance",
+[1319]="+31 Frost Resistance",
+[1320]="+32 Frost Resistance",
+[1321]="+33 Frost Resistance",
+[1322]="+34 Frost Resistance",
+[1323]="+35 Frost Resistance",
+[1324]="+36 Frost Resistance",
+[1325]="+37 Frost Resistance",
+[1326]="+38 Frost Resistance",
+[1327]="+39 Frost Resistance",
+[1328]="+40 Frost Resistance",
+[1329]="+41 Frost Resistance",
+[1330]="+42 Frost Resistance",
+[1331]="+43 Frost Resistance",
+[1332]="+44 Frost Resistance",
+[1333]="+45 Frost Resistance",
+[1334]="+46 Frost Resistance",
+[1335]="+1 Fire Resistance",
+[1336]="+2 Fire Resistance",
+[1337]="+3 Fire Resistance",
+[1338]="+4 Fire Resistance",
+[1339]="+5 Fire Resistance",
+[1340]="+6 Fire Resistance",
+[1341]="+7 Fire Resistance",
+[1342]="+8 Fire Resistance",
+[1343]="+9 Fire Resistance",
+[1344]="+10 Fire Resistance",
+[1345]="+11 Fire Resistance",
+[1346]="+12 Fire Resistance",
+[1347]="+13 Fire Resistance",
+[1348]="+14 Fire Resistance",
+[1349]="+15 Fire Resistance",
+[1350]="+16 Fire Resistance",
+[1351]="+17 Fire Resistance",
+[1352]="+18 Fire Resistance",
+[1353]="+19 Fire Resistance",
+[1354]="+20 Fire Resistance",
+[1355]="+21 Fire Resistance",
+[1356]="+22 Fire Resistance",
+[1357]="+23 Fire Resistance",
+[1358]="+24 Fire Resistance",
+[1359]="+25 Fire Resistance",
+[1360]="+26 Fire Resistance",
+[1361]="+27 Fire Resistance",
+[1362]="+28 Fire Resistance",
+[1363]="+29 Fire Resistance",
+[1364]="+30 Fire Resistance",
+[1365]="+31 Fire Resistance",
+[1366]="+32 Fire Resistance",
+[1367]="+33 Fire Resistance",
+[1368]="+34 Fire Resistance",
+[1369]="+35 Fire Resistance",
+[1370]="+36 Fire Resistance",
+[1371]="+37 Fire Resistance",
+[1372]="+38 Fire Resistance",
+[1373]="+39 Fire Resistance",
+[1374]="+40 Fire Resistance",
+[1375]="+41 Fire Resistance",
+[1376]="+42 Fire Resistance",
+[1377]="+43 Fire Resistance",
+[1378]="+44 Fire Resistance",
+[1379]="+45 Fire Resistance",
+[1380]="+46 Fire Resistance",
+[1381]="+1 Nature Resistance",
+[1382]="+2 Nature Resistance",
+[1383]="+3 Nature Resistance",
+[1384]="+4 Nature Resistance",
+[1385]="+5 Nature Resistance",
+[1386]="+6 Nature Resistance",
+[1387]="+7 Nature Resistance",
+[1388]="+8 Nature Resistance",
+[1389]="+9 Nature Resistance",
+[1390]="+10 Nature Resistance",
+[1391]="+11 Nature Resistance",
+[1392]="+12 Nature Resistance",
+[1393]="+13 Nature Resistance",
+[1394]="+14 Nature Resistance",
+[1395]="+15 Nature Resistance",
+[1396]="+16 Nature Resistance",
+[1397]="+17 Nature Resistance",
+[1398]="+18 Nature Resistance",
+[1399]="+19 Nature Resistance",
+[1400]="+20 Nature Resistance",
+[1401]="+21 Nature Resistance",
+[1402]="+22 Nature Resistance",
+[1403]="+23 Nature Resistance",
+[1404]="+24 Nature Resistance",
+[1405]="+25 Nature Resistance",
+[1406]="+26 Nature Resistance",
+[1407]="+27 Nature Resistance",
+[1408]="+28 Nature Resistance",
+[1409]="+29 Nature Resistance",
+[1410]="+30 Nature Resistance",
+[1411]="+31 Nature Resistance",
+[1412]="+32 Nature Resistance",
+[1413]="+33 Nature Resistance",
+[1414]="+34 Nature Resistance",
+[1415]="+35 Nature Resistance",
+[1416]="+36 Nature Resistance",
+[1417]="+37 Nature Resistance",
+[1418]="+38 Nature Resistance",
+[1419]="+39 Nature Resistance",
+[1420]="+40 Nature Resistance",
+[1421]="+41 Nature Resistance",
+[1422]="+42 Nature Resistance",
+[1423]="+43 Nature Resistance",
+[1424]="+44 Nature Resistance",
+[1425]="+45 Nature Resistance",
+[1426]="+46 Nature Resistance",
+[1427]="+1 Shadow Resistance",
+[1428]="+2 Shadow Resistance",
+[1429]="+3 Shadow Resistance",
+[1430]="+4 Shadow Resistance",
+[1431]="+5 Shadow Resistance",
+[1432]="+6 Shadow Resistance",
+[1433]="+7 Shadow Resistance",
+[1434]="+8 Shadow Resistance",
+[1435]="+9 Shadow Resistance",
+[1436]="+10 Shadow Resistance",
+[1437]="+11 Shadow Resistance",
+[1438]="+12 Shadow Resistance",
+[1439]="+13 Shadow Resistance",
+[1440]="+14 Shadow Resistance",
+[1441]="+15 Shadow Resistance",
+[1442]="+16 Shadow Resistance",
+[1443]="+17 Shadow Resistance",
+[1444]="+18 Shadow Resistance",
+[1445]="+19 Shadow Resistance",
+[1446]="+20 Shadow Resistance",
+[1447]="+21 Shadow Resistance",
+[1448]="+22 Shadow Resistance",
+[1449]="+23 Shadow Resistance",
+[1450]="+24 Shadow Resistance",
+[1451]="+25 Shadow Resistance",
+[1452]="+26 Resist Shadow",
+[1453]="+27 Shadow Resistance",
+[1454]="+28 Shadow Resistance",
+[1455]="+29 Shadow Resistance",
+[1456]="+30 Shadow Resistance",
+[1457]="+31 Shadow Resistance",
+[1458]="+32 Shadow Resistance",
+[1459]="+33 Shadow Resistance",
+[1460]="+34 Shadow Resistance",
+[1461]="+35 Shadow Resistance",
+[1462]="+36 Shadow Resistance",
+[1463]="+37 Shadow Resistance",
+[1464]="+38 Shadow Resistance",
+[1465]="+39 Shadow Resistance",
+[1466]="+40 Shadow Resistance",
+[1467]="+41 Shadow Resistance",
+[1468]="+42 Shadow Resistance",
+[1469]="+43 Shadow Resistance",
+[1470]="+44 Shadow Resistance",
+[1471]="+45 Shadow Resistance",
+[1472]="+46 Shadow Resistance",
+[1483]="+150 Mana",
+[1503]="+100 Health",
+[1504]="125 Armor",
+[1505]="+20 Fire Resistance",
+[1506]="8 Str",
+[1507]="8 Stam",
+[1508]="8 Agi",
+[1509]="8 Int",
+[1510]="8 Spirit",
+[1523]="+85 Mana and +14 Fire Resistance",
+[1524]="+75 Health and +14 Fire Resistance",
+[1525]="110 Armor",
+[1526]="10 Str",
+[1527]="10 Stam",
+[1528]="10 Agi",
+[1529]="10 Int",
+[1530]="10 Spirit",
+[1531]="10 Str, 10 Stam",
+[1532]="15 Str",
+[1543]="15 Int",
+[1563]="2 AP",
+[1583]="4 AP",
+[1584]="6 AP",
+[1585]="8 AP",
+[1586]="10 AP",
+[1587]="12 AP",
+[1588]="14 AP",
+[1589]="16 AP",
+[1590]="18 AP",
+[1591]="20 AP",
+[1592]="22 AP",
+[1593]="24 AP",
+[1594]="26 AP",
+[1595]="28 AP",
+[1596]="30 AP",
+[1597]="32 AP",
+[1598]="34 AP",
+[1599]="36 AP",
+[1600]="38 AP",
+[1601]="32 AP",
+[1602]="42 AP",
+[1603]="44 AP",
+[1604]="46 AP",
+[1605]="48 AP",
+[1606]="50 AP",
+[1607]="52 AP",
+[1608]="54 AP",
+[1609]="56 AP",
+[1610]="58 AP",
+[1611]="60 AP",
+[1612]="62 AP",
+[1613]="64 AP",
+[1614]="66 AP",
+[1615]="68 AP",
+[1616]="70 AP",
+[1617]="72 AP",
+[1618]="74 AP",
+[1619]="76 AP",
+[1620]="78 AP",
+[1621]="80 AP",
+[1622]="82 AP",
+[1623]="84 AP",
+[1624]="86 AP",
+[1625]="88 AP",
+[1626]="90 AP",
+[1627]="92 AP",
+[1643]="Sharpened (+8 Damage)",
+[1703]="Weighted (+8 Damage)",
+[1704]="Thorium Spike (20-30)",
+[1723]="Omen of Clarity",
+[1743]="MHTest02",
+[1763]="Cold Blood",
+[1803]="Firestone 1",
+[1823]="Firestone 2",
+[1824]="Firestone 3",
+[1825]="Firestone 4",
+[1843]="40 Armor",
+[1883]="7 Int",
+[1884]="9 Spirit",
+[1885]="9 Str",
+[1886]="9 Stam",
+[1887]="7 Agi",
+[1888]="+5 All Resistances",
+[1889]="70 Armor",
+[1890]="10 Stam, 10 Spirit",
+[1891]="4 Str, 4 Agi, 4 Stam, 4 Int, 4 Spirit",
+[1892]="+100 Health",
+[1893]="+100 Mana",
+[1894]="Icy Chill",
+[1895]="+9 Damage",
+[1896]="+9 Weapon Damage",
+[1897]="+5 Weapon Damage",
+[1898]="Lifestealing",
+[1899]="Unholy Weapon",
+[1900]="Crusader",
+[1901]="9 Int",
+[1903]="9 Spirit",
+[1904]="9 Int",
+[1923]="+3 Fire Resistance",
+[1943]="12 Dodge",
+[1944]="8 Dodge",
+[1945]="9 Dodge",
+[1946]="10 Dodge",
+[1947]="11 Dodge",
+[1948]="13 Dodge",
+[1949]="14 Dodge",
+[1950]="15 Dodge",
+[1951]="18 Dodge",
+[1952]="20 Dodge",
+[1953]="22 Dodge",
+[1954]="25 Dodge",
+[1955]="32 Dodge",
+[1956]="17 Dodge",
+[1957]="18 Dodge",
+[1958]="19 Dodge",
+[1959]="21 Dodge",
+[1960]="23 Dodge",
+[1961]="24 Dodge",
+[1962]="26 Dodge",
+[1963]="27 Dodge",
+[1964]="28 Dodge",
+[1965]="29 Dodge",
+[1966]="30 Dodge",
+[1967]="31 Dodge",
+[1968]="33 Dodge",
+[1969]="34 Dodge",
+[1970]="35 Dodge",
+[1971]="36 Dodge",
+[1972]="37 Dodge",
+[1973]="38 Dodge",
+[1983]="+5 Block",
+[1984]="+10 Block",
+[1985]="+15 Block",
+[1986]="+20 Block",
+[1987]="Block Level 14",
+[1988]="Block Level 15",
+[1989]="Block Level 16",
+[1990]="Block Level 17",
+[1991]="Block Level 18",
+[1992]="Block Level 19",
+[1993]="Block Level 20",
+[1994]="Block Level 21",
+[1995]="Block Level 22",
+[1996]="Block Level 23",
+[1997]="Block Level 24",
+[1998]="Block Level 25",
+[1999]="Block Level 26",
+[2000]="Block Level 27",
+[2001]="Block Level 28",
+[2002]="Block Level 29",
+[2003]="Block Level 30",
+[2004]="Block Level 31",
+[2005]="Block Level 32",
+[2006]="Block Level 33",
+[2007]="Block Level 34",
+[2008]="Block Level 35",
+[2009]="Block Level 36",
+[2010]="Block Level 37",
+[2011]="Block Level 38",
+[2012]="Block Level 39",
+[2013]="Block Level 40",
+[2014]="Block Level 41",
+[2015]="Block Level 42",
+[2016]="Block Level 43",
+[2017]="Block Level 44",
+[2018]="Block Level 45",
+[2019]="Block Level 46",
+[2020]="Block Level 47",
+[2021]="Block Level 48",
+[2022]="Block Level 49",
+[2023]="Block Level 50",
+[2024]="Block Level 51",
+[2025]="Block Level 52",
+[2026]="Block Level 53",
+[2027]="Block Level 54",
+[2028]="Block Level 55",
+[2029]="Block Level 56",
+[2030]="Block Level 57",
+[2031]="Block Level 58",
+[2032]="Block Level 59",
+[2033]="Block Level 60",
+[2034]="Block Level 61",
+[2035]="Block Level 62",
+[2036]="Block Level 63",
+[2037]="Block Level 64",
+[2038]="Block Level 65",
+[2039]="Block Level 66",
+[2040]="+2 Ranged Attack Power",
+[2041]="+5 Ranged Attack Power",
+[2042]="+7 Ranged Attack Power",
+[2043]="+10 Ranged Attack Power",
+[2044]="+12 Ranged Attack Power",
+[2045]="+14 Ranged Attack Power",
+[2046]="+17 Ranged Attack Power",
+[2047]="+19 Ranged Attack Power",
+[2048]="+22 Ranged Attack Power",
+[2049]="+24 Ranged Attack Power",
+[2050]="+26 Ranged Attack Power",
+[2051]="+29 Ranged Attack Power",
+[2052]="+31 Ranged Attack Power",
+[2053]="+34 Ranged Attack Power",
+[2054]="+36 Ranged Attack Power",
+[2055]="+38 Ranged Attack Power",
+[2056]="+41 Ranged Attack Power",
+[2057]="+43 Ranged Attack Power",
+[2058]="+46 Ranged Attack Power",
+[2059]="+48 Ranged Attack Power",
+[2060]="+50 Ranged Attack Power",
+[2061]="+53 Ranged Attack Power",
+[2062]="+55 Ranged Attack Power",
+[2063]="+58 Ranged Attack Power",
+[2064]="+60 Ranged Attack Power",
+[2065]="+62 Ranged Attack Power",
+[2066]="+65 Ranged Attack Power",
+[2067]="+67 Ranged Attack Power",
+[2068]="+70 Ranged Attack Power",
+[2069]="+72 Ranged Attack Power",
+[2070]="+74 Ranged Attack Power",
+[2071]="+77 Ranged Attack Power",
+[2072]="+79 Ranged Attack Power",
+[2073]="+82 Ranged Attack Power",
+[2074]="+84 Ranged Attack Power",
+[2075]="+86 Ranged Attack Power",
+[2076]="+89 Ranged Attack Power",
+[2077]="+91 Ranged Attack Power",
+[2078]="12 Dodge",
+[2079]="+1 Arcane Spell Damage",
+[2080]="+3 Arcane Spell Damage",
+[2081]="+4 Arcane Spell Damage",
+[2082]="+6 Arcane Spell Damage",
+[2083]="+7 Arcane Spell Damage",
+[2084]="+9 Arcane Spell Damage",
+[2085]="+10 Arcane Spell Damage",
+[2086]="+11 Arcane Spell Damage",
+[2087]="+13 Arcane Spell Damage",
+[2088]="+14 Arcane Spell Damage",
+[2089]="+16 Arcane Spell Damage",
+[2090]="+17 Arcane Spell Damage",
+[2091]="+19 Arcane Spell Damage",
+[2092]="+20 Arcane Spell Damage",
+[2093]="+21 Arcane Spell Damage",
+[2094]="+23 Arcane Spell Damage",
+[2095]="+24 Arcane Spell Damage",
+[2096]="+26 Arcane Spell Damage",
+[2097]="+27 Arcane Spell Damage",
+[2098]="+29 Arcane Spell Damage",
+[2099]="+30 Arcane Spell Damage",
+[2100]="+31 Arcane Spell Damage",
+[2101]="+33 Arcane Spell Damage",
+[2102]="+34 Arcane Spell Damage",
+[2103]="+36 Arcane Spell Damage",
+[2104]="+37 Arcane Spell Damage",
+[2105]="+39 Arcane Spell Damage",
+[2106]="+40 Arcane Spell Damage",
+[2107]="+41 Arcane Spell Damage",
+[2108]="+43 Arcane Spell Damage",
+[2109]="+44 Arcane Spell Damage",
+[2110]="+46 Arcane Spell Damage",
+[2111]="+47 Arcane Spell Damage",
+[2112]="+49 Arcane Spell Damage",
+[2113]="+50 Arcane Spell Damage",
+[2114]="+51 Arcane Spell Damage",
+[2115]="+53 Arcane Spell Damage",
+[2116]="+54 Arcane Spell Damage",
+[2117]="+1 Shadow Spell Damage",
+[2118]="+3 Shadow Spell Damage",
+[2119]="+4 Shadow Spell Damage",
+[2120]="+6 Shadow Spell Damage",
+[2121]="+7 Shadow Spell Damage",
+[2122]="+9 Shadow Spell Damage",
+[2123]="+10 Shadow Spell Damage",
+[2124]="+11 Shadow Spell Damage",
+[2125]="+13 Shadow Spell Damage",
+[2126]="+14 Shadow Spell Damage",
+[2127]="+16 Shadow Spell Damage",
+[2128]="+17 Shadow Spell Damage",
+[2129]="+19 Shadow Spell Damage",
+[2130]="+20 Shadow Spell Damage",
+[2131]="+21 Shadow Spell Damage",
+[2132]="+23 Shadow Spell Damage",
+[2133]="+24 Shadow Spell Damage",
+[2134]="+26 Shadow Spell Damage",
+[2135]="+27 Shadow Spell Damage",
+[2136]="+29 Shadow Spell Damage",
+[2137]="+30 Shadow Spell Damage",
+[2138]="+31 Shadow Spell Damage",
+[2139]="+33 Shadow Spell Damage",
+[2140]="+34 Shadow Spell Damage",
+[2141]="+36 Shadow Spell Damage",
+[2142]="+37 Shadow Spell Damage",
+[2143]="+39 Shadow Spell Damage",
+[2144]="+40 Shadow Spell Damage",
+[2145]="+41 Shadow Spell Damage",
+[2146]="+43 Shadow Spell Damage",
+[2147]="+44 Shadow Spell Damage",
+[2148]="+46 Shadow Spell Damage",
+[2149]="+47 Shadow Spell Damage",
+[2150]="+49 Shadow Spell Damage",
+[2151]="+50 Shadow Spell Damage",
+[2152]="+51 Shadow Spell Damage",
+[2153]="+53 Shadow Spell Damage",
+[2154]="+54 Shadow Spell Damage",
+[2155]="+1 Fire Spell Damage",
+[2156]="+3 Fire Spell Damage",
+[2157]="+4 Fire Spell Damage",
+[2158]="+6 Fire Spell Damage",
+[2159]="+7 Fire Spell Damage",
+[2160]="+9 Fire Spell Damage",
+[2161]="+10 Fire Spell Damage",
+[2162]="+11 Fire Spell Damage",
+[2163]="+13 Fire Spell Damage",
+[2164]="+14 Fire Spell Damage",
+[2165]="+16 Fire Spell Damage",
+[2166]="+17 Fire Spell Damage",
+[2167]="+19 Fire Spell Damage",
+[2168]="+20 Fire Spell Damage",
+[2169]="+21 Fire Spell Damage",
+[2170]="+23 Fire Spell Damage",
+[2171]="+24 Fire Spell Damage",
+[2172]="+26 Fire Spell Damage",
+[2173]="+27 Fire Spell Damage",
+[2174]="+29 Fire Spell Damage",
+[2175]="+30 Fire Spell Damage",
+[2176]="+31 Fire Spell Damage",
+[2177]="+33 Fire Spell Damage",
+[2178]="+34 Fire Spell Damage",
+[2179]="+36 Fire Spell Damage",
+[2180]="+37 Fire Spell Damage",
+[2181]="+39 Fire Spell Damage",
+[2182]="+40 Fire Spell Damage",
+[2183]="+41 Fire Spell Damage",
+[2184]="+43 Fire Spell Damage",
+[2185]="+44 Fire Spell Damage",
+[2186]="+46 Fire Spell Damage",
+[2187]="+47 Fire Spell Damage",
+[2188]="+49 Fire Spell Damage",
+[2189]="+50 Fire Spell Damage",
+[2190]="+51 Fire Spell Damage",
+[2191]="+53 Fire Spell Damage",
+[2192]="+54 Fire Spell Damage",
+[2193]="+1 Holy Spell Damage",
+[2194]="+3 Holy Spell Damage",
+[2195]="+4 Holy Spell Damage",
+[2196]="+6 Holy Spell Damage",
+[2197]="+7 Holy Spell Damage",
+[2198]="+9 Holy Spell Damage",
+[2199]="+10 Holy Spell Damage",
+[2200]="+11 Holy Spell Damage",
+[2201]="+13 Holy Spell Damage",
+[2202]="+14 Holy Spell Damage",
+[2203]="+16 Holy Spell Damage",
+[2204]="+17 Holy Spell Damage",
+[2205]="+19 Holy Spell Damage",
+[2206]="+20 Holy Spell Damage",
+[2207]="+21 Holy Spell Damage",
+[2208]="+23 Holy Spell Damage",
+[2209]="+24 Holy Spell Damage",
+[2210]="+26 Holy Spell Damage",
+[2211]="+27 Holy Spell Damage",
+[2212]="+29 Holy Spell Damage",
+[2213]="+30 Holy Spell Damage",
+[2214]="+31 Holy Spell Damage",
+[2215]="+33 Holy Spell Damage",
+[2216]="+34 Holy Spell Damage",
+[2217]="+36 Holy Spell Damage",
+[2218]="+37 Holy Spell Damage",
+[2219]="+39 Holy Spell Damage",
+[2220]="+40 Holy Spell Damage",
+[2221]="+41 Holy Spell Damage",
+[2222]="+43 Holy Spell Damage",
+[2223]="+44 Holy Spell Damage",
+[2224]="+46 Holy Spell Damage",
+[2225]="+47 Holy Spell Damage",
+[2226]="+49 Holy Spell Damage",
+[2227]="+50 Holy Spell Damage",
+[2228]="+51 Holy Spell Damage",
+[2229]="+53 Holy Spell Damage",
+[2230]="+54 Holy Spell Damage",
+[2231]="+1 Frost Spell Damage",
+[2232]="+3 Frost Spell Damage",
+[2233]="+4 Frost Spell Damage",
+[2234]="+6 Frost Spell Damage",
+[2235]="+7 Frost Spell Damage",
+[2236]="+9 Frost Spell Damage",
+[2237]="+10 Frost Spell Damage",
+[2238]="+11 Frost Spell Damage",
+[2239]="+13 Frost Spell Damage",
+[2240]="+14 Frost Spell Damage",
+[2241]="+16 Frost Spell Damage",
+[2242]="+17 Frost Spell Damage",
+[2243]="+19 Frost Spell Damage",
+[2244]="+20 Frost Spell Damage",
+[2245]="+21 Frost Spell Damage",
+[2246]="+23 Frost Spell Damage",
+[2247]="+24 Frost Spell Damage",
+[2248]="+26 Frost Spell Damage",
+[2249]="+27 Frost Spell Damage",
+[2250]="+29 Frost Spell Damage",
+[2251]="+30 Frost Spell Damage",
+[2252]="+31 Frost Spell Damage",
+[2253]="+33 Frost Spell Damage",
+[2254]="+34 Frost Spell Damage",
+[2255]="+36 Frost Spell Damage",
+[2256]="+37 Frost Spell Damage",
+[2257]="+39 Frost Spell Damage",
+[2258]="+40 Frost Spell Damage",
+[2259]="+41 Frost Spell Damage",
+[2260]="+43 Frost Spell Damage",
+[2261]="+44 Frost Spell Damage",
+[2262]="+46 Frost Spell Damage",
+[2263]="+47 Frost Spell Damage",
+[2264]="+49 Frost Spell Damage",
+[2265]="+50 Frost Spell Damage",
+[2266]="+51 Frost Spell Damage",
+[2267]="+53 Frost Spell Damage",
+[2268]="+54 Frost Spell Damage",
+[2269]="+1 Nature Spell Damage",
+[2270]="+3 Nature Spell Damage",
+[2271]="+4 Nature Spell Damage",
+[2272]="+6 Nature Spell Damage",
+[2273]="+7 Nature Spell Damage",
+[2274]="+9 Nature Spell Damage",
+[2275]="+10 Nature Spell Damage",
+[2276]="+11 Nature Spell Damage",
+[2277]="+13 Nature Spell Damage",
+[2278]="+14 Nature Spell Damage",
+[2279]="+16 Nature Spell Damage",
+[2280]="+17 Nature Spell Damage",
+[2281]="+19 Nature Spell Damage",
+[2282]="+20 Nature Spell Damage",
+[2283]="+21 Nature Spell Damage",
+[2284]="+23 Nature Spell Damage",
+[2285]="+24 Nature Spell Damage",
+[2286]="+26 Nature Spell Damage",
+[2287]="+27 Nature Spell Damage",
+[2288]="+29 Nature Spell Damage",
+[2289]="+30 Nature Spell Damage",
+[2290]="+31 Nature Spell Damage",
+[2291]="+33 Nature Spell Damage",
+[2292]="+34 Nature Spell Damage",
+[2293]="+36 Nature Spell Damage",
+[2294]="+37 Nature Spell Damage",
+[2295]="+39 Nature Spell Damage",
+[2296]="+40 Nature Spell Damage",
+[2297]="+41 Nature Spell Damage",
+[2298]="+43 Nature Spell Damage",
+[2299]="+44 Nature Spell Damage",
+[2300]="+46 Nature Spell Damage",
+[2301]="+47 Nature Spell Damage",
+[2302]="+49 Nature Spell Damage",
+[2303]="+50 Nature Spell Damage",
+[2304]="+51 Nature Spell Damage",
+[2305]="+53 Nature Spell Damage",
+[2306]="+54 Nature Spell Damage",
+[2307]="1 SP",
+[2308]="2 SP",
+[2309]="4 SP",
+[2310]="5 SP",
+[2311]="6 SP",
+[2312]="7 SP",
+[2313]="8 SP",
+[2314]="9 SP",
+[2315]="11 SP",
+[2316]="12 SP",
+[2317]="13 SP",
+[2318]="14 SP",
+[2319]="15 SP",
+[2320]="16 SP",
+[2321]="18 SP",
+[2322]="19 SP",
+[2323]="20 SP",
+[2324]="21 SP",
+[2325]="22 SP",
+[2326]="23 SP",
+[2327]="25 SP",
+[2328]="26 SP",
+[2329]="27 SP",
+[2330]="28 SP",
+[2331]="29 SP",
+[2332]="30 SP",
+[2333]="32 SP",
+[2334]="33 SP",
+[2335]="34 SP",
+[2336]="35 SP",
+[2337]="36 SP",
+[2338]="37 SP",
+[2339]="39 SP",
+[2340]="40 SP",
+[2341]="41 SP",
+[2342]="42 SP",
+[2343]="43 SP",
+[2344]="44 SP",
+[2363]="+1 mana every 5 sec.",
+[2364]="+1 mana every 5 sec.",
+[2365]="+1 mana every 5 sec.",
+[2366]="+2 mana every 5 sec.",
+[2367]="+2 mana every 5 sec.",
+[2368]="+2 mana every 5 sec.",
+[2369]="+3 mana every 5 sec.",
+[2370]="+3 mana every 5 sec.",
+[2371]="+4 mana every 5 sec.",
+[2372]="+4 mana every 5 sec.",
+[2373]="+4 mana every 5 sec.",
+[2374]="+5 mana every 5 sec.",
+[2375]="+5 mana every 5 sec.",
+[2376]="+6 mana every 5 sec.",
+[2377]="+6 mana every 5 sec.",
+[2378]="+6 mana every 5 sec.",
+[2379]="+7 mana every 5 sec.",
+[2380]="+7 mana every 5 sec.",
+[2381]="20 Spirit",
+[2382]="+8 mana every 5 sec.",
+[2383]="+8 mana every 5 sec.",
+[2384]="+9 mana every 5 sec.",
+[2385]="+9 mana every 5 sec.",
+[2386]="24 Spirit",
+[2387]="25 Spirit",
+[2388]="26 Spirit",
+[2389]="27 Spirit",
+[2390]="28 Spirit",
+[2391]="29 Spirit",
+[2392]="30 Spirit",
+[2393]="31 Spirit",
+[2394]="32 Spirit",
+[2395]="33 Spirit",
+[2396]="+14 mana every 5 sec.",
+[2397]="+14 mana every 5 sec.",
+[2398]="+14 mana every 5 sec.",
+[2399]="+15 mana every 5 sec.",
+[2400]="+15 mana every 5 sec.",
+[2401]="+1 health every 5 sec.",
+[2402]="+1 health every 5 sec.",
+[2403]="+1 health every 5 sec.",
+[2404]="+1 health every 5 sec.",
+[2405]="+1 health every 5 sec.",
+[2406]="+2 health every 5 sec.",
+[2407]="+2 health every 5 sec.",
+[2408]="+2 health every 5 sec.",
+[2409]="+2 health every 5 sec.",
+[2410]="+3 health every 5 sec.",
+[2411]="+3 health every 5 sec.",
+[2412]="+5 health every 5 sec.",
+[2413]="+5 health every 5 sec.",
+[2414]="+4 health every 5 sec.",
+[2415]="+4 health every 5 sec.",
+[2416]="+4 health every 5 sec.",
+[2417]="+4 health every 5 sec.",
+[2418]="+5 health every 5 sec.",
+[2419]="+5 health every 5 sec.",
+[2420]="+5 health every 5 sec.",
+[2421]="+5 health every 5 sec.",
+[2422]="+6 health every 5 sec.",
+[2423]="+6 health every 5 sec.",
+[2424]="+6 health every 5 sec.",
+[2425]="+6 health every 5 sec.",
+[2426]="+7 health every 5 sec.",
+[2427]="+7 health every 5 sec.",
+[2428]="+7 health every 5 sec.",
+[2429]="+7 health every 5 sec.",
+[2430]="+8 health every 5 sec.",
+[2431]="+8 health every 5 sec.",
+[2432]="+8 health every 5 sec.",
+[2433]="+8 health every 5 sec.",
+[2434]="+9 health every 5 sec.",
+[2435]="+9 health every 5 sec.",
+[2436]="+9 health every 5 sec.",
+[2437]="+9 health every 5 sec.",
+[2438]="+10 health every 5 sec.",
+[2443]="+7 Frost Spell Damage",
+[2463]="+7 Fire Resistance",
+[2483]="+5 Fire Resistance",
+[2484]="+5 Frost Resistance",
+[2485]="+5 Arcane Resistance",
+[2486]="+5 Nature Resistance",
+[2487]="+5 Shadow Resistance",
+[2488]="+5 All Resistances",
+[2503]="5 Dodge",
+[2504]="30 SP",
+[2505]="29 SP",
+[2506]="+28 Melee Critical Strike",
+[2523]="30 Hit",
+[2543]="10 Haste",
+[2544]="8 SP",
+[2545]="12 Dodge",
+[2563]="15 Str",
+[2564]="15 Agi",
+[2565]="9 Spirit",
+[2566]="13 SP",
+[2567]="20 Spirit",
+[2568]="22 Int",
+[2583]="10 Dodge",
+[2584]="10 Int, 10 Dodge",
+[2585]="28 AP, 12 Dodge",
+[2586]="10 Stam, 10 Hit",
+[2587]="13 SP, 15 Int",
+[2588]="18 SP, 8 Hit",
+[2589]="18 SP, 10 Stam",
+[2590]="10 Int, 10 Spirit",
+[2591]="10 Int",
+[2603]="+2 Fishing",
+[2604]="18 SP",
+[2605]="18 SP",
+[2606]="30 AP",
+[2607]="12 SP",
+[2608]="13 SP",
+[2609]="15 SP",
+[2610]="14 SP",
+[2611]="zzOLDBlank",
+[2612]="18 SP",
+[2613]="+2% Threat",
+[2614]="+20 Shadow Spell Power",
+[2615]="+20 Frost Spell Power",
+[2616]="+20 Fire Spell Power",
+[2617]="16 SP",
+[2618]="15 Agi",
+[2619]="+15 Fire Resistance",
+[2620]="+15 Nature Resistance",
+[2621]="2% Reduced Threat",
+[2622]="12 Dodge",
+[2623]="Minor Wizard Oil",
+[2624]="Minor Mana Oil",
+[2625]="Lesser Mana Oil",
+[2626]="Lesser Wizard Oil",
+[2627]="Wizard Oil",
+[2628]="Brilliant Wizard Oil",
+[2629]="Brilliant Mana Oil",
+[2645]="Firestone 5",
+[2646]="25 Agi",
+[2647]="12 Str",
+[2648]="14 Dodge",
+[2649]="12 Stam",
+[2650]="15 SP",
+[2651]="12 SP",
+[2652]="11 SP",
+[2653]="12 Dodge",
+[2654]="12 Int",
+[2655]="15 Parry",
+[2656]="10 Stam, 10 Spirit",
+[2657]="12 Agi",
+[2658]="10 Hit, 10 Crit",
+[2659]="+150 Health",
+[2660]="+150 Mana",
+[2661]="6 Str, 6 Agi, 6 Stam, 6 Int, 6 Spirit",
+[2662]="120 Armor",
+[2663]="+7 Resist All",
+[2664]="+7 Resist All",
+[2665]="35 Spirit",
+[2666]="30 Int",
+[2667]="70 AP",
+[2668]="20 Str",
+[2669]="40 SP",
+[2670]="35 Agi",
+[2671]="+50 Arcane and Fire Spell Power",
+[2672]="+54 Shadow and Frost Spell Power",
+[2673]="Mongoose",
+[2674]="Spellsurge",
+[2675]="Battlemaster",
+[2676]="Superior Mana Oil",
+[2677]="Superior Mana Oil",
+[2678]="Superior Wizard Oil",
+[2679]="12 Spirit",
+[2680]="+7 Resist All",
+[2681]="+10 Nature Resistance",
+[2682]="+10 Frost Resistance",
+[2683]="+10 Shadow Resistance",
+[2684]="+100 Attack Power vs Undead",
+[2685]="+60 Spell Power vs Undead",
+[2686]="8 Str",
+[2687]="8 Agi",
+[2688]="8 Stam",
+[2689]="+8 mana every 5 sec.",
+[2690]="6 Int",
+[2691]="6 Str",
+[2692]="7 Int",
+[2693]="6 Agi",
+[2694]="6 Int",
+[2695]="6 Crit",
+[2696]="6 Dodge",
+[2697]="6 Hit",
+[2698]="9 Stam",
+[2699]="6 Spirit",
+[2700]="6 PvP Pow",
+[2701]="6 Spirit",
+[2702]="12 Agi",
+[2703]="+4 Agility per different colored gem",
+[2704]="+12 Strength if 4 blue gems equipped",
+[2705]="3 Int, 3 Haste",
+[2706]="4 Stam, 3 Dodge",
+[2707]="3 Int, 3 Spirit",
+[2708]="3 Int, 4 Stam",
+[2709]="3 Int, 3 Spirit",
+[2710]="3 Agi, 4 Stam",
+[2711]="3 Str, 4 Stam",
+[2712]="Sharpened (+12 Damage)",
+[2713]="14 Crit",
+[2714]="Felsteel Spike (26-38)",
+[2715]="16 SP",
+[2716]="16 Stam, 100 Armor",
+[2717]="26 AP, 14 Crit",
+[2718]="Lesser Rune of Warding",
+[2719]="Lesser Ward of Shielding",
+[2720]="Greater Ward of Shielding",
+[2721]="15 SP, 14 Crit",
+[2722]="Scope (+10 Damage)",
+[2723]="Scope (+12 Damage)",
+[2724]="28 Crit",
+[2725]="8 Str",
+[2726]="8 Agi",
+[2727]="8 Int",
+[2728]="8 Int",
+[2729]="8 Agi",
+[2730]="8 Dodge",
+[2731]="12 Stam",
+[2732]="8 Spirit",
+[2733]="8 Spirit",
+[2734]="8 Int",
+[2735]="8 Crit",
+[2736]="8 Crit",
+[2737]="8 Dodge",
+[2738]="4 Str, 6 Stam",
+[2739]="4 Agi, 6 Stam",
+[2740]="5 Int, 6 Stam",
+[2741]="4 Int, 4 Spirit",
+[2742]="4 Int, 4 Haste",
+[2743]="6 Stam, 4 Dodge",
+[2744]="4 Int, 4 Spirit",
+[2745]="25 SP, 15 Stam",
+[2746]="35 SP, 20 Stam",
+[2747]="25 SP, 15 Stam",
+[2748]="35 SP, 20 Stam",
+[2749]="12 Int",
+[2750]="6 mana per 5 sec.",
+[2751]="14 Crit",
+[2752]="3 Str, 3 Crit",
+[2753]="4 Str, 4 Crit",
+[2754]="8 Parry",
+[2755]="3 Agi, 3 Hit",
+[2756]="4 Agi, 4 Hit",
+[2757]="4 Stam, 3 Crit",
+[2758]="6 Stam, 4 Crit",
+[2759]="8 Resil",
+[2760]="3 Int, 3 Crit",
+[2761]="4 Int, 4 Crit",
+[2762]="3 PvP Pow, 3 Crit",
+[2763]="4 PvP Pow, 4 Crit",
+[2764]="8 Hit",
+[2765]="8 PvP Pow",
+[2766]="8 Int",
+[2767]="8 Hit",
+[2768]="16 SP",
+[2769]="11 Hit",
+[2770]="7 SP",
+[2771]="8 Crit",
+[2772]="14 Crit",
+[2773]="16 Crit",
+[2774]="11 Int",
+[2775]="11 Crit",
+[2776]="8 Spirit",
+[2777]="13 Spirit",
+[2778]="13 PvP Pow",
+[2779]="16 Spirit",
+[2780]="16 PvP Pow",
+[2781]="19 Stam",
+[2782]="10 Agi",
+[2783]="14 Hit",
+[2784]="12 Hit",
+[2785]="13 Hit",
+[2786]="7 Hit",
+[2787]="8 Crit",
+[2788]="9 Resil",
+[2789]="15 Resil",
+[2790]="ZZOLDLesser Rune of Warding",
+[2791]="Greater Rune of Warding",
+[2792]="8 Stam",
+[2793]="8 Dodge",
+[2794]="8 Spirit",
+[2795]="Comfortable Insoles",
+[2796]="15 Dodge",
+[2797]="9 Dodge",
+[2798]="1 Int",
+[2799]="1 Stam",
+[2800]="1 Armor",
+[2801]="8 Resil",
+[2802]="1 Agi",
+[2803]="1 Stam",
+[2804]="1 Int",
+[2805]="1 Str",
+[2806]="1 Spirit",
+[2807]="+1 Arcane Damage",
+[2808]="+1 Fire Damage",
+[2809]="+1 Nature Damage",
+[2810]="+1 Frost Damage",
+[2811]="+1 Shadow Damage",
+[2812]="+1 Healing",
+[2813]="1 Dodge",
+[2814]="+1 Health per 5 sec.",
+[2815]="1 Dodge",
+[2816]="+1 Mana Per 5 sec.",
+[2817]="+1 Arcane Resistance",
+[2818]="+1 Fire Resistance",
+[2819]="+1 Frost Resistance",
+[2820]="+1 Nature Resistance",
+[2821]="+1 Shadow Resistance",
+[2822]="1 Crit",
+[2823]="1 Crit",
+[2824]="1 SP",
+[2825]="1 AP",
+[2826]="+1 Block",
+[2827]="14 Crit",
+[2828]="Chance to Increase Spell Cast Speed",
+[2829]="12 Crit",
+[2830]="12 Crit",
+[2831]="18 Stam",
+[2832]="12 Int",
+[2833]="12 Dodge",
+[2834]="+3 Melee Damage and Chance to Stun Target",
+[2835]="12 Int",
+[2836]="3 mana per 5 sec.",
+[2837]="7 Spirit",
+[2838]="7 Crit",
+[2839]="14 Crit",
+[2840]="21 Stam",
+[2841]="10 Stam",
+[2842]="8 Spirit",
+[2843]="8 Crit",
+[2844]="8 Hit",
+[2845]="11 Hit",
+[2846]="4 mana per 5 sec.",
+[2847]="4 mana per 5 sec.",
+[2848]="5 mana per 5 sec.",
+[2849]="7 Dodge",
+[2850]="13 Crit",
+[2851]="19 Stam",
+[2852]="7 mana per 5 sec",
+[2853]="8 mana per 5 sec",
+[2854]="3 mana per 5 sec",
+[2855]="5 mana per 5 sec.",
+[2856]="4 Resil",
+[2857]="2 Crit",
+[2858]="2 Crit",
+[2859]="3 Resil",
+[2860]="3 Hit",
+[2861]="3 Dodge",
+[2862]="3 Resil",
+[2863]="3 Int",
+[2864]="4 Crit",
+[2865]="4 Spirit",
+[2866]="3 Spirit",
+[2867]="2 Resil",
+[2868]="6 Stam",
+[2869]="4 Int",
+[2870]="3 Parry",
+[2871]="4 Dodge",
+[2872]="5 SP",
+[2873]="4 Hit",
+[2874]="4 Crit",
+[2875]="3 Crit",
+[2876]="3 Dodge",
+[2877]="4 Agi",
+[2878]="4 Resil",
+[2879]="3 Str",
+[2880]="3 Hit",
+[2881]="2 Spirit",
+[2882]="6 Stam",
+[2883]="4 Stam",
+[2884]="2 Crit",
+[2885]="2 Crit",
+[2886]="2 Hit",
+[2887]="3 Crit",
+[2888]="+6 Block Value",
+[2889]="5 SP",
+[2890]="4 Spirit",
+[2891]="10 Resil",
+[2892]="4 Str",
+[2893]="3 Agi",
+[2894]="7 Str",
+[2895]="4 Stam",
+[2896]="7 Int",
+[2897]="3 Stam",
+[2898]="3 Stam, 4 Crit",
+[2899]="3 Stam, 4 Crit",
+[2900]="4 SP",
+[2901]="2 SP",
+[2902]="2 Crit",
+[2906]="1 Stam, 1 Int",
+[2907]="2 Parry",
+[2908]="4 Hit",
+[2909]="2 Hit",
+[2910]="3 SP",
+[2911]="10 Str",
+[2912]="10 Int",
+[2913]="10 Crit",
+[2914]="10 Crit",
+[2915]="5 Str",
+[2916]="5 Int, 5 Crit",
+[2917]="gem test enchantment",
+[2918]="3 Stam",
+[2919]="7 Str",
+[2921]="3 Stam, 4 Crit",
+[2922]="7 Str",
+[2923]="3 Stam, 4 Crit",
+[2924]="7 Int",
+[2925]="3 Stam",
+[2926]="2 Dodge",
+[2927]="4 Str",
+[2928]="10 Int",
+[2929]="+2 Weapon Damage",
+[2930]="10 Int",
+[2931]="4 Str, 4 Agi, 4 Stam, 4 Int, 4 Spirit",
+[2932]="4 Dodge",
+[2933]="15 Resil",
+[2934]="10 Crit",
+[2935]="15 Hit",
+[2936]="8 AP",
+[2937]="20 SP",
+[2938]="16 PvP Pow",
+[2939]="6 Agi, Run Speed",
+[2940]="9 Stam, Run Speed",
+[2941]="2 Hit",
+[2942]="6 Crit",
+[2943]="7 Agi",
+[2944]="7 Agi",
+[2945]="10 Agi",
+[2946]="5 Agi, 5 Crit",
+[2947]="+3 Resist All",
+[2948]="+4 Resist All",
+[2949]="10 Agi",
+[2950]="10 Crit",
+[2951]="4 Crit",
+[2952]="4 Crit",
+[2953]="2 SP",
+[2954]="Weighted (+12 Damage)",
+[2955]="14 Crit",
+[2956]="4 Str",
+[2957]="4 Agi",
+[2958]="4 Int",
+[2959]="4 Int",
+[2960]="4 Agi",
+[2961]="6 Stam",
+[2962]="4 Spirit",
+[2963]="4 Spirit",
+[2964]="4 Int",
+[2965]="4 Crit",
+[2966]="4 Hit",
+[2967]="4 Crit",
+[2968]="4 Dodge",
+[2969]="10 Crit",
+[2970]="10 Int",
+[2971]="6 Agi",
+[2972]="+4 Block",
+[2973]="6 AP",
+[2974]="4 SP",
+[2975]="+5 Block Value",
+[2976]="2 Dodge",
+[2977]="13 Dodge",
+[2978]="15 Stam, 15 Dodge",
+[2979]="15 SP",
+[2980]="15 Int, 10 Spirit",
+[2981]="15 SP",
+[2982]="18 SP, 10 Crit",
+[2983]="26 AP",
+[2984]="8 Stam",
+[2985]="8 Stam",
+[2986]="30 AP, 10 Crit",
+[2987]="8 Stam",
+[2988]="8 Stam",
+[2989]="8 Stam",
+[2990]="13 Dodge",
+[2991]="15 Parry, 10 Dodge",
+[2992]="12 Spirit",
+[2993]="10 Int, 16 Spirit",
+[2994]="13 Crit",
+[2995]="12 SP, 15 Crit",
+[2996]="13 Crit",
+[2997]="20 AP, 15 Crit",
+[2998]="+7 All Resistances",
+[2999]="16 Parry, 17 Dodge",
+[3000]="18 Stam, 12 Resil",
+[3001]="16 Int, 18 Spirit",
+[3002]="22 SP, 14 Hit",
+[3003]="34 AP, 16 Hit",
+[3004]="18 Stam, 20 Resil",
+[3005]="+20 Nature Resistance",
+[3006]="+20 Arcane Resistance",
+[3007]="+20 Fire Resistance",
+[3008]="+20 Frost Resistance",
+[3009]="+20 Shadow Resistance",
+[3010]="40 AP, 10 Crit",
+[3011]="30 Stam, 10 Agi",
+[3012]="50 AP, 12 Crit",
+[3013]="40 Stam, 12 Agi",
+[3015]="2 Str",
+[3016]="2 Int",
+[3017]="+3 Block",
+[3021]="Rockbiter",
+[3045]="5 Str, 6 Stam",
+[3046]="5 Int, 4 Haste",
+[3047]="6 Stam, 5 Crit",
+[3048]="5 Agi, 6 Stam",
+[3049]="5 Crit, 4 Spirit",
+[3050]="5 Int, 4 Haste",
+[3051]="5 Int, 6 Stam",
+[3052]="5 Agi, 4 Hit",
+[3053]="5 Parry, 4 Dodge",
+[3054]="5 Int, 6 Stam",
+[3055]="5 Agi, 4 Hit",
+[3056]="5 Parry, 4 Dodge",
+[3057]="5 Str, 4 Hit",
+[3058]="5 Crit, 4 Spirit",
+[3059]="5 Crit",
+[3060]="6 Stam, 5 Dodge",
+[3061]="5 Int, 4 Hit",
+[3062]="6 Stam, 5 Crit",
+[3063]="6 Stam, 5 Parry",
+[3064]="5 Int, 5 Spirit",
+[3065]="8 Str",
+[3066]="5 Int, 5 PvP Pow",
+[3067]="5 Agi, 6 Stam",
+[3068]="5 Dodge, 4 Hit",
+[3069]="5 Int, 4 Resil",
+[3070]="5 Agi, 4 Crit",
+[3071]="5 Int, 6 Stam",
+[3072]="5 Str, 4 Crit",
+[3073]="4 Agi, 5 Dodge",
+[3074]="5 Int, 4 Spirit",
+[3075]="5 Str, 4 Dodge",
+[3076]="5 Int, 4 Crit",
+[3077]="5 Int, 4 Spirit",
+[3078]="6 Stam, 5 Dodge",
+[3079]="5 Agi, 4 Resil",
+[3080]="6 Stam, 5 Resil",
+[3081]="5 Int, 4 Crit",
+[3082]="6 Stam, 5 Dodge",
+[3083]="5 Int, 4 Spirit",
+[3084]="5 Resil, 6 Stam",
+[3085]="6 Stam, 5 Crit",
+[3086]="5 Int, 4 Spirit",
+[3087]="5 Str, 4 Resil",
+[3088]="5 Hit, 4 Dodge",
+[3089]="5 Hit, 4 Haste",
+[3090]="4 Resil, 5 Parry",
+[3091]="5 PvP Pow, 5 Crit",
+[3092]="3 Crit",
+[3093]="+150 Attack Power vs Undead and Demons",
+[3094]="4 Exp",
+[3095]="+8 Resist All",
+[3096]="17 Str, 16 Int",
+[3097]="2 Spirit",
+[3098]="2 SP",
+[3099]="5 Int, 6 Stam",
+[3100]="5 Int, 6 Stam",
+[3101]="5 Str, 6 Stam",
+[3102]="Poison",
+[3103]="8 Str",
+[3104]="6 Hit",
+[3105]="8 Hit",
+[3106]="3 Agi, 4 Stam",
+[3107]="4 Agi, 6 Stam",
+[3108]="3 Agi, 4 Stam",
+[3109]="4 Agi, 4 Hit",
+[3110]="3 Int, 3 Hit",
+[3111]="4 Int, 4 Hit",
+[3112]="4 Agi, 4 Crit",
+[3113]="3 Agi, 3 Crit",
+[3114]="4 AP",
+[3115]="10 Str",
+[3116]="10 Agi",
+[3117]="10 Int",
+[3118]="10 Int",
+[3119]="10 Agi",
+[3120]="10 Dodge",
+[3121]="10 Parry",
+[3122]="15 Stam",
+[3123]="10 Spirit",
+[3124]="10 Spirit",
+[3125]="10 PvP Pow",
+[3126]="10 Int",
+[3127]="10 Crit",
+[3128]="10 Hit",
+[3129]="10 Crit",
+[3130]="10 Dodge",
+[3131]="10 Resil",
+[3132]="10 Hit",
+[3133]="5 Str, 7 Stam",
+[3134]="5 Agi, 7 Stam",
+[3135]="5 Agi, 7 Stam",
+[3136]="5 Agi, 5 Hit",
+[3137]="5 Int, 7 Stam",
+[3138]="5 Int, 5 Spirit",
+[3139]="5 Str, 5 Crit",
+[3140]="5 Int, 5 Crit",
+[3141]="5 Int, 5 Haste",
+[3142]="5 Agi, 5 Hit",
+[3143]="5 Int, 5 Hit",
+[3144]="5 Agi, 5 Crit",
+[3145]="7 Stam, 5 Dodge",
+[3146]="5 PvP Pow, 5 Crit",
+[3147]="5 Int, 5 Spirit",
+[3148]="7 Stam, 5 Crit",
+[3149]="2 Agi",
+[3150]="14 Spirit",
+[3151]="2 SP",
+[3152]="2 Crit",
+[3153]="2 SP",
+[3154]="12 Agi",
+[3155]="Chance to Increase Melee/Ranged Attack Speed",
+[3156]="5 Agi, 6 Stam",
+[3157]="4 Int, 6 Stam",
+[3158]="5 Int, 4 Spirit",
+[3159]="5 Agi, 4 Crit",
+[3160]="5 Int, 4 Haste",
+[3161]="4 Stam, 4 Crit",
+[3162]="12 Crit",
+[3163]="12 Int",
+[3164]="3 Stam",
+[3197]="10 Agi",
+[3198]="5 SP",
+[3199]="170 Armor",
+[3200]="5 SP, 4 Spirit",
+[3201]="3 Int, 3 Spirit",
+[3202]="4 Int, 4 Spirit",
+[3204]="3 Crit",
+[3205]="3 Crit",
+[3206]="8 Agi",
+[3207]="12 Str",
+[3208]="12 Agi",
+[3209]="12 Agi",
+[3210]="12 Int",
+[3211]="12 Int",
+[3212]="18 Stam",
+[3213]="+6 Mana every 5 seconds",
+[3214]="12 Spirit",
+[3215]="12 Resil",
+[3216]="12 Int",
+[3217]="12 Crit",
+[3218]="12 Hit",
+[3219]="12 Hit",
+[3220]="12 Crit",
+[3221]="12 Dodge",
+[3222]="20 Agi",
+[3223]="Adamantite Weapon Chain",
+[3224]="6 Agi",
+[3225]="Executioner",
+[3226]="4 Resil, 6 Stam",
+[3227]="10 Crit",
+[3228]="34 AP",
+[3229]="12 Resil",
+[3230]="+20 Frost Resistance",
+[3231]="15 Exp",
+[3232]="15 Stam, Run Speed",
+[3233]="+250 Mana",
+[3234]="20 Hit",
+[3235]="+12 Resist All",
+[3236]="+200 Health",
+[3237]="+10 Weapon Damage",
+[3238]="Gatherer",
+[3239]="Icebreaker Weapon",
+[3240]="23 SP",
+[3241]="Lifeward",
+[3242]="+5 Resist All",
+[3243]="28 PvP Pow",
+[3244]="14 Stam, 14 Spirit",
+[3245]="20 Resil",
+[3246]="28 SP",
+[3247]="+140 Attack Power versus Undead",
+[3248]="18 Exp",
+[3249]="16 Crit",
+[3250]="Icewalker",
+[3251]="Giantslaying",
+[3252]="8 All Stats",
+[3253]="10 Parry",
+[3254]="4 Str, 4 Agi, 4 Stam, 4 Int, 4 Spirit",
+[3255]="55 SP, 20 Spirit",
+[3256]="10 Agi, 40 Armor",
+[3257]="54 SP",
+[3258]="18 SP",
+[3259]="22 Stam",
+[3260]="24 Stam",
+[3261]="12 Crit",
+[3262]="15 Stam",
+[3263]="4 Crit",
+[3264]="150 Armor",
+[3265]="Blessed Weapon Coating",
+[3266]="Righteous Weapon Coating",
+[3267]="4 Haste",
+[3268]="15 Stam",
+[3269]="+3 Fishing",
+[3270]="8 Haste",
+[3271]="4 Int, 4 Haste",
+[3272]="6 Stam, 4 Haste",
+[3273]="Deathfrost",
+[3274]="12 Dodge",
+[3275]="12 Int",
+[3276]="20 AP",
+[3277]="12 SP",
+[3278]="12 SP",
+[3279]="3 SP",
+[3280]="6 Stam, 4 Dodge",
+[3281]="10 Agi",
+[3282]="10 Int",
+[3283]="10 Int",
+[3284]="5 Resil, 7 Stam",
+[3285]="7 Stam, 5 Haste",
+[3286]="5 Int, 5 Haste",
+[3287]="10 Haste",
+[3288]="Test Riding Crop Enchant",
+[3289]="+10% Mount Speed",
+[3290]="Use: Reduce your fall speed for 10 sec.  (5 Min Cooldown) (5 Min Cooldown)",
+[3292]="34 Agi",
+[3293]="51 Stam",
+[3294]="25 Stam",
+[3295]="16 Haste",
+[3296]="10 Spirit",
+[3297]="+275 Health",
+[3298]="Exceptional Mana Oil",
+[3299]="Exceptional Wizard Oil",
+[3300]="19 SP",
+[3301]="6 Crit",
+[3302]="8 Dodge",
+[3303]="8 Haste",
+[3304]="8 Dodge",
+[3305]="12 Stam",
+[3306]="2 mana per 5 sec.",
+[3307]="9 Stam",
+[3308]="4 Haste",
+[3309]="6 Haste",
+[3310]="6 Int",
+[3311]="6 Spirit",
+[3312]="8 Str",
+[3313]="8 Agi",
+[3314]="8 Crit",
+[3315]="+3% Mount Speed",
+[3316]="6 Crit",
+[3317]="21 Stam",
+[3318]="5 Int, 5 Spirit",
+[3319]="Test Add Sockets Enchant",
+[3320]="Test Skill Req Enchant",
+[3321]="150 Armor",
+[3322]="Frozen Rune Weapon",
+[3324]="10 Crit",
+[3325]="45 Stam, 15 Agi",
+[3326]="55 AP, 15 Crit",
+[3327]="55 Stam, 22 Agi",
+[3328]="75 AP, 22 Crit",
+[3329]="12 Stam",
+[3330]="18 Stam",
+[3331]="72 Stam, 35 Agi",
+[3332]="100 AP, 36 Crit",
+[3333]="QA Test Blank Purple Gem Enchant",
+[3334]="Northrend Flight",
+[3335]="10 Agi",
+[3336]="10 Crit",
+[3337]="5 Agi, 5 Crit",
+[3338]="5 Int, 5 Crit",
+[3339]="10 Int",
+[3340]="10 Crit",
+[3341]="Frozen Rune Weapon 2",
+[3342]="Frozen Rune Weapon 3",
+[3343]="Frozen Rune Weapon 4",
+[3344]="Frozen Rune Weapon 5",
+[3345]="Earthliving",
+[3351]="6 Hit",
+[3352]="8 Spirit",
+[3353]="8 Int",
+[3354]="12 Stam",
+[3355]="6 Agi",
+[3356]="12 AP",
+[3357]="6 Str",
+[3358]="6 Dodge",
+[3359]="4 Parry",
+[3360]="8 Parry",
+[3361]="+6 Block",
+[3362]="6 Exp",
+[3363]="+9 Block Value",
+[3364]="Empower Rune Weapon",
+[3365]="Swordshattering",
+[3366]="Lichbane",
+[3367]="Spellshattering",
+[3368]="Fallen Crusader",
+[3369]="Cinderglacier",
+[3370]="Razorice",
+[3371]="12 Str",
+[3374]="12 Agi",
+[3375]="12 Agi",
+[3376]="12 Dodge",
+[3377]="12 Parry",
+[3378]="12 Crit",
+[3379]="12 Exp",
+[3380]="12 Int",
+[3381]="12 Int",
+[3382]="12 Crit",
+[3383]="12 Hit",
+[3384]="12 Dodge",
+[3385]="12 Resil",
+[3386]="12 Haste",
+[3387]="18 Stam",
+[3388]="12 Spirit",
+[3389]="12 Spirit",
+[3390]="12 PvP Pow",
+[3391]="9 Stam, 6 Crit",
+[3392]="6 Str, 9 Stam",
+[3393]="6 Agi, 9 Stam",
+[3394]="6 Int, 9 Stam",
+[3395]="6 Agi, 9 Stam",
+[3396]="9 Stam, 6 Dodge",
+[3397]="9 Stam, 6 Parry",
+[3398]="9 Stam, 6 Exp",
+[3399]="6 Int, 6 Spirit",
+[3400]="6 Agi, 6 Hit",
+[3401]="6 Int, 6 Spirit",
+[3402]="6 Agi, 6 Hit",
+[3403]="6 Int, 6 PvP Pow",
+[3404]="6 Int, 6 Haste",
+[3405]="6 Str, 6 Crit",
+[3406]="6 Agi, 6 Hit",
+[3407]="6 Str, 6 Dodge",
+[3408]="6 Str, 6 Resil",
+[3409]="6 Str, 6 Haste",
+[3410]="6 Agi, 6 Crit",
+[3411]="6 Str, 6 Hit",
+[3412]="6 Agi, 6 Resil",
+[3413]="6 Agi, 6 Haste",
+[3414]="6 Int, 6 Crit",
+[3415]="6 Int, 6 Hit",
+[3416]="6 Int, 6 Resil",
+[3417]="6 Int, 6 Haste",
+[3418]="6 Dodge, 6 Parry",
+[3419]="6 Parry, 6 Dodge",
+[3420]="6 Exp, 6 Hit",
+[3421]="6 Exp, 6 Dodge",
+[3422]="6 Agi, 6 Crit",
+[3423]="6 Agi, 6 Hit",
+[3424]="6 Agi, 6 Resil",
+[3426]="6 Agi, 6 Haste",
+[3427]="6 Int, 9 Stam",
+[3428]="9 Stam, 6 Crit",
+[3429]="6 Hit, 6 Dodge",
+[3430]="9 Stam, 6 Dodge",
+[3431]="6 Resil, 9 Stam",
+[3432]="9 Stam, 6 Haste",
+[3433]="6 Int, 6 Spirit",
+[3434]="6 Crit, 6 Spirit",
+[3435]="6 Hit, 6 Haste",
+[3436]="6 Resil, 6 Spirit",
+[3437]="6 Haste, 6 Spirit",
+[3438]="6 Int, 6 Spirit",
+[3439]="6 Crit, 6 Spirit",
+[3440]="6 Hit, 6 Haste",
+[3441]="6 Resil, 6 Spirit",
+[3442]="6 Haste, 6 Spirit",
+[3443]="6 PvP Pow, 6 Crit",
+[3444]="6 PvP Pow, 6 Crit",
+[3445]="6 PvP Pow, 6 Haste",
+[3446]="16 Str",
+[3447]="16 Agi",
+[3448]="16 Int",
+[3449]="16 Agi",
+[3450]="16 Dodge",
+[3451]="16 Parry",
+[3452]="16 Crit",
+[3453]="16 Exp",
+[3454]="24 Stam",
+[3455]="16 Spirit",
+[3456]="16 Spirit",
+[3457]="16 PvP Pow",
+[3458]="16 Int",
+[3459]="16 Crit",
+[3460]="16 Hit",
+[3461]="16 Dodge",
+[3462]="16 Resil",
+[3463]="16 Haste",
+[3464]="8 Str, 12 Stam",
+[3465]="8 Agi, 12 Stam",
+[3466]="8 Int, 12 Stam",
+[3467]="8 Agi, 12 Stam",
+[3468]="12 Stam, 8 Dodge",
+[3469]="12 Stam, 8 Parry",
+[3470]="12 Stam, 8 Crit",
+[3471]="12 Stam, 8 Exp",
+[3472]="8 Int, 8 Spirit",
+[3473]="8 Int, 8 Spirit",
+[3474]="8 Agi, 8 Hit",
+[3475]="8 Agi, 8 Hit",
+[3476]="8 Int, 8 PvP Pow",
+[3477]="8 Str, 8 Crit",
+[3478]="8 Str, 8 Hit",
+[3479]="8 Str, 8 Dodge",
+[3480]="8 Str, 8 Resil",
+[3481]="8 Str, 8 Haste",
+[3482]="8 Agi, 8 Crit",
+[3483]="8 Agi, 8 Hit",
+[3484]="8 Agi, 8 Resil",
+[3485]="8 Agi, 8 Haste",
+[3486]="8 Int, 8 Haste",
+[3487]="8 Int, 8 Crit",
+[3488]="8 Int, 8 Hit",
+[3489]="8 Int, 8 Resil",
+[3490]="8 Int, 8 Haste",
+[3491]="8 Agi, 8 Crit",
+[3492]="8 Agi, 8 Hit",
+[3493]="8 Agi, 8 Resil",
+[3494]="8 Agi, 8 Haste",
+[3495]="8 Dodge, 8 Parry",
+[3496]="8 Parry, 8 Dodge",
+[3497]="8 Exp, 8 Hit",
+[3498]="8 Exp, 8 Dodge",
+[3499]="8 Int, 12 Stam",
+[3500]="12 Stam, 8 Crit",
+[3501]="8 Hit, 8 Dodge",
+[3502]="12 Stam, 8 Dodge",
+[3503]="8 Resil, 12 Stam",
+[3504]="12 Stam, 8 Haste",
+[3505]="8 Int, 8 Spirit",
+[3506]="8 Crit, 8 Spirit",
+[3507]="8 Hit, 8 Haste",
+[3508]="8 Resil, 8 Spirit",
+[3509]="8 Haste, 8 Spirit",
+[3510]="8 Int, 8 Spirit",
+[3511]="8 Crit, 8 Spirit",
+[3512]="8 Hit, 8 Haste",
+[3513]="8 Resil, 8 Spirit",
+[3514]="8 Haste, 8 Spirit",
+[3515]="8 PvP Pow, 8 Crit",
+[3516]="8 PvP Pow, 8 Crit",
+[3517]="8 PvP Pow, 8 Haste",
+[3518]="20 Str",
+[3519]="20 Agi",
+[3520]="20 Int",
+[3521]="20 Agi",
+[3522]="20 Dodge",
+[3523]="20 Parry",
+[3524]="20 Exp",
+[3525]="20 Crit",
+[3526]="20 Int",
+[3527]="20 Crit",
+[3528]="20 Hit",
+[3529]="20 Dodge",
+[3530]="20 Resil",
+[3531]="20 Haste",
+[3532]="30 Stam",
+[3533]="20 Spirit",
+[3534]="20 Spirit",
+[3535]="20 PvP Pow",
+[3536]="10 Str, 15 Stam",
+[3537]="10 Agi, 15 Stam",
+[3538]="10 Int, 15 Stam",
+[3539]="10 Agi, 15 Stam",
+[3540]="15 Stam, 10 Dodge",
+[3541]="15 Stam, 10 Parry",
+[3542]="15 Stam, 10 Exp",
+[3543]="15 Stam, 10 Crit",
+[3544]="10 Agi, 10 Hit",
+[3545]="10 Int, 10 Spirit",
+[3546]="10 Int, 10 Spirit",
+[3547]="10 Agi, 10 Hit",
+[3548]="10 Int, 10 PvP Pow",
+[3549]="10 Str, 10 Crit",
+[3550]="10 Str, 10 Hit",
+[3551]="10 Str, 10 Dodge",
+[3552]="10 Str, 10 Resil",
+[3553]="10 Str, 10 Haste",
+[3554]="10 Agi, 10 Crit",
+[3555]="10 Agi, 10 Hit",
+[3556]="10 Agi, 10 Resil",
+[3557]="10 Agi, 10 Haste",
+[3558]="10 Int, 10 Spirit",
+[3559]="10 Int, 10 Crit",
+[3560]="10 Int, 10 Hit",
+[3561]="10 Int, 10 Resil",
+[3563]="10 Int, 10 Haste",
+[3564]="10 Agi, 10 Crit",
+[3565]="10 Agi, 10 Hit",
+[3566]="10 Agi, 10 Resil",
+[3567]="10 Agi, 10 Haste",
+[3568]="10 Dodge, 10 Parry",
+[3569]="10 Parry, 10 Dodge",
+[3570]="10 Exp, 10 Hit",
+[3571]="10 Exp, 10 Dodge",
+[3572]="10 Int, 15 Stam",
+[3573]="15 Stam, 10 Crit",
+[3574]="10 Hit, 10 Dodge",
+[3575]="15 Stam, 10 Dodge",
+[3576]="10 Resil, 15 Stam",
+[3577]="15 Stam, 10 Haste",
+[3578]="10 Int, 10 Spirit",
+[3579]="10 Crit, 10 Spirit",
+[3580]="10 Hit, 10 Haste",
+[3581]="10 Resil, 10 Spirit",
+[3582]="10 Haste, 10 Spirit",
+[3583]="10 Int, 10 Spirit",
+[3584]="10 Crit, 10 Spirit",
+[3585]="10 Hit, 10 Haste",
+[3586]="10 Resil, 10 Spirit",
+[3587]="10 Haste, 10 Spirit",
+[3588]="10 PvP Pow, 10 Crit",
+[3589]="10 PvP Pow, 10 Crit",
+[3590]="10 PvP Pow, 10 Haste",
+[3591]="4 Int",
+[3592]="+100 Spell Power vs Undead",
+[3593]="+170 Attack Power vs Undead",
+[3594]="Swordbreaking",
+[3595]="Spellbreaking",
+[3596]="5 SP",
+[3597]="Master Firestone",
+[3599]="Use: Stuns all nearby Mechanical units for 3 sec. (1 Min Cooldown)",
+[3600]="6 Resil",
+[3601]="Use: Detatch and throw a thermal grenade, inflicting 10,000 Fire damage and incapacitating targets for 3 sec in a 3 yard radius.  Any damage will break the effect. (1 Min Cooldown)",
+[3602]="7 SP",
+[3603]="Use: Fires an explosive rocket at an enemy for 1,165 Fire damage. (45 Sec Cooldown)",
+[3604]="Use: Increases your haste by 240 for 12 sec. (1 Min Cooldown)",
+[3605]="Use: Reduces your falling speed for 30 sec. (1 Min Cooldown)",
+[3607]="40 Haste",
+[3608]="40 Crit",
+[3609]="Firestone",
+[3610]="Firestone",
+[3611]="Greater Firestone",
+[3612]="Major Firestone",
+[3613]="Fel Firestone",
+[3614]="Grand Firestone",
+[3615]="Spellstone",
+[3616]="Greater Spellstone",
+[3617]="Major Spellstone",
+[3618]="Master Spellstone",
+[3619]="Demonic Spellstone",
+[3620]="Grand Spellstone",
+[3621]="21 Crit",
+[3622]="25 Crit",
+[3623]="21 Int",
+[3624]="21 Crit",
+[3625]="21 Crit",
+[3626]="21 Int",
+[3627]="21 Int",
+[3628]="21 Agi",
+[3630]="21 Dodge",
+[3631]="21 Dodge",
+[3632]="21 Int",
+[3633]="22 Spirit",
+[3634]="32 Stam",
+[3635]="21 Int",
+[3636]="21 Crit",
+[3637]="32 Stam",
+[3638]="21 Crit",
+[3639]="21 Int",
+[3640]="21 Haste",
+[3641]="21 Crit",
+[3642]="32 Stam",
+[3643]="Chance to Increase Melee/Ranged Attack Speed",
+[3644]="14 Agi",
+[3646]="14 Dodge",
+[3647]="14 Exp",
+[3648]="14 Parry",
+[3649]="14 Str",
+[3650]="14 Int",
+[3651]="14 Agi",
+[3652]="14 Crit",
+[3653]="14 Spirit",
+[3654]="14 Spirit",
+[3655]="21 Stam",
+[3656]="14 PvP Pow",
+[3657]="14 Crit",
+[3658]="14 Dodge",
+[3659]="14 Haste",
+[3660]="14 Hit",
+[3661]="14 Int",
+[3662]="14 Resil",
+[3663]="7 Agi, 7 Hit",
+[3664]="7 Agi, 10 Stam",
+[3665]="10 Stam, 7 Crit",
+[3666]="7 Agi, 7 Hit",
+[3667]="7 Agi, 10 Stam",
+[3668]="10 Stam, 7 Dodge",
+[3669]="10 Stam, 7 Exp",
+[3670]="10 Stam, 7 Parry",
+[3671]="7 Str, 10 Stam",
+[3672]="7 Int, 7 Spirit",
+[3673]="7 Int, 7 Spirit",
+[3674]="7 Int, 7 PvP Pow",
+[3675]="7 Int, 10 Stam",
+[3676]="14 AP, 7 Crit",
+[3677]="7 Agi, 7 Haste",
+[3678]="7 Agi, 7 Haste",
+[3679]="7 Agi, 7 Hit",
+[3680]="7 Agi, 7 Resil",
+[3681]="7 Str, 7 Crit",
+[3682]="7 Str, 7 Hit",
+[3683]="7 Str, 7 Dodge",
+[3684]="7 Str, 7 Resil",
+[3685]="7 Str, 7 Haste",
+[3686]="7 Agi, 7 Crit",
+[3687]="7 Agi, 7 Hit",
+[3688]="7 Agi, 7 Resil",
+[3689]="7 Int, 7 Spirit",
+[3690]="7 Int, 7 Crit",
+[3691]="7 Int, 7 Hit",
+[3692]="7 Int, 7 Resil",
+[3693]="7 Int, 7 Haste",
+[3694]="7 Dodge, 7 Parry",
+[3695]="7 Parry, 7 Dodge",
+[3696]="7 Exp, 7 Hit",
+[3697]="7 Exp, 7 Dodge",
+[3698]="7 Crit, 7 Spirit",
+[3699]="10 Stam, 7 Crit",
+[3700]="10 Stam, 7 Dodge",
+[3701]="7 Haste, 7 Spirit",
+[3702]="10 Stam, 7 Haste",
+[3703]="7 Hit, 7 Haste",
+[3704]="7 Hit, 7 Dodge",
+[3705]="7 Int, 7 Spirit",
+[3706]="7 Int, 10 Stam",
+[3707]="7 Resil, 7 Spirit",
+[3708]="7 Resil, 10 Stam",
+[3709]="7 PvP Pow, 7 Crit",
+[3710]="7 Crit, 7 Spirit",
+[3711]="7 Int, 7 Spirit",
+[3712]="7 Hit, 7 Haste",
+[3713]="7 Resil, 7 Spirit",
+[3714]="7 Haste, 7 Spirit",
+[3715]="7 PvP Pow, 7 Crit",
+[3716]="7 PvP Pow, 7 Haste",
+[3717]="Socket Bracer",
+[3718]="35 SP, 12 Spirit",
+[3719]="50 SP, 20 Spirit",
+[3720]="35 SP, 20 Stam",
+[3721]="50 SP, 30 Stam",
+[3722]="Lightweave 1",
+[3723]="Socket Gloves",
+[3726]="1 Haste",
+[3727]="1 Hit",
+[3728]="Darkglow 1",
+[3729]="Socket Belt",
+[3730]="Swordguard 1",
+[3731]="28 Hit",
+[3732]="34 Str",
+[3733]="34 Agi",
+[3734]="34 Int",
+[3735]="34 Spirit",
+[3736]="34 Spirit",
+[3737]="34 Int",
+[3738]="34 Crit",
+[3739]="34 Haste",
+[3740]="34 Dodge",
+[3741]="34 Parry",
+[3742]="34 Hit",
+[3743]="34 Dodge",
+[3744]="34 Resil",
+[3745]="34 Crit",
+[3746]="34 Exp",
+[3747]="34 PvP Pow",
+[3748]="Titanium Spike (45-67)",
+[3749]="4 Str, 4 Agi, 4 Stam, 4 Int, 4 Spirit",
+[3750]="6 Str, 6 Agi, 6 Stam, 6 Int, 6 Spirit",
+[3751]="6 Dodge",
+[3752]="5 SP",
+[3753]="9 SP",
+[3754]="24 AP",
+[3755]="28 AP",
+[3756]="130 AP",
+[3757]="102 Stam",
+[3758]="57 Int",
+[3759]="102 Stam",
+[3760]="102 Stam",
+[3761]="102 Stam",
+[3762]="102 Stam",
+[3763]="102 Stam",
+[3764]="12 AP",
+[3765]="4 Crit",
+[3766]="12 Stam",
+[3767]="7 Agi, 7 Crit",
+[3775]="30 SP, 15 Crit",
+[3776]="45 AP, 15 Crit",
+[3777]="22 Stam, 20 Dodge",
+[3778]="8 Exp",
+[3788]="25 Hit, 25 Crit",
+[3789]="Berserking",
+[3790]="Black Magic",
+[3791]="30 Stam",
+[3792]="20 Resil",
+[3793]="40 AP, 15 Resil",
+[3794]="23 SP, 15 Resil",
+[3795]="50 AP, 20 Resil",
+[3796]="29 SP, 20 Resil",
+[3797]="29 SP, 20 Resil",
+[3798]="17 Crit",
+[3799]="17 Int",
+[3800]="17 Crit",
+[3801]="17 Crit",
+[3802]="17 Int",
+[3803]="17 Crit",
+[3804]="26 Stam",
+[3805]="17 Int",
+[3806]="18 SP, 10 Crit",
+[3807]="15 Int, 10 Spirit",
+[3808]="40 AP, 15 Crit",
+[3809]="21 Int, 16 Spirit",
+[3810]="24 SP, 15 Crit",
+[3811]="22 Stam, 20 Dodge",
+[3812]="30 Stam",
+[3813]="30 Stam",
+[3814]="30 Stam",
+[3815]="30 Stam",
+[3816]="30 Stam",
+[3817]="50 AP, 20 Crit",
+[3818]="37 Stam, 20 Dodge",
+[3819]="26 Int, 20 Spirit",
+[3820]="26 Int, 20 Crit",
+[3821]="8 Resil",
+[3822]="55 Stam, 22 Agi",
+[3823]="75 AP, 22 Crit",
+[3824]="24 AP",
+[3825]="15 Haste",
+[3826]="12 Hit, 12 Crit",
+[3827]="110 AP",
+[3828]="85 AP",
+[3829]="35 AP",
+[3830]="50 SP",
+[3831]="23 Haste",
+[3832]="10 All Stats",
+[3833]="65 AP",
+[3834]="63 SP",
+[3835]="120 AP, 15 Crit",
+[3836]="60 Int, 15 Spirit",
+[3837]="60 Dodge, 15 Parry",
+[3838]="70 SP, 15 Crit",
+[3839]="40 AP",
+[3840]="20 Int",
+[3841]="23 SP",
+[3842]="30 Stam, 25 Resil",
+[3843]="Scope (+15 Damage)",
+[3844]="45 Spirit",
+[3845]="50 AP",
+[3846]="40 SP",
+[3847]="Stoneskin Gargoyle",
+[3848]="Socket Staff",
+[3849]="Titanium Plating",
+[3850]="40 Stam",
+[3851]="50 Stam",
+[3852]="30 Stam, 15 Resil",
+[3853]="40 Resil, 28 Stam",
+[3854]="81 SP",
+[3855]="69 SP",
+[3856]="100 Agi",
+[3857]="6 Dodge",
+[3858]="5 Hit",
+[3859]="Use: Reduces your falling speed for 30 sec. (1 Min Cooldown)",
+[3860]="Use: Increases your armor by 700 for 14 sec. (1 Min Cooldown)",
+[3861]="20 Str",
+[3862]="20 Agi",
+[3863]="30 Stam",
+[3864]="20 Spirit",
+[3865]="20 Int",
+[3866]="20 Int",
+[3867]="20 Hit",
+[3868]="Fishing Lure (+100 Fishing Skill)",
+[3869]="Blade Ward",
+[3870]="Blood Draining",
+[3871]="6 Parry",
+[3872]="50 SP, 20 Spirit",
+[3873]="50 SP, 30 Stam",
+[3874]="130 AP",
+[3875]="30 AP, 10 Crit",
+[3876]="15 Dodge, 10 Parry",
+[3877]="16 AP",
+[3879]="10 All Stats",
+[3880]="6 Crit",
+[3881]="+17 Mana every 5 seconds",
+[3882]="8 Crit",
+[3883]="Nerubian Carapace",
+[3884]="24 Stam, 24 Agi",
+[3885]="15 Mastery, 15 Spirit",
+[3886]="15 Mastery, 15 Hit",
+[3887]="18 Mastery, 17 Spirit",
+[3888]="18 Mastery, 17 Hit",
+[3889]="30 Str",
+[3890]="30 Agi",
+[3891]="30 Parry",
+[3892]="30 Int",
+[3893]="30 Exp",
+[3894]="45 Stam",
+[3895]="30 Spirit",
+[3896]="30 PvP Pow",
+[3897]="30 Hit",
+[3898]="30 Dodge",
+[3899]="30 Resil",
+[3900]="30 Haste",
+[3901]="30 Mastery",
+[3902]="15 Str, 23 Stam",
+[3903]="23 Stam, 15 Parry",
+[3904]="15 Agi, 23 Stam",
+[3905]="15 Int, 23 Stam",
+[3906]="23 Stam, 15 Exp",
+[3907]="15 Int, 15 Spirit",
+[3908]="15 Str, 15 Hit",
+[3909]="15 Agi, 15 Hit",
+[3910]="15 Parry, 15 Hit",
+[3911]="15 Int, 15 Hit",
+[3912]="15 Exp, 15 Hit",
+[3913]="15 Agi, 15 Dodge",
+[3914]="15 Exp, 15 Dodge",
+[3915]="15 Str, 15 Crit",
+[3916]="15 Agi, 15 Crit",
+[3917]="15 Int, 15 Crit",
+[3918]="15 Str, 15 Haste",
+[3919]="15 Agi, 15 Haste",
+[3920]="15 Int, 15 Haste",
+[3921]="15 Str, 15 Mastery",
+[3922]="15 Agi, 15 Mastery",
+[3923]="15 Parry, 15 Mastery",
+[3924]="15 Int, 15 Mastery",
+[3925]="15 Exp, 15 Mastery",
+[3926]="23 Stam, 15 Dodge",
+[3927]="15 Dodge, 15 Hit",
+[3928]="23 Stam, 15 Crit",
+[3929]="15 Crit, 15 Hit",
+[3930]="15 Resil, 23 Stam",
+[3931]="23 Stam, 15 Haste",
+[3932]="15 Haste, 15 Hit",
+[3933]="23 Stam, 15 Mastery",
+[3936]="30 Crit",
+[3937]="18 Str, 17 Hit",
+[3938]="18 Int, 17 Spirit",
+[3939]="26 Stam, 18 Exp",
+[3940]="18 Int, 26 Stam",
+[3941]="26 Stam, 18 Parry",
+[3942]="18 Agi, 23 Stam",
+[3943]="18 Str, 26 Stam",
+[3944]="35 Mastery",
+[3945]="35 Haste",
+[3946]="35 Resil",
+[3947]="35 Crit",
+[3948]="35 Dodge",
+[3949]="35 Hit",
+[3950]="35 PvP Pow",
+[3951]="35 Spirit",
+[3952]="53 Stam",
+[3953]="35 Exp",
+[3954]="35 Int",
+[3955]="35 Parry",
+[3956]="35 Agi",
+[3957]="35 Str",
+[3958]="26 Stam, 18 Mastery",
+[3959]="18 Haste, 17 Hit",
+[3960]="26 Stam, 18 Haste",
+[3961]="18 Resil, 26 Stam",
+[3962]="18 Crit, 17 Hit",
+[3963]="26 Stam, 18 Crit",
+[3964]="18 Dodge, 17 Hit",
+[3965]="26 Stam, 18 Dodge",
+[3966]="18 Exp, 17 Mastery",
+[3967]="18 Int, 17 Mastery",
+[3968]="18 Parry, 17 Mastery",
+[3969]="18 Agi, 17 Mastery",
+[3970]="18 Str, 17 Mastery",
+[3971]="18 Int, 17 Haste",
+[3972]="18 Agi, 17 Haste",
+[3973]="18 Str, 17 Haste",
+[3974]="18 Int, 17 Crit",
+[3975]="18 Agi, 17 Crit",
+[3976]="18 Str, 17 Crit",
+[3977]="18 Exp, 17 Dodge",
+[3978]="18 Agi, 17 Dodge",
+[3979]="18 Exp, 17 Hit",
+[3980]="18 Int, 17 Hit",
+[3981]="18 Parry, 17 Hit",
+[3982]="18 Agi, 17 Hit",
+[3983]="20 Exp, 20 Hit",
+[3984]="30 Stam, 20 Parry",
+[3985]="20 Str, 20 Hit",
+[3986]="20 Int, 20 Hit",
+[3987]="20 Agi, 20 Hit",
+[3988]="30 Stam, 20 Exp",
+[3989]="20 Parry, 20 Hit",
+[3990]="20 Int, 20 Spirit",
+[3991]="20 Agi, 30 Stam",
+[3992]="20 Str, 30 Stam",
+[3993]="20 Int, 30 Stam",
+[3994]="40 Str",
+[3995]="40 Int",
+[3996]="40 Agi",
+[3997]="40 Parry",
+[3998]="40 Exp",
+[3999]="40 Mastery",
+[4000]="40 Resil",
+[4001]="40 Haste",
+[4002]="40 Crit",
+[4003]="40 Dodge",
+[4004]="40 Hit",
+[4005]="60 Stam",
+[4006]="40 Spirit",
+[4007]="40 PvP Pow",
+[4008]="20 Agi, 20 Mastery",
+[4009]="20 Int, 20 Mastery",
+[4010]="20 Int, 20 Haste",
+[4011]="20 Agi, 20 Crit",
+[4012]="20 Agi, 20 Haste",
+[4013]="20 Str, 20 Haste",
+[4014]="20 Parry, 20 Mastery",
+[4015]="20 Str, 20 Crit",
+[4016]="20 Exp, 20 Mastery",
+[4017]="20 Agi, 20 Dodge",
+[4018]="20 Int, 20 Crit",
+[4019]="20 Str, 20 Mastery",
+[4020]="20 Exp, 20 Dodge",
+[4021]="30 Stam, 20 Haste",
+[4022]="30 Stam, 20 Crit",
+[4023]="20 Haste, 20 Hit",
+[4024]="20 Dodge, 20 Hit",
+[4025]="20 Crit, 20 Hit",
+[4026]="30 Stam, 20 Mastery",
+[4027]="30 Stam, 20 Dodge",
+[4028]="20 Mastery, 20 Hit",
+[4029]="20 Resil, 30 Stam",
+[4030]="20 Mastery, 20 Spirit",
+[4031]="67 Str",
+[4032]="67 Int",
+[4033]="67 Agi",
+[4034]="67 Parry",
+[4035]="67 Mastery",
+[4036]="67 Resil",
+[4037]="67 Exp",
+[4038]="67 Haste",
+[4039]="67 Hit",
+[4040]="67 Crit",
+[4041]="101 Stam",
+[4042]="67 Spirit",
+[4043]="67 PvP Pow",
+[4044]="67 Dodge",
+[4045]="54 Mastery",
+[4046]="54 Crit",
+[4047]="54 Int",
+[4048]="81 Stam",
+[4049]="81 Stam",
+[4050]="81 Stam",
+[4051]="54 Int",
+[4052]="54 Spirit",
+[4053]="54 Crit",
+[4054]="81 Stam",
+[4055]="54 Crit",
+[4056]="54 Crit",
+[4057]="54 Int",
+[4058]="1 Exp",
+[4059]="1 Mastery",
+[4060]="1 Parry",
+[4061]="50 Mastery",
+[4062]="30 Stam, Run Speed",
+[4063]="15 All Stats",
+[4064]="56 PvP Pow",
+[4065]="50 Haste",
+[4066]="Mending",
+[4067]="Avalanche",
+[4068]="50 Haste",
+[4069]="50 Haste",
+[4070]="55 Stam",
+[4071]="50 Crit",
+[4072]="30 Int",
+[4073]="16 Stam",
+[4074]="Elemental Slayer",
+[4075]="35 Str",
+[4076]="35 Agi",
+[4077]="40 Resil",
+[4078]="40 Str",
+[4079]="40 Agi",
+[4080]="40 Int",
+[4081]="60 Stam",
+[4082]="50 Exp",
+[4083]="Hurricane",
+[4084]="Heartsong",
+[4085]="50 Mastery",
+[4086]="50 Dodge",
+[4087]="50 Crit",
+[4088]="40 Spirit",
+[4089]="50 Hit",
+[4090]="30 Stam",
+[4091]="40 Int",
+[4092]="50 Hit",
+[4093]="50 Spirit",
+[4094]="50 Mastery",
+[4095]="50 Exp",
+[4096]="50 Int",
+[4097]="Power Torrent",
+[4098]="Windwalk",
+[4099]="Landslide",
+[4100]="65 Crit",
+[4101]="65 Crit",
+[4102]="20 All Stats",
+[4103]="75 Stam",
+[4104]="35 Mastery, Run Speed",
+[4105]="25 Agi, Run Speed",
+[4106]="50 Str",
+[4107]="65 Mastery",
+[4108]="65 Haste",
+[4109]="55 Int, 45 Spirit",
+[4110]="95 Int, 55 Spirit",
+[4111]="55 Int, 65 Stam",
+[4112]="95 Int, 80 Stam",
+[4113]="95 Int, 80 Stam",
+[4114]="95 Int, 55 Spirit",
+[4115]="Lightweave 2",
+[4116]="Darkglow 2",
+[4117]="Swordguard Embroidery",
+[4118]="Swordguard 2",
+[4119]="50 Str",
+[4120]="36 Stam",
+[4121]="44 Stam",
+[4122]="110 AP, 45 Crit",
+[4123]="10 Mastery",
+[4124]="85 Stam, 45 Agi",
+[4125]="30 Spirit",
+[4126]="190 AP, 55 Crit",
+[4127]="145 Stam, 55 Agi",
+[4128]="30 Haste",
+[4129]="20 Spirit",
+[4130]="20 Crit",
+[4131]="10 Crit",
+[4132]="30 Crit",
+[4134]="30 Stam",
+[4135]="10 Str",
+[4136]="20 Str",
+[4137]="20 Mastery",
+[4138]="30 Mastery",
+[4139]="20 Parry",
+[4140]="20 Haste",
+[4141]="20 Hit",
+[4142]="10 Spirit",
+[4143]="10 Int",
+[4144]="20 Int",
+[4145]="30 Agi",
+[4146]="10 Haste",
+[4147]="10 Parry",
+[4148]="30 Parry",
+[4149]="20 Int",
+[4150]="30 Int",
+[4151]="10 Crit",
+[4152]="20 Crit",
+[4153]="30 Crit",
+[4154]="15 Stam",
+[4155]="10 Dodge",
+[4156]="20 Dodge",
+[4157]="30 Dodge",
+[4158]="30 Str",
+[4159]="45 Stam",
+[4160]="10 Hit",
+[4161]="20 Hit",
+[4162]="30 Hit",
+[4163]="10 Exp",
+[4164]="20 Exp",
+[4165]="30 Exp",
+[4166]="208 Dodge",
+[4167]="208 Crit",
+[4168]="208 Haste",
+[4169]="208 Mastery",
+[4170]="208 Exp",
+[4171]="208 Parry",
+[4172]="208 Hit",
+[4173]="208 Spirit",
+[4175]="Gnomish X-Ray",
+[4176]="88 Hit",
+[4177]="88 Haste",
+[4178]="900 Armor",
+[4179]="Use: Increases your Intellect, Agility, or Strength by 480 for 10 sec.  Your highest stat is always chosen. (1 Min Cooldown)",
+[4180]="Use: Increases your armor by 1,500 for 13 sec. (1 Min Cooldown)",
+[4181]="Use: Fires an electrified ball at an enemy for 4,800 Nature damage. (2 Min Cooldown)",
+[4184]="10 Resil",
+[4185]="20 Resil",
+[4186]="30 Resil",
+[4187]="Use: Activates a personal invisibility field.  Cannot be used in combat. (3 Min Cooldown)",
+[4188]="Use: Protects you with a shield of force that stops 18,000 damage for 8 sec.  The strong magnetic field sometimes has strange side effects... (5 Min Cooldown)",
+[4189]="195 Stam",
+[4190]="130 Agi",
+[4191]="130 Str",
+[4192]="130 Int",
+[4193]="130 Agi, 25 Mastery",
+[4194]="130 Str, 25 Crit",
+[4195]="195 Stam, 25 Dodge",
+[4196]="130 Int, 25 Haste",
+[4197]="45 Stam, 20 Dodge",
+[4198]="75 Stam, 25 Dodge",
+[4199]="30 Int, 20 Haste",
+[4200]="50 Int, 25 Haste",
+[4201]="30 Str, 20 Crit",
+[4202]="50 Str, 25 Crit",
+[4203]="30 Agi, 20 Mastery",
+[4204]="50 Agi, 25 Mastery",
+[4205]="30 Agi, 20 Mastery",
+[4206]="90 Stam, 35 Dodge",
+[4207]="60 Int, 35 Crit",
+[4208]="60 Str, 35 Mastery",
+[4209]="60 Agi, 35 Haste",
+[4211]="10 Haste",
+[4212]="7 Str",
+[4213]="7 Str",
+[4214]="Use: Summons a Cardboard Assassin to draw the attention of enemies. (5 Min Cooldown)",
+[4215]="Elementium Spike (90-133)",
+[4216]="Pyrium Spike (210-350)",
+[4217]="40 Hit",
+[4222]="Use: Engage in mental combat with a humanoid target in an attempt to pacify or control them. (10 Min Cooldown)",
+[4223]="Use: Greatly increase your run speed for 5 sec. (3 Min Cooldown)",
+[4225]="Fishing Lure (+150 Fishing Skill)",
+[4227]="130 Agi",
+[4236]="20 Int, 20 Resil",
+[4237]="20 Agi, 20 Resil",
+[4238]="20 Str, 20 Resil",
+[4239]="208 Resil",
+[4244]="20 Resil, 20 PvP Pow",
+[4245]="60 Int, 35 Resil",
+[4246]="60 Agi, 35 Resil",
+[4247]="60 Str, 35 Resil",
+[4248]="50 Int, 25 Resil",
+[4249]="50 Str, 25 Resil",
+[4250]="50 Agi, 25 Resil",
+[4251]="54 Agi",
+[4252]="54 Str",
+[4253]="54 Int",
+[4256]="50 Str",
+[4257]="50 Int",
+[4258]="50 Agi",
+[4259]="+1 Fishing",
+[4262]="30 Stam",
+[4263]="20 Spirit",
+[4264]="Fishing Lure (+15 Fishing Skill)",
+[4265]="50 Int",
+[4266]="50 Agi",
+[4267]="Flintlocke's",
+[4270]="145 Stam, 55 Dodge",
+[4273]="50 Hit",
+[4274]="50 PvP Pow",
+[4275]="50 Spirit",
+[4276]="75 Stam",
+[4277]="25 Spirit, 25 Crit",
+[4278]="25 Crit, 25 Hit",
+[4279]="25 Haste, 25 Hit",
+[4280]="25 Hit, 25 Mastery",
+[4281]="25 PvP Pow, 25 Mastery",
+[4282]="25 Spirit, 25 Mastery",
+[4283]="25 Resil, 25 Hit",
+[4284]="25 PvP Pow, 25 Resil",
+[4285]="25 Resil, 25 Spirit",
+[4286]="25 PvP Pow, 25 Crit",
+[4287]="25 PvP Pow, 25 Haste",
+[4288]="25 Haste, 25 Spirit",
+[4289]="37 Stam, 25 Crit",
+[4290]="37 Stam, 25 Dodge",
+[4291]="37 Stam, 25 Haste",
+[4292]="25 Hit, 25 Dodge",
+[4293]="37 Stam, 25 Mastery",
+[4294]="25 Resil, 37 Stam",
+[4295]="25 Agi, 25 Crit",
+[4296]="25 Exp, 25 Crit",
+[4297]="25 Int, 25 Crit",
+[4298]="25 Str, 25 Crit",
+[4299]="25 Agi, 25 Dodge",
+[4300]="25 Exp, 25 Dodge",
+[4301]="25 Parry, 25 Dodge",
+[4302]="25 Str, 25 Dodge",
+[4303]="25 Agi, 25 Haste",
+[4304]="25 Exp, 25 Haste",
+[4305]="25 Int, 25 Haste",
+[4306]="25 Str, 25 Haste",
+[4307]="25 Agi, 25 Mastery",
+[4308]="25 Exp, 25 Mastery",
+[4309]="25 Int, 25 Mastery",
+[4310]="25 Parry, 25 Mastery",
+[4311]="25 Str, 25 Mastery",
+[4312]="25 Agi, 25 Resil",
+[4313]="25 Resil, 25 Exp",
+[4314]="25 Int, 25 Resil",
+[4315]="25 Resil, 25 Parry",
+[4316]="25 Str, 25 Resil",
+[4317]="25 Agi, 25 Hit",
+[4318]="25 Exp, 25 Hit",
+[4319]="25 Int, 25 Hit",
+[4320]="25 Parry, 25 Hit",
+[4321]="25 Str, 25 Hit",
+[4322]="25 Int, 25 PvP Pow",
+[4323]="25 Int, 25 Spirit",
+[4324]="25 Agi, 37 Stam",
+[4325]="37 Stam, 25 Exp",
+[4326]="25 Int, 37 Stam",
+[4327]="37 Stam, 25 Parry",
+[4328]="25 Str, 37 Stam",
+[4329]="50 Agi",
+[4330]="50 Exp",
+[4331]="50 Int",
+[4332]="50 Parry",
+[4333]="50 Str",
+[4334]="50 Crit",
+[4335]="50 Dodge",
+[4336]="50 Haste",
+[4337]="50 Mastery",
+[4338]="50 Resil",
+[4359]="160 Agi",
+[4360]="160 Int",
+[4361]="240 Stam",
+[4411]="170 Mastery",
+[4412]="170 Dodge",
+[4414]="180 Int",
+[4415]="180 Str",
+[4416]="180 Agi",
+[4417]="200 Resil",
+[4418]="200 Spirit",
+[4419]="80 All Stats",
+[4420]="300 Stam",
+[4421]="180 Hit",
+[4422]="200 Stam",
+[4423]="180 Int",
+[4424]="180 Crit",
+[4426]="175 Haste",
+[4427]="175 Hit",
+[4428]="140 Agi, Run Speed",
+[4429]="140 Mastery, Run Speed",
+[4430]="170 Haste",
+[4431]="170 Exp",
+[4432]="170 Str",
+[4433]="170 Mastery",
+[4434]="165 Int",
+[4435]="145 Stam, 55 Dodge",
+[4436]="145 Stam, 55 Agi",
+[4437]="190 AP, 55 Crit",
+[4438]="145 Stam, 55 Dodge",
+[4439]="145 Stam, 55 Agi",
+[4440]="190 AP, 55 Crit",
+[4441]="Windsong",
+[4442]="Jade Spirit",
+[4443]="Elemental Force",
+[4444]="Dancing Steel",
+[4445]="Colossus",
+[4446]="River's Song",
+[4453]="240 Hit",
+[4454]="240 PvP Pow",
+[4455]="240 Spirit",
+[4456]="180 Stam",
+[4457]="120 Spirit, 120 Crit",
+[4458]="120 Crit, 120 Hit",
+[4459]="120 Haste, 120 Hit",
+[4460]="120 Hit, 120 Mastery",
+[4461]="120 PvP Pow, 120 Mastery",
+[4462]="120 Spirit, 120 Mastery",
+[4463]="120 Resil, 120 Hit",
+[4464]="120 PvP Pow, 120 Resil",
+[4465]="120 Resil, 120 Spirit",
+[4466]="120 PvP Pow, 120 Crit",
+[4467]="120 PvP Pow, 120 Haste",
+[4468]="120 Haste, 120 Spirit",
+[4469]="90 Stam, 120 Crit",
+[4470]="90 Stam, 120 Dodge",
+[4471]="90 Stam, 120 Haste",
+[4472]="90 Stam, 120 Hit",
+[4473]="90 Stam, 120 Mastery",
+[4474]="120 Resil, 90 Stam",
+[4475]="60 Agi, 120 Crit",
+[4476]="120 Exp, 120 Crit",
+[4477]="60 Int, 120 Crit",
+[4478]="60 Str, 120 Crit",
+[4479]="60 Agi, 120 Dodge",
+[4480]="120 Exp, 120 Dodge",
+[4481]="120 Parry, 120 Dodge",
+[4482]="60 Str, 120 Dodge",
+[4483]="60 Agi, 120 Haste",
+[4484]="120 Exp, 120 Haste",
+[4485]="60 Int, 120 Haste",
+[4486]="60 Str, 120 Haste",
+[4487]="60 Agi, 120 Mastery",
+[4488]="120 Exp, 120 Mastery",
+[4489]="60 Int, 120 Mastery",
+[4490]="120 Parry, 120 Mastery",
+[4491]="60 Str, 120 Mastery",
+[4492]="60 Agi, 120 Resil",
+[4493]="120 Resil, 120 Exp",
+[4494]="60 Int, 120 Resil",
+[4495]="120 Resil, 120 Parry",
+[4496]="60 Str, 120 Resil",
+[4497]="60 Agi, 120 Hit",
+[4498]="120 Exp, 120 Hit",
+[4499]="60 Int, 120 Hit",
+[4500]="120 Parry, 120 Hit",
+[4501]="60 Str, 120 Hit",
+[4502]="60 Int, 120 PvP Pow",
+[4503]="60 Int, 120 Spirit",
+[4504]="60 Agi, 90 Stam",
+[4505]="90 Stam, 120 Exp",
+[4506]="60 Int, 90 Stam",
+[4507]="90 Stam, 120 Parry",
+[4508]="60 Str, 90 Stam",
+[4509]="120 Agi",
+[4511]="240 Exp",
+[4512]="120 Int",
+[4513]="240 Parry",
+[4514]="120 Str",
+[4515]="240 Crit",
+[4516]="240 Dodge",
+[4517]="240 Haste",
+[4518]="240 Mastery",
+[4519]="240 Resil",
+[4520]="320 Hit",
+[4521]="320 PvP Pow",
+[4522]="320 Spirit",
+[4523]="240 Stam",
+[4524]="160 Spirit, 160 Crit",
+[4525]="160 Crit, 160 Hit",
+[4526]="160 Haste, 160 Hit",
+[4527]="160 Hit, 160 Mastery",
+[4528]="160 PvP Pow, 160 Mastery",
+[4529]="160 Spirit, 160 Mastery",
+[4530]="160 Resil, 160 Hit",
+[4531]="160 PvP Pow, 160 Resil",
+[4532]="160 Resil, 160 Spirit",
+[4533]="160 PvP Pow, 160 Crit",
+[4535]="160 PvP Pow, 160 Haste",
+[4536]="160 Haste, 160 Spirit",
+[4537]="120 Stam, 160 Crit",
+[4538]="120 Stam, 160 Dodge",
+[4539]="120 Stam, 160 Haste",
+[4540]="120 Stam, 160 Hit",
+[4541]="120 Stam, 160 Mastery",
+[4542]="160 Resil, 120 Stam",
+[4543]="80 Agi, 160 Crit",
+[4544]="160 Exp, 160 Crit",
+[4545]="80 Int, 160 Crit",
+[4546]="80 Str, 160 Crit",
+[4547]="80 Agi, 160 Dodge",
+[4548]="160 Exp, 160 Dodge",
+[4549]="160 Parry, 160 Dodge",
+[4550]="80 Str, 160 Dodge",
+[4551]="80 Agi, 160 Haste",
+[4552]="160 Exp, 160 Haste",
+[4553]="80 Int, 160 Haste",
+[4554]="80 Str, 160 Haste",
+[4555]="80 Agi, 160 Mastery",
+[4556]="160 Exp, 160 Mastery",
+[4557]="80 Int, 160 Mastery",
+[4558]="160 Parry, 160 Mastery",
+[4559]="80 Str, 160 Mastery",
+[4560]="80 Agi, 160 Resil",
+[4561]="160 Resil, 160 Exp",
+[4562]="80 Int, 160 Resil",
+[4563]="160 Resil, 160 Parry",
+[4564]="80 Str, 160 Resil",
+[4565]="80 Agi, 160 Hit",
+[4566]="160 Exp, 160 Hit",
+[4567]="80 Int, 160 Hit",
+[4568]="160 Parry, 160 Hit",
+[4569]="80 Str, 160 Hit",
+[4570]="80 Int, 160 PvP Pow",
+[4571]="80 Int, 160 Spirit",
+[4572]="80 Agi, 120 Stam",
+[4573]="120 Stam, 160 Exp",
+[4574]="80 Int, 120 Stam",
+[4575]="120 Stam, 160 Parry",
+[4576]="80 Str, 120 Stam",
+[4577]="160 Agi",
+[4578]="320 Exp",
+[4579]="160 Int",
+[4580]="320 Parry",
+[4581]="160 Str",
+[4582]="320 Crit",
+[4583]="320 Dodge",
+[4584]="320 Haste",
+[4585]="320 Mastery",
+[4586]="320 Resil",
+[4587]="320 Hit",
+[4588]="320 PvP Pow",
+[4589]="320 Spirit",
+[4590]="240 Stam",
+[4591]="160 Spirit, 160 Crit",
+[4592]="160 Crit, 160 Hit",
+[4593]="160 Haste, 160 Hit",
+[4594]="160 Hit, 160 Mastery",
+[4595]="160 PvP Pow, 160 Mastery",
+[4596]="160 Spirit, 160 Mastery",
+[4597]="160 Resil, 160 Hit",
+[4598]="160 PvP Pow, 160 Resil",
+[4599]="160 Resil, 160 Spirit",
+[4600]="160 PvP Pow, 160 Crit",
+[4601]="160 PvP Pow, 160 Haste",
+[4602]="160 Haste, 160 Spirit",
+[4603]="120 Stam, 160 Crit",
+[4604]="120 Stam, 160 Dodge",
+[4605]="120 Stam, 160 Haste",
+[4606]="120 Stam, 160 Hit",
+[4607]="120 Stam, 160 Mastery",
+[4608]="160 Resil, 120 Stam",
+[4609]="80 Agi, 160 Crit",
+[4610]="160 Exp, 160 Crit",
+[4611]="80 Int, 160 Crit",
+[4612]="80 Str, 160 Crit",
+[4613]="80 Agi, 160 Dodge",
+[4614]="160 Exp, 160 Dodge",
+[4615]="160 Parry, 160 Dodge",
+[4616]="80 Str, 160 Dodge",
+[4617]="80 Agi, 160 Haste",
+[4618]="160 Exp, 160 Haste",
+[4619]="80 Int, 160 Haste",
+[4620]="80 Str, 160 Haste",
+[4621]="80 Agi, 160 Mastery",
+[4622]="160 Exp, 160 Mastery",
+[4623]="80 Int, 160 Mastery",
+[4624]="160 Parry, 160 Mastery",
+[4625]="80 Str, 160 Mastery",
+[4626]="80 Agi, 160 Resil",
+[4627]="160 Resil, 160 Exp",
+[4628]="80 Int, 160 Resil",
+[4629]="160 Resil, 160 Parry",
+[4630]="80 Str, 160 Resil",
+[4631]="80 Agi, 160 Hit",
+[4632]="160 Exp, 160 Hit",
+[4633]="80 Int, 160 Hit",
+[4634]="160 Parry, 160 Hit",
+[4635]="80 Str, 160 Hit",
+[4636]="80 Int, 160 PvP Pow",
+[4637]="80 Int, 160 Spirit",
+[4638]="80 Agi, 120 Stam",
+[4640]="80 Int, 120 Stam",
+[4641]="120 Stam, 160 Parry",
+[4642]="80 Str, 120 Stam",
+[4643]="160 Agi",
+[4644]="160 Int",
+[4645]="320 Parry",
+[4646]="160 Str",
+[4647]="320 Crit",
+[4648]="320 Dodge",
+[4649]="320 Haste",
+[4650]="320 Mastery",
+[4651]="320 Resil",
+[4652]="120 Stam, 160 Exp",
+[4653]="320 Exp",
+[4654]="24 Hit",
+[4655]="216 Int",
+[4656]="216 Agi",
+[4657]="216 Str",
+[4658]="216 Int",
+[4659]="432 Mastery",
+[4660]="432 Spirit",
+[4661]="432 Crit",
+[4662]="324 Stam",
+[4664]="432 Crit",
+[4665]="432 Crit",
+[4666]="216 Int",
+[4667]="324 Stam",
+[4668]="432 Dodge",
+[4669]="324 Stam",
+[4671]="10 Str",
+[4672]="25 Resil, 25 Hit",
+[4673]="25 PvP Pow, 25 Mastery",
+[4674]="25 Agi, 25 Resil",
+[4675]="25 Int, 25 PvP Pow",
+[4676]="50 Resil",
+[4677]="25 PvP Pow, 25 Crit",
+[4678]="25 Str, 25 Resil",
+[4679]="25 PvP Pow, 25 Haste",
+[4680]="25 Resil, 25 Parry",
+[4681]="25 Resil, 37 Stam",
+[4682]="50 PvP Pow",
+[4683]="25 Resil, 25 Exp",
+[4684]="25 Resil, 25 Spirit",
+[4685]="25 PvP Pow, 25 Resil",
+[4686]="25 Int, 25 Resil",
+[4687]="160 Agi",
+[4688]="Samurai",
+[4697]="Use: Increases your dodge by 480 for 10 sec. (1 Min Cooldown)",
+[4698]="Use: Launches a cluster of highly explosive fireworks that detonate on impact for 14,000 Fire damage over 3 sec. (45 Sec Cooldown)",
+[4699]="Blastington's",
+[4700]="Mirror Scope",
+[4701]="200 Str",
+[4702]="400 Str",
+[4717]="Pandamonium",
+[4719]="Placeholder Shoulder Enchant",
+[4720]="+5 Health",
+[4721]="1 Stam",
+[4722]="1 Stam",
+[4723]="+2 Weapon Damage",
+[4724]="1 Agi",
+[4725]="1 Agi",
+[4726]="3 Spirit",
+[4727]="3 Spirit",
+[4728]="3 Spirit",
+[4729]="3 Int",
+[4730]="3 Stam",
+[4731]="3 Stam",
+[4732]="+5 Fishing",
+[4733]="30 Armor",
+[4734]="3 Agi",
+[4735]="5 Spirit",
+[4736]="5 Spirit",
+[4737]="5 Stam",
+[4738]="5 Stam",
+[4739]="5 Str",
+[4740]="5 Agi",
+[4741]="7 Spirit",
+[4742]="7 Str",
+[4743]="7 Stam",
+[4744]="7 Stam",
+[4745]="+3 Weapon Damage",
+[4746]="+7 Weapon Damage",
+[4747]="16 Agi",
+[4748]="16 Agi",
+[4750]="Use: Injects a Mythical Healing Potion directly into your bloodstream, increasing potency and healing you for 30,000. (1 Min Cooldown)",
+[4753]="1 Str, 1 Agi, 1 Stam, 1 Int, 1 Spirit",
+[4755]="3 Str, 3 Agi, 3 Stam, 3 Int, 3 Spirit",
+[4757]="5 Str, 5 Agi, 5 Stam, 5 Int, 5 Spirit",
+[4759]="7 Str, 7 Agi, 7 Stam, 7 Int, 7 Spirit",
+[4760]="9 Str, 9 Agi, 9 Stam, 9 Int, 9 Spirit",
+[4761]="3 Str, 3 Agi, 3 Stam, 3 Int, 3 Spirit",
+[4762]="5 Str, 5 Agi, 5 Stam, 5 Int, 5 Spirit",
+[4803]="200 Str, 100 Crit",
+[4804]="200 Agi, 100 Crit",
+[4805]="300 Stam, 100 Dodge",
+[4806]="200 Int, 100 Crit",
+[4807]="160 Str",
+[4808]="Magic Weapon",
+[4810]="320 Str",
+[4811]="320 Int",
+[4812]="320 Agi",
+[4813]="480 Parry",
+[4814]="480 Mastery",
+[4815]="480 Exp",
+[4816]="480 Haste",
+[4817]="480 Hit",
+[4818]="480 Crit",
+[4819]="480 Dodge",
+[4820]="480 Stam",
+[4821]="480 Spirit",
+[4822]="285 Agi, 165 Crit",
+[4823]="285 Str, 165 Crit",
+[4824]="430 Stam, 165 Dodge",
+[4825]="285 Int, 165 Crit",
+[4826]="285 Int, 165 Spirit",
+[4827]="60 Agi",
+[4828]="120 Agi",
+[4829]="180 Agi",
+[4830]="60 Str",
+[4831]="60 Int",
+[4832]="90 Stam",
+[4833]="60 Crit",
+[4834]="60 Mastery",
+[4835]="60 Hit",
+[4836]="60 Haste",
+[4837]="60 Exp",
+[4838]="60 Spirit",
+[4839]="60 Dodge",
+[4840]="60 Parry",
+[4841]="60 PvP Pow",
+[4842]="60 Resil",
+[4843]="120 Crit",
+[4844]="120 Dodge",
+[4845]="120 Exp",
+[4846]="120 Haste",
+[4847]="120 Hit",
+[4848]="120 Int",
+[4849]="120 Mastery",
+[4850]="120 Parry",
+[4851]="120 Resil",
+[4852]="120 Spirit",
+[4853]="120 Str",
+[4854]="180 Stam",
+[4855]="180 Crit",
+[4856]="180 Dodge",
+[4857]="180 Exp",
+[4858]="180 Haste",
+[4859]="180 Hit",
+[4860]="180 Int",
+[4861]="180 Mastery",
+[4862]="180 Parry",
+[4863]="180 Resil",
+[4864]="120 PvP Pow",
+[4865]="180 PvP Pow",
+[4866]="180 Spirit",
+[4867]="270 Stam",
+[4868]="180 Str",
+[4869]="150 Stam",
+[4870]="250 Stam, 100 Dodge",
+[4871]="170 Agi, 100 Crit",
+[4872]="170 Str, 100 Crit",
+[4873]="57 Agi",
+[4874]="57 Str",
+[4875]="500 Agi",
+[4877]="500 Int",
+[4878]="750 Stam",
+[4879]="500 Str",
+[4880]="285 Agi, 165 Crit",
+[4881]="285 Str, 165 Crit",
+[4882]="430 Stam, 165 Dodge",
+[4883]="95 Agi, 55 Crit",
+[4884]="143 Stam, 55 Dodge",
+[4885]="95 Str, 55 Crit",
+[4886]="37 Agi, 22 Crit",
+[4887]="55 Stam, 22 Dodge",
+[4888]="37 Str, 22 Crit",
+[4891]="Pandaren Fishing Lure",
+[4892]="Lightweave 3",
+[4893]="Darkglow 3",
+[4894]="Swordguard 3",
+[4895]="285 Int, 165 Crit",
+[4896]="285 Int, 165 Spirit",
+[4897]="Use: Reduces your falling speed for 2 min. (3 Min Cooldown)",
+[4898]="Use: Increases your Intellect, Agility, or Strength by 1,920 for 10 sec.  Your highest stat is always chosen. (1 Min Cooldown)",
+[4899]="600 Parry",
+[4900]="600 Mastery",
+[4901]="600 Exp",
+[4902]="600 Haste",
+[4903]="600 Hit",
+[4904]="600 Crit",
+[4905]="600 Spirit",
+[4906]="600 Dodge",
+[4907]="120 Str, 80 Crit",
+[4908]="120 Agi, 80 Crit",
+[4909]="120 Int, 80 Crit",
+[4910]="180 Stam, 80 Dodge",
+[4911]="520 Str, 100 Crit",
+[4912]="780 Stam, 100 Dodge",
+[4913]="520 Str, 100 Crit",
+[4914]="520 Agi, 100 Crit",
+[4915]="520 Int, 100 Crit",
+[4916]="520 Spirit, 100 Crit",
+[4918]="200 Exp",
+[4919]="Fishing Lure (+150 Fishing Skill)",
+[4920]="+10 Maximum Health",
+[4921]="200 Exp, 200 Hit",
+[4922]="150 Stam, 200 Parry",
+[4923]="100 Str, 200 Hit",
+[4924]="100 Agi, 200 Hit",
+[4925]="150 Stam, 200 Exp",
+[4926]="100 Int, 200 Spirit",
+[4927]="200 Parry, 200 Hit",
+[4928]="100 Agi, 150 Stam",
+[4929]="100 Str, 150 Stam",
+[4930]="100 Int, 150 Stam",
+[4931]="100 Int, 200 Hit",
+[4932]="200 Resil, 200 Hit",
+[4933]="200 PvP Pow, 200 Mastery",
+[4934]="200 Haste, 200 Spirit",
+[4935]="100 Str, 200 Hit",
+[4936]="150 Stam, 200 Haste",
+[4937]="150 Stam, 200 Crit",
+[4938]="200 Haste, 200 Hit",
+[4939]="200 Spirit, 200 Crit",
+[4940]="150 Stam, 200 Hit",
+[4941]="200 Crit, 200 Hit",
+[4942]="150 Stam, 200 Mastery",
+[4943]="200 PvP Pow, 200 Crit",
+[4944]="150 Stam, 200 Dodge",
+[4945]="200 Hit, 200 Mastery",
+[4946]="200 PvP Pow, 200 Haste",
+[4947]="200 Resil, 150 Stam",
+[4948]="200 Resil, 200 Spirit",
+[4949]="200 PvP Pow, 200 Resil",
+[4950]="200 Spirit, 200 Mastery",
+[4951]="100 Agi, 200 Mastery",
+[4952]="100 Int, 200 Mastery",
+[4953]="100 Str, 200 Dodge",
+[4954]="200 Exp, 200 Crit",
+[4955]="100 Agi, 200 Crit",
+[4956]="100 Agi, 200 Haste",
+[4957]="100 Str, 200 Haste",
+[4958]="200 Parry, 200 Mastery",
+[4959]="100 Str, 200 Crit",
+[4960]="200 Exp, 200 Mastery",
+[4961]="100 Agi, 200 Resil",
+[4962]="100 Agi, 200 Dodge",
+[4963]="100 Int, 200 Crit",
+[4964]="100 Int, 200 Haste",
+[4965]="200 Exp, 200 Dodge",
+[4966]="100 Str, 200 Resil",
+[4967]="100 Str, 200 Mastery",
+[4968]="200 Resil, 200 Parry",
+[4969]="200 Parry, 200 Dodge",
+[4970]="200 Resil, 200 Exp",
+[4971]="200 Exp, 200 Haste",
+[4972]="100 Int, 200 Resil",
+[4973]="100 Int, 200 PvP Pow",
+[4984]="80 Str, 160 PvP Pow",
+[4985]="60 Str, 120 PvP Pow",
+[4986]="80 Str, 160 PvP Pow",
+[4987]="100 Str, 200 PvP Pow",
+[4988]="60 Agi, 120 PvP Pow",
+[4989]="80 Agi, 160 PvP Pow",
+[4990]="80 Agi, 160 PvP Pow",
+[4991]="100 Agi, 200 PvP Pow",
+[4992]="254 Str",
+[4993]="170 Parry",
+[4994]="Breath of the Agile Prince",
+[4996]="500 Agi",
+[4997]="500 Str",
+[4998]="500 Int",
+[5000]="Use: Allows you to walk on water and increases swim speed for up to 6 sec. (30 Sec Cooldown)",
+[5001]="Ghost Iron Spike (600-1000)",
+[5002]="Socket Belt",
+[5003]="170 Int, 100 Crit",
+[5004]="170 Int, 100 Spirit",
+[5030]="324 Stam",
+[5031]="324 Int",
+[5032]="324 Crit",
+[5033]="324 Crit",
+[5034]="665 PvP Pow, 775 Resil",
+[5035]="Tyranny",
+[5125]="Bloody Dancing Steel"}
+
+local enchantItemIds = {
+	[-1000]=90046,
+	[1099]=44457,
+	[1597]=44469,
+	[3222]=38967,
+	[3246]=38979,
+	[3260]=34207,
+	[3845]=44815,
+	[3850]=44944,
+	[4061]=52687,
+	[4062]=52743,
+	[4063]=52744,
+	[4064]=52745,
+	[4065]=52746,
+	[4066]=52747,
+	[4067]=45872,
+	[4068]=52749,
+	[4069]=52750,
+	[4070]=52751,
+	[4071]=52752,
+	[4072]=52753,
+	[4073]=52754,
+	[4075]=52756,
+	[4076]=52757,
+	[4077]=52758,
+	[4082]=52759,
+	[4083]=52760,
+	[4084]=52761,
+	[4085]=52762,
+	[4086]=52763,
+	[4087]=52764,
+	[4088]=52765,
+	[4089]=52766,
+	[4090]=52767,
+	[4091]=52768,
+	[4092]=52769,
+	[4093]=52770,
+	[4094]=52771,
+	[4095]=52772,
+	[4096]=52773,
+	[4097]=52774,
+	[4098]=52775,
+	[4099]=52776,
+	[4100]=52777,
+	[4101]=52778,
+	[4102]=52779,
+	[4103]=52780,
+	[4104]=52782,
+	[4105]=52781,
+	[4106]=52783,
+	[4107]=52784,
+	[4108]=52785,
+	[4109]=54449,
+	[4110]=54450,
+	[4111]=54447,
+	[4112]=54448,
+	[4122]=56502,
+	[4124]=56503,
+	[4126]=56550,
+	[4127]=56551,
+	[4175]=59594,
+	[4176]=59595,
+	[4177]=59596,
+	[4197]=62321,
+	[4198]=62333,
+	[4199]=62342,
+	[4200]=62343,
+	[4201]=62344,
+	[4202]=62345,
+	[4204]=62346,
+	[4205]=62347,
+	[4217]=55057,
+	[4227]=68134,
+	[4248]=68772,
+	[4249]=68773,
+	[4250]=68774,
+	[4256]=68788,
+	[4257]=68786,
+	[4258]=68784,
+	[4267]=70139,
+	[4270]=71720,
+	[4411]=74700,
+	[4412]=74701,
+	[4414]=74703,
+	[4415]=74704,
+	[4416]=74705,
+	[4417]=74706,
+	[4418]=74707,
+	[4419]=74708,
+	[4420]=74709,
+	[4421]=74710,
+	[4422]=74711,
+	[4423]=74712,
+	[4424]=74713,
+	[4426]=74715,
+	[4427]=74716,
+	[4428]=74717,
+	[4429]=74718,
+	[4430]=74719,
+	[4431]=74720,
+	[4432]=74721,
+	[4433]=74722,
+	[4434]=74729,
+	[4441]=74723,
+	[4442]=74724,
+	[4443]=74725,
+	[4444]=74726,
+	[4445]=74727,
+	[4446]=74728,
+	[4699]=77529,
+	[4700]=77531,
+	[4803]=83006,
+	[4804]=83007,
+	[4805]=87560,
+	[4806]=87559,
+	[4822]=83764,
+	[4823]=83765,
+	[4824]=83763,
+	[4825]=82445,
+	[4826]=82444,
+	[4869]=85559,
+	[4870]=85570,
+	[4871]=85569,
+	[4872]=85568,
+	[4907]=87580,
+	[4908]=87579,
+	[4909]=87578,
+	[4910]=87577,
+	[4912]=87581,
+	[4913]=87585,
+	[4914]=87584,
+	[4915]=87582,
+	[4918]=86597,
+	[4993]=89737,
+	[5003]=82443,
+	[5004]=82442,
+	[5035]=95349,
+	[5125]=98163}
+
+local enchantSpellIds = {
+	[-1000]=122632,
+	[1099]=60663,
+	[1597]=60763,
+	[3222]=44529,
+	[3246]=44592,
+	[3255]=56039,
+	[3260]=44770,
+	[3365]=53323,
+	[3368]=53344,
+	[3369]=53341,
+	[3370]=53343,
+	[3594]=54446,
+	[3722]=55642,
+	[3728]=55769,
+	[3730]=55776,
+	[3757]=57690,
+	[3758]=57691,
+	[3845]=44575,
+	[3847]=62158,
+	[3850]=62256,
+	[3873]=56034,
+	[3883]=70164,
+	[4061]=74132,
+	[4062]=74189,
+	[4063]=74191,
+	[4064]=74192,
+	[4065]=74193,
+	[4066]=74195,
+	[4067]=74197,
+	[4068]=74198,
+	[4069]=74199,
+	[4070]=74200,
+	[4071]=74201,
+	[4072]=74202,
+	[4073]=74207,
+	[4075]=74212,
+	[4076]=74213,
+	[4077]=74214,
+	[4078]=74215,
+	[4079]=74216,
+	[4080]=74217,
+	[4081]=74218,
+	[4082]=74220,
+	[4083]=74223,
+	[4084]=74225,
+	[4085]=74226,
+	[4086]=74229,
+	[4087]=74230,
+	[4088]=74231,
+	[4089]=74232,
+	[4090]=74234,
+	[4091]=74235,
+	[4092]=44488,
+	[4093]=74237,
+	[4094]=74238,
+	[4095]=74239,
+	[4096]=74240,
+	[4097]=74242,
+	[4098]=74244,
+	[4099]=74246,
+	[4100]=74247,
+	[4101]=74248,
+	[4102]=74250,
+	[4103]=74251,
+	[4104]=74253,
+	[4105]=74252,
+	[4106]=74254,
+	[4107]=74255,
+	[4108]=74256,
+	[4109]=75255,
+	[4110]=75310,
+	[4111]=75250,
+	[4112]=75309,
+	[4113]=75154,
+	[4114]=75155,
+	[4115]=74172,
+	[4116]=75175,
+	[4118]=75177,
+	[4122]=78419,
+	[4124]=78420,
+	[4126]=78477,
+	[4127]=78478,
+	[4175]=84428,
+	[4176]=84408,
+	[4177]=84410,
+	[4189]=85007,
+	[4190]=85008,
+	[4191]=85009,
+	[4192]=85010,
+	[4193]=86375,
+	[4194]=86401,
+	[4195]=86402,
+	[4196]=86403,
+	[4217]=76442,
+	[4227]=95741,
+	[4256]=96261,
+	[4257]=96262,
+	[4258]=96264,
+	[4267]=100587,
+	[4270]=101599,
+	[4359]=103461,
+	[4360]=103462,
+	[4361]=103463,
+	[4411]=104338,
+	[4412]=104385,
+	[4414]=104389,
+	[4415]=104390,
+	[4416]=104391,
+	[4417]=104392,
+	[4418]=104393,
+	[4419]=104395,
+	[4420]=104397,
+	[4421]=104398,
+	[4422]=104401,
+	[4423]=104403,
+	[4424]=104404,
+	[4426]=104407,
+	[4427]=104408,
+	[4428]=104409,
+	[4429]=104414,
+	[4430]=104416,
+	[4431]=104417,
+	[4432]=104419,
+	[4433]=104420,
+	[4434]=104445,
+	[4441]=104425,
+	[4442]=104427,
+	[4443]=104430,
+	[4444]=104434,
+	[4445]=104440,
+	[4446]=104442,
+	[4699]=127115,
+	[4700]=127116,
+	[4803]=126997,
+	[4804]=126996,
+	[4805]=126994,
+	[4806]=126995,
+	[4807]=103465,
+	[4822]=124129,
+	[4823]=124127,
+	[4824]=124128,
+	[4825]=125555,
+	[4826]=125554,
+	[4869]=124628,
+	[4870]=124125,
+	[4871]=124124,
+	[4872]=124126,
+	[4873]=57683,
+	[4874]=124549,
+	[4875]=124551,
+	[4877]=124552,
+	[4878]=124553,
+	[4879]=124554,
+	[4880]=124559,
+	[4881]=124561,
+	[4882]=124563,
+	[4883]=124564,
+	[4884]=124565,
+	[4885]=124566,
+	[4886]=124567,
+	[4887]=124568,
+	[4888]=124569,
+	[4892]=125481,
+	[4893]=125482,
+	[4894]=125489,
+	[4895]=125496,
+	[4896]=125497,
+	[4907]=127016,
+	[4908]=127017,
+	[4909]=127018,
+	[4910]=127019,
+	[4912]=127024,
+	[4913]=127020,
+	[4914]=127021,
+	[4915]=127023,
+	[4918]=131929,
+	[4993]=130758,
+	[5003]=125553,
+	[5004]=125552,
+	[5035]=139631,
+	[5125]=142468}
+
+local enchantMaterials = {
+	[-1000]={[72104]=1},
+	[1099]={[34054]=8, [34055]=2, [34052]=2},
+	[1597]={[34055]=4, [34052]=4},
+	[3222]={[34052]=1, [34055]=4},
+	[3246]={[34054]=4, [34056]=1},
+	[3255]={[38426]=1},
+	[3260]={[23793]=4, [22452]=3},
+	[3722]={[38426]=1},
+	[3728]={[38426]=1},
+	[3730]={[38426]=1},
+	[3757]={[38426]=1},
+	[3758]={[38426]=1},
+	[3845]={[34055]=6, [34054]=24},
+	[3850]={[34055]=4, [34057]=1},
+	[3873]={[38426]=1},
+	[4061]={[52718]=1, [52555]=1},
+	[4062]={[52555]=2},
+	[4063]={[52718]=2},
+	[4064]={[52555]=3},
+	[4065]={[52718]=1, [52555]=2},
+	[4066]={[52719]=3, [52555]=11},
+	[4067]={[52719]=6, [52555]=4},
+	[4068]={[52718]=1, [52555]=4},
+	[4069]={[52719]=1, [52555]=2},
+	[4070]={[52555]=5, [52718]=1},
+	[4071]={[52718]=2, [52555]=4},
+	[4072]={[52555]=6},
+	[4073]={[52719]=1, [52327]=15},
+	[4075]={[52719]=2, [52555]=3},
+	[4076]={[52719]=2, [52555]=4},
+	[4077]={[52555]=9},
+	[4078]={[52721]=1},
+	[4079]={[52721]=1},
+	[4080]={[52721]=1},
+	[4081]={[52721]=1},
+	[4082]={[52719]=2, [52555]=5},
+	[4083]={[52721]=6, [52328]=6},
+	[4084]={[52721]=3, [52719]=3, [52555]=9, [52329]=3},
+	[4085]={[52555]=12},
+	[4086]={[52719]=5, [52328]=1},
+	[4087]={[52555]=8, [52719]=2},
+	[4088]={[52555]=10, [52719]=2},
+	[4089]={[52719]=1, [52555]=12},
+	[4090]={[52555]=8, [52719]=3},
+	[4091]={[52719]=4, [52555]=6},
+	[4092]={[52719]=2, [52555]=2, [58094]=1},
+	[4093]={[52719]=3, [52555]=9},
+	[4094]={[52719]=3, [52555]=10},
+	[4095]={[52719]=6, [52555]=4},
+	[4096]={[52555]=9, [52719]=4},
+	[4097]={[52722]=4, [52721]=8, [52555]=14},
+	[4098]={[52722]=6, [52721]=6, [52719]=4},
+	[4099]={[52722]=5, [52721]=5, [52719]=5, [52555]=6},
+	[4100]={[52722]=5},
+	[4101]={[52722]=1, [52721]=2, [52719]=3, [52555]=15},
+	[4102]={[52722]=3, [52721]=3},
+	[4103]={[52555]=10, [52721]=4, [52722]=2},
+	[4104]={[52722]=1, [52721]=2, [52719]=10},
+	[4105]={[52722]=1, [52721]=2, [52719]=7, [52555]=5},
+	[4106]={[52722]=2, [52719]=8, [52555]=4},
+	[4107]={[52722]=2, [52719]=5, [52555]=10},
+	[4108]={[52722]=1, [52721]=2, [52719]=4, [52555]=12},
+	[4109]={[53643]=3, [52326]=6},
+	[4110]={[54440]=1},
+	[4111]={[53643]=3, [52325]=6},
+	[4112]={[54440]=1},
+	[4113]={[38426]=2},
+	[4114]={[38426]=2},
+	[4115]={[38426]=2},
+	[4116]={[38426]=2},
+	[4118]={[38426]=2},
+	[4122]={[52976]=6, [52325]=4},
+	[4124]={[52976]=6, [52326]=4},
+	[4126]={[52979]=20, [52980]=1},
+	[4127]={[52980]=1, [52325]=20},
+	[4189]={[38426]=1},
+	[4190]={[38426]=1},
+	[4191]={[38426]=1},
+	[4192]={[38426]=1},
+	[4217]={[51950]=1},
+	[4227]={[52721]=3, [52719]=3, [52555]=3},
+	[4256]={[52722]=2, [52555]=6, [52327]=25},
+	[4257]={[52722]=2, [52326]=15, [52719]=4, [52555]=4},
+	[4258]={[52722]=2, [52555]=12, [52328]=15},
+	[4270]={[52980]=1, [52327]=20},
+	[4359]={[74249]=2},
+	[4360]={[74249]=2},
+	[4361]={[74249]=2},
+	[4411]={[74249]=4},
+	[4412]={[74249]=8, [74250]=2},
+	[4414]={[74248]=3},
+	[4415]={[74248]=3},
+	[4416]={[74248]=3},
+	[4417]={[74249]=3, [74250]=1},
+	[4418]={[74249]=4},
+	[4419]={[74249]=2, [74250]=3},
+	[4420]={[74249]=4, [74250]=1},
+	[4421]={[74249]=7},
+	[4422]={[74247]=2},
+	[4423]={[74249]=3, [74250]=3},
+	[4424]={[74250]=1},
+	[4426]={[74249]=2, [74250]=1},
+	[4427]={[74249]=2, [74250]=1},
+	[4428]={[74247]=2},
+	[4429]={[74249]=4, [74250]=3},
+	[4430]={[74249]=4},
+	[4431]={[74250]=2},
+	[4432]={[74249]=3, [74250]=1, [74247]=1},
+	[4433]={[74250]=3},
+	[4434]={[74250]=3},
+	[4441]={[74249]=12, [74247]=1},
+	[4442]={[74250]=4, [74248]=10},
+	[4443]={[74250]=3},
+	[4444]={[74249]=12, [74248]=10},
+	[4445]={[74247]=3},
+	[4446]={[74250]=50, [76138]=1},
+	[4699]={[72096]=27, [76131]=2, [76061]=1},
+	[4700]={[72096]=12, [76133]=2},
+	[4803]={[39354]=1, [79255]=3},
+	[4804]={[39354]=1, [79255]=3},
+	[4805]={[39354]=1, [79255]=3},
+	[4806]={[39354]=1, [79255]=3},
+	[4807]={[74249]=2},
+	[4822]={[72163]=1, [76061]=1},
+	[4823]={[72163]=1, [76061]=1},
+	[4824]={[72163]=1, [76061]=1},
+	[4825]={[82447]=1},
+	[4826]={[82447]=1},
+	[4869]={[72120]=4},
+	[4870]={[79101]=12},
+	[4871]={[72120]=12},
+	[4872]={[72120]=12},
+	[4873]={[38426]=1},
+	[4874]={[38426]=1},
+	[4875]={[38426]=1},
+	[4877]={[38426]=1},
+	[4878]={[38426]=1},
+	[4879]={[38426]=1},
+	[4880]={[38426]=1},
+	[4881]={[38426]=1},
+	[4882]={[38426]=1},
+	[4883]={[38426]=1},
+	[4884]={[38426]=1},
+	[4885]={[38426]=1},
+	[4886]={[38426]=1},
+	[4887]={[38426]=1},
+	[4888]={[38426]=1},
+	[4892]={[38426]=3},
+	[4893]={[38426]=3},
+	[4894]={[38426]=3},
+	[4895]={[38426]=3},
+	[4896]={[38426]=3},
+	[4907]={[39354]=1, [79254]=3},
+	[4908]={[39354]=1, [79254]=3},
+	[4909]={[39354]=1, [79254]=3},
+	[4910]={[39354]=1, [79254]=3},
+	[4912]={[39354]=1, [79254]=3},
+	[4913]={[39354]=1, [79254]=3},
+	[4914]={[39354]=1, [79254]=3},
+	[4915]={[39354]=1, [79254]=3},
+	[4918]={[72104]=1},
+	[4993]={[74250]=3, [74247]=1},
+	[5003]={[72988]=20},
+	[5004]={[72988]=20},
+	[5035]={[74249]=12, [74248]=10},
+	[5125]={[74249]=12, [74248]=10}}
+
+local enchantIconNames = {
+'ability_parry',
+'inv_belt_42',
+'inv_belt_42c',
+'inv_belt_robe_pvpmage_d_01',
+'inv_bracer_69',
+'inv_enchant_formulagood_01',
+'inv_enchant_formulasuperior_01',
+'inv_inscription_runescrolloffortitude_blue',
+'inv_inscription_runescrolloffortitude_yellow',
+'inv_misc_armorkit_08',
+'inv_misc_armorkit_26',
+'inv_misc_armorkit_28',
+'inv_misc_armorkit_29',
+'inv_misc_armorkit_mop_00',
+'inv_misc_armorkit_mop_01',
+'inv_misc_armorkit_mop_02',
+'inv_misc_armorkit_mop_04',
+'inv_misc_cataclysmarmorkit_01',
+'inv_misc_cataclysmarmorkit_02',
+'inv_misc_cataclysmarmorkit_08',
+'inv_misc_cataclysmarmorkit_10',
+'inv_misc_cataclysmarmorkit_11',
+'inv_misc_cataclysmarmorkit_12',
+'inv_misc_enggizmos_37',
+'inv_misc_gem_bloodstone_02',
+'inv_misc_gem_crystal_01',
+'inv_misc_gem_emeraldrough_02',
+'inv_misc_gem_goldendraenite_01',
+'inv_misc_mastersinscription',
+'inv_misc_monsterscales_14',
+'inv_misc_monsterscales_20',
+'inv_misc_note_01',
+'inv_misc_pelt_10',
+'inv_misc_pelt_11',
+'inv_misc_pelt_12',
+'inv_misc_pelt_13',
+'inv_misc_scopea',
+'inv_misc_scopeb',
+'inv_misc_scopec',
+'inv_misc_steelweaponchain',
+'inv_misc_thread_01',
+'inv_misc_thread_eternium',
+'inv_sword_130',
+'inv_sword_61',
+'item_spellcloththread',
+'spell_fire_masterofelements',
+'spell_frost_frostarmor',
+'spell_holy_greaterheal',
+'spell_holy_retributionaura',
+'spell_nature_astralrecal',
+'spell_nature_astralrecalgroup',
+'spell_shadow_chilltouch',
+'trade_engraving'}
+
+local enchantIconIndexes = {
+[-1000]=4,
+[1099]=48,
+[1597]=6,
+[3222]=48,
+[3246]=48,
+[3255]=51,
+[3260]=10,
+[3365]=1,
+[3368]=49,
+[3369]=52,
+[3370]=47,
+[3594]=1,
+[3722]=41,
+[3728]=41,
+[3730]=41,
+[3757]=33,
+[3758]=34,
+[3845]=6,
+[3847]=43,
+[3850]=7,
+[3873]=51,
+[3883]=44,
+[4061]=48,
+[4062]=48,
+[4063]=48,
+[4064]=48,
+[4065]=48,
+[4066]=48,
+[4067]=48,
+[4068]=48,
+[4069]=48,
+[4070]=48,
+[4071]=48,
+[4072]=48,
+[4073]=48,
+[4075]=48,
+[4076]=48,
+[4077]=48,
+[4078]=48,
+[4079]=48,
+[4080]=48,
+[4081]=48,
+[4082]=48,
+[4083]=48,
+[4084]=48,
+[4085]=48,
+[4086]=48,
+[4087]=48,
+[4088]=48,
+[4089]=48,
+[4090]=48,
+[4091]=48,
+[4092]=48,
+[4093]=48,
+[4094]=48,
+[4095]=48,
+[4096]=48,
+[4097]=6,
+[4098]=6,
+[4099]=6,
+[4100]=6,
+[4101]=6,
+[4102]=6,
+[4103]=6,
+[4104]=6,
+[4105]=6,
+[4106]=6,
+[4107]=6,
+[4108]=6,
+[4109]=50,
+[4110]=51,
+[4111]=45,
+[4112]=42,
+[4113]=51,
+[4114]=51,
+[4115]=41,
+[4116]=41,
+[4118]=41,
+[4122]=11,
+[4124]=13,
+[4126]=30,
+[4127]=31,
+[4175]=37,
+[4176]=39,
+[4177]=24,
+[4189]=33,
+[4190]=36,
+[4191]=35,
+[4192]=34,
+[4193]=29,
+[4194]=29,
+[4195]=29,
+[4196]=29,
+[4197]=26,
+[4198]=26,
+[4199]=25,
+[4200]=25,
+[4201]=27,
+[4202]=27,
+[4204]=28,
+[4205]=28,
+[4206]=46,
+[4207]=46,
+[4208]=46,
+[4209]=46,
+[4217]=40,
+[4227]=48,
+[4256]=7,
+[4257]=7,
+[4258]=7,
+[4267]=38,
+[4270]=20,
+[4359]=32,
+[4360]=32,
+[4361]=32,
+[4411]=32,
+[4412]=32,
+[4414]=7,
+[4415]=7,
+[4416]=7,
+[4417]=32,
+[4418]=32,
+[4419]=32,
+[4420]=32,
+[4421]=32,
+[4422]=32,
+[4423]=32,
+[4424]=32,
+[4426]=32,
+[4427]=32,
+[4428]=32,
+[4429]=32,
+[4430]=32,
+[4431]=32,
+[4432]=32,
+[4433]=32,
+[4434]=32,
+[4441]=7,
+[4442]=7,
+[4443]=7,
+[4444]=7,
+[4445]=7,
+[4446]=7,
+[4699]=38,
+[4700]=37,
+[4803]=9,
+[4804]=9,
+[4805]=9,
+[4806]=9,
+[4807]=32,
+[4822]=19,
+[4823]=17,
+[4824]=15,
+[4825]=2,
+[4826]=3,
+[4869]=12,
+[4870]=14,
+[4871]=18,
+[4872]=16,
+[4873]=36,
+[4874]=35,
+[4875]=36,
+[4877]=34,
+[4878]=33,
+[4879]=35,
+[4880]=23,
+[4881]=22,
+[4882]=21,
+[4883]=23,
+[4884]=21,
+[4885]=22,
+[4886]=23,
+[4887]=21,
+[4888]=22,
+[4892]=41,
+[4893]=41,
+[4894]=41,
+[4895]=51,
+[4896]=51,
+[4907]=8,
+[4908]=8,
+[4909]=8,
+[4910]=8,
+[4912]=29,
+[4913]=29,
+[4914]=29,
+[4915]=29,
+[4918]=40,
+[4993]=48,
+[5003]=42,
+[5004]=5,
+[5035]=53,
+[5125]=7}
+-- return 'none', the name of the enchant, or 'unknown (id)'
+function AskMrRobot.getEnchantName(enchantId)
+	if enchantId == 0 then return 'none' end	
+	local enchantName = enchantNames[enchantId]
+	if not enchantName then return 'unknown (' .. enchantId .. ')' end
+	return enchantName
+end   
+               
+-- return the spell id, if we have it, otherwise nil
+function AskMrRobot.getEnchantSpellId(enchantId)
+	if not enchantId then return nil end
+	return enchantSpellIds[enchantId]
+end
+
+-- return the item id, if we have it, otherwise nil
+function AskMrRobot.getEnchantItemId(enchantId)
+	if not enchantId then return nil end
+	return enchantItemIds[enchantId]
+end
+
+-- return the enchant icon, if we have it, otherwise nil
+function AskMrRobot.getEnchantIcon(enchantId)
+	if not enchantId then return nil end
+	local index = enchantIconIndexes[enchantId]
+	if not index then return nil end
+	return enchantIconNames[index]
+end
+
+-- material list -> itemId -> count
+function AskMrRobot.addEnchantMaterials(materialList, enchantId)
+    local materials = enchantMaterials[enchantId]
+    if materials then
+        for materialId, count in pairs(materials) do
+            local existingCount = materialList[materialId]
+            if existingCount then
+            	existingCount.total = existingCount.total + count
+            else
+            	materialList[materialId] = {count = 0, total = count}
+            end
+        end
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gems.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,3094 @@
+local _, AskMrRobot = ...
+
+local gemToColor = {
+[22459]="Prismatic",
+[22460]="Prismatic",
+[23094]="Red",
+[23095]="Red",
+[23096]="Red",
+[23097]="Red",
+[23098]="Orange",
+[23099]="Orange",
+[23100]="Purple",
+[23101]="Orange",
+[23103]="Green",
+[23104]="Green",
+[23105]="Green",
+[23106]="Purple",
+[23108]="Purple",
+[23109]="Purple",
+[23110]="Purple",
+[23111]="Purple",
+[23113]="Red",
+[23114]="Yellow",
+[23115]="Yellow",
+[23116]="Blue",
+[23118]="Blue",
+[23119]="Blue",
+[23120]="Blue",
+[23121]="Blue",
+[23233]="Red",
+[23234]="Blue",
+[23235]="Yellow",
+[24027]="Red",
+[24028]="Red",
+[24029]="Red",
+[24030]="Red",
+[24031]="Red",
+[24032]="Yellow",
+[24033]="Blue",
+[24035]="Blue",
+[24036]="Red",
+[24037]="Blue",
+[24039]="Blue",
+[24047]="Red",
+[24048]="Yellow",
+[24050]="Yellow",
+[24051]="Blue",
+[24052]="Yellow",
+[24053]="Yellow",
+[24054]="Purple",
+[24055]="Purple",
+[24056]="Purple",
+[24057]="Purple",
+[24058]="Orange",
+[24059]="Orange",
+[24060]="Orange",
+[24061]="Purple",
+[24062]="Green",
+[24065]="Purple",
+[24066]="Green",
+[24067]="Green",
+[25890]="Meta",
+[25893]="Meta",
+[25894]="Meta",
+[25895]="Meta",
+[25896]="Meta",
+[25897]="Meta",
+[25898]="Meta",
+[25899]="Meta",
+[25901]="Meta",
+[27679]="Yellow",
+[27777]="Red",
+[27785]="Green",
+[27786]="Green",
+[27809]="Green",
+[27812]="Red",
+[27820]="Green",
+[27863]="Blue",
+[27864]="Blue",
+[28118]="Red",
+[28119]="Yellow",
+[28120]="Yellow",
+[28123]="Orange",
+[28290]="Yellow",
+[28360]="Red",
+[28361]="Red",
+[28362]="Red",
+[28363]="Orange",
+[28458]="Red",
+[28459]="Red",
+[28460]="Red",
+[28461]="Red",
+[28462]="Red",
+[28463]="Blue",
+[28464]="Blue",
+[28465]="Blue",
+[28466]="Red",
+[28467]="Yellow",
+[28468]="Blue",
+[28469]="Yellow",
+[28470]="Yellow",
+[28556]="Meta",
+[28557]="Meta",
+[28595]="Red",
+[30546]="Purple",
+[30547]="Orange",
+[30548]="Green",
+[30549]="Purple",
+[30550]="Green",
+[30551]="Orange",
+[30552]="Purple",
+[30553]="Purple",
+[30554]="Orange",
+[30555]="Purple",
+[30556]="Purple",
+[30558]="Orange",
+[30559]="Purple",
+[30560]="Green",
+[30563]="Green",
+[30564]="Purple",
+[30565]="Green",
+[30566]="Purple",
+[30571]="Red",
+[30572]="Purple",
+[30573]="Purple",
+[30574]="Purple",
+[30575]="Green",
+[30581]="Orange",
+[30582]="Orange",
+[30583]="Purple",
+[30584]="Orange",
+[30585]="Orange",
+[30586]="Purple",
+[30587]="Orange",
+[30588]="Orange",
+[30589]="Purple",
+[30590]="Green",
+[30591]="Orange",
+[30592]="Green",
+[30593]="Orange",
+[30594]="Green",
+[30598]="Red",
+[30600]="Purple",
+[30601]="Green",
+[30602]="Green",
+[30603]="Purple",
+[30604]="Orange",
+[30605]="Green",
+[30606]="Green",
+[30607]="Orange",
+[30608]="Green",
+[31116]="Purple",
+[31117]="Purple",
+[31118]="Purple",
+[31860]="Blue",
+[31861]="Blue",
+[31862]="Purple",
+[31863]="Purple",
+[31864]="Purple",
+[31865]="Purple",
+[31866]="Purple",
+[31867]="Purple",
+[31868]="Orange",
+[31869]="Orange",
+[32193]="Red",
+[32194]="Red",
+[32195]="Red",
+[32196]="Red",
+[32197]="Red",
+[32198]="Yellow",
+[32199]="Red",
+[32200]="Blue",
+[32201]="Blue",
+[32202]="Blue",
+[32203]="Blue",
+[32204]="Red",
+[32205]="Yellow",
+[32206]="Blue",
+[32207]="Yellow",
+[32208]="Yellow",
+[32209]="Yellow",
+[32210]="Blue",
+[32211]="Purple",
+[32212]="Purple",
+[32213]="Purple",
+[32214]="Purple",
+[32215]="Purple",
+[32216]="Purple",
+[32217]="Orange",
+[32218]="Orange",
+[32219]="Orange",
+[32220]="Purple",
+[32221]="Purple",
+[32222]="Orange",
+[32223]="Green",
+[32224]="Green",
+[32225]="Purple",
+[32226]="Green",
+[32409]="Meta",
+[32410]="Meta",
+[32634]="Purple",
+[32635]="Purple",
+[32636]="Purple",
+[32637]="Orange",
+[32638]="Orange",
+[32639]="Green",
+[32640]="Meta",
+[32641]="Meta",
+[32735]="Red",
+[32833]="Purple",
+[32836]="Purple",
+[33060]="Yellow",
+[33131]="Red",
+[33132]="Red",
+[33133]="Red",
+[33134]="Red",
+[33135]="Blue",
+[33137]="Blue",
+[33138]="Yellow",
+[33139]="Red",
+[33140]="Yellow",
+[33141]="Blue",
+[33142]="Yellow",
+[33143]="Yellow",
+[33144]="Yellow",
+[33782]="Green",
+[34220]="Meta",
+[34256]="Blue",
+[34831]="Blue",
+[34967]="Yellow",
+[35315]="Yellow",
+[35316]="Orange",
+[35318]="Green",
+[35487]="Red",
+[35488]="Red",
+[35489]="Red",
+[35501]="Meta",
+[35503]="Meta",
+[35707]="Green",
+[35758]="Green",
+[35759]="Green",
+[35760]="Orange",
+[35761]="Yellow",
+[36766]="Red",
+[36767]="Blue",
+[37430]="Blue",
+[37503]="Purple",
+[38292]="Red",
+[38545]="Red",
+[38546]="Yellow",
+[38547]="Orange",
+[38548]="Orange",
+[38549]="Red",
+[38550]="Yellow",
+[39900]="Red",
+[39905]="Red",
+[39906]="Red",
+[39907]="Yellow",
+[39908]="Red",
+[39909]="Yellow",
+[39910]="Red",
+[39911]="Red",
+[39912]="Red",
+[39914]="Yellow",
+[39915]="Blue",
+[39916]="Yellow",
+[39917]="Yellow",
+[39918]="Yellow",
+[39919]="Blue",
+[39920]="Blue",
+[39927]="Blue",
+[39932]="Blue",
+[39933]="Green",
+[39934]="Purple",
+[39935]="Purple",
+[39936]="Purple",
+[39937]="Purple",
+[39938]="Green",
+[39939]="Purple",
+[39940]="Purple",
+[39941]="Purple",
+[39942]="Purple",
+[39943]="Purple",
+[39944]="Purple",
+[39945]="Purple",
+[39946]="Orange",
+[39947]="Orange",
+[39948]="Purple",
+[39949]="Orange",
+[39950]="Orange",
+[39951]="Orange",
+[39952]="Orange",
+[39953]="Purple",
+[39954]="Orange",
+[39955]="Orange",
+[39956]="Orange",
+[39957]="Purple",
+[39958]="Orange",
+[39959]="Orange",
+[39960]="Orange",
+[39961]="Purple",
+[39962]="Orange",
+[39963]="Orange",
+[39964]="Orange",
+[39965]="Orange",
+[39966]="Purple",
+[39967]="Orange",
+[39968]="Purple",
+[39974]="Green",
+[39975]="Green",
+[39976]="Green",
+[39977]="Green",
+[39978]="Green",
+[39979]="Purple",
+[39980]="Green",
+[39981]="Green",
+[39982]="Green",
+[39983]="Green",
+[39984]="Purple",
+[39985]="Green",
+[39986]="Green",
+[39988]="Green",
+[39989]="Green",
+[39990]="Green",
+[39991]="Green",
+[39992]="Green",
+[39996]="Red",
+[39997]="Red",
+[39998]="Red",
+[39999]="Red",
+[40000]="Yellow",
+[40001]="Red",
+[40002]="Yellow",
+[40003]="Red",
+[40008]="Blue",
+[40009]="Blue",
+[40010]="Blue",
+[40011]="Blue",
+[40012]="Red",
+[40013]="Yellow",
+[40014]="Blue",
+[40015]="Yellow",
+[40016]="Yellow",
+[40017]="Yellow",
+[40022]="Purple",
+[40023]="Purple",
+[40024]="Purple",
+[40025]="Purple",
+[40026]="Purple",
+[40027]="Purple",
+[40028]="Purple",
+[40029]="Purple",
+[40030]="Purple",
+[40031]="Green",
+[40032]="Purple",
+[40033]="Green",
+[40034]="Purple",
+[40037]="Orange",
+[40038]="Purple",
+[40039]="Orange",
+[40040]="Orange",
+[40041]="Orange",
+[40043]="Orange",
+[40044]="Purple",
+[40045]="Orange",
+[40046]="Orange",
+[40047]="Orange",
+[40048]="Orange",
+[40049]="Purple",
+[40050]="Orange",
+[40051]="Orange",
+[40052]="Orange",
+[40053]="Purple",
+[40054]="Orange",
+[40055]="Orange",
+[40056]="Orange",
+[40057]="Orange",
+[40058]="Purple",
+[40059]="Orange",
+[40085]="Purple",
+[40086]="Green",
+[40088]="Green",
+[40089]="Green",
+[40090]="Green",
+[40091]="Green",
+[40092]="Purple",
+[40094]="Purple",
+[40095]="Green",
+[40096]="Green",
+[40098]="Green",
+[40099]="Green",
+[40100]="Green",
+[40101]="Green",
+[40102]="Green",
+[40103]="Green",
+[40104]="Green",
+[40105]="Green",
+[40106]="Green",
+[40111]="Red",
+[40112]="Red",
+[40113]="Red",
+[40114]="Red",
+[40115]="Yellow",
+[40116]="Red",
+[40117]="Yellow",
+[40118]="Red",
+[40119]="Blue",
+[40120]="Blue",
+[40121]="Blue",
+[40122]="Blue",
+[40123]="Red",
+[40124]="Yellow",
+[40125]="Blue",
+[40126]="Yellow",
+[40127]="Yellow",
+[40128]="Yellow",
+[40129]="Purple",
+[40130]="Purple",
+[40131]="Purple",
+[40132]="Purple",
+[40133]="Purple",
+[40134]="Purple",
+[40135]="Purple",
+[40136]="Purple",
+[40137]="Purple",
+[40138]="Green",
+[40139]="Purple",
+[40140]="Green",
+[40141]="Purple",
+[40142]="Orange",
+[40143]="Purple",
+[40144]="Orange",
+[40145]="Orange",
+[40146]="Orange",
+[40147]="Orange",
+[40148]="Purple",
+[40149]="Orange",
+[40150]="Orange",
+[40151]="Purple",
+[40152]="Orange",
+[40153]="Purple",
+[40154]="Orange",
+[40155]="Orange",
+[40156]="Orange",
+[40157]="Purple",
+[40158]="Orange",
+[40159]="Orange",
+[40160]="Orange",
+[40161]="Orange",
+[40162]="Purple",
+[40163]="Orange",
+[40164]="Purple",
+[40165]="Green",
+[40166]="Green",
+[40167]="Green",
+[40168]="Green",
+[40169]="Green",
+[40170]="Purple",
+[40171]="Green",
+[40172]="Green",
+[40173]="Green",
+[40174]="Green",
+[40175]="Purple",
+[40176]="Green",
+[40177]="Green",
+[40178]="Green",
+[40179]="Green",
+[40180]="Green",
+[40181]="Green",
+[40182]="Green",
+[41285]="Meta",
+[41307]="Meta",
+[41333]="Meta",
+[41335]="Meta",
+[41339]="Meta",
+[41375]="Meta",
+[41376]="Meta",
+[41377]="Meta",
+[41378]="Meta",
+[41379]="Meta",
+[41380]="Meta",
+[41381]="Meta",
+[41382]="Meta",
+[41385]="Meta",
+[41389]="Meta",
+[41395]="Meta",
+[41396]="Meta",
+[41397]="Meta",
+[41398]="Meta",
+[41400]="Meta",
+[41401]="Meta",
+[41429]="Orange",
+[41432]="Red",
+[41433]="Red",
+[41434]="Red",
+[41435]="Red",
+[41436]="Yellow",
+[41437]="Red",
+[41438]="Red",
+[41439]="Yellow",
+[41440]="Blue",
+[41441]="Blue",
+[41442]="Blue",
+[41443]="Blue",
+[41444]="Red",
+[41445]="Yellow",
+[41446]="Yellow",
+[41447]="Blue",
+[41448]="Yellow",
+[41449]="Yellow",
+[41450]="Purple",
+[41451]="Purple",
+[41452]="Purple",
+[41453]="Purple",
+[41454]="Purple",
+[41455]="Purple",
+[41456]="Green",
+[41457]="Purple",
+[41458]="Green",
+[41459]="Purple",
+[41460]="Purple",
+[41461]="Purple",
+[41462]="Purple",
+[41463]="Purple",
+[41464]="Green",
+[41465]="Green",
+[41466]="Green",
+[41467]="Green",
+[41468]="Green",
+[41469]="Green",
+[41470]="Green",
+[41471]="Green",
+[41472]="Green",
+[41473]="Purple",
+[41474]="Green",
+[41475]="Green",
+[41476]="Green",
+[41477]="Green",
+[41478]="Green",
+[41479]="Purple",
+[41480]="Green",
+[41481]="Green",
+[41482]="Purple",
+[41483]="Orange",
+[41484]="Orange",
+[41485]="Orange",
+[41486]="Orange",
+[41487]="Orange",
+[41488]="Purple",
+[41489]="Orange",
+[41490]="Orange",
+[41491]="Purple",
+[41492]="Orange",
+[41493]="Orange",
+[41494]="Purple",
+[41495]="Orange",
+[41496]="Purple",
+[41497]="Orange",
+[41498]="Orange",
+[41499]="Orange",
+[41500]="Orange",
+[41501]="Orange",
+[41502]="Purple",
+[42142]="Red",
+[42143]="Red",
+[42144]="Red",
+[42145]="Blue",
+[42146]="Blue",
+[42148]="Red",
+[42149]="Yellow",
+[42150]="Yellow",
+[42151]="Yellow",
+[42152]="Red",
+[42153]="Yellow",
+[42154]="Red",
+[42155]="Blue",
+[42156]="Blue",
+[42157]="Yellow",
+[42158]="Yellow",
+[42701]="Prismatic",
+[42702]="Prismatic",
+[44066]="Yellow",
+[44076]="Meta",
+[44078]="Meta",
+[44081]="Meta",
+[44082]="Meta",
+[44084]="Meta",
+[44087]="Meta",
+[44088]="Meta",
+[44089]="Meta",
+[45862]="Red",
+[45879]="Red",
+[45880]="Blue",
+[45881]="Blue",
+[45882]="Red",
+[45883]="Red",
+[45987]="Blue",
+[49110]="Prismatic",
+[52070]="Purple",
+[52081]="Red",
+[52082]="Red",
+[52083]="Red",
+[52084]="Red",
+[52085]="Red",
+[52086]="Blue",
+[52087]="Blue",
+[52088]="Blue",
+[52089]="Blue",
+[52090]="Yellow",
+[52091]="Yellow",
+[52092]="Yellow",
+[52093]="Yellow",
+[52094]="Yellow",
+[52095]="Purple",
+[52096]="Purple",
+[52097]="Purple",
+[52098]="Purple",
+[52099]="Purple",
+[52100]="Purple",
+[52101]="Purple",
+[52102]="Purple",
+[52103]="Purple",
+[52104]="Purple",
+[52105]="Purple",
+[52106]="Orange",
+[52107]="Orange",
+[52108]="Orange",
+[52109]="Orange",
+[52110]="Orange",
+[52111]="Orange",
+[52112]="Orange",
+[52113]="Orange",
+[52114]="Orange",
+[52115]="Orange",
+[52116]="Orange",
+[52117]="Orange",
+[52118]="Orange",
+[52119]="Green",
+[52120]="Green",
+[52121]="Green",
+[52122]="Green",
+[52123]="Green",
+[52124]="Green",
+[52125]="Green",
+[52126]="Green",
+[52127]="Green",
+[52128]="Green",
+[52129]="Green",
+[52130]="Green",
+[52131]="Green",
+[52132]="Green",
+[52133]="Green",
+[52134]="Green",
+[52135]="Green",
+[52136]="Green",
+[52137]="Green",
+[52138]="Green",
+[52139]="Orange",
+[52140]="Orange",
+[52141]="Orange",
+[52142]="Orange",
+[52143]="Orange",
+[52144]="Orange",
+[52145]="Orange",
+[52146]="Orange",
+[52147]="Orange",
+[52148]="Orange",
+[52149]="Orange",
+[52150]="Orange",
+[52151]="Orange",
+[52152]="Purple",
+[52153]="Purple",
+[52154]="Purple",
+[52155]="Purple",
+[52156]="Purple",
+[52157]="Purple",
+[52158]="Purple",
+[52159]="Purple",
+[52160]="Purple",
+[52161]="Purple",
+[52162]="Purple",
+[52163]="Yellow",
+[52164]="Yellow",
+[52165]="Yellow",
+[52166]="Yellow",
+[52167]="Yellow",
+[52168]="Blue",
+[52169]="Blue",
+[52170]="Blue",
+[52171]="Blue",
+[52172]="Red",
+[52173]="Red",
+[52174]="Red",
+[52175]="Red",
+[52176]="Red",
+[52203]="Purple",
+[52204]="Orange",
+[52205]="Orange",
+[52206]="Red",
+[52207]="Red",
+[52208]="Orange",
+[52209]="Orange",
+[52210]="Purple",
+[52211]="Orange",
+[52212]="Red",
+[52213]="Purple",
+[52214]="Orange",
+[52215]="Orange",
+[52216]="Red",
+[52217]="Purple",
+[52218]="Green",
+[52219]="Yellow",
+[52220]="Purple",
+[52221]="Purple",
+[52222]="Orange",
+[52223]="Green",
+[52224]="Orange",
+[52225]="Green",
+[52226]="Yellow",
+[52227]="Green",
+[52228]="Green",
+[52229]="Orange",
+[52230]="Red",
+[52231]="Green",
+[52232]="Yellow",
+[52233]="Green",
+[52234]="Purple",
+[52235]="Blue",
+[52236]="Purple",
+[52237]="Green",
+[52238]="Purple",
+[52239]="Orange",
+[52240]="Orange",
+[52241]="Yellow",
+[52242]="Blue",
+[52243]="Purple",
+[52244]="Blue",
+[52245]="Green",
+[52246]="Blue",
+[52247]="Yellow",
+[52248]="Purple",
+[52249]="Orange",
+[52250]="Green",
+[52255]="Red",
+[52257]="Red",
+[52258]="Red",
+[52259]="Red",
+[52260]="Red",
+[52261]="Blue",
+[52262]="Blue",
+[52263]="Blue",
+[52264]="Blue",
+[52265]="Yellow",
+[52266]="Yellow",
+[52267]="Yellow",
+[52268]="Yellow",
+[52269]="Yellow",
+[52289]="Meta",
+[52291]="Meta",
+[52292]="Meta",
+[52293]="Meta",
+[52294]="Meta",
+[52295]="Meta",
+[52296]="Meta",
+[52297]="Meta",
+[52298]="Meta",
+[52299]="Meta",
+[52300]="Meta",
+[52301]="Meta",
+[52302]="Meta",
+[54616]="Red",
+[59477]="Cogwheel",
+[59478]="Cogwheel",
+[59479]="Cogwheel",
+[59480]="Cogwheel",
+[59489]="Cogwheel",
+[59491]="Cogwheel",
+[59493]="Cogwheel",
+[59496]="Cogwheel",
+[63696]="Red",
+[63697]="Red",
+[68356]="Orange",
+[68357]="Orange",
+[68358]="Orange",
+[68660]="Cogwheel",
+[68741]="Green",
+[68778]="Meta",
+[68779]="Meta",
+[68780]="Meta",
+[69922]="Red",
+[69923]="Red",
+[71817]="Blue",
+[71818]="Blue",
+[71819]="Blue",
+[71820]="Blue",
+[71822]="Green",
+[71823]="Green",
+[71824]="Green",
+[71825]="Green",
+[71826]="Green",
+[71827]="Green",
+[71828]="Green",
+[71829]="Green",
+[71830]="Green",
+[71831]="Green",
+[71832]="Green",
+[71833]="Green",
+[71834]="Green",
+[71835]="Green",
+[71836]="Green",
+[71837]="Green",
+[71838]="Green",
+[71839]="Green",
+[71840]="Orange",
+[71841]="Orange",
+[71842]="Orange",
+[71843]="Orange",
+[71844]="Orange",
+[71845]="Orange",
+[71846]="Orange",
+[71847]="Orange",
+[71848]="Orange",
+[71849]="Orange",
+[71850]="Orange",
+[71851]="Orange",
+[71852]="Orange",
+[71853]="Orange",
+[71854]="Orange",
+[71855]="Orange",
+[71856]="Orange",
+[71857]="Orange",
+[71858]="Orange",
+[71859]="Orange",
+[71860]="Orange",
+[71861]="Orange",
+[71862]="Purple",
+[71863]="Purple",
+[71864]="Purple",
+[71865]="Purple",
+[71866]="Purple",
+[71867]="Purple",
+[71868]="Purple",
+[71869]="Purple",
+[71870]="Purple",
+[71871]="Purple",
+[71872]="Purple",
+[71873]="Purple",
+[71874]="Yellow",
+[71875]="Yellow",
+[71876]="Yellow",
+[71877]="Yellow",
+[71878]="Yellow",
+[71879]="Red",
+[71880]="Red",
+[71881]="Red",
+[71882]="Red",
+[71883]="Red",
+[76502]="Blue",
+[76504]="Blue",
+[76505]="Blue",
+[76506]="Blue",
+[76507]="Green",
+[76508]="Green",
+[76509]="Green",
+[76510]="Green",
+[76511]="Green",
+[76512]="Green",
+[76513]="Green",
+[76514]="Green",
+[76515]="Green",
+[76517]="Green",
+[76518]="Green",
+[76519]="Green",
+[76520]="Green",
+[76521]="Green",
+[76522]="Green",
+[76523]="Green",
+[76524]="Green",
+[76525]="Green",
+[76526]="Orange",
+[76527]="Orange",
+[76528]="Orange",
+[76529]="Orange",
+[76530]="Orange",
+[76531]="Orange",
+[76532]="Orange",
+[76533]="Orange",
+[76534]="Orange",
+[76535]="Orange",
+[76536]="Orange",
+[76537]="Orange",
+[76538]="Orange",
+[76539]="Orange",
+[76540]="Orange",
+[76541]="Orange",
+[76542]="Orange",
+[76543]="Orange",
+[76544]="Orange",
+[76545]="Orange",
+[76546]="Orange",
+[76547]="Orange",
+[76548]="Purple",
+[76549]="Purple",
+[76550]="Purple",
+[76551]="Purple",
+[76552]="Purple",
+[76553]="Purple",
+[76554]="Purple",
+[76555]="Purple",
+[76556]="Purple",
+[76557]="Purple",
+[76558]="Purple",
+[76559]="Purple",
+[76560]="Red",
+[76561]="Red",
+[76562]="Red",
+[76563]="Red",
+[76564]="Red",
+[76565]="Yellow",
+[76566]="Yellow",
+[76567]="Yellow",
+[76568]="Yellow",
+[76569]="Yellow",
+[76570]="Blue",
+[76571]="Blue",
+[76572]="Blue",
+[76573]="Blue",
+[76574]="Green",
+[76575]="Green",
+[76576]="Green",
+[76577]="Green",
+[76578]="Green",
+[76579]="Green",
+[76580]="Green",
+[76581]="Green",
+[76582]="Green",
+[76583]="Green",
+[76584]="Green",
+[76585]="Green",
+[76586]="Green",
+[76587]="Green",
+[76588]="Green",
+[76589]="Green",
+[76590]="Green",
+[76591]="Green",
+[76592]="Orange",
+[76593]="Orange",
+[76594]="Orange",
+[76595]="Orange",
+[76596]="Orange",
+[76597]="Orange",
+[76598]="Orange",
+[76599]="Orange",
+[76600]="Orange",
+[76601]="Orange",
+[76602]="Orange",
+[76603]="Orange",
+[76604]="Orange",
+[76605]="Orange",
+[76606]="Orange",
+[76607]="Orange",
+[76608]="Orange",
+[76609]="Orange",
+[76610]="Orange",
+[76611]="Orange",
+[76612]="Orange",
+[76613]="Orange",
+[76614]="Purple",
+[76615]="Purple",
+[76616]="Purple",
+[76617]="Purple",
+[76618]="Purple",
+[76619]="Purple",
+[76620]="Purple",
+[76621]="Purple",
+[76622]="Purple",
+[76623]="Purple",
+[76624]="Purple",
+[76625]="Purple",
+[76626]="Red",
+[76627]="Red",
+[76628]="Red",
+[76629]="Red",
+[76630]="Red",
+[76631]="Yellow",
+[76632]="Yellow",
+[76633]="Yellow",
+[76634]="Yellow",
+[76635]="Yellow",
+[76636]="Blue",
+[76637]="Blue",
+[76638]="Blue",
+[76639]="Blue",
+[76640]="Green",
+[76641]="Green",
+[76642]="Green",
+[76643]="Green",
+[76644]="Green",
+[76645]="Green",
+[76646]="Green",
+[76647]="Green",
+[76648]="Green",
+[76649]="Green",
+[76650]="Green",
+[76651]="Green",
+[76652]="Green",
+[76653]="Green",
+[76654]="Green",
+[76655]="Green",
+[76656]="Green",
+[76657]="Green",
+[76658]="Orange",
+[76659]="Orange",
+[76660]="Orange",
+[76661]="Orange",
+[76662]="Orange",
+[76663]="Orange",
+[76664]="Orange",
+[76665]="Orange",
+[76666]="Orange",
+[76667]="Orange",
+[76668]="Orange",
+[76669]="Orange",
+[76670]="Orange",
+[76671]="Orange",
+[76672]="Orange",
+[76673]="Orange",
+[76674]="Orange",
+[76675]="Orange",
+[76676]="Orange",
+[76677]="Orange",
+[76678]="Orange",
+[76679]="Orange",
+[76680]="Purple",
+[76681]="Purple",
+[76682]="Purple",
+[76683]="Purple",
+[76684]="Purple",
+[76685]="Purple",
+[76686]="Purple",
+[76687]="Purple",
+[76688]="Purple",
+[76689]="Purple",
+[76690]="Purple",
+[76691]="Purple",
+[76692]="Red",
+[76693]="Red",
+[76694]="Red",
+[76695]="Red",
+[76696]="Red",
+[76697]="Yellow",
+[76698]="Yellow",
+[76699]="Yellow",
+[76700]="Yellow",
+[76701]="Yellow",
+[76879]="Meta",
+[76884]="Meta",
+[76885]="Meta",
+[76886]="Meta",
+[76887]="Meta",
+[76888]="Meta",
+[76890]="Meta",
+[76891]="Meta",
+[76892]="Meta",
+[76893]="Meta",
+[76894]="Meta",
+[76895]="Meta",
+[76896]="Meta",
+[76897]="Meta",
+[77130]="Green",
+[77131]="Green",
+[77132]="Orange",
+[77133]="Purple",
+[77134]="Yellow",
+[77136]="Orange",
+[77137]="Green",
+[77138]="Orange",
+[77139]="Green",
+[77140]="Blue",
+[77141]="Orange",
+[77142]="Green",
+[77143]="Green",
+[77144]="Orange",
+[77154]="Green",
+[77540]="Cogwheel",
+[77541]="Cogwheel",
+[77542]="Cogwheel",
+[77543]="Cogwheel",
+[77544]="Cogwheel",
+[77545]="Cogwheel",
+[77546]="Cogwheel",
+[77547]="Cogwheel",
+[83141]="Red",
+[83142]="Yellow",
+[83143]="Yellow",
+[83144]="Blue",
+[83145]="Yellow",
+[83146]="Yellow",
+[83147]="Red",
+[83148]="Blue",
+[83149]="Blue",
+[83150]="Red",
+[83151]="Red",
+[83152]="Red",
+[88911]="Green",
+[88912]="Green",
+[88913]="Green",
+[88914]="Green",
+[88915]="Green",
+[88916]="Green",
+[88917]="Green",
+[88918]="Green",
+[88919]="Green",
+[88920]="Green",
+[88921]="Green",
+[88922]="Green",
+[88923]="Green",
+[88924]="Green",
+[88925]="Green",
+[88926]="Green",
+[88927]="Green",
+[88928]="Green",
+[88930]="Orange",
+[88931]="Orange",
+[88932]="Orange",
+[88933]="Orange",
+[88934]="Orange",
+[88935]="Orange",
+[88936]="Orange",
+[88937]="Orange",
+[88938]="Orange",
+[88939]="Orange",
+[88940]="Orange",
+[88941]="Orange",
+[88942]="Orange",
+[88943]="Orange",
+[88944]="Orange",
+[88945]="Orange",
+[88946]="Orange",
+[88947]="Orange",
+[88948]="Orange",
+[88949]="Orange",
+[88950]="Orange",
+[88951]="Orange",
+[88952]="Purple",
+[88953]="Purple",
+[88954]="Purple",
+[88955]="Purple",
+[88956]="Purple",
+[88958]="Purple",
+[88959]="Purple",
+[88960]="Purple",
+[88961]="Purple",
+[88962]="Purple",
+[88963]="Purple",
+[88987]="Purple",
+[89674]="Purple",
+[89675]="Purple",
+[89676]="Purple",
+[89677]="Purple",
+[89678]="Purple",
+[89679]="Purple",
+[89680]="Purple",
+[89681]="Purple",
+[89873]="Hydraulic",
+[89881]="Hydraulic",
+[89882]="Hydraulic",
+[93364]="Hydraulic",
+[93365]="Hydraulic",
+[93366]="Hydraulic",
+[93404]="Orange",
+[93405]="Orange",
+[93406]="Orange",
+[93408]="Purple",
+[93409]="Purple",
+[93410]="Purple",
+[93705]="Green",
+[93706]="Green",
+[93707]="Green",
+[93708]="Green",
+[95344]="Meta",
+[95345]="Meta",
+[95346]="Meta",
+[95347]="Meta",
+[95348]="Meta"}
+
+AskMrRobot.alternateGemName = {
+[23094]="6 Int",
+[23095]="6 Str",
+[23096]="7 Int",
+[23097]="6 Agi",
+[23098]="3 Str, 6 Crit",
+[23099]="3 Int, 6 Haste",
+[23100]="3 Agi, 6 Hit",
+[23101]="6 Int, 3 Crit",
+[23103]="3 PvP Pow, 6 Crit",
+[23104]="4 Stam, 6 Crit",
+[23105]="4 Stam, 6 Dodge",
+[23106]="3 Int, 6 Spirit",
+[23108]="3 Int, 4 Stam",
+[23109]="3 Int, 6 Spirit",
+[23110]="3 Agi, 4 Stam",
+[23111]="3 Str, 4 Stam",
+[23113]="6 Int",
+[23114]="12 Crit",
+[23115]="12 Dodge",
+[23116]="12 Hit",
+[23118]="9 Stam",
+[23119]="12 Spirit",
+[23120]="6 PvP Pow",
+[23121]="12 Spirit",
+[23233]="8 Str",
+[23234]="8 Agi",
+[23235]="8 Stam",
+[24027]="8 Str",
+[24028]="8 Agi",
+[24029]="8 Int",
+[24030]="8 Int",
+[24031]="8 Agi",
+[24032]="16 Dodge",
+[24033]="12 Stam",
+[24035]="16 Spirit",
+[24036]="16 Parry",
+[24037]="16 Spirit",
+[24039]="8 PvP Pow",
+[24047]="8 Int",
+[24048]="16 Crit",
+[24050]="16 Crit",
+[24051]="16 Hit",
+[24052]="16 Dodge",
+[24053]="8 Resil",
+[24054]="4 Str, 6 Stam",
+[24055]="4 Agi, 6 Stam",
+[24056]="5 Int, 6 Stam",
+[24057]="4 Int, 8 Spirit",
+[24058]="8 Str, 4 Crit",
+[24059]="4 Int, 8 Crit",
+[24060]="4 Int, 8 Haste",
+[24061]="4 Agi, 8 Hit",
+[24062]="6 Stam, 8 Dodge",
+[24065]="4 Int, 8 Spirit",
+[24066]="4 PvP Pow, 8 Crit",
+[24067]="6 Stam, 8 Crit",
+[25890]="28 Crit, 1% Reflect",
+[25894]="24 Crit",
+[25895]="24 Crit, Snare",
+[25896]="18 Stam, Stun",
+[25897]="12 Int, 2% Threat",
+[25898]="24 Dodge",
+[25901]="12 Int",
+[27679]="10 Resil",
+[27777]="7 Int",
+[27785]="3 Stam, 4 Crit",
+[27786]="3 Stam, 4 Crit",
+[27809]="3 Stam, 4 Crit",
+[27812]="7 Int",
+[27820]="3 Stam, 4 Crit",
+[28118]="10 Int",
+[28119]="10 Crit",
+[28120]="10 Crit",
+[28123]="5 Int, 5 Crit",
+[28290]="12 Crit",
+[28360]="7 Agi",
+[28361]="7 Agi",
+[28362]="10 Agi",
+[28363]="5 Agi, 5 Crit",
+[28458]="4 Str",
+[28459]="4 Agi",
+[28460]="4 Int",
+[28461]="4 Int",
+[28462]="4 Agi",
+[28463]="6 Stam",
+[28464]="8 Spirit",
+[28465]="8 Spirit",
+[28466]="4 Int",
+[28467]="8 Crit",
+[28468]="8 Hit",
+[28469]="8 Crit",
+[28470]="8 Dodge",
+[28556]="10 Crit",
+[28557]="10 Int",
+[28595]="6 Agi",
+[30546]="5 Str, 6 Stam",
+[30547]="5 Int, 4 Haste",
+[30548]="6 Stam, 10 Crit",
+[30549]="5 Agi, 6 Stam",
+[30550]="10 Crit, 8 Spirit",
+[30551]="5 Int, 4 Haste",
+[30552]="5 Int, 6 Stam",
+[30553]="5 Agi, 4 Hit",
+[30554]="5 Parry, 4 Dodge",
+[30555]="5 Int, 6 Stam",
+[30556]="5 Agi, 4 Hit",
+[30558]="5 Parry, 4 Dodge",
+[30559]="5 Str, 4 Hit",
+[30560]="5 Crit, 4 Spirit",
+[30563]="6 Stam, 5 Dodge",
+[30564]="5 Int, 4 Hit",
+[30565]="6 Stam, 5 Crit",
+[30566]="6 Stam, 5 Parry",
+[30571]="8 Str",
+[30572]="5 Int, 10 Spirit",
+[30573]="5 Int, 5 PvP Pow",
+[30574]="5 Agi, 6 Stam",
+[30575]="5 Dodge, 4 Hit",
+[30581]="5 Int, 4 Resil",
+[30582]="5 Agi, 4 Crit",
+[30583]="5 Int, 6 Stam",
+[30584]="5 Str, 4 Crit",
+[30585]="4 Agi, 5 Dodge",
+[30586]="5 Int, 4 Spirit",
+[30587]="5 Str, 4 Dodge",
+[30588]="5 Int, 4 Crit",
+[30589]="5 Int, 4 Spirit",
+[30590]="6 Stam, 5 Dodge",
+[30591]="5 Agi, 4 Resil",
+[30592]="6 Stam, 5 Resil",
+[30593]="5 Int, 4 Crit",
+[30594]="6 Stam, 5 Dodge",
+[30598]="8 Str",
+[30600]="5 Int, 4 Spirit",
+[30601]="5 Resil, 6 Stam",
+[30602]="6 Stam, 5 Crit",
+[30603]="5 Int, 8 Spirit",
+[30604]="5 Str, 4 Resil",
+[30605]="10 Hit, 8 Dodge",
+[30606]="10 Hit, 8 Haste",
+[30607]="4 Resil, 5 Parry",
+[30608]="5 PvP Pow, 5 Crit",
+[31116]="5 Int, 6 Stam",
+[31117]="5 Int, 6 Stam",
+[31118]="5 Str, 6 Stam",
+[31860]="12 Hit",
+[31861]="16 Hit",
+[31862]="3 Agi, 4 Stam",
+[31863]="4 Agi, 6 Stam",
+[31864]="3 Agi, 4 Stam",
+[31865]="4 Agi, 8 Hit",
+[31866]="3 Int, 6 Hit",
+[31867]="4 Int, 8 Hit",
+[31868]="4 Agi, 8 Crit",
+[31869]="6 Agi, 3 Crit",
+[32193]="10 Str",
+[32194]="10 Agi",
+[32195]="10 Int",
+[32196]="10 Int",
+[32197]="20 Agi",
+[32198]="20 Dodge",
+[32199]="20 Parry",
+[32200]="15 Stam",
+[32201]="20 Spirit",
+[32202]="20 Spirit",
+[32203]="10 PvP Pow",
+[32204]="10 Int",
+[32205]="20 Crit",
+[32206]="20 Hit",
+[32207]="20 Crit",
+[32208]="20 Dodge",
+[32209]="10 Resil",
+[32210]="20 Hit",
+[32211]="5 Str, 7 Stam",
+[32212]="5 Agi, 7 Stam",
+[32213]="5 Agi, 7 Stam",
+[32214]="5 Agi, 10 Hit",
+[32215]="5 Int, 7 Stam",
+[32216]="5 Int, 10 Spirit",
+[32217]="5 Str, 10 Crit",
+[32218]="5 Int, 10 Crit",
+[32219]="5 Int, 10 Haste",
+[32220]="5 Agi, 10 Hit",
+[32221]="5 Int, 10 Hit",
+[32222]="5 Agi, 10 Crit",
+[32223]="7 Stam, 10 Dodge",
+[32224]="5 PvP Pow, 10 Crit",
+[32225]="5 Int, 10 Spirit",
+[32226]="7 Stam, 10 Crit",
+[32409]="12 Agi",
+[32634]="5 Agi, 6 Stam",
+[32635]="4 Int, 6 Stam",
+[32636]="5 Int, 4 Spirit",
+[32637]="5 Agi, 8 Crit",
+[32638]="5 Int, 4 Haste",
+[32639]="4 Stam, 4 Crit",
+[32640]="12 Crit",
+[32641]="12 Int",
+[32735]="10 Agi",
+[32833]="3 Int, 6 Spirit",
+[32836]="4 Int, 8 Spirit",
+[33060]="8 Agi",
+[33131]="12 Agi",
+[33132]="12 Agi",
+[33133]="12 Int",
+[33134]="12 Int",
+[33135]="18 Stam",
+[33137]="24 Spirit",
+[33138]="12 Resil",
+[33139]="12 Int",
+[33140]="24 Crit",
+[33141]="24 Hit",
+[33142]="24 Hit",
+[33143]="24 Crit",
+[33144]="24 Dodge",
+[33782]="4 Resil, 6 Stam",
+[34220]="24 Crit, 3% Crit Efct",
+[34256]="15 Stam",
+[34831]="15 Stam",
+[35315]="16 Haste",
+[35316]="4 Int, 8 Haste",
+[35318]="6 Stam, 8 Haste",
+[35487]="10 Agi",
+[35488]="10 Int",
+[35489]="10 Int",
+[35501]="24 Dodge, 1% Block",
+[35503]="12 Int, 2% Mana",
+[35707]="6 Stam, 4 Dodge",
+[35758]="5 Resil, 7 Stam",
+[35759]="7 Stam, 5 Haste",
+[35760]="5 Int, 10 Haste",
+[35761]="20 Haste",
+[36766]="34 Agi",
+[36767]="51 Stam",
+[37430]="24 Stam",
+[37503]="5 Int, 10 Spirit",
+[38292]="150 Armor",
+[38545]="10 Agi",
+[38546]="10 Crit",
+[38547]="5 Agi, 5 Crit",
+[38548]="5 Int, 5 Crit",
+[38549]="10 Int",
+[38550]="10 Crit",
+[39900]="12 Str",
+[39905]="12 Agi",
+[39906]="12 Agi",
+[39907]="24 Dodge",
+[39908]="24 Parry",
+[39909]="24 Crit",
+[39910]="24 Exp",
+[39911]="12 Int",
+[39912]="12 Int",
+[39914]="24 Crit",
+[39915]="24 Hit",
+[39916]="24 Dodge",
+[39917]="12 Resil",
+[39918]="24 Haste",
+[39919]="18 Stam",
+[39920]="24 Spirit",
+[39927]="24 Spirit",
+[39932]="12 PvP Pow",
+[39933]="9 Stam, 12 Crit",
+[39934]="6 Str, 9 Stam",
+[39935]="6 Agi, 9 Stam",
+[39936]="6 Int, 9 Stam",
+[39937]="6 Agi, 9 Stam",
+[39938]="9 Stam, 12 Dodge",
+[39939]="9 Stam, 12 Parry",
+[39940]="9 Stam, 12 Exp",
+[39941]="6 Int, 12 Spirit",
+[39942]="6 Agi, 12 Hit",
+[39943]="6 Int, 12 Spirit",
+[39944]="6 Agi, 12 Hit",
+[39945]="6 Int, 6 PvP Pow",
+[39946]="6 Int, 12 Haste",
+[39947]="6 Str, 12 Crit",
+[39948]="6 Str, 12 Hit",
+[39949]="6 Str, 12 Dodge",
+[39950]="6 Str, 6 Resil",
+[39951]="6 Str, 12 Haste",
+[39952]="6 Agi, 12 Crit",
+[39953]="6 Agi, 12 Hit",
+[39954]="6 Agi, 6 Resil",
+[39955]="6 Agi, 12 Haste",
+[39956]="6 Int, 12 Crit",
+[39957]="6 Int, 12 Hit",
+[39958]="6 Int, 6 Resil",
+[39959]="6 Int, 12 Haste",
+[39960]="6 Agi, 12 Crit",
+[39961]="6 Agi, 12 Hit",
+[39962]="6 Agi, 6 Resil",
+[39963]="6 Agi, 12 Haste",
+[39964]="12 Dodge, 12 Parry",
+[39965]="12 Parry, 12 Dodge",
+[39966]="12 Exp, 12 Hit",
+[39967]="12 Exp, 12 Dodge",
+[39968]="6 Int, 9 Stam",
+[39974]="9 Stam, 12 Crit",
+[39975]="12 Hit, 12 Dodge",
+[39976]="9 Stam, 12 Dodge",
+[39977]="6 Resil, 9 Stam",
+[39978]="9 Stam, 12 Haste",
+[39979]="6 Int, 12 Spirit",
+[39980]="12 Crit, 12 Spirit",
+[39981]="12 Hit, 12 Haste",
+[39982]="6 Resil, 12 Spirit",
+[39983]="12 Haste, 12 Spirit",
+[39984]="6 Int, 12 Spirit",
+[39985]="12 Crit, 12 Spirit",
+[39986]="12 Hit, 12 Haste",
+[39988]="6 Resil, 12 Spirit",
+[39989]="12 Haste, 12 Spirit",
+[39990]="6 PvP Pow, 12 Crit",
+[39991]="6 PvP Pow, 12 Crit",
+[39992]="6 PvP Pow, 12 Haste",
+[39996]="16 Str",
+[39997]="16 Agi",
+[39998]="16 Int",
+[39999]="16 Agi",
+[40000]="32 Dodge",
+[40001]="32 Parry",
+[40002]="32 Crit",
+[40003]="32 Exp",
+[40008]="24 Stam",
+[40009]="32 Spirit",
+[40010]="32 Spirit",
+[40011]="16 PvP Pow",
+[40012]="16 Int",
+[40013]="32 Crit",
+[40014]="32 Hit",
+[40015]="32 Dodge",
+[40016]="16 Resil",
+[40017]="32 Haste",
+[40022]="8 Str, 12 Stam",
+[40023]="8 Agi, 12 Stam",
+[40024]="8 Agi, 16 Hit",
+[40025]="8 Int, 12 Stam",
+[40026]="8 Int, 16 Spirit",
+[40027]="8 Int, 16 Spirit",
+[40028]="8 Int, 8 PvP Pow",
+[40029]="8 Agi, 12 Stam",
+[40030]="8 Agi, 16 Hit",
+[40031]="12 Stam, 16 Dodge",
+[40032]="12 Stam, 16 Parry",
+[40033]="12 Stam, 16 Crit",
+[40034]="12 Stam, 16 Exp",
+[40037]="8 Str, 16 Crit",
+[40038]="8 Str, 16 Hit",
+[40039]="8 Str, 16 Dodge",
+[40040]="8 Str, 8 Resil",
+[40041]="8 Str, 16 Haste",
+[40043]="8 Agi, 16 Crit",
+[40044]="8 Agi, 16 Hit",
+[40045]="8 Agi, 8 Resil",
+[40046]="8 Agi, 16 Haste",
+[40047]="8 Int, 16 Haste",
+[40048]="8 Int, 16 Crit",
+[40049]="8 Int, 16 Hit",
+[40050]="8 Int, 8 Resil",
+[40051]="8 Int, 16 Haste",
+[40052]="8 Agi, 16 Crit",
+[40053]="8 Agi, 16 Hit",
+[40054]="8 Agi, 8 Resil",
+[40055]="8 Agi, 16 Haste",
+[40056]="16 Dodge, 16 Parry",
+[40057]="16 Parry, 16 Dodge",
+[40058]="16 Exp, 16 Hit",
+[40059]="16 Exp, 16 Dodge",
+[40085]="8 Int, 12 Stam",
+[40086]="12 Stam, 16 Crit",
+[40088]="16 Hit, 16 Dodge",
+[40089]="12 Stam, 16 Dodge",
+[40090]="8 Resil, 12 Stam",
+[40091]="12 Stam, 16 Haste",
+[40092]="8 Int, 16 Spirit",
+[40094]="8 Int, 16 Spirit",
+[40095]="16 Crit, 16 Spirit",
+[40096]="16 Crit, 16 Spirit",
+[40098]="8 PvP Pow, 16 Crit",
+[40099]="16 Hit, 16 Haste",
+[40100]="16 Hit, 16 Haste",
+[40101]="8 PvP Pow, 16 Crit",
+[40102]="8 Resil, 16 Spirit",
+[40103]="16 Resil, 8 Spirit",
+[40104]="16 Haste, 16 Spirit",
+[40105]="16 Haste, 16 Spirit",
+[40106]="8 PvP Pow, 16 Haste",
+[40111]="20 Str",
+[40112]="20 Agi",
+[40113]="20 Int",
+[40114]="20 Agi",
+[40115]="40 Dodge",
+[40116]="40 Parry",
+[40117]="40 Crit",
+[40118]="40 Exp",
+[40119]="30 Stam",
+[40120]="40 Spirit",
+[40121]="40 Spirit",
+[40122]="20 PvP Pow",
+[40123]="20 Int",
+[40124]="40 Crit",
+[40125]="40 Hit",
+[40126]="40 Dodge",
+[40127]="20 Resil",
+[40128]="40 Haste",
+[40129]="10 Str, 15 Stam",
+[40130]="10 Agi, 15 Stam",
+[40131]="10 Agi, 20 Hit",
+[40132]="10 Int, 15 Stam",
+[40133]="10 Int, 20 Spirit",
+[40134]="10 Int, 20 Spirit",
+[40135]="10 Int, 10 PvP Pow",
+[40136]="10 Agi, 15 Stam",
+[40137]="10 Agi, 20 Hit",
+[40138]="15 Stam, 20 Dodge",
+[40139]="15 Stam, 20 Parry",
+[40140]="15 Stam, 20 Crit",
+[40141]="15 Stam, 20 Exp",
+[40142]="10 Str, 20 Crit",
+[40143]="10 Str, 20 Hit",
+[40144]="10 Str, 20 Dodge",
+[40145]="10 Str, 10 Resil",
+[40146]="10 Str, 20 Haste",
+[40147]="10 Agi, 20 Crit",
+[40148]="10 Agi, 20 Hit",
+[40149]="10 Agi, 10 Resil",
+[40150]="10 Agi, 20 Haste",
+[40151]="10 Int, 20 Spirit",
+[40152]="10 Int, 20 Crit",
+[40153]="10 Int, 20 Hit",
+[40154]="10 Int, 10 Resil",
+[40155]="10 Int, 10 Haste",
+[40156]="10 Agi, 20 Crit",
+[40157]="10 Agi, 20 Hit",
+[40158]="10 Agi, 10 Resil",
+[40159]="10 Agi, 20 Haste",
+[40160]="20 Dodge, 20 Parry",
+[40161]="20 Parry, 20 Dodge",
+[40162]="20 Exp, 20 Hit",
+[40163]="20 Exp, 20 Dodge",
+[40164]="10 Int, 15 Stam",
+[40165]="15 Stam, 20 Crit",
+[40166]="20 Hit, 20 Dodge",
+[40167]="15 Stam, 20 Dodge",
+[40168]="10 Resil, 15 Stam",
+[40169]="15 Stam, 20 Haste",
+[40170]="10 Int, 20 Spirit",
+[40171]="20 Crit, 20 Spirit",
+[40172]="20 Hit, 20 Haste",
+[40173]="10 Resil, 20 Spirit",
+[40174]="20 Haste, 20 Spirit",
+[40175]="10 Int, 20 Spirit",
+[40176]="20 Crit, 20 Spirit",
+[40177]="20 Hit, 20 Haste",
+[40178]="10 Resil, 20 Spirit",
+[40179]="10 Haste, 20 Spirit",
+[40180]="10 PvP Pow, 20 Crit",
+[40181]="10 PvP Pow, 20 Crit",
+[40182]="10 PvP Pow, 20 Haste",
+[41285]="42 Crit, 3% Crit Efct",
+[41307]="50 Crit, 1% Reflect",
+[41333]="21 Int, 2% Mana",
+[41335]="42 Crit, Snare",
+[41339]="42 Crit",
+[41375]="21 Int",
+[41376]="42 Spirit, 3% Crit Efct",
+[41377]="32 Stam",
+[41378]="21 Int, Silence",
+[41379]="42 Crit, Fear",
+[41380]="32 Stam, 2% Armor",
+[41381]="42 Crit",
+[41382]="21 Int",
+[41385]="42 Haste",
+[41389]="42 Crit",
+[41395]="21 Int, 2% Threat",
+[41396]="42 Dodge, 1% Block",
+[41397]="32 Stam, Stun",
+[41398]="21 Agi",
+[41401]="21 Int",
+[41429]="7 Agi, 14 Crit",
+[41432]="14 Str",
+[41433]="14 Agi",
+[41434]="14 Agi",
+[41435]="28 Parry",
+[41436]="28 Crit",
+[41437]="28 Exp",
+[41438]="14 Int",
+[41439]="28 Dodge",
+[41440]="28 Spirit",
+[41441]="21 Stam",
+[41442]="28 Spirit",
+[41443]="14 PvP Pow",
+[41444]="14 Int",
+[41445]="14 Resil",
+[41446]="28 Haste",
+[41447]="28 Hit",
+[41448]="28 Crit",
+[41449]="28 Dodge",
+[41450]="7 Agi, 10 Stam",
+[41451]="10 Stam, 14 Parry",
+[41452]="7 Int, 10 Stam",
+[41453]="10 Stam, 14 Exp",
+[41454]="7 Agi, 14 Hit",
+[41455]="7 Int, 7 PvP Pow",
+[41456]="10 Stam, 14 Crit",
+[41457]="7 Int, 14 Spirit",
+[41458]="10 Stam, 14 Dodge",
+[41459]="7 Int, 14 Spirit",
+[41460]="7 Agi, 10 Stam",
+[41461]="7 Str, 10 Stam",
+[41462]="7 Agi, 14 Hit",
+[41463]="7 Int, 14 Spirit",
+[41464]="10 Stam, 14 Dodge",
+[41465]="14 Haste, 14 Spirit",
+[41466]="10 Stam, 14 Haste",
+[41467]="14 Haste, 14 Spirit",
+[41468]="10 Stam, 14 Crit",
+[41469]="14 Hit, 14 Haste",
+[41470]="14 Crit, 14 Spirit",
+[41471]="7 Resil, 14 Spirit",
+[41472]="7 PvP Pow, 14 Crit",
+[41473]="7 Int, 14 Spirit",
+[41474]="7 PvP Pow, 14 Haste",
+[41475]="14 Hit, 14 Haste",
+[41476]="7 Resil, 10 Stam",
+[41477]="14 Crit, 14 Spirit",
+[41478]="7 PvP Pow, 14 Crit",
+[41479]="7 Int, 10 Stam",
+[41480]="7 Resil, 14 Spirit",
+[41481]="14 Hit, 14 Dodge",
+[41482]="14 Exp, 14 Hit",
+[41483]="7 Str, 7 Dodge",
+[41484]="7 Agi, 14 Crit",
+[41485]="7 Agi, 14 Haste",
+[41486]="7 Int, 7 Resil",
+[41487]="7 Agi, 7 Resil",
+[41488]="7 Str, 14 Hit",
+[41489]="7 Str, 14 Haste",
+[41490]="14 Parry, 14 Dodge",
+[41491]="7 Agi, 14 Hit",
+[41492]="7 Str, 14 Crit",
+[41493]="7 Agi, 7 Resil",
+[41494]="7 Int, 14 Spirit",
+[41495]="7 Int, 14 Crit",
+[41496]="7 Agi, 14 Hit",
+[41497]="7 Int, 14 Haste",
+[41498]="14 Exp, 14 Dodge",
+[41499]="7 Str, 7 Resil",
+[41500]="14 Dodge, 14 Parry",
+[41501]="7 Agi, 14 Haste",
+[41502]="7 Int, 14 Hit",
+[42142]="34 Str",
+[42143]="34 Agi",
+[42144]="34 Int",
+[42145]="68 Spirit",
+[42146]="68 Spirit",
+[42148]="34 Int",
+[42149]="68 Crit",
+[42150]="68 Haste",
+[42151]="68 Dodge",
+[42152]="68 Parry",
+[42153]="68 Crit",
+[42154]="68 Exp",
+[42155]="34 PvP Pow",
+[42156]="68 Hit",
+[42157]="68 Dodge",
+[42158]="34 Resil",
+[42701]="12 Str, 12 Agi, 12 Stam, 12 Int, 12 Spirit",
+[42702]="64 Str, 64 Agi, 64 Stam, 64 Int, 64 Spirit",
+[44066]="20 Resil",
+[44076]="17 Crit",
+[44078]="17 Int",
+[44081]="17 Crit, Snare",
+[44082]="17 Crit, Fear",
+[44084]="17 Int, Silence",
+[44087]="17 Crit",
+[44088]="26 Stam, Stun",
+[44089]="17 Int",
+[45862]="20 Str",
+[45879]="20 Agi",
+[45880]="30 Stam",
+[45881]="40 Spirit",
+[45882]="20 Int",
+[45883]="20 Int",
+[45987]="40 Hit",
+[49110]="0 Str, 0 Agi, 0 Stam, 0 Int, 0 Spirit",
+[52070]="24 Stam, 24 Agi",
+[52081]="30 Str",
+[52082]="30 Agi",
+[52083]="60 Parry",
+[52084]="30 Int",
+[52085]="60 Exp",
+[52086]="45 Stam",
+[52087]="60 Spirit",
+[52088]="30 PvP Pow",
+[52089]="60 Hit",
+[52090]="60 Dodge",
+[52091]="60 Crit",
+[52092]="30 Resil",
+[52093]="60 Haste",
+[52094]="60 Mastery",
+[52095]="15 Str, 23 Stam",
+[52096]="15 Agi, 23 Stam",
+[52097]="23 Stam, 30 Parry",
+[52098]="15 Int, 23 Stam",
+[52099]="23 Stam, 30 Exp",
+[52100]="15 Int, 30 Spirit",
+[52101]="15 Str, 30 Hit",
+[52102]="15 Agi, 30 Hit",
+[52103]="30 Parry, 30 Hit",
+[52104]="15 Int, 30 Hit",
+[52105]="30 Exp, 30 Hit",
+[52106]="15 Agi, 30 Dodge",
+[52107]="30 Exp, 30 Dodge",
+[52108]="15 Str, 30 Crit",
+[52109]="15 Agi, 30 Crit",
+[52110]="15 Int, 30 Crit",
+[52111]="15 Str, 30 Haste",
+[52112]="15 Agi, 30 Haste",
+[52113]="15 Int, 30 Haste",
+[52114]="15 Str, 30 Mastery",
+[52115]="15 Agi, 30 Mastery",
+[52116]="30 Parry, 30 Mastery",
+[52117]="15 Int, 30 Mastery",
+[52118]="30 Exp, 30 Mastery",
+[52119]="23 Stam, 30 Dodge",
+[52120]="30 Dodge, 30 Hit",
+[52121]="23 Stam, 30 Crit",
+[52122]="30 Crit, 30 Hit",
+[52123]="15 Resil, 23 Stam",
+[52124]="23 Stam, 30 Haste",
+[52125]="30 Haste, 30 Hit",
+[52126]="23 Stam, 30 Mastery",
+[52127]="30 Mastery, 30 Spirit",
+[52128]="30 Mastery, 30 Hit",
+[52129]="35 Mastery, 35 Hit",
+[52130]="35 Mastery, 35 Spirit",
+[52131]="26 Stam, 35 Mastery",
+[52132]="35 Haste, 35 Hit",
+[52133]="26 Stam, 35 Haste",
+[52134]="18 Resil, 26 Stam",
+[52135]="35 Crit, 35 Hit",
+[52136]="26 Stam, 35 Crit",
+[52137]="35 Dodge, 35 Hit",
+[52138]="26 Stam, 35 Dodge",
+[52139]="35 Exp, 35 Mastery",
+[52140]="18 Int, 35 Mastery",
+[52141]="35 Parry, 35 Mastery",
+[52142]="18 Agi, 35 Mastery",
+[52143]="18 Str, 35 Mastery",
+[52144]="18 Int, 35 Haste",
+[52145]="18 Agi, 35 Haste",
+[52146]="18 Str, 35 Haste",
+[52147]="18 Int, 35 Crit",
+[52148]="18 Agi, 35 Crit",
+[52149]="18 Str, 35 Crit",
+[52150]="35 Exp, 35 Dodge",
+[52151]="18 Agi, 35 Dodge",
+[52152]="35 Exp, 35 Hit",
+[52153]="18 Int, 35 Hit",
+[52154]="35 Parry, 35 Hit",
+[52155]="17 Agi, 35 Hit",
+[52156]="18 Str, 35 Hit",
+[52157]="18 Int, 35 Spirit",
+[52158]="26 Stam, 35 Exp",
+[52159]="18 Int, 26 Stam",
+[52160]="26 Stam, 35 Parry",
+[52161]="18 Agi, 26 Stam",
+[52162]="18 Str, 26 Stam",
+[52163]="70 Mastery",
+[52164]="70 Haste",
+[52165]="35 Resil",
+[52166]="70 Crit",
+[52167]="70 Dodge",
+[52168]="70 Hit",
+[52169]="35 PvP Pow",
+[52170]="70 Spirit",
+[52171]="53 Stam",
+[52172]="70 Exp",
+[52173]="35 Int",
+[52174]="70 Parry",
+[52175]="35 Agi",
+[52176]="35 Str",
+[52203]="40 Exp, 40 Hit",
+[52204]="20 Agi, 40 Mastery",
+[52205]="20 Int, 40 Mastery",
+[52206]="40 Str",
+[52207]="40 Int",
+[52208]="20 Int, 40 Haste",
+[52209]="20 Agi, 40 Crit",
+[52210]="30 Stam, 40 Parry",
+[52211]="20 Agi, 40 Haste",
+[52212]="40 Agi",
+[52213]="20 Str, 40 Hit",
+[52214]="20 Str, 40 Haste",
+[52215]="40 Parry, 40 Mastery",
+[52216]="80 Parry",
+[52217]="20 Int, 40 Hit",
+[52218]="30 Stam, 40 Haste",
+[52219]="80 Mastery",
+[52220]="20 Agi, 40 Hit",
+[52221]="30 Stam, 40 Exp",
+[52222]="20 Str, 40 Crit",
+[52223]="30 Stam, 40 Crit",
+[52224]="40 Exp, 40 Mastery",
+[52225]="40 Haste, 40 Hit",
+[52226]="40 Resil",
+[52227]="40 Dodge, 40 Hit",
+[52228]="40 Crit, 40 Hit",
+[52229]="20 Agi, 40 Dodge",
+[52230]="80 Exp",
+[52231]="30 Stam, 20 Mastery",
+[52232]="80 Haste",
+[52233]="30 Stam, 40 Dodge",
+[52234]="40 Parry, 40 Hit",
+[52235]="80 Hit",
+[52236]="20 Int, 40 Spirit",
+[52237]="40 Mastery, 40 Hit",
+[52238]="20 Agi, 30 Stam",
+[52239]="20 Int, 40 Crit",
+[52240]="20 Str, 40 Mastery",
+[52241]="80 Crit",
+[52242]="60 Stam",
+[52243]="20 Str, 30 Stam",
+[52244]="80 Spirit",
+[52245]="20 Resil, 30 Stam",
+[52246]="40 PvP Pow",
+[52247]="80 Dodge",
+[52248]="20 Int, 30 Stam",
+[52249]="40 Exp, 40 Dodge",
+[52250]="40 Mastery, 40 Spirit",
+[52255]="67 Str",
+[52257]="67 Int",
+[52258]="67 Agi",
+[52259]="67 Parry",
+[52260]="134 Exp",
+[52261]="101 Stam",
+[52262]="134 Spirit",
+[52263]="67 PvP Pow",
+[52264]="134 Hit",
+[52265]="134 Dodge",
+[52266]="134 Crit",
+[52267]="67 Resil",
+[52268]="134 Haste",
+[52269]="134 Mastery",
+[52289]="108 Mastery, Run Speed",
+[52291]="108 Crit, 3% Crit Efct",
+[52292]="54 Int, 2% Threat",
+[52293]="81 Stam, 1% Block",
+[52294]="81 Stam, 2% Armor",
+[52295]="81 Stam",
+[52296]="54 Int, 2% Mana",
+[52297]="108 Spirit, 3% Crit Efct",
+[52298]="108 Crit, 1% Reflect",
+[52299]="81 Stam, Stun",
+[52300]="108 Crit, Snare",
+[52301]="108 Crit, Fear",
+[52302]="54 Int, Silence",
+[54616]="50 Str",
+[59477]="208 Dodge",
+[59478]="208 Crit",
+[59479]="208 Haste",
+[59480]="208 Mastery",
+[59489]="208 Exp",
+[59491]="208 Parry",
+[59493]="208 Hit",
+[59496]="208 Spirit",
+[63696]="7 Str",
+[63697]="7 Str",
+[68356]="20 Int, 20 Resil",
+[68357]="20 Agi, 20 Resil",
+[68358]="20 Str, 20 Resil",
+[68660]="52 Resil",
+[68741]="20 Resil, 20 PvP Pow",
+[68778]="54 Agi, 3% Crit Efct",
+[68779]="54 Str, 3% Crit Efct",
+[68780]="54 Int, 3% Crit Efct",
+[69922]="50 Int",
+[69923]="50 Agi",
+[71817]="100 Hit",
+[71818]="100 PvP Pow",
+[71819]="100 Spirit",
+[71820]="75 Stam",
+[71822]="50 Spirit, 50 Crit",
+[71823]="50 Crit, 50 Hit",
+[71824]="50 Haste, 50 Hit",
+[71825]="50 Hit, 50 Mastery",
+[71826]="25 PvP Pow, 50 Mastery",
+[71827]="50 Spirit, 50 Mastery",
+[71828]="25 Resil, 50 Hit",
+[71829]="25 PvP Pow, 25 Resil",
+[71830]="25 Resil, 50 Spirit",
+[71831]="25 PvP Pow, 50 Crit",
+[71832]="25 PvP Pow, 50 Haste",
+[71833]="50 Haste, 50 Spirit",
+[71834]="37 Stam, 50 Crit",
+[71835]="37 Stam, 50 Dodge",
+[71836]="37 Stam, 50 Haste",
+[71837]="50 Hit, 50 Dodge",
+[71838]="37 Stam, 50 Mastery",
+[71839]="25 Resil, 37 Stam",
+[71840]="25 Agi, 50 Crit",
+[71841]="50 Exp, 50 Crit",
+[71842]="25 Int, 50 Crit",
+[71843]="25 Str, 50 Crit",
+[71844]="25 Agi, 50 Dodge",
+[71845]="50 Exp, 50 Dodge",
+[71846]="50 Parry, 50 Dodge",
+[71847]="25 Str, 50 Dodge",
+[71848]="25 Agi, 50 Haste",
+[71849]="50 Exp, 50 Haste",
+[71850]="25 Int, 50 Haste",
+[71851]="25 Str, 50 Haste",
+[71852]="25 Agi, 50 Mastery",
+[71853]="50 Exp, 50 Mastery",
+[71854]="25 Int, 50 Mastery",
+[71855]="50 Parry, 50 Mastery",
+[71856]="25 Str, 50 Mastery",
+[71857]="25 Agi, 25 Resil",
+[71858]="25 Resil, 50 Exp",
+[71859]="25 Int, 25 Resil",
+[71860]="25 Resil, 50 Parry",
+[71861]="25 Str, 25 Resil",
+[71862]="25 Agi, 50 Hit",
+[71863]="50 Exp, 50 Hit",
+[71864]="25 Int, 50 Hit",
+[71865]="50 Parry, 50 Hit",
+[71866]="25 Str, 50 Hit",
+[71867]="25 Int, 25 PvP Pow",
+[71868]="25 Int, 50 Spirit",
+[71869]="25 Agi, 37 Stam",
+[71870]="37 Stam, 50 Exp",
+[71871]="25 Int, 37 Stam",
+[71872]="37 Stam, 50 Parry",
+[71873]="25 Str, 37 Stam",
+[71874]="100 Crit",
+[71875]="100 Dodge",
+[71876]="100 Haste",
+[71877]="100 Mastery",
+[71878]="50 Resil",
+[71879]="50 Agi",
+[71880]="100 Exp",
+[71881]="50 Int",
+[71882]="100 Parry",
+[71883]="50 Str",
+[76502]="240 Hit",
+[76504]="120 PvP Pow",
+[76505]="240 Spirit",
+[76506]="180 Stam",
+[76507]="120 Spirit, 120 Crit",
+[76508]="120 Crit, 120 Hit",
+[76509]="120 Haste, 120 Hit",
+[76510]="120 Hit, 120 Mastery",
+[76511]="60 PvP Pow, 120 Mastery",
+[76512]="120 Spirit, 120 Mastery",
+[76513]="60 Resil, 120 Hit",
+[76514]="60 PvP Pow, 60 Resil",
+[76515]="60 Resil, 120 Spirit",
+[76517]="60 PvP Pow, 120 Crit",
+[76518]="60 PvP Pow, 120 Haste",
+[76519]="120 Haste, 120 Spirit",
+[76520]="90 Stam, 120 Crit",
+[76521]="90 Stam, 120 Dodge",
+[76522]="90 Stam, 120 Haste",
+[76523]="90 Stam, 120 Hit",
+[76524]="90 Stam, 120 Mastery",
+[76525]="60 Resil, 90 Stam",
+[76526]="60 Agi, 120 Crit",
+[76527]="120 Exp, 120 Crit",
+[76528]="60 Int, 120 Crit",
+[76529]="60 Str, 120 Crit",
+[76530]="60 Agi, 120 Dodge",
+[76531]="120 Exp, 120 Dodge",
+[76532]="120 Parry, 120 Dodge",
+[76533]="60 Str, 120 Dodge",
+[76534]="60 Agi, 120 Haste",
+[76535]="120 Exp, 120 Haste",
+[76536]="60 Int, 120 Haste",
+[76537]="60 Str, 120 Haste",
+[76538]="60 Agi, 120 Mastery",
+[76539]="120 Exp, 120 Mastery",
+[76540]="60 Int, 120 Mastery",
+[76541]="120 Parry, 120 Mastery",
+[76542]="60 Str, 120 Mastery",
+[76543]="60 Agi, 60 Resil",
+[76544]="60 Resil, 120 Exp",
+[76545]="60 Int, 60 Resil",
+[76546]="60 Resil, 120 Parry",
+[76547]="60 Str, 60 Resil",
+[76548]="60 Agi, 120 Hit",
+[76549]="120 Exp, 120 Hit",
+[76550]="60 Int, 120 Hit",
+[76551]="120 Parry, 120 Hit",
+[76552]="60 Str, 120 Hit",
+[76553]="60 Int, 60 PvP Pow",
+[76554]="60 Int, 120 Spirit",
+[76555]="60 Agi, 90 Stam",
+[76556]="90 Stam, 120 Exp",
+[76557]="60 Int, 90 Stam",
+[76558]="90 Stam, 120 Parry",
+[76559]="60 Str, 90 Stam",
+[76560]="120 Agi",
+[76561]="240 Exp",
+[76562]="120 Int",
+[76563]="240 Parry",
+[76564]="120 Str",
+[76565]="240 Crit",
+[76566]="240 Dodge",
+[76567]="240 Haste",
+[76568]="240 Mastery",
+[76569]="120 Resil",
+[76570]="320 Hit",
+[76571]="160 PvP Pow",
+[76572]="320 Spirit",
+[76573]="240 Stam",
+[76574]="160 Spirit, 160 Crit",
+[76575]="160 Crit, 160 Hit",
+[76576]="160 Haste, 160 Hit",
+[76577]="160 Hit, 160 Mastery",
+[76578]="80 PvP Pow, 160 Mastery",
+[76579]="160 Spirit, 160 Mastery",
+[76580]="80 Resil, 160 Hit",
+[76581]="80 PvP Pow, 80 Resil",
+[76582]="80 Resil, 160 Spirit",
+[76583]="80 PvP Pow, 160 Crit",
+[76584]="80 PvP Pow, 160 Haste",
+[76585]="160 Haste, 160 Spirit",
+[76586]="120 Stam, 160 Crit",
+[76587]="120 Stam, 160 Dodge",
+[76588]="120 Stam, 160 Haste",
+[76589]="120 Stam, 160 Hit",
+[76590]="120 Stam, 160 Mastery",
+[76591]="80 Resil, 120 Stam",
+[76592]="80 Agi, 160 Crit",
+[76593]="160 Exp, 160 Crit",
+[76594]="80 Int, 160 Crit",
+[76595]="80 Str, 160 Crit",
+[76596]="80 Agi, 160 Dodge",
+[76597]="160 Exp, 160 Dodge",
+[76598]="160 Parry, 160 Dodge",
+[76599]="80 Str, 160 Dodge",
+[76600]="80 Agi, 160 Haste",
+[76601]="160 Exp, 160 Haste",
+[76602]="80 Int, 160 Haste",
+[76603]="80 Str, 160 Haste",
+[76604]="80 Agi, 160 Mastery",
+[76605]="160 Exp, 160 Mastery",
+[76606]="80 Int, 160 Mastery",
+[76607]="160 Parry, 160 Mastery",
+[76608]="80 Str, 160 Mastery",
+[76609]="80 Agi, 80 Resil",
+[76610]="80 Resil, 160 Exp",
+[76611]="80 Int, 80 Resil",
+[76612]="80 Resil, 160 Parry",
+[76613]="80 Str, 80 Resil",
+[76614]="80 Agi, 160 Hit",
+[76615]="160 Exp, 160 Hit",
+[76616]="80 Int, 160 Hit",
+[76617]="160 Parry, 160 Hit",
+[76618]="80 Str, 160 Hit",
+[76619]="80 Int, 80 PvP Pow",
+[76620]="80 Int, 160 Spirit",
+[76621]="80 Agi, 120 Stam",
+[76622]="120 Stam, 160 Exp",
+[76623]="80 Int, 120 Stam",
+[76624]="120 Stam, 160 Parry",
+[76625]="80 Str, 120 Stam",
+[76626]="160 Agi",
+[76627]="320 Exp",
+[76628]="160 Int",
+[76629]="320 Parry",
+[76630]="160 Str",
+[76631]="320 Crit",
+[76632]="320 Dodge",
+[76633]="320 Haste",
+[76634]="320 Mastery",
+[76635]="160 Resil",
+[76636]="320 Hit",
+[76637]="160 PvP Pow",
+[76638]="320 Spirit",
+[76639]="240 Stam",
+[76640]="160 Spirit, 160 Crit",
+[76641]="160 Crit, 160 Hit",
+[76642]="160 Haste, 160 Hit",
+[76643]="160 Hit, 160 Mastery",
+[76644]="80 PvP Pow, 160 Mastery",
+[76645]="160 Spirit, 160 Mastery",
+[76646]="80 Resil, 160 Hit",
+[76647]="80 PvP Pow, 80 Resil",
+[76648]="80 Resil, 160 Spirit",
+[76649]="80 PvP Pow, 160 Crit",
+[76650]="80 PvP Pow, 160 Haste",
+[76651]="160 Haste, 160 Spirit",
+[76652]="120 Stam, 160 Crit",
+[76653]="120 Stam, 160 Dodge",
+[76654]="120 Stam, 160 Haste",
+[76655]="120 Stam, 160 Hit",
+[76656]="120 Stam, 160 Mastery",
+[76657]="80 Resil, 120 Stam",
+[76658]="80 Agi, 160 Crit",
+[76659]="160 Exp, 160 Crit",
+[76660]="80 Int, 160 Crit",
+[76661]="80 Str, 160 Crit",
+[76662]="80 Agi, 160 Dodge",
+[76663]="160 Exp, 160 Dodge",
+[76664]="160 Parry, 160 Dodge",
+[76665]="80 Str, 160 Dodge",
+[76666]="80 Agi, 160 Haste",
+[76667]="160 Exp, 160 Haste",
+[76668]="80 Int, 160 Haste",
+[76669]="80 Str, 160 Haste",
+[76670]="80 Agi, 160 Mastery",
+[76671]="160 Exp, 160 Mastery",
+[76672]="80 Int, 160 Mastery",
+[76673]="160 Parry, 160 Mastery",
+[76674]="80 Str, 160 Mastery",
+[76675]="80 Agi, 80 Resil",
+[76676]="80 Resil, 160 Exp",
+[76677]="80 Int, 80 Resil",
+[76678]="80 Resil, 160 Parry",
+[76679]="80 Str, 80 Resil",
+[76680]="80 Agi, 160 Hit",
+[76681]="160 Exp, 160 Hit",
+[76682]="80 Int, 160 Hit",
+[76683]="160 Parry, 160 Hit",
+[76684]="80 Str, 160 Hit",
+[76685]="80 Int, 80 PvP Pow",
+[76686]="80 Int, 160 Spirit",
+[76687]="80 Agi, 120 Stam",
+[76688]="120 Stam, 160 Exp",
+[76689]="80 Int, 120 Stam",
+[76690]="120 Stam, 160 Parry",
+[76691]="80 Str, 120 Stam",
+[76692]="160 Agi",
+[76693]="320 Exp",
+[76694]="160 Int",
+[76695]="320 Parry",
+[76696]="160 Str",
+[76697]="320 Crit",
+[76698]="320 Dodge",
+[76699]="320 Haste",
+[76700]="320 Mastery",
+[76701]="160 Resil",
+[76879]="216 Int, 2% Mana",
+[76884]="216 Agi, 3% Crit Efct",
+[76885]="216 Int, 3% Crit Efct",
+[76886]="216 Str, 3% Crit Efct",
+[76887]="432 Mastery, Run Speed",
+[76888]="432 Spirit, 3% Crit Efct",
+[76890]="432 Crit, 1% Reflect",
+[76891]="324 Stam, Stun",
+[76892]="432 Crit, Snare",
+[76893]="432 Crit, Fear",
+[76894]="216 Int, Silence",
+[76895]="324 Stam, 2% Armor",
+[76896]="432 Dodge, 1% Block",
+[76897]="324 Stam",
+[77130]="25 Resil, 50 Hit",
+[77131]="25 PvP Pow, 50 Mastery",
+[77132]="25 Agi, 25 Resil",
+[77133]="25 Int, 25 PvP Pow",
+[77134]="50 Resil",
+[77136]="25 Str, 25 Resil",
+[77137]="25 PvP Pow, 50 Haste",
+[77138]="25 Resil, 50 Parry",
+[77139]="25 Resil, 37 Stam",
+[77140]="50 PvP Pow",
+[77141]="25 Resil, 50 Exp",
+[77142]="25 Resil, 50 Spirit",
+[77143]="25 PvP Pow, 25 Resil",
+[77144]="25 Int, 25 Resil",
+[77154]="25 PvP Pow, 50 Crit",
+[77540]="600 Dodge",
+[77541]="600 Crit",
+[77542]="600 Haste",
+[77543]="600 Exp",
+[77544]="600 Parry",
+[77545]="600 Hit",
+[77546]="600 Spirit",
+[77547]="600 Mastery",
+[83141]="320 Str",
+[83142]="480 Haste",
+[83143]="480 Mastery",
+[83144]="480 Hit",
+[83145]="480 Dodge",
+[83146]="480 Crit",
+[83147]="480 Exp",
+[83148]="480 Stam",
+[83149]="480 Spirit",
+[83150]="320 Int",
+[83151]="320 Agi",
+[83152]="480 Parry",
+[88911]="100 Resil, 200 Hit",
+[88912]="100 PvP Pow, 200 Mastery",
+[88913]="200 Haste, 200 Spirit",
+[88914]="150 Stam, 200 Haste",
+[88915]="150 Stam, 200 Crit",
+[88916]="200 Haste, 200 Hit",
+[88917]="200 Spirit, 200 Crit",
+[88918]="150 Stam, 200 Hit",
+[88919]="200 Crit, 200 Hit",
+[88920]="150 Stam, 200 Mastery",
+[88921]="100 PvP Pow, 200 Crit",
+[88922]="150 Stam, 200 Dodge",
+[88923]="200 Hit, 200 Mastery",
+[88924]="100 PvP Pow, 200 Haste",
+[88925]="100 Resil, 150 Stam",
+[88926]="100 Resil, 200 Spirit",
+[88927]="100 PvP Pow, 100 Resil",
+[88928]="200 Spirit, 200 Mastery",
+[88930]="100 Agi, 200 Mastery",
+[88931]="100 Int, 200 Mastery",
+[88932]="100 Str, 200 Dodge",
+[88933]="200 Exp, 200 Crit",
+[88934]="100 Agi, 200 Crit",
+[88935]="100 Agi, 200 Haste",
+[88936]="100 Str, 200 Haste",
+[88937]="200 Parry, 200 Mastery",
+[88938]="100 Str, 200 Crit",
+[88939]="200 Exp, 200 Mastery",
+[88940]="100 Agi, 100 Resil",
+[88941]="100 Agi, 200 Dodge",
+[88942]="100 Int, 200 Crit",
+[88943]="100 Int, 200 Haste",
+[88944]="200 Exp, 200 Dodge",
+[88945]="100 Str, 100 Resil",
+[88946]="100 Str, 200 Mastery",
+[88947]="100 Resil, 200 Parry",
+[88948]="200 Parry, 200 Dodge",
+[88949]="100 Resil, 200 Exp",
+[88950]="200 Exp, 200 Haste",
+[88951]="100 Int, 100 Resil",
+[88952]="200 Exp, 200 Hit",
+[88953]="150 Stam, 200 Parry",
+[88954]="100 Str, 200 Hit",
+[88955]="100 Agi, 200 Hit",
+[88956]="150 Stam, 200 Exp",
+[88958]="100 Int, 200 Spirit",
+[88959]="200 Parry, 200 Hit",
+[88960]="100 Agi, 150 Stam",
+[88961]="100 Str, 150 Stam",
+[88962]="100 Int, 150 Stam",
+[88963]="100 Int, 200 Hit",
+[88987]="100 Int, 100 PvP Pow",
+[89674]="80 Str, 80 PvP Pow",
+[89675]="60 Str, 60 PvP Pow",
+[89676]="80 Str, 80 PvP Pow",
+[89677]="100 Str, 100 PvP Pow",
+[89678]="60 Agi, 60 PvP Pow",
+[89679]="80 Agi, 80 PvP Pow",
+[89680]="80 Agi, 80 PvP Pow",
+[89681]="100 Agi, 100 PvP Pow",
+[89873]="500 Agi",
+[89881]="500 Str",
+[89882]="500 Int",
+[93364]="550 Agi",
+[93365]="550 Str",
+[93366]="550 Int",
+[93404]="160 Str, 160 Resil",
+[93405]="160 Agi, 160 Resil",
+[93406]="160 Int, 160 Resil",
+[93408]="160 Str, 160 PvP Pow",
+[93409]="160 Agi, 160 PvP Pow",
+[93410]="160 Int, 160 PvP Pow",
+[93705]="160 Hit, 160 Dodge",
+[93706]="120 Hit, 120 Dodge",
+[93707]="160 Hit, 160 Dodge",
+[93708]="200 Hit, 200 Dodge",
+[95344]="Indomitable",
+[95345]="Courageous",
+[95346]="Capacitive",
+[95347]="Sinister",
+[95348]="665 PvP Pow, 775 Resil"}
+
+AskMrRobot.gemDuplicates = {
+[76570]=76636,
+[76571]=76637,
+[76572]=76638,
+[76573]=76639,
+[76574]=76640,
+[76575]=76641,
+[76576]=76642,
+[76577]=76643,
+[76578]=76644,
+[76579]=76645,
+[76580]=76646,
+[76581]=76647,
+[76582]=76648,
+[76583]=76649,
+[76584]=76650,
+[76585]=76651,
+[76586]=76652,
+[76587]=76653,
+[76588]=76654,
+[76589]=76655,
+[76590]=76656,
+[76591]=76657,
+[76592]=76658,
+[76593]=76659,
+[76594]=76660,
+[76595]=76661,
+[76596]=76662,
+[76597]=76663,
+[76598]=76664,
+[76599]=76665,
+[76600]=76666,
+[76601]=76667,
+[76602]=76668,
+[76603]=76669,
+[76604]=76670,
+[76605]=76671,
+[76606]=76672,
+[76607]=76673,
+[76608]=76674,
+[76609]=76675,
+[76610]=76676,
+[76611]=76677,
+[76612]=76678,
+[76613]=76679,
+[76614]=76680,
+[76615]=76681,
+[76616]=76682,
+[76617]=76683,
+[76618]=76684,
+[76619]=76685,
+[76620]=76686,
+[76621]=76687,
+[76622]=76688,
+[76623]=76689,
+[76624]=76690,
+[76625]=76691,
+[76626]=76692,
+[76627]=76693,
+[76628]=76694,
+[76629]=76695,
+[76630]=76696,
+[76631]=76697,
+[76632]=76698,
+[76633]=76699,
+[76634]=76700,
+[76635]=76701,
+[76636]=76570,
+[76637]=76571,
+[76638]=76572,
+[76639]=76573,
+[76640]=76574,
+[76641]=76575,
+[76642]=76576,
+[76643]=76577,
+[76644]=76578,
+[76645]=76579,
+[76646]=76580,
+[76647]=76581,
+[76648]=76582,
+[76649]=76583,
+[76650]=76584,
+[76651]=76585,
+[76652]=76586,
+[76653]=76587,
+[76654]=76588,
+[76655]=76589,
+[76656]=76590,
+[76657]=76591,
+[76658]=76592,
+[76659]=76593,
+[76660]=76594,
+[76661]=76595,
+[76662]=76596,
+[76663]=76597,
+[76664]=76598,
+[76665]=76599,
+[76666]=76600,
+[76667]=76601,
+[76668]=76602,
+[76669]=76603,
+[76670]=76604,
+[76671]=76605,
+[76672]=76606,
+[76673]=76607,
+[76674]=76608,
+[76675]=76609,
+[76676]=76610,
+[76677]=76611,
+[76678]=76612,
+[76679]=76613,
+[76680]=76614,
+[76681]=76615,
+[76682]=76616,
+[76683]=76617,
+[76684]=76618,
+[76685]=76619,
+[76686]=76620,
+[76687]=76621,
+[76688]=76622,
+[76689]=76623,
+[76690]=76624,
+[76691]=76625,
+[76692]=76626,
+[76693]=76627,
+[76694]=76628,
+[76695]=76629,
+[76696]=76630,
+[76697]=76631,
+[76698]=76632,
+[76699]=76633,
+[76700]=76634,
+[76701]=76635,
+[89674]=89676,
+[89676]=89674,
+[89679]=89680,
+[89680]=89679,
+[93705]=93707,
+[93707]=93705}
+
+local gemEnchantDuplicates = {
+[4520]=4587,
+[4521]=4588,
+[4522]=4589,
+[4523]=4590,
+[4524]=4591,
+[4525]=4592,
+[4526]=4593,
+[4527]=4594,
+[4528]=4595,
+[4529]=4596,
+[4530]=4597,
+[4531]=4598,
+[4532]=4599,
+[4533]=4600,
+[4535]=4601,
+[4536]=4602,
+[4537]=4603,
+[4538]=4604,
+[4539]=4605,
+[4540]=4606,
+[4541]=4607,
+[4542]=4608,
+[4543]=4609,
+[4544]=4610,
+[4545]=4611,
+[4546]=4612,
+[4547]=4613,
+[4548]=4614,
+[4549]=4615,
+[4550]=4616,
+[4551]=4617,
+[4552]=4618,
+[4553]=4619,
+[4554]=4620,
+[4555]=4621,
+[4556]=4622,
+[4557]=4623,
+[4558]=4624,
+[4559]=4625,
+[4560]=4626,
+[4561]=4627,
+[4562]=4628,
+[4563]=4629,
+[4564]=4630,
+[4565]=4631,
+[4566]=4632,
+[4567]=4633,
+[4568]=4634,
+[4569]=4635,
+[4570]=4636,
+[4571]=4637,
+[4572]=4638,
+[4573]=4652,
+[4574]=4640,
+[4575]=4641,
+[4576]=4642,
+[4577]=4643,
+[4578]=4653,
+[4579]=4644,
+[4580]=4645,
+[4581]=4646,
+[4582]=4647,
+[4583]=4648,
+[4584]=4649,
+[4585]=4650,
+[4586]=4651,
+[4587]=4520,
+[4588]=4521,
+[4589]=4522,
+[4590]=4523,
+[4591]=4524,
+[4592]=4525,
+[4593]=4526,
+[4594]=4527,
+[4595]=4528,
+[4596]=4529,
+[4597]=4530,
+[4598]=4531,
+[4599]=4532,
+[4600]=4533,
+[4601]=4535,
+[4602]=4536,
+[4603]=4537,
+[4604]=4538,
+[4605]=4539,
+[4606]=4540,
+[4607]=4541,
+[4608]=4542,
+[4609]=4543,
+[4610]=4544,
+[4611]=4545,
+[4612]=4546,
+[4613]=4547,
+[4614]=4548,
+[4615]=4549,
+[4616]=4550,
+[4617]=4551,
+[4618]=4552,
+[4619]=4553,
+[4620]=4554,
+[4621]=4555,
+[4622]=4556,
+[4623]=4557,
+[4624]=4558,
+[4625]=4559,
+[4626]=4560,
+[4627]=4561,
+[4628]=4562,
+[4629]=4563,
+[4630]=4564,
+[4631]=4565,
+[4632]=4566,
+[4633]=4567,
+[4634]=4568,
+[4635]=4569,
+[4636]=4570,
+[4637]=4571,
+[4638]=4572,
+[4652]=4573,
+[4640]=4574,
+[4641]=4575,
+[4642]=4576,
+[4643]=4577,
+[4653]=4578,
+[4644]=4579,
+[4645]=4580,
+[4646]=4581,
+[4647]=4582,
+[4648]=4583,
+[4649]=4584,
+[4650]=4585,
+[4651]=4586,
+[4984]=4986,
+[4986]=4984,
+[4989]=4990,
+[4990]=4989,
+[5024]=5026,
+[5026]=5024}
+
+local perfectGems = {
+[76570]=1,
+[76571]=1,
+[76572]=1,
+[76573]=1,
+[76574]=1,
+[76575]=1,
+[76576]=1,
+[76577]=1,
+[76578]=1,
+[76579]=1,
+[76580]=1,
+[76581]=1,
+[76582]=1,
+[76583]=1,
+[76584]=1,
+[76585]=1,
+[76586]=1,
+[76587]=1,
+[76588]=1,
+[76589]=1,
+[76590]=1,
+[76591]=1,
+[76592]=1,
+[76593]=1,
+[76594]=1,
+[76595]=1,
+[76596]=1,
+[76597]=1,
+[76598]=1,
+[76599]=1,
+[76600]=1,
+[76601]=1,
+[76602]=1,
+[76603]=1,
+[76604]=1,
+[76605]=1,
+[76606]=1,
+[76607]=1,
+[76608]=1,
+[76609]=1,
+[76610]=1,
+[76611]=1,
+[76612]=1,
+[76613]=1,
+[76614]=1,
+[76615]=1,
+[76616]=1,
+[76617]=1,
+[76618]=1,
+[76619]=1,
+[76620]=1,
+[76621]=1,
+[76622]=1,
+[76623]=1,
+[76624]=1,
+[76625]=1,
+[76626]=1,
+[76627]=1,
+[76628]=1,
+[76629]=1,
+[76630]=1,
+[76631]=1,
+[76632]=1,
+[76633]=1,
+[76634]=1,
+[76635]=1,
+[89676]=1,
+[89679]=1,
+[93707]=1}
+
+AskMrRobot.JewelcrafterGems = {
+[36766]=1,
+[36767]=1,
+[42142]=1,
+[42143]=1,
+[42144]=1,
+[42145]=1,
+[42146]=1,
+[42148]=1,
+[42149]=1,
+[42150]=1,
+[42151]=1,
+[42152]=1,
+[42153]=1,
+[42154]=1,
+[42155]=1,
+[42156]=1,
+[42157]=1,
+[42158]=1,
+[52255]=1,
+[52257]=1,
+[52258]=1,
+[52259]=1,
+[52260]=1,
+[52261]=1,
+[52262]=1,
+[52263]=1,
+[52264]=1,
+[52265]=1,
+[52266]=1,
+[52267]=1,
+[52268]=1,
+[52269]=1,
+[83141]=1,
+[83142]=1,
+[83143]=1,
+[83144]=1,
+[83145]=1,
+[83146]=1,
+[83147]=1,
+[83148]=1,
+[83149]=1,
+[83150]=1,
+[83151]=1,
+[83152]=1,
+[93404]=1,
+[93405]=1,
+[93406]=1,
+[93408]=1,
+[93409]=1,
+[93410]=1}
+
+local function DoGemsMatch(gemIdA, gemIdB)
+   return gemIdA == gemIdB or (gemIdA and gemIdB and gemIdA == AskMrRobot.gemDuplicates[gemIdB])
+end
+
+local function DoGemEnchantsMatch(gemEnchantIdA, gemEnchantIdB)
+   return gemEnchantIdA == gemEnchantIdB or (gemEnchantIdA and gemEnchantIdB and gemEnchantIdA == gemEnchantDuplicates[gemEnchantIdB])
+end
+
+local function GemMatchesSocket(gemId, socketColor)
+	local gemColor = gemToColor[gemId]
+	if socketColor == 'Red' then
+		return gemColor =='Red' or gemColor == 'Orange' or gemColor == 'Purple'
+	elseif socketColor == 'Yellow' then
+		return gemColor == 'Yellow' or gemColor == 'Orange' or gemColor == 'Green'
+	elseif socketColor == 'Blue' then
+		return gemColor == 'Blue' or gemColor == 'Purple' or gemColor == 'Green'
+	elseif socketColor == 'Prismatic' then
+		return gemColor == 'Prismatic' or gemColor == 'Orange' or gemColor == 'Green' or gemColor == 'Purple' or gemColor == 'Red' or gemColor == 'Yellow' or gemColor == 'Blue'
+	else
+		return gemColor == socketColor
+	end
+end
+
+local function CanInsertGem(gemId, socketColor)
+	local gemColor = gemToColor[gemId]
+	return gemColor == socketColor or ((socketColor == 'Red' or socketColor == 'Yellow' or socketColor == 'Blue' or socketColor == 'Prismatic')
+		and (gemColor == 'Orange' or gemColor == 'Green' or gemColor == 'Purple' or gemColor == 'Red' or gemColor == 'Yellow' or gemColor == 'Blue'))
+end
+
+-- in: [{id (gemId), color (socketColor)}]
+-- out: bool
+local function AmrExpectsSocketBonus(gems)
+	local i
+	for i = 1, #gems do
+		local gem = gems[i]
+	 	if gem.color and not GemMatchesSocket(gem.id, gem.color) then
+	 		return false
+	  	end
+	end
+	return true
+end
+
+local function GetGemPermuations(gems)
+	local count = 0
+	local i
+	for i = 1, #gems do
+		if gems[i].color then
+			count = count + 1
+		end
+	end
+	if count == 0 then
+		return {}
+	elseif count == 1 then
+		return { { gems[1] } }
+	elseif count == 2 then
+		return { { gems[1], gems[2] } , { gems[2], gems[1] } }
+	elseif count == 3 then
+		return { { gems[1], gems[2], gems[3] } , { gems[1], gems[3], gems[2] },
+				 { gems[2], gems[1], gems[3] } , { gems[2], gems[3], gems[1] },
+				 { gems[3], gems[1], gems[2] } , { gems[3], gems[2], gems[1] }
+			   }
+	end
+end
+
+local function GetMatchingGems(gems, bonus)
+	local perms = GetGemPermuations(gems)
+	local i, j
+	local valid = {}
+	for i = 1, #perms do
+		local isValid = true
+		for j = 1, #perms[i] do
+			if bonus then				
+				if not GemMatchesSocket(perms[i][j].id, gems[j].color) then
+					isValid = false
+					break
+				end
+			elseif not CanInsertGem(perms[i][j].id, gems[j].color) then
+				isValid = false
+				break
+			end
+		end
+		if isValid then
+			tinsert(valid, perms[i])
+		end
+	end
+	return valid
+end
+
+local function GetBestGems(existingItemLink, gems, bonus)
+	local perms = GetMatchingGems(gems, bonus)
+	local bestScore = -1
+	local bestPerm = gems
+	for i = 1, #perms do
+		local score = 0
+		for j = 1, #perms[i] do
+			local existingGemLink = select(2, GetItemGem(existingItemLink, j))
+			if existingGemLink then
+				local existingGemId = AskMrRobot.getItemIdFromLink(existingGemLink)
+				if DoGemsMatch(perms[i][j].id, existingGemId) then
+					score = score + 1
+				end
+			end
+		end
+		if score > bestScore then
+			bestScore = score
+			bestPerm = perms[i]
+		end
+	end
+
+	local result = {} --make a new variable, because we don't want to change the original objects
+	for i = 1, #bestPerm do
+		--restore the color from the original.  This only really changes when bonus is false
+		result[i] = {id = bestPerm[i].id, enchantId = bestPerm[i].enchantId, color = gems[i].color}
+	end
+	return result
+end
+
+local function GetBadGems(existingItemLink, existingGemEnchantIds, gems)
+	local i
+
+	local badGemCount = 0
+	local result = { optimized = gems, current = existingGemEnchantIds, badGems = {}}
+	for i = 1, #gems do
+		-- get the current gem in the specified slot
+		local existingGemLink = select(2, GetItemGem(existingItemLink, i))
+		local existingGemId = existingGemLink and AskMrRobot.getItemIdFromLink(existingGemLink) or 0
+		gems[i].matched = DoGemsMatch(existingGemId, gems[i].id)
+		if not gems[i].matched then
+			result.badGems[i] = true
+			badGemCount = badGemCount + 1
+		end
+	end
+	result.current.link = existingItemLink
+
+	return badGemCount, result
+end
+
+-- returns badGemCount and {optimized:[], current:[], badGems[]}
+function AskMrRobot.MatchesGems(existingItemLink, existingGemEnchantIds, gems)
+	local bonus = AmrExpectsSocketBonus(gems)
+	local reorderedGems = GetBestGems(existingItemLink, gems, bonus)
+	return GetBadGems(existingItemLink, existingGemEnchantIds, reorderedGems)
+end
+
+
+local preferPerfectGems = false
+
+local function findItemInBag(bagId, itemId)
+	local numSlots = GetContainerNumSlots(bagId);
+	local lockedSlotId = nil
+	for slotId = 1, numSlots do
+		local _, itemCount, locked, _, _, _, itemLink = GetContainerItemInfo(bagId, slotId);
+		if itemLink ~= nil then
+			local bagItemId = AskMrRobot.getItemIdFromLink(itemLink)
+			if itemId == bagItemId then
+				if locked then					
+					lockedSlotId = slotId
+				else
+					return slotId, false
+				end
+			end
+		end
+	end	
+	return lockedSlotId, lockedSlotId ~= nil
+end
+
+-- returns bagId, badSlotId, isLocked
+local function findItem(itemId)
+	local lockedSlotId, lockedBagId = nil, nil
+	local bagSlot, locked = findItemInBag(BACKPACK_CONTAINER, itemId) -- backpack
+	if bagSlot then 
+		if locked then
+			lockedBagId = BACKPACK_CONTAINER
+			lockedSlotId = badGems
+		else
+			return BACKPACK_CONTAINER, bagSlot, false
+		end
+	end
+	
+	for bagId = 1, NUM_BAG_SLOTS do
+		bagSlot, locked = findItemInBag(bagId, itemId)
+		if locked then
+			lockedBagId = bagId
+			lockedSlotId = badGems
+		elseif bagSlot then
+			return bagId, bagSlot, false
+		end
+	end
+
+	return lockedBagId, lockedSlotId, lockedSlotId ~= nil
+end
+
+local autoGemCoRoutine = nil
+local autoGemTime = nil
+
+local function checkAutoGemTimeout()
+	if autoGemTime and difftime(time(), autoGemTime) >= 5 then
+		autoGemTime = nil
+		autoGemCoRoutine = nil
+		return true
+	end
+	return false
+end
+
+local function autoGemHelper(inventorySlotId, gemInfo, gemSlot)
+	-- get the gem id to socket
+	local gemId = gemInfo.optimized[gemSlot].id
+
+	--loop forever until we get the item unlocked
+	while true do
+		--if preferPerfectGems then
+		--end
+
+		-- attempt to find the gem in inventory
+		local bagId, bagSlot, locked = findItem(gemId)
+		local dupId = AskMrRobot.gemDuplicates[gemId]
+		if dupId ~= nil then
+			local bagId2, bagSlot2, locked2 = findItem(dupId)
+			if bagId == nil or (bagId2 ~= nil and perfectGems[dupId] == 1 and preferPerfectGems) then
+				bagId = bagId2
+				bagSlot = bagSlot2
+				locked = locked2
+			end
+		end
+
+		if locked or IsInventoryItemLocked(inventorySlotId) then
+			coroutine.yield()
+			if checkAutoGemTimeout() then
+				return
+			end
+		else
+			-- if found...
+			if bagId then
+				ClearCursor()
+				-- launch the gem ui with the item
+				SocketInventoryItem(inventorySlotId)
+
+				if GetNumSockets() < gemSlot then
+					print('Ask Mr Robot: Something is wrong.  There are not enough sockets on this item.')
+
+					CloseSocketInfo()
+					ClearCursor()
+					return
+				end
+
+				-- grab the gem from a bag
+				PickupContainerItem(bagId, bagSlot)
+				-- put the gem in the socket
+				ClickSocketButton(gemSlot)
+				-- -- save the changes
+				AcceptSockets()
+				-- close the UI
+				CloseSocketInfo()
+				ClearCursor()
+			end
+			break
+		end
+	end
+end
+
+local function autoGem()
+	--http://wowprogramming.com/docs/api_categories#socket
+	for slotNum, gemInfo in AskMrRobot.sortSlots(AskMrRobot.itemDiffs.gems) do
+		local inventorySlotId = GetInventorySlotInfo(AskMrRobot.slotNames[slotNum])
+
+		-- do non-JC gems first
+		for gemSlot in pairs(gemInfo.badGems) do
+			if gemInfo.badGems[gemSlot] == true then
+				local gemId = gemInfo.optimized[gemSlot].id
+				if not AskMrRobot.JewelcrafterGems[gemId] then
+					autoGemHelper(inventorySlotId, gemInfo, gemSlot)
+				end
+			end
+		end
+	end
+
+	for slotNum, gemInfo in AskMrRobot.sortSlots(AskMrRobot.itemDiffs.gems) do
+		local inventorySlotId = GetInventorySlotInfo(AskMrRobot.slotNames[slotNum])
+
+		-- do JC gems next
+		for gemSlot in pairs(gemInfo.badGems) do
+			if gemInfo.badGems[gemSlot] == true then
+				local gemId = gemInfo.optimized[gemSlot].id
+				if AskMrRobot.JewelcrafterGems[gemId] then
+					autoGemHelper(inventorySlotId, gemInfo, gemSlot)
+				end
+			end
+		end
+	end
+end
+
+local function resumeAutoGemming()
+	if not autoGemCoRoutine then
+		return
+	end
+	if coroutine.status(autoGemCoRoutine) == 'dead' then
+		autoGemCoRoutine = nil
+		StaticPopup_Show('AUTOGEM_FINISHED')
+		return
+	end
+	if coroutine.status(autoGemCoRoutine) == 'suspended' then
+		coroutine.resume(autoGemCoRoutine)
+		if coroutine.status(autoGemCoRoutine) == 'dead' then
+			autoGemCoRoutine = nil
+			StaticPopup_Show('AUTOGEM_FINISHED')
+		end
+		return
+	end
+end
+
+function AskMrRobot.AutoGem(preferPerfectGems1)
+	preferPerfectGems = preferPerfectGems1
+	checkAutoGemTimeout()
+	if autoGemCoRoutine then 
+		if coroutine.status(autoGemCoRoutine) == 'dead' then
+			autoGemCoRoutine = nil
+		else
+			return false 
+		end
+	end
+	autoGemTime = time()
+	autoGemCoRoutine = coroutine.create(autoGem)
+	resumeAutoGemming()
+	return true
+end
+
+function AskMrRobot.On_ITEM_UNLOCKED()
+	resumeAutoGemming()
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,240 @@
+--[[ $Id: CallbackHandler-1.0.lua 14 2010-08-09 00:43:38Z mikk $ ]]
+local MAJOR, MINOR = "CallbackHandler-1.0", 6
+local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not CallbackHandler then return end -- No upgrade needed
+
+local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
+
+-- Lua APIs
+local tconcat = table.concat
+local assert, error, loadstring = assert, error, loadstring
+local setmetatable, rawset, rawget = setmetatable, rawset, rawget
+local next, select, pairs, type, tostring = next, select, pairs, type, tostring
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: geterrorhandler
+
+local xpcall = xpcall
+
+local function errorhandler(err)
+	return geterrorhandler()(err)
+end
+
+local function CreateDispatcher(argCount)
+	local code = [[
+	local next, xpcall, eh = ...
+
+	local method, ARGS
+	local function call() method(ARGS) end
+
+	local function dispatch(handlers, ...)
+		local index
+		index, method = next(handlers)
+		if not method then return end
+		local OLD_ARGS = ARGS
+		ARGS = ...
+		repeat
+			xpcall(call, eh)
+			index, method = next(handlers, index)
+		until not method
+		ARGS = OLD_ARGS
+	end
+
+	return dispatch
+	]]
+
+	local ARGS, OLD_ARGS = {}, {}
+	for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end
+	code = code:gsub("OLD_ARGS", tconcat(OLD_ARGS, ", ")):gsub("ARGS", tconcat(ARGS, ", "))
+	return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler)
+end
+
+local Dispatchers = setmetatable({}, {__index=function(self, argCount)
+	local dispatcher = CreateDispatcher(argCount)
+	rawset(self, argCount, dispatcher)
+	return dispatcher
+end})
+
+--------------------------------------------------------------------------
+-- CallbackHandler:New
+--
+--   target            - target object to embed public APIs in
+--   RegisterName      - name of the callback registration API, default "RegisterCallback"
+--   UnregisterName    - name of the callback unregistration API, default "UnregisterCallback"
+--   UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
+
+function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused)
+	-- TODO: Remove this after beta has gone out
+	assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused")
+
+	RegisterName = RegisterName or "RegisterCallback"
+	UnregisterName = UnregisterName or "UnregisterCallback"
+	if UnregisterAllName==nil then	-- false is used to indicate "don't want this method"
+		UnregisterAllName = "UnregisterAllCallbacks"
+	end
+
+	-- we declare all objects and exported APIs inside this closure to quickly gain access
+	-- to e.g. function names, the "target" parameter, etc
+
+
+	-- Create the registry object
+	local events = setmetatable({}, meta)
+	local registry = { recurse=0, events=events }
+
+	-- registry:Fire() - fires the given event/message into the registry
+	function registry:Fire(eventname, ...)
+		if not rawget(events, eventname) or not next(events[eventname]) then return end
+		local oldrecurse = registry.recurse
+		registry.recurse = oldrecurse + 1
+
+		Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...)
+
+		registry.recurse = oldrecurse
+
+		if registry.insertQueue and oldrecurse==0 then
+			-- Something in one of our callbacks wanted to register more callbacks; they got queued
+			for eventname,callbacks in pairs(registry.insertQueue) do
+				local first = not rawget(events, eventname) or not next(events[eventname])	-- test for empty before. not test for one member after. that one member may have been overwritten.
+				for self,func in pairs(callbacks) do
+					events[eventname][self] = func
+					-- fire OnUsed callback?
+					if first and registry.OnUsed then
+						registry.OnUsed(registry, target, eventname)
+						first = nil
+					end
+				end
+			end
+			registry.insertQueue = nil
+		end
+	end
+
+	-- Registration of a callback, handles:
+	--   self["method"], leads to self["method"](self, ...)
+	--   self with function ref, leads to functionref(...)
+	--   "addonId" (instead of self) with function ref, leads to functionref(...)
+	-- all with an optional arg, which, if present, gets passed as first argument (after self if present)
+	target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
+		if type(eventname) ~= "string" then
+			error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
+		end
+
+		method = method or eventname
+
+		local first = not rawget(events, eventname) or not next(events[eventname])	-- test for empty before. not test for one member after. that one member may have been overwritten.
+
+		if type(method) ~= "string" and type(method) ~= "function" then
+			error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
+		end
+
+		local regfunc
+
+		if type(method) == "string" then
+			-- self["method"] calling style
+			if type(self) ~= "table" then
+				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
+			elseif self==target then
+				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
+			elseif type(self[method]) ~= "function" then
+				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
+			end
+
+			if select("#",...)>=1 then	-- this is not the same as testing for arg==nil!
+				local arg=select(1,...)
+				regfunc = function(...) self[method](self,arg,...) end
+			else
+				regfunc = function(...) self[method](self,...) end
+			end
+		else
+			-- function ref with self=object or self="addonId" or self=thread
+			if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
+				error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
+			end
+
+			if select("#",...)>=1 then	-- this is not the same as testing for arg==nil!
+				local arg=select(1,...)
+				regfunc = function(...) method(arg,...) end
+			else
+				regfunc = method
+			end
+		end
+
+
+		if events[eventname][self] or registry.recurse<1 then
+		-- if registry.recurse<1 then
+			-- we're overwriting an existing entry, or not currently recursing. just set it.
+			events[eventname][self] = regfunc
+			-- fire OnUsed callback?
+			if registry.OnUsed and first then
+				registry.OnUsed(registry, target, eventname)
+			end
+		else
+			-- we're currently processing a callback in this registry, so delay the registration of this new entry!
+			-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
+			registry.insertQueue = registry.insertQueue or setmetatable({},meta)
+			registry.insertQueue[eventname][self] = regfunc
+		end
+	end
+
+	-- Unregister a callback
+	target[UnregisterName] = function(self, eventname)
+		if not self or self==target then
+			error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
+		end
+		if type(eventname) ~= "string" then
+			error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
+		end
+		if rawget(events, eventname) and events[eventname][self] then
+			events[eventname][self] = nil
+			-- Fire OnUnused callback?
+			if registry.OnUnused and not next(events[eventname]) then
+				registry.OnUnused(registry, target, eventname)
+			end
+		end
+		if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
+			registry.insertQueue[eventname][self] = nil
+		end
+	end
+
+	-- OPTIONAL: Unregister all callbacks for given selfs/addonIds
+	if UnregisterAllName then
+		target[UnregisterAllName] = function(...)
+			if select("#",...)<1 then
+				error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
+			end
+			if select("#",...)==1 and ...==target then
+				error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
+			end
+
+
+			for i=1,select("#",...) do
+				local self = select(i,...)
+				if registry.insertQueue then
+					for eventname, callbacks in pairs(registry.insertQueue) do
+						if callbacks[self] then
+							callbacks[self] = nil
+						end
+					end
+				end
+				for eventname, callbacks in pairs(events) do
+					if callbacks[self] then
+						callbacks[self] = nil
+						-- Fire OnUnused callback?
+						if registry.OnUnused and not next(callbacks) then
+							registry.OnUnused(registry, target, eventname)
+						end
+					end
+				end
+			end
+		end
+	end
+
+	return registry
+end
+
+
+-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
+-- try to upgrade old implicit embeds since the system is selfcontained and
+-- relies on closures to work.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,4 @@
+<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
+..\FrameXML\UI.xsd">
+	<Script file="CallbackHandler-1.0.lua"/>
+</Ui>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/LibDBIcon-1.0/LibDBIcon-1.0.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,344 @@
+--[[
+Name: DBIcon-1.0
+Revision: $Rev: 25 $
+Author(s): Rabbit (rabbit.magtheridon@gmail.com)
+Description: Allows addons to register to recieve a lightweight minimap icon as an alternative to more heavy LDB displays.
+Dependencies: LibStub
+License: GPL v2 or later.
+]]
+
+--[[
+Copyright (C) 2008-2011 Rabbit
+
+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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+]]
+
+-----------------------------------------------------------------------
+-- DBIcon-1.0
+--
+-- Disclaimer: Most of this code was ripped from Barrel but fixed, streamlined
+--             and cleaned up a lot so that it no longer sucks.
+--
+
+local DBICON10 = "LibDBIcon-1.0"
+local DBICON10_MINOR = tonumber(("$Rev: 25 $"):match("(%d+)"))
+if not LibStub then error(DBICON10 .. " requires LibStub.") end
+local ldb = LibStub("LibDataBroker-1.1", true)
+if not ldb then error(DBICON10 .. " requires LibDataBroker-1.1.") end
+local lib = LibStub:NewLibrary(DBICON10, DBICON10_MINOR)
+if not lib then return end
+
+lib.disabled = lib.disabled or nil
+lib.objects = lib.objects or {}
+lib.callbackRegistered = lib.callbackRegistered or nil
+lib.notCreated = lib.notCreated or {}
+
+function lib:IconCallback(event, name, key, value, dataobj)
+	if lib.objects[name] then
+		if key == "icon" then
+			lib.objects[name].icon:SetTexture(value)
+		elseif key == "iconCoords" then
+			lib.objects[name].icon:UpdateCoord()
+		end
+	end
+end
+if not lib.callbackRegistered then
+	ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__icon", "IconCallback")
+	ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconCoords", "IconCallback")
+	lib.callbackRegistered = true
+end
+
+-- Tooltip code ripped from StatBlockCore by Funkydude
+local function getAnchors(frame)
+	local x, y = frame:GetCenter()
+	if not x or not y then return "CENTER" end
+	local hhalf = (x > UIParent:GetWidth()*2/3) and "RIGHT" or (x < UIParent:GetWidth()/3) and "LEFT" or ""
+	local vhalf = (y > UIParent:GetHeight()/2) and "TOP" or "BOTTOM"
+	return vhalf..hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP")..hhalf
+end
+
+local function onEnter(self)
+	if self.isMoving then return end
+	local obj = self.dataObject
+	if obj.OnTooltipShow then
+		GameTooltip:SetOwner(self, "ANCHOR_NONE")
+		GameTooltip:SetPoint(getAnchors(self))
+		obj.OnTooltipShow(GameTooltip)
+		GameTooltip:Show()
+	elseif obj.OnEnter then
+		obj.OnEnter(self)
+	end
+end
+
+local function onLeave(self)
+	local obj = self.dataObject
+	GameTooltip:Hide()
+	if obj.OnLeave then obj.OnLeave(self) end
+end
+
+--------------------------------------------------------------------------------
+
+local onClick, onMouseUp, onMouseDown, onDragStart, onDragEnd, updatePosition
+
+do
+	local minimapShapes = {
+		["ROUND"] = {true, true, true, true},
+		["SQUARE"] = {false, false, false, false},
+		["CORNER-TOPLEFT"] = {false, false, false, true},
+		["CORNER-TOPRIGHT"] = {false, false, true, false},
+		["CORNER-BOTTOMLEFT"] = {false, true, false, false},
+		["CORNER-BOTTOMRIGHT"] = {true, false, false, false},
+		["SIDE-LEFT"] = {false, true, false, true},
+		["SIDE-RIGHT"] = {true, false, true, false},
+		["SIDE-TOP"] = {false, false, true, true},
+		["SIDE-BOTTOM"] = {true, true, false, false},
+		["TRICORNER-TOPLEFT"] = {false, true, true, true},
+		["TRICORNER-TOPRIGHT"] = {true, false, true, true},
+		["TRICORNER-BOTTOMLEFT"] = {true, true, false, true},
+		["TRICORNER-BOTTOMRIGHT"] = {true, true, true, false},
+	}
+
+	function updatePosition(button)
+		local angle = math.rad(button.db and button.db.minimapPos or button.minimapPos or 225)
+		local x, y, q = math.cos(angle), math.sin(angle), 1
+		if x < 0 then q = q + 1 end
+		if y > 0 then q = q + 2 end
+		local minimapShape = GetMinimapShape and GetMinimapShape() or "ROUND"
+		local quadTable = minimapShapes[minimapShape]
+		if quadTable[q] then
+			x, y = x*80, y*80
+		else
+			local diagRadius = 103.13708498985 --math.sqrt(2*(80)^2)-10
+			x = math.max(-80, math.min(x*diagRadius, 80))
+			y = math.max(-80, math.min(y*diagRadius, 80))
+		end
+		button:SetPoint("CENTER", Minimap, "CENTER", x, y)
+	end
+end
+
+function onClick(self, b) if self.dataObject.OnClick then self.dataObject.OnClick(self, b) end end
+function onMouseDown(self) self.isMouseDown = true; self.icon:UpdateCoord() end
+function onMouseUp(self) self.isMouseDown = false; self.icon:UpdateCoord() end
+
+do
+	local function onUpdate(self)
+		local mx, my = Minimap:GetCenter()
+		local px, py = GetCursorPosition()
+		local scale = Minimap:GetEffectiveScale()
+		px, py = px / scale, py / scale
+		if self.db then
+			self.db.minimapPos = math.deg(math.atan2(py - my, px - mx)) % 360
+		else
+			self.minimapPos = math.deg(math.atan2(py - my, px - mx)) % 360
+		end
+		updatePosition(self)
+	end
+
+	function onDragStart(self)
+		self:LockHighlight()
+		self.isMouseDown = true
+		self.icon:UpdateCoord()
+		self:SetScript("OnUpdate", onUpdate)
+		self.isMoving = true
+		GameTooltip:Hide()
+	end
+end
+
+function onDragStop(self)
+	self:SetScript("OnUpdate", nil)
+	self.isMouseDown = false
+	self.icon:UpdateCoord()
+	self:UnlockHighlight()
+	self.isMoving = nil
+end
+
+local defaultCoords = {0, 1, 0, 1}
+local function updateCoord(self)
+	local coords = self:GetParent().dataObject.iconCoords or defaultCoords
+	local deltaX, deltaY = 0, 0
+	if not self:GetParent().isMouseDown then
+		deltaX = (coords[2] - coords[1]) * 0.05
+		deltaY = (coords[4] - coords[3]) * 0.05
+	end
+	self:SetTexCoord(coords[1] + deltaX, coords[2] - deltaX, coords[3] + deltaY, coords[4] - deltaY)
+end
+
+local function createButton(name, object, db)
+	local button = CreateFrame("Button", "LibDBIcon10_"..name, Minimap)
+	button.dataObject = object
+	button.db = db
+	button:SetFrameStrata("MEDIUM")
+	button:SetWidth(31); button:SetHeight(31)
+	button:SetFrameLevel(8)
+	button:RegisterForClicks("anyUp")
+	button:RegisterForDrag("LeftButton")
+	button:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight")
+	local overlay = button:CreateTexture(nil, "OVERLAY")
+	overlay:SetWidth(53); overlay:SetHeight(53)
+	overlay:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder")
+	overlay:SetPoint("TOPLEFT")
+	local background = button:CreateTexture(nil, "BACKGROUND")
+	background:SetWidth(20); background:SetHeight(20)
+	background:SetTexture("Interface\\Minimap\\UI-Minimap-Background")
+	background:SetPoint("TOPLEFT", 7, -5)
+	local icon = button:CreateTexture(nil, "ARTWORK")
+	icon:SetWidth(17); icon:SetHeight(17)
+	icon:SetTexture(object.icon)
+	icon:SetPoint("TOPLEFT", 7, -6)
+	button.icon = icon
+	button.isMouseDown = false
+
+	icon.UpdateCoord = updateCoord
+	icon:UpdateCoord()
+
+	button:SetScript("OnEnter", onEnter)
+	button:SetScript("OnLeave", onLeave)
+	button:SetScript("OnClick", onClick)
+	if not db or not db.lock then
+		button:SetScript("OnDragStart", onDragStart)
+		button:SetScript("OnDragStop", onDragStop)
+	end
+	button:SetScript("OnMouseDown", onMouseDown)
+	button:SetScript("OnMouseUp", onMouseUp)
+
+	lib.objects[name] = button
+
+	if lib.loggedIn then
+		updatePosition(button)
+		if not db or not db.hide then button:Show()
+		else button:Hide() end
+	end
+end
+
+-- We could use a metatable.__index on lib.objects, but then we'd create
+-- the icons when checking things like :IsRegistered, which is not necessary.
+local function check(name)
+	if lib.notCreated[name] then
+		createButton(name, lib.notCreated[name][1], lib.notCreated[name][2])
+		lib.notCreated[name] = nil
+	end
+end
+
+lib.loggedIn = lib.loggedIn or false
+-- Wait a bit with the initial positioning to let any GetMinimapShape addons
+-- load up.
+if not lib.loggedIn then
+	local f = CreateFrame("Frame")
+	f:SetScript("OnEvent", function()
+		for _, object in pairs(lib.objects) do
+			updatePosition(object)
+			if not lib.disabled and (not object.db or not object.db.hide) then object:Show()
+			else object:Hide() end
+		end
+		lib.loggedIn = true
+		f:SetScript("OnEvent", nil)
+		f = nil
+	end)
+	f:RegisterEvent("PLAYER_LOGIN")
+end
+
+local function getDatabase(name)
+	return lib.notCreated[name] and lib.notCreated[name][2] or lib.objects[name].db
+end
+
+function lib:Register(name, object, db)
+	if not object.icon then error("Can't register LDB objects without icons set!") end
+	if lib.objects[name] or lib.notCreated[name] then error("Already registered, nubcake.") end
+	if not lib.disabled and (not db or not db.hide) then
+		createButton(name, object, db)
+	else
+		lib.notCreated[name] = {object, db}
+	end
+end
+
+function lib:Lock(name)
+	if not lib:IsRegistered(name) then return end
+	if lib.objects[name] then
+		lib.objects[name]:SetScript("OnDragStart", nil)
+		lib.objects[name]:SetScript("OnDragStop", nil)
+	end
+	local db = getDatabase(name)
+	if db then db.lock = true end
+end
+
+function lib:Unlock(name)
+	if not lib:IsRegistered(name) then return end
+	if lib.objects[name] then
+		lib.objects[name]:SetScript("OnDragStart", onDragStart)
+		lib.objects[name]:SetScript("OnDragStop", onDragStop)
+	end
+	local db = getDatabase(name)
+	if db then db.lock = nil end
+end
+
+function lib:Hide(name)
+	if not lib.objects[name] then return end
+	lib.objects[name]:Hide()
+end
+function lib:Show(name)
+	if lib.disabled then return end
+	check(name)
+	lib.objects[name]:Show()
+	updatePosition(lib.objects[name])
+end
+function lib:IsRegistered(name)
+	return (lib.objects[name] or lib.notCreated[name]) and true or false
+end
+function lib:Refresh(name, db)
+	if lib.disabled then return end
+	check(name)
+	local button = lib.objects[name]
+	if db then button.db = db end
+	updatePosition(button)
+	if not button.db or not button.db.hide then
+		button:Show()
+	else
+		button:Hide()
+	end
+	if not button.db or not button.db.lock then
+		button:SetScript("OnDragStart", onDragStart)
+		button:SetScript("OnDragStop", onDragStop)
+	else
+		button:SetScript("OnDragStart", nil)
+		button:SetScript("OnDragStop", nil)
+	end
+end
+function lib:GetMinimapButton(name)
+	return lib.objects[name]
+end
+
+function lib:EnableLibrary()
+	lib.disabled = nil
+	for name, object in pairs(lib.objects) do
+		if not object.db or not object.db.hide then
+			object:Show()
+			updatePosition(object)
+		end
+	end
+	for name, data in pairs(lib.notCreated) do
+		if not data.db or not data.db.hide then
+			createButton(name, data[1], data[2])
+			lib.notCreated[name] = nil
+		end
+	end
+end
+
+function lib:DisableLibrary()
+	lib.disabled = true
+	for name, object in pairs(lib.objects) do
+		object:Hide()
+	end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/LibDataBroker-1.1/LibDataBroker-1.1.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,90 @@
+
+assert(LibStub, "LibDataBroker-1.1 requires LibStub")
+assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
+
+local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4)
+if not lib then return end
+oldminor = oldminor or 0
+
+
+lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
+lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
+local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
+
+if oldminor < 2 then
+	lib.domt = {
+		__metatable = "access denied",
+		__index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
+	}
+end
+
+if oldminor < 3 then
+	lib.domt.__newindex = function(self, key, value)
+		if not attributestorage[self] then attributestorage[self] = {} end
+		if attributestorage[self][key] == value then return end
+		attributestorage[self][key] = value
+		local name = namestorage[self]
+		if not name then return end
+		callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
+		callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
+		callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
+		callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
+	end
+end
+
+if oldminor < 2 then
+	function lib:NewDataObject(name, dataobj)
+		if self.proxystorage[name] then return end
+
+		if dataobj then
+			assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
+			self.attributestorage[dataobj] = {}
+			for i,v in pairs(dataobj) do
+				self.attributestorage[dataobj][i] = v
+				dataobj[i] = nil
+			end
+		end
+		dataobj = setmetatable(dataobj or {}, self.domt)
+		self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
+		self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
+		return dataobj
+	end
+end
+
+if oldminor < 1 then
+	function lib:DataObjectIterator()
+		return pairs(self.proxystorage)
+	end
+
+	function lib:GetDataObjectByName(dataobjectname)
+		return self.proxystorage[dataobjectname]
+	end
+
+	function lib:GetNameByDataObject(dataobject)
+		return self.namestorage[dataobject]
+	end
+end
+
+if oldminor < 4 then
+	local next = pairs(attributestorage)
+	function lib:pairs(dataobject_or_name)
+		local t = type(dataobject_or_name)
+		assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)")
+
+		local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
+		assert(attributestorage[dataobj], "Data object not found")
+
+		return next, attributestorage[dataobj], nil
+	end
+
+	local ipairs_iter = ipairs(attributestorage)
+	function lib:ipairs(dataobject_or_name)
+		local t = type(dataobject_or_name)
+		assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)")
+
+		local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
+		assert(attributestorage[dataobj], "Data object not found")
+
+		return ipairs_iter, attributestorage[dataobj], 0
+	end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/LibDataBroker-1.1/README.textile	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,13 @@
+LibDataBroker is a small WoW addon library designed to provide a "MVC":http://en.wikipedia.org/wiki/Model-view-controller interface for use in various addons.
+LDB's primary goal is to "detach" plugins for TitanPanel and FuBar from the display addon.
+Plugins can provide data into a simple table, and display addons can receive callbacks to refresh their display of this data.
+LDB also provides a place for addons to register "quicklaunch" functions, removing the need for authors to embed many large libraries to create minimap buttons.
+Users who do not wish to be "plagued" by these buttons simply do not install an addon to render them.
+
+Due to it's simple generic design, LDB can be used for any design where you wish to have an addon notified of changes to a table.
+
+h2. Links
+
+* "API documentation":http://github.com/tekkub/libdatabroker-1-1/wikis/api
+* "Data specifications":http://github.com/tekkub/libdatabroker-1-1/wikis/data-specifications
+* "Addons using LDB":http://github.com/tekkub/libdatabroker-1-1/wikis/addons-using-ldb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/LibStub/LibStub.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,51 @@
+-- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $
+-- LibStub is a simple versioning stub meant for use in Libraries.  http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain
+-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2  -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+-- Check to see is this version of the stub is obsolete
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+	LibStub = LibStub or {libs = {}, minors = {} }
+	_G[LIBSTUB_MAJOR] = LibStub
+	LibStub.minor = LIBSTUB_MINOR
+	
+	-- LibStub:NewLibrary(major, minor)
+	-- major (string) - the major version of the library
+	-- minor (string or number ) - the minor version of the library
+	-- 
+	-- returns nil if a newer or same version of the lib is already present
+	-- returns empty library object or old library object if upgrade is needed
+	function LibStub:NewLibrary(major, minor)
+		assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+		minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+		
+		local oldminor = self.minors[major]
+		if oldminor and oldminor >= minor then return nil end
+		self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+		return self.libs[major], oldminor
+	end
+	
+	-- LibStub:GetLibrary(major, [silent])
+	-- major (string) - the major version of the library
+	-- silent (boolean) - if true, library is optional, silently return nil if its not found
+	--
+	-- throws an error if the library can not be found (except silent is set)
+	-- returns the library object if found
+	function LibStub:GetLibrary(major, silent)
+		if not self.libs[major] and not silent then
+			error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
+		end
+		return self.libs[major], self.minors[major]
+	end
+	
+	-- LibStub:IterateLibraries()
+	-- 
+	-- Returns an iterator for the currently registered libraries
+	function LibStub:IterateLibraries() 
+		return pairs(self.libs) 
+	end
+	
+	setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/LibStub/LibStub.toc	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,13 @@
+## Interface: 50001
+## Title: Lib: LibStub
+## Notes: Universal Library Stub
+## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
+## X-Website: http://www.wowace.com/addons/libstub/
+## X-Category: Library
+## X-License: Public Domain	
+## X-Curse-Packaged-Version: 1.0.3-50001
+## X-Curse-Project-Name: LibStub
+## X-Curse-Project-ID: libstub
+## X-Curse-Repository-ID: wow/libstub/mainline
+
+LibStub.lua
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/LibStub/tests/test.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy
+assert(lib) -- should return the library table
+assert(not oldMinor) -- should not return the old minor, since it didn't exist
+
+-- the following is to create data and then be able to check if the same data exists after the fact
+function lib:MyMethod()
+end
+local MyMethod = lib.MyMethod
+lib.MyTable = {}
+local MyTable = lib.MyTable
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version
+assert(newLib) -- library table
+assert(rawequal(newLib, lib)) -- should be the same reference as the previous
+assert(newOldMinor == 1) -- should return the minor version of the previous version
+
+assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved
+assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib) -- library table
+assert(newOldMinor == 2) -- previous version was 2
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib)
+assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string)
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string
+assert(newLib)
+assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/LibStub/tests/test2.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,27 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+for major, library in LibStub:IterateLibraries() do
+	-- check that MyLib doesn't exist yet, by iterating through all the libraries
+	assert(major ~= "MyLib")
+end
+
+assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking
+assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error.
+local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib
+assert(lib) -- check it exists
+assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference
+
+assert(LibStub:NewLibrary("MyLib", 2))	-- create a new version
+
+local count=0
+for major, library in LibStub:IterateLibraries() do
+	-- check that MyLib exists somewhere in the libraries, by iterating through all the libraries
+	if major == "MyLib" then -- we found it!
+		count = count +1
+		assert(rawequal(library, lib)) -- verify that the references are equal
+	end
+end
+assert(count == 1) -- verify that we actually found it, and only once
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/LibStub/tests/test3.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,14 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local proxy = newproxy() -- non-string
+
+assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata
+local success, ret = pcall(LibStub.GetLibrary, proxy, true)
+assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered.
+
+assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it.
+
+assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/LibStub/tests/test4.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+
+-- Pretend like loaded libstub is old and doesn't have :IterateLibraries
+assert(LibStub.minor)
+LibStub.minor = LibStub.minor - 0.0001
+LibStub.IterateLibraries = nil
+
+loadfile("../LibStub.lua")()
+
+assert(type(LibStub.IterateLibraries)=="function")
+
+
+-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created
+LibStub.IterateLibraries = 123
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created
+LibStub.minor = LibStub.minor + 0.0001
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Again with a huge number
+LibStub.minor = LibStub.minor + 1234567890
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+print("OK")
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sort.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,31 @@
+local _, AskMrRobot = ...
+
+function AskMrRobot.spairs(t, order)
+    -- collect the keys
+    local keys = {}
+    for k in pairs(t) do keys[#keys+1] = k end
+
+    -- if order function given, sort by it by passing the table and keys a, b,
+    -- otherwise just sort the keys 
+    if order then
+        table.sort(keys, function(a,b) return order(t, a, b) end)
+    else
+        table.sort(keys)
+    end
+
+    -- return the iterator function
+    local i = 0
+    return function()
+        i = i + 1
+        if keys[i] then
+            return keys[i], t[keys[i]]
+        end
+    end
+end
+
+function AskMrRobot.sortSlots(t)
+    return AskMrRobot.spairs(t, function(x, a, b)
+        if a == nil and b == nil then return 0 end
+        return AskMrRobot.sortedSlots[a] < AskMrRobot.sortedSlots[b]
+    end)
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/CombatLogTab.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,303 @@
+local _, AskMrRobot = ...
+
+-- initialize the ExportTab class
+AskMrRobot.CombatLogTab = AskMrRobot.inheritsFrom(AskMrRobot.Frame)
+
+-- helper to create text for this tab
+local function CreateText(tab, font, relativeTo, xOffset, yOffset, text)
+    local t = tab:CreateFontString(nil, "ARTWORK", font)
+	t:SetPoint("TOPLEFT", relativeTo, "BOTTOMLEFT", xOffset, yOffset)
+	t:SetPoint("RIGHT", tab, "RIGHT", -25, 0)
+	t:SetWidth(t:GetWidth())
+	t:SetJustifyH("LEFT")
+	t:SetText(text)
+    
+    return t
+end
+
+local function newCheckbox(tab, label, tooltipTitle, description, onClick)
+	local check = CreateFrame("CheckButton", "AmrCheck" .. label, tab, "InterfaceOptionsCheckButtonTemplate")
+	check:SetScript("OnClick", function(self)
+		PlaySound(self:GetChecked() and "igMainMenuOptionCheckBoxOn" or "igMainMenuOptionCheckBoxOff")
+		onClick(self, self:GetChecked() and true or false)
+	end)
+	check.label = _G[check:GetName() .. "Text"]
+	check.label:SetText(label)
+	check.tooltipText = tooltipTitle
+	check.tooltipRequirement = description
+	return check
+end
+
+function AskMrRobot.CombatLogTab:new(parent)
+
+	local tab = AskMrRobot.Frame:new(nil, parent)	
+	setmetatable(tab, { __index = AskMrRobot.CombatLogTab })
+	tab:SetPoint("TOPLEFT")
+	tab:SetPoint("BOTTOMRIGHT")
+	tab:Hide()
+
+	local text = tab:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
+	text:SetPoint("TOPLEFT", 0, -5)
+	text:SetText("Combat Logging")
+    
+	local manulText = CreateText(tab, "GameFontWhite", text, 0, -15, "Manual:")
+	manulText:SetJustifyV("MIDDLE")
+    manulText:SetHeight(30)
+	    
+    local btn = CreateFrame("Button", "AmrCombatLogStart", tab, "UIPanelButtonTemplate")
+	btn:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 75, -15)
+	btn:SetText("Start Logging")
+	btn:SetWidth(120)
+	btn:SetHeight(30)
+    tab.btnStart = btn
+    
+    btn:SetScript("OnClick", function()
+        tab:StartLogging()
+    end)
+    
+    btn = CreateFrame("Button", "AmrCombatLogEnd", tab, "UIPanelButtonTemplate")
+	btn:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 225, -15)
+	btn:SetText("Stop Logging")
+	btn:SetWidth(120)
+	btn:SetHeight(30)
+    tab.btnEnd = btn
+    
+    btn:SetScript("OnClick", function()
+        tab:StopLogging()
+    end)
+
+	local autoText = CreateText(tab, "GameFontWhite", text, 0, -50, "Automatic:")
+	autoText:SetJustifyV("MIDDLE")
+    autoText:SetHeight(28)
+
+	local autoChk = newCheckbox(tab,
+		"Always log Siege of Orgrimmar",
+		"Auto-Log Siege of Orgrimmar",
+		"Automatically start logging when you enter SoO and stop when you leave SoO.\n\nNote that you should disable similar features in other addons to avoid conflicts.",
+		function(self, value) 
+			if value then
+				AmrLogData._autoLog[AskMrRobot.instanceIds.SiegeOfOrgrimmar] = "enabled"
+			else
+				AmrLogData._autoLog[AskMrRobot.instanceIds.SiegeOfOrgrimmar] = "disabled" 
+			end
+
+			AmrLogData._lastZone = nil
+			AmrLogData._lastDiff = nil
+			tab:UpdateAutoLogging()
+		end
+	)
+	autoChk:SetChecked(AmrLogData._autoLog[AskMrRobot.instanceIds.SiegeOfOrgrimmar] == "enabled")
+	autoChk:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 75, -50)
+    autoChk:SetHeight(30)
+
+	text = CreateText(tab, "GameFontNormalLarge", text, 0, -100, "Character Data")
+
+	btn = CreateFrame("Button", "AmrCombatLogSaveCharData", tab, "UIPanelButtonTemplate")
+	btn:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 0, -5)
+	btn:SetText("Save Character Data")
+	btn:SetWidth(150)
+	btn:SetHeight(30)
+
+	btn:SetScript("OnClick", function()
+		-- reload the UI will save character data to disk
+        ReloadUI()
+    end)
+
+    text = CreateText(tab, "GameFontNormalLarge", btn, 0, -30, "INSTRUCTIONS")
+    text = CreateText(tab, "GameFontWhite", text, 0, -10, "1. Use the Start/Stop buttons or check 'Always log Siege of Orgrimmar'.")
+    text = CreateText(tab, "GameFontWhite", text, 0, -10, "2. When you are ready to upload, press 'Save Character Data'. *")
+    text = CreateText(tab, "GameFontWhite", text, 0, -10, "3. Exit World of Warcraft. **")
+	text = CreateText(tab, "GameFontWhite", text, 0, -10, "4. Launch the Ask Mr. Robot client and follow the instructions. ***")
+
+	text = CreateText(tab, "GameFontNormalSmall", text, 0, -30, "|c00999999* This will reload your UI to ensure that all collected data is saved to disk.  This step is not necessary if you log out of the game before uploading.|r")
+	text = CreateText(tab, "GameFontNormalSmall", text, 0, -10, "|c00999999** Exiting WoW before uploading your combat log is optional, but highly recommended.  This prevents your log file from getting ridiculously large and slowing down your uploads.|r")
+	text = CreateText(tab, "GameFontNormalSmall", text, 0, -10, "|c00999999*** You can download the client program at|r |c003333ffhttp://www.askmrrobot.com/wow/combatlog/upload|r|c00999999.|r")
+    
+	--[[
+	btn = CreateFrame("Button", "AmrCombatLogTest", tab, "UIPanelButtonTemplate")
+	btn:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 0, -15)
+	btn:SetText("Test")
+	btn:SetWidth(120)
+	btn:SetHeight(30)
+    
+    btn:SetScript("OnClick", function()
+        AskMrRobot.ExportToAddonChat(time())
+    end)
+	]]
+
+	-- when we start up, ensure that logging is still enabled if it was enabled when they last used the addon
+    if (tab:IsLogging()) then
+        SetCVar("advancedCombatLogging", 1)
+        LoggingCombat(true)
+    end
+    
+	-- if auto-logging is enabled, do a check when the addon is loaded to make sure that state is set correctly
+	if AmrLogData._autoLog[AskMrRobot.instanceIds.SiegeOfOrgrimmar] == "enabled" then
+		tab:UpdateAutoLogging()
+	end
+
+    tab:SetScript("OnShow", function()
+        tab:Update()
+	end)
+
+    return tab
+end
+
+function AskMrRobot.CombatLogTab:IsLogging()
+    return AmrLogData._logging == true
+end
+
+function AskMrRobot.CombatLogTab:StartLogging()
+
+	-- archive the current logging session so that users don't accidentally blow away data before uploading it
+	if AmrLogData._current2 ~= nil then
+		if not AmrLogData._history2 then AmrLogData._history2 = {} end
+
+		-- add new entries
+		for name, timeList in AskMrRobot.spairs(AmrLogData._current2) do
+			if not AmrLogData._history2[name] then AmrLogData._history2[name] = {} end
+			for timestamp, dataString in AskMrRobot.spairs(timeList) do
+				AmrLogData._history2[name][timestamp] = dataString
+			end
+		end
+
+		-- delete entries that are more than 10 days old
+		local now = time()
+		local interval = 60 * 60 * 24 * 10
+		for name, timeList in AskMrRobot.spairs(AmrLogData._history2) do
+			for timestamp, dataString in AskMrRobot.spairs(timeList) do
+				if difftime(now, tonumber(timestamp)) > interval then
+					timeList[timestamp] = nil
+				end
+			end
+			
+			local count = 0
+			for timestamp, dataString in pairs(timeList) do
+				count = count + 1
+			end
+			if count == 0 then
+				AmrLogData._history2[name] = nil
+			end
+		end
+	end
+
+	-- clean up old-style logging data from previous versions of the addon
+	for k, v in AskMrRobot.spairs(AmrLogData) do
+		if k ~= "_logging" and k ~= "_autoLog" and k ~= "_lastZone" and k ~= "_lastDiff" and k ~= "_current2" and k ~= "_history2" then
+			AmrLogData[k] = nil
+		end
+	end
+
+    -- start a new logging session
+    AmrLogData._current2 = {}
+    AmrLogData._logging = true
+    
+    -- always enable advanced combat logging via our addon, gathers more detailed data for better analysis
+    SetCVar("advancedCombatLogging", 1)
+    
+    LoggingCombat(true)
+    self:Update()
+    
+    print("You are now logging combat, and Mr. Robot is logging character data for your raid.")
+end
+
+function AskMrRobot.CombatLogTab:StopLogging()
+    LoggingCombat(false)
+    AmrLogData._logging = false
+    self:Update()
+    
+    print("Combat logging has been stopped.")
+end
+
+-- update the panel and state
+function AskMrRobot.CombatLogTab:Update()
+    local isLogging = self:IsLogging()
+    
+    if isLogging then
+        self.btnStart:Disable()
+        self.btnEnd:Enable()
+    else
+        self.btnStart:Enable()
+        self.btnEnd:Disable()
+    end
+end
+
+-- called to update logging state when auto-logging is enabled
+function AskMrRobot.CombatLogTab:UpdateAutoLogging()
+
+	-- get the info about the instance
+	--local zone, zonetype, difficultyIndex, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID = GetInstanceInfo()
+	local zone, _, difficultyIndex, _, _, _, _, instanceMapID = GetInstanceInfo()
+	--local difficulty = difficultyIndex
+	-- Unless Blizzard fixes scenarios to not return nil, let's hardcode this into returning "scenario" -Znuff
+	--if zonetype == nil and difficultyIndex == 1 then
+		--zonetype = "scenario"
+	--end
+
+	if zone == AmrLogData._lastZone and difficultyIndex == AmrLogData._lastDiff then
+	  -- do nothing if the zone hasn't actually changed, otherwise we may override the user's manual enable/disable
+		return
+	end
+
+	AmrLogData._lastZone = zone
+	AmrLogData._lastDiff = difficultyIndex
+
+	if AmrLogData._autoLog[AskMrRobot.instanceIds.SiegeOfOrgrimmar] == "enabled" then
+		if tonumber(instanceMapID) == AskMrRobot.instanceIds.SiegeOfOrgrimmar then
+			-- if in SoO, make sure logging is on
+			if not self:IsLogging() then
+				self:StartLogging()
+			end
+		else
+			-- not in SoO, turn logging off
+			if self:IsLogging() then
+				self:StopLogging()
+			end
+		end
+	end
+
+end
+
+-- read a message sent to the addon channel with a player's info at the time an encounter started
+function AskMrRobot.CombatLogTab:ReadAddonMessage(message)
+
+    -- message will be of format: timestamp\nrealm\nname\n[stuff]
+    local parts = {}
+	for part in string.gmatch(message, "([^\n]+)") do
+		tinsert(parts, part)
+	end
+    
+    local timestamp = parts[1]
+    local name = parts[2] .. ":" .. parts[3]
+    local data = parts[4]
+    
+    if (data == "done") then
+        -- we have finished receiving this message; now process it to reduce the amount of duplicate data
+        local setup = AmrLogData._current2[name][timestamp]
+        
+        if (AmrLogData._previousSetup == nil) then
+            AmrLogData._previousSetup = {}
+        end
+        
+        local previousSetup = AmrLogData._previousSetup[name]
+        
+        if (previousSetup == setup) then
+            -- if the last-seen setup for this player is the same as the current one, we don't need this entry
+            AmrLogData._current2[name][timestamp] = nil
+        else
+            -- record the last-seen setup
+            AmrLogData._previousSetup[name] = setup
+        end
+    else
+        -- concatenate messages with the same timestamp+name
+        if (AmrLogData._current2[name] == nil) then
+            AmrLogData._current2[name] = {}
+        end
+        
+        if (AmrLogData._current2[name][timestamp] == nil) then
+            AmrLogData._current2[name][timestamp] = data
+        else
+            AmrLogData._current2[name][timestamp] = AmrLogData._current2[name][timestamp] .. data
+        end
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/Components.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,162 @@
+local _, AskMrRobot = ...
+
+local unresolvedItemIds = {}
+
+-- Create a new class that inherits from a base class
+function AskMrRobot.inheritsFrom( baseClass )
+
+    -- The following lines are equivalent to the SimpleClass example:
+
+    -- Create the table and metatable representing the class.
+    local new_class = {}
+
+    -- Note that this function uses class_mt as an upvalue, so every instance
+    -- of the class will share the same metatable.
+    --
+  --   function new_class:create(o)
+  --   	o = o or {}
+		-- setmetatable( o, class_mt )
+		-- return o
+  --    end
+
+    -- The following is the key to implementing inheritance:
+
+    -- The __index member of the new class's metatable references the
+    -- base class.  This implies that all methods of the base class will
+    -- be exposed to the sub-class, and that the sub-class can override
+    -- any of these methods.
+    --
+    if baseClass then
+        setmetatable( new_class, { __index = baseClass } )
+    end
+
+    return new_class
+end
+
+local itemInfoFrame = nil;
+
+local function onGetItemInfoReceived(arg1, arg2, arg3)
+	-- since wow is awesome, it doesn't tell us *which* item id was just resolved, so we have to look at them all
+	for itemId, callbacks in pairs(unresolvedItemIds) do
+		-- attempt to get the item info AGAIN
+		local a, b, c, d, e, f, g, h, i, j, k = GetItemInfo(itemId)
+		-- if we got item info...
+		if a then
+			-- remove the callbacks from the list
+			unresolvedItemIds[itemId] = nil
+
+			-- call each callback
+			for i = 1, #callbacks do
+				callbacks[i](a, b, c, d, e, f, g, h, i, j, k)
+			end
+		end
+	end
+end
+
+
+function AskMrRobot.RegisterItemInfoCallback(itemId, callback)
+	if not itemId then
+		return
+	end
+
+	if not itemInfoFrame then
+	    waitFrame = CreateFrame("Frame","WaitFrame", UIParent);
+	    waitFrame:RegisterEvent("GET_ITEM_INFO_RECEIVED")
+	    waitFrame:SetScript("OnEvent", onGetItemInfoReceived);
+	end
+
+
+	-- get the list of registered callbacks for this particular item
+	local list = unresolvedItemIds[itemId]
+	-- if there was a list, then just add the callback to the list
+	if list then
+		tinsert(list, callback)
+	else
+		-- there wasn't a list, so make a new one with this callback
+		unresolvedItemIds[itemId] = { callback }
+	end
+end
+
+function AskMrRobot.getItemIdFromLink(item)
+	if not item then return 0 end
+	local id = tonumber (item:match ("item:(%d+):%d+:%d+:%d+:%d+:%d+:%-?%d+:%-?%d+:%d+:%d+"))
+	return (id and id ~= 0 and id or 0)
+end
+
+-- initialize the Frame class (inherit from a dummy frame)
+AskMrRobot.Frame = AskMrRobot.inheritsFrom(CreateFrame("Frame"))
+
+-- Frame contructor
+function AskMrRobot.Frame:new(name, parentFrame, inheritsFrame)
+	-- create a new frame (if one isn't supplied)
+	local o = CreateFrame("Frame", name, parentFrame, inheritsFrame)
+
+	-- use the Frame class
+	setmetatable(o, { __index = AskMrRobot.Frame })
+
+	-- return the instance of the Frame
+	return o
+end
+
+local MAINHAND = nil
+local OFFHAND = nil
+
+AskMrRobot.slotNames = {"HeadSlot", "NeckSlot", "ShoulderSlot", "BackSlot", "ChestSlot", "ShirtSlot", "TabardSlot", "WristSlot", "HandsSlot", "WaistSlot", "LegsSlot", "FeetSlot", "Finger0Slot", "Finger1Slot", "Trinket0Slot", "Trinket1Slot", "MainHandSlot", "SecondaryHandSlot", "AmmoSlot" };
+AskMrRobot.OptimizationSlots = {}
+AskMrRobot.slotIdToSlotNum = {}
+AskMrRobot.slotIds = {};
+for slotNum = 1, #AskMrRobot.slotNames do
+	local slotId = GetInventorySlotInfo(AskMrRobot.slotNames[slotNum])
+	AskMrRobot.slotIds[slotNum] = slotId
+	AskMrRobot.slotIdToSlotNum[slotId] = slotNum
+	local slotName = AskMrRobot.slotNames[slotNum]
+	if slotName == "MainHandSlot" then
+		MAINHAND = slotNum
+	end
+	if slotName == "SecondaryHandSlot" then
+		OFFHAND = slotNum
+	end
+	if slotName ~= "TabardSlot" and slotName ~= "AmmoSlot" and slotName ~= "ShirtSlot" then
+		AskMrRobot.OptimizationSlots[slotNum] = true
+	end
+
+end
+
+AskMrRobot.sortedSlots = {[MAINHAND] = 1, [OFFHAND] = 2}
+
+local i = 3
+for slotNum = 1, #AskMrRobot.slotNames do
+	if slotNum ~= MAINHAND and slotNum ~= OFFHAND then
+		AskMrRobot.sortedSlots[slotNum] = i
+		i = i + 1
+	end
+end
+
+
+-- initialize the Frame class (inherit from a dummy frame)
+AskMrRobot.FontString = AskMrRobot.inheritsFrom(AskMrRobot.Frame:new():CreateFontString(nil, "ARTWORK", "GameFontNormal"))
+
+-- Frame contructor
+function AskMrRobot.FontString:new(parentFrame, name, layer, style, fontSize)
+
+	local o = parentFrame:CreateFontString(name, layer, style)	-- create a new frame (if one isn't supplied)
+
+	-- use the fontstring class
+	setmetatable(o, { __index = AskMrRobot.FontString })
+
+	if fontSize then
+		o:SetFontSize(fontSize)
+	end
+
+	return o
+end
+
+function AskMrRobot.FontString:SetFontSize(fontSize)
+	local file, _, flags = self:GetFont()
+	self:SetFont(file, fontSize, flags)
+end
+
+function AskMrRobot.SetFontSize(fontString, fontSize)
+	local file, _, flags = fontString:GetFont()
+	fontString:SetFont(file, fontSize, flags)
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/EnchantLinkText.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,96 @@
+local _, AskMrRobot = ...
+
+AskMrRobot.EnchantLinkText = AskMrRobot.inheritsFrom(AskMrRobot.ItemTooltipFrame)
+
+function AskMrRobot.EnchantLinkText:new(name, parent)
+	local o = AskMrRobot.ItemTooltipFrame:new(name, parent)
+
+	-- use the ItemLinkText class
+	setmetatable(o, { __index = AskMrRobot.EnchantLinkText })
+
+	-- the item text
+	o.itemText = AskMrRobot.FontString:new(o, nil, "ARTWORK", "GameFontWhite")
+	o.itemText:SetPoint("TOPLEFT")
+	o.itemText:SetPoint("BOTTOMRIGHT")
+	o.itemText:SetJustifyH("LEFT")
+
+	return o
+end
+
+function AskMrRobot.EnchantLinkText:SetEnchantId(enchantId)
+	self.itemName = nil
+	if enchantId and enchantId ~= 0 then
+		local spellId = AskMrRobot.getEnchantSpellId(enchantId)
+		local link = nil
+		if spellId then
+			link = 'enchant:' .. spellId
+		end
+		self:SetItemLink(link)
+		if self.useSpellName then
+			local spellName = spellId and select(1, GetSpellInfo(spellId))
+			self.itemText:SetText(spellName)
+			self.itemName = spellName
+		else
+			self.itemName = AskMrRobot.getEnchantName(enchantId)
+			self.itemText:SetText(self.itemName)
+		end
+	else
+		self:SetItemLink(nil)
+		self.itemText:SetText('')
+	end
+end
+
+function AskMrRobot.EnchantLinkText:SetFontSize(fontSize)
+	self.itemText:SetFontSize(fontSize)
+end
+
+function AskMrRobot.EnchantLinkText:UseSpellName()
+	self.useSpellName = true
+end
+
+AskMrRobot.EnchantLinkIconAndText = AskMrRobot.inheritsFrom(AskMrRobot.EnchantLinkText)
+
+function AskMrRobot.EnchantLinkIconAndText:new(name, parent)
+	local o = AskMrRobot.EnchantLinkText:new(name, parent)
+
+	-- use the EnchantLinkIconAndText class
+	setmetatable(o, { __index = AskMrRobot.EnchantLinkIconAndText })
+
+	o.iconFrame = AskMrRobot.Frame:new(nil, o)
+	o.iconFrame:SetPoint("TOPLEFT", 0, 5)
+	o.iconFrame:SetWidth(24)
+	o.iconFrame:SetHeight(24)
+
+	o.icon = o.iconFrame:CreateTexture(nil, "BACKGROUND")
+	o.icon:SetPoint("TOPLEFT")
+	o.icon:SetPoint("BOTTOMRIGHT")
+
+	o.itemText:SetPoint("TOPLEFT", o.iconFrame, "TOPRIGHT", 4, -5)
+
+	o:SetRoundBorder()
+
+	return o
+end
+
+function AskMrRobot.EnchantLinkIconAndText:SetRoundBorder()
+	self.iconFrame:SetBackdrop({edgeFile = "Interface\\AddOns\\AskMrRobot\\Media\\round-edge", edgeSize = 8})
+end
+
+function AskMrRobot.EnchantLinkIconAndText:SetSquareBorder()
+	self.iconFrame:SetBackdrop({edgeFile = "Interface\\AddOns\\AskMrRobot\\Media\\square-edge", edgeSize = 8})
+end
+
+function AskMrRobot.EnchantLinkIconAndText:SetEnchantId(enchantId)
+	AskMrRobot.EnchantLinkText.SetEnchantId(self, enchantId)
+	if enchantId and enchantId ~= 0 then
+		local texture = AskMrRobot.getEnchantIcon(enchantId)
+		self.icon:SetTexture('Interface/Icons/' .. texture)
+		self.iconFrame:Show()
+	else
+		self.iconFrame:Hide()
+	end
+end
+
+function AskMrRobot.EnchantLinkIconAndText:SetFontSize(fontSize)
+	self.itemText:SetFontSize(fontSize)
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/EnchantTab.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,106 @@
+local _, AskMrRobot = ...
+
+-- initialize the EnchantTab class
+AskMrRobot.EnchantTab = AskMrRobot.inheritsFrom(AskMrRobot.Frame)
+
+function AskMrRobot.EnchantTab:new(parent)
+
+	local tab = AskMrRobot.Frame:new(nil, parent)
+	setmetatable(tab, { __index = AskMrRobot.EnchantTab })
+	tab:SetPoint("TOPLEFT")
+	tab:SetPoint("BOTTOMRIGHT")
+	tab:Hide()
+
+
+	local text = tab:CreateFontString("AmrEnchantsText1", "ARTWORK", "GameFontNormalLarge")
+	text:SetPoint("TOPLEFT", 0, -5)
+	text:SetText("Enchants")
+
+	tab.stamp = AskMrRobot.RobotStamp:new(nil, tab)
+	tab.stamp:Hide()
+	tab.stamp.smallText:SetText("Your enchants are 100% optimal!")
+	tab.stamp:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 2, -15)
+	tab.stamp:SetPoint("RIGHT", tab, "RIGHT", -20, 0)
+
+	tab.slotHeader = tab:CreateFontString("AmrBadEnchantSlotHeader", "ARTWORK", "GameFontNormal")
+	tab.slotHeader:SetPoint("TOPLEFT", "AmrEnchantsText1", "BOTTOMLEFT", 0, -20)
+	tab.slotHeader:SetText("Slot")
+	tab.slotHeader:SetWidth(90)
+	tab.slotHeader:SetJustifyH("LEFT")
+
+	tab.currentHeader = tab:CreateFontString("AmrBadEnchantCurrentHeader", "ARTWORK", "GameFontNormal")
+	tab.currentHeader:SetText("Current")
+	tab.currentHeader:SetPoint("TOPLEFT", "AmrBadEnchantSlotHeader", "TOPLEFT", 100, 0)
+	tab.currentHeader:SetWidth(120)
+	tab.currentHeader:SetJustifyH("LEFT")
+
+	tab.optimizedHeader = tab:CreateFontString("AmrBadEnchantOptimizedHeader", "ARTWORK", "GameFontNormal")
+	tab.optimizedHeader:SetPoint("TOPLEFT", "AmrBadEnchantCurrentHeader", "TOPLEFT", 140, 0)
+	tab.optimizedHeader:SetPoint("RIGHT", -30, 0)
+	tab.optimizedHeader:SetText("Optimized")
+	tab.optimizedHeader:SetJustifyH("LEFT")
+
+	tab.badEnchantSlots = {}
+	tab.badEnchantCurrent = {}
+	tab.badEnchantOptimized = {}
+
+	for i = 1, #AskMrRobot.slotNames do
+		local itemText = tab:CreateFontString(nil, "ARTWORK", "GameFontWhite")
+		itemText:SetPoint("TOPLEFT", "AmrBadEnchantSlotHeader", "TOPLEFT", 0, -26 * i)
+		itemText:SetPoint("BOTTOMRIGHT", "AmrBadEnchantSlotHeader", "BOTTOMRIGHT", 0, -26 * i)
+		itemText:SetJustifyH("LEFT")
+		itemText:SetText("TestSlot")
+		tinsert(tab.badEnchantSlots, itemText)
+
+		itemText = AskMrRobot.EnchantLinkText:new(nil, tab)
+		itemText:SetPoint("TOPLEFT", "AmrBadEnchantCurrentHeader", "TOPLEFT", 0, -26 * i)
+		itemText:SetPoint("BOTTOMRIGHT", "AmrBadEnchantCurrentHeader", "BOTTOMRIGHT", 0,  -26 * i)
+		tinsert(tab.badEnchantCurrent, itemText)
+
+		itemText = AskMrRobot.EnchantLinkIconAndText:new(nil, tab)
+		itemText:SetPoint("TOPLEFT", "AmrBadEnchantOptimizedHeader", "TOPLEFT", 0,  -26 * i)
+		itemText:SetPoint("BOTTOMRIGHT", "AmrBadEnchantOptimizedHeader", "BOTTOMRIGHT", 0,  -26 * i)
+		tinsert(tab.badEnchantOptimized, itemText)
+	end
+
+	return tab
+end
+
+function AskMrRobot.EnchantTab:showBadEnchants()
+
+	local badEnchants = AskMrRobot.itemDiffs.enchants
+
+	local i = 1
+
+	-- for all the bad items
+	for slotNum, badEnchant in AskMrRobot.sortSlots(badEnchants) do
+		self.badEnchantSlots[i]:SetText(_G[strupper(AskMrRobot.slotNames[slotNum])])
+		self.badEnchantSlots[i]:Show()
+
+		self.badEnchantCurrent[i]:SetEnchantId(badEnchant.current)
+
+		self.badEnchantOptimized[i]:SetEnchantId(badEnchant.optimized)
+		i = i + 1
+	end
+
+	-- hide / show the headers
+	if i == 1 then
+		self.optimizedHeader:Hide()
+		self.currentHeader:Hide()
+		self.slotHeader:Hide()
+		self.stamp:Show()
+	else
+		self.optimizedHeader:Show()
+		self.currentHeader:Show()
+		self.slotHeader:Show()
+		self.stamp:Hide()
+	end
+
+	-- hide the remaining slots
+	while i <= #self.badEnchantSlots do
+		self.badEnchantSlots[i]:Hide()
+		self.badEnchantCurrent[i]:SetEnchantId(nil)
+		self.badEnchantOptimized[i]:SetEnchantId(nil)
+		i = i + 1
+	end		
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/ExportTab.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,158 @@
+local _, AskMrRobot = ...
+
+-- initialize the ExportTab class
+AskMrRobot.ExportTab = AskMrRobot.inheritsFrom(AskMrRobot.Frame)
+
+-- helper to create text for this tab
+local function CreateText(state, tab, font, relativeTo, xOffset, yOffset, text)
+    local t = tab:CreateFontString(nil, "ARTWORK", font)
+	t:SetPoint("TOPLEFT", relativeTo, "BOTTOMLEFT", xOffset, yOffset)
+	t:SetPoint("RIGHT", tab, "RIGHT", -25, 0)
+	t:SetWidth(t:GetWidth())
+	t:SetJustifyH("LEFT")
+	t:SetText(text)
+    
+    if (state ~= nil) then
+        table.insert(state, t)
+    end
+    
+    return t
+end
+
+function AskMrRobot.ExportTab:new(parent)
+
+	local tab = AskMrRobot.Frame:new(nil, parent)	
+	setmetatable(tab, { __index = AskMrRobot.ExportTab })
+	tab:SetPoint("TOPLEFT")
+	tab:SetPoint("BOTTOMRIGHT")
+	tab:Hide()
+    
+    -- used to toggle between the two states... could use like, tabs or a UI panel or something, but then I would have to read more pseudo-documentation.
+    tab.manualElements = {}
+    tab.autoElements = {}
+
+	local text = tab:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
+	text:SetPoint("TOPLEFT", 0, -5)
+	text:SetText("Export Gear for Best in Bags")  
+    
+    local chooseText = CreateText(nil, tab, "GameFontWhite", text, 0, -15, "Choose a method:")
+	chooseText:SetJustifyV("MIDDLE")
+    chooseText:SetHeight(30)
+    
+    local btn = CreateFrame("Button", "AmrExportManual", tab, "UIPanelButtonTemplate")
+	btn:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 125, -15)
+	btn:SetText("Copy/Paste")
+	btn:SetWidth(120)
+	btn:SetHeight(30)
+    tab.btnManual = btn
+    
+    btn:SetScript("OnClick", function()
+        AmrOptions.exportToClient = false
+        tab:Update()
+    end)
+    
+    btn = CreateFrame("Button", "AmrExportAuto", tab, "UIPanelButtonTemplate")
+	btn:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 275, -15)
+	btn:SetText("AMR Client")
+	btn:SetWidth(120)
+	btn:SetHeight(30)
+    tab.btnAuto = btn
+    
+    btn:SetScript("OnClick", function()
+        AmrOptions.exportToClient = true
+        tab:Update()
+    end)
+    
+    -- copy/paste
+    text = CreateText(tab.manualElements, tab, "GameFontNormalLarge", chooseText, 0, -20, "COPY/PASTE EXPORT")
+    local text2 = CreateText(tab.manualElements, tab, "GameFontWhite", text, 0, -15, "1. Open your bank")
+    text = CreateText(tab.manualElements, tab, "GameFontWhite", text2, 0, -15, "2. Copy the text below by pressing Ctrl+C (or Cmd+C on a Mac)")
+
+	local txtExportString = CreateFrame("ScrollFrame", "AmrScrollFrame", tab, "InputScrollFrameTemplate")
+	txtExportString:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 12, -10)
+	txtExportString:SetPoint("RIGHT", -25, 0)
+	txtExportString:SetWidth(txtExportString:GetWidth())
+	txtExportString:SetHeight(50)
+	txtExportString.EditBox:SetWidth(txtExportString:GetWidth())
+    txtExportString.EditBox:SetMaxLetters(0)
+	txtExportString.CharCount:Hide()
+	tab.txtExportString = txtExportString
+    table.insert(tab.manualElements, txtExportString)
+    
+    txtExportString.EditBox:SetScript("OnEscapePressed", function()
+        AskMrRobot_ReforgeFrame:Hide()
+    end)
+    
+    text = CreateText(tab.manualElements, tab, "GameFontWhite", txtExportString, -12, -20, "3. Go to AskMrRobot.com and paste into the IMPORT window")
+    text2 = CreateText(tab.manualElements, tab, "GameFontWhite", text, 10, -5, "(located to the right of your character name near the top of the web page, see screenshot)")
+
+    local image = tab:CreateTexture(nil, "BACKGROUND")
+	image:SetPoint("TOPLEFT", text2, "BOTTOMLEFT", 2, -10)
+	image:SetTexture("Interface\\AddOns\\AskMrRobot\\Media\\BiBScreen")
+    table.insert(tab.manualElements, image)
+    
+    text = CreateText(tab.manualElements, tab, "GameFontWhite", text2, 0, -120, "NOTE: If you change something while this window is open, press the Update button below to generate a new export string.")
+    
+    btn = CreateFrame("Button", "AmrUpdateExportString", tab, "UIPanelButtonTemplate")
+	btn:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 0, -5)
+	btn:SetText("Update")
+	btn:SetWidth(120)
+	btn:SetHeight(25)
+    table.insert(tab.manualElements, btn)
+    
+    btn:SetScript("OnClick", function()
+        tab:Update()
+    end)
+    
+    -- amr client
+    text = CreateText(tab.autoElements, tab, "GameFontNormalLarge", chooseText, 0, -20, "AMR CLIENT EXPORT")
+    text2 = CreateText(tab.autoElements, tab, "GameFontWhite", text, 0, -15, "1. Open your bank")
+    text = CreateText(tab.autoElements, tab, "GameFontWhite", text2, 0, -15, "2. Press the button below to update your AskMrRobot.lua file")
+
+    btn = CreateFrame("Button", "AmrExportFile", tab, "UIPanelButtonTemplate")
+	btn:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 12, -10)
+	btn:SetText("Export to File")
+	btn:SetWidth(180)
+	btn:SetHeight(25)
+    table.insert(tab.autoElements, btn)
+    
+    btn:SetScript("OnClick", function()
+        AskMrRobot.SaveAll()
+        ReloadUI()
+    end)
+
+    text = CreateText(tab.autoElements, tab, "GameFontWhite", btn, -12, -20, "3. Go to AskMrRobot.com and press REFRESH")
+    text2 = CreateText(tab.autoElements, tab, "GameFontWhite", text, 10, -5, "(located to the right of your character name near the top of the web page, see screenshot:)")
+
+    image = tab:CreateTexture(nil, "BACKGROUND")
+	image:SetPoint("TOPLEFT", text2, "BOTTOMLEFT", 2, -10)
+	image:SetTexture("Interface\\AddOns\\AskMrRobot\\Media\\BiBScreen")
+    table.insert(tab.autoElements, image)
+
+    tab:SetScript("OnShow", function()
+        tab:Update()
+	end)
+    
+	return tab
+end
+
+-- update the panel and state
+function AskMrRobot.ExportTab:Update()
+
+    if (AmrOptions.exportToClient) then
+        for i, v in ipairs(self.manualElements) do v:Hide() end
+        for i, v in ipairs(self.autoElements) do v:Show() end
+        self.btnManual:UnlockHighlight()
+        self.btnAuto:LockHighlight()
+    else
+        for i, v in ipairs(self.autoElements) do v:Hide() end
+        for i, v in ipairs(self.manualElements) do v:Show() end
+        self.btnAuto:UnlockHighlight()
+        self.btnManual:LockHighlight()
+        
+        AskMrRobot.SaveAll()
+        self.txtExportString.EditBox:SetText(AskMrRobot.ExportToString())
+        self.txtExportString.EditBox:HighlightText()
+        self.txtExportString.EditBox:SetFocus()
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/GemIcon.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,84 @@
+local _, AskMrRobot = ...
+
+local primaryGemTexture = "Interface\\ItemSocketingFrame\\UI-ItemSockets";
+local engineeringGemTexture = "Interface\\ItemSocketingFrame\\UI-EngineeringSockets";
+ 
+GEM_TYPE_INFO = {
+	Yellow = {tex=primaryGemTexture, left=0, right=0.16796875, top=0.640625, bottom=0.80859375, r=0.97, g=0.82, b=0.29, OBLeft=0.7578125, OBRight=0.9921875, OBTop=0, OBBottom=0.22265625},
+	Red = {tex=primaryGemTexture, left=0.1796875, right=0.34375, top=0.640625, bottom=0.80859375, r=1, g=0.47, b=0.47, OBLeft=0.7578125, OBRight=0.9921875, OBTop=0.4765625, OBBottom=0.69921875},
+	Blue = {tex=primaryGemTexture,left=0.3515625, right=0.51953125, top=0.640625, bottom=0.80859375, r=0.47, g=0.67, b=1, OBLeft=0.7578125, OBRight=0.9921875, OBTop=0.23828125, OBBottom=0.4609375},
+	Hydraulic = {tex=engineeringGemTexture, left=0.01562500, right=0.68750000, top=0.50000000, bottom=0.58398438, r=1, g=1, b=1, OBLeft=0.01562500, OBRight=0.93750000, OBTop=0.11132813, OBBottom=0.21679688},
+	Cogwheel = {tex=engineeringGemTexture, left=0.01562500, right=0.68750000, top=0.41210938, bottom=0.49609375, r=1, g=1, b=1, OBLeft=0.01562500, OBRight=0.78125000, OBTop=0.31640625, OBBottom=0.40820313},
+	Meta = {tex=primaryGemTexture, left=0.171875, right=0.3984375, top=0.40234375, bottom=0.609375, r=1, g=1, b=1, OBLeft=0.7578125, OBRight=0.9921875, OBTop=0, OBBottom=0.22265625},
+	Prismatic = {tex=engineeringGemTexture, left=0.01562500, right=0.68750000, top=0.76367188, bottom=0.84765625, r=1, g=1, b=1, OBLeft=0.01562500, OBRight=0.68750000, OBTop=0.58789063, OBBottom=0.67187500}
+}
+
+AskMrRobot.GemIcon = AskMrRobot.inheritsFrom(AskMrRobot.ItemIcon)
+
+-- item icon contructor
+function AskMrRobot.GemIcon:new(name, parent)
+	-- create a new frame (if one isn't supplied)
+	local o = AskMrRobot.ItemIcon:new(name, parent)
+
+	-- use the ItemIcon class
+	setmetatable(o, { __index = AskMrRobot.GemIcon })
+
+	-- add the overlay for the 
+	o.openBracket = o:CreateTexture(nil, "ARTWORK")
+	o.openBracket:SetPoint("TOPLEFT")
+	o.openBracket:SetPoint("BOTTOMRIGHT")
+
+	-- return the instance of the GemIcon
+	return o
+end
+
+function AskMrRobot.GemIcon:UpdateGemStuff()
+	local info = GEM_TYPE_INFO[self.color]
+
+	if self.itemLink then
+		-- hide the 2nd half of the empty gem icon
+		self.openBracket:Hide()
+
+		if info then
+			self:SetBackdropBorderColor(info.r, info.g, info.b)			
+		end
+	else
+		if info then
+			-- set the empty gem background texture		
+			self.itemIcon:SetTexture(info.tex)
+			self.itemIcon:SetTexCoord(info.left, info.right, info.top, info.bottom)
+
+			-- set the empty gem overlay
+			self.openBracket:SetTexture(info.tex)
+			self.openBracket:SetTexCoord(info.OBLeft, info.OBRight, info.OBTop, info.OBBottom)
+			self.openBracket:Show()
+
+			--hide the border (the empty gem icon has a border)
+			self:SetBackdropBorderColor(0,0,0,0)
+
+			-- set the empty gem background texture		
+			self.itemIcon:SetTexture(info.tex)
+			self.itemIcon:SetTexCoord(info.left, info.right, info.top, info.bottom)
+
+			-- set the empty gem overlay
+			self.openBracket:SetTexture(info.tex)
+			self.openBracket:SetTexCoord(info.OBLeft, info.OBRight, info.OBTop, info.OBBottom)
+			self.openBracket:Show()
+		else
+			self.openBracket:Hide()
+		end
+
+		self:SetBackdropBorderColor(0,0,0,0)
+	end
+
+end
+
+function AskMrRobot.GemIcon:SetItemLink(link)
+	AskMrRobot.ItemIcon.SetItemLink(self, link)
+	self:UpdateGemStuff()
+end
+
+function AskMrRobot.GemIcon:SetGemColor(color)
+	self.color = color
+	self:UpdateGemStuff()
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/GemTab.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,195 @@
+local _, AskMrRobot = ...
+
+StaticPopupDialogs["AUTOGEM_FINISHED"] = {
+	text = "Mr. Robot finished auto-gemming. \rIf some items aren't gemmed, you may need to acquire more gems. \rIf your belt isn't gemmed, you may still need to buy a belt buckle.",
+	button1 = "Ok",
+	timeout = 0,
+	whileDead = true,
+	hideOnEscape = true,
+	preferredIndex = 3,  -- avoid some UI taint, see http://www.wowace.com/announcements/how-to-avoid-some-ui-taint/
+}
+
+StaticPopupDialogs["AUTOGEM_ONCE"] = {
+	text = "Autogemming already in progress.",
+	button1 = "Ok",
+	timeout = 0,
+	whileDead = true,
+	hideOnEscape = true,
+	preferredIndex = 3,  -- avoid some UI taint, see http://www.wowace.com/announcements/how-to-avoid-some-ui-taint/
+}
+
+-- initialize the GemTab class
+AskMrRobot.GemTab = AskMrRobot.inheritsFrom(AskMrRobot.Frame)
+
+local MAX_SLOTS = 4
+
+-- GemTab contructor
+function AskMrRobot.GemTab:new(name, parent)
+	-- create a new frame (if one isn't supplied)
+	local tab = AskMrRobot.Frame:new(name, parent)
+	tab:SetPoint("TOPLEFT")
+	tab:SetPoint("BOTTOMRIGHT")
+	-- use the GemTab class
+	setmetatable(tab, { __index = AskMrRobot.GemTab })
+	tab:Hide()
+
+	local text = tab:CreateFontString("AmrGemsText1", "ARTWORK", "GameFontNormalLarge")
+	text:SetPoint("TOPLEFT", 0, -5)
+	text:SetText("Gems")
+
+	tab.stamp = AskMrRobot.RobotStamp:new(nil, tab)
+	tab.stamp:Hide()
+	tab.stamp.smallText:SetText("Your gems are 100% optimal! You are truly, truly outrageous.")
+	tab.stamp:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 2, -15)
+	tab.stamp:SetPoint("RIGHT", tab, "RIGHT", -20, 0)
+
+	text = tab:CreateFontString("AmrGemsText2", "ARTWORK", "GameFontWhite")
+	text:SetText("You have X gems to optimize")
+	text:SetPoint("TOPLEFT", "AmrGemsText1", "BOTTOMLEFT", 0, -20)
+	text:SetWidth(200)
+	text:SetJustifyH("LEFT")
+	tab.gemsTextToOptimize = text
+
+	-- autogem button
+	tab.button = CreateFrame("Button", "AmrAutoGemButton", tab, "UIPanelButtonTemplate")	
+	tab.button:SetPoint("TOP", "AmrGemsText1", "BOTTOM", 0, -16)
+	tab.button:SetPoint("RIGHT", -40, 0)
+	tab.button:SetText("Auto Gem! (BETA)")
+	tab.button:SetWidth(150)
+	tab.button:SetHeight(20)
+	tab.button:SetScript("OnClick", function() tab:startAutoGem() end)
+	tab.button:Hide()
+
+	-- autogem checkbox button
+	tab.usePerfectButton = CreateFrame("CheckButton", "AmrUsePerfectButton", tab, "ChatConfigCheckButtonTemplate")	
+	tab.preferPerfects = true
+	tab.usePerfectButton:SetChecked(tab.preferPerfects)
+	tab.usePerfectButton:SetPoint("TOPLEFT", "AmrAutoGemButton", "BOTTOMLEFT", 0, -4)
+	tab.usePerfectButton:SetScript("OnClick", function () tab.preferPerfects = tab.usePerfectButton:GetChecked() end)
+	local text3 = getglobal(tab.usePerfectButton:GetName() .. 'Text')
+	text3:SetText("Prefer Perfect")
+	text3:SetWidth(150)
+	text3:SetPoint("TOPLEFT", tab.usePerfectButton, "TOPRIGHT", 2, -4)
+	tab.usePerfectButton:Hide()
+
+	tab.gemSlotHeader = tab:CreateFontString("AmrBadGemSlot0", "ARTWORK", "GameFontNormal")
+	tab.gemSlotHeader:SetPoint("TOPLEFT", "AmrGemsText2", "BOTTOMLEFT", 0, -20)
+	tab.gemSlotHeader:SetText("Slot")
+	tab.gemSlotHeader:SetWidth(90)
+	tab.gemSlotHeader:SetJustifyH("LEFT")
+	tab.gemSlotHeader:Hide()
+	tab.gemCurrentHeader = tab:CreateFontString("AmrBadGemCurrent0_1", "ARTWORK", "GameFontNormal")
+	tab.gemCurrentHeader:SetPoint("TOPLEFT", "AmrBadGemSlot0", "TOPLEFT", 88, 0)
+	tab.gemCurrentHeader:SetWidth(110)
+	tab.gemCurrentHeader:SetText("Current")
+	tab.gemCurrentHeader:SetJustifyH("LEFT")
+	tab.gemCurrentHeader:Hide()
+	tab.gemOptimizedHeader = tab:CreateFontString("AmrBadGemOptimized0_1", "ARTWORK", "GameFontNormal")
+	tab.gemOptimizedHeader:SetPoint("TOPLEFT", "AmrBadGemCurrent0_1", "TOPLEFT", 70, 0)
+	tab.gemOptimizedHeader:SetPoint("RIGHT", -30, 0)
+	tab.gemOptimizedHeader:SetText("Optimized")
+	tab.gemOptimizedHeader:SetJustifyH("LEFT")
+	tab.gemOptimizedHeader:Hide()
+
+	tab.fauxScroll = CreateFrame("ScrollFrame", "testme", tab, "FauxScrollFrameTemplate")
+	tab.fauxScroll:SetPoint("BOTTOMRIGHT", -40, 15)
+	tab.fauxScroll:SetPoint("TOPLEFT", "AmrBadGemSlot0", "BOTTOMLEFT", -12, -5)
+	tab.fauxScroll.parent = tab
+	tab.fauxScroll:SetScript("OnVerticalScroll", AskMrRobot.GemTab.OnVerticalScroll)
+
+	tab.jewelPanels = {}
+	for i = 1, MAX_SLOTS do
+
+		tab.jewelPanels[i] = AskMrRobot.JewelPanel:new("AmrBadGemSlot" .. i, tab)
+		if i == 1 then
+			tab.jewelPanels[i]:SetPoint("TOPLEFT", "AmrBadGemSlot" .. (i-1), "BOTTOMLEFT", -12, -5)
+			--tab.jewelPanels[i]:SetPoint("TOPLEFT")
+		else
+			tab.jewelPanels[i]:SetPoint("TOPLEFT", "AmrBadGemSlot" .. (i-1), "BOTTOMLEFT", 0, -5)
+		end
+		tab.jewelPanels[i]:SetPoint("RIGHT", -40, 0)
+	end
+
+	return tab
+end
+
+function AskMrRobot.GemTab:startAutoGem()
+	if AskMrRobot.AutoGem(self.preferPerfects) == false then 
+		StaticPopup_Show("AUTOGEM_ONCE")
+	end
+end
+
+function AskMrRobot.GemTab:Update()
+	self.count = 0
+
+	local i = 1
+	local badGemTotal = 0
+
+	if AskMrRobot.itemDiffs.gems then
+		for slotNum, badGems in AskMrRobot.sortSlots(AskMrRobot.itemDiffs.gems) do
+			self.count = self.count + 1
+			if i <= MAX_SLOTS then
+				self.jewelPanels[i]:Show()
+			end
+			for k, v in pairs(badGems.badGems) do
+				badGemTotal = badGemTotal + 1
+			end
+			i = i + 1
+		end
+	end
+
+	self.gemsTextToOptimize:SetFormattedText("You have %d \1244gem:gems; to optimize", badGemTotal)
+
+	--hide/show the headers, depending on if we have any bad gems
+	if self.count == 0 then
+		self.gemSlotHeader:Hide()
+		self.gemCurrentHeader:Hide()
+		self.gemOptimizedHeader:Hide()
+		self.gemsTextToOptimize:Hide()
+		self.button:Hide()
+		self.usePerfectButton:Hide()
+		self.stamp:Show()
+	else
+		self.gemSlotHeader:Show()
+		self.gemCurrentHeader:Show()
+		self.gemOptimizedHeader:Show()
+		self.gemsTextToOptimize:Show()
+		self.button:Show()
+		self.usePerfectButton:Show()
+		self.stamp:Hide()
+	end	
+
+	for i = self.count + 1, MAX_SLOTS do
+		self.jewelPanels[i]:Hide()
+		i = i + 1
+	end
+
+	AskMrRobot.GemTab.OnUpdate(self.fauxScroll, self.count, #self.jewelPanels, self.jewelPanels[1]:GetHeight())
+end
+
+function AskMrRobot.GemTab.OnVerticalScroll(scrollframe, offset)
+	local self = scrollframe.parent
+	FauxScrollFrame_OnVerticalScroll(self.fauxScroll, offset, self.jewelPanels[1]:GetHeight(), AskMrRobot.GemTab.OnUpdate)
+end
+
+function AskMrRobot.GemTab.OnUpdate(scrollframe)	
+	local self = scrollframe.parent
+	FauxScrollFrame_Update(self.fauxScroll, self.count, #self.jewelPanels, self.jewelPanels[1]:GetHeight())
+	local offset = FauxScrollFrame_GetOffset(scrollframe)
+
+	local i = 1
+	for slotNum, badGems in AskMrRobot.sortSlots(AskMrRobot.itemDiffs.gems) do
+		if offset > 0 then
+			offset = offset - 1
+		else
+
+			if i > MAX_SLOTS then
+				break
+			end
+
+			self.jewelPanels[i]:SetItemLink(_G[strupper(AskMrRobot.slotNames[slotNum])], badGems.current.link )
+			self.jewelPanels[i]:SetOptimizedGems(badGems.optimized, badGems.badGems)
+			i = i + 1
+		end
+	end
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/HelpTab.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,37 @@
+local _, AskMrRobot = ...
+
+-- initialize the HelpTab class
+AskMrRobot.HelpTab = AskMrRobot.inheritsFrom(AskMrRobot.Frame)
+
+function AskMrRobot.HelpTab:new(parent)
+
+	local tab = AskMrRobot.Frame:new(nil, parent)
+	setmetatable(tab, { __index = AskMrRobot.HelpTab })
+	tab:SetPoint("TOPLEFT")
+	tab:SetPoint("BOTTOMRIGHT")
+	tab:Hide()
+
+	local text = tab:CreateFontString("AmrHelpText1", "ARTWORK", "GameFontNormalLarge")
+	text:SetPoint("TOPLEFT", 0, -5)
+	text:SetText("Help")
+
+	local text2 = tab:CreateFontString(nil, "ARTWORK", "GameFontWhite")
+	text2:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 0, -20)
+	text2:SetPoint("RIGHT", tab, "RIGHT", -25, -20)
+	text2:SetWidth(text2:GetWidth())
+	text2:SetText("Visit |c003333ffhttp://blog.askmrrobot.com/addon/|r  for a full tutorial and to ask questions.\r\r" ..
+                  "|c00999999Q:|r Do I have to get a new text-string every time I need to optimize?\r" ..
+                  '|c0066dd66A:|r Yes. Go to the website and click the green "Update from Armory" button to the left of your character to make sure you have the most up-to-date gear. Optimize your gear and then click the "Export to Addon" button to get your new text-string.\r\r' ..
+				  "|c00999999Q:|r The belt buckle didn't show up in my list.\r" ..
+                  "|c0066dd66A:|r Correct, it's actually quite hard to detect it's status in-game, believe it or not. But we're working on a clever way to detect it!\r\r"..
+                  "|c00999999Q:|r My cogwheels/tinkers didn't show up.\r"..
+                  "|c0066dd66A:|r Correct, we're working on adding those into the list as well... the problem is Mr. Robot has been using them to build other robots...\r\r"..
+                  "|c00999999Q:|r Can I send my shopping list to an alt?\r"..
+                  '|c0066dd66A:|r Yes, go to the shopping list tab and select the "mail" option in the drop down. You can mail the list to your alt.\r\r'..
+                  "|c00999999Q:|r I am in the middle of a raid and just won a piece of loot. Can I optimize really quick\r"..
+                  "|c0066dd66A:|r Yes! You'll want to read the tutorial on that here: |c003333ffhttp://blog.askmrrobot.com/addon#raid|r")
+	--text2:SetHeight(100)
+	text2:SetJustifyH("LEFT")
+
+	return tab
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/ImportTab.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,64 @@
+local _, AskMrRobot = ...
+
+-- initialize the ImportTab class
+AskMrRobot.ImportTab = AskMrRobot.inheritsFrom(AskMrRobot.Frame)
+
+function AskMrRobot.ImportTab:new(parent)
+
+	local tab = AskMrRobot.Frame:new(nil, parent)
+	setmetatable(tab, { __index = AskMrRobot.ImportTab })
+	tab:SetPoint("TOPLEFT")
+	tab:SetPoint("BOTTOMRIGHT")
+	tab:Hide()
+
+	-- import button
+	tab.button = CreateFrame("Button", "AmrImportButton", tab, "UIPanelButtonTemplate")	
+	tab.button:SetPoint("BOTTOM")
+	tab.button:SetText("Import!")
+	tab.button:SetWidth(100)
+	tab.button:SetHeight(20)
+	tab.button:SetPoint("BOTTOM", 0, 15)
+
+	local text = tab:CreateFontString("AmrImportText1", "ARTWORK", "GameFontNormalLarge")
+	text:SetPoint("TOPLEFT", 0, -5)
+	text:SetFormattedText("Import Mr. Robot's optimizations")
+
+	text = tab:CreateFontString("AmrImportText2", "ARTWORK", "GameFontWhite")
+	text:SetPoint("TOPLEFT", "AmrImportText1", "BOTTOMLEFT", 0, -20)
+	text:SetPoint("RIGHT", 0, -20)
+	text:SetWidth(text:GetWidth())
+	text:SetJustifyH("LEFT")
+	text:SetText("1. Go to our website, optimize, then click the 'export to addon' button found just above the stats section.")
+
+	local image = tab:CreateTexture(nil, "BACKGROUND")
+	image:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 16, -10)
+	image:SetTexture("Interface\\AddOns\\AskMrRobot\\Media\\AddonExport")
+	image:SetSize(256, 256)
+
+	text = tab:CreateFontString("AmrImportText3", "ARTWORK", "GameFontWhite")
+	text:SetPoint("TOPLEFT", image, "BOTTOMLEFT", -16, 24)
+	text:SetPoint("RIGHT", -15, 40)
+	text:SetWidth(text:GetWidth())
+	text:SetJustifyH("LEFT")
+	text:SetText("2. A window will popup, copy the text from that window.\r\r3. Return here and paste the text into the window below. To paste it, hold ctrl + v, or on a mac apple + v.\r\r4. Click the 'Import' button below")
+
+	local scrollFrame = CreateFrame("ScrollFrame", "AmrImportScrollFrame", tab, "InputScrollFrameTemplate")
+	scrollFrame:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 5, -10)
+	scrollFrame:SetPoint("BOTTOM", "AmrImportButton", "TOP", 0, 10)
+	scrollFrame:SetPoint("RIGHT", -30, 0)
+	scrollFrame:SetWidth(430)
+	scrollFrame.EditBox:SetWidth(scrollFrame:GetWidth())
+	scrollFrame.EditBox:SetMaxLetters(1100)
+	scrollFrame.CharCount:Hide()
+	scrollFrame.EditBox.PromptText:SetText("Paste text from AskMrRobot.com here.")
+	scrollFrame.EditBox:SetFocus()
+	scrollFrame.EditBox:HighlightText()
+	tab.scrollFrame = scrollFrame
+	
+	tab:SetScript("OnShow", function()
+		tab.scrollFrame.EditBox:HighlightText()
+		tab.scrollFrame.EditBox:SetFocus()
+	end)
+
+	return tab	
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/ItemIcon.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,40 @@
+local _, AskMrRobot = ...
+
+-- initialize the ItemIcon class (inherit from a dummy frame)
+AskMrRobot.ItemIcon = AskMrRobot.inheritsFrom(AskMrRobot.ItemTooltipFrame)
+
+-- item icon contructor
+function AskMrRobot.ItemIcon:new(name, parent)
+	-- create a new frame (if one isn't supplied)
+	local o = AskMrRobot.ItemTooltipFrame:new(name, parent)
+
+	-- use the ItemIcon class
+	setmetatable(o, { __index = AskMrRobot.ItemIcon })
+
+	-- the item icon
+	o.itemIcon = o:CreateTexture(nil, "BACKGROUND")
+	o.itemIcon:SetPoint("TOPLEFT")
+	o.itemIcon:SetPoint("BOTTOMRIGHT")
+
+	-- return the instance of the ItemIcon
+	return o
+end
+
+function AskMrRobot.ItemIcon:SetRoundBorder()
+	self:SetBackdrop({edgeFile = "Interface\\AddOns\\AskMrRobot\\Media\\round-edge", edgeSize = 8})
+end
+
+function AskMrRobot.ItemIcon:SetSquareBorder()
+	self:SetBackdrop({edgeFile = "Interface\\AddOns\\AskMrRobot\\Media\\square-edge", edgeSize = 8})
+end
+
+-- set the item icon and tooltip from the specified item link
+function AskMrRobot.ItemIcon:SetItemLink(link)
+	AskMrRobot.ItemTooltipFrame.SetItemLink(self, link)
+	if link then
+		self.itemIcon:SetTexture(GetItemIcon(AskMrRobot.getItemIdFromLink(link)))
+		self.itemIcon:SetTexCoord(0, 1, 0, 1)
+	else
+		self.itemIcon:SetTexture(nil)
+	end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/ItemLinkText.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,60 @@
+local _, AskMrRobot = ...
+
+AskMrRobot.ItemLinkText = AskMrRobot.inheritsFrom(AskMrRobot.ItemTooltipFrame)
+
+function AskMrRobot.ItemLinkText:new(name, parent)
+	local o = AskMrRobot.ItemTooltipFrame:new(name, parent)
+
+	-- use the ItemLinkText class
+	setmetatable(o, { __index = AskMrRobot.ItemLinkText })
+
+	-- the item text
+	o.itemText = AskMrRobot.FontString:new(o, nil, "ARTWORK", "GameFontWhite")
+	o.itemText:SetPoint("TOPLEFT")
+	o.itemText:SetPoint("BOTTOMRIGHT")
+	o.itemText:SetJustifyH("LEFT")
+
+	return o
+end
+
+function AskMrRobot.ItemLinkText:SetFormat(formatText)
+	self.formatText = formatText
+end
+
+function AskMrRobot.ItemLinkText:SetItemId(itemId, upgradeId, suffixId)
+	AskMrRobot.ItemTooltipFrame.SetItemLink(self, link)
+	self.itemName = nil
+	if itemId > 0 then
+		local linkTemplate = "item:%d:0:0:0:0:0:%d:0:%d:0:%d"
+		local itemName, itemLink = GetItemInfo(linkTemplate:format(itemId, suffixId, UnitLevel("player"), upgradeId))
+		self:SetItemLink(itemLink)
+		if itemLink then
+			self.itemName = itemName
+			if self.formatText then
+				self.itemText:SetFormattedText(self.formatText, itemLink:gsub("%[", ""):gsub("%]", ""))
+			else
+				self.itemText:SetText(itemLink:gsub("%[", ""):gsub("%]", ""))
+			end
+		else
+			self.itemText:SetFormattedText("unknown (%d)", itemId)
+			self.itemText:SetTextColor(1,1,1)
+			AskMrRobot.RegisterItemInfoCallback(itemId, function(name, itemLink2)
+				if self.formatText then
+					self.itemText:SetFormattedText(self.formatText, itemLink2:gsub("%[", ""):gsub("%]", ""))
+				else
+					self.itemText:SetText(itemLink2:gsub("%[", ""):gsub("%]", ""))
+				end
+				self:SetItemLink(itemLink2)
+				self.itemName = name
+			end)
+		end
+	else
+		self.itemText:SetText("empty")
+		self.itemText:SetTextColor(0.5,0.5,0.5)
+		self:SetItemLink(nil)
+	end
+end
+
+function AskMrRobot.ItemLinkText:SetFontSize(fontSize)
+	self.itemText:SetFontSize(fontSize)
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/ItemTooltipFrame.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,46 @@
+local _, AskMrRobot = ...
+
+-- initialize the ItemLink class
+AskMrRobot.ItemTooltipFrame = AskMrRobot.inheritsFrom(AskMrRobot.Frame)
+
+-- item link contructor
+function AskMrRobot.ItemTooltipFrame:new(name, parent)
+	-- create a new frame
+	local o = AskMrRobot.Frame:new(name, parent)
+
+	-- use the ItemTooltipFrame class
+	setmetatable(o, { __index = AskMrRobot.ItemTooltipFrame })
+
+	o.tooltipShown = false
+
+	-- initialize the enter/leave scripts for showing the tooltips
+	o:SetScript("OnEnter", AskMrRobot.ItemTooltipFrame.OnEnterTooltipFrame)
+	o:SetScript("OnLeave", AskMrRobot.ItemTooltipFrame.OnLeaveTooltipFrame)
+
+	-- return the instance of the ItemTooltipFrame
+	return o
+end
+
+function AskMrRobot.ItemTooltipFrame:OnEnterTooltipFrame()
+	if self.itemLink then
+		GameTooltip:SetOwner(self, "ANCHOR_CURSOR")
+
+		GameTooltip:SetHyperlink(self.itemLink)
+
+		GameTooltip:Show()
+		self.tooltipShown = true
+	end
+end
+
+function AskMrRobot.ItemTooltipFrame:OnLeaveTooltipFrame()
+	GameTooltip:Hide()
+	self.tooltipShown = false
+end
+
+-- set the tooltip from the specified item link
+function AskMrRobot.ItemTooltipFrame:SetItemLink(link)
+	if self.tooltipShown then
+		GameTooltip:Hide()
+	end
+	self.itemLink = link
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/JewelPanel.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,186 @@
+local _, AskMrRobot = ...
+
+local MAX_GEMS_PER_SLOT = 3
+
+-- make the JewelPanel inherit from a dummy frame
+AskMrRobot.JewelPanel = AskMrRobot.inheritsFrom(AskMrRobot.Frame)
+
+-- JewelPanel constructor
+function AskMrRobot.JewelPanel:new (name, parent)
+	-- create a new frame if one isn't supplied
+	local o = AskMrRobot.Frame:new(name, parent)
+
+	-- make the object a JewelPanel instanct
+	setmetatable(o, { __index = AskMrRobot.JewelPanel})
+
+	-- set the height and border of the newly created jewel frame
+	o:SetHeight(95)
+	o:SetBackdrop({edgeFile = "Interface/Tooltips/UI-Tooltip-Border", edgeSize = 16})
+
+	-- setup the slot name
+	o._slotName = o:CreateFontString(nil, "ARTWORK", "GameFontWhite")
+	o._slotName:SetPoint("TOPLEFT", 11, -10)
+	o._slotName:SetWidth(80)
+	o._slotName:SetJustifyH("LEFT")
+
+	-- setup the item icon frame
+	o._itemIcon = AskMrRobot.ItemIcon:new()
+	o._itemIcon:SetParent(o)
+	o._itemIcon:SetRoundBorder()
+	o._itemIcon:SetPoint("TOPLEFT", 9, -32)
+	o._itemIcon:SetWidth(48)
+	o._itemIcon:SetHeight(48)
+
+	-- initialize the current gems array
+	o._currentGems = {}
+	o._optimizedGemText = {}
+	o._optimizedGemIcons = {}
+	-- for each row of gems
+	for i = 1, MAX_GEMS_PER_SLOT do
+		-- create an item icon for the currently equiped gem
+		local gemIcon = AskMrRobot.GemIcon:new(nil, o)
+		gemIcon:SetPoint("TOPLEFT", 100, 18 - 27 * i)
+		gemIcon:SetWidth(24)
+		gemIcon:SetHeight(24)
+		gemIcon:SetRoundBorder()
+		o._currentGems[i] = gemIcon
+
+		-- create an item icon for the optimized gem
+		gemIcon = AskMrRobot.GemIcon:new(nil, o)
+		gemIcon:SetPoint("TOPLEFT", 170, 18 - 27 * i)
+		gemIcon:SetWidth(24)
+		gemIcon:SetHeight(24)
+		gemIcon:SetRoundBorder()
+		o._optimizedGemIcons[i] = gemIcon		
+
+		-- create the optimized gem text
+		local gemText = o:CreateFontString(nil, "ARTWORK", "GameFontWhite")		
+		gemText:SetPoint("TOPLEFT", 200, 12 - 27 * i)
+		gemText:SetPoint("RIGHT", -30)
+		gemText:SetJustifyH("LEFT")
+		o._optimizedGemText[i] = gemText
+	end	
+
+	-- return the JewelPanel instance
+	return o
+end
+
+-- set the item link for this JewelPanel
+-- this updates the item icon, the slot name, and the tooltip
+function AskMrRobot.JewelPanel:SetItemLink(slotName, itemLink)
+	-- set the item icon and the tooltip
+	self._itemIcon:SetItemLink(itemLink)
+
+	if itemLink then
+		local _, _, rarity = GetItemInfo(itemLink)
+		if rarity then
+			local r,g,b = GetItemQualityColor(rarity)
+			self._itemIcon:SetBackdropBorderColor(r,g,b,1)
+		else
+			self._itemIcon:SetBackdropBorderColor(1,1,1,1)
+		end
+	else
+		self._itemIcon:SetBackdropBorderColor(1,1,1,1)
+	end
+
+	-- set the slot name
+	self._slotName:SetText(slotName)
+end
+
+-- set the optimized gem information (array of {id, color, enchantId})
+-- SetItemLink must be called first
+function AskMrRobot.JewelPanel:SetOptimizedGems(optimizedGems, showGems)
+
+	-- get the item link
+	local itemLink = self._itemIcon.itemLink
+
+	if not itemLink then return end
+
+	-- for all of the gem rows in this control
+	local itemId = AskMrRobot.getItemIdFromLink(itemLink)
+
+	local gemCount = 0
+
+	for i = 1, MAX_GEMS_PER_SLOT do
+		-- get the optimized text, optimized icon, and current icon for the row
+		local text = self._optimizedGemText[i]
+		local optimizedIcon = self._optimizedGemIcons[i]
+		local currentIcon = self._currentGems[i]
+
+		-- get the current gem in the specified slot
+		local currentGemLink = select(2, GetItemGem(itemLink, i))
+
+		-- if there is a gem to add (or remove)
+		--if i <= #optimizedGems or currentGemLink then
+		if i <= #optimizedGems or currentGemLink then
+			-- set the current gem icon / tooltip
+			currentIcon:SetItemLink(currentGemLink)
+
+			local currentGemId = AskMrRobot.getItemIdFromLink(currentGemLink)
+
+			local optimizedGemLink = nil
+			if i <= #optimizedGems then
+				-- make a link for the optimized gem
+				optimizedGemLink = select(2, GetItemInfo(optimizedGems[i].id))
+
+				if not optimizedGemLink and optimizedGems[i].id and itemId then
+					AskMrRobot.RegisterItemInfoCallback(optimizedGems[i].id, function(name, link)
+						optimizedIcon:SetItemLink(link)
+					end)
+				end
+			end
+			
+			if showGems[i] and optimizedGems[i] and optimizedGems[i].color then
+				gemCount = gemCount + 1
+				-- set the optimized gem text
+				text:SetTextColor(1,1,1)
+				text:SetText(AskMrRobot.alternateGemName[optimizedGems[i].id] or (optimizedGems[i].enchantId ~= 0 and AskMrRobot.getEnchantName(optimizedGems[i].enchantId)) or GetItemInfo(optimizedGems[i].id))
+				currentIcon:Show()
+
+				-- load the item image / tooltip
+				optimizedIcon:SetItemLink(optimizedGemLink)
+				optimizedIcon:Show()
+				optimizedIcon:SetBackdropBorderColor(1,1,1)
+				currentIcon:SetBackdropBorderColor(1,1,1)
+			else
+				if optimizedGems[i] and optimizedGems[i].color then
+					text:SetText("no change")
+					text:SetTextColor(0.5,0.5,0.5)
+					currentIcon:Show()
+					gemCount = gemCount + 1
+				else
+					text:SetText('')
+					currentIcon:Hide()
+				end
+				optimizedIcon:SetItemLink(nil)
+				optimizedIcon:Hide()
+			end
+
+			currentIcon:SetGemColor(optimizedGems[i] and optimizedGems[i].color)
+			optimizedIcon:SetGemColor(optimizedGems[i] and optimizedGems[i].color)
+
+			-- show the gem row
+			text:Show()			
+		else
+			-- hide the gem row
+			text:Hide()
+			optimizedIcon:Hide()
+			currentIcon:Hide()
+		end		
+	end
+
+	local y1 = 0
+	local y2 = 0
+	if gemCount == 1 then
+		y1 = 27
+	elseif gemCount == 2 then
+		y1 = 9
+		y2 = 4
+	end
+
+	for i = 1, MAX_GEMS_PER_SLOT do
+		self._optimizedGemText[i]:SetPoint("TOPLEFT", 200, 12 - (27 + y2) * i - y1)
+		self._optimizedGemIcons[i]:SetPoint("TOPLEFT", 170, 18 - (27 + y2) * i - y1)
+		self._currentGems[i]:SetPoint("TOPLEFT", 100, 18 - (27 + y2) * i - y1)
+	end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/ReforgesTab.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,504 @@
+local _, AskMrRobot = ...
+
+--------------------------------------------------------------------
+-- Local Reforge Utility Code
+--------------------------------------------------------------------
+
+StaticPopupDialogs["REFORGE_TAB_PLEASE_OPEN"] = {
+	text = "You need to open the reforge window for this to work",
+	button1 = "Ok",
+	timeout = 0,
+	whileDead = true,
+	hideOnEscape = true,
+	preferredIndex = 3,  -- avoid some UI taint, see http://www.wowace.com/announcements/how-to-avoid-some-ui-taint/
+}
+
+--from LibReforge
+local SPI = 1
+local DODGE = 2
+local PARRY = 3
+local HIT = 4
+local CRIT = 5
+local HASTE = 6
+local EXP = 7
+local MASTERY = 8
+
+--from LibReforge
+local StatNames = {
+	ITEM_MOD_SPIRIT_SHORT,
+	ITEM_MOD_DODGE_RATING_SHORT,
+	ITEM_MOD_PARRY_RATING_SHORT,
+	ITEM_MOD_HIT_RATING_SHORT,
+	ITEM_MOD_CRIT_RATING_SHORT,
+	ITEM_MOD_HASTE_RATING_SHORT,
+	ITEM_MOD_EXPERTISE_RATING_SHORT,
+	ITEM_MOD_MASTERY_RATING_SHORT
+}
+StatNames[0] = NONE
+local StatToString = {
+	"ITEM_MOD_SPIRIT_SHORT",
+	"ITEM_MOD_DODGE_RATING_SHORT",
+	"ITEM_MOD_PARRY_RATING_SHORT",
+	"ITEM_MOD_HIT_RATING_SHORT",
+	"ITEM_MOD_CRIT_RATING_SHORT",
+	"ITEM_MOD_HASTE_RATING_SHORT",
+	"ITEM_MOD_EXPERTISE_RATING_SHORT",
+	"ITEM_MOD_MASTERY_RATING_SHORT"
+}
+
+
+local REFORGE_TABLE_BASE = 112
+local REFORGE_TABLE = {
+  {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}, {1, 7}, {1, 8},
+  {2, 1}, {2, 3}, {2, 4}, {2, 5}, {2, 6}, {2, 7}, {2, 8},
+  {3, 1}, {3, 2}, {3, 4}, {3, 5}, {3, 6}, {3, 7}, {3, 8},
+  {4, 1}, {4, 2}, {4, 3}, {4, 5}, {4, 6}, {4, 7}, {4, 8},
+  {5, 1}, {5, 2}, {5, 3}, {5, 4}, {5, 6}, {5, 7}, {5, 8},
+  {6, 1}, {6, 2}, {6, 3}, {6, 4}, {6, 5}, {6, 7}, {6, 8},
+  {7, 1}, {7, 2}, {7, 3}, {7, 4}, {7, 5}, {7, 6}, {7, 8},
+  {8, 1}, {8, 2}, {8, 3}, {8, 4}, {8, 5}, {8, 6}, {8, 7},
+}
+
+--------------- returns the index into the REFORGE_TABLE or nil
+-- returns the reforge id or 0
+local function GetReforgeIdForItem(item)
+  local id = tonumber(item:match("item:%d+:%d+:%d+:%d+:%d+:%d+:%-?%d+:%-?%d+:%d+:(%d+)"))
+  return (id and id ~= 0 and id or 0)
+end
+
+local function GetReforgeIdFromStats(fromStat, toStat)
+	if (toStat > fromStat) then
+		return REFORGE_TABLE_BASE + 7 * (fromStat - 1) + toStat - 1;
+	else
+		return REFORGE_TABLE_BASE + 7 * (fromStat - 1) + toStat;
+	end
+end
+
+
+--------------------------------------------------------------------
+-- Initialization
+--------------------------------------------------------------------
+AskMrRobot.ReforgesTab = AskMrRobot.inheritsFrom(AskMrRobot.Frame)
+
+function AskMrRobot.ReforgesTab:new(parent)
+
+	local tab = AskMrRobot.Frame:new(nil, parent)
+	setmetatable(tab, { __index = AskMrRobot.ReforgesTab })
+	tab:SetPoint("TOPLEFT")
+	tab:SetPoint("BOTTOMRIGHT")
+	tab:Hide()
+
+	local text = tab:CreateFontString("AmrReforgesHeader", "ARTWORK", "GameFontNormalLarge")
+	text:SetPoint("TOPLEFT", 0, -5)
+	text:SetText("Reforges")
+
+	tab.stamp = AskMrRobot.RobotStamp:new(nil, tab)
+	tab.stamp:Hide()
+	tab.stamp.smallText:SetText("Your reforges are 100% optimal!")
+	tab.stamp:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 2, -15)
+	tab.stamp:SetPoint("RIGHT", tab, "RIGHT", -20, 0)
+
+	tab.reforgeDetails = tab:CreateFontString("AmrReforgeDetails", "ARTWORK", "GameFontWhite")
+	tab.reforgeDetails:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 0, -15)
+	tab.reforgeDetails:SetPoint("RIGHT", -30, 0)
+	tab.reforgeDetails:SetWordWrap(true)
+	tab.reforgeDetails:SetJustifyH("LEFT")
+	tab.reforgeDetails:SetText('Open a reforge window, then click the "Reforge!" button to do it automatically.')
+	tab.reforgeDetails:SetHeight(50)
+
+	tab.reforgeButton = CreateFrame("Button", "AmrReforgeButton", tab, "UIPanelButtonTemplate")
+	tab.reforgeButton:SetText("Reforge!")
+	tab.reforgeButton:SetPoint("TOPLEFT", 0, -80)
+	tab.reforgeButton:SetWidth(140)
+	tab.reforgeButton:SetHeight(20)
+	tab.reforgeButton:SetScript("OnClick", function()
+		tab:OnReforge()
+	end)
+
+	tab.reforgeCost = tab:CreateFontString(nil, "ARTWORK", "GameFontNormal")
+	tab.reforgeCost:SetPoint("TOPLEFT", tab.reforgeButton, "TOPRIGHT", 25, 0)
+	tab.reforgeCost:SetPoint("BOTTOM", tab.reforgeButton, "BOTTOM", 0, 0)
+	tab.reforgeCost:SetPoint("RIGHT", tab, "RIGHT", -30, 0)
+	tab.reforgeCost:SetText('')
+
+	tab.slotHeader = tab:CreateFontString(nil, "ARTWORK", "GameFontNormal")
+	tab.slotHeader:SetText("Slot")
+	tab.slotHeader:SetPoint("TOPLEFT", tab.reforgeButton, "BOTTOMLEFT", 0, -30)
+
+	tab.reforgeHeader = tab:CreateFontString(nil, "ARTWORK", "GameFontNormal")
+	tab.reforgeHeader:SetText("Optimal Reforge")
+	tab.reforgeHeader:SetPoint("TOPLEFT", tab.slotHeader, "TOPLEFT", 100, 0)
+
+	-- pre-allocate a visual element for all possible slots; showBadReforges will set text and show the number that are needed, and hide the rest
+	tab.slots = {}
+	tab.optimized = {}
+
+	for i = 1, #AskMrRobot.slotNames do
+		tab.slots[i] = tab:CreateFontString(nil, "ARTWORK", "GameFontWhite")
+		tab.slots[i]:SetPoint("TOPLEFT", tab.slotHeader, "TOPLEFT", 0, -20 * i)
+		tab.slots[i]:Hide()
+
+		tab.optimized[i] = tab:CreateFontString(nil, "ARTWORK", "GameFontWhite")
+		tab.optimized[i]:SetPoint("TOPLEFT", tab.reforgeHeader, "TOPLEFT", 0, -20 * i)
+		tab.optimized[i]:Hide()
+	end
+
+	tab:RegisterEvent("FORGE_MASTER_ITEM_CHANGED")
+	tab:RegisterEvent("FORGE_MASTER_SET_ITEM")
+	tab:RegisterEvent("FORGE_MASTER_OPENED")
+	tab:RegisterEvent("FORGE_MASTER_CLOSED")
+
+	tab:SetScript("OnEvent", function(...)
+		tab:OnEvent(...)
+	end)
+
+
+	-- initialize stat required for performing the reforges
+	tab.state = {}
+	tab:ResetState()
+
+
+	return tab
+end
+
+
+--------------------------------------------------------------------
+-- Rendering
+--------------------------------------------------------------------
+
+local function GetReforgeString(fromId, toId)
+	if toId == 0 then
+		return "Restore"
+	end
+	local pair = REFORGE_TABLE[toId - REFORGE_TABLE_BASE]
+
+	local text = _G[StatToString[pair[1]]] .. ' -> ' .. _G[StatToString[pair[2]]]
+	--print('from ' .. fromId)
+	if fromId == 0 then
+		return text
+	end
+	return 'Restore, then ' .. text
+end
+
+-- draw all of the reforges that still need to be performed
+function AskMrRobot.ReforgesTab:Render()
+
+	local reforges = AskMrRobot.itemDiffs.reforges
+	local i = 1
+	local cost = 0
+
+	-- for all the bad items
+	for slotNum, badReforge in AskMrRobot.sortSlots(reforges) do
+
+		self.optimized[i]:SetText(GetReforgeString(badReforge.current, badReforge.optimized))
+		self.optimized[i]:Show()
+
+		self.slots[i]:SetText(_G[strupper(AskMrRobot.slotNames[slotNum])])
+		self.slots[i]:Show()
+
+		-- Restore is free, so only add cost for non-restore reforges
+		if badReforge.optimized > 0 then
+			local slotId = AskMrRobot.slotIds[slotNum]
+			local itemLink = GetInventoryItemLink("player", slotId)
+			cost = cost + (itemLink and select (11, GetItemInfo(itemLink)) or 0)
+		end
+
+		i = i + 1
+	end
+
+	self.reforgeCost:SetText("Total reforge cost: ~" .. math.ceil(cost / 10000) .. " Gold")
+
+	-- hide / show the headers
+	if i == 1 then
+		self.reforgeHeader:Hide()
+		self.slotHeader:Hide()
+		self.reforgeButton:Hide()
+		self.reforgeCost:Hide()
+		self.reforgeDetails:Hide()
+		self.stamp:Show()
+	else
+		self.stamp:Hide()
+		self.reforgeButton:Show()
+		self.reforgeCost:Show()
+		self.reforgeHeader:Show()
+		self.reforgeDetails:Show()
+		self.slotHeader:Show()
+	end
+
+	-- hide the remaining slots
+	while i <= #self.slots do
+		self.optimized[i]:Hide()
+		self.slots[i]:Hide()
+		i = i + 1
+	end
+end
+
+--------------------------------------------------------------------
+-- Reforge Logic
+--------------------------------------------------------------------
+
+-- reset state for a fresh pass at automatic reforging
+function AskMrRobot.ReforgesTab:ResetState()
+
+	self.state.queue = {}           -- list of all reforges actions that still need to be performed
+	self.state.currentItem = nil    -- the current item we are trying to reforge
+	self.state.pendingSlot = nil    -- the slot that we have requested to place into the reforger
+	self.state.currentSlot = nil    -- the current slot in the reforger
+	self.state.pendingReforge = -1  -- the reforge that we have requested to perform on the current item
+end
+
+-- refresh the queue of reforges that still need to be performed
+function AskMrRobot.ReforgesTab:RefreshQueue()
+
+	-- clear the queue
+	self.state.queue = {}
+
+	local reforges = AskMrRobot.itemDiffs.reforges
+
+	-- add all reforges that need updating to the reforge queue
+	for slotNum, badReforge in AskMrRobot.sortSlots(reforges) do
+		self:AddToReforgeQueue(slotNum, badReforge.optimized);
+	end
+end
+
+function AskMrRobot.ReforgesTab:AddToReforgeQueue(itemSlot, reforgeId)
+
+	-- the game's slot id, not the same as the ids that we use on our servers
+	local gameSlot = AskMrRobot.slotIds[itemSlot]
+	
+	local item = GetInventoryItemLink("player", gameSlot)
+	if item == nil then 
+		--print ('no item')
+		return 
+	end
+
+	local current = GetReforgeIdForItem(item)
+
+	if current ~= reforgeId then
+		-- restore first
+		if current ~= 0 and reforgeId ~= 0 then
+			tinsert(self.state.queue, { ["slot"] = gameSlot, ["reforge"] = 0 })
+		end
+
+		-- then reforge to the specified reforge
+		tinsert(self.state.queue, { ["slot"] = gameSlot, ["reforge"] = reforgeId })
+	end
+end
+
+function AskMrRobot.ReforgesTab:IsQueueEmpty()
+	return self.state.queue == nil or #self.state.queue == 0 or self.state.queue == {};
+end
+
+-- returns true if we are waiting on the game to finish a pending async reforge operation
+function AskMrRobot.ReforgesTab:HasPendingOperation()
+
+	-- waiting for an item to be placed into the reforger
+	if self.state.pendingSlot then
+		return true
+	end
+
+	-- waiting for a reforge to be completed
+	if self.state.pendingReforge ~= -1 then
+		return true
+	end
+
+	return false
+end
+
+-- put the next item in the reforge queue into the game's reforge UI
+function AskMrRobot.ReforgesTab:PutNextItemInForge()
+
+	if self:IsQueueEmpty() or self:HasPendingOperation() then
+		return
+	end
+	
+	-- get the first action in the queue
+	local currentAction = self.state.queue[1]
+	local itemSlot = currentAction.slot
+
+	local item = GetInventoryItemLink("player", itemSlot)
+		
+	-- set current item that we are trying to reforge
+	self.state.currentItem = item
+
+	-- if this item isn't already in the reforger, put it in
+	if self.state.currentSlot ~= itemSlot then
+		ClearCursor()                 -- make sure no item is selected
+		SetReforgeFromCursorItem()    -- pick up the old item (calling this with an item already in the reforger will put it back on the mouse cursor)
+		ClearCursor()                 -- clear the cursor to finish removing any current item from the game reforge UI
+		PickupInventoryItem(itemSlot) -- pick up the right equipped item
+
+		-- pending, listen for an event from the game to complete setting this item into the reforger
+		self.state.pendingSlot = itemSlot
+
+		SetReforgeFromCursorItem()    -- put the item into the reforger, and wait for the FORGE_MASTER_SET_ITEM event, which calls DoReforge
+ 	end
+
+end
+
+-- an item is in the reforger, ready to be reforged, so do it
+function AskMrRobot.ReforgesTab:DoReforge()
+
+	if self:IsQueueEmpty() or self:HasPendingOperation() then
+		return
+	end
+
+	local currentAction = self.state.queue[1]
+	local desiredReforge = currentAction.reforge
+
+	-- the index that needs to be provided to WoW's ReforgeItem method, corresponds to one of the options in the game reforge UI
+	local reforgeIndex = -1
+
+	if desiredReforge ~= 0 then
+		local targetFrom = REFORGE_TABLE[desiredReforge - REFORGE_TABLE_BASE][1];
+		local targetTo = REFORGE_TABLE[desiredReforge - REFORGE_TABLE_BASE][2];
+
+		for i=1, GetNumReforgeOptions() do
+			local from, _, _, to, _, _ = GetReforgeOptionInfo(i)
+	 		--print(i .. ': ' .. from .. " -> " .. to)
+			if StatNames[targetFrom] == from and StatNames[targetTo] == to then
+				reforgeIndex = i
+				break
+			end
+		end
+	else
+		reforgeIndex = 0
+	end
+
+	if reforgeIndex == -1 then
+		-- we couldn't do this reforge... we either had a bad reforge (wrong stats on an item), or the game had no options in the UI for some reason
+
+		-- remove the item from the reforge window
+		ClearCursor()
+		SetReforgeFromCursorItem()
+		ClearCursor()
+
+		-- reset state and quit reforging (clears the queue)
+		self:ResetState()
+
+	else
+
+		local currentReforge = GetReforgeIdForItem(self.state.currentItem);
+		if currentReforge == desiredReforge then
+			-- we already have this reforge on the item... probably shouldn't ever happen, but if it does, recalculate and start over
+			tremove(self.state.queue, 1)
+
+			-- remove the item from the reforge window
+			ClearCursor()
+			SetReforgeFromCursorItem()
+			ClearCursor()
+
+			-- update the state of the entire UI, and start again with the next required reforge
+			AskMrRobot_ReforgeFrame:OnUpdate()
+			self:OnReforge()
+
+		else
+			-- we have a reforge (or restore) to do, kick it off and wait for CheckReforge to respond to completion
+			self:TryReforge(reforgeIndex)
+		end
+
+	end
+
+end
+
+-- wraps WoW API call to ReforgeItem, fires a manual timeout in case the UI does not raise an event
+function AskMrRobot.ReforgesTab:TryReforge(reforgeIndex)
+
+	-- we have a reforge (or restore) to do, kick it off and wait for FORGE_MASTER_ITEM_CHANGED, which calls CheckReforge
+	self.state.pendingReforge = reforgeIndex
+	ReforgeItem(reforgeIndex)
+
+	-- sometimes the game doesn't send the FORGE_MASTER_ITEM_CHANGED event, so also check after a delay also
+	AskMrRobot.wait(0.250, AskMrRobot.ReforgesTab.CheckReforge, self)
+
+end
+
+-- check that a requested reforge has been completed
+function AskMrRobot.ReforgesTab:CheckReforge()
+
+	if self:IsQueueEmpty() or self.state.pendingReforge == -1 then
+
+		-- responding to a reforge that the user has manually performed, update the UI and terminate any automatic process that is going on
+		AskMrRobot_ReforgeFrame:OnUpdate()
+		self:ResetState()
+
+	else
+		-- responding to a reforge that we have initiated
+
+		local currentReforge, icon, name, quality, bound, cost = GetReforgeItemInfo();
+		if currentReforge == self.state.pendingReforge then
+			tremove(self.state.queue, 1)
+
+			-- remove the item from the reforge window
+			ClearCursor()
+			SetReforgeFromCursorItem()
+			ClearCursor()
+
+			-- update the state of the entire UI, and start again with the next required reforge
+			AskMrRobot_ReforgeFrame:OnUpdate()
+			self:OnReforge()
+		else
+			-- try again
+			self:TryReforge(self.state.pendingReforge)
+		end
+	end
+
+end
+
+
+--------------------------------------------------------------------
+-- Event Handling
+--------------------------------------------------------------------
+
+-- event called when the Mr. Robot Reforge button is clicked, kicks off automatic reforge
+function AskMrRobot.ReforgesTab:OnReforge()
+
+	-- need to be at a reforger for this to work
+	if not self.isReforgeOpen then
+		StaticPopup_Show("REFORGE_TAB_PLEASE_OPEN")
+		return
+	end
+
+	-- reset state and refresh the queue of reforges that still need to be done
+	self:ResetState()
+	self:RefreshQueue()
+
+	-- get goin, put the first item in the reforger
+	self:PutNextItemInForge()
+end
+
+function AskMrRobot.ReforgesTab:On_FORGE_MASTER_SET_ITEM()
+
+	if self.state.pendingSlot then
+		
+		-- we have successfully finished placing an item into the reforger
+		self.state.currentSlot = self.state.pendingSlot
+
+		-- indicate that we are no longer waiting for an item
+		self.state.pendingSlot = nil
+
+		-- now reforge it
+		self:DoReforge()
+	end 
+
+end
+
+function AskMrRobot.ReforgesTab:On_FORGE_MASTER_ITEM_CHANGED()
+	self:CheckReforge()
+end
+
+function AskMrRobot.ReforgesTab:On_FORGE_MASTER_OPENED()
+	self.isReforgeOpen = true
+end
+
+function AskMrRobot.ReforgesTab:On_FORGE_MASTER_CLOSED()
+	self.isReforgeOpen = false
+end
+
+function AskMrRobot.ReforgesTab:OnEvent(frame, event, ...)
+	--print("EVENT " .. event)
+	local handler = self["On_" .. event]
+	if handler then
+		handler(self, ...)
+	end
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/RobotStamp.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,38 @@
+local _, AskMrRobot = ...
+
+-- initialize the RobotStamp class (inherit from Frame)
+AskMrRobot.RobotStamp = AskMrRobot.inheritsFrom(AskMrRobot.Frame)
+
+-- item icon contructor
+function AskMrRobot.RobotStamp:new(name, parent)
+	-- create a new frame (if one isn't supplied)
+	local o = AskMrRobot.Frame:new(name, parent)
+
+	-- use the RobotStamp class
+	setmetatable(o, { __index = AskMrRobot.RobotStamp })
+
+	o:SetPoint("TOPLEFT", parent, "TOPLEFT")
+	o:SetPoint("RIGHT", parent, "RIGHT")
+	o:SetHeight(80);
+
+	o.bigText = o:CreateFontString(nil, "ARTWORK", "GameFontNormalHuge")
+	o.bigText:SetTextColor(7/255, 166/255, 11/255)
+	local file, _, flags = o.bigText:GetFont()
+	o.bigText:SetFont(file, 24, flags)
+	o.bigText:SetText("ROBOT STAMP OF APPROVAL")
+	o.bigText:SetPoint("TOPLEFT", o, "TOPLEFT", 15, -20)
+	o.bigText:SetPoint("RIGHT", o, "RIGHT", -15, 0)
+
+	o.smallText = o:CreateFontString(nil, "ARTWORK", "GameFontWhite")
+	o.smallText:SetText("Your gems are 100% optimal! You are truly, truly outrageous.")
+	o.smallText:SetPoint("TOPLEFT", o.bigText, "BOTTOMLEFT", 0, -7)
+	o.smallText:SetPoint("RIGHT", o, "RIGHT", -15, 0)
+	o.smallText:SetWidth(o.smallText:GetWidth())
+	o.smallText:SetJustifyH("CENTER")
+
+	o:SetBackdrop({edgeFile = "Interface\\AddOns\\AskMrRobot\\Media\\round-edge-big", edgeSize = 16})
+	o:SetBackdropBorderColor(7/255, 166/255, 11/255)
+
+	-- return the instance of the RobotStamp
+	return o
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/ShoppingListTab.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,917 @@
+local _, AskMrRobot = ...
+
+-- initialize the ShoppingListTab class
+AskMrRobot.ShoppingListTab = AskMrRobot.inheritsFrom(AskMrRobot.Frame)
+
+StaticPopupDialogs["SHOPPING_TAB_PLEASE_OPEN"] = {
+	text = "You need to open the mail window for this to work",
+	button1 = "Ok",
+	timeout = 0,
+	whileDead = true,
+	hideOnEscape = true,
+	preferredIndex = 3,  -- avoid some UI taint, see http://www.wowace.com/announcements/how-to-avoid-some-ui-taint/
+}
+
+function AskMrRobot.ShoppingListTab:new(parent)
+
+	local tab = AskMrRobot.Frame:new(nil, parent)
+	setmetatable(tab, { __index = AskMrRobot.ShoppingListTab })
+	tab:SetPoint("TOPLEFT")
+	tab:SetPoint("BOTTOMRIGHT")
+	tab:Hide()
+	tab:RegisterEvent("AUCTION_HOUSE_CLOSED")
+	tab:RegisterEvent("AUCTION_HOUSE_SHOW")
+	tab:RegisterEvent("MAIL_SHOW")
+	tab:RegisterEvent("MAIL_CLOSED")
+
+	tab.isAuctionHouseVisible = false
+
+	tab:SetScript("OnEvent", function(...)
+		tab:OnEvent(...)
+	end)
+
+	tab.shoppingListHeader = AskMrRobot.FontString:new(tab, nil, "ARTWORK", "GameFontNormalLarge")
+	tab.shoppingListHeader:SetPoint("TOPLEFT", 0, -5)
+	tab.shoppingListHeader:SetText("Shopping List")
+
+	tab.shoppingPanel = AskMrRobot.Frame:new(nil, tab)
+	tab.shoppingPanel:SetPoint("TOPLEFT", tab.shoppingListHeader, "BOTTOMLEFT", 0, -10)
+	tab.shoppingPanel:SetPoint("BOTTOMRIGHT", tab, "BOTTOMRIGHT", -20, 17)
+
+
+	tab.sendButton = CreateFrame("Button", "AmrSendButton", tab.shoppingPanel, "UIPanelButtonTemplate")
+	tab.sendButton:SetText("send it!")
+	tab.sendButton:SetPoint("BOTTOMLEFT", 0, 0)
+	tab.sendButton:SetHeight(25)
+	tab.sendButton:SetNormalFontObject("GameFontNormalLarge")
+	tab.sendButton:SetHighlightFontObject("GameFontHighlightLarge")
+	tab.sendButton:SetWidth(150)
+	tab.sendButton:SetScript("OnClick", function()
+		tab:Send()
+	end)
+
+	tab.enchantMaterialsCheckbox = CreateFrame("CheckButton", "AmrEnchantMaterialsCheckbox", tab.shoppingPanel, "ChatConfigCheckButtonTemplate");
+	tab.enchantMaterialsCheckbox:SetChecked(AmrSendSettings.SendEnchantMaterials)
+	tab.enchantMaterialsCheckbox:SetScript("OnClick", function () AmrSendSettings.SendEnchantMaterials = tab.enchantMaterialsCheckbox:GetChecked() end)
+	tab.enchantMaterialsCheckbox:SetPoint("TOPLEFT", tab.sendButton, "TOPLEFT", 0, 25)
+	local text3 = getglobal(tab.enchantMaterialsCheckbox:GetName() .. 'Text')
+	text3:SetFontObject("GameFontHighlightLarge")
+	text3:SetText("Enchant Materials")
+	text3:SetWidth(150)
+	text3:SetPoint("TOPLEFT", tab.enchantMaterialsCheckbox, "TOPRIGHT", 2, -4)
+
+
+	tab.enchantsCheckbox = CreateFrame("CheckButton", "AmrEnchantsCheckbox", tab.shoppingPanel, "ChatConfigCheckButtonTemplate");
+	tab.enchantsCheckbox:SetChecked(AmrSendSettings.SendEnchants)
+	tab.enchantsCheckbox:SetScript("OnClick", function () AmrSendSettings.SendEnchants = tab.enchantsCheckbox:GetChecked() end)
+	tab.enchantsCheckbox:SetPoint("TOPLEFT", tab.sendButton, "TOPLEFT", 0, 50)
+	local text2 = getglobal(tab.enchantsCheckbox:GetName() .. 'Text')
+	text2:SetFontObject("GameFontHighlightLarge")
+	text2:SetText("Enchants")
+	text2:SetWidth(150)
+	text2:SetPoint("TOPLEFT", tab.enchantsCheckbox, "TOPRIGHT", 2, -4)
+
+
+
+	tab.gemsCheckbox = CreateFrame("CheckButton", "AmrGemsCheckbox", tab.shoppingPanel, "ChatConfigCheckButtonTemplate");
+	tab.gemsCheckbox:SetPoint("TOPLEFT", tab.sendButton, "TOPLEFT", 0, 75)
+	tab.gemsCheckbox:SetChecked(AmrSendSettings.SendGems)
+	tab.gemsCheckbox:SetScript("OnClick", function () AmrSendSettings.SendGems = tab.gemsCheckbox:GetChecked() end)
+	local text = getglobal(tab.gemsCheckbox:GetName() .. 'Text')
+	text:SetFontObject("GameFontHighlightLarge")
+	text:SetText("Gems")
+	text:SetWidth(150)
+	text:SetPoint("TOPLEFT", tab.gemsCheckbox, "TOPRIGHT", 2, -4)
+
+
+	tab.sendMessage4 = AskMrRobot.FontString:new(tab.shoppingPanel, nil, "ARTWORK", "GameFontHighlightLarge")
+	tab.sendMessage4:SetText("Include:")
+	tab.sendMessage4:SetPoint("TOPLEFT", tab.gemsCheckbox, "TOPLEFT", 0, 20)
+
+
+	tab.sendMessage3 = AskMrRobot.FontString:new(tab.shoppingPanel, nil, "ARTWORK", "GameFontHighlightLarge")
+	tab.sendMessage3:SetText("Send list to")
+	tab.sendMessage3:SetPoint("TOPLEFT", tab.sendMessage4, "TOPLEFT", 0, 25)
+
+
+	tab.sendMessage2 = AskMrRobot.FontString:new(tab.shoppingPanel, nil, "ARTWORK", "GameFontNormal")
+	tab.sendMessage2:SetTextColor(.5,.5,.5)
+	tab.sendMessage2:SetText("Whisper to a friend or send to a channel, like /raid or /guild.")
+	tab.sendMessage2:SetPoint("TOPLEFT", tab.sendMessage3, "TOPLEFT", 0, 25)
+
+
+	tab.sendMessage1 = AskMrRobot.FontString:new(tab.shoppingPanel, nil, "ARTWORK", "GameFontNormalLarge")
+	tab.sendMessage1:SetTextColor(0,1,0)
+	tab.sendMessage1:SetText("Send to a Jewelcraft or Enchanter friend :)")
+	tab.sendMessage1:SetPoint("TOPLEFT", tab.sendMessage2, "TOPLEFT", 0, 25)
+
+
+	tab.scrollFrame = CreateFrame("ScrollFrame", "AmrScrollFrame", tab.shoppingPanel, "UIPanelScrollFrameTemplate")
+	tab.scrollFrame:SetPoint("TOPLEFT", 0, 0)
+	tab.scrollFrame:SetPoint("RIGHT", -20, 0)
+	tab.scrollFrame:SetPoint("BOTTOM", tab.sendMessage1, "TOP", 0, 10)
+
+	tab.scrollParent = AskMrRobot.Frame:new(nil, tab.shoppingPanel)
+	tab.scrollParent:SetPoint("TOPLEFT", 0, 0)
+	tab.scrollParent:SetWidth(tab:GetWidth() - 20)
+	tab.scrollParent:SetHeight(500)
+	tab.scrollFrame:SetScrollChild(tab.scrollParent)
+
+	-- magic to get the scrollbar to work with the scrollwheel...
+	tab.scrollFrame:SetScript("OnMouseWheel", function(arg1, arg2)
+	 	ScrollFrameTemplate_OnMouseWheel(arg1, arg2, arg1.ScrollBar)
+	end)
+
+	tab.gemsHeader = AskMrRobot.FontString:new(tab.scrollParent, nil, "ARTWORK", "GameFontNormalLarge")
+	tab.gemsHeader:SetText("Gems")
+	tab.gemsHeader:SetPoint("TOPLEFT", tab.scrollParent, "TOPLEFT", 0, 0)
+
+	tab.gemsQuantityHeader = AskMrRobot.FontString:new(tab.scrollParent, nil, "ARTWORK", "GameFontNormalLarge")
+	tab.gemsQuantityHeader:SetText("Total")
+	tab.gemsQuantityHeader:SetPoint("TOPLEFT", tab.scrollParent, "TOPLEFT", 370, 0)
+
+	tab.enchantsHeader = AskMrRobot.FontString:new(tab.scrollParent, nil, "ARTWORK", "GameFontNormalLarge")
+	tab.enchantsHeader:SetText("Enchants")
+
+	tab.enchantsQuantityHeader = AskMrRobot.FontString:new(tab.scrollParent, nil, "ARTWORK", "GameFontNormalLarge")
+	tab.enchantsQuantityHeader:SetText("Total")
+	tab.enchantsQuantityHeader:SetPoint("TOPLEFT", tab.enchantsHeader, "TOPLEFT", 370, 0)
+
+	tab.enchantMaterialsHeader = AskMrRobot.FontString:new(tab.scrollParent, nil, "ARTWORK", "GameFontNormalLarge")
+	tab.enchantMaterialsHeader:SetText("Enchant Materials")
+
+	tab.enchantMaterialsQuantityHeader = AskMrRobot.FontString:new(tab.scrollParent, nil, "ARTWORK", "GameFontNormalLarge")
+	tab.enchantMaterialsQuantityHeader:SetText("Total")
+	tab.enchantMaterialsQuantityHeader:SetPoint("TOPLEFT", tab.enchantMaterialsHeader, "TOPLEFT", 370, 0)
+
+	tab.stamp = AskMrRobot.RobotStamp:new(nil, tab)
+	tab.stamp:Hide()
+	tab.stamp.bigText:SetText("YOUR SHOPPING IS ALL DONE!")
+	tab.stamp.smallText:SetText("Unless you want to buy me a birthday present! I like titanium bolts and robot dogs... Or was it titanium dogs and robot bolts...")
+	tab.stamp:SetPoint("TOPLEFT", tab.shoppingListHeader, "BOTTOMLEFT", 2, -15)
+	tab.stamp:SetPoint("RIGHT", tab, "RIGHT", -30, 0)
+	tab.stamp:SetHeight(92)
+
+	tab.gemIcons = {}
+	tab.gemLinks = {}
+	tab.gemQuantity = {}
+	tab.enchantIcons = {}
+	tab.enchantLinks = {}
+	tab.enchantQuantity = {}
+	tab.enchantMaterialIcons = {}
+	tab.enchantMaterialLinks = {}
+	tab.enchantMaterialQuantity = {}
+
+	-- Create the dropdown, and configure its appearance
+	tab.dropDown = CreateFrame("FRAME", "AmrSendType", tab.shoppingPanel, "UIDropDownMenuTemplate")
+	tab.dropDown:SetPoint("TOPLEFT", tab.sendMessage3, "TOPRIGHT", 0, 5)
+	UIDropDownMenu_SetWidth(tab.dropDown, 140)
+	UIDropDownMenu_SetText(tab.dropDown, AmrSendSettings.SendToType)
+
+	local text = getglobal(tab.dropDown:GetName() .. 'Text')
+	text:SetFontObject("GameFontHighlightLarge")
+
+	local AddButton = function(list, optionText)
+		local info = UIDropDownMenu_CreateInfo()
+		info.justifyH = "RIGHT"
+		info.text = optionText
+		info.checked = AmrSendSettings.SendToType == optionText
+		info.arg1 = optionText
+		info.func = list.SetValue
+		info.owner = list
+		info.fontObject = "GameFontHighlightLarge"
+		info.minWidth = 140
+		return info
+	end
+
+	-- Create and bind the initialization function to the dropdown menu
+	UIDropDownMenu_Initialize(tab.dropDown, function(self, level, menuList)
+	 UIDropDownMenu_AddButton(AddButton(self, "a friend"))
+	 UIDropDownMenu_AddButton(AddButton(self, "party"))
+	 UIDropDownMenu_AddButton(AddButton(self, "raid"))
+	 UIDropDownMenu_AddButton(AddButton(self, "guild"))
+	 UIDropDownMenu_AddButton(AddButton(self, "channel"))
+	 UIDropDownMenu_AddButton(AddButton(self, "mail"))
+	end)
+
+	function tab.dropDown:SetValue(newValue)
+		AmrSendSettings.SendToType = newValue
+		-- Update the text; if we merely wanted it to display newValue, we would not need to do this
+		UIDropDownMenu_SetText(tab.dropDown, AmrSendSettings.SendToType)
+		-- Because this is called from a sub-menu, only that menu level is closed by default.
+		-- Close the entire menu with this next call
+		CloseDropDownMenus()
+	end
+
+	tab.sendTo = CreateFrame("EditBox", "AmrSendTo", tab.shoppingPanel, "InputBoxTemplate" )
+	tab.sendTo:SetPoint("TOPLEFT", tab.dropDown, "TOPRIGHT", 0, 0)
+	tab.sendTo:SetPoint("RIGHT", 0, 0)
+	tab.sendTo:SetHeight(30)
+	tab.sendTo:SetText(AmrSendSettings.SendTo or "")
+	tab.sendTo:SetFontObject("GameFontHighlightLarge")
+	tab.sendTo:SetAutoFocus(false)
+	tab.sendTo:SetScript("OnChar", function()
+		AmrSendSettings.SendTo = tab.sendTo:GetText()
+	end)
+
+	tab.messageQueue = {}
+	return tab
+end
+
+-- display a gem icon in a row
+-- gemInfo is {id, enchantId, color, count }
+function AskMrRobot.ShoppingListTab:SetGemIcon(row, gemInfo)
+	-- get gem icon for the row
+	local gemIcon = self.gemIcons[row]
+
+	-- if we don't have one
+	if gemIcon == nil then
+		-- make one
+		gemIcon = AskMrRobot.GemIcon:new(nil, self.scrollParent)
+		self.gemIcons[row] = gemIcon
+		gemIcon:SetScript("OnMouseDown", function()
+			self:SearchForGem(row)
+		end)
+
+		-- position it
+		local previous = self.gemsHeader
+		if row > 1 then
+			previous = self.gemIcons[row - 1]
+		end
+		gemIcon:SetPoint("TOPLEFT", previous, "BOTTOMLEFT", 0, -7)
+
+		-- size it
+		gemIcon:SetWidth(24)
+		gemIcon:SetHeight(24)
+
+		-- give it a nice border
+		gemIcon:SetRoundBorder()
+	end
+
+	gemIcon:Show()
+
+	-- make a link for the optimized gem
+	gemLink = select(2, GetItemInfo(gemInfo.id))
+
+	-- set the link (tooltip + icon)
+	gemIcon:SetItemLink(gemLink)
+	gemIcon:SetGemColor(gemInfo.color)
+
+	-- if we didn't get one, its because WoW is slow
+	if not gemLink and gemInfo.id then
+		-- when WoW finally returns the link, set the icon / tooltip
+		AskMrRobot.RegisterItemInfoCallback(gemInfo.id, function(name, link)
+			gemIcon:SetItemLink(link)
+		end)
+	end
+
+end
+
+
+-- display a gem icon in a row
+-- gemInfo is {id, enchantId, color, count }
+function AskMrRobot.ShoppingListTab:SetGemText(row, gemInfo)
+	-- get gem icon for the row
+	local gemText = self.gemLinks[row]
+
+	-- if we don't have one
+	if gemText == nil then
+		-- make one
+		gemText = AskMrRobot.ItemLinkText:new(nil, self.scrollParent)
+		self.gemLinks[row] = gemText
+		gemText:SetScript("OnMouseDown", function()
+			self:SearchForGem(row)
+		end)	
+
+		-- position it
+		local previous = self.gemsHeader
+		if row > 1 then
+			previous = self.gemIcons[row - 1]
+		end
+		gemText:SetPoint("TOPLEFT", previous, "BOTTOMLEFT", 30, -8)
+		gemText:SetPoint("RIGHT", self, "RIGHT", -70, 0)
+		gemText:SetHeight(18)
+		gemText:SetFontSize(15)
+	end
+
+	gemText:Show()
+
+	gemText:SetItemId(gemInfo.id)
+end
+
+-- display a gem icon in a row
+-- gemInfo is {id, enchantId, color, count }
+function AskMrRobot.ShoppingListTab:SetGemQuantity(row, qty, total)
+	if qty > total then qty = total end
+
+	-- get gem icon for the row
+	local gemText = self.gemQuantity[row]
+
+	-- if we don't have one
+	if gemText == nil then
+		-- make one
+		gemText = AskMrRobot.FontString:new(self.scrollParent, nil, "ARTWORK", "GameFontNormalLarge")
+		self.gemQuantity[row] = gemText
+
+		-- position it
+		local previous = self.gemsHeader
+		if row > 1 then
+			previous = self.gemIcons[row - 1]
+		end
+		gemText:SetPoint("TOPLEFT", previous, "BOTTOMLEFT", 370, -8)
+		gemText:SetHeight(18)
+		gemText:SetFontSize(15)
+	end
+
+	gemText:SetText('' .. qty .. '/' .. total)
+	if qty == total then
+		gemText:SetTextColor(0,1,0)
+	else
+		gemText:SetTextColor(1,0,0)
+	end
+	gemText:Show()
+end
+
+
+-- display an enchant icon in a row
+function AskMrRobot.ShoppingListTab:SetEnchantIcon(row, enchantId)
+
+	-- get enchant icon for the row
+	local enchantIcon = self.enchantIcons[row]
+
+	-- if we don't have one
+	if enchantIcon == nil then
+		-- make one
+		enchantIcon = AskMrRobot.EnchantLinkIconAndText:new(nil, self.scrollParent)
+		self.enchantIcons[row] = enchantIcon
+		enchantIcon:SetScript("OnMouseDown", function()
+			self:SearchForEnchant(row)
+		end)			
+
+		-- position it
+		if row == 1 then
+			enchantIcon:SetPoint("TOPLEFT", self.enchantsHeader, "BOTTOMLEFT", 0, -12)
+			enchantIcon:SetPoint("RIGHT", self.scrollParent, "RIGHT", -30, 0)
+		else
+			enchantIcon:SetPoint("TOPLEFT", self.enchantIcons[row - 1], "BOTTOMLEFT", 0, -7)
+			enchantIcon:SetPoint("RIGHT", self.scrollParent, "RIGHT", -30, 0)
+		end
+		
+		-- size it
+		enchantIcon:SetWidth(24)
+		enchantIcon:SetHeight(24)
+		enchantIcon:SetFontSize(15)
+
+		-- give it a nice border
+		enchantIcon:SetRoundBorder()
+
+		enchantIcon:UseSpellName()
+	end
+
+	enchantIcon:SetEnchantId(enchantId)
+
+	enchantIcon:Show()
+end
+
+-- display a gem icon in a row
+-- gemInfo is {id, enchantId, color, count }
+function AskMrRobot.ShoppingListTab:SetEnchantQuantity(row, qty, total)
+	if qty > total then qty = total end
+
+	-- get gem icon for the row
+	local enchantText = self.enchantQuantity[row]
+
+	-- if we don't have one
+	if enchantText == nil then
+		-- make one
+		enchantText = AskMrRobot.FontString:new(self.scrollParent, nil, "ARTWORK", "GameFontNormalLarge")
+		self.enchantQuantity[row] = enchantText
+
+		-- position it
+		local previous = self.enchantsHeader
+		if row > 1 then
+			previous = self.enchantIcons[row - 1]
+		end
+		enchantText:SetPoint("TOPLEFT", previous, "BOTTOMLEFT", 370, -8)
+		enchantText:SetHeight(18)
+		enchantText:SetFontSize(15)
+	end
+
+	enchantText:SetText('' .. qty .. '/' .. total)
+	if qty == total then
+		enchantText:SetTextColor(0,1,0)
+	else
+		enchantText:SetTextColor(1,0,0)
+	end
+	enchantText:Show()
+end
+
+function AskMrRobot.ShoppingListTab:SearchForItem(itemName)
+	if self.isAuctionHouseVisible then
+		QueryAuctionItems(itemName, nil, nil, 0, 0, 0, 0, 0, 0, 0)
+	end
+end
+
+function AskMrRobot.ShoppingListTab:SearchForGem(row)
+	self:SearchForItem(self.gemLinks[row].itemName)
+end
+
+function AskMrRobot.ShoppingListTab:SearchForEnchant(row)
+	self:SearchForItem(self.enchantIcons[row].itemName)
+end
+
+function AskMrRobot.ShoppingListTab:SearchForEnchantMaterial(row)
+	self:SearchForItem(self.enchantMaterialLinks[row].itemName)
+end
+
+
+-- display an enchant material icon in a row
+function AskMrRobot.ShoppingListTab:SetEnchantMaterialIcon(row, itemId)
+	-- get enchant material icon for the row
+	local materialIcon = self.enchantMaterialIcons[row]
+
+	-- if we don't have one
+	if materialIcon == nil then
+		-- make one
+		materialIcon = AskMrRobot.ItemIcon:new(nil, self.scrollParent)
+		self.enchantMaterialIcons[row] = materialIcon
+		materialIcon:SetScript("OnMouseDown", function()
+			self:SearchForEnchantMaterial(row)
+		end)
+
+		-- position it
+		local previous = self.enchantMaterialsHeader
+		if row > 1 then
+			previous = self.enchantMaterialIcons[row - 1]
+		end
+		materialIcon:SetPoint("TOPLEFT", previous, "BOTTOMLEFT", 0, -7)
+
+		-- size it
+		materialIcon:SetWidth(24)
+		materialIcon:SetHeight(24)
+
+		-- give it a nice border
+		materialIcon:SetRoundBorder()
+	end
+
+	materialIcon:Show()
+
+	-- make a link for the optimized gem
+	local itemLink = select(2, GetItemInfo(itemId))
+
+	materialIcon:SetItemLink(itemLink)
+
+	-- if we didn't get one, its because WoW is slow
+	if not itemLink and itemId then
+		-- when WoW finally returns the link, set the icon / tooltip
+		AskMrRobot.RegisterItemInfoCallback(itemId, function(name, link)
+			materialIcon:SetItemLink(link)
+		end)
+	end
+end
+
+
+-- display an enchant material link in a row
+function AskMrRobot.ShoppingListTab:SetEnchantMaterialLink(row, itemId)
+	-- get gem icon for the row
+	local materialLink = self.enchantMaterialLinks[row]
+
+	-- if we don't have one
+	if materialLink == nil then
+		-- make one
+		materialLink = AskMrRobot.ItemLinkText:new(nil, self.scrollParent)
+		self.enchantMaterialLinks[row] = materialLink
+		materialLink:SetScript("OnMouseDown", function()
+			self:SearchForEnchantMaterial(row)
+		end)
+
+		-- position it
+		local previous = self.enchantMaterialsHeader
+		if row > 1 then
+			previous = self.enchantMaterialIcons[row - 1]
+		end
+		materialLink:SetPoint("TOPLEFT", previous, "BOTTOMLEFT", 30, -8)
+		materialLink:SetPoint("RIGHT", self, "RIGHT", -30, 0)
+		materialLink:SetHeight(18)
+		materialLink:SetFontSize(15)
+	end
+
+	materialLink:Show()
+
+	materialLink:SetItemId(itemId)
+	materialLink.itemId = itemId
+end
+
+-- display a gem icon in a row
+-- gemInfo is {id, enchantId, color, count }
+function AskMrRobot.ShoppingListTab:SetEnchantMaterialQuantity(row, qty, total)
+	if qty > total then qty = total end
+
+	-- get gem icon for the row
+	local enchantText = self.enchantMaterialQuantity[row]
+
+	-- if we don't have one
+	if enchantText == nil then
+		-- make one
+		enchantText = AskMrRobot.FontString:new(self.scrollParent, nil, "ARTWORK", "GameFontNormalLarge")
+		self.enchantMaterialQuantity[row] = enchantText
+
+		-- position it
+		local previous = self.enchantMaterialsHeader
+		if row > 1 then
+			previous = self.enchantMaterialIcons[row - 1]
+		end
+		enchantText:SetPoint("TOPLEFT", previous, "BOTTOMLEFT", 370, -8)
+		enchantText:SetHeight(18)
+		enchantText:SetFontSize(15)
+	end
+
+	enchantText:SetText('' .. qty .. '/' .. total)
+	if qty == total then
+		enchantText:SetTextColor(0,1,0)
+	else
+		enchantText:SetTextColor(1,0,0)
+	end
+	enchantText:Show()
+end
+
+function AskMrRobot.ShoppingListTab:HasStuffToBuy()
+
+	local gemList, enchantList, enchantMaterials = self:CalculateItems()
+
+	local count = 0
+	for gemId, gemInfo in AskMrRobot.spairs(gemList) do
+		count = count + gemInfo.total - gemInfo.count
+	end
+	for slot, enchant in AskMrRobot.spairs(enchantList) do
+		count = count + enchant.total - enchant.count
+	end
+
+	return count > 0
+end
+
+function AskMrRobot.ShoppingListTab:CalculateItems()
+	-- build a map of missing gem-ids -> {id, color, enchantid, count, total}
+	local gemList = {}
+	for slotNum, badGems in pairs(AskMrRobot.itemDiffs.gems) do
+		--badGems: {current: array of enchant ids, optimized: (array of {id, color, enchantId})
+		for i = 1, #badGems.optimized do
+			if badGems.badGems[i] then
+				local goodGem = badGems.optimized[i]
+				if goodGem.id ~= 0 then
+					local gem = gemList[goodGem.id]
+					if gem == nil then
+						gemList[goodGem.id] = {id = goodGem.id, enchantId = goodGem.enchantId, color = goodGem.color, count = 0, total = 1}
+					else
+						gem.total = gem.total + 1
+					end
+				end
+			end
+		end
+	end
+
+	local enchantList = {}
+	for slot, enchantData in AskMrRobot.sortSlots(AskMrRobot.itemDiffs.enchants) do
+		local id = AskMrRobot.getEnchantItemId(enchantData.optimized) or enchantData.optimized
+		local qty = enchantList[id]
+		if qty then
+			qty.total = qty.total + 1
+		else
+			qty = { count = 0, total = 1, optimized = enchantData.optimized }
+			enchantList[id] = qty
+		end
+	end
+
+	local enchantMaterials = {}
+	for slot, enchantData in pairs(AskMrRobot.itemDiffs.enchants) do
+		AskMrRobot.addEnchantMaterials(enchantMaterials, enchantData.optimized)
+	end
+	
+	--substract any inventory we already have in the bank
+	for i = 1, #AmrBankItemsAndCounts do
+		local itemId = AskMrRobot.getItemIdFromLink(AmrBankItemsAndCounts[i].link)
+		if itemId then
+			local gem = gemList[itemId]
+			if gem then
+				gem.count = gem.count + AmrBankItemsAndCounts[i].count
+			else 
+				local alternateGemId = AskMrRobot.gemDuplicates[itemId]
+				if alternateGemId then
+					gem = gemList[alternateGemId]
+					if gem then
+						gem.count = gem.count + AmrBankItemsAndCounts[i].count
+					end
+				end
+			end
+			local material = enchantMaterials[itemId]
+			if material then
+				material.count = material.count + AmrBankItemsAndCounts[i].count
+			end
+			local enchant = enchantList[itemId]
+			if enchant then
+				enchant.count = enchant.count + AmrBankItemsAndCounts[i].count
+			end
+		end
+	end
+
+	local _ , bagItemsWithCount = AskMrRobot.ScanBags()
+
+	--substract any inventory we already have in bags
+	for i = 1, #bagItemsWithCount do
+		local itemId = AskMrRobot.getItemIdFromLink(bagItemsWithCount[i].link)
+		if itemId then
+			local gem = gemList[itemId]
+			if gem then
+				gem.count = gem.count + bagItemsWithCount[i].count
+			else 
+				local alternateGemId = AskMrRobot.gemDuplicates[itemId]
+				if alternateGemId then
+					gem = gemList[alternateGemId]
+					if gem then
+						gem.count = gem.count + bagItemsWithCount[i].count
+					end
+				end
+			end
+			local material = enchantMaterials[itemId]
+			if material then
+				material.count = material.count + bagItemsWithCount[i].count
+			end
+			local enchant = enchantList[itemId]
+			if enchant then
+				enchant.count = enchant.count + bagItemsWithCount[i].count
+			end
+		end
+	end
+
+	return gemList, enchantList, enchantMaterials
+end
+
+function AskMrRobot.ShoppingListTab:Update()
+	
+	local gemList, enchantList, enchantMaterials = self:CalculateItems()
+
+	-- update the UI
+	local lastControl = nil
+	local row = 1
+	for gemId, gemInfo in AskMrRobot.spairs(gemList) do
+		self:SetGemIcon(row, gemInfo)
+		self:SetGemText(row, gemInfo)
+		self:SetGemQuantity(row, gemInfo.count, gemInfo.total)
+		lastControl = self.gemIcons[row]
+		row = row + 1
+	end
+
+	-- hide any extra gem icons
+	for i = row, #self.gemIcons do
+		self.gemIcons[i]:Hide()
+		self.gemLinks[i]:Hide()
+		self.gemQuantity[i]:Hide()
+	end
+
+	-- hide / show the gems header, and position the enchant headers
+	if row > 1 then
+		self.gemsHeader:Show()
+		self.gemsQuantityHeader:Show()
+		self.enchantsHeader:SetPoint("TOPLEFT", self.gemIcons[row - 1], "BOTTOMLEFT", 0, -15)
+	else
+		self.gemsHeader:Hide()
+		self.gemsQuantityHeader:Hide()
+		self.enchantsHeader:SetPoint("TOPLEFT", self.scrollParent, "TOPLEFT", 0, 0)
+	end
+
+	row = 1
+	for slot, enchant in AskMrRobot.spairs(enchantList) do
+		self:SetEnchantIcon(row, enchant.optimized)
+		self:SetEnchantQuantity(row, enchant.count, enchant.total)
+		lastControl = self.enchantIcons[row]
+		row = row + 1
+	end
+
+	-- hide any extra enchant icons
+	for i = row, #self.enchantIcons do
+		self.enchantIcons[i]:Hide()
+		self.enchantQuantity[i]:Hide()
+	end
+
+	-- hide / show the enchants header, and position the enchant materials headers
+	if row > 1 then
+		self.enchantsHeader:Show()
+		self.enchantsQuantityHeader:Show()
+		self.enchantMaterialsHeader:SetPoint("TOPLEFT", self.enchantIcons[row - 1], "BOTTOMLEFT", 0, -15)
+	else
+		self.enchantsHeader:Hide()
+		self.enchantsQuantityHeader:Hide()
+		self.enchantMaterialsHeader:SetPoint("TOPLEFT", self.scrollParent, "TOPLEFT", 0, 0)
+	end
+
+	row = 1
+	for itemId, count in AskMrRobot.spairs(enchantMaterials) do
+		self:SetEnchantMaterialIcon(row, itemId)
+		self:SetEnchantMaterialLink(row, itemId)
+		self:SetEnchantMaterialQuantity(row, count.count, count.total)
+		lastControl = self.enchantMaterialIcons[row]
+		row = row + 1
+	end
+
+	for i = row, #self.enchantMaterialIcons do
+		self.enchantMaterialIcons[i]:Hide()
+		self.enchantMaterialLinks[i]:Hide()
+		self.enchantMaterialQuantity[i]:Hide()
+	end
+
+	if row == 1 then
+		self.enchantMaterialsHeader:Hide()
+		self.enchantMaterialsQuantityHeader:Hide()
+	else
+		self.enchantMaterialsHeader:Show()
+		self.enchantMaterialsQuantityHeader:Show()
+	end
+
+	-- fix up the scrollbar length
+	if lastControl then
+		local height = self.scrollParent:GetTop() - lastControl:GetBottom()
+		self.scrollParent:SetHeight(height)
+		if height < self.scrollFrame:GetHeight() then
+			self.scrollFrame.ScrollBar:Hide()
+		else
+			self.scrollFrame:Show()
+			self.scrollFrame.ScrollBar:Show()
+		end
+		self.stamp:Hide()
+		self.shoppingPanel:Show()
+	else
+		self.scrollFrame.ScrollBar:Hide()
+		self.shoppingPanel:Hide()
+		self.stamp:Show()
+	end
+end
+
+
+function AskMrRobot.ShoppingListTab:OnEvent(frame, event, ...)
+	local handler = self["On_" .. event]
+	if handler then
+		handler(self, ...)
+	end
+end
+
+function AskMrRobot.ShoppingListTab:On_MAIL_SHOW()
+	self.mailOpen = true
+end
+
+function AskMrRobot.ShoppingListTab:On_MAIL_CLOSED()
+	self.mailOpen = nil
+end
+
+function AskMrRobot.ShoppingListTab:On_AUCTION_HOUSE_SHOW()
+	self.isAuctionHouseVisible = true
+end
+
+function AskMrRobot.ShoppingListTab:On_AUCTION_HOUSE_CLOSED()
+	self.isAuctionHouseVisible = false
+end
+
+function AskMrRobot.ShoppingListTab:sendMail()
+
+	-- need mail window to be open for this to work
+	if not self.mailOpen then
+		StaticPopup_Show("SHOPPING_TAB_PLEASE_OPEN")
+		return
+	end
+
+	local message = "Mr. Robot says I need the following to optimize my gear:\n"
+
+	local gemList, enchantList, enchantMaterials = self:CalculateItems()
+
+	if AmrSendSettings.SendGems then
+		for k,v in pairs(gemList) do
+			--exclude jewelcrafter gems
+			if not AskMrRobot.JewelcrafterGems[k] then
+				local needed = v.total - v.count
+				if needed > 0 then
+					local itemName = GetItemInfo(k)
+					if itemName then
+						message = message .. "\n" .. needed .. "x " .. itemName
+					end
+				end
+			end
+		end
+	end
+
+	if AmrSendSettings.SendEnchants then
+		for k,v in pairs(enchantList) do
+			local needed = v.total - v.count
+			if needed > 0 then
+				local itemName = GetItemInfo(k)
+				if itemName then
+					message = message .. "\n" .. needed .. "x " .. itemName
+				end
+			end
+		end
+	end
+
+	if AmrSendSettings.SendEnchantMaterials then
+		for k,v in pairs(enchantMaterials) do
+			local needed = v.total - v.count
+			if needed > 0 then
+				local itemName = GetItemInfo(k)
+				if itemName then
+					message = message .. "\n" .. needed .. "x " .. itemName
+				end
+			end
+		end
+	end
+
+	MailFrameTab_OnClick(nil, 2)
+	if AmrSendSettings.SendGems then
+		if AmrSendSettings.SendEnchants then
+			SendMailSubjectEditBox:SetText('Request for gems and enchants')
+		else
+			SendMailSubjectEditBox:SetText('Request for gems')
+		end
+	else
+		SendMailSubjectEditBox:SetText('Request for enchants')
+	end
+	SendMailNameEditBox:SetText(AmrSendSettings.SendTo)
+	SendMailBodyEditBox:SetText(message)
+end
+
+function AskMrRobot.ShoppingListTab:Send()	
+	local chatType = nil
+	if AmrSendSettings.SendToType == "party" then
+		chatType = "PARTY"
+	elseif AmrSendSettings.SendToType == "guild" then
+		chatType = "GUILD"
+	elseif AmrSendSettings.SendToType == "raid" then
+		chatType = "RAID"
+	elseif AmrSendSettings.SendToType == "channel" then
+		chatType = "CHANNEL"
+	elseif AmrSendSettings.SendToType == "mail" then
+		self:sendMail()
+		return
+	else
+		chatType = "WHISPER"
+	end
+
+	local message = "Mr. Robot says I need"
+	local count = 0
+
+
+	local gemList, enchantList, enchantMaterials = self:CalculateItems()
+
+	local items = {}
+	if AmrSendSettings.SendGems then
+		for k,v in pairs(gemList) do
+			if not AskMrRobot.JewelcrafterGems[k] then
+				local needed = v.total - v.count
+				if needed > 0 then
+					tinsert(items, {id = k, needed = needed})
+				end
+			end
+		end
+	end
+
+	if AmrSendSettings.SendEnchants then
+		for k,v in pairs(enchantList) do
+			local needed = v.total - v.count
+			if needed > 0 then
+				tinsert(items, {id = k, needed = needed})
+			end
+		end
+	end
+
+	if AmrSendSettings.SendEnchantMaterials then
+		for k,v in pairs(enchantMaterials) do
+			local needed = v.total - v.count
+			if needed > 0 then
+				tinsert(items, {id = k, needed = needed})
+			end
+		end
+	end
+
+	for i, entry in ipairs(items) do
+		local _, link = GetItemInfo(entry.id)
+		if link then
+			message = message .. " " .. entry.needed .. "x " .. link
+			count = count + 1
+			if count == 2 then
+				tinsert(self.messageQueue, {message = message, chatType = chatType, chatChannel = AmrSendSettings.SendTo})
+				count = 0
+				message = "Mr. Robot says I need"
+			end
+		end
+	end
+
+	if count > 0 then
+		tinsert(self.messageQueue, {message = message, chatType = chatType, chatChannel = AmrSendSettings.SendTo})
+	end
+
+	self:SendNextMessage()
+end
+
+function AskMrRobot.ShoppingListTab:SendNextMessage()
+	while #self.messageQueue > 0 do
+		local entry = self.messageQueue[1]
+		table.remove(self.messageQueue, 1)
+		SendChatMessage(entry.message, entry.chatType, nil, entry.chatChannel)
+	end
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/SummaryTab.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,454 @@
+local _, AskMrRobot = ...
+
+AskMrRobot.SummaryTab = AskMrRobot.inheritsFrom(AskMrRobot.Frame)
+
+function AskMrRobot.SummaryTab:new(parent)
+
+	local tab = AskMrRobot.Frame:new(nil, parent)
+	setmetatable(tab, { __index = AskMrRobot.SummaryTab })
+	tab:SetPoint("TOPLEFT")
+	tab:SetPoint("BOTTOMRIGHT")
+	tab:Hide()
+
+	
+	tab.importDate = ""
+
+	local text = tab:CreateFontString("AmrSummaryText1", "ARTWORK", "GameFontNormalLarge")
+	text:SetPoint("TOPLEFT", 0, -5)
+	text:SetFormattedText("Summary")
+
+	-- error text
+	tab.errorText1 = tab:CreateFontString("AmrSummaryErrorText1", "ARTWORK", "GameFontRedLarge")
+	tab.errorText1:SetPoint("TOPLEFT", "AmrSummaryText1", "BOTTOMLEFT", 0, -20)
+	tab.errorText1:SetText("You have no optimizations imported.")
+	tab.errorText1:SetPoint("RIGHT", -20, 0)
+	tab.errorText1:SetWidth(tab.errorText1:GetWidth())
+	tab.errorText1:SetWordWrap(true)
+	tab.errorText1:SetJustifyH("LEFT")
+
+	tab.errorText2 = tab:CreateFontString("AmrSummaryErrorText2", "ARTWORK", "GameFontWhite")
+	tab.errorText2:SetPoint("TOPLEFT", "AmrSummaryErrorText1", "BOTTOMLEFT", 0, -15)
+	tab.errorText2:SetPoint("RIGHT", -20, 0)
+	tab.errorText2:SetWidth(tab.errorText2:GetWidth())
+	tab.errorText2:SetJustifyH("LEFT")
+	tab.errorText2:SetText('Click the "Import" tab to get started.')
+
+	-- bad items
+	tab.badItemSlots = {}
+	tab.badItemNames = {}
+
+	local itemText = tab:CreateFontString("AmrBadItemSlot0", "ARTWORK", "GameFontNormal")
+	itemText:SetPoint("TOPLEFT", "AmrSummaryErrorText2", "BOTTOMLEFT", 0, -20)
+	itemText:SetText("Slot")
+	itemText:SetWidth(100)
+	itemText:SetJustifyH("LEFT")
+	itemText:Hide()
+	tinsert(tab.badItemSlots, itemText)
+
+	itemText = tab:CreateFontString("AmrBadItemName0", "ARTWORK", "GameFontNormal")
+	itemText:SetPoint("TOPLEFT", "AmrBadItemSlot0", "TOPLEFT", 120, 0)
+	itemText:SetPoint("RIGHT", -30, 0)
+	itemText:SetText("Item Name")
+	itemText:SetJustifyH("LEFT")
+	itemText:Hide()
+	tinsert(tab.badItemNames, itemText)
+
+	itemText = tab:CreateFontString(nil, "ARTWORK", "GameFontWhite")
+	itemText:SetPoint("LEFT", 0, 0)
+	itemText:SetPoint("RIGHT", -30, 0)
+	itemText:SetPoint("TOP", "AmrBadItemSlot0", "TOP", 0, 0 )
+	itemText:SetText("Please upgrade the following items:")
+	itemText:SetJustifyH("LEFT")
+	itemText:Hide()
+	tab.upgradeInstructions = itemText
+
+	itemText = tab:CreateFontString(nil, "ARTWORK", "GameFontNormal")
+	itemText:SetPoint("LEFT", "AmrBadItemSlot0", "LEFT", 0, -20)
+	itemText:SetPoint("RIGHT", "AmrBadItemSlot0", "RIGHT", 0, -20)
+	itemText:SetPoint("TOP", tab.upgradeInstructions, "BOTTOM", 0, -10 )
+	itemText:SetHeight(20)
+	itemText:SetText("Slot")
+	itemText:SetJustifyH("LEFT")
+	itemText:Hide()
+	tab.upgradeSlotHeader = itemText
+
+	itemText = tab:CreateFontString(nil, "ARTWORK", "GameFontNormal")
+	itemText:SetPoint("LEFT", "AmrBadItemName0", "LEFT", 0, 0)
+	itemText:SetPoint("RIGHT", "AmrBadItemName0", "RIGHT", 0, 0)
+	itemText:SetPoint("TOP", tab.upgradeSlotHeader, "TOP", 0, 0)
+	itemText:SetPoint("BOTTOM", tab.upgradeSlotHeader, "BOTTOM", 0, 0)
+	itemText:SetText("Item Name")
+	itemText:SetJustifyH("LEFT")
+	itemText:Hide()
+	tab.upgradeItemHeader = itemText
+
+	for i = 1, #AskMrRobot.slotNames do
+		local itemText = tab:CreateFontString("AmrBadItemSlot" .. i, "ARTWORK", "GameFontWhite")
+		itemText:SetPoint("TOPLEFT", "AmrBadItemSlot" .. (i-1), "BOTTOMLEFT", 0, -5)
+		itemText:SetPoint("TOPRIGHT", "AmrBadItemSlot" .. (i-1), "BOTTOMRIGHT", 0, -5)
+		itemText:SetJustifyH("LEFT")
+		itemText:Hide()
+		tinsert(tab.badItemSlots, itemText)
+
+		itemText = AskMrRobot.ItemLinkText:new(nil, tab)
+		itemText:SetPoint("LEFT", "AmrBadItemName0", "TOPLEFT", 0, 0)
+		itemText:SetPoint("RIGHT", "AmrBadItemName0", "BOTTOMRIGHT", 0, 0)
+		itemText:SetPoint("TOP", "AmrBadItemSlot" .. i, 0, 0)
+		itemText:SetPoint("BOTTOM", "AmrBadItemSlot" .. i, 0, 0)
+		itemText:Hide()
+		tinsert(tab.badItemNames, itemText)
+	end
+
+	tab.upgradeItemSlots = {}
+	tab.upgradeItemNames = {}
+	for i = 1, #AskMrRobot.slotNames do
+		local itemText = tab:CreateFontString(nil, "ARTWORK", "GameFontWhite")
+		if i == 1 then
+			itemText:SetPoint("TOPLEFT", tab.upgradeSlotHeader, "BOTTOMLEFT", 0, -5)
+			itemText:SetPoint("TOPRIGHT", tab.upgradeSlotHeader, "BOTTOMRIGHT", 0, -5)
+		else
+			itemText:SetPoint("TOPLEFT", tab.upgradeItemSlots[i-1], "BOTTOMLEFT", 0, -5)
+			itemText:SetPoint("TOPRIGHT", tab.upgradeItemSlots[i-1], "BOTTOMRIGHT", 0, -5)
+		end
+		itemText:SetJustifyH("LEFT")
+		itemText:Hide()
+		tinsert(tab.upgradeItemSlots, itemText)
+
+		itemText = AskMrRobot.ItemLinkText:new(nil, tab)
+		itemText:SetFormat("|cff00ff00Upgrade|r %s")
+		itemText:SetPoint("LEFT", tab.upgradeItemHeader, "LEFT", 0, 0)
+		itemText:SetPoint("RIGHT", tab.upgradeItemHeader, "RIGHT", 0, 0)
+		itemText:SetPoint("TOP", tab.upgradeItemSlots[i], 0, 0)
+		itemText:SetPoint("BOTTOM", tab.upgradeItemSlots[i], 0, 0)
+		itemText:Hide()
+		tinsert(tab.upgradeItemNames, itemText)
+	end
+
+	tab.importInfo = tab:CreateFontString(nil, "ARTWORK", "GameFontNormal")
+	tab.importInfo:SetText("Last import: ?\rThese optimizations are for ?")
+	tab.importInfo:SetPoint("TOPLEFT", text, "BOTTOMLEFT", 0, -20)
+	tab.importInfo:SetJustifyH("LEFT")
+	tab.importInfo:Hide()
+
+	tab.specIcon = tab:CreateTexture(nil, "BACKGROUND")
+	tab.specIcon:SetPoint("TOPLEFT")
+	tab.specIcon:SetWidth(64)
+	tab.specIcon:SetHeight(64)
+	tab.specIcon:SetPoint("TOPLEFT", tab.importInfo, "BOTTOMLEFT", 0, -10)
+	tab.specIcon:Hide()
+
+	tab.stamp = AskMrRobot.RobotStamp:new(nil, tab)
+	tab.stamp:Hide()
+	tab.stamp.smallText:SetText("Congratulations! You are 100% optimal")
+	tab.stamp:SetPoint("TOPLEFT", tab.specIcon, "BOTTOMLEFT", 2, -25)
+	tab.stamp:SetPoint("RIGHT", tab, "RIGHT", -20, 0)
+	tab.stamp:Hide()
+
+	tab.specText = tab:CreateFontString(nil, "ARTWORK", "GameFontHighlightLarge")
+	local Path, Size, Flags = tab.specText:GetFont()
+	tab.specText:SetFont(Path, 24, Flags);
+	tab.specText:SetPoint("LEFT", tab.specIcon, "RIGHT", 10, 0)
+	tab.specText:SetText("?")
+	tab.specText:Hide()
+
+	tab.optimizationSummary = tab:CreateFontString(nil, "ARTWORK", "GameFontNormal")
+	tab.optimizationSummary:SetPoint("TOPLEFT", tab.specIcon, "BOTTOMLEFT", 0, -15)
+	tab.optimizationSummary:SetText("You have ? optimizations to make:")
+	tab.optimizationSummary:Hide()
+
+	tab.gemCount = tab:CreateFontString(nil, "ARTWORK", "GameFontWhite")
+	tab.gemCount:SetPoint("TOPLEFT", tab.optimizationSummary, "BOTTOMLEFT", 0, -15)
+	tab.gemCount:SetText("? gems")
+	tab.gemCount:Hide()
+
+	tab.enchantCount = tab:CreateFontString(nil, "ARTWORK", "GameFontWhite")
+	tab.enchantCount:SetPoint("TOPLEFT", tab.gemCount, "BOTTOMLEFT", 0, -5)
+	tab.enchantCount:SetText("? enchants")
+	tab.enchantCount:Hide()
+
+	tab.reforgeCount = tab:CreateFontString(nil, "ARTWORK", "GameFontWhite")
+	tab.reforgeCount:SetPoint("TOPLEFT", tab.enchantCount, "BOTTOMLEFT", 0, -5)
+	tab.reforgeCount:SetText("? reforges")
+	tab.reforgeCount:Hide()
+
+	tab.instructions = tab:CreateFontString(nil, "ARTWORK", "GameFontWhite")
+	tab.instructions:SetPoint("TOPLEFT", tab.reforgeCount, "BOTTOMLEFT", 0, -15)
+	tab.instructions:SetText("View the Gem, Enchant and Reforge tabs for suggested optimizations.")
+	tab.instructions:Hide()
+
+	return tab
+end
+
+function AskMrRobot.SummaryTab:getSpecIcon(specId)
+	for i = 1, GetNumSpecializations() do
+		local id, _, _, icon = GetSpecializationInfo(i)
+		if id == specId then
+			return icon
+		end
+	end
+	return nil
+end
+
+function AskMrRobot.SummaryTab:showBadItems()
+	local badItems = AskMrRobot.itemDiffs.items
+
+	local i = 2
+
+	-- for all the bad items
+	for slotNum, badItem in AskMrRobot.sortSlots(badItems) do
+		if not badItem.needsUpgrade then
+			self.badItemSlots[i]:SetText(_G[strupper(AskMrRobot.slotNames[slotNum])])
+			self.badItemSlots[i]:Show()
+			if badItem.optimized then
+				self.badItemNames[i]:SetItemId(badItem.optimized.itemId, badItem.optimized.upgradeId, badItem.optimized.suffixId)
+			else
+				self.badItemNames[i]:SetItemId(nil, 0, 0)
+			end
+			self.badItemNames[i]:Show()
+			i = i + 1
+		end
+	end
+
+    -- for all the upgrade items
+    local j = 1
+	for slotNum, badItem in AskMrRobot.sortSlots(badItems) do
+		if badItem.needsUpgrade then
+			self.upgradeItemSlots[j]:SetText(_G[strupper(AskMrRobot.slotNames[slotNum])])
+			self.upgradeItemSlots[j]:Show()
+			if badItem.optimized then
+				self.upgradeItemNames[j]:SetItemId(badItem.optimized.itemId, badItem.optimized.upgradeId, badItem.optimized.suffixId)
+			else
+				self.upgradeItemNames[j]:SetItemId(nil, 0, 0)
+			end
+			self.upgradeItemNames[j]:Show()
+			j = j + 1
+		end
+	end
+
+	-- hide / show the headers
+	if i == 2 and j == 1 then
+		self.badItemSlots[1]:Hide()
+		self.badItemNames[1]:Hide()
+		self:showImportError(nil)
+		self.importInfo:Show()
+		self.specIcon:Show()
+		self.optimizationSummary:Show()
+		self.gemCount:Show()
+		self.enchantCount:Show()
+		self.reforgeCount:Show()
+		self.instructions:Show()
+		self.specText:Show()
+
+		local gemCount = 0
+		for slotNum, badGems in pairs(AskMrRobot.itemDiffs.gems) do
+			for k, v in pairs(badGems.badGems) do
+				gemCount = gemCount + 1
+			end
+		end
+
+		self.gemCount:SetFormattedText("%d \1244gem:gems;", gemCount)
+
+		local enchantCount = 0
+		for slotNum, badEnchant in pairs(AskMrRobot.itemDiffs.enchants) do
+			enchantCount = enchantCount + 1
+		end
+
+		self.enchantCount:SetFormattedText("%d \1244enchant:enchants;", enchantCount)
+
+		local reforgeCount = 0
+		for slotNum, badReforge in pairs(AskMrRobot.itemDiffs.reforges) do
+			reforgeCount = reforgeCount + 1
+		end
+
+		self.reforgeCount:SetFormattedText("%d \1244reforge:reforges;", reforgeCount)
+		self.optimizationSummary:SetFormattedText("You have %d \1244optimization:optimizations; to make:", gemCount + enchantCount + reforgeCount)
+
+		if gemCount + enchantCount + reforgeCount == 0 then
+			self.stamp:Show()
+			self.optimizationSummary:Hide()
+			self.enchantCount:Hide()
+			self.reforgeCount:Hide()
+			self.instructions:Hide()
+			self.gemCount:Hide()
+		else
+			self.stamp:Hide()
+			self.optimizationSummary:Show()
+			self.enchantCount:Show()
+			self.reforgeCount:Show()
+			self.instructions:Show()
+			self.gemCount:Show()
+		end
+
+		local activeSpecGroup = GetActiveSpecGroup()
+
+		if activeSpecGroup == nil then
+			self.importInfo:SetFormattedText("Last import: %s\rThese optimizations are for %s", self.importDate, UnitName("player"))
+		else
+			self.importInfo:SetFormattedText("Last import: %s\rThese optimizations are for %s's...", self.importDate, UnitName("player"))
+			local spec = GetSpecialization(false, false, group);
+			if spec then
+				local _, name, _, icon = GetSpecializationInfo(spec);
+				if activeSpecGroup == 1 then
+					self.specText:SetFormattedText("Primary Spec - %s", name)
+				else
+					self.specText:SetFormattedText("Secondary Spec - %s", name)
+				end
+				self.specIcon:SetTexture(icon)
+			end
+		end
+
+
+		--local currentSpec = GetAmrSpecialization(GetActiveSpecGroup())
+		--return (not currentSpec and not spec) or tostring(currentSpec) == spec
+	else
+		self.importInfo:Hide()
+		self.specIcon:Hide()
+		self.optimizationSummary:Hide()
+		self.gemCount:Hide()
+		self.enchantCount:Hide()
+		self.reforgeCount:Hide()
+		self.instructions:Hide()
+		self.specText:Hide()		
+	end
+
+	if i == 2 then
+		self.badItemSlots[1]:Hide()
+		self.badItemNames[1]:Hide()
+	else
+		self.badItemSlots[1]:Show()
+		self.badItemNames[1]:Show()
+		local warnings = {}
+		if self.badRealm then
+			tinsert(warnings, "a different realm: " .. self.badRealm)
+		end
+		if self.badTalents then
+			tinsert(warnings, "different talents")
+		end
+		if self.badGlyphs then
+			tinsert(warnings, "different glyphs")
+		end
+		local message = "Mr. Robot optimized a different set of gear"
+		if #warnings > 0 then
+			message = message .. " (and "
+			for k = 1, #warnings do
+				if k > 1 then
+					message = message .. ', '
+				end
+				message = message .. warnings[k]
+			end
+			message = message .. ")"
+		end
+		message = message .. ". Please equip the following items before proceeding with the optimizations."
+		self:showImportWarning("WARNING: Please check your character before proceeding:", message)
+	end
+
+	if j == 1 then
+		self.upgradeItemHeader:Hide()
+		self.upgradeSlotHeader:Hide()
+		self.upgradeInstructions:Hide()
+	else
+		if i == 2 then
+			local warnings = {}
+			if self.badRealm then
+				tinsert(warnings, "a different realm: " .. self.badRealm)
+			end
+			if self.badTalents then
+				tinsert(warnings, "different talents")
+			end
+			if self.badGlyphs then
+				tinsert(warnings, "different glyphs")
+			end
+			local message = nil
+			if #warnings > 0 then 
+				message = "Mr. Robot optimized for "
+				for k = 1, #warnings do
+					if k > 1 then
+						message = message .. ', '
+					end
+					message = message .. warnings[k]
+				end
+				message = message .. "."
+			end
+			self:showImportWarning("WARNING: Please check your character before proceeding:", message)
+		end
+		self.upgradeItemHeader:Show()
+		self.upgradeSlotHeader:Show()
+		self.upgradeInstructions:Show()
+		if i == 2 then
+			self.upgradeInstructions:SetPoint("TOP", self.badItemSlots[1], "TOP", 0, 0)
+			self.errorText2:Hide()
+		else
+			self.upgradeInstructions:SetPoint("TOP", self.badItemSlots[i], "BOTTOM", 0, -20)
+		end		
+	end
+
+	-- hide the remaining slots
+	while i <= #self.badItemSlots do
+		self.badItemSlots[i]:Hide()
+		self.badItemNames[i]:Hide()
+		i = i + 1
+	end
+
+	-- hide the remaining slots
+	while j <= #self.upgradeItemSlots do
+		self.upgradeItemSlots[j]:Hide()
+		self.upgradeItemNames[j]:Hide()
+		j = j + 1
+	end
+end
+
+
+function AskMrRobot.SummaryTab:showImportError(text, text2)
+	self.stamp:Hide()
+	self.gemCount:Hide()
+	self.instructions:Hide()
+	self.reforgeCount:Hide()
+	self.enchantCount:Hide()
+	self.optimizationSummary:Hide()
+	if text then
+		self.errorText1:Show()
+		self.errorText1:SetText('Error! Your import did not work:|n|n' .. text)
+		self.errorText1:Show()
+		self.errorText2:SetText(text2)
+		self.errorText2:Show()
+		self.importInfo:Hide()
+		self.upgradeSlotHeader:Hide()
+		self.upgradeItemHeader:Hide()
+		self.upgradeInstructions:Hide()
+		self.specIcon:Hide()
+		self.specText:Hide()
+	else
+		self.errorText1:Hide()
+		self.errorText2:Hide()
+		self.importInfo:Show()
+	end
+	for i = 1, #AskMrRobot.slotNames + 1 do
+		self.badItemSlots[i]:Hide()
+		self.badItemNames[i]:Hide()
+	end
+	for i = 1, #AskMrRobot.slotNames do
+		self.upgradeItemSlots[i]:Hide()
+		self.upgradeItemNames[i]:Hide()
+	end	
+end
+
+function AskMrRobot.SummaryTab:showImportWarning (text, text2)
+	self.stamp:Hide()
+	self.hasImportError = false
+	self.gemCount:Hide()
+	self.instructions:Hide()
+	self.reforgeCount:Hide()
+	self.enchantCount:Hide()
+	self.specIcon:Hide()
+	self.specText:Hide()
+	self.optimizationSummary:Hide()
+	if text then
+		self.errorText1:SetText(text)
+		self.errorText1:Show()
+		self.errorText2:SetText(text2)
+		self.errorText2:Show()		
+	else			
+		self.errorText1:Hide()
+		self.errorText2:Hide()
+	end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wait.lua	Tue May 20 21:43:23 2014 -0500
@@ -0,0 +1,33 @@
+local _, AskMrRobot = ...
+
+local waitTable = {};
+local waitFrame = nil;
+
+function AskMrRobot.wait(delay, func, ...)
+  if(type(delay)~="number" or type(func)~="function") then
+    print("Bad Arguments to amr__wait");
+    return false;
+  end
+  if(waitFrame == nil) then
+    waitFrame = CreateFrame("Frame","WaitFrame", UIParent);
+    waitFrame:SetScript("OnUpdate",function (self,elapse)
+      local count = #waitTable;
+      local i = 1;
+      while(i<=count) do
+        local waitRecord = tremove(waitTable,i);
+        local d = tremove(waitRecord,1);
+        local f = tremove(waitRecord,1);
+        local p = tremove(waitRecord,1);
+        if(d>elapse) then
+          tinsert(waitTable,i,{d-elapse,f,p});
+          i = i + 1;
+        else
+          count = count - 1;
+          f(unpack(p));
+        end
+      end
+    end);
+  end
+  tinsert(waitTable,{delay,func,{...}});
+  return true;
+end