tilttek / seasonal-events
Seasons and their events for gamification: a season once or each year by an RFC 5545 rule in its timezone, the quests, items and decorations it brings while it lasts, multipliers of gains only on events announced ahead, a port to read what is on, and bridges to tilttek/quests and tilttek/collections
Requires
- php: >=8.5
- phil/recurrence: ^0.1@dev
- phil/resource: ^0.1@dev
- psr/clock: ^1.0
Requires (Dev)
- phpunit/phpunit: ^13.4
- symfony/clock: ^8.2
- tilttek/collections: ^0.1@dev
- tilttek/quests: ^0.1@dev
Suggests
- tilttek/collections: To list the items of a collections catalog the seasons bring, with Bridge\Collections\SeasonalItems
- tilttek/quests: To open a quest with a season or one of its events, with Bridge\Quests\SeasonQuestSchedule
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-13 22:47:54 UTC
README
Seasons and their events: the quests, items and decorations of a period, in the site's timezone, coming back each year.
tilttek/seasonal-events keeps the seasons of a site — a winter festival, a spooky season, a harvest feast — and the events inside them. A season comes once, between two dates, or each year for a number of days from a date an RFC 5545 yearly rule gives: the 15th of December, the fourth Thursday of November. Its days are counted in its timezone, from midnight on the wall clock, across changes of time. A season brings quests, items and decorations while it lasts; an event inside it adds its own for some of its days, and may multiply the gains of a ledger — only when it is announced at least a day ahead, so that nothing multiplies by surprise and the highest multiplier applies when events meet. Each time a season comes has a code, the date of its first day, so that what a member earns in it is told apart from the next year.
The other packages read what is on through one port, ActiveContent: the quests open now, the items offered, the
decorations shown, the multiplier of a ledger. They never read the seasons themselves, and the library depends on none
of them: optional bridges open a tilttek/quests quest with a season and list the tilttek/collections items it
brings, when those packages are installed.
It is for a community or a game that wants seasonal content without hand-switching it on and off: the seasons are declared ahead, in code, a configuration or a database, and answer for any moment. There is no season pass to buy and no item that never comes back: a season that comes each year brings its items again.
It is a plain PHP library whose dependencies are phil/recurrence, which reads the yearly rules, phil/resource, the
references of quests, items and decorations, and psr/clock. It keeps no state between two questions.
Status
| Part | State |
|---|---|
SeasonSchedule: once, or each year by an RFC 5545 yearly rule, in a timezone, up to 183 days |
Implemented and tested |
Season, SeasonalEvent, Content, ContentKind, Multiplier: what a season and its events bring |
Implemented and tested |
SeasonalEvents, Snapshot, ActiveSeason, ActiveEvent, Period: what is on at a moment, and what is announced |
Implemented and tested |
ActiveContent: the port other packages read |
Implemented and tested |
SeasonCatalogue, InMemorySeasonCatalogue, SeasonReader: seasons from code or plain arrays, and back |
Implemented and tested |
Bridges to tilttek/quests and tilttek/collections |
Implemented and tested |
Exceptions under one SeasonalEventsException interface |
Implemented and tested |
Documentation
| Document | What it covers |
|---|---|
| Installation | Requirements, installing and wiring the library. |
| Seasons and events | Schedules, timezones, recurrence, contents, events, announcements and multipliers. |
| What is on | The questions of a moment, the snapshot, the announced events and the port ActiveContent. |
| Definitions | Seasons written as plain arrays — a configuration, JSON or YAML — read and written back. |
| Bridges | Quests, collections, and an advent calendar during a season. |
| Extension points | What an application gives the library: the catalogue, the clock. |
| Testing | The library's tests, fuzzing and benchmarks, and how to test code that reads the seasons. |
| Reference | Every type of the library, with its role. |
Quick start
composer require tilttek/seasonal-events
use Symfony\Component\Clock\Clock; use Tilttek\SeasonalEvents\{Content, Multiplier, Season, SeasonalEvent, SeasonalEvents, SeasonSchedule}; use Tilttek\SeasonalEvents\Store\InMemorySeasonCatalogue; $winter = new Season( 'winter-festival', SeasonSchedule::yearly('America/Toronto', '2026-12-15', 23), [Content::quest('quest:winter-hunt'), Content::decoration('decoration:snowflakes')], [new SeasonalEvent('gift-week', fromDay: 8, days: 7, contents: [Content::item('item:wrapped-die')], multiplier: new Multiplier('points', 200), announceDays: 7)], ); $seasons = new SeasonalEvents(new InMemorySeasonCatalogue([$winter]), new Clock()); $seasons->at()->decorations(); // [decoration:snowflakes] while the festival is on $seasons->multiplier('points')?->apply(10); // 20 during the gift week
Requirements
PHP 8.5 or later.
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.