@@ -184,12 +184,17 @@ function TradeQueryClass:PriceBuilderProcessPoENinjaResponse(resp)
184184 if resp then
185185 -- Populate the chaos-converted values for each tradeId
186186 for currencyName , chaosEquivalent in pairs (resp ) do
187+ local currencyName = currencyName :lower ()
187188 if self .currencyConversionTradeMap [currencyName ] then
188189 self .pbCurrencyConversion [self .pbLeague ][self .currencyConversionTradeMap [currencyName ]] = chaosEquivalent
189190 else
190191 ConPrintf (" Unhandled Currency Name: '" .. currencyName .. " '" )
191192 end
192193 end
194+ -- if nothing was actually found, we should add a notice
195+ if next (self .pbCurrencyConversion [self .pbLeague ]) == nil then
196+ self :SetNotice (self .controls .pbNotice , " No currencies received from PoE Ninja" )
197+ end
193198 else
194199 self :SetNotice (self .controls .pbNotice , " PoE Ninja JSON Processing Error" )
195200 end
@@ -277,7 +282,23 @@ You can click this button to enter your POESESSID.
277282- You can only generate weighted searches for public leagues. (Generated searches can be modified
278283on trade site to work on other leagues and realms)]]
279284
280- -- Fetches Box
285+ -- Buyout selection
286+ self .tradeTypes = {
287+ " Instant buyout" ,
288+ " Instant buyout and in person" ,
289+ " In person (online in league)" ,
290+ " In person (online)" ,
291+ " Any (includes offline)"
292+ }
293+
294+ self .controls .tradeTypeSelection = new (" DropDownControl" , { " TOPLEFT" , self .controls .poesessidButton , " BOTTOMLEFT" },
295+ { 0 , row_vertical_padding , 188 , row_height }, self .tradeTypes , function (index , value )
296+ self .tradeTypeIndex = index
297+ end )
298+ -- remember previous choice
299+ self .controls .tradeTypeSelection :SetSel (self .tradeTypeIndex or 1 )
300+
301+ -- Fetches Box
281302 self .maxFetchPerSearchDefault = 2
282303 self .controls .fetchCountEdit = new (" EditControl" , {" TOPRIGHT" , nil , " TOPRIGHT" }, {- 12 , 19 , 154 , row_height }, " " , " Fetch Pages" , " %D" , 3 , function (buf )
283304 self .maxFetchPages = m_min (m_max (tonumber (buf ) or self .maxFetchPerSearchDefault , 1 ), 10 )
@@ -338,20 +359,12 @@ on trade site to work on other leagues and realms)]]
338359[[ Weighted Sum searches will always sort using descending weighted sum
339360Additional post filtering options can be done these include:
340361Highest Stat Value - Sort from highest to lowest Stat Value change of equipping item
341- Highest Stat Value / Price - Sorts from highest to lowest Stat Value per currency
362+ Highest Stat Value / Price - Sorts from highest to lowest by estimated Stat Value per currency
342363Lowest Price - Sorts from lowest to highest price of retrieved items
343364Highest Weight - Displays the order retrieved from trade]]
344- self .controls .itemSortSelection :SetSel (self .pbItemSortSelectionIndex )
345- self .controls .itemSortSelectionLabel = new (" LabelControl" , {" TOPRIGHT" , self .controls .itemSortSelection , " TOPLEFT" }, {- 4 , 0 , 60 , 16 }, " ^7Sort By:" )
346-
347- -- Use Enchant in DPS sorting
348- self .controls .enchantInSort = new (" CheckBoxControl" , {" TOPRIGHT" ,self .controls .fetchCountEdit ," TOPLEFT" }, {- 8 , 0 , row_height }, " Include Enchants:" , function (state )
349- self .enchantInSort = state
350- for row_idx , _ in pairs (self .resultTbl ) do
351- self :UpdateControlsWithItems (row_idx )
352- end
353- end )
354- self .controls .enchantInSort .tooltipText = " This includes enchants in sorting that occurs after trade results have been retrieved"
365+ -- avoid calling selFunc to avoid updating controls before they are initialised
366+ self .controls .itemSortSelection :SetSel (self .pbItemSortSelectionIndex , true )
367+ self .controls .itemSortSelectionLabel = new (" LabelControl" , {" TOPRIGHT" , self .controls .itemSortSelection , " TOPLEFT" }, {- 4 , 0 , 56 , 16 }, " ^7Sort By:" )
355368
356369 -- Realm selection
357370 self .controls .realmLabel = new (" LabelControl" , {" LEFT" , self .controls .setSelect , " RIGHT" }, {18 , 0 , 20 , row_height - 4 }, " ^7Realm:" )
@@ -449,7 +462,7 @@ Highest Weight - Displays the order retrieved from trade]]
449462 t_insert (slotTables , { slotName = self .itemsTab .sockets [nodeId ].label , nodeId = nodeId })
450463 end
451464
452- self .controls .sectionAnchor = new (" LabelControl" , {" LEFT" , self .controls .poesessidButton , " LEFT" }, {0 , 0 , 0 , 0 }, " " )
465+ self .controls .sectionAnchor = new (" LabelControl" , {" LEFT" , self .controls .tradeTypeSelection , " LEFT" }, {0 , row_vertical_padding + row_height , 0 , 0 }, " " )
453466 top_pane_alignment_ref = {" TOPLEFT" , self .controls .sectionAnchor , " TOPLEFT" }
454467 local scrollBarShown = # slotTables > 21 -- clipping starts beyond this
455468 -- dynamically hide rows that are above or below the scrollBar
@@ -747,10 +760,7 @@ function TradeQueryClass:GetResultEvaluation(row_idx, result_index, calcFunc, ba
747760 table.sort (result .evaluation , function (a , b ) return a .weight > b .weight end )
748761 else
749762 local item = new (" Item" , result .item_string )
750- if not self .enchantInSort then -- Calc item DPS without anoint or enchant as these can generally be added after.
751- item .enchantModLines = { }
752- item :BuildAndParseRaw ()
753- end
763+
754764 local output = self :ReduceOutput (calcFunc ({ repSlotName = slotName , repItem = item }))
755765 local weight = self .tradeQueryGenerator .WeightedRatioOutputs (baseOutput , output , self .statSortSelectionList )
756766 result .evaluation = {{ output = output , weight = weight }}
@@ -759,6 +769,22 @@ function TradeQueryClass:GetResultEvaluation(row_idx, result_index, calcFunc, ba
759769end
760770
761771-- Method to update controls after a search is completed
772+ function TradeQueryClass :UpdateDropdownList (row_idx )
773+ local dropdownLabels = {}
774+
775+ if not self .resultTbl [row_idx ] then return end
776+
777+ for result_index = 1 , # self .resultTbl [row_idx ] do
778+
779+ local pb_index = self .sortedResultTbl [row_idx ][result_index ].index
780+ local result = self .resultTbl [row_idx ][pb_index ]
781+ local price = string.format (" %s(%d %s)" , colorCodes [" CURRENCY" ], result .amount , result .currency )
782+ local item = new (" Item" , result .item_string )
783+ table.insert (dropdownLabels , colorCodes [item .rarity ] .. item .name .. price )
784+ end
785+ self .controls [" resultDropdown" .. row_idx ].selIndex = 1
786+ self .controls [" resultDropdown" .. row_idx ]:SetList (dropdownLabels )
787+ end
762788function TradeQueryClass :UpdateControlsWithItems (row_idx )
763789 local sortMode = self .itemSortSelectionList [self .pbItemSortSelectionIndex ]
764790 local sortedItems , errMsg = self :SortFetchResults (row_idx , sortMode )
@@ -782,14 +808,7 @@ function TradeQueryClass:UpdateControlsWithItems(row_idx)
782808 amount = self .resultTbl [row_idx ][pb_index ].amount ,
783809 }
784810 self .controls .fullPrice .label = " Total Price: " .. self :GetTotalPriceString ()
785- local dropdownLabels = {}
786- for result_index = 1 , # self .resultTbl [row_idx ] do
787- local pb_index = self .sortedResultTbl [row_idx ][result_index ].index
788- local item = new (" Item" , self .resultTbl [row_idx ][pb_index ].item_string )
789- table.insert (dropdownLabels , colorCodes [item .rarity ].. item .name )
790- end
791- self .controls [" resultDropdown" .. row_idx ].selIndex = 1
792- self .controls [" resultDropdown" .. row_idx ]:SetList (dropdownLabels )
811+ self :UpdateDropdownList (row_idx )
793812end
794813
795814-- Method to set the current result return in the pane based of an index
@@ -838,6 +857,7 @@ function TradeQueryClass:SortFetchResults(row_idx, mode)
838857 return newTbl
839858 elseif mode == self .sortModes .StatValue then
840859 for result_index = 1 , # self .resultTbl [row_idx ] do
860+ -- ConPrintf("%.3f", getResultWeight(result_index))
841861 t_insert (newTbl , { outputAttr = getResultWeight (result_index ), index = result_index })
842862 end
843863 table.sort (newTbl , function (a ,b ) return a .outputAttr > b .outputAttr end )
@@ -847,7 +867,20 @@ function TradeQueryClass:SortFetchResults(row_idx, mode)
847867 return nil , " MissingConversionRates"
848868 end
849869 for result_index = 1 , # self .resultTbl [row_idx ] do
850- t_insert (newTbl , { outputAttr = getResultWeight (result_index ) / priceTable [result_index ], index = result_index })
870+ -- generally, because we are filtering our results to only the top
871+ -- contenders, we will end up with a small spread of result weights.
872+ -- this is however not true for prices as *decent* items might start
873+ -- at a couple of div while perfect items are worth hundreds of
874+ -- divs. I think the best option here is weight - k * log10(price)
875+ -- to prioritise good items while only slightly punishing high
876+ -- prices. another option would be weight / log10(price), but it
877+ -- still seems to overrate very cheap items that are bad
878+
879+ -- scaling factor for price
880+ local k = 0.03
881+ t_insert (newTbl ,
882+ { outputAttr = getResultWeight (result_index ) - k * math.log (priceTable [result_index ], 10 ), index =
883+ result_index })
851884 end
852885 table.sort (newTbl , function (a ,b ) return a .outputAttr > b .outputAttr end )
853886 elseif mode == self .sortModes .Price then
@@ -927,6 +960,7 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro
927960 return
928961 end
929962 context .controls [" priceButton" .. context .row_idx ].label = " Searching..."
963+ self .lastQuery = query
930964 self .tradeQueryRequests :SearchWithQueryWeightAdjusted (self .pbRealm , self .pbLeague , query ,
931965 function (items , errMsg )
932966 if errMsg then
@@ -936,6 +970,25 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro
936970 else
937971 self :SetNotice (context .controls .pbNotice , " " )
938972 end
973+
974+ -- replace eldritch mods or enchants if the user requested
975+ -- so in TradeQueryGenerator
976+ if self .tradeQueryGenerator .lastCopyEldritch or
977+ self .tradeQueryGenerator .lastCopyEnchantMode == " Copy Current" then
978+ for i , _ in ipairs (items ) do
979+ local item = new (" Item" , items [i ].item_string )
980+ self .itemsTab :CopyAnointsAndEldritchImplicits (item , true , true , context .slotTbl .slotName )
981+ items [i ].item_string = item :BuildRaw ()
982+ end
983+ elseif self .tradeQueryGenerator .lastCopyEnchantMode == " Remove" then
984+ for i , _ in ipairs (items ) do
985+ local item = new (" Item" , items [i ].item_string )
986+ item .enchantModLines = {}
987+ items [i ].item_string = item :BuildRaw ()
988+ end
989+ end
990+
991+
939992 self .resultTbl [context .row_idx ] = items
940993 self :UpdateControlsWithItems (context .row_idx )
941994 context .controls [" priceButton" .. context .row_idx ].label = " Price Item"
@@ -983,11 +1036,12 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro
9831036 controls [" priceButton" .. row_idx ] = new (" ButtonControl" , { " TOPLEFT" , controls [" uri" .. row_idx ], " TOPRIGHT" }, {8 , 0 , 100 , row_height }, " Price Item" ,
9841037 function ()
9851038 controls [" priceButton" .. row_idx ].label = " Searching..."
986- self .tradeQueryRequests :SearchWithURL (controls [" uri" .. row_idx ].buf , function (items , errMsg )
1039+ self .tradeQueryRequests :SearchWithURL (controls [" uri" .. row_idx ].buf , function (items , errMsg , query )
9871040 if errMsg then
9881041 self :SetNotice (controls .pbNotice , " Error: " .. errMsg )
9891042 else
9901043 self :SetNotice (controls .pbNotice , " " )
1044+ self .lastQuery = query
9911045 self .resultTbl [row_idx ] = items
9921046 self :UpdateControlsWithItems (row_idx )
9931047 end
@@ -1019,15 +1073,11 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro
10191073 self .controls .fullPrice .label = " Total Price: " .. self :GetTotalPriceString ()
10201074 end )
10211075 controls [" changeButton" .. row_idx ].shown = function () return self .resultTbl [row_idx ] end
1022- local dropdownLabels = {}
1023- for _ , sortedResult in ipairs (self .sortedResultTbl [row_idx ] or {}) do
1024- local item = new (" Item" , self .resultTbl [row_idx ][sortedResult .index ].item_string )
1025- table.insert (dropdownLabels , colorCodes [item .rarity ].. item .name )
1026- end
1027- controls [" resultDropdown" .. row_idx ] = new (" DropDownControl" , { " TOPLEFT" , controls [" changeButton" .. row_idx ], " TOPRIGHT" }, {8 , 0 , 325 , row_height }, dropdownLabels , function (index )
1076+ controls [" resultDropdown" .. row_idx ] = new (" DropDownControl" , { " TOPLEFT" , controls [" changeButton" .. row_idx ], " TOPRIGHT" }, {8 , 0 , 325 , row_height }, {}, function (index )
10281077 self .itemIndexTbl [row_idx ] = self .sortedResultTbl [row_idx ][index ].index
10291078 self :SetFetchResultReturn (row_idx , self .itemIndexTbl [row_idx ])
10301079 end )
1080+ self :UpdateDropdownList (row_idx )
10311081 local function addMegalomaniacCompareToTooltipIfApplicable (tooltip , result_index )
10321082 if slotTbl .slotName ~= " Megalomaniac" then
10331083 return
@@ -1103,23 +1153,58 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro
11031153 return self .itemIndexTbl [row_idx ] and self .resultTbl [row_idx ][self .itemIndexTbl [row_idx ]].item_string ~= nil
11041154 end
11051155 -- Whisper so we can copy to clipboard
1106- controls [" whisperButton" .. row_idx ] = new (" ButtonControl" , { " TOPLEFT" , controls [" importButton" .. row_idx ], " TOPRIGHT" }, {8 , 0 , 185 , row_height }, function ()
1107- return self .totalPrice [row_idx ] and " Whisper for " .. self .totalPrice [row_idx ].amount .. " " .. self .totalPrice [row_idx ].currency or " Whisper"
1108- end , function ()
1109- Copy (self .resultTbl [row_idx ][self .itemIndexTbl [row_idx ]].whisper )
1110- end )
1111- controls [" whisperButton" .. row_idx ].enabled = function ()
1112- return self .itemIndexTbl [row_idx ] and self .resultTbl [row_idx ][self .itemIndexTbl [row_idx ]].whisper ~= nil
1113- end
1114- controls [" whisperButton" .. row_idx ].tooltipFunc = function (tooltip )
1156+ controls [" whisperButton" .. row_idx ] = new (" ButtonControl" ,
1157+ { " TOPLEFT" , controls [" importButton" .. row_idx ], " TOPRIGHT" }, { 8 , 0 , 170 , row_height }, function ()
1158+ local itemResult = self .itemIndexTbl [row_idx ] and self .resultTbl [row_idx ][self .itemIndexTbl [row_idx ]]
1159+
1160+ if not itemResult then return " " end
1161+
1162+ local price = self .totalPrice [row_idx ] and
1163+ self .totalPrice [row_idx ].amount .. " " .. self .totalPrice [row_idx ].currency
1164+
1165+ if itemResult .whisper then
1166+ return price and " Whisper for " .. price or " Whisper"
1167+ else
1168+ return price and " Search for " .. price or " Search"
1169+ end
1170+
1171+ end , function ()
1172+ local itemResult = self .itemIndexTbl [row_idx ] and self .resultTbl [row_idx ][self .itemIndexTbl [row_idx ]]
1173+ if itemResult .whisper then
1174+ Copy (itemResult .whisper )
1175+ else
1176+ local exactQuery = dkjson .decode (self .lastQuery )
1177+ -- use trade sum to get the specific item. both min and max
1178+ -- weight on site uses floats but only shows integer in the api
1179+ -- e.g. weight of 172.3 shows up as 172 in the api
1180+ exactQuery .query .stats [1 ].value = { min = floor (itemResult .weight , 1 ) - 1 , max = round (itemResult .weight , 1 ) + 1 }
1181+ -- also apply trader name. this should make false positives
1182+ -- extremely unlikely. this doesn't seem to take up a filter slot
1183+ exactQuery .query .filters = exactQuery .query .filters or { }
1184+ exactQuery .query .filters .trade_filters = exactQuery .query .filters .trade_filters or { filters = { } }
1185+ exactQuery .query .filters .trade_filters .filters = exactQuery .query .filters .trade_filters .filters or { }
1186+ exactQuery .query .filters .trade_filters .filters .account = { input = itemResult .trader }
1187+
1188+ local exactQueryStr = dkjson .encode (exactQuery )
1189+
1190+ self .tradeQueryRequests :SearchWithQuery (self .pbRealm , self .pbLeague , exactQueryStr , function (_ , _ )
1191+ end , {callbackQueryId = function (queryId )
1192+ local url = self .hostName .. " trade/search/" .. self .pbLeague .. " /" .. queryId
1193+ Copy (url )
1194+ OpenURL (url )
1195+ end })
1196+ end
1197+ end )
1198+
1199+ controls [" whisperButton" .. row_idx ].tooltipFunc = function (tooltip )
11151200 tooltip :Clear ()
1116- if self .itemIndexTbl [row_idx ] and self .resultTbl [row_idx ][self .itemIndexTbl [row_idx ]].item_string then
1117- tooltip .center = true
1118- tooltip :AddLine (16 , " Copies the item purchase whisper to the clipboard" )
1119- end
1201+ tooltip .center = true
1202+ local itemResult = self .itemIndexTbl [row_idx ] and self .resultTbl [row_idx ][self .itemIndexTbl [row_idx ]]
1203+ local text = itemResult .whisper and " Copies the item purchase whisper to the clipboard" or
1204+ " Opens the search page to show the item"
1205+ tooltip :AddLine (16 , text )
11201206 end
11211207end
1122-
11231208-- Method to update the Total Price string sum of all items
11241209function TradeQueryClass :GetTotalPriceString ()
11251210 local text = " "
0 commit comments