Modulo:Provejo2

El Vikipedio, la libera enciklopedio

Dokumentado por ĉi tiu modulo povas esti kreata ĉe Modulo:Provejo2/dokumentado

--[[ Coordinates 2014-02-04
This module is intended to replace the functionality of {{Coord}} and related
templates.  It provides several methods, including

{{#Invoke:Coordinates | coord }} : General function formatting and displaying
coordinate values.

{{#Invoke:Coordinates | dec2dms }} : Simple function for converting decimal
degree values to DMS format.

{{#Invoke:Coordinates | dms2dec }} : Simple function for converting DMS format
to decimal degree format.

{{#Invoke:Coordinates | dec2ch1903 }} : Simple function for converting decimal
degree values to CH1903 format.

{{#Invoke:Coordinates | dms2ch1903 }} : Simple function for converting DMS format
to CH1903 format.

{{#Invoke:Coordinates | dec2utm }} : Simple function for converting decimal
degree values to UTM format.

{{#Invoke:Coordinates | dms2utm }} : Simple function for converting DMS format
to UTM format.

{{#Invoke:Coordinates | link }} : Export the link used to reach the tools

]]

-- global variables
globalFrame = nil

coordinates = {};

-- imports other modules
math_mod = require( "Module:Math" );
-- configuration for the analylis of parameters
local cfg = mw.loadData("Modulo:Coordinates/Configuration")

-- defines variables
currentTitle = mw.title.getCurrentTitle()
namespace   = currentTitle.namespace
page_name = mw.uri.encode( currentTitle.prefixedText, 'WIKI' );
lang=mw.language.getContentLanguage():getCode();
coord_link = '//tools.wmflabs.org/geohack/geohack.php?pagename=' .. page_name .. '&language=' .. lang .. '&params='
coord_tooltip = 'Mapoj, elĉielaj bildoj kaj aliaj datumoj por '
errorcat = '[[Kategorio:Artikoloj kun problemo de koordinatoj]]'

-------------------------------------------------------------------------------
--         functions for display the resulting coordinates
-------------------------------------------------------------------------------
--[[ Helper function, replacement for {{coord/display/title}} ]]
function displaytitle (s, notes, globe)
    if mw.ustring.lower(mw.ustring.sub(s,1,5)) == "(div)" then
        s = mw.ustring.sub(s,6);
        tag = "div"
    end
    if mw.ustring.lower(mw.ustring.sub(s,1,6)) == "(span)" then
        s = mw.ustring.sub(s,7);
        tag = "span"
    end
    local l = "[[Geografia koordinata sistemo|Koordinatoj]]: " .. s
    -- local l = "" .. s
    local extracat = ""
    
    if mw.title.getCurrentTitle().nsText == "" then
        if globe~= nil and globe~= "earth" then
            if globe == "moon" then
                extracat = "[[Kategorio:Artikoloj geolokigitaj sur la Luno]]";                
            elseif globe == "mars" then
                extracat = "[[Kategorio:Artikoloj geolokigitaj sur Marso]]";
            else
                extracat = "[[Kategorio:Artikoloj geolokigitaj ekstertere]]";
            end            
        else
            extracat = "[[Kategorio:Artikoloj geolokigitaj sur Tero]]";
        end
    end
    if tag ~= "" and tag ~= nil then 
    co = '<' .. tag .. ' id="coordinates">' .. l .. notes .. '</' .. tag .. '>';        
    else
    co = '<span id="coordinates">' .. l .. notes .. '</span>';
    end
    if tag == "div" then
        return co .. extracat;
    else 
        return '<span style="font-size: small;">' .. co .. '</span>' .. extracat;
    end
end

--[[ Helper function, replacement for {{CoordinateNOx}}, but its text is elsewhere ]]
function displaytitle2 (s, format)
    --local l = "[[Geographic coordinate system|Coordinates]]: " .. s
    local l = "" .. s
    if format ~= "" and format ~= nil then
        co = '<span id="coordinates" style="' .. format .. '">' .. l .. '</span>';
    else co = '<span id="coordinates">' .. l .. '</span>';
    end
    return '<span style="font-size: small;">' .. co .. '</span>'
end  

--[[ Helper function, Replacement for {{coord/display/inline}} ]]
function displayinline (s, notes)
    return s .. notes    
end

--[[ Helper function, for {{Coordinate}}, if a map is used ]]
function displaymap (map, lat, long, title, text, float, position, large, maptype, shadow, region, type1, dim, globe, name, alt, display)
	
	if title ~= "" and title ~= nil then
		t = title
	else
		t = 'Lokigo de ' .. text .. ' en ' .. map
	end	
	local frame = mw.getCurrentFrame()
	return
	        frame:expandTemplate{
            title = 'situo sur mapo',
            args = {
                map,
                Lat = lat,
                Lon = long,
                region = region,
                type = type1,
                dim = dim,
                globe = globe,
                name = name,
                Marko = 'Red pog.svg',
                Marko_ampl = '8',
                Floso = float or 'center',
                Largho = large,
                Mapospeco = maptype,
                Titolo = t,
                Alia_mapo  =  alt,
                Bordo  = '0',
                Teksto = text,                
                Teksto_loko  = position,
                senombre = shadow, 
                montrukoordinatojn = display or 'ne'
          }
      }
end	

------------------------------------------------------------------------------
--         Parsing parameters
------------------------------------------------------------------------------
--[[
    Normalize cardinal direction
    @param string cardDir Cardinal direction, English or Esperanto
    @return string
--]]
local function normCardDir(cardDir)
	local cardDir = mw.text.trim(cardDir);  --remove whitespace
    if cardDir:upper() == 'N' or cardDir:upper() == "NORDO" then return 'N' end
    if cardDir:upper()  == 'S' or cardDir:upper() == "SUDO" then return 'S' end
    if cardDir:upper()  == 'E' or cardDir:upper() == "O" or cardDir:upper() == "ORIENTO" then return 'E' end
    if cardDir:upper()  == 'W' or cardDir:upper() == "U" or cardDir:upper() == "OKCIDENTO" then return 'W' end
    return cardDir
end

--[[ Helper function, used in detecting DMS formatting ]]
local dmsTest = function(first, second)
    first = normCardDir(first or '')
    second = normCardDir(second or '')
    local concatenated = first:upper() .. second:upper()
 
    if concatenated == "NE" or concatenated == "NW" or concatenated == "SE" or concatenated == "SW" or
        concatenated == "EN" or concatenated == "WN" or concatenated == "ES" or concatenated == "WS" then
        return true
    end
    return false
end

-- Con le richieste "dm" e "dms" verifica se ci sono
-- parametri lasciati vuoti in modo valido.
-- Ritorna il tipo di richiesta dopo la eventuale semplificazione.
local function paramsEmpty(args, reqFormat)
	local errors = {}
    if reqFormat == "dms" then
        -- {{coord|1|2||N|5|6||E}} valido
        if args[3] == "" and args[7] == "" then
            table.remove(args, 7)
            table.remove(args, 3)
            reqFormat = "dm"
        -- {{coord|1|2|3|N|5|6||E}} non valido
        elseif args[3] == "" or args[7] == "" then
            table.insert( errors, { 'paramsEmpty', 'Latitudo kaj longitudo havas malsaman precizecon.' } );
            -- error("* lat e long hanno diversa precisione")
        -- {{coord|1||3|N|5||7|E}} valido
        elseif args[2] == "" and args[6] == "" then
            args[2], args[6] = 0, 0
        -- {{coord|1|2|3|N|5||7|E}} non valido
        elseif args[2] == "" or args[6] == "" then
            table.insert( errors, { 'paramsEmpty', 'Latitudo kaj longitudo havas malsaman precizecon.' } );
            -- error("* lat e long hanno diversa precisione")
        end
    end
 
    if reqFormat == "dm" then
        -- {{coord|1||N|4||E}} valido
        if args[2] == "" and args[5] == "" then
            table.remove(args, 5)
            table.remove(args, 2)
            reqFormat = "d"
        -- {{coord|1|2|N|4||E}} non valido
    elseif args[2] == "" or args[5] == "" then
    	    table.insert( errors, { 'paramsEmpty', 'Latitudo kaj longitudo havas malsaman precizecon.' } );
            -- error("* lat e long hanno diversa precisione")
        end
    end
 
    return args, reqFormat
end

--[[
parseDec

Transforms decimal format latitude and longitude into the a
structure to be used in displaying coordinates
]]
function parseDec( lat, long, format )
    local coordinateSpec = {}
    local errors = {}
    
    if long == "" or long == nil then
        return nil, {{"parseDec", "Mankas longitudo"}}
    end
    
    errors = validate( lat, nil, nil, long, nil, nil, 'parseDec', false );    
    coordinateSpec["dec-lat"]  = lat;
    coordinateSpec["dec-long"] = long;

    local mode = coordinates.determineMode( lat, long );
    coordinateSpec["dms-lat"]  = convert_dec2dms( lat, "N", "S", mode)  -- {{coord/dec2dms|{{{1}}}|N|S|{{coord/prec dec|{{{1}}}|{{{2}}}}}}}
    coordinateSpec["dms-long"] = convert_dec2dms( long, "O", "U", mode)  -- {{coord/dec2dms|{{{2}}}|E|W|{{coord/prec dec|{{{1}}}|{{{2}}}}}}}  
    coordinateSpec["dmslong-lat"]  = convert_dec2dms( lat, "Nordo", "Sudo", mode)  -- {{coord/dec2dms|{{{1}}}|N|S|{{coord/prec dec|{{{1}}}|{{{2}}}}}}}
    coordinateSpec["dmslong-long"] = convert_dec2dms( long, "Oriento", "Okcidento", mode)  -- {{coord/dec2dms|{{{2}}}|E|W|{{coord/prec dec|{{{1}}}|{{{2}}}}}}}      
    --added formats
    coordinateSpec['ch1903-x'], coordinateSpec['ch1903-y'] = convert_dec2ch1903("",lat,long,0) -- for Swiss coordinates
    coordinateSpec['zonenumber'], coordinateSpec['zonedir'], coordinateSpec['zone'], coordinateSpec['utm-x'], coordinateSpec['utm-y'] = convert_dec2utm("",lat,long,0) -- for UTM coordinates
    coordinateSpec["dm-lat"]  = convert_dec2dms( lat, "N", "S", "dm")  
    coordinateSpec["dm-long"] = convert_dec2dms( long, "O", "U", "dm") 
    coordinateSpec["d-lat"]  = convert_dec2dms( lat, "N", "S", "d")  
    coordinateSpec["d-long"] = convert_dec2dms( long, "O", "U", "d")     
 
    
    if format ~= "" then
        coordinateSpec.default = format
    else
        coordinateSpec.default = "dec"
    end

    return coordinateSpec, errors
end

--[[ Helper function, handle optional args. ]]
function optionalArg(arg, suplement)
    if arg ~= nil and arg ~= "" then
        return arg .. suplement
    end
    return ""
end

--[[
parseDMS

Transforms degrees, minutes, seconds format latitude and longitude 
into the a structure to be used in displaying coordinates
]]
function parseDMS( lat_d, lat_m, lat_s, lat_f, long_d, long_m, long_s, long_f, format )
    lat_f = normCardDir(lat_f):upper()
    long_f = normCardDir(long_f):upper()	
    local coordinateSpec = {}
    local errors = {}
    
    local lat_flong = 'Nordo';
    if lat_f == 'S' then
        lat_flong = 'Sudo';
    end
    local long_flong = 'Okcidento';
    if long_f == 'E' or long_f == 'O' then
        long_flong = 'Oriento';
    end
    
    
    -- Check if specified backward
    if lat_f == 'E' or lat_f == "O" or lat_f == 'W' or lat_f == 'U' then
        local t_d, t_m, t_s, t_f;
        t_d = lat_d;
        t_m = lat_m;
        t_s = lat_s;
        t_f = lat_f;
        lat_d = long_d;
        lat_m = long_m;
        lat_s = long_s;
        lat_f = long_f;
        long_d = t_d;
        long_m = t_m;
        long_s = t_s;
        long_f = t_f;
    end    
    
    errors = validate( lat_d, lat_m, lat_s, long_d, long_m, long_s, 'parseDMS', true );
    if long_d == nil or long_d == "" then
        table.insert(errors, {"parseDMS", "Mankas longitudo" })
    end
    
    if lat_m == nil and lat_s == nil and long_m == nil and long_s == nil and #errors == 0 then 
        if math_mod._precision( lat_d ) > 0 or math_mod._precision( long_d ) > 0 then
            if lat_f:upper() == 'S' then 
                lat_d = '-' .. lat_d;
            end
            if long_f:upper() == 'W' or long_f:upper() == 'U' then 
                long_d = '-' .. long_d;
            end     
            
            return parseDec( lat_d, long_d, format );
        end        
    end   
    
    if long_f == "W" then
        long_f = "U"        -- montri direkton, escepte de coordinateSpec["param"]
    end
    if long_f == "E" then
        long_f = "O"        -- montri direkton, escepte de coordinateSpec["param"]
    end    
    coordinateSpec["dms-lat"]  = lat_d.."°&nbsp;"..optionalArg(lat_m,"′&nbsp;") .. optionalArg(lat_s,"″&nbsp;") .. lat_f
    coordinateSpec["dmslong-lat"]  = lat_d.."°&nbsp;"..optionalArg(lat_m,"′&nbsp;") .. optionalArg(lat_s,"″&nbsp;") .. lat_flong
    coordinateSpec["dms-long"] = long_d.."°&nbsp;"..optionalArg(long_m,"′&nbsp;") .. optionalArg(long_s,"″&nbsp;") .. long_f
    coordinateSpec["dmslong-long"] = long_d.."°&nbsp;"..optionalArg(long_m,"′&nbsp;") .. optionalArg(long_s,"″&nbsp;") .. long_flong
    coordinateSpec["dec-lat"]  = convert_dms2dec(lat_f, lat_d, lat_m, lat_s) -- {{coord/dms2dec|{{{4}}}|{{{1}}}|0{{{2}}}|0{{{3}}}}}
    coordinateSpec["dec-long"] = convert_dms2dec(long_f, long_d, long_m, long_s) -- {{coord/dms2dec|{{{8}}}|{{{5}}}|0{{{6}}}|0{{{7}}}}}
    --added formats
    coordinateSpec['ch1903-x'], coordinateSpec['ch1903-y'] = convert_dms2ch1903(lat_f, lat_d, lat_m, lat_s ,long_f, long_d, long_m, long_s) -- for Swiss coordinates
    coordinateSpec['zonenumber'], coordinateSpec['zonedir'], coordinateSpec['zone'], coordinateSpec['utm-x'], coordinateSpec['utm-y'] = convert_dms2utm(lat_f, lat_d, lat_m, lat_s ,long_f, long_d, long_m, long_s) -- for UTM coordinates
    coordinateSpec["dm-lat"]  = lat_d.."°&nbsp;"..optionalArg(lat_m,"′&nbsp;") .. lat_f
    coordinateSpec["dm-long"] = long_d.."°&nbsp;"..optionalArg(long_m,"′&nbsp;") .. long_f
    coordinateSpec["d-lat"]  = lat_d.."°&nbsp;" .. lat_f
    coordinateSpec["d-long"] = long_d.."°&nbsp;" .. long_f    
    
    
    if format ~= "" then
        coordinateSpec.default = format
    else
        coordinateSpec.default = "dms"
    end   

    return coordinateSpec, errors
end

--[[ 
Check the input arguments for coord to determine the kind of data being provided
and then make the necessary processing.
]]
function formatTest(args)
    local result = {}
    local format = ''
    local errors = {}
    local primary = false;
    
    if #args == 0 then
    	error ("* Neniuj koordinatoj estas difinitaj")
    	-- table.insert( errors, { 'formatTest', 'Neniuj koordinatoj estas difinitaj' } );
    	-- return errorReturn( {{'formatTest', 'Neniuj koordinatoj estas difinitaj.' }} )
        -- error("* coordinate non specificate")
    elseif #args == 1 then
        -- no lat logic
        error ("* Mankas latitudo")
        -- table.insert( errors, { 'formatTest', 'Mankas latitudo' } );
        -- return errorReturn( {{"formatTest", "Mankas latitudo"}} )
    elseif args[4] == "" and args[5] == "" and args[6] == "" then
        -- dec logic
        format = 'dec'
    elseif dmsTest(args[4], args[8]) then
        -- dms logic
        args[4] = normCardDir(args[4])
        args[8] = normCardDir(args[8])        	
        format = 'dms'
        if args[10] ~= '' then
            table.insert( errors, { 'formatTest', 'Kromaj neatenditaj parametroj' } );
        end        
    elseif dmsTest(args[3], args[6]) then
        -- dm logic
        args[3] = normCardDir(args[3])
        args[6] = normCardDir(args[6])        	
        format = 'dm'
        if args[8] ~= '' then
            table.insert( errors, { 'formatTest', 'Kromaj neatenditaj parametroj' } );
        end        
    elseif dmsTest(args[2], args[4]) then
        -- d logic
        args[2] = normCardDir(args[2])        
        args[4] = normCardDir(args[4])        	
        format = 'd'
        if args[6] ~= '' then
            table.insert( errors, { 'formatTest', 'Kromaj neatenditaj parametroj' } );
        end        
    else
        -- Error
        -- table.insert( errors, { 'formatTest', 'Nekonata argumenta formato' } );
        error ("* Nekonata argumenta formato")
    end
    
    -- valides the parameters that could be leaved empty
    result, format = paramsEmpty(args, format)
    
    result.name     = args["name"]
    
    -- validazione parametri posizionali
    local r = result
    local param = {}
    currFormat = cfg.params[format]
    globe = args[#args]:match("globe:(%w+)")
    earth = not globe or globe == "earth"
    for k, v in ipairs(r) do
        if currFormat[k] then
            param.type = currFormat[k][1]
            param.name = currFormat[k][2]
            param.min = currFormat[k][3]
            param.max = currFormat[k][4]
            prefix = format .. " formato: " .. param.name .. " (" .. v .. ")"
            -- valida un parametro di tipo numero
            if param.type == "number" then
                num = tonumber(v)
                if num then
                    if earth and num < param.min then
                    	table.insert( errors, { 'formatTest', prefix .. ' < ' .. param.min } );
                        -- dumpError(prefix, " < ", param.min)
                    elseif earth and math.floor(num) > param.max then
                    	table.insert( errors, { 'formatTest', prefix .. ' > ' .. param.max } );
                        -- dumpError(prefix, " > ", param.max)
                    end
                else
                	table.insert( errors, { 'formatTest', prefix .. ' ne estas numero' } );
                    -- dumpError(prefix, " non è un numero")
                end
            -- valida un parametro di tipo stringa
            elseif param.type == "string" then
                if v ~= param.min and v ~= param.max then
                	table.insert( errors, { 'formatTest', prefix .. ' malsamas de ' .. param.min .. " kaj de " .. param.max } );
                    -- dumpError(prefix, " diverso da ", param.min, " e da ", param.max)
                end
            end
        end
    end
    
    local extra_param = {'dim', 'globe', 'scale', 'region', 'source', 'type', 'src'}
    for _, v in ipairs( extra_param ) do
        if (args[v] or '') ~= '' then 
            table.insert( errors, {'formatTest', 'Parametro: "' .. v .. '=" estu "' .. v .. ':"' } );
        end
    end
    
    if #errors > 0 then
    	result = errorPrinter(errors)
    	local cat = ''
        if namespace == 0 then
            cat = errorcat 
        end
        return result .. cat
    end

    --return args, result, format, coordParams, errors
    return result, format    
end

--[[ Helper function, convert the decimal comma to decimal point ]]
function formatPoint(num)
    return mw.ustring.gsub(num, ",", ".")
end

--[[ 
Checks input values to for out of range errors.
]]
function validate( lat_d, lat_m, lat_s, long_d, long_m, long_s, source, strong )
    local errors = {};
    lat_d = tonumber( lat_d ) or 0;
    lat_m = tonumber( lat_m ) or 0;
    lat_s = tonumber( lat_s ) or 0;
    long_d = tonumber( long_d ) or 0;
    long_m = tonumber( long_m ) or 0;
    long_s = tonumber( long_s ) or 0;

    if strong then
        if lat_d < 0 then
            table.insert(errors, {source, "latitudaj gradoj < 0 kun hemisfera flago"})
        end
        if long_d < 0 then
            table.insert(errors, {source, "longitudaj gradoj < 0 kun hemisfera flago"})
        end
        --[[ 
        #coordinates is inconsistent about whether this is an error.  If globe: is
        specified, it won't error on this condition, but otherwise it will.
        
        For not simply disable this check.
        
        if long_d > 180 then
            table.insert(errors, {source, "longitude degrees > 180 with hemisphere flag"})
        end
        ]]
    end    
        
    if lat_d > 90 then
        table.insert(errors, {source, "latitudaj gradoj > 90"})
    end
    if lat_d < -90 then
        table.insert(errors, {source, "latitudaj gradoj < -90"})
    end
    if lat_m >= 60 then
        table.insert(errors, {source, "latitudaj minutoj >= 60"})
    end
    if lat_m < 0 then
        table.insert(errors, {source, "latitudaj minutoj < 0"})
    end
    if lat_s >= 60 then
        table.insert(errors, {source, "latitudaj sekundoj >= 60"})
    end
    if lat_s < 0 then
        table.insert(errors, {source, "latitudaj sekundoj < 0"})
    end
    if long_d >= 360 then
        table.insert(errors, {source, "longitudaj gradoj >= 360"})
    end
    if long_d <= -360 then
        table.insert(errors, {source, "longitudaj gradoj <= -360"})
    end
    if long_m >= 60 then
        table.insert(errors, {source, "longitudaj minutoj >= 60"})
    end
    if long_m < 0 then
        table.insert(errors, {source, "longitudaj minutoj < 0"})
    end
    if long_s >= 60 then
        table.insert(errors, {source, "longitudaj sekundoj >= 60"})
    end
    if long_s < 0 then
        table.insert(errors, {source, "longitudaj sekundoj < 0"})
    end
    
    return errors;
end

------------------------------------------------------------------------------
--           Creating the HTML for the templates
------------------------------------------------------------------------------

--[[
Determine the required CSS class to display coordinates

Usually geo-nondefault is hidden by CSS, unless a user has overridden this for himself
default is the mode as specificied by the user when calling the {{coord}} template
mode is the display mode (dec or dms) that we will need to determine the css class for 
]]
function displayDefault(default, mode)
    if default == "" then
        default = "dec"
    end
    
    if default:sub(1,4) == mode:sub(1,4) or default:sub(1,3) == mode:sub(1,3) then
        return "geo-default"
    else
        return "geo-nondefault"
    end
end

--[[
specPrinter

Output formatter.  Takes the structure generated by either parseDec
or parseDMS and formats it for inclusion on Wikipedia.
]]
function specPrinter(args, coordinateSpec)
    local uriComponents = coordinateSpec["param"]
    if uriComponents == "" then
        -- RETURN error, should never be empty or nil
        return "ERARO param estis malplena"
    end

    if args["name"] ~= "" and args["name"] ~= nil then
        uriComponents = uriComponents .. "&title=" .. mw.uri.encode(coordinateSpec["name"])
    end
    
    local geodmshtml = '<span class="geo-dms" title="' .. coord_tooltip .. coordinateSpec["dms-lat"] .. ' ' ..  coordinateSpec["dms-long"] .. '">'
             .. '<span class="latitudo">' .. coordinateSpec["dms-lat"] .. '</span> '
             .. '<span class="longitudo">' ..coordinateSpec["dms-long"] .. '</span>'
             .. '</span>'
    local geodmhtml = '<span title="' .. coord_tooltip .. coordinateSpec["dm-lat"] .. ' ' ..  coordinateSpec["dm-long"] .. '">'
             .. '<span title="Latitudo">' .. coordinateSpec["dm-lat"] .. '</span> '
             .. '<span title="Longitudo">' ..coordinateSpec["dm-long"] .. '</span>'
             .. '</span>'       
    local geodhtml = '<span title="' .. coord_tooltip .. coordinateSpec["d-lat"] .. ' ' ..  coordinateSpec["d-long"] .. '">'
             .. '<span title="Latitudo">' .. coordinateSpec["d-lat"] .. '</span> '
             .. '<span title="Longitudo">' ..coordinateSpec["d-long"] .. '</span>'
             .. '</span>'               
    local geodmslonghtml = '<span class="geo-dms" title="' .. coord_tooltip .. coordinateSpec["dmslong-lat"] .. ' ' ..  coordinateSpec["dmslong-long"] .. '">'
             .. '<span class="latitudo">' .. coordinateSpec["dmslong-lat"] .. '</span> '
             .. '<span class="longitudo">' ..coordinateSpec["dmslong-long"] .. '</span>'
             .. '</span>'
    local lat = tonumber( coordinateSpec["dec-lat"] ) or 0
    if lat < 0 then
        -- FIXME this breaks the pre-existing precision
        geodeclat = coordinateSpec["dec-lat"]:sub(2) .. " °S"
        --geodeclat = "-" .. coordinateSpec["dec-lat"]:sub(2)
    else
        geodeclat = (coordinateSpec["dec-lat"] or 0) .. " °N"
        --geodeclat = (coordinateSpec["dec-lat"] or 0)
    end

    local long = tonumber( coordinateSpec["dec-long"] ) or 0
    if long < 0 then
        -- FIXME does not handle unicode minus
        geodeclong = coordinateSpec["dec-long"]:sub(2) .. " °U"
        --geodeclong = '-' .. coordinateSpec["dec-long"]:sub(2)
    else
        geodeclong = (coordinateSpec["dec-long"] or 0) .. " °O"
        --geodeclong = (coordinateSpec["dec-long"] or 0)
    end
    
    local geodechtml = '<span class="geo-dec" title="' .. coord_tooltip .. coordinateSpec["dec-lat"] .. ' ' ..  coordinateSpec["dec-long"] .. '">'
             .. geodeclat .. ', '
             .. geodeclong
             .. '</span>'

    local geonumhtml = '<span class="geo">'
             .. coordinateSpec["dec-lat"] .. '; '
             .. coordinateSpec["dec-long"]
             .. '</span>'


    local inner;
    if coordinateSpec["default"] == "dms" then
        inner = '<span class="' .. displayDefault(coordinateSpec["default"], "dms" ) .. '">' .. geodmshtml .. '</span>'
                    .. '<span class="geo-multi-punct">&#xfeff; / &#xfeff;</span>'
                    .. '<span class="' .. displayDefault(coordinateSpec["default"], "dec" ) .. '">';
    elseif coordinateSpec["default"] == "dm" then
        inner = '<span class="' .. displayDefault(coordinateSpec["default"], "dm" ) .. '">' .. geodmhtml .. '</span>'
                    .. '<span class="geo-multi-punct">&#xfeff; / &#xfeff;</span>'
                    .. '<span class="' .. displayDefault(coordinateSpec["default"], "dec" ) .. '">';
    elseif coordinateSpec["default"] == "d" then
        inner = '<span class="' .. displayDefault(coordinateSpec["default"], "d" ) .. '">' .. geodhtml .. '</span>'
                    .. '<span class="geo-multi-punct">&#xfeff; / &#xfeff;</span>'
                    .. '<span class="' .. displayDefault(coordinateSpec["default"], "dec" ) .. '">';                    
    else
        inner = '<span class="' .. displayDefault(coordinateSpec["default"], "dms long" ) .. '">' .. geodmslonghtml .. '</span>'
                    .. '<span class="geo-multi-punct">&#xfeff; / &#xfeff;</span>'
                    .. '<span class="' .. displayDefault(coordinateSpec["default"], "dec" ) .. '">';        
    end


    if args["name"] == "" or args["name"] == nil then
        inner = inner .. geodechtml 
                .. '<span style="display:none">&#xfeff; / ' .. geonumhtml .. '</span></span>'
    else
        inner = inner .. '<span class="vcard">' .. geodechtml 
                .. '<span style="display:none">&#xfeff; / ' .. geonumhtml .. '</span>'
                .. '<span style="display:none">&#xfeff; (<span class="fn org">'
                .. args["name"] .. '</span>)</span></span></span>'
    end

    if args["link"] == "jes" or args["link"] == "yes" or args["link"] == "" or args["link"] == nil then
    return '<span class="plainlinks nourlexpansion">' .. 
        '[' .. coord_link .. uriComponents .. ' ' .. inner .. ']' .. '</span>'
    elseif args["link"] == "ne" or args["link"] == "no" then
    return '<span class="plainlinks nourlexpansion">' .. inner .. '</span>'    	
    end    
end

--[[ geodataPrinter
returns the {{#coordinates: with latitude and longitude in the decimal format
]]
function geodataPrinter(args, coordinateSpec)
    --cf http://www.mediawiki.org/wiki/Extension:GeoData
    local geodata = ''
    local r,s,t=string.match (coordinateSpec["param"],'(.*)_(E?W?)_(.*)')
    local globe,globend=string.match (coordinateSpec["param"],'_globe:(.*)(_*)')
    --Désactivé pour les astres à cause de problèmes de longitudes planétocentriques/planétographiques
    if globe == nil or globe == 'earth' then
    	geodata = '{{#coordinates:' .. coordinateSpec["dec-lat"] .. '|' .. coordinateSpec["dec-long"] .. '|primary' 
    	if t == nil or t == '' then
    		geodata = geodata .. '}}'
    	else
    		geodata = geodata .. '|' .. t .. '}}'
  		end
    end
    if args['geodata'] ~= nil then
        return geodata;
    else
    	return ""
    end  
end

--[[
specPrinter2 - for {{Koordinato}} 

Output formatter.  Takes the structure generated by either parseDec
or parseDMS and formats it for inclusion on Wikipedia.
]]
function specPrinter2(args, coordinateSpec)
    local uriComponents = coordinateSpec["param"]
    if uriComponents == "" then
        -- RETURN error, should never be empty or nil
        return "ERARO param estis malplena"
    end

    if args["name"] ~= "" and args["name"] ~= nil then
        uriComponents = uriComponents .. "&title=" .. mw.uri.encode(coordinateSpec["name"])
    end
    
    local geodmshtml = '<span title="' .. coord_tooltip .. coordinateSpec["dms-lat"] .. ' ' ..  coordinateSpec["dms-long"] .. '">'
             .. '<span title="Latitudo">' .. coordinateSpec["dms-lat"] .. '</span> '
             .. '<span title="Longitudo">' ..coordinateSpec["dms-long"] .. '</span>'
             .. '</span>'
    local geodmslonghtml = '<span title="' .. coord_tooltip .. coordinateSpec["dmslong-lat"] .. ' ' ..  coordinateSpec["dmslong-long"] .. '">'
             .. '<span title="Latitudo">' .. coordinateSpec["dmslong-lat"] .. '</span> '
             .. '<span title="Longitudo">' ..coordinateSpec["dmslong-long"] .. '</span>'
             .. '</span>'
    local geodmhtml = '<span title="' .. coord_tooltip .. coordinateSpec["dm-lat"] .. ' ' ..  coordinateSpec["dm-long"] .. '">'
             .. '<span title="Latitudo">' .. coordinateSpec["dm-lat"] .. '</span> '
             .. '<span title="Longitudo">' ..coordinateSpec["dm-long"] .. '</span>'
             .. '</span>'    
    local geodhtml = '<span title="' .. coord_tooltip .. coordinateSpec["d-lat"] .. ' ' ..  coordinateSpec["d-long"] .. '">'
             .. '<span title="Latitudo">' .. coordinateSpec["d-lat"] .. '</span> '
             .. '<span title="Longitudo">' ..coordinateSpec["d-long"] .. '</span>'
             .. '</span>'               
             
    local lat = tonumber( coordinateSpec["dec-lat"] ) or 0
    if lat < 0 then
        -- FIXME this breaks the pre-existing precision
        geodeclat = coordinateSpec["dec-lat"]:sub(2) .. " °S"
        --geodeclat = "-" .. coordinateSpec["dec-lat"]:sub(2)
    else
        geodeclat = (coordinateSpec["dec-lat"] or 0) .. " °N"
        --geodeclat = (coordinateSpec["dec-lat"] or 0)
    end

    local long = tonumber( coordinateSpec["dec-long"] ) or 0
    if long < 0 then
        -- FIXME does not handle unicode minus
        geodeclong = coordinateSpec["dec-long"]:sub(2) .. " °U"
        --geodeclong = '-' .. coordinateSpec["dec-long"]:sub(2)
    else
        geodeclong = (coordinateSpec["dec-long"] or 0) .. " °O"
        --geodeclong = (coordinateSpec["dec-long"] or 0)
    end
    
    local geodechtml = '<span title="' .. coord_tooltip .. coordinateSpec["dec-lat"] .. ' ' ..  coordinateSpec["dec-long"] .. '">'
             .. '<span title="Latitudo">' .. geodeclat .. '</span>' .. ', '
             .. '<span title="Longitudo">' .. geodeclong .. '</span>'
             .. '</span>'

    local geonumhtml = '<span class="geo">'
             .. coordinateSpec["dec-lat"] .. '; '
             .. coordinateSpec["dec-long"]
             .. '</span>'
             
    --<span title="Svislandaj landaj koordinatoj">CH1903:&nbsp;</span>
    --<span title="y easting">562330</span>&nbsp;/&nbsp;<span title="x northing">124404</span>
    if coordinateSpec['ch1903-x'] ~= nil and coordinateSpec['ch1903-y'] ~= nil then
    geoch1903html = '<span title="Svislandaj landaj koordinatoj">CH1903:&nbsp;</span>'
        .. '<span title="y easting">' .. coordinateSpec['ch1903-y'] .. '</span>&nbsp;/&nbsp;'        
        .. '<span title="x northing">' .. coordinateSpec ['ch1903-x'] .. '</span>' 
        ch1903 = "yes"
    end    
    
    --UTM format
    if coordinateSpec['utm-x'] ~= nil and coordinateSpec['utm-y'] ~= nil then
    geoutmhtml = '<span title="Universal Transverse Mercator, baziĝanta sur WGS84">UTM:&nbsp;</span>'
        .. 'Zono&nbsp;<span title="Zononumero">' .. coordinateSpec['zonenumber'] .. '</span>'
        .. '<span title="Zonobendo, ' .. coordinateSpec['zonedir'] .. ' de la ekvatoro">' .. coordinateSpec['zone'] .. '</span>, '
        .. '<span title="easting">' .. coordinateSpec['utm-y'] .. '</span>&nbsp;/&nbsp;'        
        .. '<span title="northing">' .. coordinateSpec['utm-x'] .. '</span>' 
        utm = "yes"
    end    
    
    local inner;
        
    if coordinateSpec["default"] == "dms" then
        inner = geodmshtml 
    elseif coordinateSpec["default"] == "dms long" then
        inner = geodmslonghtml 
    elseif coordinateSpec["default"] == "dm" then
        inner = geodmhtml    
    elseif coordinateSpec["default"] == "d" then
        inner = geodhtml            
    elseif coordinateSpec["default"] == "ch1903" and ch1903 == "yes" then
        inner = geoch1903html
    elseif coordinateSpec["default"] == "utm" and utm == "yes" then
        inner = geoutmhtml        
    else inner = geodechtml 
    end

    local id = " "
    local test = ""
       
    if args['text'] == "yes" then
    -- creates a text for id, if it used in the text, not in the title       
        if args["name"] ~= "" and args["name"] ~= nil then
        id = ' id="' .. args['name'] .. '" '    
        else id = ' id="text_coordinates" '
        end                
        -- for microformats according to {{Koordinato}}
        micro = '<span class="geo microformat"><span class="latitude">' .. coordinateSpec["dec-lat"] .. '</span>'
        micro = micro .. '<span class="longitude">' .. coordinateSpec["dec-long"] .. '</span><span class="elevation"></span></span>'
        --sortkey has to be added only, if display is "inline"
        --replacement for {{CoordinateSort}}
        if args['sortkey'] ~= "" and args['sortkey'] ~= nil then
            local k = args['sortkey']             
            local z = 500.0000005
            local h
            key = '<span style="display:none">!' 
                k = mw.ustring.upper(k) -- capitalize 
                if k == "EW" or k == "LONG" then 
                   h = math_mod._round(z + long, 6) .. math_mod._round(z + lat, 6)
                   key = key .. h
                else 
                   h = math_mod._round(z + lat, 6) .. math_mod._round(z + long, 6)
                   key = key .. h
                end     
            key = key .. '</span>'
        else key = ""    
        end
        if args['format'] ~= "" and args['format'] ~= nil then
        -- create first format
               local format = args['format']:lower()
               if format == "dms" then
                    f = geodmshtml 
               elseif format == "dms long" then
                    f = geodmslonghtml 
               elseif format == "ch1903" and ch1903 == "yes" then
                    f = geoch1903html
               elseif format == "utm" and utm == "yes" then
                    f = geoutmhtml                    
               else f = geodechtml 
               end
               test = "" --"formato: " .. args['format']
        else f = ""   
        	test = ""
        end 
        if args['format2'] ~= "" and args['format2'] ~= nil then
        -- create second format
               local format2 = args['format2']:lower()
               if format2 == "dms" then
                    f2 = geodmshtml 
               elseif format2 == "dms long" then
                    f2 = geodmslonghtml 
               elseif format2 == "ch1903" and ch1903 == "yes" then
                    f2 = geoch1903html
               elseif format2 == "utm" and utm == "yes" then
                    f2 = geoutmhtml                    
               else f2 = geodechtml 
               end
               -- f2 = ' ( ' .. f2 .. ' ) '
        else f2 = ""   
        end    
        if args['format3'] ~= "" and args['format3'] ~= nil then
        -- create third format
               local format3 = args['format3']:lower()
               if format3 == "dms" then
                    f3 = geodmshtml 
               elseif format3 == "dms long" then
                    f3 = geodmslonghtml 
               elseif format3 == "ch1903" and ch1903 == "yes" then
                    f3 = geoch1903html
               elseif format3 == "utm" and utm == "yes" then
                    f2 = geoutmhtml                       
               else f3 = geodechtml 
               end
               -- f3 = ' ( ' .. f3 .. ' ) '
        else f3 = ""                
        end        
        if args['format4'] ~= "" and args['format4'] ~= nil then
        -- create fourth format
               local format4 = args['format4']:lower()
               if format4 == "dms" then
                    f4 = geodmshtml 
               elseif format4 == "dms long" then
                    f4 = geodmslonghtml 
               elseif format4 == "ch1903" and ch1903 == "yes" then
                    f4 = geoch1903html
               elseif format4 == "utm" and utm == "yes" then
                    f2 = geoutmhtml                       
               else f4 = geodechtml 
               end
               -- f4 = ' ( ' .. f4 .. ' ) '
        else f4 = ""    
        end    
    else     
        micro = '<div class="geo microformat"><span class="latitude">' .. coordinateSpec["dec-lat"] .. '</span>'
        micro = micro .. '<span class="longitude">' .. coordinateSpec["dec-long"] .. '</span><span class="elevation"></span></div>'
        key = ""
        f2 = ""
        f3 = ""
        f4 = ""
    end   
    if args['article'] == "yes" then
        if args['formatitle'] ~= "" and args['formatitle'] ~= nil then
        -- create first format
               local formatitle = args['formatitle']:lower()
               f = geodmshtml 
               test = "" -- "<br />titola formato: " .. args['formatitle'] .. "<br />"
        else f = ""   
        	test = ""
        end      	
        if args['formatitle2'] ~= "" and args['formatitle2'] ~= nil then
        -- create second format
               local formatitle2 = args['formatitle2']:lower()
        --       if formatitle2 == "dms" then
        --            ft2 = geodmshtml 
        --       elseif formatitle2 == "dms long" then
        --            ft2 = geodmslonghtml 
        --       elseif formatitle2 == "ch1903" and ch1903 == "yes" then
               if formatitle2 == "ch1903" and ch1903 == "yes" then
                    ft2 = geoch1903html
               else ft2 = geodechtml 
               end
               -- ft2 = ' ( ' .. ft2 .. ' ) '
        else ft2 = ""   
        end        
    end    
    
    -- add a clip before and after the added formats
    if args['second'] == "yes" then
        if ft2 ~= "" and ft2 ~= nil then
        otherformat = ' (' .. ft2 .. ')'
        else otherformat = ''
        end
    else
        if (f2 ~= "" and f2 ~= nil) or (f3 ~= "" and f3 ~= nil) or (f4 ~= "" and f4 ~= nil) then
        if f2 ~= "" and f2 ~= nil and f3 ~= "" and f3 ~= nil then 
            f2f3 = ' ; '
        else f2f3 = ""    
        end
        if f3 ~= "" and f3 ~= nil and f4 ~= "" and f4 ~= nil then 
            f3f4 = ' ; '
        else f3f4 = ""    
        end        
        otherformat = ' (' .. f2 .. f2f3 .. f3 .. f3f4 .. f4 .. ')'
        else otherformat = ''    
        end
    end 
    
    -- a little trick for return the microformats only
    if args['micro'] == "yes" then
       return micro
    end    

    -- analyzes the parameter "word", if it a has a value for certain symbol
    if args['word'] ~= "" and args['word'] ~= nil then
        local word = args['word']
        upperword = string.upper(word)
        --ICON0 and ICON1
        if upperword == "ICON0" then
            word = "⊙"
        elseif upperword == "ICON" then
            word = "⦁"    
        elseif upperword == "ICON1" then
            word = "<sup>▼</sup>"
        elseif upperword == "ICON2" then
            word = "[[Dosiero:Erioll world.svg|15px|link=|loko]]"
        end
        if args['name'] ~= "" and args['name'] ~= nil then
            word = '<span title="' .. args['name'] .. '">' .. word .. '</span>'
        else
            word = '<span>' .. word .. '</span>'
        end
        return key .. '<span' .. id .. 'class="plainlinks nourlexpansion">' .. 
        '[' .. coord_link .. uriComponents .. ' ' .. word .. ']' .. '</span>'
    else
       return key .. '<span' .. id .. 'class="plainlinks nourlexpansion">' .. 
        '[' .. coord_link .. uriComponents .. ' ' .. f .. otherformat .. ']' .. test .. '</span>' 
    end
end

--[[ catPrinter
Outputs categories
]]
function catPrinter(args, coordinateSpec)
	
	local lat = tonumber( coordinateSpec["dec-lat"] ) or 0
    if lat < 0 then
        catlat    = coordinateSpec["dec-lat"]:sub(2) 
        catdirlat = "° S"
    else
        catlat    = (coordinateSpec["dec-lat"] or 0) 
        catdirlat = "° N"
    end

    local long = tonumber( coordinateSpec["dec-long"] ) or 0
    if long < 0 then
        catlong    = coordinateSpec["dec-long"]:sub(2) 
        catdirlong = "° U"
    else
        catlong    = (coordinateSpec["dec-long"] or 0) 
        catdirlong = "° E" -- O estus pli taŭga, se por okcidento estas U
    end
	
    -- it creates coding for categories, if the paramter "category" is used. after that returns it
    if args['category'] =="jes" or args['category'] =="yes" then
        -- category scheme from {{Ŝablono:Koord/kategorioj}}
        local cat =""
        catlong = math.floor (catlong) -- catlong % 10000
        catlat = math.floor (catlat) -- catlat % 10000
        if catlong == 180 then cat= "[[Kategorio:179° U]][[Kategorio:179° E]]"
        else cat ="[[Kategorio:" .. catlong .. catdirlong .. "]]"  
        end
        cat = cat .. "[[Kategorio:" .. catlat .. catdirlat .. "]]"
        return cat        
    elseif args['category'] == "ne" or args['category'] == "no" then
        cat = "[[Kategorio:Artikolo kun koordinatoj, sed sen koordinataj ligiloj]]" 
        return cat
    end
end	 --end catPrinter()

--[[ mapPrinter - returns parameters for the map with a little mark for the local position ]]
function mapPrinter(args, coordinateSpec)
	if args["name"] ~= "" and args["name"] ~= nil then
        name = args["name"]
    else 
    	name = page_name
    end
	-- coordinates
	local lat = tonumber( coordinateSpec["dec-lat"] ) or 0
    local long = tonumber( coordinateSpec["dec-long"] ) or 0
    -- analize of the params in the link
    local region = args['mapr']
    local type1 = args['mapt']
    local dim = args['mapd']
    local globe = args['mapg']
    local pop = args['mapp']
    local elevation = args['mape']
    if region ~= "" and region ~= nil then
    	-- use the first region value before the first / only
    	local r=mw.text.split( region, '/' )
    	if(#r>1) then 
            r1 = r[1]
        end
    end
    local map = 'Tero'       -- this has to be changed after some tests
    local title = page_name  -- this has to be changed after some tests
    local text = page_name   -- this has to be changed after some tests
    local float = args['float']
    local position = args['position']
    local large = args['large']
    local maptype = args['maptype']
    local shadow = args['shadow']
    local mapparam = ""       -- this has to be changed after some tests
    local alt = args['alt'] -- alternative map
    return displaymap(map, lat, long, title, text, float, position, large, maptype, shadow, region, type1, dim, globe, name, alt) 
end	

------------------------------------------------------------------------------
--     Error handling
------------------------------------------------------------------------------

--[[
Returns any error messages generated for display
]]
function errorReturn(errors)
    return nil, nil, nil, errors
end

--[[
Formats any error messages generated for display
]]
function errorPrinter(errors)
    local result = ""
    for _,v in ipairs(errors) do
        local errorHTML = '<strong class="error">Koordinatoj: ' .. v[2] .. '</strong>'
        result = result .. errorHTML .. "<br />"
    end
    return result
end

------------------------------------------------------------------------------
--    Converting functions
------------------------------------------------------------------------------

--[[ 
Helper function, convert decimal latitude or longitude to 
degrees, minutes, and seconds format based on the specified precision.  
]]
function convert_dec2dms(coordinate, firstPostfix, secondPostfix, precision)
    local coord = tonumber(coordinate) or 0
    local postfix
    if coord >= 0 then
        postfix = firstPostfix
    else
        postfix = secondPostfix
    end

    precision = precision:lower();
    if precision == "dms" then
        return convert_dec2dms_dms( math.abs( coord ) ) .. postfix;
    elseif precision == "dm" then
        return convert_dec2dms_dm( math.abs( coord ) ) .. postfix;
    elseif precision == "d" then
        return convert_dec2dms_d( math.abs( coord ) ) .. postfix;
    end
end

--[[ Helper function, convert decimal to degrees ]]
function convert_dec2dms_d(coordinate)
    local d = math_mod._round( coordinate, 0 ) .. "°&nbsp;"
    return d .. ""
end

--[[ Helper function, convert decimal to degrees and minutes ]]
function convert_dec2dms_dm(coordinate)    
    coordinate = math_mod._round( coordinate * 60, 0 );
    local m = coordinate % 60;
    coordinate = math.floor( (coordinate - m) / 60 );
    local d = coordinate % 360 .."°&nbsp;"
    
    return d .. string.format( "%02d′&nbsp;", m )
end

--[[ Helper function, convert decimal to degrees, minutes, and seconds ]]
function convert_dec2dms_dms(coordinate)
    coordinate = math_mod._round( coordinate * 60 * 60, 0 );
    local s = coordinate % 60
    coordinate = math.floor( (coordinate - s) / 60 );
    local m = coordinate % 60
    coordinate = math.floor( (coordinate - m) / 60 );
    local d = coordinate % 360 .."°&nbsp;"

    return d .. string.format( "%02d′&nbsp;", m ) .. string.format( "%02d″&nbsp;", s )
end

--[[
Convert DMS format into a N or E decimal coordinate
]]
function convert_dms2dec(direction, degrees_str, minutes_str, seconds_str)
    local degrees = tonumber(degrees_str) or 0
    local minutes = tonumber(minutes_str) or 0
    local seconds = tonumber(seconds_str) or 0
    
    local factor
    direction = mw.ustring.gsub(direction, '^[ ]*(.-)[ ]*$', '%1');
    if direction == "N" or direction == "E" or direction == "O" then
        factor = 1
    else
        factor = -1
    end
    
    local precision = 0
    if seconds_str ~= nil and seconds_str ~= '' then
        precision = 5 + math.max( math_mod._precision(seconds_str), 0 );
    elseif minutes_str ~= nil and minutes_str ~= '' then
        precision = 3 + math.max( math_mod._precision(minutes_str), 0 );
    else
        precision = math.max( math_mod._precision(degrees_str), 0 );
    end
    
    local decimal = factor * (degrees+(minutes+seconds/60)/60) 
    return string.format( "%." .. precision .. "f", decimal ) -- not tonumber since this whole thing is string based.
end

--[[ Helper function 
  Convert decimal into CH1903 - replacement for {{Coordinate/to CH1903}}
]] 
function convert_dec2ch1903(label,lat,lon,prec)
              local errors = {}
              local b_lbl = (label or "" ) ~= "";
              local n     =  math.floor (tonumber(prec) or 0);
              local lat = tonumber(lat)
              local lon = tonumber(lon)
              if lat == nil or lon == nil then
              	table.insert(errors, {"dec2ch1903", "latitudaj gradoj < 45.7 aŭ > 47.9 aŭ longitudaj gradoj < 5.8 aŭ > 10.6"})
              	return nil, nil, errors;
              end
              if( lat < 45.7 or lat > 47.9 or lon < 5.8 or lon > 10.6 ) then
                 --ErrMsg(ErrCode='OOR', ErrFun='WGS84toCH1903',ErrData="keine")
                 table.insert(errors, {"dec2ch1903", "latitudaj gradoj < 45.7 aŭ > 47.9 aŭ longitudaj gradoj < 5.8 aŭ > 10.6"})
              end
              -- genaue Berechnung, Lua kann sich das leisten
              local phi    = (lat * 3600 - 169028.66 ) /10000;
              local lambda = (lon * 3600 - 26782.5) / 10000;
              local x = 200147.07 + 308807.95 * phi    +  3745.25 * lambda^2 +    76.63 * phi^2 + 119.79 * phi^3 - 194.56 * lambda^2 * phi;
              local y = 600072.37 + 211455.93 * lambda - 10938.51 * lambda * phi - 0.36 * lambda * phi^2 - 44.54 * lambda^3;
              x = (math.floor(x* 10^n + 0.5))/10^n;
              y = (math.floor(y* 10^n + 0.5))/10^n;
              x = math_mod._round( x, 0 )
              y = math_mod._round( y, 0 )
              return x .. "", y .. "", errors;
end

--[[ Helper function 
  Convert dms into CH1903 
]] 
function convert_dms2ch1903(lat_f, lat_d, lat_m, lat_s ,long_f, long_d, long_m, long_s)
            local errors = {}
            local label = ""
            local prec = 0
            local lat = convert_dms2dec(lat_f, lat_d, lat_m, lat_s)
            local lon = convert_dms2dec(long_f, long_d, long_m, long_s)
            local x, y = convert_dec2ch1903(label, lat, lon, prec)
            x = tonumber(x) .. ""
            y = tonumber(y) .. ""
            return x, y, errors
end    

--[[ Helper function - replacement for {{Coordinate/to UTM/Easting}}
   ({{{A}}})
 + ( 1 - ({{{T}}}) + ({{{C}}}) ) * ({{{A}}})^3 / 6
 + ( 5 - 18*({{{T}}}) + ({{{T}}})^2 + 72*({{{C}}}) - 0.39089<!--58e²/(1-e²)-->) * ({{{A}}})^5 / 120
]]
function easting (A,T,C)
    local easting = (A) 
      + ( 1 - (T) + (C) ) * (A)^3 / 6 
      + ( 5 - 18*(T) + (T)^2 + 72*(C) - 0.39089) * (A)^5 / 120
    return easting
end    
--[[ Helper function - replacement for {{Coordinate/to UTM/Northing}}
  ({{{A}}})^2 / 2
+ ( 5 - ({{{T}}}) + 9*({{{C}}}) + 4*({{{C}}})^2 ) * ({{{A}}})^4 / 24
+ ( 61 - 58*({{{T}}}) + ({{{T}}})^2 + 600*({{{C}}}) - 2.22403) * ({{{A}}})^6 / 720
]]
function northing (A,T,C)
    local northing = (A)^2 / 2 + ( 5 - (T) + 9*(C) + 4*(C)^2 ) * (A)^4 / 24 + ( 61 - 58*(T) + (T)^2 + 600*(C) - 2.22403) * (A)^6 / 720
    return northing 
end    
 
--[[ Helper function 
  Convert decimal into UTM - replacement for {{Coordinate/to UTM}}
]] 
function convert_dec2utm(label,lat,lon,prec)
              local errors = {}
              local b_lbl = (label or "" ) ~= "";
              local n     =  math.floor (tonumber(prec) or 0);
              local lat = tonumber(lat)
              local lon = tonumber(lon)
              local zonenumber = math.ceil(lon/6)+30
              if lat == nil or lon == nil then
              	  table.insert(errors, {"dec2utm", "latitudaj aŭ longitudaj gradoj estas ekster la eblaj valoroj."})
              	  return nil, nil, nil, nil, nil, errors;
              end
              if lat < 0 then
                  zonedir = "sude"
              else
                  zonedir = "norde"
              end
              local z = math.floor(lat/8)
              if z == -10 then zone = "C"
              elseif z == -9 then zone = "D"
              elseif z == -8 then zone = "E"
              elseif z == -7 then zone = "F"
              elseif z == -6 then zone = "G"
              elseif z == -5 then zone = "H"
              elseif z == -4 then zone = "J"
              elseif z == -3 then zone = "K"
              elseif z == -2 then zone = "L"
              elseif z == -1 then zone = "M"
              elseif z == 0 then zone = "N"
              elseif z == 1 then zone = "P"
              elseif z == 2 then zone = "Q"
              elseif z == 3 then zone = "R"
              elseif z == 4 then zone = "S"
              elseif z == 5 then zone = "T"
              elseif z == 6 then zone = "U"
              elseif z == 7 then zone = "V"
              elseif z == 8 then zone = "W"
              elseif z == 9 then zone = "X"
              elseif math.abs(lat-78) <= 6 then zone = "X"    
              else table.insert(errors, {"dec2utm", "latitudaj gradoj estas ekster la eblaj valoroj."})      
                  if lat > 0 then
                      if lon > 0 then zone = "B"
                      else zone = "A"  
                      end
                  else 
                      if lon > 0 then zone = "Z"
                      else zone = "Y"
                      end
                  end
              end 
              local k_0 = 0.9996
              local a = 6378137
              local pi = 3.1415926535898
              local A = (lon - math.ceil(lon/6) * 6 + 3)/180*pi * math.cos(lat/180*pi)
              local T = math.tan(lat/180*pi)^2
              local C = 0.0067394968 * math.cos(lat/180*pi)^2
              local y = 500000 + k_0 * a / ( 1 - 0.00669438 * math.sin(lat/180*pi)^2 )^.5 * easting(A,T,C);
              if lat < 0 then 
                  x1 = 1
              else
                  x1 = 0
              end
              local x = x1*10000000 + k_0 * a * (0.9983243 * ( lat/180*pi) - 2.51460708e-3 * math.sin(2 * lat/180*pi) 
                + 2.63904664e-6 * math.sin(4 * lat/180*pi) - 3.41804618e-9 * math.sin(6 * lat/180*pi) 
                + math.tan(lat/180*pi) / ( 1 - 0.00669438 * math.sin(lat/180*pi)^2 )^.5 * (northing(A,T,C) ) ); 
              x = math_mod._round( x, 0 )
              y = math_mod._round( y, 0 )
              return zonenumber .. "", zonedir .. "", zone .. "", x .. "", y .. "", errors;
end

--[[ Helper function 
  Convert dms into UTM 
]] 
function convert_dms2utm(lat_f, lat_d, lat_m, lat_s ,long_f, long_d, long_m, long_s)
            local errors = {}
            local label = ""
            local prec = 0
            local lat = convert_dms2dec(lat_f, lat_d, lat_m, lat_s)
            local lon = convert_dms2dec(long_f, long_d, long_m, long_s)
            local zonenumber, zonedir, zone, x, y = convert_dec2utm(label, lat, lon, prec)
            x = tonumber(x) .. ""
            y = tonumber(y) .. ""
            return zonenumber, zonedir, zone, x, y, errors
end  

------------------------------------------------------------------------------
--     Exported functions
------------------------------------------------------------------------------

--[[
link
 
Simple function to export the coordinates link for other uses.
 
Usage:
	{{ Invoke:Coordinates | link }}
 
]]
function coordinates.link(frame)
	return coord_link;
end

--[[
dec2dms

Wrapper to allow templates to call dec2dms directly.

Usage:
    {{ Invoke:Coordinates | dec2dms | decimal_coordinate | positive_suffix | 
        negative_suffix | precision }}
    
decimal_coordinate is converted to DMS format.  If positive, the positive_suffix
is appended (typical N or E), if negative, the negative suffix is appended.  The
specified precision is one of 'D', 'DM', or 'DMS' to specify the level of detail
to use.
]]
function coordinates.dec2dms(frame)
    globalFrame = frame
    local coordinate = frame.args[1]
    local firstPostfix = frame.args[2]
    local secondPostfix = frame.args[3]
    local precision = frame.args[4]

    return convert_dec2dms(coordinate, firstPostfix, secondPostfix, precision)
end

--[[ Wrapper to allow templates to call dec2ch1903 directly 
]]
function coordinates.dec2ch1903 (frame)
    globaFrame = frame
    local label = frame.args[1]
    local lat = frame.args[2]
    local lon = frame.args[3]
    local prec = frame.args[4]
    local text = ""
    local x, y = convert_dec2ch1903(label,lat,lon, prec)
    if label ~= "" and label ~= nil then
        text = '<span title="Svislandaj landaj koordinatoj">CH1903:&nbsp;</span>'
        .. '<span title="y easting">' .. y .. '</span>&nbsp;/&nbsp;'        
        .. '<span title="x northing">' .. x .. '</span>' 
    else
        text = "CH1903: " .. y .. " / " .. x
    end    
    return text
end    

--[[ Wrapper to allow templates to call dec2utm directly 
]]
function coordinates.dec2utm (frame)
    globaFrame = frame
    local label = frame.args[1]
    local lat = frame.args[2]
    local lon = frame.args[3]
    local prec = frame.args[4]
    local text = ""
    local zonenumber, zonedir, zone, x, y = convert_dec2utm(label,lat,lon, prec)
    -- if label ~= "" and label ~= nil then
        text = '<span title="Universal Transverse Mercator, baziĝanta sur WGS84">UTM:&nbsp;</span>'
        .. 'Zono&nbsp;<span title="Zononumero">' .. zonenumber .. '</span>'
        .. '<span title="Zonobendo, ' .. zonedir .. ' de la ekvatoro">' .. zone .. '</span>, '
        .. '<span title="easting">' .. y .. '</span>&nbsp;/&nbsp;'        
        .. '<span title="northing">' .. x .. '</span>' 
    -- else
       -- text = "CH1903: " .. y .. " / " .. x
    -- end    
    return text
end

--[[
Helper function to determine whether to use D, DM, or DMS
format depending on the precision of the decimal input.
]]
function coordinates.determineMode( value1, value2 )
    local precision = math.max( math_mod._precision( value1 ), math_mod._precision( value2 ) );
    if precision <= 0 then
        return 'd'
    elseif precision <= 2 then
        return 'dm';
    else
        return 'dms';
    end
end        

--[[
dms2dec

Wrapper to allow templates to call dms2dec directly.

Usage:
    {{ Invoke:Coordinates | dms2dec | direction_flag | degrees | 
        minutes | seconds }}
    
Converts DMS values specified as degrees, minutes, seconds too decimal format.
direction_flag is one of N, S, E, W, and determines whether the output is 
positive (i.e. N and E) or negative (i.e. S and W).
]]
function coordinates.dms2dec(frame)
    globalFrame = frame
    
    local direction = frame.args[1]
    local degrees = frame.args[2]
    local minutes = frame.args[3]
    local seconds = frame.args[4]  
    
    if frame.args[2] == nil then 
        local explode=mw.text.split( frame.args[1], '/' )
        if (#explode > 1) then
            direction = explode[#explode]
            degrees = explode[1]
        else
            local sign, val=string.match (explode[1], '([\-]*)([%d.]*)')
            if sign == '-' then direction='S' else direction='N' end
            degrees = val
        end    
        if(#explode>2) then 
            minutes = explode[2]
        end
        if(#explode>3) then 
            seconds = explode[3]
        end
    end     

    return convert_dms2dec(direction, degrees, minutes, seconds)
end

--[[
dms2ch1903

Wrapper to allow templates to call dms2ch1903 directly.

Usage:
    {{ Invoke:Coordinates | dms2ch1903 | direction_flag1 | degrees | 
        minutes | seconds | direction_flag2 | degrees | minutes | seconds }}
    
Converts DMS values specified as degrees, minutes, seconds too format of Swiss coordinates.
direction_flag1 is one of N, S and direction_flag2 is one of E, W, and determines whether the output is 
positive (i.e. N and E) or negative (i.e. S and W).
]]
function coordinates.dms2ch1903(frame)
    globalFrame = frame
    
    local lat_f = frame.args[1]
    local lat_d = frame.args[2]
    local lat_m = frame.args[3]
    local lat_s = frame.args[4]
    local long_f = frame.args[5]
    local long_d = frame.args[6]
    local long_m = frame.args[7]
    local long_s = frame.args[8]
    local label = frame.args['label']
    local text = ""
    
    if frame.args[3] == nil then 
        local explode1=mw.text.split( frame.args[1]:match( '^%s*(.-)%s*$' ), '/' )
        local explode2=mw.text.split( frame.args[2]:match( '^%s*(.-)%s*$' ), '/' )  
        --latitude
        if (#explode1 > 1) then
            lat_f = explode1[#explode1]
            lat_d = explode1[1]
        else
            local sign, val=string.match (explode1[1], '([\-]*)([%d.]*)')
            if sign == '-' then lat_f='S' else lat_f='N' end
            lat_d = val
        end    
        if(#explode1>2) then 
            lat_m = explode1[2]
        end
        if(#explode1>3) then 
            lat_s = explode1[3]
        end
        --longitude
        if (#explode2 > 1) then
            long_f = explode2[#explode2]
            long_d = explode2[1]
        else
            local sign, val=string.match (explode2[1], '([\-]*)([%d.]*)')
            if sign == '-' then long_f='W' else long_f='E' end
            long_d = val
        end    
        if(#explode2>2) then 
            long_m = explode2[2]
        end
        if(#explode2>3) then 
            long_s = explode2[3]
        end
    end     
    
    local x, y = convert_dms2ch1903(lat_f, lat_d, lat_m, lat_s, long_f, long_d, long_m, long_s)
    if label ~= "" and label ~= nil then
        text = '<span title="Svislandaj landaj koordinatoj">CH1903:&nbsp;</span>'
        .. '<span title="y easting">' .. y .. '</span>&nbsp;/&nbsp;'        
        .. '<span title="x northing">' .. x .. '</span>' 
    else
        text = "CH1903: " .. y .. " / " .. x
    end    
    return text
end    

--[[
dms2utm

Wrapper to allow templates to call dms2utm directly.

Usage:
    {{ Invoke:Coordinates | dms2utm | direction_flag1 | degrees | 
        minutes | seconds | direction_flag2 | degrees | minutes | seconds }}
    
Converts DMS values specified as degrees, minutes, seconds too format of Swiss coordinates.
direction_flag1 is one of N, S and direction_flag2 is one of E, W, and determines whether the output is 
positive (i.e. N and E) or negative (i.e. S and W).
]]
function coordinates.dms2utm(frame)
    globalFrame = frame
    
    local lat_f = frame.args[1]
    local lat_d = frame.args[2]
    local lat_m = frame.args[3]
    local lat_s = frame.args[4]
    local long_f = frame.args[5]
    local long_d = frame.args[6]
    local long_m = frame.args[7]
    local long_s = frame.args[8]
    local label = frame.args['label']
    local text = ""
    
    if frame.args[3] == nil then 
        local explode1=mw.text.split( frame.args[1]:match( '^%s*(.-)%s*$' ), '/' )
        local explode2=mw.text.split( frame.args[2]:match( '^%s*(.-)%s*$' ), '/' )  
        --latitude
        if (#explode1 > 1) then
            lat_f = explode1[#explode1]
            lat_d = explode1[1]
        else
            local sign, val=string.match (explode1[1], '([\-]*)([%d.]*)')
            if sign == '-' then lat_f='S' else lat_f='N' end
            lat_d = val
        end    
        if(#explode1>2) then 
            lat_m = explode1[2]
        end
        if(#explode1>3) then 
            lat_s = explode1[3]
        end
        --longitude
        if (#explode2 > 1) then
            long_f = explode2[#explode2]
            long_d = explode2[1]
        else
            local sign, val=string.match (explode2[1], '([\-]*)([%d.]*)')
            if sign == '-' then long_f='W' else long_f='E' end
            long_d = val
        end    
        if(#explode2>2) then 
            long_m = explode2[2]
        end
        if(#explode2>3) then 
            long_s = explode2[3]
        end
    end     
    
    local zonenumber, zonedir, zone, x, y = convert_dms2utm(lat_f, lat_d, lat_m, lat_s, long_f, long_d, long_m, long_s)
    -- if label ~= "" and label ~= nil then
        text = '<span title="Universal Transverse Mercator, baziĝanta sur WGS84">UTM:&nbsp;</span>'
        .. 'Zono&nbsp;<span title="Zononumero">' .. zonenumber .. '</span>'
        .. '<span title="Zonobendo, ' .. zonedir .. ' de la ekvatoro">' .. zone .. '</span>, '
        .. '<span title="easting">' .. y .. '</span>&nbsp;/&nbsp;'        
        .. '<span title="northing">' .. x .. '</span>' 
    -- else
       -- text = "CH1903: " .. y .. " / " .. x
    -- end     
    return text
end 

--[[ Helper function, returns values for "display", if the parameter "montru" is used instead
if the given text in "montru" is empty, it returns nil
if the given text in "montru" isn't empty, it returns an utilizable value
]]
function coordinates.montru (montru)
    local text = ""
    -- if montru isn't empty, then it changes the text in "montru" in lower case letters
    if montru ~= "" and montru ~= nil then montru = string.lower(montru)
       -- it analyzes the text
       if string.find(montru, "titolo") ~= nil then text = "title"
       end    
       if string.find(montru, "entekste") ~= nil then 
           if text == "" then text = "inline" 
           else text = "inline," .. text
           end    
       end    
    -- elseif montru == nil then text = montru    
    end     
    return text
end    

--[[ Helper function, returns values for "format", if the paramter "formato" is used instead
if the given text in "formato" is empty, it returns nil
if the given text in "formato" isn't empty, it returns an utilizable value
]]
function coordinates.formato (formato)
    local text = ""
    if formato ~= nil and formato ~= "" then
       -- if formato isn't empty, then it changes the text in "formato" into lower case letters 
       formato = string.lower(formato)
       -- the value of formato is analyzed
       if formato == "gms" or formato == "dms" then text = "dms"
       elseif formato == "gm" or formato == "dm" then text = "dm"
       elseif formato == "g" or formato == "grado" or formato == "d" then text = "d"       	
       elseif formato == "gms-longa" or formato == "gms longa" or formato == "dms long" then text = "dms long"   
       elseif formato == "dek" or formato == "dec" then text = "dec"   
       -- if there is a nonsense text in "formato", then it returns "dms"  
       else text = "dms"    
       end
    else text = formato   
    end   
    return text
end    

--[[ Helper function, for {{Koordinato}}, which returns values for "format", if the paramter "formato" is used instead
if the given text in "formato" is empty, it returns nil
if the given text in "formato" isn't empty, it returns an utilizable value
]]
function coordinates.formattext (formato)
    local text = ""
    if formato ~= nil and formato ~= "" then
       -- if formato isn't empty, then it changes the text in "formato" into lower case letters 
       formato = string.lower(formato)
       -- the value of formato is analyzed
       if formato == "gms" or formato == "dms" then text = "dms"
       elseif formato == "gm" or formato == "dm" then text = "dm"
       elseif formato == "g" or formato == "grado" or formato == "d" then text = "d"       	
       elseif formato == "gms-longa" or formato == "gms longa" or formato == "dms long" then text = "dms long"   
       -- addition for {{Koordinato}}
       elseif formato == "ch1903" then text = formato
       elseif formato == "utm" then text = formato
       elseif formato == "dek" or formato == "dec" then text = "dec"   
       -- some icons for {{Koordinato}}
       elseif formato == "icon0" or formato == "icon1" or formato == "icon2" then text = formato
       -- any image with the name space prefix
       elseif mw.ustring.lower(mw.ustring.sub(formato,1,5)) == "file:" or mw.ustring.lower(mw.ustring.sub(formato,1,6)) == "image:"
           or mw.ustring.lower(mw.ustring.sub(formato,1,8)) == "dosiero:" then text = formato
       -- if there is an other text in "formato", then it returns dms  
       else text = "dms" 
       end
    else text = formato   
    end   
    return text
end    

--[[ Helper function, chiefly for {{Koordinato}}, which returns values for "formatitle", if the paramter "titolformato" is used instead
if the given text in "formato" is empty, it returns nil
if the given text in "formato" isn't empty, it returns an utilizable value
]]
function coordinates.formatarticle (formato)
    local text = ""
    if formato ~= nil and formato ~= "" then
       -- if formato isn't empty, then it changes the text in "formato" into lower case letters 
       formato = string.lower(formato)
       -- the value of formato is analyzed
       if formato == "gms" or formato == "dms" then text = "dms"
       elseif formato == "gm" or formato == "dm" then text = "dm"	
       elseif formato == "g" or formato == "grado" or formato == "d" then text = "d"	       	
       elseif formato == "gms-longa" or formato == "gms longa" or formato == "dms long" then text = "dms long"   
       -- addition for {{Koordinato}}
       elseif formato == "ch1903" then text = formato
       elseif formato == "dek" or formato == "dec" then text = "dec"   
       -- if there is an other text in "formato", then it returns dms  
       else text = "dms" 
       end
    else text = formato   
    end   
    return text
end    

--[[ deg2slash
it translates parameters according to the "polish" syntax into the syntax with /
]]
function deg2slash (arg)
    local r    = arg
    r = r:match( '^%s*(.-)%s*$' );  --remove whitespace
 
   -- from polish module
   local d1, m1, s1, h1, d2, m2, s2, h2 = mw.ustring.match(r, "^([0-9,.]+)[°_]?%s*([0-9,.]*)['′_]?%s*([0-9,.]*)[\"″_]?%s*([NSEWOU])[,;]?%s+([0-9,.]+)[°_]?%s*([0-9,.]*)['′_]?%s*([0-9,.]*)[\"″_]?%s*([EWOUNS])$")
   if d1 then
       if (((h1 == "N") or (h1 == "S")) and ((h2 == "N") or (h2 == "S"))) or (((h1 == "E") or (h1 == "O") or (h1 == "U") or (h1 == "W")) and ((h2 == "E") or (h2 == "O") or (h2 == "U") or (h2 == "W"))) then
             return "Error!" -- place for error message
       end
       if m1 == "" or m1 == nil then
       	  m1=0
       end
       if s1 == "" or s1 == nil then
       	  s1=0
       end  
       if m2 == "" or m2 == nil then
       	  m2=0
       end
       if s2 == "" or s2 == nil then
       	  s2=0
       end
       if s1 == 0 and s2 == 0 and m1 ~= 0 and m2 ~= 0 then 
       	  r = d1 .. "/" .. m1 .. "/" .. h1 .. "/" .. d2 .. "/" .. m2 .. "/" .. h2
       elseif s1 == 0 and s2 == 0 and m1 == 0 and m2 == 0 then
       	  r = d1 .. "/" .. h1 .. "/" .. d2 .. "/" .. h2
       else
          r = d1 .. "/" .. m1 .. "/" .. s1 .. "/" .. h1 .. "/" .. d2 .. "/" .. m2 .. "/" .. s2 .. "/" .. h2   	
       end
    end
    local lat, lon = string.match(r, "^(-?[0-9.,]+)%s+(-?[0-9.,]+)$")
    if lat then
    	r = lat .. "/" .. lon
    end
 
    return  r
end

--[[
coord

Main entry point for Lua function to replace {{coord}}

Usage:
    {{ Invoke:Coordinates | coord }}
    {{ Invoke:Coordinates | coord | lat | long }}
    {{ Invoke:Coordinates | coord | lat | lat_flag | long | long_flag }}
    ...
    
    Refer to {{coord}} documentation page for many additional parameters and 
    configuration options.
    
Note: This function provides the visual display elements of {{coord}}.  In
order to load coordinates into the database, the {{#coordinates:}} parser 
function must also be called, this is done automatically in the Lua
version of {{coord}}.
]]
function coordinates.coord(frame)
    globalFrame = frame
    
    local text = ''
    local coordinateSpec = {}
    
    local args = frame.args
    if args[1] == nil then
        local pFrame = frame:getParent();
        args = pFrame.args;
        for k,v in pairs( frame.args ) do
            args[k] = v;
        end
    end
    
    for i=1,10 do 
        if args[i] == nil then 
            args[i] = ""
        else
            args[i] = args[i]:match( '^%s*(.-)%s*$' );  --remove whitespace
        end        
    end

    args[1] = deg2slash (args[1]) -- helping function for "polish" syntax of parameters
    local latdms=mw.text.split( args[1], '/' )
    local lngdms=mw.text.split( args[2], '/' )
    if #latdms > 1 or #lngdms >1 then 
        -- je copie
        local argsN=mw.clone(args)   
        local i = 1 -- point de départ
        local ia = 1 -- point de départ
        while (latdms[i] ~= nil) do
          args[ia]=mw.text.trim(latdms[i])
          i = i + 1
          ia = ia +1
        end
        local i = 1 -- point de départ
        while (lngdms[i] ~= nil) do
          args[ia]=mw.text.trim(lngdms[i])
          i = i + 1
          ia = ia +1
        end
        local i = 3 -- point de départ
        while (argsN[i] ~= nil) do
          args[ia]=argsN[i]
          i = i + 1
          ia = ia +1
        end
    end       
    
    --definition of the planete
    local astre
    for _, l in ipairs(args) do
        for w in string.gmatch(l, "globe:(%a+)") do
            astre=w
            break
        end
    end    
    
    -- local contents = formatTest(args)
    -- local args, coord, inputFormat, errors = formatTest(args)
    local coord, inputFormat = formatTest(args)
    
    if not inputFormat then 
    	return coord
    end
    
    if args['mode'] == "de" then
        args['format'] = coordinates.formattext(args['format']) or coordinates.formattext(args['formato']) or '';


        -- return coord2 ()	
    else    
        args['format'] = coordinates.formato(args['format']) or coordinates.formato(args['formato']) or '';
    end
    args['name'] = args['name'] or args['nomo']
    args['category'] = args['category'] or args['kategorio'];
    args['link'] = args['link'] or args['ligu'];    

    reqFormat =  inputFormat

    if reqFormat == "dec" then
    -- {{coord|1.111|2.222}}    	
    lat  = coord[1];
    long = coord[2];    	
    
    elseif reqFormat == "d" then
	-- {{coord|1.111|N|3.333|W}}
    lat_d  = coord[1]
    lat_f  = coord[2]
    long_d = coord[3]    
    long_f = coord[4]
    
    elseif reqFormat == "dm" then
	-- {{coord|1|2|N|4|5|W}}
	lat_d = coord[1]
	lat_m = coord[2]
	lat_f = coord[3]
	long_d = coord[4]
	long_m = coord[5]
	long_f = coord[6]
	
    elseif reqFormat == "dms" then
	-- {{coord|1|2|3|N|5|6|7|W}}
	lat_d = coord[1]
	lat_m = coord[2]
	lat_s = coord[3]
	lat_f = coord[4]
	long_d = coord[5]
	long_m = coord[6]
	long_s = coord[7]
	long_f = coord[8]
    end
    
-- for dec or d to dms ...    
    if reqFormat == "dec" or reqFormat == "d" then
    	if reqFormat == "dec" then
            coordinateSpec["dec-lat"]  = lat;
            coordinateSpec["dec-long"] = long;  
            local mode = coordinates.determineMode( lat, long );        
            coordinateSpec["dms-lat"]  = convert_dec2dms( lat, "N", "S", mode)  -- {{coord/dec2dms|{{{1}}}|N|S|{{coord/prec dec|{{{1}}}|{{{2}}}}}}}
            coordinateSpec["dms-long"] = convert_dec2dms( long, "O", "U", mode)  -- {{coord/dec2dms|{{{2}}}|E|W|{{coord/prec dec|{{{1}}}|{{{2}}}}}}}  
            coordinateSpec["dmslong-lat"]  = convert_dec2dms( lat, "Nordo", "Sudo", mode)  -- {{coord/dec2dms|{{{1}}}|N|S|{{coord/prec dec|{{{1}}}|{{{2}}}}}}}
            coordinateSpec["dmslong-long"] = convert_dec2dms( long, "Oriento", "Okcidento", mode)  -- {{coord/dec2dms|{{{2}}}|E|W|{{coord/prec dec|{{{1}}}|{{{2}}}}}}}      
            --added formats
            coordinateSpec['ch1903-x'], coordinateSpec['ch1903-y'] = convert_dec2ch1903("",lat,long,0) -- for Swiss coordinates
            coordinateSpec['zonenumber'], coordinateSpec['zonedir'], coordinateSpec['zone'], coordinateSpec['utm-x'], coordinateSpec['utm-y'] = convert_dec2utm("",lat,long,0) -- for UTM coordinates
            coordinateSpec["dm-lat"]  = convert_dec2dms( lat, "N", "S", "dm")  
            coordinateSpec["dm-long"] = convert_dec2dms( long, "O", "U", "dm") 
            coordinateSpec["d-lat"]  = convert_dec2dms( lat, "N", "S", "d")  
            coordinateSpec["d-long"] = convert_dec2dms( long, "O", "U", "d")      

        elseif reqFormat == "d" then
          	if lat_f:upper() == "S" then
          		coordinateSpec["dec-lat"] = '-' .. lat_d
          	else 
          		coordinateSpec["dec-lat"] = lat_d
          	end	
          	if long_f:upper() == "W" then
          		coordinateSpec["dec-long"] = '-' .. long_d
          	else
          		coordinateSpec["dec-long"] = long_d
          	end
          	local mode = coordinates.determineMode( lat_d, long_d );
            coordinateSpec["dms-lat"]  = convert_dec2dms( lat_d, "N", "S", mode)  -- {{coord/dec2dms|{{{1}}}|N|S|{{coord/prec dec|{{{1}}}|{{{2}}}}}}}
            coordinateSpec["dms-long"] = convert_dec2dms( long_d, "O", "U", mode)  -- {{coord/dec2dms|{{{2}}}|E|W|{{coord/prec dec|{{{1}}}|{{{2}}}}}}}  
            coordinateSpec["dmslong-lat"]  = convert_dec2dms( lat_d, "Nordo", "Sudo", mode)  -- {{coord/dec2dms|{{{1}}}|N|S|{{coord/prec dec|{{{1}}}|{{{2}}}}}}}
            coordinateSpec["dmslong-long"] = convert_dec2dms( long_d, "Oriento", "Okcidento", mode)  -- {{coord/dec2dms|{{{2}}}|E|W|{{coord/prec dec|{{{1}}}|{{{2}}}}}}}      
            --added formats
            coordinateSpec['ch1903-x'], coordinateSpec['ch1903-y'] = convert_dec2ch1903("",lat_d,long_d,0) -- for Swiss coordinates
            coordinateSpec['zonenumber'], coordinateSpec['zonedir'], coordinateSpec['zone'], coordinateSpec['utm-x'], coordinateSpec['utm-y'] = convert_dec2utm("",lat_d,long_d,0) -- for UTM coordinates
            coordinateSpec["dm-lat"]  = convert_dec2dms( lat_d, "N", "S", "dm")  
            coordinateSpec["dm-long"] = convert_dec2dms( long_d, "O", "U", "dm") 
            coordinateSpec["d-lat"]  = convert_dec2dms( lat_d, "N", "S", "d")  
            coordinateSpec["d-long"] = convert_dec2dms( long_d, "O", "U", "d")            	
          	
    	end
    end
        
-- for dms or dm to dec ...
    if reqFormat == "dm" or reqFormat == "dms" then
    	local lat_flong = 'Nordo';
        if lat_f == 'S' then
           lat_flong = 'Sudo';
        end
        local long_flong = 'Okcidento';
        if long_f == 'E' or long_f == 'O' then
           long_flong = 'Oriento';
        end
        if long_f == "W" then
           long_f = "U"        -- montri direkton, escepte de coordinateSpec["param"]
        end
        if long_f == "E" then
           long_f = "O"        -- montri direkton, escepte de coordinateSpec["param"]
        end    
    coordinateSpec["dms-lat"]  = lat_d.."°&nbsp;"..optionalArg(lat_m,"′&nbsp;") .. optionalArg(lat_s,"″&nbsp;") .. lat_f
    coordinateSpec["dmslong-lat"]  = lat_d.."°&nbsp;"..optionalArg(lat_m,"′&nbsp;") .. optionalArg(lat_s,"″&nbsp;") .. lat_flong
    coordinateSpec["dms-long"] = long_d.."°&nbsp;"..optionalArg(long_m,"′&nbsp;") .. optionalArg(long_s,"″&nbsp;") .. long_f
    coordinateSpec["dmslong-long"] = long_d.."°&nbsp;"..optionalArg(long_m,"′&nbsp;") .. optionalArg(long_s,"″&nbsp;") .. long_flong
    coordinateSpec["dec-lat"]  = convert_dms2dec(lat_f, lat_d, lat_m, lat_s) -- {{coord/dms2dec|{{{4}}}|{{{1}}}|0{{{2}}}|0{{{3}}}}}
    coordinateSpec["dec-long"] = convert_dms2dec(long_f, long_d, long_m, long_s) -- {{coord/dms2dec|{{{8}}}|{{{5}}}|0{{{6}}}|0{{{7}}}}}
    --added formats
    coordinateSpec['ch1903-x'], coordinateSpec['ch1903-y'] = convert_dms2ch1903(lat_f, lat_d, lat_m, lat_s ,long_f, long_d, long_m, long_s) -- for Swiss coordinates
    coordinateSpec['zonenumber'], coordinateSpec['zonedir'], coordinateSpec['zone'], coordinateSpec['utm-x'], coordinateSpec['utm-y'] = convert_dms2utm(lat_f, lat_d, lat_m, lat_s ,long_f, long_d, long_m, long_s) -- for UTM coordinates
    coordinateSpec["dm-lat"]  = lat_d.."°&nbsp;"..optionalArg(lat_m,"′&nbsp;") .. lat_f
    coordinateSpec["dm-long"] = long_d.."°&nbsp;"..optionalArg(long_m,"′&nbsp;") .. long_f
    coordinateSpec["d-lat"]  = lat_d.."°&nbsp;" .. lat_f
    coordinateSpec["d-long"] = long_d.."°&nbsp;" .. long_f  
    end

    if args["format"] then
        coordinateSpec.default = args["format"]
    elseif reqFormat == "dec" then
        coordinateSpec.default = "dec"
    else
        coordinateSpec.default = "dms"
    end
    
    -- create the string param for geohack.php
    if reqFormat == "dec" then
         coordinateSpec.param = coord[1] .. "_N_" .. coord[2] .. "_E" .. (coord[3] and ("_" .. coord[3]) or "")
    elseif reqFormat == "dms" then
         coordinateSpec.param = table.concat( { coord[1], coord[2], formatPoint(coord[3]), normCardDir(coord[4]), coord[5],
            coord[6], formatPoint(coord[7]), normCardDir(coord[8]), coord[9] } , '_' );
    elseif reqFormat == "dm" then
    	 coordinateSpec.param = table.concat( { coord[1], formatPoint(coord[2]), normCardDir(coord[3]), coord[4], formatPoint(coord[5]),
            normCardDir(coord[6]), coord[7] } , '_' );
    elseif reqFormat == "d" then
    	 coordinateSpec.param = table.concat( { formatPoint(coord[1]), normCardDir(coord[2]), formatPoint(coord[3]), normCardDir(coord[4]), coord[5] } , '_' );
    end


    local Notes = args.notes or ""
    local Display = string.lower(args.display or coordinates.montru(args.montru) or "inline")
    if Display == '' then
        Display = 'inline';
    end
    
    local havedisplay = "";
    
    if args['category'] ~= "" and args['category'] ~= nil then
        text = catPrinter(args, coordinateSpec)
        text = displayinline(text, Notes)    
        return text
    end
 
    if string.find( Display, 'inline' ) ~= nil or Display == 'i' or 
            Display == 'it' or Display == 'ti' or args['link'] == "ne" or args['link']  == "no" then
        content = specPrinter( args, coordinateSpec )    	
        text = text .. displayinline(content, Notes)
        havedisplay = havedisplay .. "i";
    end
    if args['link'] == "" or args['link'] == nil or args['link'] == "jes" or args['link'] == "yes" then 
       if string.find( Display, 'title' ) ~= nil or Display == 't' or 
              Display == 'it' or Display == 'ti' then
           if args['formatitle'] ~= nil then
              args['format'] = args['formatitle'] or args['format']
              -- contents = formatTest(args)
              content = specPrinter( args, coordinateSpec )
              text = text .. displaytitle(content, Notes, astre) 
           else
              content = specPrinter( args, coordinateSpec )
              text = text .. displaytitle(content, Notes, astre)               
           end   
           args['geodata']="primary"
           -- text = text ..  globalFrame:preprocess(formatTest(args) )
           text = text .. globalFrame:preprocess(geodataPrinter( args, coordinateSpec ))
 
           havedisplay = havedisplay .. "t";
       end
    end

    if havedisplay == "" then
        --rien n'a été affiché!
        if args['mode'] == "de" then
           contents = specPrinter2( args, coordinateSpec )
        else	 
           contents = specPrinter( args, coordinateSpec )
        end
        text = text .. displayinline(contents, Notes) .. errorPrinter( {{"display", "argumento display estas malĝusta"}} )
 
    end 

    return text
end

function coordinates.Coord(frame)
    return coordinates.coord(frame)
end

--[[ coord2 - variant of coord for use in Modulo:Coordinates2
]]
function coordinates.coord2(frame)
        globalFrame = frame.args.gf 
        local origArgs = {}
 
             if frame == mw.getCurrentFrame() then
                 origArgs = frame:getParent().args
             else        
                 origArgs = frame.args
             end
 
         args = {}
            for k, v in pairs(origArgs) do                 
                     args[k] = v                    
            end
    for i=1,10 do 
        if args[i] == nil then 
            args[i] = ""
        else
            args[i] = args[i]:match( '^%s*(.-)%s*$' );  --remove whitespace
        end        
    end

    -- args['format'] = coordinates.formattext(args['format']) or coordinates.formattext(args['formato']) or '';        
    -- args['formatitle'] = coordinates.formatarticle(args['formatitle']) or coordinates.formatarticle(args['titolformato']) -- or '';
    args['name'] = args['name'] or args['nomo']
    args['category'] = args['category'] or args['kategorio'];
    -- args['mode'] = "de"
    local map = args['map']

    args[1] = deg2slash (args[1]) -- helping function for "polish" syntax of parameters
    local latdms=mw.text.split( args[1], '/' )
    local lngdms=mw.text.split( args[2], '/' )
    if #latdms > 1 or #lngdms >1 then 
        -- je copie
        local argsN=mw.clone(args)   
        local i = 1 -- point de départ
        local ia = 1 -- point de départ
        while (latdms[i] ~= nil) do
          args[ia]=mw.text.trim(latdms[i])
          i = i + 1
          ia = ia +1
        end
        local i = 1 -- point de départ
        while (lngdms[i] ~= nil) do
          args[ia]=mw.text.trim(lngdms[i])
          i = i + 1
          ia = ia +1
        end
        local i = 3 -- point de départ
        while (argsN[i] ~= nil) do
          args[ia]=argsN[i]
          i = i + 1
          ia = ia +1
        end
    end       

    -- local contents = formatTest(args)
    --local args, coord, inputFormat, errors = formatTest(args)
    local coord, inputFormat = formatTest(args)
    
    if not inputFormat then 
    	return coord
    end

    -- args['format'] = args['format'] or inputFormat;        
    local Notes = args.notes or ""
    -- local Display = string.lower(args.display or coordinates.montru(args.montru) or "inline")
    local Display = string.lower(args.display or "inline")    
    if Display == '' then
        Display = 'inline';
    end
    
    local text = ''
    
    if args['category'] ~= "" and args['category'] ~= nil then
    	text = catPrinter(args, coord)
    	text = displayinline(text, Notes)
    	return text
    end
    
    if string.find( Display, 'inline' ) ~= nil or Display == 'i' or 
            Display == 'it' or Display == 'ti' then
        args['text'] = "yes"            	
        content = specPrinter2( args, coord )    
        text = displayinline(content, Notes)
        args['text'] = "no"        
        isInline = "yes"
    else isInline = "no"    
    end
        -- creates the code for the microformat
        args['micro'] = "yes"
        -- content = formatTest(args)
        content = specPrinter2( args, coord )
        args['micro'] = ""
        text = text .. content -- adds it to the return string
      if string.find( Display, 'title' ) ~= nil or Display == 't' or 
            Display == 'it' or Display == 'ti' then
        -- a helper parameter for uses, if there are more than one format for the coordinates              
        args['second'] = "yes"  
            -- contents = formatTest(args)
            args['article'] = "yes"
            contents = specPrinter2( args, coord )
            -- test
            -- Notes = "<br />titola formato: " .. args['formatitle']
            if isInline == "no" then
            -- a little bit tricky methode to put in an information about the tags to be used
            contents = "(div)" .. contents  
            else contents = "(span)" .. contents      
            end
            text = text .. displaytitle(contents, Notes)
            args['article'] = "no"
        args['geodata']="primary"
        local frame = mw.getCurrentFrame()
        -- text = text .. frame:preprocess(formatTest(args))
        text = text ..frame:preprocess(geodataPrinter(args, coord))
      end  
      -- for adding a map
      if map ~= "" and map ~= nil then
         args['float'] = map
         args['map'] = 'test'  -- this has to be changed after some tests
         args['geodata'] = ''   -- the helping argument has to be empty here, because in formatTest it is tested
         -- contents = formatTest(args)
         contents = mapPrinter(args, coord)
      	 text = text .. contents
      end

    if string.find( Display, 'project' ) ~= nil then
        -- message from {{CoordinateNOx}}. but its HTML-code is elsewhere
        text = displaytitle2('Koordinatoj mankas! [[Projekto:Geografiaj koordinatoj|Bonvolu kunhelpi]]',"background:#FFC")
    end        
    return text
end

return coordinates