"use strict"; let cntNbr = []; let cursor = ''; let geojson = []; /* geojson and countries are separate objects which match by name. */ let geo = {} let country = {}; let mapName = ''; let continent = {}; let map = null; let coords = {}; // hash of country name to coordinates let outerArea = {"id":"MNE", "type":"Feature", "geometry":{ "type":"MultiPolygon", "coordinates" : [[[[-82.955,35.242],[-81.929,35.235],[-81.927,34.4],[-82.772,34.419],[-82.955,35.242]], [[-82.36,35.10],[-82.36,34.8],[-82.5,34.8],[-82.53,35.1],[-82.36,35.10]]]], }, "properties":{"name":"ob"}}; // "coordinates":[[[-82.755,35.242],[-81.929,35.235],[-81.927,34.4],[-82.772,34.419],[-82.755,35.242]]] // map.setFilter("countryNameGood", ["==", "name", 1]); function resetOuter(){ outerArea.geometry.coordinates = [[[[-82.955,35.242],[-81.929,35.235],[-81.927,34.4],[-82.772,34.419],[-82.955,35.242]]], [[-82.57643,35.07392],[-82.5788,35.07378],[-82.57993,35.07747],[-82.57799,35.07792],[-82.57643,35.07392]]]; // outerArea.geometry.coordinates = [[[[-82.955,35.242],[-81.929,35.235],[-81.927,34.4],[-82.772,34.419],[-82.955,35.242]]]]; // outerArea.geometry.coordinates = [[[[-82.955,35.242],[-81.929,35.235],[-81.927,34.4],[-82.772,34.419],[-82.955,35.242]], [[-82.36,35.10],[-82.36,34.8],[-82.5,34.8],[-82.53,35.1],[-82.36,35.10]]]]; // "coordinates":[[[-82.36,35.10],[-82.36,35.06],[-82.47,35.06],[-82.49,35.1],[-82.31,35.10]],[[-82.36,35.08],[-827,35.0],[-82.33,35.08],[-82.36,35.08]]]},"properties":{"name":"tone"}}, map.getSource('high').setData(outerArea); map.setFilter("highbox", ["==", "name", "ob"]); } function add(name, x){ if(x){ geo.features[cntNbr[name]].properties.active = 1; } else { geo.features[cntNbr[name]].properties.active = 0; } map.getSource('countries').setData(geo); map.setFilter("countryNameGood", ["==", "active",0]) } //function dP(name){ // geo.features[cntNbr[name]].properties.active = 0; // map.getSource('countries').setData(geo); // map.setFilter("countryNameGood", ["==", "active",0]) //} function addPolygon(name){ if( geojson[name].geometry.type === "MultiPolygon" ){ for (let i=0; i All Done. Click here to redo this map."); } else { document.getElementById("infoScreen").style.display = "block"; infoScreenOn(); } } function infoScreenOn() { } function infoScreenOff() { } function distanceBetween(p, p2) { let dx = p[0] - p2[0]; let dy = p[1] - p2[1]; return Math.sqrt(Math.pow( dx, 2) + Math.pow( dy, 2)); } function makeMap(map_name){ console.log("make make map"); coords = {}; // zero out var let mapNamePlus = "/u/z/" + map_name + "/map.json"; $.getJSON(mapNamePlus, function(data){ continent = data; continent.diagDist = distanceBetween(continent.bounds[0], continent.bounds[1]); cursor = ''; //global var if( typeof continent.tiles !== "undefined" ){ cursor = "crosshair"; circleGreen = '/images/greenWhiteCircle.png'; } if( continent.cursor ){ cursor = continent.cursor; circleGreen = '/images/greenWhiteCircle.png'; } setTimeout(function() { $('.maplibregl-canvas-container').css('cursor', cursor); }, 100); if (typeof continent.geojURL === "undefined") { continent.geojURL = "/u/z/" + map_name + "/geo.json"; } map = createMap( continent.geojURL, continent.tiles, continent.style, map_name, continent.bounds, continent.maxzoom, continent.attribution ); // overlays: if( typeof continent.overlay !== "undefined" || typeof continent.overlayWater !== "undefined" || typeof continent.overlayLines !== "undefined" || typeof continent.overlayPoints !== "undefined") { let cnt = 1900; let load_overlay = setInterval(function() { if( map.loaded() ){ clearInterval(load_overlay); if( typeof continent.overlay !== "undefined" ) { map.setFilter("mapBorder", ["==", "name", continent.overlay]); } if( typeof continent.overlayWater !== "undefined" ){ map.setFilter("justAddWater", ["==", "name", continent.overlayWater]); // overlayWater is not in any current data files. } if( typeof continent.overlayLines !== "undefined"){ map.setFilter("addLines", ["!=", "$type", "Point"]); if( typeof continent.overlayLines === "number" ){ map.setPaintProperty('addLines', 'line-width', continent.overlayLines); map.setPaintProperty('showLineG', 'line-width', (continent.overlayLines * 7)); // make right/wrong markings wider since lines are on map. map.setPaintProperty('showLineR', 'line-width', (continent.overlayLines * 7)); } else { map.setPaintProperty('showLineG', 'line-width', 15); // make right/wrong markings wider since lines are on map. map.setPaintProperty('showLineR', 'line-width', 14); } } if( typeof continent.overlayPoints !== "undefined"){ // map.json line: "overlayPoints" : true, map.setFilter("pointsOf", ["==", "$type", "Point"]); // city dots to click at. } } if( cnt-- < 0 ){ alert("Map taking too much time to load."); clearInterval(load_overlay); } }, 333); } if( continent.bounds ){ map.fitBounds(data.bounds, {padding: 8}); // sets zoom map before placing the question popup. } let polytype = {}; $.getJSON(continent.geojURL + "?1235", function(g){ geo = g; for( let i=0; i < geo.features.length; i++ ){ name = geo.features[i].properties.name; cntNbr[name] = i; geojson[name] = geo.features[i]; polytype[name] = geo.features[i].geometry.type; switch( polytype[name] ){ case "Polygon": coords[name] = geo.features[i].geometry.coordinates[0]; break; case "MultiPolygon": coords[name] = geo.features[i].geometry.coordinates; break; case "LineString": coords[name] = geo.features[i].geometry.coordinates; break; case "MultiLineString": coords[name] = geo.features[i].geometry.coordinates; break; case "Point": coords[name] = geo.features[i].geometry.coordinates; break; case "MultiPoint": coords[name] = geo.features[i].geometry.coordinates[0]; break; } } let SW_llx = map.getBounds()._sw.lng; // -89 bounds: 0 0 -88 x let SW_lly = map.getBounds()._sw.lat; // -5 0 1 -5 y let NE_llx = map.getBounds()._ne.lng; // -51 1 0 -56 let NE_lly = map.getBounds()._ne.lat; // 65 1 1 66 continent.area = 2 * area([[SW_llx,SW_lly], [SW_llx,NE_lly], [NE_llx,NE_lly]]); }); }); document.getElementById("infoScreen").style.display = "none"; // xverlayOff(); } // end makeMap function areaOf(name){ // to decide whether to place circle around if( geojson[name].geometry.type === "MultiPolygon" ){ let areaSum = 0; for (let m=0; m < coords[name].length; m++ ){ let vertices = coords[name][m]; areaSum += area(vertices[0]); } return areaSum; } if( geojson[name].geometry.type === "Point" || geojson[name].geometry.type === "MultiPoint" || geojson[name].geometry.type === "LineString" || geojson[name].geometry.type === "MultiLineString" ){ return 0.0001; } return area(coords[name]); // polygon } function area(vertices){ let total = 0; for (let i = 0, l = vertices.length; i < l; i++) { let addX = vertices[i][0]; let addY = vertices[i == vertices.length - 1 ? 0 : i + 1][1]; let subX = vertices[i == vertices.length - 1 ? 0 : i + 1][0]; let subY = vertices[i][1]; total += (addX * addY * 0.5); total -= (subX * subY * 0.5); } return Math.abs(total); } let ll_of_name = {}; function getLand_ll(name){ if(typeof ll_of_name[name] !== "undefined" ){ return ll_of_name[name]; } let sumlat = 0; let sumlng = 0; let count = 0 if(coords[name]) { if (geojson[name].geometry.type === "Polygon" || geojson[name].geometry.type === "LineString" ){ for (let j= 0; j< coords[name].length; j++){ let lat = coords[name][j][1]; let lng = coords[name][j][0]; sumlat += lat; sumlng += lng; count++; } } else if( geojson[name].geometry.type === "MultiPolygon" ){ for (let m=0; m < coords[name].length; m++ ){ let island = coords[name][m][0]; let isleSumLat = 0; let isleSumLng = 0; for (let n= 0; n< island.length; n++){ let lat = island[n][1]; let lng = island[n][0]; isleSumLat += lat; isleSumLng += lng; sumlat += lat; sumlng += lng; count++ } coords[name][m].lat = isleSumLat/island.length; coords[name][m].lng = isleSumLng/island.length; } } else if( geojson[name].geometry.type === "Point" ){ return [coords[name][0], coords[name][1] ]; } else if( geojson[name].geometry.type === "MultiLineString" ){ for (let m=0; m < coords[name].length; m++ ){ let lineseg = coords[name][m]; for (let n= 0; n< lineseg.length; n++){ sumlat += lineseg[n][1]; sumlng += lineseg[n][0]; count++ } } } } let lt = sumlat / count; let ln = sumlng / count; ll_of_name[name] = [ln, lt]; return [ln,lt]; } function createMap(geoURL, tiles, mystyle, name, bounds, mz = 22, atr="wikimedia") { let shakeyflag = 0; var center = [0,0]; let zoom = 13; let minzoom = 2; if( typeof mystyle === "undefined" ){ if(! tiles ){ tiles = '/' + name +'/tiles/{z}/tile_{x}_{y}.png'; } var mystyle = { "version": 8, "name": "Raster Tiles", "sources": { "TileLayer": { "attribution" : atr, "type": "raster", "tiles": [tiles], "maxzoom" : mz, "minzoom" : minzoom, "tileSize": 256 } }, "layers": [{ "id": "TileLayer", "type": "raster", "source": "TileLayer" }] }; } else { if( mystyle.includes("mapbox") ) { // change to labeled. mystyle = 'https://api.maptiler.com/maps/1695cdd4-2994-448d-b3d4-7446f978cf03/style.json?key=7zhdu6GExk8YG7dFLoDE'; // mapTiler } } if( bounds ){ center = [(bounds[0][0]+bounds[1][0])/2, (bounds[0][1]+bounds[1][1])/2]; zoom = 9.66 - (1.44 * Math.log2( distanceBetween( bounds[0], bounds[1] ) )); } maplibregl.accessToken = 'pk.eyJ1IjoiemVrZXNlbGJ5IiwiYSI6ImNpc2JycGc0MTAxNXAydnFvc2Z5eGpteHAifQ.QWjQ0kpS3usdtU-p83kC6w'; // good var map = new maplibregl.Map({ container: 'mapid', style: mystyle, zoom: zoom, center: center, interactive: true }); map.dragRotate.disable(); map.on('dragend', function(){ shakeyflag = 0; }); let url = '/u/z/schoolHigh/geo.json?999'; // + continent.geojURL; map.on('load', function() { map.addSource('high', { 'type': 'geojson', 'data': outerArea }); map.addLayer({ // layers for highlighting map area / xountry. 'id': 'highbox', 'type':'fill', 'source':'high', 'paint':{ 'fill-color': 'rgba(55, 211, 55, 0.29)', 'fill-outline-color': 'rgba(20, 40, 10, 0.99)' }, "filter": ["==", "name", ""] }); map.addSource('countries', { 'type': 'geojson', 'data': geoURL }); map.addLayer({ // layers for highlighting map area / xountry. 'id': 'countryNameGood', 'type':'fill', 'source':'countries', 'paint':{ 'fill-color': 'rgba(55, 211, 55, 0.89)', 'fill-outline-color': 'rgba(20, 40, 10, 0.99)' }, "filter": ["==", "active", "1"] }); map.addLayer({ 'id': 'mapBorder', 'type':'line', 'source':'countries', 'paint':{ 'line-color': 'rgba(1, 196, 1, .5)' ,'line-width': 6 }, "filter": ["==", "name", ""] }); map.addLayer({ 'id': 'showLineB', 'type':'line', 'source':'countries', 'paint':{ 'line-color': 'rgba(5, 5, 5, .66)' ,'line-width': 2 }, "filter": ["==", "name", ""] }); map.addLayer({ 'id': 'showLineG', // Green Line 'type':'line', 'source':'countries', 'paint':{ 'line-color': 'rgba(1, 196, 1, .8)' ,'line-width': 7 }, "filter": ["==", "name", ""] }); map.addLayer({ 'id': 'showLineR', // Red Line 'type':'line', 'source':'countries', 'paint':{ 'line-color': 'rgba(200, 2, 21, .8)' ,'line-width': 8 }, "filter": ["==", "name", ""] }); map.addLayer({ // layer for highlighting map area / xountry. 'id': 'justAddWater', // overlayWater is not in any current data files. 'type':'line', 'source':'countries', 'paint':{ 'line-color': 'rgba(1, 21, 116, .3)' ,'line-width': 8 }, "filter": ["==", "name", ""] }); map.addLayer({ // for giving pt targets for cities. 'id': 'pointsOf', 'type':'circle', 'paint':{ 'circle-color': 'rgba(1, 69, 155, .7)', 'circle-radius': 4 }, 'source':'countries', "filter": ["==", "name", ""] }); map.addLayer({ 'id': 'addLines', // overlaid lines for borders 'type':'line', 'source':'countries', 'paint':{ 'line-color': 'cornflowerblue' ,'line-width': 3 }, 'source':'countries', "filter": ["==", "name", ""] }); map.on('mousedown', function (e) { nonClickCount = 0; shakeyflag = 1; setTimeout(function(){shakeyflag=0}, 433); // length of time between mousedown/up to be a click }); map.on('mouseup', function (e) { if ( shakeyflag == 1 ) { shakeyflag = 0; showSchoolName(e); // clickedIt(e); } }); var touchStartEvent; map.on('touchstart', function (e) { nonClickCount = 0; shakeyflag = 1; touchStartEvent = e; setTimeout(function(){shakeyflag=0}, 433); // length of time between mousedown/up to be a click }); map.on('touchend', function (e) { if ( shakeyflag == 1 ) { shakeyflag = 0; showSchoolName(e); // clickedIt(e); } }); }); return map; } function inside(point, geo) { if( typeof geo === "undefined" || typeof geo.type === "undefined" ){ return false; } if( geo.type === "Polygon" ){ return inside_polygon(point, geo.coordinates[0]); } else if( geo.type === "MultiPolygon" ){ for (let k=0; k < geo.coordinates.length; k++ ){ if (inside_polygon(point, geo.coordinates[k][0])) { return true; } } } return false; } function inside_polygon(point, vs) { var x = point[0], y = point[1]; var inside = false; for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) { var xi = vs[i][0], yi = vs[i][1]; var xj = vs[j][0], yj = vs[j][1]; var intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); if (intersect) inside = !inside; } return inside; } // =============================== timer ============================================================= let mouseX, mouseY; // fat cursor when fast. let dX = 0, dY = 0; let prevX = 0, prevY = 0; let fatCurs = 0; $(document).mousemove(function(e) { mouseX = e.pageX; mouseY = e.pageY; }); function start_cursedSpeed() { // started and cleared by stop/start timer let cursedSpeed = setInterval(function(){ dX = prevX - mouseX; dY = prevY - mouseY; prevX = mouseX; prevY = mouseY; let dis = Math.sqrt(Math.pow(dX, 2) + Math.pow(dY, 2)); if( dis > 100 ){ if( fatCurs == 0 ){ $('.maplibregl-canvas-container').css('cursor', 'cell'); fatCurs = 1; } } else if( dis < 50 && fatCurs == 1 ) { fatCurs = 0; setTimeout(function() { $('.maplibregl-canvas-container').css('cursor', cursor); }, 333); } }, 200); } // ------------------------------ end timer funcs -------------------------------------------------------------- function showElems(elems){ // for el in elems { // geodata.features[index].geometry.coordinates.push(new_coords); // } map.setFilter("countryNameGood", ["==", "name", land.name]); } let correct_count = 0; let incorrect_count = 0; let nonClickCount = 0; let answer_mu = 0; function showSchoolName(e) { let pin; let land = country; pin = placePin(map, e.lngLat, '/images/yellowPin.png'); setTimeout(function(){ if( pin ){ pin.remove(); } answer_mu = 0; map.setFilter("countryNameGood", ["==", "name", ""]); // map.setFilter("countryNameBad", ["==", "name", ""]); map.setFilter("showLineR", ["==", "name", '']); map.setFilter("showLineB", ["==", "name", '']); map.setFilter("showLineG", ["==", "name", '']); map.setFilter("countryNameBadOutline", ["==", "name", ""]); // rm_circles(ans_circleArray); }, 700); // }, delaytime); // setLearnInterval(mapName, land.name, distancePercent); // gloval name } // ............................................................... function rm_circles(cA){ // todo delete this if (typeof cA[0] !== 'undefined') { for (let i = 0; i < cA.length; i++){ cA[i].remove(); } } } function flash_lines(name){ setTimeout(function(){ map.setFilter("showLineR", ["==", "name", '']); setTimeout(function(){ map.setFilter("showLineR", ["==", "name", name]); }, 400); }, 300); } function flash_area(name){ setTimeout(function(){ // map.setPaintProperty('countryNameBad', 'fill-color', 'rgba(256, 21, 21, 0.3)'); map.setPaintProperty('countryNameBadOutline', 'line-color', 'rgba(5, 2, 2, 0.6)'); setTimeout(function(){ // map.setPaintProperty('countryNameBad', 'fill-color', 'rgba(256, 21, 21, 0.7)'); map.setPaintProperty('countryNameBadOutline', 'line-color', 'rgba(5, 2, 2, 2)'); // map.setFilter("countryNameBad", ["==", "name", name]); }, 400); }, 300); } function placePin(map, ll, mmarker){ const el = document.createElement('div'); el.className = 'marker'; el.style.backgroundImage = 'url(' + mmarker +')'; el.style.width = '35px'; el.style.height = '30px'; return new maplibregl.Marker({element: el, offset: [1.5, -13]}).setLngLat(ll).addTo(map); } function placeCircle(map, ll, mmarker){ var el = document.createElement('div'); el.className = 'marker'; el.style.backgroundImage = 'url(' + mmarker +')'; el.style.width = '56px'; el.style.height = '56px'; var p = new maplibregl.Marker({element: el, offset: [-1, 0]}).setLngLat(ll).addTo(map); return p; } function placeCircleBigX(map, ll, mmarker){ console.log(" placeCircleBigX(", ll, " mm:", mmarker); var el = document.createElement('div'); el.className = 'marker'; el.style.backgroundImage = 'url(' + mmarker +')'; el.style.width = '74px'; el.style.height = '74px'; var p = new maplibregl.Marker({element: el, offset: [-1, 0]}).setLngLat(ll).addTo(map); return p; } function placeCircleBig(map, ll, mmarker, distPercent=1){ if( typeof ll[0] === "undefined" || typeof ll[1] === "undefined" ){ return; } var el = document.createElement('div'); el.className = 'marker'; el.style.backgroundImage = 'url(' + mmarker +')'; el.style.width = '400px'; el.style.height = '400px'; let p = new maplibregl.Marker({element: el, offset: [-1, 0]}).setLngLat(ll).addTo(map); // let timeOut = distPercent * 66; // if (timeOut > 3500){ timeOut = 3500; } let timeOut = 6666; console.log("Flash circle timeout:", timeOut); setTimeout(function(){ p.remove(); }, timeOut); return p; } let hl_undo; function highlightQuestion(rc){ clearTimeout(hl_undo); if( document.getElementById("question") ){ document.getElementById("question").firstChild.classList.add('highlight'); } if( rc < 1 ){ rc = 1; } hl_undo = setTimeout(function(){ if( document.getElementById("question")){ document.getElementById("question").firstChild.classList.remove('highlight'); } }, (500 + 2000/rc)); } let runCount = 0; let sleepTimeBase = 50; function showHelpNote(note, ll){ let n = Math.floor(Math.random() * note.length); let msg = "" + note[n] ; let centerLong = (continent.bounds[0][0] + continent.bounds[1][0])/2; let c = new maplibregl.LngLat(centerLong, map.getBounds()._ne.lat); // middle top let popup = new maplibregl.Popup({className: "messagePop"}) .setLngLat( c ) .setMaxWidth( 'none' ) .setHTML( msg ) .addTo(map); setTimeout(function(){ popup.remove(); }, 2600); $(".maplibregl-popup-close-button").remove(); $(".maplibregl-popup-tip").remove(); } function lineLength_multi(c){ let len = 0; for(let i = 0; i < c.length; i++){ len += lineLength(c[i]); } return len; } function lineLength(line){ let len = 0; for (let i=0; i < line.length -1; i++ ){ len += distanceBetween(line[i], line[i+1]); } return len; }