پودمان:Gapnum

    از دزفول ویکی

    توضیحات این پودمان می‌تواند در پودمان:Gapnum/توضیحات قرار گیرد.

    local p = {}
    
    local getArgs
    
    function p.main(frame)
    	if not getArgs then
    		getArgs = require('Module:Arguments').getArgs
    	end
    
    	local args = getArgs(frame, {wrappers = 'Template:Gapnum'})
    	local n = args[1]
    
    	if not n then
    		error('Parameter 1 is required')
    	elseif not tonumber(n) and not tonumber(n, 36) then -- Validates any number with base ≤ 36
    		error('Unable to convert "' .. args[1] .. '" to a number')
    	end
    
    	local gap = args.gap
    	local precision = tonumber(args.prec)
    
    	return p.gaps(n,{gap=gap,prec=precision})
    end
    
    -- Not named p._main so that it has a better function name when required by Module:Val
    function p.gaps(n,tbl)
    	local nstr = tostring(n)
    	if not tbl then
    		tbl = {}
    	end
    	local gap = tbl.gap or '.25em'
    
    	local int_part, frac_part = p.groups(n,tbl.prec)
    
    	local ret = mw.html.create('span')
    							:css('white-space','nowrap')
    							-- No gap necessary on first group
    							:wikitext(table.remove(int_part,1))
    
    	-- Build int part
    	for _, v in ipairs(int_part) do
    		ret:tag('span')
    				:css('margin-left',gap)
    				:wikitext(v)
    	end
    
    	if frac_part then
    		-- The first group after the decimal shouldn't have a gap
    		ret:wikitext('.' .. table.remove(frac_part,1))
    		-- Build frac part
    		for _, v in ipairs(frac_part) do
    			ret:tag('span')
    					:css('margin-left',gap)
    					:wikitext(v)
    		end
    	end
    
    	return ret
    end
    
    -- Creates tables where each element is a different group of the number
    function p.groups(num,precision)
    	local nstr = tostring(num)
    	if not precision then
    		precision = -1
    	end
    
    	local decimalloc = nstr:find('.', 1, true)
    	local int_part, frac_part
    	if decimalloc == nil then
    		int_part = nstr
    	else
    		int_part = nstr:sub(1, decimalloc-1)
    		frac_part = nstr:sub(decimalloc + 1)
    	end
    	-- only define ret_i as an empty table, let ret_d stay nil
    	local ret_i,ret_d = {}
    	-- Loop to handle most of the groupings; from right to left, so that if a group has less than 3 members, it will be the first group
    	while int_part:len() > 3 do
    		-- Insert in first spot, since we're moving backwards
    		table.insert(ret_i,1,int_part:sub(-3))
    		int_part = int_part:sub(1,-4)
    	end
    	-- handle any left over numbers
    	if int_part:len() > 0 then
    		table.insert(ret_i,1,int_part)
    	end
    
    	if precision ~= 0 and frac_part then
    		ret_d = {}
    		if precision == -1 then
    			precision = frac_part:len()
    		end
    		-- Reduce the length of the string if required precision is less than actual precision
    		-- OR
    		-- Increase it (by adding 0s) if the required precision is more than actual
    		local offset = precision - frac_part:len()
    		if offset < 0 then
    			frac_part = frac_part:sub(1,precision)
    		elseif offset > 0 then
    			frac_part = frac_part .. string.rep('0', offset)
    		end
    
    		-- Allow groups of 3 or 2 (3 first)
    		for v in string.gmatch(frac_part,'%d%d%d?') do
    			table.insert(ret_d,v)
    		end
    		-- Preference for groups of 4 instead of groups of 1 at the end
    		if #frac_part % 3 == 1 then
    			if frac_part:len() == 1 then
    				ret_d = {frac_part}
    			else
    				local last_g = ret_d[#ret_d] or ''
    				last_g = last_g..frac_part:sub(-1)
    				ret_d[#ret_d] = last_g
    			end
    		end
    	end
    
    	return ret_i,ret_d
    end
    
    return p