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