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:
commit
1ace9ae0b2
@ -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;
|
||||||
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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) {
|
||||||
|
@ -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 [
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user