Merged in feature/MAPG-7-implement-automatic-deployment (pull request #8)

Feature/MAPG-7 implement automatic deployment
This commit is contained in:
Bence Pőcze 2020-05-20 12:51:36 +00:00
commit c36b91d5a8
11 changed files with 230 additions and 189 deletions

View File

@ -1,4 +1,4 @@
DEV=true DEV=1
DB_HOST=mariadb DB_HOST=mariadb
DB_USER=mapguesser DB_USER=mapguesser
DB_PASSWORD=mapguesser DB_PASSWORD=mapguesser

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
.env .env
installed
vendor vendor

View File

@ -13,7 +13,6 @@ services:
volumes: volumes:
- mysql:/var/lib/mysql - mysql:/var/lib/mysql
environment: environment:
#TZ: Europe/Budapest
MYSQL_ROOT_PASSWORD: 'root' MYSQL_ROOT_PASSWORD: 'root'
MYSQL_DATABASE: 'mapguesser' MYSQL_DATABASE: 'mapguesser'
MYSQL_USER: 'mapguesser' MYSQL_USER: 'mapguesser'

View File

@ -4,13 +4,9 @@ ENV DEBIAN_FRONTEND noninteractive
# Install Apache, PHP and further necessary packages # Install Apache, PHP and further necessary packages
RUN apt update RUN apt update
RUN apt install -y curl git apache2 \ RUN apt install -y curl git mariadb-client apache2 \
php-apcu php-xdebug php7.4-cli php7.4-fpm php7.4-mbstring php7.4-mysql php7.4-zip php-apcu php-xdebug php7.4-cli php7.4-fpm php7.4-mbstring php7.4-mysql php7.4-zip
# Configure tzdata
#RUN ln -fs /usr/share/zoneinfo/Europe/Budapest /etc/localtime
#RUN dpkg-reconfigure --frontend noninteractive tzdata
# Configure Apache with PHP # Configure Apache with PHP
RUN mkdir -p /run/php RUN mkdir -p /run/php
RUN a2enmod proxy_fcgi rewrite RUN a2enmod proxy_fcgi rewrite
@ -24,6 +20,12 @@ RUN echo "xdebug.remote_connect_back = 1" >> /etc/php/7.4/mods-available/xdebug.
COPY scripts/install-composer.sh install-composer.sh COPY scripts/install-composer.sh install-composer.sh
RUN ./install-composer.sh RUN ./install-composer.sh
# Install Node.js and required packages
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash -
RUN apt install -y nodejs
RUN npm install -g uglify-js
RUN npm install -g clean-css-cli
EXPOSE 80 EXPOSE 80
VOLUME /var/www/mapguesser VOLUME /var/www/mapguesser
WORKDIR /var/www/mapguesser WORKDIR /var/www/mapguesser

View File

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
EXPECTED_CHECKSUM="$(curl -s https://composer.github.io/installer.sig)" EXPECTED_CHECKSUM="$(curl -sL https://composer.github.io/installer.sig)"
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")" ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"

View File

@ -3,6 +3,7 @@
require '../main.php'; require '../main.php';
// very basic routing // very basic routing
$host = $_SERVER["REQUEST_SCHEME"] . '://' . $_SERVER["SERVER_NAME"];
$url = $_SERVER['REQUEST_URI']; $url = $_SERVER['REQUEST_URI'];
switch($url) { switch($url) {
case '/game': case '/game':
@ -11,6 +12,9 @@ switch($url) {
case '/getNewPosition.json': case '/getNewPosition.json':
$controller = new MapGuesser\Controller\GetNewPosition(); $controller = new MapGuesser\Controller\GetNewPosition();
break; break;
case '/':
header('Location: ' . $host . '/game', true, 302);
die;
default: default:
echo 'Error 404'; echo 'Error 404';
die; die;

View File

@ -1,17 +1,92 @@
Math.deg2rad = function (deg) { (function () {
return deg * (this.PI / 180.0); var Core = {
};
var Util = {
EARTH_RADIUS_IN_METER: 6371000,
MAX_SCORE: 1000, MAX_SCORE: 1000,
realPosition: null,
panorama: null,
guessMap: null,
guessMarker: null,
resultMap: null,
resultMarkers: { guess: null, real: null },
googleLink: null,
getNewPosition: function () {
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
Core.realPosition = this.response.position;
var sv = new google.maps.StreetViewService();
sv.getPanorama({ location: this.response.position, preference: google.maps.StreetViewPreference.NEAREST }, Core.loadPano);
}
};
xhr.open('GET', 'getNewPosition.json', true);
xhr.send();
},
loadPano: function (data, status) {
if (status !== google.maps.StreetViewStatus.OK) {
Core.getNewPosition();
return;
}
Core.panorama.setPov({ heading: 0, pitch: 0, zoom: 1 });
Core.panorama.setPano(data.location.pano);
},
calculateScore: function (distance) {
var goodness = 1.0 - distance / Math.sqrt(mapArea);
return Math.pow(Core.MAX_SCORE, goodness);
},
calculateScoreBarProperties: function (score) {
var percent = Math.round((score / Core.MAX_SCORE) * 100);
var color;
if (percent >= 90) {
color = '#11ca00';
} else if (percent >= 10) {
color = '#ea9000';
} else {
color = '#ca1100';
}
return { width: percent + '%', backgroundColor: color };
},
rewriteGoogleLink: function () {
if (!Core.googleLink) {
var anchors = document.getElementById('panorama').getElementsByTagName('a');
for (var i = 0; i < anchors.length; i++) {
var a = anchors[i];
if (a.href.indexOf('maps.google.com/maps') !== -1) {
Core.googleLink = a;
break;
}
}
}
setTimeout(function () {
Core.googleLink.title = 'Google Maps'
Core.googleLink.href = 'https://maps.google.com/maps'
}, 1);
}
};
var Util = {
EARTH_RADIUS_IN_METER: 6371000,
deg2rad: function (deg) {
return deg * (Math.PI / 180.0);
},
calculateDistance: function (position1, position2) { calculateDistance: function (position1, position2) {
var lat1 = Math.deg2rad(position1.lat); var lat1 = Util.deg2rad(position1.lat);
var lng1 = Math.deg2rad(position1.lng); var lng1 = Util.deg2rad(position1.lng);
var lat2 = Math.deg2rad(position2.lat); var lat2 = Util.deg2rad(position2.lat);
var lng2 = Math.deg2rad(position2.lng); var lng2 = Util.deg2rad(position2.lng);
var angleCos = Math.cos(lat1) * Math.cos(lat2) * Math.cos(lng2 - lng1) + var angleCos = Math.cos(lat1) * Math.cos(lat2) * Math.cos(lng2 - lng1) +
Math.sin(lat1) * Math.sin(lat2); Math.sin(lat1) * Math.sin(lat2);
@ -35,75 +110,25 @@ 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 }; Core.guessMap = new google.maps.Map(document.getElementById('guessMap'), {
}
};
var MapManipulator = {
rewriteGoogleLink: function () {
if (!googleLink) {
var anchors = document.getElementById('panorama').getElementsByTagName('a');
for (var i = 0; i < anchors.length; i++) {
var a = anchors[i];
if (a.href.indexOf('maps.google.com/maps') !== -1) {
googleLink = a;
break;
}
}
}
setTimeout(function () {
googleLink.title = 'Google Maps'
googleLink.href = 'https://maps.google.com/maps'
}, 1);
}
};
var realPosition;
var panorama;
var guessMap;
var guessMarker;
var resultMap;
var resultMarkers = { guess: null, real: null };
var googleLink;
function initialize() {
guessMap = new google.maps.Map(document.getElementById('guessMap'), {
disableDefaultUI: true, disableDefaultUI: true,
clickableIcons: false, clickableIcons: false,
draggableCursor: 'crosshair' draggableCursor: 'crosshair'
}); });
guessMap.fitBounds(guessMapBounds); Core.guessMap.fitBounds(guessMapBounds);
guessMap.addListener('click', function (e) { Core.guessMap.addListener('click', function (e) {
if (guessMarker) { if (Core.guessMarker) {
guessMarker.setPosition(e.latLng); Core.guessMarker.setPosition(e.latLng);
return; return;
} }
guessMarker = new google.maps.Marker({ Core.guessMarker = new google.maps.Marker({
map: guessMap, map: Core.guessMap,
position: e.latLng, position: e.latLng,
clickable: false, clickable: false,
draggable: true, draggable: true,
@ -119,83 +144,57 @@ function initialize() {
document.getElementById('guessButton').disabled = false; document.getElementById('guessButton').disabled = false;
}); });
panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), { Core.panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), {
disableDefaultUI: true, disableDefaultUI: true,
linksControl: true, linksControl: true,
showRoadLabels: false showRoadLabels: false
}); });
panorama.addListener('position_changed', function () { Core.panorama.addListener('position_changed', function () {
MapManipulator.rewriteGoogleLink(); Core.rewriteGoogleLink();
}); });
panorama.addListener('pov_changed', function () { Core.panorama.addListener('pov_changed', function () {
MapManipulator.rewriteGoogleLink(); Core.rewriteGoogleLink();
}); });
resultMap = new google.maps.Map(document.getElementById('resultMap'), { Core.resultMap = new google.maps.Map(document.getElementById('resultMap'), {
disableDefaultUI: true, disableDefaultUI: true,
clickableIcons: false, clickableIcons: false,
}); });
getNewPosition(); Core.getNewPosition();
}
function getNewPosition() { document.getElementById('guessButton').onclick = function () {
var xhr = new XMLHttpRequest(); if (!Core.guessMarker) {
xhr.responseType = 'json';
xhr.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
realPosition = this.response.position;
var sv = new google.maps.StreetViewService();
sv.getPanorama({ location: this.response.position, preference: google.maps.StreetViewPreference.NEAREST }, loadPano);
}
};
xhr.open('GET', 'getNewPosition.json', true);
xhr.send();
}
function loadPano(data, status) {
if (status !== google.maps.StreetViewStatus.OK) {
getNewPosition();
return; return;
} }
panorama.setPov({heading: 0, pitch: 0, zoom: 1}); var guessedPosition = Core.guessMarker.getPosition();
panorama.setPano(data.location.pano);
}
document.getElementById('guessButton').onclick = function () {
if (!guessMarker) {
return;
}
var guessedPosition = guessMarker.getPosition();
this.disabled = true; this.disabled = true;
guessMarker.setMap(null); Core.guessMarker.setMap(null);
guessMarker = null; Core.guessMarker = null;
var distance = Util.calculateDistance(realPosition, { lat: guessedPosition.lat(), lng: guessedPosition.lng() }); var distance = Util.calculateDistance(Core.realPosition, { lat: guessedPosition.lat(), lng: guessedPosition.lng() });
document.getElementById('guess').style.visibility = 'hidden'; document.getElementById('guess').style.visibility = 'hidden';
document.getElementById('result').style.visibility = 'visible'; document.getElementById('result').style.visibility = 'visible';
var resultBounds = new google.maps.LatLngBounds(); var resultBounds = new google.maps.LatLngBounds();
resultBounds.extend(realPosition); resultBounds.extend(Core.realPosition);
resultBounds.extend(guessedPosition); resultBounds.extend(guessedPosition);
resultMap.fitBounds(resultBounds); Core.resultMap.fitBounds(resultBounds);
resultMarkers.real = new google.maps.Marker({ Core.resultMarkers.real = new google.maps.Marker({
map: resultMap, map: Core.resultMap,
position: realPosition, position: Core.realPosition,
clickable: true, clickable: true,
draggable: false draggable: false
}); });
resultMarkers.guess = new google.maps.Marker({ Core.resultMarkers.guess = new google.maps.Marker({
map: resultMap, map: Core.resultMap,
position: guessedPosition, position: guessedPosition,
clickable: false, clickable: false,
draggable: false, draggable: false,
@ -208,34 +207,35 @@ document.getElementById('guessButton').onclick = function () {
} }
}); });
resultMarkers.real.addListener('click', function () { Core.resultMarkers.real.addListener('click', function () {
window.open('https://www.google.com/maps/search/?api=1&query=' + realPosition.lat + ',' + realPosition.lng, '_blank'); window.open('https://www.google.com/maps/search/?api=1&query=' + Core.realPosition.lat + ',' + Core.realPosition.lng, '_blank');
}); });
document.getElementById('distance').innerHTML = Util.printDistanceForHuman(distance); document.getElementById('distance').innerHTML = Util.printDistanceForHuman(distance);
var score = Util.calculateScore(distance); var score = Core.calculateScore(distance);
var scoreBarProperties = Util.calculateScoreBarProperties(score); var scoreBarProperties = Core.calculateScoreBarProperties(score);
document.getElementById('score').innerHTML = Number.parseFloat(score).toFixed(0); document.getElementById('score').innerHTML = Number.parseFloat(score).toFixed(0);
var scoreBar = document.getElementById('scoreBar'); var scoreBar = document.getElementById('scoreBar');
scoreBar.style.backgroundColor = scoreBarProperties.backgroundColor; scoreBar.style.backgroundColor = scoreBarProperties.backgroundColor;
scoreBar.style.width = scoreBarProperties.width; scoreBar.style.width = scoreBarProperties.width;
} }
document.getElementById('continueButton').onclick = function () { document.getElementById('continueButton').onclick = function () {
document.getElementById('scoreBar').style.width = '0'; document.getElementById('scoreBar').style.width = '0';
resultMarkers.real.setMap(null); Core.resultMarkers.real.setMap(null);
resultMarkers.real = null; Core.resultMarkers.real = null;
resultMarkers.guess.setMap(null); Core.resultMarkers.guess.setMap(null);
resultMarkers.guess = null; Core.resultMarkers.guess = null;
document.getElementById('guess').style.visibility = 'visible'; document.getElementById('guess').style.visibility = 'visible';
document.getElementById('result').style.visibility = 'hidden'; document.getElementById('result').style.visibility = 'hidden';
guessMap.fitBounds(guessMapBounds); Core.guessMap.fitBounds(guessMapBounds);
getNewPosition(); Core.getNewPosition();
} }
})();

23
scripts/install.sh Executable file
View File

@ -0,0 +1,23 @@
#/bin/bash
ROOT_DIR=$(dirname $(readlink -f "$0"))/..
. ${ROOT_DIR}/.env
if [ -f ${ROOT_DIR}/installed ]; then
echo "Mapguesser is already installed! To force reinstall, delete file 'installed' from the root directory!"
exit 1
fi
echo "Installing MapGuesser DB..."
mysql --host=${DB_HOST} --user=${DB_USER} --password=${DB_PASSWORD} ${DB_NAME} < ${ROOT_DIR}/db/mapguesser.sql
if [ -z "${DEV}" ] || [ "${DEV}" -eq "0" ]; then
echo "Uglifying JS and CSS files..."
uglifyjs ${ROOT_DIR}/public/static/js/mapguesser.js -c -m -o ${ROOT_DIR}/public/static/js/mapguesser.js
cleancss ${ROOT_DIR}/public/static/css/mapguesser.css -o ${ROOT_DIR}/public/static/css/mapguesser.css
fi
touch ${ROOT_DIR}/installed

12
scripts/update.sh Executable file
View File

@ -0,0 +1,12 @@
#/bin/bash
ROOT_DIR=$(dirname $(readlink -f "$0"))/..
. ${ROOT_DIR}/.env
if [ -z "${DEV}" ] || [ "${DEV}" -eq "0" ]; then
echo "Uglifying JS and CSS files..."
uglifyjs ${ROOT_DIR}/public/static/js/mapguesser.js -c -m -o ${ROOT_DIR}/public/static/js/mapguesser.js
cleancss ${ROOT_DIR}/public/static/css/mapguesser.css -o ${ROOT_DIR}/public/static/css/mapguesser.css
fi

View File

@ -35,7 +35,7 @@
var mapArea = <?= $bounds->calculateApproximateArea() ?>; var mapArea = <?= $bounds->calculateApproximateArea() ?>;
var guessMapBounds = <?= $bounds->toJson() ?>; var guessMapBounds = <?= $bounds->toJson() ?>;
</script> </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/mapguesser.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=<?= $_ENV['GOOGLE_MAPS_JS_API_KEY'] ?>&callback=initialize"></script>
</body> </body>
</html> </html>