diff --git a/components/disenchant.lua b/components/disenchant.lua index dcca492..ee8302a 100644 --- a/components/disenchant.lua +++ b/components/disenchant.lua @@ -36,7 +36,7 @@ do } function public.source(item_id) - return data[item_id] and unpack(data[item_id]) + return unpack(data[item_id] or {}) end end @@ -84,14 +84,14 @@ function public.value(slot, quality, level) end function public.distribution(slot, quality, level) - if not (m.armor[slot] or m.weapon[slot]) or level == 0 then + if not (m.armor(slot) or m.weapon(slot)) or level == 0 then return {} end local function p(probability_armor, probability_weapon) - if m.armor[slot] then + if m.armor(slot) then return probability_armor - elseif m.weapon[slot] then + elseif m.weapon(slot) then return probability_weapon end end diff --git a/components/scan.lua b/components/scan.lua index fa99a61..83cd206 100644 --- a/components/scan.lua +++ b/components/scan.lua @@ -1,15 +1,51 @@ local m, public, private = Aux.module'scan' -local PAGE_SIZE = 50 +private.PAGE_SIZE = 50 -private.threads = {} private.last_query_time = {} -private.state = Aux.dynamic_table(function() - return Aux.util.filter(m.threads, function(thread) return thread.id == Aux.control.thread_id end)[1] -end) +do + local scan_states = {} -private.q = Aux.dynamic_table(function() + function public.start(params) + for old_state in {scan_states[params.type]} do + m.abort(old_state.id) + end + local thread_id = Aux.control.thread(Aux.f(m.wait_for_callback, params.on_scan_start, m.scan)) + scan_states[params.type] = { + id = thread_id, + params = params, + } + return thread_id + end + + function public.abort(scan_id) + local aborted = {} + for type, state in scan_states do + if not scan_id or state.id == scan_id then + Aux.control.kill_thread(state.id) + scan_states[type] = nil + tinsert(aborted, state) + end + end + for _, state in aborted do + Aux.safe_call(state.params.on_abort) + end + end + + function private.complete() + local on_complete = m.state.params.on_complete + scan_states[m.state.params.type] = nil + Aux.safe_call(on_complete) + end + + private.state = Aux.dynamic_table(function() + local _, state = next(Aux.util.filter(scan_states, function(state) return state.id == Aux.control.thread_id end)) + return state + end) +end + +private.query = Aux.dynamic_table(function() return m.state.params.queries[m.state.query_index] end) @@ -36,58 +72,20 @@ function private.wait_for_callback(...) end function private.total_pages(total_auctions) - return math.ceil(total_auctions / PAGE_SIZE) + return ceil(total_auctions / m.PAGE_SIZE) end function private.last_page(total_auctions) local last_page = max(m.total_pages(total_auctions) - 1, 0) - local last_page_limit = m.q.blizzard_query and m.q.blizzard_query.last_page or last_page + local last_page_limit = m.query.blizzard_query and m.query.blizzard_query.last_page or last_page return min(last_page_limit, last_page) end -function public.start(params) - if m.threads[params.type] then - m.abort(m.threads[params.type].id) - end - - local thread_id = Aux.control.thread(Aux.f(m.wait_for_callback, params.on_scan_start, m.scan)) - - m.threads[params.type] = { - id = thread_id, - params = params, - } - return thread_id -end - -function public.abort(scan_id) - local aborted_threads = {} - for t, thread in m.threads do - if not scan_id or thread.id == scan_id then - Aux.control.kill_thread(thread.id) - m.threads[t] = nil - tinsert(aborted_threads, thread) - end - end - - for _, thread in aborted_threads do - Aux.safe_call(thread.params.on_abort) - end -end - -function private.complete() - local on_complete = m.state.params.on_complete - m.threads[m.state.params.type] = nil - if on_complete then - return on_complete() - end -end - function private.scan() - Aux.log(Aux.control.thread_id) m.state.query_index = m.state.query_index and m.state.query_index + 1 or 1 - if m.q() then - if m.q.blizzard_query then - m.state.page = m.q.blizzard_query.first_page or 0 + if m.query() then + if m.query.blizzard_query then + m.state.page = m.query.blizzard_query.first_page or 0 else m.state.page = nil end @@ -98,7 +96,7 @@ function private.scan() end function private.process_query() - if m.q.blizzard_query then + if m.query.blizzard_query then return m.submit_query() else return m.scan_page() @@ -114,7 +112,7 @@ function private.submit_query() elseif m.state.params.type == 'owner' then GetOwnerAuctionItems(m.state.page) else - local blizzard_query = m.q.blizzard_query or {} + local blizzard_query = m.query.blizzard_query or {} QueryAuctionItems( blizzard_query.name, blizzard_query.min_level, @@ -134,9 +132,9 @@ end function private.scan_page(i) i = i or 1 local recurse = function(retry) - if i >= PAGE_SIZE then + if i >= m.PAGE_SIZE then m.wait_for_callback(m.state.params.on_page_scanned, function() - if m.q.blizzard_query and m.state.page < m.last_page(m.state.total_auctions) then + if m.query.blizzard_query and m.state.page < m.last_page(m.state.total_auctions) then m.state.page = m.state.page + 1 return m.process_query() else @@ -152,7 +150,7 @@ function private.scan_page(i) if auction_info and (auction_info.owner or m.state.params.ignore_owner or aux_ignore_owner) then auction_info.index = i auction_info.page = m.state.page - auction_info.blizzard_query = m.q.blizzard_query + auction_info.blizzard_query = m.query.blizzard_query auction_info.query_type = m.state.params.type Aux.history.process_auction(auction_info) @@ -161,7 +159,7 @@ function private.scan_page(i) local c = Aux.control.await(recurse) Aux.place_bid(auction_info.query_type, auction_info.index, auction_info.buyout_price, Aux.f(c, true)) return Aux.control.thread(Aux.control.sleep, 10, Aux.f(c, false)) - elseif not m.q.validator or m.q.validator(auction_info) then + elseif not m.query.validator or m.query.validator(auction_info) then return m.wait_for_callback(m.state.params.on_auction, auction_info, function(removed) if removed then return recurse(true) @@ -187,8 +185,8 @@ function private.wait_for_results() _, m.state.total_auctions = GetNumAuctionItems(m.state.params.type) return m.wait_for_callback( m.state.params.on_page_loaded, - m.state.page - (m.q.blizzard_query.first_page or 0) + 1, - m.last_page(m.state.total_auctions) - (m.q.blizzard_query.first_page or 0) + 1, + m.state.page - (m.query.blizzard_query.first_page or 0) + 1, + m.last_page(m.state.total_auctions) - (m.query.blizzard_query.first_page or 0) + 1, m.total_pages(m.state.total_auctions) - 1, m.scan_page ) @@ -232,7 +230,7 @@ function private.wait_for_list_results(c) end function private.owner_data_complete(type) - for i=1,PAGE_SIZE do + for i=1,m.PAGE_SIZE do local auction_info = Aux.info.auction(i, type) if auction_info and not auction_info.owner then return false diff --git a/control.lua b/control.lua index f4852f3..7467e1a 100644 --- a/control.lua +++ b/control.lua @@ -14,7 +14,6 @@ do local active_listener function public.kill(...) - Aux.log(arg.n) --TODO active_listener.killed = arg.n == 0 or arg[1] end @@ -80,7 +79,6 @@ function public.thread(k, ...) end function public.kill_thread(thread_id) - Aux.log('kek') if m.threads[thread_id] then m.threads[thread_id].killed = true end diff --git a/core.lua b/core.lua index f868a1a..eeb94ea 100644 --- a/core.lua +++ b/core.lua @@ -2,6 +2,23 @@ local addon = Aux_module() Aux = tremove(addon, 1) local m, public, private = unpack(addon) +--m.enum TODO +--setmetatable({}, { AUX -> aux +-- __index = function(self, key) +-- self[key] = true +-- return self +-- end, +-- __call = function(self, key) +-- for key in self do +-- decl[key] = +-- end +-- end, +--}) +--.INVTYPE_HEAD +--.INVTYPE_NECK +--.INVTYPE_SHOULDER +--() + private.modules = { Aux } function public.module(name) local module = Aux_module() @@ -38,13 +55,11 @@ do end end ---unpack(arg) TODO +--for notnil in {maybenil} do TODO +--end ---m.enum TODO ---.INVTYPE_HEAD ---.INVTYPE_NECK ---.INVTYPE_SHOULDER ---() +-- ipairs TODO +--unpack(arg) TODO do local x = 0 diff --git a/tabs/post/core.lua b/tabs/post/core.lua index df9f8a5..72f229c 100644 --- a/tabs/post/core.lua +++ b/tabs/post/core.lua @@ -91,10 +91,10 @@ function private.update_inventory_listing() return end - Aux.item_listing.populate(m.item_listing, Aux.util.filter(m.inventory_records, function(record) + Aux.item_listing.populate(m.item_listing, Aux.util.values(Aux.util.filter(m.inventory_records, function(record) local settings = m.read_settings(record.key) return record.aux_quantity > 0 and (not settings.hidden or m.show_hidden_checkbox:GetChecked()) - end)) + end))) end function private.update_auction_listing() @@ -174,7 +174,7 @@ function private.update_auction_listing() end function public.select_item(item_key) - for _, inventory_record in ipairs(Aux.util.filter(m.inventory_records, function(record) return record.aux_quantity > 0 end)) do + for _, inventory_record in Aux.util.filter(m.inventory_records, function(record) return record.aux_quantity > 0 end) do if inventory_record.key == item_key then m.set_item(inventory_record) break diff --git a/tabs/search/core.lua b/tabs/search/core.lua index 1004aa8..e9bb7df 100644 --- a/tabs/search/core.lua +++ b/tabs/search/core.lua @@ -902,7 +902,7 @@ function private.remove_post_filter() end function private.update_filter_display() - local lines = getn(Aux.util.filter(m.post_components, function(component) return component[1] == 'operator' and component[2] ~= 'not' end)) + local lines = Aux.util.size(Aux.util.filter(m.post_components, function(component) return component[1] == 'operator' and component[2] ~= 'not' end)) local width_scale = max(200/m.filter_display:GetStringWidth()) local height_scale = min((200 / lines) / 18) m.filter_display.scale_frame:SetScale(min(1, width_scale, height_scale)) diff --git a/util/core.lua b/util/core.lua index 053dc7f..747b765 100644 --- a/util/core.lua +++ b/util/core.lua @@ -21,8 +21,28 @@ function public.size(t) return x end -function public.round(x) - return floor(x + 0.5) +function public.key(value, t) + for k, v in t do + if v == value then + return k + end + end +end + +function public.keys(t) + local ks = {} + for k in t do + tinsert(ks, k) + end + return ks +end + +function public.values(t) + local vs = {} + for _, v in t do + tinsert(vs, v) + end + return vs end function public.eq(t1, t2) @@ -45,6 +65,118 @@ function public.eq(t1, t2) return true end +function public.any(xs, p) + local holds = false + for _, x in xs do + holds = holds or p(x) + end + return holds +end + +function public.all(xs, p) + local holds = true + for _, x in xs do + holds = holds and p(x) + end + return holds +end + +function public.filter(xs, p) + local ys = {} + for k, x in xs do + if p(x, k) then + ys[k] = x + end + end + return ys +end + +function public.map(xs, f) + local ys = {} + for k, x in xs do + ys[k] = f(x, k) + end + return ys +end + +do + local mt = { + __call = function(self) + return + end, + } + + -- local methods = {} + -- + -- function methods:add(key) + -- self[key] = true + -- end + -- + -- function methods:remove(key) + -- self[key] = nil + -- end + -- + -- function methods:size() + -- local size = 0 + -- for _,_ in self do + -- size = size + 1 + -- end + -- return size + -- end + -- + -- function methods:elements() + -- local elements = {} + -- for element, _ in self do + -- tinsert(elements, element) + -- end + -- return elements + -- end + + function public.set(...) + local self = {} + for i=1,arg.n do + self[arg[i]] = true + end + return setmetatable(self, mt) + end +end + +function public.join(array, separator) + local str = '' + for i, element in ipairs(array) do + if i > 1 then + str = str..separator + end + str = str..element + end + return str +end + +function public.split(str, separator) + local parts = {} + while true do + local start_index, _ = strfind(str, separator, 1, true) + + if start_index then + local part = strsub(str, 1, start_index - 1) + tinsert(parts, part) + str = strsub(str, start_index + 1) + else + local part = strsub(str, 1) + tinsert(parts, part) + return parts + end + end +end + +function public.tokenize(str) + local tokens = {} + for token in string.gfind(str, '%S+') do + tinsert(tokens, token) + end + return tokens +end + function public.wipe(t) while getn(t) > 0 do tremove(t) @@ -62,16 +194,12 @@ function public.copy(t) return copy end -function public.cons(element, list) - local new_list = public.copy_table(list) - tinsert(new_list, 1, element) - return new_list +function public.round(x) + return floor(x + 0.5) end function public.trim(str) - str = gsub(str, '^%s*', '') - str = gsub(str, '%s*$', '') - return str + return gsub(str, '^%s*(.-)%s*$', '%1') end function public.inventory() @@ -120,162 +248,6 @@ function public.without_sound(f) SetCVar('MasterSoundEffects', orig) end -function public.any(xs, p) - local holds = false - for _, x in xs do - holds = holds or p(x) - end - return holds -end - -function public.all(xs, p) - local holds = true - for _, x in xs do - holds = holds and p(x) - end - return holds -end - -function public.set_filter(xs, p) - local ys = {} - for x, _ in xs do - if p(x) then - m.set_add(ys, x) - end - end - return ys -end - -function public.filter(xs, p) - local ys = {} - for k, x in xs do - if p(x) then - ys[k] = x - end - end - return ys -end - -function public.map(xs, f) - local ys = {} - for k, x in xs do - ys[k] = f(x) - end - return ys -end - -function public.take(n, xs) - local ys = {} - for i=1,min(n, getn(xs)) do - tinsert(ys, xs[i]) - end - return ys -end - -function public.key(value, t) - for k, v in t do - if v == value then - return k - end - end -end - -function public.group_by(tables, equal) - local groups = {} - for _, table in ipairs(tables) do - local found_group - for _, group in ipairs(groups) do - if equal(table, group[1]) then - tinsert(group, table) - found_group = true - end - end - if not found_group then - tinsert(groups, { table }) - end - end - return groups -end - -do - local mt = { - __call = function(self) - return - end, - } - - local methods = {} - - function methods:add(key) - self[key] = true - end - - function methods:remove(key) - self[key] = nil - end - - function methods:size() - local size = 0 - for _,_ in self do - size = size + 1 - end - return size - end - - function methods:elements() - local elements = {} - for element, _ in self do - tinsert(elements, element) - end - return elements - end - - function public.set(...) - local self = {} - for i=1,arg.n do - set[arg[i]] = true - end - return setmetatable(self, mt) - end -end - -function public.join(array, separator) - local str = '' - for i, element in ipairs(array) do - if i > 1 then - str = str..separator - end - str = str..element - end - return str -end - -function public.split(str, separator) - - local array = {} - while true do - local start_index, _ = strfind(str, separator, 1, true) - - if start_index then - local part = strsub(str, 1, start_index - 1) - tinsert(array, part) - str = strsub(str, start_index + 1) - else - local part = strsub(str, 1) - tinsert(array, part) - return array - end - end -end - -function public.tokenize(str) - local tokens = {} - for token in string.gfind(str, '%S+') do - tinsert(tokens, token) - end - return tokens -end - function public.format_money(money, exact, color) color = color or '|r' @@ -290,7 +262,7 @@ function public.format_money(money, exact, color) if not exact and money >= 10000 then -- Round to nearest silver - money = math.floor(money / 100 + 0.5) * 100 + money = floor(money / 100 + 0.5) * 100 end local g, s, c = Aux.money.to_GSC(money)