const minZoomForRequest = 16; const urlADSL = 'https://tools.aquilenet.fr/cgi-bin/recherchend.cgi' const urlTestFTTH = 'https://tools.aquilenet.fr/cgi-bin/test.cgi' const streetTypeConversion = new Map(); streetTypeConversion.set("aire", "aire") streetTypeConversion.set("allée", "all") streetTypeConversion.set("allee", "all") streetTypeConversion.set("avenue", "av") streetTypeConversion.set("base", "base") streetTypeConversion.set("boulevard", "bd") streetTypeConversion.set("cami", "cami") streetTypeConversion.set("carrefour", "car") streetTypeConversion.set("chemin", "che") streetTypeConversion.set("cheminement", "chem") streetTypeConversion.set("chaussée", "chs") streetTypeConversion.set("cité", "cite") streetTypeConversion.set("cite", "cite") streetTypeConversion.set("clos", "clos") streetTypeConversion.set("coin", "coin") streetTypeConversion.set("corniche", "cor") streetTypeConversion.set("cote", "cote") streetTypeConversion.set("cour", "cour") streetTypeConversion.set("cours", "crs") streetTypeConversion.set("domaine", "dom") streetTypeConversion.set("descente", "dsc") streetTypeConversion.set("ecart", "eca") streetTypeConversion.set("esplanade", "esp") streetTypeConversion.set("faubourg", "fg") streetTypeConversion.set("gare", "gare") streetTypeConversion.set("grande rue", "gr") streetTypeConversion.set("hameau", "ham") streetTypeConversion.set("halle", "hle") streetTypeConversion.set("ilôt", "ilot") streetTypeConversion.set("impasse", "imp") streetTypeConversion.set("lieu dit", "ld") streetTypeConversion.set("lotissement", "lot") streetTypeConversion.set("marché", "mar") streetTypeConversion.set("montée", "mte") streetTypeConversion.set("parc", "parc") streetTypeConversion.set("passage", "pas") streetTypeConversion.set("place", "pl") streetTypeConversion.set("plan", "plan") streetTypeConversion.set("plaine", "pln") streetTypeConversion.set("plateau", "plt") streetTypeConversion.set("pont", "pont") streetTypeConversion.set("port", "port") streetTypeConversion.set("promenade", "pro") streetTypeConversion.set("parvis", "prv") streetTypeConversion.set("quartier", "qua") streetTypeConversion.set("quai", "quai") streetTypeConversion.set("résidence", "res") streetTypeConversion.set("residence", "res") streetTypeConversion.set("ruelle", "rle") streetTypeConversion.set("rocade", "roc") streetTypeConversion.set("rond point", "rpt") streetTypeConversion.set("route", "rte") streetTypeConversion.set("rue", "rue") streetTypeConversion.set("sentier", "sen") streetTypeConversion.set("sente", "sen") streetTypeConversion.set("square", "sq") streetTypeConversion.set("tour", "tour") streetTypeConversion.set("terre-plein", "tpl") streetTypeConversion.set("traverse", "tra") streetTypeConversion.set("villa", "vla") streetTypeConversion.set("village", "vlge ") streetTypeConversion.set("voie", "voie") streetTypeConversion.set("zone artisanale", "za") streetTypeConversion.set("zone d'aménagement concerté", "zac") streetTypeConversion.set("zone d'aménagement différé", "zad") streetTypeConversion.set("zone industrielle", "zi") streetTypeConversion.set("zone", "zone") let markers = new Map(); // Default search bounds DEFAULT_MAX_LNG_INTERVAL = 0.0028 DEFAULT_MAX_LAT_INTERVAL = 0.0014 // Search bounds from server server_max_lng_interval = undefined server_max_lat_interval = undefined function getRectangleCoord(map) { max_lng_interval = DEFAULT_MAX_LNG_INTERVAL max_lat_interval = DEFAULT_MAX_LAT_INTERVAL if (server_max_lat_interval !== undefined && server_max_lng_interval !== undefined) { max_lng_interval = server_max_lng_interval max_lat_interval = server_max_lat_interval } let center = map.getCenter(); let corner1 = L.latLng(center.lat - (max_lat_interval / 2), center.lng - (max_lng_interval / 2)); let corner2 = L.latLng(center.lat + (max_lat_interval / 2), center.lng + (max_lng_interval / 2)); return [corner1, corner2] } function initMap(btn) { // Init map position/zoom. Potentially using what's in the URL search string. const params = new URLSearchParams(window.location.search); let x = parseFloat(params.get('x')); let y = parseFloat(params.get('y')); let z = parseInt(params.get('z')); let map = L.map('map'); if (x && y && z) { map.setView([y, x], z); fetchEligData(map); } else { map.setView([46.710, 3.669], 6); } L.tileLayer('https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors', maxNativeZoom: 19, maxZoom: 19 }).addTo(map); map.on("zoom move", () => { /* We only want to enable the search button when we reached a sufficient zoom level */ if (btn.disabled && map.getZoom() >= minZoomForRequest) { displayBtn(btn); } if (!btn.disabled && map.getZoom() < minZoomForRequest) { hideBtn(btn); } }); map.on("zoomend moveend", () => { if (map.getZoom() >= minZoomForRequest) { fetchEligData(map); } }); return map; } async function initLimitsBox(map, btn) { // Create box to show where data is fetched const box = createRectangleBox(map); await getServerBoxBounds(map, box); box.addTo(map); map.on("zoom move zoomend moveend", () => { box.setBounds(getRectangleCoord(map)) }) btn.addEventListener("click", () => { getServerBoxBounds(map, box); }); addEventListener("resize", () => { getServerBoxBounds(map, box); }); } function createRectangleBox(map) { return L.rectangle(getRectangleCoord(map), { color: "#ff7800", fillOpacity: 0.07, weight: 1 }); } // Ask server the narrowed area bounds that it will search in async function getServerBoxBounds(map, box) { const bounds = map.getBounds(); const sw = bounds.getSouthWest(); const ne = bounds.getNorthEast(); const reqUri = encodeURI(`eligdata/bounds?swx=${sw.lng}&swy=${sw.lat}&nex=${ne.lng}&ney=${ne.lat}`); const resp = await fetch(reqUri); if (resp.status != 200) { return } const data = await resp.json(); server_max_lat_interval = data.bounds.ney - data.bounds.swy server_max_lng_interval = data.bounds.nex - data.bounds.swx box.setBounds(getRectangleCoord(map)) } function initAddrSearch(map) { const autocompleteOptions = { debounceTime: 300, search: async (query) => { if (query.length > 2) { const mapCenter = map.getCenter(); const reqUri = `https://photon.komoot.io/api/?q=${encodeURI(query)}&lat=${mapCenter.lat}&lon=${mapCenter.lng}&limit=20&lang=fr`; const source = await fetch(reqUri); const data = await source.json(); return data.features; } else { return []; } }, renderResult: (res, props) => { const p = res.properties; if (p.name && p.postcode && p.city && p.county && res.geometry.coordinates && res.geometry.coordinates.length === 2) return `
  • ${p.name} - ${p.postcode} ${p.city}, ${p.county}
  • `; else return ""; }, onSubmit: async (res) => { const searchInput = document.getElementById('search-addr-autocomplete-input'); const p = res.properties; searchInput.value = `${p.name} - ${p.postcode} ${p.city}, ${p.county}`; // We already filtered out the result not having strictly 2 coordinates at item display map.setView([res.geometry.coordinates[1], res.geometry.coordinates[0]], 19); fetchEligData(map); } }; const autocompleteAddr = new Autocomplete("#search-addr-autocomplete", autocompleteOptions); return autocompleteAddr; } function updateEligData(map, eligData) { let buildings = eligData.buildings; buildings.forEach(building => { if (!markers.has(building.idImm)) { const latlng = new L.latLng(building.y, building.x); let addrImm = `${building.numVoieImm} ${building.typeVoieImm} ${building.nomVoieImm}` if (building.bat_info != "") { addrImm += ` (Bat ${building.bat_info})` } let colorMarker = 'black' let messageElig = `` // On construit l'appel API pour le test FTTH, on indique si c'est éligible Kosc et/ou Axione dans l'url eligTestApi = `eligtest/ftth?idImm=${building.idImm}&codePostal=${building.codePostal}&axione=${building.aquilenetEligStatus.isEligible}&liazo=${building.fdnEligStatus.isEligible}` // éligible chez Aquilenet, lien pour le test if (building.aquilenetEligStatus.isEligible) { // Si fibre Axione déployé mais pas encore commandable if (building.aquilenetEligStatus.ftthStatus == "DEPLOYE MAIS NON COMMANDABLE") { colorMarker = 'orange' messageElig = `

    Fibre deployée mais ne sera commandable qu\'à partir du ${building.aquilenetEligStatus.dateCommandable}

    ` } else { messageElig = `

    Fibre deployée et disponible par Aquilenet !

    ` const zip = encodeURIComponent(building.codePostal); const idImm = encodeURIComponent(building.idImm); messageElig += `
    Tester l'éligibilité` colorMarker = 'green' } // pas de données Axione mais éligible peut-être Kosc ou au moins ARCEP // Enfin on affiche un lien vers le test d'éligibilté FTTH avec Kosc & Netwo } else if (building.fdnEligStatus.isEligible || building.othersEligStatus.isEligible) { messageElig = `

    Fibre deployee mais pas chez Axione !` messageElig += `
    Tester l'eligibilite par Kosc, Netwo et Bouygues

    ` colorMarker = 'orange' } else { messageElig = `

    Fibre non deployee :(

    ` const zip = encodeURIComponent(building.codePostal); const comm = encodeURIComponent(building.commune); let convertType = streetTypeConversion.get(building.typeVoieImm.toLowerCase()); if (!convertType) { convertType = building.typeVoieImm; } const street = encodeURIComponent(`${convertType} ${building.nomVoieImm}`) const street_nb = encodeURIComponent(building.numVoieImm) messageElig += `
    Tester ADSL a cette adresse
    Si la fibre a été recemment installée chez vous, il se pourrait que ce test soit erroné, cliquez ici pour tout de même tester l'eligibilité fibre` if (building.othersEligStatus.reasonNotEligible != "") { messageElig += `

    Status general ARCEP: ${building.othersEligStatus.reasonNotEligible}` } } // Si pas d'éligibilité fibre, on affiche la raison si elle existe if (building.aquilenetEligStatus.reasonNotEligible != "") { messageElig += `
    Pour Aquilenet, raison non eligible: ${building.aquilenetEligStatus.reasonNotEligible}` if (building.aquilenetEligStatus.dateCommandable != "") { messageElig += ` (date commandable: ${building.aquilenetEligStatus.dateCommandable})` } } var markerIcon = new L.Icon({ iconUrl: `static/icons/marker-icon-${colorMarker}.png`, shadowUrl: 'static/vendor/images/marker-shadow.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] }); // if (building.othersEligStatus.isEligible) { // messageElig += `
    Tester d'autres offres via Netwo` // } const marker = new L.marker(latlng, { icon: markerIcon, zIndexOffset: - building.etat_imm_priority }) .bindPopup(`${addrImm}
    ${building.codePostal} ${building.commune}` + `

    ${messageElig}

    Ref Immeuble: ${building.idImm}`, { maxWidth: 560 }); map.addLayer(marker); markers.set(building.idImm, marker) } }); } function updateUrl(map) { const c = map.getCenter(); history.replaceState({}, "", encodeURI(`?x=${c.lng}&y=${c.lat}&z=${map.getZoom()}`)); } async function fetchEligData(map) { const zoom = map.getZoom(); if (zoom >= minZoomForRequest) { const bounds = map.getBounds(); const sw = bounds.getSouthWest(); const ne = bounds.getNorthEast(); let btn = document.getElementById("btn-load-elig-data"); waitBtn(btn); const reqUri = encodeURI(`eligdata?swx=${sw.lng}&swy=${sw.lat}&nex=${ne.lng}&ney=${ne.lat}`); const resp = await fetch(reqUri); if (resp.status == 200) { const eligData = await resp.json(); updateEligData(map, eligData); } else { error = await resp.text() console.log(`Error could not get data from server: ${resp.status} ${error}`) } updateUrl(map); displayBtn(btn); } } function initBtn() { const btn = document.getElementById("btn-load-elig-data"); btn.disabled = true; btn.title = "Veuillez zoomer plus la carte pour charger l'éligibilité."; return btn; } function setBtnListener(btn, map) { btn.onclick = () => { // Reset markers when button is clicked if (markers) { for (let marker of markers.values()) { map.removeLayer(marker); } markers.clear(); } fetchEligData(map); } } function displayBtn(btn) { btn.classList.remove('loader'); btn.disabled = false; btn.title = "Actualiser la recherche dans cette zone" btn.innerHTML = "Actualiser"; } function hideBtn(btn) { btn.disabled = true; btn.innerHTML = "Zoomez sur la carte"; btn.title = "Veuillez zoomer plus la carte afin de lancer la recherche d'éligibilité."; } function waitBtn(btn) { btn.disabled = true; btn.innerHTML = ""; btn.title = "Chargement des batiments..."; btn.classList.add('loader'); } // Init button and map const btn = initBtn(); const map = initMap(btn); const addrSearch = initAddrSearch(map); setBtnListener(btn, map); // Init a limits box that shows area where data will be fetched initLimitsBox(map, btn);