Module:Number table sorting

local lang = mw.language.getContentLanguage()
local Math = require('Module:Math')
local SortKey = require('Module:Sortkey')
-- constants
local INF = math.huge
local NEGINF = -math.huge
local MINUS = '−'  -- Unicode U+2212 MINUS SIGN (UTF-8: e2 88 92)

--------------------------------------------------------------------------------
-- Nts class
--------------------------------------------------------------------------------

local Nts = {}
Nts.__index = Nts

Nts.formats = {
	no = true,
	yes = true,
}

function Nts.new(args)
	local self = setmetatable({}, Nts)

	self:parseNumber(args[1])

	-- Set the format string
	self.format = args.format or 'yes'
	if not Nts.formats[self.format] then
		error(string.format(
			"'%s' is not a valid format",
			tostring(self.format)
		), 0)
	end
	
	-- To display some text before the display version of the number
	-- {{nts|123456789.00123|prefix=approx. }} → approx. 123,456,789.00123
	self.prefix = args.prefix or ''
	
	-- debug info
	self.debug = args.debug or 'no'
	self.quiet = args.quiet or 'no'

	return self
end


-- Parse the entered number
function Nts:parseNumber(s)
	-- sanitize
	s = s or '';
	s = string.gsub(s,'−','-')
	s = string.gsub(s, MINUS, '-')
	self.rawNumberString = s
	
	-- fractions. was somewhat but completely broken at some point
	self.isFraction = (string.find(s, '/') ~= nil)
	if self.isFraction then
		error(string.format(
				"Fractions are not supported",
				tostring(s)
			), 0)
	end
	
	-- format detection
	self.isScientificNotation = (string.find(s, 'e') ~= nil)
	
	-- parse with language options
	self.number = lang:parseFormattedNumber(s)
	
	-- parse with fallback
	if not self.number then
		self.number = tonumber(s)
	end
	
	-- allow for empty string as a value
	if not self.number then
		-- error(string.format(
		-- 		"'%s' is not a valid number",
		-- 		tostring(s)
		-- 	), 0)
		self.number = NEGINF
	end
	
	if self.number < 0 then
		self.sign = MINUS
	else
		self.sign = ''
	end

	self.absNumber = math.abs(self.number)
	if self.absNumber ~= INF then
		self.magnitude = math.floor(math.log10(self.absNumber))
		self.significand = self.number / 10^self.magnitude
		self.precision = Math._precision(self.rawNumberString)
		self.integer = math.floor(self.absNumber)
		self.fractional = math.abs(self.number - self.integer)
	end
end

function Nts:makeDisplay()
	local ret ={}

	if self.quiet == 'yes' then
		return ''
	end

	ret[#ret + 1] = self.prefix
	local sciNotation = string.find(tostring(self.number),'e')
	if self.absNnumber == INF or isNaN(self.number) or self.magnitude ==nil or math.abs(self.magnitude) == INF then
		ret[#ret + 1] = string.gsub(self.rawNumberString, '-', MINUS)
	elseif sciNotation ~= nil or math.abs(self.magnitude) >= 9 then
		ret[#ret + 1] = self.sign
		if self.format == 'yes' then
			ret[#ret + 1] = lang:formatNum(math.abs(self.number * 10^-self.magnitude))
		else
			ret[#ret + 1] = math.abs(self.number * 10^-self.magnitude)
		end
		ret[#ret + 1] = '<span style="margin-left:0.2em">×<span style="margin-left:0.1em">10</span></span><s style="display:none">^</s><sup>'
		if self.magnitude<0 then
			ret[#ret + 1] = MINUS .. (-self.magnitude)
		else
			ret[#ret + 1] = self.magnitude
		end
		ret[#ret + 1] = '</sup>'
	else
		ret[#ret + 1] = self.sign
		if self.format == 'yes' then
			ret[#ret + 1] = Math._precision_format(self.absNumber, self.precision)
		else
			local newPrecision = Math._precision(self.absNumber)
			ret[#ret + 1] = tostring(self.absNumber)
			if newPrecision < self.precision then
				if self.integer == self.absNumber then
					ret[#ret + 1] = '.'
				end
				ret[#ret + 1] = string.rep('0', math.min(12, self.precision - newPrecision) )
			end
		end
	end
    return table.concat(ret) 
end

function Nts:makeSortKey()
	return SortKey._sortKeyForNumber(self.number) .. '♠'
end

function ifNaNThen(n,p)
	if isNaN(n) then
		return p
	end
	return n
end

function isNaN(n)
	return n ~= n
end

function Nts:renderTrackingCategories()
	if self.hasDeprecatedParameters then
		return '[[Category:Nts templates with deprecated parameters]]'
	else
		return ''
	end
end

function Nts:__tostring()
	local root = mw.html.create()
	local span = root:tag('span')
		:attr('data-sort-value', self:makeSortKey())

	if self.debug == 'yes' then
		span:tag('span')
			:css('border', '1px solid')
			:wikitext(self:makeSortKey())
	elseif self.quiet ~= 'no' then
		span:css('display', 'none')
	end

	-- Display
	if self.quiet == 'no' then
		span:wikitext(self:makeDisplay())
	end

	-- Tracking categories
	root:wikitext(self:renderTrackingCategories())

	return tostring(root)
end

--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------

local p = {}

function p._exportClasses()
	return {
		Nts = Nts
	}
end

function p._main(args)
	local success, ret = pcall(function ()
		local nts = Nts.new(args)
		return tostring(nts)
	end)
	if success then
		return ret
	else
		ret = string.format(
			'<strong class="error">Error in [[Template:Nts]]: %s</strong>',
			ret
		)
		if mw.title.getCurrentTitle().namespace == 0 then
			-- Only categorise in the main namespace
			ret = ret .. '[[Category:Nts templates with errors]]'
		end
		return ret
	end
end

function p.main(frame)
	local args = require('Module:Arguments').getArgs(frame, {
		wrappers = { 'Template:Number table sorting' },
	})
	return p._main(args)
end

return p

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.