Moduł:Wikidane/format/quantity
< Moduł:Wikidane | format
Dedykowana uniwersalna wtyczka formatująca wartość cechy z wartością ilościową z opcjonalną jednostką.
Wtyczka obsługuje parametr format, w którym można wskazać identyfikator Wikidanych (Qnnnnn) określający jednostkę miary w jakiej ma być zaprezentowany wynik. Jeśli jest pusty to wyświetlana jest aktualna wartość wraz z jednostką.
Zobacz też
edytuj
Na stronie Moduł:Wikidane/format/quantity wykorzystano treści ze strony Moduł:Wikidane/format/quantity w polskiej Wikipedii (link do wersji).
Jej autorzy wymienieni są w historii edycji.
Prawa autorskie: na licencji Creative Commons CC-BY-SA.
local i18n = mw.loadData("Moduł:Wikidane/data").quantityFormats
local units = mw.loadData("Moduł:Wikidane/data").quantityUnits
local function selectRoundCoefficients(value)
local num = math.abs(value)
if num > i18n.maximumAmount then
return false, "", math.floor(num * i18n.maximumVarFactor)
end
for i, v in ipairs(i18n) do
if num > v.amount then
return v.factor, v.suffix, v.minvar
end
end
return false, "", 0
end
local function formatVar(snak)
local amount = tonumber(snak.datavalue.value.amount)
local upperVar = snak.datavalue.value.upperBound and (tonumber(snak.datavalue.value.upperBound) - amount) or 0
local lowerVar = snak.datavalue.value.lowerBound and (amount - tonumber(snak.datavalue.value.lowerBound)) or 0
local lang = mw.getContentLanguage()
if (upperVar == 0) and (lowerVar == 0) then
return lang:formatNum(amount), amount
elseif math.abs(upperVar - lowerVar) < ((upperVar + lowerVar) / 1000) then
local var = math.max(upperVar, lowerVar)
var = string.format("%f", var)
if string.match(var, "%.") then
var, _ = string.gsub(var, "%.", ",")
var, _ = string.gsub(var, "0+$", "")
var, _ = string.gsub(var, ",$", "")
end
return string.format(i18n.variance, lang:formatNum(amount), var), amount
else
return string.format(i18n.between, lang:formatNum(tonumber(snak.datavalue.value.lowerBound)), lang:formatNum(tonumber(snak.datavalue.value.upperBound))), tonumber(snak.datavalue.value.upperBound)
end
end
local function formatText(snak)
local amount = tonumber(snak.datavalue.value.amount)
local upperVar = snak.datavalue.value.upperBound and (tonumber(snak.datavalue.value.upperBound) - amount) or 0
local lowerVar = snak.datavalue.value.lowerBound and (amount - tonumber(snak.datavalue.value.lowerBound)) or 0
local div = false
local suffix = ""
local var = 0
if (upperVar ~= 0) or (lowerVar ~= 0) then
div, suffix, var = selectRoundCoefficients(amount)
end
local lang = mw.getContentLanguage()
if (div == 1) or not div then
if (upperVar == 0) and (lowerVar == 0) then
return lang:formatNum(amount), amount
elseif math.max(upperVar, lowerVar) <= var then
return string.format(i18n.around, lang:formatNum(amount)), amount
elseif upperVar == lowerVar then
return string.format(i18n.variance, lang:formatNum(amount), lang:formatNum(upperVar)), amount
else
return string.format(i18n.between, lang:formatNum(tonumber(snak.datavalue.value.lowerBound)), lang:formatNum(tonumber(snak.datavalue.value.upperBound))), tonumber(snak.datavalue.value.upperBound)
end
elseif div then
if math.max(upperVar, lowerVar) <= var then
local atxt = lang:formatNum(tonumber(string.format("%.2f", amount / div)))..suffix
return string.format(i18n.around, atxt), amount / div
elseif upperVar == lowerVar then
local atxt = lang:formatNum(tonumber(string.format("%.2f", amount / div)))..suffix
local vtxt = lang:formatNum(tonumber(string.format("%.2f", upperVar / div)))..suffix
return string.format(i18n.variance, atxt, vtxt), amount / div
else
local ltxt = lang:formatNum(tonumber(string.format("%.2f", tonumber(snak.datavalue.value.lowerBound) / div)))..suffix
local utxt = lang:formatNum(tonumber(string.format("%.2f", tonumber(snak.datavalue.value.upperBound) / div)))..suffix
return string.format(i18n.between, ltxt, utxt), tonumber(snak.datavalue.value.lowerBound) / div
end
end
end
local function formatUnit(unitEntityId, options, value)
local quantityUnits = units[unitEntityId]
if type(quantityUnits) == "table" then
return mw.getContentLanguage():convertPlural(value, quantityUnits)
end
local symbol = false
local unitSymbols = mw.wikibase.getBestStatements(unitEntityId, "P5061")
for _, v in ipairs(unitSymbols) do
if (v.mainsnak.snaktype == "value") and (v.mainsnak.datatype == "monolingualtext") and (v.mainsnak.datavalue.value.language == "pl") then
symbol = v.mainsnak.datavalue.value.text
break
end
end
if not symbol then
for _, v in ipairs(unitSymbols) do
if (v.mainsnak.snaktype == "value") and (v.mainsnak.datatype == "monolingualtext") and (v.mainsnak.datavalue.value.language == "en") then
symbol = v.mainsnak.datavalue.value.text
break
end
end
end
if not symbol then
for _, s in ipairs(mw.wikibase.getBestStatements(unitEntityId, "P487")) do
if (s.mainsnak.snaktype == "value") and (s.mainsnak.datatype == "string") and (s.mainsnak.datavalue.type == "string") then
symbol = s.mainsnak.datavalue.value
break
end
end
end
if not symbol then
symbol = mw.wikibase.getLabel(unitEntityId)
end
local sitelink = options.linkItem and mw.wikibase.getSitelink(unitEntityId)
if symbol and sitelink then
return "[["..sitelink.."|"..symbol.."]]"
elseif symbol then
return symbol
else
return unitEntityId
end
end
local autoUnitConverter = {
-- temperatura
Q42289 = function(value) return "Q25267", (value - 32) * 5/9 end, -- stopień Fahrenheita [°C]
Q223061 = function(value) return "Q25267", value * 5/4 end, -- skala Réaumura [°C]
Q488013 = function(value) return "Q25267", (value - 7.5) * 40/21 end, -- skala Rømera [°C]
Q839449 = function(value) return "Q25267", 100 - value * 2/3 end, -- skala Delisle [°C]
Q1133606 = function(value) return "Q25267", value * 100/33 end, -- Skala Newtona [°C]
-- odległość
Q3710 = function(value) return "Q11573", value * 0.3048006 end, -- stopa angielska [m]
Q253276 = function(value) return "Q828224", value * 1.609344 end, -- mila [km]
Q482798 = function(value) return "Q11573", value * 0.9144 end, -- jard [m]
Q218593 = function(value) return "Q174728", value * 2.54 end, -- cal [cm]
-- masa
Q48013 = function(value) return "Q41803", value * 28.34952 end, -- uncja [g]
Q100995 = function(value) return "Q11570", value * 0.4535923 end, -- funt [kg]
-- prędkość
Q748716 = function(value) return "Q182429", value * 0.3048006 end, -- stopy na sekundę [m/s]
Q22673229= function(value) return "Q21014455", value * 0.3048006 end, -- stopy na minutę [m/min]
Q6014364 = function(value) return "Q18413919", value * 2.54 end, -- cale na sekundę [cm/s]
Q211256 = function(value) return "Q180154", value * 1.609344 end, -- mila na godzinę [km/h]
}
local function round(value)
if not tonumber(value) or (value == 0) then
return value
end
local abs = math.abs(value)
local fix = value >= 0 and 0.5 or -0.5
if abs >= 1000 then
return math.floor(value + fix)
elseif abs >= 100 then
return math.floor(10*value + fix) / 10
elseif abs >= 10 then
return math.floor(100*value + fix) / 100
elseif abs >= 1 then
return math.floor(1000*value + fix) / 1000
elseif abs >= 0.1 then
return math.floor(10000*value + fix) / 10000
else
return value
end
end
return {
scope = "snak",
options = {
default = {
linkItem = false,
},
},
format = function(snak, options)
local value, last
if options.format == "tekst" then
value, last = formatText(snak)
else
value, last = formatVar(snak)
end
if snak.datavalue.value.unit == "1" then
return value
end
local unitEntityId = string.match(snak.datavalue.value.unit, "^http://www%.wikidata%.org/entity/(Q%d+)$")
if not unitEntityId then
mw.log("unrecognized unit: "..snak.datavalue.value.unit)
return value.." ?"
end
local unit = formatUnit(unitEntityId, options, last)
local builder = mw.html.create()
local converter = autoUnitConverter[unitEntityId]
if converter then
local unitId2, amount2 = converter(snak.datavalue.value.amount)
local _, upperBound = snak.datavalue.value.upperBound and converter(snak.datavalue.value.upperBound) or nil
local _, lowerBound = snak.datavalue.value.upperBound and converter(snak.datavalue.value.lowerBound) or nil
local v2, l2 = formatText( { datavalue = { value = { amount = round(amount2), upperBount = round(upperBound), lowerBound = round(lowerBound) } } } )
local u2 = formatUnit(unitId2, options, last)
builder:tag("span")
:addClass("wd-auto-converted")
:attr("title", value.." "..unit)
:wikitext(v2, " ", u2)
else
builder:wikitext(value, " ", unit or "!")
end
return tostring(builder)
end,
}