diff --git a/core.lua b/core.lua index 030ad04..67eb3dc 100644 --- a/core.lua +++ b/core.lua @@ -391,7 +391,7 @@ end function Aux.item_class_index(item_class) for i, class in ipairs({ GetAuctionItemClasses() }) do - if strlower(class) == strlower(item_class) then + if strupper(class) == strupper(item_class) then return i end end @@ -399,16 +399,24 @@ end function Aux.item_subclass_index(class_index, item_subclass) for i, subclass in ipairs({ GetAuctionItemSubClasses(class_index) }) do - if strlower(subclass) == strlower(item_subclass) then + if strupper(subclass) == strupper(item_subclass) then return i end end end +function Aux.item_slot(class_index, subclass_index, slot_name) + for _, slot in ipairs({ GetAuctionInvTypes(class_index, subclass_index) }) do + if strupper(getglobal(slot)) == strupper(slot_name) then + return slot + end + end +end + function Aux.item_quality_index(item_quality) for i=0,4 do local quality = getglobal('ITEM_QUALITY'..i..'_DESC') - if strlower(item_quality) == strlower(quality) then + if strupper(item_quality) == strupper(quality) then return i end end diff --git a/filter_search_frame.lua b/filter_search_frame.lua index 2d34be6..c84b849 100644 --- a/filter_search_frame.lua +++ b/filter_search_frame.lua @@ -59,18 +59,16 @@ function private.clear_filter() end function private.get_form_filter() - local category = UIDropDownMenu_GetSelectedValue(AuxFilterSearchFrameFiltersCategoryDropDown) - return { name = AuxFilterSearchFrameFiltersNameInputBox:GetText(), min_level = tonumber(AuxFilterSearchFrameFiltersMinLevel:GetText()), max_level = tonumber(AuxFilterSearchFrameFiltersMaxLevel:GetText()), - slot = category and category.slot, - class = category and category.class, - subclass = category and category.subclass, - quality = UIDropDownMenu_GetSelectedValue(AuxFilterSearchFrameFiltersQualityDropDown), - usable_only = AuxFilterSearchFrameFiltersUsableCheckButton:GetChecked(), - exact_only = AuxFilterSearchFrameFiltersExactCheckButton:GetChecked(), + class = UIDropDownMenu_GetSelectedValue(private.class_dropdown), + subclass = UIDropDownMenu_GetSelectedValue(private.subclass_dropdown), + slot = UIDropDownMenu_GetSelectedValue(private.slot_dropdown), + quality = UIDropDownMenu_GetSelectedValue(private.quality_dropdown), + usable = AuxFilterSearchFrameFiltersUsableCheckButton:GetChecked(), + exact = AuxFilterSearchFrameFiltersExactCheckButton:GetChecked(), } end @@ -408,13 +406,13 @@ function public.on_load() do local line = Aux.gui.horizontal_line(AuxFilterSearchFrameSavedRecent, -30) local label = Aux.gui.label(AuxFilterSearchFrameSavedRecent, 15) - label:SetPoint('BOTTOM', line, 'TOP', 0, 5) + label:SetPoint('BOTTOM', line, 'TOP', 0, 7) label:SetText('Recent Searches') end do local line = Aux.gui.horizontal_line(AuxFilterSearchFrameSavedFavorite, -30) local label = Aux.gui.label(AuxFilterSearchFrameSavedFavorite, 15) - label:SetPoint('BOTTOM', line, 'TOP', 0, 5) + label:SetPoint('BOTTOM', line, 'TOP', 0, 7) label:SetText('Favorite Searches') end do @@ -542,26 +540,54 @@ function public.on_load() dropdown:SetHeight(10) local label = Aux.gui.label(dropdown, 13) label:SetPoint('BOTTOMLEFT', dropdown, 'TOPLEFT', -2, -4) - label:SetText('Category') - private.category_dropdown = dropdown - UIDropDownMenu_Initialize(dropdown, AuxFilterSearchFrameFiltersCategoryDropDown_Initialize) + label:SetText('Item Class') + UIDropDownMenu_Initialize(dropdown, private.initialize_class_dropdown) dropdown:SetScript('OnShow', function() - UIDropDownMenu_Initialize(this, AuxFilterSearchFrameFiltersCategoryDropDown_Initialize) + UIDropDownMenu_Initialize(this, private.initialize_class_dropdown) end) + private.class_dropdown = dropdown end do local dropdown = Aux.gui.dropdown(private.elements[FILTER].filters) - dropdown:SetPoint('TOPLEFT', 14, -93) + dropdown:SetPoint('TOPLEFT', 14, -100) + dropdown:SetWidth(250) + dropdown:SetHeight(10) + local label = Aux.gui.label(dropdown, 13) + label:SetPoint('BOTTOMLEFT', dropdown, 'TOPLEFT', -2, -4) + label:SetText('Item Subclass') + UIDropDownMenu_Initialize(dropdown, private.initialize_subclass_dropdown) + dropdown:SetScript('OnShow', function() + UIDropDownMenu_Initialize(this, private.initialize_subclass_dropdown) + end) + private.subclass_dropdown = dropdown + end + do + local dropdown = Aux.gui.dropdown(private.elements[FILTER].filters) + dropdown:SetPoint('TOPLEFT', 14, -150) + dropdown:SetWidth(250) + dropdown:SetHeight(10) + local label = Aux.gui.label(dropdown, 13) + label:SetPoint('BOTTOMLEFT', dropdown, 'TOPLEFT', -2, -4) + label:SetText('Item Slot') + UIDropDownMenu_Initialize(dropdown, private.initialize_slot_dropdown) + dropdown:SetScript('OnShow', function() + UIDropDownMenu_Initialize(this, private.initialize_slot_dropdown) + end) + private.slot_dropdown = dropdown + end + do + local dropdown = Aux.gui.dropdown(private.elements[FILTER].filters) + dropdown:SetPoint('TOPLEFT', 14, -200) dropdown:SetWidth(250) dropdown:SetHeight(10) local label = Aux.gui.label(dropdown, 13) label:SetPoint('BOTTOMLEFT', dropdown, 'TOPLEFT', -2, -4) label:SetText('Min Rarity') - private.quality_dropdown = dropdown - UIDropDownMenu_Initialize(dropdown, AuxFilterSearchFrameFiltersQualityDropDown_Initialize) + UIDropDownMenu_Initialize(dropdown, private.initialize_quality_dropdown) dropdown:SetScript('OnShow', function() - UIDropDownMenu_Initialize(this, AuxFilterSearchFrameFiltersQualityDropDown_Initialize) + UIDropDownMenu_Initialize(this, private.initialize_quality_dropdown) end) + private.quality_dropdown = dropdown end do local editbox = Aux.gui.editbox(private.elements[FILTER].filters, '$parentMinLevel') @@ -761,7 +787,6 @@ function public.start_search() local queries --- queries = { private.create_filter_query() } local filters = Aux.scan_util.parse_filter_string(private.search_box:GetText()) if filters then queries = Aux.util.map(filters, function(filter) @@ -808,9 +833,7 @@ function public.start_search() end, on_read_auction = function(auction_info) auctions = auctions or {} --- if Aux.info.tooltip_match(tooltip_patterns, auction_info.tooltip) then tinsert(auctions, private.create_auction_record(auction_info)) --- end end, on_complete = function() auctions = auctions or {} @@ -961,83 +984,93 @@ function public.on_update() end end -function AuxFilterSearchFrameFiltersCategoryDropDown_Initialize(arg1) - local level = arg1 or 1 +function private.initialize_class_dropdown() + local function on_click() + if this.value ~= UIDropDownMenu_GetSelectedValue(private.class_dropdown) then + UIDropDownMenu_ClearAll(private.subclass_dropdown) + UIDropDownMenu_ClearAll(private.slot_dropdown) + end + UIDropDownMenu_SetSelectedValue(private.class_dropdown, this.value) + end - if level == 1 then - local value = {} - UIDropDownMenu_AddButton({ - text = ALL, - value = value, - func = AuxFilterSearchFrameFiltersCategoryDropDown_OnClick, - }, 1) + UIDropDownMenu_AddButton{ + text = ALL, + func = on_click, + } - for i, class in pairs({ GetAuctionItemClasses() }) do - local value = { class = i } - UIDropDownMenu_AddButton({ - hasArrow = GetAuctionItemSubClasses(value.class), - text = class, - value = value, - func = AuxFilterSearchFrameFiltersCategoryDropDown_OnClick, - }, 1) - end - end - - if level == 2 then - local menu_value = UIDROPDOWNMENU_MENU_VALUE - for i, subclass in pairs({ GetAuctionItemSubClasses(menu_value.class) }) do - local value = { class = menu_value.class, subclass = i } - UIDropDownMenu_AddButton({ - hasArrow = GetAuctionInvTypes(value.class, value.subclass), - text = subclass, - value = value, - func = AuxFilterSearchFrameFiltersCategoryDropDown_OnClick, - }, 2) - end - end - - if level == 3 then - local menu_value = UIDROPDOWNMENU_MENU_VALUE - for i, slot in pairs({ GetAuctionInvTypes(menu_value.class, menu_value.subclass) }) do - local slot_name = getglobal(slot) - local value = { class = menu_value.class, subclass = menu_value.subclass, slot = i } - UIDropDownMenu_AddButton({ - text = slot_name, - value = value, - func = AuxFilterSearchFrameFiltersCategoryDropDown_OnClick, - }, 3) - end - end + for i, class in pairs({ GetAuctionItemClasses() }) do + UIDropDownMenu_AddButton{ + text = class, + value = i, + func = on_click, + } + end end -function AuxFilterSearchFrameFiltersCategoryDropDown_OnClick() - local qualified_name = ({ GetAuctionItemClasses() })[this.value.class] or 'All' - if this.value.subclass then - local subclass_name = ({ GetAuctionItemSubClasses(this.value.class) })[this.value.subclass] - qualified_name = qualified_name .. ' - ' .. subclass_name - if this.value.slot then - local slot_name = getglobal(({ GetAuctionInvTypes(this.value.class, this.value.subclass) })[this.value.slot]) - qualified_name = qualified_name .. ' - ' .. slot_name - end - end +function private.initialize_subclass_dropdown() - UIDropDownMenu_SetSelectedValue(private.category_dropdown, this.value) - UIDropDownMenu_SetText(qualified_name, private.category_dropdown) - CloseDropDownMenus(1) + local function on_click() + if this.value ~= UIDropDownMenu_GetSelectedValue(private.subclass_dropdown) then + UIDropDownMenu_ClearAll(private.slot_dropdown) + end + UIDropDownMenu_SetSelectedValue(private.subclass_dropdown, this.value) + end + + local class_index = UIDropDownMenu_GetSelectedValue(private.class_dropdown) + + if class_index and GetAuctionItemSubClasses(class_index) then + UIDropDownMenu_AddButton{ + text = ALL, + func = on_click, + } + + for i, subclass in pairs({ GetAuctionItemSubClasses(class_index) }) do + UIDropDownMenu_AddButton{ + text = subclass, + value = i, + func = on_click, + } + end + end end -function AuxFilterSearchFrameFiltersQualityDropDown_Initialize() +function private.initialize_slot_dropdown() + + local function on_click() + UIDropDownMenu_SetSelectedValue(private.slot_dropdown, this.value) + end + + local class_index = UIDropDownMenu_GetSelectedValue(private.class_dropdown) + local subclass_index = UIDropDownMenu_GetSelectedValue(private.subclass_dropdown) + + if class_index and subclass_index and GetAuctionInvTypes(class_index, subclass_index) then + UIDropDownMenu_AddButton{ + text = ALL, + func = on_click, + } + + for i, slot in pairs({ GetAuctionInvTypes(class_index, subclass_index) }) do + local slot_name = getglobal(slot) + UIDropDownMenu_AddButton{ + text = slot_name, + value = slot, + func = on_click, + } + end + end +end + +function private.initialize_quality_dropdown() local function on_click() UIDropDownMenu_SetSelectedValue(private.quality_dropdown, this.value) end UIDropDownMenu_AddButton{ - text = 'All', - value = -1, + text = ALL, func = on_click, } - for i=0,getn(ITEM_QUALITY_COLORS)-2 do + for i=0,4 do UIDropDownMenu_AddButton{ text = getglobal('ITEM_QUALITY'..i..'_DESC'), value = i, diff --git a/filter_search_frame.xml b/filter_search_frame.xml index c7e6466..74b9a99 100644 --- a/filter_search_frame.xml +++ b/filter_search_frame.xml @@ -40,14 +40,13 @@ - - + + - - - + + @@ -56,8 +55,8 @@ - - + + diff --git a/groups.lua b/groups.lua index a81da89..f102435 100644 --- a/groups.lua +++ b/groups.lua @@ -1,19 +1,6 @@ local m = {} Aux.test = m -function m.on_char() - for _, data in ipairs(TSM.db.global.savedSearches) do - if data.searchMode == 'normal' then - local prevSearch = strlower(data.filter) - if strsub(prevSearch, 1, textLen) == text then - self:SetText(prevSearch) - self:HighlightText(textLen, -1) - break - end - end - end -end - function m.prettify_search(search) local item_pattern = '([^/;]+)([^;]*)/exact' while true do @@ -32,21 +19,92 @@ function m.display_name(item_id) end function m:complete() - local options = {'exact', 'even', 'discard' } - - for _, class in ipairs({ GetAuctionItemClasses() }) do - tinsert(options, class) - end local filter_string = this:GetText() - local start_index, _, current_modifier = strfind(filter_string, '([^/;]*)$') - current_modifier = current_modifier or '' - for _, option in ipairs(options) do - if strfind(strupper(option), '^'..strupper(current_modifier)) then - this:SetText(string.sub(filter_string, 1, start_index - 1)..option) - this:HighlightText(strlen(filter_string), -1) - return + local completed_filter_string = ({strfind(filter_string, '([^;]*)/[^/]*$')})[3] + local current_filter = completed_filter_string and Aux.scan_util.filter_from_string(completed_filter_string) + + local options = {} + + if current_filter or not completed_filter_string then + current_filter = current_filter or {} + + if current_filter.name + and Aux.static.auctionable_items[strupper(current_filter.name)] + and not current_filter.min_level + and not current_filter.max_level + and not current_filter.class + and not current_filter.subclass + and not current_filter.slot + and not current_filter.quality + and not current_filter.usable + then + tinsert(options, 'exact') + end + + -- classes + if not current_filter.class and not current_filter.exact then + for _, class in ipairs({ GetAuctionItemClasses() }) do + tinsert(options, class) + end + end + + -- subclasses + if current_filter.class and not current_filter.subclass then + for _, class in ipairs({ GetAuctionItemSubClasses(current_filter.class) }) do + tinsert(options, class) + end + end + + -- slots + if current_filter.class and current_filter.subclass then + for _, invtype in ipairs({ GetAuctionInvTypes(current_filter.class, current_filter.subclass) }) do + tinsert(options, getglobal(invtype)) + end + end + + -- usable + if not current_filter.usable and not current_filter.exact then + tinsert(options, 'usable') + end + + -- rarities + if not current_filter.quality and not current_filter.exact then + for i=0,4 do + tinsert(options, getglobal('ITEM_QUALITY'..i..'_DESC')) + end + end + + -- discard + if not current_filter.discard then + tinsert(options, 'discard') + end + + -- item names + snipe.log(key_count) + if not completed_filter_string then + local item_names = {} + for key, value in Aux.static.auctionable_items do + if type(key) == 'number' then + tinsert(item_names, value.name) + end + end + sort(item_names) + for _, item_name in ipairs(item_names) do + tinsert(options, item_name) + end + end + + local start_index, _, current_modifier = strfind(filter_string, '([^/;]*)$') + current_modifier = current_modifier or '' + + for _, option in ipairs(options) do + if strfind(strupper(option), '^'..strupper(current_modifier)) then + this:SetText(string.sub(filter_string, 1, start_index - 1)..option) + this:HighlightText(strlen(filter_string), -1) + return + end end end end \ No newline at end of file diff --git a/scan_util.lua b/scan_util.lua index 3bfb5c6..a35b866 100644 --- a/scan_util.lua +++ b/scan_util.lua @@ -47,34 +47,17 @@ function m.find(test, query, page, status_bar, on_failure, on_success) end) end -function m.create_item_filter(item_id) +function m.create_item_query(item_id) + local item_info = Aux.static.item_info(item_id) if item_info then + local filter = m.filter_from_string(item_info.name..'/exact') return { - exact_only = true, - name = item_info.name, - min_level = item_info.level, - min_level = item_info.level, - slot = item_info.slot, - class = item_info.class, - subclass = item_info.subclass, - quality = item_info.quality, - usable = item_info.usable, - } - end -end - -function m.create_item_query(item_id) - - local filter = m.create_item_filter(item_id) - - if filter then - return { - type = 'list', - start_page = 0, - validator = m.validator(filter), - blizzard_query = m.blizzard_query(filter), + type = 'list', + start_page = 0, + validator = m.validator(filter), + blizzard_query = m.blizzard_query(filter), } end end @@ -111,10 +94,10 @@ function m.filter_from_string(filter_term) if tonumber(str) then if not filter.min_level then filter.min_level = tonumber(str) - elseif not filter.max_level then + elseif not filter.max_level and tonumber(str) >= filter.min_level then filter.max_level = tonumber(str) else - return false, 'Invalid Min Level' + return false, 'Invalid Level Range' end elseif not filter.class and Aux.item_class_index(str) then if not filter.class then @@ -128,6 +111,12 @@ function m.filter_from_string(filter_term) else return false, 'Invalid Item Subclass' end + elseif filter.subclass and Aux.item_slot(filter.class, filter.class, str) then + if not filter.slot then + filter.slot = Aux.item_slot(filter.class, filter.class, str) + else + return false, 'Invalid Item Slot' + end elseif Aux.item_quality_index(str) then if not filter.quality then filter.quality = Aux.item_quality_index(str) @@ -135,28 +124,22 @@ function m.filter_from_string(filter_term) return false, 'Invalid Item Rarity' end elseif strlower(str) == 'usable' then - if not filter.usable_only then - filter.usable_only = true + if not filter.usable then + filter.usable = true else return false, 'Invalid Usable Only Filter' end elseif strlower(str) == 'exact' then - if not filter.exact_only then - filter.exact_only = true + if not filter.exact then + filter.exact = true else return false, 'Invalid Exact Only Filter' end - elseif strlower(str) == 'even' then - if not filter.even_only then - filter.even_only = true - else - return false, 'Invalid Even Only Filter' - end elseif strlower(str) == 'discard' then if not filter.discard then filter.discard = true else - return false, 'Invalid Even Only Filter' + return false, 'Invalid Discard Filter' end elseif Aux.money.from_string(str) > 0 then if not filter.max_price then @@ -171,71 +154,75 @@ function m.filter_from_string(filter_term) end end - if filter.exact_only then - if filter.min_level or filter.max_level or filter.class or filter.subclass or filter.quality or filter.usable_only then + if filter.exact then + if filter.min_level or filter.max_level or filter.class or filter.subclass or filter.slot or filter.quality or filter.usable or not Aux.static.auctionable_items[strupper(filter.name)] then return false, 'Invalid Exact Only Filter' end - local id = Aux.static.auctionable_items[strupper(filter.name)] - if id then - local item_filter = m.create_item_filter(id) - item_filter.even_only = filter.even_only - item_filter.discard = filter.discard - return item_filter - end - return false, 'Invalid Exact Only Filter' - end - - if filter.max_level then - filter.min_level, filter.max_level = min(filter.min_level, filter.max_level), max(filter.min_level, filter.max_level) end return filter end -function m.filter_to_string(filter) -- TODO belongs in filter search +function m.filter_to_string(filter) local filter_term = filter.name or '' + local function add(part) + filter_term = filter_term == '' and part or filter_term..'/'..part + end + + if filter.min_level then + add(filter.min_level) + end + if filter.max_level then - filter_term = format('%s/%d/%d', filter_term, filter.min_level, filter.max_level) - elseif filter.min_level then - filter_term = format('%s/%d', filter_term, filter.min_level) + add(filter.max_level) end if filter.class then local classes = { GetAuctionItemClasses() } - filter_term = format('%s/%s', filter_term, classes[filter.class]) + add(classes[filter.class]) if filter.subclass then local subclasses = {GetAuctionItemSubClasses(filter.class)} - filter_term = format('%s/%s', filter_term, subclasses[filter.subclass]) + add(subclasses[filter.subclass]) + if filter.slot then + add(getglobal(filter.slot)) + end end end if filter.quality then - filter_term = format('%s/%s', filter_term, getglobal['ITEM_QUALITY'..filter.quality..'_DESC']) + add(getglobal('ITEM_QUALITY'..filter.quality..'_DESC')) end - if filter.usable_only then - filter_term = format('%s/usable', filter_term) + if filter.usable then + add(filter_term) end - if filter.exact_only then - filter_term = format('%s/exact', filter_term) + if filter.exact then + add(filter_term) end return filter_term end function m.blizzard_query(filter) + + local item_info + if filter.exact then + local item_id = Aux.static.auctionable_items[strupper(filter.name)] + item_info = Aux.static.auctionable_items[item_id] + end + return { name = filter.name, - min_level = filter.min_level, - max_level = filter.max_level, - slot = filter.slot, - class = filter.class, - subclass = filter.subclass, - usable = filter.usable_only and 1 or 0, - quality = filter.quality, + min_level = filter.exact and item_info.level or filter.min_level, + max_level = filter.exact and item_info.level or filter.max_level, + slot = filter.exact and item_info.slot or filter.slot, + class = filter.exact and item_info.class or filter.class, + subclass = filter.exact and item_info.subclass or filter.subclass, + usable = filter.exact and item_info.usable or filter.usable and 1 or 0, + quality = filter.exact and item_info.quality or filter.quality, } end @@ -245,10 +232,7 @@ function m.validator(filter) if filter.discard then return end - if filter.exact_only and record.name ~= filter.name then - return - end - if filter.even_only and mod(record.aux_quantity, 5) ~= 0 then + if filter.exact and strupper(record.name) ~= strupper(filter.name) then return end if filter.min_level and record.level < filter.min_level then