Modulo:Random

Da Wikiquote, aforismi e citazioni in libertà.

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.

Number[modifica]

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.63979647012418
  • {{#invoke:random|number|100}} → 62
  • {{#invoke:random|number|-100|-50}} → -67

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).

Item[modifica]

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.

List[modifica]

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}} → ddd · bbb · ccc · eee · aaa
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=none}} → dddeeecccaaabbb
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=space}} → ccc ddd eee aaa bbb
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=dot}} → bbb · eee · aaa · ddd · ccc
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=dash}} → bbb – aaa – ddd – ccc – eee
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=pipe}} → bbb | ccc | aaa | ddd | eee
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=comma}} → ddd, eee, ccc, aaa, bbb
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=semicolon}} → ddd; bbb; aaa; ccc; eee
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep= * }} → ddd * eee * bbb * aaa * ccc
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=_}} → aaa_ddd_eee_bbb_ccc
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|sep=xxx}} → bbbxxxeeexxxcccxxxdddxxxaaa
  • {{#invoke:random|list|aaa|bbb|ccc|ddd|eee|limit=3}} → eee · ddd · aaa

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=//}} → quattro · tre · uno · due · cinque
  • {{#invoke:random|list|input=uno{{·}}due{{·}}tre{{·}}quattro{{·}}cinque|splitter={{·}}}} → tre · due · cinque · uno · quattro

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}} → uno · cinque · tre · due · quattro

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}} → aaa, ccc, bbb, eee e ddd
  • {{#invoke:random|text_list|aaa|bbb|ccc|ddd|eee|sep=semicolon}} → eee; bbb; aaa; ccc e ddd
  • {{#invoke:random|text_list|aaa|bbb|ccc|ddd|eee|conj= oppure }} → aaa, eee, ddd, bbb oppure ccc
  • {{#invoke:random|text_list|aaa|bbb|ccc|ddd|eee|limit=3}} → aaa, bbb e eee

-- 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