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