3.2. Mapa de oferta y adjudicaciones

La aplicación utiliza leafext.js para desarrollar un objeto que implemente un mapa de adjudicaciones provisionales y oferta educativa. Tal desarrollo se encuentra dentro del directorio dist/adjofer/maps y el epígrafe esta dedicado a describir cómo usar tal objeto para construir una interfaz visual para ese mapa.

Advertencia

Se presupondrá que el desarrollador está familiarizado con el uso de la librería Leaflet.

3.2.1. Características

El objeto posibilita:

  • Disponer sobre el mapa marcas que representas 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 distintos filtros predefinidos.
  • Utilizar distintos estilos para los iconos que representan centros.
  • Definir un origen de viajes.
  • Consultar la ruta entre el origen y cualquier centro.
  • Definir con respecto al origen las isocronas de 10, 20, 30, 40, 50 y 60 minutos.

3.2.2. Requisitos

En el documento HTML es necesario cargar una serie de scripts y hojas de estilo:

<!-- Leaflet -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css"
      integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA=="
      crossorigin="">
<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet.js"
         integrity="sha512-QVftwZFqvtRNi0ZyCtsznlKSWOStnDORoefr1enyq5mVL4tmKB3S/EnC3rRJcxCPavG10IcrVGSmPh6Qw5lwrg=="
         crossorigin=""></script>

<!-- Plugin: Añade botón para maximizar el mapa -->
<script src='https://api.mapbox.com/mapbox.js/plugins/leaflet-fullscreen/v1.0.1/Leaflet.fullscreen.min.js'></script>
<link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-fullscreen/v1.0.1/leaflet.fullscreen.css' rel='stylesheet'>

<!-- Plugin: Agrupa marcas contiguas -->
<script src="https://unpkg.com/leaflet.markercluster@1.4.1/dist/leaflet.markercluster.js"></script>
<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">

<!-- Plugin: Menu contextual con el botón derecho -->
<script src="https://aratcliffe.github.io/Leaflet.contextmenu/dist/leaflet.contextmenu.js"></script>
<link rel="stylesheet" href="https://aratcliffe.github.io/Leaflet.contextmenu/dist/leaflet.contextmenu.css">

<!-- Librería turf: necesaria para isocronas -->
<script src='https://npmcdn.com/@turf/turf/turf.min.js'></script>

<!-- Plugin: Leaflet Control Search -->
<script src="https://cdn.jsdelivr.net/npm/leaflet-search@2.4.0/dist/leaflet-search.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet-search@2.4.0/dist/leaflet-search.min.css">
<link rel="alternate stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet-search@2.4.0/dist/leaflet-search.mobile.min.css">
<!-- Fuse.js: Fuzzy-search -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/fuse.js/1.2.2/fuse.min.js"></script>

A esta dependencias habría que añadir los scripts propios del mapa:

<!-- Extensión para el soporte de iconos mutables -->
<script src="../../dist/leafext.js"></script>

<!-- Particularidades de esta página -->
<script src="../../dist/maps/adjofer/map.js"></script>
<script src="scripts/demo.visual.js"></script>
<link rel="stylesheet" href="../../dist/maps/adjofer/css/adjofer.css">

3.2.3. 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 se corresponde con los datos relevantes de un 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
               }
            ]
         }
      }
   ]
}

Algunas apuntes clave para entender los datos son:

  • 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.

3.2.4. Creación del objeto

La primera acción para disponer del mapa es contruir el objeto y almacenarlo en una variable que sea accesible desde el resto del código.

mapAdjOfer(path, opts)

La función permite contruir un objeto de tipp MapAdjOfer que será el que nos permita crear e interactuar con el mapa:

const g = mapAdjOfer("../../dist", {
   zoom: 8,
   center: [37.45, -4.5],
   ors: {
      key: "xxxxx"
   }
});

Los parámerros necesarios son:

  • La ruta relativa al directorio donde se encuentre la aplicación.

  • Un objeto con las opciones de constitución del objeto. Estas opciones pueden ser:

    id

    Identificador del elemento HTML donde se empotrará el mapa. Por defecto, «map».

    light

    Si true, implementa algunos aspectos del comportamiento del mapa:

    • Click sobre el centro, lo selecciona.
    • Crea menús contextuales al hacer click derecho sobre el mapa, la marca que representa el origen de los viajes, la marca de los centros y las áreas que encierran las isocronas.

    Por defecto, true.

    search

    Crea un cajetín para localizar centros por nombre. Por defecto, true.

    icon

    Estilo del icono. Puede ser «boliche» o «chupachups». Por defecto, boliche.

    loading

    Función que construye un indicador para notar la carga de datos remotos. Si es true, usa el indicador interno; y si false, se prescindirá de indicador alguno. Valor predeterminado: true.

    unclusterZoom

    Zoom a partir del cual las marcas de centro se mostrarán siembre desagregadas. Por defecto, 14.

    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.

    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().

    ors

    Objeto que facilita las opciones para generar isocronas, crear rutas y geocodificar puntos utilizando la API de OpenRouteService. Acepta los siguientes atributos:

    • key: clave para el uso de la API REST de OpenRouteService.
    • rutaPopup: 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. Valor predeterminado: true.
    • loading: Tiene exactamente el mismo significado que la opción general. Su valor predeterminado es el que tenga la opción general.
    • chunkProgress: Función para mostrar el progreso en operaciones lentas (cálculo de isocronas). Si true, se usa el indicador interna, y si false, se prescinde de indicador. Valor predeterminado: true.

    Pueden, además, añadirse opciones propias del objeto L.Map como en el ejemplo zoom o center.

    Nota

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

3.2.5. Atributos

Advertencia

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 mapa[1]. No presenta ninguna característica extendida.

Centro

Clase de iconos mutables a la que pertenecen las marcas de centro. Sobra esta clase se pueden aplicar las correcciones y filtros.

Ver también

Revise lo expuesto sobre marcas en leafext.js y cómo se aplican correcciones y filtros.

El atributo añade el método .get(codigo) que permite obtener la marca del centro cuyo código es el suministrado:

centro = g.Centro.get(23001111);
centro.getData().id.cod // Devuelve 23001111

El código es posible también expresarlo como una cadena o como la cadena seguida del caracter «C» (mayúscula):

centro = g.Centro.get("23001111");
centro = g.Centro.get("23001111C");

Por otra parte a los datos se incorpora un getter, que permite obtener el código normalizado 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 mapa que ofrece el objeto GeoJSON de datos.

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.

Ver también

Consulte el 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 podríamos 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, y cambia al cambiar de origen. El establecimniento del origen está asociado al evento originset.

Presenta un atributo g.origen.postal que almacena la dirección postal, si es que se llegó a averiguar.

Nota

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

g.on("originset", e => {
   if(!e.newval) return;
   e.newval.on("geocode", x => {
      console.log(`Pues sí, estoy en '${x.newval}'`);
   });
});
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).

3.2.6. 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, cargar una nueva especialidad debería suponer:

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.

geoCodificar(query)

Obtiene la dirección postal de unas coordenadas, si no 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.

setOrigen(latlng)

Establece el origen de los viajes en el punto pasado como argumento.

La obtención del origen tiene asociado el evento originset.

calcularOrigen()

Obtener 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;
    
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 null 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.

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.

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.

getStatus(extra)

Devuelve una cadena que describe el estado actual del mapa (centro, zoom, origen, isochronas, 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,

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.

getIcon(estilo)

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

const Boliche = g,getIcon("boliche");
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 es el predeterminado y se basa en SVG.
  • chupachups, un estilo basado en CSS 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:

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());

3.2.7. Correcciones

Se han definido las siguientes correcciones a los datos de los centros:

Sobre la 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.

Nota

Hay otras correcciones que admiten la opción inv como inversor de significado. Se notará a partir de aahora 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):

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

Nota

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

ofens

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 como marcadas como preferentes en la base de datos. Por ejemplo, para una especialidad normal de secundaria, los bachilleratos (frente a la enseñanza secundaria que no lo es):

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

Nota

En realidad, la corrección está implementada como una una corrección que no filtrada nada, pero lenza 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», {});

Sobre las 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.

vi

Elimina adjudicaciones que no respondan a vacantes iniciales:

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

Elimina adjudicaciones que no hayan sido telefónicas:

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

Elimina adjudicaciones hechas a adjudicatarios con mayor prioridad que el adjudicatario que se proporciona como referencia. Para establecer este adjudicatario de referencia 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 números: [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]
});

Nota

Recuerde que la aplicación de una corrección C tiene asociado el evento «correct:C»; y su desaplicación, el evento «uncorrect:C».

3.2.8. Filtros

Se han definido los siguientes filtros:

adj

Elimina centros que se hayan con 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 centro de compensatoria.
g.Centro.filter("tipo", {tipo: 2});  // Filtra centro de difícil desempeño.
g.Centro.filter("tipo", {tipo: 3});  // Filtra ambos tipos de centro.

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

Nota

Recuerde que la aplicación de un filtro F tiene asociado el evento «filter:F»; y su desaplicación, el evento «unfilter:F». Además, las marcas concretas disparan el evento «filtered», si un filtro las filtra desde un estado no filtrado, y disparan el evento «unfiltered» si su remoción las restituye desde un estado filtrado.

3.2.9. Eventos

Hay toda una serie de eventos 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) {
      console.log(`Antes tenía seleccionado el centro ${e.oldval.getData().id.nom}`);
   }
   if(e.newval) {
      console.log(`Acaba de seleccionar el centro ${e.newoldval.getData().id.nom}`);
   }
});
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 isocronas.
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.

Nota

Se enumeran exclusivamente los nuevos tipos de eventos que introduce el objeto MapAdjOfer. Es obvio que para la creación de la interfaz visual seguiran siendo necesarios otros eventos como los asociados a las correcciones y filtros o a los eventos de ratón.

3.2.10. Petición de destinos

Para facilitar la creación de un formulario de petición de destinos, el objeto de manipulación del mapa añade dos 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.

Nota

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.

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.

Además de este atributo, los centros tiene dos características más relacionadas con la petición de destinos:

  • Entre sus datos un atributo llamado peticion que indica en que posición se pidió el centro. Si el centro no está pedido, vale 0. Al comienzo, todos los centros tiene este atributo a 0.
  • El estilo de icono «solicitud», distinto radicalmente al estilo «boliche», y que sólo muestra como dato relevante el número de petición.

3.2.10.1. Descripción de solicitud

3.2.10.1.1. 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».

Ver también

Revise lo referente a localidades, indicado más adelante.

BolicheIcono

Constructor para el icono de tipo boliche:

const Icono = g.solicitud.BolicheIcono;
centro.setIcon(new Icono());
SolicitudIcono

Constructir para el icono de tipo solicitud.

3.2.10.1.2. Métodos

add(centro)

Añade el centro (o localidad) suminitrado al final de la lista de peticiones. El argumento puede ser el código (como número o como cadena o incluso como cadena acabada en «C» o «L») o el objeto marca que lo representa en el mapa.

Nota

Para el resto de métodos en los que sea posible pasar como argumento un centro, son posibles todas estas posibilidades.

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

Ejemplo:

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 N 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)

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.
g.solicitud.getPosition("11004866C");  // Devuelve 1.
g.solicitud.getPosition(centro);  // Devuelve 1.
remove(centro)

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.

Nota

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.

Advertencia

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[2].

3.2.10.2. Eventos

Hay varios eventos del objeto MapAdjOfer aplicables exclusivamente a la petición de centros y localidades:

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}`);
   }
});

Advertencia

Pulsar sobre un centro en este modo «solicitud», no provoca ningún cambio en la lista de peticiones: es labor de programdor que así sea.

requestclick

Se lanza cada vez que se pulsa un centro o una localidad si se trabaja en el modo «solicitud». 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.

Nota

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.

3.2.10.3. Filtros

Para posibilitar el filtrado de centros según se hayan solicitado, está definido el filtro:

solicitado

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

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

3.2.10.4. Localidades

Para facilitar la petición de destinos el objeto incorpora también marcas que representan localidades:

Localidad

Tipo de marca para las localidades. Es de tipo mutable, como las de centro, pero con un diseño más sencillo y 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) para poder obtener la marca correspondiente a partir de su código, que puede estar en forma de número, de cadena o de cadena que añade el carácter «L» (mayúscula). En consecuencia:

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 facilita 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.

3.2.10.4.1. Filtros

Tiene definidos dos:

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, Es obvio que para poder seleccionar localidades al elaborar la lista de petición de destino, habrá de desaplicar este filtro.

solicitado
Filtro análogo al definido también la Centro, por lo que filtra las localidades que hayan sido solicitadas.

3.2.10.4.2. Eventos

locloaded

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

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

Los eventos requestclick y requestset también son aplicables a localidades.

3.2.10.5. Recetas

3.2.10.5.1. 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()));
      }
   }
});

3.2.10.5.2. Ocultar centros filtrados

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

3.2.10.5.3. Mostrar localidades sin bloquear la interfaz

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

Notas al pie

[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.