Ir al contenido

Módulo:Ficha de astronáutica

De Wikipedia, la enciclopedia libre

Módulo que implementa la plantilla {{Ficha de astronáutica}}.

  • No está pensado para que sea llamado desde otros módulos.
  • La documentación se encuentra en la página de la plantilla.

local p = {}  --Exportadas

-- Variables globales
local args = {}       --Argumentos limpios
local entidad = {}    --Entidad completa
local categorias = {} --Categorías
local entidad_id = "" --ID de la entidad
local frame = {}      --Frame original

-- Dependencias (Módulos, funciones, etc)
local Wikidata      = require('Módulo:Wikidata')
local Wd            = require('Módulo:Wd')
local ModuloFicha   = require('Módulo:Ficha')
local ModuloPaginas	= require('Módulo:Páginas')
local EventoMision  = require('Módulo:EventoMisión')

local getArgs     = require('Módulo:Argumentos').obtenerArgumentosConValor
local Date		  = require('Módulo:Date')._Date
local CurrentDate = require('Módulo:Date')._current

-- Estilos
local estiloTituloSecciones = 'background: #ddf;'

-- Etiquetas
local direcciones = {
	["Q16938806"] = "frontal",  -- adelante
	["Q16938807"] = "trasero",  -- atrás
	["Q82806"]    = "cénit",    -- arriba
	["Q145825"]   = "nadir",    -- abajo
	["Q392907"]   = "estribor", -- derecha
	["Q11723008"] = "babor",    -- izquierda
	[""]          = "",  		-- default
}


function p.Ficha(f)
	  --Guardar frame
	frame = f
	  --Cargar frame en módulo de Wikidata
	Wikidata:setFrame(frame)
	  --Cargar argumentos
	args = getArgs(frame)
	  --Cargar ID de entidad
	entidad_id = (args['qid']~=nil and args['qid']~='') and args['qid'] or (mw.wikibase.getEntityIdForCurrentPage() and mw.wikibase.getEntityIdForCurrentPage() or '')
	if entidad_id=='' then return '<span class="error">Error: no se ha indicado una id de entidad y esta no es una página del espacio principal. Indica una id utilizando el parámetro |qid=.</span>' end
	  --Cargar entidad
	entidad = mw.wikibase.getEntity(entidad_id) 
	
	-- Datos calculados
	local imgs = getImages()
	local nssdc_id = args['NSSDC_ID']
	if nssdc_id~=nil then
		nssdc_id = '[https://nssdc.gsfc.nasa.gov/nmc/spacecraft/display.action?id='..nssdc_id..' '..nssdc_id..']'
	end
	nssdc_id = nssdc_id or Wd._property({"linked", "normal+",entidad_id,"P8913"})
	
	
	local instrumentoTitle = args['tipo_instrumento'] or args['telescopio']
	if instrumentoTitle~=nil then 
		instrumentoTitle = instrumentoTitle ..' principal'
		instrumentoTitle:gsub("^%l", string.upper)
	end
	local sitio_web = args['sitio_web'] or propiedad('P856')
	if sitio_web ~= nil and sitio_web ~= '' then
		sitio_web = '['..sitio_web.. ' enlace]'
	end
	
	local expedicion = getExpedicion()
	local tripulacion =	getTripulacion()
	local comienzo = getComienzoMision()
	local fin = getFinMision()
	
	local duracion_mision = ''
	if getLaunchDate()~='' then
		local parts = split(getLaunchDate(), '-')
		duracion_mision = ((#parts)>2) and frame:preprocess("{{intervalo tiempo|" .. getLaunchDate() .. '|'.. getLandingDate() ..'|show=dh}}') or ''
	end
	
	local sponsor = Wd._property({"linked",entidad_id,"P859",["sep%s"]=' · ',["sep"]=''})
	local op = Wd._property({"linked",entidad_id,"P137",["sep%s"]=' · ',["sep"]=''})
	
	local operator = (sponsor~='' and (sponsor .. ' · ') or '') .. op
	
	
	-- Ficha
	local Ficha = {
		titulo       = args['nombre'] or ModuloPaginas.nombrePagina({desambiguar='sí'}) or Wikidata.obtenerEtiquetaWikidata(),
		tipocabecera = 'cabecera transbordador',
		
		estilo       = 'width:25em; font-size: 90%',
		
		imagen       = formatImg(imgs.top),
		pie          = imgs.top.image~='' and imgs.top.caption or '',
		
		
		{'Nombres', args['lista_nombres']},
		
		{tipo='sección',
			{'Estado',                                  args['estado']},
			{'Tipo de misión',                          args['tipo_misión']},	
			{'Operador',                                args['operador'] or operator},	
			{'Coste',                                   args['coste'] or propiedad('P2130', {rangoMayor='sí'})},	
			{'Designación Harvard',                     args['designación_Harvard']},	
			{'[[International Designator|ID COSPAR]]',  getCOSPAR()},	
			{'[[Satellite Catalog Number|no. SATCAT]]', args['SATCAT'] or propiedad('P377')},	
			{'ID NSSDCA',                               nssdc_id},	
			{'Página web',                              sitio_web},	
			{'Duración planificada',                    args['duración_planificada']},	
			{'Duración de la misión',                   args['duración_misión'] or duracion_mision},	
			{'Distancia viajada',                       args['distancia_viajada']},	
			{'Órbitas completadas',                     args['órbitas_completadas'] or propiedad('P1418')},	
			{'Rango',                                   args['rango_suborbital']},	
			{'Apoastro',                                args['apogeo_suborbital']},	
		},
		
		{tipo='sección',
			titulo = 'Propiedades de la nave',
			estilotitulo = estiloTituloSecciones,
			{'Nave',                                       args['nave']},
			{'Tipo de nave',                               args['tipo_nave']},
			{'Modelo',                                     args['bus_nave'] or propiedad('P707')},
			{'Fabricante',                                 args['fabricante'] or propiedad('P176', {separador='<br>'})},
			{'Masa de lanzamiento',                        args['masa_lanzamiento'] or propiedad('P2067')},
			{'[[Tiempo de vida útil#BOL y EOL|Masa BOL]]', args['masa_BOL']},
			{'Masa de aterrizaje',                         args['masa_aterrizaje']},
			{'Peso en seco',                               args['masa_seco']},
			{'Masa de mercancía',                          args['masa_mercancía']},
			{'Dimensiones',                                args['dimensiones']},
			{'Configuración',                              args['configuración']},
			{'Potencia eléctrica',                         args['potencia'] or propiedad('P2791')},
			{'Propulsión',                                 args['propulsión']},
		},
		
		expedicion,
	
		tripulacion,
		
		comienzo,
		
		fin,
		
		{tipo='sección',
			titulo = 'Parámetros orbitales',
			estilotitulo = estiloTituloSecciones,
			{'Sistema de referencia',                                                                                                                                   args['órbita_referencia'] or propiedad('P552')},
			{'Régimen',                                                                                                                                                 args['órbita_régimen']},
			{'Longitud',                                                                                                                                                args['órbita_longitud']},
			{'Espacio',                                                                                                                                                 args['órbita_posición']},
			{'Semieje mayor',                                                                                                                                           args['órbita_semieje_mayor'] or propiedad('P2233')},
			{'[[Excentricidad orbital|Excentricidad]]',                                                                                                                 args['órbita_excentricidad'] or propiedad('P1096')},
			{'Altitud',                                                                                                                                                 args['órbita_altitud']},
			{'Altitud del [[Periastro|peri' .. (args['apsis'] ~= nil and args['apsis'] or 'astro') .. ']]',                                                             args['órbita_periastro'] or propiedad('P2244')},
			{'Altitud del [[Apoastro|ap' .. (args['apsis'] ~= nil and (args['apsis'] ~= 'helio' and ('o'..args['apsis']) or (' '..args['apsis'])) or 'astro') .. ']]', args['órbita_apoastro'] or propiedad('P2243')},
			{'[[Inclinación orbital|Inclinación]]',                                                                                                                     args['órbita_inclinación'] or propiedad('P2045')},
			{'[[Período orbital|Período]]',                                                                                                                             args['órbita_periodo'] or propiedad('P2146')},
			{'[[Longitud del nodo ascendente|RAAN]]',                                                                                                                   args['órbita_RAAN'] or propiedad('P2213')},
			{ '[[Argumento del periastro|Argumento del peri' .. ( args['apsis'] or 'astro' )  ..']]',                                                                   args['órbita_arg_periastro'] or propiedad('P2248')},
			{'[[Anomalía media]]',                                                                                                                                      args['órbita_anomalía_media']},
			{'Movimiento medio',                                                                                                                                        args['órbita_movimiento_medio']},
			{'Intervalo de repetición',                                                                                                                                 args['órbita_repeticiones']},
			{'Velocidad',                                                                                                                                               args['órbita_velocidad']},
			{'[[Época (astronomía)|Época]]',                                                                                                                            args['órbita_época']},
			{'{{nowrap|Número de revolución}}',                                                                                                                         args['órbita_número_revoluciones']},
			{'', ((args['órbita_apoastro'] or args['órbita_periastro'] or args['órbita_arg_periastro']) and not args['apsis'] and frame:preprocess( "{{REVISIONID}}" ) == "") and '<span class="error">Error: no se ha especificado un valor para el parámetro obligatorio "apsis"</span>' or ''} --Error si no se especifica "apsis"
		},
	
		{'', args['interplanetario']},
		{'', args['acople'] or getDockings()},
		
		{tipo='sección',
			titulo = 'Carga',
			estilotitulo = estiloTituloSecciones,
			{'',               args['items_carga']},
			{'Masa',           args['masa_carga']},
			{'Presurizada',    args['masa_carga_pres']},
			{'Sin presurizar', args['masa_carga_nopres']},
			{'Combustible',    args['masa_carga_fuel']},
			{'Gases',          args['masa_carga_gas']},
			{'Agua',           args['masa_carga_agua']},
		},
		
		{tipo='sección',
			titulo = instrumentoTitle,
			estilotitulo = estiloTituloSecciones,
			{'Nombre',              args['telescopio_nombre']},
			{'Tipo',                args['telescopio_tipo']},
			{'Diámetro',            args['telescopio_diámetro']},
			{'Longitud focal',      args['telescopio_longitud_focal']},
			{'Ratio focal',         args['telescopio_ratio_focal']},
			{'Área de recolección', args['telescopio_área']},
			{'Longitudes de onda',  args['telescopio_longitud_onda']},
			{'Resolución',          args['telescopio_resolución']},
		},
		
		{tipo='sección',
			titulo = 'Transpondedores',
			estilotitulo = estiloTituloSecciones,
			{'Nombre',                                           args['trans_nombre']},
			{'Banda',                                            args['trans_banda']},
			{'Frecuencia',                                       args['trans_frecuencia']},
			{'Ancho de banda',                                   args['trans_ancho_banda']},
			{'Capacidad',                                        args['trans_capacidad']},
			{'Área de cobertura',                                args['trans_cobertura']},
			{'Potencia [[Tubo de onda progresiva|TWTA]]',        args['trans_TWTA']},
			{'[[Potencia Isotrópica Radiada Equivalente|PIRE]]', args['trans_EIRP']},
			{'HPBW',                                             args['trans_HPBW']},
		},
		
		--[[   Sección vacía de ejemplo
		{tipo='sección',
			titulo = '',
			estilotitulo = estiloTituloSecciones
		},
		--]]
		
		piedetabla = (imgs.b1.image~='' and formatImg(imgs.b1)..'<br/>'..imgs.b1.caption or '')..
		(imgs.b2.image~='' and '<br/>'..formatImg(imgs.b2)..'<br/>'..imgs.b2.caption or '')..'</br>'..
		
		frame:expandTemplate{ title = 'Ficha de astronáutica/SucesiónSimple', args = { estiloencima = "border-top:1px #aaa solid; font-weight: bold", encima = args['programa'], izquierda = args['misión_anterior'], derecha = args['misión_siguiente'] } }..'</br>'..
		frame:expandTemplate{ title = 'Ficha de astronáutica/SucesiónSimple', args = { estiloencima = "border-top:1px #aaa solid; font-weight: bold", encima = args['programa2'], izquierda = args['misión_anterior2'], derecha = args['misión_siguiente2'] } },
	
		
		entidad = entidad_id
	}
	
	-- Comprobación de argumentos extraños
	local argsCheck = checkUnknown(args)
	if argsCheck ~= nil then 
		if frame:preprocess( "{{REVISIONID}}" ) == "" then
			table.insert(categorias, argsCheck .. ' ')
		end
		table.insert(categorias, '[[Categoría:Wikipedia:Páginas que utilizan la Ficha de astronáutica con un parámetro desconocido]]')
	end
	
	-- Agregar o no categorización
	namespace = mw.title.getCurrentTitle().namespace
    if categorias[1] and (namespace == 0 or namespace == 104) then
        return ModuloFicha.infobox(Ficha) .. table.concat(categorias)
    else
        return ModuloFicha.infobox(Ficha)
    end
	
end

--[[
	Función que extrae imágenes, tamaños, pies de foto y textos alternativos ya sea de los argumentos o de Wikidata
	
	Devuelve una tabla con "top", "b1" y "b2" con los datos de las imágenes que irán arriba, abajo (primera) y abajo (segunda) respectivamente
--]]
function getImages()
	local out = {}
	
	local insigniaStruct = {
		image =   args['insignia'] or propiedad('P154', {uno="sí"}) or '',
		size =    args['insignia_tamaño'] or '',
		upright = args['insignia_escalado'] or '0.82',
		caption = args['insignia_pie'] or ('Insignia de la misión '.. (args['nombre'] or Wikidata.obtenerEtiquetaWikidata() or ModuloPaginas.nombrePagina({desambiguar='sí'}))),
		alt =     args['insignia_alt'] or '',
	}
	local imagenStruct = {
		image =   args['imagen'] or propiedad('P18', {uno="sí", filtroCalificador="P180;Q345844;n"}) or '',
		size =    args['imagen_tamaño'] or '',
		upright = args['imagen_escalado'] or '1.18',
		caption = args['imagen_pie'] or propiedad('P18', {uno="sí", filtroCalificador="P180;Q345844;n", calificador="P2096", idioma="es"}) or '',
		alt =     args['imagen_alt'] or '',
	}
	local tripulacionStruct = {
		image =   args['tripulación_foto'] or propiedad('P18', {uno="sí", filtroCalificador="P180;Q345844"}) or '',
		size =    args['tripulación_foto_tamaño'] or '',
		upright = args['tripulación_foto_escalado'] or '1',
		caption = args['tripulación_foto_pie'] or propiedad('P18', {uno="sí", filtroCalificador="P180;Q345844", calificador="P2096", idioma="es"}) or '',
		alt =     args['tripulación_foto_alt'] or '',
	}
	
	if insigniaStruct.image and (args['tripulación_tamaño'] or tripulacionStruct.image ~= '') then  --Si tenemos insignia y es una misión tripulada
		out.top = insigniaStruct
		out.b1 =  imagenStruct
	else 	
		out.top = imagenStruct
		out.b1 =  insigniaStruct
	end
	out.b2 = tripulacionStruct
	
	return out
end

--[[
	Función que formatea una estructura de imágen de las devueltas por la anterior para su inclusión en la Ficha
--]]
function formatImg(imgInfo) 
	return imgInfo.image ~= '' and '[[File:'..imgInfo.image..'|frameless|alt='..imgInfo.alt..'|upright='..imgInfo.upright..'|'..imgInfo.size..']]' or ''
end


--[[
function p.formatearConstelacionCospar(tablaOrdenada, opciones)
	if(tablaOrdenada["id"] ~= nil) then
		local cospar_id = Wikidata.getPropiedad({propiedad='P247'}, mw.wikibase.getEntity(tablaOrdenada["id"]).claims['P247']) or ''
		if cospar_id~=nil and string.match(cospar_id, '^%d%d%d%d%-%d%d%d%a%a?%a?')~=nil then
			cospar_id = '[https://nssdc.gsfc.nasa.gov/nmc/spacecraft/display.action?id='..cospar_id..' '..cospar_id..'] <span style="font-size:85%">('.. Wikidata.obtenerEtiquetaWikidata(mw.wikibase.getEntity(tablaOrdenada["id"])) ..')</span><br>'
		end
		return cospar_id
	end
	
end
--]]

--[[
	Función que obtiene la ID COSPAR de un objeto lanzado al espacio
	Si se trata de una constelación obtiene las IDs de los satélites que la conforman y las formatea
--]]
function getCOSPAR()
	local returned = ""
	
	if propertyIs('P31','Q967145') then --Es constelación 
		
		local partes = Wd._properties({"raw",entidad_id,"P527",['sep%s']=",",['sep']=""})
		partes = split(partes, ",")
		for _,v in pairs(partes) do
			local cospar_id = Wd._property({v,'P247'}) or ''
			if cospar_id~=nil and string.match(cospar_id, '^%d%d%d%d%-%d%d%d%a%a?%a?')~=nil then
				cospar_id = '[https://nssdc.gsfc.nasa.gov/nmc/spacecraft/display.action?id='..cospar_id..' '..cospar_id..'] <span style="font-size:85%">('.. Wikidata.obtenerEtiquetaWikidata(mw.wikibase.getEntity(v)) ..')</span><br>'
			end
			returned = returned .. cospar_id
		end
		--returned = propiedad('P527', {['conjunción']=" ", separador=" ", ['valor-módulo']="Ficha de astronáutica", ['valor-función']="formatearConstelacionCospar"})
	else --No es constelación
		returned = Wd._property({entidad_id,'P247'}) or ''
		if returned~=nil and string.match(returned, '^%d%d%d%d%-%d%d%d%a%a?%a?')~=nil then
			returned = '[https://nssdc.gsfc.nasa.gov/nmc/spacecraft/display.action?id='..returned..' '..returned..']'
		end
	end
	
	return args['COSPAR_ID'] or returned 
end

function getComienzoMision() 
	if propertyIs("P31", "Q18201623") then -- Si es una expedición no tiene este apartado
		return {}
	end
	
	local lanzamiento_fecha = frame:preprocess("{{EventoMisión|lanzamiento|"..entidad_id.."|hora=sí}}")
	local lanzamiento_vehiculo = Wd._property({"linked","qualifier",entidad_id,"P375","P2598"})
	local lanzamiento_lugar = Wd._qualifiers({"linked",entidad_id,"P793","Q797476","P276"})
	local lanzamiento_contratista = Wd._properties({"linked",entidad_id,"P1079",["sep%s"]=' · ',["sep"]=''})
	
	
	return {tipo='sección',
				titulo = 'Comienzo de la misión',
				estilotitulo = estiloTituloSecciones,
				{'Lanzamiento',         args['lanzamiento_fecha'] or lanzamiento_fecha },
				{'Vehículo',            args['lanzamiento_vehículo'] or lanzamiento_vehiculo },
				{'Lugar',               args['lanzamiento_lugar'] or lanzamiento_lugar }, -- or propiedad('P1427') }, 
				{'Contratista',         args['lanzamiento_contratista'] or lanzamiento_contratista},
				{'Desplegado desde',    args['despliegue_lugar']},
				{'Fecha de despliegue', args['despliegue_fecha']},
				{'Entrada en servicio', args['entrada_servicio']},
			}
end

function getFinMision() 
	if propertyIs("P31", "Q18201623") or propertyIs("P31", "Q967145") then -- Si es una expedición o constelación no tiene este apartado
		return {}
	end
	
	local tipo_eliminacion = ''
	
	-- La nave vuelve a la tierra
	local is_splashdown = propertyIs("P1079", "Q193701") -- Solo comprueba spacex por ahora
	local aterrizaje_lugar = ""
	local aterrizaje_fecha = ""
	
	if args['tipo_eliminación'] and args['tipo_eliminación']~='' and args['tipo_eliminación']=='reingreso' then
		aterrizaje_fecha = ""
	else
		aterrizaje_fecha = frame:preprocess("{{EventoMisión|aterrizaje|"..entidad_id.."|hora=sí}}")
	end
	
	if is_splashdown then
		aterrizaje_lugar = Wd._qualifier({"linked",entidad_id,"P793","Q1642255","P276"})
	else
		aterrizaje_lugar = Wd._qualifier({"linked",entidad_id,"P793","Q844947","P276"})
	end
	
	
	-- La nave no vuelve a la tierra [pérdida de señal]
	local ultima_senal_fecha = ''
	local is_los = propertyIs("P793", "Q83494660") -- Existe 'loss of signal' (Q83494660) como 'special event' (P793)
	if is_los then
		tipo_eliminacion = 'Pérdida de señal'
		ultima_senal_fecha = getSignificantEventDate("Q83494660")
		-- Completar con otros campos según aparezcan
	end
	
	
	-- La nave no vuelve a la tierra [desactivación]
		-- TODO
	-- La nave no vuelve a la tierra [decaída]
		-- TODO
	
	
	local lanzamiento_lugar = Wd._qualifiers({"linked",entidad_id,"P793","Q797476","P276"})
	
	
	-- Si no hay ningún otro parámetro eliminar la fecha de aterrizaje. PROVISIONAL: hay que encontrar una manera mejor de decidir si una misión tendrá fecha de aterrizaje
	if not args['tipo_eliminación'] and not args['fin_declarado'] and not args['desactivación_fecha'] 
	and not args['destrucción_fecha'] and not args['última_señal_fecha'] and not args['recuperada_por'] 
	and not args['recuperado_fecha'] and not args['decaída_fecha'] and not args['aterrizaje_lugar'] then
		aterrizaje_fecha = ""
	end
	
	
	
	return {tipo='sección',
				titulo = 'Fin de la misión',
				estilotitulo = estiloTituloSecciones,
				{'Tipo',                  args['tipo_eliminación'] or tipo_eliminacion},
				{'Declarado',             args['fin_declarado']},
				{'Desactivado',           args['desactivación_fecha']},
				{'Destruido',             args['destrucción_fecha']},
				{'Último contacto',       args['última_señal_fecha'] or ultima_senal_fecha},
				{'Recuperado por',        args['recuperada_por'] or args['recuperado_por']},
				{'Fecha de recuperación', args['recuperado_fecha'] or args['recuperada_fecha']},
				{'Fecha de decaída',      args['decaída_fecha']},
				{'Aterrizaje',            args['aterrizaje_fecha'] or aterrizaje_fecha },
				{'Lugar',                 args['aterrizaje_lugar'] or aterrizaje_lugar },
			}
end

function getTripulacion()
	
	local tripulacion_miembros = Wd._properties({"linked",entidad_id,"P1029",["sep%s"]="<br>",['sep']=''})
	local splitted = (tripulacion_miembros~='') and split(Wd._properties({"linked",entidad_id,"P1029",["sep%s"]=",",['sep']=''}), ',') or {}
	local tripulacion_tamano = (#splitted==0) and '' or #splitted
	return {tipo='sección',
				titulo = 'Tripulación',
				estilotitulo = estiloTituloSecciones,
				{'Tamaño',                                     args['tripulación_tamaño'] or tripulacion_tamano},
				{'Miembros',                                   args['tripulación_miembros'] or tripulacion_miembros},
				{'En lanzamiento',                             args['tripulación_lanzamiento']},
				{'En aterrizaje',                              args['tripulación_aterrizaje']},
				{'Indicativo',                                 args['tripulación_indicativo'] or propiedad('P2317')},
				{'Expedición',                                 args['tripulación_expedición']},
				{'[[Actividad extravehicular|EVAs]]',          args['tripulación_EVAs']},
				{'Tiempo de [[Actividad extravehicular|EVA]]', args['tripulación_tiempo_EVA']},
			}
end

-- Solo funciona con expediciones a la ISS (por ahora)
function getExpedicion()
	
	-- Comprobar si es una expedición a la ISS
	if propertyIs("P31", "Q18201623") then
		local nave_llegada = Wd._properties({"linked",entidad_id,"P1876",['P3831']="Q854248"})
		local nave_marcha = Wd._properties({"linked",entidad_id,"P1876",['P3831']="Q844947"})
		local fecha_comienzo = Wd._property({entidad_id,"P580"})
		local fecha_fin = Wd._property({entidad_id,"P582"})
		
		
		return {tipo='sección',
					titulo = 'Expedición',
					estilotitulo = estiloTituloSecciones,
					{'Estación espacial', args['estación_espacial'] or '[[Estación Espacial Internacional]]'},
					{'Comenzó',           args['fecha_comienzo'] or fecha_comienzo},
					{'Finalizó',          args['fecha_fin'] or fecha_fin},
					{'Llegada',           args['nave_llegada'] or nave_llegada},
					{'Partida',           args['nave_marcha'] or nave_marcha},
				}
	else -- Por defecto, devolver los argumentos tal cual
		return {tipo='sección',
					titulo = 'Expedición',
					estilotitulo = estiloTituloSecciones,
					{'Estación espacial', args['estación_espacial']},
					{'Comenzó',           args['fecha_comienzo']},
					{'Finalizó',          args['fecha_fin']},
					{'Llegada',           args['nave_llegada']},
					{'Partida',           args['nave_marcha']},
				}
	end
end

function formatDocking(tipo_acople, objetivo_acople, puerto_acople, fecha_captura, fecha_acople, fecha_desacople, fecha_liberacion, tiempo_acoplado)
	local term = (tipo_acople and tipo_acople:lower() or 'acople')
	local title = " con " .. (objetivo_acople and objetivo_acople or '')
	local tiempo_acoplado_title = "Tiempo "
	
	if (term == "acople") then
		title = "Acople" .. title
		tiempo_acoplado_title = tiempo_acoplado_title .. "acoplado"
	elseif (term == "atraque") then
		title = "Atraque" .. title
		tiempo_acoplado_title = tiempo_acoplado_title .. "atracado"
	else
		title = "Acople" .. title
		tiempo_acoplado_title = tiempo_acoplado_title .. "acoplado"
	end
	
	local FichaIntegrada = {
		integrada    = 'sí',
		
		{tipo='sección',
			titulo = title,
			estilotitulo = estiloTituloSecciones,
			{'Puerto de ' .. term,                                                            puerto_acople or '' },
			{'Captura con el ' .. frame:preprocess("{{abbr|RMS|Remote Manipulator System}}"), (term=='atraque' and fecha_captura) and fecha_captura or '' },	
			{'Fecha de ' .. term,                               							  fecha_acople or '' },
			{'Fecha de des' .. term,                                                          fecha_desacople or '' },	
			{'Liberación con el RMS',                                                         (term=='atraque' and fecha_liberacion) and fecha_liberacion or '' },	
			{tiempo_acoplado_title,                                                           tiempo_acoplado or '' },
		}
	}

	return ModuloFicha.infobox(FichaIntegrada)
	
end

function getDockings() 
	local locations = {}
	
	function formatLocation(location) 
		if (locations[location]) then
			location = location .. ' <span style="font-size:85%">(Recolocación)</span>' 
		else
			locations[location] = true
		end
		if string.find(location, 'EEI') then location = 'la ' .. location end
		return location
	end
	
	local dockings = {}
	local dockings_dates = Wd._qualifiers({"raw",entidad_id,"P793","Q22988075","P585",["sep%s"]=",",["sep"]=""})
	if dockings_dates~='' then
		for _,v in pairs(split(dockings_dates, ',')) do
			
			--Ubicación
			local location = formatLocation(Wd._qualifier({"linked","short",entidad_id,"P793","Q22988075","P276",["P585"]=v}))
			local direction = direcciones[Wd._qualifier({"raw",entidad_id,"P793","Q22988075","P560",["P585"]=v})]
			table.insert(dockings, {
				["location"] = location,
				["port"] = Wd._qualifier({"linked",entidad_id,"P793","Q22988075","P546",["P585"]=v}),
				["direction"] = direction and direction or '',
				["point_time"] = Wd._qualifier({"raw",entidad_id,"P793","Q22988075","P585",["P585"]=v}),
				["refine_date"] = Wd._qualifier({entidad_id,"P793","Q22988075","P4241",["P585"]=v}),
			})
		end
	end
	
	
	local undockings = {}
	local undockings_dates = Wd._qualifiers({"raw",entidad_id,"P793","Q19858600","P585",["sep%s"]=",",["sep"]=""})
	if undockings_dates~='' then
		for _,v in pairs(split(undockings_dates, ',')) do
			local location = formatLocation(Wd._qualifier({"short","linked",entidad_id,"P793","Q19858600","P276",["P585"]=v}))
			local direction = direcciones[Wd._qualifier({"raw",entidad_id,"P793","Q19858600","P560",["P585"]=v})]
			table.insert(undockings, {
				["location"] = location,
				["port"] = Wd._qualifier({"linked",entidad_id,"P793","Q19858600","P546",["P585"]=v}),
				["direction"] = direction and direction or '',
				["point_time"] = Wd._qualifier({"raw",entidad_id,"P793","Q19858600","P585",["P585"]=v}),
				["refine_date"] = Wd._qualifier({entidad_id,"P793","Q19858600","P4241",["P585"]=v}),
			})
		end
	end
	
	local combined = {}
	local combined_dates = Wd._qualifiers({"raw",entidad_id,"P793","Q557450","P580",["sep%s"]=",",["sep"]=""})
	if combined_dates~='' then
		for _,v in pairs(split(combined_dates, ',')) do
			local location = formatLocation(Wd._qualifier({"short","linked",entidad_id,"P793","Q557450","P276",["P580"]=v}))
			local direction = direcciones[Wd._qualifier({"raw",entidad_id,"P793","Q557450","P560",["P580"]=v})]
			table.insert(combined, {
				["location"] = location,
				["port"] = Wd._qualifier({"linked",entidad_id,"P793","Q557450","P546",["P580"]=v}),
				["direction"] = direction and direction or '',
				["start_time"] = Wd._qualifier({"raw",entidad_id,"P793","Q557450","P580",["P580"]=v}),
				["end_time"] = Wd._qualifier({"raw",entidad_id,"P793","Q557450","P582",["P580"]=v}),
			})
		end
	end
	
	
	local retorno = {}
	
	for _,v in pairs(combined) do
		local tipo_acople, objetivo_acople, puerto_acople, fecha_captura, fecha_acople, fecha_desacople, fecha_liberacion, tiempo_acoplado
		tipo_acople = "acople"
		
		
		objetivo_acople = v.location
		puerto_acople = v.port .. ' ' .. v.direction
		
		local fecha_a = Date(v.start_time)
		fecha_captura = fecha_a:text("%-d de %B de %-Y")
		fecha_acople = fecha_a:text("%-d de %B de %-Y")
		
		if v.end_time ~= '' then
			local fecha_b = Date(v.end_time)
			fecha_desacople = fecha_b:text("%-d de %B de %-Y")
			fecha_liberacion = fecha_b:text("%-d de %B de %-Y")
			tiempo_acoplado = frame:preprocess("{{intervalo tiempo|" .. fecha_a:text() .. '|' .. fecha_b:text() .. '||show=d}}') -- con undocking
		else
			tiempo_acoplado = frame:preprocess("{{intervalo tiempo|" .. fecha_a:text() .. '||show=d}}') -- sin undocking	
		end
		
		retorno[v.start_time] = formatDocking(tipo_acople, objetivo_acople, puerto_acople, fecha_captura, fecha_acople, fecha_desacople, fecha_liberacion, tiempo_acoplado)
	end
	
	for _,v in pairs(dockings) do
		local tipo_acople, objetivo_acople, puerto_acople, fecha_captura, fecha_acople, fecha_desacople, fecha_liberacion, tiempo_acoplado
		tipo_acople = "acople"
		
		local fecha_a = Date(v.point_time .. ', ' .. v.refine_date)
		
		objetivo_acople = v.location
		puerto_acople = v.port .. ' ' .. v.direction
		
		fecha_captura = fecha_a:text("%C") .. ' UTC'
		fecha_acople = fecha_a:text("%C") .. ' UTC'
		
		if(undockings_dates~='' and ((#undockings-1)<=_)) then
			local fecha_b = Date(undockings[_].point_time .. ', ' .. undockings[_].refine_date)
			fecha_desacople = fecha_b:text("%C") .. ' UTC'
			fecha_liberacion = fecha_b:text("%C") .. ' UTC'
			
			tiempo_acoplado = frame:preprocess("{{intervalo tiempo|" .. fecha_a:text() .. '|'.. fecha_b:text() ..'|show=d}}') -- con undocking
		else		
			tiempo_acoplado = frame:preprocess("{{intervalo tiempo|" .. fecha_a:text() .. '||show=d}}') -- sin undocking
		end
		
		retorno[v.point_time] = formatDocking(tipo_acople, objetivo_acople, puerto_acople, fecha_captura, fecha_acople, fecha_desacople, fecha_liberacion, tiempo_acoplado)
	end
	
	local text_retorno = ""
	
	function compareDate(a, b) 
		da, ma, ya = string.match(a, "(%d+)-(%d+)-(%d+)")
		db, mb, yb = string.match(b, "(%d+)-(%d+)-(%d+)")
		return tonumber(da..ma..ya) < tonumber(db..mb..yb)	
	end
	
	function pairsByDateKey (t, comparator)
      local a = {}
      for n in pairs(t) do table.insert(a, n) end
      table.sort(a, comparator)
      local i = 0      -- iterator variable
      local iter = function ()   -- iterator function
        i = i + 1
        if a[i] == nil then return nil
        else return a[i], t[a[i]]
        end
      end
      return iter
	end

	for _,v in pairsByDateKey(retorno, compareDate) do
		text_retorno = text_retorno .. v
	end
	
	return text_retorno
end


----------------FUNCIONES VARIAS DE AYUDA, UTILIDADES

-- Función que comprueba si entre los valores de una propiedad [prop] se encuentra e valor [val]
function propertyIs(prop, val) 
	
	local value = propiedad(prop, {filtroValor=val})
	return (value ~= nil and value ~= '')
	
end

-- Función que separa la cadena de texto 'inputstr' utilizando un separador 'sep' 
function split(inputstr, sep) 
	sep=sep or '%s' 
	local t={}
	for field,s in string.gmatch(inputstr, "([^"..sep.."]*)("..sep.."?)") do 
		table.insert(t,field)  
		if s=="" then 
			return t 
		end 
	end 
end

-- Comprueba los argumentos recibidos por el módulo para generar un error en caso de que se encuentre uno no reconocido
function checkUnknown(arguments)
	local unknownValues = {}
	local previewOutput = ''
	
	function Set (list)
	  local set = {}
	  for _, l in ipairs(list) do set[l] = true end
	  return set
	end	
	
	local items = Set ( { "qid", "apsis", "nave_llegada", "auto", "masa_BOL", "masa_carga", "masa_carga_fuel", "masa_carga_gas", "masa_carga_pres", "masa_carga_nopres", "masa_carga_agua", "COSPAR_ID", "NSSDC_ID", "tripulación_indicativo", "tripulación_tiempo_EVA", "tripulación_EVAs", "tripulación_expedición", "tripulación_aterrizaje", "tripulación_lanzamiento", "tripulación_miembros", "tripulación_foto", "tripulación_foto_alt", "tripulación_foto_pie", "tripulación_foto_tamaño", "tripulación_foto_escalado", "tripulación_tamaño", "desactivación_fecha", "decaída_fecha", "decay_field", "fin_declarado", "nave_marcha", "despliegue_fecha", "despliegue_lugar", "destrucción_fecha", "dimensiones", "tipo_eliminación", "distance", "distancia_viajada", "acople", "masa_seco", "fecha_fin", "duración_planificada", "entrada_servicio", "designación_Harvard", "imagen", "imagen_alt", "imagen_pie", "imagen_tamaño", "imagen_escalado", "insignia", "insignia_alt", "insignia_pie", "insignia_tamaño", "insignia_escalado", "tipo_instrumento", "instrumentos", "instrumentos_lista", "interplanetario", "aterrizaje_fecha", "masa_aterrizaje", "aterrizaje_lugar", "última_señal_fecha", "lanzamiento_contratista", "lanzamiento_fecha", "masa_lanzamiento", "lanzamiento_vehículo", "lanzamiento_lugar", "fabricante", "duración_misión", "tipo_misión", "nombre", "lista_nombres", "misión_siguiente", "misión_siguiente2", "operador", "órbita_altitud", "órbita_apoastro", "órbita_arg_periastro", "órbita_excentricidad", "órbita_época", "órbita_inclinación", "órbita_longitud", "órbita_anomalía_media", "órbita_movimiento_medio", "órbita_periastro", "órbita_periodo", "órbita_RAAN", "órbita_referencia", "órbita_régimen", "órbita_repeticiones", "órbita_número_revoluciones", "órbita_semieje_mayor", "órbita_posición", "órbita_velocidad", "órbitas_completadas", "items_carga", "masa_mercancía", "potencia", "misión_anterior", "misión_anterior2", "programa", "programa2", "recuperada_por", "recuperada_fecha", "recuperado_por", "recuperado_fecha", "SATCAT", "estación_espacial", "nave", "bus_nave", "tipo_nave", "fecha_comienzo", "apogeo_suborbital", "rango_suborbital", "telescopio_área", "telescopio_diámetro", "telescopio_longitud_focal", "telescopio_ratio_focal", "telescopio_nombre", "telescopio_resolución", "telescopio_tipo", "telescopio_longitud_onda", "trans_banda", "trans_ancho_banda", "trans_capacidad", "trans_cobertura", "trans_EIRP", "trans_frecuencia", "trans_HPBW", "trans_TWTA", "sitio_web", "estado", "coste", "propulsión", "configuración", "trans_nombre" } )

	
	for k,v in pairs(arguments) do
		if not items[k] then
			table.insert(unknownValues, k)
		end
	end
	if #unknownValues > 0 then
		for _,v in ipairs(unknownValues) do 
			previewOutput = previewOutput .. '<div class="hatnote" style="color:red"><strong>Atención:</strong> Se llama a la plantilla \'[[Plantilla:Ficha de astronáutica|Ficha de astronáutica]]\' con el parámetro desconocido ' .. v .. ' (este mensaje solo se muestra en la vista previa).</div>'
		end
		return previewOutput
	end
	
	return nil
end

-- Obtiene el valor de una propiedad o calificador del elemento de Wikidata. Utilizando [[Módulo:Wikidata]]
function propiedad(pid, opciones)
    if entidad and entidad.claims and entidad.claims[pid] then
        if not opciones then
            opciones = {} --{['linkback']='sí'}
        end
		
        opciones.entityId = entidad.id
        opciones.propiedad = pid

        valorPropiedad = Wikidata.getPropiedad(opciones,entidad.claims[pid])

        if not valorPropiedad then
            return
        end

        return valorPropiedad
    end
	
end

function getLandingDate()
	local landing = Wd._qualifier({"raw","qualifier",entidad_id,"P793","Q844947","P585","P4241",["sep%q"]=',_'})
	local splashdown = Wd._qualifier({"raw","qualifier",entidad_id,"P793","Q1642255","P585","P4241",["sep%q"]=',_'})
	local time_of_landing = Wd._property({"raw","qualifier",entidad_id,"P620","P4241",["format"]='%p[, %q]'})
	local time_of_reentry = Wd._property({"raw","qualifier",entidad_id,"P621","P4241",["format"]='%p[, %q]'})
	if landing ~= '' then
		return landing
	elseif splashdown ~= '' then
		return splashdown
	elseif time_of_landing ~= '' then
		return time_of_landing
	else
		return time_of_reentry
	end
end

function getLaunchDate()
	local launch = Wd._qualifier({"raw","qualifier",entidad_id,"P793","Q797476","P585","P4241",["sep%q"]=',_'})
	local time_of_launch = Wd._property({"raw","qualifier",entidad_id,"P619","P4241",["format"]='%p[, %q]'})
	if launch ~= '' then
		return launch	
	else
		return time_of_launch
	end
end

function getSignificantEventDate(event) -- event = Q identifier of the special event
	local date_time = Wd._qualifier({"raw","qualifier",entidad_id,"P793",event,"P585","P4241",["sep%q"]=',_'})
	return date_time
end


return p