Compare commits

..
Author SHA1 Message Date
bence 1a40e3a18d Merge pull request 'MAPG-226 change remaining time calculation' (#21) from feature/MAPG-226-change-timeout-algorithm into develop
default-pipeline default-pipeline #106
Reviewed-on: https://gitea.e5tv.hu/esoko/mapguesser/pulls/21
2021-04-10 19:00:20 +02:00
bence 1aa5d3b43e MAPG-226 change remaining time calculation 2021-04-10 18:59:27 +02:00
bence a418d5cf66 Merge pull request 'MAPG-213 move visibility workaround to Game.showResultMap' (#20) from bugfix/MAPG-213-result-map-not-show-on-mobile-after-reload into develop
Reviewed-on: https://gitea.e5tv.hu/esoko/mapguesser/pulls/20
2021-04-04 23:41:05 +02:00
bence 5cae286a5b MAPG-213 move visibility workaround to Game.showResultMap 2021-04-04 23:40:27 +02:00
bence c5d2591371 Merge pull request 'MAPG-223 send error if member already guessed' (#19) from feature/MAPG-223-user-should-not-be-able-to-guess-after-round-is-over into develop
Reviewed-on: https://gitea.e5tv.hu/esoko/mapguesser/pulls/19
2021-04-04 23:29:04 +02:00
bence cf59f937c9 MAPG-223 send error if member already guessed
default-pipeline default-pipeline #104
2021-04-04 23:28:44 +02:00
bence 257f59c96e Merge pull request 'MAPG-222 fixes: skip invalid guessPosition, hide showSummaryButton, handle countdown time if timeout is 0' (#18) from bugfix/MAPG-222-show-summary-can-be-clicked-when-game-is-restarted into develop
default-pipeline default-pipeline #98
Reviewed-on: https://gitea.e5tv.hu/esoko/mapguesser/pulls/18
2021-04-04 23:05:47 +02:00
bence c2f5806394 MAPG-222 fixes: skip invalid guessPosition, hide showSummaryButton, handle countdown time if timeout is 0
default-pipeline default-pipeline #96
2021-04-04 23:04:07 +02:00
bence ac0b71fe09 Merge pull request 'feature/MAPG-213-user-shouldn-t-be-able-to-re-guess-when-page-is-reloaded' (#17) from feature/MAPG-213-user-shouldn-t-be-able-to-re-guess-when-page-is-reloaded into develop
default-pipeline default-pipeline #94
Reviewed-on: https://gitea.e5tv.hu/esoko/mapguesser/pulls/17
2021-04-04 22:31:29 +02:00
bence 19f7b50002 MAPG-213 show results immediately if user already guessed
default-pipeline default-pipeline #91
2021-04-04 22:24:40 +02:00
bence 6342bb1e79 MAPG-213 send round data at initialization if user guessed 2021-04-04 22:18:00 +02:00
bence 3abdb6910e MAPG-213 clean up init
default-pipeline default-pipeline #90
2021-04-04 20:52:28 +02:00
4 changed files with 146 additions and 97 deletions

No files matched your search

+44 -24
View File
@@ -5,7 +5,7 @@ process.title = 'mapguesser-multi';
class MultiGame { class MultiGame {
static ROUND_TIMEOUT_DEFAULT = 120000; static ROUND_TIMEOUT_DEFAULT = 120000;
static ROUND_TIMEOUT_MINIMUM = 15000; static ROUND_TIMEOUT_MINIMUM = 15000;
static ROUND_TIMEOUT_DIVIDER = 2; static ROUND_TIMEOUT_DIVIDER = 1.5;
static ROUND_TIMEOUT_OFFSET = 500; static ROUND_TIMEOUT_OFFSET = 500;
constructor() { constructor() {
@@ -36,19 +36,20 @@ class MultiGame {
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,13 +59,13 @@ class MultiGame {
}); });
room.members.set(token, { userName: userName, 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);
@@ -84,19 +85,23 @@ class MultiGame {
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];
if (round.results.has(token)) {
return { error: 'already_guessed' };
}
var member = room.members.get(token); var member = room.members.get(token);
var allResults = this._collectResultsInRound(room, round); var allResults = this._collectResultsInRound(room, round);
@@ -106,14 +111,12 @@ class MultiGame {
this._setNewTimeout(room, round); this._setNewTimeout(room, round);
return allResults; 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);
@@ -137,6 +140,8 @@ class MultiGame {
room.members.forEach(function (member) { room.members.forEach(function (member) {
self._sendToMember(member, 'new_round', data); self._sendToMember(member, 'new_round', data);
}); });
return { ok: true };
} }
_setNewTimeout(room, round) { _setNewTimeout(room, round) {
@@ -150,7 +155,7 @@ class MultiGame {
} else { } else {
round.timeout = round.timeout - (new Date() - round.timeoutStarted); round.timeout = round.timeout - (new Date() - round.timeoutStarted);
if (round.timeout > MultiGame.ROUND_TIMEOUT_DIVIDER * MultiGame.ROUND_TIMEOUT_MINIMUM) { if (round.timeout > MultiGame.ROUND_TIMEOUT_DIVIDER * MultiGame.ROUND_TIMEOUT_MINIMUM) {
round.timeout = round.timeout / MultiGame.ROUND_TIMEOUT_DIVIDER; round.timeout = Math.round(round.timeout / MultiGame.ROUND_TIMEOUT_DIVIDER);
} else if (round.timeout > MultiGame.ROUND_TIMEOUT_MINIMUM) { } else if (round.timeout > MultiGame.ROUND_TIMEOUT_MINIMUM) {
round.timeout = MultiGame.ROUND_TIMEOUT_MINIMUM; round.timeout = MultiGame.ROUND_TIMEOUT_MINIMUM;
} }
@@ -165,9 +170,18 @@ class MultiGame {
} }
_endRound(room, round) { _endRound(room, round) {
var data = { position: round.place.position, allResults: this._collectResultsInRound(room, round) }; var allResults = this._collectResultsInRound(room, round);
var self = this; var self = this;
room.members.forEach(function (member) { 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); self._sendToMember(member, 'end_round', data);
}); });
} }
@@ -183,9 +197,13 @@ class MultiGame {
} }
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];
if (i === room.currentRound && !round.results.has(token)) {
continue;
}
var result = { guessPosition: null, distance: null, score: 0 }; var result = { guessPosition: null, distance: null, score: 0 };
var allResults = []; var allResults = [];
@@ -210,6 +228,8 @@ 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);
} }
@@ -280,30 +300,30 @@ var tcpServer = net.createServer(function (socket) {
return; return;
} }
var response = { data: null }; var response;
switch (data.func) { switch (data.func) {
case 'create_room': case 'create_room':
response.data = multiGame.createRoom(data.args.roomId); response = multiGame.createRoom(data.args.roomId);
break; break;
case 'join_room': case 'join_room':
response.data = 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':
response.data = multiGame.startGame(data.args.roomId, data.args.places); response = multiGame.startGame(data.args.roomId, data.args.places);
break break
case 'guess': case 'guess':
response.data = 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':
response.data = multiGame.nextRound(data.args.roomId, data.args.currentRound); response = multiGame.nextRound(data.args.roomId, data.args.currentRound);
break; break;
} }
+95 -66
View File
@@ -97,52 +97,59 @@
}, },
initialize: function (data) { initialize: function (data) {
if (data.history) { if (data.history.length === 0 && !data.place) {
for (var i = 0; i < data.history.length; ++i) { var div = document.getElementById('players');
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) { for (var i = 0; i < data.members.length; ++i) {
var result = round.allResults[j]; 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); 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);
} }
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) { if (data.timeout) {
Game.startCountdown(data.timeout); Game.startCountdown(data.timeout);
} }
if (data.place) { if (data.place) {
Game.readyToContinue = false; 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('multi').style.visibility = 'hidden'; document.getElementById('multi').style.visibility = 'hidden';
document.getElementById('panoCover').style.visibility = 'hidden';
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) {
@@ -195,15 +202,10 @@
return; return;
} }
// TODO: refactor - it is necessary for mobile
if (window.getComputedStyle(document.getElementById('guess')).visibility === 'hidden') {
document.getElementById('showGuessButton').click();
}
document.getElementById('guessButton').disabled = true; document.getElementById('guessButton').disabled = true;
document.getElementById('panoCover').style.visibility = 'visible'; document.getElementById('panoCover').style.visibility = 'visible';
Game.showResults(data.position, null, { distance: NaN, score: 0 }, data.allResults); Game.receiveResult(data.position, data.result.guessPosition, { distance: data.result.distance, score: data.result.score }, data.allResults);
} }
}, },
@@ -253,8 +255,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'
@@ -279,19 +279,17 @@
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.result.guessPosition, realMarker: null, guessMarkers: [] }); Game.addPositionToResultMap(true);
Game.addPositionToResultMap(true); Game.addGuessPositionToResultMap(round.result.guessPosition, null, true);
Game.addGuessPositionToResultMap(round.result.guessPosition, null, true); Game.scoreSum += round.result.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();
}); });
}, },
@@ -329,6 +327,7 @@
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;
@@ -415,18 +414,7 @@
Game.panorama.setPano(panoId); Game.panorama.setPano(panoId);
}, },
showResults: function (position, guessPosition, result, allResults) { receiveResult: function (position, guessPosition, result, allResults) {
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.scoreSum += result.score; Game.scoreSum += result.score;
document.getElementById('currentScoreSum').innerHTML = String(Game.scoreSum) + '/' + String(Game.rounds.length * Game.MAX_SCORE); document.getElementById('currentScoreSum').innerHTML = String(Game.scoreSum) + '/' + String(Game.rounds.length * Game.MAX_SCORE);
@@ -444,18 +432,58 @@
if (allResults) { if (allResults) {
for (var i = 0; i < allResults.length; ++i) { for (var i = 0; i < allResults.length; ++i) {
var currentResult = allResults[i]; var currentResult = allResults[i];
Game.addGuessPositionToResultMap(currentResult.guessPosition, currentResult); if (currentResult.guessPosition) {
resultBounds.extend(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({ Game.map.setOptions({
draggableCursor: 'grab' draggableCursor: 'grab'
}); });
Game.map.fitBounds(resultBounds); Game.map.fitBounds(resultBounds);
var distanceInfo = document.getElementById('distanceInfo'); var distanceInfo = document.getElementById('distanceInfo');
if (Number.isNaN(result.distance)) { if (result.distance === null) {
distanceInfo.children[0].style.display = 'none'; distanceInfo.children[0].style.display = 'none';
distanceInfo.children[1].style.display = 'block'; distanceInfo.children[1].style.display = 'block';
} else { } else {
@@ -510,7 +538,7 @@
return; return;
} }
Game.showResults(this.response.position, guessPosition, this.response.result, this.response.allResults); Game.receiveResult(this.response.position, guessPosition, this.response.result, this.response.allResults);
if (this.response.place) { if (this.response.place) {
Game.panoId = this.response.place.panoId; Game.panoId = this.response.place.panoId;
@@ -712,15 +740,16 @@
clearInterval(Game.countdownHandler); clearInterval(Game.countdownHandler);
} }
Game.countdownElement = document.getElementById('countdown');
Game.countdownTimeElement = document.getElementById('countdownTime');
Game.setCountdownTime(Math.round(timeout / 1000));
if (timeout <= 0) { if (timeout <= 0) {
return; return;
} }
Game.timeoutEnd = new Date(new Date().getTime() + timeout); Game.timeoutEnd = new Date(new Date().getTime() + timeout);
Game.countdownElement = document.getElementById('countdown');
Game.countdownTimeElement = document.getElementById('countdownTime');
Game.setCountdownTime(Math.round(timeout / 1000));
Game.countdownHandler = setInterval(function () { Game.countdownHandler = setInterval(function () {
var timeLeft = Math.round((Game.timeoutEnd - new Date()) / 1000); var timeLeft = Math.round((Game.timeoutEnd - new Date()) / 1000);
+6 -2
View File
@@ -164,7 +164,7 @@ 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']);
$allResults = $this->multiConnector->sendMessage('guess', [ $responseFromMulti = $this->multiConnector->sendMessage('guess', [
'roomId' => $roomId, 'roomId' => $roomId,
'token' => $multiState['token'], 'token' => $multiState['token'],
'guessPosition' => $guessPosition->toArray(), 'guessPosition' => $guessPosition->toArray(),
@@ -172,10 +172,14 @@ class GameFlowController
'score' => $result['score'] 'score' => $result['score']
]); ]);
if (isset($responseFromMulti['error'])) {
return new JsonContent(['error' => $responseFromMulti['error']]);
}
$response = [ $response = [
'position' => $last['position']->toArray(), 'position' => $last['position']->toArray(),
'result' => $result, 'result' => $result,
'allResults' => $allResults 'allResults' => $responseFromMulti['allResults']
]; ];
return new JsonContent($response); return new JsonContent($response);
+1 -5
View File
@@ -17,10 +17,6 @@ class MultiConnector
} }
fclose($connection); fclose($connection);
$response = json_decode($response, true); return json_decode($response, true);
if (isset($response['data'])) {
return $response['data'];
}
} }
} }