From df8bd9d826fc517ee2c65de319c133deb4295c34 Mon Sep 17 00:00:00 2001 From: Pjotr Savitski Date: Mon, 15 May 2017 17:29:56 +0300 Subject: [PATCH] References #100, added an implementation. A line would connect user marker with closest unanswered question. It will also have an arrow closet to the player marker with the direction of the question marker. --- public/js/play.js | 2 +- resources/assets/js/components/GameMap.vue | 60 ++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/public/js/play.js b/public/js/play.js index 1f1903a..8c6f68c 100644 --- a/public/js/play.js +++ b/public/js/play.js @@ -89,7 +89,7 @@ eval("//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n// /***/ function(module, exports, __webpack_require__) { "use strict"; -eval("//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\nfunction GameControls(controlDiv, map, playerMarker, vm) {\n var controlUI = document.createElement('div');\n controlUI.id = 'sz-map-controls'\n controlDiv.appendChild(controlUI);\n\n var completionControlItem = document.createElement('i');\n completionControlItem.className = 'label label-success';\n completionControlItem.style.fontSize = '20px';\n completionControlItem.style.position = 'relative';\n completionControlItem.style.top = '-7px';\n completionControlItem.style.marginLeft = '5px';\n completionControlItem.style.marginRight = '5px';\n completionControlItem.textContent = vm.getAnsweredQuestionsCount() + '/' + _.size(vm.game.activity.questions);\n controlUI.appendChild(completionControlItem);\n\n vm.$watch('game.answers', function() {\n completionControlItem.textContent = vm.getAnsweredQuestionsCount() + '/' + _.size(vm.game.activity.questions);\n });\n\n var informationControlItem = document.createElement('i');\n informationControlItem.className = 'mdi mdi-information-outline';\n informationControlItem.title = vm.$t('info');\n controlUI.appendChild(informationControlItem);\n\n informationControlItem.addEventListener('click', function() {\n vm.$refs.informationModal.open();\n });\n\n var navigationControlItem = document.createElement('i');\n navigationControlItem.className = 'mdi mdi-navigation';\n navigationControlItem.title = vm.$t('position-tracking');\n controlUI.appendChild(navigationControlItem);\n\n navigationControlItem.addEventListener('click', function() {\n if ( map.szTrackingEnabled ) {\n map.szTrackingEnabled = false;\n navigationControlItem.className = 'mdi mdi-navigation';\n } else {\n map.panTo(playerMarker.getPosition());\n google.maps.event.trigger(playerMarker, 'click');\n map.szTrackingEnabled = true;\n navigationControlItem.className = 'mdi mdi-navigation active';\n }\n });\n\n var boundsControlItem = document.createElement('i');\n boundsControlItem.className = 'mdi mdi-map-marker-multiple';\n boundsControlItem.title = vm.$t('apply-item-bounds');\n controlUI.appendChild(boundsControlItem);\n\n boundsControlItem.addEventListener('click', function() {\n var bounds = vm.getMarkerBounds();\n\n if ( !bounds.isEmpty() ) {\n map.fitBounds(bounds);\n }\n });\n\n var exitControlIcon = document.createElement('i');\n exitControlIcon.className = 'mdi mdi-exit-to-app';\n exitControlIcon.title = vm.$t('exit');\n controlUI.appendChild(exitControlIcon);\n\n exitControlIcon.addEventListener('click', function() {\n vm.exit();\n });\n}\n\nvar connectMarkers = window.SmartZoos.config.connect_markers || false;\n\n/* harmony default export */ exports[\"default\"] = {\n components: {\n 'game-information-modal': __webpack_require__(8),\n 'game-question-modal': __webpack_require__(9),\n 'game-results-modal': __webpack_require__(10)\n },\n props: ['latitude', 'longitude'],\n mounted: function mounted() {\n this.baseUrl = window.SmartZoos.config.base_url;\n\n this.game = window.SmartZoos.data.game;\n\n this.mapData = {};\n this.mapData.markers = [];\n this.mapData.mapOptions = {\n center: {\n lat: this.latitude,\n lng: this.longitude\n },\n zoom: 18,\n mapTypeId: google.maps.MapTypeId.ROADMAP,\n disableDefaultUI: true,\n zoomControl: true,\n streetViewControl: true,\n styles: [\n {\n featureType: 'poi',\n stylers: [{visibility: 'off'}]\n },\n {\n featureType: 'transit.station',\n stylers: [{visibility: 'off'}]\n },\n ]\n };\n this.mapData.iconAnchor = new google.maps.Point(17.35, 20);\n this.mapData.iconSize = new google.maps.Size(52, 60);\n this.mapData.iconScaledSize = new google.maps.Size(34.7, 40);\n\n this.initMap();\n },\n data: function data() {\n return {\n question: null,\n game: null,\n baseUrl: ''\n };\n },\n methods: {\n initMap: function initMap() {\n var this$1 = this;\n\n var _this = this;\n\n this.mapData.map = new google.maps.Map(document.getElementById('map'), this.mapData.mapOptions);\n\n this.mapData.infoWindow = new google.maps.InfoWindow();\n\n this.initGroundOverlays();\n\n this.initPlayerMarker();\n\n this.initGameControls();\n\n this.$parent.getGeoLocation(function(position) {\n var map = _this.mapData.map,\n playerMarker = _this.mapData.playerMarker;\n\n playerMarker.setPosition({\n lat: position.coords.latitude,\n lng: position.coords.longitude\n });\n if ( map.szTrackingEnabled === true ) {\n map.panTo(playerMarker.getPosition());\n }\n if ( _this.hasProximityCheck() ) {\n // TODO Might make sense to cancel in case location\n // does change rpidly\n // Giving it half a second or so should be good enough\n _.each(_this.mapData.markers, function(marker) {\n if ( !_this.isAnswered(marker.questionId) ) {\n _this.detectAndSetMarkerIcon(marker);\n }\n });\n }\n }, true);\n\n if ( _this.game.activity.questions ) {\n var map = _this.mapData.map,\n markers = _this.mapData.markers,\n infoWindow = _this.mapData.infoWindow,\n playerMarker = _this.mapData.playerMarker;\n\n _.each(_this.game.activity.questions, function(question) {\n var marker = new google.maps.Marker({\n title: question.title,\n position: {\n lat: Number(question.latitude),\n lng: Number(question.longitude)\n },\n map: map,\n animation: google.maps.Animation.DROP,\n questionId: question.id\n });\n\n _this.detectAndSetMarkerIcon(marker);\n\n markers.push(marker);\n\n marker.addListener('click', function() {\n if ( _this.isAnswered(question.id) ) {\n return;\n }\n\n if ( _this.hasProximityCheck() ) {\n var distance = google.maps.geometry.spherical.computeDistanceBetween(playerMarker.getPosition(), marker.getPosition());\n\n if ( distance <= _this.getProximityRadius() ) {\n _this.openQuestionModal(question);\n }\n } else {\n _this.openQuestionModal(question);\n }\n });\n });\n\n if ( connectMarkers ) {\n _this.connectMarkers();\n }\n }\n\n this.$nextTick(function () {\n if ( this$1.game.complete ) {\n this$1.$refs.resultsModal.open();\n } else {\n this$1.$refs.informationModal.open();\n }\n });\n },\n initGroundOverlays: function initGroundOverlays() {\n this.mapData.skansenGroundOverlay = new google.maps.GroundOverlay(this.baseUrl + '/img/map/overlays/skansen.png',{\n north: 59.329167,\n south: 59.324011,\n east: 18.111242,\n west: 18.099022\n }, {\n clickable: false,\n map: this.mapData.map\n });\n },\n initGameControls: function initGameControls() {\n var map = this.mapData.map,\n playerMarker = this.mapData.playerMarker,\n gameControlsDiv = document.createElement('div'),\n gameControls = new GameControls(gameControlsDiv, map, playerMarker, this);\n\n // XXX This is a strange code pience that sends index without a reason()\n gameControls.index = 1;\n map.controls[google.maps.ControlPosition.TOP_RIGHT].push(gameControlsDiv);\n },\n closeInfoWindow: function closeInfoWindow() {\n var infoWindow = this.mapData.infoWindow;\n\n if ( infoWindow && infoWindow.getMap() ) {\n infoWindow.close();\n }\n },\n initPlayerMarker: function initPlayerMarker() {\n var circle,\n playerMarker,\n activeDistanceCircle,\n _this = this,\n map = this.mapData.map,\n infoWindow = this.mapData.infoWindow;\n\n circle = {\n path: google.maps.SymbolPath.CIRCLE,\n fillColor: 'red',\n fillOpacity: 1.0,\n scale: 4.5,\n strokeColor: 'white',\n strokeWeight: 1\n };\n\n var playerMarker = new google.maps.Marker({\n title: this.$t('its-you'),\n position: {\n lat: this.latitude,\n lng: this.longitude\n },\n map: map,\n icon: circle\n });\n\n playerMarker.addListener('click', function() {\n _this.closeInfoWindow();\n infoWindow.setContent(this.title);\n infoWindow.open(map, this);\n });\n\n if ( this.hasProximityCheck() ) {\n var activeDistanceCircle = new google.maps.Circle({\n map: map,\n radius: this.getProximityRadius(),\n fillColor: 'blue',\n fillOpacity: 0.25,\n strokeColor: 'blue',\n strokeWeight: 1,\n strokeOpacity: 0.5\n });\n activeDistanceCircle.bindTo('center', playerMarker, 'position');\n }\n\n google.maps.event.trigger(playerMarker, 'click');\n\n this.mapData.playerMarker = playerMarker;\n },\n isAnswered: function isAnswered(questionId) {\n return _.has(this.game.answers, questionId);\n },\n isCorrect: function isCorrect(questionId) {\n var answer = _.get(this.game.answers, questionId, null);\n\n return answer && answer.correct === true;\n },\n markAnswered: function markAnswered(id, answer) {\n var this$1 = this;\n\n this.$set(this.game.answers, id, answer);\n\n // TODO Might make sense to raise an error if marker can not be found\n var marker = _.find(this.mapData.markers, function(marker) { return marker.questionId === id; });\n\n if ( marker ) {\n this.detectAndSetMarkerIcon(marker);\n }\n\n var answerIds = _.keys(this.game.answers).map(function (id) {\n return _.toNumber(id);\n });\n var questionIds = _.map(this.game.activity.questions, function (question) {\n return question.id;\n });\n\n if ( _.intersection(questionIds, answerIds).length === questionIds.length ) {\n this.game.complete = true;\n\n this.$nextTick(function () {\n this$1.$refs.resultsModal.open();\n });\n }\n },\n connectMarkers: function connectMarkers$1() {\n var map = this.mapData.map,\n markers = this.mapData.markers;\n\n if ( markers.length > 1 ) {\n _.each(markers, function (marker, index) {\n if ( index === 0 ) {\n return;\n }\n\n var line = new google.maps.Polyline({\n path: [\n markers[index-1].getPosition(),\n markers[index].getPosition()\n ],\n strokeWeight: 2,\n strokeOpacity: 0.5,\n icons: [{\n icon: {path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW},\n offset: '100%'\n }],\n geodesic: true,\n map: map\n });\n });\n }\n },\n exit: function exit() {\n var confirmation = confirm(this.$t('exit-confirmation'));\n\n if ( confirmation ) {\n window.location = this.baseUrl;\n }\n },\n hasProximityCheck: function hasProximityCheck() {\n return this.game.activity.proximity_check;\n },\n getProximityRadius: function getProximityRadius() {\n return this.game.activity.proximity_radius || 25;\n },\n openQuestionModal: function openQuestionModal(question) {\n var this$1 = this;\n\n this.question = question;\n this.$nextTick(function () {\n this$1.$refs.questionModal.open();\n });\n },\n detectAndSetMarkerIcon: function detectAndSetMarkerIcon(marker) {\n // TODO Check it we should fail in case question could not be found\n var question = _.find(this.game.activity.questions, ['id', marker.questionId]);\n var nameMapping = {\n 1: 'information',\n 2: 'one-correct-answer',\n 3: 'multiple-correct-answers',\n 4: 'freeform-answer',\n 5: 'match-pairs',\n 6: 'embedded-content',\n 7: 'photo'\n };\n var iconBase = this.baseUrl + '/img/icons/item/';\n\n if ( this.isAnswered(question.id) ) {\n iconBase += this.isCorrect(question.id) ? 'correct/' : 'incorrect/';\n } else if ( this.hasProximityCheck() ) {\n var distance = google.maps.geometry.spherical.computeDistanceBetween(this.mapData.playerMarker.getPosition(), marker.getPosition());\n\n if ( distance > this.getProximityRadius() ) {\n iconBase += 'inactive/';\n }\n }\n\n marker.setIcon({\n anchor: this.mapData.iconAnchor,\n size: this.mapData.iconSize,\n scaledSize: this.mapData.iconScaledSize,\n url: iconBase + nameMapping[question.type] + '.png'\n });\n },\n getMarkerBounds: function getMarkerBounds() {\n if ( this.mapData.markerBounds ) return this.mapData.markerBounds;\n\n this.mapData.markerBounds = new google.maps.LatLngBounds();\n\n if ( this.mapData.markers.length > 0 ) {\n var vm = this;\n\n _.each(this.mapData.markers, function(marker) {\n vm.mapData.markerBounds.extend(marker.getPosition());\n });\n }\n\n return this.mapData.markerBounds;\n },\n getAnsweredQuestionsCount: function getAnsweredQuestionsCount() {\n if ( _.size(this.game.activity.questions) === 0 || _.size(this.game.answers) === 0 ) return 0;\n\n var questionIds = _.map(this.game.activity.questions, function (question) {\n return question.id;\n });\n\n var answered = _.filter(this.game.answers, function (answer) {\n return questionIds.indexOf(answer.question) !== -1;\n });\n\n return _.size(answered);\n }\n }\n};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy9yZXNvdXJjZXMvYXNzZXRzL2pzL2NvbXBvbmVudHMvR2FtZU1hcC52dWU/YmI4NCJdLCJzb3VyY2VzQ29udGVudCI6WyIvL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuXG5mdW5jdGlvbiBHYW1lQ29udHJvbHMoY29udHJvbERpdiwgbWFwLCBwbGF5ZXJNYXJrZXIsIHZtKSB7XG4gICAgdmFyIGNvbnRyb2xVSSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGNvbnRyb2xVSS5pZCA9ICdzei1tYXAtY29udHJvbHMnXG4gICAgY29udHJvbERpdi5hcHBlbmRDaGlsZChjb250cm9sVUkpO1xuXG4gICAgdmFyIGNvbXBsZXRpb25Db250cm9sSXRlbSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2knKTtcbiAgICBjb21wbGV0aW9uQ29udHJvbEl0ZW0uY2xhc3NOYW1lID0gJ2xhYmVsIGxhYmVsLXN1Y2Nlc3MnO1xuICAgIGNvbXBsZXRpb25Db250cm9sSXRlbS5zdHlsZS5mb250U2l6ZSA9ICcyMHB4JztcbiAgICBjb21wbGV0aW9uQ29udHJvbEl0ZW0uc3R5bGUucG9zaXRpb24gPSAncmVsYXRpdmUnO1xuICAgIGNvbXBsZXRpb25Db250cm9sSXRlbS5zdHlsZS50b3AgPSAnLTdweCc7XG4gICAgY29tcGxldGlvbkNvbnRyb2xJdGVtLnN0eWxlLm1hcmdpbkxlZnQgPSAnNXB4JztcbiAgICBjb21wbGV0aW9uQ29udHJvbEl0ZW0uc3R5bGUubWFyZ2luUmlnaHQgPSAnNXB4JztcbiAgICBjb21wbGV0aW9uQ29udHJvbEl0ZW0udGV4dENvbnRlbnQgPSB2bS5nZXRBbnN3ZXJlZFF1ZXN0aW9uc0NvdW50KCkgKyAnLycgKyBfLnNpemUodm0uZ2FtZS5hY3Rpdml0eS5xdWVzdGlvbnMpO1xuICAgIGNvbnRyb2xVSS5hcHBlbmRDaGlsZChjb21wbGV0aW9uQ29udHJvbEl0ZW0pO1xuXG4gICAgdm0uJHdhdGNoKCdnYW1lLmFuc3dlcnMnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgY29tcGxldGlvbkNvbnRyb2xJdGVtLnRleHRDb250ZW50ID0gdm0uZ2V0QW5zd2VyZWRRdWVzdGlvbnNDb3VudCgpICsgJy8nICsgXy5zaXplKHZtLmdhbWUuYWN0aXZpdHkucXVlc3Rpb25zKTtcbiAgICB9KTtcblxuICAgIHZhciBpbmZvcm1hdGlvbkNvbnRyb2xJdGVtID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaScpO1xuICAgIGluZm9ybWF0aW9uQ29udHJvbEl0ZW0uY2xhc3NOYW1lID0gJ21kaSBtZGktaW5mb3JtYXRpb24tb3V0bGluZSc7XG4gICAgaW5mb3JtYXRpb25Db250cm9sSXRlbS50aXRsZSA9IHZtLiR0KCdpbmZvJyk7XG4gICAgY29udHJvbFVJLmFwcGVuZENoaWxkKGluZm9ybWF0aW9uQ29udHJvbEl0ZW0pO1xuXG4gICAgaW5mb3JtYXRpb25Db250cm9sSXRlbS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKCkge1xuICAgICAgICB2bS4kcmVmcy5pbmZvcm1hdGlvbk1vZGFsLm9wZW4oKTtcbiAgICB9KTtcblxuICAgIHZhciBuYXZpZ2F0aW9uQ29udHJvbEl0ZW0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpJyk7XG4gICAgbmF2aWdhdGlvbkNvbnRyb2xJdGVtLmNsYXNzTmFtZSA9ICdtZGkgbWRpLW5hdmlnYXRpb24nO1xuICAgIG5hdmlnYXRpb25Db250cm9sSXRlbS50aXRsZSA9IHZtLiR0KCdwb3NpdGlvbi10cmFja2luZycpO1xuICAgIGNvbnRyb2xVSS5hcHBlbmRDaGlsZChuYXZpZ2F0aW9uQ29udHJvbEl0ZW0pO1xuXG4gICAgbmF2aWdhdGlvbkNvbnRyb2xJdGVtLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICggbWFwLnN6VHJhY2tpbmdFbmFibGVkICkge1xuICAgICAgICAgICAgbWFwLnN6VHJhY2tpbmdFbmFibGVkID0gZmFsc2U7XG4gICAgICAgICAgICBuYXZpZ2F0aW9uQ29udHJvbEl0ZW0uY2xhc3NOYW1lID0gJ21kaSBtZGktbmF2aWdhdGlvbic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtYXAucGFuVG8ocGxheWVyTWFya2VyLmdldFBvc2l0aW9uKCkpO1xuICAgICAgICAgICAgZ29vZ2xlLm1hcHMuZXZlbnQudHJpZ2dlcihwbGF5ZXJNYXJrZXIsICdjbGljaycpO1xuICAgICAgICAgICAgbWFwLnN6VHJhY2tpbmdFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIG5hdmlnYXRpb25Db250cm9sSXRlbS5jbGFzc05hbWUgPSAnbWRpIG1kaS1uYXZpZ2F0aW9uIGFjdGl2ZSc7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHZhciBib3VuZHNDb250cm9sSXRlbSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2knKTtcbiAgICBib3VuZHNDb250cm9sSXRlbS5jbGFzc05hbWUgPSAnbWRpIG1kaS1tYXAtbWFya2VyLW11bHRpcGxlJztcbiAgICBib3VuZHNDb250cm9sSXRlbS50aXRsZSA9IHZtLiR0KCdhcHBseS1pdGVtLWJvdW5kcycpO1xuICAgIGNvbnRyb2xVSS5hcHBlbmRDaGlsZChib3VuZHNDb250cm9sSXRlbSk7XG5cbiAgICBib3VuZHNDb250cm9sSXRlbS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgYm91bmRzID0gdm0uZ2V0TWFya2VyQm91bmRzKCk7XG5cbiAgICAgICAgaWYgKCAhYm91bmRzLmlzRW1wdHkoKSApIHtcbiAgICAgICAgICAgIG1hcC5maXRCb3VuZHMoYm91bmRzKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgdmFyIGV4aXRDb250cm9sSWNvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2knKTtcbiAgICBleGl0Q29udHJvbEljb24uY2xhc3NOYW1lID0gJ21kaSBtZGktZXhpdC10by1hcHAnO1xuICAgIGV4aXRDb250cm9sSWNvbi50aXRsZSA9IHZtLiR0KCdleGl0Jyk7XG4gICAgY29udHJvbFVJLmFwcGVuZENoaWxkKGV4aXRDb250cm9sSWNvbik7XG5cbiAgICBleGl0Q29udHJvbEljb24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBmdW5jdGlvbigpIHtcbiAgICAgICAgdm0uZXhpdCgpO1xuICAgIH0pO1xufVxuXG52YXIgY29ubmVjdE1hcmtlcnMgPSAgd2luZG93LlNtYXJ0Wm9vcy5jb25maWcuY29ubmVjdF9tYXJrZXJzIHx8IGZhbHNlO1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gICAgY29tcG9uZW50czoge1xuICAgICAgICAnZ2FtZS1pbmZvcm1hdGlvbi1tb2RhbCc6IHJlcXVpcmUoJy4vR2FtZUluZm9ybWF0aW9uTW9kYWwudnVlJyksXG4gICAgICAgICdnYW1lLXF1ZXN0aW9uLW1vZGFsJzogcmVxdWlyZSgnLi9HYW1lUXVlc3Rpb25Nb2RhbC52dWUnKSxcbiAgICAgICAgJ2dhbWUtcmVzdWx0cy1tb2RhbCc6IHJlcXVpcmUoJy4vR2FtZVJlc3VsdHNNb2RhbC52dWUnKVxuICAgIH0sXG4gICAgcHJvcHM6IFsnbGF0aXR1ZGUnLCAnbG9uZ2l0dWRlJ10sXG4gICAgbW91bnRlZCgpIHtcbiAgICAgICAgdGhpcy5iYXNlVXJsID0gd2luZG93LlNtYXJ0Wm9vcy5jb25maWcuYmFzZV91cmw7XG5cbiAgICAgICAgdGhpcy5nYW1lID0gd2luZG93LlNtYXJ0Wm9vcy5kYXRhLmdhbWU7XG5cbiAgICAgICAgdGhpcy5tYXBEYXRhID0ge307XG4gICAgICAgIHRoaXMubWFwRGF0YS5tYXJrZXJzID0gW107XG4gICAgICAgIHRoaXMubWFwRGF0YS5tYXBPcHRpb25zID0ge1xuICAgICAgICAgICAgY2VudGVyOiB7XG4gICAgICAgICAgICAgICAgbGF0OiB0aGlzLmxhdGl0dWRlLFxuICAgICAgICAgICAgICAgIGxuZzogdGhpcy5sb25naXR1ZGVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB6b29tOiAxOCxcbiAgICAgICAgICAgIG1hcFR5cGVJZDogZ29vZ2xlLm1hcHMuTWFwVHlwZUlkLlJPQURNQVAsXG4gICAgICAgICAgICBkaXNhYmxlRGVmYXVsdFVJOiB0cnVlLFxuICAgICAgICAgICAgem9vbUNvbnRyb2w6IHRydWUsXG4gICAgICAgICAgICBzdHJlZXRWaWV3Q29udHJvbDogdHJ1ZSxcbiAgICAgICAgICAgIHN0eWxlczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZmVhdHVyZVR5cGU6ICdwb2knLFxuICAgICAgICAgICAgICAgICAgICBzdHlsZXJzOiBbe3Zpc2liaWxpdHk6ICdvZmYnfV1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZmVhdHVyZVR5cGU6ICd0cmFuc2l0LnN0YXRpb24nLFxuICAgICAgICAgICAgICAgICAgICBzdHlsZXJzOiBbe3Zpc2liaWxpdHk6ICdvZmYnfV1cbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5tYXBEYXRhLmljb25BbmNob3IgPSBuZXcgZ29vZ2xlLm1hcHMuUG9pbnQoMTcuMzUsIDIwKTtcbiAgICAgICAgdGhpcy5tYXBEYXRhLmljb25TaXplID0gbmV3IGdvb2dsZS5tYXBzLlNpemUoNTIsIDYwKTtcbiAgICAgICAgdGhpcy5tYXBEYXRhLmljb25TY2FsZWRTaXplID0gbmV3IGdvb2dsZS5tYXBzLlNpemUoMzQuNywgNDApO1xuXG4gICAgICAgIHRoaXMuaW5pdE1hcCgpO1xuICAgIH0sXG4gICAgZGF0YSgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHF1ZXN0aW9uOiBudWxsLFxuICAgICAgICAgICAgZ2FtZTogbnVsbCxcbiAgICAgICAgICAgIGJhc2VVcmw6ICcnXG4gICAgICAgIH07XG4gICAgfSxcbiAgICBtZXRob2RzOiB7XG4gICAgICAgIGluaXRNYXAoKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAgICAgICB0aGlzLm1hcERhdGEubWFwID0gbmV3IGdvb2dsZS5tYXBzLk1hcChkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbWFwJyksIHRoaXMubWFwRGF0YS5tYXBPcHRpb25zKTtcblxuICAgICAgICAgICAgdGhpcy5tYXBEYXRhLmluZm9XaW5kb3cgPSBuZXcgZ29vZ2xlLm1hcHMuSW5mb1dpbmRvdygpO1xuXG4gICAgICAgICAgICB0aGlzLmluaXRHcm91bmRPdmVybGF5cygpO1xuXG4gICAgICAgICAgICB0aGlzLmluaXRQbGF5ZXJNYXJrZXIoKTtcblxuICAgICAgICAgICAgdGhpcy5pbml0R2FtZUNvbnRyb2xzKCk7XG5cbiAgICAgICAgICAgIHRoaXMuJHBhcmVudC5nZXRHZW9Mb2NhdGlvbihmdW5jdGlvbihwb3NpdGlvbikge1xuICAgICAgICAgICAgICAgIHZhciBtYXAgPSBfdGhpcy5tYXBEYXRhLm1hcCxcbiAgICAgICAgICAgICAgICAgICAgcGxheWVyTWFya2VyID0gX3RoaXMubWFwRGF0YS5wbGF5ZXJNYXJrZXI7XG5cbiAgICAgICAgICAgICAgICBwbGF5ZXJNYXJrZXIuc2V0UG9zaXRpb24oe1xuICAgICAgICAgICAgICAgICAgICBsYXQ6IHBvc2l0aW9uLmNvb3Jkcy5sYXRpdHVkZSxcbiAgICAgICAgICAgICAgICAgICAgbG5nOiBwb3NpdGlvbi5jb29yZHMubG9uZ2l0dWRlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKCBtYXAuc3pUcmFja2luZ0VuYWJsZWQgPT09IHRydWUgKSB7XG4gICAgICAgICAgICAgICAgICAgIG1hcC5wYW5UbyhwbGF5ZXJNYXJrZXIuZ2V0UG9zaXRpb24oKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICggX3RoaXMuaGFzUHJveGltaXR5Q2hlY2soKSApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVE9ETyBNaWdodCBtYWtlIHNlbnNlIHRvIGNhbmNlbCBpbiBjYXNlIGxvY2F0aW9uXG4gICAgICAgICAgICAgICAgICAgIC8vIGRvZXMgY2hhbmdlIHJwaWRseVxuICAgICAgICAgICAgICAgICAgICAvLyBHaXZpbmcgaXQgaGFsZiBhIHNlY29uZCBvciBzbyBzaG91bGQgYmUgZ29vZCBlbm91Z2hcbiAgICAgICAgICAgICAgICAgICAgXy5lYWNoKF90aGlzLm1hcERhdGEubWFya2VycywgZnVuY3Rpb24obWFya2VyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoICFfdGhpcy5pc0Fuc3dlcmVkKG1hcmtlci5xdWVzdGlvbklkKSApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5kZXRlY3RBbmRTZXRNYXJrZXJJY29uKG1hcmtlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sIHRydWUpO1xuXG4gICAgICAgICAgICBpZiAoIF90aGlzLmdhbWUuYWN0aXZpdHkucXVlc3Rpb25zICkge1xuICAgICAgICAgICAgICAgIHZhciBtYXAgPSBfdGhpcy5tYXBEYXRhLm1hcCxcbiAgICAgICAgICAgICAgICAgICAgbWFya2VycyA9IF90aGlzLm1hcERhdGEubWFya2VycyxcbiAgICAgICAgICAgICAgICAgICAgaW5mb1dpbmRvdyA9IF90aGlzLm1hcERhdGEuaW5mb1dpbmRvdyxcbiAgICAgICAgICAgICAgICAgICAgcGxheWVyTWFya2VyID0gX3RoaXMubWFwRGF0YS5wbGF5ZXJNYXJrZXI7XG5cbiAgICAgICAgICAgICAgICBfLmVhY2goX3RoaXMuZ2FtZS5hY3Rpdml0eS5xdWVzdGlvbnMsIGZ1bmN0aW9uKHF1ZXN0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBtYXJrZXIgPSBuZXcgZ29vZ2xlLm1hcHMuTWFya2VyKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlOiBxdWVzdGlvbi50aXRsZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0OiBOdW1iZXIocXVlc3Rpb24ubGF0aXR1ZGUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxuZzogTnVtYmVyKHF1ZXN0aW9uLmxvbmdpdHVkZSlcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXA6IG1hcCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFuaW1hdGlvbjogZ29vZ2xlLm1hcHMuQW5pbWF0aW9uLkRST1AsXG4gICAgICAgICAgICAgICAgICAgICAgICBxdWVzdGlvbklkOiBxdWVzdGlvbi5pZFxuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5kZXRlY3RBbmRTZXRNYXJrZXJJY29uKG1hcmtlcik7XG5cbiAgICAgICAgICAgICAgICAgICAgbWFya2Vycy5wdXNoKG1hcmtlcik7XG5cbiAgICAgICAgICAgICAgICAgICAgbWFya2VyLmFkZExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCBfdGhpcy5pc0Fuc3dlcmVkKHF1ZXN0aW9uLmlkKSApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICggX3RoaXMuaGFzUHJveGltaXR5Q2hlY2soKSApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZGlzdGFuY2UgPSBnb29nbGUubWFwcy5nZW9tZXRyeS5zcGhlcmljYWwuY29tcHV0ZURpc3RhbmNlQmV0d2VlbihwbGF5ZXJNYXJrZXIuZ2V0UG9zaXRpb24oKSwgbWFya2VyLmdldFBvc2l0aW9uKCkpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCBkaXN0YW5jZSA8PSBfdGhpcy5nZXRQcm94aW1pdHlSYWRpdXMoKSApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlblF1ZXN0aW9uTW9kYWwocXVlc3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMub3BlblF1ZXN0aW9uTW9kYWwocXVlc3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmICggY29ubmVjdE1hcmtlcnMgKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbm5lY3RNYXJrZXJzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLiRuZXh0VGljaygoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCB0aGlzLmdhbWUuY29tcGxldGUgKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJHJlZnMucmVzdWx0c01vZGFsLm9wZW4oKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiRyZWZzLmluZm9ybWF0aW9uTW9kYWwub3BlbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBpbml0R3JvdW5kT3ZlcmxheXMoKSB7XG4gICAgICAgICAgICB0aGlzLm1hcERhdGEuc2thbnNlbkdyb3VuZE92ZXJsYXkgPSBuZXcgZ29vZ2xlLm1hcHMuR3JvdW5kT3ZlcmxheSh0aGlzLmJhc2VVcmwgKyAnL2ltZy9tYXAvb3ZlcmxheXMvc2thbnNlbi5wbmcnLHtcbiAgICAgICAgICAgICAgICBub3J0aDogNTkuMzI5MTY3LFxuICAgICAgICAgICAgICAgIHNvdXRoOiA1OS4zMjQwMTEsXG4gICAgICAgICAgICAgICAgZWFzdDogMTguMTExMjQyLFxuICAgICAgICAgICAgICAgIHdlc3Q6IDE4LjA5OTAyMlxuICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgIGNsaWNrYWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgbWFwOiB0aGlzLm1hcERhdGEubWFwXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgaW5pdEdhbWVDb250cm9scygpIHtcbiAgICAgICAgICAgIHZhciBtYXAgPSB0aGlzLm1hcERhdGEubWFwLFxuICAgICAgICAgICAgICAgIHBsYXllck1hcmtlciA9IHRoaXMubWFwRGF0YS5wbGF5ZXJNYXJrZXIsXG4gICAgICAgICAgICAgICAgZ2FtZUNvbnRyb2xzRGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksXG4gICAgICAgICAgICAgICAgZ2FtZUNvbnRyb2xzID0gbmV3IEdhbWVDb250cm9scyhnYW1lQ29udHJvbHNEaXYsIG1hcCwgcGxheWVyTWFya2VyLCB0aGlzKTtcblxuICAgICAgICAgICAgLy8gWFhYIFRoaXMgaXMgYSBzdHJhbmdlIGNvZGUgcGllbmNlIHRoYXQgc2VuZHMgaW5kZXggd2l0aG91dCBhIHJlYXNvbigpXG4gICAgICAgICAgICBnYW1lQ29udHJvbHMuaW5kZXggPSAxO1xuICAgICAgICAgICAgbWFwLmNvbnRyb2xzW2dvb2dsZS5tYXBzLkNvbnRyb2xQb3NpdGlvbi5UT1BfUklHSFRdLnB1c2goZ2FtZUNvbnRyb2xzRGl2KTtcbiAgICAgICAgfSxcbiAgICAgICAgY2xvc2VJbmZvV2luZG93KCkge1xuICAgICAgICAgICAgdmFyIGluZm9XaW5kb3cgPSB0aGlzLm1hcERhdGEuaW5mb1dpbmRvdztcblxuICAgICAgICAgICAgaWYgKCBpbmZvV2luZG93ICYmIGluZm9XaW5kb3cuZ2V0TWFwKCkgKSB7XG4gICAgICAgICAgICAgICAgaW5mb1dpbmRvdy5jbG9zZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBpbml0UGxheWVyTWFya2VyKCkge1xuICAgICAgICAgICAgdmFyIGNpcmNsZSxcbiAgICAgICAgICAgICAgICBwbGF5ZXJNYXJrZXIsXG4gICAgICAgICAgICAgICAgYWN0aXZlRGlzdGFuY2VDaXJjbGUsXG4gICAgICAgICAgICAgICAgX3RoaXMgPSB0aGlzLFxuICAgICAgICAgICAgICAgIG1hcCA9IHRoaXMubWFwRGF0YS5tYXAsXG4gICAgICAgICAgICAgICAgaW5mb1dpbmRvdyA9IHRoaXMubWFwRGF0YS5pbmZvV2luZG93O1xuXG4gICAgICAgICAgICBjaXJjbGUgPSB7XG4gICAgICAgICAgICAgICAgcGF0aDogZ29vZ2xlLm1hcHMuU3ltYm9sUGF0aC5DSVJDTEUsXG4gICAgICAgICAgICAgICAgZmlsbENvbG9yOiAncmVkJyxcbiAgICAgICAgICAgICAgICBmaWxsT3BhY2l0eTogMS4wLFxuICAgICAgICAgICAgICAgIHNjYWxlOiA0LjUsXG4gICAgICAgICAgICAgICAgc3Ryb2tlQ29sb3I6ICd3aGl0ZScsXG4gICAgICAgICAgICAgICAgc3Ryb2tlV2VpZ2h0OiAxXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB2YXIgcGxheWVyTWFya2VyID0gbmV3IGdvb2dsZS5tYXBzLk1hcmtlcih7XG4gICAgICAgICAgICAgICAgdGl0bGU6IHRoaXMuJHQoJ2l0cy15b3UnKSxcbiAgICAgICAgICAgICAgICBwb3NpdGlvbjoge1xuICAgICAgICAgICAgICAgICAgICBsYXQ6IHRoaXMubGF0aXR1ZGUsXG4gICAgICAgICAgICAgICAgICAgIGxuZzogdGhpcy5sb25naXR1ZGVcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG1hcDogbWFwLFxuICAgICAgICAgICAgICAgIGljb246IGNpcmNsZVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHBsYXllck1hcmtlci5hZGRMaXN0ZW5lcignY2xpY2snLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZUluZm9XaW5kb3coKTtcbiAgICAgICAgICAgICAgICBpbmZvV2luZG93LnNldENvbnRlbnQodGhpcy50aXRsZSk7XG4gICAgICAgICAgICAgICAgaW5mb1dpbmRvdy5vcGVuKG1hcCwgdGhpcyk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKCB0aGlzLmhhc1Byb3hpbWl0eUNoZWNrKCkgKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFjdGl2ZURpc3RhbmNlQ2lyY2xlID0gbmV3IGdvb2dsZS5tYXBzLkNpcmNsZSh7XG4gICAgICAgICAgICAgICAgICAgIG1hcDogbWFwLFxuICAgICAgICAgICAgICAgICAgICByYWRpdXM6IHRoaXMuZ2V0UHJveGltaXR5UmFkaXVzKCksXG4gICAgICAgICAgICAgICAgICAgIGZpbGxDb2xvcjogJ2JsdWUnLFxuICAgICAgICAgICAgICAgICAgICBmaWxsT3BhY2l0eTogMC4yNSxcbiAgICAgICAgICAgICAgICAgICAgc3Ryb2tlQ29sb3I6ICdibHVlJyxcbiAgICAgICAgICAgICAgICAgICAgc3Ryb2tlV2VpZ2h0OiAxLFxuICAgICAgICAgICAgICAgICAgICBzdHJva2VPcGFjaXR5OiAwLjVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBhY3RpdmVEaXN0YW5jZUNpcmNsZS5iaW5kVG8oJ2NlbnRlcicsIHBsYXllck1hcmtlciwgJ3Bvc2l0aW9uJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGdvb2dsZS5tYXBzLmV2ZW50LnRyaWdnZXIocGxheWVyTWFya2VyLCAnY2xpY2snKTtcblxuICAgICAgICAgICAgdGhpcy5tYXBEYXRhLnBsYXllck1hcmtlciA9IHBsYXllck1hcmtlcjtcbiAgICAgICAgfSxcbiAgICAgICAgaXNBbnN3ZXJlZChxdWVzdGlvbklkKSB7XG4gICAgICAgICAgICByZXR1cm4gXy5oYXModGhpcy5nYW1lLmFuc3dlcnMsIHF1ZXN0aW9uSWQpO1xuICAgICAgICB9LFxuICAgICAgICBpc0NvcnJlY3QocXVlc3Rpb25JZCkge1xuICAgICAgICAgICAgY29uc3QgYW5zd2VyID0gXy5nZXQodGhpcy5nYW1lLmFuc3dlcnMsIHF1ZXN0aW9uSWQsIG51bGwpO1xuXG4gICAgICAgICAgICByZXR1cm4gYW5zd2VyICYmIGFuc3dlci5jb3JyZWN0ID09PSB0cnVlO1xuICAgICAgICB9LFxuICAgICAgICBtYXJrQW5zd2VyZWQoaWQsIGFuc3dlcikge1xuICAgICAgICAgICAgdGhpcy4kc2V0KHRoaXMuZ2FtZS5hbnN3ZXJzLCBpZCwgYW5zd2VyKTtcblxuICAgICAgICAgICAgLy8gVE9ETyBNaWdodCBtYWtlIHNlbnNlIHRvIHJhaXNlIGFuIGVycm9yIGlmIG1hcmtlciBjYW4gbm90IGJlIGZvdW5kXG4gICAgICAgICAgICB2YXIgbWFya2VyID0gXy5maW5kKHRoaXMubWFwRGF0YS5tYXJrZXJzLCBmdW5jdGlvbihtYXJrZXIpIHsgcmV0dXJuIG1hcmtlci5xdWVzdGlvbklkID09PSBpZDsgfSk7XG5cbiAgICAgICAgICAgIGlmICggbWFya2VyICkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGV0ZWN0QW5kU2V0TWFya2VySWNvbihtYXJrZXIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgYW5zd2VySWRzID0gXy5rZXlzKHRoaXMuZ2FtZS5hbnN3ZXJzKS5tYXAoaWQgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBfLnRvTnVtYmVyKGlkKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyIHF1ZXN0aW9uSWRzID0gXy5tYXAodGhpcy5nYW1lLmFjdGl2aXR5LnF1ZXN0aW9ucywgcXVlc3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBxdWVzdGlvbi5pZDtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAoIF8uaW50ZXJzZWN0aW9uKHF1ZXN0aW9uSWRzLCBhbnN3ZXJJZHMpLmxlbmd0aCA9PT0gcXVlc3Rpb25JZHMubGVuZ3RoICkge1xuICAgICAgICAgICAgICAgIHRoaXMuZ2FtZS5jb21wbGV0ZSA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICB0aGlzLiRuZXh0VGljaygoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJHJlZnMucmVzdWx0c01vZGFsLm9wZW4oKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgY29ubmVjdE1hcmtlcnMoKSB7XG4gICAgICAgICAgICB2YXIgbWFwID0gdGhpcy5tYXBEYXRhLm1hcCxcbiAgICAgICAgICAgICAgICBtYXJrZXJzID0gdGhpcy5tYXBEYXRhLm1hcmtlcnM7XG5cbiAgICAgICAgICAgIGlmICggbWFya2Vycy5sZW5ndGggPiAxICkge1xuICAgICAgICAgICAgICAgIF8uZWFjaChtYXJrZXJzLCAobWFya2VyLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIGluZGV4ID09PSAwICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGxpbmUgPSBuZXcgZ29vZ2xlLm1hcHMuUG9seWxpbmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0aDogW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcnNbaW5kZXgtMV0uZ2V0UG9zaXRpb24oKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJzW2luZGV4XS5nZXRQb3NpdGlvbigpXG4gICAgICAgICAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3Ryb2tlV2VpZ2h0OiAyLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3Ryb2tlT3BhY2l0eTogMC41LFxuICAgICAgICAgICAgICAgICAgICAgICAgaWNvbnM6IFt7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWNvbjoge3BhdGg6IGdvb2dsZS5tYXBzLlN5bWJvbFBhdGguRk9SV0FSRF9DTE9TRURfQVJST1d9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldDogJzEwMCUnXG4gICAgICAgICAgICAgICAgICAgICAgICB9XSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdlb2Rlc2ljOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWFwOiBtYXBcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGV4aXQoKSB7XG4gICAgICAgICAgICB2YXIgY29uZmlybWF0aW9uID0gY29uZmlybSh0aGlzLiR0KCdleGl0LWNvbmZpcm1hdGlvbicpKTtcblxuICAgICAgICAgICAgaWYgKCBjb25maXJtYXRpb24gKSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uID0gdGhpcy5iYXNlVXJsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBoYXNQcm94aW1pdHlDaGVjaygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdhbWUuYWN0aXZpdHkucHJveGltaXR5X2NoZWNrO1xuICAgICAgICB9LFxuICAgICAgICBnZXRQcm94aW1pdHlSYWRpdXMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nYW1lLmFjdGl2aXR5LnByb3hpbWl0eV9yYWRpdXMgfHzCoDI1O1xuICAgICAgICB9LFxuICAgICAgICBvcGVuUXVlc3Rpb25Nb2RhbChxdWVzdGlvbikge1xuICAgICAgICAgICAgdGhpcy5xdWVzdGlvbiA9IHF1ZXN0aW9uO1xuICAgICAgICAgICAgdGhpcy4kbmV4dFRpY2soKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuJHJlZnMucXVlc3Rpb25Nb2RhbC5vcGVuKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgZGV0ZWN0QW5kU2V0TWFya2VySWNvbihtYXJrZXIpIHtcbiAgICAgICAgICAgIC8vIFRPRE8gQ2hlY2sgaXQgd2Ugc2hvdWxkIGZhaWwgaW4gY2FzZSBxdWVzdGlvbiBjb3VsZCBub3QgYmUgZm91bmRcbiAgICAgICAgICAgIGNvbnN0IHF1ZXN0aW9uID0gXy5maW5kKHRoaXMuZ2FtZS5hY3Rpdml0eS5xdWVzdGlvbnMsIFsnaWQnLCBtYXJrZXIucXVlc3Rpb25JZF0pO1xuICAgICAgICAgICAgY29uc3QgbmFtZU1hcHBpbmcgPSB7XG4gICAgICAgICAgICAgICAgMTogJ2luZm9ybWF0aW9uJyxcbiAgICAgICAgICAgICAgICAyOiAnb25lLWNvcnJlY3QtYW5zd2VyJyxcbiAgICAgICAgICAgICAgICAzOiAnbXVsdGlwbGUtY29ycmVjdC1hbnN3ZXJzJyxcbiAgICAgICAgICAgICAgICA0OiAnZnJlZWZvcm0tYW5zd2VyJyxcbiAgICAgICAgICAgICAgICA1OiAnbWF0Y2gtcGFpcnMnLFxuICAgICAgICAgICAgICAgIDY6ICdlbWJlZGRlZC1jb250ZW50JyxcbiAgICAgICAgICAgICAgICA3OiAncGhvdG8nXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgbGV0IGljb25CYXNlID0gdGhpcy5iYXNlVXJsICsgJy9pbWcvaWNvbnMvaXRlbS8nO1xuXG4gICAgICAgICAgICBpZiAoIHRoaXMuaXNBbnN3ZXJlZChxdWVzdGlvbi5pZCkgKSB7XG4gICAgICAgICAgICAgICAgaWNvbkJhc2UgKz0gdGhpcy5pc0NvcnJlY3QocXVlc3Rpb24uaWQpID8gJ2NvcnJlY3QvJyA6ICdpbmNvcnJlY3QvJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIHRoaXMuaGFzUHJveGltaXR5Q2hlY2soKSApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkaXN0YW5jZSA9IGdvb2dsZS5tYXBzLmdlb21ldHJ5LnNwaGVyaWNhbC5jb21wdXRlRGlzdGFuY2VCZXR3ZWVuKHRoaXMubWFwRGF0YS5wbGF5ZXJNYXJrZXIuZ2V0UG9zaXRpb24oKSwgbWFya2VyLmdldFBvc2l0aW9uKCkpO1xuXG4gICAgICAgICAgICAgICAgaWYgKCBkaXN0YW5jZSA+IHRoaXMuZ2V0UHJveGltaXR5UmFkaXVzKCkgKSB7XG4gICAgICAgICAgICAgICAgICAgIGljb25CYXNlICs9ICdpbmFjdGl2ZS8nO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbWFya2VyLnNldEljb24oe1xuICAgICAgICAgICAgICAgIGFuY2hvcjogdGhpcy5tYXBEYXRhLmljb25BbmNob3IsXG4gICAgICAgICAgICAgICAgc2l6ZTogdGhpcy5tYXBEYXRhLmljb25TaXplLFxuICAgICAgICAgICAgICAgIHNjYWxlZFNpemU6IHRoaXMubWFwRGF0YS5pY29uU2NhbGVkU2l6ZSxcbiAgICAgICAgICAgICAgICB1cmw6IGljb25CYXNlICsgbmFtZU1hcHBpbmdbcXVlc3Rpb24udHlwZV0gKyAnLnBuZydcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBnZXRNYXJrZXJCb3VuZHMoKSB7XG4gICAgICAgICAgICBpZiAoIHRoaXMubWFwRGF0YS5tYXJrZXJCb3VuZHMgKSByZXR1cm4gdGhpcy5tYXBEYXRhLm1hcmtlckJvdW5kcztcblxuICAgICAgICAgICAgdGhpcy5tYXBEYXRhLm1hcmtlckJvdW5kcyA9IG5ldyBnb29nbGUubWFwcy5MYXRMbmdCb3VuZHMoKTtcblxuICAgICAgICAgICAgaWYgKCB0aGlzLm1hcERhdGEubWFya2Vycy5sZW5ndGggPiAwICkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZtID0gdGhpcztcblxuICAgICAgICAgICAgICAgIF8uZWFjaCh0aGlzLm1hcERhdGEubWFya2VycywgZnVuY3Rpb24obWFya2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHZtLm1hcERhdGEubWFya2VyQm91bmRzLmV4dGVuZChtYXJrZXIuZ2V0UG9zaXRpb24oKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1hcERhdGEubWFya2VyQm91bmRzO1xuICAgICAgICB9LFxuICAgICAgICBnZXRBbnN3ZXJlZFF1ZXN0aW9uc0NvdW50KCkge1xuICAgICAgICAgICAgaWYgKCBfLnNpemUodGhpcy5nYW1lLmFjdGl2aXR5LnF1ZXN0aW9ucykgPT09IDAgfHwgXy5zaXplKHRoaXMuZ2FtZS5hbnN3ZXJzKSA9PT0gMCApIHJldHVybiAwO1xuXG4gICAgICAgICAgICB2YXIgcXVlc3Rpb25JZHMgPSBfLm1hcCh0aGlzLmdhbWUuYWN0aXZpdHkucXVlc3Rpb25zLCBxdWVzdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHF1ZXN0aW9uLmlkO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHZhciBhbnN3ZXJlZCA9IF8uZmlsdGVyKHRoaXMuZ2FtZS5hbnN3ZXJzLCBhbnN3ZXIgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBxdWVzdGlvbklkcy5pbmRleE9mKGFuc3dlci5xdWVzdGlvbikgIT09IC0xO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHJldHVybiBfLnNpemUoYW5zd2VyZWQpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIHJlc291cmNlcy9hc3NldHMvanMvY29tcG9uZW50cy9HYW1lTWFwLnZ1ZSJdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7O0FBV0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBQUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0="); +eval("//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\nfunction GameControls(controlDiv, map, playerMarker, vm) {\n var controlUI = document.createElement('div');\n controlUI.id = 'sz-map-controls'\n controlDiv.appendChild(controlUI);\n\n var completionControlItem = document.createElement('i');\n completionControlItem.className = 'label label-success';\n completionControlItem.style.fontSize = '20px';\n completionControlItem.style.position = 'relative';\n completionControlItem.style.top = '-7px';\n completionControlItem.style.marginLeft = '5px';\n completionControlItem.style.marginRight = '5px';\n completionControlItem.textContent = vm.getAnsweredQuestionsCount() + '/' + _.size(vm.game.activity.questions);\n controlUI.appendChild(completionControlItem);\n\n vm.$watch('game.answers', function() {\n completionControlItem.textContent = vm.getAnsweredQuestionsCount() + '/' + _.size(vm.game.activity.questions);\n });\n\n var informationControlItem = document.createElement('i');\n informationControlItem.className = 'mdi mdi-information-outline';\n informationControlItem.title = vm.$t('info');\n controlUI.appendChild(informationControlItem);\n\n informationControlItem.addEventListener('click', function() {\n vm.$refs.informationModal.open();\n });\n\n var navigationControlItem = document.createElement('i');\n navigationControlItem.className = 'mdi mdi-navigation';\n navigationControlItem.title = vm.$t('position-tracking');\n controlUI.appendChild(navigationControlItem);\n\n navigationControlItem.addEventListener('click', function() {\n if ( map.szTrackingEnabled ) {\n map.szTrackingEnabled = false;\n navigationControlItem.className = 'mdi mdi-navigation';\n } else {\n map.panTo(playerMarker.getPosition());\n google.maps.event.trigger(playerMarker, 'click');\n map.szTrackingEnabled = true;\n navigationControlItem.className = 'mdi mdi-navigation active';\n }\n });\n\n var boundsControlItem = document.createElement('i');\n boundsControlItem.className = 'mdi mdi-map-marker-multiple';\n boundsControlItem.title = vm.$t('apply-item-bounds');\n controlUI.appendChild(boundsControlItem);\n\n boundsControlItem.addEventListener('click', function() {\n var bounds = vm.getMarkerBounds();\n\n if ( !bounds.isEmpty() ) {\n map.fitBounds(bounds);\n }\n });\n\n var exitControlIcon = document.createElement('i');\n exitControlIcon.className = 'mdi mdi-exit-to-app';\n exitControlIcon.title = vm.$t('exit');\n controlUI.appendChild(exitControlIcon);\n\n exitControlIcon.addEventListener('click', function() {\n vm.exit();\n });\n}\n\nvar connectMarkers = window.SmartZoos.config.connect_markers || false;\n\n/* harmony default export */ exports[\"default\"] = {\n components: {\n 'game-information-modal': __webpack_require__(8),\n 'game-question-modal': __webpack_require__(9),\n 'game-results-modal': __webpack_require__(10)\n },\n props: ['latitude', 'longitude'],\n mounted: function mounted() {\n this.baseUrl = window.SmartZoos.config.base_url;\n\n this.game = window.SmartZoos.data.game;\n\n this.mapData = {};\n this.mapData.markers = [];\n this.mapData.mapOptions = {\n center: {\n lat: this.latitude,\n lng: this.longitude\n },\n zoom: 18,\n mapTypeId: google.maps.MapTypeId.ROADMAP,\n disableDefaultUI: true,\n zoomControl: true,\n streetViewControl: true,\n styles: [\n {\n featureType: 'poi',\n stylers: [{visibility: 'off'}]\n },\n {\n featureType: 'transit.station',\n stylers: [{visibility: 'off'}]\n },\n ]\n };\n this.mapData.iconAnchor = new google.maps.Point(17.35, 20);\n this.mapData.iconSize = new google.maps.Size(52, 60);\n this.mapData.iconScaledSize = new google.maps.Size(34.7, 40);\n\n this.initMap();\n },\n data: function data() {\n return {\n question: null,\n game: null,\n baseUrl: ''\n };\n },\n methods: {\n initMap: function initMap() {\n var this$1 = this;\n\n var _this = this;\n\n this.mapData.map = new google.maps.Map(document.getElementById('map'), this.mapData.mapOptions);\n\n this.mapData.infoWindow = new google.maps.InfoWindow();\n\n this.initGroundOverlays();\n\n this.initPlayerMarker();\n\n this.initGameControls();\n\n this.$parent.getGeoLocation(function(position) {\n var map = _this.mapData.map,\n playerMarker = _this.mapData.playerMarker;\n\n playerMarker.setPosition({\n lat: position.coords.latitude,\n lng: position.coords.longitude\n });\n if ( map.szTrackingEnabled === true ) {\n map.panTo(playerMarker.getPosition());\n }\n _this.initUpdateClosestUnansweredMarkerArrow();\n if ( _this.hasProximityCheck() ) {\n // TODO Might make sense to cancel in case location\n // does change rpidly\n // Giving it half a second or so should be good enough\n _.each(_this.mapData.markers, function(marker) {\n if ( !_this.isAnswered(marker.questionId) ) {\n _this.detectAndSetMarkerIcon(marker);\n }\n });\n }\n }, true);\n\n if ( _this.game.activity.questions ) {\n var map = _this.mapData.map,\n markers = _this.mapData.markers,\n infoWindow = _this.mapData.infoWindow,\n playerMarker = _this.mapData.playerMarker;\n\n _.each(_this.game.activity.questions, function(question) {\n var marker = new google.maps.Marker({\n title: question.title,\n position: {\n lat: Number(question.latitude),\n lng: Number(question.longitude)\n },\n map: map,\n animation: google.maps.Animation.DROP,\n questionId: question.id\n });\n\n _this.detectAndSetMarkerIcon(marker);\n\n markers.push(marker);\n\n marker.addListener('click', function() {\n if ( _this.isAnswered(question.id) ) {\n return;\n }\n\n if ( _this.hasProximityCheck() ) {\n var distance = google.maps.geometry.spherical.computeDistanceBetween(playerMarker.getPosition(), marker.getPosition());\n\n if ( distance <= _this.getProximityRadius() ) {\n _this.openQuestionModal(question);\n }\n } else {\n _this.openQuestionModal(question);\n }\n });\n });\n\n if ( connectMarkers ) {\n _this.connectMarkers();\n }\n\n _this.initUpdateClosestUnansweredMarkerArrow();\n }\n\n this.$nextTick(function () {\n if ( this$1.game.complete ) {\n this$1.$refs.resultsModal.open();\n } else {\n this$1.$refs.informationModal.open();\n }\n });\n },\n initGroundOverlays: function initGroundOverlays() {\n this.mapData.skansenGroundOverlay = new google.maps.GroundOverlay(this.baseUrl + '/img/map/overlays/skansen.png',{\n north: 59.329167,\n south: 59.324011,\n east: 18.111242,\n west: 18.099022\n }, {\n clickable: false,\n map: this.mapData.map\n });\n },\n initGameControls: function initGameControls() {\n var map = this.mapData.map,\n playerMarker = this.mapData.playerMarker,\n gameControlsDiv = document.createElement('div'),\n gameControls = new GameControls(gameControlsDiv, map, playerMarker, this);\n\n // XXX This is a strange code pience that sends index without a reason()\n gameControls.index = 1;\n map.controls[google.maps.ControlPosition.TOP_RIGHT].push(gameControlsDiv);\n },\n closeInfoWindow: function closeInfoWindow() {\n var infoWindow = this.mapData.infoWindow;\n\n if ( infoWindow && infoWindow.getMap() ) {\n infoWindow.close();\n }\n },\n initPlayerMarker: function initPlayerMarker() {\n var circle,\n playerMarker,\n activeDistanceCircle,\n _this = this,\n map = this.mapData.map,\n infoWindow = this.mapData.infoWindow;\n\n circle = {\n path: google.maps.SymbolPath.CIRCLE,\n fillColor: 'red',\n fillOpacity: 1.0,\n scale: 4.5,\n strokeColor: 'white',\n strokeWeight: 1\n };\n\n var playerMarker = new google.maps.Marker({\n title: this.$t('its-you'),\n position: {\n lat: this.latitude,\n lng: this.longitude\n },\n map: map,\n icon: circle\n });\n\n playerMarker.addListener('click', function() {\n _this.closeInfoWindow();\n infoWindow.setContent(this.title);\n infoWindow.open(map, this);\n });\n\n if ( this.hasProximityCheck() ) {\n var activeDistanceCircle = new google.maps.Circle({\n map: map,\n radius: this.getProximityRadius(),\n fillColor: 'blue',\n fillOpacity: 0.25,\n strokeColor: 'blue',\n strokeWeight: 1,\n strokeOpacity: 0.5\n });\n activeDistanceCircle.bindTo('center', playerMarker, 'position');\n }\n\n google.maps.event.trigger(playerMarker, 'click');\n\n this.mapData.playerMarker = playerMarker;\n },\n isAnswered: function isAnswered(questionId) {\n return _.has(this.game.answers, questionId);\n },\n isCorrect: function isCorrect(questionId) {\n var answer = _.get(this.game.answers, questionId, null);\n\n return answer && answer.correct === true;\n },\n markAnswered: function markAnswered(id, answer) {\n var this$1 = this;\n\n this.$set(this.game.answers, id, answer);\n\n // TODO Might make sense to raise an error if marker can not be found\n var marker = _.find(this.mapData.markers, function(marker) { return marker.questionId === id; });\n\n if ( marker ) {\n this.detectAndSetMarkerIcon(marker);\n }\n\n var answerIds = _.keys(this.game.answers).map(function (id) {\n return _.toNumber(id);\n });\n var questionIds = _.map(this.game.activity.questions, function (question) {\n return question.id;\n });\n\n this.initUpdateClosestUnansweredMarkerArrow();\n\n if ( _.intersection(questionIds, answerIds).length === questionIds.length ) {\n this.game.complete = true;\n\n this.$nextTick(function () {\n this$1.$refs.resultsModal.open();\n });\n }\n },\n connectMarkers: function connectMarkers$1() {\n var map = this.mapData.map,\n markers = this.mapData.markers;\n\n if ( markers.length > 1 ) {\n _.each(markers, function (marker, index) {\n if ( index === 0 ) {\n return;\n }\n\n var line = new google.maps.Polyline({\n path: [\n markers[index-1].getPosition(),\n markers[index].getPosition()\n ],\n strokeWeight: 2,\n strokeOpacity: 0.5,\n icons: [{\n icon: {path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW},\n offset: '100%'\n }],\n geodesic: true,\n map: map\n });\n });\n }\n },\n exit: function exit() {\n var confirmation = confirm(this.$t('exit-confirmation'));\n\n if ( confirmation ) {\n window.location = this.baseUrl;\n }\n },\n hasProximityCheck: function hasProximityCheck() {\n return this.game.activity.proximity_check;\n },\n getProximityRadius: function getProximityRadius() {\n return this.game.activity.proximity_radius || 25;\n },\n openQuestionModal: function openQuestionModal(question) {\n var this$1 = this;\n\n this.question = question;\n this.$nextTick(function () {\n this$1.$refs.questionModal.open();\n });\n },\n detectAndSetMarkerIcon: function detectAndSetMarkerIcon(marker) {\n // TODO Check it we should fail in case question could not be found\n var question = _.find(this.game.activity.questions, ['id', marker.questionId]);\n var nameMapping = {\n 1: 'information',\n 2: 'one-correct-answer',\n 3: 'multiple-correct-answers',\n 4: 'freeform-answer',\n 5: 'match-pairs',\n 6: 'embedded-content',\n 7: 'photo'\n };\n var iconBase = this.baseUrl + '/img/icons/item/';\n\n if ( this.isAnswered(question.id) ) {\n iconBase += this.isCorrect(question.id) ? 'correct/' : 'incorrect/';\n } else if ( this.hasProximityCheck() ) {\n var distance = google.maps.geometry.spherical.computeDistanceBetween(this.mapData.playerMarker.getPosition(), marker.getPosition());\n\n if ( distance > this.getProximityRadius() ) {\n iconBase += 'inactive/';\n }\n }\n\n marker.setIcon({\n anchor: this.mapData.iconAnchor,\n size: this.mapData.iconSize,\n scaledSize: this.mapData.iconScaledSize,\n url: iconBase + nameMapping[question.type] + '.png'\n });\n },\n getMarkerBounds: function getMarkerBounds() {\n if ( this.mapData.markerBounds ) return this.mapData.markerBounds;\n\n this.mapData.markerBounds = new google.maps.LatLngBounds();\n\n if ( this.mapData.markers.length > 0 ) {\n var vm = this;\n\n _.each(this.mapData.markers, function(marker) {\n vm.mapData.markerBounds.extend(marker.getPosition());\n });\n }\n\n return this.mapData.markerBounds;\n },\n getAnsweredQuestionsCount: function getAnsweredQuestionsCount() {\n if ( _.size(this.game.activity.questions) === 0 || _.size(this.game.answers) === 0 ) return 0;\n\n var questionIds = _.map(this.game.activity.questions, function (question) {\n return question.id;\n });\n\n var answered = _.filter(this.game.answers, function (answer) {\n return questionIds.indexOf(answer.question) !== -1;\n });\n\n return _.size(answered);\n },\n getClosestUnansweredMarker: function getClosestUnansweredMarker() {\n var vm = this,\n unansweredMarkers = _.filter(this.mapData.markers, function (marker) { return !vm.isAnswered(marker.questionId); }),\n playerMarker = this.mapData.playerMarker;\n\n if ( unansweredMarkers.length > 0 ) {\n return _.minBy(unansweredMarkers, function (marker) {\n return google.maps.geometry.spherical.computeDistanceBetween(playerMarker.getPosition(), marker.getPosition());\n });\n }\n\n return null;\n },\n initUpdateClosestUnansweredMarkerArrow: function initUpdateClosestUnansweredMarkerArrow() {\n var vm = this,\n marker = vm.getClosestUnansweredMarker();\n\n if ( !marker ) {\n if ( vm.mapData.closestUnansweredMarkerArrow ) {\n vm.mapData.closestUnansweredMarkerArrow.setMap(null);\n }\n return;\n }\n\n if ( !vm.mapData.closestUnansweredMarkerArrow ) {\n vm.mapData.closestUnansweredMarkerArrow = new google.maps.Polyline({\n path: [\n vm.mapData.playerMarker.getPosition(),\n marker.getPosition()\n ],\n strokeColor: 'red',\n strokeWeight: 2,\n strokeOpacity: 0.4,\n icons: [{\n icon: {\n path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,\n fillColor: 'red',\n strokeColor: 'red',\n fillOpacity: 0.8,\n strokeOpacity: 0.8,\n scale: 4\n },\n offset: '50px',\n }],\n geodesic: true,\n map: vm.mapData.map,\n zIndex: 2\n });\n } else {\n vm.mapData.closestUnansweredMarkerArrow.setPath([\n vm.mapData.playerMarker.getPosition(),\n marker.getPosition()\n ]);\n }\n }\n }\n};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy9yZXNvdXJjZXMvYXNzZXRzL2pzL2NvbXBvbmVudHMvR2FtZU1hcC52dWU/YmI4NCJdLCJzb3VyY2VzQ29udGVudCI6WyIvL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuXG5mdW5jdGlvbiBHYW1lQ29udHJvbHMoY29udHJvbERpdiwgbWFwLCBwbGF5ZXJNYXJrZXIsIHZtKSB7XG4gICAgdmFyIGNvbnRyb2xVSSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGNvbnRyb2xVSS5pZCA9ICdzei1tYXAtY29udHJvbHMnXG4gICAgY29udHJvbERpdi5hcHBlbmRDaGlsZChjb250cm9sVUkpO1xuXG4gICAgdmFyIGNvbXBsZXRpb25Db250cm9sSXRlbSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2knKTtcbiAgICBjb21wbGV0aW9uQ29udHJvbEl0ZW0uY2xhc3NOYW1lID0gJ2xhYmVsIGxhYmVsLXN1Y2Nlc3MnO1xuICAgIGNvbXBsZXRpb25Db250cm9sSXRlbS5zdHlsZS5mb250U2l6ZSA9ICcyMHB4JztcbiAgICBjb21wbGV0aW9uQ29udHJvbEl0ZW0uc3R5bGUucG9zaXRpb24gPSAncmVsYXRpdmUnO1xuICAgIGNvbXBsZXRpb25Db250cm9sSXRlbS5zdHlsZS50b3AgPSAnLTdweCc7XG4gICAgY29tcGxldGlvbkNvbnRyb2xJdGVtLnN0eWxlLm1hcmdpbkxlZnQgPSAnNXB4JztcbiAgICBjb21wbGV0aW9uQ29udHJvbEl0ZW0uc3R5bGUubWFyZ2luUmlnaHQgPSAnNXB4JztcbiAgICBjb21wbGV0aW9uQ29udHJvbEl0ZW0udGV4dENvbnRlbnQgPSB2bS5nZXRBbnN3ZXJlZFF1ZXN0aW9uc0NvdW50KCkgKyAnLycgKyBfLnNpemUodm0uZ2FtZS5hY3Rpdml0eS5xdWVzdGlvbnMpO1xuICAgIGNvbnRyb2xVSS5hcHBlbmRDaGlsZChjb21wbGV0aW9uQ29udHJvbEl0ZW0pO1xuXG4gICAgdm0uJHdhdGNoKCdnYW1lLmFuc3dlcnMnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgY29tcGxldGlvbkNvbnRyb2xJdGVtLnRleHRDb250ZW50ID0gdm0uZ2V0QW5zd2VyZWRRdWVzdGlvbnNDb3VudCgpICsgJy8nICsgXy5zaXplKHZtLmdhbWUuYWN0aXZpdHkucXVlc3Rpb25zKTtcbiAgICB9KTtcblxuICAgIHZhciBpbmZvcm1hdGlvbkNvbnRyb2xJdGVtID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaScpO1xuICAgIGluZm9ybWF0aW9uQ29udHJvbEl0ZW0uY2xhc3NOYW1lID0gJ21kaSBtZGktaW5mb3JtYXRpb24tb3V0bGluZSc7XG4gICAgaW5mb3JtYXRpb25Db250cm9sSXRlbS50aXRsZSA9IHZtLiR0KCdpbmZvJyk7XG4gICAgY29udHJvbFVJLmFwcGVuZENoaWxkKGluZm9ybWF0aW9uQ29udHJvbEl0ZW0pO1xuXG4gICAgaW5mb3JtYXRpb25Db250cm9sSXRlbS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKCkge1xuICAgICAgICB2bS4kcmVmcy5pbmZvcm1hdGlvbk1vZGFsLm9wZW4oKTtcbiAgICB9KTtcblxuICAgIHZhciBuYXZpZ2F0aW9uQ29udHJvbEl0ZW0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpJyk7XG4gICAgbmF2aWdhdGlvbkNvbnRyb2xJdGVtLmNsYXNzTmFtZSA9ICdtZGkgbWRpLW5hdmlnYXRpb24nO1xuICAgIG5hdmlnYXRpb25Db250cm9sSXRlbS50aXRsZSA9IHZtLiR0KCdwb3NpdGlvbi10cmFja2luZycpO1xuICAgIGNvbnRyb2xVSS5hcHBlbmRDaGlsZChuYXZpZ2F0aW9uQ29udHJvbEl0ZW0pO1xuXG4gICAgbmF2aWdhdGlvbkNvbnRyb2xJdGVtLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICggbWFwLnN6VHJhY2tpbmdFbmFibGVkICkge1xuICAgICAgICAgICAgbWFwLnN6VHJhY2tpbmdFbmFibGVkID0gZmFsc2U7XG4gICAgICAgICAgICBuYXZpZ2F0aW9uQ29udHJvbEl0ZW0uY2xhc3NOYW1lID0gJ21kaSBtZGktbmF2aWdhdGlvbic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtYXAucGFuVG8ocGxheWVyTWFya2VyLmdldFBvc2l0aW9uKCkpO1xuICAgICAgICAgICAgZ29vZ2xlLm1hcHMuZXZlbnQudHJpZ2dlcihwbGF5ZXJNYXJrZXIsICdjbGljaycpO1xuICAgICAgICAgICAgbWFwLnN6VHJhY2tpbmdFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIG5hdmlnYXRpb25Db250cm9sSXRlbS5jbGFzc05hbWUgPSAnbWRpIG1kaS1uYXZpZ2F0aW9uIGFjdGl2ZSc7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHZhciBib3VuZHNDb250cm9sSXRlbSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2knKTtcbiAgICBib3VuZHNDb250cm9sSXRlbS5jbGFzc05hbWUgPSAnbWRpIG1kaS1tYXAtbWFya2VyLW11bHRpcGxlJztcbiAgICBib3VuZHNDb250cm9sSXRlbS50aXRsZSA9IHZtLiR0KCdhcHBseS1pdGVtLWJvdW5kcycpO1xuICAgIGNvbnRyb2xVSS5hcHBlbmRDaGlsZChib3VuZHNDb250cm9sSXRlbSk7XG5cbiAgICBib3VuZHNDb250cm9sSXRlbS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgYm91bmRzID0gdm0uZ2V0TWFya2VyQm91bmRzKCk7XG5cbiAgICAgICAgaWYgKCAhYm91bmRzLmlzRW1wdHkoKSApIHtcbiAgICAgICAgICAgIG1hcC5maXRCb3VuZHMoYm91bmRzKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgdmFyIGV4aXRDb250cm9sSWNvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2knKTtcbiAgICBleGl0Q29udHJvbEljb24uY2xhc3NOYW1lID0gJ21kaSBtZGktZXhpdC10by1hcHAnO1xuICAgIGV4aXRDb250cm9sSWNvbi50aXRsZSA9IHZtLiR0KCdleGl0Jyk7XG4gICAgY29udHJvbFVJLmFwcGVuZENoaWxkKGV4aXRDb250cm9sSWNvbik7XG5cbiAgICBleGl0Q29udHJvbEljb24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBmdW5jdGlvbigpIHtcbiAgICAgICAgdm0uZXhpdCgpO1xuICAgIH0pO1xufVxuXG52YXIgY29ubmVjdE1hcmtlcnMgPSAgd2luZG93LlNtYXJ0Wm9vcy5jb25maWcuY29ubmVjdF9tYXJrZXJzIHx8IGZhbHNlO1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gICAgY29tcG9uZW50czoge1xuICAgICAgICAnZ2FtZS1pbmZvcm1hdGlvbi1tb2RhbCc6IHJlcXVpcmUoJy4vR2FtZUluZm9ybWF0aW9uTW9kYWwudnVlJyksXG4gICAgICAgICdnYW1lLXF1ZXN0aW9uLW1vZGFsJzogcmVxdWlyZSgnLi9HYW1lUXVlc3Rpb25Nb2RhbC52dWUnKSxcbiAgICAgICAgJ2dhbWUtcmVzdWx0cy1tb2RhbCc6IHJlcXVpcmUoJy4vR2FtZVJlc3VsdHNNb2RhbC52dWUnKVxuICAgIH0sXG4gICAgcHJvcHM6IFsnbGF0aXR1ZGUnLCAnbG9uZ2l0dWRlJ10sXG4gICAgbW91bnRlZCgpIHtcbiAgICAgICAgdGhpcy5iYXNlVXJsID0gd2luZG93LlNtYXJ0Wm9vcy5jb25maWcuYmFzZV91cmw7XG5cbiAgICAgICAgdGhpcy5nYW1lID0gd2luZG93LlNtYXJ0Wm9vcy5kYXRhLmdhbWU7XG5cbiAgICAgICAgdGhpcy5tYXBEYXRhID0ge307XG4gICAgICAgIHRoaXMubWFwRGF0YS5tYXJrZXJzID0gW107XG4gICAgICAgIHRoaXMubWFwRGF0YS5tYXBPcHRpb25zID0ge1xuICAgICAgICAgICAgY2VudGVyOiB7XG4gICAgICAgICAgICAgICAgbGF0OiB0aGlzLmxhdGl0dWRlLFxuICAgICAgICAgICAgICAgIGxuZzogdGhpcy5sb25naXR1ZGVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB6b29tOiAxOCxcbiAgICAgICAgICAgIG1hcFR5cGVJZDogZ29vZ2xlLm1hcHMuTWFwVHlwZUlkLlJPQURNQVAsXG4gICAgICAgICAgICBkaXNhYmxlRGVmYXVsdFVJOiB0cnVlLFxuICAgICAgICAgICAgem9vbUNvbnRyb2w6IHRydWUsXG4gICAgICAgICAgICBzdHJlZXRWaWV3Q29udHJvbDogdHJ1ZSxcbiAgICAgICAgICAgIHN0eWxlczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZmVhdHVyZVR5cGU6ICdwb2knLFxuICAgICAgICAgICAgICAgICAgICBzdHlsZXJzOiBbe3Zpc2liaWxpdHk6ICdvZmYnfV1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZmVhdHVyZVR5cGU6ICd0cmFuc2l0LnN0YXRpb24nLFxuICAgICAgICAgICAgICAgICAgICBzdHlsZXJzOiBbe3Zpc2liaWxpdHk6ICdvZmYnfV1cbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5tYXBEYXRhLmljb25BbmNob3IgPSBuZXcgZ29vZ2xlLm1hcHMuUG9pbnQoMTcuMzUsIDIwKTtcbiAgICAgICAgdGhpcy5tYXBEYXRhLmljb25TaXplID0gbmV3IGdvb2dsZS5tYXBzLlNpemUoNTIsIDYwKTtcbiAgICAgICAgdGhpcy5tYXBEYXRhLmljb25TY2FsZWRTaXplID0gbmV3IGdvb2dsZS5tYXBzLlNpemUoMzQuNywgNDApO1xuXG4gICAgICAgIHRoaXMuaW5pdE1hcCgpO1xuICAgIH0sXG4gICAgZGF0YSgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHF1ZXN0aW9uOiBudWxsLFxuICAgICAgICAgICAgZ2FtZTogbnVsbCxcbiAgICAgICAgICAgIGJhc2VVcmw6ICcnXG4gICAgICAgIH07XG4gICAgfSxcbiAgICBtZXRob2RzOiB7XG4gICAgICAgIGluaXRNYXAoKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAgICAgICB0aGlzLm1hcERhdGEubWFwID0gbmV3IGdvb2dsZS5tYXBzLk1hcChkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbWFwJyksIHRoaXMubWFwRGF0YS5tYXBPcHRpb25zKTtcblxuICAgICAgICAgICAgdGhpcy5tYXBEYXRhLmluZm9XaW5kb3cgPSBuZXcgZ29vZ2xlLm1hcHMuSW5mb1dpbmRvdygpO1xuXG4gICAgICAgICAgICB0aGlzLmluaXRHcm91bmRPdmVybGF5cygpO1xuXG4gICAgICAgICAgICB0aGlzLmluaXRQbGF5ZXJNYXJrZXIoKTtcblxuICAgICAgICAgICAgdGhpcy5pbml0R2FtZUNvbnRyb2xzKCk7XG5cbiAgICAgICAgICAgIHRoaXMuJHBhcmVudC5nZXRHZW9Mb2NhdGlvbihmdW5jdGlvbihwb3NpdGlvbikge1xuICAgICAgICAgICAgICAgIHZhciBtYXAgPSBfdGhpcy5tYXBEYXRhLm1hcCxcbiAgICAgICAgICAgICAgICAgICAgcGxheWVyTWFya2VyID0gX3RoaXMubWFwRGF0YS5wbGF5ZXJNYXJrZXI7XG5cbiAgICAgICAgICAgICAgICBwbGF5ZXJNYXJrZXIuc2V0UG9zaXRpb24oe1xuICAgICAgICAgICAgICAgICAgICBsYXQ6IHBvc2l0aW9uLmNvb3Jkcy5sYXRpdHVkZSxcbiAgICAgICAgICAgICAgICAgICAgbG5nOiBwb3NpdGlvbi5jb29yZHMubG9uZ2l0dWRlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKCBtYXAuc3pUcmFja2luZ0VuYWJsZWQgPT09IHRydWUgKSB7XG4gICAgICAgICAgICAgICAgICAgIG1hcC5wYW5UbyhwbGF5ZXJNYXJrZXIuZ2V0UG9zaXRpb24oKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF90aGlzLmluaXRVcGRhdGVDbG9zZXN0VW5hbnN3ZXJlZE1hcmtlckFycm93KCk7XG4gICAgICAgICAgICAgICAgaWYgKCBfdGhpcy5oYXNQcm94aW1pdHlDaGVjaygpICkge1xuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPIE1pZ2h0IG1ha2Ugc2Vuc2UgdG8gY2FuY2VsIGluIGNhc2UgbG9jYXRpb25cbiAgICAgICAgICAgICAgICAgICAgLy8gZG9lcyBjaGFuZ2UgcnBpZGx5XG4gICAgICAgICAgICAgICAgICAgIC8vIEdpdmluZyBpdCBoYWxmIGEgc2Vjb25kIG9yIHNvIHNob3VsZCBiZSBnb29kIGVub3VnaFxuICAgICAgICAgICAgICAgICAgICBfLmVhY2goX3RoaXMubWFwRGF0YS5tYXJrZXJzLCBmdW5jdGlvbihtYXJrZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICggIV90aGlzLmlzQW5zd2VyZWQobWFya2VyLnF1ZXN0aW9uSWQpICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmRldGVjdEFuZFNldE1hcmtlckljb24obWFya2VyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgdHJ1ZSk7XG5cbiAgICAgICAgICAgIGlmICggX3RoaXMuZ2FtZS5hY3Rpdml0eS5xdWVzdGlvbnMgKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hcCA9IF90aGlzLm1hcERhdGEubWFwLFxuICAgICAgICAgICAgICAgICAgICBtYXJrZXJzID0gX3RoaXMubWFwRGF0YS5tYXJrZXJzLFxuICAgICAgICAgICAgICAgICAgICBpbmZvV2luZG93ID0gX3RoaXMubWFwRGF0YS5pbmZvV2luZG93LFxuICAgICAgICAgICAgICAgICAgICBwbGF5ZXJNYXJrZXIgPSBfdGhpcy5tYXBEYXRhLnBsYXllck1hcmtlcjtcblxuICAgICAgICAgICAgICAgIF8uZWFjaChfdGhpcy5nYW1lLmFjdGl2aXR5LnF1ZXN0aW9ucywgZnVuY3Rpb24ocXVlc3Rpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1hcmtlciA9IG5ldyBnb29nbGUubWFwcy5NYXJrZXIoe1xuICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU6IHF1ZXN0aW9uLnRpdGxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXQ6IE51bWJlcihxdWVzdGlvbi5sYXRpdHVkZSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG5nOiBOdW1iZXIocXVlc3Rpb24ubG9uZ2l0dWRlKVxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hcDogbWFwLFxuICAgICAgICAgICAgICAgICAgICAgICAgYW5pbWF0aW9uOiBnb29nbGUubWFwcy5BbmltYXRpb24uRFJPUCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHF1ZXN0aW9uSWQ6IHF1ZXN0aW9uLmlkXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmRldGVjdEFuZFNldE1hcmtlckljb24obWFya2VyKTtcblxuICAgICAgICAgICAgICAgICAgICBtYXJrZXJzLnB1c2gobWFya2VyKTtcblxuICAgICAgICAgICAgICAgICAgICBtYXJrZXIuYWRkTGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIF90aGlzLmlzQW5zd2VyZWQocXVlc3Rpb24uaWQpICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCBfdGhpcy5oYXNQcm94aW1pdHlDaGVjaygpICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkaXN0YW5jZSA9IGdvb2dsZS5tYXBzLmdlb21ldHJ5LnNwaGVyaWNhbC5jb21wdXRlRGlzdGFuY2VCZXR3ZWVuKHBsYXllck1hcmtlci5nZXRQb3NpdGlvbigpLCBtYXJrZXIuZ2V0UG9zaXRpb24oKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIGRpc3RhbmNlIDw9IF90aGlzLmdldFByb3hpbWl0eVJhZGl1cygpICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuUXVlc3Rpb25Nb2RhbChxdWVzdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5vcGVuUXVlc3Rpb25Nb2RhbChxdWVzdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgaWYgKCBjb25uZWN0TWFya2VycyApIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29ubmVjdE1hcmtlcnMoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBfdGhpcy5pbml0VXBkYXRlQ2xvc2VzdFVuYW5zd2VyZWRNYXJrZXJBcnJvdygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLiRuZXh0VGljaygoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCB0aGlzLmdhbWUuY29tcGxldGUgKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJHJlZnMucmVzdWx0c01vZGFsLm9wZW4oKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiRyZWZzLmluZm9ybWF0aW9uTW9kYWwub3BlbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBpbml0R3JvdW5kT3ZlcmxheXMoKSB7XG4gICAgICAgICAgICB0aGlzLm1hcERhdGEuc2thbnNlbkdyb3VuZE92ZXJsYXkgPSBuZXcgZ29vZ2xlLm1hcHMuR3JvdW5kT3ZlcmxheSh0aGlzLmJhc2VVcmwgKyAnL2ltZy9tYXAvb3ZlcmxheXMvc2thbnNlbi5wbmcnLHtcbiAgICAgICAgICAgICAgICBub3J0aDogNTkuMzI5MTY3LFxuICAgICAgICAgICAgICAgIHNvdXRoOiA1OS4zMjQwMTEsXG4gICAgICAgICAgICAgICAgZWFzdDogMTguMTExMjQyLFxuICAgICAgICAgICAgICAgIHdlc3Q6IDE4LjA5OTAyMlxuICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgIGNsaWNrYWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgbWFwOiB0aGlzLm1hcERhdGEubWFwXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgaW5pdEdhbWVDb250cm9scygpIHtcbiAgICAgICAgICAgIHZhciBtYXAgPSB0aGlzLm1hcERhdGEubWFwLFxuICAgICAgICAgICAgICAgIHBsYXllck1hcmtlciA9IHRoaXMubWFwRGF0YS5wbGF5ZXJNYXJrZXIsXG4gICAgICAgICAgICAgICAgZ2FtZUNvbnRyb2xzRGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksXG4gICAgICAgICAgICAgICAgZ2FtZUNvbnRyb2xzID0gbmV3IEdhbWVDb250cm9scyhnYW1lQ29udHJvbHNEaXYsIG1hcCwgcGxheWVyTWFya2VyLCB0aGlzKTtcblxuICAgICAgICAgICAgLy8gWFhYIFRoaXMgaXMgYSBzdHJhbmdlIGNvZGUgcGllbmNlIHRoYXQgc2VuZHMgaW5kZXggd2l0aG91dCBhIHJlYXNvbigpXG4gICAgICAgICAgICBnYW1lQ29udHJvbHMuaW5kZXggPSAxO1xuICAgICAgICAgICAgbWFwLmNvbnRyb2xzW2dvb2dsZS5tYXBzLkNvbnRyb2xQb3NpdGlvbi5UT1BfUklHSFRdLnB1c2goZ2FtZUNvbnRyb2xzRGl2KTtcbiAgICAgICAgfSxcbiAgICAgICAgY2xvc2VJbmZvV2luZG93KCkge1xuICAgICAgICAgICAgdmFyIGluZm9XaW5kb3cgPSB0aGlzLm1hcERhdGEuaW5mb1dpbmRvdztcblxuICAgICAgICAgICAgaWYgKCBpbmZvV2luZG93ICYmIGluZm9XaW5kb3cuZ2V0TWFwKCkgKSB7XG4gICAgICAgICAgICAgICAgaW5mb1dpbmRvdy5jbG9zZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBpbml0UGxheWVyTWFya2VyKCkge1xuICAgICAgICAgICAgdmFyIGNpcmNsZSxcbiAgICAgICAgICAgICAgICBwbGF5ZXJNYXJrZXIsXG4gICAgICAgICAgICAgICAgYWN0aXZlRGlzdGFuY2VDaXJjbGUsXG4gICAgICAgICAgICAgICAgX3RoaXMgPSB0aGlzLFxuICAgICAgICAgICAgICAgIG1hcCA9IHRoaXMubWFwRGF0YS5tYXAsXG4gICAgICAgICAgICAgICAgaW5mb1dpbmRvdyA9IHRoaXMubWFwRGF0YS5pbmZvV2luZG93O1xuXG4gICAgICAgICAgICBjaXJjbGUgPSB7XG4gICAgICAgICAgICAgICAgcGF0aDogZ29vZ2xlLm1hcHMuU3ltYm9sUGF0aC5DSVJDTEUsXG4gICAgICAgICAgICAgICAgZmlsbENvbG9yOiAncmVkJyxcbiAgICAgICAgICAgICAgICBmaWxsT3BhY2l0eTogMS4wLFxuICAgICAgICAgICAgICAgIHNjYWxlOiA0LjUsXG4gICAgICAgICAgICAgICAgc3Ryb2tlQ29sb3I6ICd3aGl0ZScsXG4gICAgICAgICAgICAgICAgc3Ryb2tlV2VpZ2h0OiAxXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB2YXIgcGxheWVyTWFya2VyID0gbmV3IGdvb2dsZS5tYXBzLk1hcmtlcih7XG4gICAgICAgICAgICAgICAgdGl0bGU6IHRoaXMuJHQoJ2l0cy15b3UnKSxcbiAgICAgICAgICAgICAgICBwb3NpdGlvbjoge1xuICAgICAgICAgICAgICAgICAgICBsYXQ6IHRoaXMubGF0aXR1ZGUsXG4gICAgICAgICAgICAgICAgICAgIGxuZzogdGhpcy5sb25naXR1ZGVcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG1hcDogbWFwLFxuICAgICAgICAgICAgICAgIGljb246IGNpcmNsZVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHBsYXllck1hcmtlci5hZGRMaXN0ZW5lcignY2xpY2snLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZUluZm9XaW5kb3coKTtcbiAgICAgICAgICAgICAgICBpbmZvV2luZG93LnNldENvbnRlbnQodGhpcy50aXRsZSk7XG4gICAgICAgICAgICAgICAgaW5mb1dpbmRvdy5vcGVuKG1hcCwgdGhpcyk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKCB0aGlzLmhhc1Byb3hpbWl0eUNoZWNrKCkgKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFjdGl2ZURpc3RhbmNlQ2lyY2xlID0gbmV3IGdvb2dsZS5tYXBzLkNpcmNsZSh7XG4gICAgICAgICAgICAgICAgICAgIG1hcDogbWFwLFxuICAgICAgICAgICAgICAgICAgICByYWRpdXM6IHRoaXMuZ2V0UHJveGltaXR5UmFkaXVzKCksXG4gICAgICAgICAgICAgICAgICAgIGZpbGxDb2xvcjogJ2JsdWUnLFxuICAgICAgICAgICAgICAgICAgICBmaWxsT3BhY2l0eTogMC4yNSxcbiAgICAgICAgICAgICAgICAgICAgc3Ryb2tlQ29sb3I6ICdibHVlJyxcbiAgICAgICAgICAgICAgICAgICAgc3Ryb2tlV2VpZ2h0OiAxLFxuICAgICAgICAgICAgICAgICAgICBzdHJva2VPcGFjaXR5OiAwLjVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBhY3RpdmVEaXN0YW5jZUNpcmNsZS5iaW5kVG8oJ2NlbnRlcicsIHBsYXllck1hcmtlciwgJ3Bvc2l0aW9uJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGdvb2dsZS5tYXBzLmV2ZW50LnRyaWdnZXIocGxheWVyTWFya2VyLCAnY2xpY2snKTtcblxuICAgICAgICAgICAgdGhpcy5tYXBEYXRhLnBsYXllck1hcmtlciA9IHBsYXllck1hcmtlcjtcbiAgICAgICAgfSxcbiAgICAgICAgaXNBbnN3ZXJlZChxdWVzdGlvbklkKSB7XG4gICAgICAgICAgICByZXR1cm4gXy5oYXModGhpcy5nYW1lLmFuc3dlcnMsIHF1ZXN0aW9uSWQpO1xuICAgICAgICB9LFxuICAgICAgICBpc0NvcnJlY3QocXVlc3Rpb25JZCkge1xuICAgICAgICAgICAgY29uc3QgYW5zd2VyID0gXy5nZXQodGhpcy5nYW1lLmFuc3dlcnMsIHF1ZXN0aW9uSWQsIG51bGwpO1xuXG4gICAgICAgICAgICByZXR1cm4gYW5zd2VyICYmIGFuc3dlci5jb3JyZWN0ID09PSB0cnVlO1xuICAgICAgICB9LFxuICAgICAgICBtYXJrQW5zd2VyZWQoaWQsIGFuc3dlcikge1xuICAgICAgICAgICAgdGhpcy4kc2V0KHRoaXMuZ2FtZS5hbnN3ZXJzLCBpZCwgYW5zd2VyKTtcblxuICAgICAgICAgICAgLy8gVE9ETyBNaWdodCBtYWtlIHNlbnNlIHRvIHJhaXNlIGFuIGVycm9yIGlmIG1hcmtlciBjYW4gbm90IGJlIGZvdW5kXG4gICAgICAgICAgICB2YXIgbWFya2VyID0gXy5maW5kKHRoaXMubWFwRGF0YS5tYXJrZXJzLCBmdW5jdGlvbihtYXJrZXIpIHsgcmV0dXJuIG1hcmtlci5xdWVzdGlvbklkID09PSBpZDsgfSk7XG5cbiAgICAgICAgICAgIGlmICggbWFya2VyICkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGV0ZWN0QW5kU2V0TWFya2VySWNvbihtYXJrZXIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgYW5zd2VySWRzID0gXy5rZXlzKHRoaXMuZ2FtZS5hbnN3ZXJzKS5tYXAoaWQgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBfLnRvTnVtYmVyKGlkKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyIHF1ZXN0aW9uSWRzID0gXy5tYXAodGhpcy5nYW1lLmFjdGl2aXR5LnF1ZXN0aW9ucywgcXVlc3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBxdWVzdGlvbi5pZDtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0aGlzLmluaXRVcGRhdGVDbG9zZXN0VW5hbnN3ZXJlZE1hcmtlckFycm93KCk7XG5cbiAgICAgICAgICAgIGlmICggXy5pbnRlcnNlY3Rpb24ocXVlc3Rpb25JZHMsIGFuc3dlcklkcykubGVuZ3RoID09PSBxdWVzdGlvbklkcy5sZW5ndGggKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5nYW1lLmNvbXBsZXRlID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIHRoaXMuJG5leHRUaWNrKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy4kcmVmcy5yZXN1bHRzTW9kYWwub3BlbigpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBjb25uZWN0TWFya2VycygpIHtcbiAgICAgICAgICAgIHZhciBtYXAgPSB0aGlzLm1hcERhdGEubWFwLFxuICAgICAgICAgICAgICAgIG1hcmtlcnMgPSB0aGlzLm1hcERhdGEubWFya2VycztcblxuICAgICAgICAgICAgaWYgKCBtYXJrZXJzLmxlbmd0aCA+IDEgKSB7XG4gICAgICAgICAgICAgICAgXy5lYWNoKG1hcmtlcnMsIChtYXJrZXIsIGluZGV4KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICggaW5kZXggPT09IDAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgbGluZSA9IG5ldyBnb29nbGUubWFwcy5Qb2x5bGluZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRoOiBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2Vyc1tpbmRleC0xXS5nZXRQb3NpdGlvbigpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcnNbaW5kZXhdLmdldFBvc2l0aW9uKClcbiAgICAgICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICAgICAgICBzdHJva2VXZWlnaHQ6IDIsXG4gICAgICAgICAgICAgICAgICAgICAgICBzdHJva2VPcGFjaXR5OiAwLjUsXG4gICAgICAgICAgICAgICAgICAgICAgICBpY29uczogW3tcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpY29uOiB7cGF0aDogZ29vZ2xlLm1hcHMuU3ltYm9sUGF0aC5GT1JXQVJEX0NMT1NFRF9BUlJPV30sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0OiAnMTAwJSdcbiAgICAgICAgICAgICAgICAgICAgICAgIH1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2VvZGVzaWM6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXA6IG1hcFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZXhpdCgpIHtcbiAgICAgICAgICAgIHZhciBjb25maXJtYXRpb24gPSBjb25maXJtKHRoaXMuJHQoJ2V4aXQtY29uZmlybWF0aW9uJykpO1xuXG4gICAgICAgICAgICBpZiAoIGNvbmZpcm1hdGlvbiApIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24gPSB0aGlzLmJhc2VVcmw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGhhc1Byb3hpbWl0eUNoZWNrKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2FtZS5hY3Rpdml0eS5wcm94aW1pdHlfY2hlY2s7XG4gICAgICAgIH0sXG4gICAgICAgIGdldFByb3hpbWl0eVJhZGl1cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdhbWUuYWN0aXZpdHkucHJveGltaXR5X3JhZGl1cyB8fMKgMjU7XG4gICAgICAgIH0sXG4gICAgICAgIG9wZW5RdWVzdGlvbk1vZGFsKHF1ZXN0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLnF1ZXN0aW9uID0gcXVlc3Rpb247XG4gICAgICAgICAgICB0aGlzLiRuZXh0VGljaygoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy4kcmVmcy5xdWVzdGlvbk1vZGFsLm9wZW4oKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBkZXRlY3RBbmRTZXRNYXJrZXJJY29uKG1hcmtlcikge1xuICAgICAgICAgICAgLy8gVE9ETyBDaGVjayBpdCB3ZSBzaG91bGQgZmFpbCBpbiBjYXNlIHF1ZXN0aW9uIGNvdWxkIG5vdCBiZSBmb3VuZFxuICAgICAgICAgICAgY29uc3QgcXVlc3Rpb24gPSBfLmZpbmQodGhpcy5nYW1lLmFjdGl2aXR5LnF1ZXN0aW9ucywgWydpZCcsIG1hcmtlci5xdWVzdGlvbklkXSk7XG4gICAgICAgICAgICBjb25zdCBuYW1lTWFwcGluZyA9IHtcbiAgICAgICAgICAgICAgICAxOiAnaW5mb3JtYXRpb24nLFxuICAgICAgICAgICAgICAgIDI6ICdvbmUtY29ycmVjdC1hbnN3ZXInLFxuICAgICAgICAgICAgICAgIDM6ICdtdWx0aXBsZS1jb3JyZWN0LWFuc3dlcnMnLFxuICAgICAgICAgICAgICAgIDQ6ICdmcmVlZm9ybS1hbnN3ZXInLFxuICAgICAgICAgICAgICAgIDU6ICdtYXRjaC1wYWlycycsXG4gICAgICAgICAgICAgICAgNjogJ2VtYmVkZGVkLWNvbnRlbnQnLFxuICAgICAgICAgICAgICAgIDc6ICdwaG90bydcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBsZXQgaWNvbkJhc2UgPSB0aGlzLmJhc2VVcmwgKyAnL2ltZy9pY29ucy9pdGVtLyc7XG5cbiAgICAgICAgICAgIGlmICggdGhpcy5pc0Fuc3dlcmVkKHF1ZXN0aW9uLmlkKSApIHtcbiAgICAgICAgICAgICAgICBpY29uQmFzZSArPSB0aGlzLmlzQ29ycmVjdChxdWVzdGlvbi5pZCkgPyAnY29ycmVjdC8nIDogJ2luY29ycmVjdC8nO1xuICAgICAgICAgICAgfSBlbHNlIGlmICggdGhpcy5oYXNQcm94aW1pdHlDaGVjaygpICkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRpc3RhbmNlID0gZ29vZ2xlLm1hcHMuZ2VvbWV0cnkuc3BoZXJpY2FsLmNvbXB1dGVEaXN0YW5jZUJldHdlZW4odGhpcy5tYXBEYXRhLnBsYXllck1hcmtlci5nZXRQb3NpdGlvbigpLCBtYXJrZXIuZ2V0UG9zaXRpb24oKSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoIGRpc3RhbmNlID4gdGhpcy5nZXRQcm94aW1pdHlSYWRpdXMoKSApIHtcbiAgICAgICAgICAgICAgICAgICAgaWNvbkJhc2UgKz0gJ2luYWN0aXZlLyc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBtYXJrZXIuc2V0SWNvbih7XG4gICAgICAgICAgICAgICAgYW5jaG9yOiB0aGlzLm1hcERhdGEuaWNvbkFuY2hvcixcbiAgICAgICAgICAgICAgICBzaXplOiB0aGlzLm1hcERhdGEuaWNvblNpemUsXG4gICAgICAgICAgICAgICAgc2NhbGVkU2l6ZTogdGhpcy5tYXBEYXRhLmljb25TY2FsZWRTaXplLFxuICAgICAgICAgICAgICAgIHVybDogaWNvbkJhc2UgKyBuYW1lTWFwcGluZ1txdWVzdGlvbi50eXBlXSArICcucG5nJ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIGdldE1hcmtlckJvdW5kcygpIHtcbiAgICAgICAgICAgIGlmICggdGhpcy5tYXBEYXRhLm1hcmtlckJvdW5kcyApIHJldHVybiB0aGlzLm1hcERhdGEubWFya2VyQm91bmRzO1xuXG4gICAgICAgICAgICB0aGlzLm1hcERhdGEubWFya2VyQm91bmRzID0gbmV3IGdvb2dsZS5tYXBzLkxhdExuZ0JvdW5kcygpO1xuXG4gICAgICAgICAgICBpZiAoIHRoaXMubWFwRGF0YS5tYXJrZXJzLmxlbmd0aCA+IDAgKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgdm0gPSB0aGlzO1xuXG4gICAgICAgICAgICAgICAgXy5lYWNoKHRoaXMubWFwRGF0YS5tYXJrZXJzLCBmdW5jdGlvbihtYXJrZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgdm0ubWFwRGF0YS5tYXJrZXJCb3VuZHMuZXh0ZW5kKG1hcmtlci5nZXRQb3NpdGlvbigpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubWFwRGF0YS5tYXJrZXJCb3VuZHM7XG4gICAgICAgIH0sXG4gICAgICAgIGdldEFuc3dlcmVkUXVlc3Rpb25zQ291bnQoKSB7XG4gICAgICAgICAgICBpZiAoIF8uc2l6ZSh0aGlzLmdhbWUuYWN0aXZpdHkucXVlc3Rpb25zKSA9PT0gMCB8fCBfLnNpemUodGhpcy5nYW1lLmFuc3dlcnMpID09PSAwICkgcmV0dXJuIDA7XG5cbiAgICAgICAgICAgIHZhciBxdWVzdGlvbklkcyA9IF8ubWFwKHRoaXMuZ2FtZS5hY3Rpdml0eS5xdWVzdGlvbnMsIHF1ZXN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcXVlc3Rpb24uaWQ7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdmFyIGFuc3dlcmVkID0gXy5maWx0ZXIodGhpcy5nYW1lLmFuc3dlcnMsIGFuc3dlciA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHF1ZXN0aW9uSWRzLmluZGV4T2YoYW5zd2VyLnF1ZXN0aW9uKSAhPT0gLTE7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgcmV0dXJuIF8uc2l6ZShhbnN3ZXJlZCk7XG4gICAgICAgIH0sXG4gICAgICAgIGdldENsb3Nlc3RVbmFuc3dlcmVkTWFya2VyKCkge1xuICAgICAgICAgICAgdmFyIHZtID0gdGhpcyxcbiAgICAgICAgICAgICAgICB1bmFuc3dlcmVkTWFya2VycyA9IF8uZmlsdGVyKHRoaXMubWFwRGF0YS5tYXJrZXJzLCBtYXJrZXIgPT4geyByZXR1cm4gIXZtLmlzQW5zd2VyZWQobWFya2VyLnF1ZXN0aW9uSWQpOyB9KSxcbiAgICAgICAgICAgICAgICBwbGF5ZXJNYXJrZXIgPSB0aGlzLm1hcERhdGEucGxheWVyTWFya2VyO1xuXG4gICAgICAgICAgICBpZiAoIHVuYW5zd2VyZWRNYXJrZXJzLmxlbmd0aCA+IDAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF8ubWluQnkodW5hbnN3ZXJlZE1hcmtlcnMsIG1hcmtlciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBnb29nbGUubWFwcy5nZW9tZXRyeS5zcGhlcmljYWwuY29tcHV0ZURpc3RhbmNlQmV0d2VlbihwbGF5ZXJNYXJrZXIuZ2V0UG9zaXRpb24oKSwgbWFya2VyLmdldFBvc2l0aW9uKCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfSxcbiAgICAgICAgaW5pdFVwZGF0ZUNsb3Nlc3RVbmFuc3dlcmVkTWFya2VyQXJyb3coKSB7XG4gICAgICAgICAgICB2YXIgdm0gPSB0aGlzLFxuICAgICAgICAgICAgICAgIG1hcmtlciA9IHZtLmdldENsb3Nlc3RVbmFuc3dlcmVkTWFya2VyKCk7XG5cbiAgICAgICAgICAgIGlmICggIW1hcmtlciApIHtcbiAgICAgICAgICAgICAgICBpZiAoIHZtLm1hcERhdGEuY2xvc2VzdFVuYW5zd2VyZWRNYXJrZXJBcnJvdyApIHtcbiAgICAgICAgICAgICAgICAgICAgdm0ubWFwRGF0YS5jbG9zZXN0VW5hbnN3ZXJlZE1hcmtlckFycm93LnNldE1hcChudWxsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoICF2bS5tYXBEYXRhLmNsb3Nlc3RVbmFuc3dlcmVkTWFya2VyQXJyb3cgKSB7XG4gICAgICAgICAgICAgICAgdm0ubWFwRGF0YS5jbG9zZXN0VW5hbnN3ZXJlZE1hcmtlckFycm93ID0gbmV3IGdvb2dsZS5tYXBzLlBvbHlsaW5lKHtcbiAgICAgICAgICAgICAgICAgICAgcGF0aDogW1xuICAgICAgICAgICAgICAgICAgICAgICAgdm0ubWFwRGF0YS5wbGF5ZXJNYXJrZXIuZ2V0UG9zaXRpb24oKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlci5nZXRQb3NpdGlvbigpXG4gICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZUNvbG9yOiAncmVkJyxcbiAgICAgICAgICAgICAgICAgICAgc3Ryb2tlV2VpZ2h0OiAyLFxuICAgICAgICAgICAgICAgICAgICBzdHJva2VPcGFjaXR5OiAwLjQsXG4gICAgICAgICAgICAgICAgICAgIGljb25zOiBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgaWNvbjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGg6IGdvb2dsZS5tYXBzLlN5bWJvbFBhdGguRk9SV0FSRF9DTE9TRURfQVJST1csXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbENvbG9yOiAncmVkJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2VDb2xvcjogJ3JlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbE9wYWNpdHk6IDAuOCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2VPcGFjaXR5OiAwLjgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGU6IDRcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQ6ICc1MHB4JyxcbiAgICAgICAgICAgICAgICAgICAgfV0sXG4gICAgICAgICAgICAgICAgICAgIGdlb2Rlc2ljOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBtYXA6IHZtLm1hcERhdGEubWFwLFxuICAgICAgICAgICAgICAgICAgICB6SW5kZXg6IDJcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdm0ubWFwRGF0YS5jbG9zZXN0VW5hbnN3ZXJlZE1hcmtlckFycm93LnNldFBhdGgoW1xuICAgICAgICAgICAgICAgICAgICB2bS5tYXBEYXRhLnBsYXllck1hcmtlci5nZXRQb3NpdGlvbigpLFxuICAgICAgICAgICAgICAgICAgICBtYXJrZXIuZ2V0UG9zaXRpb24oKVxuICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIHJlc291cmNlcy9hc3NldHMvanMvY29tcG9uZW50cy9HYW1lTWFwLnZ1ZSJdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7O0FBV0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBQUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0="); /***/ }, /* 4 */ diff --git a/resources/assets/js/components/GameMap.vue b/resources/assets/js/components/GameMap.vue index 5d3b8fd..943964d 100644 --- a/resources/assets/js/components/GameMap.vue +++ b/resources/assets/js/components/GameMap.vue @@ -152,6 +152,7 @@ if ( map.szTrackingEnabled === true ) { map.panTo(playerMarker.getPosition()); } + _this.initUpdateClosestUnansweredMarkerArrow(); if ( _this.hasProximityCheck() ) { // TODO Might make sense to cancel in case location // does change rpidly @@ -206,6 +207,8 @@ if ( connectMarkers ) { _this.connectMarkers(); } + + _this.initUpdateClosestUnansweredMarkerArrow(); } this.$nextTick(() => { @@ -319,6 +322,8 @@ return question.id; }); + this.initUpdateClosestUnansweredMarkerArrow(); + if ( _.intersection(questionIds, answerIds).length === questionIds.length ) { this.game.complete = true; @@ -431,6 +436,61 @@ }); return _.size(answered); + }, + getClosestUnansweredMarker() { + var vm = this, + unansweredMarkers = _.filter(this.mapData.markers, marker => { return !vm.isAnswered(marker.questionId); }), + playerMarker = this.mapData.playerMarker; + + if ( unansweredMarkers.length > 0 ) { + return _.minBy(unansweredMarkers, marker => { + return google.maps.geometry.spherical.computeDistanceBetween(playerMarker.getPosition(), marker.getPosition()); + }); + } + + return null; + }, + initUpdateClosestUnansweredMarkerArrow() { + var vm = this, + marker = vm.getClosestUnansweredMarker(); + + if ( !marker ) { + if ( vm.mapData.closestUnansweredMarkerArrow ) { + vm.mapData.closestUnansweredMarkerArrow.setMap(null); + } + return; + } + + if ( !vm.mapData.closestUnansweredMarkerArrow ) { + vm.mapData.closestUnansweredMarkerArrow = new google.maps.Polyline({ + path: [ + vm.mapData.playerMarker.getPosition(), + marker.getPosition() + ], + strokeColor: 'red', + strokeWeight: 2, + strokeOpacity: 0.4, + icons: [{ + icon: { + path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW, + fillColor: 'red', + strokeColor: 'red', + fillOpacity: 0.8, + strokeOpacity: 0.8, + scale: 4 + }, + offset: '50px', + }], + geodesic: true, + map: vm.mapData.map, + zIndex: 2 + }); + } else { + vm.mapData.closestUnansweredMarkerArrow.setPath([ + vm.mapData.playerMarker.getPosition(), + marker.getPosition() + ]); + } } } }