Moduuli:Koordinaatit

Wikipediasta
Siirry navigaatioon Siirry hakuun

Tämän moduulin ohjeistuksen voi tehdä sivulle Moduuli:Koordinaatit/ohje

-- This module is for sorting out coordinates in {{M|Coord}} and 
-- aim is to allow using them with location maps when they are made to use modules
-- (currently they have various issues).

local p = {}

-- flags for where coordinates will be displayed: inline or title
local g_displaytitle = false
local g_displayinline = false

-- dd|mm|ss.s|N/S|ddd|mm|ss.s|E/W|
local function isvalid8(listItems)
	local latd = tonumber(listItems[1])
	local latm = tonumber(listItems[2])
	local lats = tonumber(listItems[3])
	local lond = tonumber(listItems[5])
	local lonm = tonumber(listItems[6])
	local lons = tonumber(listItems[7])
	
	if (latd ~= nil and latm ~= nil and lats ~= nil 
		and lond ~= nil and lonm ~= nil and lons ~= nil) then
		-- also values should be in sensible range
		-- (dd > 90 dec, m/s > 60, ddd > 180)
		if (math.abs(latd) > 90 or math.abs(latm) > 60 or math.abs(lats) > 60 
			or math.abs(lond) > 180 or math.abs(lonm) > 60 or math.abs(lons) > 60) then
			return false
		end
		if ((listItems[4] == 'N' or listItems[4] == 'S') and (listItems[8] == 'E' or listItems[8] == 'W')) then
			return true
		end
	end
	return false
end

-- dd|mm.m|N/S|ddd|mm.m|E/W|
local function isvalid6(listItems)
	local latd = tonumber(listItems[1])
	local latm = tonumber(listItems[2])
	local lond = tonumber(listItems[4])
	local lonm = tonumber(listItems[5])

	if (latd ~= nil and latm ~= nil 
		and lond ~= nil and lonm ~= nil) then
		-- also values should be in sensible range
		-- (dd > 90 dec, m/s > 60, ddd > 180)
		if (math.abs(latd) > 90 or math.abs(latm) > 60 
			or math.abs(lond) > 180 or math.abs(lonm) > 60) then
			return false
		end
		if ((listItems[3] == 'N' or listItems[3] == 'S') and (listItems[6] == 'E' or listItems[6] == 'W')) then
			return true
		end
	end
	return false
end

-- dd.d|N/S|ddd.d|E/W|
local function isvalid4(listItems)
	local lat = tonumber(listItems[1])
	local lon = tonumber(listItems[3])
	
	if (lat ~= nil and lon ~= nil) then
		-- also values should be in sensible range
		-- (dd > 90 dec, m/s > 60, ddd > 180)
		if (math.abs(lat) > 90 or math.abs(lon) > 180) then
			return false
		end
		if ((listItems[2] == 'N' or listItems[2] == 'S') and (listItems[4] == 'E' or listItems[4] == 'W')) then
			return true
		end
	end
	return false
end

-- dd.d|ddd.d|
local function isvalid2(listItems)
	local lat = tonumber(listItems[1])
	local lon = tonumber(listItems[2])
	if (lat ~= nil and lon ~= nil) then
		-- also values should be in sensible range
		-- (dd > 90 dec, m/s > 60, ddd > 180)
		if (math.abs(lat) > 90 or math.abs(lon) > 180) then
			return false
		end
		return true
	end
	return false
end

-- region: 
local function isregion( par )
	if par == nil then
		return false
	end
    if not type( par ) == 'string' then
        return false
    end
    i, j = string.find(par, "region:")
    if (i >= 0 and j >= 0 and j < string.len(par)) then
    	return true
	end
end

-- d/m/s format to decimal
local function dmstodec()
end

-- decimal format to d/m/s
local function dectodms()
end

-- 22.90361°S, 43.20972°W
local function makestringdec(lat, lon)
	local ns ="N"
	local we ="W"
	local _lat = tonumber(lat)
	local _lon = tonumber(lon)	
	if (_lat < 0) then
		ns = "S"
	end
	if (_lon < 0) then
		we = "E"
	end
	return mw.ustring.format( '%s°%s, %s°%s', lat, ns, lon, we )
end

-- combine parameters to single displayable string
-- 22°54′13″S, 43°12′35″W
local function makestringdms(listItems, count)
	if (count >= 8) then
		return mw.ustring.format( '%s°%s′%s″%s, %s°%s′%s″%s', 
			listItems[1], listItems[2], listItems[3], listItems[4], 
			listItems[5], listItems[6], listItems[7], listItems[8] )
	end
	if (count >= 6) then
		return mw.ustring.format( '%s°%s′%s, %s°%s′%s', 
			listItems[1], listItems[2], listItems[3], 
			listItems[4], listItems[5], listItems[6] )
	end
	if (count >= 4) then
		return mw.ustring.format( '%s°%s, %s°%s', 
			listItems[1], listItems[2], 
			listItems[3], listItems[4] )
	end
	if (count >= 2) then
		return makestringdec(listItems[1], listItems[2])
	end
end

-- https://geohack.toolforge.org/geohack.php?language=fi&pagename=Malline:Coord&params=60_10_10_N_24_57_09_E_region:FI-18_type:landmark&title=Senaatintori
local function makegeohacklink(listItems, name, count)
	local link = 'https://geohack.toolforge.org/geohack.php?language=fi&pagename=Malline:Coord&params='

	-- TODO: if coordinates are given in decimal format, convert to dms for use in the link?

	local k = 1
	while (k <= #listItems and k <= count) do
		link = link .. listItems[k]
		k = k + 1
		if (k <= count) then
			link = link .. "_"
		end
	end
	if (string.len(name) > 0) then
		link = link .. "&title=" .. name
	end
	return link
end

-- tags for displaying in title
local function maketitle(coordstring)
	-- does not work on a user-page?
	return '<span id="coordinatespan" class="plainlinksneverexpand">Koordinaatit: ' .. coordstring ..'</span>'
end

-- title,inline,rivi,otsikko,t,it,i,ti,o,ro,r,or,primary
local function parsedisplay(dispstring)
	local i = 0
	local j = 0
	local len = string.len(dispstring)
	while (i < len) do
		i = string.find(dispstring, ",", i)
		if (i == nil) then
			i = len
		end
		if (i == j) then
			break
		end
		local par = ''
		if (i < len) then
			par = string.sub(dispstring, j, i-1)
		else
			par = string.sub(dispstring, j, len)
		end
		-- check par match 
		if (par == "primary") then
			g_displaytitle = true
		end
		if (par == "title" or par == "otsikko" or par == "t" or par == "o") then
			g_displaytitle = true
		end
		if (par == "inline" or par == "rivi" or par == "i" or par == "r") then
			g_displayinline = true
		end
		if (par == "it" or par == "ti" or par == "ro" or par == "or") then
			g_displaytitle = true
			g_displayinline = true
		end
		i = i + 1
		j = i
	end
end

local function buildCoords( args )
    -- Get the list items.
    local listItems = args
    if #listItems == 0 then
        return '<span class="error">Parametrit puuttuvat</span>'
    end

	-- parameters can have various combinations without named fields:
	-- dd|mm|ss.s|N/S|ddd|mm|ss.s|E/W|
	-- dd|mm.m|N/S|ddd|mm.m|E/W|
	-- dd.d|N/S|ddd.d|E/W|
	-- dd.d|ddd.d|
	--
	-- by number of parameters, validate that parameters are of correct type 
	-- and within sensible range

	local formatting = args['muoto'] or args['format'] or '' -- dms/dec
	local name = args['nimi'] or args['name'] or ''
	local notes = args['huom'] or args['notes'] or ''
	local display = args['näyttö'] or args['display'] or '' -- title,inline,rivi,otsikko,t,it,i,ti,o,ro,r,or,primary

	parsedisplay(display)

	
	-- TODO: there may be two or more extra fields after the actual coordinates.. detect that too
	-- try these in descending order
	local isvalid = false
	if (#listItems >= 8) then
		isvalid = isvalid8(listItems)
	end
	if (#listItems >= 6 and isvalid == false) then
		isvalid = isvalid6(listItems)
	end
	if (#listItems >= 4 and isvalid == false) then
		isvalid = isvalid4(listItems)
	end
	if (#listItems >= 2 and isvalid == false) then
		isvalid = isvalid2(listItems)
	end

	if (isvalid == false) then
		return '<span class="error">Virheelliset koordinaatit</span>[[Luokka:Virheellisiä koordinaatteja sisältävät sivut]]'
	end
	
	local coords = makestringdms(listItems, #listItems)
	local link = makegeohacklink(listItems, name, #listItems)

	local coordstring = '[' .. link .. ' ' .. coords ..']'
	if (g_displaytitle == true and g_displayinline == true) then
		return coordstring .. maketitle(coordstring)
	end
	if (g_displaytitle == true) then
		return maketitle(coordstring)
	end
	if (g_displayinline == true) then
		return coordstring
	end
	-- no known display format
	return ""
end

function p.main( frame )
    local origArgs
    if frame == mw.getCurrentFrame() then
        origArgs = frame:getParent().args
        for k, v in pairs( frame.args ) do
            origArgs = frame.args
            break
        end
    else
        origArgs = frame
    end
    
    local args = {}
    for k, v in pairs( origArgs ) do
        if type( k ) == 'number' or v ~= '' then
            args[ k ] = v
        end
    end
    return buildCoords( args )
end

return p