991 lines
37 KiB
JavaScript
991 lines
37 KiB
JavaScript
'use strict';
|
|
|
|
const GameType = Object.freeze({'SINGLE': 0, 'MULTI': 1, 'CHALLENGE': 2});
|
|
|
|
(function () {
|
|
var Game = {
|
|
NUMBER_OF_ROUNDS: 5,
|
|
MAX_SCORE: 1000,
|
|
|
|
type: GameType.SINGLE,
|
|
mapBounds: null,
|
|
multi: { token: null, owner: false },
|
|
rounds: [],
|
|
scoreSum: 0,
|
|
panoId: null,
|
|
pov: null,
|
|
panorama: null,
|
|
map: null,
|
|
guessMarker: null,
|
|
adaptGuess: false,
|
|
googleLink: null,
|
|
|
|
readyToContinue: true,
|
|
timeoutEnd: null,
|
|
countdownHandler: null,
|
|
|
|
MultiConnector: {
|
|
connection: null,
|
|
reconnectCounter: 0,
|
|
|
|
connect: function () {
|
|
if (Game.MultiConnector.connection && Game.MultiConnector.connection.readyState !== WebSocket.CLOSED) {
|
|
return;
|
|
}
|
|
|
|
Game.MultiConnector.connection = new WebSocket((MapGuesser.isSecure ? 'wss' : 'ws') + '://' + multiUrl);
|
|
|
|
Game.MultiConnector.connection.onopen = function () {
|
|
document.getElementById('loading').style.visibility = 'hidden';
|
|
Game.MultiConnector.reconnectCounter = 0;
|
|
Game.MultiConnector.connection.send(JSON.stringify({ func: 'connect_to_room', args: { roomId: roomId, token: Game.multi.token } }));
|
|
};
|
|
|
|
Game.MultiConnector.connection.onclose = Game.MultiConnector.noConnection;
|
|
|
|
Game.MultiConnector.connection.onerror = function (event) {
|
|
console.error('WebSocket error in Game.MultiConnector:', event);
|
|
};
|
|
|
|
Game.MultiConnector.connection.onmessage = function (message) {
|
|
var json;
|
|
|
|
try {
|
|
json = JSON.parse(message.data);
|
|
} catch (e) {
|
|
console.error('Cannot parse message!');
|
|
console.error(message.data);
|
|
return;
|
|
}
|
|
|
|
switch (json.type) {
|
|
case 'initialize':
|
|
Game.MultiConnector.initialize(json.data);
|
|
break;
|
|
|
|
case 'member_joined':
|
|
Game.MultiConnector.memberJoined(json.data);
|
|
break;
|
|
|
|
case 'new_round':
|
|
Game.MultiConnector.newRound(json.data);
|
|
break;
|
|
|
|
case 'guess':
|
|
Game.MultiConnector.guess(json.data);
|
|
break;
|
|
|
|
case 'timeout_changed':
|
|
Game.MultiConnector.timeoutChanged(json.data);
|
|
break;
|
|
|
|
case 'end_round':
|
|
Game.MultiConnector.endRound(json.data);
|
|
break;
|
|
}
|
|
};
|
|
},
|
|
|
|
noConnection: function () {
|
|
if (Game.MultiConnector.reconnectCounter === 2) {
|
|
console.error('Could not reconnect WebSocket for Game.MultiConnector...')
|
|
}
|
|
|
|
setTimeout(function () {
|
|
Game.MultiConnector.reconnectCounter++;
|
|
|
|
console.log('Reconnecting WebSocket for Game.MultiConnector... ' + Game.MultiConnector.reconnectCounter);
|
|
Game.MultiConnector.connect();
|
|
}, 1000 + Math.min(Game.MultiConnector.reconnectCounter * 500, 9000));
|
|
},
|
|
|
|
initialize: function (data) {
|
|
Game.readyToContinue = false;
|
|
|
|
if (data.history.length === 0 && !data.place) {
|
|
var div = document.getElementById('players');
|
|
|
|
for (var i = 0; i < data.members.length; ++i) {
|
|
var member = data.members[i];
|
|
|
|
var p = document.createElement('p');
|
|
p.innerHTML = member.userName + (member.me ? ' (me)' : '');
|
|
div.appendChild(p);
|
|
}
|
|
}
|
|
|
|
for (var i = 0; i < data.history.length; ++i) {
|
|
var round = data.history[i];
|
|
Game.rounds.push({ position: round.position, guessPosition: round.result.guessPosition, realMarker: null, guessMarkers: [] });
|
|
Game.addPositionToResultMap(true);
|
|
if (round.result.guessPosition) {
|
|
Game.addGuessPositionToResultMap(round.result.guessPosition, null, true);
|
|
}
|
|
Game.scoreSum += round.result.score;
|
|
|
|
for (var j = 0; j < round.allResults.length; ++j) {
|
|
var result = round.allResults[j];
|
|
if (result.guessPosition) {
|
|
Game.addGuessPositionToResultMap(result.guessPosition, result, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
document.getElementById('currentRound').innerHTML = String(Game.rounds.length) + '/' + String(Game.NUMBER_OF_ROUNDS);
|
|
document.getElementById('currentScoreSum').innerHTML = String(Game.scoreSum) + '/' + String(Game.rounds.length * Game.MAX_SCORE);
|
|
|
|
if (data.timeout) {
|
|
Game.startCountdown(data.timeout);
|
|
}
|
|
|
|
if (data.place) {
|
|
Game.readyToContinue = data.readyToContinue;
|
|
Game.panoId = data.place.panoId;
|
|
Game.pov = data.place.pov;
|
|
|
|
document.getElementById('multi').style.visibility = 'hidden';
|
|
|
|
if (Game.rounds.length === 0 || !Game.rounds[Game.rounds.length - 1].position) {
|
|
document.getElementById('panoCover').style.visibility = 'hidden';
|
|
Game.startNewRound();
|
|
} else {
|
|
Game.loadPano(Game.panoId, Game.pov);
|
|
Game.showResultFromHistory(data.history[data.history.length - 1].result);
|
|
}
|
|
}
|
|
|
|
document.getElementById('loading').style.visibility = 'hidden';
|
|
},
|
|
|
|
memberJoined: function (data) {
|
|
var div = document.getElementById('players');
|
|
|
|
var p = document.createElement('p');
|
|
p.innerHTML = data.userName;
|
|
div.appendChild(p);
|
|
},
|
|
|
|
newRound: function (data) {
|
|
if (Game.rounds.length === Game.NUMBER_OF_ROUNDS) {
|
|
Game.reset();
|
|
}
|
|
|
|
Game.readyToContinue = false;
|
|
Game.panoId = data.place.panoId;
|
|
Game.pov = data.place.pov;
|
|
|
|
document.getElementById('multi').style.visibility = 'hidden';
|
|
Game.resetRound();
|
|
Game.startNewRound();
|
|
|
|
Game.startCountdown(data.timeout);
|
|
},
|
|
|
|
guess: function (data) {
|
|
var resultBounds = Game.map.getBounds();
|
|
|
|
Game.addGuessPositionToResultMap(data.guessPosition, data);
|
|
resultBounds.extend(data.guessPosition);
|
|
|
|
Game.map.fitBounds(resultBounds);
|
|
},
|
|
|
|
timeoutChanged: function (data) {
|
|
Game.startCountdown(data.timeout);
|
|
},
|
|
|
|
endRound: function (data) {
|
|
Game.readyToContinue = true;
|
|
Game.startCountdown(0);
|
|
|
|
if (Game.rounds[Game.rounds.length - 1].guessPosition || Game.rounds[Game.rounds.length - 1].position) {
|
|
if (Game.multi.owner) {
|
|
document.getElementById('continueButton').disabled = false;
|
|
document.getElementById('startNewGameButton').disabled = false;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
document.getElementById('guessButton').disabled = true;
|
|
document.getElementById('panoCover').style.visibility = 'visible';
|
|
|
|
Game.receiveResult(data.position, data.result.guessPosition, { distance: data.result.distance, score: data.result.score }, data.allResults);
|
|
}
|
|
},
|
|
|
|
getGameIdentifier: function() {
|
|
switch(Game.type) {
|
|
case GameType.SINGLE:
|
|
return '/game/' + mapId;
|
|
case GameType.MULTI:
|
|
return '/multiGame/' + roomId;
|
|
case GameType.CHALLENGE:
|
|
return '/challenge/' + challengeToken;
|
|
default:
|
|
return '/game/' + mapId;
|
|
}
|
|
},
|
|
|
|
prepare: function () {
|
|
var data = new FormData();
|
|
var userNames;
|
|
|
|
if (roomId) {
|
|
var userNames = localStorage.userNames ? JSON.parse(localStorage.userNames) : {};
|
|
if (!userNames.hasOwnProperty(roomId)) {
|
|
userNames[roomId] = prompt('Your name: ');
|
|
localStorage.userNames = JSON.stringify(userNames);
|
|
}
|
|
|
|
data.append('userName', userNames[roomId]);
|
|
}
|
|
|
|
document.getElementById('loading').style.visibility = 'visible';
|
|
var url = Game.getGameIdentifier() + '/prepare.json';
|
|
MapGuesser.httpRequest('POST', url, function () {
|
|
document.getElementById('loading').style.visibility = 'hidden';
|
|
|
|
if (this.response.error) {
|
|
Game.handleErrorResponse(this.response.error);
|
|
return;
|
|
}
|
|
|
|
document.getElementById('mapName').innerHTML = this.response.mapName;
|
|
Game.mapBounds = this.response.bounds;
|
|
|
|
Game.initialize();
|
|
|
|
if (roomId) {
|
|
Game.multi.token = this.response.token;
|
|
Game.multi.owner = this.response.owner;
|
|
|
|
document.getElementById('multi').style.visibility = 'visible';
|
|
if (Game.multi.owner) {
|
|
document.getElementById('startMultiGameButton').style.display = 'block';
|
|
}
|
|
|
|
document.getElementById('loading').style.visibility = 'visible';
|
|
Game.MultiConnector.connect();
|
|
}
|
|
}, data);
|
|
},
|
|
|
|
initialize: function () {
|
|
document.getElementById('panoCover').style.visibility = 'visible';
|
|
|
|
Game.map.setOptions({
|
|
draggableCursor: 'crosshair'
|
|
});
|
|
Game.map.fitBounds(Game.mapBounds);
|
|
|
|
if (roomId) {
|
|
// if it is multiplayer mode, data is sent via WS
|
|
return;
|
|
}
|
|
|
|
document.getElementById('loading').style.visibility = 'visible';
|
|
MapGuesser.httpRequest('POST', Game.getGameIdentifier() + '/initialData.json', function () {
|
|
document.getElementById('loading').style.visibility = 'hidden';
|
|
document.getElementById('panoCover').style.visibility = 'hidden';
|
|
|
|
if (this.response.error) {
|
|
Game.handleErrorResponse(this.response.error);
|
|
return;
|
|
}
|
|
|
|
Game.panoId = this.response.place.panoId;
|
|
Game.pov = this.response.place.pov;
|
|
|
|
for (var i = 0; i < this.response.history.length; ++i) {
|
|
var round = this.response.history[i];
|
|
Game.rounds.push({ position: round.position, guessPosition: round.result.guessPosition, realMarker: null, guessMarkers: [] });
|
|
Game.addPositionToResultMap(true);
|
|
Game.addGuessPositionToResultMap(round.result.guessPosition, null, true);
|
|
Game.scoreSum += round.result.score;
|
|
}
|
|
|
|
document.getElementById('currentRound').innerHTML = String(Game.rounds.length) + '/' + String(Game.NUMBER_OF_ROUNDS);
|
|
document.getElementById('currentScoreSum').innerHTML = String(Game.scoreSum) + '/' + String(Game.rounds.length * Game.MAX_SCORE);
|
|
|
|
Game.startNewRound();
|
|
});
|
|
},
|
|
|
|
reset: function () {
|
|
if (Game.guessMarker) {
|
|
Game.guessMarker.setMap(null);
|
|
Game.guessMarker = null;
|
|
}
|
|
|
|
for (var i = 0; i < Game.rounds.length; ++i) {
|
|
var round = Game.rounds[i];
|
|
|
|
if (round.realMarker) {
|
|
round.realMarker.setMap(null);
|
|
}
|
|
for (var j = 0; j < round.guessMarkers.length; ++j) {
|
|
var guessMarker = round.guessMarkers[j];
|
|
guessMarker.marker.setMap(null);
|
|
guessMarker.line.setMap(null);
|
|
if (guessMarker.info) {
|
|
guessMarker.info.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
Game.rounds = [];
|
|
Game.scoreSum = 0;
|
|
|
|
var distanceInfo = document.getElementById('distanceInfo');
|
|
distanceInfo.children[0].style.display = null;
|
|
distanceInfo.children[1].style.display = null;
|
|
distanceInfo.children[2].style.display = null;
|
|
var scoreInfo = document.getElementById('scoreInfo');
|
|
scoreInfo.children[0].style.display = null;
|
|
scoreInfo.children[1].style.display = null;
|
|
document.getElementById('continueButton').style.display = null;
|
|
document.getElementById('showSummaryButton').style.display = null;
|
|
document.getElementById('startNewGameButton').style.display = null;
|
|
|
|
document.getElementById('showGuessButton').style.visibility = null;
|
|
document.getElementById('guess').style.visibility = null;
|
|
document.getElementById('guess').classList.remove('result');
|
|
|
|
// needs to be set visible after the show guess map hid it in mobile view
|
|
document.getElementById("navigation").style.visibility = 'visible';
|
|
|
|
Game.initialize();
|
|
},
|
|
|
|
resetRound: function () {
|
|
document.getElementById('scoreBar').style.width = null;
|
|
|
|
if (Game.rounds.length > 0) {
|
|
var lastRound = Game.rounds[Game.rounds.length - 1];
|
|
|
|
lastRound.realMarker.setVisible(false);
|
|
for (var i = 0; i < lastRound.guessMarkers.length; ++i) {
|
|
var guessMarker = lastRound.guessMarkers[i];
|
|
guessMarker.marker.setVisible(false);
|
|
guessMarker.line.setVisible(false);
|
|
if (guessMarker.info) {
|
|
guessMarker.info.close();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
document.getElementById('panoCover').style.visibility = 'hidden';
|
|
document.getElementById('showGuessButton').style.visibility = null;
|
|
document.getElementById('guess').style.visibility = null;
|
|
document.getElementById('guess').classList.remove('result');
|
|
|
|
// needs to be set visible after the show guess map hid it in mobile view
|
|
document.getElementById("navigation").style.visibility = 'visible';
|
|
|
|
Game.map.setOptions({
|
|
draggableCursor: 'crosshair'
|
|
});
|
|
Game.map.fitBounds(Game.mapBounds);
|
|
|
|
if (roomId) {
|
|
// if it is multiplayer mode, data is sent via WS
|
|
return;
|
|
}
|
|
|
|
Game.startNewRound();
|
|
},
|
|
|
|
startNewRound: function () {
|
|
Game.rounds.push({ position: null, guessPosition: null, realMarker: null, guessMarkers: [] });
|
|
|
|
document.getElementById('currentRound').innerHTML = String(Game.rounds.length) + '/' + String(Game.NUMBER_OF_ROUNDS);
|
|
|
|
Game.loadPano(Game.panoId, Game.pov);
|
|
|
|
// update the compass
|
|
const heading = Game.panorama.getPov().heading;
|
|
document.getElementById("compass").style.transform = "translateY(-50%) rotate(" + heading + "deg)";
|
|
},
|
|
|
|
handleErrorResponse: function (error) {
|
|
switch (error) {
|
|
case 'no_session_found':
|
|
MapGuesser.showModalWithContent('Error', 'Your session is invalid!', [{
|
|
type: 'button',
|
|
classNames: [],
|
|
text: 'Restart game',
|
|
onclick: function () {
|
|
window.location.reload();
|
|
}
|
|
}]);
|
|
break;
|
|
|
|
case 'game_already_started':
|
|
MapGuesser.showModalWithContent('Error', 'This game is already started, you cannot join.');
|
|
break;
|
|
|
|
case 'game_not_found':
|
|
MapGuesser.showModalWithContent('Error', 'The game room was not found by this ID. Please check the link.');
|
|
break;
|
|
|
|
default:
|
|
MapGuesser.showModalWithContent('Error', 'Error code: \'' + error + '\'');
|
|
break
|
|
}
|
|
},
|
|
|
|
loadPano: function (panoId, pov) {
|
|
if (Game.adaptGuess) {
|
|
document.getElementById('guess').classList.add('adapt');
|
|
}
|
|
|
|
Game.panorama.setPov({ heading: pov.heading, pitch: pov.pitch });
|
|
Game.panorama.setZoom(pov.zoom);
|
|
Game.panorama.setPano(panoId);
|
|
},
|
|
|
|
receiveResult: function (position, guessPosition, result, allResults) {
|
|
Game.scoreSum += result.score;
|
|
document.getElementById('currentScoreSum').innerHTML = String(Game.scoreSum) + '/' + String(Game.rounds.length * Game.MAX_SCORE);
|
|
|
|
var resultBounds = new google.maps.LatLngBounds();
|
|
|
|
Game.rounds[Game.rounds.length - 1].position = position;
|
|
Game.addPositionToResultMap();
|
|
resultBounds.extend(position);
|
|
|
|
if (guessPosition) {
|
|
Game.addGuessPositionToResultMap(guessPosition);
|
|
resultBounds.extend(guessPosition);
|
|
}
|
|
|
|
if (allResults) {
|
|
for (var i = 0; i < allResults.length; ++i) {
|
|
var currentResult = allResults[i];
|
|
if (currentResult.guessPosition) {
|
|
Game.addGuessPositionToResultMap(currentResult.guessPosition, currentResult);
|
|
resultBounds.extend(currentResult.guessPosition);
|
|
}
|
|
}
|
|
}
|
|
|
|
Game.showResultMap(result, resultBounds);
|
|
},
|
|
|
|
showResultFromHistory: function (result) {
|
|
var round = Game.rounds[Game.rounds.length - 1];
|
|
var resultBounds = new google.maps.LatLngBounds();
|
|
|
|
round.realMarker.setVisible(true);
|
|
resultBounds.extend(round.position);
|
|
|
|
for (var j = 0; j < round.guessMarkers.length; ++j) {
|
|
var guessMarker = round.guessMarkers[j];
|
|
guessMarker.marker.setVisible(true);
|
|
guessMarker.line.setVisible(true);
|
|
|
|
resultBounds.extend(guessMarker.marker.getPosition());
|
|
}
|
|
|
|
Game.showResultMap(result, resultBounds);
|
|
},
|
|
|
|
showResultMap: function (result, resultBounds) {
|
|
// TODO: refactor - it is necessary for mobile
|
|
if (window.getComputedStyle(document.getElementById('guess')).visibility === 'hidden') {
|
|
document.getElementById('showGuessButton').click();
|
|
}
|
|
|
|
if (Game.adaptGuess) {
|
|
document.getElementById('guess').classList.remove('adapt');
|
|
}
|
|
|
|
if (Game.guessMarker) {
|
|
Game.guessMarker.setMap(null);
|
|
Game.guessMarker = null;
|
|
}
|
|
|
|
document.getElementById('guess').classList.add('result');
|
|
|
|
Game.map.setOptions({
|
|
draggableCursor: 'grab'
|
|
});
|
|
Game.map.fitBounds(resultBounds);
|
|
|
|
var distanceInfo = document.getElementById('distanceInfo');
|
|
if (result.distance === null) {
|
|
distanceInfo.children[0].style.display = 'none';
|
|
distanceInfo.children[1].style.display = 'block';
|
|
} else {
|
|
distanceInfo.children[0].style.display = 'block';
|
|
distanceInfo.children[1].style.display = 'none';
|
|
document.getElementById('distance').innerHTML = Util.printDistanceForHuman(result.distance);
|
|
}
|
|
|
|
document.getElementById('score').innerHTML = result.score;
|
|
|
|
var scoreBarProperties = Game.calculateScoreBarProperties(result.score, Game.MAX_SCORE);
|
|
var scoreBar = document.getElementById('scoreBar');
|
|
scoreBar.style.backgroundColor = scoreBarProperties.backgroundColor;
|
|
scoreBar.style.width = scoreBarProperties.width;
|
|
|
|
if (Game.rounds.length === Game.NUMBER_OF_ROUNDS) {
|
|
document.getElementById('continueButton').style.display = 'none';
|
|
document.getElementById('showSummaryButton').style.display = 'block';
|
|
} else if (roomId) {
|
|
if (Game.multi.owner) {
|
|
if (!Game.readyToContinue) {
|
|
document.getElementById('continueButton').disabled = true;
|
|
}
|
|
} else {
|
|
document.getElementById('continueButton').style.display = 'none';
|
|
}
|
|
}
|
|
},
|
|
|
|
guess: function () {
|
|
if (!Game.guessMarker) {
|
|
return;
|
|
}
|
|
|
|
var guessPosition = Game.guessMarker.getPosition().toJSON();
|
|
Game.rounds[Game.rounds.length - 1].guessPosition = guessPosition;
|
|
|
|
document.getElementById('guessButton').disabled = true;
|
|
document.getElementById('panoCover').style.visibility = 'visible';
|
|
|
|
var data = new FormData();
|
|
data.append('lat', String(guessPosition.lat));
|
|
data.append('lng', String(guessPosition.lng));
|
|
|
|
document.getElementById('loading').style.visibility = 'visible';
|
|
var url = roomId ? '/multiGame/' + roomId + '/guess.json' : '/game/' + mapId + '/guess.json';
|
|
MapGuesser.httpRequest('POST', url, function () {
|
|
document.getElementById('loading').style.visibility = 'hidden';
|
|
|
|
if (this.response.error) {
|
|
Game.handleErrorResponse(this.response.error);
|
|
return;
|
|
}
|
|
|
|
Game.receiveResult(this.response.position, guessPosition, this.response.result, this.response.allResults);
|
|
|
|
if (this.response.place) {
|
|
Game.panoId = this.response.place.panoId;
|
|
Game.pov = this.response.place.pov;
|
|
}
|
|
}, data);
|
|
},
|
|
|
|
addPositionToResultMap: function (hidden) {
|
|
var round = Game.rounds[Game.rounds.length - 1];
|
|
var position = round.position;
|
|
|
|
round.realMarker = new google.maps.Marker({
|
|
map: Game.map,
|
|
visible: !hidden,
|
|
position: position,
|
|
title: 'Open in Google Maps',
|
|
zIndex: Game.rounds.length * 2,
|
|
clickable: true,
|
|
draggable: false,
|
|
icon: {
|
|
url: STATIC_ROOT + '/img/markers/marker-green.svg?rev=' + REVISION,
|
|
size: new google.maps.Size(24, 32),
|
|
scaledSize: new google.maps.Size(24, 32),
|
|
anchor: new google.maps.Point(12, 32)
|
|
},
|
|
});
|
|
|
|
round.realMarker.addListener('click', function () {
|
|
window.open('https://www.google.com/maps/search/?api=1&query=' + this.getPosition().toUrlValue(), '_blank');
|
|
});
|
|
},
|
|
|
|
addGuessPositionToResultMap: function (guessPosition, result, hidden) {
|
|
var round = Game.rounds[Game.rounds.length - 1];
|
|
var position = round.position;
|
|
|
|
var guessMarker = { marker: null, line: null, info: null };
|
|
var markerSvg = result ? 'marker-gray-empty.svg' : 'marker-blue-empty.svg';
|
|
var markerLabel = result ? result.userName.charAt(0).toUpperCase() : '?';
|
|
|
|
guessMarker.marker = new google.maps.Marker({
|
|
map: Game.map,
|
|
visible: !hidden,
|
|
position: guessPosition,
|
|
zIndex: Game.rounds.length,
|
|
clickable: !!result,
|
|
draggable: false,
|
|
icon: {
|
|
url: STATIC_ROOT + '/img/markers/' + markerSvg + '?rev=' + REVISION,
|
|
size: new google.maps.Size(24, 32),
|
|
scaledSize: new google.maps.Size(24, 32),
|
|
anchor: new google.maps.Point(12, 32),
|
|
labelOrigin: new google.maps.Point(12, 14)
|
|
},
|
|
label: {
|
|
color: '#ffffff',
|
|
fontFamily: 'Roboto',
|
|
fontSize: '16px',
|
|
fontWeight: '500',
|
|
text: markerLabel
|
|
}
|
|
});
|
|
|
|
guessMarker.line = new google.maps.Polyline({
|
|
map: Game.map,
|
|
visible: !hidden,
|
|
path: [
|
|
position,
|
|
guessPosition
|
|
],
|
|
geodesic: true,
|
|
strokeOpacity: 0,
|
|
icons: [{
|
|
icon: {
|
|
path: 'M 0,-1 0,1',
|
|
strokeOpacity: 1,
|
|
strokeWeight: 2,
|
|
scale: 2
|
|
},
|
|
offset: '0',
|
|
repeat: '10px'
|
|
}],
|
|
clickable: false,
|
|
draggable: false,
|
|
editable: false
|
|
});
|
|
|
|
if (result) {
|
|
guessMarker.info = new google.maps.InfoWindow({
|
|
content: '<p class="small bold">' + result.userName + '</p>' +
|
|
'<p class="small">' + Util.printDistanceForHuman(result.distance) + ' | ' + result.score + ' points</p>',
|
|
});
|
|
|
|
guessMarker.marker.addListener('click', function () {
|
|
guessMarker.info.open(Game.map, this);
|
|
});
|
|
}
|
|
|
|
round.guessMarkers.push(guessMarker);
|
|
},
|
|
|
|
calculateScoreBarProperties: function (score, maxScore) {
|
|
var percent = Math.floor((score / maxScore) * 100);
|
|
|
|
var color;
|
|
if (percent >= 90) {
|
|
color = '#11ca00';
|
|
} else if (percent >= 10) {
|
|
color = '#ea9000';
|
|
} else {
|
|
color = '#ca1100';
|
|
}
|
|
|
|
return { width: percent + '%', backgroundColor: color };
|
|
},
|
|
|
|
showSummary: function () {
|
|
var distanceInfo = document.getElementById('distanceInfo');
|
|
distanceInfo.children[0].style.display = 'none';
|
|
distanceInfo.children[1].style.display = 'none';
|
|
distanceInfo.children[2].style.display = 'block';
|
|
var scoreInfo = document.getElementById('scoreInfo');
|
|
scoreInfo.children[0].style.display = 'none';
|
|
scoreInfo.children[1].style.display = 'block';
|
|
document.getElementById('showSummaryButton').style.display = null;
|
|
|
|
if (!roomId || Game.multi.owner) {
|
|
document.getElementById('startNewGameButton').style.display = 'block';
|
|
if (!Game.readyToContinue) {
|
|
document.getElementById('startNewGameButton').disabled = true;
|
|
}
|
|
}
|
|
|
|
var resultBounds = new google.maps.LatLngBounds();
|
|
|
|
for (var i = 0; i < Game.rounds.length; ++i) {
|
|
var round = Game.rounds[i];
|
|
|
|
round.realMarker.setIcon({
|
|
url: STATIC_ROOT + '/img/markers/marker-green-empty.svg?rev=' + REVISION,
|
|
size: new google.maps.Size(24, 32),
|
|
scaledSize: new google.maps.Size(24, 32),
|
|
anchor: new google.maps.Point(12, 32),
|
|
labelOrigin: new google.maps.Point(12, 14)
|
|
});
|
|
round.realMarker.setLabel({
|
|
color: '#285624',
|
|
fontFamily: 'Roboto',
|
|
fontSize: '16px',
|
|
fontWeight: '500',
|
|
text: String(i + 1)
|
|
});
|
|
|
|
round.realMarker.setVisible(true);
|
|
resultBounds.extend(round.position);
|
|
|
|
for (var j = 0; j < round.guessMarkers.length; ++j) {
|
|
var guessMarker = round.guessMarkers[j];
|
|
guessMarker.marker.setVisible(true);
|
|
guessMarker.line.setVisible(true);
|
|
|
|
resultBounds.extend(guessMarker.marker.getPosition());
|
|
}
|
|
}
|
|
|
|
Game.map.fitBounds(resultBounds);
|
|
|
|
document.getElementById('scoreSum').innerHTML = String(Game.scoreSum);
|
|
|
|
var scoreBarProperties = Game.calculateScoreBarProperties(Game.scoreSum, Game.NUMBER_OF_ROUNDS * Game.MAX_SCORE);
|
|
var scoreBar = document.getElementById('scoreBar');
|
|
scoreBar.style.backgroundColor = scoreBarProperties.backgroundColor;
|
|
scoreBar.style.width = scoreBarProperties.width;
|
|
},
|
|
|
|
rewriteGoogleLink: function () {
|
|
if (!Game.googleLink) {
|
|
var anchors = document.getElementById('panorama').getElementsByTagName('a');
|
|
for (var i = 0; i < anchors.length; i++) {
|
|
var a = anchors[i];
|
|
if (a.href.indexOf('maps.google.com/maps') !== -1) {
|
|
Game.googleLink = a;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
setTimeout(function () {
|
|
if (Game.googleLink) {
|
|
Game.googleLink.title = 'Google Maps';
|
|
Game.googleLink.href = 'https://maps.google.com/maps';
|
|
}
|
|
}, 1);
|
|
},
|
|
|
|
startCountdown: function (timeout) {
|
|
if (Game.countdownHandler) {
|
|
clearInterval(Game.countdownHandler);
|
|
}
|
|
|
|
Game.countdownElement = document.getElementById('countdown');
|
|
Game.countdownTimeElement = document.getElementById('countdownTime');
|
|
|
|
Game.setCountdownTime(Math.round(timeout / 1000));
|
|
|
|
if (timeout <= 0) {
|
|
return;
|
|
}
|
|
|
|
Game.timeoutEnd = new Date(new Date().getTime() + timeout);
|
|
|
|
Game.countdownHandler = setInterval(function () {
|
|
var timeLeft = Math.round((Game.timeoutEnd - new Date()) / 1000);
|
|
|
|
Game.setCountdownTime(timeLeft);
|
|
|
|
if (timeLeft <= 0) {
|
|
document.getElementById('panoCover').style.visibility = 'visible';
|
|
clearInterval(Game.countdownHandler);
|
|
}
|
|
}, 1000);
|
|
},
|
|
|
|
setCountdownTime: function (time) {
|
|
if (time <= 0) {
|
|
Game.countdownElement.style.visibility = 'hidden';
|
|
return;
|
|
}
|
|
|
|
if (time <= 15) {
|
|
Game.countdownElement.className = 'red';
|
|
} else if (time <= 30) {
|
|
Game.countdownElement.className = 'yellow';
|
|
} else {
|
|
Game.countdownElement.className = '';
|
|
}
|
|
|
|
Game.countdownElement.style.visibility = 'visible';
|
|
Game.countdownTimeElement.innerHTML = time;
|
|
}
|
|
};
|
|
|
|
var Util = {
|
|
printDistanceForHuman: function (distance) {
|
|
if (distance < 1000) {
|
|
return Number.parseFloat(distance).toFixed(0) + ' m';
|
|
} else if (distance < 10000) {
|
|
return Number.parseFloat(distance / 1000).toFixed(2) + ' km';
|
|
} else if (distance < 100000) {
|
|
return Number.parseFloat(distance / 1000).toFixed(1) + ' km';
|
|
} else {
|
|
return Number.parseFloat(distance / 1000).toFixed(0) + ' km';
|
|
}
|
|
}
|
|
};
|
|
|
|
MapGuesser.sessionAvailableHooks.reinitializeGame = Game.prepare;
|
|
|
|
if (!('ontouchstart' in document.documentElement)) {
|
|
Game.adaptGuess = true;
|
|
}
|
|
|
|
Game.map = new google.maps.Map(document.getElementById('map'), {
|
|
disableDefaultUI: true,
|
|
clickableIcons: false,
|
|
draggingCursor: 'grabbing'
|
|
});
|
|
|
|
Game.map.addListener('click', function (e) {
|
|
if (Game.rounds[Game.rounds.length - 1].guessPosition || Game.rounds[Game.rounds.length - 1].position) {
|
|
return;
|
|
}
|
|
|
|
if (Game.guessMarker) {
|
|
Game.guessMarker.setPosition(e.latLng);
|
|
return;
|
|
}
|
|
|
|
Game.guessMarker = new google.maps.Marker({
|
|
map: Game.map,
|
|
position: e.latLng,
|
|
clickable: false,
|
|
draggable: true,
|
|
icon: {
|
|
url: STATIC_ROOT + '/img/markers/marker-blue-empty.svg?rev=' + REVISION,
|
|
size: new google.maps.Size(24, 32),
|
|
scaledSize: new google.maps.Size(24, 32),
|
|
anchor: new google.maps.Point(12, 32),
|
|
labelOrigin: new google.maps.Point(12, 14)
|
|
},
|
|
label: {
|
|
color: '#ffffff',
|
|
fontFamily: 'Roboto',
|
|
fontSize: '16px',
|
|
fontWeight: '500',
|
|
text: '?'
|
|
}
|
|
});
|
|
|
|
document.getElementById('guessButton').disabled = false;
|
|
});
|
|
|
|
Game.panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), {
|
|
disableDefaultUI: true,
|
|
linksControl: true,
|
|
showRoadLabels: false,
|
|
motionTracking: false
|
|
});
|
|
|
|
Game.panorama.addListener('position_changed', function () {
|
|
Game.rewriteGoogleLink();
|
|
});
|
|
|
|
Game.panorama.addListener('pov_changed', function () {
|
|
Game.rewriteGoogleLink();
|
|
|
|
const heading = Game.panorama.getPov().heading;
|
|
document.getElementById("compass").style.transform = "translateY(-50%) rotate(" + heading + "deg)";
|
|
});
|
|
|
|
if(roomId !== null) {
|
|
Game.type = GameType.MULTI;
|
|
} else if(challengeToken !== null) {
|
|
Game.type = GameType.CHALLENGE;
|
|
}
|
|
|
|
if (COOKIES_CONSENT) {
|
|
Game.prepare();
|
|
}
|
|
|
|
document.getElementById('showGuessButton').onclick = function () {
|
|
this.style.visibility = 'hidden';
|
|
document.getElementById('guess').style.visibility = 'visible';
|
|
document.getElementById('navigation').style.visibility = 'hidden';
|
|
}
|
|
|
|
document.getElementById('closeGuessButton').onclick = function () {
|
|
document.getElementById('showGuessButton').style.visibility = null;
|
|
document.getElementById('guess').style.visibility = null;
|
|
document.getElementById('navigation').style.visibility = 'visible';
|
|
}
|
|
|
|
document.getElementById('guessButton').onclick = function () {
|
|
Game.guess();
|
|
}
|
|
|
|
document.getElementById('continueButton').onclick = function () {
|
|
if (roomId) {
|
|
if (!Game.multi.owner || !Game.readyToContinue) {
|
|
return;
|
|
}
|
|
|
|
document.getElementById('loading').style.visibility = 'visible';
|
|
MapGuesser.httpRequest('POST', '/multiGame/' + roomId + '/nextRound.json', function () {
|
|
document.getElementById('loading').style.visibility = 'hidden';
|
|
|
|
if (this.response.error) {
|
|
Game.handleErrorResponse(this.response.error);
|
|
return;
|
|
}
|
|
});
|
|
} else {
|
|
Game.resetRound();
|
|
}
|
|
}
|
|
|
|
document.getElementById('showSummaryButton').onclick = function () {
|
|
Game.showSummary();
|
|
}
|
|
|
|
document.getElementById('startNewGameButton').onclick = function () {
|
|
if (roomId) {
|
|
if (!Game.multi.owner) {
|
|
return;
|
|
}
|
|
|
|
document.getElementById('loading').style.visibility = 'visible';
|
|
MapGuesser.httpRequest('POST', '/multiGame/' + roomId + '/initialData.json', function () {
|
|
document.getElementById('loading').style.visibility = 'hidden';
|
|
|
|
if (this.response.error) {
|
|
Game.handleErrorResponse(this.response.error);
|
|
return;
|
|
}
|
|
});
|
|
} else {
|
|
Game.reset();
|
|
}
|
|
}
|
|
|
|
document.getElementById('startMultiGameButton').onclick = function () {
|
|
if (!roomId || !Game.multi.owner) {
|
|
return;
|
|
}
|
|
|
|
document.getElementById('multi').style.visibility = 'hidden';
|
|
|
|
document.getElementById('loading').style.visibility = 'visible';
|
|
MapGuesser.httpRequest('POST', '/multiGame/' + roomId + '/initialData.json', function () {
|
|
document.getElementById('loading').style.visibility = 'hidden';
|
|
|
|
if (this.response.error) {
|
|
Game.handleErrorResponse(this.response.error);
|
|
return;
|
|
}
|
|
});
|
|
}
|
|
|
|
document.getElementById('returnToStart').onclick = function () {
|
|
Game.loadPano(Game.panoId, Game.pov);
|
|
}
|
|
|
|
document.getElementById('compassContainer').onclick = function () {
|
|
Game.panorama.setPov({ heading: 0, pitch: Game.panorama.getPov().pitch });
|
|
}
|
|
})();
|