Module:Gapnum: Difference between revisions
From Zoophilia Wiki
Jump to navigationJump to search
meta>The Mol Man I forgot about rounding... Let's see if we can get away with not converting |
m 73 revisions imported |
||
(28 intermediate revisions by 4 users not shown) | |||
Line 7: | Line 7: | ||
getArgs = require('Module:Arguments').getArgs | getArgs = require('Module:Arguments').getArgs | ||
end | end | ||
local args = getArgs(frame, {wrappers = 'Template:Gapnum'}) | local args = getArgs(frame, {wrappers = 'Template:Gapnum'}) | ||
local gap = | 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 | 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 | |||
if | 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 | ||
end | end | ||
local nstr = tostring( | 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 decimalloc = nstr:find('.', 1, true) | ||
local int_part, frac_part | local int_part, frac_part | ||
Line 31: | Line 74: | ||
frac_part = nstr:sub(decimalloc + 1) | frac_part = nstr:sub(decimalloc + 1) | ||
end | end | ||
-- only define ret_i as an empty table, let ret_d stay nil | |||
local | local ret_i,ret_d = {} | ||
-- Loop to handle most of the groupings; from right to left, so that if a group has | -- 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 | 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) | int_part = int_part:sub(1,-4) | ||
end | end | ||
-- handle any left over numbers | -- 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 | if precision ~= 0 and frac_part then | ||
ret_d = {} | |||
if precision == -1 then | if precision == -1 then | ||
precision = frac_part:len() | precision = frac_part:len() | ||
Line 60: | Line 101: | ||
frac_part = frac_part .. string.rep('0', offset) | frac_part = frac_part .. string.rep('0', offset) | ||
end | 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 | end | ||
-- Preference for groups of 4 instead of groups of 1 at the end | |||
if | 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 | ||
end | end | ||
return | return ret_i,ret_d | ||
end | end | ||
return p | return p |
Latest revision as of 13:41, 3 September 2020
Documentation for this module may be created at Module:Gapnum/doc
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