Questo modulo Lua gestisce le funzioni del template {{random}}. Può fornire numeri casuali, selezionare un elemento casuale da una lista, riordinare totalmente o parzialmente una lista in modo casuale e visualizzarla con diversi formati. Le funzioni disponibili sono meglio descritte nelle sezioni seguenti.

La funzione number (numero) restituisce un numero casuale.

{{#invoke:random|number|m|n}}
oppure, tramite il template
{{random|output=number|m|n}}

Gli argomenti m e n sono opzionali e possono essere omessi; se specificati devono poter essere convertiti in numeri interi.

  • Senza argomenti, restituisce un numero reale nell'intervallo .
  • Con un argomento, restituisce un numero intero nell'intervallo . m deve essere positivo.
  • Con due argomenti, restituisce un numero intero nell'intervallo . m e n possono essere sia positivi sia negativi. Se m è maggiore di n, restituisce invece un numero intero nell'intervallo .

Esempi

  • {{#invoke:random|number}} → 0.13103275239981
  • {{#invoke:random|number|100}} → 1
  • {{#invoke:random|number|-100|-50}} → -63

La documentazione per questa funzione è in parte tratta da (EN) Scribunto Lua reference manual, basato su Lua 5.1 Reference Manual, disponibile sotto licenza MIT (Massachusetts Institute of Technology).

La funzione item (elemento) restituisce un elemento casuale di una lista.

{{#invoke:random|item|elemento 1|elemento 2|elemento 3|...}}
oppure, tramite il template
{{random|output=item|elemento 1|elemento 2|elemento 3|...}}

Esempi

  • {{#invoke:random|item|aaa|bbb|ccc|ddd|eee}} → ccc

La lista di elementi in ingresso può essere specificata anche tramite i parametri input e splitter, analogamente a quanto specificato per la funzione list.

La funzione list (lista) restituisce una lista riordinata in modo casuale.

Parametri nominali

modifica
{{#invoke:random|list|elemento 1|elemento 2|elemento 3|...|sep=separatore|limit=numero di elementi da visualizzare}}
oppure, tramite il template
{{random|output=list|elemento 1|elemento 2|elemento 3|...|sep=separatore|limit=numero di elementi da visualizzare}}
  • sep o separator - eventuale separatore per gli elementi della lista. È possibile utilizzare dei valori predefiniti per particolari separatori, vedere la tabella seguente.
  • limit - numero di elementi da visualizzare; valore minimo = 0; valore massimo = numero totale di elementi della lista (valore predefinito).
Separatori predefiniti
Codice Risultato
none nessuno spazio
space spazio
dot  ·
dash  –
pipe |
comma ,
semicolon ;
altri valori qualsiasi altro valore di testo viene riportato tale e quale

A causa di limitazioni tecniche nel software MediaWiki, non è possibile inserire direttamente spazi vuoti per il parametro separatore. In alternativa utilizzare il valore space (vedere tabella precedente) oppure   per uno spazio normale, e   per uno spazio indivisibile (non-breaking space).

Esempi

  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee}} → eee · aaa · ddd · bbb · ccc
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=none}} → aaacccdddbbbeee
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=space}} → bbb eee ddd aaa ccc
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=dot}} → eee · bbb · ccc · ddd · aaa
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=dash}} → eee – aaa – bbb – ccc – ddd
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=pipe}} → ddd | eee | bbb | ccc | aaa
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=comma}} → ddd, aaa, bbb, eee, ccc
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=semicolon}} → aaa; bbb; ccc; eee; ddd
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep= * }} → eee * aaa * ddd * ccc * bbb
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=_}} → aaa_ccc_eee_ddd_bbb
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=xxx}} → bbbxxxeeexxxdddxxxaaaxxxccc
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|limit=3}} → eee · aaa · ccc

Nota

Se non diversamente specificato, il separatore di default è " · " (dot, vedere tabella precedente).

Parametri nominali avanzati

modifica
{{#invoke:random|list|input=elemento 1, elemento 2, elemento 3...|splitter=,}}
oppure, tramite il template
{{random|output=list|input=elemento 1, elemento 2, elemento 3...|splitter=,}}
  • input - eventuale lista di elementi in ingresso scritta in forma testuale. È possibile specificare in modo compatto una lista di elementi in ingresso che verranno suddivisi e separati tramite il parametro splitter.
  • splitter - separatore per gli elementi della lista d'ingresso. È possibile utilizzare ad esempio la virgola (",") o qualsiasi altro carattere o gruppo di caratteri (es. "//"), oppure il template {{·}}, ecc.

Esempi

  • {{#invoke:random|list|input=uno // due // tre // quattro // cinque|splitter=//}} → cinque · tre · quattro · due · uno
  • {{#invoke:random|list|input=uno{{·}}due{{·}}tre{{·}}quattro{{·}}cinque|splitter={{·}}}} → tre · due · quattro · uno · cinque

Nota

Il template {{random}} imposta, per le liste in ingresso, il separatore di default " · " (ottenuto tramite il template {{·}}).
  • {{random|output=list|input=uno{{·}}due{{·}}tre{{·}}quattro{{·}}cinque}} → due · cinque · quattro · tre · uno

Text list

modifica

La funzione text_list (lista testuale) restituisce una lista riordinata in modo casuale, formattata per essere inserita in un testo. In altre parole, è simile alla funzione list ma con un separatore differente per l'ultimo elemento della lista.

{{#invoke:random|text_list|elemento 1|elemento 2|elemento 3|...|sep=separatore|conj=congiunzione finale|limit=numero di elementi da visualizzare}}
oppure, tramite il template
{{random|output=text_list|elemento 1|elemento 2|elemento 3|...|sep=separatore|conj=congiunzione finale|limit=numero di elementi da visualizzare}}

Il separatore può essere specificato tramite il parametro sep o separator; il valore di default è ", " (vedere MediaWiki:comma-separator). La congiunzione finale può essere specificata tramite il parametro conj o conjunction; il valore di default è " e " (vedere MediaWiki:and e MediaWiki:word-separator). Separatore e congiunzione finale possono essere specificati con gli stessi valori speciali definiti per la funzione list.

La lista di elementi in ingresso può essere specificata anche tramite i parametri input e splitter, analogamente a quanto specificato per la funzione list.

Il numero massimo di elementi da visualizzare può essere impostato con il parametro limit; valore minimo = 0; valore massimo = numero totale di elementi della lista (valore predefinito).

Esempi

  • {{#invoke:random|text_list|aaa|bbb|ccc|ddd|eee}} → ccc, ddd, aaa, bbb e eee
  • {{#invoke:random|text_list|aaa|bbb|ccc|ddd|eee|sep=semicolon}} → ccc; eee; ddd; bbb e aaa
  • {{#invoke:random|text_list|aaa|bbb|ccc|ddd|eee|conj= oppure }} → ccc, bbb, eee, aaa oppure ddd
  • {{#invoke:random|text_list|aaa|bbb|ccc|ddd|eee|limit=3}} → aaa, eee e ccc

-- This module contains a number of functions that make use of random numbers.

local p = {} -- For functions available from other Lua modules.
local l = {} -- For functions not available from other Lua modules, but that need to be accessed using table keys.

--------------------------------------------------------------------------------------
-- random number function
--------------------------------------------------------------------------------------

local function getBigRandom(l, u)
	-- Gets a random integer between l and u, and is not limited to RAND_MAX.
	local r = 0
	local n = 2^math.random(30) -- Any power of 2.
	local limit = math.ceil(53 / (math.log(n) / math.log(2)))
	for i = 1, limit do
		r = r + math.random(0, n - 1) / (n^i)
	end
	return math.floor(r * (u - l + 1)) + l
end

function l.number(args)
	-- Gets a random number.
	first = tonumber(args[1])
	second = tonumber(args[2])
	-- This needs to use if statements as math.random won't accept explicit nil values as arguments.
	if first then
		if second then
			if first > second then -- Second number cannot be less than the first, or it causes an error.
				first, second = second, first
			end
			return getBigRandom(first, second)
		else
			return getBigRandom(1, first)
		end
	else
		return math.random()
	end
end

--------------------------------------------------------------------------------------
-- List functions
--------------------------------------------------------------------------------------

local function randomizeArray(t, limit)
	-- Randomizes an array. It works by iterating through the list backwards, each time swapping the entry
	-- "i" with a random entry. Courtesy of Xinhuan at http://forums.wowace.com/showthread.php?p=279756
	-- If the limit parameter is set, the array is shortened to that many elements after being randomized.
	-- The lowest possible value is 0, and the highest possible is the length of the array.
	local len = #t
	for i = len, 2, -1 do
		local r = math.random(i)
		t[i], t[r] = t[r], t[i]
	end
	if limit and limit < len then
		local ret = {}
		for i, v in ipairs(t) do
			if i > limit then
				break
			end
			ret[i] = v
		end
		return ret
	else
		return t
	end
end

local function removeBlanks(t)
	-- Removes blank entries from an array so that it can be used with ipairs.
	local ret = {}
	for k, v in pairs(t) do
		if type(k) == 'number' then
			table.insert(ret, k)
		end
	end
	table.sort(ret)
	for i, v in ipairs(ret) do
		ret[i] = t[v]
	end
	return ret
end

local function makeSeparator(sep)
	if type(sep) == 'string' then
		-- If the separator is a recognised separator, use that. Otherwise use the value of sep if it is a string.
		local separators = {
			none = '',
			space = ' ',
			dot = '&nbsp;\'\'\'·\'\'\' ',
			dash = '&nbsp;– ',
			pipe = '&nbsp;| ',
			comma = ', ',
			semicolon = '; '
		}
		return separators[sep] or sep
	end
end

local function makeRandomList(args)
	local list = removeBlanks(args)
	list = randomizeArray(list, tonumber(args.limit))
	return list
end

function l.item(args)
	-- Returns a random item from a numbered list.
	local list = removeBlanks(args)
	local len = #list
	if len >= 1 then
		return list[math.random(len)]
	end
end

function l.list(args)
	-- Randomizes a list and concatenates the result with a separator.
	local list = makeRandomList(args)
	local sep = makeSeparator(args.sep or args.separator or 'dot')
	return table.concat(list, sep)
end

function l.text_list(args)
	-- Randomizes a list and concatenates the result, text-style. Accepts separator and conjunction arguments.
	local list = makeRandomList(args)
	local sep = makeSeparator(args.sep or args.separator)
	local conj = makeSeparator(args.conj or args.conjunction)
	return mw.text.listToText(list, sep, conj)
end

function l.array(args)
	-- Returns a Lua array, randomized. For use from other Lua modules.
	return randomizeArray(args.t, args.limit)
end

--------------------------------------------------------------------------------------
-- The main function. Called from other Lua modules.
--------------------------------------------------------------------------------------

function p.main(funcName, args)
	-- Sets the seed for the random number generator and passes control over to the other functions.
	-- Generates a different number every time the module is called, even from the same page.
	-- This is because of the variability of os.clock (the time in seconds that the Lua script has been running for).
	math.randomseed(mw.site.stats.edits + mw.site.stats.pages + os.time() + math.floor(os.clock() * 1000000000))
	if type(args) ~= 'table' then
		error('the second argument to p.main must be a table')
	end
	return l[funcName](args)
end

--------------------------------------------------------------------------------------
-- Process arguments from #invoke
--------------------------------------------------------------------------------------

local function addListArgs(args)
	-- If it exists, splits the input list and adds its items to the args.
	if args.input and type(args.input) == 'string' then
		local splitter = args.splitter or ''
		local listArgs = mw.text.split(args.input, splitter, true)
		for k, v in pairs(listArgs) do
			if type(v) == 'string' then
				v = mw.text.trim(v)
			end
			if v ~= '' then
				table.insert(args, v)
			end
		end
	end
	return args
end

local function getArgs(funcName)
	-- This function get and process arguments from #invoke.
	return function (frame)
		-- If called via #invoke, use the args passed into the invoking template, or the args passed to #invoke if any exist.
		-- Otherwise assume args are being passed directly in from the debug console or from another Lua module.
		local origArgs = {}
		if frame == mw.getCurrentFrame() then
			local parent = frame:getParent()
			local parentArgs = parent and parent.args or {}
			for k, v in pairs(parentArgs) do
				origArgs[k] = v
			end
			for k, v in pairs(frame.args) do
				origArgs[k] = v
			end
		else
			origArgs = frame
		end
		-- Trim whitespace and remove blank arguments.
		local args = {}
		for k, v in pairs(origArgs) do
			if type(v) == 'string' then
				v = mw.text.trim(v)
			end
			if v ~= '' then
				args[k] = v
			end
		end
		if funcName ~= 'number' then
			args = addListArgs(args)
		end
		return p.main(funcName, args)
	end
end

-- Process arguments for functions.
local funcs = {'number', 'item', 'list', 'text_list'}
for _, funcName in ipairs(funcs) do
	p[funcName] = getArgs(funcName)
end

return p