implemented fuzzy search for buy

This commit is contained in:
Manuel Simon Hirsig
2015-10-07 00:11:36 +02:00
parent cfe55f902b
commit 0e70040682
7 changed files with 173 additions and 67 deletions
+1 -1
View File
@@ -20,5 +20,5 @@ about.xml
list.xml
completion.lua
completion.xml
+4 -12
View File
@@ -419,21 +419,12 @@ function AuxBuyTooltipButton_OnClick()
local pattern = AuxBuyTooltipInputBox:GetText()
if pattern ~= '' then
Aux.util.set_add(tooltip_patterns, pattern)
end
AuxBuyTooltipInputBox:SetText('')
if DropDownList1:IsVisible() then
if DropDownList1:IsVisible() then
Aux.buy.toggle_tooltip_dropdown()
end
Aux.buy.toggle_tooltip_dropdown()
end
Aux.buy.toggle_tooltip_dropdown()
end
function AuxBuyTooltipRemoveButton_OnClick()
Aux.util.set_remove(tooltip_patterns, AuxBuyTooltipInputBox:GetText())
AuxBuyTooltipInputBox:SetText('')
if DropDownList1:IsVisible() then
Aux.buy.toggle_tooltip_dropdown()
end
Aux.buy.toggle_tooltip_dropdown()
end
function AuxBuyTooltipDropDown_Initialize()
@@ -442,6 +433,7 @@ function AuxBuyTooltipDropDown_Initialize()
text = pattern,
value = pattern,
func = AuxBuyTooltipDropDown_OnClick,
notCheckable = true,
}
end
end
+12 -5
View File
@@ -231,12 +231,19 @@
</Layer>
</Layers>
<Scripts>
<OnChar>
Aux.util.item_name_autocomplete()
</OnChar>
<OnTextChanged>
Aux.completion.make_suggestions(this)
</OnTextChanged>
<OnTabPressed>
Aux.completion.highlight_next(this)
</OnTabPressed>
<OnEnterPressed>
this:ClearFocus()
Aux.buy.SearchButton_onclick()
if Aux.completion.highlighted() then
Aux.completion.select(this)
else
this:ClearFocus()
Aux.buy.SearchButton_onclick()
end
</OnEnterPressed>
</Scripts>
</EditBox>
+112 -29
View File
@@ -1,44 +1,127 @@
Aux.completion = {}
local NUM_MATCHES = 5
local leven, fuzzy, populate_dropdown, toggle_dropdown, suggestions, highlight
local item_names = {}
for item_id=1,100 do
local current_suggestions = {}
local selected_index
for item_id=1,30000 do
local name = GetItemInfo(item_id)
tinsert(item_names, name)
if name then
tinsert(item_names, name)
end
end
function leven(s,t)
if s == '' then return strlen(t) end
if t == '' then return strlen(s) end
local s1 = string.sub(s, 2, -1)
local t1 = string.sub(t, 2, -1)
if string.sub(s, 0, 1) == string.sub(t, 0, 1) then
return leven(s1, t1)
end
return 1 + math.min(
leven(s1, t1),
leven(s, t1),
leven(s1, t)
)
function fuzzy(input)
local uppercase_input = strupper(input)
local pattern = '(.*)'
for i=1,strlen(uppercase_input) do
pattern = pattern .. string.sub(uppercase_input, i, i) .. '(.*)'
end
return function(input)
local match = { string.find(strupper(input), pattern) }
if match[1] then
local rating = 1
for i=3,getn(match) do
rating = rating * max(strlen(match[i]), 1)
end
return rating
end
end
end
function get_matches(input)
local closest = {}
for _, name in pairs(item_names) do
local edit_distance = leven(input, name)
if getn(closest) < NUM_MATCHES then
tinsert(closest, { name=name, edit_distance=edit_distance })
function update_highlighting()
for i=1,32 do
local highlight = getglobal('DropDownList1Button' .. i .. 'Highlight')
if i == selected_index then
highlight:Show()
else
sort(closest, function(a, b) return a.edit_distance > b.edit_distance end)
if closest[1].edit_distance > edit_distance then
closest[1] = { name=name, edit_distance=edit_distance }
highlight:Hide()
end
end
end
function suggestions(input)
local matcher = fuzzy(input)
local best = {}
for _, name in ipairs(item_names) do
local rating = matcher(name)
if rating then
if getn(best) < NUM_MATCHES then
tinsert(best, { name=name, rating=rating })
sort(best, function(a, b) return a.rating < b.rating end)
else
if best[1].rating > rating then
best[1] = { name=name, rating=rating }
sort(best, function(a, b) return a.rating < b.rating end)
end
end
end
end
for _, winner in ipairs(closest) do
Aux.log(winner.name)
return Aux.util.map(best, function(match) return match.name end)
end
function Aux.completion.make_suggestions(input_box)
selected_index = nil
update_highlighting()
local input = input_box:GetText()
if input == '' then
current_suggestions = {}
else
current_suggestions = suggestions(input)
UIDropDownMenu_Initialize(AuxCompletionDropDown, function() populate_dropdown(input_box, current_suggestions) end)
end
if DropDownList1:IsVisible() then
toggle_dropdown(input_box)
end
toggle_dropdown(input_box)
end
function Aux.completion.highlight_next(input_box)
if getn(current_suggestions) > 0 then
selected_index = selected_index and math.mod(selected_index, getn(current_suggestions)) + 1 or 1
end
update_highlighting()
end
function Aux.completion.highlighted()
return selected_index ~= nil
end
function Aux.completion.select(input_box)
Aux.completion.set_quietly(input_box, current_suggestions[selected_index])
selected_index = nil
update_highlighting()
CloseDropDownMenus(1)
end
function Aux.completion.set_quietly(edit_box, text)
local orig = edit_box:GetScript('OnTextChanged')
edit_box:SetScript('OnTextChanged', function() edit_box:SetScript('OnTextChanged', orig) end)
edit_box:SetText(text)
end
function populate_dropdown(input_box, suggestions)
for _, suggestion in ipairs(suggestions) do
UIDropDownMenu_AddButton{
text = suggestion,
value = suggestion,
notCheckable = true,
func = function()
Aux.completion.set_quietly(input_box, this.value)
end,
}
end
end
function toggle_dropdown(input_box)
ToggleDropDownMenu(1, nil, AuxCompletionDropDown, input_box, -12, 4)
end
+8
View File
@@ -0,0 +1,8 @@
<Ui xsi:schemaLocation="http://www.blizzard.com/wow/ui/">
<Script file="completion.lua"/>
<Frame name="AuxCompletionDropDown" inherits="UIDropDownMenuTemplate" hidden="true">
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="555" y="0"/></Offset></Anchor></Anchors>
</Frame>
</Ui>
-1
View File
@@ -114,7 +114,6 @@ end
function Aux_SetupHookFunctions()
BrowseName:SetScript('OnChar', Aux.util.item_name_autocomplete)
Aux.orig.AuctionFrameAuctions_OnShow = AuctionFrameAuctions_OnShow
AuctionFrameAuctions_OnShow = Aux_Sell_AuctionFrameAuctions_OnShow
+36 -19
View File
@@ -6,6 +6,9 @@ Aux.util.GT = {}
local merge, copy_array
function Aux.util.pass()
end
function Aux.util.iter(array)
local with_index = ipairs(array)
return function()
@@ -14,20 +17,6 @@ function Aux.util.iter(array)
end
end
function Aux.util.item_name_autocomplete()
local text = this:GetText()
local textlen = strlen(text)
local name
for item_id=1,30000 do
name = GetItemInfo(item_id)
if name and strfind(strupper(name), '^' .. strupper(text)) then
this:SetText(name)
this:HighlightText(textlen, -1)
return
end
end
end
function Aux.util.format_money(val)
local g = math.floor(val / 10000)
@@ -91,14 +80,42 @@ function Aux.util.all(xs, p)
return holds
end
function Aux.util.set_filter(set, p)
filtered = {}
for x, _ in pairs(set) do
function Aux.util.set_filter(xs, p)
ys = {}
for x, _ in pairs(xs) do
if p(x) then
Aux.util.set_add(filtered, x)
Aux.util.set_add(ys, x)
end
end
return filtered
return ys
end
function Aux.util.filter(xs, p)
ys = {}
for _, x in ipairs(xs) do
if p(x) then
tinsert(ys, x)
end
end
return ys
end
function Aux.util.map(xs, f)
ys = {}
for _, x in ipairs(xs) do
tinsert(ys, f(x))
end
return ys
end
function Aux.util.take(n, xs)
ys = {}
for i=1,n do
if xs[i] then
tinsert(ys, xs[i])
end
end
return ys
end
function Aux.util.merge_sort(A, comp)