Compare commits
69
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19a1b79b0a | ||
|
|
d432a5b584 | ||
|
|
8b9345eb36 | ||
|
|
e1eb0077b1 | ||
|
|
745bda11c0 | ||
|
|
0bb31cbe14 | ||
|
|
ef8ad69506 | ||
|
|
3d663fb5d6 | ||
|
|
759f654a0d | ||
|
|
c09cce3c97 | ||
|
|
276e331a47
|
||
|
|
62f4fd7b84 | ||
|
|
8f0cfd4489 | ||
|
|
3122696364 | ||
|
|
462f6cde80 | ||
|
|
3f4fa83d87 | ||
|
|
f0b0de405c | ||
|
|
ffc4aaf110 | ||
|
|
58cdc1be8d | ||
|
|
4039202268
|
||
|
|
4677cc5229 | ||
|
|
8800724aa9
|
||
|
|
3d52c967b6 | ||
|
|
5c8f3d6fb9 | ||
|
|
b9927f79fc | ||
|
|
56f3a9b380 | ||
|
|
a0d41c388b | ||
|
|
092cc63148 | ||
|
|
95553296bd | ||
|
|
9330227879 | ||
|
|
faaff33841 | ||
|
|
508a6899d8 | ||
|
|
be0f7b64b8 | ||
|
|
15e3248ee1 | ||
|
|
04a897c958 | ||
|
|
845d77ebda | ||
|
|
8bc3fda49b | ||
|
|
d78817180b | ||
|
|
0f810bd2ba | ||
|
|
9d1fc8b60c
|
||
|
|
dd46fb3d32
|
||
|
|
1a40e3a18d | ||
|
|
1aa5d3b43e
|
||
|
|
a418d5cf66 | ||
|
|
5cae286a5b
|
||
|
|
c5d2591371 | ||
|
|
cf59f937c9
|
||
|
|
257f59c96e | ||
|
|
c2f5806394
|
||
|
|
ac0b71fe09 | ||
|
|
19f7b50002
|
||
|
|
6342bb1e79
|
||
|
|
3abdb6910e
|
||
|
|
7d2588f7cd | ||
|
|
be40acdb2d
|
||
|
|
a2f2080959
|
||
|
|
cc49c56075 | ||
|
|
69329b9f81
|
||
|
|
20914b466e
|
||
|
|
3630637ec1
|
||
|
|
42224b074e
|
||
|
|
0e8ed14305
|
||
|
|
d3a12fb6f1 | ||
|
|
3f9d104adc
|
||
|
|
9e5d20796c
|
||
|
|
7433813337 | ||
|
|
42854fe975
|
||
|
|
71681f1e55 | ||
|
|
1cf0ab44fd
|
No files matched your search
+139
-62
@@ -2,13 +2,12 @@
|
|||||||
|
|
||||||
process.title = 'mapguesser-multi';
|
process.title = 'mapguesser-multi';
|
||||||
|
|
||||||
class State {
|
|
||||||
static OPEN = 1;
|
|
||||||
static PLACE_RECEIVED = 2;
|
|
||||||
static GUESS_SENT = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
class MultiGame {
|
class MultiGame {
|
||||||
|
static ROUND_TIMEOUT_DEFAULT = 120000;
|
||||||
|
static ROUND_TIMEOUT_MINIMUM = 15000;
|
||||||
|
static ROUND_TIMEOUT_DIVIDER = 1.5;
|
||||||
|
static ROUND_TIMEOUT_OFFSET = 500;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.rooms = new Map();
|
this.rooms = new Map();
|
||||||
}
|
}
|
||||||
@@ -32,24 +31,25 @@ class MultiGame {
|
|||||||
var member = room.members.get(token);
|
var member = room.members.get(token);
|
||||||
member.connection = connection;
|
member.connection = connection;
|
||||||
|
|
||||||
this._sendInitialData(room, member);
|
this._sendInitialData(room, member, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
createRoom(roomId) {
|
createRoom(roomId) {
|
||||||
this.rooms.set(roomId, { members: new Map(), rounds: [], currentRound: -1, updated: new Date() });
|
this.rooms.set(roomId, { members: new Map(), rounds: [], currentRound: -1, updated: new Date() });
|
||||||
|
|
||||||
|
return { ok: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
joinRoom(roomId, token, userName) {
|
joinRoom(roomId, token, userName) {
|
||||||
if (!this.rooms.has(roomId)) {
|
if (!this.rooms.has(roomId)) {
|
||||||
console.error('Room does not exist!')
|
return { error: 'room_not_found' };
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var room = this.rooms.get(roomId);
|
var room = this.rooms.get(roomId);
|
||||||
room.updated = new Date();
|
room.updated = new Date();
|
||||||
|
|
||||||
if (room.members.has(token)) {
|
if (room.members.has(token)) {
|
||||||
return;
|
return { error: 'member_already_joined' };
|
||||||
}
|
}
|
||||||
|
|
||||||
var data = { userName: userName };
|
var data = { userName: userName };
|
||||||
@@ -58,14 +58,14 @@ class MultiGame {
|
|||||||
self._sendToMember(member, 'member_joined', data);
|
self._sendToMember(member, 'member_joined', data);
|
||||||
});
|
});
|
||||||
|
|
||||||
room.members.set(token, { userName: userName, state: State.OPEN, connection: null });
|
room.members.set(token, { userName: userName, connection: null });
|
||||||
|
|
||||||
|
return { ok: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
startGame(roomId, places) {
|
startGame(roomId, places) {
|
||||||
if (!this.rooms.has(roomId)) {
|
if (!this.rooms.has(roomId)) {
|
||||||
//TODO: send something back
|
return { error: 'room_not_found' };
|
||||||
console.log('Room does not exist!')
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var room = this.rooms.get(roomId);
|
var room = this.rooms.get(roomId);
|
||||||
@@ -73,40 +73,50 @@ class MultiGame {
|
|||||||
|
|
||||||
var rounds = [];
|
var rounds = [];
|
||||||
places.forEach(function (place) {
|
places.forEach(function (place) {
|
||||||
rounds.push({ place: place, results: new Map() })
|
rounds.push({
|
||||||
|
place: place,
|
||||||
|
results: new Map(),
|
||||||
|
timeout: MultiGame.ROUND_TIMEOUT_DEFAULT,
|
||||||
|
timeoutStarted: null,
|
||||||
|
timeoutHandler: null
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
room.rounds = rounds;
|
room.rounds = rounds;
|
||||||
|
|
||||||
this.nextRound(roomId, 0);
|
this.nextRound(roomId, 0);
|
||||||
|
|
||||||
|
return { ok: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
guess(roomId, token, guessPosition, distance, score) {
|
guess(roomId, token, guessPosition, distance, score) {
|
||||||
if (!this.rooms.has(roomId)) {
|
if (!this.rooms.has(roomId)) {
|
||||||
//TODO: send something back
|
return { error: 'room_not_found' };
|
||||||
console.log('Room does not exist!')
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var room = this.rooms.get(roomId);
|
var room = this.rooms.get(roomId);
|
||||||
room.updated = new Date();
|
room.updated = new Date();
|
||||||
|
|
||||||
var round = room.rounds[room.currentRound];
|
var round = room.rounds[room.currentRound];
|
||||||
var member = this.rooms.get(roomId).members.get(token);
|
if (round.results.has(token)) {
|
||||||
|
return { error: 'already_guessed' };
|
||||||
|
}
|
||||||
|
|
||||||
this._sendResultsUntilNow(room, member);
|
var member = room.members.get(token);
|
||||||
|
var allResults = this._collectResultsInRound(room, round);
|
||||||
round.results.set(member.userName, { guessPosition: guessPosition, distance: distance, score: score });
|
|
||||||
member.state = State.GUESS_SENT;
|
|
||||||
|
|
||||||
this._broadcastGuess(room, member.userName, guessPosition, distance, score);
|
this._broadcastGuess(room, member.userName, guessPosition, distance, score);
|
||||||
|
|
||||||
|
round.results.set(token, { guessPosition: guessPosition, distance: distance, score: score });
|
||||||
|
|
||||||
|
this._setNewTimeout(room, round);
|
||||||
|
|
||||||
|
return { allResults: allResults };
|
||||||
}
|
}
|
||||||
|
|
||||||
nextRound(roomId, currentRound) {
|
nextRound(roomId, currentRound) {
|
||||||
if (!this.rooms.has(roomId)) {
|
if (!this.rooms.has(roomId)) {
|
||||||
//TODO: send something back
|
return { error: 'room_not_found' };
|
||||||
console.log('Room does not exist!')
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var room = this.rooms.get(roomId);
|
var room = this.rooms.get(roomId);
|
||||||
@@ -116,43 +126,100 @@ class MultiGame {
|
|||||||
|
|
||||||
var round = room.rounds[room.currentRound];
|
var round = room.rounds[room.currentRound];
|
||||||
|
|
||||||
|
round.timeoutStarted = new Date();
|
||||||
|
var self = this;
|
||||||
|
round.timeoutHandler = setTimeout(function () {
|
||||||
|
self._endRound(room, round);
|
||||||
|
}, round.timeout + MultiGame.ROUND_TIMEOUT_OFFSET);
|
||||||
|
|
||||||
var data = {};
|
var data = {};
|
||||||
data.place = { panoId: round.place.panoId, pov: round.place.pov };
|
data.place = { panoId: round.place.panoId, pov: round.place.pov };
|
||||||
|
data.timeout = round.timeout;
|
||||||
if (room.currentRound > 0) {
|
|
||||||
data.result = { position: room.rounds[room.currentRound - 1].place.position };
|
|
||||||
}
|
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
room.members.forEach(function (member) {
|
room.members.forEach(function (member) {
|
||||||
self._sendToMember(member, 'new_round', data);
|
self._sendToMember(member, 'new_round', data);
|
||||||
|
});
|
||||||
|
|
||||||
member.state = State.PLACE_RECEIVED;
|
return { ok: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
_setNewTimeout(room, round) {
|
||||||
|
clearTimeout(round.timeoutHandler);
|
||||||
|
|
||||||
|
if (room.members.size === round.results.size) {
|
||||||
|
round.timeout = 0;
|
||||||
|
round.timeoutStarted = new Date();
|
||||||
|
|
||||||
|
this._endRound(room, round);
|
||||||
|
} else {
|
||||||
|
round.timeout = round.timeout - (new Date() - round.timeoutStarted);
|
||||||
|
if (round.timeout > MultiGame.ROUND_TIMEOUT_DIVIDER * MultiGame.ROUND_TIMEOUT_MINIMUM) {
|
||||||
|
round.timeout = Math.round(round.timeout / MultiGame.ROUND_TIMEOUT_DIVIDER);
|
||||||
|
} else if (round.timeout > MultiGame.ROUND_TIMEOUT_MINIMUM) {
|
||||||
|
round.timeout = MultiGame.ROUND_TIMEOUT_MINIMUM;
|
||||||
|
}
|
||||||
|
round.timeoutStarted = new Date();
|
||||||
|
var self = this;
|
||||||
|
round.timeoutHandler = setTimeout(function () {
|
||||||
|
self._endRound(room, round);
|
||||||
|
}, round.timeout + MultiGame.ROUND_TIMEOUT_OFFSET);
|
||||||
|
|
||||||
|
this._broadcastTimeout(room, round);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_endRound(room, round) {
|
||||||
|
var allResults = this._collectResultsInRound(room, round);
|
||||||
|
var self = this;
|
||||||
|
room.members.forEach(function (member, token) {
|
||||||
|
var result = { guessPosition: null, distance: null, score: 0 };
|
||||||
|
|
||||||
|
if (round.results.has(token)) {
|
||||||
|
result = round.results.get(token);
|
||||||
|
} else {
|
||||||
|
round.results.set(token, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = { position: round.place.position, result: result, allResults: allResults };
|
||||||
|
self._sendToMember(member, 'end_round', data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_sendInitialData(room, member) {
|
_sendInitialData(room, member, token) {
|
||||||
var data = {};
|
var data = {};
|
||||||
|
|
||||||
if (room.currentRound >= 0) {
|
if (room.currentRound >= 0) {
|
||||||
data.place = room.rounds[room.currentRound].place;
|
var round = room.rounds[room.currentRound];
|
||||||
|
|
||||||
|
data.place = round.place;
|
||||||
|
data.timeout = round.timeout - (new Date() - round.timeoutStarted);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.history = [];
|
data.history = [];
|
||||||
for (var i = 0; i < room.currentRound; ++i) {
|
for (var i = 0; i <= room.currentRound; ++i) {
|
||||||
var round = room.rounds[i];
|
var round = room.rounds[i];
|
||||||
var result;
|
|
||||||
if (round.results.has(member.userName)) {
|
if (i === room.currentRound && !round.results.has(token)) {
|
||||||
result = round.results.get(member.userName);
|
continue;
|
||||||
} else {
|
|
||||||
result = { guessPosition: null, distance: null, score: 0 };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var result = { guessPosition: null, distance: null, score: 0 };
|
||||||
|
var allResults = [];
|
||||||
|
|
||||||
|
round.results.forEach(function (currentResult, currentToken) {
|
||||||
|
if (token === currentToken) {
|
||||||
|
result = currentResult;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
allResults.push({ userName: room.members.get(currentToken).userName, guessPosition: currentResult.guessPosition, distance: currentResult.distance, score: currentResult.score });
|
||||||
|
});
|
||||||
|
|
||||||
data.history.push({
|
data.history.push({
|
||||||
position: round.place.position,
|
position: round.place.position,
|
||||||
guessPosition: result.guessPosition,
|
result: result,
|
||||||
distance: result.distance,
|
allResults: allResults
|
||||||
score: result.score
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,33 +228,42 @@ class MultiGame {
|
|||||||
data.members.push({ userName: currentMember.userName, me: member === currentMember });
|
data.members.push({ userName: currentMember.userName, me: member === currentMember });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
data.readyToContinue = room.currentRound >= 0 && room.members.size === room.rounds[room.currentRound].results.size
|
||||||
|
|
||||||
this._sendToMember(member, 'initialize', data);
|
this._sendToMember(member, 'initialize', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
_sendResultsUntilNow(room, member) {
|
_collectResultsInRound(room, round) {
|
||||||
if (member.state !== State.GUESS_SENT) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var round = room.rounds[room.currentRound];
|
|
||||||
|
|
||||||
var results = [];
|
var results = [];
|
||||||
round.results.forEach(function (result, userName) {
|
round.results.forEach(function (result, token) {
|
||||||
results.push({ userName: userName, guessPosition: result.guessPosition, distance: result.distance, score: result.score });
|
results.push({
|
||||||
|
userName: room.members.get(token).userName,
|
||||||
|
guessPosition: result.guessPosition,
|
||||||
|
distance: result.distance,
|
||||||
|
score: result.score
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this._sendToMember(member, 'results', results);
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
_broadcastTimeout(room, round) {
|
||||||
|
var self = this;
|
||||||
|
room.members.forEach(function (member) {
|
||||||
|
self._sendToMember(member, 'timeout_changed', { timeout: round.timeout });
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_broadcastGuess(room, userName, guessPosition, distance, score) {
|
_broadcastGuess(room, userName, guessPosition, distance, score) {
|
||||||
var data = { userName: userName, guessPosition: guessPosition, distance: distance, score: score };
|
var data = { userName: userName, guessPosition: guessPosition, distance: distance, score: score };
|
||||||
|
var round = room.rounds[room.currentRound];
|
||||||
room.members.forEach(function (member) {
|
var self = this;
|
||||||
if (!member.state !== State.GUESS_SENT) {
|
room.members.forEach(function (member, token) {
|
||||||
|
if (!round.results.has(token)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._sendToMember(member, 'guess', data);
|
self._sendToMember(member, 'guess', data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,34 +300,35 @@ var tcpServer = net.createServer(function (socket) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var response;
|
||||||
switch (data.func) {
|
switch (data.func) {
|
||||||
case 'create_room':
|
case 'create_room':
|
||||||
multiGame.createRoom(data.args.roomId);
|
response = multiGame.createRoom(data.args.roomId);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'join_room':
|
case 'join_room':
|
||||||
multiGame.joinRoom(data.args.roomId, data.args.token, data.args.userName);
|
response = multiGame.joinRoom(data.args.roomId, data.args.token, data.args.userName);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'start_game':
|
case 'start_game':
|
||||||
multiGame.startGame(data.args.roomId, data.args.places);
|
response = multiGame.startGame(data.args.roomId, data.args.places);
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'guess':
|
case 'guess':
|
||||||
multiGame.guess(data.args.roomId, data.args.token, data.args.guessPosition, data.args.distance, data.args.score);
|
response = multiGame.guess(data.args.roomId, data.args.token, data.args.guessPosition, data.args.distance, data.args.score);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'next_round':
|
case 'next_round':
|
||||||
multiGame.nextRound(data.args.roomId, data.args.currentRound);
|
response = multiGame.nextRound(data.args.roomId, data.args.currentRound);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.write('OK');
|
socket.write(JSON.stringify(response));
|
||||||
socket.end();
|
socket.end();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+1
-1
@@ -8,6 +8,6 @@
|
|||||||
"ws": "^7.4.4"
|
"ws": "^7.4.4"
|
||||||
},
|
},
|
||||||
"scripts": {},
|
"scripts": {},
|
||||||
"author": "Pőcze Bence <bence@pocze.ch>",
|
"author": "Pőcze Bence and The MapGuesser Contributors <bence@pocze.ch>",
|
||||||
"license": "GNU AGPL 3.0"
|
"license": "GNU AGPL 3.0"
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#distanceInfo>p:nth-child(2), #scoreInfo>p:nth-child(2) {
|
#distanceInfo>p:nth-child(2), #distanceInfo>p:nth-child(3), #scoreInfo>p:nth-child(2) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,13 +111,85 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#countdown {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
right: 5px;
|
||||||
|
height: 28px;
|
||||||
|
line-height: 28px;
|
||||||
|
padding: 0 8px;
|
||||||
|
background-color: #eeeeee;
|
||||||
|
border: solid 1px #555555;
|
||||||
|
border-radius: 3px;
|
||||||
|
opacity: 0.95;
|
||||||
|
z-index: 5;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#countdown.yellow {
|
||||||
|
background-color: #f7c789;
|
||||||
|
border: solid 1px #e8a349;
|
||||||
|
}
|
||||||
|
|
||||||
|
#countdown.red {
|
||||||
|
background-color: #f7a5a5;
|
||||||
|
border: solid 1px #aa5e5e;
|
||||||
|
}
|
||||||
|
|
||||||
|
#countdown p {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#countdown.yellow p {
|
||||||
|
color: #9c4308;
|
||||||
|
}
|
||||||
|
|
||||||
|
#countdown.red p {
|
||||||
|
color: #701919;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation .navigationItem {
|
||||||
|
margin-top: 10px;
|
||||||
|
opacity: 70%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation .navigationItem:hover {
|
||||||
|
opacity: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation .navigationItem div {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation .circleBackground {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
opacity: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation .navigationIcon {
|
||||||
|
width: 75%;
|
||||||
|
height: 75%;
|
||||||
|
margin: auto;
|
||||||
|
margin-top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
-ms-transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 599px) {
|
@media screen and (max-width: 599px) {
|
||||||
#mapName {
|
#mapName {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
#showGuessButtonContainer {
|
#showGuessButtonContainer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 20px;
|
left: 65px;
|
||||||
bottom: 30px;
|
bottom: 30px;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
@@ -134,6 +206,14 @@
|
|||||||
#scoreBarBase {
|
#scoreBarBase {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
#navigation {
|
||||||
|
bottom: 25px;
|
||||||
|
left: 10px;
|
||||||
|
width: 45px;
|
||||||
|
}
|
||||||
|
#navigation .navigationItem {
|
||||||
|
height: 45px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 600px) {
|
@media screen and (min-width: 600px) {
|
||||||
@@ -177,6 +257,14 @@
|
|||||||
#scoreBarBase {
|
#scoreBarBase {
|
||||||
width: 60%;
|
width: 60%;
|
||||||
}
|
}
|
||||||
|
#navigation {
|
||||||
|
bottom: 50px;
|
||||||
|
left: 20px;
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
#navigation .navigationItem {
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
@media screen and (max-height: 424px) {
|
@media screen and (max-height: 424px) {
|
||||||
#guess {
|
#guess {
|
||||||
top: 10px;
|
top: 10px;
|
||||||
@@ -191,5 +279,13 @@
|
|||||||
right: 20px;
|
right: 20px;
|
||||||
bottom: 30px;
|
bottom: 30px;
|
||||||
}
|
}
|
||||||
|
#navigation {
|
||||||
|
bottom: 30px;
|
||||||
|
left: 10px;
|
||||||
|
width: 45px;
|
||||||
|
}
|
||||||
|
#navigation .navigationItem {
|
||||||
|
height: 45px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#map {
|
.map {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
@@ -7,6 +7,13 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#mapSelection img {
|
||||||
|
display: inline;
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
vertical-align: -0.15em;
|
||||||
|
}
|
||||||
|
|
||||||
/* modify the cursor for the Leaflet map */
|
/* modify the cursor for the Leaflet map */
|
||||||
.leaflet-container {
|
.leaflet-container {
|
||||||
cursor: crosshair;
|
cursor: crosshair;
|
||||||
@@ -65,6 +72,9 @@
|
|||||||
#placeControl {
|
#placeControl {
|
||||||
top: calc(50% + 10px);
|
top: calc(50% + 10px);
|
||||||
}
|
}
|
||||||
|
.hideOnMobile {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 1000px), (max-height: 599px) {
|
@media screen and (min-width: 1000px), (max-height: 599px) {
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ html, body {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #cccccc;
|
||||||
|
}
|
||||||
|
|
||||||
button::-moz-focus-inner, input::-moz-focus-inner {
|
button::-moz-focus-inner, input::-moz-focus-inner {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
@@ -374,6 +378,7 @@ header>p>span:not(:last-child) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
background-color: #ffffff;
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 16 16">
|
||||||
|
<circle cx="50%" cy="50%" r="50%" fill="black" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 146 B |
@@ -0,0 +1,5 @@
|
|||||||
|
<!-- Original image: Copyright (c) 2019 The Bootstrap Authors. License can be found in 'USED_SOFTWARE' in section 'Bootstrap Icons'. -->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" fill="#3183ce" viewBox="0 0 16 16">
|
||||||
|
<path fill-rule="evenodd" d="m8 3.293 6 6V13.5a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 2 13.5V9.293l6-6zm5-.793V6l-2-2V2.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5z"/>
|
||||||
|
<path fill-rule="evenodd" d="M7.293 1.5a1 1 0 0 1 1.414 0l6.647 6.646a.5.5 0 0 1-.708.708L8 2.207 1.354 8.854a.5.5 0 1 1-.708-.708L7.293 1.5z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 556 B |
@@ -0,0 +1,4 @@
|
|||||||
|
<!-- Copyright (c) 2019 The Bootstrap Authors. License can be found in 'USED_SOFTWARE' in section 'Bootstrap Icons'. -->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="#ffffff" viewBox="0 0 16 16">
|
||||||
|
<path fill-rule="evenodd" d="M15.817.113A.5.5 0 0 1 16 .5v14a.5.5 0 0 1-.402.49l-5 1a.502.502 0 0 1-.196 0L5.5 15.01l-4.902.98A.5.5 0 0 1 0 15.5v-14a.5.5 0 0 1 .402-.49l5-1a.5.5 0 0 1 .196 0L10.5.99l4.902-.98a.5.5 0 0 1 .415.103zM10 1.91l-4-.8v12.98l4 .8V1.91zm1 12.98 4-.8V1.11l-4 .8v12.98zm-6-.8V1.11l-4 .8v12.98l4-.8z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 530 B |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,10 @@
|
|||||||
|
<!-- Original image: Copyright (c) 2019 The Bootstrap Authors. License can be found in 'USED_SOFTWARE' in section 'Bootstrap Icons'. -->
|
||||||
|
<svg viewBox="0 0 12 16" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
fill="#3183ce"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
stroke="#19456d"
|
||||||
|
stroke-width="0.3"
|
||||||
|
stroke-linecap="round"
|
||||||
|
d="m 5.9999998,15.849652 c 0,0 5.8511182,-5.579947 5.8511182,-9.8134832 a 5.8511179,5.8880898 0 0 0 -11.7022358,0 c 0,4.2335362 5.8511176,9.8134832 5.8511176,9.8134832" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 529 B |
@@ -0,0 +1,5 @@
|
|||||||
|
<!-- Copyright (c) 2019 The Bootstrap Authors. License can be found in 'USED_SOFTWARE' in section 'Bootstrap Icons'. -->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="#ffffff" viewBox="0 0 16 16">
|
||||||
|
<path d="m14.12 10.163 1.715.858c.22.11.22.424 0 .534L8.267 15.34a.598.598 0 0 1-.534 0L.165 11.555a.299.299 0 0 1 0-.534l1.716-.858 5.317 2.659c.505.252 1.1.252 1.604 0l5.317-2.66zM7.733.063a.598.598 0 0 1 .534 0l7.568 3.784a.3.3 0 0 1 0 .535L8.267 8.165a.598.598 0 0 1-.534 0L.165 4.382a.299.299 0 0 1 0-.535L7.733.063z"/>
|
||||||
|
<path d="m14.12 6.576 1.715.858c.22.11.22.424 0 .534l-7.568 3.784a.598.598 0 0 1-.534 0L.165 7.968a.299.299 0 0 1 0-.534l1.716-.858 5.317 2.659c.505.252 1.1.252 1.604 0l5.317-2.659z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 718 B |
+368
-146
@@ -17,6 +17,10 @@
|
|||||||
adaptGuess: false,
|
adaptGuess: false,
|
||||||
googleLink: null,
|
googleLink: null,
|
||||||
|
|
||||||
|
readyToContinue: true,
|
||||||
|
timeoutEnd: null,
|
||||||
|
countdownHandler: null,
|
||||||
|
|
||||||
MultiConnector: {
|
MultiConnector: {
|
||||||
connection: null,
|
connection: null,
|
||||||
reconnectCounter: 0,
|
reconnectCounter: 0,
|
||||||
@@ -30,9 +34,7 @@
|
|||||||
|
|
||||||
Game.MultiConnector.connection.onopen = function () {
|
Game.MultiConnector.connection.onopen = function () {
|
||||||
document.getElementById('loading').style.visibility = 'hidden';
|
document.getElementById('loading').style.visibility = 'hidden';
|
||||||
|
|
||||||
Game.MultiConnector.reconnectCounter = 0;
|
Game.MultiConnector.reconnectCounter = 0;
|
||||||
|
|
||||||
Game.MultiConnector.connection.send(JSON.stringify({ func: 'connect_to_room', args: { roomId: roomId, token: Game.multi.token } }));
|
Game.MultiConnector.connection.send(JSON.stringify({ func: 'connect_to_room', args: { roomId: roomId, token: Game.multi.token } }));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,12 +68,16 @@
|
|||||||
Game.MultiConnector.newRound(json.data);
|
Game.MultiConnector.newRound(json.data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'results':
|
case 'guess':
|
||||||
//TODO
|
Game.MultiConnector.guess(json.data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'guess':
|
case 'timeout_changed':
|
||||||
//TODO
|
Game.MultiConnector.timeoutChanged(json.data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'end_round':
|
||||||
|
Game.MultiConnector.endRound(json.data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -91,39 +97,61 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
initialize: function (data) {
|
initialize: function (data) {
|
||||||
if (data.history) {
|
Game.readyToContinue = false;
|
||||||
for (var i = 0; i < data.history.length; ++i) {
|
|
||||||
var round = data.history[i];
|
|
||||||
Game.rounds.push({ position: round.position, guessPosition: round.guessPosition, realMarker: null, guessMarker: null, line: null });
|
|
||||||
Game.addRealGuessPair(round.position, round.guessPosition, true);
|
|
||||||
Game.scoreSum += round.score;
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('currentRound').innerHTML = String(Game.rounds.length) + '/' + String(Game.NUMBER_OF_ROUNDS);
|
if (data.history.length === 0 && !data.place) {
|
||||||
document.getElementById('currentScoreSum').innerHTML = String(Game.scoreSum) + '/' + String(Game.rounds.length * Game.MAX_SCORE);
|
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) {
|
if (data.place) {
|
||||||
|
Game.readyToContinue = data.readyToContinue;
|
||||||
Game.panoId = data.place.panoId;
|
Game.panoId = data.place.panoId;
|
||||||
Game.pov = data.place.pov;
|
Game.pov = data.place.pov;
|
||||||
|
|
||||||
document.getElementById('panoCover').style.visibility = 'hidden';
|
document.getElementById('multi').style.visibility = 'hidden';
|
||||||
MapGuesser.hideModal();
|
|
||||||
|
|
||||||
Game.startNewRound();
|
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';
|
document.getElementById('loading').style.visibility = 'hidden';
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
memberJoined: function (data) {
|
memberJoined: function (data) {
|
||||||
@@ -135,27 +163,51 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
newRound: function (data) {
|
newRound: function (data) {
|
||||||
//TODO: workaround until results are not sent
|
|
||||||
if (Game.adaptGuess) {
|
|
||||||
document.getElementById('guess').classList.remove('adapt');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Game.rounds.length === Game.NUMBER_OF_ROUNDS) {
|
if (Game.rounds.length === Game.NUMBER_OF_ROUNDS) {
|
||||||
Game.reset();
|
Game.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if player didn't guess - TODO: show everything on a map
|
Game.readyToContinue = false;
|
||||||
if (data.result && Game.rounds.length > 0 && !Game.rounds[Game.rounds.length - 1].position) {
|
|
||||||
Game.rounds[Game.rounds.length - 1].position = data.result.position;
|
|
||||||
Game.addRealGuessPair(data.result.position, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
Game.panoId = data.place.panoId;
|
Game.panoId = data.place.panoId;
|
||||||
Game.pov = data.place.pov;
|
Game.pov = data.place.pov;
|
||||||
|
|
||||||
MapGuesser.hideModal();
|
document.getElementById('multi').style.visibility = 'hidden';
|
||||||
Game.resetRound();
|
Game.resetRound();
|
||||||
Game.startNewRound();
|
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);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -174,11 +226,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('loading').style.visibility = 'visible';
|
document.getElementById('loading').style.visibility = 'visible';
|
||||||
|
|
||||||
var url = roomId ? '/multiGame/' + roomId + '/prepare.json' : '/game/' + mapId + '/prepare.json';
|
var url = roomId ? '/multiGame/' + roomId + '/prepare.json' : '/game/' + mapId + '/prepare.json';
|
||||||
MapGuesser.httpRequest('POST', url, function () {
|
MapGuesser.httpRequest('POST', url, function () {
|
||||||
document.getElementById('loading').style.visibility = 'hidden';
|
document.getElementById('loading').style.visibility = 'hidden';
|
||||||
|
|
||||||
|
if (this.response.error) {
|
||||||
|
Game.handleErrorResponse(this.response.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById('mapName').innerHTML = this.response.mapName;
|
document.getElementById('mapName').innerHTML = this.response.mapName;
|
||||||
Game.mapBounds = this.response.bounds;
|
Game.mapBounds = this.response.bounds;
|
||||||
|
|
||||||
@@ -188,13 +244,12 @@
|
|||||||
Game.multi.token = this.response.token;
|
Game.multi.token = this.response.token;
|
||||||
Game.multi.owner = this.response.owner;
|
Game.multi.owner = this.response.owner;
|
||||||
|
|
||||||
MapGuesser.showModal('multi');
|
document.getElementById('multi').style.visibility = 'visible';
|
||||||
if (Game.multi.owner) {
|
if (Game.multi.owner) {
|
||||||
document.getElementById('startMultiGameButton').style.display = 'block';
|
document.getElementById('startMultiGameButton').style.display = 'block';
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('loading').style.visibility = 'visible';
|
document.getElementById('loading').style.visibility = 'visible';
|
||||||
|
|
||||||
Game.MultiConnector.connect();
|
Game.MultiConnector.connect();
|
||||||
}
|
}
|
||||||
}, data);
|
}, data);
|
||||||
@@ -202,8 +257,6 @@
|
|||||||
|
|
||||||
initialize: function () {
|
initialize: function () {
|
||||||
document.getElementById('panoCover').style.visibility = 'visible';
|
document.getElementById('panoCover').style.visibility = 'visible';
|
||||||
document.getElementById('currentRound').innerHTML = '1/' + String(Game.NUMBER_OF_ROUNDS);
|
|
||||||
document.getElementById('currentScoreSum').innerHTML = '0/0';
|
|
||||||
|
|
||||||
Game.map.setOptions({
|
Game.map.setOptions({
|
||||||
draggableCursor: 'crosshair'
|
draggableCursor: 'crosshair'
|
||||||
@@ -216,31 +269,29 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('loading').style.visibility = 'visible';
|
document.getElementById('loading').style.visibility = 'visible';
|
||||||
|
|
||||||
MapGuesser.httpRequest('POST', '/game/' + mapId + '/initialData.json', function () {
|
MapGuesser.httpRequest('POST', '/game/' + mapId + '/initialData.json', function () {
|
||||||
document.getElementById('loading').style.visibility = 'hidden';
|
document.getElementById('loading').style.visibility = 'hidden';
|
||||||
document.getElementById('panoCover').style.visibility = 'hidden';
|
document.getElementById('panoCover').style.visibility = 'hidden';
|
||||||
|
|
||||||
if (this.response.error) {
|
if (this.response.error) {
|
||||||
//TODO: handle this error
|
Game.handleErrorResponse(this.response.error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Game.panoId = this.response.place.panoId;
|
Game.panoId = this.response.place.panoId;
|
||||||
Game.pov = this.response.place.pov;
|
Game.pov = this.response.place.pov;
|
||||||
|
|
||||||
if (this.response.history) {
|
for (var i = 0; i < this.response.history.length; ++i) {
|
||||||
for (var i = 0; i < this.response.history.length; ++i) {
|
var round = this.response.history[i];
|
||||||
var round = this.response.history[i];
|
Game.rounds.push({ position: round.position, guessPosition: round.result.guessPosition, realMarker: null, guessMarkers: [] });
|
||||||
Game.rounds.push({ position: round.position, guessPosition: round.guessPosition, realMarker: null, guessMarker: null, line: null });
|
Game.addPositionToResultMap(true);
|
||||||
Game.addRealGuessPair(round.position, round.guessPosition, true);
|
Game.addGuessPositionToResultMap(round.result.guessPosition, null, true);
|
||||||
Game.scoreSum += round.score;
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
Game.startNewRound();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -257,9 +308,13 @@
|
|||||||
if (round.realMarker) {
|
if (round.realMarker) {
|
||||||
round.realMarker.setMap(null);
|
round.realMarker.setMap(null);
|
||||||
}
|
}
|
||||||
if (round.guessMarker) {
|
for (var j = 0; j < round.guessMarkers.length; ++j) {
|
||||||
round.guessMarker.setMap(null);
|
var guessMarker = round.guessMarkers[j];
|
||||||
round.line.setMap(null);
|
guessMarker.marker.setMap(null);
|
||||||
|
guessMarker.line.setMap(null);
|
||||||
|
if (guessMarker.info) {
|
||||||
|
guessMarker.info.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,16 +324,21 @@
|
|||||||
var distanceInfo = document.getElementById('distanceInfo');
|
var distanceInfo = document.getElementById('distanceInfo');
|
||||||
distanceInfo.children[0].style.display = null;
|
distanceInfo.children[0].style.display = null;
|
||||||
distanceInfo.children[1].style.display = null;
|
distanceInfo.children[1].style.display = null;
|
||||||
|
distanceInfo.children[2].style.display = null;
|
||||||
var scoreInfo = document.getElementById('scoreInfo');
|
var scoreInfo = document.getElementById('scoreInfo');
|
||||||
scoreInfo.children[0].style.display = null;
|
scoreInfo.children[0].style.display = null;
|
||||||
scoreInfo.children[1].style.display = null;
|
scoreInfo.children[1].style.display = null;
|
||||||
document.getElementById('continueButton').style.display = null;
|
document.getElementById('continueButton').style.display = null;
|
||||||
|
document.getElementById('showSummaryButton').style.display = null;
|
||||||
document.getElementById('startNewGameButton').style.display = null;
|
document.getElementById('startNewGameButton').style.display = null;
|
||||||
|
|
||||||
document.getElementById('showGuessButton').style.visibility = null;
|
document.getElementById('showGuessButton').style.visibility = null;
|
||||||
document.getElementById('guess').style.visibility = null;
|
document.getElementById('guess').style.visibility = null;
|
||||||
document.getElementById('guess').classList.remove('result');
|
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();
|
Game.initialize();
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -289,16 +349,24 @@
|
|||||||
var lastRound = Game.rounds[Game.rounds.length - 1];
|
var lastRound = Game.rounds[Game.rounds.length - 1];
|
||||||
|
|
||||||
lastRound.realMarker.setVisible(false);
|
lastRound.realMarker.setVisible(false);
|
||||||
if (lastRound.guessMarker) {
|
for (var i = 0; i < lastRound.guessMarkers.length; ++i) {
|
||||||
lastRound.guessMarker.setVisible(false);
|
var guessMarker = lastRound.guessMarkers[i];
|
||||||
lastRound.line.setVisible(false);
|
guessMarker.marker.setVisible(false);
|
||||||
|
guessMarker.line.setVisible(false);
|
||||||
|
if (guessMarker.info) {
|
||||||
|
guessMarker.info.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('panoCover').style.visibility = 'hidden';
|
document.getElementById('panoCover').style.visibility = 'hidden';
|
||||||
document.getElementById('showGuessButton').style.visibility = null;
|
document.getElementById('showGuessButton').style.visibility = null;
|
||||||
document.getElementById('guess').style.visibility = null;
|
document.getElementById('guess').style.visibility = null;
|
||||||
document.getElementById('guess').classList.remove('result')
|
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({
|
Game.map.setOptions({
|
||||||
draggableCursor: 'crosshair'
|
draggableCursor: 'crosshair'
|
||||||
@@ -314,7 +382,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
startNewRound: function () {
|
startNewRound: function () {
|
||||||
Game.rounds.push({ position: null, guessPosition: null, realMarker: null, guessMarker: null, line: null });
|
Game.rounds.push({ position: null, guessPosition: null, realMarker: null, guessMarkers: [] });
|
||||||
|
|
||||||
document.getElementById('currentRound').innerHTML = String(Game.rounds.length) + '/' + String(Game.NUMBER_OF_ROUNDS);
|
document.getElementById('currentRound').innerHTML = String(Game.rounds.length) + '/' + String(Game.NUMBER_OF_ROUNDS);
|
||||||
|
|
||||||
@@ -322,19 +390,26 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleErrorResponse: function (error) {
|
handleErrorResponse: function (error) {
|
||||||
// for the time being we only handle the "no_session_found" error and reset the game
|
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;
|
||||||
|
|
||||||
if (roomId) {
|
case 'game_already_started':
|
||||||
//TODO: better error message
|
MapGuesser.showModalWithContent('Error', 'This game is already started, you cannot join.');
|
||||||
alert('Your session is invalid, please start multiplayer again!')
|
break;
|
||||||
return;
|
|
||||||
|
default:
|
||||||
|
MapGuesser.showModalWithContent('Error', 'Error code: \'' + error + '\'');
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
MapGuesser.httpRequest('GET', '/game/' + mapId + '/prepare.json', function () {
|
|
||||||
Game.mapBounds = this.response.bounds;
|
|
||||||
|
|
||||||
Game.reset();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
loadPano: function (panoId, pov) {
|
loadPano: function (panoId, pov) {
|
||||||
@@ -347,7 +422,106 @@
|
|||||||
Game.panorama.setPano(panoId);
|
Game.panorama.setPano(panoId);
|
||||||
},
|
},
|
||||||
|
|
||||||
evaluateGuess: function () {
|
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) {
|
if (!Game.guessMarker) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -356,73 +530,34 @@
|
|||||||
Game.rounds[Game.rounds.length - 1].guessPosition = guessPosition;
|
Game.rounds[Game.rounds.length - 1].guessPosition = guessPosition;
|
||||||
|
|
||||||
document.getElementById('guessButton').disabled = true;
|
document.getElementById('guessButton').disabled = true;
|
||||||
if (Game.adaptGuess) {
|
|
||||||
document.getElementById('guess').classList.remove('adapt');
|
|
||||||
}
|
|
||||||
document.getElementById('loading').style.visibility = 'visible';
|
|
||||||
document.getElementById('panoCover').style.visibility = 'visible';
|
document.getElementById('panoCover').style.visibility = 'visible';
|
||||||
|
|
||||||
var data = new FormData();
|
var data = new FormData();
|
||||||
data.append('lat', String(guessPosition.lat));
|
data.append('lat', String(guessPosition.lat));
|
||||||
data.append('lng', String(guessPosition.lng));
|
data.append('lng', String(guessPosition.lng));
|
||||||
|
|
||||||
|
document.getElementById('loading').style.visibility = 'visible';
|
||||||
var url = roomId ? '/multiGame/' + roomId + '/guess.json' : '/game/' + mapId + '/guess.json';
|
var url = roomId ? '/multiGame/' + roomId + '/guess.json' : '/game/' + mapId + '/guess.json';
|
||||||
MapGuesser.httpRequest('POST', url, function () {
|
MapGuesser.httpRequest('POST', url, function () {
|
||||||
|
document.getElementById('loading').style.visibility = 'hidden';
|
||||||
|
|
||||||
if (this.response.error) {
|
if (this.response.error) {
|
||||||
Game.handleErrorResponse(this.response.error);
|
Game.handleErrorResponse(this.response.error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Game.guessMarker.setMap(null);
|
Game.receiveResult(this.response.position, guessPosition, this.response.result, this.response.allResults);
|
||||||
Game.guessMarker = null;
|
|
||||||
|
|
||||||
document.getElementById('loading').style.visibility = 'hidden';
|
|
||||||
document.getElementById('guess').classList.add('result');
|
|
||||||
|
|
||||||
Game.scoreSum += this.response.result.score;
|
|
||||||
document.getElementById('currentScoreSum').innerHTML = String(Game.scoreSum) + '/' + String(Game.rounds.length * Game.MAX_SCORE);
|
|
||||||
|
|
||||||
Game.rounds[Game.rounds.length - 1].position = this.response.result.position;
|
|
||||||
Game.addRealGuessPair(this.response.result.position, guessPosition);
|
|
||||||
|
|
||||||
var resultBounds = new google.maps.LatLngBounds();
|
|
||||||
resultBounds.extend(this.response.result.position);
|
|
||||||
resultBounds.extend(guessPosition);
|
|
||||||
|
|
||||||
Game.map.setOptions({
|
|
||||||
draggableCursor: 'grab'
|
|
||||||
});
|
|
||||||
Game.map.fitBounds(resultBounds);
|
|
||||||
|
|
||||||
document.getElementById('distance').innerHTML = Util.printDistanceForHuman(this.response.result.distance);
|
|
||||||
document.getElementById('score').innerHTML = this.response.result.score;
|
|
||||||
|
|
||||||
var scoreBarProperties = Game.calculateScoreBarProperties(this.response.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';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.response.place) {
|
if (this.response.place) {
|
||||||
Game.panoId = this.response.place.panoId;
|
Game.panoId = this.response.place.panoId;
|
||||||
Game.pov = this.response.place.pov;
|
Game.pov = this.response.place.pov;
|
||||||
} else {
|
|
||||||
if (!Game.multi.owner) {
|
|
||||||
//TODO: "waiting for" disabled button
|
|
||||||
document.getElementById('continueButton').style.display = 'none';
|
|
||||||
}
|
|
||||||
Game.panoId = null;
|
|
||||||
Game.pov = null;
|
|
||||||
}
|
}
|
||||||
}, data);
|
}, data);
|
||||||
},
|
},
|
||||||
|
|
||||||
addRealGuessPair: function (position, guessPosition, hidden) {
|
addPositionToResultMap: function (hidden) {
|
||||||
var round = Game.rounds[Game.rounds.length - 1];
|
var round = Game.rounds[Game.rounds.length - 1];
|
||||||
|
var position = round.position;
|
||||||
|
|
||||||
round.realMarker = new google.maps.Marker({
|
round.realMarker = new google.maps.Marker({
|
||||||
map: Game.map,
|
map: Game.map,
|
||||||
@@ -443,20 +578,25 @@
|
|||||||
round.realMarker.addListener('click', function () {
|
round.realMarker.addListener('click', function () {
|
||||||
window.open('https://www.google.com/maps/search/?api=1&query=' + this.getPosition().toUrlValue(), '_blank');
|
window.open('https://www.google.com/maps/search/?api=1&query=' + this.getPosition().toUrlValue(), '_blank');
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
if (!guessPosition) {
|
addGuessPositionToResultMap: function (guessPosition, result, hidden) {
|
||||||
return;
|
var round = Game.rounds[Game.rounds.length - 1];
|
||||||
}
|
var position = round.position;
|
||||||
|
|
||||||
round.guessMarker = new google.maps.Marker({
|
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,
|
map: Game.map,
|
||||||
visible: !hidden,
|
visible: !hidden,
|
||||||
position: guessPosition,
|
position: guessPosition,
|
||||||
zIndex: Game.rounds.length,
|
zIndex: Game.rounds.length,
|
||||||
clickable: false,
|
clickable: !!result,
|
||||||
draggable: false,
|
draggable: false,
|
||||||
icon: {
|
icon: {
|
||||||
url: STATIC_ROOT + '/img/markers/marker-gray-empty.svg?rev=' + REVISION,
|
url: STATIC_ROOT + '/img/markers/' + markerSvg + '?rev=' + REVISION,
|
||||||
size: new google.maps.Size(24, 32),
|
size: new google.maps.Size(24, 32),
|
||||||
scaledSize: new google.maps.Size(24, 32),
|
scaledSize: new google.maps.Size(24, 32),
|
||||||
anchor: new google.maps.Point(12, 32),
|
anchor: new google.maps.Point(12, 32),
|
||||||
@@ -467,11 +607,11 @@
|
|||||||
fontFamily: 'Roboto',
|
fontFamily: 'Roboto',
|
||||||
fontSize: '16px',
|
fontSize: '16px',
|
||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
text: '?'
|
text: markerLabel
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
round.line = new google.maps.Polyline({
|
guessMarker.line = new google.maps.Polyline({
|
||||||
map: Game.map,
|
map: Game.map,
|
||||||
visible: !hidden,
|
visible: !hidden,
|
||||||
path: [
|
path: [
|
||||||
@@ -494,6 +634,19 @@
|
|||||||
draggable: false,
|
draggable: false,
|
||||||
editable: 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) {
|
calculateScoreBarProperties: function (score, maxScore) {
|
||||||
@@ -514,7 +667,8 @@
|
|||||||
showSummary: function () {
|
showSummary: function () {
|
||||||
var distanceInfo = document.getElementById('distanceInfo');
|
var distanceInfo = document.getElementById('distanceInfo');
|
||||||
distanceInfo.children[0].style.display = 'none';
|
distanceInfo.children[0].style.display = 'none';
|
||||||
distanceInfo.children[1].style.display = 'block';
|
distanceInfo.children[1].style.display = 'none';
|
||||||
|
distanceInfo.children[2].style.display = 'block';
|
||||||
var scoreInfo = document.getElementById('scoreInfo');
|
var scoreInfo = document.getElementById('scoreInfo');
|
||||||
scoreInfo.children[0].style.display = 'none';
|
scoreInfo.children[0].style.display = 'none';
|
||||||
scoreInfo.children[1].style.display = 'block';
|
scoreInfo.children[1].style.display = 'block';
|
||||||
@@ -522,6 +676,9 @@
|
|||||||
|
|
||||||
if (!roomId || Game.multi.owner) {
|
if (!roomId || Game.multi.owner) {
|
||||||
document.getElementById('startNewGameButton').style.display = 'block';
|
document.getElementById('startNewGameButton').style.display = 'block';
|
||||||
|
if (!Game.readyToContinue) {
|
||||||
|
document.getElementById('startNewGameButton').disabled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var resultBounds = new google.maps.LatLngBounds();
|
var resultBounds = new google.maps.LatLngBounds();
|
||||||
@@ -545,14 +702,14 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
round.realMarker.setVisible(true);
|
round.realMarker.setVisible(true);
|
||||||
if (round.guessMarker) {
|
|
||||||
round.guessMarker.setVisible(true);
|
|
||||||
round.line.setVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
resultBounds.extend(round.position);
|
resultBounds.extend(round.position);
|
||||||
if (round.guessMarker) {
|
|
||||||
resultBounds.extend(round.guessPosition);
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,6 +741,52 @@
|
|||||||
Game.googleLink.href = 'https://maps.google.com/maps';
|
Game.googleLink.href = 'https://maps.google.com/maps';
|
||||||
}
|
}
|
||||||
}, 1);
|
}, 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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -614,7 +817,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
Game.map.addListener('click', function (e) {
|
Game.map.addListener('click', function (e) {
|
||||||
if (Game.rounds[Game.rounds.length - 1].guessPosition) {
|
if (Game.rounds[Game.rounds.length - 1].guessPosition || Game.rounds[Game.rounds.length - 1].position) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -629,7 +832,7 @@
|
|||||||
clickable: false,
|
clickable: false,
|
||||||
draggable: true,
|
draggable: true,
|
||||||
icon: {
|
icon: {
|
||||||
url: STATIC_ROOT + '/img/markers/marker-gray-empty.svg?rev=' + REVISION,
|
url: STATIC_ROOT + '/img/markers/marker-blue-empty.svg?rev=' + REVISION,
|
||||||
size: new google.maps.Size(24, 32),
|
size: new google.maps.Size(24, 32),
|
||||||
scaledSize: new google.maps.Size(24, 32),
|
scaledSize: new google.maps.Size(24, 32),
|
||||||
anchor: new google.maps.Point(12, 32),
|
anchor: new google.maps.Point(12, 32),
|
||||||
@@ -669,27 +872,33 @@
|
|||||||
document.getElementById('showGuessButton').onclick = function () {
|
document.getElementById('showGuessButton').onclick = function () {
|
||||||
this.style.visibility = 'hidden';
|
this.style.visibility = 'hidden';
|
||||||
document.getElementById('guess').style.visibility = 'visible';
|
document.getElementById('guess').style.visibility = 'visible';
|
||||||
|
document.getElementById('navigation').style.visibility = 'hidden';
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('closeGuessButton').onclick = function () {
|
document.getElementById('closeGuessButton').onclick = function () {
|
||||||
document.getElementById('showGuessButton').style.visibility = null;
|
document.getElementById('showGuessButton').style.visibility = null;
|
||||||
document.getElementById('guess').style.visibility = null;
|
document.getElementById('guess').style.visibility = null;
|
||||||
|
document.getElementById('navigation').style.visibility = 'visible';
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('guessButton').onclick = function () {
|
document.getElementById('guessButton').onclick = function () {
|
||||||
Game.evaluateGuess();
|
Game.guess();
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('continueButton').onclick = function () {
|
document.getElementById('continueButton').onclick = function () {
|
||||||
if (roomId) {
|
if (roomId) {
|
||||||
if (!Game.multi.owner) {
|
if (!Game.multi.owner || !Game.readyToContinue) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('loading').style.visibility = 'visible';
|
document.getElementById('loading').style.visibility = 'visible';
|
||||||
|
|
||||||
MapGuesser.httpRequest('POST', '/multiGame/' + roomId + '/nextRound.json', function () {
|
MapGuesser.httpRequest('POST', '/multiGame/' + roomId + '/nextRound.json', function () {
|
||||||
document.getElementById('loading').style.visibility = 'hidden';
|
document.getElementById('loading').style.visibility = 'hidden';
|
||||||
|
|
||||||
|
if (this.response.error) {
|
||||||
|
Game.handleErrorResponse(this.response.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Game.resetRound();
|
Game.resetRound();
|
||||||
@@ -707,9 +916,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('loading').style.visibility = 'visible';
|
document.getElementById('loading').style.visibility = 'visible';
|
||||||
|
|
||||||
MapGuesser.httpRequest('POST', '/multiGame/' + roomId + '/initialData.json', function () {
|
MapGuesser.httpRequest('POST', '/multiGame/' + roomId + '/initialData.json', function () {
|
||||||
document.getElementById('loading').style.visibility = 'hidden';
|
document.getElementById('loading').style.visibility = 'hidden';
|
||||||
|
|
||||||
|
if (this.response.error) {
|
||||||
|
Game.handleErrorResponse(this.response.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Game.reset();
|
Game.reset();
|
||||||
@@ -721,11 +934,20 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapGuesser.hideModal();
|
document.getElementById('multi').style.visibility = 'hidden';
|
||||||
document.getElementById('loading').style.visibility = 'visible';
|
|
||||||
|
|
||||||
|
document.getElementById('loading').style.visibility = 'visible';
|
||||||
MapGuesser.httpRequest('POST', '/multiGame/' + roomId + '/initialData.json', function () {
|
MapGuesser.httpRequest('POST', '/multiGame/' + roomId + '/initialData.json', function () {
|
||||||
document.getElementById('loading').style.visibility = 'hidden';
|
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);
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
+349
-74
@@ -7,7 +7,6 @@
|
|||||||
description: null
|
description: null
|
||||||
},
|
},
|
||||||
map: null,
|
map: null,
|
||||||
markers: null,
|
|
||||||
panorama: null,
|
panorama: null,
|
||||||
selectedMarker: null,
|
selectedMarker: null,
|
||||||
added: {},
|
added: {},
|
||||||
@@ -118,16 +117,13 @@
|
|||||||
MapEditor.resetSelected();
|
MapEditor.resetSelected();
|
||||||
MapEditor.selectedMarker = marker;
|
MapEditor.selectedMarker = marker;
|
||||||
|
|
||||||
MapEditor.map.invalidateSize(true);
|
MapEditor.map.resize();
|
||||||
MapEditor.map.panTo(marker.getLatLng());
|
MapEditor.map.panTo(marker.getLatLng());
|
||||||
|
|
||||||
MapEditor.panorama.setVisible(false);
|
MapEditor.panorama.setVisible(false);
|
||||||
|
|
||||||
if (marker.placeId) {
|
if (marker.placeId) {
|
||||||
MapEditor.markers.removeLayer(MapEditor.selectedMarker);
|
MapEditor.map.changeMarkerIcon(marker, MapEditor.map.iconCollection.iconBlue);
|
||||||
MapEditor.map.addLayer(MapEditor.selectedMarker);
|
|
||||||
marker.setIcon(IconCollection.iconBlue);
|
|
||||||
marker.setZIndexOffset(2000);
|
|
||||||
|
|
||||||
document.getElementById('deleteButton').style.display = 'block';
|
document.getElementById('deleteButton').style.display = 'block';
|
||||||
|
|
||||||
@@ -165,13 +161,13 @@
|
|||||||
var placeId = MapEditor.selectedMarker.placeId
|
var placeId = MapEditor.selectedMarker.placeId
|
||||||
|
|
||||||
if (places[placeId].id && !del) {
|
if (places[placeId].id && !del) {
|
||||||
MapEditor.map.removeLayer(MapEditor.selectedMarker);
|
MapEditor.map.changeMarkerIcon(
|
||||||
MapEditor.markers.addLayer(MapEditor.selectedMarker);
|
MapEditor.selectedMarker,
|
||||||
MapEditor.selectedMarker.setIcon(places[placeId].noPano ? IconCollection.iconRed : IconCollection.iconGreen);
|
places[placeId].noPano ? MapEditor.map.iconCollection.iconRed : MapEditor.map.iconCollection.iconGreen
|
||||||
MapEditor.selectedMarker.setZIndexOffset(1000);
|
);
|
||||||
} else {
|
} else {
|
||||||
delete places[placeId];
|
delete places[placeId];
|
||||||
MapEditor.map.removeLayer(MapEditor.selectedMarker);
|
MapEditor.map.removeMarker(MapEditor.selectedMarker);
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('deleteButton').style.display = 'none';
|
document.getElementById('deleteButton').style.display = 'none';
|
||||||
@@ -223,7 +219,7 @@
|
|||||||
MapEditor.resetSelected(del);
|
MapEditor.resetSelected(del);
|
||||||
MapEditor.selectedMarker = null;
|
MapEditor.selectedMarker = null;
|
||||||
|
|
||||||
MapEditor.map.invalidateSize(true);
|
MapEditor.map.resize();
|
||||||
},
|
},
|
||||||
|
|
||||||
deletePlace: function () {
|
deletePlace: function () {
|
||||||
@@ -239,6 +235,7 @@
|
|||||||
|
|
||||||
delete MapEditor.added[placeId];
|
delete MapEditor.added[placeId];
|
||||||
delete MapEditor.edited[placeId];
|
delete MapEditor.edited[placeId];
|
||||||
|
delete places[placeId];
|
||||||
|
|
||||||
document.getElementById('added').innerHTML = String(Object.keys(MapEditor.added).length);
|
document.getElementById('added').innerHTML = String(Object.keys(MapEditor.added).length);
|
||||||
document.getElementById('edited').innerHTML = String(Object.keys(MapEditor.edited).length);
|
document.getElementById('edited').innerHTML = String(Object.keys(MapEditor.edited).length);
|
||||||
@@ -313,24 +310,6 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var IconCollection = {
|
|
||||||
iconGreen: L.icon({
|
|
||||||
iconUrl: STATIC_ROOT + '/img/markers/marker-green.svg?rev' + REVISION,
|
|
||||||
iconSize: [24, 32],
|
|
||||||
iconAnchor: [12, 32]
|
|
||||||
}),
|
|
||||||
iconRed: L.icon({
|
|
||||||
iconUrl: STATIC_ROOT + '/img/markers/marker-red.svg?rev=' + REVISION,
|
|
||||||
iconSize: [24, 32],
|
|
||||||
iconAnchor: [12, 32]
|
|
||||||
}),
|
|
||||||
iconBlue: L.icon({
|
|
||||||
iconUrl: STATIC_ROOT + '/img/markers/marker-blue.svg?rev=' + REVISION,
|
|
||||||
iconSize: [24, 32],
|
|
||||||
iconAnchor: [12, 32]
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
var Util = {
|
var Util = {
|
||||||
getHighResData: function () {
|
getHighResData: function () {
|
||||||
if (window.devicePixelRatio >= 4) {
|
if (window.devicePixelRatio >= 4) {
|
||||||
@@ -340,64 +319,316 @@
|
|||||||
} else {
|
} else {
|
||||||
return { ppi: 72, tileSize: 512, zoomOffset: -1, minZoom: 2, maxZoom: 20 };
|
return { ppi: 72, tileSize: 512, zoomOffset: -1, minZoom: 2, maxZoom: 20 };
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
extractCoordinates: function (coordinatesStr) {
|
||||||
|
var coordinates = { valid: false, latlng: { lat: 0., lng: 0. } };
|
||||||
|
var delimiters = [',', ' ', ';'];
|
||||||
|
|
||||||
|
coordinatesStr = coordinatesStr.trim();
|
||||||
|
if (coordinatesStr.length == 0) {
|
||||||
|
return coordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var delimiter of delimiters) {
|
||||||
|
if (coordinatesStr.indexOf(delimiter) != -1) {
|
||||||
|
|
||||||
|
var coordinatesArr = coordinatesStr.split(delimiter);
|
||||||
|
coordinates.latlng.lat = parseFloat(coordinatesArr[0]);
|
||||||
|
coordinates.latlng.lng = parseFloat(coordinatesArr[1]);
|
||||||
|
|
||||||
|
if (!isNaN(coordinates.latlng.lat) && !isNaN(coordinates.latlng.lng)) {
|
||||||
|
coordinates.valid = true;
|
||||||
|
return coordinates;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return coordinates;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
MapEditor.map = L.map('map', {
|
var LMapWrapper = {
|
||||||
zoomControl: false
|
map: null,
|
||||||
});
|
markers: null,
|
||||||
|
divId: null,
|
||||||
|
iconCollection: {
|
||||||
|
iconGreen: L.icon({
|
||||||
|
iconUrl: STATIC_ROOT + '/img/markers/marker-green.svg?rev' + REVISION,
|
||||||
|
iconSize: [24, 32],
|
||||||
|
iconAnchor: [12, 32]
|
||||||
|
}),
|
||||||
|
iconRed: L.icon({
|
||||||
|
iconUrl: STATIC_ROOT + '/img/markers/marker-red.svg?rev=' + REVISION,
|
||||||
|
iconSize: [24, 32],
|
||||||
|
iconAnchor: [12, 32]
|
||||||
|
}),
|
||||||
|
iconBlue: L.icon({
|
||||||
|
iconUrl: STATIC_ROOT + '/img/markers/marker-blue.svg?rev=' + REVISION,
|
||||||
|
iconSize: [24, 32],
|
||||||
|
iconAnchor: [12, 32]
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
MapEditor.map.on('click', function (e) {
|
init: function (divId, places) {
|
||||||
var marker = L.marker(e.latlng, {
|
document.getElementById(divId).style.display = "block";
|
||||||
icon: IconCollection.iconBlue,
|
|
||||||
zIndexOffset: 2000
|
if (!LMapWrapper.map) {
|
||||||
})
|
LMapWrapper.divId = divId;
|
||||||
.addTo(MapEditor.map)
|
LMapWrapper.map = L.map(LMapWrapper.divId, {
|
||||||
.on('click', function () {
|
zoomControl: false
|
||||||
|
});
|
||||||
|
|
||||||
|
LMapWrapper.map.on('click', function (e) {
|
||||||
|
LMapWrapper.placeMarker(e.latlng);
|
||||||
|
});
|
||||||
|
|
||||||
|
var highResData = Util.getHighResData();
|
||||||
|
|
||||||
|
L.tileLayer(tileUrl, {
|
||||||
|
attribution: tileAttribution,
|
||||||
|
subdomains: '1234',
|
||||||
|
ppi: highResData.ppi,
|
||||||
|
tileSize: highResData.tileSize,
|
||||||
|
zoomOffset: highResData.zoomOffset,
|
||||||
|
minZoom: highResData.minZoom,
|
||||||
|
maxZoom: highResData.maxZoom
|
||||||
|
}).addTo(LMapWrapper.map);
|
||||||
|
|
||||||
|
LMapWrapper.map.fitBounds(L.latLngBounds({ lat: mapBounds.south, lng: mapBounds.west }, { lat: mapBounds.north, lng: mapBounds.east }));
|
||||||
|
}
|
||||||
|
|
||||||
|
LMapWrapper.loadMarkers(places);
|
||||||
|
|
||||||
|
document.getElementById('streetViewCoverSelector').disabled = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
hide: function () {
|
||||||
|
document.getElementById(LMapWrapper.divId).style.display = 'none';
|
||||||
|
},
|
||||||
|
|
||||||
|
loadMarkers: function (places) {
|
||||||
|
if (!LMapWrapper.markers) {
|
||||||
|
LMapWrapper.markers = L.markerClusterGroup({
|
||||||
|
maxClusterRadius: 50
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
LMapWrapper.markers.clearLayers();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var placeId in places) {
|
||||||
|
if (!places.hasOwnProperty(placeId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var place = places[placeId];
|
||||||
|
|
||||||
|
var marker = L.marker({ lat: place.lat, lng: place.lng }, {
|
||||||
|
icon: place.noPano ? LMapWrapper.iconCollection.iconRed : LMapWrapper.iconCollection.iconGreen,
|
||||||
|
zIndexOffset: 1000
|
||||||
|
})
|
||||||
|
.addTo(LMapWrapper.markers)
|
||||||
|
.on('click', function () {
|
||||||
|
MapEditor.select(this);
|
||||||
|
});
|
||||||
|
|
||||||
|
marker.placeId = placeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
LMapWrapper.map.addLayer(LMapWrapper.markers);
|
||||||
|
},
|
||||||
|
|
||||||
|
// TODO: check whether marker is already existing on the map for the coordinates
|
||||||
|
// or alternatively block saving for matching coordinates
|
||||||
|
placeMarker: function (latLng) {
|
||||||
|
var marker = L.marker(latLng, {
|
||||||
|
icon: LMapWrapper.iconCollection.iconBlue,
|
||||||
|
zIndexOffset: 2000
|
||||||
|
})
|
||||||
|
.addTo(LMapWrapper.markers)
|
||||||
|
.on('click', function () {
|
||||||
|
MapEditor.select(this);
|
||||||
|
});
|
||||||
|
|
||||||
|
MapEditor.select(marker);
|
||||||
|
},
|
||||||
|
|
||||||
|
panTo: function (latLng) {
|
||||||
|
LMapWrapper.map.panTo(latLng);
|
||||||
|
},
|
||||||
|
|
||||||
|
resize: function () {
|
||||||
|
LMapWrapper.map.invalidateSize(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
changeMarkerIcon: function (marker, icon) {
|
||||||
|
marker.setIcon(icon);
|
||||||
|
marker.setZIndexOffset(2000);
|
||||||
|
},
|
||||||
|
|
||||||
|
removeMarker: function (marker) {
|
||||||
|
LMapWrapper.markers.removeLayer(marker);
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleStreetViewCover: function () { }
|
||||||
|
};
|
||||||
|
|
||||||
|
var GMapWrapper = {
|
||||||
|
map: null,
|
||||||
|
markers: null,
|
||||||
|
divId: null,
|
||||||
|
streetViewCover: null,
|
||||||
|
streetViewCoverOn: false,
|
||||||
|
iconCollection: {
|
||||||
|
iconGreen: {
|
||||||
|
url: STATIC_ROOT + '/img/markers/marker-green.svg?rev' + REVISION,
|
||||||
|
scaledSize: new google.maps.Size(24, 32), // scaled size
|
||||||
|
origin: new google.maps.Point(0, 0), // origin
|
||||||
|
anchor: new google.maps.Point(12, 32) // anchor
|
||||||
|
},
|
||||||
|
iconRed: {
|
||||||
|
url: STATIC_ROOT + '/img/markers/marker-red.svg?rev' + REVISION,
|
||||||
|
scaledSize: new google.maps.Size(24, 32), // scaled size
|
||||||
|
origin: new google.maps.Point(0, 0), // origin
|
||||||
|
anchor: new google.maps.Point(12, 32) // anchor
|
||||||
|
},
|
||||||
|
iconBlue: {
|
||||||
|
url: STATIC_ROOT + '/img/markers/marker-blue.svg?rev' + REVISION,
|
||||||
|
scaledSize: new google.maps.Size(24, 32), // scaled size
|
||||||
|
origin: new google.maps.Point(0, 0), // origin
|
||||||
|
anchor: new google.maps.Point(12, 32) // anchor
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function (divId, places) {
|
||||||
|
document.getElementById(divId).style.display = "block";
|
||||||
|
|
||||||
|
if (!GMapWrapper.map) {
|
||||||
|
GMapWrapper.divId = divId;
|
||||||
|
GMapWrapper.map = new google.maps.Map(document.getElementById(GMapWrapper.divId), {
|
||||||
|
center: { lat: 0., lng: 0. },
|
||||||
|
zoom: 2,
|
||||||
|
fullscreenControl: false,
|
||||||
|
zoomControl: true,
|
||||||
|
zoomControlOptions: {
|
||||||
|
position: google.maps.ControlPosition.LEFT_BOTTOM
|
||||||
|
},
|
||||||
|
streetViewControl: true,
|
||||||
|
streetViewControlOptions: {
|
||||||
|
position: google.maps.ControlPosition.LEFT_BOTTOM
|
||||||
|
},
|
||||||
|
draggableCursor: 'crosshair'
|
||||||
|
});
|
||||||
|
|
||||||
|
GMapWrapper.streetViewCover = new google.maps.StreetViewCoverageLayer();
|
||||||
|
|
||||||
|
GMapWrapper.map.addListener('click', function (mapsMouseEvent) {
|
||||||
|
GMapWrapper.placeMarker({
|
||||||
|
lat: mapsMouseEvent.latLng.lat(),
|
||||||
|
lng: mapsMouseEvent.latLng.lng()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GMapWrapper.loadMarkers(places);
|
||||||
|
|
||||||
|
document.getElementById('streetViewCoverSelector').disabled = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
hide: function () {
|
||||||
|
document.getElementById(GMapWrapper.divId).style.display = 'none';
|
||||||
|
},
|
||||||
|
|
||||||
|
loadMarkers: function (places) {
|
||||||
|
if (!GMapWrapper.markers) {
|
||||||
|
GMapWrapper.markers = new MarkerClusterer(GMapWrapper.map, [], {
|
||||||
|
imagePath: STATIC_ROOT + '/img/markers/m',
|
||||||
|
imageExtension: 'png?rev' + REVISION
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
GMapWrapper.markers.clearMarkers();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var placeId in places) {
|
||||||
|
if (!places.hasOwnProperty(placeId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var place = places[placeId];
|
||||||
|
|
||||||
|
var marker = new google.maps.Marker({
|
||||||
|
position: {
|
||||||
|
lat: place.lat,
|
||||||
|
lng: place.lng
|
||||||
|
},
|
||||||
|
icon: place.noPano ? GMapWrapper.iconCollection.iconRed : GMapWrapper.iconCollection.iconGreen
|
||||||
|
});
|
||||||
|
|
||||||
|
marker.getLatLng = function () { return { lat: this.getPosition().lat(), lng: this.getPosition().lng() } };
|
||||||
|
marker.setLatLng = function (coords) { this.setPosition(coords) };
|
||||||
|
|
||||||
|
marker.addListener('click', function () {
|
||||||
|
MapEditor.select(this);
|
||||||
|
});
|
||||||
|
|
||||||
|
marker.placeId = placeId;
|
||||||
|
|
||||||
|
GMapWrapper.markers.addMarker(marker);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// TODO: check whether marker is already existing on the map for the coordinates
|
||||||
|
// or alternatively block saving for matching coordinates
|
||||||
|
placeMarker: function (latLng) {
|
||||||
|
var marker = new google.maps.Marker({
|
||||||
|
map: GMapWrapper.map,
|
||||||
|
position: latLng,
|
||||||
|
icon: GMapWrapper.iconCollection.iconBlue,
|
||||||
|
});
|
||||||
|
|
||||||
|
marker.getLatLng = function () { return { lat: this.getPosition().lat(), lng: this.getPosition().lng() } };
|
||||||
|
marker.setLatLng = function (coords) { this.setPosition(coords) };
|
||||||
|
|
||||||
|
marker.addListener('click', function () {
|
||||||
MapEditor.select(this);
|
MapEditor.select(this);
|
||||||
});
|
});
|
||||||
|
|
||||||
MapEditor.select(marker);
|
GMapWrapper.markers.addMarker(marker);
|
||||||
});
|
|
||||||
|
|
||||||
var highResData = Util.getHighResData();
|
MapEditor.select(marker);
|
||||||
|
},
|
||||||
|
|
||||||
L.tileLayer(tileUrl, {
|
panTo: function (latLng) {
|
||||||
attribution: tileAttribution,
|
GMapWrapper.map.panTo(latLng);
|
||||||
subdomains: '1234',
|
},
|
||||||
ppi: highResData.ppi,
|
|
||||||
tileSize: highResData.tileSize,
|
|
||||||
zoomOffset: highResData.zoomOffset,
|
|
||||||
minZoom: highResData.minZoom,
|
|
||||||
maxZoom: highResData.maxZoom
|
|
||||||
}).addTo(MapEditor.map);
|
|
||||||
|
|
||||||
MapEditor.map.fitBounds(L.latLngBounds({ lat: mapBounds.south, lng: mapBounds.west }, { lat: mapBounds.north, lng: mapBounds.east }));
|
resize: function () {
|
||||||
|
google.maps.event.trigger(GMapWrapper.map, 'resize');
|
||||||
|
},
|
||||||
|
|
||||||
MapEditor.markers = L.markerClusterGroup({
|
changeMarkerIcon: function (marker, icon) {
|
||||||
maxClusterRadius: 50
|
marker.setIcon(icon);
|
||||||
});
|
},
|
||||||
|
|
||||||
for (var placeId in places) {
|
removeMarker: function (marker) {
|
||||||
if (!places.hasOwnProperty(placeId)) {
|
GMapWrapper.markers.removeMarker(marker);
|
||||||
continue;
|
},
|
||||||
|
|
||||||
|
toggleStreetViewCover: function () {
|
||||||
|
if (GMapWrapper.streetViewCoverOn) {
|
||||||
|
GMapWrapper.streetViewCover.setMap(null);
|
||||||
|
GMapWrapper.streetViewCoverOn = false;
|
||||||
|
} else {
|
||||||
|
GMapWrapper.streetViewCover.setMap(GMapWrapper.map);
|
||||||
|
GMapWrapper.streetViewCoverOn = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var place = places[placeId];
|
// initialize content of #map with google maps
|
||||||
|
MapEditor.map = GMapWrapper;
|
||||||
var marker = L.marker({ lat: place.lat, lng: place.lng }, {
|
MapEditor.map.init('gmap', places);
|
||||||
icon: place.noPano ? IconCollection.iconRed : IconCollection.iconGreen,
|
|
||||||
zIndexOffset: 1000
|
|
||||||
})
|
|
||||||
.addTo(MapEditor.markers)
|
|
||||||
.on('click', function () {
|
|
||||||
MapEditor.select(this);
|
|
||||||
});
|
|
||||||
|
|
||||||
marker.placeId = place.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
MapEditor.map.addLayer(MapEditor.markers);
|
|
||||||
|
|
||||||
MapEditor.panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), {
|
MapEditor.panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), {
|
||||||
// switch off fullscreenControl because positioning doesn't work
|
// switch off fullscreenControl because positioning doesn't work
|
||||||
@@ -440,4 +671,48 @@
|
|||||||
document.getElementById('deleteButton').onclick = function () {
|
document.getElementById('deleteButton').onclick = function () {
|
||||||
MapEditor.deletePlace();
|
MapEditor.deletePlace();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
document.getElementById('jumpButton').onclick = function (e) {
|
||||||
|
var coordinatesStr = document.getElementById("jumpCoordinates").value;
|
||||||
|
var coordinates = Util.extractCoordinates(coordinatesStr);
|
||||||
|
|
||||||
|
if (coordinates.valid) {
|
||||||
|
MapEditor.map.placeMarker(coordinates.latlng);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById('jumpCoordinates').onkeyup = function (e) {
|
||||||
|
var coordinatesStr = document.getElementById("jumpCoordinates").value;
|
||||||
|
var coordinates = Util.extractCoordinates(coordinatesStr);
|
||||||
|
var jumpButton = document.getElementById("jumpButton");
|
||||||
|
|
||||||
|
if (coordinates.valid) {
|
||||||
|
jumpButton.disabled = false;
|
||||||
|
|
||||||
|
if (e.key == 'Enter') {
|
||||||
|
MapEditor.map.placeMarker(coordinates.latlng);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
jumpButton.disabled = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById('mapSelector').onclick = function () {
|
||||||
|
MapEditor.closePlace();
|
||||||
|
MapEditor.map.hide();
|
||||||
|
|
||||||
|
if (MapEditor.map === GMapWrapper) {
|
||||||
|
MapEditor.map = LMapWrapper;
|
||||||
|
MapEditor.map.init('lmap', places);
|
||||||
|
} else {
|
||||||
|
MapEditor.map = GMapWrapper;
|
||||||
|
MapEditor.map.init('gmap', places);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('streetViewCoverSelector').onclick = function () {
|
||||||
|
MapEditor.map.toggleStreetViewCover();
|
||||||
|
}
|
||||||
|
|
||||||
})();
|
})();
|
||||||
@@ -59,10 +59,25 @@ def getRevisionForRef(ref):
|
|||||||
return subprocess.check_output(["git", "rev-list", "-1", ref], cwd=REPO).decode().strip()
|
return subprocess.check_output(["git", "rev-list", "-1", ref], cwd=REPO).decode().strip()
|
||||||
|
|
||||||
def getLatestReleaseTag():
|
def getLatestReleaseTag():
|
||||||
return subprocess.check_output(["git", "for-each-ref", "refs/tags/Release*", "--count=1", "--sort=-creatordate", "--format=%(refname:short)"], cwd=REPO).decode().strip()
|
process = subprocess.Popen(["git", "for-each-ref", "refs/tags/Release*", "--sort=-creatordate", "--format=%(refname:short)"], stdout=subprocess.PIPE, cwd=REPO)
|
||||||
|
|
||||||
|
for line in process.stdout:
|
||||||
|
tag = line.decode().rstrip()
|
||||||
|
|
||||||
|
if isTagVerified(tag):
|
||||||
|
return tag
|
||||||
|
|
||||||
|
print(f"[WARNING] Tag '{tag}' is not verified, skipping.")
|
||||||
|
|
||||||
|
raise Exception("No verified 'Release*' tag found!")
|
||||||
|
|
||||||
|
def isTagVerified(tag):
|
||||||
|
process = subprocess.run(["git", "tag", "--verify", tag], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=REPO)
|
||||||
|
|
||||||
|
return process.returncode == 0
|
||||||
|
|
||||||
def updateRepoFromRemote():
|
def updateRepoFromRemote():
|
||||||
subprocess.call(["git", "fetch", "origin", "--prune"], cwd=REPO)
|
subprocess.call(["git", "fetch", "origin", "--prune", "--prune-tags"], cwd=REPO)
|
||||||
|
|
||||||
def checkoutWorktree(worktreePath, ref):
|
def checkoutWorktree(worktreePath, ref):
|
||||||
subprocess.call(["git", "checkout", "-f", ref], cwd=worktreePath)
|
subprocess.call(["git", "checkout", "-f", ref], cwd=worktreePath)
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ echo "Installing Yarn packages..."
|
|||||||
(cd ${ROOT_DIR}/public/static && yarn install)
|
(cd ${ROOT_DIR}/public/static && yarn install)
|
||||||
|
|
||||||
echo "Installing MapGuesser DB..."
|
echo "Installing MapGuesser DB..."
|
||||||
mysql --host=${DB_HOST} --user=${DB_USER} --password=${DB_PASSWORD} ${DB_NAME} < ${ROOT_DIR}/db/mapguesser.sql
|
mysql --host=${DB_HOST} --user=${DB_USER} --password=${DB_PASSWORD} ${DB_NAME} < ${ROOT_DIR}/database/mapguesser.sql
|
||||||
|
|
||||||
echo "Migrating DB..."
|
echo "Migrating DB..."
|
||||||
(cd ${ROOT_DIR} && ./mapg db:migrate)
|
(cd ${ROOT_DIR} && ./mapg db:migrate)
|
||||||
|
|||||||
@@ -92,6 +92,9 @@ class GameController
|
|||||||
'rounds' => [],
|
'rounds' => [],
|
||||||
'currentRound' => -1
|
'currentRound' => -1
|
||||||
]);
|
]);
|
||||||
|
} else { // update the area of the map in the session in any case
|
||||||
|
$state['area'] = $map->getArea();
|
||||||
|
$session->set('state', $state);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new JsonContent([
|
return new JsonContent([
|
||||||
|
|||||||
@@ -61,9 +61,11 @@ class GameFlowController
|
|||||||
$round = $state['rounds'][$i];
|
$round = $state['rounds'][$i];
|
||||||
$response['history'][] = [
|
$response['history'][] = [
|
||||||
'position' => $round['position']->toArray(),
|
'position' => $round['position']->toArray(),
|
||||||
'guessPosition' => $round['guessPosition']->toArray(),
|
'result' => [
|
||||||
'distance' => $round['distance'],
|
'guessPosition' => $round['guessPosition']->toArray(),
|
||||||
'score' => $round['score']
|
'distance' => $round['distance'],
|
||||||
|
'score' => $round['score']
|
||||||
|
]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,11 +128,8 @@ class GameFlowController
|
|||||||
$last['score'] = $result['score'];
|
$last['score'] = $result['score'];
|
||||||
|
|
||||||
$response = [
|
$response = [
|
||||||
'result' => [
|
'position' => $last['position']->toArray(),
|
||||||
'position' => $last['position']->toArray(),
|
'result' => $result
|
||||||
'distance' => $result['distance'],
|
|
||||||
'score' => $result['score']
|
|
||||||
]
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$state['rounds'][$state['currentRound']] = $last;
|
$state['rounds'][$state['currentRound']] = $last;
|
||||||
@@ -165,20 +164,22 @@ class GameFlowController
|
|||||||
$guessPosition = new Position((float) $this->request->post('lat'), (float) $this->request->post('lng'));
|
$guessPosition = new Position((float) $this->request->post('lat'), (float) $this->request->post('lng'));
|
||||||
$result = $this->evalueteGuess($last['position'], $guessPosition, $state['area']);
|
$result = $this->evalueteGuess($last['position'], $guessPosition, $state['area']);
|
||||||
|
|
||||||
$this->multiConnector->sendMessage('guess', [
|
$responseFromMulti = $this->multiConnector->sendMessage('guess', [
|
||||||
'roomId' => $roomId,
|
'roomId' => $roomId,
|
||||||
'token' => $multiState['token'],
|
'token' => $multiState['token'],
|
||||||
'guess' => $guessPosition->toArray(),
|
'guessPosition' => $guessPosition->toArray(),
|
||||||
'distance' => $result['distance'],
|
'distance' => $result['distance'],
|
||||||
'score' => $result['score']
|
'score' => $result['score']
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (isset($responseFromMulti['error'])) {
|
||||||
|
return new JsonContent(['error' => $responseFromMulti['error']]);
|
||||||
|
}
|
||||||
|
|
||||||
$response = [
|
$response = [
|
||||||
'result' => [
|
'position' => $last['position']->toArray(),
|
||||||
'position' => $last['position']->toArray(),
|
'result' => $result,
|
||||||
'distance' => $result['distance'],
|
'allResults' => $responseFromMulti['allResults']
|
||||||
'score' => $result['score']
|
|
||||||
]
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return new JsonContent($response);
|
return new JsonContent($response);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
class MultiConnector
|
class MultiConnector
|
||||||
{
|
{
|
||||||
public function sendMessage(string $func, array $args = []): void
|
public function sendMessage(string $func, array $args = [])
|
||||||
{
|
{
|
||||||
$message = json_encode([
|
$message = json_encode([
|
||||||
'func' => $func,
|
'func' => $func,
|
||||||
@@ -17,8 +17,6 @@ class MultiConnector
|
|||||||
}
|
}
|
||||||
fclose($connection);
|
fclose($connection);
|
||||||
|
|
||||||
if ($response !== 'OK') {
|
return json_decode($response, true);
|
||||||
throw new \Exception('Sending message failed with response: ' . $response);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,12 +6,27 @@
|
|||||||
@js(node_modules/leaflet/dist/leaflet.js)
|
@js(node_modules/leaflet/dist/leaflet.js)
|
||||||
@js(node_modules/leaflet.markercluster/dist/leaflet.markercluster.js)
|
@js(node_modules/leaflet.markercluster/dist/leaflet.markercluster.js)
|
||||||
@js(https://maps.googleapis.com/maps/api/js?key=<?= $_ENV['GOOGLE_MAPS_JS_API_KEY'] ?>)
|
@js(https://maps.googleapis.com/maps/api/js?key=<?= $_ENV['GOOGLE_MAPS_JS_API_KEY'] ?>)
|
||||||
|
@js(https://unpkg.com/@googlemaps/markerclustererplus/dist/index.min.js)
|
||||||
@js(js/map_editor.js)
|
@js(js/map_editor.js)
|
||||||
|
|
||||||
@extends(templates/layout_full)
|
@extends(templates/layout_full)
|
||||||
|
|
||||||
@section(subheader)
|
@section(subheader)
|
||||||
<span><a href="javascript:;" id="mapName" title="Edit map data"><?= $mapName ?></a></span><!--
|
<span><a href="javascript:;" id="mapName" title="Edit map data"><?= $mapName ?></a></span><!--
|
||||||
|
--><span class="inline hideOnMobile" id="mapSelection">
|
||||||
|
<button id="mapSelector">
|
||||||
|
<img src="<?= $_ENV['STATIC_ROOT'] ?>/img/map.svg?rev=<?= REVISION ?>" alt="Map Selector" />
|
||||||
|
</button>
|
||||||
|
</span><!--
|
||||||
|
--><span class="inline hideOnMobile" id="mapSelection">
|
||||||
|
<button id="streetViewCoverSelector">
|
||||||
|
<img src="<?= $_ENV['STATIC_ROOT'] ?>/img/street-view-cover.svg?rev=<?= REVISION ?>" alt="Street View Conver" />
|
||||||
|
</button>
|
||||||
|
</span><!--
|
||||||
|
--><span class="inline hideOnMobile">
|
||||||
|
<input type="text" id="jumpCoordinates" placeholder="Insert coordinates here" />
|
||||||
|
<button id="jumpButton" disabled >Jump</button>
|
||||||
|
</span><!--
|
||||||
--><span><!--
|
--><span><!--
|
||||||
<?php /* Copyright (c) 2019 The Bootstrap Authors. License can be found in 'USED_SOFTWARE' in section 'Bootstrap Icons'. */ ?>
|
<?php /* Copyright (c) 2019 The Bootstrap Authors. License can be found in 'USED_SOFTWARE' in section 'Bootstrap Icons'. */ ?>
|
||||||
--><svg class="inline" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
--><svg class="inline" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||||
@@ -53,7 +68,10 @@
|
|||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section(main)
|
@section(main)
|
||||||
<div id="map"></div>
|
<div id="map" class="map">
|
||||||
|
<div id="lmap" class="map"></div>
|
||||||
|
<div id="gmap" class="map"></div>
|
||||||
|
</div>
|
||||||
<div id="panorama"></div>
|
<div id="panorama"></div>
|
||||||
<div id="noPano">
|
<div id="noPano">
|
||||||
<p class="bold">No panorama is available for this location.</p>
|
<p class="bold">No panorama is available for this location.</p>
|
||||||
|
|||||||
+15
-1
@@ -15,12 +15,15 @@
|
|||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section(subheader)
|
@section(subheader)
|
||||||
<span id="mapName" class="bold"></span><!--
|
<span id="mapName" class="bold">Loading map...</span><!--
|
||||||
--><span>Round <span id="currentRound" class="bold"></span></span><!--
|
--><span>Round <span id="currentRound" class="bold"></span></span><!--
|
||||||
--><span>Score <span id="currentScoreSum" class="bold"></span></span>
|
--><span>Score <span id="currentScoreSum" class="bold"></span></span>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section(main)
|
@section(main)
|
||||||
|
<div id="countdown">
|
||||||
|
<p id="countdownTime" class="mono bold"></p>
|
||||||
|
</div>
|
||||||
<div id="panoCover"></div>
|
<div id="panoCover"></div>
|
||||||
<div id="panorama"></div>
|
<div id="panorama"></div>
|
||||||
<div id="showGuessButtonContainer">
|
<div id="showGuessButtonContainer">
|
||||||
@@ -37,6 +40,7 @@
|
|||||||
<div id="resultInfo">
|
<div id="resultInfo">
|
||||||
<div id="distanceInfo">
|
<div id="distanceInfo">
|
||||||
<p>You were <span id="distance" class="bold"></span> close.</p>
|
<p>You were <span id="distance" class="bold"></span> close.</p>
|
||||||
|
<p>You didn't guess in this round.</p>
|
||||||
<p class="bold">Game finished.</p>
|
<p class="bold">Game finished.</p>
|
||||||
</div>
|
</div>
|
||||||
<div id="scoreInfo">
|
<div id="scoreInfo">
|
||||||
@@ -55,6 +59,16 @@
|
|||||||
<button id="startNewGameButton" class="fullWidth">Play this map again</button>
|
<button id="startNewGameButton" class="fullWidth">Play this map again</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="navigation">
|
||||||
|
<div id="returnToStart" class="navigationItem">
|
||||||
|
<div>
|
||||||
|
<img src="<?= $_ENV['STATIC_ROOT'] ?>/img/circle_background.svg?rev=<?= REVISION ?>" alt="Circle Background" class="circleBackground" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<img src="<?= $_ENV['STATIC_ROOT'] ?>/img/house-fill.svg?rev=<?= REVISION ?>" alt="Return to Start icon" class="navigationIcon" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section(pageScript)
|
@section(pageScript)
|
||||||
|
|||||||
@@ -29,6 +29,6 @@
|
|||||||
</main>
|
</main>
|
||||||
<footer>
|
<footer>
|
||||||
<p><span class="bold"><?= $_ENV['APP_NAME'] ?></span> <?= str_replace('Release_', '', VERSION) ?></p><!--
|
<p><span class="bold"><?= $_ENV['APP_NAME'] ?></span> <?= str_replace('Release_', '', VERSION) ?></p><!--
|
||||||
--><p>© Pőcze Bence <?= (new DateTime(REVISION_DATE))->format('Y') ?></p>
|
--><p>© The MapGuesser Contributors <?= (new DateTime(REVISION_DATE))->format('Y') ?></p>
|
||||||
</footer>
|
</footer>
|
||||||
@endsection
|
@endsection
|
||||||
Reference in new issue
Block a user