diff --git a/public/index.php b/public/index.php index cae72c9..45f4ab8 100644 --- a/public/index.php +++ b/public/index.php @@ -8,9 +8,16 @@ switch($url) { case '/': $controller = new MapGuesser\Controller\GuessController(); break; + case '/getNewPosition.json': + $controller = new MapGuesser\Controller\GetNewPosition(); + break; default: echo 'Error 404'; die; } -echo $controller->render(); +$view = $controller->run(); + +header('Content-Type: ' . $view->getContentType() . '; charset=UTF-8'); + +echo $view->render(); diff --git a/public/static/js/mapguesser.js b/public/static/js/mapguesser.js index 1dc203d..4b85e78 100644 --- a/public/static/js/mapguesser.js +++ b/public/static/js/mapguesser.js @@ -45,26 +45,14 @@ var MapManipulator = { } }; +var realPosition; var panorama; var guessMap; var guessMarker; var googleLink; function initialize() { - panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), { - position: realPosition, - disableDefaultUI: true, - linksControl: true, - showRoadLabels: false - }); - - panorama.addListener('position_changed', function () { - MapManipulator.rewriteGoogleLink(); - }); - - panorama.addListener('pov_changed', function () { - MapManipulator.rewriteGoogleLink(); - }); + getNewPosition(); guessMap = new google.maps.Map(document.getElementById('guessMap'), { 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 () { if (!guessMarker) { return; @@ -98,7 +128,13 @@ document.getElementById('guessButton').onclick = function () { var guessedPosition = guessMarker.getPosition(); 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(); } diff --git a/src/Controller/BaseController.php b/src/Controller/BaseController.php deleted file mode 100644 index 9e2c2a7..0000000 --- a/src/Controller/BaseController.php +++ /dev/null @@ -1,24 +0,0 @@ -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; -} diff --git a/src/Controller/ControllerInterface.php b/src/Controller/ControllerInterface.php new file mode 100644 index 0000000..22d2f8f --- /dev/null +++ b/src/Controller/ControllerInterface.php @@ -0,0 +1,8 @@ +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); + } +} diff --git a/src/Controller/GuessController.php b/src/Controller/GuessController.php index 036d224..1b851ef 100644 --- a/src/Controller/GuessController.php +++ b/src/Controller/GuessController.php @@ -2,13 +2,13 @@ use MapGuesser\Util\Geo\Bounds; use MapGuesser\Util\Geo\Position; +use MapGuesser\View\HtmlView; +use MapGuesser\View\ViewBase; use mysqli; -class GuessController extends BaseController +class GuessController implements ControllerInterface { - protected string $view = 'guess'; - - protected function operate() : void + public function run(): ViewBase { $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']); $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); } } diff --git a/src/Util/Geo/Bounds.php b/src/Util/Geo/Bounds.php index bd1c458..b34d583 100644 --- a/src/Util/Geo/Bounds.php +++ b/src/Util/Geo/Bounds.php @@ -10,7 +10,7 @@ class Bounds private bool $initialized = false; - public static function createWithPosition(Position $position) : Bounds + public static function createWithPosition(Position $position): Bounds { $instance = new static(); @@ -19,7 +19,7 @@ class Bounds 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(); diff --git a/src/Util/Geo/Position.php b/src/Util/Geo/Position.php index 4e2499c..2ac9fc2 100644 --- a/src/Util/Geo/Position.php +++ b/src/Util/Geo/Position.php @@ -21,11 +21,16 @@ class Position return $this->lng; } - public function toJson(): string + public function toArray(): array { - return json_encode([ + return [ 'lat' => $this->lat, 'lng' => $this->lng, - ]); + ]; + } + + public function toJson(): string + { + return json_encode($this->toArray()); } } diff --git a/src/View/HtmlView.php b/src/View/HtmlView.php new file mode 100644 index 0000000..35f5e9a --- /dev/null +++ b/src/View/HtmlView.php @@ -0,0 +1,29 @@ +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'; + } +} diff --git a/src/View/JsonView.php b/src/View/JsonView.php new file mode 100644 index 0000000..78eb90f --- /dev/null +++ b/src/View/JsonView.php @@ -0,0 +1,21 @@ +data = &$data; + } + + public function &render(): string + { + $content = json_encode($this->data); + + return $content; + } + + public function getContentType(): string + { + return 'application/json'; + } +} diff --git a/src/View/ViewBase.php b/src/View/ViewBase.php new file mode 100644 index 0000000..9bad81f --- /dev/null +++ b/src/View/ViewBase.php @@ -0,0 +1,15 @@ +data; + } + + abstract public function &render(): string; + + abstract public function getContentType(): string; +} diff --git a/views/guess.php b/views/guess.php index 4658d5a..2c96a51 100644 --- a/views/guess.php +++ b/views/guess.php @@ -14,7 +14,6 @@