Модуль:Coordinates

Документация

Модуль для шаблона {{coord}}.

--[[ 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. g {{#Invoke:Coordinates | dms2dec }} : Simple function for converting DMS format to decimal degree format.  ]]  local stylesheetLink = 'Module:Coordinates/styles.css' local math_mod = require( "Module:Math" );  local coordinates = {};  local globe_list = '||earth|mercury|venus|moon|mars|phobos|deimos|ganymede|callisto|io|europa|mimas|enceladus|tethys|dione|rhea|titan|hyperion|iapetus|phoebe|miranda|ariel|umbriel|titania|oberon|triton|pluto|charon|ceres|vesta|'  local Display = '';  --[[ Helper function, replacement for {{coord/display/title}} ]] function displaytitle (s, notes) 	return mw.getCurrentFrame():extensionTag{ 		name = 'indicator', 		content = s .. notes, 		args = { name = '0-coord' } 	}; end  --[[ Helper function, Replacement for {{coord/display/inline}} ]] function displayinline (s, notes) 	return s .. notes end  --[[ Helper function, used in detecting DMS formatting ]] local dmsTest = function(first, second) 	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  --[[ 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 = {}  	errors = validate( lat, nil, nil, long, nil, nil, 'parseDec', false ); 	if #errors ~= 0 then 		return nil, errors 	end 	 	coordinateSpec["dec-lat"]  = lat; 	coordinateSpec["dec-long"] = long;  	local mode = coordinates.determineMode( lat, long ); 	coordinateSpec["dms-lat"]  = convert_dec2dms( lat, "&nbsp;с.&nbsp;ш.", "&nbsp;ю.&nbsp;ш.", mode)  -- {{coord/dec2dms|{{{1}}}|N|S|{{coord/prec dec|{{{1}}}|{{{2}}}}}}} 	coordinateSpec["dms-long"] = convert_dec2dms( long, "&nbsp;в.&nbsp;д.", "&nbsp;з.&nbsp;д.", mode)  -- {{coord/dec2dms|{{{2}}}|E|W|{{coord/prec dec|{{{1}}}|{{{2}}}}}}} 	 	if format ~= "" then 		coordinateSpec.default = format 	else 		coordinateSpec.default = "dms" 	end  	return coordinateSpec, errors end  --[[ Helper function, handle optional args. ]] function optionalArg(arg, suplement, bool) 	if arg ~= nil and arg ~= "" then  			arg = (tonumber( arg ) % 1 == 0 or not bool) and  			string.format( "%02d", arg ) or  			string.format( "%02.2f", arg):gsub('%.', ',') 		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 ) 	local coordinateSpec = {} 	local errors = {} 	 	lat_f = lat_f:upper(); 	long_f = long_f:upper(); 	 	-- Check if specified backward 	if lat_f == 'E' or lat_f == 'W' 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 #errors ~= 0 then 		return nil, errors 	end 	 	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}}}}}  	if lat_m == nil and lat_s == nil and long_m == nil and long_s == nil and #errors == 0  		or math_mod._precision( lat_d ) > 0 or math_mod._precision( long_d ) > 0 then 			if lat_f:upper() == 'S' then 				lat_d = '-' .. lat_d; 				lat_f = "&nbsp;ю.&nbsp;ш."; 			else 				lat_f = "&nbsp;с.&nbsp;ш."; 			end 			if long_f:upper() == 'W' then 				long_d = '-' .. long_d; 				long_f = "&nbsp;з.&nbsp;д."; 			else 				long_f = "&nbsp;в.&nbsp;д."; 			end 			 			return parseDec( lat_d, long_d, format ); 	end  	if lat_f:upper() == 'S' then 		lat_f = "&nbsp;ю.&nbsp;ш."; 	else 		lat_f = "&nbsp;с.&nbsp;ш."; 	end  	if long_f:upper() == 'E' then 		long_f = "&nbsp;в.&nbsp;д."; 	else 		long_f = "&nbsp;з.&nbsp;д."; 	end 	 	if lat_s == '0' and long_s == '0'  then 		lat_s, long_s = nil, nil 		if lat_m == '0' and long_m == '0' then 			lat_m, long_m = nil, nil 		end 	end  	coordinateSpec["dms-lat"]  = lat_d.."°"..optionalArg(lat_m,"′", true) .. optionalArg(lat_s,"″") .. lat_f 	coordinateSpec["dms-long"] = long_d.."°"..optionalArg(long_m,"′", true) .. optionalArg(long_s,"″") .. long_f  	if format ~= "" then 		coordinateSpec.default = format 	else 		coordinateSpec.default = "dms" 	end  	return coordinateSpec, errors end  --[[ splitParam  Split the parameter string and convert it into an object. ]] function splitParam( param ) 	local out = {} 	for pair in mw.text.gsplit( param, '_', true ) do 		local keyValue = mw.text.split( pair, ':', true ) 		if #keyValue == 2 then 			out[keyValue[1]] = keyValue[2] 		end 	end 	return out end  --[[ specPrinter  Output formatter.  Takes the structure generated by either parseDec or parseDMS and formats it for inclusion on Wikipedia. ]] function specPrinter(args) 	local coordinateSpec, errors = formatTest(args) 	 	if coordinateSpec == nil then 		return errors 	end 	 	local param = coordinateSpec["param"] .. '_' .. coordinateSpec["extra_param"] 	local uriComponents = param 	if uriComponents == "" then 		-- RETURN error, should never be empty or nil 		return "Ошибка: не задан param" 	end 	if args["name"] ~= "" and args["name"] ~= nil then 		uriComponents = uriComponents .. "&title=" .. mw.uri.encode(coordinateSpec["name"]) 	end 	local text = '' 	 	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):gsub('%.', ',') .. "°&nbsp;ю.&nbsp;ш." 	else 		geodeclat = (coordinateSpec["dec-lat"]:gsub('%.', ',') or 0) .. "°&nbsp;с.&nbsp;ш." 	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):gsub('%.', ',') .. "°&nbsp;з.&nbsp;д." 	else 		geodeclong = (coordinateSpec["dec-long"]:gsub('%.', ',') or 0) .. "°&nbsp;в.&nbsp;д." 	end 	 	local geodmshtml = '<span class="geo-dms" title="Различные карты и схемы для этого места">' 			 .. '<span class="latitude">' .. coordinateSpec["dms-lat"] .. '</span> ' 			 .. '<span class="longitude">' ..coordinateSpec["dms-long"] .. '</span>' 			 .. '</span>'  	local geodechtml = '<span class="geo-dec" title="Различные карты и схемы для этого места">' 			 .. geodeclat .. ' ' 			 .. geodeclong 			 .. '</span>'  	local geonumhtml = '<span class="geo">' 			 .. coordinateSpec["dec-lat"] .. '; ' 			 .. coordinateSpec["dec-long"] 			 .. '</span>'  	local inner; 	inner = '<span class="geo-geo-' .. coordinateSpec.default .. '"><span class="geo-dms">' .. geodmshtml .. '</span>' 				.. '<span class="geo-multi-punct">&#xfeff; / &#xfeff;</span>' 				.. '<span class="geo-dec">';  	if args["name"] == "" or args["name"] == nil then 		inner = inner .. geodechtml 				.. '<span style="display:none">&#xfeff; / ' .. geonumhtml .. '</span></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></span>' 	end  	local params = splitParam( param ) 	local type = string.gsub( string.lower( params.type or '' ), '%(.+$', '' )  	local scale 	if args.scale and args.scale ~= '' then 		scale = tonumber( args.scale ) 	end 	if not scale then 		local typeScale = { 			adm1st = 1000000, 			adm2nd = 300000, 			adm3rd = 100000, 			airport = 30000, 			city = 100000, 			country = 10000000, 			edu = 10000, 			event = 50000, 			forest = 50000, 			glacier = 50000, 			isle = 100000, 			landmark = 10000, 			mountain = 100000, 			pass = 10000, 			railwaystation = 10000, 			river = 100000, 			satellite = 10000000, 			waterbody = 100000, 			camera = 10000 		} 		if typeScale[type] then 			scale = typeScale[type] 		else 			scale = 30000 		end 	end  	if scale < 2000 then zoom = 18 	elseif scale <   5000 then zoom = 17 	elseif scale <  10000 then zoom = 16 	elseif scale <  20000 then zoom = 15 	elseif scale <  40000 then zoom = 14 	elseif scale <  80000 then zoom = 13 	elseif scale < 160000 then zoom = 12 	elseif scale < 320000 then zoom = 11 	elseif scale < 640000 then zoom = 10 	elseif scale < 1280000 then zoom = 9 	elseif scale < 2560000 then zoom = 8 	elseif scale < 5120000 then zoom = 7 	elseif scale < 10240000 then zoom = 6 	elseif scale < 20480000 then zoom = 5 	elseif scale < 40960000 then zoom = 4 	else zoom = 3 	end  	if coordinateSpec.default == 'dec' then 		text = geodeclat .. ' ' .. geodeclong 	else 		text = coordinateSpec["dms-lat"] .. ' ' .. coordinateSpec["dms-long"] 	end 	 	local maplinkArgs = { 		['latitude'] = coordinateSpec['dec-lat'], 		['longitude'] = coordinateSpec['dec-long'], 		['zoom'] = zoom, 		['text'] = text, 		['title'] = mw.title.getCurrentTitle().text, 		['lang'] = 'ru' 	}  	if coordinateSpec['name'] and coordinateSpec['name'] ~= '' then 		maplinkArgs['title'] = coordinateSpec['name'] 	end  	local maplinkMarkerSymbol = 'star' 	local markerSymbols = { 		adm1st = 'city', 		adm2nd = 'city', 		adm3rd = 'city', 		airport = 'airport', 		city = 'city', 		country = 'city', 		edu = 'college', 		forest = 'park', 		glacier = 'mountain', 		mountain = 'mountain', 		pass = 'mountain', 		railwaystation = 'rail', 		river = 'water', 		satellite = 'rocket', 		waterbody = 'water', 		camera = 'attraction' 	} 	if markerSymbols[type] then 		maplinkMarkerSymbol = markerSymbols[type] 	end  	local maplinkContent = [[ { 		"type": "Feature", 		"geometry": { 			"type": "Point", 			"coordinates": [ 				]] .. coordinateSpec['dec-long'] .. [[, 				]] .. coordinateSpec['dec-lat'] .. [[ 			] 		}, 		"properties": { 			"title": "]] .. mw.text.encode( maplinkArgs['title'] ) .. [[", 			"marker-symbol": "]] .. maplinkMarkerSymbol .. [[", 			"marker-color": "#3366cc" 		} 	} ]]; 	 	local entityId = mw.wikibase.getEntityIdForCurrentPage() 	if entityId then 		maplinkContent = maplinkContent .. [[, { 			"type": "ExternalData", 			"service": "geoline", 			"ids": "]] .. mw.wikibase.getEntityIdForCurrentPage() .. [[", 			"properties": { 				"stroke": "#FF9999" 			} 		}, { 			"type": "ExternalData", 			"service": "geoshape", 			"ids": "]] .. mw.wikibase.getEntityIdForCurrentPage() .. [[", 			"properties": { 				"fill": "#FF0000", 				"fill-opacity": 0.1, 				"stroke": "#FF9999" 			} 		} ]] 	end  	local globe = string.lower( args.globe or params.globe or '' ) 	if globe == '' then globe = 'earth' end  	local result = mw.getCurrentFrame():extensionTag{ 		name = 'templatestyles', args = { src = stylesheetLink } 	} .. '<span class="coordinates plainlinks nourlexpansion" data-param="' .. mw.text.encode( param ) .. '">'  	-- external links 	local nogoogle = string.lower( args.nogoogle or '' ) 	local noosm = string.lower( args.noosm or '' ) 	local noyandex = string.lower( args.noyandex or '' ) 	local pageNameUri = mw.title.getCurrentTitle():partialUrl()  	if globe == 'earth' then 		result = result .. '<span title="Показать карту">' .. mw.getCurrentFrame():extensionTag{ 			name = 'maplink', 			content = '[' .. maplinkContent .. ']', 			args = maplinkArgs 		} .. '</span>' 		if nogoogle == '' or noosm == '' or noyandex == '' then 			result = result .. '<sup class="geo-services noprint">' 			 			result = result .. '<span class="geo-geohack" title="Карты и инструменты на GeoHack">' .. 			'[https://geohack.toolforge.org/geohack.php?language=ru&pagename=' .. pageNameUri .. '&params=' .. 			uriComponents .. ' ' .. '<span>H</span>]</span>' 			 			if nogoogle == '' then 				result = result .. '<span class="geo-google" title="Это место на «Картах Google»">[https://maps.google.com/maps?' 					.. 'll=' ..  coordinateSpec["dec-lat"] .. ',' .. coordinateSpec["dec-long"] 					.. '&q=' ..  coordinateSpec["dec-lat"] .. ',' .. coordinateSpec["dec-long"] 					.. '&spn=' .. (scale / 1000000) .. ',' .. (scale / 1000000) 					.. '&t=h&hl=ru ' 					.. '<span>G</span>]</span>' 			end 			if noyandex == '' then 				result = result .. '<span class="geo-yandex" title="Это место на «Яндекс.Картах»">[https://yandex.ru/maps/' 					.. '?ll=' .. coordinateSpec["dec-long"] .. ',' .. coordinateSpec["dec-lat"] 					.. '&pt=' .. coordinateSpec["dec-long"] .. ',' .. coordinateSpec["dec-lat"] 					.. '&spn=' .. (scale / 1000000) .. ',' .. (scale / 1000000) 					.. '&l=' .. 'sat,skl ' 					.. '<span>Я</span>]</span>' 			end 			if noosm == '' then 				result = result .. '<span class="geo-osm" title="Это место на карте OpenStreetMap">[https://www.openstreetmap.org/?' 					.. 'mlat=' .. coordinateSpec["dec-lat"] .. '&mlon=' .. coordinateSpec["dec-long"] 					.. '&zoom=' .. zoom .. ' ' 					.. '<span>O</span>]</span>' 			end 			result = result .. '</sup>' 		end 	else 		-- FIXME [[phab:T151138]] 		result = result .. '[https://geohack.toolforge.org/geohack.php?language=ru&pagename=' .. pageNameUri .. '&params=' .. 			uriComponents .. ' ' .. inner .. ']' 		if globe == 'moon' or globe == 'mars' and nogoogle == '' then 			result = result .. '<sup class="geo-services noprint"><span class="geo-google" title="Это место на «Картах Google»">[https://www.google.com/' .. globe 			.. '/#lat=' ..  coordinateSpec["dec-lat"] .. '&lon=' .. coordinateSpec["dec-long"] 			.. '&zoom=7' 			.. '&map=visible' 			.. '&apollo= <span>G</span>]</span></sup>' 		end 	end 	 	result = result .. '</span>' 	 	local geodata = '' 	if coordinateSpec["dec-lat"] and coordinateSpec["dec-long"] then 		 		if globe ~= 'earth' and globe ~= 'moon' then 			if tonumber(coordinateSpec["dec-long"]) < 0 then 				coordinateSpec["dec-long"] = tostring(360 + tonumber(coordinateSpec["dec-long"])) 			end 		end 		local frame = mw.getCurrentFrame() 		local geodataparams = {[1] = coordinateSpec["dec-lat"], [2] = coordinateSpec["dec-long"], [3] = coordinateSpec["extra_param"], ['globe'] = globe } 		if string.find( Display, 'title' ) ~= nil and mw.title.getCurrentTitle():inNamespace(0) then 			geodataparams[4] = 'primary' 		end 		if coordinateSpec["name"] then 			geodataparams.name = coordinateSpec["name"] 		end 		 		geodata = frame:callParserFunction('#coordinates', geodataparams ) 		result = result .. geodata 	end 	 	return errors and result .. errors or result 	 end  --[[ Formats any error messages generated for display ]] function errorPrinter(errors) 	local result = "" 	for i,v in ipairs(errors) do 		local errorHTML = '<strong class="error">Координаты: ' .. v[2] .. '</strong>' 		result = result .. errorHTML .. "<br />" 	end 	if result ~= '' then 		if mw.title.getCurrentTitle():inNamespace(0) then 			return result .. '[[Категория:Страницы с некорректными тегами координат]]' 		else 			return result 		end 	end end  --[[ 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 == mode then 		return "geo-default" 	else 		return "geo-nondefault" 	end 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, errors; 	 	local param, extra_param = {}, {} 	 	local globe = string.lower( args.globe or '' ) 	if not globe_list:find('|' .. globe .. '|') then 		return nil, errorPrinter( {{"formatTest", "неизвестный глобус"}} ) 	end  	if args[4] == "" and args[5] == "" and args[6] == "" then 		-- dec logic 		result, errors = parseDec( args[1], args[2], args['format'] ) 		param = { args[1], "N", args[2], "E", args[3] }; 	elseif dmsTest(args[4], args[8]) then 		-- dms logic 		result, errors = parseDMS( args[1], args[2], args[3], args[4], 			args[5], args[6], args[7], args[8], args['format'] ) 		param = { args[1], args[2], args[3], args[4], args[5], 			args[6], args[7], args[8], args[9] }; 		if args[10] ~= '' then 			table.insert( errors, { 'formatTest', 'неожиданные дополнительные параметры' } ); 		end 	elseif dmsTest(args[3], args[6]) then 		-- dm logic 		result, errors = parseDMS( args[1], args[2], nil, args[3], 			args[4], args[5], nil, args[6], args['format'] ) 		param = { args[1], args[2], args[3], args[4], args[5], args[6], args[7] }; 		if args[8] ~= '' then 			table.insert( errors, { 'formatTest', 'неожиданные дополнительные параметры' } ); 		end 	elseif dmsTest(args[2], args[4]) then 		-- d logic 		result, errors = parseDMS( args[1], nil, nil, args[2], 			args[3], nil, nil, args[4], args['format'] ) 		param = { args[1], args[2], args[3], args[4], args[5] }; 		if args[6] ~= '' then 			table.insert( errors, { 'formatTest', 'неожиданные дополнительные параметры' } ); 		end 	else 		-- Error 		return nil, errorPrinter( {{"formatTest", "неизвестный формат аргумента"}} ) 	end 	 	if not result then  		return nil, errorPrinter( errors ) 	end  	result.name = args["name"] 	 	local last = table.getn (param) 	if param[last] == '' then 		table.remove(param, last) 	end  	local extra_params = { 'dim', 'globe', 'scale', 'region', 'source', 'type' } 	for _, v in ipairs( extra_params ) do 		if (args[v] or '') ~= '' then 			table.insert( extra_param, v .. ':' .. args[v] ); 		end 	end  	result.param = table.concat( param , '_' ); 	result.extra_param = table.concat( extra_param , '_' );  	return result, errorPrinter( errors ) end  --[[ 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 ) .. "°" 	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 .."°" 	 	return d .. string.format( "%02d′", 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 .."°"  	return d .. string.format( "%02d′", m ) .. string.format( "%02d″", 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 == "S" or direction == "W" 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  --[[ 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 = {}; 	 	if long_d == nil or long_d == '' then 		table.insert(errors, {source, "пропущена долгота"}) 	end 	if lat_d == nil or lat_d == '' then 		table.insert(errors, {source, "пропущена широта"}) 	end 	 	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, "градусы широты  < 0"}) 		end 		if long_d < 0 then 			table.insert(errors, {source, "градусы долготы < 0"}) 		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, "градусы широты > 90"}) 	end 	if lat_d < -90 then 		table.insert(errors, {source, "градусы широты < -90"}) 	end 	if lat_m >= 60 then 		table.insert(errors, {source, "минуты широты >= 60"}) 	end 	if lat_m < 0 then 		table.insert(errors, {source, "минуты широты < 0"}) 	end 	if lat_s >= 60 then 		table.insert(errors, {source, "секунды широты >= 60"}) 	end 	if lat_s < 0 then 		table.insert(errors, {source, "секунды широты < 0"}) 	end 	if long_d >= 360 then 		table.insert(errors, {source, "градусы долготы >= 360"}) 	end 	if long_d <= -360 then 		table.insert(errors, {source, "градусы долготы <= -360"}) 	end 	if long_m >= 60 then 		table.insert(errors, {source, "минуты долготы >= 60"}) 	end 	if long_m < 0 then 		table.insert(errors, {source, "минуты долготы < 0"}) 	end 	if long_s >= 60 then 		table.insert(errors, {source, "секунды долготы >= 60"}) 	end 	if long_s < 0 then 		table.insert(errors, {source, "секунды долготы < 0"}) 	end 	 	return errors; end  local function splitCoord(args, s) 	if s and s~= nil then 		local iterator = mw.ustring.gmatch(s, "[^/]+"); 		local i = 1; 		for w in iterator do 			args[i] = w; 			i = i + 1; 		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 	 	return args 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  --[[ 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) 	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 	 	local coord = args.coord or nil; 	args = splitCoord(args, coord) 	args['format'] = args['format'] or ''; 	 	Display = string.lower(args.display or "inline") 	local contents = specPrinter(args) 	local Notes = args.notes or "" 	if Display == '' then 		Display = 'inline'; 	end 	 	local text = '' 	if string.find( Display, 'inline' ) ~= nil then 		text = displayinline(contents, Notes) 	end 	if string.find( Display, 'title' ) ~= nil then 		displaytitle_ = true 		text = text .. displaytitle(contents, Notes) 	end 	return text end  function coordinates.getLon(frame) 	local args = frame.args 	 	args = splitCoord(args, args[1]) 	 	local out = formatTest(args) 	return out['dec-long'] end  function coordinates.getLat(frame) 	local args = frame.args 	 	args = splitCoord(args, args[1]) 	 	local out = formatTest(args) 	return out['dec-lat'] end  return coordinates