Compare commits

...

2 Commits

5 changed files with 119 additions and 54 deletions

View File

@ -20,6 +20,7 @@ const GameType = Object.freeze({ 'SINGLE': 0, 'MULTI': 1, 'CHALLENGE': 2 });
adaptGuess: false,
googleLink: null,
history: [],
restrictions: null,
readyToContinue: true,
timeoutEnd: null,
@ -304,17 +305,7 @@ const GameType = Object.freeze({ 'SINGLE': 0, 'MULTI': 1, 'CHALLENGE': 2 });
} else {
if (this.response.restrictions) {
Game.panorama.setOptions({
clickToGo: !this.response.restrictions.noMove,
linksControl: !this.response.restrictions.noMove,
scrollwheel: !this.response.restrictions.noZoom
});
if (this.response.restrictions.noPan) {
document.getElementById('panningBlockerCover').style.display = 'block';
}
}
Game.restrictions = this.response.restrictions;
Game.panoId = this.response.place.panoId;
Game.pov = this.response.place.pov;
@ -327,6 +318,40 @@ const GameType = Object.freeze({ 'SINGLE': 0, 'MULTI': 1, 'CHALLENGE': 2 });
});
},
enableRestrictions: function () {
if (!Game.restrictions) {
return;
}
Game.panorama.setOptions({
clickToGo: !Game.restrictions.noMove,
linksControl: !(Game.restrictions.noMove || Game.restrictions.noPan),
scrollwheel: !Game.restrictions.noZoom
});
if (Game.restrictions.noPan) {
document.getElementById('panningBlockerCover').style.display = 'block';
}
if (Game.restrictions.timeLimit) {
Game.startCountdown(Game.restrictions.timeLimit, function() {
Game.guess();
});
}
},
disableRestrictions: function () {
Game.panorama.setOptions({
clickToGo: true,
linksControl: true,
scrollwheel: true
});
document.getElementById('panningBlockerCover').style.display = null;
Game.startCountdown(0);
},
transitToResultMap: function () {
// TODO: refactor - it is necessary for mobile
if (window.getComputedStyle(document.getElementById('guess')).visibility === 'hidden') {
@ -452,11 +477,8 @@ const GameType = Object.freeze({ 'SINGLE': 0, 'MULTI': 1, 'CHALLENGE': 2 });
// needs to be set visible after the show guess map hid it in mobile view
document.getElementById("navigation").style.visibility = 'visible';
Game.panorama.setOptions({
clickToGo: true,
linksControl: true,
scrollwheel: true
});
Game.disableRestrictions();
document.getElementById('panningBlockerCover').style.display = null;
Game.initialize();
@ -511,6 +533,8 @@ const GameType = Object.freeze({ 'SINGLE': 0, 'MULTI': 1, 'CHALLENGE': 2 });
// update the compass
const heading = Game.panorama.getPov().heading;
document.getElementById("compass").style.transform = "translateY(-50%) rotate(" + heading + "deg)";
Game.enableRestrictions();
},
handleErrorResponse: function (error) {
@ -625,22 +649,24 @@ const GameType = Object.freeze({ 'SINGLE': 0, 'MULTI': 1, 'CHALLENGE': 2 });
},
guess: function () {
if (!Game.guessMarker) {
return;
}
var guessPosition = Game.guessMarker.getPosition().toJSON();
Game.rounds[Game.rounds.length - 1].guessPosition = guessPosition;
Game.disableRestrictions();
var data = new FormData();
if (Game.guessMarker) {
var guessPosition = Game.guessMarker.getPosition().toJSON();
Game.rounds[Game.rounds.length - 1].guessPosition = guessPosition;
data.append('lat', String(guessPosition.lat));
data.append('lng', String(guessPosition.lng));
}
document.getElementById('guessButton').disabled = true;
document.getElementById('panoCover').style.visibility = 'visible';
var data = new FormData();
data.append('lat', String(guessPosition.lat));
data.append('lng', String(guessPosition.lng));
document.getElementById('loading').style.visibility = 'visible';
var url = Game.getGameIdentifier() + '/guess.json';
MapGuesser.httpRequest('POST', url, function () {
document.getElementById('loading').style.visibility = 'hidden';
@ -650,6 +676,7 @@ const GameType = Object.freeze({ 'SINGLE': 0, 'MULTI': 1, 'CHALLENGE': 2 });
}
Game.history = this.response.history;
Game.restrictions = this.response.restrictions;
Game.receiveResult(this.response.position, guessPosition, this.response.result, this.response.allResults);
@ -851,7 +878,7 @@ const GameType = Object.freeze({ 'SINGLE': 0, 'MULTI': 1, 'CHALLENGE': 2 });
}, 1);
},
startCountdown: function (timeout) {
startCountdown: function (timeout, timedOutHandler) {
if (Game.countdownHandler) {
clearInterval(Game.countdownHandler);
}
@ -873,7 +900,12 @@ const GameType = Object.freeze({ 'SINGLE': 0, 'MULTI': 1, 'CHALLENGE': 2 });
Game.setCountdownTime(timeLeft);
if (timeLeft <= 0) {
document.getElementById('panoCover').style.visibility = 'visible';
if (typeof timedOutHandler === 'function') {
timedOutHandler();
} else {
document.getElementById('panoCover').style.visibility = 'visible';
}
clearInterval(Game.countdownHandler);
}
}, 1000);

View File

@ -107,6 +107,10 @@ class GameController
{
// create Challenge
$challengeToken = rand();
while ($this->challengeRepository->getByToken($challengeToken)) {
// if a challenge with the same token already exists
$challengeToken = rand();
}
$challenge = new Challenge();
$challenge->setToken($challengeToken);

View File

@ -150,6 +150,7 @@ class GameFlowController
$currentPlace = $this->placeRepository->getByRoundInChallenge($challenge, $currentRound);
if (!isset($currentPlace) || $withHistory) {
$withRelations = [User::class, PlaceInChallenge::class, Place::class];
foreach ($this->guessRepository->getAllInChallenge($challenge, $withRelations) as $guess) {
$round = $guess->getPlaceInChallenge()->getRound();
@ -171,6 +172,22 @@ class GameFlowController
];
}
}
// setting default values for rounds without guesses (because of timeout)
for ($i = 0; $i < $currentRound; ++$i) {
if (!isset($response['history'][$i]) || !isset($response['history'][$i]['result'])) {
$response['history'][$i]['result'] = [
'guessPosition' => null,
'distance' => null,
'score' => 0
];
$response['history'][$i]['position'] =
$this->placeRepository->getByRoundInChallenge($challenge, $i)->getPosition()->toArray();
}
}
$response['history']['length'] = $currentRound;
}
if (!isset($currentPlace)) { // game finished
@ -196,7 +213,7 @@ class GameFlowController
}
$response['restrictions'] = [
'timeLimit' => $challenge->getTimeLimit(),
'timeLimit' => $challenge->getTimeLimit() * 1000,
'noMove' => $challenge->getNoMove(),
'noPan' => $challenge->getNoPan(),
'noZoom' => $challenge->getNoZoom()
@ -339,40 +356,38 @@ class GameFlowController
$currentPlace = $currentPlaceInChallenge->getPlace();
$map = $currentPlace->getMap();
$guessPosition = new Position((float) $this->request->post('lat'), (float) $this->request->post('lng'));
$result = $this->evaluateGuess($currentPlace->getPosition(), $guessPosition, $map->getArea());
// save guess
$guess = new Guess();
$guess->setUserId($userId);
$guess->setPlaceInChallenge($currentPlaceInChallenge);
$guess->setPosition($guessPosition);
$guess->setDistance($result['distance']);
$guess->setScore($result['score']);
$this->pdm->saveToDb($guess);
// update round
// creating response
$nextRound = $currentRound + 1;
$response = $this->prepareChallengeResponse($userId, $challenge, $nextRound);
$response['position'] = $currentPlace->getPosition()->toArray();
if ($this->request->post('lat') && $this->request->post('lng')) {
$guessPosition = new Position((float) $this->request->post('lat'), (float) $this->request->post('lng'));
$result = $this->evaluateGuess($currentPlace->getPosition(), $guessPosition, $map->getArea());
// save guess
$guess = new Guess();
$guess->setUserId($userId);
$guess->setPlaceInChallenge($currentPlaceInChallenge);
$guess->setPosition($guessPosition);
$guess->setDistance($result['distance']);
$guess->setScore($result['score']);
$this->pdm->saveToDb($guess);
$response['result'] = $result;
} else {
// user didn't manage to guess in the round in the given timeframe
$response['result'] = ['distance' => null, 'score' => 0];
}
$userInChallenge->setCurrentRound($nextRound);
$this->pdm->saveToDb($userInChallenge);
// creating response
$response = $this->prepareChallengeResponse($userId, $challenge, $nextRound);
$response['position'] = $currentPlace->getPosition()->toArray();
$response['result'] = $result;
if(isset($response['history'][$currentRound]['allResults'])) {
$response['allResults'] = $response['history'][$currentRound]['allResults'];
}
$this->saveVisit($currentPlace->getId());
return new JsonContent($response);

View File

@ -31,6 +31,13 @@ class ChallengeRepository
public function getByTokenStr(string $token_str): ?Challenge
{
// validate token string
foreach (str_split($token_str) as $char) {
if (!(('0' <= $char && $char <= '9') || ('a' <= $char && $char <= 'f'))) {
return null;
}
}
// convert token to int
$token = hexdec($token_str);
return $this->getByToken($token);

View File

@ -48,6 +48,13 @@ class UserInChallengeRepository
$withRelations = array_unique(array_merge($withRelations, $necessaryRelations));
}
// validate token string
foreach (str_split($token_str) as $char) {
if (!(('0' <= $char && $char <= '9') || ('a' <= $char && $char <= 'f'))) {
return null;
}
}
// convert token to int
$token = hexdec($token_str);
$select = new Select(\Container::$dbConnection);