Modul:Wikidata/Formatters
Skočit na navigaci
Skočit na vyhledávání
Věci přenesené přes šablony z cs:wiki
require "Modul:No globals"
local p = {}
local lib = require 'Modul:Wikidata/lib'
local function formatCoordinateValue(value, typeOfValue, field)
local function fastConvertDdToDms(ddValue)
local dmsArr = {
degrees = 0,
minutes = 0,
seconds = 0.0
}
if ddValue then
dmsArr.degrees = math.floor(tonumber(ddValue))
dmsArr.minutes = math.floor((tonumber(ddValue) - dmsArr["degrees"]) * 60)
dmsArr.seconds = (tonumber(ddValue) - dmsArr["degrees"] - dmsArr["minutes"]/60) * 3600
end
return dmsArr
end
-- type bude nepovinny - tj. "nil"
-- priklad pouze -- je tam asi X chyb (mimo jine N vs S a podobne)
local result = ""
local latdmsText, londmsText
if typeOfValue == 'dms' then
local latDms = fastConvertDdToDms(value.latitude)
local lonDms = fastConvertDdToDms(value.longitude)
latdmsText = mw.ustring.format('N %s° %s\' %s"', latDms["degrees"], latDms["minutes"], latDms["seconds"])
londmsText = mw.ustring.format('E %s° %s\' %s"', lonDms["degrees"], lonDms["minutes"], lonDms["seconds"])
if field then
if field == 'latitude' then
result = latdmsText
elseif field == 'longitude' then
result = londmsText
end
else
result = latdmsText .. " " .. londmsText
end
elseif typeOfValue == 'dd' then
latdmsText = tonumber(value.latitude)
londmsText = tonumber(value.longitude)
if field then
if field == 'latitude' then
result = latdmsText
elseif field == 'longitude' then
result = londmsText
end
else
result = latdmsText .. " " .. londmsText
end
else
result = value.latitude .. ' / ' .. value.longitude .. ' (přesnost: ' .. value.precision .. ')'
end
return result
end
local function findPattern(property)
local entity = mw.wikibase.getEntity(property:upper())
if entity then
local Statements = entity:getBestStatements('P1630')
for _, statement in pairs(Statements) do
if lib.IsSnakValue(statement.mainsnak) then
return p.getRawValue(statement.mainsnak)
end
end
end
return nil
end
local function formatQuantity(value, options)
local amount = tonumber(value.amount)
local margin
if lib.IsOptionTrue(options, 'showmargin') then
margin = tonumber(value.upperBound) - amount
if margin == 0 then
margin = nil
end
end
local prefix
if amount < 0 then
amount = tonumber(mw.ustring.sub(amount, 2))
prefix = '-'
end
if lib.IsOptionTrue(options, 'formatted') then
local function formatNumber(number)
local integer, decimal
if mw.ustring.find(number, '%.') then
integer, decimal = mw.ustring.match(number, '^(.+)%.(.+)$')
else
integer = number
end
local length = mw.ustring.len(integer)
local i = length % 3
if i == 0 then
i = 3
end
local formatted_num = mw.ustring.sub(integer, 1, i)
while i < length do
formatted_num = formatted_num .. ' ' .. mw.ustring.sub(integer, i + 1, i + 3)
i = i + 3
end
if decimal then
local length = mw.ustring.len(decimal)
local i = 3
formatted_num = formatted_num .. ',' .. mw.ustring.sub(decimal, 1, 3)
while i < length do
formatted_num = formatted_num .. ' ' .. mw.ustring.sub(decimal, i + 1, i + 3)
i = i + 3
end
end
return formatted_num
end
amount = formatNumber(amount)
if margin then
margin = formatNumber(margin)
end
end
if margin then
amount = amount .. '±' .. margin
end
if prefix then
amount = prefix .. amount
end
local unit = value.unit
if unit ~= '1' and tostring(options.showunit) ~= 'false' then
local unit_id = mw.ustring.match(unit, '(Q%d+)') -- separate handler
if unit_id then
local module = require 'Modul:Wikidata'
local unit = module.formatStatementsFromLua{
id = unit_id,
limit = 1,
property = 'P558',
rank = 'best'
}
if not unit then
local ItemFormatter = require 'Modul:Wikidata/item'
unit = ItemFormatter.formatEntityId(unit_id, {})
end
amount = amount .. ' ' .. unit
end
end
return amount
end
local function executeFormatter(formatters, value, options)
if formatters.module or formatters.withmodule then
if not formatters.module or not formatters.func then
return formatError('unknown-value-module')
end
local formatter = require ('Modul:' .. formatters.module)
if not formatter then
return formatError('value-module-not-found', formatters.module)
end
local fun = formatter[formatters.func]
if not fun then
return formatError('value-function-not-found', formatters.func)
end
return fun(value, options)
else
return formatters.func(value, options)
end
end
local function getFormatter(datavalue, aspect, options)
local FormattersMap = {
globecoordinate = {
formatted = {
func = function(value, options)
if not options.field or options.field == '' then
-- return error(lib.formatError('param-not-provided', 'field'))
return formatCoordinateValue(value, 'dms')
elseif options.field == "latitude" or options.field == "longitude" then
return formatCoordinateValue(value, options.typeOfCoordinates, options.field)
elseif options.field == "precision" or options.field == "globe" then
return value[options.field]
else
return error(lib.formatError('invalid-field', options.field))
end
end
}
},
monolingualtext = {
formatted = {
func = function(value)
return '<span lang="' .. value.language .. '">' .. value.text .. '</span>'
end
},
raw = {
func = function(value)
return value.text
end
}
},
quantity = {
formatted = {
func = formatQuantity
},
raw = {
func = function(value)
return tonumber(value.amount)
end
}
},
string = {
formatted = {
func = function(value, options)
if options.pattern and options.pattern ~= '' then
return lib.formatFromPattern(value, options.pattern)
elseif lib.IsOptionTrue(options, 'autoformat') then
local pattern = findPattern(options.property)
if pattern then
return lib.formatFromPattern(value, '[' .. pattern .. ' $1]')
end
else
return value
end
end,
}
},
time = {
formatted = {
func = 'formatDateFromWikidataValue',
module = 'Wikidata/datum'
},
raw = {
func = 'newFromWikidataValue',
module = 'Time'
}
},
["wikibase-entityid"] = {
convert = {
func = '',
module = 'Wikidata/item'
},
formatted = {
func = function(value, options)
local module = require 'Modul:Wikidata/item'
return module.formatEntityId(lib.getEntityIdFromValue(value), options)
end
},
raw = {
func = function(...)
return lib.getEntityIdFromValue(...)
end
}
},
}
if not FormattersMap[datavalue.type] then
return error(lib.formatError('unknown-datavalue-type', datavalue.type))
end
if not FormattersMap[datavalue.type][aspect] then
if aspect == 'raw' then
return datavalue.value
else
return error() -- TODO
end
end
return executeFormatter(FormattersMap[datavalue.type][aspect], datavalue.value, options)
end
function p.getRawValue(snak, options)
if snak.snaktype == 'value' then
return getFormatter(snak.datavalue, 'raw', options)
elseif snak.snaktype == 'somevalue' or snak.snaktype == 'novalue' then
return snak.snaktype
else
return error(lib.formatError('unknown-snak-type', snak.snaktype))
end
end
function p.getFormattedValue(snak, options)
if snak.snaktype == 'somevalue' or snak.snaktype == 'novalue' then
return snak.snaktype
elseif snak.snaktype ~= 'value' then
return error(lib.formatError('unknown-snak-type', snak.snaktype))
end
if options['value-module'] or options['value-function'] then
local formatterMap = {
func = options['value-function'],
module = options['value-module'],
withmodule = true -- force throwing error
}
return executeFormatter(formatterMap, snak.datavalue.value, options)
end
return getFormatter(snak.datavalue, 'formatted', options)
end
return p