Aller au contenu

Module:Conversion

Cette page fait l’objet d’une mesure de semi-protection étendue.
Une page de Wikipédia, l'encyclopédie libre.

 Documentation[voir] [modifier] [historique] [purger]

Modèle de mise en forme de valeur numérique éventuellement accompagnée d'une unité de mesure.

Utilisation

Fonctions exportables vers un autre module

  • fonction p.displayvalue(value, sourceunit, displayformat) met en forme une valeur numérique éventuellement accompagné d'une unité de mesure
  • value doit être un nombre, ou une chaîne pouvant être convertie en nombre
  • sourceunit doit correspondre à une valeur acceptée sur Module:Conversion/Données.
  • la table displayformat contient les paramètres suivant :
  • targetunit = l'unité vers laquelle convertir
  • showunit showunit = true affiche l'unité de mesure, en utilisant l'abréviation donnée dans Module:Conversion/Données. showunit = long utilise le format long ("mètres" à la place de "m").
  • showlink = affiche un lien vers l'article concernant l'unité de mesure (m -> m)
  • rounding = nombre de chiffres après la virgule

Fonctions exportables vers un modèle

  • fonction p.display(frame) : sert d'intermédiaire entre le wikicode et la fonction displayvalue. Arguments:
  • 1 = valeur numérique
  • 2 = unité de mesure de la valeur d'origine
  • 3 = unité de mesure de la valeur à retourner
  • showunit = mettre "true" pour afficher l'unité de mesure
  • rounding = nombre de chiffres après la virgule

Exemples

  • {{#invoke:Conversion|display|25|foot|metre}} 7,62
  • {{#invoke:Conversion|display|25|foot|metre|rounding=0|showunit = true}} 8 m

Modules externes et autres éléments dont ce module a besoin pour fonctionner

Voir aussi

local math_mod = require "Module:Math"
local params = mw.loadData("Module:Conversion/Données")
local linguistic = require "Module:Linguistique"

local p = {}

local i18n = {
	invalidunitcat = 'Page avec une unité de mesure non prise en charge',
	invalidsourceunit = '$1 (unité non prise en charge)',
	invalidtargetunit = 'unité cible non prise en charge $1',
	typemismatch = 'impossible de convertir $1 en $2'
}

local function convert(value, sourceunitdata, targetunitdata) -- convertir une valeur numérique en son équivalent dans une autre unité de mesure
	if not value then
		return nil
	end
	if type(value) ~= 'number' then
		return error("bad datatype: " .. type(value))
	end
	if (not sourceunitdata) or (not targetunitdata) then
		return value
	end
	return value * sourceunitdata[2] / targetunitdata[2]
end

function p.displayvalue(val, sourceunit, displayformat, complement) -- affiche une valeur formatée)
	
	-- préparation des paramètres
	local numval = tonumber(val)
	if not numval then -- si les données sont inhabituelles, on laisse la fonction appelante se débrouiller
		return val
	end
	
	if not displayformat or type(displayformat) ~= 'table' then
		displayformat = {}
	end
	local showunit, showlink, targetunit = displayformat.showunit, displayformat.showlink, displayformat.targetunit
	if showlink == 'true' then
		showlink = true
	end
	local rounding = displayformat.rounding or 2
	-- récupération des donnnées concernant les unités
	if sourceunit and not targetunit then
		targetunit = sourceunit
	end
	local sourceunitdata, targetunitdata = sourceunit, targetunit
	if type(sourceunitdata) ~= 'table' then
		sourceunitdata = params.units[sourceunit] or params.units[params.redirects[sourceunit]]
	end
	if type(targetunitdata) ~= 'table' then	
		targetunitdata = params.units[targetunit] or params.units[params.redirects[targetunit]]
	end
	local suffix = {'', '', ''}

	local maintenancestr = ""

	
	-- conversion

	local function invalidsourcefallback(val, sourceunit) -- text to be shown when source unit is not supported
		local str = tostring(val)
		if sourceunit:match('Q%d ') or sourceunit:match('q%d ') then -- wikidata item
			sourceunit = mw.wikibase.label(sourceunit)
		end
		return val .. ' ' .. i18n['invalidsourceunit']:gsub('$1', sourceunit) .. '[[Category:' .. i18n.invalidunitcat .. '|' .. sourceunit .. ']]'
	end


	-- escape if source unit is invalid
	if (sourceunit and targetunit) and (targetunit~= sourceunit) and (not sourceunitdata or not sourceunitdata[1]) then
		return invalidsourcefallback(val, sourceunit)
	end

	if sourceunit and (not sourceunitdata) then 
		local label = sourceunit
		local item = sourceunit:match('q%d ') or sourceunit:match('Q%d ')
		local link
		local symbol
		if item then
			label = mw.wikibase.label(item)
			link = mw.wikibase.sitelink(item)
			if showunit and (showunit ~= 'long') then -- symbole retrieved only if needed (somewhat expensive)
				for _,statement in pairs(mw.wikibase.getBestStatements(item, 'P5061')) do
					if statement['mainsnak']['snaktype'] == 'value' and (statement['mainsnak']['datavalue']['value']['language'] == 'fr' or statement['mainsnak']['datavalue']['value']['language'] == 'mul') then
						symbol = statement['mainsnak']['datavalue']['value']['text']
					end
				end
			end
		end
		sourceunitdata = {nil, 1, symbol or label, item, link, label, label}
		targetunit, targetunitdata  = sourceunit, sourceunitdata 
	end
	
	-- warn if targetunit is unknown
	if targetunit and (not targetunitdata) then
		targetunit, targetunitdata = sourceunit, sourceunitdata
		maintenancestr = maintenancestr .. " "  .. i18n['invalidtargetunit']:gsub('$1', targetunit) .. '[[Category:' .. i18n.invalidunitcat .. '|' .. targetunit .. ']]'
	end

	-- check for type mismatch
	if (sourceunitdata and targetunitdata) and (targetunitdata[1] ~= sourceunitdata[1]) then
		local errmsg = i18n.typemismatch
		errmsg = errmsg:gsub('$1', sourceunit)
		errmsg = errmsg:gsub('$2', targetunit)
		maintenancestr = maintenancestr .. '(' .. errmsg .. ')'
		targetunit, targetunitdata = sourceunit, sourceunitdata
	end

	-- convert if needed
	if (sourceunit and targetunit) and (sourceunit ~= targetunit) then
		numval = convert(numval, sourceunitdata, targetunitdata)
	end
	
	if rounding then
		numval = math_mod._round( numval, rounding )
	end
	
	if displayformat.raw == true then -- nombre non formaté chaîne convertible en nombre sauf si catégorie de maintenance
		return (tostring(numval) or "") .. maintenancestr
	end
	
	if not displayformat.rounding then
		if (math.abs(numval) > 1E9) then
			numval = math_mod._round( numval / 1E9, 1 )
			suffix = {"milliard ", "milliards ", "<abbr title=\"milliard\">G</abbr> "}
		elseif (math.abs(numval) > 1E6) then
			numval = math_mod._round( numval / 1E6, 1 )
			suffix = {"million ", "millions ", "<abbr title=\"million\">M</abbr> "}
		end
	end
	
	local numstr = mw.getContentLanguage():formatNum(numval)

	-- showlink
	if not targetunitdata then -- pour éviter les bugs
		targetunitdata = {}
	end
	local link
	if showlink == '-' then
		link = nil
	elseif type(showlink) == 'string' then
		link = showlink
	elseif showlink then
		link = targetunitdata[5]
	end
	
	-- affichage de l'unité
	local unitstr, suffixstr
	if showunit == 'long' then -- format long = montrer l'unité en entier
		if math.abs(numval or 0) >= 2 then
			unitstr = targetunitdata[7]
		else
			unitstr = targetunitdata[6]
		end
		if ((unitstr ~= '') and link) then
			unitstr = '[[' .. link .. '|' .. unitstr .. ']]'
		end
		if (unitstr ~= '') and ((suffix[1] ~= '') or (((numval or 0) > 999999) and ( (numval or 0)% 1000000 == 0))) then
			unitstr = linguistic.of(unitstr) -- 10 000 000 "de" tonnes
		end
		if math.abs(numval or 0) >= 2 then
			suffixstr = suffix[2]
		else
			suffixstr = suffix[1]
		end
			
	elseif showunit and (showunit ~= '-') then
		unitstr = targetunitdata[3]
		if string.find(unitstr, "^%a") then -- 8 G$ mais 8 G CHF
			suffixstr = suffix[3]
		else
			suffixstr = mw.text.trim(suffix[3])
		end
		if ((unitstr ~= '') and link) then
			unitstr = '[[' .. link .. '|' .. unitstr .. ']]'
		end
	else
		suffixstr = suffix[3]
	end
	
	local str = numstr .. ' ' .. (suffixstr or '') .. (unitstr or '')
	str = mw.text.trim(str) .. maintenancestr
	if complement then
		if sourceunit then
			str = str .. " " .. linguistic.of(complement) -- "10 kg de bambous"
		else
			str = str .. " " .. complement -- "3000 véhicules"
		end
	end
	return str

end

function p.display(frame)
	local args = frame.args
	local value, origunit, targetunit = args[1], args[2], args[3]
	local rounding = args.rounding
	local showlink, showunit = 	args.showlink, args.showunit
	displayformat = {showunit = showunit, showlink = showlink, rounding = rounding, targetunit = targetunit}
	return p.displayvalue(value, origunit, displayformat)
end
return p