Migration du serveur Minetest (en PostgreSQL !)

Le moment était venu. Le serveur qui hébergeait jusqu’alors mon jeu Minetest « Amelaye in Minerland » commençait à souffrir, tant la base de données tendait à être énorme (33 Go, vous voyez un peu …). Difficile de dire aux joueurs d’arrêter d’explorer, de creuser, bref de tirer la plus-value du monde qu’ils aimaient modifier. D’autant plus que j’avais bien envie d’installer de nouveaux mods. Et puis surtout, le serveur qui héberge le jeu est une machine perso, qui sert également pour pas mal de choses.

Alors j’ai décidé d’une part de louer un nouveau serveur Kimsufi, une machine assez robuste pour cet usage exclusif, et d’autre part, de migrer la base de données Minetest, à l’origine en SQLite vers PostgreSQL. Pourquoi ? Parce que si on regarde bien, c’est plutôt vivement recommandé.

Documentation des backends Minetest

Tout est dit, ne plus rester sous SQLite implique de limiter les lags, et également de réduire les risques de corruption de la base de données (ma plus grande crainte !). Et ça, c’est tout bénéf’ !

Allons-y. Ma nouvelle machine arrive toute fraiche avec la dernière version d’Ubuntu. Déjà, je m’enlève de la tête qu’on n’installe pas Minetest avec un simple apt-get dans mon cas de figure, ce serait trop simple. Car la version déjà compilée ne supporte pas PostgreSQL. Il va falloir compiler les sources. Je relève le défi.

On prépare le terrain

J’installe la matière première, les librairies qui me seront utiles …

sudo apt install wget postgresql 
postgresql-contrib g++ make libc6-dev libirrlicht-dev cmake 
libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev 
libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev 
libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev 
libjsoncpp-dev libpq-dev libpqtypes-dev doxygen 
libluajit-5.1-dev libspatialindex-dev libncurses-dev

Comme ça, c’est fait. Je me crée un utilisateur minetest :

sudo useradd -mU minetest

Et je me logue sur le compte, comme ça :

sudo -i -u minetest

Puis je télécharge les sources de Minetest. Important : téléchargez la DERNIERE VERSION stable qui correspond à celle que vous utilisiez, sinon ça peut engendrer des bugs. Dans mon cas, c’est la 5.5.1 :

git clone https://github.com/minetest/minetest.git
git checkout 5.5.1
cd minetest/games/
git clone https://github.com/minetest/minetest_game.git
git checkout 5.5.1
cd ..

Ok, c’est facile. Maintenant, je passe à la pré-compilation (et je croise les doigts) :

cmake . -DRUN_IN_PLACE=TRUE 
-DBUILD_CLIENT=FALSE 
-DBUILD_SERVER=TRUE 
-DCMAKE_BUILD_TYPE=Release 
-DBUILD_UNITTESTS=FALSE 
-DENABLE_POSTGRESQL=TRUE 
-DVERSION_EXTRA=postgresql 
-DPostgreSQL_INCLUDE_DIR=/usr/include/postgresql 
-DPostgreSQL_TYPE_INCLUDE_DIR=/usr/include/postgresql 
-DPostgreSQL_LIBRARY=/usr/lib/x86_64-linux-gnu/libpq.so

Et là … ça plante.

CMake Error at CMakeLists.txt:110 (message):
IrrlichtMt headers are required to build the server, but none found.
The Minetest team has forked Irrlicht to make their own customizations.
It can be found here: https://github.com/minetest/irrlicht
For example use: 
git clone --depth=1 https://github.com/minetest/irrlicht lib/irrlichtmt

On sent bien les origines allemandes du jeu, tiens. Il a besoin d’une librairie « Irrlicht » pour pouvoir compiler. Mais pourtant, je l’ai apt-getté, celui-là … bon, on va là aussi compiler les sources avec l’adresse GIT qui est fournie alors.

Installation d’Irrlicht

Donc, on récupère Irrlicht dans le répertoire minetest pour pouvoir faire en sorte que l’include dans les sources trouve ses petits. Il est très important d’installer Irrlicht dans lib/irrlichtmt

git clone --depth=1 https://github.com/minetest/irrlicht lib/irrlichtmt

On va dans le répertoire et on compile :

cd lib/irrlichtmt
cmake . -DBUILD_SHARED_LIBS=OFF
make -j$(nproc)

Normalement on s’en sort avec juste quelques warnings.

Compilation réussie !

Je reviens deux répertoires en arrière, relance la pré-compilation de Minetest, et … mince encore des erreurs.

CMake Error at /usr/share/cmake-3.22/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
Could NOT find Zstd (missing: ZSTD_LIBRARY ZSTD_INCLUDE_DIR)
Call Stack (most recent call first):
/usr/share/cmake-3.22/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
cmake/Modules/FindZstd.cmake:24 (find_package_handle_standard_args)
src/CMakeLists.txt:228 (find_package)

Bon, certainement une lib qui manque, ce ne sera pas la mer à boire. Je reviens dans mon compte utilisateur et je fais un petit :

sudo apt install -y libzstd-dev

Je reviens dans mon compte minetest et mon répertoire minetest, je relance la pré-compilation. Cool, ça a marché. Maintenant je lance la compilation :

make -j$(nproc)

Okay, le terminal m’indique que minetestserver a été compilé avec succès.

Je lance le binaire :

cd ..
./minetest/bin/minetestserver

Et je lance mon jeu depuis Minetest en spécifiant l’adresse IP du serveur. Tout se lance, génial. J’éteins le serveur, le plus complexe reste à venir.

Configuration du serveur PostgreSQL

Je relance par sécurité le service :

sudo systemctl restart postgresql.service

Et puis je lance mon interface PostgreSQL

sudo -u postgres psql 
CREATE USER monuser WITH PASSWORD '*****';
CREATE DATABASE adventure OWNER monuser;
GRANT ALL PRIVILEGES ON DATABASE adventure TO monuser;

Je vérifie avec /l que tout est ok et je sors

La migration de l’ancien serveur

Là, je suis obligée de dire à mes joueurs que le serveur doit être fermé pour la migration. J’éteins mon ancien serveur et je fais une copie de mon monde vers le nouveau. Je ne cache pas que ça prend du temps, vu le nombre de gigaoctets de mon map.sqlite.

Pour vous situer, il faut copier deux répertoires :
– celui des mods : .minetest/mods vers minetest/mods
– celui du monde, dans mon cas : .minetest/worlds/adventure vers minetest/worlds/adventure

Je tremble un peu durant ce transfert et prie pour que tout se passe bien. Je relance après cette étape en spécifiant mon monde et … ça se lance ! Tout va bien, je souffle un peu ! Maintenant passons aux choses sérieuses !

J’édite mon fichier world.mt du monde adventure pour y ajouter mes identifiants de connexion PostgreSQL. On ne touche à rien d’autre, notamment la configuration des backends en SQLite. Ce sera fait automatiquement.

pgsql_connection = host=127.0.0.1 port=5432 user=monuser password=***** dbname=adventure
pgsql_auth_connection = host=127.0.0.1 port=5432 user=monuser password=***** dbname=adventure
pgsql_player_connection = host=127.0.0.1 port=5432 user=monuser password=***** dbname=adventure

Et je lance ma première migration, celle du monde, et j’attends. Ce qui est sympa, c’est que l’avancée de la migration s’affiche :

./minetest/bin/minetestserver --migrate postgresql --world minetest/worlds/adventure

Si vous avez comme moi une base de données énorme, ne faites pas l’erreur que j’ai faite, de lancer le script dans un terminal et le laisser juste agir comme ça (sincèrement, je ne pensais pas que ça prendrait tant de temps !). Je suis partie me coucher, le lendemain mon ordi avait rebooté tout seul, interrompant le process (que j’avais lancé la veille à 15h30), et que j’ai dû relancer cette fois dans un screen (ou faites un nohup … &, bref, permettez au script de le laisser exécuté même si il y a une coupure.). Bref, une bonne vingtaine d’heures plus tard (oui, une VINGTAINE d’heures !!!) après le deuxième lancement, la base des blocs est migrée !

Regardons le fichier world.mt. Il a changé automatiquement le backend correspondant à la base des blocs. Nickel. Faisons la suite. Les autres bases de données migrent très vite.

./minetest/bin/minetestserver --migrate-auth postgresql --world minetest/worlds/adventure
./minetest/bin/minetestserver --migrate-players postgresql --world minetest/worlds/adventure

L’heure de vérité à sonné. Je vérifie que mes backends ont bien été modifiés et que tout pointe sur ma base PostgreSQL. Mieux que ça, je convertis mes fichiers map.sqlite, auth.sqlite et players.sqlite en map.old, auth.old et players.old. Je lance le jeu, et super, tout marche et je retrouve mon monde tel que je l’avais laissé …

Reste à remettre dans mon minetest.conf les paramètres de l’ancien serveur, sauf l’adresse, qui change.

Pour terminer, augmentez la mémoire allouée pour les requêtes PostgreSQL, sinon vous allez vous retrouver avec des plantages core dumped. Donc dans /etc/postgresql/potgresql.conf, changez la valeur du paramètre shared_buffer pour qu’il ait au moins une valeur supérieure à 512Mo. Chez moi, j’ai affecté 1024Mo.

Il ne reste plus qu’à profiter du jeu maintenant !

Mes notes du Symfony Live – Jour 2

Vous avez dit Symfony 6.1? – Nicolas Grekas

Ici, un autre « core dev » de Symfony pour cette première conférence, qui nous rappelle qu’au sein même d’une même version majeure, il y a promesse de rétrocompatibilité … D’une version majeure à une autre, le chemin de migration continue. Il est conseillé de faire un composer update tous les mois; et tous les 6 mois, un composer update pour passer en version mineure suivante, pour corriger les dépréciations.
Il est déconseillé de commencer ou rester sur une version LTS, pour ne pas rester « lent » ou « stable ».
En 6.1 on a droit à :
– une modernisation du code via nouvelles syntaxes / fonctions
– une meilleure description des types natifs et génériques
– une simplification par abandon : SwiftMailer, Twig, FlexServer
– une revisitation des classiques : composer runtime, symfony new (l’option –-full pour le website skeleton devient –website)
– des serveurs à longue durée d’exécutions
– une performance accrue.
Retour sur le nombre de PR : 6PR/jour en 12 mois soit 2000PR : 400 features, 700 bugs, +900 mineures)
Je vous laisse le loisir de regarder la rediffusion de la conférence pour avoir l’aperçu complet, et non exhaustif de cette mise à jour !

Mon avis : un bon tour de découverte de cette nouvelle version de SF, bien hâte de la tester en fait !

Code asynchrone dans une application Symfony synchrone – Jérôme Tamarelle

Petit rappel : Composer utilise depuis la version 2 des composants de ReactPHP, et peu de gens le savent.
Il est question de ces différents concepts :
1. I/O non bloquants
Fonctions natives de PHP pour les flux non-bloquants : stream_select, curl_multi_select, Symfony HTTPClient est non-bloquant.
2. Délégation de traitement à des processus parallèles
Effectuer des traitements en parallèle sans bloquer le processus courant, avec Sf Process ou encore Messenger
3. Branches de code concurrentes dans un même thread
Ici , on parle de promesses, coroutine, et fibers pour exécuter plusieurs branches de code en concurrence, sur le même thread.
A retenir :
– Une fonction synchrone peut appeler une fonction synchrone mais pas une fonction asynchrone.
– Une fonction asynchrone peut appeler une fonction synchrone et une fonction asynchrone.

Mon avis : je suis peu familiarisée avec ces concepts. Intéressant à découvrir par la pratique, peut-être avec un projet futur.                                     

Développer une application web décentralisée avec Symfony et API Platform – Kevin Dunglas

SAUVONS LE WEB !!! DECENTRALISONS !!! Tel est le message de cette conférence de Dunglas, connu de tous pour être un des core devs de Api Platform.
Les GAFAM représentent 57% de tout le trafic mondial, la majorité de l’usage du web passe par ces quelques acteurs-là, et leur donne un contrôle quasi total des contenus des internautes. Ce qui était à des milliards de lieues de la volonté de Tim Berners-Lee quand il a crée le web ! Au départ il voulait vraiment créer un espace de libre expression pour les gens qui ne pouvaient pas le faire … le Web devait donner une voie aux personnes marginalisées, les autres médias étant réellement contrôlés, tous ceux qui avaient quelque chose à dire pouvaient le faire, via les URL, qui relient les sources les unes aux autres (on a donc un graphe de connaissances). Or les GAFAM donnent donc pas mal de problèmes de démocratie, vu qu’ils censurent à tout-va.
Aux origines, le Web 1.0, tout était décentralisé.
Puis le Web 2.0 (terme marketing) est arrivé, permettant aux utilisateurs de bénéficier des formulaires pour publier du contenu, créer des mixs de communautés. On a vu apparaitre les API web, ainsi qu’un mix d’acteurs non-commerciaux et commerciaux, ça se passait plutôt bien. Mais l’argent est entré en jeu.
Puis on voit naitre le Web 3, la promesse : re-décentraliser le web, casser le pouvoir des états surveillants. On propose d’utiliser la blockchain d’Ethereum et d’exécuter ce code sur les ordinateurs du réseau pour faire des sites web. Donc base sur les cryptomonnaies, trustless et permissionless. Sauf que des problèmes se posent : consommation énergétique (Ethereum toujours en POW), d’énormes structures américaines sont intéressées par le concept, chaine de Ponzi.
Donc, voici le concept du Web 3.0, apparu avec le web sémantique, crée par Tim Berners-Lee, qui consiste à utiliser le web comme immense base de données, le web est donc considéré comme base de connaissances, les opérations auraient une grande interopérabilité.
Pour cela on utilise un modèles de données abstrait pour représenter n’importe quel set de données : RDF. Mais on a d’autres formats : tableau HTML, N-Tuple dans un fichier texte, Turtle, JSON-LD.
Tim Berners-Lee présente son projet : SOLID. Les considérations physiques, politiques, etc … dont détaillées dans des documents émis en dur. Solid Toolkit permet de créer des application décentralisées et interopérables, la décentralisation des données personnelles, etc …
A mentionner qu’on peut construire une application Symfony avec Solid. Dunglas propose son bundle.

Mon avis : je suis TRES sensibilisée sur sujet, et j'avais envie, avant la pandémie de faire un gros projet lié au web, son évolution et sa centralisation, hélas remis à plus tard. L'idée est interessante et je vais me pencher sur le sujet, et regarder Solid d'un peu plus près ... mais toutefois, je me pose des questions. N'est-il pas mieux de sensibiliser les gens à faire leur propre site internet, comme avant ? et de créer l'arborescence de leur communauté à cet effet ? Leur faire comprendre ce qu'est le logiciel libre ? Si Dunglas passe par là, je serai ravie qu'il puisse répondre à mon interrogation ;) !

Mon avis global sur le séminaire

Une joie de retrouver tout ce beau monde et l’ambiance des séminaires sans entendre les mots maske aubligatouar, pace vaksinale et tout le toutim. J’aspire vraiment à retrouver la vie active d’avant que je menais sur ce point-là. Les différents stands étaient attractifs, et je suis bien contente d’avoir eu un beau t-shirt en cadeau, et un autre gagné sur le stand des Tilleuls.coop. Il faut juste que je pense la prochaine fois à imprimer mon badge avant de venir ! Les thèmes des conférences étaient variées, et la plupart étaient bien intéressantes et donnent envie de creuser le sujet abordé.
Sinon … gros bémol pour les déjeuners. J’adorais le concept du buffet proposé lors de ma dernière venue, qui permettait un éventail varié. Je fais très attention à ce que je mange, surtout quand je ne trouve pas le temps de faire du sport, que je mange au resto le soir avec ma chérie + les copains que je n’ai pas revus depuis un bail, et que j’ai de gros problèmes avec certains aliments (comme le fromage). Là c’était vraiment bourratif, trop riche et pas varié (sérieux les gars, un gâteau au Daim ? Pas un seul fruit !). Le souci c’est que le tarif du SfLive est plutôt conséquent, et pour moi chaque centime compte, la nourriture en fait partie. Et qu’on ne me parle pas de « raisons sanitaires », vu qu’on reste toujours tous mélangés dans les différentes salles … mais bon, on va me répondre qu’on n’a pas eu le choix, c’est ça ou rien … Oui, je suis exigeante 😀 !

Mes notes du Symfony Live – Jour 1

Quelle joie pour moi de revenir à cette vie d’avant qui m’avait tant manquée … Il s’agit ici du deuxième Symfony Live auquel j’assiste, et comme bien des séminaires, j’ai appris pas mal de choses, que j’ai notées, remises au propre, et vous fais partager !

La keynote de Fabien Potencier

Fabien est en forme pour cette nouvelle session ! Pour démarrer le show, il nous fait un retour d’expérience sur un bug qu’il a eu avec Twig. Après une mise à jour des tests des selectors css, il y a eu un problème de « match » avec une expression qui devait figurer dans le code, via preg_match(). Il commence alors une session de debug, pour avoir un détail plus explicite de la source du bug.
S’inclut alors un petit speech sur l’open source, qui consiste à contribuer pour :
– éviter aux autres ou à soi de refaire la même erreur
– éviter à quelqu’un, voire des centaines de gens de réfléchir de nouveau à un problème
Du coup, quick fix, on fork, on ouvre le code, on essaye de faire le changement, on écrit les tests, on les exécute, on pull request et on croise les doigts 🙂 …
Quand il s’agit d’un package, on peut aussi modifier le code et faire un link dans les vendors pour pouvoir tester plus efficacement.
Cependant, ici il s’agit d’une modification dans ExpressionLangage, qui est une sous-partie de Twig. On peut faire mieux que simplement corriger, ou faire une fonctionnalité qui peut poser problème avec d’autres cas de figure. Du coup, Fabien a poussé la réflexion plus loin … On est en PHP8.1 et on supporte PHP7 dans Twig, ce qui pose problème pour la contribution. La solution : travailler sur Twig4 pour moderniser le code. On ouvre les issues, entre autres : résolution des mismatches camelcase vs. snake_case, ne plus avoir de fonctions globales, analyse syntaxique …
En fin de compte : Twig sera intégré en tant que composant de Symfony, Twig4 sera alors nommé Twig6.2 en parallèle à la nouvelle version de Symfony, et changera de namespace.

Mon avis : une bonne mise en bouche, qui m'a poussée à la réflexion quand à certains de mes side projects.

Comment valider de la donnée – Marion Horteau

Ici, Marion nous fait un parallèle avec l’univers de Pokémon. Personnellement, je ne suis pas du tout fan, mais je me suis laissée tenter.
Pour rappel, un validateur est composé d’une contrainte, qui est appliquée à un objet, et elle est appliquée à un validateur. nativement, il y en a une bonne dizaine (que j’ai du bûcher par cœur pour ma certif …).
Mais certaines contraintes ne sont pas forcément liées à un validateur, comme UniqueEntity dans Doctrine.
On valide sur une propriété, dans un formulaire, dans une méthode (getter ou autre), ou sur une classe entière, et soit dans le code, soit lors d’un submit dans un formulaire.
Mais ici on veut faire de la validation dynamique …
Marion propose donc une solution basée sur une API avec des paramètres qui varient.
Dans le contrôleur, on alimente un objet Evolution, avec un attribut Callback. Comme les contraintes sont différentes, on peut en ajouter avec Assert\Collection. InContext permet de rendre la validation récursive.
Pour externaliser les contraintes, elle crée une interface pour les différents types de contraintes. Elle ajoute des tags dans la définition des services. La persistance se fait soit par Doctrine, soit par Json.

Mon avis : dommage que le contexte Pokémon me rebute, mais il s'agit ici d'un avis personnel. L'introduction sur les validateurs natifs est toutefois un peu longuette, j'aurais aimé qu'elle détaille plus en détails cette validation dynamique. Mais intéressant.

Du DDD avec API Platform – Mathias Arlaud, Robin Chalas

Rappelons-le, ce pattern permet une conception tactique et architecturale. le DDD ce n’est pas du RAD, la conception est pilotée par le métier, et ça ne permet pas de développer rapidement.
Petit rappel de l’archi hexagonale : les layers sont des couches où on écrit du code, ils obéissent à la règle des dépendances.
– Couche basse : domaine (models, events, repo, services …)
– Couche application : contient les services applicatifs pour traiter les use-case métier
– Couche infrastructure : porte vers le monde extérieur (controllers, bases de données, caches, vendors …), c’est la SEULE qui aura accès à du code tiers.
Les avantages :
– on préserve l’intégrité de notre domaine,
– le code est d’avantage testable,
– on est capable de repousser les décisions technologiques,
– le domaine est agnostique du contexte utilisé (ligne de commande, terminal, navigateur …)
Dans Api Platform, on peut configurer via ApiResource les opérations, via new Get() et new Post(). Mais ce n’est pas la bonne approche.
Le pattern command bus va nous permettre de reprendre complètement le main sur nos use case métier en faisant appel à nos domaines. Ça implique : Notion de commande (objet PHP) + un handler (service applicatif) + bus (trouver le bon handler pour une commande données) + deuxième bus (query) pour nous permettre de contrôler la manière dont on interagit avec notre domaine.
On manipule entre autres :
ItemOperations
CollectionOperations (ça dépend si on a un id dans le chemin) – supprimée dans ApiP3, tout est operation
– Notion de ChainProvide qui fait appel aux autres providers
– On peut créer nos propres providers, qui auront d’autres priorités
– Création de DataTransformers

Mon avis :  Haaa ! API Platform ! J'adooore ce framework, et je voulais vraiment en savoir plus sur le Domain Design Development. Je comprends ici que je n'ai pas fait le tour de ce framework, je pense à certains side projects que je définis en DDD, qui font appel à une API crée par ApiP, mais j'ai envie de remanier tout ça. Conférence très interessante qui m'a remise en question. Merci :D !

Doctrine, objet typé, et colonne JSON – Grégoire Pineau

Ici, on parle CMS, notamment celui utilisé par JoliCode. Composé de blocs, qui représentent chacun un objet.
L’objectif de ces blocs :
– éviter la duplication de code
– pouvoir stocker les blocs en BDD
– avoir un maximum d’objets PHP
– et si possible, un objet par type de bloc
Pour ce faire, deux solutions : utiliser l’héritage Doctrine, et stocker du PHP sérialisé.
Les options :
MappedSuperClass : Doctrine ne sait pas gérer les relations avec
Single Table (genre une première classe) avec une entité. On aura une entité mais la deuxième classe sera vide, si la première est remplie.
Class Table : crée une table par type de bloc, pas très pratique à administrer.
On rejette d’emblée le PHP sérialisé via serialize() et unserialize(), non interopérable ! Quand à l’objet stocké en JSON, c’est « so 2013 » …
La solution proposée c’est le Concept Unit Of Work, la donnée est encapsulée via l’EntityManger qui :
– contient le cache de toutes les entitées passées
– gère les écritures en BDD,
– gère les transactions,
– s’occupe de quel objet doit être insert / delete / update
– s’occupe de gérer les dépendances entre les objets
– fait des snapshots des objets qu’il rencontre pour faire un diff au moment du flush.
On utilise alors les event Doctrine, qu’on hooke dans notre code, avec un listener Doctrine.

Mon avis : Je vais me faire taper sur les doigts, mais je vais être franche. C'est assez pénible quand les slides sont passées vite-vite quand on ne connait pas vraiment le sujet (qui ici est spécifique, puisque retour d'expérience). J'ai eu beaucoup de mal à suivre. Personnellement, j'aurais préféré moins de contenu, mais peut-être plus d'explications.

Connaissez-vous vraiment JWT ? – Karim Pinchon

Pour rappel, JWT (prononcé abusivement « jot ») = Json Web Token.
C’est une solution simple et sécurisée, qui a une référence et une valeur.
La cryto, ça obéit à des régles : c’est mathématique, c’est de confiance, ça communique, ça passe sur un canal non sûr, et c’est CAIN.
ça implique :
– la signature numérique
– le chiffrement
– le hachage (intégrité et sens unique)
– Mac / HMac (intégrité et authentification)
– encodage (chaine de caractères)
Pour voir à quoi ça ressemble, il existe les outils token.dev et jwt.io
Après un tour des tokens existants (JWE, JOSE …), quelques conseils :
– attention à ne pas tout accepter côté serveur
– valider les claims
– préférer l’asymétrique
– utiliser une librairie existante et éprouvée
– ne vous battez pas pour révoquer les JWT (ça doit avoir un cycle de vie)
– éviter de logger les jetons (pour la confidentialité)

Mon avis : je suis peu familière avec le cryptage des données, car je n'en ai fait que rarement dans ma carrière, mais c'est bon à savoir.

Des composants Symfony méconnus qui valent le détour – Alexandre Daubois

  • HTMLSanitizer : prévu pour SF 6.1, expérimental.
    HTMLPurifier : garde au mieux l’arborescence des noeuds, supprime les données potentiellement dangereuses.
    Le Sanitizer reconstruit les données du HTML en extrayant les données safe de l’input, la structure de base peut être perdue. Le comportement est défini par HTMLSanitizerConfig. Il peut forcer les https pour les URL, autorise les Schemes, autorise les media hosts.
  • STRING : arrivé en SF 5.0, il permet de faire de la manipulation simplifiée de codepoints, par exemple des emojis : combinaisons possibles pour faire des couleurs de peau, crée des chaines par contructeur (CodePointString, UnicodeString, ByteCodeString …), crée des chaines par factories.
  • OptionsResolver (remplace SPL) : valeurs obligatoires, callbacks, etc … , normalisation pour résoudre les options.
  • L’internationalisation : ce n’est pas seulement de la traduction (dates, nombres, monnaies, etc …), INTL depuis SF 2.3 (mai 2013).
    International Component For Unicode : quelques entreprises bien connues l’utilisent. Permet de formater : les langues, les locales, les monnaies, les timezones (reprises par les forms, qui vont puiser dans ce composant.)
Mon avis : je connaissais déjà OptionsResolver, mais c'est bien sympa d'en connaitre d'autres ! :D ...

Un fabuleux mapping avec Leaflet.js !

Aujourd’hui, pour changer, je vous parlerai de … front-end ! Bien que plus dévolue back, j’avais envie de faire d’une pierre deux-coups et de réaliser un joli mapping de mon monde Minetest.

Avec Minetest, c’est assez facile de générer des fichiers image qui retracent en 2D l’univers généré dans le jeu, avec minetestmapper. A partir de là, les plus créatifs peuvent s’amuser.

Pour la petite histoire, je suis en fait tombée sur le plan interactif du serveur Minetest LinuxForks, qui est juste splendide, et j’ai eu vraiment envie de me lancer ce défi.

Au commencement, une map qui rame à mort !

Du coup, j’ai intégré ce fichier dans une carte de base. Le code est simple, j’intègre Leaflet.js dans ma page web, et j’y intègre quelques markers. La bibliothèque, je la connaissais déjà, car je l’avais déjà intégrée pour l’outil d’un de mes clients BTP, pour y localiser les chantiers en cours. Mais Leaflet, c’est vraiment l’outil qui permet de créer des cartes, sans forcément qu’elle soit « terrestre », une « mappemonde ». Donc pas mal privilégiée par les geeks gamers.
Voilà grosso modo le code de base du premier jet que j’ai intégré dans mon index (j’y ai intégré après un div vide appelé map, bien entendu):

var map = L.map('map', {
    crs: L.CRS.Simple,
    center: [500, 500],
    scale: function (zoom) {
        return Math.pow(2, zoom);
    },
    zoom: function (scale) {
        return Math.log(scale / 256) / Math.LN2;
    },
});
 
var bounds = [[0,0], [2000,2000]];
var image = L.imageOverlay('map.png', bounds).addTo(map);
// Spawn
var spawn = L.latLng([971.5, 1156.5]);
L.marker(spawn).addTo(map).bindTooltip('Spawn Station', {sticky: false, direction: 'top'});
// Maison de Jym
var jymHome = L.latLng([972, 1137]);
L.marker(jymHome).addTo(map).bindTooltip('Maison de Jym', {sticky: false, direction: 'top'});
 
map.setView( [971.5, 1156.5], 3);

C’est déjà pas mal. La définition de la map en crs permet de générer une map personnalisable, le niveau de zoom est correct, on peut naviguer pépère. Sauf que la carte, qui est grande, met pas mal de secondes à charger, c’est lourd, très lourd. Et ça, c’est un gros souci. Sans compter que la map devient floue à un certain niveau de zoom avancé. A revoir, donc !

Le tiling, solution miracle !

Et puis j’apprends que Leaflet intègre très bien des briques d’images. A la base, on peut sans souci utiliser un coup d’imagemagick pour ce faire et recoller les morceaux, chose que la bibliothèque fait très bien. Donc pile ce dont j’ai besoin !

Pour créer les briques, il y a un script existant qui gère Leaflet. Il est en Python et s’appelle gdal2tiles-leaflet. Ne pas oublier avant de faire un petit sudo apt install python-gdal (pour les utilisateurs d’Ubuntu) et éventuellement installer python si ce n’est déjà fait, juste avant de l’utiliser.

Voici la commande que j’ai lancée :
./gdal2tiles.py -l -p raster -z 0-10 -w none ../map.png ../tiles
Et j’ai attendu quelques bonnes minutes pour que toutes les briques soient générées. C’est un peu long mais ça vaut le coup. Ne pas oublier l’option -p raster car on en aura besoin par la suite, et surtout l’option -l qui définit spécialement des briques adaptées pour leaflet. J’ai demandé un niveau de zoom variable de 0 à 10, pour bien pouvoir avoir chaque détail de ma carte.

Gérer le tiling dans Leaflet

Maintenant qu’on a généré les briques, il faut pouvoir les assembler. Là encore, après pas mal de recherches, j’ai pu trouver de quoi satisfaire ma faim.

Bien avant, il faut intégrer la librairie rastercoords, pour pouvoir faire la correspondance des briques au format « raster » (l’option que nous avions vu plus haut). Et ainsi, avec ce code, vous pouvez déjà disposer d’une map sympa :

;(function (window) {
    function init (mapid) {
        var minZoom = 0
        var maxZoom = 9
        var img = [
            38192, // original width of image
            29792  // original height of image
       ]
    // create the map
    var map = L.map(mapid, {
       minZoom: minZoom,
       maxZoom: maxZoom
    })
 
    var rc = new L.RasterCoords(map, img)
    map.setView(rc.unproject([22000, 15450]), 9)
    L.control.layers({}, {
        //@todo
    }).addTo(map)
 
    L.tileLayer('./tiles/{z}/{x}/{y}.png', {
        noWrap: true,
        attribution: 'Creation Amelie DUVERNET aka Amelaye <a href="http://minetest.amelieonline.net">Projet Amelaye In Minerland</a>'
        }).addTo(map)
    }
 
    init('map')
}(window))

Des markers jolis et dynamiques

Nous avons la carte, il faut maintenant y ajouter les markers. Pour ce faire, vous avez besoin de :
– La librairie font-awesome (on en a besoin pour extra-markers)
– La librairie leaflet-extra-markers

J’ai crée deux fonctions, la première, layerGeo qui permet de récupérer les points définis dans mon fichier geojson.js

function layerGeo (map, rc) {
  var layerGeo = L.geoJson(window.geoInfo, {
    // correctly map the geojson coordinates on the image
    coordsToLatLng: function (coords) {
      return rc.unproject(coords)
    },
    // add a popup content to the marker
    onEachFeature: function (feature, layer) {
      if (feature.properties &amp;&amp; feature.properties.name) {
        layer.bindPopup(feature.properties.name)
      }
    },
    pointToLayer: function (feature, latlng) {
      return L.marker(latlng, {
        icon: feature.properties.id
      })
    }
  })
  map.addLayer(layerGeo)
  return layerGeo
}

Ainsi qu’une autre, qui permet de trouver les « frontières » de la carte, et également d’afficher les coordonnées d’un emplacement au hasard cliqué :

function layerBounds (map, rc, img) {
  // set marker at the image bound edges
  var layerBounds = L.layerGroup([
    L.marker(rc.unproject([0, 0])).bindPopup('[0,0]'),
    L.marker(rc.unproject(img)).bindPopup(JSON.stringify(img))
  ])
  map.addLayer(layerBounds)
 
  // set markers on click events in the map
  map.on('click', function (event) {
    // to obtain raster coordinates from the map use `project`
    var coord = rc.project(event.latlng)
    // to set a marker, ... in raster coordinates in the map use `unproject`
    var marker = L.marker(rc.unproject(coord)).addTo(layerBounds)
    marker.bindPopup('[' + Math.floor(coord.x) + ',' + Math.floor(coord.y) + ']').openPopup()
  })
  return layerBounds
}

Du coup, on revient sur notre code qui affiche la map et on corrige la ligne L.control.layers pour appeler nos fonctions :

L.control.layers({}, {
  'Bounds': layerBounds(map, rc, img),
  'Info': layerGeo(map, rc)
}).addTo(map)

Maintenant passons aux choses sérieuses, la définition de nos coordonnées. Et là, on va passer nos jolis markers, ainsi que les points qui nous intéressent, et tout ceci va se passer au niveau d’un nouveau fichier geojson.js :

;(function (window) {
    // Markers
    var spawnStation = L.ExtraMarkers.icon({
        icon: 'fa-anchor',
        markerColor: 'red',
        shape: 'star',
        prefix: 'fa'
    });
 
    var metroStation = L.ExtraMarkers.icon({
        icon: 'fa-subway',
        markerColor: 'blue',
        shape: 'circle',
        prefix: 'fa'
    });
 
    var castle = L.ExtraMarkers.icon({
        icon: 'fa-dungeon',
        markerColor: 'violet',
        shape: 'square',
        prefix: 'fa'
    });
 
    // etc ...
 
    // geoJson definitions
    window.geoInfo = [
        {
            'type': 'Feature',
            'properties': {
                'name': 'Spawn Station',
                'id': spawnStation
            },
            'geometry': {
                'type': 'Point',
                'coordinates': [22087, 15321]
            }
        },
        // Castles
        {
            'type': 'Feature',
            'properties': {
                'name': 'Chateau dans le ciel',
                'id': castle
            },
            'geometry': {
                'type': 'Point',
                'coordinates': [22088,14112]
            }
        },
        {
            'type': 'Feature',
            'properties': {
                'name': 'Chateau Royal',
                'id': castle
            },
            'geometry': {
                'type': 'Point',
                'coordinates': [22229,15299]
            }
        },
        {
            'type': 'Feature',
            'properties': {
                'name': 'Chateau Amelaye',
                'id': castle
            },
            'geometry': {
                'type': 'Point',
                'coordinates': [22060,15402]
            }
        }, // etc ...
    ]
}(window))

Là, j’ai pas mal galéré car il faut injecter les markers personnalisés dans un fichier qui doit être scrupuleusement rigoureux, car geojson est une norme. J’ai donc passé les variables qui correspondent à la définition des « templates de markers » dans la propriété id. C’est caduque, bricolé, mais ça marche.

Et voilà le résultat (disponible en ligne) :

Nous voici maintenant avec une map rapide à charger, qui intègre pas mal de points personnalisables. Il reste pas mal de choses à faire, j’ai bien envie d’utiliser une base de données pour créer une API, voire une base ElasticSearch qui se chargera de générer le fichier geojson, mais pour l’instant je n’ai pas décidé de la suite. Qu’en pensez-vous ?

Voici pour plus de détails le rendu final sur mon Github.

Ma recette anti-déprime (et booster d’immunité)

Voilà, mercredi, le couperet est tombé. Je voulais pourtant remonter cette pente dans laquelle je m’étais engluée depuis mars dernier. Certains le savent, comme beaucoup j’ai pris cher à l’annonce du premier confinement. Je n’avais, pour couronner le tout, pas passé une super année 2019, ponctuée de drames personnels, deux deuils, c’est pas mal comme mauvais combo. je m’étais dit qu’en 2020, j’allais sortir, voir d’autres gens, me changer les idées, au lieu d’être la geek qui aligne les lignes de PHP, même si ça m’a permis de m’aider dans la démarche des étapes du deuil. Bref, je ne vais pas m’étaler là-dessus, je ne suis pas là pour jouer les victimes.

Avec le recul, j’ai vécu le premier confinement comme un stress post-traumatique, et ça a été même un le réveil d’un autre traumatisme. En effet, ce n’était pas le premier confinement que je subissais. Le premier je l’ai subi à 19 ans, l’après-midi du 21 septembre 2001. J’habitais à Toulouse. Et croyez-moi, là, j’avais vraiment peur car sortir représentait un vrai danger à cause des émanations chimiques. Et près de 20 ans après, subsiste toujours l’angoisse de penser qu’un cancer lié à tout ça puisse se développer un jour où l’autre. Mais vous savez quoi ? J’étais contente de pouvoir être confinée … cela voulait dire que j’avais toujours mon studio d’étudiante. D’autres n’ont pas eu cette chance.

Lors du premier confinement, je ne suis sortie que pour les premières nécessité, courses, vétérinaire (car le Maître de la maison nécessite des soins réguliers à cause d’un souci de santé important), et achat de pièces informatiques chez une technicienne indépendante. Étant auto-entrepreneure, avoir un matos informatique de qualité est primordial, et le mien commençait à dater. Il fallait s’en occuper. Mais je ne faisais que bosser et jouer à Minetest en fait, les fesses collées à ma chaise. Je n’avais envie de rien, plus possible de faire du sport en salle, d’aller courir en bord de mer, de faire de la rando, d’aller à la piscine, et surtout … PLUS D’URBEX. Je n’avais pas le cœur à faire trois gainages sur le sol de l’appartement. J’ai commencé à déprimer. Et ça a duré à cause des mesures sanitaires : forçage du gel hydro-alcoolique alors que je fais de l’urticaire aux mains (alors que je me les lave régulièrement à l’eau et au savon), port du masque alors que je fais des attaques de panique (Fort heureusement, le médecin a pu me faire une dérogation à ce sujet).

En septembre, ayant conscience que j’avais repris des poignées d’amour, j’ai recommencé à faire du sport, à me réinscrire à la piscine, reprendre les cours de guitare. Un retour progressif à ma vie d’avant, en somme, mais ma joie fut de courte durée. Fermeture des salles de sport, puis couvre-feu, puis re-confinement. PAN ! A vrai dire je me suis demandée si je n’allais tout simplement pas basculer dans la folie. Quitte à vivre dans un monde de fous, allons-y gaiement ! Non mais en plus, j’avais commencé une thérapie régulière chez ma kinésiologue, sans rire !!!

Mais là, j’ai dit NON. J’ai appris à dépasser ceci en fin de compte. J’ai déjà eu des coups durs, des bons punchs dans la tête, et là, un coin de mon cerveau a refusé l’enlisement. J’ai cherché des idées pour changer mon énergie. Jeudi dernier, j’ai passé la journée devant mes fourneaux : mélanger des ingrédients, concevoir des bons petits plats en faisant preuve de patience me canalise. Le lendemain, j’ai chaussé mes baskets et je suis allée courir autour de chez moi. Et j’ai décidé de mettre en place un protocole.

  • Ne pas se lever après 8h30. Je ne dois pas perdre une matinée à paresser, hop on règle son réveil !
  • Avant le petit-déjeuner, prendre :
    – un jus de citron pressé (immunité, boost et alcalinisation de l’organisme) dans de l’eau tiède
    – gelée royale (aide l’immunité, indispensable en ces temps actuels)
    – magnésium bisglycinate (le magnésium marin, tu oublies, il n’y a pas de magnésium dans la mer)
    zinc
    safran (anti-dépresseur naturel, aide l’immunité)
    rhodiola
    – 5 gouttes de Fleurs de Bach : cherry plum
  • Activité physique régulière, aide l’immunité, donne une belle silhouette et c’est bon aussi pour la santé mentale : « un esprit sain dans un corps sain », dit-on bien.
  • Méditation pleine conscience le matin (personnellement j’utilise « Petit Bambou« ) après le petit déjeuner, avant d’attaquer le travail, pour l’ancrage, suivie d’un mantra que ma kinésiologue a écrit pour moi.
  • Et bien sûr, alimentation équilibrée, riche en fibres. Pour ma part, je cuisine beaucoup, avec des produits frais non-transformés (fruits et légumes de saison et locaux, viande du boucher, poisson du marché), ou du moins qui le sont au minimum. J’évite les sucres, les gâteaux, je mange des pâtes assez rarement.
  • Étant d’une nature spirituelle, je termine mon ménage en passant l’appartement à la sauge, mais il faut aimer l’odeur. J’utilise souvent des bâtons d’encens aux vertus apaisantes.
  • Faire des choses qui me plaisent : mes morceaux préférés à la guitare, réviser ma liste de mots en allemand ou écoute de chansons en allemand et les chanter à tue-tête pour améliorer ma prononciation (coucou les voisins), faire mon plat préféré ou inventer de nouvelles recettes, faire des câlins au chat

Parce que si les média nous inondent à coups de masques et de gels, ils ne nous disent pas qu’une alimentation équilibrée, de l’exercice physique et des compléments alimentaires naturels ralentissent eux aussi la propagation des virus. Hé oui …

Résultats des courses, au bout de quelques jours seulement, je retrouve progressivement une certaine sérénité, même si j’ai tendance à envisager des scénarios catastrophes. Je suis moins en colère, je me retrouve petit à petit. Et surtout la qualité de mon sommeil a bien changé, je ne me réveille plus au cours de la nuit, plus d’insomnies ni de cauchemars, un vrai repos …

J’ai encore des soucis de concentration à l’heure actuelle mais je ne suis qu’au début de mon protocole et je me dis à terme que ça va porter ses fruits sur ma dispersion mentale.

Du tutoiement sur les réseaux sociaux

Je vais être honnête : un truc m’agace. Le vouvoiement sur les réseaux sociaux. Cette phrase peut être absurde mais elle ne l’est pas tant que ça. Dans la vraie vie, nous Français, on aime bien, quand on ne se connaît pas, mettre cette distance verbale, quitte à fustiger son interlocuteur qui glisserait un « tu » indélicat. Personnellement, ça m’arrive. Idem pour les Allemands avec leur « Sie », les Espagnols avec « usted ». Bref.

J’ai eu cette idée de post en voyant une conversation tourner au combat de poissonniers sur un thread Facebook (pléonasme), qui concernait la critique d’une photo, avec cette fameuse phrase « ouais, déjà on ne se connaît pas je ne vous permets pas de me tutoyer ! « .

Mes premiers « surfs » sur la toile datent de fin novembre 1997, soit 8 ans après la création du Web, dans le CDI de mon lycée. A l’époque, seule une certaine « elite » pouvait créer du contenu dans la toile, il fallait savoir les bases du HTML et se débrouiller avec un logiciels FTP, donc une certaine intelligence. C’était le bon temps, tu pouvais même avoir Thierry Lhermitte en prof pour qu’il t’explique tout ça (dire que je me suis débarrassée de ce CD :'( , je suis dépit) :

Mais quelque chose m’a frappée. Dans cet univers virtuel, les créateurs et ceux qui postaient dans des forums faisaient un peu comme partie d’une communauté. Rappelez-vous qu’à l’époque (pour ceux qui étaient nés, c’est un temps que les moins de 20 ans etc …), Internet était le support du projet Autoroutes de l’information et finalement, cet internet était une ideosphère qui devait réunir le monde. Pourquoi s’embêter avec un « vous », franchement, puisqu’on est tous copains ? C’était le bon temps, où les insultes envoyées étaient bon enfant, et faisaient rire.

Voici d’ailleurs un extrait d’un texte intéressant que je vous invite à lire, et qui donne une idée dans quoi on baignait à cette époque, et c’était vraiment ça (inutile de préciser que je suis tombée de haut, naïveté adolescente oblige) :

[…] Ensuite ce discours a pris une deuxième direction, parallèle de la première, consistant à valo­riser sur un mode quasi religieux le nouveau monde d’Internet. La forme rhétorique, complémentaire de la disqualification, est celle du prosélytisme. L’idée selon laquelle le réseau Internet pourrait bien servir à réaliser concrètement les vieux rêves de « conscience planétaire » du « New age », l’idéal d’une « unification universelle des consciences » ou encore la montée vers la « noosphère » chère à Teilhard de Chardin (jésuite et philosophe, qui inventa dans les années quarante la notion de « noosphère » et plaida pour une « collectivisation des consciences » à l’échelle planétaire), est devenue très populaire dans certains milieux proches de la « Toile ».

https://journals.openedition.org/ress/604

Du coup j’ai balancé une référence de la Netiquette. La Netiquette peu de gens savent ce que c’est pourtant ça date de 1994, et c’est un « contrat » (inclus dans les RFC du web) ou plutôt une charte des bonnes attitudes à avoir sur le Net. Rien de très officiel mais ça a été longtemps une référence à l’époque où le Net comptait 200 millions d’utilisateurs, et que le cadre était assez mal légiféré. Il est stipulé dans la discussion :

L’usage, dans les forums, veut qu’on utilise le tutoiement, c’est une pratique courante, bien que non généralisée sur l’ensemble des forums.

Tutoyer un inconnu sur internet, n’est pas considéré comme malpoli (encore que ça dépende du contexte et de l’usage qui règne sur le forum en question), alors que tutoyer un inconnu dans la rue, est beaucoup plus délicat (sauf rapports d’âges « favorables »)

Quand j’ai commencé à utiliser internet, il y a un paquet d’années, les articles sur la netiquette prévenait que le tutoiement ne devait pas être mal pris, que c’était l’usage le plus répandu. L’article, sans doute traduit de l’anglais, du coup, ne le mentionne pas.

Il serait quand même intéressant de traiter ce sujet, afin que les gens ne connaissant pas la nétiquette, et peu familiarisé avec l’usage des discussions sur internet, ne se sentent pas intimidés. Il ne faut pas confondre tutoiement et manque de respect. Le vouvoiement peut aussi être irrespectueux quand il est utilisé pour établir une distance.

Le tutoiement n’est bien sûr pas une obligation de la nétiquette, mais il n’est pas un comportement grossier, comme certains pourraient le penser. Internet aboli pas mal de frontières, quand on ignore l’âge, le sexe, et le statut social de la personne avec qui on discute, à bâtons rompus. ça vaut quand même le coup de le mentionner!

Wikipedia

Un bel exemple de jolie page des années 90 avec le règlement de Usenet.

Bien sur, dans les années qui suivirent, dans des cadres « formels » comme des lettres de motivation, je vouvoyais mais je n’ai jamais abordé sur les réseaux et IRC en « vous ».

Voilà un peu pourquoi ça me fait de la peine. D’autant plus que beaucoup de gens s’insultent bien comme il faut, tout en gardant le vouvoiement. Style, je t’insulte et te manque de respect, mais je reste polie.e, tavu. Paradoxal tout ça.

Personnellement, je vais être dure mais je le ressens tel, je trouve que le vous sur internet, de par mon vécu (23 années sur la Toile), a un retentissement condescendant et hypocrite, surtout quand on le voit suivi d’injures. Après, il y a une génération excusables de Boomers (la génération de mes parents, nés après-guerre qui ont donc 60-70 ans) qui sont arrivés dans les années 2000 et qui ne connaissaient pas les us et coutumes et pensent que le vouvoiement est donc de mise. Et je pense que de débarquement de gens méconnaissant ces principes, et la centralisation du net, tuant les communautés de passionnés, qui est à l’origine de cet abandon du « tu » qui nous était cher, à nous, premiers arrivés.

Donc ne m’en veux pas si je te tutoie, internaute, même si tu me vouvoies auparavant, car ce sont mes règles, mes repères, et si tu es respectueux je le serai aussi 😉 . Je garde le vous pour mes prospects (et encore !), mes conversations sur LinkedIn (réseau professionnel oblige, donc formel) ou les organismes-suceurs.

Ces organismes-suceurs-là

J’ai passé un test de QI

Plus jeune, et encore maintenant, j’ai toujours eu ce sentiment un peu étrange d’être décalée, un peu extraterrestre. Une de mes anciennes camarades de classe me décrivait comme celle qui « était toujours penchée sur ses livres ». Mes souvenirs d’enfance sont majoritairement des moments de soif de connaissances, de promenade dans la nature pour étudier la botanique, découvrir la science. A trois ans, j’avais un jeu de cartes constituées de lettres en capitales que je savais très bien reproduire, je savais écrire mon nom et j’avais compris la numération jusqu’à 100. J’ai visiblement acquis très tôt le langage. Mais il ne m’était jamais venu à l’idée que je pouvais faire partie des « Hauts Potentiels ».

Ma scolarité s’est très bien passée, j’ai eu mon BAC mention bien et j’étais pratiquement toujours dans le peloton de tête, à part en seconde où j’étais en pleine crise d’ado, rébellion et tourments émotionnels constituaient mon quotidien, et la fac n’a pas été non plus une chouette période. Début de vie d’adulte, je me posais d’autres questions plus concrètes que je n’étalerais pas ici … J’ai également une certaine façon d’apprendre, très pratique, par l’exemple, qui n’est pas toujours en accointance avec la … pédagogie de la fac ? si toutefois on peut dire que la plupart des profs de fac sont pédagogues … bref, un autre souci que je ne développerai pas.

Je me suis donc souvent dévaluée, j’ai cru les mauvaises personnes, je faisais un complexe d’infériorité avec mon premier amour qui lui doit avoir un QI d’au moins 150 (large). Mais plusieurs fois, certains conseillers d’orientation, ou des collègues m’ont conseillé de passer ce test. Mais le vrai, encadré par un psychologue, pas celui qu’on trouve dans les magazines.

Je me suis longtemps cherchée, parcourant diverses théories, car j’ai un gros souci de gestion des émotions, jusqu’à aller loin, étais-je borderline ? asperger ? Jusqu’à ce jour de 2016 où une de mes ex m’emmène à une conférence qui parlait de ces fameux zèbres. Et là j’ai eu le déclic : cette pensée en arborescence, cette soif de connaissances, cette hyper sensibilité qui les caractérisent reflétaient ma propre vie ! Et si j’étais … surdouée ?

Un long chemin de prise de conscience

Le temps s’est écoulé jusqu’à ce que je me dise qu’il fallait vraiment que j’ai le cœur net. Trouver un.e psychologue habilité.e à faire passer les tests de QI est facile, Google est mon ami. J’ai pris rendez-vous en faisant d’une pierre deux coups : je voulais passer le test, le WAIS-IV, basé sur l’échelle de Wechsler, et poser également le diagnostic de l’hyper-sensibilité. Faire en bref un bilan cognitif qui dirait enfin qui je suis …

Le premier rendez-vous a été consacré à l’établissement de l’anamnèse : en gros elle a établi avec moi mon « mode d’emploi », et là elle n’a posé aucun doute sur mon hyper-sensibilité et mon hyper-émotivité.

Le deuxième rendez-vous a été consacré au test et a duré deux heures … alors autant vous prévenir : le test se passe en face à face, et il n’y a aucune fiche a remplir. Les test ont été très divers : des images à reconstituer avec des cubes-puzzles (très à l’aise), des suites de nombres à restituer de mémoire (dans l’ordre d’énonciation, ordre croissant, ordre décroissant …), suite de figures à terminer, éléments de dessins qui manquent, problèmes à résoudre mentalement, motifs à retrouver le plus vite possible, et mon talon d’Achille : les codes, mettre des signes correspondant à des chiffres. Petit à petit la fatigue me gagne force 10, je prends du sucre, bois de l’eau, c’est pas facile, et je termine l’épreuve les-si-vée. La psy trouve que je suis une bonne réfléchisseuse mais ne se prononce pas sur le verdict. Il faut qu’elle calcule tous mes scores.

Il n’y a pas que le QI dans la vie !

Troisième rendez-vous, verdict. Et la réponse est étonnante : mon QI est … invalide ! J’insiste … combien, combien ? J’ai un QI de 120, ce qui n’est pas si mal, et me pose dans l’étalonnage supérieur. Mais j’ai un gros déficit concernant la concentration : je réfléchis bien mais le traitement des informations me coûte énormément en énergie. Ça, je l’avais remarqué quand je passais mes leçons de conduite par exemple. Ou même dans la vie pro, quand je n’étais pas presta. J’ai besoin de longues poses, ce qui n’est pas bien vu quand on est dans une entreprise.

Courbe de Wechsler

Elle détaille les 4 zones de performances :
– la compréhension verbale (ICV) qui est à 131 (zone très supérieure)
– le raisonnement perceptif (IRP) qui est à 118
– la mémoire de travail (IMT) qui est à 109
– la vitesse de traitement (IVT) qui est à 94

Et là, la psy me parle de mon IAG, qui fait « assouplit » certains coefficients déficitaires, et me dit que c’est ce chiffre-là qui doit être pris en compte pour mon diagnostic.

Mon IAG est de 129, et il est se situe entre 123 et 133, au 97eme rang percentile. Elle ajoute donc, qu’au vu des résultats, et de mon fonctionnement cognitif, on peut me classer dans la catégorie des « hauts potentiels ». C’est de justesse, mais j’en suis.

Maintenant concrètement, ça donne quoi ?

Une bien belle machine au final … (vraie photo de moi avec des parties intimes dedans)

Hé bien je dirais que ça rassure, niveau identitaire, un peu comme quand j’ai compris et admis mon homosexualité … je sais que ça fait partie de moi. Maintenant que j’y réfléchis, mes meilleurs amis sont des gens qui « en ont », même si niveau amoureux, je me dévalorisais tellement que ça me rassurait d’être la plupart du temps avec des femmes « pas futées », mais je finissais par m’ennuyer avec elles. D’autant plus que même en se sachant pas malines, elle n’en n’étaient pas humbles, et pensaient avoir toujours raison (tacle personnel, pim). Je suis également rassurée, et sais que la machine marche plutôt bien. Mais je sais prévenir maintenant mes clients et quoi leur dire pour leur expliquer pourquoi je préfère le télétravail pour les missions de dev : je suis neuro-atypique et je sais comment je fonctionne, et comment je tire le meilleur de mes performances, et ça c’est cool 🙂

Création de mon Wiki Minetest !

Être sérieux tout en s’amusant, beau concept ! J’adhère !

Comme certains le savent déjà, je n’ai pas super bien vécu le confinement. Je pensais être une louve solitaire dans l’âme, pensant que son rêve le plus cher serait d’être débarquée sans retour sur une île déserte.
Ben non ! En fait. J’aime les gens.
Bref, durant cette période de confinement, il a bien fallu s’occuper. J’ai eu la chance de pouvoir continuer à travailler normalement, étant déjà autoentrepreneur à la maison, mais j’avoue que en dehors de ces heures, il a fallu m’occuper, si mes sides-projects sont prenants, il me fallait « sortir », et ça j’avoue que ça m’a bien manqué, surtout pour l’urbex. Alors je suis sortie d’une autre façon.

Il y a dix ans de ça, je découvrais Minecraft … de loin. Je l’ai associé malgré moi à une tête de nœud qui voulait jouer les petits chefs, et qui pendant les pauses de midi, passait son temps sur la plate-forme, tout en ingurgitant un répugnant « hachis parmentier » made in Carrefour ou Casino. Ecoeurée par l’odeur de ce truc infâme qui se voulait être de la nourriture, je regardais ce qu’il faisait du coin de l’œil, le traitant intérieurement de « bébé qui joue aux Lego ». Je me suis ensuite renseignée sur le projet, et j’avais même écrit un article assassin sur ce blog, espérant que mon ennemi allait tomber dessus et se sentir outrageusement blessé dans son égo trop développé.

Dix ans plus tard, je me rends compte que ce programme a toujours du succès et que bon nombre de geeks dans mon entourage jouaient au dérivé libre et gratuit de Minecraft (parce que racheté par Microsoft, c’est devenu diabolique) appelé Minetest. Je me suis dit alors que si ces gens, intelligents, aimaient ce jeu c’est qu’il devait y avoir une bonne raison. Oui je sais, j’ai tendance à mettre des cases « tout blanc tout noir ».

Des cookies ! Plein de cookies !!!

Je m’y suis mise en test, en mode survival, en mode créative, un peu touché à tout, construit une maison de fortune, et j’ai été surprise de tout ce qu’on pouvait faire. Puis j’ai un pote qui m’a dit « viens sur mon serveur, j’y joue avec mon fils, on est bien et des cookies t’attendent ! » … donc là j’ai commencé à construire des trucs plus sympas, un cottage en bord de mer, que j’ai relié à un « donjon », devenu base de crafting (fabrication). Puis ayant fini, j’ai crée un château, puis des champs cultivables, avec des éléments craftables pour créer des petits plats, une ferme avec des vaches et des moutons, etc …

Si c’est pas sympa, franchement ?
Domaine avec château, champs et ferme
Salut, toi !

Personnalisable à l’infini !

Laissant jouer mon pote en famille, j’ai récupéré les sources du monde qu’il avait crée pour l’installer sur mon serveur. J’ai réinstallé les mods pour qu’ils soient compatibles avec ma version, et j’ai commencé à installer d’autres mods sympas. J’avais en effet commencé à faire une sorte de station de métro à côté du château, avec les rails de base, et j’ai donc voulu tester le formidable AdvTrains pour qu’on croit vraiment, à ce métro. Et franchement, je me suis bien amusée à y mettre des wagons qui semblent bien inspirés du U-Bahn berlinois, qui roulent réellement ! Et je pourrai même à l’avenir les automatiser ! Oui, c’est exactement une version virtuelle du petit train électrique !

Prenez place …

C’est ainsi que j’ai commencé à créer un vrai petit village avec : église, mairie (j’ai même un cimetière où j’ai mis les prénoms de mes exs) … à travers différents mods : mod_church, homedecor, x-decor … pour ne citer que ceux-là. Parce que oui, on peut optimiser son jeu comme on le souhaite, soit en installant des mods existants, soit en les créant soi-même avec le langage LUA. Et là on commence à toucher le côté geek du jeu (cœur avec les doigts <3).

J’essaie pas mal de m’inspirer des tutos de Richard Jeffres, qui a l’air de bien s’amuser et qui fait vraiment des choses impressionnantes.

Une de mes dernières créations en date : garage privé et voitures de luxe

Comme dans mon rêve

Ce que certains mods apportent, ce sont des extensions aux biomes existants. Parce que oui, ton monde dans Minetest et juste immense et s’étale en 3 dimensions sur 60000 blocs pour la dernière version. Je pense que peu de joueurs ont déjà tenté de générer la map complète de leur univers. C’est ainsi qu’on traverse savanes, jungles, icebergs, déserts … Mais on peut y ajouter une touche bien fantaisiste.

Le mod Ethereal apporte de nouveaux biomes, ainsi que de nouveaux arbres et plantes … il y a également le mod Caverealms qui apporte aussi de nouveaux styles de caves. J’ai également installé Nether mais je ne le trouve pas aussi sympa que ça en a l’air. Il faudra voir à l’utilisation.

Oui, ce sont des champignons géants.
Je sais pas vous mais je trouve ça trop joli <3

Geek stuff

Bien sûr je ne compte pas m’arrêter là. Si je compte agrandir mon petit village en y ajoutant des restaurants et des boutiques, j’ai également très envie de faire des choses bien plus poussées qui font l’attrait de Minetest : créer des usines et automatiser le métro. Car avec le langage LUA, qui peut s’injecter dans les éléments du jeu, on comprend l’intérêt ludique de ce qu’on appelle Serious Gaming.

J’ai commencé à suivre quelques tutoriels justement pour commencer à comprendre comment tout cela fonctionne.

Un calculateur qui affiche le résultat en chiffres et en lettres (avec Mesecons et Digilines)

Du coup voilà, j’ai plein de projets et espère bien ramener des gens car je m’y sens un peu seule sur ce serveur. Donc j’ai commencé à créer un wiki et ferai à l’avenir quelques vidéos pour vous monter un peu ce mignon petit monde 😉

Et hop : http://minetest.amelieonline.net

Et sinon la moralité de cette histoire : quand on ne connaît pas, on ne juge pas 😉 ! A plus tard dans la Matrice 😉 !

Non, PHP n’est pas « OK boomer »

Il y a quelques jours je suis tombée sur cet article, réponse à un tout autre billet de blog que j’avais plutôt trouvé pertinent.

J’ai été à la fois dev et lead dev. J’ai pu me confronter à des problématiques de gestion d’équipe dans une structure où il y avait quelques soucis qui ne dépendaient pas de moi, et ça retraçait assez fidèlement ce qu’une boite doit faire pour garder une bonne équipe. Ce n’est pas uniquement une affaire de garder un dev, mais garder une vraie équipe soudée et productive dans la satisfaction. A mes yeux, une boite qui comprend ces points a un gage de qualité. Mais passons, ce n’est pas le sujet. Le sujet a été une seule phrase, tellement absurde que je n’ai pu m’empêcher de la twitter : « Twitter a démarré avec Ruby; Facebook avec PHP ; deux technologies bien pourries et so OK Boomer aujourd’hui. » (sic).

Déjà, ça manque d’argument, pourquoi « pourries », et puis ce « ok boomer » tellement dénué de sens …

Je n’ai pas d’affinité particulière avec Ruby, j’ai déjà bidouillé avec Ruby On Rails, que j’ai trouvé pas mal … mais sans plus.

Pour moi PHP représente tout la dynamique du web, et pour preuve, c’est le rare qui tienne encore debout et qui ait autant de popularité depuis 25 ans. Je ne parlerai pas de Go, qui a sa côte de popularité, mais tout frais, ou de Javascript qui a engendré NodeJS qui pour moi est plus une mode. Javascript n’a son intérêt qu’en front-end, à mes yeux.

Au commencement … il y avait … juste du script pour page HTML en fait …

Je me suis mise en premier à PHP car c’était à mes yeux celui qui allait pérenniser, j’ai eu comme une intuition qui me disait de foncer dedans. Car ce n’était pas gagné, au début des années 2000, les entreprises préféraient embaucher des développeurs ASP ou J2EE pour leur back-end et applications web. Fraîchement sortie des bancs de fac, je ne pouvais pas payer et investir pour apprendre ASP sur un serveur dédié, alors que PHP est disponible gratuitement.
Je passe cette discussion avec le « petit Gregory du Japon » (il se reconnaîtra) qui m’avait balancé en 2000 : « si tu fais un jour du PHP je me ferai nonne. Oui, tu as bien lu : NONNE ». Challenge accepted. J’attends toujours que tu mettes le voile, Greg.
Donc j’ai continué à me pencher sur le vilain petit canard, ce PHP qui pouvait « additionner des salades avec des macaronis ». Et il suffit de regarder du code legacy pour se rendre compte de ses faiblesses … le PHP 4 objet avec ses constructeurs spéciaux (car le langage n’avait pas au départ été conçu pour le modèle objet), il fallait parfois réinventer la roue pour faire des itérateurs, ses noms de fonctions natives à la one-again (on a str_​getcsv et puis après strchr, un coup underscore, un coup pas, logique les gars ?) et surtout son faible typage (toujours d’actualité mais en voie de progrès. Mais n’est-ce pas un bon point, aussi ?). Mais PHP était un langage facile à apprendre, et il l’est toujours : pour ceux qui veulent se faire la main en programmation, c’est un bon début.

Le souci de qualité

Pourtant 25 ans après, PHP est on ne peut plus présent, ASP ne fait plus parler de lui et J2EE se raréfie. Il est même devenu plus costaud qu’avant … son modèle objet se peaufine, le typage se fait de plus en plus strict, et puis les librairies évoluent de plus en plus notamment avec l’apparition de SPL, mais également des librairies. Vanilla PHP n’est plus trop d’actualité, on a vu apparaître PECL, PEAR, et aujourd’hui la star c’est Composer, qui permet d’installer à la volée bon nombre de bibliothèques, et d’analyseurs syntaxiques. Car le développeur PHP d’aujourd’hui est soucieux de la qualité de son code : il fait appel à des analyseurs (notamment PHP-Stan) et produit des tests unitaires et des tests fonctionnels (Behat …).

La puissance des frameworks et des design patterns

La force de PHP, après avoir proposé moult CMS tels que SPIP, Joomla … dans les années 2000, a résidé dans l’apparition des frameworks, qui ont solidifié les bases du langage pour permettre non seulement aux devs de coder plus proprement, mais également de pouvoir définir des architectures évoluées en fonction des design patterns (ce qui fait de plus en plus penser à une structure type JAVA) : Zend Framework, Symfony et Laravel en tête de liste. Des architectures qui évoluent et peuvent solliciter efficacement des API REST pour permettre une mobilité des données, segmenter le code en multi-repositories pour permettre une meilleure maintenabilité du code. Et par ce biais, a permis aux CMS d’évoluer, on pense à Drupal ou Prestashop qui ont intégré Symfony dans leur code.

PHP a également gagné en performance et scalabilité grâce à FPM, qui permet de pouvoir lancer plusieurs versions du serveur. Et by the way, Facebook utilise toujours PHP … en sous-marin mais toujours …

Toujours en évolution !

A ce jour, PHP 8 est en prévision, avec plein d’améliorations, notamment le Just In Time. Et j’avoue avoir bien reçu PHP 7.4, car je l’avais attendue longtemps depuis des années, cette feature : PHP 7.4 intègre les déclarations de type d’argument. Enfin on peut typer les propriétés d’une classe !!! Yes we can ! Yalla !

Aujourd’hui PHP est devenu plus qu’un simple outil de scriptage pour sites web :
– il permet de réaliser des scripts en ligne de commandes et tâches automatisées, et on peut même créer des exécutables !
– il permet de programmer de vraies applications web
– il permet efficacement de se connecter avec une base de données, de manière de plus en plus sécurisée via les requêtes préparées

Il est PARTOUT, et même Microsoft, qui avait lancé ASP, le soutient dans les séminaires. Les débutants peuvent facilement l’appréhender en manipulant progressivement leurs pages HTML, et en guise de cerise sur le gâteau, la communauté des développeurs PHP est LARGE, depuis toujours. Vous séchez ? Vous avez obligatoirement des forums, des sites, la doc officielle régulièrement mise à jour, des Slacks pour vous aiguiller. Et il reste open-source et gratuit !

Alors sérieusement, PHP, un langage pourri et OK Boomer ?

Devs : on a tous débuté …

Rappelez-vous : dans mon article « Fuck you Masterboy », je mentionnais ce fameux site où j’avais crée mes premières lignes en PHP. C’était vers 2002-2003. Et comme je le mentionne dans « Comment archiver sans trop pleurer », je suis en train de gratter dans mes sources pour déterrer mes vieux projets.

Et ça tombe bien, j’ai trouvé les sources de ce site, que je mets à dispo sur Github : amelaye/MasterboyForEver . Alors pourquoi je fais ceci car en fait, c’est assez difficile de le faire marcher, peut-être même impossible pour certains.

J’y suis à peu près arrivée avec de la patience …

Parce qu’il y a eu beaucoup de mes élèves, lors des cours que j’ai menés, qui ont pas mal culpabilisé. Entre autres une jeune femme remplie de détermination et de bonne volonté, mais également dotée d’une faible confiance en elle, que j’avais mentorée pour Openclassrooms. J’avais énormément apprécié cette mission, car elle avançait vite et elle voulait réussir son année, des qualités qu’on prof/mentor ne peut qu’admirer. Elle (ainsi que d’autres) tenait hélas parfois une petite moue, et un œil triste « mais non je fais de la m…, la preuve je peux pas être autonome, je pompe des scripts par ci par là, je comprends pas pourquoi ci pas pourquoi ça, toi tu sais le faire, je voudrais coder comme toi. » … Et là, en position de lotus dans ma toge blanche, je lui répondais systématiquement « de temps et de patience tu necessiteras … ». Car ses doutes étaient normaux, je les avais traversés. Du coup j’ai eu envie de raconter l’histoire de ce site et de son affreux code qui marchait quand même.

Pour contextualiser le projet, en fin 2002 j’étais en licence pro internet, sortant d’un BTS qui n’avait rien à voir, et n’ayant à mon actif que des sites full HTML et bidouillages JS. La programmation, je n’en avais aucune notion, et la pire des surprises que cette licence m’avait faite a été de commencer par l’apprentissage de …

… JAVA …
Oui. Ils ont fait ça.

Bon bref, inutile de dire que j’avais complètement décroché cette partie-là, et que ce qui avait sauvé mon année a été le HTML, les bases de données et la communication. Dans le lot il y avait du PHP, le langage que je voulais absolument apprendre, bien que découragée par les cours. Dans ce cas, il n’y a pas de secret, il me fallait trouver un projet qui puisse à la fois me motiver et me permettre d’utiliser et comprendre PHP. A l’époque je tenais un site sur Masterboy, qui marchait plutôt bien, car il était le seul site francophone qui parlait à ce point du groupe, du coup c’est ainsi j’ai voulu sortir de ma zone de confort.

J’ai commencé par prendre un script existant pour faire une « fan-zone » dans laquelle on pouvait s’inscrire et partager dans cet espace. Puis quand j’ai fait mon stage, j’ai voulu mettre un peu plus les mains dans le cambouis, mais tout en piochant par-ci par là des bouts de code que je trouvais sur le web (sérieusement il n’y a pas mieux pour comprendre). C’est vraiment du taf de débutant, on y remarque entre autres :

  1. Les shorts tags. Bon à l’époque ça se faisait pas mal d’utiliser les shorts tags, je me souviens qu’en licence on ne nous avait pas déconseillé de les utiliser.
  2. Les multiples appels aux scripts de connexion. Au cas où le premier ne marchait pas, les autres peuvent mieux marcher, pensais-je.
  3. Douce époque où les requêtes n’étaient pas préparées. A cette époque je pensais aussi qu’il fallait faire des mysql_num_rows() après chaque requête même si on n’en avait pas besoin. On ne sait jamais qui peut le plus peut le moins, nesspa. D’ailleurs sur admin/liste.php la requête y est deux fois … on ne sait jamais, je vous dis.
  4. Ne me parlez pas de la programmation objet, je n’ai rien compris à ça.
  5. C’était bien de récupérer les variables en get du genre « num= » en $num, register_globals c’était la belle vie … puis PHP5 est arrivé et ça a changé.
  6. Gros embrouillamini sur mboy.php mais comme ça marchait, je ne me suis pas soucié de ça (j’ai hélas été longtemps adepte du « tant que ça marche casse pas les noix de coco. » à mes dépens …).
  7. Le camelCase ? Nan connais pas …
  8. L’indentation ? Mais ça marche, donc casse pas les noix de coco.
  9. Ha les die() avec des erreurs bien explicites … et puis la profusion de @ devant les fonctions au cas où il y aurait un bug mais chut …

ET SURTOUT : Je bidouillais parfois direct « en prod », surtout les bases de données. Et donc un jour, en voulant exécuter le script qui effaçait un post, bien ça m’a … TOUT effacé 🙂 j’étais sans filet, je n’avais aucun utilitaire pour sauvegarder mes bases (en même temps je ne maîtrisais à l’époque pas du tout Linux donc j’étais en mutualisé), et je n’avais même pas pensé à l’utilité d’un dump avant toute manipulation #lalose … ce qui explique le joli message en rouge sur la page d’accueil 😀 … voilà voilà …

Donc voilà ce que j’avais pondu à l’époque. Mais je m’auto-pardonne, parce que je sais que je devais commencer et on fait tous des choses moches quand on commence. Du coup comment puis-je flageller mes élèves qui sont de bonne volonté mais culpabilisent de leur rendu ?

Rendez-vous dans 10 ans pour que je voie votre super-code, les amis 😉