Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Avistamientos OVNI\n",
"**Autores de la versión Java**: Mariano González y Fermín Cruz\n",
"\n",
"**Idea original y adaptación a Notebook**: Daniel Mateos-García\n",
"\n",
"**version 1.0.1**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"| |\n",
"|:---|\n",
"**MUY IMPORTANTE:** Antes de empezar este Notebook, debes haber trabajado hasta el bloque 3 de los apuntes de teoría disponibles en la plataforma de enseñanza virtual. Sin este requisito, problablemente entenderás muy poco de lo que se detalla a continuación."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Éste es el primero de los ejercicios típicos de la asignatura que vamos a realizar. Lo único que aún se va a posponer un poco, va a ser los tratamientos secuenciales con *Streams* (en su lugar los haremos con bucles). Veamos el enunciado.\n",
"<!-- blank line -->\n",
"----\n",
"<!-- blank line -->\n",
"En este ejercicio vamos a trabajar con un conjunto de datos con información sobre\n",
"avistamientos de objetos voladores no identificados (OVNIs) en los Estados Unidos. El objetivo\n",
"del ejercicio es leer estos datos y realizar distintas operaciones con ellos.\n",
"Los datos se encuentran almacenados en un fichero en formato CSV codificado en UTF-8. Cada\n",
"registro del fichero ocupa una línea y contiene los datos correspondientes a un avistamiento:\n",
"fecha en la que se produjo del avistamiento, ciudad donde se produjo, duración en segundos,\n",
"forma observada del avistamiento y latitud y longitud del lugar donde se produjo.\n",
"Estas son las primeras líneas del fichero. La primera línea es una cabecera que contiene los\n",
"nombres de los campos del registro:\n",
"\n",
"|date;|city;|duration;|shape;|location|\n",
"|:--|:--|:--|:--|:--|\n",
"|04/07/2011;|muncie;|240;|OTRA;|(40.1933333, -85. 3863889)|\n",
"|07/04/2005;|deming (somewhere near);|1200;|OTRA;|(32.2686111, -107.7580556)|\n",
"|12/03/2010;|erie;|300;|OTRA;|(42.1291667, -80. 0852778)|\n",
"|04/07/2013;|seattle;|600;|OTRA;|(47.6063889, -122.3308333)|\n",
"|09/09/2003;|clearwater;|120;|TRIANGULAR;|(27.9655556, -82. 8002778)|\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Los tipos que forman el modelo de datos son los siguientes:\n",
"+ **Hemisferio**: tipo enumerado con los dos valores posibles de un hemisferio terrestre.\n",
"+ **Coordenadas**: ubicación geográfica de un avistamiento.\n",
"+ **Avistamiento**: tipo que representa un avistamiento OVNI.\n",
"+ **Avistamientos**: tipo contenedor que representa una colección de avistamientos.\n",
"+ **FactoriaAvistamientos**: tipo factoría para cargar los avistamientos del fichero. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Los tipos principales con los que vamos a trabajar son *Avistamiento*, *Avistamientos* y *FactoriaAvistamientos* (los restantes se pueden considerar tipos de apoyo o auxiliares). El objetivo de este tipo de ejercicios es:\n",
"+ **Leer un fichero CSV en el que cada línea representa un objeto.**\n",
"+ **Almacenar cada objeto en una estructura de datos.**\n",
"+ **Realizar operaciones con los datos almacenados.**\n",
"\n",
"La **factoría** será la encargada de leer el fichero, convertir cada línea de texto en un objeto y almacenarlo en una estructura de datos o producir un stream. Las operaciones estarán a cargo del tipo **contenedor** (en este caso *Avistamientos*). Y el tipo **básico** se corresponderá con una unidad (un *Avistamiento*).\n",
"\n",
"El objetivo de hoy es intentar hacer el tipo *Avistamiento* completo (el tipo básico), y una parte del tipo *Avistamientos* (tipo contenedor). El tipo *Coordenadas* ya apareció en el último Notebook. Os pongo de nuevo el enunciado y la solución.\n",
"\n",
"**Tipo Coordenadas**\n",
"+ Propiedades:\n",
" + latitud, de tipo Double. Consultable y modificable. Latitud de las coordenadas.\n",
" + longitud, de tipo Double. Consultable y modificable. Longitud de las coordenadas.\n",
" + hemisferio, del tipo enumerado Hemisferio, que puede tomar los valores NORTE, SUR y ECUADOR. Consultable. Hemisferio al que pertenecen las coordenadas. Recuerda que si la latitud es positiva estaremos en el hemisferio norte, y si es negativa en el hemisferio sur (la latitud cero pertenece al ecuador).\n",
"+ Constructores:\n",
" + Un constructor que recibe un parámetro por cada propiedad básica del tipo, en el\n",
"mismo orden en el que están definidas.\n",
" + Un constructor sin parámetros que crea un objeto con latitud 0º y longitud 0º.\n",
" + Un constructor a partir de String. Formato: (latitud, longitud). P. ej. “(-1.5, 0.22)”\n",
"+ Criterio de igualdad: dos coordenadas son iguales si su latitud y su longitud son iguales.\n",
"+ Criterio de ordenación: por latitud, y a igualdad de esta por longitud.\n",
"+ Representación como cadena: (latitud, longitud)\n",
"+ Restricciones:\n",
" + La latitud debe estar comprendida entre -90º y +90º.\n",
" + La longitud debe estar comprendida entre -180º y +180º.\n",
"+ Otras operaciones:\n",
" + ```Double getDistancia(Coordenadas c)``` Calcula la distancia euclidiana entre dos coordenadas\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"public enum Hemisferio {\n",
"\tNORTE, SUR, ECUADOR\n",
"}\n",
"\n",
"public class Coordenadas implements Comparable<Coordenadas> {\n",
"\tprivate Double latitud;\n",
"\tprivate Double longitud;\n",
"\n",
"\t/*\n",
"\t * constructores\n",
"\t */\n",
"\tpublic Coordenadas(Double latitud, Double longitud) {\n",
"\t\tif(!(-90<=latitud && latitud<=90)) {\n",
"\t\t\tthrow new IllegalArgumentException(\"La latitud debe estar comprendida entre -90 y +90 grados\");\n",
"\t\t}\n",
"\t\tif(!(-180<=longitud && longitud<=180)) {\n",
"\t\t\tthrow new IllegalArgumentException(\"La longitud debe estar comprendida entre -180 y +180 grados\");\n",
"\t\t}\n",
"\t\tthis.latitud = latitud;\n",
"\t\tthis.longitud = longitud;\n",
"\t}\n",
"\n",
"\tpublic Coordenadas() {\n",
"\t\tthis.latitud = 0.;\n",
"\t\tthis.longitud = 0.;\n",
"\t}\n",
"\n",
"\tpublic Coordenadas(String s) {\n",
"\t\tString s1 = s.replace(\"(\", \"\").replace(\")\", \"\");\n",
"\t\tString[] trozos = s1.split(\",\");\n",
"\n",
"\t\tif (trozos.length != 2) {\n",
"\t\t\tthrow new IllegalArgumentException(\"Formato de cadena no válido\");\n",
"\t\t}\n",
"\t\tDouble latitud = Double.valueOf(trozos[0].trim());\n",
"\t\tDouble longitud = Double.valueOf(trozos[1].trim());\n",
" \n",
" if(!(-90<=latitud && latitud<=90)) {\n",
"\t\t\tthrow new IllegalArgumentException(\"La latitud debe estar comprendida entre -90 y +90 grados\");\n",
"\t\t}\n",
"\t\tif(!(-180<=longitud && longitud<=180)) {\n",
"\t\t\tthrow new IllegalArgumentException(\"La longitud debe estar comprendida entre -180 y +180 grados\");\n",
"\t\t}\n",
"\t\tthis.latitud = latitud;\n",
"\t\tthis.longitud = longitud;\n",
"\t}\n",
"\n",
"\t/*\n",
"\t * getters y setters\n",
"\t */\n",
"\tpublic Double getLatitud() {\n",
"\t\treturn latitud;\n",
"\t}\n",
"\n",
"\tpublic void setLatitud(Double latitud) {\n",
"\t\tif(!(-90<=latitud && latitud<=90)) {\n",
"\t\t\tthrow new IllegalArgumentException(\"La latitud debe estar comprendida entre -90 y +90 grados\");\n",
"\t\t}\n",
"\t\t\n",
"\t\tthis.latitud = latitud;\n",
"\t}\n",
"\n",
"\tpublic Double getLongitud() {\n",
"\t\treturn longitud;\n",
"\t}\n",
"\n",
"\tpublic void setLongitud(Double longitud) {\n",
"\t\tif(!(-180<=longitud && longitud<=180)) {\n",
"\t\t\tthrow new IllegalArgumentException(\"La longitud debe estar comprendida entre -180 y +180 grados\");\n",
"\t\t}\n",
"\t\tthis.longitud = longitud;\n",
"\t}\n",
"\n",
"\t/*\n",
"\t * propiedad derivada\n",
"\t */\n",
"\tpublic Hemisferio getHemisferio() {\n",
"\t\tif (this.getLatitud() > 0) {\n",
"\t\t\treturn Hemisferio.NORTE;\n",
"\t\t} else if (this.getLatitud() < 0) {\n",
"\t\t\treturn Hemisferio.SUR;\n",
"\t\t} else {\n",
"\t\t\treturn Hemisferio.ECUADOR;\n",
"\t\t}\n",
"\t}\n",
"\t\n",
"\t/*\n",
"\t * toString\n",
"\t */\n",
"\tpublic String toString() {\n",
"\t\treturn \"(\"+this.getLatitud()+\" ,\"+this.getLongitud()+\")\";\n",
"\t}\n",
"\n",
"\t/*\n",
"\t * equals y hashCode\n",
"\t */\n",
"\tpublic boolean equals(Object o) {\n",
"\t\tboolean r = false;\n",
"\t\tif (o instanceof Coordenadas) {\n",
"\t\t\tCoordenadas c = (Coordenadas) o;\n",
"\t\t\tr = this.getLatitud().equals(c.getLatitud()) \n",
"\t\t\t\t\t&& this.getLongitud().equals(c.getLongitud());\n",
"\t\t}\n",
"\t\treturn r;\n",
"\t}\n",
"\t\n",
"\tpublic int hashCode() {\n",
"\t\treturn this.getLatitud().hashCode() + this.getLongitud().hashCode() * 31;\n",
"\t}\n",
"\n",
"\t/*\n",
"\t *\torden natural \n",
"\t */\n",
"\tpublic int compareTo(Coordenadas c) {\n",
"\t\tint r=this.getLatitud().compareTo(c.getLatitud());\n",
"\t\tif(r==0) {\n",
"\t\t\tr=this.getLongitud().compareTo(c.getLongitud());\n",
"\t\t}\n",
"\t\treturn r;\n",
"\t}\n",
"\t/*\n",
"\t * operaciones\n",
"\t */\n",
"\tpublic Double getDistancia(Coordenadas c) {\n",
"\t\tDouble difLat=this.getLatitud()-c.getLatitud();\n",
"\t\tDouble difLon=this.getLongitud()-c.getLongitud();\n",
"\t\treturn Math.sqrt(difLat*difLat + difLon*difLon);\n",
"\t}\n",
"\t\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Ejercicio: Define el tipo Avistamiento con las siguientes especificaciones:**\n",
"+ Propiedades:\n",
" + fecha, de tipo LocalDate. Consultable. Fecha en la que se produce el avistamiento.\n",
" + lugar, de tipo String. Consultable y modificable. Ciudad donde se produce el\n",
"avistamiento.\n",
" + duracion, de tipo Duration. Consultable y modificable. Duración del avistamiento.\n",
" + forma, del tipo enumerado Forma, que puede tomar los valores CIRCULAR,\n",
"TRIANGULAR y OTRA. Consultable. Forma observada del avistamiento.\n",
" + ubicacion, de tipo Coordenadas. Consultable. Coordenadas geográficas en las que se\n",
"produce el avistamiento.\n",
" + año, de tipo Integer. Consultable. Año del avistamiento.\n",
"+ Constructores:\n",
" + Un constructor que recibe un parámetro por cada propiedad básica del tipo, en el\n",
"mismo orden en el que aparecen en el enunciado.\n",
" + Un constructor que recibe un parámetro por cada propiedad básica del tipo salvo la\n",
"fecha, para la que se toma la fecha del día actual.\n",
" + Un constructor a partir de String. Ejemplo de formato de la cadena: “21/01/2019;\n",
"Sevilla; 30; CIRCULAR; (37.38, -5.97)”. Para convertir la fecha puede usar:\n",
"```\n",
"DateTimeFormatter formatter=DateTimeFormatter.ofPattern(\"dd/MM/yyyy\");\n",
"LocalDate fecha=LocalDate.parse(texto con la fecha, formatter);\n",
"```\n",
"+ Criterio de igualdad: dos avistamientos son iguales si su fecha y su lugar son iguales.\n",
"+ Criterio de ordenación: por fecha, y a igualdad de ésta por lugar.\n",
"+ Representación como cadena: [dd/MM/yyyy, lugar, forma]. Para formatear la fecha, puede usar el siguiente método:\n",
"```\n",
"private String formatea(LocalDate f) {\n",
"\t\tDateTimeFormatter formatter=DateTimeFormatter.ofPattern(\"dd/MM/yyyy\");\n",
"\t\treturn f.format(formatter);\n",
"}\n",
"```\n",
"+ Restricciones:\n",
" + La duración del avistamiento debe ser positiva.\n",
" + La fecha del avistamiento debe ser igual o anterior a la fecha actual.\n",
" \n",
"+ Otras operaciones:\n",
" + ```Double getDistancia(Avistamiento av)```: calcula la distancia entre dos avistamientos\n",
" \n",
"Para poder usar fechas, horas, instantes y duraciones, debes importarlas primero. Para ello, basta con poner:\n",
"\n",
"```\n",
"import java.time.*;\n",
"import java.time.format.*;\n",
"```\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import java.time.*;\n",
"import java.time.format.*;\n",
"\n",
"public enum Forma {\n",
"\tCIRCULAR, TRIANGULAR, OTRA\n",
"}\n",
"\n",
"public class Avistamiento implements Comparable<Avistamiento>{\n",
" \n",
"\t/*\n",
"\t * Atributos (prop. básicas)\n",
"\t */\n",
"\tprivate LocalDate fecha;\n",
"\tprivate String lugar; \n",
"\tprivate Duration duracion; \n",
"\tprivate Forma forma;\n",
"\tprivate Coordenadas ubicacion;\n",
"\t\n",
"\t/*\n",
"\t * constructores\n",
"\t */\n",
"\tpublic Avistamiento(LocalDate fecha, String lugar, Duration duracion, Forma forma, Coordenadas ubicacion) {\n",
"\t\tif(duracion.isNegative()) {\n",
"\t\t\tthrow new IllegalArgumentException(\"La duración debe ser positiva\");\n",
"\t\t}\n",
"\t\tif(fecha.isAfter(LocalDate.now())) {\n",
"\t\t\tthrow new IllegalArgumentException(\"La fecha debe ser igual o anterior a la actual\");\n",
"\t\t}\n",
"\t\t\n",
"\t\tthis.fecha = fecha;\n",
"\t\tthis.lugar = lugar;\n",
"\t\tthis.duracion = duracion;\n",
"\t\tthis.forma = forma;\n",
"\t\tthis.ubicacion = ubicacion;\n",
"\t}\n",
"\tpublic Avistamiento(String lugar, Duration duracion, Forma forma, Coordenadas ubicacion) {\n",
"\t\tif(duracion.isNegative()) {\n",
"\t\t\tthrow new IllegalArgumentException(\"La duración debe ser positiva\");\n",
"\t\t}\n",
"\t\t\n",
"\t\tthis.fecha = LocalDate.now();\n",
"\t\tthis.lugar = lugar;\n",
"\t\tthis.duracion = duracion;\n",
"\t\tthis.forma = forma;\n",
"\t\tthis.ubicacion = ubicacion;\n",
"\t}\n",
"\tpublic Avistamiento(String s) {\n",
"\t\t//formato de s: “21/01/2019; Sevilla; 30; CIRCULAR; (37.38, -5.97)”\n",
"\t\tString[] trozos=s.split(\";\");\n",
"\t\tif(trozos.length!=5) {\n",
"\t\t\tthrow new IllegalArgumentException(\"Formato de cadena no válido\");\n",
"\t\t}\n",
"\t\tDateTimeFormatter formatter=DateTimeFormatter.ofPattern(\"dd/MM/yyyy\");\n",
"\t\tLocalDate fecha=LocalDate.parse(trozos[0].trim(), formatter);\n",
"\t\t\n",
"\t\tString lugar=trozos[1].trim();\n",
"\t\t\n",
"\t\tLong segundos=Long.valueOf(trozos[2].trim());\n",
"\t\tDuration duracion=Duration.ofSeconds(segundos);\n",
"\t\t\n",
"\t\tForma forma=Forma.valueOf(trozos[3].trim());\n",
"\t\t\n",
"\t\t//Fíjate que para las Coordenadas usamos su constructor basado en String\n",
"\t\tCoordenadas ubicacion=new Coordenadas(trozos[4].trim());\n",
"\t\t\n",
"\t\tif(duracion.isNegative()) {\n",
"\t\t\tthrow new IllegalArgumentException(\"La duración debe ser positiva\");\n",
"\t\t}\n",
"\t\tif(fecha.isAfter(LocalDate.now())) {\n",
"\t\t\tthrow new IllegalArgumentException(\"La fecha debe ser igual o anterior a la actual\");\n",
"\t\t}\n",
"\t\t\n",
"\t\tthis.fecha = fecha;\n",
"\t\tthis.lugar = lugar;\n",
"\t\tthis.duracion = duracion;\n",
"\t\tthis.forma = forma;\n",
"\t\tthis.ubicacion = ubicacion;\n",
"\t}\n",
"\t\n",
"\t/*\n",
"\t * getters y setters\n",
"\t */\n",
"\t\n",
"\tpublic Integer getAño() {\n",
"\t\treturn this.getFecha().getYear();\n",
"\t}\n",
"\n",
"\tpublic String getLugar() {\n",
"\t\treturn lugar;\n",
"\t}\n",
"\n",
"\tpublic void setLugar(String lugar) {\n",
"\t\tthis.lugar = lugar;\n",
"\t}\n",
"\n",
"\tpublic Duration getDuracion() {\n",
"\t\treturn duracion;\n",
"\t}\n",
"\n",
"\tpublic void setDuracion(Duration duracion) {\n",
"\t\tif(duracion.isNegative()) {\n",
"\t\t\tthrow new IllegalArgumentException(\"La duración debe ser positiva\");\n",
"\t\t}\n",
"\t\tthis.duracion = duracion;\n",
"\t}\n",
"\n",
"\tpublic LocalDate getFecha() {\n",
"\t\treturn fecha;\n",
"\t}\n",
"\n",
"\tpublic Forma getForma() {\n",
"\t\treturn forma;\n",
"\t}\n",
"\n",
"\tpublic Coordenadas getUbicacion() {\n",
"\t\treturn ubicacion;\n",
"\t}\n",
"\t/*\n",
"\t * toString: fecha, lugar, forma\n",
"\t */\n",
"\tpublic String toString() {\n",
"\t\treturn \"[\"+formatea(this.getFecha())+\", \"+this.getLugar()+\", \"+this.getForma()+\"]\";\n",
"\t}\n",
"\t\n",
"\tprivate String formatea(LocalDate f) {\n",
"\t\tDateTimeFormatter formatter=DateTimeFormatter.ofPattern(\"dd/MM/yyyy\");\n",
"\t\treturn f.format(formatter);\n",
"\t}\n",
"\t/*\n",
"\t * equals y hashCode: fecha, lugar\n",
"\t */\n",
"\tpublic boolean equals(Object o) {\n",
"\t\tboolean r = false;\n",
"\t\tif (o instanceof Avistamiento) {\n",
"\t\t\tAvistamiento a = (Avistamiento) o;\n",
"\t\t\tr = this.getFecha().equals(a.getFecha()) && this.getLugar().equals(a.getLugar());\n",
"\t\t}\n",
"\t\treturn r;\n",
"\t}\n",
"\tpublic int hashCode() {\n",
"\t\treturn this.getFecha().hashCode() + this.getLugar().hashCode() * 31;\n",
"\t}\n",
"\t\n",
"\t/*\n",
"\t * compareTo: fecha, lugar\n",
"\t */\n",
"\tpublic int compareTo(Avistamiento a) {\n",
"\t\tint r=this.getFecha().compareTo(a.getFecha());\n",
"\t\tif(r==0) {\n",
"\t\t\tr=this.getLugar().compareTo(a.getLugar());\n",
"\t\t}\n",
"\t\treturn r;\n",
"\t}\n",
"\t\n",
"\t/*\n",
"\t * operaciones\n",
"\t */\n",
"\tpublic Double getDistancia(Avistamiento av) {\n",
"\t\treturn this.getUbicacion().getDistancia(av.getUbicacion());\n",
"\t}\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Ejercicio: Define el tipo Avistamientos con las siguientes especificaciones:**\n",
"+ Propiedades:\n",
" + avistamientos, de tipo Set&lt;Avistamiento&gt;. Consultable. Conjunto de avistamientos.\n",
"+ Constructores:\n",
" + Un constructor sin parámetros.\n",
" + Un constructor a partir de un Stream&lt;Avistamiento&gt;. \n",
" Para ello utilice la siguiente línea:\n",
" \n",
" ```this.avistamientos = avistamientos.collect(Collectors.toSet());```\n",
"+ Representación como cadena: La misma que la propiedad *avistamientos*\n",
"+ Otras operaciones:\n",
" + ```void añadirAvistamiento(Avistamiento av)```: añade un avistamiento al conjunto\n",
" \n",
"Para usar *Stream* y *Collectors*, debes importarlos primero. Para ello, basta con poner: \n",
"```import java.util.stream.*;```\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"import java.util.stream.*;\n",
"\n",
"public class Avistamientos {\n",
"\tpublic Set<Avistamiento> avistamientos;\n",
"\n",
"\t/*\n",
"\t * constructores\n",
"\t */\n",
"\tpublic Avistamientos() {\n",
"\t\tthis.avistamientos = new HashSet<Avistamiento>();\n",
"\t}\n",
"\n",
"\tpublic Avistamientos(Stream<Avistamiento> avistamientos) {\n",
"\t\tthis.avistamientos = avistamientos.collect(Collectors.toSet());\n",
"\t}\n",
"\n",
"\t/*\n",
"\t * getters y setters\n",
"\t */\n",
"\tpublic Set<Avistamiento> getAvistamientos() {\n",
"\t\t//recuerda devolver una copia\n",
"\t\treturn new HashSet<Avistamiento>(this.avistamientos);\n",
"\t}\n",
"\n",
"\t/*\n",
"\t * toString\n",
"\t */\n",
"\tpublic String toString() {\n",
"\t\treturn this.getAvistamientos().toString();\n",
"\t}\n",
" /*\n",
"\t * operaciones\n",
"\t */\n",
"\tpublic void añadirAvistamiento(Avistamiento av) {\n",
" //recuerda NO usar getAvistamientos()\n",
"\t\tthis.avistamientos.add(av);\n",
"\t}\n",
" /****** tratamientos iterativos *********/\n",
" \n",
" public Integer getNumeroAvistamientosFecha(LocalDate f) {\n",
"\t\tInteger r = 0;\n",
"\t\tfor (Avistamiento av : this.getAvistamientos()) {\n",
"\t\t\tif (av.getFecha().equals(f)) {\n",
"\t\t\t\tr++;\n",
"\t\t\t}\n",
"\t\t}\n",
"\t\treturn r;\n",
"\t}\n",
" public Set<Avistamiento> getAvistamientosCercanosUbicacion(Coordenadas c, Double d) {\n",
"\t\tSet<Avistamiento> r = new HashSet<Avistamiento>();\n",
"\t\tfor (Avistamiento av : this.getAvistamientos()) {\n",
"\t\t\tif(av.getUbicacion().getDistancia(c).compareTo(d)<=0) {\n",
"\t\t\t\tr.add(av);\n",
"\t\t\t}\n",
"\t\t}\n",
"\t\treturn r;\n",
"\t}\n",
" public Boolean existeAvistamientoLugarAño(String l, Integer a) {\n",
"\t\tBoolean r=false;\n",
"\t\tfor (Avistamiento av : this.getAvistamientos()) {\n",
"\t\t\tif(av.getLugar().equals(l) && av.getAño().equals(a)) {\n",
"\t\t\t\tr=true;\n",
"\t\t\t\tbreak;\n",
"\t\t\t}\n",
"\t\t}\n",
"\t\treturn r;\n",
"\t}\n",
" public Avistamiento getAvistamientoMayorDuracion() {\n",
"\t\tAvistamiento r = null;\n",
"\t\tfor (Avistamiento av : this.getAvistamientos()) {\n",
"\t\t\tif(r==null || av.getDuracion().compareTo(r.getDuracion())>0) {\n",
"\t\t\t\tr=av;\n",
"\t\t\t}\n",
"\t\t}\n",
"\t\treturn r;\n",
"\t}\n",
" public Map<LocalDate, Set<Avistamiento>> getAvistamientosPorFecha() {\n",
"\t\tMap<LocalDate, Set<Avistamiento>>r=new HashMap<LocalDate, Set<Avistamiento>>();\n",
"\t\tfor (Avistamiento av : this.getAvistamientos()) {\n",
"\t\t\tLocalDate clave=av.getFecha();\n",
"\t\t\tif(!r.containsKey(clave)) {\n",
"\t\t\t\tr.put(clave, new HashSet<Avistamiento>());\n",
"\t\t\t}\n",
"\t\t\tr.get(clave).add(av);\n",
"\t\t}\n",
"\t\treturn r;\n",
"\t}\n",
" public Map<Integer, Integer> getNumeroAvistamientosPorAño() {\n",
"\t\tMap<Integer, Integer> r=new HashMap<Integer, Integer>();\n",
"\t\tfor (Avistamiento av : this.getAvistamientos()) {\n",
"\t\t\tInteger clave=av.getAño();\n",
"\t\t\tif(!r.containsKey(clave)) {\n",
"\t\t\t\tr.put(clave, 0);\n",
"\t\t\t}\n",
"\t\t\tr.put(clave, r.get(clave)+1);\n",
"\t\t}\n",
"\t\treturn r;\n",
"\t}\n",
" /****** comparadores *********/\n",
" \n",
" public SortedSet<Avistamiento> getAvistamientosOrdenadosPor(Comparator<Avistamiento> cmp) {\n",
"\t\tSortedSet<Avistamiento> r = new TreeSet<Avistamiento>(cmp);\n",
"\t\tr.addAll(this.getAvistamientos());\n",
"\t\treturn r;\n",
"\t}\n",
" public Avistamiento getAvistamientoMasCercanoA(Coordenadas c){\n",
" return Collections.min(this.getAvistamientos(), Comparator.comparing(av -> av.getUbicacion().getDistancia(c)));\n",
" }\n",
" public SortedMap<String, SortedSet<Forma>> getFormasPorLugar(){\n",
"\t\t// claves ordenadas por longitud de la cadena\n",
"\t\t// valores ordenados alfabéticamente\n",
"\t\tSortedMap<String, SortedSet<Forma>> r = new TreeMap<String, SortedSet<Forma>>(Comparator.comparing(l -> l.length()));\n",
"\t\tfor (Avistamiento av : this.avistamientos) {\n",
"\t\t\tString clave = av.getLugar();\n",
"\t\t\tif (!r.containsKey(clave)) {\n",
" // NOTA: El orden natural de los enumerados se define por el orden en que se\n",
" // declaran los valores (por tanto, la solución no sería con naturalOrder)\n",
"\t\t\t\tr.put(clave, new TreeSet<Forma>(Comparator.comparing(f -> f.toString())));\n",
"\t\t\t}\n",
"\t\t\tr.get(clave).add(av.getForma());\n",
"\t\t}\n",
"\t\treturn r;\n",
" }\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Ejercicio: Completa el tipo Avistamientos con los siguientes métodos iterativos:**\n",
"+ ```public Integer getNumeroAvistamientosFecha(LocalDate f)```: Devuelve el número de avistamientos producidos en la fecha *f*.\n",
"+ ```public Set<Avistamiento> getAvistamientosCercanosUbicacion(Coordenadas c, Double d)```: Devuelve un conjunto con los avistamientos que están cerca de las coordenadas *c*, en un radio menor o igual que *d*.\n",
"+ ```public Boolean existeAvistamientoLugarAño(String l, Integer a)```: Devuelve *true* si existe algún avistamiento ubicado en *l* en el año *a*. En caso contrario devolverá *false*.\n",
"+ ```public Avistamiento getAvistamientoMayorDuracion()```: Devuelve el avistamiento que dura más tiempo.\n",
"+ ```public Map<LocalDate, Set<Avistamiento>> getAvistamientosPorFecha()```: Agrupa los avistamientos por fecha.\n",
"+ ```public Map<Integer, Integer> getNumeroAvistamientosPorAño() ```: Cuenta el número de avistamientos en cada año."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Para probar lo anterior, utiliza lo que viene a continuación. No te preocupes de momento sobre cómo funciona *leerAvistamientos*. Observa y guarda la salida esperada antes de ejecutar el test."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Mostrando los 10 primeros\n",
"[03/04/2014, revere, OTRA]\n",
"[07/07/2000, tacna (approx), OTRA]\n",
"[05/06/2012, bowie, OTRA]\n",
"[23/10/2006, cypress, OTRA]\n",
"[27/12/2005, fairfax, OTRA]\n",
"[16/02/2006, estero, OTRA]\n",
"[06/01/2012, tucson, OTRA]\n",
"[25/10/2007, monterey, OTRA]\n",
"[20/12/2013, west jordan, OTRA]\n",
"[20/08/2003, lakewood, OTRA]\n",
"\n",
"Existe algún avistamiento en Bowie en el 2012?\n",
"true\n",
"\n",
"Y en 2010?\n",
"false\n",
"\n",
"Mostrando el avistamiento de mayor duración\n",
"[24/08/2002, englewood, OTRA]\n",
"con una duración de 609 días\n",
"\n",
"Mostrando avistamientos cercanos a (42.0, -85.0) tomando como radio 0.1\n",
"[[20/07/2006, girard, OTRA], [08/09/2013, coldwater, TRIANGULAR], [14/07/1975, girard, OTRA], [03/08/1978, coldwater, OTRA]]\n",
"\n",
"Mostrando avistamientos producidos el 30/01/2008\n",
"[[30/01/2008, copperas cove, OTRA], [30/01/2008, kings park, TRIANGULAR], [30/01/2008, myrtle beach, OTRA], [30/01/2008, oklahoma city, OTRA]]\n",
"\n",
"Mostrando el número de avistamientos producidos el 30/01/2008\n",
"4\n",
"\n",
"Mostrando el número de avistamientos producidos en 2008\n",
"1938\n"
]
}
],
"source": [
"import java.io.IOException;\n",
"import java.nio.charset.StandardCharsets;\n",
"import java.nio.file.Files;\n",
"import java.nio.file.Paths;\n",
"\n",
"public static Avistamientos leerAvistamientos(String nombreFichero) {\n",
"\t\tStream<Avistamiento> str = Stream.empty();\n",
"\t\ttry {\n",
"\t\t\tstr = Files.lines(Paths.get(nombreFichero), StandardCharsets.UTF_8)\n",
"\t\t\t\t\t.skip(1)\n",
"\t\t\t\t\t.map(linea -> new Avistamiento(linea));\n",
"\t\t} catch (IOException e) {\n",
"\t\t\te.printStackTrace();\n",
"\t\t}\n",
"\t return new Avistamientos(str);\n",
"}\n",
" \n",
"Avistamientos avistamientos=leerAvistamientos(\"./ovnis.csv\");\n",
"System.out.println(\"Mostrando los 10 primeros\");\n",
"int i=1;\n",
"for(Avistamiento av:avistamientos.getAvistamientos()) {\n",
"\tif(i>10) {\n",
"\t\tbreak;\n",
"\t}\n",
"\tSystem.out.println(av);\n",
"\ti++;\n",
"}\n",
"\t\t\n",
"System.out.println(\"\\nExiste algún avistamiento en Bowie en el 2012?\");\n",
"System.out.println(avistamientos.existeAvistamientoLugarAño(\"bowie\", 2012));\n",
"System.out.println(\"\\nY en 2010?\");\n",
"System.out.println(avistamientos.existeAvistamientoLugarAño(\"bowie\", 2010));\n",
"\t\t\n",
"System.out.println(\"\\nMostrando el avistamiento de mayor duración\");\n",
"Avistamiento mayor=avistamientos.getAvistamientoMayorDuracion();\n",
"System.out.println(mayor);\n",
"System.out.println(\"con una duración de \"+mayor.getDuracion().getSeconds()/86400+\" días\");\n",
"\t\t\n",
"System.out.println(\"\\nMostrando avistamientos cercanos a (42.0, -85.0) tomando como radio 0.1\");\n",
"System.out.println(avistamientos.getAvistamientosCercanosUbicacion(new Coordenadas(42.0, -85.0), 0.1));\n",
"\t\t\n",
"System.out.println(\"\\nMostrando avistamientos producidos el 30/01/2008\");\n",
"System.out.println(avistamientos.getAvistamientosPorFecha().get(LocalDate.of(2008, 1, 30)));\n",
"\t\t\n",
"System.out.println(\"\\nMostrando el número de avistamientos producidos el 30/01/2008\");\n",
"System.out.println(avistamientos.getNumeroAvistamientosFecha(LocalDate.of(2008, 1, 30)));\n",
"\t\t\n",
"System.out.println(\"\\nMostrando el número de avistamientos producidos en 2008\");\n",
"System.out.println(avistamientos.getNumeroAvistamientosPorAño().get(2008));"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Ejercicio: Completa el tipo Avistamientos con los siguientes métodos basados en comparadores:**\n",
"+ ```public Avistamiento getAvistamientoMasCercanoA(Coordenadas c)```: Devuelve el avistamiento más cercano a la coordenada que se pasa como parámetro\n",
"+ ```public SortedMap<String, SortedSet<Forma>> getFormasPorLugar()```: Devuelve un diccionario ordenado que agrupa las formas registradas en cada lugar. Los lugares estarán ordenados por el tamaño del nombre, y los conjuntos estarán ordenados por orden alfabético de las formas.\n",
" + En el test, muestra el valor asociado a la primera clave, y el valor asociado a la última clave.\n",
"+ Utiliza en el test el método ```getAvistamientosOrdenadosPor(...)``` (cuya implementación ya está en *Avistamientos*) para:\n",
" + Ordenar los avistamientos por año de mayor a menor\n",
" + Ordenar los avistamientos por año, forma y lugar\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Mostrando las formas por lugar (lugares ordenados por longitud, y las formas alfabéticamente)\n",
"mio=[CIRCULAR, OTRA, TRIANGULAR]\n",
"vail=[CIRCULAR, OTRA, TRIANGULAR]\n",
"bowie=[CIRCULAR, OTRA, TRIANGULAR]\n",
"revere=[CIRCULAR, OTRA, TRIANGULAR]\n",
"cypress=[CIRCULAR, OTRA, TRIANGULAR]\n",
"monterey=[CIRCULAR, OTRA, TRIANGULAR]\n",
"camarillo=[CIRCULAR, OTRA, TRIANGULAR]\n",
"hood river=[CIRCULAR, OTRA, TRIANGULAR]\n",
"west jordan=[CIRCULAR, OTRA, TRIANGULAR]\n",
"harleysville=[CIRCULAR, OTRA, TRIANGULAR]\n",
"\n",
"Mostrando el valor asociado a la primera clave: [CIRCULAR, OTRA, TRIANGULAR]\n",
"Mostrando el valor asociado a la última clave: [OTRA]\n",
"\n",
"Ordenando los avistamientos por año (de mayor a menor)\n",
"[01/01/2014, albuquerque, OTRA]\n",
"[01/01/2014, austin, CIRCULAR]\n",
"[01/01/2014, boston, OTRA]\n",
"[01/01/2014, bradenton, OTRA]\n",
"[01/01/2014, burbank, OTRA]\n",
"[01/01/2014, cincinnati, CIRCULAR]\n",
"[01/01/2014, dallas, OTRA]\n",
"[01/01/2014, deltona, CIRCULAR]\n",
"[01/01/2014, el paso, OTRA]\n",
"[01/01/2014, elon, CIRCULAR]\n",
"\n",
"Ordenando los avistamientos por año,forma y lugar\n",
"[01/06/1910, wills point, OTRA]\n",
"[11/06/1920, cicero, OTRA]\n",
"[28/12/1925, atkinson (6 miles north of), OTRA]\n",
"[15/09/1934, valley city (6.5 miles east of), OTRA]\n",
"[15/10/1936, eklutna, OTRA]\n",
"[15/08/1937, fontana, OTRA]\n",
"[15/06/1937, hubbard, OTRA]\n",
"[07/07/1939, keokuk, OTRA]\n",
"[02/04/1944, clovis, OTRA]\n",
"[01/06/1945, jasper, OTRA]\n"
]
}
],
"source": [
"//utiliza el objeto 'avistamientos' de la celda anterior para llamar a los métodos\n",
"System.out.println(\"\\nMostrando las formas por lugar (lugares ordenados por longitud, y las formas alfabéticamente)\");\n",
"SortedMap<String,SortedSet<Forma>>sm=avistamientos.getFormasPorLugar();\n",
"int i=1;\n",
"for(Map.Entry<String,SortedSet<Forma>> e:sm.entrySet()) {\n",
"\tif(i>10) {\n",
"\t\tbreak;\n",
"\t}\n",
"\tSystem.out.println(e);\n",
"\ti++;\n",
"}\n",
"System.out.println(\"\\nMostrando el valor asociado a la primera clave: \"+sm.get(sm.firstKey()));\n",
"System.out.println(\"Mostrando el valor asociado a la última clave: \"+sm.get(sm.lastKey()));\n",
"\n",
"System.out.println(\"\\nOrdenando los avistamientos por año (de mayor a menor)\");\n",
"SortedSet<Avistamiento>ss= avistamientos.getAvistamientosOrdenadosPor(Comparator.comparing((Avistamiento av) -> av.getFecha().getYear()).reversed()\n",
"\t\t\t\t.thenComparing(Comparator.naturalOrder()));\n",
"i=1;\n",
"for(Avistamiento av:ss) {\n",
"\tif(i>10) {\n",
"\t\tbreak;\n",
"\t}\n",
"\tSystem.out.println(av);\n",
"\ti++;\n",
"}\n",
"\n",
"System.out.println(\"\\nOrdenando los avistamientos por año,forma y lugar\");\n",
"ss=avistamientos.getAvistamientosOrdenadosPor(Comparator.comparing((Avistamiento av) -> av.getFecha().getYear())\n",
"\t\t\t\t.thenComparing(av -> av.getForma())\n",
"\t\t\t\t.thenComparing(av -> av.getLugar())\n",
"\t\t\t\t.thenComparing(Comparator.naturalOrder()));\n",
"i=1;\n",
"for(Avistamiento av:ss) {\n",
"\tif(i>10) {\n",
"\t\tbreak;\n",
"\t}\n",
"\tSystem.out.println(av);\n",
"\ti++;\n",
"}\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Java",
"language": "java",
"name": "java"
},
"language_info": {
"codemirror_mode": "java",
"file_extension": ".jshell",
"mimetype": "text/x-java-source",
"name": "Java",
"pygments_lexer": "java",
"version": "13.0.1+9"
}
},
"nbformat": 4,
"nbformat_minor": 4
}