feature/MAPG-235-basic-challenge-mode #48
@ -14,7 +14,6 @@ CREATE TABLE `user_in_challenge` (
|
||||
`user_id` int(10) unsigned NOT NULL,
|
||||
`challenge_id` int(10) unsigned NOT NULL,
|
||||
`round` smallint(5) signed NOT NULL DEFAULT 0,
|
||||
`score` int(10) unsigned NOT NULL DEFAULT 0,
|
||||
`time_left` int(10) unsigned,
|
||||
`is_owner` tinyint(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
@ -43,6 +42,8 @@ CREATE TABLE `guesses` (
|
||||
`place_in_challenge_id` int(10) unsigned NOT NULL,
|
||||
`lat` decimal(8,6) NOT NULL,
|
||||
`lng` decimal(9,6) NOT NULL,
|
||||
`score` int(10) NOT NULL,
|
||||
`distance` int(10) NOT NULL,
|
||||
`time_spent` int(10),
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `user_id` (`user_id`),
|
||||
|
@ -294,9 +294,6 @@ const GameType = Object.freeze({'SINGLE': 0, 'MULTI': 1, 'CHALLENGE': 2});
|
||||
return;
|
||||
}
|
||||
|
||||
Game.panoId = this.response.place.panoId;
|
||||
Game.pov = this.response.place.pov;
|
||||
|
||||
for (var i = 0; i < this.response.history.length; ++i) {
|
||||
var round = this.response.history[i];
|
||||
Game.rounds.push({ position: round.position, guessPosition: round.result.guessPosition, realMarker: null, guessMarkers: [] });
|
||||
@ -305,6 +302,35 @@ const GameType = Object.freeze({'SINGLE': 0, 'MULTI': 1, 'CHALLENGE': 2});
|
||||
Game.scoreSum += round.result.score;
|
||||
}
|
||||
|
||||
if (this.response.finished) {
|
||||
|
||||
// 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.showSummary();
|
||||
return;
|
||||
}
|
||||
|
||||
Game.panoId = this.response.place.panoId;
|
||||
Game.pov = this.response.place.pov;
|
||||
|
||||
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);
|
||||
|
||||
@ -561,7 +587,7 @@ const GameType = Object.freeze({'SINGLE': 0, 'MULTI': 1, 'CHALLENGE': 2});
|
||||
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 = Game.getGameIdentifier() + '/guess.json';
|
||||
MapGuesser.httpRequest('POST', url, function () {
|
||||
document.getElementById('loading').style.visibility = 'hidden';
|
||||
|
||||
|
@ -244,7 +244,9 @@ class GameController
|
||||
if(!$this->userInChallengeRepository->isUserParticipatingInChallenge($userId, $challenge)) {
|
||||
$userInChallenge = new UserInChallenge();
|
||||
$userInChallenge->setUserId($userId);
|
||||
$userInChallenge->setChallenge($challenge);
|
||||
$userInChallenge->setTimeLeft($challenge->getTimerSec());
|
||||
$this->pdm->saveToDb($userInChallenge);
|
||||
}
|
||||
|
||||
$map = $this->mapRepository->getByChallenge($challenge);
|
||||
|
@ -8,9 +8,13 @@ use MapGuesser\Interfaces\Response\IContent;
|
||||
use MapGuesser\Multi\MultiConnector;
|
||||
use MapGuesser\PersistentData\Model\UserInChallenge;
|
||||
use MapGuesser\PersistentData\PersistentDataManager;
|
||||
use MapGuesser\PersistentData\Model\Guess;
|
||||
use MapGuesser\PersistentData\Model\UserPlayedPlace;
|
||||
use MapGuesser\Repository\ChallengeRepository;
|
||||
use MapGuesser\Repository\GuessRepository;
|
||||
use MapGuesser\Repository\MapRepository;
|
||||
use MapGuesser\Repository\MultiRoomRepository;
|
||||
use MapGuesser\Repository\PlaceInChallengeRepository;
|
||||
use MapGuesser\Repository\PlaceRepository;
|
||||
use MapGuesser\Repository\UserInChallengeRepository;
|
||||
use MapGuesser\Repository\UserPlayedPlaceRepository;
|
||||
@ -30,12 +34,18 @@ class GameFlowController
|
||||
|
||||
private PlaceRepository $placeRepository;
|
||||
|
||||
private MapRepository $mapRepository;
|
||||
|
||||
private UserPlayedPlaceRepository $userPlayedPlaceRepository;
|
||||
|
||||
private ChallengeRepository $challengeRepository;
|
||||
|
||||
private UserInChallengeRepository $userInChallengeRepository;
|
||||
|
||||
private PlaceInChallengeRepository $placeInChallengeRepository;
|
||||
|
||||
private GuessRepository $guessRepository;
|
||||
|
||||
public function __construct(IRequest $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
@ -43,9 +53,12 @@ class GameFlowController
|
||||
$this->multiConnector = new MultiConnector();
|
||||
$this->multiRoomRepository = new MultiRoomRepository();
|
||||
$this->placeRepository = new PlaceRepository();
|
||||
$this->mapRepository = new MapRepository();
|
||||
$this->userPlayedPlaceRepository = new UserPlayedPlaceRepository();
|
||||
$this->challengeRepository = new ChallengeRepository();
|
||||
$this->userInChallengeRepository = new UserInChallengeRepository();
|
||||
$this->placeInChallengeRepository = new PlaceInChallengeRepository();
|
||||
$this->guessRepository = new GuessRepository();
|
||||
}
|
||||
|
||||
public function initialData(): IContent
|
||||
@ -126,7 +139,6 @@ class GameFlowController
|
||||
|
||||
public function challengeInitialData(): IContent
|
||||
{
|
||||
// TODO
|
||||
$session = $this->request->session();
|
||||
$userId = $session->get('userId');
|
||||
$challengeToken_str = $this->request->query('challengeToken');
|
||||
@ -138,34 +150,36 @@ class GameFlowController
|
||||
|
||||
$userInChallenge = $this->userInChallengeRepository->getByUserIdAndChallenge($userId, $challenge);
|
||||
$currentRound = $userInChallenge->getRound();
|
||||
|
||||
$currentPlace = $this->placeRepository->getCurrentInChallenge($challenge, $currentRound);
|
||||
$currentPlace = $this->placeRepository->getByRoundInChallenge($challenge, $currentRound);
|
||||
|
||||
$response = [];
|
||||
|
||||
// $last = $state['rounds'][$state['currentRound']];
|
||||
// $response['place'] = [
|
||||
// 'panoId' => $last['panoId'],
|
||||
// 'pov' => $last['pov']->toArray()
|
||||
// ];
|
||||
|
||||
$response['place'] = [
|
||||
'panoId' => $currentPlace->getPanoIdCached(),
|
||||
'pov' => [$currentPlace->getPov()->toArray()]
|
||||
];
|
||||
|
||||
$response['history'] = [];
|
||||
// for ($i = 0; $i < $state['currentRound']; ++$i) {
|
||||
// $round = $state['rounds'][$i];
|
||||
// $response['history'][] = [
|
||||
// 'position' => $round['position']->toArray(),
|
||||
// 'result' => [
|
||||
// 'guessPosition' => $round['guessPosition']->toArray(),
|
||||
// 'distance' => $round['distance'],
|
||||
// 'score' => $round['score']
|
||||
// ]
|
||||
// ];
|
||||
// }
|
||||
|
||||
$guesses = iterator_to_array($this->guessRepository->getAllInChallenge($userId, $challenge));
|
||||
$places = iterator_to_array($this->placeRepository->getAllInChallenge($challenge));
|
||||
|
||||
for($i = 0; $i < $currentRound; ++$i)
|
||||
{
|
||||
$response['history'][] = [
|
||||
'position' => $places[$i]->getPosition()->toArray(),
|
||||
'result' => [
|
||||
'guessPosition' => $guesses[$i]->getPosition()->toArray(),
|
||||
'distance' => $guesses[$i]->getDistance(),
|
||||
'score' => $guesses[$i]->getScore()
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
if(!isset($currentPlace)) { // game finished
|
||||
$response['finished'] = true;
|
||||
|
||||
} else { // continue game
|
||||
$response['place'] = [
|
||||
'panoId' => $currentPlace->getPanoIdCached(),
|
||||
'pov' => [$currentPlace->getPov()->toArray()]
|
||||
];
|
||||
}
|
||||
|
||||
return new JsonContent($response);
|
||||
}
|
||||
@ -181,7 +195,7 @@ class GameFlowController
|
||||
|
||||
$last = $state['rounds'][$state['currentRound']];
|
||||
$guessPosition = new Position((float) $this->request->post('lat'), (float) $this->request->post('lng'));
|
||||
$result = $this->evalueteGuess($last['position'], $guessPosition, $state['area']);
|
||||
$result = $this->evaluateGuess($last['position'], $guessPosition, $state['area']);
|
||||
|
||||
$last['guessPosition'] = $guessPosition;
|
||||
$last['distance'] = $result['distance'];
|
||||
@ -205,19 +219,18 @@ class GameFlowController
|
||||
|
||||
$session->set('state', $state);
|
||||
|
||||
$this->saveVisit($last);
|
||||
$this->saveVisit($last['placeId']);
|
||||
|
||||
return new JsonContent($response);
|
||||
}
|
||||
|
||||
// save the selected place for the round in UserPlayedPlace
|
||||
private function saveVisit($last): void
|
||||
private function saveVisit($placeId): void
|
||||
{
|
||||
$session = $this->request->session();
|
||||
$userId = $session->get('userId');
|
||||
|
||||
if(isset($userId)) {
|
||||
$placeId = $last['placeId'];
|
||||
$userPlayedPlace = $this->userPlayedPlaceRepository->getByUserIdAndPlaceId($userId, $placeId);
|
||||
if(!$userPlayedPlace) {
|
||||
$userPlayedPlace = new UserPlayedPlace();
|
||||
@ -245,7 +258,7 @@ class GameFlowController
|
||||
|
||||
$last = $state['rounds'][$state['currentRound']];
|
||||
$guessPosition = new Position((float) $this->request->post('lat'), (float) $this->request->post('lng'));
|
||||
$result = $this->evalueteGuess($last['position'], $guessPosition, $state['area']);
|
||||
$result = $this->evaluateGuess($last['position'], $guessPosition, $state['area']);
|
||||
|
||||
$responseFromMulti = $this->multiConnector->sendMessage('guess', [
|
||||
'roomId' => $roomId,
|
||||
@ -268,6 +281,61 @@ class GameFlowController
|
||||
return new JsonContent($response);
|
||||
}
|
||||
|
||||
public function challengeGuess(): IContent
|
||||
{
|
||||
$session = $this->request->session();
|
||||
$userId = $session->get('userId');
|
||||
$challengeToken_str = $this->request->query('challengeToken');
|
||||
$challenge = $this->challengeRepository->getByTokenStr($challengeToken_str);
|
||||
|
||||
if (!isset($challenge)) {
|
||||
return new JsonContent(['error' => 'game_not_found']);
|
||||
}
|
||||
|
||||
$userInChallenge = $this->userInChallengeRepository->getByUserIdAndChallenge($userId, $challenge);
|
||||
$currentRound = $userInChallenge->getRound();
|
||||
$currentPlace = $this->placeRepository->getByRoundInChallenge($challenge, $currentRound);
|
||||
$map = $this->mapRepository->getByPlace($currentPlace);
|
||||
$placeInChallenge = $this->placeInChallengeRepository->getByPlaceAndChallenge($currentPlace, $challenge);
|
||||
|
||||
$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($placeInChallenge);
|
||||
$guess->setPosition($guessPosition);
|
||||
$guess->setDistance($result['distance']);
|
||||
$guess->setScore($result['score']);
|
||||
$this->pdm->saveToDb($guess);
|
||||
|
||||
$response = [
|
||||
'position' => $currentPlace->getPosition()->toArray(),
|
||||
'result' => $result
|
||||
];
|
||||
|
||||
// update round
|
||||
$nextRound = $currentRound + 1;
|
||||
|
||||
$userInChallenge->setRound($nextRound);
|
||||
$this->pdm->saveToDb($userInChallenge);
|
||||
|
||||
if ($nextRound < static::NUMBER_OF_ROUNDS) {
|
||||
|
||||
$nextPlace = $this->placeRepository->getByRoundInChallenge($challenge, $nextRound);
|
||||
|
||||
$response['place'] = [
|
||||
'panoId' => $nextPlace->getPanoIdCached(),
|
||||
'pov' => $nextPlace->getPov()->toArray()
|
||||
];
|
||||
}
|
||||
|
||||
$this->saveVisit($currentPlace->getId());
|
||||
|
||||
return new JsonContent($response);
|
||||
}
|
||||
|
||||
public function multiNextRound(): IContent
|
||||
{
|
||||
$roomId = $this->request->query('roomId');
|
||||
@ -297,7 +365,7 @@ class GameFlowController
|
||||
return new JsonContent(['ok' => true]);
|
||||
}
|
||||
|
||||
private function evalueteGuess(Position $realPosition, Position $guessPosition, float $area)
|
||||
private function evaluateGuess(Position $realPosition, Position $guessPosition, float $area)
|
||||
{
|
||||
$distance = $this->calculateDistance($realPosition, $guessPosition);
|
||||
$score = $this->calculateScore($distance, $area);
|
||||
|
@ -4,9 +4,9 @@ use MapGuesser\Util\Geo\Position;
|
||||
|
||||
class Guess extends Model
|
||||
{
|
||||
protected static string $table = 'guess';
|
||||
protected static string $table = 'guesses';
|
||||
|
||||
protected static array $fields = ['user_id', 'place_in_challenge_id', 'lat', 'lng', 'time_spent'];
|
||||
protected static array $fields = ['user_id', 'place_in_challenge_id', 'lat', 'lng', 'score', 'distance', 'time_spent'];
|
||||
|
||||
protected static array $relations = ['user' => User::class, 'place_in_challenge' => PlaceInChallenge::class];
|
||||
|
||||
@ -20,7 +20,16 @@ class Guess extends Model
|
||||
|
||||
private Position $position;
|
||||
|
||||
private int $timeSpent;
|
||||
private int $score = 0;
|
||||
|
||||
private int $distance = 0;
|
||||
|
||||
private int $timeSpent = 0;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->position = new Position(0.0, 0.0);
|
||||
}
|
||||
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
@ -57,6 +66,16 @@ class Guess extends Model
|
||||
$this->position->setLng($lng);
|
||||
}
|
||||
|
||||
public function setScore(int $score): void
|
||||
{
|
||||
$this->score = $score;
|
||||
}
|
||||
|
||||
public function setDistance(int $distance): void
|
||||
{
|
||||
$this->distance = $distance;
|
||||
}
|
||||
|
||||
public function setTimeSpent(int $timeSpent): void
|
||||
{
|
||||
$this->timeSpent = $timeSpent;
|
||||
@ -97,6 +116,16 @@ class Guess extends Model
|
||||
return $this->position->getLng();
|
||||
}
|
||||
|
||||
public function getScore(): int
|
||||
{
|
||||
return $this->score;
|
||||
}
|
||||
|
||||
public function getDistance(): int
|
||||
{
|
||||
return $this->distance;
|
||||
}
|
||||
|
||||
public function getTimeSpent(): ?int
|
||||
{
|
||||
return $this->timeSpent;
|
||||
|
@ -4,7 +4,7 @@ class UserInChallenge extends Model
|
||||
{
|
||||
protected static string $table = 'user_in_challenge';
|
||||
|
||||
protected static array $fields = ['user_id', 'challenge_id', 'round', 'score', 'time_left', 'is_owner'];
|
||||
protected static array $fields = ['user_id', 'challenge_id', 'round', 'time_left', 'is_owner'];
|
||||
|
||||
protected static array $relations = ['user' => User::class, 'challenge' => Challenge::class];
|
||||
|
||||
@ -18,8 +18,6 @@ class UserInChallenge extends Model
|
||||
|
||||
private int $round = 0;
|
||||
|
||||
private int $score = 0;
|
||||
|
||||
private ?int $timeLeft = null;
|
||||
|
||||
private bool $isOwner = false;
|
||||
@ -49,11 +47,6 @@ class UserInChallenge extends Model
|
||||
$this->round = $round;
|
||||
}
|
||||
|
||||
public function setScore(int $score): void
|
||||
{
|
||||
$this->score = $score;
|
||||
}
|
||||
|
||||
public function setTimeLeft(?int $timeLeft): void
|
||||
{
|
||||
if(isset($timeLeft)) {
|
||||
@ -91,11 +84,6 @@ class UserInChallenge extends Model
|
||||
return $this->round;
|
||||
}
|
||||
|
||||
public function getScore(): int
|
||||
{
|
||||
return $this->score;
|
||||
}
|
||||
|
||||
public function getTimeLeft(): ?int
|
||||
{
|
||||
return $this->timeLeft;
|
||||
|
@ -21,7 +21,7 @@ class GuessRepository
|
||||
public function getAllByUserAndChallenge(User $user, Challenge $challenge) : Generator
|
||||
{
|
||||
$select = new Select(\Container::$dbConnection);
|
||||
$select->innerJoin('place_in_challenge', ['place_in_challenge', 'id'], '=', ['guess', 'place_in_challenge_id']);
|
||||
$select->innerJoin('place_in_challenge', ['place_in_challenge', 'id'], '=', ['guesses', 'place_in_challenge_id']);
|
||||
$select->where('user_id', '=', $user->getId());
|
||||
$select->where('challenge_id', '=', $challenge->getId());
|
||||
|
||||
@ -31,11 +31,22 @@ class GuessRepository
|
||||
public function getByUserAndPlaceInChallenge(User $user, Challenge $challenge, Place $place) : ?Guess
|
||||
{
|
||||
$select = new Select(\Container::$dbConnection);
|
||||
$select->innerJoin('place_in_challenge', ['place_in_challenge', 'id'], '=', ['guess', 'place_in_challenge_id']);
|
||||
$select->innerJoin('place_in_challenge', ['place_in_challenge', 'id'], '=', ['guesses', 'place_in_challenge_id']);
|
||||
$select->where('user_id', '=', $user->getId());
|
||||
$select->where('challenge_id', '=', $challenge->getId());
|
||||
$select->where('place_id', '=', $place->getId());
|
||||
|
||||
return $this->pdm->selectFromDb($select, Guess::class);
|
||||
}
|
||||
|
||||
public function getAllInChallenge(int $userId, Challenge $challenge): Generator
|
||||
{
|
||||
$select = new Select(\Container::$dbConnection);
|
||||
$select->innerJoin('place_in_challenge', ['place_in_challenge', 'id'], '=', ['guesses', 'place_in_challenge_id']);
|
||||
$select->where('user_id', '=', $userId);
|
||||
$select->where('challenge_id', '=', $challenge->getId());
|
||||
$select->orderBy('order');
|
||||
|
||||
yield from $this->pdm->selectMultipleFromDb($select, Guess::class);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
use MapGuesser\Database\Query\Select;
|
||||
use MapGuesser\PersistentData\Model\Challenge;
|
||||
use MapGuesser\PersistentData\Model\Map;
|
||||
use MapGuesser\PersistentData\Model\Place;
|
||||
use MapGuesser\PersistentData\PersistentDataManager;
|
||||
|
||||
class MapRepository
|
||||
@ -19,6 +20,14 @@ class MapRepository
|
||||
return $this->pdm->selectFromDbById($mapId, Map::class);
|
||||
}
|
||||
|
||||
public function getByPlace(Place $place): ?Map
|
||||
{
|
||||
$select = new Select(\Container::$dbConnection);
|
||||
$select->where('id', '=', $place->getMapId());
|
||||
|
||||
return $this->pdm->selectFromDb($select, Map::class);
|
||||
}
|
||||
|
||||
public function getByChallenge(Challenge $challenge): ?Map
|
||||
{
|
||||
$select = new Select(\Container::$dbConnection);
|
||||
|
@ -31,4 +31,13 @@ class PlaceInChallengeRepository
|
||||
|
||||
yield from $this->pdm->selectMultipleFromDb($select, PlaceInChallenge::class);
|
||||
}
|
||||
|
||||
public function getByPlaceAndChallenge(Place $place, Challenge $challenge) : ?PlaceInChallenge
|
||||
{
|
||||
$select = new Select(\Container::$dbConnection);
|
||||
$select->where('place_id', '=', $place->getId());
|
||||
$select->where('challenge_id', '=', $challenge->getId());
|
||||
|
||||
return $this->pdm->selectFromDb($select, PlaceInChallenge::class);
|
||||
}
|
||||
}
|
||||
|
@ -178,14 +178,25 @@ class PlaceRepository
|
||||
return $places;
|
||||
}
|
||||
|
||||
public function getCurrentInChallenge(Challenge $challenge, int $round): ?Place
|
||||
public function getByRoundInChallenge(Challenge $challenge, int $round): ?Place
|
||||
{
|
||||
$select = new Select(\Container::$dbConnection);
|
||||
$select->innerJoin('place_in_challenge', ['places', 'id'], '=', ['place_in_challenge', 'place_id']);
|
||||
$select->where('challenge_id', '=', $challenge->getId());
|
||||
$select->orderBy('order');
|
||||
$select->limit(1, $round);
|
||||
|
||||
return $this->pdm->selectFromDb($select, Place::class);
|
||||
}
|
||||
|
||||
public function getAllInChallenge(Challenge $challenge): Generator
|
||||
{
|
||||
$select = new Select(\Container::$dbConnection);
|
||||
$select->innerJoin('place_in_challenge', ['places', 'id'], '=', ['place_in_challenge', 'place_id']);
|
||||
$select->where('challenge_id', '=', $challenge->getId());
|
||||
$select->orderBy('order');
|
||||
|
||||
yield from $this->pdm->selectMultipleFromDb($select, Place::class);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user