Module:Get drop info
Revision as of 18:15, 7 November 2022 by Jacmob (talk | contribs) (Created page with "local p = {} local onmain = require('Module:Mainonly').on_main local yesno = require('Module:Yesno') local purge = require('Module:Purge')._purge local params = require('Module:Paramtest') local images = { agility = '<span class="drops-agility" style="margin-left:0.3em;">link=Agility|frameless|20px</span>', combat = '<span class="drops-combat" style="margin-left:0.3em;">link=Combat level|frameless|20px</span>', hunt...")
Module documentation
This documentation is transcluded from Template:No documentation/doc. [edit] [history] [purge]
This module does not have any documentation. Please consider adding documentation at Module:Get drop info/doc. [edit]
Module:Get drop info's function main is invoked by Template:Dropping monsters list.
Module:Get drop info requires Module:Mainonly.
Module:Get drop info requires Module:Paramtest.
Module:Get drop info requires Module:Purge.
Module:Get drop info requires Module:Yesno.
local p = {} local onmain = require('Module:Mainonly').on_main local yesno = require('Module:Yesno') local purge = require('Module:Purge')._purge local params = require('Module:Paramtest') local images = { agility = '<span class="drops-agility" style="margin-left:0.3em;">[[File:Agility icon.png|link=Agility|frameless|20px]]</span>', combat = '<span class="drops-combat" style="margin-left:0.3em;">[[File:Multicombat.png|link=Combat level|frameless|20px]]</span>', hunter = '<span class="drops-hunter" style="margin-left:0.3em;">[[File:Hunter icon.png|link=Hunter|frameless|20px]]</span>', farming = '<span class="drops-farming" style="margin-left:0.3em;">[[File:Farming icon.png|link=Farming|frameless|20px]]</span>', fishing = '<span class="drops-fishing" style="margin-left:0.3em;">[[File:Fishing icon.png|link=Fishing|frameless|20px]]</span>', mining = '<span class="drops-mining" style="margin-left:0.3em;">[[File:Mining icon.png|link=Mining|frameless|20px]]</span>', reward = '<span class="drops-reward" style="margin-left:0.3em;">[[File:Casket.png|link=Reward|frameless|20px]]</span>', woodcutting = '<span class="drops-woodcutting" style="margin-left:0.3em;">[[File:Woodcutting icon.png|link=Woodcutting|frameless|20px]]</span>', thieving = '<span class="drops-thieving" style="margin-left:0.3em;">[[File:Thieving icon.png|link=Thieving|frameless|20px]]</span>' } --class, sort local rarities = { always = { 'table-bg-blue', 1 }, common = { 'table-bg-green', 16 }, uncommon = { 'table-bg-yellow', 64 }, rare = { 'table-bg-orange', 256 }, ['very rare'] = { 'table-bg-red', 1024 }, random = { 'table-bg-pink', 4096 }, varies = { 'table-bg-pink', 4096 }, _default = { 'table-bg-grey', 65536 } } -- arbitrary numbers local rarities2 = { { 1, 'table-bg-blue' }, { 1/25, 'table-bg-green' }, { 1/99.99, 'table-bg-yellow' }, { 1/999.99, 'table-bg-orange' }, { 1/9999999, 'table-bg-red' } } local lang = mw.language.getContentLanguage() local commas = function (n) return lang:formatNum(tonumber(n)) end local _noted = ' <span class="dropsline-noted">(noted)</span>' -- supporting function for number => colour function get_rarity_class(val) for i,v in ipairs(rarities2) do curr = v if val >= v[1] then break end end return curr[2] end function expr(t) t = t:gsub(',', '') local err, val = pcall(mw.ext.ParserFunctions.expr, t) if err then return tonumber(val) else return false end end function sigfig(n, f) f = math.floor(f-1) if n == 0 then return 0 end local m = math.floor(math.log10(n)) f = math.max(m, f) local v = n / (10^(m-f)) v = math.floor(v + 0.5) * 10^(m-f) return v end function p.main(frame) return p._main(frame:getParent().args) end function p._main(args) local item = args.item or args[1] local skipheader = yesno(params.default_to(args.skipheader,'no')) local smwitem if item then local cleanedName = item local dropVers = '' if item:match(' ?%(%d%)$') then cleanedName, dropVers = mw.ustring.match(item, '^(.-) ?(%(%d%))$') elseif item:match(' ?%(p%+*%)$') then cleanedName, dropVers = mw.ustring.match(item, '^(.-) ?(%(p%+*%))$') elseif item:match('%#') then cleanedName, dropVers = mw.ustring.match(item, '^(.-)%#([%w%s%(%)]+)$') end if dropVers ~= nil and dropVers ~= '' then smwitem = cleanedName .. '#' .. dropVers end else item = mw.title.getCurrentTitle().text end if not smwitem then smwitem = item end local difrdt = '[[Dropped item from RDT::'..smwitem..']]' local q = { '[[Dropped item::'..smwitem..']]', '?Drop JSON', limit = args.limit or 500, } local t1 = os.clock() local smwdata = mw.smw.ask(q) local t2 = os.clock() if not smwdata then return ":''No drop sources found. To force an update, click " ..purge('dml-'..mw.uri.anchorEncode(item), 'here', 'span') ..".''[[Category:Empty drop lists]]" end mw.log(string.format('SMW: entries: %d, time elapsed: %.3f ms.', #smwdata, (t2 - t1) * 1000)) if params.has_content(args.sort) then assert(smwdata[1][args.sort], 'Invalid sorting key specified.') table.sort(smwdata, function(a, b) return a[args.sort] < b[args.sort] end) end local ret = {} if smwdata then for i,v in ipairs(smwdata) do local dropJSON = mw.text.jsonDecode(v['Drop JSON'] or '{}') table.insert(ret, makeLine(item, dropJSON)) end end local t = mw.html.create('table') t :addClass('wikitable sortable filterable item-drops autosort=4,a') :css('text-align', 'center') :tag('tr') :tag('th'):addClass('drop-disp-btn btn-first'):wikitext('Source'):done() :tag('th'):wikitext('Level'):done() :tag('th'):wikitext('Quantity'):done() :tag('th'):wikitext('Rarity'):addClass('drops-rarity-header'):done() for i,v in ipairs(ret) do t:node(v) end if skipheader then return tostring(t) end local text = { "<div class=\"seealso\">For an exhaustive list of all known sources for this item, see <span class='plainlinks'>[", tostring(mw.uri.fullUrl('Special:Ask', {q=q[1], po = '?Drop Quantity\n?Rarity', p = { mainlabel = 'Monster', format = 'table'}, limit = 500})), " here]</span> (<span class='plainlinks'>[", tostring(mw.uri.fullUrl('Special:Ask', {q=q[1]..' OR '..difrdt, po = '?Drop Quantity\n?Rarity', p = { mainlabel = 'Monster', format = 'table'}, limit = 500})), " include RDT]</span>).</div>\n", tostring(t) } local cat = '' if smwdata and onmain() then cat = '[[Category:Items dropped by monster]]' table.insert(text, cat) end return table.concat(text, '') end function makeLine(item, data) local dropType = data['Drop type'] or 'combat' local img = images[dropType] if img == nil then return nil end local level = data['Drop level'] or 'Not Available' local levelsort = data['Drop level'] or -1 if dropType == 'reward' then level = 'N/A' levelsort = -1000 end if string.find(level, ',') then levelsort = tonumber(mw.text.split(level, ',')[1]) level = level:gsub(',', '; ') end local cleanSrc = data['Dropped from'] or '' local splitSrc = mw.text.split(data['Dropped from'] or '', '%#') if #splitSrc == 2 then splitSrc[2] = splitSrc[2]:gsub('_', ' ') cleanSrc = string.format('%s|%s <span class="beast-version">%s</span>', cleanSrc, splitSrc[1], splitSrc[2]) end return line({cleanSrc, data['Name Notes'], level, img, levelsort, data['Drop Quantity'], '', data['Rarity'], data['Alt Rarity'], data['Alt Rarity Dash'], data['Rarity Notes'], dropType, data['Rolls']}) end function line(...) local name,namenotes, combat,cbnotes,dtype, quantity,quantitynotes, rarity,altrarity,altraritydash,raritynotes,dtype,rolls = unpack(...) -- missing notes to empty string (and not nil) namenotes = namenotes or '' cbnotes = cbnotes or '' quantitynotes = quantitynotes or '' raritynotes = raritynotes or '' local rarity_value local alt_rarity_value if rarities[string.lower(tostring(rarity))] then rarity = params.ucflc(rarity) else rarity_value = expr(rarity) end local rare_class, rare_sort = '', nil if rarity_value == undefined then rare_class, rare_sort = unpack(rarities[string.lower(tostring(rarity))] or rarities._default) elseif rarity_value == false then rare_class, rare_sort = unpack(rarities._default) else rare_sort = 1/rarity_value rare_class = get_rarity_class(rarity_value) end local rollstext = '' if rolls ~= 1 and rolls then rollstext = rolls .. ' × ' rare_sort = rare_sort / rolls rare_class = get_rarity_class(math.min(1/rare_sort,0.99)) end -- Clean up the lists quantity = qty(quantity) local qtysort = mw.text.split(quantity, '[^%d,]')[1] if qtysort == '' then qtysort = 0 end local cmbclass = '' local cmbsort = combat if combat == 'N/A' then cmbclass = 'table-na' cmbsort = 0 else combat, cmbsort = cmb(combat) end -- Check if name is already formated if name:match('^%[%[') then name = name else name = '[['..name..']]' end if #namenotes > 5 then name = name..' '..namenotes end if #cbnotes > 5 then combat = combat..' '..cbnotes end if #quantitynotes > 5 then quantity = quantity..' '..quantitynotes end -- Table row creation local ret = mw.html.create('tr') ret :css('text-align','center') :tag('td') :css('text-align','left') :css('border-right','none') :wikitext(name) :done() :tag('td') :wikitext(combat) :addClass(cmbclass) :attr('data-sort-value', cmbsort) :done() :tag('td') :attr('data-sort-value', qtysort) :wikitext(quantity) :done() local rarity_cell = ret:tag('td') local rarity_span = rarity_cell:tag('span') rarity_span:wikitext(rollstext .. rarity) rarity_cell:attr('data-sort-value', rare_sort) :addClass(rare_class) :done() if type(rarity_value) == 'number' then rarity_span:attr({ ['title'] = rollstext .. string.format('%.3g%%', 100 * rarity_value), ['data-drop-fraction'] = rollstext .. rarity, ['data-drop-oneover'] = rollstext .. '1/' .. commas(sigfig(1/rarity_value, 4)), ['data-drop-percent'] = rollstext .. sigfig(100 * rarity_value, 3), ['data-drop-permil'] = rollstext .. sigfig(1000 * rarity_value, 3), ['data-drop-permyriad'] = rollstext .. sigfig(10000 * rarity_value, 3), }) end if altrarity ~= '' and altrarity ~= nil then if rarities[string.lower(tostring(altrarity))] then altrarity = params.ucflc(altrarity) else alt_rarity_value = expr(altrarity) end if altraritydash ~= '' and altraritydash ~= nil then rarity_cell:tag('span'):wikitext('–') else rarity_cell:tag('span'):wikitext('; ') end local altrarityspan = rarity_cell:tag('span') altrarityspan:wikitext(altrarity) if type(alt_rarity_value) == 'number' then altrarityspan:attr({ ['data-drop-fraction'] = altrarity, ['data-drop-oneover'] = '1/' .. commas(sigfig(1/alt_rarity_value, 3)), ['data-drop-percent'] = sigfig(100 * alt_rarity_value, 3), ['data-drop-permil'] = sigfig(1000 * alt_rarity_value, 3), ['data-drop-permyriad'] = sigfig(10000 * alt_rarity_value, 3), }) end end if #raritynotes > 5 then rarity_cell:wikitext(raritynotes) end return ret:done() end function qty(quantity) -- if no quantity is given, return unknown if not quantity or quantity == 'unknown' then return 'Unknown' end -- en dashes are the proper dash for number ranges -- replace all hyphens and em dashes with en -- strip *all* whitespace -- change '(noted)' to '$n' for parsing quantity = mw.ustring.gsub(quantity,'[-—]','–') :gsub('%s','') :gsub('%(noted%)','$n') -- split list into table local vals = mw.text.split(quantity,'[,;]') -- recreate the quantity string to ensure consistent formatting local numstr = {} for i, v in ipairs(vals) do local clean = v:gsub('$n','') -- if list element contains an en dash (indicating range) -- Find the smaller/larger number (just in case) -- Compare them to the current min/max -- put them in order with desired format if mw.ustring.find(v,'–') then local splitvals = mw.text.split(clean,'–') -- assume a is smaller, b is larger local a = tonumber(splitvals[1]) local b = tonumber(splitvals[2]) -- Just in case if a and b then if a > b then a,b = b,a end addx = commas(a)..'–'..commas(b) else addx = splitvals[1]..'–'..splitvals[2] end if v:find('$n') then addx = addx.._noted end table.insert(numstr,addx) else local addx = tonumber(clean) ~= nil and commas(tonumber(clean)) or clean if v:find('$n') then addx = addx.._noted end table.insert(numstr,addx) end end -- To prevent any possible confusion with formatted numbers -- elements should be separated with semicolons followed by a space numstr = table.concat(numstr,'; ') if numstr:find('%d') then return numstr else return 'Unknown' end end function cmb(levels) -- if no level is given, return unknown if not levels then return 'Unknown', 0 end -- split list into table -- recreate the list string to ensure consistent formatting local numstr = {} for v in mw.text.gsplit(levels, '[,;]') do v = mw.text.trim(v) table.insert(numstr,tonumber(v)) end table.sort(numstr) -- give a range if 5+ combat levels if #numstr > 4 then return numstr[1] .. '–' .. numstr[#numstr], numstr[1] end -- To prevent any possible confusion with formatted numbers -- elements should be separated with semicolons followed by a space return table.concat(numstr,'; '), numstr[1] or 0 end --[[ DEBUG COPYPASTA = p._main({item = 'Iron bar'}) --]] return p