Skip to main content

level-up-development

Build and work with cjmellor/level-up features, including XP, levels, tiers, achievements, streaks, multipliers, challenges, leaderboards, leagues, and auditing.

Informations de source

Dépôt
cjmellor/level-up
Dernière activité de la source
18 juin 2026 à 21:01
Langue détectée de SKILL.md
anglais
Étoiles
675
Forks
54

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
level-up-development
description
Build and work with cjmellor/level-up features, including XP, levels, tiers, achievements, streaks, multipliers, challenges, leaderboards, leagues, and auditing.
## When to use this skill Use this skill when working with gamification features — adding experience points, levels, tiers, achievements, streaks, multipliers, leaderboards, leagues, or auditing — using cjmellor/level-up. ## Core Concepts - **XP and Levels** — Users earn experience points (XP) and automatically progress through a defined level structure. - **Tiers** — Named status brackets (e.g. Bronze, Silver, Gold) based on XP thresholds, independent of numeric levels. - **Achievements** — Unlockable rewards, optionally with progress tracking, optionally gated by tier. - **Streaks** — Track consecutive daily activities with freeze support. - **Multipliers** — Database-backed point modifiers with scoping, scheduling, and configurable stacking strategies. - **Leaderboard** — Rank users by any metric (XP by default) with competition-style rank numbers, optionally scoped to a tier or a time period (day/week/month/custom). - **Leagues** — A competitive cycle on one periodic Board: active users are grouped into small Cohorts within a Division each period and ranked within their Cohort. A Division is competition history, NOT a Tier (which is XP status) — a user holds both independently. - **Auditing** — Automatic history of all XP changes, level-ups, and tier changes. ## Setup ### Install ```bash composer require cjmellor/level-up php artisan vendor:publish --tag="level-up-migrations" php artisan migrate php artisan vendor:publish --tag="level-up-config" ``` ### Add Traits to the User Model Add only the traits you need: ```php use LevelUp\Experience\Concerns\GiveExperience; use LevelUp\Experience\Concerns\HasAchievements; use LevelUp\Experience\Concerns\HasChallenges; use LevelUp\Experience\Concerns\HasLeagues; use LevelUp\Experience\Concerns\HasStreaks; use LevelUp\Experience\Concerns\HasTiers; class User extends Authenticatable { use GiveExperience; // Required — XP and levels use HasAchievements; // Optional — achievements use HasStreaks; // Optional — streaks use HasTiers; // Optional — tiers use HasChallenges; // Optional — challenges use HasLeagues; // Optional — leagues (divisions/cohorts) } ``` `GiveExperience` is the foundation. The others are opt-in. ## Levels ### Define Levels ```php use LevelUp\Experience\Models\Level; Level::add( ['level' => 1, 'next_level_experience' => null], ['level' => 2, 'next_level_experience' => 100], ['level' => 3, 'next_level_experience' => 250], ['level' => 4, 'next_level_experience' => 500], ['level' => 5, 'next_level_experience' => 1000], ); ``` Level 1 must have `next_level_experience` set to `null` — it is the default starting point. Users level up automatically when their XP reaches the threshold. Throws `LevelExistsException` if a level number already exists. ### Level Queries ```php $user->getLevel(); // Current level number (int), 0 if no experience $user->getPoints(); // Current XP total (int), 0 if no experience $user->nextLevelAt(); // XP remaining until next level (int) $user->nextLevelAt(checkAgainst: 5); // XP remaining until level 5 $user->nextLevelAt(showAsPercentage: true); // Progress as 0-100 percentage ``` ### Manual Level Up ```php $user->levelUp(to: 5); // Jump to level 5 ``` Throws `InvalidArgumentException` if the level does not exist. Fires `UserLevelledUp` for each intermediate level gained. Respects the level cap. ### Level Cap Configured in `config/level-up.php`: ```php 'level_cap' => [ 'enabled' => env('LEVEL_CAP_ENABLED', true), 'level' => env('LEVEL_CAP', 100), 'points_continue' => env('LEVEL_CAP_POINTS_CONTINUE', true), ], ``` When the cap is reached, the user stops levelling. If `points_continue` is `true`, XP still accumulates. If `false`, XP stops accumulating too. ## Experience Points (XP) ### Add Points ```php $user->addPoints(50); $user->addPoints(50, reason: 'Completed tutorial'); $user->addPoints(50, multiplier: 2); $user->addPoints(50, type: AuditType::Add->value, reason: 'Bonus'); ``` Creates an experience record if none exists, otherwise increments. Automatically levels up if the threshold is crossed. Points past the highest level's `next_level_experience` cap the user at the top level (no exception). ### Deduct Points ```php $user->deductPoints(30); $user->deductPoints(30, reason: 'Penalty'); ``` Throws `Exception` if the user has no experience record. ### Set Points ```php $user->setPoints(500); ``` Directly overwrites the XP total, then recalculates level and tier from the new total (firing `UserLevelledUp` / `UserTierUpdated` as needed). Throws `Exception` if the user has no experience record. Writes no audit record — it is an administrative override, invisible to periodic leaderboards. ### Get Points ```php $user->getPoints(); // int, returns 0 if no experience record ``` ## Multipliers Multipliers are database-backed records that modify point calculations. They can be scoped to specific users or tiers, scheduled with time windows, and configured to stack using different strategies. ### Create Multipliers ```php use LevelUp\Experience\Models\Multiplier; Multiplier::create([ 'name' => 'Weekend Bonus', 'multiplier' => 2.0, 'is_active' => true, 'starts_at' => now()->startOfWeekend(), 'expires_at' => now()->endOfWeekend(), ]); ``` Active multipliers are automatically applied when `addPoints()` is called. The `multiplier` value must be at least `0.01`. If both `starts_at` and `expires_at` are set, `starts_at` must be before `expires_at`. ### Scope Multipliers Multipliers with no scopes apply to all users. Use the typed `scopeToUser` / `scopeToTier` methods to restrict: ```php $multiplier->scopeToUser($user); // Specific user only $multiplier->scopeToTier($goldTier); // Gold tier users only $multiplier->scopeToUser($user)->scopeToTier($tier); // Both — chains via fluent return // Variadic — attach multiple of the same type in one call $multiplier->scopeToUser($alice, $bob, $carol); $multiplier->scopeToTier($silver, $gold, $platinum); // Reverse the scope $multiplier->unscopeFromUser($user); $multiplier->unscopeFromTier($goldTier); // Check whether a multiplier has any scopes attached $multiplier->isGlobal(); // true when no users or tiers attached ``` `scopeToUser` and `scopeToTier` are idempotent (they use `syncWithoutDetaching` internally) — calling them twice with the same model does not create duplicates. ### Inline Multiplier ```php $user->addPoints(amount: 10, multiplier: 3); // 30 points ``` Inline multipliers stack with DB multipliers according to the configured strategy. ### Stacking Strategies Configure in `config/level-up.php`: ```php 'multiplier' => [ 'enabled' => env('MULTIPLIER_ENABLED', true), 'stack_strategy' => env('MULTIPLIER_STACK', 'compound'), // 'compound' — multipliers multiply each other: 2 × 5 = 10x // 'additive' — multipliers sum: 2 + 5 = 7x // 'highest' — only the largest applies: max(2, 5) = 5x ], ``` ### Query Multipliers ```php Multiplier::active()->get(); // Currently active Multiplier::active()->forUser($user)->get(); // Active for a specific user Multiplier::scheduled()->get(); // Future (starts_at > now) Multiplier::expired()->get(); // Past (expires_at < now) ``` ### MultiplierApplied Event Fires when multipliers modify a point calculation. Properties: `Model $user`, `Collection $multipliers`, `int $originalAmount`, `int $finalAmount`, `string $strategy`. ## Tiers ### Define Tiers ```php use LevelUp\Experience\Models\Tier; Tier::add( ['name' => 'Bronze', 'experience' => 0], ['name' => 'Silver', 'experience' => 500], ['name' => 'Gold', 'experience' => 2000], ['name' => 'Platinum', 'experience' => 5000, 'metadata' => ['color' => '#E5E4E2', 'icon' => 'crown']], ); ``` Tier names and experience values must be unique. Throws `TierExistsException` on duplicates. The `metadata` column is a flexible JSON field for any extra data (colours, icons, descriptions). The entire `add()` call is wrapped in a database transaction — if any tier fails, none are created. ### Automatic Tier Promotion Tiers update automatically when XP changes. When `addPoints()` causes the user to cross a tier threshold, `experience.tier_id` is updated and a `UserTierUpdated` event fires with `TierDirection::Promoted`. ### Query Tiers ```php $user->getTier(); // Current Tier model or null $user->getNextTier(); // Next tier above current (Tier or null) $user->tierProgress(); // Percentage 0-100 through current bracket $user->nextTierAt(); // XP remaining until next tier $user->isAtTier('Gold'); // Exact match (bool) $user->isAtOrAboveTier('Silver'); // At or above (bool) ``` `getTier()` returns `null` if the user has no experience record or tiers are disabled. ### Demotion By default, tiers use a **high-water mark** — once earned, they persist even if points decrease. Enable demotion to allow tier drops: ``` TIER_DEMOTION=true ``` When enabled, `deductPoints()` checks if the user should drop and fires `UserTierUpdated` with `TierDirection::Demoted`. The `newTier` property is nullable — it will be `null` if the user drops below all tier thresholds. ### Tier-Scoped Multipliers Create a multiplier and scope it to a tier so it only applies to users at that tier: ```php $multiplier = Multiplier::create([ 'name' => 'Gold Bonus', 'multiplier' => 2.0, 'is_active' => true, ]); $goldTier = Tier::where('name', 'Gold')->first(); $multiplier->scopeToTier($goldTier); ``` When a Gold-tier user calls `addPoints()`, this multiplier is automatically included. ### Tier-Gated Achievements Restrict achievements so only users at a certain tier can earn them: ```php $goldTier = Tier::where('name', 'Gold')->first(); Achievement::create([ 'name' => 'Golden Streak', 'tier_id' => $goldTier->id, ]); ``` Attempting to grant to a user below Gold throws `TierRequirementNotMet`. ### Tier-Scaled Streak Freezes Higher tiers get longer freeze durations: ```php // config/level-up.php 'tiers' => [ 'streak_freeze_days' => [ 'Bronze' => 1, 'Silver' => 2, 'Gold' => 3, 'Platinum' => 7, ], ], ``` Falls back to the global `freeze_duration` if the tier is not listed or tiers are disabled. ### Tier-Scoped Leaderboards ```php use LevelUp\Experience\Facades\Leaderboard; Leaderboard::forTier('Gold')->generate(); Leaderboard::forTier($tierModel)->generate(); ``` ### Tier Config ```php 'tiers' => [ 'enabled' => env('TIERS_ENABLED', true), 'demotion' => env('TIER_DEMOTION', false), 'streak_freeze_days' => [], ], ``` ## Achievements ### Create Achievements ```php use LevelUp\Experience\Models\Achievement; Achievement::create([ 'name' => 'First Login', 'is_secret' => false, 'description' => 'Log in for the first time', 'image' => 'storage/app/achievements/first-login.png', ]); // Secret achievement (hidden until earned) Achievement::create([ 'name' => 'Hidden Gem', 'is_secret' => true, ]); // Tier-gated achievement Achievement::create([ 'name' => 'Gold Member Badge', 'tier_id' => $goldTier->id, ]); ``` ### Grant Achievement ```php $user->grantAchievement($achievement); // With progress (0-100) $user->grantAchievement($achievement, progress: 50); ``` Throws `Exception` if progress exceeds 100, or if the user already has the achievement. Throws `TierRequirementNotMet` if tier-gated and user does not meet the tier requirement. `AchievementAwarded` event fires only when progress is `null` or `100`. ### Revoke Achievement ```php
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub