var app = angular.module('batmanDelivers', ['ngSanitize', 'ui.select']); app.controller('myCtrl', function($scope, $http, $rootScope, $sce) { //GLOBAL VARIABLES var key = 'AIzaSyAPYatPrCcmNcVdAO_MF0YhO3c1mgdLvuQ'; var distance; var map; var mapReset = false; $scope.routeStarted = false; //UI VARIABLES $scope.warning = ''; $scope.timer = 0; $scope.predictedTime = 0; $scope.speed = 50; //Average MPH //UI ARRAYS $scope.settings = [{ description: 'Enable Time Prediction', enabled: true, showOnRouteLoad: true, showOnPageLoad: false, template: $sce.trustAsHtml("Prediction: {{predictedTime}} (Mins)") }, { description: 'Enable Speed Manipulation', enabled: true, showOnRouteLoad: true, showOnPageLoad: false, template: $sce.trustAsHtml("Manipulate Speed:
") }, { description: 'Enable Speed Display', enabled: true, showOnRouteLoad: true, showOnPageLoad: false, template: $sce.trustAsHtml("

View Speed: {{speed}} (MPH)

") }, { description: 'Enable Additional Stops', enabled: true, showOnRouteLoad: false, showOnPageLoad: true, template: $sce.trustAsHtml("

Additional Stop

") }, { description: 'Reset Map', enabled: true, showOnRouteLoad: false, showOnPageLoad: true, template: $sce.trustAsHtml("

Reset Map

") } ] $scope.stops = [ { Description: "Start typing to search...", lbl: "Pickup", valid: false, id: 1 }, { Description: "Start typing to search...", lbl: "Drop", valid: false, id: 2 }] //INIT MAP var directionsService = new google.maps.DirectionsService; var directionsDisplay = new google.maps.DirectionsRenderer(); initMap(); //FUNCTIONS $scope.$on('StopChanged', function() { var validstops = $scope.stops.filter(function(x) { return x.valid; }); if (validstops.length == 1) { map.panTo(validstops[0].$marker.getPosition()); } else if (validstops.length > 1) { var bounds = new google.maps.LatLngBounds(); for (var i = 0; i < validstops.length; i++) { bounds.extend(validstops[i].$marker.getPosition()); } map.fitBounds(bounds, 100); } if (validstops.length == $scope.stops.length) { //Set Markers as null **** var waypoints = []; if ($scope.stops.length > 2) { waypoints = $scope.stops.slice(1, $scope.stops.length - 1); } calcRoute($scope.stops[0], $scope.stops[$scope.stops.length - 1], waypoints); } }); function refreshSettings(completed){ newSettings = []; $scope.settings.forEach(function(s, i){ if(completed && !s.showOnPageLoad){ s.showOnRouteLoad = true; } else { s.showOnRouteLoad = false; } newSettings.push(s); if (i == $scope.settings.length - 1){ $scope.settings = newSettings; } }) } function getTime() { var speed = $scope.speed / distance; //Difference setTimeout(function() { $scope.$apply(function() { $scope.predictedTime = (60 / speed).toFixed(1); //Work out the minutes based on the difference }); }, 500) } function initMap() { map = new google.maps.Map(document.getElementById('map-div'), { scrollwheel: false, center: { lat: 51.491903, lng: -0.024640 }, mapTypeId: 'roadmap', zoom: 14, mapTypeControl: false, styles: [{ "featureType": "all", "elementType": "labels.text.fill", "stylers": [{ "saturation": 36 }, { "color": "#000000" }, { "lightness": 40 } ] }, { "featureType": "all", "elementType": "labels.text.stroke", "stylers": [{ "visibility": "on" }, { "color": "#000000" }, { "lightness": 16 } ] }, { "featureType": "all", "elementType": "labels.icon", "stylers": [{ "visibility": "off" }] }, { "featureType": "administrative", "elementType": "geometry.fill", "stylers": [{ "color": "#000000" }, { "lightness": 20 } ] }, { "featureType": "administrative", "elementType": "geometry.stroke", "stylers": [{ "color": "#000000" }, { "lightness": 17 }, { "weight": 1.2 } ] }, { "featureType": "landscape", "elementType": "geometry", "stylers": [{ "color": "#000000" }, { "lightness": 20 } ] }, { "featureType": "poi", "elementType": "geometry", "stylers": [{ "color": "#000000" }, { "lightness": 21 } ] }, { "featureType": "road.highway", "elementType": "geometry.fill", "stylers": [{ "color": "#000000" }, { "lightness": 17 } ] }, { "featureType": "road.highway", "elementType": "geometry.stroke", "stylers": [{ "color": "#000000" }, { "lightness": 29 }, { "weight": 0.2 } ] }, { "featureType": "road.arterial", "elementType": "geometry", "stylers": [{ "color": "#000000" }, { "lightness": 18 } ] }, { "featureType": "road.local", "elementType": "geometry", "stylers": [{ "color": "#000000" }, { "lightness": 16 } ] }, { "featureType": "transit", "elementType": "geometry", "stylers": [{ "color": "#000000" }, { "lightness": 19 } ] }, { "featureType": "water", "elementType": "geometry", "stylers": [{ "color": "#000000" }, { "lightness": 17 } ] } ] }); $rootScope.map = map; } function calcRoute(start, end, waypoints) { directionsService.route({ origin: start.$marker.getPosition(), destination: end.$marker.getPosition(), waypoints: waypoints.map(function(x) { return { location: x.Description, stopover: true }; }), travelMode: 'DRIVING', provideRouteAlternatives: false }, function(response, status) { if (status === 'OK') { distance = response.routes[0].legs[0].distance.value * 0.000621371; if (distance < 35) { directionsDisplay.setMap(map); directionsDisplay.setDirections(response); directionsDisplay.setOptions({ suppressMarkers: true }); slider(); getTime(); refreshSettings(); follow(response.routes[0].overview_path); } else { $scope.warning = 'Destination Too Far Away!'; setTimeout(function() { $scope.warning = " "; }, 1000) } } else { console.log("Need more Stops", start, end, waypoints) } }); } function follow(overview_path) { var marker = new SlidingMarker({ position: overview_path[0], icon: { url: "../includes/images/car3x.png", scaledSize: new google.maps.Size(32, 32), anchor: new google.maps.Point(16, 16) }, map: map, optimized: false, duration: 0, easing: "linear" }); //Distances and Measurements var pre = [0]; var j = 0; var rotateTime = 0; var heading; var metres; function moveDriver() { $scope.routeStarted = true; var from = new google.maps.LatLng(overview_path[j].lat(), overview_path[j].lng()); var to = new google.maps.LatLng(overview_path[j + 1].lat(), overview_path[j + 1].lng()); $scope.stops.forEach(function(stop) { if (stop.valid) { var stopLatLng = new google.maps.LatLng(stop.$marker.position.lat(), stop.$marker.position.lng()); var distance = google.maps.geometry.spherical.computeDistanceBetween(from, stopLatLng); //Metres if (distance < 50) { stop.$marker.setMap(null); stop.valid = false; //Delete Marker } else { //Already removed } } }) var heading = Math.round(google.maps.geometry.spherical.computeHeading(from, to)); pre.push(heading); var turn = Math.abs(pre[0]) - Math.abs(pre[1]); if (Math.abs(turn) > 40 && Math.abs(turn) < 140) { if ($scope.speed < 100) { rotateTime = 1500; //secs } else { rotateTime = 500; //secs } if (heading < 0) { //Turning left setTimeout(function() { $('img[src="../includes/images/car3x.png"]').css({ 'transform': 'rotate(' + heading + 'deg)' }); }, rotateTime) } else { setTimeout(function() { $('img[src="../includes/images/car3x.png"]').css({ 'transform': 'rotate(' + heading + 'deg)' }); }, rotateTime) } } else { rotateTime = 0; $('img[src="../includes/images/car3x.png"]').css({ 'transform': 'rotate(' + heading + 'deg)' }); } //** Make batman do skid over roundabouts //Getting Distance to milliseconds var metres = google.maps.geometry.spherical.computeDistanceBetween(from, to); //Metres var miles = metres * 0.000621371; //Miles var speed = $scope.speed / miles; //Difference var speedPerHour = 60 / speed; //Work out the minutes based on the difference var speedPerMilli = speedPerHour * 60000; // Convert to milliseconds j++; marker.duration = speedPerMilli + rotateTime; setTimeout(function() { marker.setPosition(overview_path[j]); }, rotateTime) if (j < overview_path.length - 1 && mapReset != true) { map.setZoom(16); map.panTo(marker.getPosition()); setTimeout(function() { pre.shift(); moveDriver(); }, speedPerMilli + rotateTime) } else { refreshSettings(true); $scope.routeStarted = false; $scope.warning = 'Route Completed!'; setTimeout(function() { $scope.warning = " "; }, 1000) } } moveDriver(); } //UI FUNCTIONS $scope.checkRouteSetting = function(setting){ if (setting.enabled == true && setting.showOnRouteLoad == false){ return true; } else { return false; } } $scope.resetMap = function() { initMap(); mapReset = true; $scope.stops = [{ Description: "Start typing to search...", lbl: "Pickup", valid: false, id: 1 }, { Description: "Start typing to search...", lbl: "Drop", valid: false, id: 2 }] $scope.warning = 'Map Reset!'; setTimeout(function() { $scope.warning = " "; mapReset = false; }, 1000) } $scope.addStop = function() { if ($scope.stops.length < 4) { if ($scope.routeStarted) { $scope.warning = 'Route Has Started!'; setTimeout(function() { $scope.warning = " "; }, 1000) } else { $scope.stops.splice($scope.stops.length - 1, 0, { Description: "Start typing to search...", lbl: "Stop" }) } } else { $scope.warning = 'Reached Stop Limit!'; setTimeout(function() { $scope.warning = ''; }, 500) } } $scope.checkStop = function(i) { if (i == 0 || i == $scope.stops.length - 1) { return true; } else { return false; } } $scope.enableSettings = function() { if ($('.settings').css('display') == 'none') { $('.settings').slideDown("slow"); } else { $('.settings').slideUp("slow"); } } $scope.changeSetting = function(change, i) { if (change == 'enable') { $scope.settings[i].enabled = true; $scope.warning = 'Setting Enabled, Click X To Disable!'; $(".setting" + i).css("text-decoration", "none"); setTimeout(function() { $scope.warning = " "; }, 1000) } else { $scope.settings[i].enabled = false; $scope.warning = 'Setting Disabled, Click X To Enable!'; $(".setting" + i).css("text-decoration", "line-through"); setTimeout(function() { $scope.warning = " "; }, 1000) } } $scope.removeStop = function(i) { //TODO: STOP REMOVES PICKUP $scope.stops.splice(stop, 1); } function slider() { $("#slider").slider({ animate: "fast", animate: true, value: 50, min: 20, max: 300, step: 1, slide: function(event, ui) { $scope.$apply(function() { $scope.speed = ui.value; getTime(); }); } }); } });