Merge pull request 'feature/MAPG-204-show-guesses-from-others' (#14) from feature/MAPG-204-show-guesses-from-others into develop
All checks were successful
default-pipeline default-pipeline #76

Reviewed-on: https://gitea.e5tv.hu/esoko/mapguesser/pulls/14
This commit is contained in:
Bence Pőcze 2021-04-03 22:13:52 +02:00 committed by Gitea
commit d3a12fb6f1
No known key found for this signature in database
GPG Key ID: 2E27A8C281A1CC2C
5 changed files with 164 additions and 106 deletions

View File

@ -2,12 +2,6 @@
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 {
constructor() { constructor() {
this.rooms = new Map(); this.rooms = new Map();
@ -32,7 +26,7 @@ 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) {
@ -58,7 +52,7 @@ 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 });
} }
startGame(roomId, places) { startGame(roomId, places) {
@ -92,14 +86,14 @@ class MultiGame {
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); var member = room.members.get(token);
var allResults = this._collectResultsInRound(room, round);
this._sendResultsUntilNow(room, member);
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 });
return allResults;
} }
nextRound(roomId, currentRound) { nextRound(roomId, currentRound) {
@ -126,12 +120,10 @@ class MultiGame {
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;
}); });
} }
_sendInitialData(room, member) { _sendInitialData(room, member, token) {
var data = {}; var data = {};
if (room.currentRound >= 0) { if (room.currentRound >= 0) {
@ -141,18 +133,23 @@ 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];
var result;
if (round.results.has(member.userName)) { var result = { guessPosition: null, distance: null, score: 0 };
result = round.results.get(member.userName); var allResults = [];
} else {
result = { guessPosition: null, distance: null, score: 0 }; 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
}); });
} }
@ -164,30 +161,30 @@ class MultiGame {
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;
} }
_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 +221,35 @@ var tcpServer = net.createServer(function (socket) {
return; return;
} }
var response = { data: null };
switch (data.func) { switch (data.func) {
case 'create_room': case 'create_room':
multiGame.createRoom(data.args.roomId); response.data = 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.data = 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.data = 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.data = 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.data = multiGame.nextRound(data.args.roomId, data.args.currentRound);
break; break;
} }
socket.write('OK'); socket.write(JSON.stringify(response));
socket.end(); socket.end();
}); });
}); });

View File

@ -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

View File

@ -66,12 +66,8 @@
Game.MultiConnector.newRound(json.data); Game.MultiConnector.newRound(json.data);
break; break;
case 'results':
//TODO
break;
case 'guess': case 'guess':
//TODO Game.MultiConnector.guess(json.data);
break; break;
} }
}; };
@ -94,9 +90,17 @@
if (data.history) { if (data.history) {
for (var i = 0; i < data.history.length; ++i) { for (var i = 0; i < data.history.length; ++i) {
var round = data.history[i]; var round = data.history[i];
Game.rounds.push({ position: round.position, guessPosition: round.guessPosition, realMarker: null, guessMarker: null, line: null }); Game.rounds.push({ position: round.position, guessPosition: round.result.guessPosition, realMarker: null, guessMarkers: [] });
Game.addRealGuessPair(round.position, round.guessPosition, true); Game.addPositionToResultMap(true);
Game.scoreSum += round.score; 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];
Game.addGuessPositionToResultMap(result.guessPosition, result, true);
}
} }
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);
@ -147,7 +151,7 @@
// if player didn't guess - TODO: show everything on a map // if player didn't guess - TODO: show everything on a map
if (data.result && Game.rounds.length > 0 && !Game.rounds[Game.rounds.length - 1].position) { 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.rounds[Game.rounds.length - 1].position = data.result.position;
Game.addRealGuessPair(data.result.position, null); Game.addPositionToResultMap();
} }
Game.panoId = data.place.panoId; Game.panoId = data.place.panoId;
@ -156,6 +160,15 @@
document.getElementById('multi').style.visibility = 'hidden'; document.getElementById('multi').style.visibility = 'hidden';
Game.resetRound(); Game.resetRound();
Game.startNewRound(); Game.startNewRound();
},
guess: function (data) {
var resultBounds = Game.map.getBounds();
Game.addGuessPositionToResultMap(data.guessPosition, data);
resultBounds.extend(data.guessPosition);
Game.map.fitBounds(resultBounds);
} }
}, },
@ -234,9 +247,10 @@
if (this.response.history) { 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.guessPosition, realMarker: null, guessMarker: null, line: null }); Game.rounds.push({ position: round.position, guessPosition: round.result.guessPosition, realMarker: null, guessMarkers: [] });
Game.addRealGuessPair(round.position, round.guessPosition, true); Game.addPositionToResultMap(true);
Game.scoreSum += round.score; Game.addGuessPositionToResultMap(round.result.guessPosition, null, true);
Game.scoreSum += round.result.score;
} }
document.getElementById('currentRound').innerHTML = String(Game.rounds.length) + '/' + String(Game.NUMBER_OF_ROUNDS); document.getElementById('currentRound').innerHTML = String(Game.rounds.length) + '/' + String(Game.NUMBER_OF_ROUNDS);
@ -259,9 +273,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();
}
} }
} }
@ -291,10 +309,15 @@
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';
@ -316,7 +339,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);
@ -356,7 +379,7 @@
Game.panorama.setPano(panoId); Game.panorama.setPano(panoId);
}, },
evaluateGuess: function () { guess: function () {
if (!Game.guessMarker) { if (!Game.guessMarker) {
return; return;
} }
@ -392,13 +415,22 @@
Game.scoreSum += this.response.result.score; Game.scoreSum += this.response.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);
Game.rounds[Game.rounds.length - 1].position = this.response.result.position;
Game.addRealGuessPair(this.response.result.position, guessPosition);
var resultBounds = new google.maps.LatLngBounds(); var resultBounds = new google.maps.LatLngBounds();
resultBounds.extend(this.response.result.position);
Game.rounds[Game.rounds.length - 1].position = this.response.position;
Game.addPositionToResultMap();
resultBounds.extend(this.response.position);
Game.addGuessPositionToResultMap(guessPosition);
resultBounds.extend(guessPosition); resultBounds.extend(guessPosition);
if (roomId) {
for (var i = 0; i < this.response.allResults.length; ++i) {
var result = this.response.allResults[i];
Game.addGuessPositionToResultMap(result.guessPosition, result);
resultBounds.extend(result.guessPosition);
}
}
Game.map.setOptions({ Game.map.setOptions({
draggableCursor: 'grab' draggableCursor: 'grab'
}); });
@ -431,8 +463,9 @@
}, 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,
@ -453,20 +486,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),
@ -477,11 +515,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: [
@ -504,6 +542,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) {
@ -555,14 +606,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());
} }
} }
@ -639,7 +690,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),
@ -687,7 +738,7 @@
} }
document.getElementById('guessButton').onclick = function () { document.getElementById('guessButton').onclick = function () {
Game.evaluateGuess(); Game.guess();
} }
document.getElementById('continueButton').onclick = function () { document.getElementById('continueButton').onclick = function () {

View File

@ -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,18 @@ 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', [ $allResults = $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']
]); ]);
$response = [ $response = [
'result' => [ 'position' => $last['position']->toArray(),
'position' => $last['position']->toArray(), 'result' => $result,
'distance' => $result['distance'], 'allResults' => $allResults
'score' => $result['score']
]
]; ];
return new JsonContent($response); return new JsonContent($response);

View File

@ -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,10 @@ class MultiConnector
} }
fclose($connection); fclose($connection);
if ($response !== 'OK') { $response = json_decode($response, true);
throw new \Exception('Sending message failed with response: ' . $response);
if (isset($response['data'])) {
return $response['data'];
} }
} }
} }