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;
}
#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;
}

View File

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

View File

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

View File

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

View File

@ -17,11 +17,22 @@
<div id="result">
<div id="resultMap"></div>
<div id="resultInfo">
<p>You were <span id="distance" class="bold"></span> close.</p>
<button id="continueButton">Continue</button>
<div>
<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>
<script>
var mapArea = <?= $bounds->calculateApproximateArea() ?>;
var guessMapBounds = <?= $bounds->toJson() ?>;
</script>
<script src="static/js/mapguesser.js" async defer></script>