Мазмунга өтүү

Модуль:Number table sorting

Википедия — ачык энциклопедия

Documentation for this module may be created at Модуль:Number table sorting/doc

local lang = mw.language.getContentLanguage()
local Math = require('Module:Math')
local SortKey = require('Module:Sortkey')
-- константалар
local INF = math.huge
local NEGINF = -math.huge
local MINUS = '−'  -- Unicode U+2212 MINUS SIGN

--------------------------------------------------------------------------------
-- Nts класс (санды форматтоо жана сорттоо)
--------------------------------------------------------------------------------

local Nts = {}
Nts.__index = Nts

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

-- Жаңы объект түзүү
function Nts.new(args)
	local self = setmetatable({}, Nts)

	-- Санды талдоо
	self:parseNumber(args[1])

	-- Формат параметрин орнотуу
	self.format = args.format or 'yes'
	if not Nts.formats[self.format] then
		error(string.format("'%s' жараксыз формат", tostring(self.format)), 0)
	end
	
	-- Сан алдында текст кошуу (мисалы, "approx. 1,000")
	self.prefix = args.prefix or ''

	-- отладка (debug) жана тынч режим
	self.debug = args.debug or 'no'
	self.quiet = args.quiet or 'no'

	return self
end

-- Киргизилген санды талдоо
function Nts:parseNumber(s)
	s = s or ''
	s = string.gsub(s, '−', '-')
	s = string.gsub(s, MINUS, '-')
	self.rawNumberString = s

	-- Бөлүк сан текшерүү (колдоосу жок)
	self.isFraction = (string.find(s, '/') ~= nil)
	if self.isFraction then
		error("Бөлүк сандар колдоого алынбайт: " .. tostring(s), 0)
	end

	-- илимий экспоненциалдык жазуу текшерүү
	self.isScientificNotation = (string.find(s, 'e') ~= nil)

	-- тилдин форматынан parse кылуу
	self.number = lang:parseFormattedNumber(s)

	-- эгер parse болбосо, tonumber колдонуу
	if not self.number then
		self.number = tonumber(s)
	end

	-- бош сапка жол берүү
	if not self.number then
		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 sci = string.find(tostring(self.number), 'e')
	if self.absNumber == INF or isNaN(self.number) or not self.magnitude then
		ret[#ret+1] = string.gsub(self.rawNumberString, '-', MINUS)
	elseif sci 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><sup>'
		ret[#ret+1] = (self.magnitude < 0 and MINUS) or '' .. math.abs(self.magnitude)
		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
			ret[#ret+1] = tostring(self.absNumber)
			local newp = Math._precision(self.absNumber)
			if newp < self.precision then
				if self.integer == self.absNumber then ret[#ret+1] = '.' end
				ret[#ret+1] = string.rep('0', math.min(12, self.precision - newp))
			end
		end
	end
	return table.concat(ret)
end

-- Сорттоо ачкычы түзүү
function Nts:makeSortKey()
	return SortKey._sortKeyForNumber(self.number) .. '♠'
end

-- NaN текшерүү
function isNaN(n) return n ~= n end

-- Трекинг категория чыгаруу
function Nts:renderTrackingCategories()
	if self.hasDeprecatedParameters then
		return '[[Категория:Nts шаблондору эски параметрлери менен]]'
	else
		return ''
	end
end

-- tostring методу (читүү форматы жана категориялар)
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

	if self.quiet == 'no' then span:wikitext(self:makeDisplay()) end
	root:wikitext(self:renderTrackingCategories())
	return tostring(root)
end

--------------------------------------------------------------------------------
-- Экспорт жана негизги функция
--------------------------------------------------------------------------------

local p = {}

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

-- Иштетүү негизги логика
function p._main(args)
	local ok, ret = pcall(function() return tostring(Nts.new(args)) end)
	if ok then return ret else
		ret = string.format('<strong class="error">Ката: Калып:Nts: %s</strong>', ret)
		if mw.title.getCurrentTitle().namespace == 0 then
			ret = ret .. '[[Категория:Nts шаблондору каталары менен]]'
		end
		return ret
	end
end

function p.main(frame)
	local args = require('Module:Arguments').getArgs(frame, {wrappers={'Калып:Nts'}})
	return p._main(args)
end

return p