require 'Амодуль:No globals'
local getArgs = require('Амодуль:Arguments').getArgs
local p = {}
--- Сопоставление идентификатора объекта в Викиданных с идентификатором тела в GeoHack.
p.myGlobes = {
Q2 = "earth",
Q308 = "mercury",
Q313 = "venus",
Q405 = "moon",
Q111 = "mars",
Q7547 = "phobos",
Q7548 = "deimos",
Q3169 = "ganymede",
Q3134 = "callisto",
Q3123 = "io",
Q3143 = "europa",
Q15034 = "mimas",
Q3303 = "enceladus",
Q15047 = "tethys",
Q15040 = "dione",
Q15050 = "rhea",
Q2565 = "titan",
Q15037 = "hyperion",
Q17958 = "iapetus",
Q17975 = "phoebe",
Q3352 = "miranda",
Q3343 = "ariel",
Q3338 = "umbriel",
Q3322 = "titania",
Q3332 = "oberon",
Q3359 = "triton",
Q339 = "pluto",
}
local roundingForType = {
landmark = 2,
railwaystation = 2,
pass = 2,
edu = 2
}
-- dec2dms(0) --> 0°
-- dec2dms(10.5) --> 10°30′
-- dec2dms(0.016667) --> 0°1′
-- dec2dms(0.004166) --> 0°0′15″
function p._dec2dms(value, precision, display)
value = math.abs(value)
local sec, secfrac = math.modf(value * 3600 + 0.005)
local minTotal = math.floor(value * 60 + 0.5)
if display == "table" then
precision = 0
elseif not precision then
if sec % 60 > 0 then
precision = 0
elseif minTotal % 60 > 0 then
precision = -1
else
precision = -2
end
end
if precision == -2 then
local deg = math.floor(value + 0.5)
return string.format("%d°", deg)
elseif precision == -1 then
local min = minTotal % 60
local deg = math.floor(minTotal / 60)
return string.format("%d°%d′", deg, min)
else
local mult = 10^precision
local secTotal = math.floor(value * 3600 * mult + 0.5) / mult
local min = math.floor(secTotal / 60)
local sec = secTotal - min * 60
local deg = math.floor(min / 60)
min = min % 60
-- ošetření zaokrouhlovací chyby
sec = math.floor(sec * mult + 0.1) / mult
if display ~= "table" then
local lang = mw.language.getContentLanguage()
return string.format("%d°%d′%s″", deg, min, lang:formatNum(sec))
else
return string.format("%d°%02d′%02d″", deg, min, sec)
end
end
end
function p.dec2dms(frame)
return p._dec2dms(frame.args[1], frame.args[2], nil)
end
function p._renderCoordinates(args, frame)
local pageTitle = mw.title.getCurrentTitle()
local lat = tonumber(args[1])
local lon = tonumber(args[2])
if not lat or not lon then
local err = "<span class='error'>Неправильный синтаксис координат: <code>" .. mw.text.nowiki(args[1] or "") .. "</code>, <code>" .. mw.text.nowiki(args[2] or "") .. "</code></span>"
if pageTitle.namespace == 0 then err = err .. "[[Акатегориа:Обслуживание:Страницы с неправильными координатами]]" end
return err
end
local display = args.display
local isMain = display == "top" or display == "infobox"
local globe = args.globe
local explicitName = args.name
local name = explicitName or (isMain and pageTitle.text)
local typ = args.typ or args.type
local region = args.region
local scale = args.scale
local rounding = typ and roundingForType[typ]
typ = typ or "landmark"
local geoParams = { tostring(lat), "N", tostring(lon), "E" }
if globe then table.insert(geoParams, "globe:" .. globe) end
if typ then table.insert(geoParams, "type:" .. typ) end
if region then table.insert(geoParams, "region:" .. region) end
if scale then table.insert(geoParams, "scale:" .. scale) end
local urlParams = {
language = "ab",
pagename = pageTitle.prefixedText
}
if explicitName then urlParams.title = explicitName end
-- WikiMiniAtlas требуется параметр «params» в самом конце (https://github.com/dschwen/wikiminiatlas/issues/35)
local geohackUrl = "//geohack.toolforge.org/geohack.php?" .. mw.uri.buildQueryString(urlParams) .. '¶ms=' .. table.concat(geoParams, "_")
local latStr = p._dec2dms(lat, rounding, display)
local lonStr = p._dec2dms(lon, rounding, display)
local sp = " "
if display == "table" then
local latLen = #string.gsub(string.gsub(args[1], '^-', ''), '%..*', '') - #string.gsub(latStr, '°.*', '')
latStr = string.rep(' ', latLen) .. latStr -- číslicová mezera
local lonLen = #string.gsub(string.gsub(args[2], '^-', ''), '%..*', '') - #string.gsub(lonStr, '°.*', '')
lonStr = string.rep(' ', lonLen) .. lonStr
sp = " " -- úzká mezera
end
local coordStrTab = {latStr .. sp .. (lat >= 0 and "ҩ." or "л.") .. sp .. "ҭ.",
lonStr .. sp .. (lon >= 0 and "мг." or "мҭ.") .. sp .. "н."}
for i, str in pairs(coordStrTab) do
coordStrTab[i] = tostring(mw.html.create('span')
:attr({style = "white-space:pre"})
:wikitext(str)
:done())
end
local coordStr = table.concat(coordStrTab, "," .. sp)
local result = {}
if pageTitle.namespace == 0 then
if globe and globe ~= 'earth' and globe ~= 'moon' and lon < 0 then
-- [[mw:Extension:GeoData#Glossary]]
-- [[Амодуль ахцәажәара:Coordinates#Инопланетные объекты]]
lon = lon + 360
end
local coordTagArgs = { isMain and "primary" or "", tostring(lat), tostring(lon) }
if scale then coordTagArgs["scale"] = scale end
if globe then coordTagArgs["globe"] = globe end
if name then coordTagArgs["name"] = name end
if region then coordTagArgs["region"] = region end
if typ then coordTagArgs["type"] = typ end
table.insert(result, frame:callParserFunction("#coordinates", coordTagArgs))
end
if isMain then
table.insert(result, "<span>")
table.insert(result, frame:extensionTag('indicator', 'Souřadnice: [' .. geohackUrl .. ' ' .. coordStr .. ']', { name = 'coordinates' }))
table.insert(result, "</span>")
end
if display ~= "top" then
local linkResult = {}
table.insert(linkResult, "[")
table.insert(linkResult, geohackUrl)
table.insert(linkResult, " ")
if display == "link" and explicitName then
table.insert(linkResult, explicitName)
else
table.insert(linkResult, coordStr)
end
table.insert(linkResult, "]")
local attrs = { class = 'coordinates' }
if explicitName then
attrs.id = explicitName -- внимание, необходимо гарантировать, что id будет уникальным на странице
end
if display == "table" then
attrs.class = attrs.class .. ' plainlinks'
end
table.insert(result, tostring(mw.html.create('span')
:attr(attrs)
:wikitext(table.concat(linkResult))
:done()))
end
return table.concat(result)
end
function p.renderCoordinates(frame)
local args = getArgs(frame, { removeBlanks = true })
return p._renderCoordinates(args, frame)
end
return p