MAPG-73 introduce map selection

unify CSS
This commit is contained in:
Bence Pőcze 2020-05-30 15:37:26 +02:00
parent 92c35a2087
commit 9ffedf6030
5 changed files with 275 additions and 43 deletions

View File

@ -9,6 +9,9 @@ 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':
$mapId = isset($_GET['map']) ? (int) $_GET['map'] : 0; $mapId = isset($_GET['map']) ? (int) $_GET['map'] : 0;
$controller = new MapGuesser\Controller\GameController($mapId); $controller = new MapGuesser\Controller\GameController($mapId);
@ -22,7 +25,7 @@ switch($url) {
$controller = new MapGuesser\Controller\PositionController($mapId); $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,35 @@ html, body {
padding: 0; padding: 0;
} }
p, button { p, h1, h2, button, a {
font-family: 'Roboto', sans-serif; font-family: 'Roboto', sans-serif;
} }
h1, h2 {
font-weight: 500;
}
h1 {
font-size: 32px;
line-height: inherit;
}
h2 {
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;
max-width: 100%;
} }
.mono { .mono {
@ -29,7 +51,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 {
text-decoration: underline;
}
button, a.button {
cursor: pointer; cursor: pointer;
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;
@ -39,11 +91,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,19 +108,31 @@ 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.main {
padding: 6px 12px;
}
div.buttonContainer { div.buttonContainer {
height: 35px; height: 35px;
} }
@ -73,12 +141,45 @@ 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: 375px;
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>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 {
@ -108,11 +209,12 @@ div.buttonContainer.bottom {
#roundInfo p { #roundInfo p {
font-size: 16px; font-size: 16px;
line-height: inherit;
} }
#panorama { #panorama {
height: 100%;
width: 100%; width: 100%;
height: 100%;
z-index: 1; z-index: 1;
} }
@ -127,8 +229,7 @@ div.buttonContainer.bottom {
display: none; display: none;
} }
#guess.result > #closeGuessButtonContainer, #guess.result>#closeGuessButtonContainer, #guess.result>#guessButtonContainer {
#guess.result > #guessButtonContainer {
display: none; display: none;
} }
@ -147,8 +248,8 @@ div.buttonContainer.bottom {
#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;
@ -162,8 +263,8 @@ div.buttonContainer.bottom {
} }
#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,6 +272,7 @@ 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) {
@ -185,8 +287,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 +298,35 @@ div.buttonContainer.bottom {
display: none; display: none;
} }
@media screen and (min-width: 1600px) {
div.mapContainer {
grid-template-columns: auto auto auto auto;
}
}
@media screen and (min-width: 1200px) and (max-width: 1599px) {
div.mapContainer {
grid-template-columns: auto auto auto;
}
}
@media screen and (min-width: 800px) and (max-width: 1199px) {
div.mapContainer {
grid-template-columns: auto auto;
}
}
@media screen and (max-width: 799px) {
div.mapContainer {
grid-template-columns: auto;
}
}
@media screen and (max-width: 599px) { @media screen and (max-width: 599px) {
button { button {
padding: 0; padding: 0;
width: 100%; width: 100%;
} }
#showGuessButtonContainer { #showGuessButtonContainer {
position: absolute; position: absolute;
left: 20px; left: 20px;
@ -209,18 +334,15 @@ div.buttonContainer.bottom {
right: 20px; right: 20px;
z-index: 2; z-index: 2;
} }
#guess { #guess {
left: 20px; left: 20px;
top: 40px; 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 +352,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,22 +366,18 @@ 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;
@ -270,22 +386,18 @@ div.buttonContainer.bottom {
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: 40px;
height: initial; height: initial;
} }
#guess.adapt:hover { #guess.adapt:hover {
top: 40px; top: 40px;
height: initial; height: initial;
} }
#guess.result { #guess.result {
left: 20px; left: 20px;
right: 20px; right: 20px;

View File

@ -0,0 +1,60 @@
<?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->formatMapArea($bounds->calculateApproximateArea());
$maps[] = $map;
}
$data = ['maps' => $maps];
return new HtmlView('maps', $data);
}
private function formatMapArea(float $area): string
{
//TODO: this should be formatted more properly
if ($area < 100000.0) {
return round($area, 0) . ' m^2';
} elseif ($area < 100000000.0) {
return round($area / 1000000.0, 0) . ' km^2';
} elseif ($area < 10000000000.0) {
return round($area / 1000000.0, -2) . ' km^2';
} else {
return round($area / 1000000.0, -4) . ' km^2';
}
}
}

View File

@ -19,11 +19,11 @@
<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,10 +41,10 @@
</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>

57
views/maps.php Normal file
View File

@ -0,0 +1,57 @@
<!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 class="header">
<h1>
<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=375x200&visible=<?= $map['bound_south_lat'] . ',' . $map['bound_west_lng'] . '|' . $map['bound_north_lat'] . ',' . $map['bound_east_lng'] ?>&key=<?= $_ENV['GOOGLE_MAPS_JS_API_KEY'] ?>" width="375" height="200">
<div class="inner">
<div class="info">
<p>
<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>
<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'] ?>
</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>
</body>
</html>