Module:Val: Difference between revisions

From Zoophilia Wiki
Jump to navigationJump to search
meta>The Mol Man
No edit summary
meta>The Mol Man
No edit summary
Line 3: Line 3:
local getArgs
local getArgs
local delimit_groups = require('Module:Gapnum').groups
local delimit_groups = require('Module:Gapnum').groups
local makeunit = require('Module:Val/units')
local mSu = require('Module:Su')._main


function p.main(frame)
function p.main(frame)
Line 16: Line 14:
-- Error checking
-- Error checking
if not validnumber(args[1]) then
if not validnumber(args[1]) then
return valerror('Error in {{Val}}: first argument is not a valid number.',nocat)
return valerror('first argument is not a valid number.',nocat)
end
end
if args[2] and not validnumber(args[2]) then
if args[2] and not validnumber(args[2]) then
return valerror('Error in {{Val}}: second argument is not a valid number.',nocat)
return valerror('second argument is not a valid number.',nocat)
end
end
if args[3] and not validnumber(args[3]) then
if args[3] and not validnumber(args[3]) then
return valerror('Error in {{Val}}: third argument is not a valid number.',nocat)
return valerror('third argument is not a valid number.',nocat)
end
end
-- Negative third param
-- Negative third param
if args[3] and (not mw.ustring.find(args[3],'[−%-]') or mw.ustring.find(args[3],'^%D0$')) then
if args[3] and (not mw.ustring.find(args[3],'[−%-]') or mw.ustring.find(args[3],'^%D0$')) then
return valerror('Error in {{Val}}: third argument is not negative.',nocat)
return valerror('third argument is not negative.',nocat)
end
end
if args.e and not validnumber(args.e) then
if args.e and not validnumber(args.e) then
return valerror('Error in &#123;&#123;Val&#125;&#125;: exponent argument (<b>e</b>) is not a valid number.',nocat)
return valerror('exponent argument (<b>e</b>) is not a valid number.',nocat)
end
end
if args.u and args.ul then
if args.u and args.ul then
return valerror('Error in &#123;&#123;Val&#125;&#125;: unit (<b>u</b>) and units with link (<b>ul</b>) are both specified, only one is allowed.',nocat)
return valerror('unit (<b>u</b>) and units with link (<b>ul</b>) are both specified, only one is allowed.',nocat)
end
end
if args.up and args.upl then
if args.up and args.upl then
return valerror('Error in &#123;&#123;Val&#125;&#125;: unit per (<b>up</b>) and units per with link (<b>upl</b>) are both specified, only one is allowed.',nocat)
return valerror('unit per (<b>up</b>) and units per with link (<b>upl</b>) are both specified, only one is allowed.',nocat)
end
end


-- Group arguments into related categories and unpack when needed
local uncertainty = {upper=args[2], lower=args[3],
local uncertainty = {upper=args[2], lower=args[3],
errend=args.errend,
errend=args.errend,
Line 52: Line 51:
local e_10 = misc_tbl.e
local e_10 = misc_tbl.e
local unc
local uncU, uncL = uncertainty.upper, uncertainty.lower
if number.nend then
if number.nend then
n:wikitext(number.nend)
n:wikitext(number.nend)
end
end
 
-- If units are defined, load the unit submodule to create a string
local paren_wrap = misc_tbl.e and (not uncL and (uncU and not uncU:find('%(')))
if u_tbl.u then
if u_tbl.u then
local makeunit = require('Module:Val/units')
units = makeunit(u_tbl.u,
units = makeunit(u_tbl.u,
{link=u_tbl.ul,
{link=u_tbl.ul,
Line 66: Line 62:
per_link=u_tbl.pl})
per_link=u_tbl.pl})
end
end
-- Uncertainty
local unc
-- Upper and lower
local uncU, uncL = uncertainty.upper, uncertainty.lower
-- Whether or not the entire number needs to be wrapped in parentheses
-- true if:
---- the expontent parameter (e) is defined
---- AND
---- no lower uncertainty is defined
---- AND
---- upper uncertainty is defined and contains no parentheses
local paren_wrap = misc_tbl.e and (not uncL and (uncU and not uncU:find('%(')))
-- boolean to be defined and used later
local paren_uncertainty
local paren_uncertainty
-- Upper is always used, so look for it first
if uncU then
if uncU then
-- Look for lower uncertainty
if uncL then
if uncL then
-- Load the sup/sub module
local mSu = require('Module:Su')._main
-- Format upper and lower
uncU = delimit(uncU,fmt)
uncU = delimit(uncU,fmt)
uncL = delimit(uncL,fmt)
uncL = delimit(uncL,fmt)
-- If no exponent is defined, and there are units, add them
if not e_10 and units then
if not e_10 and units then
uncU = uncU..units
uncU = uncU..units
uncL = uncL..units
uncL = uncL..units
end
end
-- Add the uncertainty suffixes here
uncU = uncU..(uncertainty.upperend or '')
uncU = uncU..(uncertainty.upperend or '')
uncL = uncL..(uncertainty.lowerend or '')
uncL = uncL..(uncertainty.lowerend or '')
unc = '<span style="margin-left:0.3em;">'..mSu(uncU,uncL)..'</span>'
unc = '<span style="margin-left:0.3em;">'..mSu(uncU,uncL)..'</span>'
else
else
-- Look for parentheses surrounding upper uncertainty
local uncU_n = mw.ustring.match(uncU,('%((.+)%)')) or uncU
local uncU_n = mw.ustring.match(uncU,('%((.+)%)')) or uncU
-- If no parens, use ±
if uncU == uncU_n then
if uncU == uncU_n then
unc = '<span style="margin-left:0.3em;margin-right:0.15em">±</span>'..delimit(uncU_n,fmt)
unc = '<span style="margin-left:0.3em;margin-right:0.15em">±</span>'..delimit(uncU_n,fmt)
unc = unc..'</span>'
unc = unc..'</span>'
-- Otherwise tidy the number and put it back in parentheses
-- Indicate parentheses were used (for later)
else
else
unc = '('..delimit(uncU_n,fmt)..')'
unc = '('..delimit(uncU_n,fmt)..')'
paren_uncertainty = true
paren_uncertainty = true
end
end
-- Add units if no exponent argument
if not e_10 and units then
if not e_10 and units then
unc = unc..units
unc = unc..units
Line 92: Line 116:
end
end
end
end
 
-- Add units if no exponent argument and no parentheses for uncertainty
if not e_10 and units and not paren_uncertainty then
if not e_10 and units and not paren_uncertainty then
n = n..units
n = n..units
end
end
-- If exponent defined, create 10<sup>e</sup>
-- Add units if they're defined
if e_10 then
if e_10 then
e_10 = '<span style="margin-left:0.25em;margin-right:0.15em">×</span>10<sup>'..delimit(misc_tbl.e)..'</sup>'
e_10 = '<span style="margin-left:0.25em;margin-right:0.15em">×</span>10<sup>'..delimit(misc_tbl.e)..'</sup>'
Line 105: Line 130:
e_10 = ''
e_10 = ''
end
end
local ret = {  
-- Table to concat in order of what goes where
local ret =
table.concat({
-- prefix
misc_tbl.pre or '',
misc_tbl.pre or '',
-- opening parenthesis if needed
paren_wrap and '(' or '',
paren_wrap and '(' or '',
-- number
n,
n,
misc_tbl.nend or '',
-- uncertainties
unc or '',
unc or '',
-- closes parenthesis if needed
paren_wrap and ')' or '',
paren_wrap and ')' or '',
-- 10^e if needed
e_10,
e_10,
-- suffix
misc_tbl.suf or ''
misc_tbl.suf or ''
}
})
ret = table.concat(ret)
return ret
return ret
end
end
Line 158: Line 190:
end
end


-- Specific message for {{Val}} errors
function valerror(msg,nocat)
function valerror(msg,nocat)
local ret = mw.html.create('strong')
local ret = mw.html.create('strong')
:addClass('error')
:addClass('error')
:wikitext(msg)
:wikitext('Error in &#123;&#123;Val&#125;&#125;: '..msg)
-- Not in talk, user, user_talk, or wikipedia_talk
-- Not in talk, user, user_talk, or wikipedia_talk
if not nocat and not mw.title.getCurrentTitle():inNamespaces(1,2,3,5) then
if not nocat and not mw.title.getCurrentTitle():inNamespaces(1,2,3,5) then
Line 169: Line 202:
end
end


-- true/false whether or not the string is a valid number
-- ignores parentheses and parity symbolts
function validnumber(n)
function validnumber(n)
-- Look for a number that may be surrounded by parentheses or may have +/-
-- Look for a number that may be surrounded by parentheses or may have +/-

Revision as of 20:52, 9 January 2015

Documentation for this module may be created at Module:Val/doc

local p = {}
 
local getArgs
local delimit_groups = require('Module:Gapnum').groups

function p.main(frame)
	if not getArgs then
		getArgs = require('Module:Arguments').getArgs
	end
	local args = getArgs(frame, {wrappers = 'Template:Val'})
	local number = {n=args[1], nend=args['end']}
	local nocat = args.nocategory
	
	-- Error checking
	if not validnumber(args[1]) then
		return valerror('first argument is not a valid number.',nocat)
	end
	if args[2] and not validnumber(args[2]) then
		return valerror('second argument is not a valid number.',nocat)
	end
	if args[3] and not validnumber(args[3]) then
		return valerror('third argument is not a valid number.',nocat)
	end
	-- Negative third param
	if args[3] and (not mw.ustring.find(args[3],'[−%-]') or mw.ustring.find(args[3],'^%D0$')) then
		return valerror('third argument is not negative.',nocat)
	end
	if args.e and not validnumber(args.e) then
		return valerror('exponent argument (<b>e</b>) is not a valid number.',nocat)
	end
	if args.u and args.ul then
		return valerror('unit (<b>u</b>) and units with link (<b>ul</b>) are both specified, only one is allowed.',nocat)
	end
	if args.up and args.upl then
		return valerror('unit per (<b>up</b>) and units per with link (<b>upl</b>) are both specified, only one is allowed.',nocat)
	end

	-- Group arguments into related categories and unpack when needed
	local uncertainty = {upper=args[2], lower=args[3],
							errend=args.errend,
							upperend=args['+errend'], lowerend=args['-errend']}
	local u_tbl = {u=args.ul or args.u, ul=args.ul ~= nil,
					p=args.upl or args.up, pl=args.upl ~= nil}
	local misc_tbl = {e=args.e, pre=args.p, suf=args.s, fmt=args.fmt or '', nocat=args.nocategory}
	return p._main(number,uncertainty,u_tbl,misc_tbl)
end

function p._main(number,uncertainty,u_tbl,misc_tbl)
	local fmt = misc_tbl.fmt
	local n = delimit(number.n,fmt)
	local e_10 = misc_tbl.e
	
	if number.nend then
		n:wikitext(number.nend)
	end
	-- If units are defined, load the unit submodule to create a string
	if u_tbl.u then
		local makeunit = require('Module:Val/units')
		units = makeunit(u_tbl.u,
						{link=u_tbl.ul,
							per=u_tbl.p,
							per_link=u_tbl.pl})
	end

	-- Uncertainty
	local unc
	-- Upper and lower
	local uncU, uncL = uncertainty.upper, uncertainty.lower
	-- Whether or not the entire number needs to be wrapped in parentheses
	-- true if:
	---- the expontent parameter (e) is defined
	---- AND
	---- no lower uncertainty is defined
	---- AND
	---- upper uncertainty is defined and contains no parentheses
	local paren_wrap = misc_tbl.e and (not uncL and (uncU and not uncU:find('%(')))

	-- boolean to be defined and used later
	local paren_uncertainty
	-- Upper is always used, so look for it first
	if uncU then
		-- Look for lower uncertainty
		if uncL then
			-- Load the sup/sub module
			local mSu = require('Module:Su')._main
			-- Format upper and lower
			uncU = delimit(uncU,fmt)
			uncL = delimit(uncL,fmt)
			-- If no exponent is defined, and there are units, add them
			if not e_10 and units then
				uncU = uncU..units
				uncL = uncL..units
			end
			-- Add the uncertainty suffixes here
			uncU = uncU..(uncertainty.upperend or '')
			uncL = uncL..(uncertainty.lowerend or '')

			unc = '<span style="margin-left:0.3em;">'..mSu(uncU,uncL)..'</span>'
		else
			-- Look for parentheses surrounding upper uncertainty
			local uncU_n = mw.ustring.match(uncU,('%((.+)%)')) or uncU
			-- If no parens, use ±
			if uncU == uncU_n then
				unc = '<span style="margin-left:0.3em;margin-right:0.15em">±</span>'..delimit(uncU_n,fmt)
				unc = unc..'</span>'
			-- Otherwise tidy the number and put it back in parentheses
			-- Indicate parentheses were used (for later)
			else
				unc = '('..delimit(uncU_n,fmt)..')'
				paren_uncertainty = true
			end
			-- Add units if no exponent argument
			if not e_10 and units then
				unc = unc..units
			end
		end
	end
	-- Add units if no exponent argument and no parentheses for uncertainty
	if not e_10 and units and not paren_uncertainty then
		n = n..units
	end
	-- If exponent defined, create 10<sup>e</sup>
	-- Add units if they're defined
	if e_10 then
		e_10 = '<span style="margin-left:0.25em;margin-right:0.15em">×</span>10<sup>'..delimit(misc_tbl.e)..'</sup>'
		if units then
			e_10 = e_10..units
		end
	else
		e_10 = ''
	end
	-- Table to concat in order of what goes where
	local ret =
	table.concat({
				-- prefix
				misc_tbl.pre or '',
				-- opening parenthesis if needed
				paren_wrap and '(' or '',
				-- number
				n,
				-- uncertainties
				unc or '',
				-- closes parenthesis if needed
				paren_wrap and ')' or '',
				-- 10^e if needed
				e_10,
				-- suffix
				misc_tbl.suf or ''
			})
	return ret
end

-- TODO: Add other format options
function delimit(n,fmt)
	local prefix,num
	if not fmt then fmt = '' end
	if n:find('[%-%+]') then
		prefix,num = mw.ustring.match(n,'([-+])([%d.]+)')
	else
		num = n
	end
	local ipart, dpart = delimit_groups(num)
	if fmt:lower() == 'commas' then
		num = table.concat(ipart,',')
		if dpart then
			dpart = table.concat(dpart)
			num = num..'.'..dpart
		end
	else
		num = {}
		num[1] = table.remove(ipart,1)
		for _, v in ipairs(ipart) do
			table.insert(num,'<span style="margin-left:.25em">'..v..'</span>')
		end
		if dpart then
			table.insert(num,'.'..table.remove(dpart,1))
			for _, v in ipairs(dpart) do
				table.insert(num,'<span style="margin-left:.25em">'..v..'</span>')
			end
		end
		num = table.concat(num)
	end
	if prefix then
		if prefix == '-' then
			prefix = '&minus;'
		end
		num = prefix..num
	end
	return num
end

-- Specific message for {{Val}} errors
function valerror(msg,nocat)
	local ret = mw.html.create('strong')
							:addClass('error')
							:wikitext('Error in &#123;&#123;Val&#125;&#125;: '..msg)
	-- Not in talk, user, user_talk, or wikipedia_talk
	if not nocat and not mw.title.getCurrentTitle():inNamespaces(1,2,3,5) then
		ret:wikitext('[[Category:Pages with incorrect formatting templates use]]')
	end
	return tostring(ret)
end

-- true/false whether or not the string is a valid number
-- ignores parentheses and parity symbolts
function validnumber(n)
	-- Look for a number that may be surrounded by parentheses or may have +/-
	n = mw.ustring.match(tostring(n),'^%(?[±%-%+]?([%d\.]+)%)?$')
	return tonumber(n) ~= nil
end
return p