Skip to content

sio2sio2/lobaton-core

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Lobatón (core)

Lobaton desarrolla, a través del plugin leaflet.mutatismutandis de Leaflet un mapa de adjudicaciones provisionales y oferta de centros educativos, pero sin implementar la interfaz que permite al usuario controlar la aplicación de filtros y correcciones, hacer solicitudes o consultar la información detallada de cada centro. Es, pues, la librería base para contruir una aplicación web completa con la heramienta que se desee (VueJS, AngularJS, React o, claro está, directamente VanillaJS)

La librería define un objeto que posibilita:

  • Disponer sobre el mapa marcas que representan centros educativos y cuyo aspecto despende de su oferta educativa, sus planes de bilinguismo, su tipo y sus adjudicaciones.
  • Agrupar marcas usando el plugin Leaflet.MarkerCluster.
  • Realizar Correcciones sobre las adjudicaciones y la oferta educativa.
  • Aplicar Filtros predefinidos.
  • Definir un origen de viajes, a fin de:
    • Consultar el tiempo y la distancia de trayecto a cualquier centro.
    • Consultar las isocronas de 10, 20, 30, 40, 50 y 60 minutos, y poder usarlas como criterio de filtro.

Un ejemplo con una interfaz muy simple de aplicación, que permite manipular mínimamente los datos del mapa es éste.

Instalación

Para el desarrollo de la interfaz con NodeJS basta con instalar el paquete:

$ npm install git+https://github.com/sio2sio2/lobaton-core

e importar la función que crear el objeto de manipulación del mapa en el código propio:

import "@lobaton/core/dist/core.bundle.css";
import * as Lo from "@lobaton/core";

Si nuestra intención es usar la librería directamente en el navegador, disponemos de tres sabores distintos:

  • core.js que contiene la versión minimizada de la librería sin dependencias, por lo que exige hacer referencia a todas ellas en el HTML:

    <!-- Leaflet -->
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css>
    <script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"></script>
    
    <!-- Plugin: Markercluster -->
    <link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.4.1/dist/MarkerCluster.css">
    <link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.4.1/dist/MarkerCluster.Default.css">
    <script src="https://unpkg.com/leaflet.markercluster@1.4.1/dist/leaflet.markercluster.js"></script>
    
    <!-- Plugin: Menú contextual -->
    <link rel="stylesheet" href="https://unpkg.com/leaflet-contextmenu@1.4.0/dist/leaflet.contextmenu.min.css">
    <script src="https://unpkg.com/leaflet-contextmenu@1.4.0/dist/leaflet.contextmenu.min.js"></script>
    
    <!-- Plugin: mutatismutandis -->
    <script src="https://unpkg.com/leaflet.mutatismutandis/dist/leaflet.mutatismutandis.js"></script>
    
    <!-- turf (polígonos): para isocronas -->
    <script src='https://npmcdn.com/@turf/turf/turf.min.js'></script>
    
    <!-- Lobatón Core -->
    <link rel="stylesheet" href="https://sio2sio2.github.io/lobaton-core/dist/core.css">
    <script src="https://sio2sio2.github.io/lobaton-core/dist/core.js"></script>
  • core.bundle.js, que incluye todas las dependencias y es más aconsejable de usar (excluida la opción de desarrollar con NodeJS):

    <!-- Lobatón Core + Dependencias -->
    <link rel="stylesheet" href="https://sio2sio2.github.io/lobaton-core/dist/core.bundle.css">
    <script src="https://sio2sio2.github.io/lobaton-core/dist/core.bundle.js"></script>
  • core-debug.js, que es la versión de desarrollo de la librería y es sólo útil para labores de depuración con el navegador, aunque para tal labor es aconsejable utilizar NodeJS. Requiere cargar las mismas dependencias y sólo difiere en cómo cargar el propio Lobatón:

    <!-- Las mismas dependencias expuestas para core.js -->
    
    <!-- Lobatón Core -->
    <link rel="stylesheet" href="https://sio2sio2.github.io/lobaton-core/dist/core-debug.css">
    <script src="https://sio2sio2.github.io/lobaton-core/dist/core-debug.js"></script>

Datos

Los datos se facilitan en un formato GeoJSON en que la primera feature describe aspectos generales de los datos suministrados (p.e. qué nombre se corresponde con cada código de puesto) y cada una de las restantes features los datos detallados de cada centro.

{
   "type": "FeatureCollection",
   "features": [
      {
         "type": "Feature",
         "properties": {
            "curso": "2018\/19",
            "tipo": "adjoferta",
            "objetivo": "especialidad",
            "entidad": [
               590107
            ],
            "spider": {
               "cgt": false,
               "vt": true,
               "organica": "2018\/19",
               "ofertafp": "2018\/19",
               "ofertasec": "2019\/20"
            },
            "limite": false,
            "puestos": {
               "00590059": "APOYO AL ÁREA CIENTÍFICA O TECNOLÓGICA",
               "00590107": "Informática P.E.S",
               "11590107": "Informática (Inglés) P.E.S.",
               "CI590107": "Informática (Nueva implantación) P.E.S.",
               "DU590107": "Informática (Dual) P.E.S.",
               "ED590107": "Informática (IEDA) P.E.S.",
               "SP590107": "Informática (Semipresencial) P.E.S."
            },
            "colectivos": {
               "B": {
                  "o": 0,
                  "v": "Suprimido"
               },
               "C": {
                  "o": 1,
                  "v": "Desplazado"
               },
               "N": {
                  "o": 2,
                  "v": "ExDirector"
               },
               "E": {
                  "o": 3,
                  "v": "Adscrito"
               },
               "F": {
                  "o": 4,
                  "v": "Reingresado"
               },
               "DA": {
                  "o": 5,
                  "v": "SaludPropia"
               },
               "DB": {
                  "o": 6,
                  "v": "Conciliación"
               },
               "DC": {
                  "o": 6,
                  "v": "CargoElecto"
               },
               "G": {
                  "o": 8,
                  "v": "Provisional"
               },
               "M": {
                  "o": 9,
                  "v": "PueEspec"
               },
               "H": {
                  "o": 10,
                  "v": "EnPracticas"
               },
               "I": {
                  "o": 11,
                  "v": "Aprobado"
               },
               "DZ": {
                  "o": 12,
                  "v": "InterCom"
               },
               "J": {
                  "o": 13,
                  "v": "Interino"
               }
            },
            "ens": {
               "23GMSMR168": {
                  "nombre": "Sistemas Microinformáticos y Redes",
                  "puestos": [
                     "00590107",
                     "11590107",
                     "DU590107",
                     "ED590107",
                     "SP590107"
                  ],
                  "grado": "CFGM"
               },
               "23GSASI820": {
                  "nombre": "Administración de Sistemas Informáticos en Red",
                  "puestos": [
                     "00590107",
                     "11590107",
                     "DU590107",
                     "ED590107",
                     "SP590107"
                  ],
                  "grado": "CFGS"
               },
               "23GSDA859": {
                  "nombre": "Desarrollo de Aplicaciones Web",
                  "puestos": [
                     "00590107",
                     "11590107",
                     "DU590107",
                     "ED590107",
                     "SP590107"
                  ],
                  "grado": "CFGS"
               },
               "23GSDAM517": {
                  "nombre": "Desarrollo de Aplicaciones Multiplataforma",
                  "puestos": [
                     "00590107",
                     "11590107",
                     "DU590107",
                     "ED590107",
                     "SP590107"
                  ],
                  "grado": "CFGS"
               },
               "BAE": {
                  "nombre": "Bachillerato de Artes Escénicas",
                  "puestos": [
                     "00590107",
                     "11590107",
                     "CI590107",
                     "DU590107",
                     "ED590107",
                     "SP590107"
                  ]
               },
               "BAP": {
                  "nombre": "Bachillerato de Artes Plásticas",
                  "puestos": [
                     "00590107",
                     "11590107",
                     "CI590107",
                     "DU590107",
                     "ED590107",
                     "SP590107"
                  ]
               },
               "BCT": {
                  "nombre": "Bachillerato de Ciencias",
                  "puestos": [
                     "00590107",
                     "11590107",
                     "CI590107",
                     "DU590107",
                     "ED590107",
                     "SP590107"
                  ]
               },
               "BHCS": {
                  "nombre": "Bachillerato de Humanidades y Ciencias Sociales",
                  "puestos": [
                     "00590107",
                     "11590107",
                     "CI590107",
                     "DU590107",
                     "ED590107",
                     "SP590107"
                  ]
               }
            },
            "version": 0.2
         }
      },
      {
         "type": "Feature",
         "geometry": {
            "type": "Point",
            "coordinates": [
               -3.0248339999999998,
               36.746941
            ]
         },
         "properties": {
            "id": {
               "cod": 4000110,
               "nom": "I.E.S. Abdera",
               "dom": "C\/ Marisma, 6",
               "mun": "Adra",
               "cp": 4770,
               "pro": "Almeria"
            },
            "oferta": [
               {
                  "ens": "BHCS",
                  "mod": "semi",
                  "idi": null,
                  "adu": true,
                  "ext": false,
                  "ene": false,
                  "nue": 0,
                  "mar": false
               },
               {
                  "ens": "BHCS",
                  "mod": "pres",
                  "idi": "Inglés",
                  "adu": false,
                  "ext": false,
                  "ene": false,
                  "nue": 0,
                  "mar": false
               },
               {
                  "ens": "BCT",
                  "mod": "pres",
                  "idi": "Inglés",
                  "adu": false,
                  "ext": false,
                  "ene": false,
                  "nue": 0,
                  "mar": false
               },
               {
                  "ens": "23GSDA859",
                  "mod": "pres",
                  "idi": null,
                  "adu": false,
                  "ext": false,
                  "ene": false,
                  "nue": 0,
                  "tur": "matutino",
                  "esp": null,
                  "pla": 20,
                  "pro": false,
                  "mar": true
               }
            ],
            "mod": {
               "bil": [
                  11
               ]
            },
            "pla": {
               "00590107": {
                  "fun": 3,
                  "org": 3,
                  "norg": null,
                  "vi": 1,
                  "vt": 0
               }
            },
            "adj": [
               {
                  "col": "J",
                  "esc": [
                     2,
                     9,
                     7
                  ],
                  "pue": "00590107",
                  "pet": "15",
                  "per": false,
                  "ubi": false
               },
               {
                  "col": "J",
                  "esc": [
                     1,
                     7,
                     6
                  ],
                  "pue": "00590107",
                  "pet": "7",
                  "per": false,
                  "ubi": false
               }
            ]
         }
      }
   ]
}

Los datos son bastante elocuentes, pero algunos requieren explicación:

  • La "o" en los colectivos representa el orden de prelación de cada colectivo. Cuanto menor sea, mayor será la prelación. El dato es útil para la corrección adjref:
  • Las características de cada enseñanza son las siguientes:
    • ens, código de la enseñanza.
    • mod, modalidad de enseñanza que puede ser pres (presencial), semi (semipresencial) y dist (a distancia).
    • idi, idioma (Inglés, Francés o Alemán).
    • adu, enseñanza de adultos.
    • ext, true, si la enseñanza se extinguió y el curso presente ya no existe.
    • ene, true, en extinción, pero sigue aún existiendo.
    • nue, nueva implantación: 1, en primer año; 2, en segundo año; 0, no es una nueva enseñanza.
    • mar, true si la enseñanza es deseable.
    • tur, que puede ser matutino, vespertino o ambos. Sólo aparece en enseñanzas de formación profesional. En las enseñanzas de secundaria y bachillerato, se sobreentiende que la enseñanza de adultos es por la tarde.
    • esp, especial que puede ser "parcial", "dual"
    • pla, número de plazas (F.P.).
    • aum, que representa la variación de plazas y puede ser un número positivo o negativo.
    • pro, true si es un programa específico de formación profesional.
  • Las características de cada adjudicación son las siguientes:
    • col, letra que representa al colectivo.
    • esc, escalafón o tiempo de servicio, si es funcionario interino.
    • pue, puesto de adjudicación.
    • pet, número de petición.
    • per, true si la vacante se adjudicó en el concurso de traslados y, consecuentemente, no estará disponible más en el procedimiento.
    • ubi, true si el funcionario obtuvo plaza en el concurso de traslados y, en principio, no volverá a ocupar esa plaza.

Objeto

El paquete facilita, mediante la función lobaton, la creación de un objeto para el acceso a la manipulación del mapa:

Creación

lobaton(opts)

Crea un objeto para interactuar con el mapa:

g = lobaton({
   center: [37.45, -4.5],
   pathLoc: "json/localidades.json",
   unclusterZoom: 13,
   zoom: 8,
   ors: {key: "###--KEY--###"}
});

A la función pueden facilitarse cualquiera de las opciones para la creación de un objeto L.Map (como zoom o center) y las siguientes:

Opción Descripción
autostatus Aplica automáticamente la configuración proporcionada a través de la opción status. Por defecto, true. Véase el método setStatus()
icon Estilo del icono. Puede ser "boliche" o "chupachups". Por defecto, "boliche".
id Identificador del elemento HTML donde se incrustará el mapa.
light

Si true (su valor por defecto), se implementan algunos aspectos del comportamiento del mapa:

  • Click sobre el centro, lo selecciona.
  • Crea menús contextuales al pulsar el botón derecho sobre el mapa, los centros, el origen de los viajes y las áreas que encierran las isocronas.
loading Función que construye un indicador para notar la carga de datos remotos. Si es true, se usa el indicador interno; y si false, se prescindirá de indicador alguno. Valor predeterminado: true.
ors Objeto que proporciona las opciones para generar isocronas, crear rutas y geocodificar puntos utilizando la API de OpenRouteService.
status Pasa un objeto de configuración del estado inicial codificado en base64. Su decodificación pasará a ser el valor inicial del atributo status.
unclusterZoom Zoom a partir del cual las marcas de centro se mostrarán siembre desagregadas. Por defecto, 14.

A su vez, el objeto ors puede tener estos atributos:

Opción Descripción
chunkProgress Función para mostrar el progreso en operaciones lentas (cálculo de isocronas). Si true, se usa el indicador interno, y si false, se prescinde de indicador. Por defecto, true.
key Clave para el uso de la API REST de OpenRouteService.
loading Tiene exactamente el mismo significado que la opción general. Su valor predeterminado es el que tenga la opción general.
routaPopup Función que construye el popup con información sobre la ruta generada. La función recibe como primer argumento la marca de origen, como segundo la marca del centro destino y como último argumento el objeto GeoJSON que representa la ruta. También admite los valores true si se desea usar la función predefinida, o false si no desea mostrar popup. Por defecto, true.

Note

Si no se facilita centro (opción center), la aplicación intentará averiguar las coordenadas del dispositivo para situar en ellas el centro.

Atributos

Warning

No sobreescriba los valores de estos atributos. Limítese a consultarlos y usarlos. Para cambiarlos existen métodos específicos.

cluster

Es la capa a la que se añaden las marcas de centro. En consecuencia:

g.cluster.getLayers()

nos devolvería todas las marcas de centro que se encuentren sobre el mapa1. No presenta ninguna característica extendida.

Centro

Clase de iconos mutables (L.Marker.Mutable) a la que pertenecen las marcas de centro. Sobra esta clase se aplicar las Correcciones y Filtros, que trataremos más adelante.

Además, esta clase añade dos particularidades a los atributos propios de L.Marker.Mutable:

.get(codigo),

que permite obtener la amrca del centro cuyo código es el suministrado en cualquiera de sus variantes:

centro = g.Centro.get(23001111);     // Variante numérica.
centro = g.Centro.get("23001111");   // Variante de cadena.
centro = g.Centro.get("23001111C");   // Variante normalizada.

Además, a los datos se incorpora un getter, que permite obtener el código normalizado2 del centro:

centro.getData().id.cod;  // código numérico de los datos: 23001111
centro.getData().codigo;  // Código normalizado: 23001111C
general

Almacena la información general del GeoJSON de Datos (o sea, la primera feature).

status

Devuelve el estado actual del mapa (origen, filtros correcciones, etc.). El estado adicional que aporte la interfaz visual se encontrará dentro de su atributo visual. Este estado es dinámico y varía cada vez que se realiza una acción sobre el mapa que modifica el estado. excepto visual, que como recoge caractarísticas del estado de la interfaz ajenas al mapa, mantendrá sus valores iniciales. Para más información eche un ojo al método getStatus().

seleccionado

Establece un centro como el seleccionado, lo que se notará visualmente rodeando el icono con una circunferencia roja. Es la única propiedad a la que podemos asociar valor directamente:

g.seleccionado = g.Centro.get(21002100);  // Seleccionamos el centro 21002100.
g.seleccionado = null;     // Deshacemos la selección.

La selección de un centro tiene asociado el evento markerselect.

origen

Marca que representa el origen del viaje. Puede no existir, si no se ha definido ningún origen. El establecimniento del origen está asociado al evento originset.

La asignación de un valor a g.origen.postal tiene asociado el evento geocode aplicable a la propia marca de origen.

contador

Número de consultas realizadas al servicio de OpenRouteService.

direccion

Almacena el resultado de una geocodificación. Si se realizó la consulta de la dirección postal de unas coordenadas contendrá una cadena; y, si se pretendió obtener las coordenadas de una dirección postal, el objeto GeoJSON con todas las localizaciones posibles.

isocronas

Array con las marcas que representan las áreas de los anillos que se forman entre isocronas. Tales marcas tienen asociadas mediante su atributo feature el objeto GeoJSON que define el área.

ruta

Objeto que contiene dos atributos: ruta.destino, que es la marca de centro que se usó como destino de la ruta; y ruta.layer que es la capa que representa la ruta (la cual a su vez tendrá asociada en su atributo feature el objeto GeoJSON que define la ruta).

Métodos

agregarCentros(datos)

Método apropiado para agregar los centros asociados a una especialidad. Los datos pueden ser el objeto GeoJSON o la dirección URL de la que descargar dicho objeto. Por tanto, para cargar una nueva especialidad basta:

g.agregarCentros("json/590107.json");

Ahora bien, de haber una especialidad previa, convendría antes eliminar todo lo que se hubiera hecho anteriormente:

g.on("dataloaded", e => {
   console.log("Acabo de terminar de cargar los datos");
});

g.cluster.clearLayers();  // Eliminamos los anteriores centros.
g.Centro.reset();         // Eliminamos correcciones aplicadas.
g.setRuta(null);          // Eliminamos la ruta dibujada.
g.seleccionado = null;    // Deseleccionamos el centro.

// Cargamos unos nuevos datos.
g.agregarCentros("json/590107.json");

El fin de la carga de datos está asociado al evento dataloaded.

calcularOrigen()

Obtiene la dirección postal del origen, si de este sólo se conocen las coordenadas. La dirección se almacenará en g.origen.postal. Es útil cuando el origen se ha obtenido pinchando sobre el mapa. En caso de que el origen se establezca escribiendo una dirección a través de la interfaz virtual, lo conveniente sería:

  • Utilizar geoCodificar() a partir de la dirección suministrada por el usuario, para obtener los distintos candidatos.
  • Permitir al usuario escoger uno de los candidatos, del cual se podrá obtener tanto las coordenadas como la dirección postal.
  • Usar setOrigen() para establecer el origen.
  • Fijar la dirección postal, haciendo:

    g.origen.postal = direccion_postal_del_candidato;
geoCodificar(query)

Obtiene la dirección postal de unas coordenadas, si se suministra un punto; o un objeto GeoJSON con posibles ubicaciones si se suministra una dirección. En el primer caso, el punto debe ser un objeto con los atributos lat y lng; y en el segundo, una cadena.

La geocodificación tiene asociado el evento addressset.

getIcon(estilo)

Devuelve la clase de icono cuyo nombre se especifica en el argumento:

const Boliche = g,getIcon("boliche");
getIsocronas(maciza)

Si maciza es false (u otro valor evaluable a falso), devuelve un array con las capas que se dibujan al crear las isocronas. De lo contrario, devuelve un array con la definición en formato GeoJSON de las áreas que encierran las isocronas. Lo primero es útil si se quiere manipular desde la interfaz visual el dibujo de las isocronas (por ejemplo, asociando eventos de ratón a tales capas). Lo segundo es útil si se desea aplicar el filtro lejos.

setOrigen(latlng)

Establece el origen de los viajes en el punto pasado como argumento. La obtención del origen tiene asociado el evento originset.

getStatus(extra)

Devuelve una cadena que describe el estado actual del mapa (centro, zoom, origen, isocronas, correcciones, filtros. etc.). La cadena es la codificación en base64 del objeto que devuelve el atributo status. El argumento extra deberá aportar las caracterísicas que depende de la interfaz y sobreescribirá las opciones incluidas dentro del atrbuto visual de dicho atributo.

El retorno proporcionado por este método es apto como valor de la opción status que se puede pasar al crear el objeto.

setIcon(estilo)

Define un nuevo estilo para el icono de las marcas de centro. El parámetro es una cadena con el nombre del nuevo estilo que puede ser:

  • boliche, que se el predeterminado.
  • chupachups, estilo alternativo al anterior, pero basado en CSS y mucho más sencillo.
  • solicitud, que es un estilo pensado para el futuro módulo de peticiones.

El método modifica el estilo para todas las marcas y luego las redibuja. Si lo que se pretende es alterar el estilo de nuevas marcas que se añadan, entonces debería alterarse la opción icon del objeto:

g.options.icon = "solicitud";

Y si se pretende alterar el estilo de una marca ya existente usar el meodo homónimo para la marca en particular:

// centro es una marca que representa un centro concreto.
const Icono = g.getIcon("solicitud");
centro.setIcon(new Icono());
setIsocronas(point)

Genera las isocronas referidas al punto suministrado. Si no se suministra ninguno, se entiende que el punto es el origen del viaje, y si nul, se eliminan las isocronas que pudieran haberse generado anterioremente. No puede haber más de un juego de isocronas

La generación de las isocronas tiene asociado el evento isochroneset.

setRuta(destino)

Calcula una ruta entre el origen de viajes y el centro de destino suministrado. Como argumento debe usarse la marca del centro. Si se proporciona null, la ruta anteriomente calculada y dibujada, se elimina.

La generación de la ruta tiene asociado el evento routeset.

setStatus()

Aplica la configuración proporcionada a través de la opción status al crear el objeto. Sólo es necesario en caso de que se haya establecido la opción autostatus a false.

Eventos

Hay toda una serie de eventos asociados al objeto que pueden ayudarnos a capturar acciones que se realizan sobre el mapa:

dataloaded

Se desencadena al terminar de cargar los datos el método agregarCentros().

markerselect

Se desencadena al seleccionar o deseleccionar un centro. En el objeto de evento e.oldval y e.newval contienen respectivamente la marca anteriormente y posteriomente seleccionadas:

g.on("markerselect", e => {
   if(e.oldval) {
      const nombre = e.oldval.getData().id.nom;
      console.log(`Antes tenía seleccionado el centro ${nombre}`);
   }
   if(e.newval) {
      const nombre = e.newval.getData().id.nom;
      console.log(`Acaba de seleccionar el centro ${nombre}`);
   }
});
addressset

Se desencadena tras resolver una geocodificación con OpenRouteService a través del método geoCodificar(). e.newval contiene el resultado de la geocodificación.

originset

Se desencadena tras establecer un origen de viajes. Dispone de e.oldval y e.newval como el evento markerselect.

isochroneset

Se desencadena al terminar de generar un juego de isocronas a través del método setIsocronas(). e.newval proporcionará el nuevo valor del atributo isocronasi.

routeset

Se desencadena al terminar de generar la ruta entre el origen y el centro definido como destino mediante el método setRuta(). e.newval proporcionará el nuevo calor del atributo ruta.

statuschange

Se desencadena siempre que se lleva a cabo una acción que provoca un cambio en el mapa desde crear un origen o cambiar de zoom. Para conocer cuál es la acción, puede consultarse el atributo attr del evento:

g.on("statuschange", e => console.log(`El culpable soy yo, ${e.attr}`));
statusset

Se desencadena al acabar de aplicar el estado inicial del mapa. El evento dispone del atributo status para saber si se aplicó una configuración guardada.

Centro

Los centros son objetos de las características propias del tipo L.Marker.Mutable que definen:

  • Si el centro es el origen de los viajes tiene definido un evento adicional:

    geocode

    Se desencadena cuando se asigna valor al atributo postal de la marca:

    g.on("originset", e => {

    if(!e.newval) return; e.newval.once("geocode", f => { console.log(Pues sí, estoy en '${f.newval}'); });

    });

en concreto las siguientes correcciones y filtros:

Correcciones

Se pueden definir correcciones bien sobre la oferta, bien las adjudicaciones.

Oferta

bilingue

Permite corregir las enseñanzas impartidas basándose en los planes de bilingüismo. Se aplica así:

Centro.correct("bilingue", {
   bil: [ "Inglés", "Francés"],
   inv: false
}):

Su sentido es el de eliminar las enseñanzas que sean bilingües en alguno de los idiomas mencionados. Este sentido se produce cuando no se incluye la opción inv o se hace con un valor falso. Añadir inv con valor true implica invertir el significado, por lo que en este caso concreto:

Centro.correct("bilingue", {
   bil: [ "Inglés", "Francés"],
   inv: true
}):

significa no eliminar las enseñanzas que sean bilingües en inglés o francés.

Note

Hay otras correcciones que admiten la opción inv como inversor de significado. Se notará a partir de ahora incluyéndola como en el primer ejemplo con su valor a false, pero sin detallar más para no resultar tedioso.

Si se añade un añade un tercer argumento true:

Centro.correct("bilingue", {
   bil: [ "Inglés", "Francés"],
   inv: false
}, true):

lanza automáticamente una corrección adjpue que elimina los puestos bilingües asociados.

Note

A partir de ahora, si la corrección es capaz de lanzar automáticamente alguna otra, se notará este hecho incluyendo im tercer argumento false.

Elimina las enseñanzas que se sumunistran:

Centro.correct("ofens", {
   ens: ["23GMSMR168", "23GSASI820"],
   inv: false
}, false);

En este caso, se eliminarán de las oferta de cada centro las enseñanzas con esos dos códigos.

Si se habilita el encadenamiento, se lanzará una corrección adjpue que elimina los puestos que sólo puedan impartir clase en las enseñanzas eliminadas.

deseable

Elimina enseñanzas no desables, que son aquellas no marcadas como preferentes en la base de datos. Por ejemplo, para una especialidad como Matemáticas los bachilleratos (frente a la enseñanza secundaria):

Centro.conrrect("deseable", {});

Note

En realidad, la corrección está implementada como una una corrección que no filtra nada, sino que lanza automáticamente una corrección ofens. No es necesario añadir el tercer argumentoa true, porque el encadenamiento se lanza automáticamente.``

turno

Elimina enseñanzas que sean del turno indicado, de manera que 1 representa la mañana, y 2 la tarde:

Centro.correct("turno", {
   turno : 1,
   inv: false
});

En este caso, se eliminan las enseñanzas que se impartan por la mañana.

nueva

Elimina enseñanzas que no sean de nueva implantación:

Centro.correct("nueva", {});

Adjudicaciones

vt+

Agrega a las adjudicaciones del procedimiento, las aparecidas en septiembre como consecuencia del aumento en las plantillas de funcionamiento. Son las que se notan como telefónicas en la aplicación. No requiere opciones:

Centro.correct("vt+", {});
adjpue

Elimina adjudicaciones según el puesto. En este caso:

Centro.correct("adj", {
   puesto: [ "00590059", "11590107" ],
   inv: false
});

elimina las adjudicaciones que sean de los puestos 00590059 y 11590107.

vt

Elimina adjudicaciones que no hayan sido telefónicas:

Centro.correct("vt", {});
adjref

Elimina las adjudicaciones hechas a adjudicatarios con mayor prioridad que el adjudicatario que se proporciona como referencia. Para establecer este referente se proporcionan tres opciones:

  • col, que representa el colectivo, según la letra que tiene asignada (véase el GeoJSON de datos).
  • ts, que es el tiempo de servicio del funcionario y se expresa como un array de tres enteros ([años, meses, días]). Si no se proporciona este tiempo para los funcionarios no interinos, se estima basándose en el escalafón.
  • esc, que es el número de escalafón de los funcionarios de carrera y en prácticas.

Por ejemplo:

Centro.correct("adjref", {
   colectivo: "DB",  // Funcioanrio con comisión de servicios.
   esc: 20041111,
   ts: [9, 10, 2]
});

Note

Recuerde que la aplicación y desaplicación de correcciones tiene asociados eventos. Consulte estos eventos en la documentación de Leaflet.mutatismutandis

Filtros

Hay definidos los siguientes filtros:

adj

Elimina centros que se tengan menos de un determinado número de adjudicaciones. Requiere pasar el atributo min:

g.Centro.filter("adj", {min: 1});

En este caso, se filtrarán los centros sin ninguna adjudicación.

oferta

Elimina centros que se hayan quedado con menos de un determinado número de enseñanzas. Se usa exactamente del mismo modo que el anterior:

g.Centro.filter("oferta", {min: 1});
tipo

Elimina centros según su dificultad, que puede ser normal, compensataria (1) dificil [desempeño] (2). Debe pasársele un atributo tipo cuyo valor debe ser la suma de los tipos de centro que se quieren filtrar:

g.Centro.filter("tipo", {tipo: 1});  // Filtra de compensatoria.
g.Centro.filter("tipo", {tipo: 2});  // Filtra de difícil desempeño.
g.Centro.filter("tipo", {tipo: 3});  // Filtra de ambos tipos.

Es posible añadir la atributo inv para invertir el sentido del filtro:

g.Centro.filter("tipo", {tipo: 3, inv: true});  // Filtra centros normales.
lejos

Elimina centros que se encuentren fuera de una determinada área. El nombre deriva de que se aplica a las áreas que encierran las isocronas y, en consecuencia, filtra centros más lejano en tiempo al que define la isocrona. Puede aplicarse pasando un area en formato GeoJSON:

const iso20 = g.getIsocronas(true)[1];  // // Área que encierra la isocrona de 20 min
g.Centro.filter("lejos", {area: iso20}); // Filtro centros alejados en más de 20 min

Note

Recuerde que la aplicación y desaplicación de filtros tiene asociados eventos. Consulte estos eventos en la documentación de Leaflet.mutatismutandis

Peticiones de destino

Para facilitar la creación de una lista de peticiones el objeto de acceso al mapa y las marcas de centro añaden algunos atributos y eventos; y se crea un nuevo tipo de marcas mutables (Localidad) y un nuevo tipo de objeto solicitud.

Objeto de manipulación del mapa

Atributos

mode

Modo de trabajo. Hay definidos dos:

  • el modo «*normal*», que provoca que un click de ratón sobre la marca de un centro lo seleccione; y
  • el modo «solicitud», que en vez de seleccionar el centro, lanza el evento requestclick. En este segundo modo, el evento también se lanza cuando se hace click sobre la marca de una localidad.

Note

Esto es cierto siempre que la opción light del objeto sea verdadera. Si no es el caso, no hay ninguna acción asociada al click sobre el centro.

Note

Pulsar sobre un centro en modo "solicitud", no provoca ningún cambio en la lista de peticiones: sólo desencadena el método requestclick.

solicitud

Objeto que permite manipular la lista de peticiones. Tiene sus propios métodos y atributos que será necesario conocer si se implementa la solicitud de centros. Por ejemplo, esta orden:

g.solicitud.add(11004866);

añade al final de la lista de peticiones el centro con el código indicado.

Localidad

Tipo de Marca mutable, análoga a Centro, para representar localidades:

g.Localidad.store.length;  // Cantidad de localidad cargadas.

Más adelante volveremos a tratar Localidad.

Eventos

modeset

Se lanza cuando cambia el modo de trabajo. Como en otros tipos de eventos, el objeto evento guarda en el atributo oldval el modo viejo y en newval el nuevo:

g.on("modeset", e => {
   if(e.oldval !== e.newval) {
      console.log(`Ha pasado de ${e.oldval} a ${e.newval}`);
   }
});
requestclick

Se lanza cada vez que se pulsa un centro o localidad en el modo "solicitud" (y la opción light sea true). El evento añade el atributo marker que identifica la marca sobre la que se ha pulsado:

g.on("requestclick", e => {
   const data = e.marker.getData(),
         nombre = data.nom?data.nom:data.id.nom;

   console.log("Parece que quiere pedir", nombre);
});
requestset

Se lanza cada vez que un centro modifica su atributo de petición. El evento dispone de los atributos oldval y newval para conocer los valores de las peticiones; y marker para conocer cuál fue el centro que modificó el atributo:

g.on("requestset", e => {
   const data = e.marker.getData(),
    nom = data.id?data.id.nom:data.nom;

   if(e.newval === 0) {
      console.log(`Deja de pedirse '${nom}'`);
   }
   else {
      console.log(`Se pide '${nom}' en la petición ${e.newval}`);
   }
});
requestchange

Se lanza cada vez que se cambia la lista de peticiones. El evento dispone de un atributo markers que es un array que contiene todas las marcas de los centros y localidades que han modificado su valor.

Note

Advierta que cuando se provoca un cambio en la lista, este evento se desencadena una vez y el anterior lo hace tantas veces como cuentros hayan modificado su petición.

locloaded

Se lanza cuando acaban de cargarse las localidades de su archivo GeoJSON correspondiente:

g.on("locloaded", e => {
   console.log(`Las ${g.Localidad.store.length} localidades ya están disponibles`);
});

Centro

Se define el estilo de icono "solicitud", distinto radicalmente al estilo "boliche", y que sólo muestra como dato relevante el número de petición.

Además, los datos incorporan uno llamado petición, que indica en que posición se ha pedido el centro. Si el centro no está pedido, vale 0, que es el valor asignado en un comienzo a todos los centros:

const centro = g.Centro.get(21002100);
centro.getData().peticion > 0  // true, si el centro se ha solicitado.

Para posibilitar el filtrado de centros según se soliciten, se añade el filtro:

solicitado

Elimina los centros que se hayan solicitado, a menos que se incluya la opción inv como true, en cuyo caso tendrá el sentido contrario:

g.Centro.filter("solicitado", {});  // Filtra los centros solicitados.

Objeto solicitud

El objeto solicitud enganchado al objeto de manipulación del mapa presenta la siguiente API:

Atributos

list

Array con los códigos de los centros y localidades solicitadas. En el caso de los centros el código se muestra como una cadena de 9 caracteres el último de los cuales es el carácter C; y en el caso de las localidades, como una cadena de 10 caracteres el último de los cuales es el carácter L.

BolicheIcono

Devuelve el icono del boliche. Por tanto:

g.getIcon("boliche") === g.solicitud.BolicheIcono  // true
SolicitudIcono

Devuelve el icono de solicitud. Por tanto:

Métodos

Warning

Cuando un método acepta como argumento un centro o localidad, admite el código numérico, el código de cadena y el código normalizado (el que acaba en "C" o "L").

add(centro|localidad)

Añade el centro (o localidad) suministrado al final de la lista de peticiones. El argumento puede ser el código (en cualquiera de sus tres versiones) o el objeto marca que lo representa en el mapa.

Si la adición tiene éxito, devuelve el propio centro; en caso contrario (p.e. porque el centro no existe o porque ya se encontraba en la lista, devuelve null).

g.solicitud.add(11004866);
g.solicitud.add(21002100);
g.solicitud.add("23001111C");
g.solicitud.add(g.Centro.get(11700603));
g.solicitud.list;  // Devuelve ["11004866C", "21002100C", "23001111C", "11700603C"]
getCentro(pos)

Devuelve la marca del centro (o localidad) que ocupa la posición pos en la lista de peticiones. Devuelve null, si la posición no existe:

const centro = g.solicitud.getCentro(1);
centro.getData().id.cod;  // Devuelve 11004866
getPosition(centro|localidad)

Devuelve la posición en la lista de peticiones del centro (o localidad) suministrado. Si no se encuentra el centro, se devuelve 0:

g.solicitud.getPosition(11004866);  // Devuelve 1.
remove(centro|localidad)

Elimina el centro solicitado de la lista de peticiones. Devuelve un array con todos los centros afectados, esto es, un array que contiene el propio centro y todos los posteriores:

g.solicitud.remove(23001111);
g.solicitud.list;  // Devuelve ["11004866C", "21002100C", "11700603C"]
delete(pos, cuantos)

Elimina de la listas tantos centros (o localidades) como se especifique en cuántos a partir de la posición indicada. Si no se especifica cuántos, borra hasta el final de la lista:

g.solicitud.delete(2, 2);
g.solicitud.list;  // Devuelve ["11004866C", "11700603C"]

Devuelve un array con las marcas de los centros afectados por la eliminación, o sea, los eliminados y todos los que iban por detrás en lista de peticiones.

insert(centro, pos)

Agrega un centro (o localidad) en la posición indicada de la lista de peticiones. Devuelve un array con las marcas de los centros afectados por la eliminación:

g.solicitud.insert(11004039, 3);
move(pos1. pos2, cuantos)

Mueve tantos centros como especifique cuantos desde la pos1 a la posición necesaria para que se inserten antes del que ocupa la pos2:

g.solicitud.list;  // Devuelve ["11004866C", "21002100C", "23001111C", "11700603C"]
g.solicitud.move(1, 4, 2);
g.solicitud.list;  // Devuelve ["23001111C", "11004866C", "21002100C", "11700603C"]

Devuelve, como el resto de métodos, un array con todos los centros.

Note

Todos los métodos que alteran la lista de peticiones, se encargan de modificar el atributo peticion de los datos de cada centro que sufre cambios en su número de petición. También alteran el valor de status para incorporar la nueva lista.

Note

La lista de peticiones se conserva, aunque se cambie de especialidad. Los centros solicitados que en la nueva especialidad no existan, carecerán de marca, por lo que internamente se almacenará para ellos no una marca, sino el código correspondiente. Esto tiene repercusión en los valores de retorno de aquellos métodos que devuelven las marcas de los centros afectados por un cambio en la lista, ya que consecuentemente no devolverán las marcas de estos centros inexistentes, sino sus códigos normalizados.

Localidad

Como además de pedirse centros pueden pedirse localidades, el objeto incorpora también este tipo de marca mutable cuya única opción de dibujo depende de si la localidad se pidió o no. De modo análogo a Centro incorpora un método:

get(codigo)

Obtiene la marca correspondiente a partir de su código, en cualquiera de las tres versiones posibles:

jerez = g.Localidad.get(110200014);
jerez = g.Localidad.get("110200014");
jerez = g.Localidad.get("110200014L");

Además, también como se hace con Centro, se incorporta un getter a los datos que proporciona el código normalizado:

jerez.getData().cod;     // Devuelve 110200014
jerez.getData().codigo;  // Devuelve 110200014L

Estas localidades se cargan en la propia capa cluster a partir de un archivo GeoJSON con el siguiente aspecto:

{
   "type": "FeatureCollection",
   "features": [
      {
         "type": "Feature",
         "geometry": {
            "type": "Point",
            "coordinates": [-6.116667, 36.7]
         },
         "properties": {
            "nom": "Jerez de la Frontera",
            "cod": "110200014"
         }
      },
      {
         "type": "Feature",
         "geometry": {
            "type": "Point",
            "coordinates": [-5.983333, 37.383333]
         },
         "properties": {
            "nom": "Sevilla",
            "cod": "410910002"
         }
      }
   ]
}

Como se observa, los únicos datos de interés de cada localidad son sus coordenadas, su nombre y su código.

Las localidades sólo tiene habilitados dos filtros:

invisible

Filtra todas las localidades indiscriminadamente:

g.Localidad.filter("invisiable", {});

Este filtro es el responsable de que no se vea ningún centro al abrir el mapa, ya que está aplicado por defecto,

solicitado

Filtro análogo al homónimo solicitado de Centro, por lo que filtra las localidades que hayan sido solicitadas.

Recetas

Cambiar icono al solicitar centro

g.on("requestset", e => {
   e.marker.refresh();
   if(e.marker instanceof e.target.Centro) {
      // Solo si pasa de pedido a no pedido
      // o viceversa debe cambiarse el icono.
      if(!!e.newval !== !!e.oldval) {
         const tipo = e.newval === 0?"BolicheIcono":"SolicitudIcono",
               Icono = e.target.solicitud[tipo];

         Icono.onready(() => e.marker.setIcon(new Icono()));
      }
   }
});

Ocultar centros filtrados

g.Centro.filter("solicitado", {});

Mostrar localidades sin bloquear la interfaz

g.Centro.unfilter("invisible");
g.Centro.invoke("refresh", g.progressBar);

  1. Lo cual no significa que devuelve todas las marcas de centro, ya que puede haber centros que no se encuentren sobre el mapa porque hayan ido desaparecido al filtrarse. Para obtener todos los centros necesitaría recurrir a g.Centro.store.

  2. Los códigos normalizados son cadenas de ocho dígitos y una letra "C" para centros y nuevo dígitos y una letra "L" para localidades.

About

Mapa de adjudicaciones y oferta de centros educativos (core)

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published