Modul:Sorterbart tall

Fra Wikipedia, den frie encyklopedi
Moduldokumentasjon

Denne modulen inneholder noen funksjoner for å lage sorteringsnøkler og sorterbare strenger av et tall. Den implementerer funksjonalitet tilsvarende malene {{st}}/{{nts}}/{{Sorterbart tall}} og {{sts}}/{{Sorterbart tall skjult}}. Modulen kan både brukes direkte fra maler og fra andre moduler.

Oversikt[rediger kilde]

Funksjoner tilgjengelig fra moduler:

-- Returns the magnitude of a number defined as the integer part of log10 of the absolute value of the number
-- Equivalent to [[Mal:Magnitude]]
function magnitude(number)

-- Returns a sorting key for a number
function sortableNumber(number)

-- Returns a sortable string of a number (but without the number)
-- Argument displayCode is optional
-- Equivalent to [[Mal:Sorterbart tall skjult]]
function sortableNumberFormat1(number, displayCode)

-- Returns a sortable string with a formatted number
-- Arguments preStr, postStr, positiveSign, decimals and displayCode are optional
-- Equivalent to [[Mal:Sorterbart tall]]
function p.sortableNumberFormat2(number, preStr, postStr, positiveSign, decimals, displayCode)

Fra maler kan man bruke:

-- To be used from a template. Uses args from parent to template
-- Arguments from parent:
--      1 The number
--      2 Optional boolean: If true then display the code generated
-- Returns a sortable string of a number (but without the number)
-- Equivalent to [[Mal:Sorterbart tall skjult]]
function formatHidden(frame)

-- To be used from a template. Uses args from parent to template
-- Arguments from parent:
--      1 The number
--      2 Optional prefix
--      3 Optional postfix
--      4 Optional boolean: If true then display the code generated
-- Returns a sortable string with a formatted number
-- Equivalent to [[Mal:Sorterbart tall]]
function format(frame)

Eksempel på bruk i mal:

{{#invoke:Sorterbart tall | format | 4222 | tallet er  |  omtrent}}
tallet er 4 222 omtrent (eller egentlig 3&503&4222& tallet er 4 222 omtrent)

local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')

local languageEnglish = mw.getLanguage('en')
-- local languageNorwegian = mw.getLanguage('no')
local languageNorwegian = mw.getContentLanguage()

local p = {}

-- Returns the magnitude of a number defined as the integer part of log10 of the absolute value of the number
-- Equivalent to [[Mal:Magnitude]]
function p.magnitude(number)
	if number == 0 then return nil end
	return math.floor(math.log10(math.abs(number)))
end

-- Returns a sorting key for a number
function p.sortableNumber(number)
	local result = ''
	if number > 0 then
		result = result .. '3&' .. tostring(500 + p.magnitude(number))
	elseif number < 0 then
		result = result .. '1&' .. tostring(500 - p.magnitude(number))
	else -- 0
		result = result .. '2'
	end
	if number >= 0 then
		result = result .. '&' .. tostring(number)
	else -- negative
		result = result .. '&' .. tostring(100000 * (10 + number / 10 ^ p.magnitude(number)))
	end
	return result .. '&';
end

-- Returns a sortable string of a number (but without the number)
-- Argument displayCode is optional
-- Equivalent to [[Mal:Sorterbart tall skjult]]
function p.sortableNumberFormat1(number, displayCode)
	if number == nil then return '' end
	local result = '<span data-sort-value="' .. p.sortableNumber(number) .. '">'
	if displayCode then
		result = result .. '<code>' .. p.sortableNumber(number) .. '</code> '
	end
	return result
end

-- Returns number of decimals in a numeric string
local function numberOfDecimals(numstr)
	local idx1, idx2, decStr = string.find(numstr, '.*[,%.](.*)') -- Find last occurence of ',' or '.' (the decimal separation sign)
	if not decStr then return 0 end
	return #decStr
end

-- Returns a sortable string with a formatted number
-- Arguments preStr, postStr, positiveSign, decimals and displayCode are optional
-- Equivalent to [[Mal:Sorterbart tall]]
function p.sortableNumberFormat2(number, preStr, postStr, positiveSign, decimals, displayCode)
	if number == nil then return '' end
	local preStr_ = preStr or ''
	local postStr_ = postStr or ''
	local formattedNumber = languageNorwegian:formatNum(number)
	formattedNumber = string.gsub(formattedNumber, '-', '−') -- Replace hyphen with minus
	local expIdx = string.find(formattedNumber, 'E')
	if expIdx then
		local base = string.sub(formattedNumber, 1, expIdx - 1)
		local exp = string.sub(formattedNumber, expIdx + 1)
		exp = string.gsub(exp, '+', '') -- Remove plus sign in exponent
		formattedNumber = base .. ' · 10<sup>' .. exp .. '</sup>'
	elseif decimals and decimals > 0 then -- Only try to maintain number of decimals if not on exponential format
		local decimalsInOutput = numberOfDecimals(formattedNumber)
		local diffDecimals = decimals - decimalsInOutput
		if diffDecimals > 0 then -- Pad output with zeros in order to maintain number of decimals
			if decimalsInOutput == 0 then -- No decimals in output: Add decimal separation character
				formattedNumber = formattedNumber .. ','
			end
			formattedNumber = formattedNumber .. string.rep('0', diffDecimals)
		end
	end
	if positiveSign and number > 0 then -- Display plus sign for positive numbers?
		formattedNumber = '+' .. formattedNumber
	end
	return p.sortableNumberFormat1(number, displayCode) .. preStr_ .. formattedNumber .. postStr_ .. '</span>'
end

-- Converts and returns a numeric string to a number.
-- Tries first to interpret the number as Norwegian then as English
-- Returns nil if no success
local function strToNumber(numstr)
	if not numstr or #numstr == 0 then return nil end
	local number = languageNorwegian:parseFormattedNumber(numstr) -- Try first Norwegian formatting
	if not number then -- Not recognized as Norwegian, try English
		number = languageEnglish:parseFormattedNumber(numstr)
	end
	if not number then
		number = tonumber(numstr) -- This is a (very) long shot
	end
	if not number then
		error('Uttrykksfeil: «' .. numstr .. '» blir ikke tolket som en numerisk verdi', 0)
	end
	return number
end

-- Converts numeric string to a number.
-- Checks if a positive number is prefixed with a plus sign
-- Returns number, state of sign and number of decimals in number
local function decodeNumberArg(numstr)
	local number = strToNumber(numstr)
	if not number then return nil, nil end
	
	local positiveSign = false
	if number > 0 then -- Check if numstr string begins with '+': Interpret this as sign for a positive number is wanted in output
		positiveSign = string.match(numstr, '^%+') ~= nil
	end
	
	-- Check number of decimals in input in order to try to maintain same number of decimals in output
	local decimals = numberOfDecimals(numstr)
	
	return number, positiveSign, decimals
end

local function displayCodeParse(arg)
	if not arg then return false end -- Missing arg: Default is hide
	if #arg == 0 then return true end -- Empty arg: Interpret as display (due to legacy template)
	if string.match(arg, 'display *: *none') then return false end -- Default arg from legacy template
	return yesno(arg)
end

-- To be used from a template. Uses args from parent to template
-- Arguments from parent:
--		1 The number
--		2 Optional boolean: If true then display the code generated
-- Returns a sortable string of a number (but without the number)
-- Equivalent to [[Mal:Sorterbart tall skjult]]
function p.formatHidden(frame)
	local args = getArgs(frame:getParent().args, {trim = true, removeBlanks = false, parentFirst = true})
	return p.sortableNumberFormat1(strToNumber(args[1]), displayCodeParse(args[2])) .. '</span>'
end

-- Same as formatHidden, but should be used directly with #invoke
function p.formatHidden0(frame)
	local args = getArgs(frame.args, {trim = true, removeBlanks = false, parentFirst = true})
	return p.sortableNumberFormat1(strToNumber(args[1]), displayCodeParse(args[2])) .. '</span>'
end

-- To be used from a template. Uses args from parent to template
-- Arguments from parent:
--		1 The number
--		2 Optional prefix
--		3 Optional postfix
--		4 Optional boolean: If true then display the code generated
-- Returns a sortable string with a formatted number
-- Equivalent to [[Mal:Sorterbart tall]]
function p.format(frame)
	local args = getArgs(frame:getParent().args, {trim = true, removeBlanks = false, parentFirst = true})
	if not args[1] then error('Uttrykksfeil: Argument for tall mangler', 0)	end
	local numstr =  string.gsub(args[1], ' ', '') -- Remove any spaces in number input
	local number, positiveSign, decimals = decodeNumberArg(numstr)
	if not number then return args[1] end
	return p.sortableNumberFormat2(number, args[2], args[3], positiveSign, decimals, displayCodeParse(args[4]))
end

-- Same as format, but should be used directly with #invoke
function p.format0(frame)
	local args = getArgs(frame.args, {trim = true, removeBlanks = false, parentFirst = true})
	if not args[1] then error('Uttrykksfeil: Argument for tall mangler', 0)	end
	local numstr =  string.gsub(args[1], ' ', '') -- Remove any spaces in number input
	local number, positiveSign, decimals = decodeNumberArg(numstr)
	if not number then return args[1] end
	return p.sortableNumberFormat2(number, args[2], args[3], positiveSign, decimals, displayCodeParse(args[4]))
end

return p