Merged in feature/MAPG-6-calculate-and-show-score-after-the-guess (pull request #5)

Feature/MAPG-6 calculate and show score after the guess
This commit is contained in:
Bence Pőcze 2020-05-19 23:20:39 +00:00
commit 1ace9ae0b2
5 changed files with 114 additions and 15 deletions

View File

@ -75,7 +75,7 @@ button:disabled {
transition-delay: 0s; transition-delay: 0s;
} }
#guess #guessMap { #guess > #guessMap {
height: 115px; height: 115px;
width: 100%; width: 100%;
transition-property: height; transition-property: height;
@ -84,7 +84,7 @@ button:disabled {
border-radius: 3px; border-radius: 3px;
} }
#guess:hover #guessMap { #guess:hover > #guessMap {
height: 315px; height: 315px;
transition-delay: 0s; transition-delay: 0s;
} }
@ -122,12 +122,33 @@ button:disabled {
#resultInfo { #resultInfo {
height: 30%; height: 30%;
width: 100%; width: 100%;
padding: 20px; padding: 10px 20px;
text-align: center; text-align: center;
box-sizing: border-box; box-sizing: border-box;
} }
#resultInfo > div {
height: 25%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
#resultInfo p { #resultInfo p {
margin-bottom: 20px;
font-size: 24px; 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;
}

View File

@ -5,21 +5,22 @@ Math.deg2rad = function (deg) {
var Util = { var Util = {
EARTH_RADIUS_IN_METER: 6371000, EARTH_RADIUS_IN_METER: 6371000,
MAX_SCORE: 1000,
calculateDistance: function (position1, position2) { calculateDistance: function (position1, position2) {
var lat1 = Math.deg2rad(position1.lat); var lat1 = Math.deg2rad(position1.lat);
var lng1 = Math.deg2rad(position1.lng); var lng1 = Math.deg2rad(position1.lng);
var lat2 = Math.deg2rad(position2.lat); var lat2 = Math.deg2rad(position2.lat);
var lng2 = Math.deg2rad(position2.lng); var lng2 = Math.deg2rad(position2.lng);
var latDelta = lat2 - lat1; var angleCos = Math.cos(lat1) * Math.cos(lat2) * Math.cos(lng2 - lng1) +
var lonDelta = lng2 - lng1; Math.sin(lat1) * Math.sin(lat2);
var angle = 2 * Math.asin( if (angleCos > 1.0) {
Math.sqrt( angleCos = 1.0;
Math.pow(Math.sin(latDelta / 2), 2) + }
Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(lonDelta / 2), 2)
) var angle = Math.acos(angleCos);
);
return angle * Util.EARTH_RADIUS_IN_METER; return angle * Util.EARTH_RADIUS_IN_METER;
}, },
@ -34,6 +35,27 @@ var Util = {
} else { } else {
return Number.parseFloat(distance / 1000).toFixed(0) + ' km'; 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); 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('continueButton').onclick = function () {
document.getElementById('scoreBar').style.width = '0';
resultMarkers.real.setMap(null); resultMarkers.real.setMap(null);
resultMarkers.real = null; resultMarkers.real = null;
resultMarkers.guess.setMap(null); resultMarkers.guess.setMap(null);

View File

@ -2,6 +2,8 @@
class Bounds class Bounds
{ {
const ONE_DEGREE_OF_LATITUDE_IN_METER = 111132.954;
private float $southLat; private float $southLat;
private float $westLng; private float $westLng;
@ -19,7 +21,7 @@ class Bounds
return $instance; 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(); $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 public function toJson(): string
{ {
if (!$this->initialized) { if (!$this->initialized) {

View File

@ -2,6 +2,8 @@
class Position class Position
{ {
const EARTH_RADIUS_IN_METER = 6371000;
private float $lat; private float $lat;
private float $lng; private float $lng;
@ -21,6 +23,24 @@ class Position
return $this->lng; 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 public function toArray(): array
{ {
return [ return [

View File

@ -17,11 +17,22 @@
<div id="result"> <div id="result">
<div id="resultMap"></div> <div id="resultMap"></div>
<div id="resultInfo"> <div id="resultInfo">
<p>You were <span id="distance" class="bold"></span> close.</p> <div>
<button id="continueButton">Continue</button> <p>You were <span id="distance" class="bold"></span> close.</p>
</div>
<div>
<p>You earned <span id="score" class="bold"></span> points.</p>
</div>
<div>
<div id="scoreBarBase"><div id="scoreBar"></div></div>
</div>
<div>
<button id="continueButton">Continue</button>
</div>
</div> </div>
</div> </div>
<script> <script>
var mapArea = <?= $bounds->calculateApproximateArea() ?>;
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>