Амодуль:Coordinates validate

Аматериал Авикипедиа аҟынтә - зхы иақәиҭу аенциклопедиа

require 'Амодуль:No globals'

local p = {}

local getArgs = require( 'Амодуль:Arguments' ).getArgs

local function makeCategory( category )
	if mw.title.getCurrentTitle().namespace == 0 then
		local Kategorie = require 'Амодуль:Category'
		return Kategorie.makeCategory(
			category,
			mw.title.getCurrentTitle().namespace,
			mw.title.getCurrentTitle().text
		)
	else
		return ''
	end
end

-- @author [[Wikipedista:Oashi]]
local function makeDiffCategory( range )
	local unit = 'm'
	if range >= 1000 then
		unit = 'км'
		range = math.floor( range / 1000 )
	end
	local category_pattern = 'Обслуживание:Координаты из Викиданных отличаются более чем на %d %s'
	return makeCategory( mw.ustring.format( category_pattern, range, unit ) )
end

-- @author [[Wikipedista:Oashi]]
local function validateRange( range )
	if range < 0 then
		return false, '' --TODO: error
	end
	if range < 0.1 then
		return true, ''
	end
	local metre = math.min( range, 999 ) * 1000
	local magn, fract = math.modf( math.log10( metre ) )
	for _, num in ipairs{ 5, 2 } do
		if 10 ^ fract > num then
			return false, makeDiffCategory( num * ( 10 ^ magn ) )
		end
	end
	return false, makeDiffCategory( 10 ^ magn )
end

local function getFirstKey( args, ... )
	for _, key in ipairs{ ... } do
		if args[key] then
			return tonumber( args[key] )
		end
	end
	return nil
end

function p.main( frame )
	local args = getArgs( frame, {
		parentOnly = true,
		readOnly = true,
		removeBlanks = true,
	} )
	local lat = getFirstKey( args, 'аҭбаара', 'широта', 'latitude', 'lat', 1 )
	local long = getFirstKey( args, 'аноурылара', 'долгота', 'longitude', 'long', 'lon', 2 )
	local Wikidata = require 'Амодуль:Wikidata'
	local WD_coord = Wikidata.getRawValueFromLua{ property = 'P625', id = args.id, of = args.of }
	local _, category = p.validate( lat, long, WD_coord, args.kategorie )
	return category
end

function p.validate( lat, long, WD_coord, missing_cat )
	if not (lat or long) then
		if not WD_coord then
			return false, makeCategory( missing_cat or 'Обслуживание:Страницы объектов без координат' )
		else
			return true, ''
		end
	end
	if not (lat and long) then
		return false, makeCategory( 'Обслуживание:Страницы с неверными координатами' )
	end
	if not WD_coord then
		return false, makeCategory( 'Обслуживание:В Викиданных нет координат' )
	end
	local bool, category = validateRange( p.range( lat, long, WD_coord.latitude, WD_coord.longitude ) )
	return bool, category .. makeCategory( 'Амониторинг:Аԥхьаӡарақәа рдаҟьа' )
end

-- @see [[Ortodroma#Délky ortodromy]]
function p.range( lat1, long1, lat2, long2 )
	local radius = 6372.795
	local cosValue = math.sin( math.rad( lat1 ) ) * math.sin( math.rad( lat2 ) )
		+ math.cos( math.rad( lat1 ) ) * math.cos( math.rad( lat2 ) ) * math.cos( math.rad( long2 - long1 ) )
	if cosValue > 1 then return 0 end
	if cosValue < -1 then return radius * math.pi end
	return radius * math.acos( cosValue )
end

return p