Merged in feature/MAPG-10-check-if-place-has-panorama (pull request #3)

Feature/MAPG-10 check if place has panorama
This commit is contained in:
Bence Pőcze 2020-05-19 01:45:29 +00:00
commit 5c9b54c881
12 changed files with 177 additions and 52 deletions

View File

@ -8,9 +8,16 @@ switch($url) {
case '/': case '/':
$controller = new MapGuesser\Controller\GuessController(); $controller = new MapGuesser\Controller\GuessController();
break; break;
case '/getNewPosition.json':
$controller = new MapGuesser\Controller\GetNewPosition();
break;
default: default:
echo 'Error 404'; echo 'Error 404';
die; die;
} }
echo $controller->render(); $view = $controller->run();
header('Content-Type: ' . $view->getContentType() . '; charset=UTF-8');
echo $view->render();

View File

@ -45,26 +45,14 @@ var MapManipulator = {
} }
}; };
var realPosition;
var panorama; var panorama;
var guessMap; var guessMap;
var guessMarker; var guessMarker;
var googleLink; var googleLink;
function initialize() { function initialize() {
panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), { getNewPosition();
position: realPosition,
disableDefaultUI: true,
linksControl: true,
showRoadLabels: false
});
panorama.addListener('position_changed', function () {
MapManipulator.rewriteGoogleLink();
});
panorama.addListener('pov_changed', function () {
MapManipulator.rewriteGoogleLink();
});
guessMap = new google.maps.Map(document.getElementById('guessMap'), { guessMap = new google.maps.Map(document.getElementById('guessMap'), {
disableDefaultUI: true, disableDefaultUI: true,
@ -90,6 +78,48 @@ function initialize() {
}); });
} }
function getNewPosition() {
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
realPosition = this.response.position;
var sv = new google.maps.StreetViewService();
sv.getPanorama({ location: this.response.position, preference: google.maps.StreetViewPreference.BEST }, loadPano);
}
};
xhr.open('GET', 'getNewPosition.json', true);
xhr.send();
}
function loadPano(data, status) {
if (status !== google.maps.StreetViewStatus.OK) {
getNewPosition();
return;
}
if (panorama) {
panorama.setPano(data.location.pano);
return;
}
panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), {
pano: data.location.pano,
disableDefaultUI: true,
linksControl: true,
showRoadLabels: false
});
panorama.addListener('position_changed', function () {
MapManipulator.rewriteGoogleLink();
});
panorama.addListener('pov_changed', function () {
MapManipulator.rewriteGoogleLink();
});
}
document.getElementById('guessButton').onclick = function () { document.getElementById('guessButton').onclick = function () {
if (!guessMarker) { if (!guessMarker) {
return; return;
@ -98,7 +128,13 @@ document.getElementById('guessButton').onclick = function () {
var guessedPosition = guessMarker.getPosition(); var guessedPosition = guessMarker.getPosition();
var distance = Util.calculateDistance(realPosition, { lat: guessedPosition.lat(), lng: guessedPosition.lng() }); var distance = Util.calculateDistance(realPosition, { lat: guessedPosition.lat(), lng: guessedPosition.lng() });
alert('You were ' + distance + 'm close!'); alert('You were ' + (Math.round(distance) / 1000) + ' km close!');
this.blur(); this.disabled = true;
guessMarker.setMap(null);
guessMarker = null;
//TODO: fit to the same size as on init
guessMap.fitBounds(guessMapBounds);
getNewPosition();
} }

View File

@ -1,24 +0,0 @@
<?php namespace MapGuesser\Controller;
abstract class BaseController
{
protected string $view;
protected array $variables = [];
public function render() : string
{
$this->operate();
extract($this->variables);
ob_start();
require ROOT . '/views/' . $this->view . '.php';
$content = ob_get_contents();
ob_end_clean();
return $content;
}
abstract protected function operate() : void;
}

View File

@ -0,0 +1,8 @@
<?php namespace MapGuesser\Controller;
use MapGuesser\View\ViewBase;
interface ControllerInterface
{
public function run(): ViewBase;
}

View File

@ -0,0 +1,28 @@
<?php namespace MapGuesser\Controller;
use MapGuesser\Util\Geo\Position;
use MapGuesser\View\JsonView;
use MapGuesser\View\ViewBase;
use mysqli;
class GetNewPosition implements ControllerInterface
{
public function run(): ViewBase
{
$mysql = new mysqli($_ENV['DB_HOST'], $_ENV['DB_USER'], $_ENV['DB_PASSWORD'], $_ENV['DB_NAME']);
// demo map
$mapId = 1;
// using RAND() for the time being, could be changed in the future
$stmt = $mysql->prepare('SELECT lat, lng FROM places WHERE map_id=? ORDER BY RAND() LIMIT 1');
$stmt->bind_param("i", $mapId);
$stmt->execute();
$place = $stmt->get_result()->fetch_assoc();
$position = new Position($place['lat'], $place['lng']);
$data = ['position' => $position->toArray()];
return new JsonView($data);
}
}

View File

@ -2,13 +2,13 @@
use MapGuesser\Util\Geo\Bounds; use MapGuesser\Util\Geo\Bounds;
use MapGuesser\Util\Geo\Position; use MapGuesser\Util\Geo\Position;
use MapGuesser\View\HtmlView;
use MapGuesser\View\ViewBase;
use mysqli; use mysqli;
class GuessController extends BaseController class GuessController implements ControllerInterface
{ {
protected string $view = 'guess'; public function run(): ViewBase
protected function operate() : void
{ {
$mysql = new mysqli($_ENV['DB_HOST'], $_ENV['DB_USER'], $_ENV['DB_PASSWORD'], $_ENV['DB_NAME']); $mysql = new mysqli($_ENV['DB_HOST'], $_ENV['DB_USER'], $_ENV['DB_PASSWORD'], $_ENV['DB_NAME']);
@ -29,6 +29,7 @@ class GuessController extends BaseController
$realPosition = new Position($place['lat'], $place['lng']); $realPosition = new Position($place['lat'], $place['lng']);
$bounds = Bounds::createDirectly($map['bound_south_lat'], $map['bound_west_lng'], $map['bound_north_lat'], $map['bound_east_lng']); $bounds = Bounds::createDirectly($map['bound_south_lat'], $map['bound_west_lng'], $map['bound_north_lat'], $map['bound_east_lng']);
$this->variables = compact('realPosition', 'bounds'); $data = compact('bounds');
return new HtmlView('guess', $data);
} }
} }

View File

@ -10,7 +10,7 @@ class Bounds
private bool $initialized = false; private bool $initialized = false;
public static function createWithPosition(Position $position) : Bounds public static function createWithPosition(Position $position): Bounds
{ {
$instance = new static(); $instance = new static();
@ -19,7 +19,7 @@ class Bounds
return $instance; return $instance;
} }
public static function createDirectly(float $southLat, $westLng, $northLat, $eastLng) : Bounds public static function createDirectly(float $southLat, $westLng, $northLat, $eastLng): Bounds
{ {
$instance = new static(); $instance = new static();

View File

@ -21,11 +21,16 @@ class Position
return $this->lng; return $this->lng;
} }
public function toJson(): string public function toArray(): array
{ {
return json_encode([ return [
'lat' => $this->lat, 'lat' => $this->lat,
'lng' => $this->lng, 'lng' => $this->lng,
]); ];
}
public function toJson(): string
{
return json_encode($this->toArray());
} }
} }

29
src/View/HtmlView.php Normal file
View File

@ -0,0 +1,29 @@
<?php namespace MapGuesser\View;
class HtmlView extends ViewBase
{
private string $template;
public function __construct(string $template, array &$data = [])
{
$this->template = $template;
$this->data = &$data;
}
public function &render(): string
{
extract($this->data);
ob_start();
require ROOT . '/views/' . $this->template . '.php';
$content = ob_get_contents();
ob_end_clean();
return $content;
}
public function getContentType(): string
{
return 'text/html';
}
}

21
src/View/JsonView.php Normal file
View File

@ -0,0 +1,21 @@
<?php namespace MapGuesser\View;
class JsonView extends ViewBase
{
public function __construct(array &$data = [])
{
$this->data = &$data;
}
public function &render(): string
{
$content = json_encode($this->data);
return $content;
}
public function getContentType(): string
{
return 'application/json';
}
}

15
src/View/ViewBase.php Normal file
View File

@ -0,0 +1,15 @@
<?php namespace MapGuesser\View;
abstract class ViewBase
{
protected array $data;
public function &getData(): array
{
return $this->data;
}
abstract public function &render(): string;
abstract public function getContentType(): string;
}

View File

@ -14,7 +14,6 @@
</div> </div>
</div> </div>
<script> <script>
var realPosition = <?= $realPosition->toJson() ?>;
var guessMapBounds = <?= $bounds->toJson() ?>; var guessMapBounds = <?= $bounds->toJson() ?>;
</script> </script>
<script src="static/js/mapguesser.js" async defer></script> <script src="static/js/mapguesser.js" async defer></script>