Jump to content

Module:Currency

Permanently protected module
From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Trappist the monk (talk | contribs) at 11:37, 6 April 2016. The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

require('Module:No globals')
local getArgs = require('Module:Arguments').getArgs

local p = {}
local presentation ={};															-- table of tales that contain currencty presentation data

--[[--------------------------< I S _ S E T >------------------------------------------------------------------

Whether variable is set or not.  A variable is set when it is not nil and not empty.

]]

local function is_set( var )
	return not (var == nil or var == '');
end


--[[--------------------------< G R O U P I N G >--------------------------------------------------------------

Takes a number string in the form nnnn.nn and adds grouping to it, return n,nnn.nn

Grouping is added by reversing the digits portion of the value:
	123456789.nn
becomes
	987654321
	
Then, string.gsub replaces each group of three digits with the same three digits (the capture) followed by a comma:
	987,654,321,
The string is reversed again:
	,123,456,789
and the leading comma (if present) is removed:
	123,456,789
	
At the end, the digits and decimal portions are reunited with a decimal point which is returned to calling function.

Unrecognized 'numbers' return '0.00'

]]

local function grouping (val)
	local digits;																-- left side of the decimal point
	local decimals;																-- right side of the decimal point
	
	if val:match ('^%d+%.%d+$') then											-- has digits and decimals
		digits, decimals = val:match ('(%d+)%.(%d+)');
	elseif val:match ('^%d+%.$') then											-- has digits and decimal point but no decimals
		digits = val:match ('(%d+)%.')
	elseif val:match ('^%.%d+$') then											-- has no digits but has decimal point and decimals
		decimals = val:match ('%.(%d+)')
	elseif 	val:match ('^%d+$')	then											-- just has digits
		digits = val;
	else
		return '0.00';															-- something that isn't a number; return default  TODO: error message here
	end

	if is_set (digits) then
		digits = digits:reverse():gsub ('%d%d%d', '%1,'):reverse():gsub('^,', '');	-- apply grouping
	else
		digits = '0';															-- otherwise set default value
	end
	
	if not is_set (decimals) then
		decimals = '00';														-- set to default
	end
	
	return digits .. '.' .. decimals;											-- return formatted value
end


--[[--------------------------< F O R M A T _ C U R R E N C Y >------------------------------------------------


]]

local function format_currency (val, code)
	local symbol = string.format ('[[%s|%s]]', presentation.currency_properties[code].page, presentation.currency_properties[code].symbol);	-- make wikilink of page and symbol
	local position = presentation.currency_properties[code].position;
	
	if 'b' == position then														-- choose appropriate format: unspaced before the amount
		return string.format ('%s%s', symbol, val);
	elseif 'bs' == position then												-- spaced before the amount
		return string.format ('%s&nbsp;%s', symbol, val);
	elseif 'a' == position then													-- unspaced after the amount
		return string.format ('%s%s', val, symbol);
	elseif 'as' == position then												-- spaced after the amount
		return string.format ('%s&nbsp;%s', val, symbol);
	else
		return val;																-- position not defined TODO: error message here
	end
end



--[[--------------------------< P . C U R R E N C Y >----------------------------------------------------------


]]

function p.currency (frame)
	local args = getArgs(frame);
	local amount, code;
	
	
	if not tonumber (args[1]) then												-- if args[1] can't be converted to a number then error
		return '{{currency}} – invalid amount';
	end
	
	if nil == args[2] then														-- if not provided
		args[2] = USD;															-- default to USD
	else
		code = args[2]:upper();
	end
	
	presentation = mw.loadData ('Module:Currency/Presentation');
	
	if nil == presentation.currency_properties[code] then
		return '{{currency}} – invalid code';
	end


	amount = grouping (args[1]);												-- format the amount
	
	amount = format_currency (amount, code);									-- wrap the amount with appropriate symbol
	
	return amount;
end

return p;