comparison Summary.lua @ 10:c4d0e5d47e10

Ok, please don?t crash again you silly Ace3 multiselect dropdown box. I know you?re itchy, but there?s nothing I can do for you. Cleaned up group management layout, added a duplicate group button. Track at character data is erased when exporting/importing groups. Duplicate items are erased when importing groups. Bug fixes and speed increases in Summary. Added a button to refresh the cache. Added a slider to increase caching speed. Auction value will no longer be cached if the threshold was set to 0.
author Zerotorescue
date Tue, 12 Oct 2010 02:08:37 +0200
parents 3bac0bdd59e2
children 10a2244f7ff0
comparison
equal deleted inserted replaced
9:3bac0bdd59e2 10:c4d0e5d47e10
65 local cacheStart; 65 local cacheStart;
66 66
67 function mod:BuildMain() 67 function mod:BuildMain()
68 LibStub("AceConfigDialog-3.0"):Close("InventoryOptions"); 68 LibStub("AceConfigDialog-3.0"):Close("InventoryOptions");
69 69
70 self:CloseFrame();
71
70 -- Main Window 72 -- Main Window
71 mod.frame = AceGUI:Create("Frame"); 73 mod.frame = AceGUI:Create("Frame");
72 mod.frame:SetTitle("Inventory Summary"); 74 mod.frame:SetTitle("Inventory Summary");
73 mod.frame:SetLayout("Fill"); 75 mod.frame:SetLayout("Fill");
74 mod.frame:SetCallback("OnClose", function(widget) 76 mod.frame:SetCallback("OnClose", function(widget)
88 90
89 function mod:CloseFrame() 91 function mod:CloseFrame()
90 if mod.frame then 92 if mod.frame then
91 mod.frame:Release(); 93 mod.frame:Release();
92 mod.frame = nil; 94 mod.frame = nil;
95
96 -- Stop caching
97
98 -- Stop timer
99 self:CancelTimer(self.tmrUpdater, true);
100
101 -- Reset trackers
102 CACHE_ITEMS_TOTAL = 0;
103 CACHE_ITEMS_CURRENT = 0;
93 end 104 end
94 end 105 end
95 106
96 local sortMethod = "item"; 107 local sortMethod = "item";
97 local sortDirectory = "ASC"; 108 local sortDirectory = "ASC";
103 end 114 end
104 sortMethod = subject; 115 sortMethod = subject;
105 116
106 mod:Build(); 117 mod:Build();
107 end 118 end
119
120 -- From http://www.wowwiki.com/API_sort
121 local function pairsByKeys (t, f)
122 local a = {}
123 for n in pairs(t) do table.insert(a, n) end
124 table.sort(a, f)
125 local i = 0 -- iterator variable
126 local iter = function () -- iterator function
127 i = i + 1
128 if a[i] == nil then return nil
129 else return a[i], t[a[i]]
130 end
131 end
132 return iter
133 end
108 134
109 function mod:Build() 135 function mod:Build()
110 local start = GetTime(); 136 local buildStartTime, times = GetTime(), {};
111
112 mod.scrollFrame:ReleaseChildren();
113 137
114 -- We are going to add hunderds of widgets to this container, but don't want it to also cause hunderds of reflows, thus pause reflowing and just do it once when everything is prepared 138 -- We are going to add hunderds of widgets to this container, but don't want it to also cause hunderds of reflows, thus pause reflowing and just do it once when everything is prepared
115 -- This appears to be required for each container we wish to pause, so also do this for the contents 139 -- This appears to be required for each container we wish to pause, so also do this for the contents
116 mod.scrollFrame:PauseLayout(); 140 mod.scrollFrame:PauseLayout();
117 141
142 mod.scrollFrame:ReleaseChildren();
143
144 -- Refresh button
145 local btnRefresh = AceGUI:Create("Button");
146 btnRefresh:SetText("Refresh");
147 -- SetTooltip: Reload all item counts and auction values.
148 btnRefresh:SetRelativeWidth(.2);
149 btnRefresh:SetCallback("OnClick", function()
150 -- Reset items cache
151 table.wipe(itemsCache);
152
153 -- Rebuild itemlist and start caching
154 mod:Build();
155 end);
156
157 mod.scrollFrame:AddChild(btnRefresh);
158
159 -- Speed slider
160 local btnRefresh = AceGUI:Create("Slider");
161 btnRefresh:SetLabel("Processing speed");
162 btnRefresh:SetSliderValues(0.01, 1, 0.01);
163 btnRefresh:SetIsPercent(true);
164 -- SetTooltip: Change the speed at which item counts and auction values are being cached. Higher is faster but may drastically reduce your FPS while caching.
165 btnRefresh:SetRelativeWidth(.3);
166 btnRefresh:SetCallback("OnMouseUp", function(self, event, value)
167 CACHE_ITEMS_PER_UPDATE = ceil( value * 100 / 5 ); -- max = 20, min = 1
168 end);
169 btnRefresh:SetValue( CACHE_ITEMS_PER_UPDATE * 5 / 100 );
170
171 mod.scrollFrame:AddChild(btnRefresh);
172
173 times.init = ceil( ( GetTime() - buildStartTime ) * 1000 );
174 addon:Debug("Time spent legend: (init / sorting / preparing / building / all).");
175
118 local playerName = UnitName("player"); 176 local playerName = UnitName("player");
119 177
120 -- Go through all our stored groups 178 -- Go through all our stored groups
121 for groupName, values in pairs(addon.db.global.groups) do 179 for groupName, values in pairsByKeys(addon.db.global.groups, function(a, b) return a:lower() < b:lower(); end) do
180 local groupStartTime, groupTimes = GetTime(), {};
181
122 local trackAt = (values.trackAtCharacters or (values.trackAtCharacters == nil and addon.db.global.defaults.trackAtCharacters)); 182 local trackAt = (values.trackAtCharacters or (values.trackAtCharacters == nil and addon.db.global.defaults.trackAtCharacters));
123 183
124 -- Does this group have any items and do we want to track it at this char? 184 -- Does this group have any items and do we want to track it at this char?
125 if values.items and trackAt[playerName] then 185 if values.items and trackAt[playerName] then
186
187
126 -- Get group settings 188 -- Get group settings
127 local minimumStock = (values.minimumStock or (values.minimumStock == nil and addon.db.global.defaults.minimumStock)); 189 local minimumStock = (values.minimumStock or (values.minimumStock == nil and addon.db.global.defaults.minimumStock));
128 local showWhenBelow = (values.summaryThresholdShow or (values.summaryThresholdShow == nil and addon.db.global.defaults.summaryThresholdShow)); 190 local showWhenBelow = (values.summaryThresholdShow or (values.summaryThresholdShow == nil and addon.db.global.defaults.summaryThresholdShow));
129 local priceThreshold = (values.priceThreshold or (values.priceThreshold == nil and addon.db.global.defaults.priceThreshold)); 191 local priceThreshold = (values.priceThreshold or (values.priceThreshold == nil and addon.db.global.defaults.priceThreshold));
130 local hideWhenBelowPriceThreshold = (values.hideFromSummaryWhenBelowPriceThreshold or (values.hideFromSummaryWhenBelowPriceThreshold == nil and addon.db.global.defaults.hideFromSummaryWhenBelowPriceThreshold)); 192 local hideWhenBelowPriceThreshold = (values.hideFromSummaryWhenBelowPriceThreshold or (values.hideFromSummaryWhenBelowPriceThreshold == nil and addon.db.global.defaults.hideFromSummaryWhenBelowPriceThreshold));
193
131 194
132 -- Make group container 195 -- Make group container
133 local iGroup = AceGUI:Create("InlineGroupWithButton"); 196 local iGroup = AceGUI:Create("InlineGroupWithButton");
134 iGroup:PauseLayout(); 197 iGroup:PauseLayout();
135 iGroup:SetTitle(groupName); 198 iGroup:SetTitle(groupName);
141 exec = function() 204 exec = function()
142 print(groupName); 205 print(groupName);
143 end, 206 end,
144 }); 207 });
145 208
209
210
146 -- Headers 211 -- Headers
147 212
148 -- Itemlink 213 -- Itemlink
149 local lblItem = AceGUI:Create("InteractiveLabel"); 214 local lblItem = AceGUI:Create("InteractiveLabel");
150 lblItem:SetText("|cfffed000Item|r"); 215 lblItem:SetText("|cfffed000Item|r");
151 lblItem:SetFontObject(GameFontHighlight); 216 lblItem:SetFontObject(GameFontHighlight);
152 lblItem:SetRelativeWidth(0.7); 217 lblItem:SetRelativeWidth(.7);
153 lblItem:SetCallback("OnClick", function() ReSort("item"); end); 218 lblItem:SetCallback("OnClick", function() ReSort("item"); end);
154 219
155 iGroup:AddChild(lblItem); 220 iGroup:AddChild(lblItem);
156 221
157 -- Current quantity 222 -- Current quantity
158 local lblQuantity = AceGUI:Create("InteractiveLabel"); 223 local lblQuantity = AceGUI:Create("InteractiveLabel");
159 lblQuantity:SetText("|cfffed000Cur.|r"); 224 lblQuantity:SetText("|cfffed000Cur.|r");
160 lblQuantity:SetFontObject(GameFontHighlight); 225 lblQuantity:SetFontObject(GameFontHighlight);
161 lblQuantity:SetRelativeWidth(0.099); 226 lblQuantity:SetRelativeWidth(.099);
162 lblQuantity:SetCallback("OnClick", function() ReSort("current"); end); 227 lblQuantity:SetCallback("OnClick", function() ReSort("current"); end);
163 228
164 iGroup:AddChild(lblQuantity); 229 iGroup:AddChild(lblQuantity);
165 230
166 -- Required stock 231 -- Required stock
167 local lblMinimumStock = AceGUI:Create("InteractiveLabel"); 232 local lblMinimumStock = AceGUI:Create("InteractiveLabel");
168 lblMinimumStock:SetText("|cfffed000Req.|r"); 233 lblMinimumStock:SetText("|cfffed000Req.|r");
169 lblMinimumStock:SetFontObject(GameFontHighlight); 234 lblMinimumStock:SetFontObject(GameFontHighlight);
170 lblMinimumStock:SetRelativeWidth(0.099); 235 lblMinimumStock:SetRelativeWidth(.099);
171 lblMinimumStock:SetCallback("OnClick", function() ReSort("percentage"); end); 236 lblMinimumStock:SetCallback("OnClick", function() ReSort("percentage"); end);
172 237
173 iGroup:AddChild(lblMinimumStock); 238 iGroup:AddChild(lblMinimumStock);
174 239
175 -- Lowest value 240 -- Lowest value
176 local lblValue = AceGUI:Create("InteractiveLabel"); 241 local lblValue = AceGUI:Create("InteractiveLabel");
177 lblValue:SetText("|cfffed000Value|r"); 242 lblValue:SetText("|cfffed000Value|r");
178 lblValue:SetFontObject(GameFontHighlight); 243 lblValue:SetFontObject(GameFontHighlight);
179 lblValue:SetRelativeWidth(0.099); 244 lblValue:SetRelativeWidth(.099);
180 lblValue:SetCallback("OnClick", function() ReSort("value"); end); 245 lblValue:SetCallback("OnClick", function() ReSort("value"); end);
181 246
182 iGroup:AddChild(lblValue); 247 iGroup:AddChild(lblValue);
183 248
249
250 -- Retrieve items list
184 if not itemsCache[groupName] then 251 if not itemsCache[groupName] then
185 itemsCache[groupName] = {}; 252 itemsCache[groupName] = {};
186 253
187 -- Sort item list 254 -- Sort item list
188 for itemId in pairs(values.items) do 255 for itemId in pairs(values.items) do
190 257
191 table.insert(itemsCache[groupName], { 258 table.insert(itemsCache[groupName], {
192 id = itemId, 259 id = itemId,
193 name = itemName, 260 name = itemName,
194 link = itemLink, 261 link = itemLink,
195 value = -3,--addon:GetAuctionValue(itemLink), 262 value = ((priceThreshold == 0) and 0) or -3,-- if no price threshold is set for this item, then don't look it up either --addon:GetAuctionValue(itemLink),
196 rarity = itemRarity, 263 rarity = itemRarity,
197 count = -3,--addon:GetItemCount(itemId), 264 count = -3,--addon:GetItemCount(itemId),
198 set = {}, 265 set = {},
199 }); 266 });
200 CACHE_ITEMS_TOTAL = CACHE_ITEMS_TOTAL + 1; 267 CACHE_ITEMS_TOTAL = CACHE_ITEMS_TOTAL + 1;
201 end 268 end
202 end 269 end
203 270
271 groupTimes.init = ceil( ( GetTime() - groupStartTime ) * 1000 );
272
273
274
275 -- Sort items
204 table.sort(itemsCache[groupName], function(a, b) 276 table.sort(itemsCache[groupName], function(a, b)
205 if sortMethod == "item" and a.rarity == b.rarity then 277 if sortMethod == "item" and a.rarity == b.rarity then
206 -- Do a name-compare for items of the same rarity 278 -- Do a name-compare for items of the same rarity
207 -- Otherwise epics first, then junk 279 -- Otherwise epics first, then junk
208 if sortDirectory == "ASC" then 280 if sortDirectory == "ASC" then
222 else 294 else
223 return a.count > b.count; 295 return a.count > b.count;
224 end 296 end
225 elseif sortMethod == "percentage" then 297 elseif sortMethod == "percentage" then
226 if sortDirectory == "ASC" then 298 if sortDirectory == "ASC" then
227 return ( a.count / lblMinimumStock ) < ( b.count / lblMinimumStock ); 299 return ( a.count / minimumStock ) < ( b.count / minimumStock );
228 else 300 else
229 return ( a.count / lblMinimumStock ) > ( b.count / lblMinimumStock ); 301 return ( a.count / minimumStock ) > ( b.count / minimumStock );
230 end 302 end
231 elseif sortMethod == "value" then 303 elseif sortMethod == "value" then
232 if sortDirectory == "ASC" then 304 if sortDirectory == "ASC" then
233 return a.value < b.value; 305 return a.value < b.value;
234 else 306 else
235 return a.value > b.value; 307 return a.value > b.value;
236 end 308 end
237 end 309 end
238 end); 310 end);
239 311
240 -- Show stuff 312 groupTimes.sorting = ceil( ( GetTime() - groupStartTime ) * 1000 );
313
314
315
316
317 -- Show itemslist
241 for i, item in pairs(itemsCache[groupName]) do 318 for i, item in pairs(itemsCache[groupName]) do
242 if ( item.count / minimumStock ) < showWhenBelow and not (hideWhenBelowPriceThreshold and item.value < priceThreshold) then 319 if ( item.count / minimumStock ) < showWhenBelow and not (hideWhenBelowPriceThreshold and item.value < priceThreshold) then
243 local btnItemLink = AceGUI:Create("ItemLinkButton"); 320 local btnItemLink = AceGUI:Create("ItemLinkButton");
244 btnItemLink:SetUserData("exec", function() 321 --btnItemLink:SetUserData("exec", function()
245 print("Win."); 322 -- print("Nothing happening yet.");
246 end); 323 --end);
247 btnItemLink:SetRelativeWidth(0.7); 324 btnItemLink:SetRelativeWidth(.7);
248 btnItemLink:SetItemId(item.id); 325 btnItemLink:SetItemId(item.id);
249 326
250 iGroup:AddChild(btnItemLink); 327 iGroup:AddChild(btnItemLink);
251 328
252 -- Current quantity 329 -- Current quantity
253 local lblQuantity = AceGUI:Create("Label"); 330 local lblQuantity = AceGUI:Create("Label");
254 lblQuantity:SetText(self:DisplayItemCount(item.count, minimumStock)); 331 lblQuantity:SetText(self:DisplayItemCount(item.count, minimumStock));
255 lblQuantity:SetRelativeWidth(0.099); 332 lblQuantity:SetRelativeWidth(.099);
256 333
257 iGroup:AddChild(lblQuantity); 334 iGroup:AddChild(lblQuantity);
258 335
259 -- Required stock 336 -- Required stock
260 local lblMinimumStock = AceGUI:Create("Label"); 337 local lblMinimumStock = AceGUI:Create("Label");
261 lblMinimumStock:SetText(minimumStock); 338 lblMinimumStock:SetText(minimumStock);
262 lblMinimumStock:SetRelativeWidth(0.099); 339 lblMinimumStock:SetRelativeWidth(.099);
263 340
264 iGroup:AddChild(lblMinimumStock); 341 iGroup:AddChild(lblMinimumStock);
265 342
266 -- Value 343 -- Value
267 local lblValue = AceGUI:Create("Label"); 344 local lblValue = AceGUI:Create("Label");
268 lblValue:SetText(self:DisplayMoney(item.value, priceThreshold)); 345 lblValue:SetText(self:DisplayMoney(item.value, priceThreshold));
269 lblValue:SetRelativeWidth(0.099); 346 lblValue:SetRelativeWidth(.099);
270 347
271 iGroup:AddChild(lblValue); 348 iGroup:AddChild(lblValue);
272 349
273 -- Remember references to the value and current fields so we can fill them later 350 -- Remember references to the value and current fields so we can fill them later
274 if item.set then 351 if item.set then
275 item.set.value = lblValue; 352 -- -3 means the price is unknown, queue look up
276 item.set.current = lblQuantity; 353 if item.value == -3 then
354 item.set.value = lblValue;
355 end
356 if item.count == -3 then
357 item.set.current = lblQuantity;
358 end
359
360 -- Don't queue if we already know everything we want to know
361 if item.value ~= -3 and item.count ~= -3 then
362 item.set = nil;
363 end
277 end 364 end
278 end 365 end
279 end 366 end
367
368 groupTimes.preparing = ceil( ( GetTime() - groupStartTime ) * 1000 );
280 369
281 iGroup:ResumeLayout(); 370 iGroup:ResumeLayout();
282 mod.scrollFrame:AddChild(iGroup); -- this can take up to .5 seconds, might need to look into again at a later time 371 mod.scrollFrame:AddChild(iGroup); -- this can take up to .5 seconds, might need to look into again at a later time
372
373 groupTimes.building = ceil( ( GetTime() - groupStartTime ) * 1000 );
283 end 374 end
375
376 addon:Debug(("Building of %s took %d ms (%d / %d / %d / %d / %d)."):format(groupName, ceil( ( GetTime() - groupStartTime ) * 1000 ), groupTimes.init, groupTimes.sorting, groupTimes.preparing, groupTimes.building, ceil( ( GetTime() - buildStartTime ) * 1000 )));
284 end 377 end
285 378
286 mod.scrollFrame:ResumeLayout(); 379 mod.scrollFrame:ResumeLayout();
287 mod.scrollFrame:DoLayout(); 380 mod.scrollFrame:DoLayout();
381
382 addon:Debug(("Done building summary after %d ms."):format(ceil( ( GetTime() - buildStartTime ) * 1000 )));
288 383
289 if CACHE_ITEMS_TOTAL > 0 then 384 if CACHE_ITEMS_TOTAL > 0 then
290 cacheStart = GetTime(); 385 cacheStart = GetTime();
291 self:CancelTimer(self.tmrUpdater, true); 386 self:CancelTimer(self.tmrUpdater, true);
292 self.tmrUpdater = self:ScheduleRepeatingTimer("UpdateNextItem", .01); -- Once every 100 frames (or once every x frames if you have less than 100 FPS, basically, once every frame) 387 self.tmrUpdater = self:ScheduleRepeatingTimer("UpdateNextItem", .01); -- Once every 100 frames (or once every x frames if you have less than 100 FPS, basically, once every frame)
297 local i = 0; 392 local i = 0;
298 393
299 for groupName, items in pairs(itemsCache) do 394 for groupName, items in pairs(itemsCache) do
300 local minimumStock = addon:GetOptionByKey(groupName, "minimumStock"); 395 local minimumStock = addon:GetOptionByKey(groupName, "minimumStock");
301 local priceThreshold = addon:GetOptionByKey(groupName, "priceThreshold"); 396 local priceThreshold = addon:GetOptionByKey(groupName, "priceThreshold");
302 local groupUpdated;
303 397
304 for _, item in pairs(items) do 398 for _, item in pairs(items) do
305 if item.set then 399 if item.set then
306 item.count = addon:GetItemCount(item.id); 400 if item.count == -3 then
307 if item.set.current and item.set.current.SetText then 401 -- Only if item count was queued, update it
308 item.set.current:SetText(self:DisplayItemCount(item.count, minimumStock)); 402 item.count = addon:GetItemCount(item.id);
403 if item.set.current and item.set.current.SetText then
404 item.set.current:SetText(self:DisplayItemCount(item.count, minimumStock));
405 end
309 end 406 end
310 407
311 item.value = addon:GetAuctionValue(item.link); 408 if item.value == -3 then
312 if item.set.value and item.set.value.SetText then 409 -- Only if item value was queued, update it
313 item.set.value:SetText(self:DisplayMoney(item.value, priceThreshold)); 410 item.value = addon:GetAuctionValue(item.link);
411 if item.set.value and item.set.value.SetText then
412 item.set.value:SetText(self:DisplayMoney(item.value, priceThreshold));
413 end
314 end 414 end
315 415
316 item.set = nil; 416 item.set = nil;
317 417
318 i = i + 1; 418 i = i + 1;
319 CACHE_ITEMS_CURRENT = CACHE_ITEMS_CURRENT + 1; 419 CACHE_ITEMS_CURRENT = CACHE_ITEMS_CURRENT + 1;
320 groupUpdated = true;
321 420
322 if mod.frame then 421 if mod.frame then
323 mod.frame:SetStatusText(("Caching auction values and item-counts... %d%% has already been processed."):format(floor(CACHE_ITEMS_CURRENT / CACHE_ITEMS_TOTAL * 100))); 422 mod.frame:SetStatusText(("Caching auction values and item-counts... %d%% has already been processed."):format(floor(CACHE_ITEMS_CURRENT / CACHE_ITEMS_TOTAL * 100)));
324 end 423 end
325 424
326 if i >= CACHE_ITEMS_PER_UPDATE then 425 if i >= CACHE_ITEMS_PER_UPDATE then
327 return; 426 return;
328 end 427 end
329 end 428 end
330 end 429 end
331
332 if groupUpdated then
333 -- Rebuild list so hidden items due to too low prices get added
334 self:Build();
335 end
336 end 430 end
337 431
338 -- Reset trackers 432 -- Reset trackers
339 CACHE_ITEMS_TOTAL = 0; 433 CACHE_ITEMS_TOTAL = 0;
340 CACHE_ITEMS_CURRENT = 0; 434 CACHE_ITEMS_CURRENT = 0;
341 435
342 -- Stop timer 436 -- Stop timer
343 self:CancelTimer(self.tmrUpdater, true); 437 self:CancelTimer(self.tmrUpdater, true);
438
439 -- Rebuild list so hidden items due to too low prices get added
440 self:Build();
344 441
345 -- Announce 442 -- Announce
346 mod.frame:SetStatusText("All prices and itemcounts have been cached. This process took " .. ceil(GetTime() - cacheStart) .. " seconds."); 443 mod.frame:SetStatusText("All required prices and itemcounts have been cached. This process took " .. ceil(GetTime() - cacheStart) .. " seconds.");
347 444
348 -- Forget time 445 -- Forget time
349 cacheStart = nil; 446 cacheStart = nil;
350 end 447 end
351 448