Aller au contenu

tilttek/leaderboards

✅ publié

Des membres classés selon ce qu'ils font, par période, et personne n'est montré aux autres sans l'avoir choisi.

tilttek/leaderboards classe des membres selon une mesure pendant une période : les parties jouées ce mois-ci, les points gagnés cette semaine, le meilleur score d'une seule partie, les jours d'activité, un niveau ou la plus longue série. Quatre mesures se tirent de l'activité des membres, enregistrée par tilttek/activity : les gestes comptés, leurs quantités additionnées, la meilleure quantité d'un seul geste, les jours distincts où il y a un geste. Deux mesures prennent une valeur que l'application rapporte à partir d'un solde qu'elle garde ailleurs : la dernière valeur, ou la plus haute. Un classement porte sur un jour, une semaine ISO, un mois, un trimestre, une année, des saisons nommées, depuis toujours ou une fenêtre glissante de ses derniers jours, chacun dans le fuseau horaire qu'il déclare. Les scores sont tenus à jour à mesure que l'activité est enregistrée, et non recomptés à chaque affichage ; une annulation reprend sa contribution, et un classement modifié est rejoué à partir du journal. Les scores égaux sont départagés par au plus deux critères de départage (le moins de tentatives, le temps le plus court), puis reviennent au premier qui les a atteints, ou partagent un rang. Un classement se fait entre amis ou à l'intérieur d'un groupe, par un cercle de membres que donne l'application, et peut classer les membres pour chaque objet : chaque jeu, chaque livre. Un instantané fige les premiers membres à la fin d'une période, une seule fois, pour montrer le classement final et les récompenser. Un classement hebdomadaire peut avoir une ligue : ses membres sont répartis en divisions d'une trentaine, par paliers, formées selon leur ordre d'arrivée ou selon leur volume de la semaine précédente ; chacun ne voit que sa division, et à la fin de la semaine les premiers montent d'un palier et les derniers descendent. Un classement peut donner un titre à partir d'un seuil, et classer des équipes avec une part de chance que l'application active. Personne n'est classé publiquement sans l'avoir choisi : un membre qui n'a pas choisi de paraître voit son propre rang, et les autres voient une ligne sans nom ; un membre peut paraître sous son nom ou sous un pseudonyme. Effacer un membre retire ses scores, ses lignes dans les instantanés et son choix.

Elle s'adresse à une application qui veut que ses membres comparent ce qu'ils font (un site communautaire, un site de jeu, une plateforme de lecture ou d'écriture) et qui ne doit pas exposer un membre qui ne l'a pas demandé. tilttek/leaderboards-bundle l'intègre à Symfony et garde les classements dans Doctrine DBAL, les scores dans Valkey quand il est activé ; une application sans Symfony prend la bibliothèque seule, avec les stockages en mémoire, les scores dans Valkey par le client qu'elle a, ou ses propres stockages.

C'est une simple bibliothèque PHP. Ses dépendances sont tilttek/activity, le journal que lisent les classements, phil/resource, la référence opaque d'un membre, et psr/clock. Les membres sont des références que donne l'application, member:44 : la bibliothèque ne lit jamais un nom, un courriel ou un compte, et c'est à l'application de donner le nom qu'affiche une ligne publique.

La conception est sobre : un Board contient sa Measure, son Schedule de Period, ses verbes et ses conditions, son Ranking de TieBreak et de Ties, et ses options. LeaderboardProjection lit le journal et écrit des Contribution et des Score dans un ScoreStore. Leaderboards lit un Standing tel qu'un spectateur le voit (des Row selon l'Appearance de chaque membre), prend les valeurs que rapporte l'application, prend des Snapshot, et exporte et efface un membre. Leagues place les membres dans les divisions de la League d'un classement et règle ses semaines.

État

PartieÉtat
Board, Boards, Measure, Ties : des classements sur six mesures, à partir d'une configurationImplémentés et testés
TieBreak, Aggregate, Direction, Ranking : jusqu'à deux critères de départage, puis le premier à atteindre un score ou un rang partagéImplémentés et testés
Period, PeriodKind, Schedule : jours, semaines ISO, mois, trimestres, années, saisons, depuis toujours et fenêtres glissantes, dans un fuseau horaireImplémentés et testés
LeaderboardProjection : scores tenus à jour à partir du journal, annulations, reconstructions et fenêtres glissantesImplémentée et testée
Leaderboards : classements, rangs, cercles, classements par objet, valeurs rapportées, apparences, instantanés, exportation et effacementImplémenté et testé
Title, Team, TeamRow, Chance : titres à partir d'un seuil ; équipes classées, avec la chance qu'un classement activeImplémentés et testés
ValkeyScoreStore, ValkeyConnection, RawCommandConnection : les scores dans les ensembles triés de ValkeyImplémentés et testés
Appearance, Visibility, Row, Standing : caché par défaut, par nom ou par pseudonymeImplémentés et testés
Snapshot, Placing, LeaderboardObserver : le classement final d'une période, annoncé une foisImplémentés et testés
League, Leagues, Division, Settlement, Formation : divisions hebdomadaires par paliers, formées par arrivée ou par volume, promotion et relégationImplémentés et testés
Quatre stockages et leurs implémentations en mémoire, avec les contrats que tout stockage respecteImplémentés et testés
Exceptions sous une seule interface LeaderboardsExceptionImplémentées et testées

Documentation

DocumentCe qu'il couvre
InstallationPrérequis et installation.
Classements et périodesMesures, verbes, conditions, périodes, fuseaux horaires, saisons, fenêtres glissantes, égalités et critères de départage, classements par objet et configuration des classements.
Scores et projectionComment le journal est lu, les annulations, les reconstructions, et les valeurs que rapporte l'application.
Classements affichésUn classement tel qu'un spectateur le voit, les égalités, la ligne du spectateur et les cercles.
Paraître dans un classementCaché par défaut, par nom ou par pseudonyme, et ce que voit chaque spectateur.
InstantanésFiger une période, récompenser les premiers et montrer le classement final.
LiguesDivisions hebdomadaires par paliers, entrée dans une division, divisions formées par volume, promotion et relégation à la fin de la semaine.
Équipes et titresTitres détenus à partir d'un seuil, équipes classées et chance qu'un classement ajoute à leurs scores.
EffacementCe que contient l'exportation d'un membre et ce que retire son effacement.
Écrire un stockageLes quatre contrats de stockage qu'implémente le support d'une application, et les scores dans Valkey.
Points d'extensionCe qu'une application donne à la bibliothèque : stockages, observateurs, horloge.
ExceptionsLeaderboardsException et ses exceptions, avec leurs messages.
TestsLes tests de la bibliothèque et son seuil de mutation, et comment tester du code qui lit les classements.
RéférenceChaque type de la bibliothèque, avec son rôle.

Démarrage rapide

use Tilttek\Leaderboards\{Appearance, Boards, LeaderboardProjection, Leaderboards};
use Tilttek\Leaderboards\Store\{InMemoryAppearanceStore, InMemoryScoreStore, InMemorySnapshotStore};

$boards = Boards::fromArray([
    'games-month' => ['measure' => 'count', 'verbs' => ['game.played'], 'period' => 'month'],
    'level' => ['measure' => 'latest'],
], 'America/Toronto');
$scores = new InMemoryScoreStore();
$projection = new LeaderboardProjection($boards, $scores); // handed to the journal's projections
$leaderboards = new Leaderboards($boards, $scores, new InMemorySnapshotStore(), new InMemoryAppearanceStore(), $clock);

$leaderboards->appear($member, Appearance::pseudonym('Le Nain Gris'));
$standing = $leaderboards->standing('games-month', viewer: $member);

Prérequis

PHP 8.5 ou plus récent.

Contribuer

Les contributions sont les bienvenues sur le monodépôt de PHIL : lisez le guide de contribution et le code de conduite. Signalez une vulnérabilité en privé, comme l'explique la politique de sécurité, jamais dans un ticket public.

Licence

MIT, © Philippe Gamache, doing business as Le Gnome Archiviste; a Tilttek project. Voir LICENSE.