Перайсці да зместу

Модуль:WikidataCoords

З Вікіпедыі, свабоднай энцыклапедыі

Дакументацыю да гэтага модуля можна стварыць у Модуль:WikidataCoords/Дакументацыя

local p = {}

-- Значэнні прадвызначаных аргументаў
local defaultArgs = {
	['lat_deg'] = '',
	['lat_min'] = '0',
	['lat_sec'] = '0',
	['lat_dir'] = 'N',
	['lon_deg'] = '',
	['lon_min'] = '0',
	['lon_sec'] = '0',
	['lon_dir'] = 'E'
}

-- Дадатковыя прадвызначаныя аргументы для *_wikidata
local defaultArgsWikidata = {
	['lat_deg_wikidata'] = '',
	['lat_min_wikidata'] = '0',
	['lat_sec_wikidata'] = '0',
	['lat_dir_wikidata'] = 'N',
	['lon_deg_wikidata'] = '0',
	['lon_min_wikidata'] = '0',
	['lon_sec_wikidata'] = '0',
	['lon_dir_wikidata'] = 'E'
}

-- Суадносіны найменных і лікавых параметраў
local argsMap = {
	'lat_deg','lat_min','lat_sec','lat_dir',
	'lon_deg','lon_min','lon_sec','lon_dir'
}

-- === Дапаможныя функцыі ===

local function trimUnits(v)
	if v == nil then return v end
	return mw.text.trim(v, '°′″ ')
end

local function trimUnitsForKeys(tbl, keys)
	for _, k in ipairs(keys) do
		if tbl[k] ~= nil and tbl[k] ~= '' then
			tbl[k] = trimUnits(tbl[k])
		end
	end
end

-- Вяртае lat, lon або nil, nil калі няма
local function fetchCoordsFromWD(frame, property)
	local moduleWikidata = require('Module:Wikidata')

	-- Падтрымка параметра propertyFilter; прадвызначана P625
	local prop = property or 'p625'
	frame.args = {
		['property'] = prop,
		['plain'] = true,
		['subvalue'] = 'plain'
	}

	local coords = moduleWikidata.formatProperty(frame)
	if not coords or coords == '' then
		return nil, nil
	end

	-- Замена HTML-сутнасцей
	coords = tostring(coords)
	coords = string.gsub(coords, ''', '′')
	coords = string.gsub(coords, '"', '″')

	-- Выдаляем усё, што не лічбы/знакі раздзялення
	coords = mw.ustring.gsub(coords, '[^%d.,-]', '')

	local parts = mw.text.split(coords, ',', true)
	local lat = tonumber(parts[1])
	local lon = tonumber(parts[2])

	return lat, lon
end

-- === Асноўныя функцыі ===

-- Зваротна сумяшчальная версія: калі няма lat/coord — падцягваем ВД у базавыя палі;
-- калі lat зададзены, з ВД дадаём *_wikidata
function p.execTplAddCoords(frame)
	local pFrame = frame:getParent()
	local args = mw.clone(pFrame.args)
	setmetatable(args, nil)

	local template = mw.text.trim(args[1])

	-- Калі базавыя параметры пустыя — нічога не робім
	if not args.lat_deg or args.lat_deg == '' then
		return ''
	end

	-- Атрыманне каардынат з Вікіданых у *_wikidata
	local propertyFilter = args.propertyFilter or 'p625'
	local lat, lon = fetchCoordsFromWD(frame, propertyFilter)

	if lat ~= nil then
		args.lat_deg_wikidata = math.abs(lat)
		args.lat_dir_wikidata = (lat >= 0) and 'N' or 'S'
	end
	if lon ~= nil then
		args.lon_deg_wikidata = math.abs(lon)
		args.lon_dir_wikidata = (lon >= 0) and 'E' or 'W'
	end

	-- Прадвызначаныя значэнні і абрэзка адзінак
	for name, value in pairs(defaultArgsWikidata) do
		if not args[name] or args[name] == '' then
			args[name] = value
		end
		args[name] = trimUnits(args[name])
	end
	for name, value in pairs(defaultArgs) do
		if not args[name] or args[name] == '' then
			args[name] = value
		end
		args[name] = trimUnits(args[name])
	end

	return frame:expandTemplate{ title = template, args = args }
end

-- Метад выклікае шаблон, дадаючы да параметраў каардынаты з Вікіданых
function p.execTplWithCoords(frame)
	local pFrame = frame:getParent()
	local args = mw.clone(pFrame.args)
	setmetatable(args, nil)

	local template = mw.text.trim(args[1]); args[1] = nil

	-- Фармат вываду
	local outType = args[2]
	if outType then outType = mw.text.trim(outType) end

	-- Перавызначэнне 1 і 2 параметра
	args[1] = args['01']; args['01'] = nil
	args[2] = args['02']; args['02'] = nil

	local isWikidata = false

	-- Калі няма ні coord, ні lat_deg — спрабуем ВД,
	-- але з падтрымкай propertyFilter
	if (not args.lat_deg or args.lat_deg == '') and (not args.coord or args.coord == '') then
		isWikidata = true
		local propertyFilter = args.propertyFilter or 'p625'
		local lat, lon = fetchCoordsFromWD(frame, propertyFilter)

		-- Калі ВД нічога не вярнуў — не выклікаем шаблон (палепшаны ранні выхад)
		if lat == nil and lon == nil then
			return ''
		end

		if lat ~= nil then
			args.lat_deg = math.abs(lat)
			args.lat_dir = (lat >= 0) and 'N' or 'S'
		end
		if lon ~= nil then
			args.lon_deg = math.abs(lon)
			args.lon_dir = (lon >= 0) and 'E' or 'W'
		end
	end

	-- Устаноўка прадвызначаных значэнняў
	for name, value in pairs(defaultArgs) do
		if not args[name] or args[name] == '' then
			args[name] = value;
		end
	end

	-- Абрэзка адзінак ва ўваходных значэннях (стар. паводзіны)
	trimUnitsForKeys(args, {
		'lat_deg','lat_min','lat_sec','lat_dir',
		'lon_deg','lon_min','lon_sec','lon_dir'
	})

	-- Калі параметры пустыя, шаблон не выклікаецца
	if (args.lat_deg == '' and args.lon_deg == '') and (not args.coord or args.coord == '') then
		return '';
	end

	-- Апрацоўка фармату вываду
	if outType and (not args.coord or args.coord == '') then
		-- Нумараваныя параметры, пачынаючы з n-га
		if outType == '12345678' or outType == '23456789' or outType == '345678910' then
			local n = 0;
			if outType == '23456789' then
				n = 1;
			elseif outType == '345678910' then
				n = 2;
			end

			for i, name in ipairs(argsMap) do
				args[i + n] = args[name];
				args[name] = nil;
			end
		end
		if outType == 'coord' then
			args['coord'] = args.lat_deg ..
				'/' ..
				args.lat_min ..
				'/' ..
				args.lat_sec ..
				'/' ..
				args.lat_dir .. '/' .. args.lon_deg .. '/' .. args.lon_min .. '/' .. args.lon_sec .. '/' .. args.lon_dir
		end
	end

	local out = frame:expandTemplate{ title = template, args = args }
	if (not isWikidata) and not (args.display and args['display'] == 'title') then
		out = '<span class="no-wikidata" data-wikidata-property-id="P625">' .. out .. '</span>'
	end

	return out
end

return p;