Search by

ernestdefoe / fantasy

ernestdefoe

A season-long fantasy league where members draft TEAMS rather than players. Snake draft, weekly lineups that lock at each team's own kickoff, head-to-head matchups, and a scoring system the commissioner sets. Plays whatever competition the Picks season is, and starts each league from that sport's ow

Package info

github.com/ernestdefoe/fantasy

Type:flarum-extension

pkg:composer/ernestdefoe/fantasy

Fund package maintenance!

Buy Me A Coffee

Statistics

Installs: 13

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.1.1 2026-10-24 14:37 UTC

This package is auto-updated.

Last update: 2026-10-24 15:09:25 UTC


README

A season-long fantasy league for Flarum 2, where members draft teams rather than players.

A fantasy league: the standings, each franchise's roster as crests, and the scoring rules

Every result is read from the fixtures and scores Picks already syncs, so nothing here needs a second data source or a second API key.

composer require ernestdefoe/fantasy
php flarum migrate
php flarum cache:clear

fantasy:score runs hourly on Flarum's scheduler.

How a league runs

  1. Members join. While a league is taking members, its page has a Take a franchise button; a member names their franchise (or leaves it as "Mara's team").
  2. The commissioner starts the draft. The order is shuffled and the league stops taking members.
  3. The draft room shows who is on the clock, the order, every pick so far, and the teams still available, with search. It's a snake draft: the last pick of a round picks first in the next. Only the franchise on the clock can pick, or the commissioner on its behalf, so the draft never stalls on someone who wandered off. The room refreshes itself every few seconds, and not while the tab is hidden.
  4. Lineups. Once every roster is full the league goes live. Each week an owner switches teams in and out of their lineup, up to the league's number of starters. A team locks when its game kicks off. An owner who changes nothing plays last week's lineup, so a missed week isn't a lost one.

A game that kicked off before the draft finished never scores: it's a result the owner already knew when they drafted the team.

It plays whatever sport its season is

A league plays a Picks season, and a season belongs to a competition — so a league plays college football, the NFL, the NBA, MLB, the NHL or league football, whichever its season is.

Two things follow, and they are the whole of it:

A draft only offers teams that actually play in the season. picks_teams holds six sports' teams, so "a team exists" is not the same question as "a team is in this competition" — without the scope a college-football draft board offers the Milwaukee Bucks, and the franchise that took one is a starter short for the rest of the year with nothing on screen saying why. It is asked of the fixtures, which is stricter than a label: a club with no games this season is not draftable however it is filed.

A league starts from its own sport's numbers. The rules travel between sports; the numbers do not.

Sport A game Per point Win Shutout
Gridiron ~31–17 1.00 10 8
Basketball ~112–104 0.25 10 —
Baseball ~5–3 4.00 10 12
Ice hockey ~3–2 6.00 10 15
Football ~2–1 12.00 15 10

They are calibrated so an ordinary win is worth roughly the same in any sport — between 25 and 39 points for one starter — which makes two leagues on one forum comparable and stops a basketball table reading like a phone number.

🚨 A basketball shutout bonus is zero and the row is not drawn at all, because a basketball shutout cannot happen. A rule listed at 0.00 that can never pay out reads as a broken rule rather than as an impossible event.

This only decides what a new league starts from, and it never touches a league that already exists.

Settings

The admin settings (franchises per league, teams on a roster, teams in a lineup) are the defaults for new leagues. A league takes them when it is started and keeps them: changing a setting later only affects leagues started afterwards. There is no screen for changing an existing league's size or scoring.

Things worth knowing

🚨 A game only scores once it is finished. picks_events carries a live score while a game is being played; scoring off that would move a franchise's total up and down all afternoon and make a matchup "final" at half time. A game with a NULL score has not been reported on, which is not 0–0.

🚨 Scoring is idempotent. Every pass upserts, so running it twice writes the same rows and changes nothing — which is what makes it safe on a schedule beside a live-score sync that will re-report a game that was already final.

🚨 One owner per team is a UNIQUE INDEX, not a rule the application remembers. Two people clicking Add on the same free agent in the same second both pass a "is it taken?" check; only one insert can win, and the loser is told so rather than shown a stack trace.

🚨 The workings are stored, not just the total. Points scored, allowed, the win, the shutout and the bonus are written beside the points — because a scoring rule corrected mid-season would otherwise make every earlier week unexplainable.

Requires

Support

Licence

MIT.