Skip to content

tilttek/collections

✅ published

Items to collect — cards, dice, figurines, costumes —, their rarity and sets, the item of the day and packs whose odds are published.

tilttek/collections keeps what the members of a site collect. A catalog declares rarities — common, rare, legendary — with their weights, items with a translated name and description, an image, a rarity and the sets they belong to, sets worth their declared rewards once a member owns every item of them, and packs. A member's copies come under a key that makes each one count once: the base sets on arrival, a set earned for points or bought whole, a reward, a gift, the item of the day — one item a day, from a calendar computed of fixed dates, dates of the application's own rules and a draw weighted by rarity on the free days, given on the members' activity recorded by tilttek/activity —, or a pack, several items drawn by rarity with published odds, from a seed committed by the site and a client seed given by the member, which let anyone replay the draw. Doubles are counted, the album shows 12 of 20, a set completed for the first time is told with its rewards, a member chooses which of their dice the dice roller shows, copies move between members for a trade, and erasing a member removes what the collections kept of them.

It is for a site that gives its members something to collect — a community site's mascots in costume, virtual trading cards, the dice of a set. tilttek/collections-bundle integrates it with Symfony and keeps everything in Doctrine DBAL; an application without Symfony takes the library alone and writes its own stores, or uses those in memory.

It is a plain PHP library whose dependencies are tilttek/activity, the journal the item of the day is claimed on, phil/resource, the opaque reference of a member, psr/clock, and the mbstring and sodium extensions. Members are references the application gives, member:44: the library never reads a name, an e-mail or an account. It depends on no other gamification package: rewards are declared and the application gives them, and tilttek/exchange reaches the copies through the inventory the bundle provides.

The design is small: a Catalog holds Rarity, Item, ItemSet and Pack definitions, read by CatalogReader from plain values and provided by a CatalogProvider; Collections gives Copy objects under a CollectionKey, moves them, takes them back and builds the Album; Packs commits a Pack into a PendingOpening, then opens it into a PackOpening from the Odds; DailyCalendar, Daily and DailyProjection give the item of the day; DiceShelf keeps the dice a member chose; MemberData exports and erases a member.

Status

PartState
Names, Texts, Rarity, CollectibleDie, Reward, Item, SetKind, ItemSet, Pack: the definitions, translated, checkedImplemented and tested
Catalog, CatalogReader, CatalogProvider, FixedCatalog, WritableCatalog, DefinitionKind, Odds: the catalog from plain values, its references checked, the odds of a draw and the drawImplemented and tested
CollectionKey, Source, Copy, CopyMove, Collections: copies given once per key, sets given whole, base sets on arrival, moves of a trade, copies taken backImplemented and tested
Album, Holding, SetProgress, SetCompletion, SetCompleted, CollectionObserver: the album, doubles, progress and sets completed once with their rewardsImplemented and tested
Pack\Packs, Pack\PendingOpening, Pack\PackOpening, Pack\SeedSource, Pack\SecureSeeds: packs committed, then opened from the site's seed and the member's client seed, published odds and verificationImplemented and tested
Daily\DailyCalendar, Daily\DateRule, Daily\FixedDate, Daily\DailyPick, Daily\PickOrigin, Daily\Days: the computed calendar of the item of the day, generated and correctedImplemented and tested
Daily\Daily, Daily\DailyProjection: the item of the day claimed once per member and day on the activity, cancellations and rebuildsImplemented and tested
Dice\DiceShelf, Dice\DieChoice: the dice a member owns and the one they roll for each number of sidesImplemented and tested
The five stores with their in-memory implementations and the contracts any store passesImplemented and tested
MemberData, Erasure: the export and erasure of a memberImplemented and tested
Exceptions under one CollectionsException interfaceImplemented and tested

Documentation

DocumentWhat it covers
InstallationRequirements and installing.
The catalogRarities, items, sets, packs, the definition a configuration holds, and a catalog kept in a database.
Copies and the albumKeys, sources, bound copies, sets given whole, base sets, the album, doubles, sets completed and their rewards, moves and copies taken back.
The item of the dayThe computed calendar, its rules and its draw, generating and correcting it, claiming the item, the projection.
PacksPublished odds, opening a pack, seeds, commitments and verification.
DiceThe dice of a set, the die a member chooses, and the dice roller.
ErasureWhat exporting and erasing a member covers.
Writing a storeThe five store contracts an application's storage implements.
Extension pointsWhat an application gives the library: the catalog, stores, date rules, seeds, observers, the clock.
ExceptionsCollectionsException and its exceptions, with their messages.
TestingThe library's tests and mutation bar, and how to test code that reads the collections.
ReferenceEvery type of the library, with its role.

Quick start

composer require tilttek/collections
use Tilttek\Collections\Collections;
use Tilttek\Collections\FixedCatalog;
use Tilttek\Collections\Source;
use Tilttek\Collections\Store\InMemoryCompletionStore;
use Tilttek\Collections\Store\InMemoryCopyStore;

$catalog = FixedCatalog::fromArray([
    'rarities' => ['common' => 70, 'rare' => 25, 'legendary' => 5],
    'items' => [
        'deckhand' => ['name' => ['en' => 'Deckhand', 'fr' => 'Matelot'], 'rarity' => 'common', 'sets' => ['crew']],
        'captain' => ['name' => 'Captain', 'rarity' => 'legendary', 'sets' => ['crew']],
    ],
    'sets' => ['crew' => ['name' => 'The crew', 'rewards' => [['kind' => 'points', 'code' => 'xp', 'amount' => 50]]]],
]);
$collections = new Collections($catalog, new InMemoryCopyStore(), new InMemoryCompletionStore(), $clock);

$collections->grant($member, 'deckhand', Source::Purchase, 'order:2026-0193:line:1');
$collections->album($member)->set('crew')?->total(); // 2

Requirements

PHP 8.5 or later, with the mbstring and sodium extensions.

Contributing

Contributions are welcome on the PHIL monorepo: read the contribution guide and the code of conduct. Report a vulnerability privately, as the security policy explains, never in a public issue.

License

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