La Bureautique vaincra.
|
@ -0,0 +1,2 @@
|
||||||
|
cache/
|
||||||
|
tests/
|
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1,94 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
ini_set('display_errors', 1);
|
||||||
|
ini_set('display_startup_errors', 1);
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
define('DEFAULT_RADIUS', 50);
|
||||||
|
|
||||||
|
define('TAILLE_SPRITE', 32);
|
||||||
|
define('DEMI_TAILLE_SPRITE', (TAILLE_SPRITE/2));
|
||||||
|
|
||||||
|
define('SONAR_DURATION', 5);
|
||||||
|
|
||||||
|
define("LAT_ASTROPORT_ONE", 44.22484418236386);
|
||||||
|
define("LON_ASTROPORT_ONE", 1.6395813014177014);
|
||||||
|
|
||||||
|
class Player {
|
||||||
|
|
||||||
|
private $pubkey;
|
||||||
|
|
||||||
|
private $name;
|
||||||
|
|
||||||
|
function __construct ($pubkey, $name) {
|
||||||
|
|
||||||
|
$this->pubkey = $pubkey;
|
||||||
|
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPubkey () {
|
||||||
|
|
||||||
|
return $this->pubkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getName () {
|
||||||
|
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$players = [
|
||||||
|
|
||||||
|
new Player('2L8vaYixCf97DMT8SistvQFeBj7vb6RQL7tvwyiv1XVH', 'Fred'),
|
||||||
|
new Player('25zB1gSC7Qhwnx463cuDLDCKLRVieLAgFiPbYq6jVHG9', 'Boris'),
|
||||||
|
new Player('u3rNW7CzqDC5V4L3FGVbSPsrBd78y8pkRACKHtBtCPx', 'Syoul'),
|
||||||
|
new Player('8PTThXiUSwwuPoqQWw3tuAn4MpvzQzpKhs6LMuiozS7Z', 'kimamila')
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
if (!isset($_SESSION['radius'])) {
|
||||||
|
|
||||||
|
$_SESSION['radius'] = DEFAULT_RADIUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
Games
|
||||||
|
=====================
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
$games = [
|
||||||
|
|
||||||
|
'spationaute' => [
|
||||||
|
|
||||||
|
'title' => 'SpaceĞ1',
|
||||||
|
'description' => 'Les extraterrestres viennent terraformer ta planète'
|
||||||
|
],
|
||||||
|
|
||||||
|
'magie' => [
|
||||||
|
|
||||||
|
'title' => 'Ğ1Quest',
|
||||||
|
'description' => 'Ğarry Potier à l\'école des sourciers.'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
define('DEFAULT_GAME', 'spationaute');
|
||||||
|
|
||||||
|
if (!isset($_SESSION['gameId'])) {
|
||||||
|
|
||||||
|
$_SESSION['gameId'] = DEFAULT_GAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
require_once('functions.php');
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>Created by La Bureautique Incorporated, STI (Société Totalement Irresponsable) au capital de 200 000 Ğ1.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
echo '
|
||||||
|
|
||||||
|
<script src="themes/'. $_SESSION['gameId'] .'/layout.js"></script>
|
||||||
|
<script src="themes/'. $_SESSION['gameId'] .'/deco.js"></script>
|
||||||
|
|
||||||
|
';
|
||||||
|
?>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function moisFr ($n) {
|
||||||
|
|
||||||
|
switch ($n) {
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
return "janvier";
|
||||||
|
case 2:
|
||||||
|
return "février";
|
||||||
|
case 3:
|
||||||
|
return "mars";
|
||||||
|
case 4:
|
||||||
|
return "avril";
|
||||||
|
case 5:
|
||||||
|
return "mai";
|
||||||
|
case 6:
|
||||||
|
return "juin";
|
||||||
|
case 7:
|
||||||
|
return "juillet";
|
||||||
|
case 8:
|
||||||
|
return "août";
|
||||||
|
case 9:
|
||||||
|
return "septembre";
|
||||||
|
case 10:
|
||||||
|
return "octobre";
|
||||||
|
case 11:
|
||||||
|
return "novembre";
|
||||||
|
case 12:
|
||||||
|
return "décembre";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Geoloc</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
<button onclick="getLocation()">Me géolocaliser</button>
|
||||||
|
|
||||||
|
<p id="result">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
var result = document.getElementById('result');
|
||||||
|
|
||||||
|
function getLocation() {
|
||||||
|
|
||||||
|
if (navigator.geolocation) {
|
||||||
|
navigator.geolocation.getCurrentPosition(showPosition);
|
||||||
|
} else {
|
||||||
|
result.innerHTML = "Geolocation is not supported by this browser.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showPosition(position) {
|
||||||
|
|
||||||
|
result.innerHTML = "Latitude: " + position.coords.latitude +
|
||||||
|
"<br>Longitude: " + position.coords.longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,24 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>La bureautique</title>
|
||||||
|
<?php
|
||||||
|
echo '
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="themes/'. $_SESSION['gameId'] .'/layout.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="themes/'. $_SESSION['gameId'] .'/deco.css" />
|
||||||
|
|
||||||
|
';
|
||||||
|
?>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
</head>
|
||||||
|
<?php
|
||||||
|
$bodyIds = !isset($bodyIds) ? '' : ' id="'. $bodyIds .'"';
|
||||||
|
?>
|
||||||
|
<body<?php echo $bodyIds; ?>>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<h1>La bureautique</h1>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<main>
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
require_once('config.php');
|
||||||
|
require_once('lib/Gchange.class.php');
|
||||||
|
require_once('lib/Location.class.php');
|
||||||
|
|
||||||
|
$bodyIds = 'home';
|
||||||
|
include_once('header.php');
|
||||||
|
|
||||||
|
|
||||||
|
$gchange = new Gchange();
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<h1>Ze Ğ1 jeux</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
À quel jeu voulez-vous jouer ?
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<dl>';
|
||||||
|
|
||||||
|
foreach ($games as $gameId => $game) {
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<dt>
|
||||||
|
<a href="select_game.php?gameId='. $gameId .'">
|
||||||
|
'. $game['title'] .'
|
||||||
|
</a>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
'. $game['description'] .'
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '
|
||||||
|
</dl>';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
include_once('footer.php');
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once('DAO.class.php');
|
||||||
|
|
||||||
|
class CesiumPlus {
|
||||||
|
|
||||||
|
private $dao;
|
||||||
|
|
||||||
|
public function __construct () {
|
||||||
|
|
||||||
|
$this->dao = DAO::getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNearbyUsers ($lat, $lon, $radius) {
|
||||||
|
|
||||||
|
$n = 15;
|
||||||
|
|
||||||
|
$queryParams = [
|
||||||
|
'size' => $n,
|
||||||
|
|
||||||
|
'query' => [
|
||||||
|
'bool' => [
|
||||||
|
'must' => [
|
||||||
|
[
|
||||||
|
'geo_distance' => [
|
||||||
|
|
||||||
|
"distance" => $radius . 'km',
|
||||||
|
"geoPoint"=> [
|
||||||
|
"lat" => $lat,
|
||||||
|
"lon" => $lon
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
|
||||||
|
"sort" => [
|
||||||
|
[ "time" => ["order" => "desc"] ],
|
||||||
|
"_score"
|
||||||
|
]
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
$json = $this->dao->fetchJson('/user/profile/_search?pretty', 'gchange', $queryParams);
|
||||||
|
$result = json_decode($json);
|
||||||
|
|
||||||
|
return $result->hits->hits;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,588 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
date_default_timezone_set('Europe/Paris');
|
||||||
|
|
||||||
|
class DAO {
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* Constants
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
const PUBKEY_FORMAT = '#^[a-zA-Z1-9]{43,44}$#';
|
||||||
|
|
||||||
|
const DATE_FORMAT = 'Y-m-d';
|
||||||
|
|
||||||
|
private $units = ['quantitative','relative'];
|
||||||
|
|
||||||
|
private $truePossibleValues = ['true','1', 'yes'];
|
||||||
|
|
||||||
|
private $qrCodesFolder = __DIR__ . '/img/qrcodes';
|
||||||
|
|
||||||
|
private $qrCodePath = NULL;
|
||||||
|
|
||||||
|
private $logosFolder = __DIR__ . '/img/logos';
|
||||||
|
|
||||||
|
private $logo = NULL;
|
||||||
|
|
||||||
|
private $logoPath = NULL;
|
||||||
|
|
||||||
|
private $validDisplayTypes = ['img', 'svg', 'html'];
|
||||||
|
|
||||||
|
private $cacheDir = __DIR__ . '/../cache/';
|
||||||
|
|
||||||
|
private $isActivatedCache = true;
|
||||||
|
|
||||||
|
private $cacheLongevity = 10800; // in seconds
|
||||||
|
|
||||||
|
public static $dao;
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* General parameters
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
private $pubkey;
|
||||||
|
|
||||||
|
private $nodes = [
|
||||||
|
|
||||||
|
'gchange' => [
|
||||||
|
|
||||||
|
'data.gchange.fr'
|
||||||
|
],
|
||||||
|
|
||||||
|
'cesiumplus' => [
|
||||||
|
|
||||||
|
'g1.data.le-sou.org',
|
||||||
|
'g1.data.duniter.fr'
|
||||||
|
],
|
||||||
|
|
||||||
|
'duniter' => [
|
||||||
|
|
||||||
|
'duniter.g1.1000i100.fr',
|
||||||
|
'duniter-g1.p2p.legal',
|
||||||
|
'duniter.normandie-libre.fr',
|
||||||
|
'g1.mithril.re',
|
||||||
|
'g1.presles.fr',
|
||||||
|
'duniter.vincentux.fr',
|
||||||
|
'g1.le-sou.org',
|
||||||
|
'g1.donnadieu.fr',
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
private $nodeTimeout = [
|
||||||
|
|
||||||
|
'duniter' => 2,
|
||||||
|
'cesiumplus' => 5,
|
||||||
|
'gchange' => 5,
|
||||||
|
];
|
||||||
|
|
||||||
|
private $nodeTimeoutIncrement = [
|
||||||
|
|
||||||
|
'duniter' => 2,
|
||||||
|
'cesiumplus' => 10,
|
||||||
|
'gchange' => 10
|
||||||
|
];
|
||||||
|
|
||||||
|
private $node = NULL;
|
||||||
|
|
||||||
|
private $unit = 'quantitative';
|
||||||
|
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* Methods
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
public function __construct () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getInstance () {
|
||||||
|
|
||||||
|
if (!isset(DAO::$dao)) {
|
||||||
|
|
||||||
|
DAO::$dao = new DAO();
|
||||||
|
}
|
||||||
|
|
||||||
|
return DAO::$dao;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setUnit ($unit) {
|
||||||
|
|
||||||
|
if (!empty($unit)) {
|
||||||
|
|
||||||
|
if (!in_array($unit, $this->units)) {
|
||||||
|
|
||||||
|
$out = [];
|
||||||
|
$out[] = _('L\'unité renseignée n\'existe pas.');
|
||||||
|
$out[] = _('Vérifiez votre synthaxe.');
|
||||||
|
|
||||||
|
$this->decease($out);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$this->unit = $unit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function decease ($errorMsgs) {
|
||||||
|
|
||||||
|
if (!is_array($errorMsgs)) {
|
||||||
|
|
||||||
|
$errorMsgs = explode("\n", $errorMsgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ($this->displayType == 'img') {
|
||||||
|
|
||||||
|
$source = imagecreatetruecolor(500, 200);
|
||||||
|
|
||||||
|
$bgColor = imagecolorallocate($source,
|
||||||
|
255, 255, 255);
|
||||||
|
|
||||||
|
imagefill($source,
|
||||||
|
0, 0,
|
||||||
|
$bgColor);
|
||||||
|
|
||||||
|
$txtColor = imagecolorallocate($source,
|
||||||
|
0, 0, 0);
|
||||||
|
|
||||||
|
$errorMsgFontSize = 3;
|
||||||
|
$x = 5;
|
||||||
|
$y = 5;
|
||||||
|
|
||||||
|
foreach ($errorMsgs as $msg) {
|
||||||
|
|
||||||
|
imagestring($source, $errorMsgFontSize, $x, $y, utf8_decode($msg), $txtColor);
|
||||||
|
|
||||||
|
$y += $errorMsgFontSize + 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
imagepng($source);
|
||||||
|
imagedestroy($source);
|
||||||
|
|
||||||
|
} else if ($this->displayType == 'svg') {
|
||||||
|
|
||||||
|
echo '<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<svg width="580"
|
||||||
|
height="224"
|
||||||
|
style="fill:black;"
|
||||||
|
version="1.1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
|
||||||
|
<g style="font-family:sans-serif;">';
|
||||||
|
|
||||||
|
$x = 25;
|
||||||
|
$y = 25;
|
||||||
|
|
||||||
|
foreach ($errorMsgs as $msg) {
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<text
|
||||||
|
style="font-size:.8rem;"
|
||||||
|
x="'. $x .'"
|
||||||
|
y="'. $y . '"
|
||||||
|
dominant-baseline="hanging">
|
||||||
|
'. $msg . '
|
||||||
|
</text>';
|
||||||
|
|
||||||
|
$y += 25;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '
|
||||||
|
</g>
|
||||||
|
</svg>';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ob_get_clean(); // to prevent error message to display inside an HTML container (case of error generated by get method calls)
|
||||||
|
|
||||||
|
echo '<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>'. _('Erreur critique') . '</title>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
div {
|
||||||
|
|
||||||
|
overflow: auto;
|
||||||
|
word-wrap: break-word;
|
||||||
|
background-color: hsl(0, 100%, 69%);
|
||||||
|
color: hsl(0, 100%, 19%);
|
||||||
|
margin: 1em;
|
||||||
|
padding: 1em;
|
||||||
|
border-radius: 1em;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: calc(100% - 4em);
|
||||||
|
max-height: calc(100vh - 4em);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div>';
|
||||||
|
|
||||||
|
|
||||||
|
foreach ($errorMsgs as $msg) {
|
||||||
|
|
||||||
|
echo '<p>' . $msg . '</p>';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>';
|
||||||
|
}
|
||||||
|
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function printUnit () {
|
||||||
|
|
||||||
|
if ($this->unit == 'relative') {
|
||||||
|
|
||||||
|
if ($this->displayType == 'img') {
|
||||||
|
|
||||||
|
return _('DUĞ1');
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return _('DU<sub>Ğ1</sub>');
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return _('Ğ1');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function convertIntoChosenUnit ($amountInQuantitative) {
|
||||||
|
|
||||||
|
if ($this->unit == 'quantitative') {
|
||||||
|
|
||||||
|
return $amountInQuantitative;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (!isset($this->startDateUdAmount)) {
|
||||||
|
|
||||||
|
$this->startDateUdAmount = $this->getUdAmount($this->startDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return round($amountInQuantitative / $this->startDateUdAmount, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function addNode ($node) {
|
||||||
|
|
||||||
|
$node = htmlspecialchars($node);
|
||||||
|
|
||||||
|
$this->nodes = array_unique(
|
||||||
|
array_merge(
|
||||||
|
(array)$node,
|
||||||
|
$this->nodes
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function addNodes ($nodes) {
|
||||||
|
|
||||||
|
if (!is_array($nodes)) {
|
||||||
|
|
||||||
|
$nodes = explode(' ', $nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($nodes as $node) {
|
||||||
|
|
||||||
|
$this->addNode($node);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return $nodes array
|
||||||
|
*/
|
||||||
|
public function getNodesList ($nodeType = 'duniter') {
|
||||||
|
|
||||||
|
switch ($nodeType) {
|
||||||
|
|
||||||
|
case 'gchange':
|
||||||
|
$nodesFilename = 'nodes-gchange';
|
||||||
|
break;
|
||||||
|
case 'cesiumplus':
|
||||||
|
$nodesFilename = 'nodes-cesiumplus';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$nodesFilename = 'nodes';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$nodesFilename .= '.txt';
|
||||||
|
$nodesFullpath = $this->cacheDir . $nodesFilename;
|
||||||
|
|
||||||
|
$nodes = $this->nodes[$nodeType];
|
||||||
|
|
||||||
|
if ($this->isActivatedCache) {
|
||||||
|
|
||||||
|
if (!file_exists($nodesFullpath)) {
|
||||||
|
|
||||||
|
shuffle($nodes);
|
||||||
|
|
||||||
|
$this->cacheNodes($nodes, $nodeType);
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$nodesStr = file_get_contents($nodesFullpath);
|
||||||
|
|
||||||
|
$nodes = explode("\n", $nodesStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
shuffle($nodes);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return $nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function cacheNodes ($nodes, $nodeType = 'duniter') {
|
||||||
|
|
||||||
|
switch ($nodeType) {
|
||||||
|
|
||||||
|
case 'gchange':
|
||||||
|
$nodesFilename = 'nodes-gchange';
|
||||||
|
break;
|
||||||
|
case 'cesiumplus':
|
||||||
|
$nodesFilename = 'nodes-cesiumplus';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$nodesFilename = 'nodes';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$nodesFilename .= '.txt';
|
||||||
|
|
||||||
|
if (!file_exists($this->cacheDir)) {
|
||||||
|
|
||||||
|
mkdir($this->cacheDir, 0777, true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
file_put_contents($this->cacheDir . $nodesFilename, implode("\n", $nodes));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function saveNodes ($nodes, $nodeType = 'duniter') {
|
||||||
|
|
||||||
|
$this->nodes[$nodeType] = $nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function fetchJson_aux ($nodes, $uri, $nodeType, $queryParams, $nodesNb, $nodeTimeout) {
|
||||||
|
|
||||||
|
// $header = 'Content-Type: application/x-www-form-urlencoded';
|
||||||
|
// $header = "Content-Type: text/xml\r\n";
|
||||||
|
|
||||||
|
if (!empty($queryParams)) {
|
||||||
|
|
||||||
|
$opts = [
|
||||||
|
'http' => [
|
||||||
|
'method' => 'POST',
|
||||||
|
'content' => json_encode($queryParams),
|
||||||
|
// 'header' => $header,
|
||||||
|
'timeout' => $nodeTimeout
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$opts = [
|
||||||
|
'http' => [
|
||||||
|
'method' => 'GET',
|
||||||
|
'timeout' => $nodeTimeout
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$streamContext = stream_context_create($opts);
|
||||||
|
|
||||||
|
$i = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
|
||||||
|
$json = @file_get_contents("https://" . current($nodes) . $uri,
|
||||||
|
false,
|
||||||
|
$streamContext);
|
||||||
|
|
||||||
|
if (empty($json)) {
|
||||||
|
|
||||||
|
$nodes[] = array_shift($nodes);
|
||||||
|
++$i;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (empty($json) and ($i < $nodesNb));
|
||||||
|
|
||||||
|
if (!empty($json)) {
|
||||||
|
|
||||||
|
// Let's save node order for other queries :
|
||||||
|
$this->saveNodes($nodes, $nodeType);
|
||||||
|
|
||||||
|
if ($this->isActivatedCache) {
|
||||||
|
|
||||||
|
$this->cacheNodes($nodes, $nodeType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $json;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function fetchJson ($uri, $nodeType = 'duniter', $queryParams = NULL) {
|
||||||
|
|
||||||
|
$json = NULL;
|
||||||
|
|
||||||
|
$nodes = $this->getNodesList($nodeType);
|
||||||
|
|
||||||
|
$nodesNb = count($nodes);
|
||||||
|
|
||||||
|
$maxTries = 3;
|
||||||
|
|
||||||
|
$nodeTimeout = $this->nodeTimeout[$nodeType];
|
||||||
|
$nodeTimeoutIncrement = $this->nodeTimeoutIncrement[$nodeType];
|
||||||
|
|
||||||
|
for ($i = 0; ($i < 3) and empty($json); ++$i) {
|
||||||
|
|
||||||
|
$json = $this->fetchJson_aux($nodes, $uri, $nodeType, $queryParams, $nodesNb, $nodeTimeout);
|
||||||
|
|
||||||
|
$nodeTimeout += $nodeTimeoutIncrement;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($json)) {
|
||||||
|
|
||||||
|
$out = [];
|
||||||
|
$out[] = _('Aucun noeud '. $nodeType .' n\'a été trouvé ou la requête n\'a pas abouti.');
|
||||||
|
$out[] = _('Noeud interrogés : ');
|
||||||
|
|
||||||
|
$out = array_merge($out, $nodes);
|
||||||
|
|
||||||
|
$out[] = _('URI: ' . $uri);
|
||||||
|
|
||||||
|
if (isset($queryParams)) {
|
||||||
|
|
||||||
|
$out[] = _('Paramètres de la requête : ');
|
||||||
|
$out[] = print_r($queryParams, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->decease($out);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $json;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function fetchUdAmount ($date) {
|
||||||
|
|
||||||
|
// On récupère les numéros de chaque blocks de DU journalier
|
||||||
|
$json = $this->fetchJson('/blockchain/with/ud');
|
||||||
|
$blocks = json_decode($json)->result->blocks;
|
||||||
|
|
||||||
|
if ($date > $this->now) {
|
||||||
|
|
||||||
|
// On récupère le dernier block
|
||||||
|
$blockNum = end($blocks);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// On récupère le bloc de la date qui nous intéresse
|
||||||
|
$blockNum = $blocks[count($blocks) - $this->today->diff($date)->format("%a") - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Puis on récupère le montant du DU
|
||||||
|
$json = $this->fetchJson('/blockchain/block/' . $blockNum);
|
||||||
|
$block = json_decode($json);
|
||||||
|
|
||||||
|
|
||||||
|
return ($block->dividend / 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUdAmount ($date) {
|
||||||
|
|
||||||
|
$udFilename = $this->getUdFilename($date);
|
||||||
|
$udsCacheDir = $this->cacheDir . 'uds/';
|
||||||
|
$udFullPath = $udsCacheDir . $udFilename;
|
||||||
|
|
||||||
|
if ($this->isActivatedCache) {
|
||||||
|
|
||||||
|
if (file_exists($udFullPath)) {
|
||||||
|
|
||||||
|
$udCachedAmount = file_get_contents($udFullPath);
|
||||||
|
|
||||||
|
if (is_numeric($udCachedAmount) and $udCachedAmount != 0) {
|
||||||
|
|
||||||
|
$udAmount = floatval($udCachedAmount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!isset($udAmount)) {
|
||||||
|
|
||||||
|
$udAmount = $this->fetchUdAmount($date);
|
||||||
|
|
||||||
|
// Cache UD amount
|
||||||
|
|
||||||
|
if (!file_exists($udsCacheDir)) {
|
||||||
|
|
||||||
|
mkdir($udsCacheDir, 0777, true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
file_put_contents($udFullPath, $udAmount);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$udAmount = $this->fetchUdAmount($date);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return $udAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected function getUdFilename ($date) {
|
||||||
|
|
||||||
|
$datePreviousAutumnEquinox = new DateTime($date->format('Y') . '-09-22');
|
||||||
|
$datePreviousSpringEquinox = new DateTime($date->format('Y') . '-03-20');
|
||||||
|
|
||||||
|
if ($date > $datePreviousAutumnEquinox) {
|
||||||
|
|
||||||
|
$udFilename = $date->format('Y') . '-autumn';
|
||||||
|
|
||||||
|
} elseif ($date > $datePreviousSpringEquinox) {
|
||||||
|
|
||||||
|
$udFilename = $date->format('Y') . '-spring';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$udFilename = ($date->sub(new DateInterval('P1Y'))->format('Y')). '-autumn';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $udFilename . '.txt';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class Fred {
|
||||||
|
|
||||||
|
private $gatewayProtocol = 'http';
|
||||||
|
|
||||||
|
private $gatewayDomain = 'libra.copylaradio.com';
|
||||||
|
|
||||||
|
private $gatewayPort = '1234';
|
||||||
|
|
||||||
|
private $gatewayDelay = 3;
|
||||||
|
|
||||||
|
public function __construct () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function donneMoiLaPutainDeClefIPNS ($prenomNom, $nomDuChienSuivieDeLaDateDeNaissanceDeJohnnyHallyday) {
|
||||||
|
|
||||||
|
$salt = $prenomNom;
|
||||||
|
$pepper = $nomDuChienSuivieDeLaDateDeNaissanceDeJohnnyHallyday;
|
||||||
|
|
||||||
|
$query = 'salt='. $salt .'&pepper='. $pepper;
|
||||||
|
|
||||||
|
$page1 = @file_get_contents($this->gatewayProtocol . '://'. $this->gatewayDomain .':' . $this->gatewayPort . '/?' . $query)
|
||||||
|
or die('<p>On a fait du sale.</p>');
|
||||||
|
|
||||||
|
preg_match("`url='([^']+)'`isU", $page1, $matches);
|
||||||
|
|
||||||
|
$url = $matches[1];
|
||||||
|
|
||||||
|
sleep($this->gatewayDelay);
|
||||||
|
|
||||||
|
$page2 = @file_get_contents($url)
|
||||||
|
or die('</p>On a chié dans la colle.</p>');
|
||||||
|
|
||||||
|
preg_match("`url='.*/ipns/([^']+)'`isU", $page2, $matches);
|
||||||
|
|
||||||
|
$ipnsKey = $matches[1];
|
||||||
|
|
||||||
|
return $ipnsKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function donneMoiSesPutainDeMessagesGchange ($prenomNom, $nomDuChienSuivieDeLaDateDeNaissanceDeJohnnyHallyday, $gchangeId) {
|
||||||
|
|
||||||
|
|
||||||
|
$salt = $prenomNom;
|
||||||
|
$pepper = $nomDuChienSuivieDeLaDateDeNaissanceDeJohnnyHallyday;
|
||||||
|
|
||||||
|
$query = 'salt='. $salt .'&pepper='. $pepper . '&messaging=' . $gchangeId;
|
||||||
|
|
||||||
|
$url = $this->gatewayProtocol . '://'. $this->gatewayDomain .':' . $this->gatewayPort . '/?' . $query;
|
||||||
|
|
||||||
|
echo '<pre>'; var_dump(htmlspecialchars($url)); echo '</pre>';
|
||||||
|
|
||||||
|
$page1 = file_get_contents($url)
|
||||||
|
or die('<p>On a fait du sale.</p>');
|
||||||
|
|
||||||
|
echo '<pre>'; var_dump(htmlspecialchars($page1)); echo '</pre>';
|
||||||
|
|
||||||
|
preg_match("`url='([^']+)'`isU", $page1, $matches);
|
||||||
|
|
||||||
|
$url = $matches[0];
|
||||||
|
|
||||||
|
echo '<pre>'; var_dump($url); echo '</pre>';
|
||||||
|
|
||||||
|
$page2 = '';
|
||||||
|
|
||||||
|
while (empty($page2)) {
|
||||||
|
|
||||||
|
sleep($this->gatewayDelay);
|
||||||
|
|
||||||
|
$page2 = @file_get_contents($url);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '<pre>'; var_dump($page2); echo '</pre>';
|
||||||
|
|
||||||
|
die();
|
||||||
|
|
||||||
|
$json = $page2;
|
||||||
|
|
||||||
|
return $page1;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,279 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once('DAO.class.php');
|
||||||
|
|
||||||
|
class Gchange {
|
||||||
|
|
||||||
|
private $dao;
|
||||||
|
|
||||||
|
private $cacheDir = __DIR__ . '/../cache/';
|
||||||
|
|
||||||
|
private $isActivatedCache = true;
|
||||||
|
|
||||||
|
private $cacheLongevity = array(
|
||||||
|
'placesNearby' => 604800, // 3 jours
|
||||||
|
'users' => 43200, // 12 heures
|
||||||
|
'records' => 900 // 15 min
|
||||||
|
);
|
||||||
|
|
||||||
|
public function __construct () {
|
||||||
|
|
||||||
|
$this->dao = DAO::getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRecordsByIssuer ($issuer) {
|
||||||
|
|
||||||
|
|
||||||
|
$recordsCacheDir = 'records/user/';
|
||||||
|
$recordsCacheFile = $issuer . '.json';
|
||||||
|
|
||||||
|
$json = $this->getJsonFromCache($recordsCacheDir, $recordsCacheFile, $this->cacheLongevity['records']);
|
||||||
|
|
||||||
|
if (empty($json)) {
|
||||||
|
|
||||||
|
$n = 20;
|
||||||
|
|
||||||
|
$queryParams = [
|
||||||
|
'size' => $n,
|
||||||
|
'query' => [
|
||||||
|
'bool' =>[
|
||||||
|
'must' => [
|
||||||
|
'term' => [
|
||||||
|
'issuer' => $issuer
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'must_not' => [
|
||||||
|
[ "term" => ["stock" => 0] ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'sort' => [
|
||||||
|
['time' => 'desc']
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$json = $this->dao->fetchJson('/market/record/_search', 'gchange', $queryParams);
|
||||||
|
|
||||||
|
$this->cacheJson($recordsCacheDir, $recordsCacheFile, $json);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = json_decode($json);
|
||||||
|
|
||||||
|
return $result->hits->hits;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getJsonFromCache ($dir, $file, $cacheLongevity) {
|
||||||
|
|
||||||
|
if (!$this->isActivatedCache) {
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$json = null;
|
||||||
|
$jsonFullPath = $this->cacheDir . $dir . $file;
|
||||||
|
|
||||||
|
if (file_exists($jsonFullPath) and ((time() - filemtime($jsonFullPath)) < $cacheLongevity)) {
|
||||||
|
|
||||||
|
$json = file_get_contents($jsonFullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $json;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function cacheJson ($dir, $file, $json) {
|
||||||
|
|
||||||
|
if (!$this->isActivatedCache) {
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
$jsonCacheDir = $this->cacheDir . $dir;
|
||||||
|
$jsonFullPath = $jsonCacheDir . $file;
|
||||||
|
|
||||||
|
if (!file_exists($jsonCacheDir)) {
|
||||||
|
|
||||||
|
mkdir($jsonCacheDir, 0777, true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
file_put_contents($jsonFullPath, $json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUser ($pubkey) {
|
||||||
|
|
||||||
|
$usersCacheDir = 'users/';
|
||||||
|
$usersCacheFile = $pubkey . '.json';
|
||||||
|
|
||||||
|
$json = $this->getJsonFromCache($usersCacheDir, $usersCacheFile, $this->cacheLongevity['users']);
|
||||||
|
|
||||||
|
if (empty($json)) {
|
||||||
|
|
||||||
|
$json = $this->dao->fetchJson(('/user/profile/'. $pubkey), 'gchange');
|
||||||
|
|
||||||
|
$this->cacheJson($usersCacheDir, $usersCacheFile, $json);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = json_decode($json);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPlacesNearUser ($user, $radius) {
|
||||||
|
|
||||||
|
$placesCacheDir = 'places-nearby/user/';
|
||||||
|
$placesCacheFile = $user->_id . '.json';
|
||||||
|
|
||||||
|
$json = $this->getJsonFromCache($placesCacheDir, $placesCacheFile, $this->cacheLongevity['placesNearby']);
|
||||||
|
|
||||||
|
if (empty($json)) {
|
||||||
|
|
||||||
|
$json = $this->getNearbyPlacesJson($user->_source->geoPoint->lat, $user->_source->geoPoint->lon, RADIUS);
|
||||||
|
|
||||||
|
$this->cacheJson($placesCacheDir, $placesCacheFile, $json);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = json_decode($json);
|
||||||
|
|
||||||
|
return $result->hits->hits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNearbyPlaces ($lat, $lon, $maxDistance, $minDistance = NULL) {
|
||||||
|
|
||||||
|
$json = $this->getNearbyPlacesJson($lat, $lon, $maxDistance, $minDistance);
|
||||||
|
|
||||||
|
$result = json_decode($json);
|
||||||
|
|
||||||
|
return $result->hits->hits;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getNearbyPlacesJson ($lat, $lon, $maxDistance, $minDistance = NULL) {
|
||||||
|
|
||||||
|
$n = 20;
|
||||||
|
|
||||||
|
$queryParams = [
|
||||||
|
'size' => $n,
|
||||||
|
'query' => [
|
||||||
|
'bool' => [
|
||||||
|
'must' => [
|
||||||
|
[
|
||||||
|
'geo_distance' => [
|
||||||
|
|
||||||
|
"distance" => $maxDistance . 'km',
|
||||||
|
"geoPoint"=> [
|
||||||
|
"lat" => $lat,
|
||||||
|
"lon" => $lon
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$json = $this->dao->fetchJson('/page/record/_search', 'gchange', $queryParams);
|
||||||
|
|
||||||
|
return $json;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNearbyRecords ($lat, $lon, $maxDistance, $minDistance = NULL) {
|
||||||
|
|
||||||
|
$n = 20;
|
||||||
|
|
||||||
|
$queryParams = [
|
||||||
|
'size' => $n,
|
||||||
|
'query' => [
|
||||||
|
'bool' => [
|
||||||
|
'must' => [
|
||||||
|
[
|
||||||
|
'geo_distance' => [
|
||||||
|
|
||||||
|
"distance" => $maxDistance . 'km',
|
||||||
|
"geoPoint"=> [
|
||||||
|
"lat" => $lat,
|
||||||
|
"lon" => $lon
|
||||||
|
]
|
||||||
|
]
|
||||||
|
], [
|
||||||
|
'range' => [
|
||||||
|
'stock' => [
|
||||||
|
'gte' => 1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$json = $this->dao->fetchJson('/market/record/_search?pretty', 'gchange', $queryParams);
|
||||||
|
$result = json_decode($json);
|
||||||
|
|
||||||
|
return $result->hits->hits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getImmaterialRecords () {
|
||||||
|
|
||||||
|
$n = 20;
|
||||||
|
|
||||||
|
$queryParams = [
|
||||||
|
'size' => $n,
|
||||||
|
'query' => [
|
||||||
|
'nested' => [
|
||||||
|
'path' => 'category',
|
||||||
|
'query' => [
|
||||||
|
'bool' => [
|
||||||
|
'should' => [
|
||||||
|
[ 'term' => [ 'category.parent' => 'cat31' ] ],
|
||||||
|
[ 'term' => [ 'category.id' => 'cat31' ] ],
|
||||||
|
[ 'term' => [ 'category.parent' => 'cat74' ] ],
|
||||||
|
[ 'term' => [ 'category.id' => 'cat74' ] ]
|
||||||
|
],
|
||||||
|
'must_not' => [
|
||||||
|
[ "term" => ["category.id" => "cat65"] ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$json = $this->dao->fetchJson('/market/record/_search?pretty', 'gchange', $queryParams);
|
||||||
|
$result = json_decode($json);
|
||||||
|
|
||||||
|
return $result->hits->hits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getShippable () {
|
||||||
|
|
||||||
|
$n = 20;
|
||||||
|
|
||||||
|
$queryParams = [
|
||||||
|
'size' => $n,
|
||||||
|
'query' => [
|
||||||
|
'match' => [
|
||||||
|
'description' => 'envoi possible'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$json = $this->dao->fetchJson('/market/record/_search?pretty', 'gchange', $queryParams);
|
||||||
|
$result = json_decode($json);
|
||||||
|
|
||||||
|
return $result->hits->hits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHousingOffers () {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getShippableOffers () {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,131 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
class Location {
|
||||||
|
|
||||||
|
const API_URL = 'http://nominatim.openstreetmap.org/search?q=%s&format=json';
|
||||||
|
|
||||||
|
|
||||||
|
private $lat;
|
||||||
|
|
||||||
|
private $lon;
|
||||||
|
|
||||||
|
private $name;
|
||||||
|
|
||||||
|
private $city;
|
||||||
|
|
||||||
|
private $postCode;
|
||||||
|
|
||||||
|
private $successfulQuery;
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetchOpenStreetMap ($searchQuery) {
|
||||||
|
|
||||||
|
$json = NULL;
|
||||||
|
|
||||||
|
$streamContext = stream_context_create(
|
||||||
|
array(
|
||||||
|
"http" => array(
|
||||||
|
"header" => "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$url = sprintf(Location::API_URL, urlencode($searchQuery));
|
||||||
|
$json = @file_get_contents($url, false, $streamContext);
|
||||||
|
|
||||||
|
if (!empty($json)) {
|
||||||
|
|
||||||
|
$json = json_decode($json);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $json;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createFromAddress ($searchTerms) {
|
||||||
|
|
||||||
|
if (is_array($searchTerms)) {
|
||||||
|
|
||||||
|
while (!empty($searchTerms)) {
|
||||||
|
|
||||||
|
$searchQuery = implode(' ', $searchTerms);
|
||||||
|
$results = Location::fetchOpenStreetMap($searchQuery);
|
||||||
|
|
||||||
|
if (empty($json)) {
|
||||||
|
|
||||||
|
$searchTerms = array_slice($searchTerms, 0, -1);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$searchQuery = $searchTerms;
|
||||||
|
$results = Location::fetchOpenStreetMap($searchQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($results[0])) {
|
||||||
|
|
||||||
|
$firstResult = $results[0];
|
||||||
|
|
||||||
|
$loc = new Location();
|
||||||
|
|
||||||
|
$loc->setPosition($firstResult->lat, $firstResult->lon);
|
||||||
|
$loc->successfulQuery = $searchQuery;
|
||||||
|
|
||||||
|
return $loc;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPosition ($lat, $lon) {
|
||||||
|
|
||||||
|
$this->lat = $lat;
|
||||||
|
$this->lon = $lon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPosition () {
|
||||||
|
|
||||||
|
return [$this->lat, $this->lon];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSuccessfulQuery () {
|
||||||
|
|
||||||
|
return $this->successfulQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getLat () {
|
||||||
|
|
||||||
|
return $this->lat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getLon () {
|
||||||
|
|
||||||
|
return $this->lon;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function geoDist (Location $p1, Location $p2) {
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/365826/calculate-distance-between-2-gps-coordinates
|
||||||
|
|
||||||
|
$pos1 = $p1->getPosition();
|
||||||
|
$pos2 = $p2->getPosition();
|
||||||
|
|
||||||
|
$a = sin(deg2rad($pos2[0]-$pos1[0])/2)**2 + sin(deg2rad($pos2[1]-$pos1[1])/2)**2 * cos(deg2rad($pos1[0])) * cos(deg2rad($pos2[0]));
|
||||||
|
|
||||||
|
return 12742 * atan2(sqrt($a), sqrt(1-$a));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?php
|
||||||
|
require_once('config.php');
|
||||||
|
require_once('lib/Gchange.class.php');
|
||||||
|
|
||||||
|
|
||||||
|
if (isset($_POST['player'])) {
|
||||||
|
|
||||||
|
$_SESSION['player_pubkey'] = $_POST['player'];
|
||||||
|
|
||||||
|
$gchange = new Gchange();
|
||||||
|
$user = $gchange->getUser($_SESSION['player_pubkey']);
|
||||||
|
|
||||||
|
$_SESSION['player_lat'] = $user->_source->geoPoint->lat;
|
||||||
|
$_SESSION['player_lon'] = $user->_source->geoPoint->lon;
|
||||||
|
|
||||||
|
header('Location:map.php');
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$bodyIds = 'login-page';
|
||||||
|
|
||||||
|
include_once('header.php');
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<form method="post" action="">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<label>Joueur :
|
||||||
|
<select name="player">';
|
||||||
|
|
||||||
|
foreach ($players as $p) {
|
||||||
|
|
||||||
|
echo '<option value="'. $p->getPubkey() .'">'. $p->getName() .'</option>';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '
|
||||||
|
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<label>
|
||||||
|
Sel :
|
||||||
|
<input type="text" name="salt" />
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<label>
|
||||||
|
Poivre:
|
||||||
|
<input type="text" name="pepper" />
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<input type="submit" />
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
';
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,281 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once('config.php');
|
||||||
|
require_once('lib/Gchange.class.php');
|
||||||
|
require_once('lib/Location.class.php');
|
||||||
|
|
||||||
|
if (!isset($_SESSION['player_pubkey'])) {
|
||||||
|
|
||||||
|
header('Location: index.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
$bodyIds = 'sonar';
|
||||||
|
include_once('header.php');
|
||||||
|
|
||||||
|
|
||||||
|
$gchange = new Gchange();
|
||||||
|
|
||||||
|
|
||||||
|
$player = $gchange->getUser($_SESSION['player_pubkey']);
|
||||||
|
|
||||||
|
$origLat = $player->_source->geoPoint->lat;
|
||||||
|
$origLon = $player->_source->geoPoint->lon;
|
||||||
|
|
||||||
|
$origLoc = new Location();
|
||||||
|
$origLoc->setPosition($origLat, $origLon);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<section id="mapview">
|
||||||
|
|
||||||
|
<aside id="geoPoint">
|
||||||
|
<a href=".">'. $origLat . ' , ' . $origLon .'</a>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="map"
|
||||||
|
data-orig-lat="'. $origLat .'"
|
||||||
|
data-orig-lon="'. $origLon .'"
|
||||||
|
data-radius="'. $_SESSION['radius'] .'"
|
||||||
|
>
|
||||||
|
<div id="map-deco"></div>
|
||||||
|
|
||||||
|
<section class="player" style="left: calc(50% - '. DEMI_TAILLE_SPRITE . 'px); top: calc(50% - '. DEMI_TAILLE_SPRITE . 'px);">';
|
||||||
|
|
||||||
|
if (isset($player->_source->avatar->_content) and !empty($player->_source->avatar->_content)) {
|
||||||
|
|
||||||
|
$src = 'data:'. $player->_source->avatar->_content_type .';base64,' . $player->_source->avatar->_content;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$src = 'assets/img/avatars/32/et-in-flying-saucer.png.png';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<img src="'. $src . '"
|
||||||
|
alt="'. $player->_source->title .'"
|
||||||
|
width="'. TAILLE_SPRITE .'"
|
||||||
|
height="'. TAILLE_SPRITE .'" />
|
||||||
|
</section>
|
||||||
|
';
|
||||||
|
|
||||||
|
|
||||||
|
$places = $gchange->getPlacesNearUser($player, $_SESSION['radius']);
|
||||||
|
|
||||||
|
$selectedPlace = NULL;
|
||||||
|
|
||||||
|
foreach ($places as $place) {
|
||||||
|
|
||||||
|
if (isset($_GET['place']) and ($place->_id == $_GET['place'])) {
|
||||||
|
|
||||||
|
$selectedPlace = $place;
|
||||||
|
}
|
||||||
|
|
||||||
|
$placeLat = $place->_source->geoPoint->lat;
|
||||||
|
$placeLon = $place->_source->geoPoint->lon;
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<section class="place"
|
||||||
|
id="place-'. $place->_id .'"
|
||||||
|
data-place-lat="'. $placeLat .'"
|
||||||
|
data-place-lon="'. $placeLon .'"
|
||||||
|
>';
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<a href="?place='. $place->_id .'">';
|
||||||
|
|
||||||
|
if (isset($place->_source->avatar->_content) and !empty($place->_source->avatar->_content)) {
|
||||||
|
|
||||||
|
$src = 'data:'. $place->_source->avatar->_content_type .';base64,' . $place->_source->avatar->_content;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$src = 'assets/img/yourte.png';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '
|
||||||
|
|
||||||
|
<img src="'. $src .'"
|
||||||
|
alt="'. $place->_source->title . '"
|
||||||
|
title="'. $place->_source->title .'"
|
||||||
|
width="'. TAILLE_SPRITE .'"
|
||||||
|
height="'. TAILLE_SPRITE .'" />';
|
||||||
|
|
||||||
|
echo '
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<article>';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
echo '
|
||||||
|
</article>
|
||||||
|
|
||||||
|
</section>';
|
||||||
|
}
|
||||||
|
echo '
|
||||||
|
</div>
|
||||||
|
</section>';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (isset($selectedPlace)) {
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<aside id="place-details">';
|
||||||
|
|
||||||
|
$place = $selectedPlace;
|
||||||
|
|
||||||
|
$placeLat = $place->_source->geoPoint->lat;
|
||||||
|
$placeLon = $place->_source->geoPoint->lon;
|
||||||
|
|
||||||
|
$placeLoc = new Location();
|
||||||
|
$placeLoc->setPosition($placeLat, $placeLon);
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<h3 class="place-name">
|
||||||
|
'. $place->_source->title . '
|
||||||
|
</h3>';
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<address>
|
||||||
|
<p class="position">
|
||||||
|
'. $placeLat . ',' . $placeLon .'
|
||||||
|
</p>
|
||||||
|
<p class="distance">
|
||||||
|
à '. ceil(Location::geoDist($origLoc, $placeLoc)) .'km
|
||||||
|
</p>
|
||||||
|
</address>
|
||||||
|
|
||||||
|
<p class="get-directions">
|
||||||
|
Y aller :
|
||||||
|
<a class="car" href="https://www.google.com/maps/dir/'. $origLat .','. $origLon .'/'.$placeLat .','. $placeLon .'/data=!3m1!4b1!4m2!4m1!3e0">
|
||||||
|
<span>
|
||||||
|
en voiture
|
||||||
|
</span>
|
||||||
|
</a>,
|
||||||
|
|
||||||
|
<a class="bike" href="https://www.google.com/maps/dir/'. $origLat .','. $origLon .'/'.$placeLat .','. $placeLon .'/data=!3m1!4b1!4m2!4m1!3e1">
|
||||||
|
<span>
|
||||||
|
en vélo
|
||||||
|
</span>
|
||||||
|
</a>,
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<a class="foot" href="https://www.google.com/maps/dir/'. $origLat .','. $origLon .'/'.$placeLat .','. $placeLon .'/data=!3m1!4b1!4m2!4m1!3e2">
|
||||||
|
<span>
|
||||||
|
à pied
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
';
|
||||||
|
|
||||||
|
|
||||||
|
$records = $gchange->getRecordsByIssuer($place->_source->issuer);
|
||||||
|
|
||||||
|
$offers = [];
|
||||||
|
$needs = [];
|
||||||
|
$crowdfundings = [];
|
||||||
|
|
||||||
|
foreach ($records as $record) {
|
||||||
|
|
||||||
|
switch ($record->_source->type) {
|
||||||
|
|
||||||
|
case 'offer':
|
||||||
|
$offers[] = $record;
|
||||||
|
break;
|
||||||
|
case 'need':
|
||||||
|
$needs[] = $record;
|
||||||
|
break;
|
||||||
|
case 'crowdfunding':
|
||||||
|
$crowdfundings[] = $record;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!empty($needs)) {
|
||||||
|
|
||||||
|
echo '<h4>Demandes</h4>';
|
||||||
|
echo '<ul>';
|
||||||
|
foreach ($needs as $item) {
|
||||||
|
|
||||||
|
$description = isset($item->_source->description) ? ' title="'. substr($item->_source->description, 0, 30) . '"' : '';
|
||||||
|
|
||||||
|
echo '
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="https://www.gchange.fr/#/app/market/view/'. $item->_id . '/"'. $description .'>
|
||||||
|
' . $item->_source->title . '
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
';
|
||||||
|
}
|
||||||
|
echo '</ul>';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!empty($offers)) {
|
||||||
|
|
||||||
|
echo '<h4>Offres</h4>';
|
||||||
|
echo '<ul>';
|
||||||
|
foreach ($offers as $item) {
|
||||||
|
|
||||||
|
$description = isset($item->_source->description) ? ' title="'. substr($item->_source->description, 0, 30) . '"' : '';
|
||||||
|
|
||||||
|
echo '
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="https://www.gchange.fr/#/app/market/view/'. $item->_id . '/"'. $description .'>
|
||||||
|
' . $item->_source->title . '
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
';
|
||||||
|
}
|
||||||
|
echo '</ul>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($crowdfundings)) {
|
||||||
|
|
||||||
|
echo '<h4>Financements participatifs</h4>';
|
||||||
|
echo '<ul>';
|
||||||
|
foreach ($crowdfundings as $item) {
|
||||||
|
|
||||||
|
$description = isset($item->description) ? ' title="'. substr($item->_source->description, 0, 30) . '"' : '';
|
||||||
|
|
||||||
|
echo '
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="https://www.gchange.fr/#/app/market/view/'. $item->_id . '/"'. $description .'>
|
||||||
|
' . $item->_source->title . '
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
';
|
||||||
|
}
|
||||||
|
echo '</ul>';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (isset($place->_source->description) and !empty($place->_source->description)) {
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<h4>À propos du lieu</h4>
|
||||||
|
|
||||||
|
<p class="place-desc">
|
||||||
|
'. $place->_source->description . '
|
||||||
|
|
||||||
|
</p>';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '
|
||||||
|
</aside>';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
include_once('footer.php');
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once('config.php');
|
||||||
|
|
||||||
|
if ( !isset($_GET['gameId']) or !in_array($_GET['gameId'], array_keys($games)) ) {
|
||||||
|
|
||||||
|
header('Location: index.php');
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$_SESSION['gameId'] = $_GET['gameId'];
|
||||||
|
|
||||||
|
header('Location: login.php');
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
body {
|
||||||
|
|
||||||
|
font-family: cursive;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#map {
|
||||||
|
|
||||||
|
background-color: hsl(240, 7.5%, 60.6%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#map-deco {
|
||||||
|
|
||||||
|
background: radial-gradient(circle at 33% 33%, hsl(240, 28.6%, 86.3%) 0%, transparent 50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.place {
|
||||||
|
|
||||||
|
opacity: 0.5;
|
||||||
|
|
||||||
|
animation: appear 3s ease-in-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes appear {
|
||||||
|
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details {
|
||||||
|
|
||||||
|
|
||||||
|
animation: appear 3s ease-in-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.distance:after {
|
||||||
|
|
||||||
|
content: " à vol d\'OVNI";
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details > address .distance:after {
|
||||||
|
|
||||||
|
content: " en balais volant";
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details .get-directions a span {
|
||||||
|
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details .get-directions .car:after {
|
||||||
|
|
||||||
|
content: "en poudre de cheminette";
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details .get-directions .bike:after {
|
||||||
|
|
||||||
|
content: "en Nimbus 2000";
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details .get-directions .foot:after {
|
||||||
|
|
||||||
|
content: "en botte de sept lieues";
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
../spationaute/layout.css
|
|
@ -0,0 +1 @@
|
||||||
|
../spationaute/layout.js
|
|
@ -0,0 +1,192 @@
|
||||||
|
:root {
|
||||||
|
|
||||||
|
--panel-bg-color: hsl(131.6, 47.7%, 12.5%);
|
||||||
|
--panel-place-name-bg-color: hsl(131.6, 52.7%, 7.5%);
|
||||||
|
--panel-place-name-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
body {
|
||||||
|
|
||||||
|
background: hsl(0, 50%, 2%);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#login-page {
|
||||||
|
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#mapview #geoPoint a,
|
||||||
|
#mapview #geoPoint a:visited {
|
||||||
|
|
||||||
|
color: white;
|
||||||
|
opacity: 0.4;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
body#sonar {
|
||||||
|
|
||||||
|
background:
|
||||||
|
/*
|
||||||
|
repeating-linear-gradient(to right, hsl(132.2, 59.8%, 52.2%) 0vh, hsl(132.2, 59.8%, 52.2%) 0.4vh, transparent 0.4vh, transparent 10vh),
|
||||||
|
repeating-linear-gradient(transparent, transparent 9.8vh, hsl(132.2, 59.8%, 52.2%) 10.2vh, hsl(132.2, 59.8%, 52.2%) 10.2vh, transparent 10.2vh),
|
||||||
|
*/
|
||||||
|
|
||||||
|
linear-gradient(to right, transparent 0vw, transparent 32.9vw, hsl(132.2, 59.8%, 74.2%) 32.9vw, hsl(132.2, 59.8%, 74.2%) 33.1vw, transparent 33.1vw),
|
||||||
|
linear-gradient(to right, hsl(132.2, 59.8%, 12.1%) 0vw, hsl(132.2, 59.8%, 12.1%) 0.1vw, transparent 0.1vw),
|
||||||
|
repeating-linear-gradient(to right, hsl(132.2, 59.8%, 52.2%) 0vw, hsl(132.2, 59.8%, 52.2%) 0.1vw, transparent 0.1vw, transparent 5.4vw, hsl(132.2, 59.8%, 52.2%) 5.4vw, hsl(132.2, 59.8%, 52.2%) 5.5vw),
|
||||||
|
|
||||||
|
/*linear-gradient(to bottom, transparent 0vw, transparent 32.9vw, hsl(132.2, 59.8%, 74.2%) 32.9vw, hsl(132.2, 59.8%, 74.2%) 33.1vw, transparent 33.1vw), */
|
||||||
|
linear-gradient(to bottom, hsl(132.2, 59.8%, 12.1%) 0vw, hsl(132.2, 59.8%, 12.1%) 0.1vw, transparent 0.1vw),
|
||||||
|
repeating-linear-gradient(to bottom, hsl(132.2, 59.8%, 52.2%) 0vw, hsl(132.2, 59.8%, 52.2%) 0.1vw, transparent 0.1vw, transparent 5.4vw, hsl(132.2, 59.8%, 52.2%) 5.4vw, hsl(132.2, 59.8%, 52.2%) 5.5vw),
|
||||||
|
|
||||||
|
hsl(132.2, 59.8%, 12.1%);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#map {
|
||||||
|
|
||||||
|
background:
|
||||||
|
linear-gradient( 0deg, transparent 49.85%, hsl(132.2, 59.8%, 74.2%) 49.85%, hsl(132.2, 59.8%, 74.2%) 50.15%, transparent 50.15%),
|
||||||
|
linear-gradient( 90deg, transparent 49.85%, hsl(132.2, 59.8%, 74.2%) 49.85%, hsl(132.2, 59.8%, 74.2%) 50.15%, transparent 50.15%),
|
||||||
|
linear-gradient( 45deg, transparent 49.90%, hsl(132.2, 59.8%, 74.2%) 49.90%, hsl(132.2, 59.8%, 74.2%) 50.10%, transparent 50.10%),
|
||||||
|
linear-gradient(135deg, transparent 49.90%, hsl(132.2, 59.8%, 74.2%) 49.90%, hsl(132.2, 59.8%, 74.2%) 50.10%, transparent 50.10%),
|
||||||
|
repeating-radial-gradient(transparent 0, transparent 10%, hsl(132.2, 59.8%, 74.2%) 10%, hsl(132.2, 59.8%, 74.2%) 10.4%),
|
||||||
|
/*radial-gradient(circle at center, hsl(132.2, 59.8%, 37.1%) 0%, hsl(132.2, 59.8%, 74.2%) 50%, hsl(132.2, 59.8%, 37.1%) 100%), */
|
||||||
|
hsla(132.2, 59.8%, 37.1%, 0.8);
|
||||||
|
|
||||||
|
border-style: solid;
|
||||||
|
border-color: hsl(132.2, 59.8%, 74.2%);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#map-deco {
|
||||||
|
|
||||||
|
background:
|
||||||
|
conic-gradient(hsla(132.2, 59.8%, 74.2%, 1) 0deg, hsla(132.2, 59.8%, 74.2%, 0) 45deg, hsla(132.2, 59.8%, 74.2%, 0) 0deg);
|
||||||
|
animation: sonar 5s linear infinite reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes sonar {
|
||||||
|
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: rotate(355deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#map .place {
|
||||||
|
|
||||||
|
opacity: 0;
|
||||||
|
animation: appear infinite 5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes appear {
|
||||||
|
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#map .place,
|
||||||
|
#map .player {
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#place-details {
|
||||||
|
|
||||||
|
background: var(--panel-bg-color);
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
cursor: auto;
|
||||||
|
|
||||||
|
animation: slideIn 1s forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideIn {
|
||||||
|
|
||||||
|
0% {
|
||||||
|
transform: translateX(33vw);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details > .place-name {
|
||||||
|
|
||||||
|
|
||||||
|
background-color: var(--panel-place-name-bg-color);
|
||||||
|
color: var(--panel-place-name-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#place-details > address {
|
||||||
|
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details > address .distance:after {
|
||||||
|
|
||||||
|
content: " à vol d\'OVNI";
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details .get-directions a span {
|
||||||
|
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#place-details .get-directions .car:after {
|
||||||
|
|
||||||
|
content: "en hyperespace";
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details .get-directions .bike:after {
|
||||||
|
|
||||||
|
content: "en vitesse supraluminique";
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details .get-directions .foot:after {
|
||||||
|
|
||||||
|
content: "en vitesse subluminique";
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details > h4 {
|
||||||
|
|
||||||
|
background: var(--panel-place-name-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details a,
|
||||||
|
#place-details a:hover,
|
||||||
|
#place-details a:focus,
|
||||||
|
#place-details a:active,
|
||||||
|
#place-details a:visited {
|
||||||
|
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
const SONAR_DURATION = 5;
|
||||||
|
|
||||||
|
|
||||||
|
function computeLatDistanceInKm (dest, orig) {
|
||||||
|
|
||||||
|
// Approximation française
|
||||||
|
return ((dest - orig) * 111);
|
||||||
|
}
|
||||||
|
|
||||||
|
function computeLonDistanceInKm (dest, orig) {
|
||||||
|
|
||||||
|
// Approximation française
|
||||||
|
return ((dest - orig) * 79);
|
||||||
|
}
|
||||||
|
|
||||||
|
function computeDelay (latDistanceKm, lonDistanceKm, sonarDuration) {
|
||||||
|
|
||||||
|
placeDirection = Math.atan(latDistanceKm / lonDistanceKm);
|
||||||
|
placeWay = lonDistanceKm < 0 ? -1 : 1;
|
||||||
|
placeAngle = placeDirection * placeWay;
|
||||||
|
|
||||||
|
unsignedAngle = placeAngle + (2 * Math.PI);
|
||||||
|
|
||||||
|
animOrigAngle = 3 * Math.PI / 2;
|
||||||
|
animAngle_verbose = animOrigAngle + unsignedAngle;
|
||||||
|
animAngle_bounded = fmod(animAngle_verbose, (2 * Math.PI));
|
||||||
|
|
||||||
|
circleRatio = animAngle_bounded / (2 * Math.PI);
|
||||||
|
delay = circleRatio * sonarDuration;
|
||||||
|
|
||||||
|
return delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
var places = document.getElementsByClassName('place');
|
||||||
|
var map = document.getElementById('map');
|
||||||
|
var origLat = map.getAttribute('data-orig-lat');
|
||||||
|
var origLon = map.getAttribute('data-orig-lon');
|
||||||
|
|
||||||
|
for (place of places) {
|
||||||
|
|
||||||
|
if ( !( (placeLat == origLat) && (placeLon == origLon) ) ) {
|
||||||
|
|
||||||
|
var placeLat = place.getAttribute("data-place-lat");
|
||||||
|
var placeLon = place.getAttribute("data-place-lon");
|
||||||
|
|
||||||
|
var latDistanceKm = computeLatDistanceInKm(placeLat, origLat);
|
||||||
|
var lonDistanceKm = computeLonDistanceInKm(placeLon, origLon);
|
||||||
|
|
||||||
|
var delay = computeDelay(latDistanceKm, lonDistanceKm, SONAR_DURATION);
|
||||||
|
|
||||||
|
place.style.animationDelay = delay + 's';
|
||||||
|
|
||||||
|
console.log('delay JS : ' + delay);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
:root {
|
||||||
|
|
||||||
|
--taille-sprite: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#aside {
|
||||||
|
width: 33vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mapview {
|
||||||
|
|
||||||
|
width: 66vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#mapview #geoPoint {
|
||||||
|
|
||||||
|
padding: 1rem;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
main {
|
||||||
|
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#map {
|
||||||
|
|
||||||
|
margin: auto;
|
||||||
|
|
||||||
|
margin-top: 2vh;
|
||||||
|
height: 94vh;
|
||||||
|
width: 94vh;
|
||||||
|
|
||||||
|
border-width: 0.125rem;
|
||||||
|
border-radius: 33vw;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#map-deco {
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
left: 0%;
|
||||||
|
top: 0%;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 33vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#map .place,
|
||||||
|
#map .player {
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#map .place header {
|
||||||
|
|
||||||
|
z-index: 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#map .place a:active + article,
|
||||||
|
#map .place a:focus + article {
|
||||||
|
|
||||||
|
z-index: 100;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
width: 33vw;
|
||||||
|
overflow: hidden;
|
||||||
|
/*box-shadow: 0.125rem 0.125rem 1em black;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#place-details {
|
||||||
|
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 33vw;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
padding: 0rem;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details > * {
|
||||||
|
|
||||||
|
margin-left: 1rem;
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details > .place-name {
|
||||||
|
|
||||||
|
margin: 0;
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details > address {
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#place-details > h4 {
|
||||||
|
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
background: var(--panel-place-name-bg-color);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
function fmod (x, y) {
|
||||||
|
|
||||||
|
// discuss at: https://locutus.io/php/fmod/
|
||||||
|
// original by: Onno Marsman (https://twitter.com/onnomarsman)
|
||||||
|
// input by: Brett Zamir (https://brett-zamir.me)
|
||||||
|
// bugfixed by: Kevin van Zonneveld (https://kvz.io)
|
||||||
|
// example 1: fmod(5.7, 1.3)
|
||||||
|
// returns 1: 0.5
|
||||||
|
let tmp
|
||||||
|
let tmp2
|
||||||
|
let p = 0
|
||||||
|
let pY = 0
|
||||||
|
let l = 0.0
|
||||||
|
let l2 = 0.0
|
||||||
|
|
||||||
|
tmp = x.toExponential().match(/^.\.?(.*)e(.+)$/)
|
||||||
|
p = parseInt(tmp[2], 10) - (tmp[1] + '').length
|
||||||
|
|
||||||
|
tmp = y.toExponential().match(/^.\.?(.*)e(.+)$/)
|
||||||
|
pY = parseInt(tmp[2], 10) - (tmp[1] + '').length
|
||||||
|
|
||||||
|
if (pY > p) {
|
||||||
|
p = pY
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp2 = (x % y)
|
||||||
|
|
||||||
|
if (p < -100 || p > 20) {
|
||||||
|
|
||||||
|
// toFixed will give an out of bound error so we fix it like this:
|
||||||
|
l = Math.round(Math.log(tmp2) / Math.log(10))
|
||||||
|
l2 = Math.pow(10, l)
|
||||||
|
|
||||||
|
return (tmp2 / l2).toFixed(l - p) * l2
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return parseFloat(tmp2.toFixed(-p))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const TAILLE_SPRITE = 32;
|
||||||
|
|
||||||
|
var places = document.getElementsByClassName('place');
|
||||||
|
var map = document.getElementById('map');
|
||||||
|
var origLat = map.getAttribute('data-orig-lat');
|
||||||
|
var origLon = map.getAttribute('data-orig-lon');
|
||||||
|
var radius = map.getAttribute('data-radius');
|
||||||
|
|
||||||
|
function computeLatDistanceInKm (dest, orig) {
|
||||||
|
|
||||||
|
// Approximation française
|
||||||
|
return ((dest - orig) * 111);
|
||||||
|
}
|
||||||
|
|
||||||
|
function computeLonDistanceInKm (dest, orig) {
|
||||||
|
|
||||||
|
// Approximation française
|
||||||
|
return ((dest - orig) * 79);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position places on map
|
||||||
|
|
||||||
|
for (place of places) {
|
||||||
|
|
||||||
|
var placeLat = place.getAttribute("data-place-lat");
|
||||||
|
var placeLon = place.getAttribute("data-place-lon");
|
||||||
|
|
||||||
|
var latDistanceKm = computeLatDistanceInKm(placeLat, origLat);
|
||||||
|
var lonDistanceKm = computeLonDistanceInKm(placeLon, origLon);
|
||||||
|
|
||||||
|
var latDistancePcts = latDistanceKm / (2 * radius) * 100;
|
||||||
|
var lonDistancePcts = lonDistanceKm / (2 * radius) * 100;
|
||||||
|
|
||||||
|
var leftPcts = 50 + lonDistancePcts;
|
||||||
|
var topPcts = 50 - latDistancePcts;
|
||||||
|
|
||||||
|
var cssLeft = 'calc(' + leftPcts + '% - ' + (TAILLE_SPRITE / 2) + 'px)';
|
||||||
|
var cssTop = 'calc(' + topPcts + '% - ' + (TAILLE_SPRITE / 2) + 'px)';
|
||||||
|
|
||||||
|
place.style.left = cssLeft;
|
||||||
|
place.style.top = cssTop;
|
||||||
|
}
|