Skip to content

Commit

Permalink
nueva descripcion en la ficha IUCN Red List
Browse files Browse the repository at this point in the history
  • Loading branch information
calonsot committed Jun 28, 2021
1 parent d15c0dd commit 9d35a41
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 34 deletions.
24 changes: 19 additions & 5 deletions app/controllers/especies_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ class EspeciesController < ApplicationController

skip_before_action :set_locale, only: [:create, :update, :edit_photos, :comentarios, :fotos_referencia,
:fotos_naturalista, :bdi_photos, :bdi_videos, :nombres_comunes_naturalista,
:nombres_comunes_todos, :consulta_registros, :cambia_id_naturalista, :resumen_wikipedia]
:nombres_comunes_todos, :consulta_registros, :cambia_id_naturalista, :resumen_wikipedia, :descripcion_iucn]

before_action :set_especie, only: [:show, :edit, :update, :destroy, :edit_photos, :media, :descripcion, :descripcion_app,
:consulta_registros, :cat_tax_asociadas,
:descripcion_catalogos, :comentarios, :bdi_photos, :bdi_videos,
:fotos_referencia, :fotos_naturalista, :nombres_comunes_naturalista,
:nombres_comunes_todos, :cambia_id_naturalista,
:dame_nombre_con_formato, :noticias, :media_tropicos, :resumen_wikipedia]
:dame_nombre_con_formato, :noticias, :media_tropicos, :resumen_wikipedia, :descripcion_iucn]

before_action :authenticate_usuario!, :only => [:new, :create, :edit, :update, :destroy, :destruye_seleccionados, :cambia_id_naturalista]

Expand All @@ -21,7 +21,7 @@ class EspeciesController < ApplicationController
:comentarios,
:fotos_referencia, :bdi_photos, :bdi_videos, :media_cornell, :media_tropicos, :fotos_naturalista, :nombres_comunes_naturalista,
:nombres_comunes_todos, :ejemplares_snib, :ejemplar_snib, :observacion_naturalista,
:cambia_id_naturalista, :dame_nombre_con_formato, :noticias, :resumen_wikipedia]
:cambia_id_naturalista, :dame_nombre_con_formato, :noticias, :resumen_wikipedia, :descripcion_iucn]

# Pone en cache el webservice que carga por default
caches_action :descripcion, :expires_in => eval(CONFIG.cache.fichas), :cache_path => Proc.new { |c| "especies/#{c.params[:id]}/#{c.params[:from]}" }, :if => :params_from_conabio_present?
Expand Down Expand Up @@ -492,6 +492,18 @@ def descripcion_catalogos
end
end

# La descripcion proveniente de IUCN redlist
def descripcion_iucn
iucn = IUCNService.new
iucn.taxon = @especie
iucn.encuentra_descripcion

@campos = [['geographicrange', 'Geographic Range'], ['habitat', 'Habitat'], ['population', 'Population'], ['populationtrend', 'Population Trend'], ['usetrade', 'Use and Trade'], ['threats', 'Threats'], ['conservationmeasures', 'Conservation Measures'], ['rationale', 'Rationale'], ['taxonomicnotes', 'Taxonomic Notes']]

@descripcion = iucn.datos
render 'especies/descripciones/descripcion_iucn'
end

# Descarga los registros de naturalista, snib y en el formato solicitado. Tambien se incluye para el app
def consulta_registros
if params[:coleccion].present? && params[:formato].present?
Expand Down Expand Up @@ -805,14 +817,16 @@ def asigna_variables_descripcion(app=false)
desc = eval("Api::#{params[:from].camelize}")
@descripcion = desc.new(taxon: @especie, app: app).dame_descripcion
@api = params[:from]
rescue
rescue => e
Rails.logger.info e.inspect
end
else
begin
desc = Api::Descripcion.new(taxon: @especie, app: app).dame_descripcion
@descripcion = desc[:descripcion]
@api = desc[:api]
rescue
rescue => e
Rails.logger.info e.inspect
end
end
end
Expand Down
209 changes: 184 additions & 25 deletions app/lib/web_services/iucn_service.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,55 @@
class IUCNService

attr_accessor :datos, :row, :validacion
attr_accessor :datos, :row, :validacion, :taxon

VERSION_IUCN = "2021-1"
CATEGORIAS_IUCN = {
'Data Deficient' => 'DD',
'Least Concern' => 'LC',
'Near Threatened' => 'NT',
'Vulnerable' => 'VU',
'Endangered' => 'EN',
'Critically Endangered' => 'CR',
'Extinct in The Wild' => 'EW',
'Extinct' => 'EX'
}

SUBPOBLACIONES = {
'Atlantic subpopulation' => 'Atlántico',
'East Pacific Ocean subpopulation' => 'Este del Océano Pacífico',
'East Pacific subpopulation' => 'Pacífico Este',
'Eastern North Pacific subpopulation' => 'Pacífico Norte Oriental',
'Eastern Pacific subpopulation' => 'Pacífico Oriental',
'North Pacific subpopulation' => 'Pacífico Norte',
'North West Atlantic subpopulation' => 'Atlántico Noroeste',
'Northeast Pacific subpopulation' => 'Noreste del Pacífico',
'Northwest Atlantic Ocean subpopulation' => 'Noroeste del Océano Atlántico',
'Western Atlantic subpopulation' => 'Atlántico Occidental',
'Western subpopulation' => 'Occidenta'
}

SALTA_CASOS = ['Búsqueda similar', 'Sin coincidencias']

# Enceuntra la descripcion por el nombre cientifico en IUCN
def encuentra_descripcion
endpoint = "species/narrative/#{taxon.nombre_cientifico.limpiar(tipo: 'ssp')}"
consulta_api(endpoint)

return if datos[:estatus]

# Busco en sinonimos
sinonimos = taxon.especies_estatus.sinonimos

if sinonimos.any?
sinonimos.each do |sinonimo|
endpoint = "species/narrative/#{sinonimo.especie.nombre_cientifico.limpiar(tipo: 'ssp')}"
consulta_api(endpoint)
return if datos[:estatus]
end
else
self.datos = { estatus: false, msg: 'No hubo resultados' }
end
end

# Consulta la categoria de riesgo de un taxon dado
def consultaRiesgo(opts)
Expand Down Expand Up @@ -32,14 +81,14 @@ def dameRiesgo(opc={})

# Accede al archivo que contiene los assessments y la taxonomia dentro de la carpeta versiones_IUCN
# NOTAS: Este archivo se baja de la pagina de IUCN y hay que unir el archivo de asessments con el de taxonomy y guardarlo bajo public/IUCN
def actualiza_IUCN(archivo)
def valida_version_IUCN(archivo)
csv_path = Rails.root.join('public', 'IUCN', archivo)
bitacora.puts 'Nombre científico en IUCN,Categoría en IUCN,Nombre en CAT,IdCAT,Estatus nombre,IdCAT válido,Nombre válido CAT,observaciones'
bitacora.puts 'Nombre científico en IUCN,Categoría en IUCN,Subpoblación,Nombre en CAT,IdCAT,Estatus nombre,IdCAT válido,Nombre válido CAT,mensaje,observación RelNombreCatalogo'
return unless File.exists? csv_path

CSV.foreach(csv_path, :headers => true) do |r|
self.row = r
self.datos = [row['scientificName'], row['redlistCategory'], nil, nil, nil, nil, nil, nil] # Se inicializa la respuesta vacia
self.datos = [row['scientificName'], row['redlistCategory'], row['subpopulationName'], nil, nil, nil, nil, nil, nil] # Se inicializa la respuesta vacia

v = Validacion.new

Expand All @@ -53,19 +102,19 @@ def actualiza_IUCN(archivo)
v.encuentra_por_nombre

self.validacion = v.validacion
self.datos[7] = validacion[:msg]
self.datos[8] = validacion[:msg]

if validacion[:estatus]
valida_extras # Solo un resultado y al menos fue coincidencia
else
if validacion[:taxones].present? # Mas de un resultado
if datos[7] == 'Existe más de una búsqueda exacta'
if datos[8] == 'Existe más de una búsqueda exacta'
cuantos_encontro = 0

validacion[:taxones].each do |taxon|
validacion[:taxon] = taxon
if valida_extras # Encontro el verdadero de entre las coincidencias
self.datos[7] = 'Búsqueda exacta'
self.datos[8] = 'Búsqueda exacta'
cuantos_encontro+= 1
break
end
Expand All @@ -86,14 +135,14 @@ def actualiza_IUCN(archivo)

if cuantos_encontro.length == 0
sin_coincidencias
elsif cuantos_encontro.length == 1
elsif cuantos_encontro.length == 1
sin_coincidencias
validacion[:taxon] = cuantos_encontro.first
self.datos[7] = 'Búsqueda similar'
self.datos[8] = 'Búsqueda similar'
valida_extras
else
sin_coincidencias
self.datos[7] = "Existe más de una búsqueda similar: #{validacion[:taxones].map{ |t| t.scat.catalogo_id }.join('|')}"
self.datos[8] = "Existe más de una búsqueda similar: #{validacion[:taxones].map{ |t| t.scat.catalogo_id }.join('|')}"
end

end # End si existe mas de una busqueda exacta con multiples coincidencias
Expand All @@ -107,6 +156,94 @@ def actualiza_IUCN(archivo)
bitacora.close
end

# Arroja un hash con los datos iterados, para posteriormente guardarlos en la base
def asigna_catalogocentralizado(archivo)
self.datos = {}
csv_path = Rails.root.join('log', 'validacion_IUCN', archivo)
return unless File.exists? csv_path

CSV.foreach(csv_path, :headers => true) do |row|
next if SALTA_CASOS.include?(row['observaciones'])
self.datos[row['IdCAT válido']] = { 'iucn' => [], 'sinonimos' => [] } unless datos[row['IdCAT válido']].present?

# Caso mas "simple" cuando es busqueda exacta
if row['observaciones'] == 'Búsqueda exacta'
datos[row['IdCAT válido']]['iucn'] << CATEGORIAS_IUCN[row['Categoría en IUCN']]
elsif row['observaciones'] == 'Búsqueda exacta y era un sinónimo'
datos[row['IdCAT válido']]['sinonimos'] << [row['Nombre científico en IUCN'], CATEGORIAS_IUCN[row['Categoría en IUCN']]]
end

end
end

# Este proceso se corre una vez que valida_version_IUCN fue aprobado por catalogos, se vuelve a leer el archivo
def actualiza_catalogocentralizado(archivo)
# Borra la anterior informacion de IUCN en catalogocentralizado
#EspecieCatalogo.where(catalogo_id: [25,26,27,28,29,30,31,32,1022,1023]).destroy_all

#datos = {}
#csv_path = Rails.root.join('public', 'IUCN', archivo)
#return unless File.exists? csv_path

#CSV.foreach(csv_path, :headers => true) do |row|
datos.each do |dato|
#next if SALTA_CASOS.include?(row['observaciones'])

# Caso mas "simple" cuando es busqueda exacta
if row['mensaje'] == 'Búsqueda exacta'
datos[row['IdCAT válido']] = { 'iucn' => '', 'observaciones' => '', 'iucn_sinonimos' => [], 'nombre valido CAT' => '' } unless datos[row['IdCAT válido']].present?
datos[row['IdCAT válido']]['nombre valido CAT'] = row['Nombre válido CAT']
datos[row['IdCAT válido']]['iucn'] = row['Categoría en IUCN']

sinonimos = datos[row['IdCAT válido']]['iucn_sinonimos']
if sinonimos.any?
# Hubo alguna categoria de IUCN que coincidio con el sinonimo y valido, caso 2
if (sinonimos.map{ |s| s[1] } & [row['Categoría en IUCN']]).any?
mensaje_caso2 = "En IUCN Red List #{VERSION_IUCN} con categoría #{CATEGORIAS_IUCN[row['Categoría en IUCN']]}, como "
mensaje_taxa_caso2 = []

sinonimos.each do |sinonimo|
if sinonimo[1] == row['Categoría en IUCN']
mensaje_taxa_caso2 << sinonimo[0]
end
end

datos[row['IdCAT válido']]['observaciones'] = mensaje_caso2 + row['Nombre válido CAT'] + ', ' + mensaje_taxa_caso2.join(', ') + '(ver relaciones de sinonimia).'
end

# El valido y el sinonimo tienen 2 categorias diferentes, caso 3
if (sinonimos.map{ |s| s[1] } - [row['Categoría en IUCN']]).any?
mensaje_caso3 = "Nombres válido y sinónimo con diferente categoría en IUCN Red List #{VERSION_IUCN}. "
mensaje_caso3 += "#{row['Nombre válido CAT']} con categoría #{CATEGORIAS_IUCN[row['Categoría en IUCN']]}, "
mensaje_taxa_caso3 = []

sinonimos = datos[row['IdCAT válido']]['iucn_sinonimos']
sinonimos.each do |sinonimo|
mensaje_taxa_caso3 << "#{sinonimo[0]} con categoría #{CATEGORIAS_IUCN[sinonimo[1]]}"
end

if datos[row['IdCAT válido']]['observaciones'].present?
datos[row['IdCAT válido']]['observaciones'] += mensaje_caso3 + mensaje_taxa_caso3.join(', ') + '(ver relaciones de sinonimia).'
else
datos[row['IdCAT válido']]['observaciones'] = mensaje_caso3 + mensaje_taxa_caso3.join(', ') + '(ver relaciones de sinonimia).'
end

end
end

elsif row['mensaje'] == 'Búsqueda exacta y era un sinónimo'
if datos[row['IdCAT válido']].present?
datos[row['IdCAT válido']]['iucn_sinonimos'] << [row['Nombre válido CAT'], row['Categoría en IUCN']]
else
datos[row['IdCAT válido']] = { 'iucn' => '', 'observaciones' => '', 'iucn_sinonimos' => [], 'nombre valido CAT' => '' }
datos[row['IdCAT válido']]['iucn_sinonimos'] << [row['Nombre válido CAT'], row['Categoría en IUCN']]
#datos[row['IdCAT válido']]['nombre valido CAT'] = row['Nombre válido CAT']
end
end

end
end


private

Expand All @@ -126,7 +263,7 @@ def mismo_phylum?
return true if validacion[:taxon].x_division.estandariza == row['phylumName'].estandariza
end

self.datos[7] = 'Sin coincidencias'
self.datos[8] = 'Sin coincidencias'
false
end

Expand All @@ -143,7 +280,7 @@ def misma_categoria?
cat_taxon = validacion[:taxon].categoria_taxonomica.nombre_categoria_taxonomica.estandariza

unless cat_taxon == categoria
self.datos[7] = 'Sin coincidencias'
self.datos[8] = 'Sin coincidencias'
return false
end

Expand All @@ -155,18 +292,18 @@ def dame_el_valido
if validacion[:taxon].estatus == 1
if taxon_valido = validacion[:taxon].dame_taxon_valido
validacion[:taxon] = taxon_valido
self.datos[5] = validacion[:taxon].scat.catalogo_id
self.datos[6] = validacion[:taxon].nombre_cientifico
self.datos[7] = 'Búsqueda exacta, era un sinónimo'
self.datos[6] = validacion[:taxon].scat.catalogo_id
self.datos[7] = validacion[:taxon].nombre_cientifico
self.datos[8] = 'Búsqueda exacta y era un sinónimo'
true
else
self.datos[7] = 'Es un sinónimo y hubo problemas al encontrar el válido'
self.datos[8] = 'Es un sinónimo y hubo problemas al encontrar el válido'
false
end

else
self.datos[5] = validacion[:taxon].scat.catalogo_id
self.datos[6] = validacion[:taxon].nombre_cientifico
self.datos[6] = validacion[:taxon].scat.catalogo_id
self.datos[7] = validacion[:taxon].nombre_cientifico
true
end
end
Expand All @@ -176,21 +313,43 @@ def valida_extras
return false unless misma_categoria?
return false unless mismo_phylum?

self.datos[2] = validacion[:taxon].nombre_cientifico
self.datos[3] = validacion[:taxon].scat.catalogo_id
self.datos[4] = validacion[:taxon].estatus == 2 ? 'Válido/Aceptado' : 'Sinónimo'
self.datos[3] = validacion[:taxon].nombre_cientifico
self.datos[4] = validacion[:taxon].scat.catalogo_id
self.datos[5] = validacion[:taxon].estatus == 2 ? 'Válido/Aceptado' : 'Sinónimo'

return true if ['Búsqueda similar'].include?(datos[7])
return dame_el_valido if ['Búsqueda exacta', 'Existe más de una búsqueda exacta'].include?(datos[7])
return true if ['Búsqueda similar'].include?(datos[8])
return dame_el_valido if ['Búsqueda exacta', 'Existe más de una búsqueda exacta'].include?(datos[8])
end

def sin_coincidencias
self.datos[2] = nil
self.datos[3] = nil
self.datos[4] = nil
self.datos[5] = nil
self.datos[6] = nil
self.datos[7] = 'Sin coincidencias'
self.datos[7] = nil
self.datos[8] = 'Sin coincidencias'
end

# Pasar solo una parte relativa del endpoint
def consulta_api(endpoint)
@iucn = CONFIG.iucn.api
@token = CONFIG.iucn.token
url = "#{@iucn}/#{endpoint}?token=#{@token}"

begin
uri = URI.escape(url)
resp = RestClient.get uri
jres = JSON.parse(resp)

if jres["result"].any?
self.datos = { estatus: true, resultado: jres["result"][0] }
else
self.datos = { estatus: false, msg: 'No hubo resultados' }
end

rescue => e
self.datos = { estatus: false, msg: e }
end
end

end
Expand Down
1 change: 1 addition & 0 deletions app/models/api/conabio_tecnico.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ class Api::ConabioTecnico < Api::Conabio
def initialize(opc = {})
super(opc)
self.servidor = servidor || CONFIG.site_url
self.timeout = 15
end

def nombre
Expand Down
Loading

0 comments on commit 9d35a41

Please sign in to comment.