Compare commits

...

4 Commits

Author SHA1 Message Date
Boris 1bd4554893 themes 2022-10-26 13:08:25 +02:00
Boris 7c87c4a371 Ajout ratings gchange 2022-10-26 12:12:20 +02:00
Boris 5917c74e4e La Bureautique tue tout 2022-10-24 19:14:58 +02:00
Boris a2e2d4583f La Bureautique, c'est mieux que le gin tonic. 2022-10-24 14:16:30 +02:00
23 changed files with 763 additions and 130 deletions

View File

@ -8,7 +8,7 @@ error_reporting(E_ALL);
session_start();
define('DEFAULT_RADIUS', 10);
define('DEFAULT_RADIUS', 50);
define('TAILLE_SPRITE', 32);
define('DEMI_TAILLE_SPRITE', (TAILLE_SPRITE/2));
@ -85,7 +85,7 @@ $games = [
]
];
$radiuses = [5, 10, 20, 50, 100];
$radiuses = [5, 10, 20, 50];
define('DEFAULT_GAME', 'spationaute');
@ -95,6 +95,8 @@ if (!isset($_SESSION['gameId'])) {
}
define('DEFAULT_WEBPAGE_TITLE', 'La bureautique');
require_once('functions.php');

View File

@ -4,14 +4,18 @@
<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>
<?php
$themeJSDir = 'themes/'. $_SESSION['gameId'] . '/js';
$files = scandir($themeJSDir);
$files = array_slice($files, 2);
';
?>
foreach ($files as $f) {
echo '
<script type="text/javascript" src="'. $themeJSDir . '/' . $f .'"></script>
';
}
?>
</body>
</html>

View File

@ -1,15 +1,27 @@
<!DOCTYPE html>
<?php
$webpageTitle = isset($webpageTitle) ? $webpageTitle : DEFAULT_WEBPAGE_TITLE;
?><!DOCTYPE html>
<html>
<head>
<title>La bureautique</title>
<?php
echo '
<title><?php echo $webpageTitle; ?></title>
<link rel="stylesheet" type="text/css" href="themes/'. $_SESSION['gameId'] .'/layout.css" />
<link rel="stylesheet" type="text/css" href="themes/'. $_SESSION['gameId'] .'/deco.css" />
';
<?php
$themeCSSDir = 'themes/'. $_SESSION['gameId'] . '/css';
$files = scandir($themeCSSDir);
$files = array_slice($files, 2);
foreach ($files as $f) {
echo '
<link rel="stylesheet" type="text/css" href="'. $themeCSSDir . '/' . $f .'" title="'. $games[$_SESSION['gameId']]['title'] .'" />';
}
?>
<link rel="stylesheet" type="text/css" href="themes/layout.css" />
<link rel="stylesheet" type="text/css" href="themes/deco.css" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<?php

29
home.php Normal file
View File

@ -0,0 +1,29 @@
<?php
require_once('config.php');
$bodyIds = 'home';
include_once('header.php');
echo '
<nav>
<ul>
<li>
<a href="map.php">
Carte
</a>
</li>
<li>
<a href="messenger.php">
Messagerie
</a>
</li>
</ul>
</nav>
';
include_once('footer.php');

View File

@ -5,7 +5,7 @@ require_once('config.php');
require_once('lib/Gchange.class.php');
require_once('lib/Location.class.php');
$bodyIds = 'home';
$bodyIds = 'startpage';
include_once('header.php');
@ -18,25 +18,37 @@ echo '
À quel jeu voulez-vous jouer ?
</p>
<dl>';
<ul id="games-list">';
foreach ($games as $gameId => $game) {
echo '
<dt>
<a href="select_game.php?gameId='. $gameId .'">
'. $game['title'] .'
</a>
</dt>
<dd>
'. $game['description'] .'
</dd>
<li class="game">
<h2>
<a href="select_game.php?gameId='. $gameId .'">
<span>
'. $game['title'] .'
</span>
</a>
</h2>
<p>
<img
src="themes/'. $gameId . '/game-icon.png"
alt="'. $game['title'] .'"
/>
</p>
<p>
'. $game['description'] .'
</p>
</li>
';
}
echo '
</dl>';
</ul>';

View File

@ -1,4 +1,7 @@
<?php
/**
* https://github.com/duniter/cesium-plus-pod/blob/master/src/site/markdown/REST_API.md
*/
require_once('DAO.class.php');
@ -11,6 +14,8 @@ class CesiumPlus {
$this->dao = DAO::getInstance();
}
public function
/*
public function getNearbyUsers ($lat, $lon, $radius) {
$n = 15;
@ -47,4 +52,5 @@ class CesiumPlus {
return $result->hits->hits;
}
*/
}

View File

@ -1,4 +1,7 @@
<?php
/**
* https://github.com/duniter/duniter-bma/blob/master/doc/API.md
*/
date_default_timezone_set('Europe/Paris');
@ -72,7 +75,7 @@ class DAO {
'duniter' => 2,
'cesiumplus' => 5,
'gchange' => 5,
'gchange' => 10,
];
private $nodeTimeoutIncrement = [
@ -481,7 +484,7 @@ class DAO {
if (isset($queryParams)) {
$out[] = _('Paramètres de la requête : ');
$out[] = print_r($queryParams, true);
$out[] = '<pre>'. print_r($queryParams, true) . '<pre>';
}
$this->decease($out);

View File

@ -1,7 +1,12 @@
<?php
/**
* https://github.com/duniter-gchange/gchange-pod/blob/master/src/site/markdown/REST_API.md
*/
require_once('DAO.class.php');
require_once('GchangeUser.class.php');
require_once('GchangeRecord.class.php');
require_once('GchangeRating.class.php');
class Gchange {
@ -13,6 +18,7 @@ class Gchange {
private $cacheLongevity = array(
'placesNearby' => 604800, // 3 jours
'usersNearby' => 43200, // 12 heures
'users' => 43200, // 12 heures
'records' => 900 // 15 min
);
@ -37,15 +43,29 @@ class Gchange {
$queryParams = [
'size' => $n,
'query' => [
'bool' =>[
'must' => [
'bool' => [
'filter' => [
'term' => [
'issuer' => $issuer
]
],
'must_not' => [
/*
, 'range' => [
'stock' => [
'gte' => 1
]
]
*/
]
/*
, 'filter' => [
]
*/
, 'must_not' => [
[ "term" => ["stock" => 0] ]
]
]
],
'sort' => [
@ -60,7 +80,15 @@ class Gchange {
$result = json_decode($json);
return $result->hits->hits;
$records = [];
foreach ($result->hits->hits as $hit) {
$records[] = new GchangeRecord($hit);
}
return $records;
}
@ -124,6 +152,9 @@ class Gchange {
public function getPlacesNearUser ($user, $radius) {
return $this->getNearbyPlaces($user->getLat(), $user->getLon(), $radius);
/*
$placesCacheDir = 'places-nearby/user/';
$placesCacheFile = $user->getUserGchangeId() . '.json';
@ -140,20 +171,129 @@ class Gchange {
$result = json_decode($json);
return $result->hits->hits;
*/
}
public function getNearbyPlaces ($lat, $lon, $maxDistance, $minDistance = NULL) {
$json = $this->getNearbyPlacesJson($lat, $lon, $maxDistance, $minDistance);
$placesCacheDir = 'places-nearby/geopoint/';
$placesCacheFile = $lat . ',' . $lon . '.json';
$json = $this->getJsonFromCache($placesCacheDir, $placesCacheFile, $this->cacheLongevity['placesNearby']);
if (empty($json)) {
$json = $this->getNearbyPlacesJson($lat, $lon, $maxDistance, $minDistance);
$this->cacheJson($placesCacheDir, $placesCacheFile, $json);
}
$result = json_decode($json);
return $result->hits->hits;
}
public function getNearbyPlacesJson ($lat, $lon, $maxDistance, $minDistance = NULL) {
public function getNearbyUsers ($lat, $lon, $maxDistance, $minDistance = NULL) {
$placesCacheDir = 'users-nearby/geopoint/';
$placesCacheFile = $lat . ',' . $lon . '.json';
$json = $this->getJsonFromCache($placesCacheDir, $placesCacheFile, $this->cacheLongevity['usersNearby']);
if (empty($json)) {
$json = $this->getNearbyPlacesJson($lat, $lon, $maxDistance, $minDistance);
$this->cacheJson($placesCacheDir, $placesCacheFile, $json);
}
$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);
$records = [];
foreach ($result->hits->hits as $hit) {
$records[] = new GchangeRecord($hit);
}
return $records;
}
public function getUsersInDaPlace ($placeId) {
$n = 20;
$queryParams = [
'size' => $n,
'query' => [
'nested' => [
'path' => 'socials',
'query' => [
'bool' => [
'filter' => [
'term' => [
'socials.url' => 'https://www.gchange.fr/#/app/page/view/'. $placeId .'/'
]
]
]
]
]
]
];
$json = $this->dao->fetchJson('/user/profile/_search', 'gchange', $queryParams);
$result = json_decode($json);
$users = [];
foreach ($result->hits->hits as $hit) {
$users[] = new GchangeUser($hit);
}
return $users;
}
public function getRatingsSentBy ($issuer) {
$n = 20;
$queryParams = [
@ -161,6 +301,70 @@ class Gchange {
'query' => [
'bool' => [
'must' => [
'term' => ['kind' => 'STAR']
],
'filter' => [
'term' => ['issuer' => $issuer]
]
]
]
];
$json = $this->dao->fetchJson('/like/record/_search', 'gchange', $queryParams);
$result = json_decode($json);
$ratings = [];
foreach ($result->hits->hits as $hit) {
$ratings[] = new GchangeRating($hit);
}
return $ratings;
}
public function getRatingsReceivedBy ($receiver) {
$n = 20;
$queryParams = [
'size' => $n,
'query' => [
'bool' => [
'must' => [
'term' => ['kind' => 'STAR']
],
'filter' => [
'term' => ['id' => $receiver]
]
]
]
];
$json = $this->dao->fetchJson('/like/record/_search', 'gchange', $queryParams);
$result = json_decode($json);
$ratings = [];
foreach ($result->hits->hits as $hit) {
$ratings[] = new GchangeRating($hit);
}
return $ratings;
}
public function getNearbyPlacesJson ($lat, $lon, $maxDistance, $minDistance = NULL) {
$n = 20;
$queryParams = [
'size' => $n,
'query' => [
'bool' => [
'filter' => [
[
'geo_distance' => [
@ -214,39 +418,15 @@ class Gchange {
$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;
$records = [];
foreach ($result->hits->hits as $hit) {
$records[] = new GchangeRecord($hit);
}
return $records;
}
public function getShippable () {
@ -265,7 +445,15 @@ class Gchange {
$json = $this->dao->fetchJson('/market/record/_search?pretty', 'gchange', $queryParams);
$result = json_decode($json);
return $result->hits->hits;
$records = [];
foreach ($result->hits->hits as $hit) {
$records[] = new GchangeRecord($hit);
}
return $records;
}
public function getHousingOffers () {

View File

@ -0,0 +1,44 @@
<?php
class GchangeRating {
private $senderPubkey;
private $receiverPubkey;
private $level;
private $time;
public function __construct ($gchangeObject) {
$this->senderPubkey = $gchangeObject->_source->issuer;
$this->receiverPubkey = $gchangeObject->_source->id;
$this->level = $gchangeObject->_source->level;
$this->time = $gchangeObject->_source->time;
}
public function getLevel () {
return $this->level;
}
public function getSenderPubkey () {
return $this->senderPubkey;
}
public function getReceiverPubkey () {
return $this->receiverPubkey;
}
public function getTime () {
return $this->time;
}
}

View File

@ -0,0 +1,57 @@
<?php
class GchangeRecord {
private $gchangeId;
private $title;
private $description;
private $type;
private $imgSrc = null;
public function __construct ($gchangeObject) {
$this->title = $gchangeObject->_id;
$this->type = $gchangeObject->_source->type;
$this->title = $gchangeObject->_source->title;
$this->description = $gchangeObject->_source->description;
if (isset($gchangeObject->_source->avatar->_content) and
!empty($gchangeObject->_source->avatar->_content)) {
$this->imgSrc = 'data:'. $gchangeObject->_source->avatar->_content_type .';base64,' . $gchangeObject->_source->avatar->_content;
}
}
public function getGchangeId () {
return $this->gchangeId;
}
public function getType () {
return $this->type;
}
public function getTitle () {
return $this->title;
}
public function getDescription () {
return $this->description;
}
public function getImgSrc () {
return $this->imgSrc;
}
}

View File

@ -21,55 +21,43 @@ if (isset($_POST['salt'], $_POST['pepper'])) {
$_SESSION['salt'] = $_POST['salt'];
$_SESSION['pepper'] = $_POST['pepper'];
header('Location:map.php');
header('Location:home.php');
} else {
$bodyIds = 'login-page';
$webpageTitle = $games[$_SESSION['gameId']]['title'];
include_once('header.php');
echo '
<form method="post" action="">';
<form method="post" action="">
/*
<p>
<label>Joueur&nbsp;:
<select name="player">';
<fieldset>
<legend>Identification par Ğchange</legend>
foreach ($players as $p) {
<p>
<label>
Identifiant :
<input type="text" name="salt" />
</label>
</p>
echo '<option value="'. $p->getPubkey() .'">'. $p->getName() .'</option>';
}
<p>
<label>
Mot de passe :
<input type="password" name="pepper" />
</label>
</p>
echo '
</select>
</label>
</p>
*/
echo '
<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>
<p>
<input type="submit" value="Jouer" />
</p>
</fieldset>
</form>
';
include_once('footer.php');
}

85
map.php
View File

@ -34,10 +34,22 @@ $origLoc->setPosition($origLat, $origLon);
echo '
<nav id="go-back-home">
<a href="home.php">
<span>
'. dgettext($_SESSION['gameId'], _('Retour au tableau de bord')) . '
</span>
</a>
</nav>
<section id="mapview">
<aside id="geoPoint">
<a href=".">'. $origLat . ' , ' . $origLon .'</a>
<span id="origLat">'.
$origLat .
'</span><span class="sep">,</span><span id="origLon">' .
$origLon .
'</span>
</aside>
<nav id="zoom">
@ -61,7 +73,10 @@ echo '
data-radius="'. $_SESSION['radius'] .'"
>
<div id="map-deco"></div>
';
/*
echo '
<section class="player" style="left: calc(50% - '. DEMI_TAILLE_SPRITE . 'px); top: calc(50% - '. DEMI_TAILLE_SPRITE . 'px);">';
$avatarSrc = $player->getAvatarImgSrc();
@ -75,18 +90,13 @@ echo '
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;
@ -129,6 +139,11 @@ echo '
</article>
</section>';
if (isset($_GET['place']) and ($place->_id == $_GET['place'])) {
$selectedPlace = $place;
}
}
echo '
</div>
@ -189,8 +204,42 @@ if (isset($selectedPlace)) {
';
$visitors = $gchange->getUsersInDaPlace($place->_id);
$records_visitors = [];
$records = $gchange->getRecordsByIssuer($place->_source->issuer);
if (!empty($visitors)) {
echo '
<h4>Visiteurs</h4>
<ul class="visitors">';
foreach ($visitors as $visitor) {
$records_visitors = array_merge($records_visitors, $gchange->getRecordsByIssuer($visitor->getUserGchangeId()));
echo '
<li class="visitor">';
$avatarSrc = $visitor->getAvatarImgSrc();
$src = !empty($avatarSrc) ? $avatarSrc : $games[$_SESSION['gameId']]['default_avatar'];
echo '
<img src="'. $src . '"
alt="'. $visitor->getUserName() .'"
title="'. $visitor->getUserName() .'"
width="64"
height="64" />
</li>';
}
echo '
</ul>';
}
$records_placeCreator = $gchange->getRecordsByIssuer($place->_source->issuer);
$records = array_merge($records_placeCreator, $records_visitors);
$offers = [];
$needs = [];
@ -198,7 +247,7 @@ if (isset($selectedPlace)) {
foreach ($records as $record) {
switch ($record->_source->type) {
switch ($record->getType()) {
case 'offer':
$offers[] = $record;
@ -219,13 +268,13 @@ if (isset($selectedPlace)) {
echo '<ul>';
foreach ($needs as $item) {
$description = isset($item->_source->description) ? ' title="'. substr($item->_source->description, 0, 30) . '"' : '';
$description = !empty($item->getDescription()) ? ' title="'. substr($item->getDescription(), 0, 30) . '"' : '';
echo '
<li>
<a href="https://www.gchange.fr/#/app/market/view/'. $item->_id . '/"'. $description .'>
' . $item->_source->title . '
<a href="https://www.gchange.fr/#/app/market/view/'. $item->getGchangeId() . '/"'. $description .'>
' . $item->getTitle() . '
</a>
</li>
@ -241,13 +290,13 @@ if (isset($selectedPlace)) {
echo '<ul>';
foreach ($offers as $item) {
$description = isset($item->_source->description) ? ' title="'. substr($item->_source->description, 0, 30) . '"' : '';
$description = !empty($item->getDescription()) ? ' title="'. substr($item->getDescription(), 0, 30) . '"' : '';
echo '
<li>
<a href="https://www.gchange.fr/#/app/market/view/'. $item->_id . '/"'. $description .'>
' . $item->_source->title . '
<a href="https://www.gchange.fr/#/app/market/view/'. $item->getGchangeId() . '/"'. $description .'>
' . $item->getTitle() . '
</a>
</li>
@ -262,13 +311,13 @@ if (isset($selectedPlace)) {
echo '<ul>';
foreach ($crowdfundings as $item) {
$description = isset($item->description) ? ' title="'. substr($item->_source->description, 0, 30) . '"' : '';
$description = !empty($item->getDescription()) ? ' title="'. substr($item->getDescription(), 0, 30) . '"' : '';
echo '
<li>
<a href="https://www.gchange.fr/#/app/market/view/'. $item->_id . '/"'. $description .'>
' . $item->_source->title . '
<a href="https://www.gchange.fr/#/app/market/view/'. $item->getGchangeId() . '/"'. $description .'>
' . $item->getTitle() . '
</a>
</li>

31
themes/deco.css Normal file
View File

@ -0,0 +1,31 @@
body#startpage {
background: hsl(0, 0%, 5%);
color: white;
}
body#startpage a,
body#startpage a:visited {
color: white;
text-decoration: none;
}
body#startpage #games-list .game {
border-style: solid;
border-color: yellow;
}
body#startpage #games-list .game:hover {
background-color: yellow;
}
body#startpage #games-list .game:hover,
body#startpage #games-list .game:hover a {
color: black;
}

56
themes/layout.css Normal file
View File

@ -0,0 +1,56 @@
body#startpage
{
text-align: center;
}
body#startpage ul#games-list {
list-style: none;
margin: 0;
padding: 0;
}
body#startpage ul#games-list li {
margin: 0;
padding: 0;
}
body#startpage #games-list {
display: flex;
flex-wrap: wrap;
flex-direction: row;
}
body#startpage #games-list .game {
width: 31.333%;
margin-left: 1%;
margin-right: 1%;
border-width: 0.125rem ;
position: relative;
}
body#startpage #games-list .game h2 {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
body#startpage #games-list .game h2 a {
display: block;
width: 100%;
height: 100%;
}
body#startpage #games-list .game h2 + * {
margin-top: 4rem;
}

1
themes/magie/css/layout.css Symbolic link
View File

@ -0,0 +1 @@
../../spationaute/css/layout.css

BIN
themes/magie/game-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -1 +0,0 @@
../spationaute/layout.css

View File

@ -10,17 +10,49 @@
body {
background: hsl(0, 50%, 2%);
color: white;
}
a,
a:visited {
color: white;
}
#login-page {
color: white;
}
#go-back-home {
#mapview #geoPoint a,
#mapview #geoPoint a:visited {
background-color: hsla(132.2, 59.8%, 12.1%, 0.5);
}
#go-back-home a {
text-decoration: none;
}
#go-back-home a span {
display: none;
}
#go-back-home a:before {
content: "<";
background: hsl(132.2, 59.8%, 52.2%);
color: hsla(132.2, 59.8%, 12.1%);
width: 3rem;
height: 3rem;
font-size: 2rem;
font-weight: bolder;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
}
#mapview #geoPoint {
color: white;
opacity: 0.4;

View File

@ -20,11 +20,21 @@ body {
}
#go-back-home {
position: fixed;
top: 0;
left: 0;
padding: 0.5rem;
margin: 0.5rem;
z-index: 200;
}
#mapview #geoPoint {
padding: 1rem;
position: fixed;
top: 0;
position: absolute;
bottom: 0;
left: 0;
display: inline-block;
}
@ -113,8 +123,37 @@ main {
#place-details ul.visitors {
margin: 0;
padding: 0;
list-style: none;
}
#place-details ul.visitors li {
margin: 0;
padding: 0;
}
#place-details .visitors {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
#place-details .visitors .visitor {
margin-right: 1rem;
flex-basis: 64px;
text-align: center;
}
#place-details .visitors .visitor img {
display: block;
}
#place-details {
@ -159,6 +198,30 @@ main {
#messenger-page main {
display: flex;
@ -276,3 +339,60 @@ main {
right: 0;
}
#login-page input {
border-radius: 0;
}
#login-page {
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
flex-shrink: 1;
flex-basis: 100%;
}
#login-page footer {
justify-self: flex-end;
}
#login-page main {
flex-basis: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
}
#login-page fieldset {
border-width: 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB