commit 833b9147c154fe65f1826469e23cf6eb888182f7 Author: Boris Date: Fri Oct 21 21:26:41 2022 +0200 La Bureautique vaincra. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57a9ee8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +cache/ +tests/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..e45fb3e --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Ze Ğ1 jeux + +> Life is short. +> Play more. + diff --git a/assets/img/Armurerie.png b/assets/img/Armurerie.png new file mode 100644 index 0000000..84b1a0a Binary files /dev/null and b/assets/img/Armurerie.png differ diff --git a/assets/img/Atelier.png b/assets/img/Atelier.png new file mode 100644 index 0000000..781b34e Binary files /dev/null and b/assets/img/Atelier.png differ diff --git a/assets/img/Bunker.png b/assets/img/Bunker.png new file mode 100644 index 0000000..4e7f88b Binary files /dev/null and b/assets/img/Bunker.png differ diff --git a/assets/img/Dispensaire.png b/assets/img/Dispensaire.png new file mode 100644 index 0000000..dea0162 Binary files /dev/null and b/assets/img/Dispensaire.png differ diff --git a/assets/img/Entrepot.png b/assets/img/Entrepot.png new file mode 100644 index 0000000..4420cfb Binary files /dev/null and b/assets/img/Entrepot.png differ diff --git a/assets/img/Ferme.png b/assets/img/Ferme.png new file mode 100644 index 0000000..fb1572c Binary files /dev/null and b/assets/img/Ferme.png differ diff --git a/assets/img/Garage.png b/assets/img/Garage.png new file mode 100644 index 0000000..929c4f6 Binary files /dev/null and b/assets/img/Garage.png differ diff --git a/assets/img/Maison.png b/assets/img/Maison.png new file mode 100644 index 0000000..403e0a3 Binary files /dev/null and b/assets/img/Maison.png differ diff --git a/assets/img/Mirador.png b/assets/img/Mirador.png new file mode 100644 index 0000000..d074668 Binary files /dev/null and b/assets/img/Mirador.png differ diff --git a/assets/img/Poste_communautaire.png b/assets/img/Poste_communautaire.png new file mode 100644 index 0000000..1b012e7 Binary files /dev/null and b/assets/img/Poste_communautaire.png differ diff --git a/assets/img/Puits.png b/assets/img/Puits.png new file mode 100644 index 0000000..d5bcd5f Binary files /dev/null and b/assets/img/Puits.png differ diff --git a/assets/img/Rangée_de_pieux.png b/assets/img/Rangée_de_pieux.png new file mode 100644 index 0000000..feb0ab2 Binary files /dev/null and b/assets/img/Rangée_de_pieux.png differ diff --git a/assets/img/avatars/128/donatello.png b/assets/img/avatars/128/donatello.png new file mode 100644 index 0000000..54d207f Binary files /dev/null and b/assets/img/avatars/128/donatello.png differ diff --git a/assets/img/avatars/256/donatello.png b/assets/img/avatars/256/donatello.png new file mode 100644 index 0000000..ae12866 Binary files /dev/null and b/assets/img/avatars/256/donatello.png differ diff --git a/assets/img/avatars/32/donatello.png b/assets/img/avatars/32/donatello.png new file mode 100644 index 0000000..0ecf206 Binary files /dev/null and b/assets/img/avatars/32/donatello.png differ diff --git a/assets/img/avatars/32/et-in-flying-saucer.png b/assets/img/avatars/32/et-in-flying-saucer.png new file mode 100644 index 0000000..c29cbf6 Binary files /dev/null and b/assets/img/avatars/32/et-in-flying-saucer.png differ diff --git a/assets/img/avatars/32/guitar-player.png b/assets/img/avatars/32/guitar-player.png new file mode 100644 index 0000000..280d063 Binary files /dev/null and b/assets/img/avatars/32/guitar-player.png differ diff --git a/assets/img/avatars/32/leonardo.png b/assets/img/avatars/32/leonardo.png new file mode 100644 index 0000000..06ecb4a Binary files /dev/null and b/assets/img/avatars/32/leonardo.png differ diff --git a/assets/img/avatars/32/michaelangelo.png b/assets/img/avatars/32/michaelangelo.png new file mode 100644 index 0000000..fa51303 Binary files /dev/null and b/assets/img/avatars/32/michaelangelo.png differ diff --git a/assets/img/avatars/32/ninja.png b/assets/img/avatars/32/ninja.png new file mode 100644 index 0000000..2f1a82d Binary files /dev/null and b/assets/img/avatars/32/ninja.png differ diff --git a/assets/img/avatars/32/ninja_pink.png b/assets/img/avatars/32/ninja_pink.png new file mode 100644 index 0000000..3dff71f Binary files /dev/null and b/assets/img/avatars/32/ninja_pink.png differ diff --git a/assets/img/avatars/32/superhero.png b/assets/img/avatars/32/superhero.png new file mode 100644 index 0000000..4c628b0 Binary files /dev/null and b/assets/img/avatars/32/superhero.png differ diff --git a/assets/img/avatars/32/valkyrie.png b/assets/img/avatars/32/valkyrie.png new file mode 100644 index 0000000..65e0adf Binary files /dev/null and b/assets/img/avatars/32/valkyrie.png differ diff --git a/assets/img/avatars/32/wizard.png b/assets/img/avatars/32/wizard.png new file mode 100644 index 0000000..036c16b Binary files /dev/null and b/assets/img/avatars/32/wizard.png differ diff --git a/assets/img/avatars/512/donatello.png b/assets/img/avatars/512/donatello.png new file mode 100644 index 0000000..de0f5c7 Binary files /dev/null and b/assets/img/avatars/512/donatello.png differ diff --git a/assets/img/f1.png b/assets/img/f1.png new file mode 100644 index 0000000..9bba704 Binary files /dev/null and b/assets/img/f1.png differ diff --git a/assets/img/f2.png b/assets/img/f2.png new file mode 100644 index 0000000..2c9bf0c Binary files /dev/null and b/assets/img/f2.png differ diff --git a/assets/img/f3.png b/assets/img/f3.png new file mode 100644 index 0000000..86e8e83 Binary files /dev/null and b/assets/img/f3.png differ diff --git a/assets/img/f4.png b/assets/img/f4.png new file mode 100644 index 0000000..0b106c6 Binary files /dev/null and b/assets/img/f4.png differ diff --git a/assets/img/marq2.png b/assets/img/marq2.png new file mode 100644 index 0000000..eabb9b8 Binary files /dev/null and b/assets/img/marq2.png differ diff --git a/assets/img/marq7.png b/assets/img/marq7.png new file mode 100644 index 0000000..daea886 Binary files /dev/null and b/assets/img/marq7.png differ diff --git a/assets/img/marq8.png b/assets/img/marq8.png new file mode 100644 index 0000000..9e6c51f Binary files /dev/null and b/assets/img/marq8.png differ diff --git a/assets/img/yourte.png b/assets/img/yourte.png new file mode 100644 index 0000000..e604420 Binary files /dev/null and b/assets/img/yourte.png differ diff --git a/config.php b/config.php new file mode 100644 index 0000000..287a7cd --- /dev/null +++ b/config.php @@ -0,0 +1,94 @@ +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'); + diff --git a/footer.php b/footer.php new file mode 100644 index 0000000..d7c3f61 --- /dev/null +++ b/footer.php @@ -0,0 +1,17 @@ + + + + + + + + '; +?> + + + diff --git a/functions.php b/functions.php new file mode 100644 index 0000000..bcf2490 --- /dev/null +++ b/functions.php @@ -0,0 +1,34 @@ + + + + Geoloc + + + + + + +

+

+ + + + \ No newline at end of file diff --git a/header.php b/header.php new file mode 100644 index 0000000..19ce74b --- /dev/null +++ b/header.php @@ -0,0 +1,24 @@ + + + + La bureautique + + + + '; + ?> + + + +> + + + +
\ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 0000000..e5c98f2 --- /dev/null +++ b/index.php @@ -0,0 +1,43 @@ +Ze Ğ1 jeux + +

+ À quel jeu voulez-vous jouer ? +

+ +
'; + + foreach ($games as $gameId => $game) { + + echo ' +
+ + '. $game['title'] .' + +
+
+ '. $game['description'] .' +
+ + '; + } + + echo ' +
'; + + + +include_once('footer.php'); \ No newline at end of file diff --git a/lib/CesiumPlus.class.php b/lib/CesiumPlus.class.php new file mode 100644 index 0000000..29efe68 --- /dev/null +++ b/lib/CesiumPlus.class.php @@ -0,0 +1,50 @@ +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; + } +} diff --git a/lib/DAO.class.php b/lib/DAO.class.php new file mode 100644 index 0000000..f95d515 --- /dev/null +++ b/lib/DAO.class.php @@ -0,0 +1,588 @@ + [ + + '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 ' + + + '; + + $x = 25; + $y = 25; + + foreach ($errorMsgs as $msg) { + + echo ' + + '. $msg . ' + '; + + $y += 25; + } + + echo ' + + '; + + } else { + + ob_get_clean(); // to prevent error message to display inside an HTML container (case of error generated by get method calls) + + echo ' + + + + '. _('Erreur critique') . ' + + + + + +
'; + + + foreach ($errorMsgs as $msg) { + + echo '

' . $msg . '

'; + } + + echo ' +
+ + '; + } + + exit; + } + + public function printUnit () { + + if ($this->unit == 'relative') { + + if ($this->displayType == 'img') { + + return _('DUĞ1'); + + } else { + + return _('DUĞ1'); + } + + } 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'; + + } + + +} diff --git a/lib/Fred.class.php b/lib/Fred.class.php new file mode 100644 index 0000000..4f8baae --- /dev/null +++ b/lib/Fred.class.php @@ -0,0 +1,84 @@ +gatewayProtocol . '://'. $this->gatewayDomain .':' . $this->gatewayPort . '/?' . $query) + or die('

On a fait du sale.

'); + + preg_match("`url='([^']+)'`isU", $page1, $matches); + + $url = $matches[1]; + + sleep($this->gatewayDelay); + + $page2 = @file_get_contents($url) + or die('

On a chié dans la colle.

'); + + 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 '
'; var_dump(htmlspecialchars($url)); echo '
'; + + $page1 = file_get_contents($url) + or die('

On a fait du sale.

'); + + echo '
'; var_dump(htmlspecialchars($page1)); echo '
'; + + preg_match("`url='([^']+)'`isU", $page1, $matches); + + $url = $matches[0]; + + echo '
'; var_dump($url); echo '
'; + + $page2 = ''; + + while (empty($page2)) { + + sleep($this->gatewayDelay); + + $page2 = @file_get_contents($url); + } + + echo '
'; var_dump($page2); echo '
'; + + die(); + + $json = $page2; + + return $page1; + + } +} \ No newline at end of file diff --git a/lib/Gchange.class.php b/lib/Gchange.class.php new file mode 100644 index 0000000..fd5187d --- /dev/null +++ b/lib/Gchange.class.php @@ -0,0 +1,279 @@ + 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 () { + + + } +} diff --git a/lib/Location.class.php b/lib/Location.class.php new file mode 100644 index 0000000..78ad795 --- /dev/null +++ b/lib/Location.class.php @@ -0,0 +1,131 @@ + 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)); + } + +} diff --git a/login.php b/login.php new file mode 100644 index 0000000..c7d186b --- /dev/null +++ b/login.php @@ -0,0 +1,63 @@ +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 ' +
+ +

+ +

+ +

+ +

+ +

+ +

+ + +

+ +

+
+ '; + +} \ No newline at end of file diff --git a/map.php b/map.php new file mode 100644 index 0000000..a8a2c95 --- /dev/null +++ b/map.php @@ -0,0 +1,281 @@ +getUser($_SESSION['player_pubkey']); + +$origLat = $player->_source->geoPoint->lat; +$origLon = $player->_source->geoPoint->lon; + +$origLoc = new Location(); +$origLoc->setPosition($origLat, $origLon); + + + +echo ' +
+ + + +
+
+ +
'; + + 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 ' + '. $player->_source->title .' +
+ '; + + + $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 ' +
'; + + echo ' + '; + + 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 ' + + '. $place->_source->title . ''; + + echo ' + + +
'; + + + + echo ' +
+ +
'; + } + echo ' +
+
'; + + + +if (isset($selectedPlace)) { + + echo ' + '; +} + + +include_once('footer.php'); \ No newline at end of file diff --git a/select_game.php b/select_game.php new file mode 100644 index 0000000..80ccca8 --- /dev/null +++ b/select_game.php @@ -0,0 +1,14 @@ + 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"; +} \ No newline at end of file diff --git a/themes/magie/deco.js b/themes/magie/deco.js new file mode 100644 index 0000000..e69de29 diff --git a/themes/magie/layout.css b/themes/magie/layout.css new file mode 120000 index 0000000..8523640 --- /dev/null +++ b/themes/magie/layout.css @@ -0,0 +1 @@ +../spationaute/layout.css \ No newline at end of file diff --git a/themes/magie/layout.js b/themes/magie/layout.js new file mode 120000 index 0000000..4e58ba6 --- /dev/null +++ b/themes/magie/layout.js @@ -0,0 +1 @@ +../spationaute/layout.js \ No newline at end of file diff --git a/themes/spationaute/deco.css b/themes/spationaute/deco.css new file mode 100644 index 0000000..0c8564d --- /dev/null +++ b/themes/spationaute/deco.css @@ -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; +} diff --git a/themes/spationaute/deco.js b/themes/spationaute/deco.js new file mode 100644 index 0000000..8c13293 --- /dev/null +++ b/themes/spationaute/deco.js @@ -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); + } +} \ No newline at end of file diff --git a/themes/spationaute/layout.css b/themes/spationaute/layout.css new file mode 100644 index 0000000..b1b8952 --- /dev/null +++ b/themes/spationaute/layout.css @@ -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); +} + diff --git a/themes/spationaute/layout.js b/themes/spationaute/layout.js new file mode 100644 index 0000000..a7ffda2 --- /dev/null +++ b/themes/spationaute/layout.js @@ -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; +}