Documentation for this module may be created at Module:Drops/doc
-- Rewrite of Module:DropsLine
-- Rewrite of Module:Get drop info
local Drops = {}
----------------------------
-- Libraries of functions --
----------------------------
-- Loads high frequency functions
local HF = require('Module:HF')
-- Parses invocation and template parameters, trims whitespace, and removes blanks.
local getArgs = require('Dev:Arguments').getArgs
-- Language functions for the default language
local lang = mw.language.getContentLanguage()
-- Smarter boolean logic
local yesno = require( 'Dev:Yesno' )
-- Wikitext lists
local L = require( 'Dev:List' )
-- {{ItemDropsLine}} support
--local IDL = require( 'Module:ItemDropsLine' ).main
--local _IDL = require( 'Module:ItemDropsLine' )._main
-------------------------------------------
-- Local data (used only in this Module) --
-------------------------------------------
--bg, txt, sort
local rarities = {
always = {'#8FD7FA !important', '#083F66', 1},
common = {'#98E553 !important', '#245200', 2},
uncommon = {'#F5EB4E !important', '#524E00', 3},
rare = {'#F6AB58 !important', '#582E00', 4},
['very rare'] = {'#F86C67 !important', '#520800', 5},
random = {'#F3BFF3 !important', '#801B80', 6},
varies = {'#F3BFF3 !important', '#801B80', 6},
discontinued = {'#CFCFCF !important', '#464646', 7}
}
------------------------------------------------
-- Local functions (used only in this Module) --
------------------------------------------------
local commas = function (n) return lang:formatNum(tonumber(n)) end
local function categories(...)
local name,quantity,rarity = unpack(...)
local cats = {}
name = name:lower()
quantity = quantity:lower()
if name:find('effigy') then table.insert(cats, HF.Category('Effigy dropping monsters'))
elseif name:find('clue scroll') then table.insert(cats, HF.Category('Clue scroll dropping monsters'))
elseif name:find('rare drop table') then table.insert(cats, HF.Category('Monsters with access to the rare drop table'))
end
if not rarities[rarity:lower()] then table.insert(cats, HF.Category('Needs drop rarity added')) end
if quantity:find('unknown') then table.insert(cats, HF.Category('Needs drop quantity added')) end
return table.concat(cats)
end
local 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 > b then
a,b = b,a
end
addx = commas(a)..'–'..commas(b)
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
local function cmb(levels)
-- if no level is given, return unknown
if not levels then
return 'Unknown'
end
-- split list into table
local vals = mw.text.split(levels,'[,;]')
-- recreate the list string to ensure consistent formatting
local numstr = {}
for i, v in ipairs(vals) do
table.insert(numstr,v)
end
table.sort(numstr,function (a,b)
a = tonumber(a) or 0
b = tonumber(b) or 0
return a < b
end)
-- To prevent any possible confusion with formatted numbers
-- elements should be separated with semicolons followed by a space
return table.concat(numstr,'; ')
end
local function getCombatLevel(source)
local levelstring
local results = mw.smw.ask{
HF.Link(source),
'?All Combat level=CLs',
'format=list',
'headers=hide',
'mainlabel=-'
}
if type(results) == 'table' then
levelstring = results[1]['CLs']
else
levelstring = 'N/A'
end
return levelstring
end
local function IDL_HTML ( name, combat, qtysort, quantity, rarity)
local rare_bg, rare_txt, rare_sort = unpack(rarities[rarity:lower()] or {'#FFFFFF !important', '#000000', 8})
local row = mw.html.create('tr')
:css('text-align','center')
:tag('td'):css('text-align','left'):wikitext(name):done()
:tag('td'):wikitext('N/A'):done()
:tag('td'):attr('data-sort-value', qtysort):wikitext(quantity):done()
:tag('td')
:attr('data-sort-value', rare_sort)
:css('background', rare_bg)
:css('color', rare_txt)
:wikitext(rarity)
:done()
return tostring(row)
end
---------------------------------------------------------
-- Internal functions (used in this and other Modules) --
---------------------------------------------------------
-- {{Dropping monsters list}}
function Drops.DML (frame)
local args = getArgs(frame, { parentOnly = true })
local listfor = args[1] or mw.title.getCurrentTitle().fullText
local head = frame:newTemplateParserValue{
title = "ItemDropsTableHead",
args = { listfor }
}
local foot = frame:newTemplateParserValue{ title = "ItemDropsEnd" }
local results = mw.smw.ask{
HF.Category('Drops'),
HF.Link(("Item::%s"):format(listfor)),
'?Source',
'?Drops/Quantity (low)=Low',
'?Drops/Quantity (high)=High',
'?Rarity',
'mainlabel=-',
'limit='..(args['limit'] or 50),
'sort='..(args['sort'] or 'Rarity,Source'),
'order='..(args['order'] or '')
}
if not results then return HF.Category('Empty drop lists') end
local output = {}
--[==[
<includeonly>:''This list was created dynamically. For help, see [[Template:Dropping monsters list/FAQ|the FAQ]].''
:''To force an update of this list, click {{purge|here|tag=span}}.''
{{ItemDropsTableHead|{{{1|{{PAGENAME}}}}}}}
{{#ask:[[Drops item::{{{1|{{PAGENAME}}}}}]]|?=monster|userparam={{{1|{{PAGENAME}}}}}|format=template|template=Get drop info|named args=yes|link=none|searchlabel=|limit={{{limit|50}}}|sort={{{sort|}}}|order={{{order|}}}|default=[[Category:Empty drop lists]]}}
{{ItemDropsEnd}}</includeonly><noinclude>{{/doc}}</noinclude>
--]==]
for _,item in ipairs(results) do
item.Source = item.Source:gsub('[][]','')
-- merge quantity if same
local quantity
if item['Low'] and item['High'] and item['Low'] == item['High'] then
quantity = item['Low']
elseif type(tonumber(item['Low'])) == 'number' and type(tonumber(item['High'])) then
quantity = item['Low'] .. '–' .. item['High']
else
quantity = 'unknown'
end
item.Rarity = item.Rarity and lang:lc(item.Rarity) or 'Unknown'
item.Rarity = item.Rarity and lang:ucfirst(item.Rarity)
table.insert(output, Drops._IDL{
['Monster'] = item['Source'],
['Combat'] = getCombatLevel(item['Source']),
['Quantity'] = quantity,
['Rarity'] = item['Rarity']
})
end
return
( head and head:expand() or '' ) .. table.concat(output) .. ( foot and foot:expand() or '' )
end
function Drops.IDL (frame)
local args = getArgs(frame, { parentOnly = true })
args.Monster = args.Monster or 'monster'
args.Quantity = args.Quantity and args['Quantity']:lower() or 'unknown'
args.Rarity = args.Rarity and lang:lc(args.Rarity) or 'Unknown'
args.Rarity = args.Rarity and lang:ucfirst(args.Rarity)
return Drops._IDL(args)
end
function Drops._IDL (args)
args.Monster = args.Monster and HF.Link(args.Monster)
args.Monster = (args.Namenotes and #args['Namenotes'] > 5)
and (args.Monster ..' '.. args.Namenotes) or args.Monster
args.Combat = (args.cbnotes and #args['cbnotes'] > 5)
and (args.combat ..' '.. args.cbnotes) or args.Combat
args.Quantity = (args.Quantitynotes and #args['Quantitynotes'] > 5)
and (args.Quantity ..' '.. args.Quantitynotes) or args.Quantity
args.Rarity = (args.Raritynotes and #args['Raritynotes'] > 5)
and (args.Rarity ..' '.. args.Raritynotes) or args.Rarity
-- Clean up the lists
quantity = qty(quantity)
local qtysort = mw.text.split(quantity, '%D')[1]
if qtysort == '' then
qtysort = 0
end
args.Combat = args.Combat
return IDL_HTML ( args.Monster, args.Combat, qtysort, args.Quantity, args.Rarity)
end
-------------------------------------------------
-- Output (send it back to whatever called it) --
-------------------------------------------------
return Drops