Merged in develop (pull request #64)

Develop
This commit is contained in:
Bence Pőcze 2020-05-30 18:48:47 +00:00
commit 74dd30178d
10 changed files with 459 additions and 113 deletions

26
USED_SOFTWARE Normal file
View File

@ -0,0 +1,26 @@
---------------------------------------------------------------
Bootstrap Icons
https://github.com/twbs/icons
---------------------------------------------------------------
The MIT License (MIT)
Copyright (c) 2019 The Bootstrap Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------

View File

@ -3,23 +3,29 @@
require '../main.php'; require '../main.php';
// very basic routing // very basic routing
$host = $_SERVER["REQUEST_SCHEME"] . '://' . $_SERVER["SERVER_NAME"]; $host = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['SERVER_NAME'];
$url = $_SERVER['REQUEST_URI']; $url = $_SERVER['REQUEST_URI'];
if (($pos = strpos($url, '?')) !== false) { if (($pos = strpos($url, '?')) !== false) {
$url = substr($url, 0, $pos); $url = substr($url, 0, $pos);
} }
switch($url) { switch($url) {
case '/maps':
$controller = new MapGuesser\Controller\MapsController();
break;
case '/game': case '/game':
$controller = new MapGuesser\Controller\GameController(); $mapId = isset($_GET['map']) ? (int) $_GET['map'] : 0;
$controller = new MapGuesser\Controller\GameController($mapId);
break; break;
case '/game.json': case '/game.json':
$controller = new MapGuesser\Controller\GameController(true); $mapId = isset($_GET['map']) ? (int) $_GET['map'] : 0;
$controller = new MapGuesser\Controller\GameController($mapId, true);
break; break;
case '/position.json': case '/position.json':
$controller = new MapGuesser\Controller\PositionController(); $mapId = isset($_GET['map']) ? (int) $_GET['map'] : 0;
$controller = new MapGuesser\Controller\PositionController($mapId);
break; break;
case '/': case '/':
header('Location: ' . $host . '/game', true, 302); header('Location: ' . $host . '/maps', true, 302);
die; die;
default: default:
echo 'Error 404'; echo 'Error 404';

View File

@ -12,13 +12,61 @@ html, body {
padding: 0; padding: 0;
} }
p, button { button::-moz-focus-inner, input::-moz-focus-inner {
padding: 0;
border: 0;
}
p, h1, h2, button, a {
font-family: 'Roboto', sans-serif; font-family: 'Roboto', sans-serif;
} }
h1, h2 {
font-weight: 500;
}
h1 {
font-size: 32px;
}
h1>a:link, h1>a:visited {
color: inherit;
}
h1>a:hover, h1>a:focus {
text-decoration: none;
}
h2, div.header.small h1 {
font-size: 24px;
}
p, h2 {
line-height: 150%;
}
p { p {
font-weight: 300; font-weight: 300;
font-size: 12px; font-size: 16px;
}
img {
display: block;
}
sup, sub {
position: relative;
font-size: smaller;
}
sup {
vertical-align: top;
top: -0.4em;
}
sub {
vertical-align: bottom;
bottom: -0.4em;
} }
.mono { .mono {
@ -29,7 +77,37 @@ p {
font-weight: 500; font-weight: 500;
} }
button { .small {
font-size: 12px;
}
.justify {
text-align: justify;
}
.marginTop {
margin-top: 10px;
}
.marginBottom {
margin-bottom: 10px;
}
svg.inline {
vertical-align: -0.15em;
}
a:link, a:visited {
color: #3b5998;
font-weight: 500;
text-decoration: none;
}
a:hover, a:focus {
text-decoration: underline;
}
button, a.button {
cursor: pointer; cursor: pointer;
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;
@ -39,11 +117,15 @@ button {
height: 35px; height: 35px;
border: none; border: none;
border-radius: 3px; border-radius: 3px;
display: inline-block;
text-align: center;
line-height: 35px;
} }
button:enabled:hover, button:enabled:focus { button:enabled:hover, button:enabled:focus, a.button:hover, a.button:focus {
background-color: #29457f; background-color: #29457f;
outline: none; outline: none;
text-decoration: none;
} }
button:disabled { button:disabled {
@ -52,33 +134,92 @@ button:disabled {
opacity: 0.7; opacity: 0.7;
} }
button.fullWidth { button.fullWidth, a.button.fullWidth {
padding: 0; padding: 0;
width: 100%; width: 100%;
} }
button.gray { button.gray, a.button.gray {
background-color: #808080; background-color: #808080;
} }
button.gray:hover, button.gray:focus { button.gray:hover, button.gray:focus, a.button.gray:hover, a.button.gray:focus {
background-color: #555555; background-color: #555555;
} }
div.header {
background-color: #333333;
height: 50px;
line-height: 50px;
padding: 0 12px;
color: white;
}
div.header>div.grid {
display: grid;
grid-template-columns: auto auto;
}
div.header.small {
height: 40px;
line-height: 40px;
}
div.main {
padding: 6px 12px;
}
div.buttonContainer { div.buttonContainer {
height: 35px; height: 35px;
} }
div.buttonContainer > button { div.buttonContainer>button {
margin: 0 auto; margin: 0 auto;
} }
div.buttonContainer.top { div.mapContainer {
margin-bottom: 10px; display: grid;
} }
div.buttonContainer.bottom { div.mapItem {
margin-top: 10px; width: 350px;
background-color: #eeeeee;
border-radius: 3px;
margin: 10px auto;
}
div.mapItem>div.title {
background-color: #28a745;
color: white;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
padding: 4px 8px;
}
div.mapItem>div.title>p.title {
font-weight: 500;
font-size: 18px;
}
div.mapItem>img {
width: 100%;
}
div.mapItem>div.inner {
padding: 8px;
}
div.mapItem>div.inner>div.info {
display: grid;
grid-template-columns: auto auto;
}
div.mapItem>div.inner>div.info>p:nth-child(1) {
text-align: left;
}
div.mapItem>div.inner>div.info>p:nth-child(2) {
text-align: right;
} }
#loading { #loading {
@ -89,33 +230,36 @@ div.buttonContainer.bottom {
left: 50%; left: 50%;
margin-top: -32px; margin-top: -32px;
margin-left: -32px; margin-left: -32px;
z-index: 3; z-index: 5;
} }
#roundInfo { #roundInfo {
position: absolute; line-height: inherit;
top: 5px; text-align: right;
left: 5px;
height: 28px;
line-height: 28px;
padding: 0 8px;
background-color: #eeeeee;
border: solid 1px #555555;
border-radius: 3px;
opacity: 0.95;
z-index: 2;
} }
#roundInfo p { #roundInfo p {
font-size: 16px; font-size: 16px;
line-height: inherit;
} }
#panorama { #panorama {
height: 100%;
width: 100%; width: 100%;
height: calc(100% - 40px);
z-index: 1; z-index: 1;
} }
#cover {
position: absolute;
top: 40px;
left: 0;
bottom: 0;
right: 0;
background-color: #000000;
opacity: 0.5;
z-index: 3;
}
#guess { #guess {
position: absolute; position: absolute;
bottom: 30px; bottom: 30px;
@ -123,16 +267,19 @@ div.buttonContainer.bottom {
z-index: 2; z-index: 2;
} }
#guess > #continueButtonContainer { #guess.result {
z-index: 4;
}
#guess>#continueButtonContainer {
display: none; display: none;
} }
#guess.result > #closeGuessButtonContainer, #guess.result>#closeGuessButtonContainer, #guess.result>#guessButtonContainer {
#guess.result > #guessButtonContainer {
display: none; display: none;
} }
#guess.result > #continueButtonContainer { #guess.result>#continueButtonContainer {
display: block; display: block;
} }
@ -141,14 +288,14 @@ div.buttonContainer.bottom {
border-radius: 3px; border-radius: 3px;
} }
#guess.result > #map { #guess.result>#map {
height: calc(100% - 170px); height: calc(100% - 170px);
} }
#resultInfo { #resultInfo {
margin-top: 5px; margin-top: 5px;
height: 120px;
width: 100%; width: 100%;
height: 120px;
padding: 5px 20px; padding: 5px 20px;
text-align: center; text-align: center;
box-sizing: border-box; box-sizing: border-box;
@ -157,13 +304,13 @@ div.buttonContainer.bottom {
display: none; display: none;
} }
#guess.result > #resultInfo { #guess.result>#resultInfo {
display: block; display: block;
} }
#resultInfo > div { #resultInfo>div {
height: 33.33%;
width: 100%; width: 100%;
height: 33.33%;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@ -171,9 +318,10 @@ div.buttonContainer.bottom {
#resultInfo p { #resultInfo p {
font-size: 24px; font-size: 24px;
line-height: 1;
} }
#distanceInfo > p:nth-child(2), #scoreInfo > p:nth-child(2) { #distanceInfo>p:nth-child(2), #scoreInfo>p:nth-child(2) {
display: none; display: none;
} }
@ -185,8 +333,8 @@ div.buttonContainer.bottom {
} }
#scoreBar { #scoreBar {
height: 100%;
width: 0; width: 0;
height: 100%;
border-radius: 3px; border-radius: 3px;
transition-property: width; transition-property: width;
transition-duration: 2.0s; transition-duration: 2.0s;
@ -196,12 +344,44 @@ div.buttonContainer.bottom {
display: none; display: none;
} }
@media screen and (min-width: 1504px) {
div.mapContainer {
grid-template-columns: auto auto auto auto;
}
}
@media screen and (min-width: 1134px) and (max-width: 1503px) {
div.mapContainer {
grid-template-columns: auto auto auto;
}
}
@media screen and (min-width: 764px) and (max-width: 1133px) {
div.mapContainer {
grid-template-columns: auto auto;
}
}
@media screen and (max-width: 763px) {
div.mapContainer {
grid-template-columns: auto;
}
}
@media screen and (max-width: 374px) {
div.mapItem {
width: initial;
}
}
@media screen and (max-width: 599px) { @media screen and (max-width: 599px) {
div.header.small h1 span {
display: none;
}
button { button {
padding: 0; padding: 0;
width: 100%; width: 100%;
} }
#showGuessButtonContainer { #showGuessButtonContainer {
position: absolute; position: absolute;
left: 20px; left: 20px;
@ -209,18 +389,15 @@ div.buttonContainer.bottom {
right: 20px; right: 20px;
z-index: 2; z-index: 2;
} }
#guess { #guess {
top: 50px;
left: 20px; left: 20px;
top: 40px;
opacity: 0.95; opacity: 0.95;
visibility: hidden; visibility: hidden;
} }
#map { #map {
height: calc(100% - 90px); height: calc(100% - 90px);
} }
#scoreBarBase { #scoreBarBase {
width: 100%; width: 100%;
} }
@ -230,13 +407,11 @@ div.buttonContainer.bottom {
#showGuessButtonContainer { #showGuessButtonContainer {
display: none; display: none;
} }
#guess { #guess {
width: 500px; width: 500px;
height: 375px; height: 375px;
opacity: 0.95; opacity: 0.95;
} }
#guess.adapt { #guess.adapt {
top: initial; top: initial;
width: 250px; width: 250px;
@ -246,46 +421,38 @@ div.buttonContainer.bottom {
transition-duration: 0.1s; transition-duration: 0.1s;
transition-delay: 0.8s; transition-delay: 0.8s;
} }
#guess.adapt:hover { #guess.adapt:hover {
width: 500px; width: 500px;
height: 375px; height: 375px;
opacity: 0.95; opacity: 0.95;
transition-delay: 0s; transition-delay: 0s;
} }
#closeGuessButtonContainer { #closeGuessButtonContainer {
display: none; display: none;
} }
#map { #map {
height: calc(100% - 45px); height: calc(100% - 45px);
} }
#guess.result { #guess.result {
width: initial; width: initial;
height: initial; height: initial;
top: 40px; top: 50px;
left: 50px; left: 50px;
right: 50px; right: 50px;
bottom: 50px; bottom: 50px;
} }
#scoreBarBase { #scoreBarBase {
width: 60%; width: 60%;
} }
@media screen and (max-height: 424px) { @media screen and (max-height: 424px) {
#guess { #guess {
top: 40px; top: 50px;
height: initial; height: initial;
} }
#guess.adapt:hover { #guess.adapt:hover {
top: 40px; top: 50px;
height: initial; height: initial;
} }
#guess.result { #guess.result {
left: 20px; left: 20px;
right: 20px; right: 20px;

View File

@ -16,6 +16,7 @@
initialize: function () { initialize: function () {
document.getElementById('loading').style.visibility = 'visible'; document.getElementById('loading').style.visibility = 'visible';
document.getElementById('cover').style.visibility = 'visible';
document.getElementById('currentRound').innerHTML = '1/' + String(Core.NUMBER_OF_ROUNDS); document.getElementById('currentRound').innerHTML = '1/' + String(Core.NUMBER_OF_ROUNDS);
document.getElementById('currentScoreSum').innerHTML = '0/0'; document.getElementById('currentScoreSum').innerHTML = '0/0';
@ -33,6 +34,7 @@
} }
document.getElementById('loading').style.visibility = 'hidden'; document.getElementById('loading').style.visibility = 'hidden';
document.getElementById('cover').style.visibility = 'hidden';
Core.panoId = this.response.panoId; Core.panoId = this.response.panoId;
@ -51,11 +53,16 @@
Core.startNewRound(); Core.startNewRound();
}; };
xhr.open('GET', 'position.json', true); xhr.open('GET', 'position.json?map=' + mapId, true);
xhr.send(); xhr.send();
}, },
resetGame: function () { resetGame: function () {
if (Core.guessMarker) {
Core.guessMarker.setMap(null);
Core.guessMarker = null;
}
for (var i = 0; i < Core.rounds.length; ++i) { for (var i = 0; i < Core.rounds.length; ++i) {
var round = Core.rounds[i]; var round = Core.rounds[i];
@ -96,6 +103,7 @@
lastRound.line.setVisible(false); lastRound.line.setVisible(false);
} }
document.getElementById('cover').style.visibility = 'hidden';
document.getElementById('showGuessButton').style.visibility = null; document.getElementById('showGuessButton').style.visibility = null;
document.getElementById('guess').style.visibility = null; document.getElementById('guess').style.visibility = null;
document.getElementById('guess').classList.remove('result') document.getElementById('guess').classList.remove('result')
@ -127,7 +135,7 @@
Core.resetGame(); Core.resetGame();
}; };
xhr.open('GET', 'game.json', true); xhr.open('GET', 'game.json?map=' + mapId, true);
xhr.send(); xhr.send();
}, },
@ -149,6 +157,7 @@
document.getElementById('guess').classList.remove('adapt'); document.getElementById('guess').classList.remove('adapt');
} }
document.getElementById('loading').style.visibility = 'visible'; document.getElementById('loading').style.visibility = 'visible';
document.getElementById('cover').style.visibility = 'visible';
var data = new FormData(); var data = new FormData();
data.append('guess', '1'); data.append('guess', '1');
@ -192,7 +201,7 @@
scoreBar.style.backgroundColor = scoreBarProperties.backgroundColor; scoreBar.style.backgroundColor = scoreBarProperties.backgroundColor;
scoreBar.style.width = scoreBarProperties.width; scoreBar.style.width = scoreBarProperties.width;
if (Core.rounds.length == Core.NUMBER_OF_ROUNDS) { if (Core.rounds.length === Core.NUMBER_OF_ROUNDS) {
document.getElementById('continueButton').style.display = 'none'; document.getElementById('continueButton').style.display = 'none';
document.getElementById('showSummaryButton').style.display = 'block'; document.getElementById('showSummaryButton').style.display = 'block';
} }
@ -200,7 +209,7 @@
Core.panoId = this.response.panoId; Core.panoId = this.response.panoId;
}; };
xhr.open('POST', 'position.json', true); xhr.open('POST', 'position.json?map=' + mapId, true);
xhr.send(data); xhr.send(data);
}, },
@ -438,7 +447,13 @@
Core.resetGame(); Core.resetGame();
} }
// showing the loading animation is not possible, because we don't know if user cancelled the leave
window.onbeforeunload = function (e) { window.onbeforeunload = function (e) {
if (Core.rounds[Core.rounds.length - 1].position) {
return;
}
e.preventDefault(); e.preventDefault();
e.returnValue = ''; e.returnValue = '';
}; };

View File

@ -10,13 +10,13 @@ use MapGuesser\Interfaces\View\IView;
class GameController implements IController class GameController implements IController
{ {
private int $mapId;
private bool $jsonResponse; private bool $jsonResponse;
// demo map public function __construct(int $mapId, $jsonResponse = false)
private int $mapId = 1;
public function __construct($jsonResponse = false)
{ {
$this->mapId = $mapId;
$this->jsonResponse = $jsonResponse; $this->jsonResponse = $jsonResponse;
} }
@ -32,7 +32,7 @@ class GameController implements IController
]; ];
} }
$data = ['bounds' => $bounds->toArray()]; $data = ['mapId' => $this->mapId, 'bounds' => $bounds->toArray()];
if ($this->jsonResponse) { if ($this->jsonResponse) {
return new JsonView($data); return new JsonView($data);

View File

@ -0,0 +1,66 @@
<?php namespace MapGuesser\Controller;
use MapGuesser\Database\Query\Select;
use MapGuesser\Database\RawExpression;
use MapGuesser\Interfaces\Controller\IController;
use MapGuesser\Interfaces\Database\IResultSet;
use MapGuesser\Interfaces\View\IView;
use MapGuesser\Util\Geo\Bounds;
use MapGuesser\View\HtmlView;
class MapsController implements IController
{
public function run(): IView
{
$select = new Select(\Container::$dbConnection, 'maps');
$select->columns([
['maps', 'id'],
['maps', 'name'],
['maps', 'description'],
['maps', 'bound_south_lat'],
['maps', 'bound_west_lng'],
['maps', 'bound_north_lat'],
['maps', 'bound_east_lng'],
new RawExpression('COUNT(places.id) AS num_places')
]);
$select->leftJoin('places', ['places', 'map_id'], '=', ['maps', 'id']);
$select->orderBy('name');
$result = $select->execute();
$maps = [];
while ($map = $result->fetch(IResultSet::FETCH_ASSOC)) {
$bounds = Bounds::createDirectly($map['bound_south_lat'], $map['bound_west_lng'], $map['bound_north_lat'], $map['bound_east_lng']);
$map['area'] = $this->formatMapAreaForHuman($bounds->calculateApproximateArea());
$maps[] = $map;
}
$data = ['maps' => $maps];
return new HtmlView('maps', $data);
}
private function formatMapAreaForHuman(float $area): array
{
if ($area < 100000.0) {
$digits = 0;
$rounded = round($area, 0);
$unit = 'm';
} elseif ($area < 100000000.0) {
$digits = 0;
$rounded = round($area / 1000000.0, 0);
$unit = 'km';
} elseif ($area < 10000000000.0) {
$digits = 0;
$rounded = round($area / 1000000.0, -2);
$unit = 'km';
} else {
$digits = 0;
$rounded = round($area / 1000000.0, -4);
$unit = 'km';
}
return [number_format($rounded, $digits, '.', ' '), $unit];
}
}

View File

@ -13,8 +13,12 @@ class PositionController implements IController
const NUMBER_OF_ROUNDS = 5; const NUMBER_OF_ROUNDS = 5;
const MAX_SCORE = 1000; const MAX_SCORE = 1000;
// demo map private int $mapId;
private int $mapId = 1;
public function __construct(int $mapId)
{
$this->mapId = $mapId;
}
public function run(): IView public function run(): IView
{ {
@ -120,7 +124,7 @@ class PositionController implements IController
$select->where('id', 'NOT IN', $exclude); $select->where('id', 'NOT IN', $exclude);
$select->where('map_id', '=', $this->mapId); $select->where('map_id', '=', $this->mapId);
$numberOfPlaces = $select->count(); $numberOfPlaces = $select->count();// TODO: what if 0
$randomOffset = random_int(0, $numberOfPlaces - 1); $randomOffset = random_int(0, $numberOfPlaces - 1);
$select->orderBy('id'); $select->orderBy('id');

View File

@ -4,21 +4,25 @@ class Bounds
{ {
const ONE_DEGREE_OF_LATITUDE_IN_METER = 111132.954; const ONE_DEGREE_OF_LATITUDE_IN_METER = 111132.954;
private float $southLat; private float $southLat = 90.0;
private float $westLng; private float $westLng = 180.0;
private float $northLat; private float $northLat = -90.0;
private float $eastLng; private float $eastLng = -180.0;
private bool $initialized = false; public function __construct(Position $position = null)
public static function createWithPosition(Position $position): Bounds
{ {
$instance = new static(); if ($position === null) {
return;
}
$instance->initialize($position); $lat = $position->getLat();
$lng = $position->getLng();
return $instance; $this->northLat = $lat;
$this->westLng = $lng;
$this->southLat = $lat;
$this->eastLng = $lng;
} }
public static function createDirectly(float $southLat, float $westLng, float $northLat, float $eastLng): Bounds public static function createDirectly(float $southLat, float $westLng, float $northLat, float $eastLng): Bounds
@ -30,19 +34,11 @@ class Bounds
$instance->northLat = $northLat; $instance->northLat = $northLat;
$instance->eastLng = $eastLng; $instance->eastLng = $eastLng;
$instance->initialized = true;
return $instance; return $instance;
} }
public function extend(Position $position): void public function extend(Position $position): void
{ {
if (!$this->initialized) {
$this->initialize($position);
return;
}
$lat = $position->getLat(); $lat = $position->getLat();
$lng = $position->getLng(); $lng = $position->getLng();
@ -77,10 +73,6 @@ class Bounds
public function toArray(): array public function toArray(): array
{ {
if (!$this->initialized) {
throw new \Exception("Bounds are not initialized!");
}
return [ return [
'south' => $this->southLat, 'south' => $this->southLat,
'west' => $this->westLng, 'west' => $this->westLng,
@ -93,17 +85,4 @@ class Bounds
{ {
return json_encode($this->toArray()); return json_encode($this->toArray());
} }
private function initialize(Position $position)
{
$lat = $position->getLat();
$lng = $position->getLng();
$this->northLat = $lat;
$this->westLng = $lng;
$this->southLat = $lat;
$this->eastLng = $lng;
$this->initialized = true;
}
} }

View File

@ -11,19 +11,31 @@
<div id="loading"> <div id="loading">
<img src="static/img/loading.svg"> <img src="static/img/loading.svg">
</div> </div>
<div id="roundInfo"> <div class="header small">
<p>Round: <span id="currentRound" class="mono bold"></span> | Score: <span id="currentScoreSum" class="mono bold"></span></p> <div class="grid">
<h1>
<a href="maps" title="Back to playable maps">
<!-- Copyright (c) 2019 The Bootstrap Authors. License can be found in 'USED_SOFTWARE' in section 'Bootstrap Icons'. -->
<svg class="inline" width="1em" height="1em" viewBox="0 0 16 16" fill="#28a745" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M15.817.613A.5.5 0 0 1 16 1v13a.5.5 0 0 1-.402.49l-5 1a.502.502 0 0 1-.196 0L5.5 14.51l-4.902.98A.5.5 0 0 1 0 15V2a.5.5 0 0 1 .402-.49l5-1a.5.5 0 0 1 .196 0l4.902.98 4.902-.98a.5.5 0 0 1 .415.103zM10 2.41l-4-.8v11.98l4 .8V2.41zm1 11.98l4-.8V1.61l-4 .8v11.98zm-6-.8V1.61l-4 .8v11.98l4-.8z" />
</svg>
<span>MapGuesser</span>
</a>
</h1>
<p id="roundInfo">Round: <span id="currentRound" class="mono bold"></span> | Score: <span id="currentScoreSum" class="mono bold"></span></p>
</div> </div>
</div>
<div id="cover"></div>
<div id="panorama"></div> <div id="panorama"></div>
<div id="showGuessButtonContainer"> <div id="showGuessButtonContainer">
<button id="showGuessButton" class="fullWidth">Show guess map</button> <button id="showGuessButton" class="fullWidth">Show guess map</button>
</div> </div>
<div id="guess"> <div id="guess">
<div id="closeGuessButtonContainer" class="buttonContainer top"> <div id="closeGuessButtonContainer" class="buttonContainer marginBottom">
<button id="closeGuessButton" class="fullWidth gray">Close</button> <button id="closeGuessButton" class="fullWidth gray">Close</button>
</div> </div>
<div id="map"></div> <div id="map"></div>
<div id="guessButtonContainer" class="buttonContainer bottom"> <div id="guessButtonContainer" class="buttonContainer marginTop">
<button id="guessButton" class="fullWidth" disabled>Guess</button> <button id="guessButton" class="fullWidth" disabled>Guess</button>
</div> </div>
<div id="resultInfo"> <div id="resultInfo">
@ -41,16 +53,17 @@
</div> </div>
</div> </div>
</div> </div>
<div id="continueButtonContainer" class="buttonContainer bottom"> <div id="continueButtonContainer" class="buttonContainer marginTop">
<button id="continueButton" class="fullWidth">Continue</button> <button id="continueButton" class="fullWidth">Continue</button>
<button id="showSummaryButton" class="fullWidth">Show summary</button> <button id="showSummaryButton" class="fullWidth">Show summary</button>
<button id="startNewGameButton" class="fullWidth">Start new game</button> <button id="startNewGameButton" class="fullWidth">Play this map again</button>
</div> </div>
</div> </div>
<script> <script>
var mapId = '<?= $mapId ?>';
var mapBounds = <?= json_encode($bounds) ?>; var mapBounds = <?= json_encode($bounds) ?>;
</script> </script>
<script src="https://maps.googleapis.com/maps/api/js?key=<?= $_ENV['GOOGLE_MAPS_JS_API_KEY'] ?>"></script> <script src="https://maps.googleapis.com/maps/api/js?key=<?= $_ENV['GOOGLE_MAPS_JS_API_KEY'] ?>"></script>
<script src="static/js/mapguesser.js"></script> <script src="static/js/game.js"></script>
</body> </body>
</html> </html>

70
views/maps.php Normal file
View File

@ -0,0 +1,70 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>MapGuesser</title>
<link href="static/css/mapguesser.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;500&family=Roboto+Mono:wght@300;500&display=swap" rel="stylesheet">
</head>
<body>
<div id="loading">
<img src="static/img/loading.svg">
</div>
<div class="header">
<h1>
<!-- Copyright (c) 2019 The Bootstrap Authors. License can be found in 'USED_SOFTWARE' in section 'Bootstrap Icons'. -->
<svg class="inline" width="1em" height="1em" viewBox="0 0 16 16" fill="#28a745" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M15.817.613A.5.5 0 0 1 16 1v13a.5.5 0 0 1-.402.49l-5 1a.502.502 0 0 1-.196 0L5.5 14.51l-4.902.98A.5.5 0 0 1 0 15V2a.5.5 0 0 1 .402-.49l5-1a.5.5 0 0 1 .196 0l4.902.98 4.902-.98a.5.5 0 0 1 .415.103zM10 2.41l-4-.8v11.98l4 .8V2.41zm1 11.98l4-.8V1.61l-4 .8v11.98zm-6-.8V1.61l-4 .8v11.98l4-.8z" />
</svg>
MapGuesser
</h1>
</div>
<div class="main">
<h2>Playable maps</h2>
<div class="mapContainer">
<?php foreach ($maps as $map) : ?>
<div class="mapItem">
<div class="title">
<p class="title"><?= $map['name'] ?></p>
</div>
<img src="https://maps.googleapis.com/maps/api/staticmap?size=350x175&visible=<?= $map['bound_south_lat'] . ',' . $map['bound_west_lng'] . '|' . $map['bound_north_lat'] . ',' . $map['bound_east_lng'] ?>&key=<?= $_ENV['GOOGLE_MAPS_JS_API_KEY'] ?>">
<div class="inner">
<div class="info">
<p>
<!-- Copyright (c) 2019 The Bootstrap Authors. License can be found in 'USED_SOFTWARE' in section 'Bootstrap Icons'. -->
<svg class="inline" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M8 16s6-5.686 6-10A6 6 0 0 0 2 6c0 4.314 6 10 6 10zm0-7a3 3 0 1 0 0-6 3 3 0 0 0 0 6z" />
</svg>
<?= $map['num_places'] ?> places
</p>
<p>
<!-- Copyright (c) 2019 The Bootstrap Authors. License can be found in 'USED_SOFTWARE' in section 'Bootstrap Icons'. -->
<svg class="inline" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M12.5 2h-9V1h9v1zm-10 1.5v9h-1v-9h1zm11 9v-9h1v9h-1zM3.5 14h9v1h-9v-1z" />
<path fill-rule="evenodd" d="M14 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0 1a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0 11a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0 1a2 2 0 1 0 0-4 2 2 0 0 0 0 4zM2 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0 1a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0 11a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0 1a2 2 0 1 0 0-4 2 2 0 0 0 0 4z" />
</svg>
~ <?= $map['area'][0] ?> <?= $map['area'][1] ?><sup>2</sup>
</p>
</div>
<p class="small justify marginTop"><?= $map['description'] ?></p>
</div>
<a class="button fullWidth" href="game?map=<?= $map['id']; ?>" title="Play map '<?= $map['name'] ?>'">Play this map</a>
</div>
<?php endforeach; ?>
<?php if (count($maps) < 4): ?>
<?php for ($i = 0; $i < 4 - count($maps); ++$i): ?>
<div class="mapItem"></div>
<?php endfor; ?>
<?php endif; ?>
</div>
</div>
<script>
document.getElementById('loading').style.visibility = 'hidden';
window.addEventListener('beforeunload', function (e) {
document.getElementById('loading').style.visibility = 'visible';
});
</script>
</body>
</html>