diff --git a/public/static/css/mapguesser.css b/public/static/css/mapguesser.css index d271969..0c8b591 100644 --- a/public/static/css/mapguesser.css +++ b/public/static/css/mapguesser.css @@ -75,7 +75,7 @@ button:disabled { transition-delay: 0s; } -#guess #guessMap { +#guess > #guessMap { height: 115px; width: 100%; transition-property: height; @@ -84,7 +84,7 @@ button:disabled { border-radius: 3px; } -#guess:hover #guessMap { +#guess:hover > #guessMap { height: 315px; transition-delay: 0s; } @@ -122,12 +122,33 @@ button:disabled { #resultInfo { height: 30%; width: 100%; - padding: 20px; + padding: 10px 20px; text-align: center; box-sizing: border-box; } +#resultInfo > div { + height: 25%; + width: 100%; + display: flex; + justify-content: center; + align-items: center; +} + #resultInfo p { - margin-bottom: 20px; font-size: 24px; } + +#scoreBarBase { + height: 20px; + width: 60%; + margin: 0 auto; + background-color: #eeeeee; + border-radius: 3px; +} + +#scoreBar { + height: 100%; + transition-property: width; + transition-duration: 1.0s; +} diff --git a/public/static/js/mapguesser.js b/public/static/js/mapguesser.js index 2b8090a..4f5dc35 100644 --- a/public/static/js/mapguesser.js +++ b/public/static/js/mapguesser.js @@ -5,21 +5,22 @@ Math.deg2rad = function (deg) { var Util = { EARTH_RADIUS_IN_METER: 6371000, + MAX_SCORE: 1000, + calculateDistance: function (position1, position2) { var lat1 = Math.deg2rad(position1.lat); var lng1 = Math.deg2rad(position1.lng); var lat2 = Math.deg2rad(position2.lat); var lng2 = Math.deg2rad(position2.lng); - var latDelta = lat2 - lat1; - var lonDelta = lng2 - lng1; + var angleCos = Math.cos(lat1) * Math.cos(lat2) * Math.cos(lng2 - lng1) + + Math.sin(lat1) * Math.sin(lat2); - var angle = 2 * Math.asin( - Math.sqrt( - Math.pow(Math.sin(latDelta / 2), 2) + - Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(lonDelta / 2), 2) - ) - ); + if (angleCos > 1.0) { + angleCos = 1.0; + } + + var angle = Math.acos(angleCos); return angle * Util.EARTH_RADIUS_IN_METER; }, @@ -34,6 +35,27 @@ var Util = { } else { return Number.parseFloat(distance / 1000).toFixed(0) + ' km'; } + }, + + calculateScore: function (distance) { + var goodness = 1.0 - distance / Math.sqrt(mapArea); + + return Math.pow(this.MAX_SCORE, goodness); + }, + + calculateScoreBarProperties: function (score) { + var percent = Math.round((score / this.MAX_SCORE) * 100); + + var color; + if (percent >= 90) { + color = '#11ca00'; + } else if (percent >= 10) { + color = '#ea9000'; + } else { + color = '#ca1100'; + } + + return { width: percent + '%', backgroundColor: color }; } }; @@ -190,9 +212,20 @@ document.getElementById('guessButton').onclick = function () { }); document.getElementById('distance').innerHTML = Util.printDistanceForHuman(distance); + + var score = Util.calculateScore(distance); + var scoreBarProperties = Util.calculateScoreBarProperties(score); + + document.getElementById('score').innerHTML = Number.parseFloat(score).toFixed(0); + + var scoreBar = document.getElementById('scoreBar'); + scoreBar.style.backgroundColor = scoreBarProperties.backgroundColor; + scoreBar.style.width = scoreBarProperties.width; } document.getElementById('continueButton').onclick = function () { + document.getElementById('scoreBar').style.width = '0'; + resultMarkers.real.setMap(null); resultMarkers.real = null; resultMarkers.guess.setMap(null); diff --git a/src/Util/Geo/Bounds.php b/src/Util/Geo/Bounds.php index b34d583..c77d2b1 100644 --- a/src/Util/Geo/Bounds.php +++ b/src/Util/Geo/Bounds.php @@ -2,6 +2,8 @@ class Bounds { + const ONE_DEGREE_OF_LATITUDE_IN_METER = 111132.954; + private float $southLat; private float $westLng; @@ -19,7 +21,7 @@ class Bounds return $instance; } - public static function createDirectly(float $southLat, $westLng, $northLat, $eastLng): Bounds + public static function createDirectly(float $southLat, float $westLng, float $northLat, float $eastLng): Bounds { $instance = new static(); @@ -61,6 +63,18 @@ class Bounds } } + public function calculateApproximateArea(): float + { + $dLat = $this->northLat - $this->southLat; + $dLng = $this->eastLng - $this->westLng; + + $m = $dLat * static::ONE_DEGREE_OF_LATITUDE_IN_METER; + $a = $dLng * static::ONE_DEGREE_OF_LATITUDE_IN_METER * cos(deg2rad($this->northLat)); + $c = $dLng * static::ONE_DEGREE_OF_LATITUDE_IN_METER * cos(deg2rad($this->southLat)); + + return $m * ($a + $c) / 2; + } + public function toJson(): string { if (!$this->initialized) { diff --git a/src/Util/Geo/Position.php b/src/Util/Geo/Position.php index 2ac9fc2..33eb0cd 100644 --- a/src/Util/Geo/Position.php +++ b/src/Util/Geo/Position.php @@ -2,6 +2,8 @@ class Position { + const EARTH_RADIUS_IN_METER = 6371000; + private float $lat; private float $lng; @@ -21,6 +23,24 @@ class Position return $this->lng; } + public function calculateDistanceTo(Position $otherPosition): float + { + $lat1 = deg2rad($this->lat); + $lng1 = deg2rad($this->lng); + $lat2 = deg2rad($otherPosition->lat); + $lng2 = deg2rad($otherPosition->lng); + + $angleCos = cos($lat1) * cos($lat2) * cos($lng2 - $lng1) + sin($lat1) * sin($lat2); + + if ($angleCos > 1.0) { + $angleCos = 1.0; + } + + $angle = acos($angleCos); + + return $angle * static::EARTH_RADIUS_IN_METER; + } + public function toArray(): array { return [ diff --git a/views/game.php b/views/game.php index 4246a94..370aa66 100644 --- a/views/game.php +++ b/views/game.php @@ -17,11 +17,22 @@
-

You were close.

- +
+

You were close.

+
+
+

You earned points.

+
+
+
+
+
+ +