Coder Social home page Coder Social logo

cjmellor / level-up Goto Github PK

View Code? Open in Web Editor NEW
512.0 4.0 37.0 214 KB

Level-Up is a Laravel package introducing gamification into your applications. Users earn experience points (XP) and levels through interactions, while also unlocking achievements. It promotes engagement, competition, and fun through its dynamic leaderboard feature. Customisable to fit your specific needs

License: MIT License

PHP 100.00%
gamification laravel achievements engagment experience leaderboard levelling

level-up's Introduction

Latest Version on Packagist GitHub Tests Action Status Total Downloads Packagist PHP Version Laravel Version

This package allows users to gain experience points (XP) and progress through levels by performing actions on your site. It can provide a simple way to track user progress and implement gamification elements into your application

Banner

Installation

You can install the package via composer:

composer require cjmellor/level-up

You can publish and run the migrations with:

php artisan vendor:publish --tag="level-up-migrations"
php artisan migrate

You can publish the config file with:

php artisan vendor:publish --tag="level-up-config"

This is the contents of the published config file:

return [
    /*
    |--------------------------------------------------------------------------
    | User Foreign Key
    |--------------------------------------------------------------------------
    |
    | This value is the foreign key that will be used to relate the Experience model to the User model.
    |
     */
    'user' => [
        'foreign_key' => 'user_id',
        'model' => App\Models\User::class,
    ],

    /*
    |--------------------------------------------------------------------------
    | Experience Table
    |--------------------------------------------------------------------------
    |
    | This value is the name of the table that will be used to store experience data.
    |
     */
    'table' => 'experiences',

    /*
    |-----------------------------------------------------------------------
    | Starting Level
    |-----------------------------------------------------------------------
    |
    | The level that a User starts with.
    |
    */
    'starting_level' => 1,

    /*
    |-----------------------------------------------------------------------
    | Multiplier Paths
    |-----------------------------------------------------------------------
    |
    | Set the path and namespace for the Multiplier classes.
    |
    */
    'multiplier' => [
        'enabled' => env(key: 'MULTIPLIER_ENABLED', default: true),
        'path' => env(key: 'MULTIPLIER_PATH', default: app_path(path: 'Multipliers')),
        'namespace' => env(key: 'MULTIPLIER_NAMESPACE', default: 'App\\Multipliers\\'),
    ],

    /*
    |-----------------------------------------------------------------------
    | Level Cap
    |-----------------------------------------------------------------------
    |
    | Set the maximum level a User can reach.
    |
    */
    'level_cap' => [
        'enabled' => env(key: 'LEVEL_CAP_ENABLED', default: true),
        'level' => env(key: 'LEVEL_CAP', default: 100),
        'points_continue' => env(key: 'LEVEL_CAP_POINTS_CONTINUE', default: true),
    ],

    /*
    | -------------------------------------------------------------------------
    | Audit
    | -------------------------------------------------------------------------
    |
    | Set the audit configuration.
    |
    */
    'audit' => [
        'enabled' => env(key: 'AUDIT_POINTS', default: false),
    ],

    /*
    | -------------------------------------------------------------------------
    | Record streak history
    | -------------------------------------------------------------------------
    |
    | Set the streak history configuration.
    |
    */
    'archive_streak_history' => [
        'enabled' => env(key: 'ARCHIVE_STREAK_HISTORY_ENABLED', default: true),
    ],

    /*
     | -------------------------------------------------------------------------
     | Default Streak Freeze Time
     | -------------------------------------------------------------------------
     |
     | Set the default time in days that a streak will be frozen for.
     |
     */
    'freeze_duration' => env(key: 'STREAK_FREEZE_DURATION', default: 1),
];

Usage

💯 Experience Points (XP)

Note

XP is enabled by default. You can disable it in the config

Add the GiveExperience trait to your User model.

use LevelUp\Experience\Concerns\GiveExperience;

class User extends Model
{
    use GiveExperience;

    // ...
}

Give XP points to a User

$user->addPoints(10);

A new record will be added to the experiences table which stores the Users’ points. If a record already exists, it will be updated instead. All new records will be given a level_id of 1.

Note

If you didn't set up your Level structure yet, a default Level of 1 will be added to get you started.

Deduct XP points from a User

$user->deductPoints(10);

Set XP points to a User

For an event where you just want to directly add a certain number of points to a User. Points can only be set if the User has an Experience Model.

$user->setPoints(10);

Retrieve a Users’ points

$user->getPoints();

Multipliers

Point multipliers can be used to modify the experience point value of an event by a certain multiplier, such as doubling or tripling the point value. This can be useful for implementing temporary events or promotions that offer bonus points.

To get started, you can use an Artisan command to crease a new Multiplier.

php artisan level-up:multiplier IsMonthDecember

This will create a file at app\Multipliers\IsMonthDecember.php.

Here is how the class looks:

<?php

namespace LevelUp\Experience\Tests\Fixtures\Multipliers;

use LevelUp\Experience\Contracts\Multiplier;

class IsMonthDecember implements Multiplier
{
    public bool $enabled = true;
    
    public function qualifies(array $data): bool
    {
        return now()->month === 12;
    }

    public function setMultiplier(): int
    {
        return 2;
    }
}

Multipliers are enabled by default, but you can change the $enabled variable to false so that it won’t even run.

The qualifies method is where you put your logic to check against and multiply if the result is true.

This can be as simple as checking that the month is December.

public function qualifies(array $data): bool
{
    return now()->month === 12;
}

Or passing extra data along to check against. This is a bit more complex.

You can pass extra data along when you're adding points to a User. Any enabled Multiplier can then use that data to check against.

$user
    ->withMultiplierData([
        'event_id' => 222,
    ])
    ->addPoints(10);

//

public function qualifies(array $data): bool
{
    return isset($data['event_id']) && $data['event_id'] === 222;
}

Conditional Multipliers

If you don't want to use the class based method to check conditionals to add multipliers, you can do this inline by giving the method a callback with the conditional. When using this method, make sure you have the multiplier set as an argument in the addPoints method, otherwise an error will occur. See example below:

$user
    ->withMultiplierData(fn () => true)
    ->addPoints(amount: 10, multiplier: 2);

The setMultiplier method expects an int which is the number it will be multiplied by.

Multiply Manually

You can skip this altogether and just multiply the points manually if you desire.

$user->addPoints(
    amount: 10, 
    multiplier: 2
);

Events

PointsIncrease - When points are added.

public int $pointsAdded,
public int $totalPoints,
public string $type,
public ?string $reason,
public Model $user,

PointsDecreased - When points are decreased.

public int $pointsDecreasedBy,
public int $totalPoints,
public ?string $reason,
public Model $user,

⬆️ Levelling

Note

If you add points before setting up your levelling structure, a default Level of 1 will be added to get you started.

Set up your levelling structure

The package has a handy facade to help you create your levels.

Level::add(
    ['level' => 1, 'next_level_experience' => null],
    ['level' => 2, 'next_level_experience' => 100],
    ['level' => 3, 'next_level_experience' => 250],
);

Level 1 should always be null for the next_level_experience as it is the default starting point.

As soon as a User gains the correct number of points listed for the next level, they will level-up.

Tip

a User gains 50 points, they’ll still be on Level 1, but gets another 50 points, so the User will now move onto Level 2

See how many points until the next level

$user->nextLevelAt();

Get the Users’ current Level

$user->getLevel();

Level Cap

A level cap sets the maximum level that a user can reach. Once a user reaches the level cap, they will not be able to gain any more levels, even if they continue to earn experience points. The level cap is enabled by default and capped to level 100. These options can be changed in the packages config file at config/level-up.php or by adding them to your .env file.

LEVEL_CAP_ENABLED=
LEVEL_CAP=
LEVEL_CAP_POINTS_CONTINUE

By default, even when a user hits the level cap, they will continue to earn experience points. To freeze this, so points do not increase once the cap is hit, turn on the points_continue option in the config file, or set it in the .env.

Events

UserLevelledUp - When a User levels-up

public Model $user,
public int $level

🏆 Achievements

This is a feature that allows you to recognise and reward users for completing specific tasks or reaching certain milestones. You can define your own achievements and criteria for earning them. Achievements can be static or have progression. Static meaning the achievement can be earned instantly. Achievements with progression can be earned in increments, like an achievement can only be obtained once the progress is 100% complete.

Creating Achievements

There is no built-in methods for creating achievements, there is just an Achievement model that you can use as normal:

Achievement::create([
    'name' => 'Hit Level 20',
    'is_secret' => false,
    'description' => 'When a User hits Level 20',
    'image' => 'storage/app/achievements/level-20.png',
]);

Gain Achievement

To use Achievements in your User model, you must first add the Trait.

// App\Models\User.php

use LevelUp\Experience\Concerns\HasAchievements;

class User extends Authenticable
{
	use HasAchievements;
	
	// ...
}

Then you can start using its methods, like to grant a User an Achievement:

$achievement = Achievement::find(1);

$user->grantAchievement($achievement);

To retrieve your Achievements:

$user->achievements;

Add progress to Achievement

$user->grantAchievement(
    achievement: $achievement, 
    progress: 50 // 50%
);

Note

Achievement progress is capped to 100%

Check Achievement Progression

Check at what progression your Achievements are at.

$user->achievementsWithProgress()->get();

Check Achievements that have a certain amount of progression:

$user->achievements
    ->first()
    ->pivot()
    ->withProgress(25)
    ->get();

Increase Achievement Progression

You can increment the progression of an Achievement up to 100.

$user->incrementAchievementProgress(
    achievement: $achievement, 
    amount: 10
);

A AchievementProgressionIncreased Event runs on method execution.

Secret Achievements

Secret achievements are achievements that are hidden from users until they are unlocked.

Secret achievements are made secret when created. If you want to make a non-secret Achievement secret, you can just update the Model.

$achievement->update(['is_secret' => true]);

You can retrieve the secret Achievements.

$user->secretAchievements;

To view all Achievements, both secret and non-secret:

$user->allAchievements;

Events

AchievementAwarded - When an Achievement is attached to the User

public Achievement $achievement,
public Model $user,

Note

This event only runs if the progress of the Achievement is 100%

AchievementProgressionIncreased - When a Users’ progression for an Achievement is increased.

public Achievement $achievement,
public Model $user,
public int $amount,

📈 Leaderboard

The package also includes a leaderboard feature to track and display user rankings based on their experience points.

The Leaderboard comes as a Service.

Leaderboard::generate();

This generates a User model along with its Experience and Level data and ordered by the Users’ experience points.

The Leaderboard is very basic and has room for improvement

🔍 Auditing

You can enable an Auditing feature in the config, which keeps a track each time a User gains points, levels up and what level to.

The type and reason fields will be populated automatically based on the action taken, but you can overwrite these when adding points to a User

$user->addPoints(
    amount: 50,
    multiplier: 2,
    type: AuditType::Add->value,
    reason: "Some reason here",
);

Note

Auditing happens when the addPoints and deductPoints methods are called. Auditing must be enabled in the config file.

View a Users’ Audit Experience

$user->experienceHistory;

🔥 Streaks

With the Streaks feature, you can track and motivate user engagement by monitoring consecutive daily activities. Whether it's logging in, completing tasks, or any other daily activity, maintaining streaks encourages users to stay active and engaged.

Streaks are controlled in a Trait, so only use the trait if you want to use this feature. Add the Trait to you User model

use LevelUp\Experience\Concerns\HasStreaks;

class User extends Model
{
	use HasStreaks;

	// ...
}

Activities

Use the Activies model to add new activities that you want to track. Here’s some examples:

  • Logs into a website
  • Posts an article

Record a Streak

$activity = Activity::find(1);

$user->recordStreak($activity);

This will increment the streak count for the User on this activity. An `Event is ran on increment.

Break a Streak

Streaks can be broken, both automatically and manually. This puts the count back to 1 to start again. An Event is ran when a streak is broken.

For example, if your streak has had a successful run of 5 days, but a day is skipped and you run the activity on day 7, the streak will be broken and reset back to 1. Currently, this happens automatically.

Reset a Streak

You can reset a streak manually if you desire. If level-up.archive_streak_history.enabled is true, the streak history will be recorded.

$activity = Activity::find(1);

$user->resetStreak($activity);

Archive Streak Histories

Streaks are recorded, or “archived” by default. When a streak is broken, a record of the streak is recorded. A Model is supplied to use this data.

use LevelUp\Experience\Models\StreakHistory;

StreakHistory::all();

Get Current Streak Count

See the streak count for an activity for a User

$user->getCurrentStreakCount($activity); // 2

Check User Streak Activity

Check if the User has performed a streak for the day

$user->hasStreakToday($activity);

Events

StreakIncreased - If an activity happens on a day after the previous day, the streak is increased.

public int $pointsAdded,
public int $totalPoints,
public string $type,
public ?string $reason,
public Model $user,

StreakBroken - When a streak is broken and the counter is reset.

public Model $user,
public Activity $activity,
public Streak $streak,

🥶 Streak Freezing

Streaks can be frozen, which means they will not be broken if a day is skipped. This is useful for when you want to allow users to take a break from an activity without losing their streak.

The freeze duration is a configurable option in the config file.

'freeze_duration' => env(key: 'STREAK_FREEZE_DURATION', default: 1),

Freeze a Streak

Fetch the activity you want to freeze and pass it to the freezeStreak method. A second parameter can be passed to set the duration of the freeze. The default is 1 day (as set in the config)

A StreakFrozen Event is ran when a streak is frozen.

$user->freezeStreak(activity: $activity);

$user->freezeStreak(activity: $activity, days: 5); // freeze for 5 days

Unfreeze a Streak

The opposite of freezing a streak is unfreezing it. This will allow the streak to be broken again.

A StreakUnfrozen Event is run when a streak is unfrozen.

$user->unfreezeStreak($activity);

Check if a Streak is Frozen

$user->isStreakFrozen($activity);

Events

StreakFrozen - When a streak is frozen.

public int $frozenStreakLength,
public Carbon $frozenUntil,

StreakUnfrozen - When a streak is unfrozen.

No data is sent with this event

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

License

The MIT Licence (MIT). Please see Licence File for more information.

level-up's People

Contributors

7omi avatar cjmellor avatar dependabot[bot] avatar github-actions[bot] avatar guptarakesh198 avatar ibrunotome avatar joydeep-bhowmik avatar matthewscalf avatar mohamedalwhaidi avatar quintenjustus avatar theihasan avatar xmuntane avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

level-up's Issues

[Bug]: First Migration Bug

What happened?

Just trying to do first migration and had a issue with streak_history_table.

I changed the migration table as a placebo, but since i just did it, no idea if will face bugs because of that, so just sharing.

            $table->id();
            $table->foreignId(column: config(key: 'level-up.user.foreign_key'))->constrained(table: config(key: 'level-up.user.users_table'))->cascadeOnDelete();
            $table->foreignIdFor(model: Activity::class)->constrained(table: 'streak_activities');
            $table->integer(column: 'count')->default(value: 1);
            $table->timestamp(column: 'started_at')**->nullable(**);
            $table->timestamp(column: 'ended_at'**)->nullable()**;
            $table->timestamps();

`PS C:\Users\tatia\Dropbox\Coding\Laravel\l96lab> php artisan migrate

INFO Running migrations.

2023_10_31_000158_create_streak_histories_table ...................................................... 11ms FAIL

Illuminate\Database\QueryException

SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'ended_at' (Connection: mysql, SQL: create table streak_histories (id bigint unsigned not null auto_increment primary key, user_id bigint unsigned not null, activity_id bigint unsigned not null, count int not null default '1', started_at timestamp not null, ended_at timestamp not null, created_at timestamp null, updated_at timestamp null) default character set utf8mb4 collate 'utf8mb4_unicode_ci')

at vendor\laravel\framework\src\Illuminate\Database\Connection.php:801
797▕ $this->getName(), $query, $this->prepareBindings($bindings), $e
798▕ );
799▕ }
800▕
➜ 801▕ throw new QueryException(
802▕ $this->getName(), $query, $this->prepareBindings($bindings), $e
803▕ );
804▕ }
805▕ }

1 vendor\laravel\framework\src\Illuminate\Database\Connection.php:580
PDOException::("SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'ended_at'")

2 vendor\laravel\framework\src\Illuminate\Database\Connection.php:580
PDOStatement::execute()
`

How to reproduce the bug

Only did a migration on my actual project and had this error.

Package Version

1.1

PHP Version

8.2

Laravel Version

10

Which operating systems does with happen with?

No response

Notes

I made a pull request if that solution make sense. Ignore if dont.

first migration [Bug]:

What happened?

Illuminate\Database\QueryException

SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value
for 'ended_at' (Connection: mysql, SQL: create table streak_histories (id bi
gint unsigned not null auto_increment primary key, user_id bigint unsigned not
null, activity_id bigint unsigned not null, count int not null default '1',
started_at timestamp not null, ended_at timestamp not null, created_at ti
mestamp null, updated_at timestamp null) default character set utf8mb4 collate
'utf8mb4_unicode_ci')

How to reproduce the bug

i try to do fresh migrate

Package Version

2

PHP Version

8

Laravel Version

10

Which operating systems does with happen with?

Windows

Notes

No response

[Bug]: Attempt to read property "status" on null at GiveExperience.php:103

What happened?

I am trying to integrate this package with my application.
However I am not able to pass through registering an user as package causes an error:
[2023-08-24 01:23:49] local.ERROR: Attempt to read property "status" on null {"userId":1,"exception":"[object] (ErrorException(code: 0): Attempt to read property "status" on null at C:\Users\username\Desktop\application_name\script\vendor\cjmellor\level-up\src\Concerns\GiveExperience.php:103)

How to reproduce the bug

I have added GiveExperience trait to Used model as instructed.
I have added custom name and reward columns into levels table.
I have seeded test levels:

$levelsArray = [
            [
                'name' => 'Rookie',
                'required_turnover' => null,
                'reward' => null
            ],
            [
                'name' => 'Seeker',
                'required_turnover' => '200000',
                'reward' => '5000'
            ],
        ];

        foreach ($levelsArray as $index => $level) {
            $levelRecord = new Level();
            $levelRecord->name = $level['name'];
            $levelRecord->level = $index+1;
            $levelRecord->next_level_experience = $level['required_turnover'];
            $levelRecord->reward = $level['reward'];
            $levelRecord->save();
        }

Then I am trying to seed first user

        $user = new User();
        $user->username = config('administrator.username');
        $user->email = config('administrator.email');
        $user->password = config('administrator.password');
        $user->status = UserStatus::active;
        $user->level_id = 1;
        $user->save();

        $user->addPoints(amount: 1);

        $userService = new UserService();
        $userService->createRequiredUsersTables($user->id);

And script is killed with error I have posted above.
What is causing this issue?
Same error happens when I add levels using package provided Level model method on "stock" table.

Package Version

^0.0.6

PHP Version

8.1

Laravel Version

10.2

Which operating systems does with happen with?

Windows

Notes

No response

[Bug]:

What happened?

Missing Listener for Points Decrease

I've noticed that the package has a listener for the PointsIncreased event (PointsIncreasedListener.php), but there is no dedicated listener for the PointsDecreased event.

Additionally, while the database migration for experience audits (create_experience_audits_table.php.stub) has a column for type that can be 'add', 'remove', 'reset', or 'level_up', it seems that the decrement case is not explicitly stored in the database through a listener.

This could be an important feature for tracking user activities related to points decrement.

Would it be possible to add a listener for the PointsDecreased event and store this information in the database?

How to reproduce the bug

When I deductPoints the decrement case is not explicitly stored in the database through a listener.

Package Version

0.0.13

PHP Version

8.2.0

Laravel Version

10.0.0

Which operating systems does with happen with?

No response

Notes

No response

[Bug]: Comparison fails in recordStreak

What happened?

I was testing streak continuation this morning and have found that the check at HasStreaks:51 for strict equality $diffInDays === 1.

If you see the screenshot attached you'll see that even though $diffInDays shows as 1, this evaluates to false. This is because $diffInDays is a float.

Untitled

How to reproduce the bug

Try with Laravel 11 / Carbon 3.

Package Version

1.2

PHP Version

8.2

Laravel Version

11.0

Which operating systems does with happen with?

Windows

Notes

After a quick search I found this article, breaking change in Carbon 3.0 is that these will be returned as floats now.

I cloned this repo and ran the test suite on a fresh install and can confirm that your tests are also failing on this.

Thank you for this library!

2024-06-05 09_13_23-C__Windows_System32_cmd exe

[Bug]:

What happened?

If there is no experience record yet and you run getPoints() it returns the following:
App\Models\User::getPoints(): Return value must be of type int, null returned

How to reproduce the bug

try to run getPoints() while there are no points

Package Version

1.1.0

PHP Version

8.2.14

Laravel Version

10.41

Which operating systems does with happen with?

Linux

Notes

Fix could be:

public function getPoints(): int
    {
        return $this->experience->experience_points ?? 0;
    }

Where it will always return 0 if there are no XP points yet.
If you are fine with it I can shoot a PR including a test

[Bug]: Deduct Points

What happened?

User's level is not changing when the points are reduced.
When a user gains certain amount of points the level changes and he will get to a higher level.
However if I deduct points for this user , his experience changes but his level stays the same even tho now it should be lower.

How to reproduce the bug

Add points to a user until he reaches a certain level. Then try to deduct his points. The experience will change however the level will stay the same

Package Version

2

PHP Version

8.2.0

Laravel Version

9.0.0

Which operating systems does with happen with?

macOS, Linux

Notes

No response

fix: Customise Migration Constraints

Discussed in #11

Originally posted by matthewscalf July 21, 2023
When utilizing this package, the Achievements are cool idea but the migrations and Pivot models assume you have named the User model users. But you have the option to customize that for the other functions. Would be good to see the achievements utilize the same level of customization.

Add the config option for the User model in more places

[Bug]: User's level does not increase

What happened?

When creating 3 levels as the documentation indicates, I carried out tests loading 50 points in my user repeatedly and although the points reached 100 to go to level 2, this never happened.
When implementing the AUDIT_POINTS=true option I could notice as if the attempt to level up was marked but my experience record remained at 1 even though my points were 250

How to reproduce the bug

I created 3 levels as the documentation indicates:

Level::add(
     ['level' => 1, 'next_level_experience' => null],
     ['level' => 2, 'next_level_experience' => 100],
     ['level' => 3, 'next_level_experience' => 250],
);

implement a route where I do this:

$user = \App\Models\User::find(1);

$user->addPoints(50);
echo $user->getLevel();
echo $user->getPoints();

Run api calls to the route repeatedly

Environment Variables

LEVEL_CAP_ENABLED=true
LEVEL_CAP=3
LEVEL_CAP_POINTS_CONTINUE=true
AUDIT_POINTS=true

Package Version

0.0.4

PHP Version

8.2.8

Laravel Version

10.10

Which operating systems does with happen with?

macOS

Notes

When I ran into this error, I did some tests on the package code and realized that I wasn't updating my experience level record but my points were.

While debugging, I changed in the vendor/cjmellor/level-up/src/Concerns/GiveExperience.php file the line 160 in the levelUp method of and was able to solve my problem:

Before:

$this->experience->status()->associate(model: $nextLevel);

After:

$this->experience->status()->associate(model: $nextLevel)->save();

Could you tell me if I'm doing something wrong?

I am using:

  • Docker version 20.10.17, build 100c701
  • PHP 8.2-fpm
  • Postgres 13

[Bug]: Event fired only once even when user has points for multiple levels

What happened?

Hello
I was messing around with your package and noticed very bad bug.
When points earned by user are enough to gain more than one level it gets increased only by one closest to level user currently has.
When next points are awarded next level is unlocked but it should be done in one run in my opinion as there may be along time before user earns next points and he will be stuck at lower level making functions like:

$user->nextLevelAt();

useless as they will display 0 as points requirements for next level are already met.
Is there any way to award multiple levels at one points increase operation?

How to reproduce the bug

  1. Setup default levels
Level::add(
    ['level' => 1, 'next_level_experience' => null],
    ['level' => 2, 'next_level_experience' => 100],
    ['level' => 3, 'next_level_experience' => 250],
);
  1. Award user 300 points
$user->addPoints(300);
  1. Only one UserLevelledUp event is fired with level 2
  2. Award one more point:
$user->addPoints(1);
  1. User level gets increased to level 3

Package Version

v0.0.10

PHP Version

8.1

Laravel Version

10.2

Which operating systems does with happen with?

Windows

Notes

No response

[Bug]: Unknown named parameter $to

What happened?

screencapture-netisu-market-2024-03-20-14_54_33

How to reproduce the bug

When i add the points needed to level up to the next level i get this.

             $amount = 200;
             $Pointsamount = 400;
       
        $user->coins += $amount;
        $user->addPoints($Pointsamount);

Package Version

^1.2.3

PHP Version

8.2.7

Laravel Version

^10.0

Which operating systems does with happen with?

Linux

Notes

No response

[Bug]: Auditing Reason not adding to Db

What happened?

First thing, I love this repo. Great job!

$user->addPoints(
    amount: 50,
    multiplier: 2,
    type: AuditType::Add->value,
    reason: "Some reason here",
);

Adds the amount and multiplier, but doesn't trigger the AuditType and reason.

How to reproduce the bug

$user->addPoints(
    amount: 50,
    multiplier: 2,
    type: AuditType::Add->value,
    reason: "Some reason here",
);

Package Version

0.0.6

PHP Version

8.2

Laravel Version

10.x

Which operating systems does with happen with?

macOS

Notes

No response

[Bug]: $user->nextLevelAt(); returning 0

What happened?

Hey mate when I try to utilise $user->nextLevelAt(); it only ever returns 0 and when I add points to the user in question, it increments the level regardless of what the next_level_experience column has stored.

How to reproduce the bug

Seed the levels, add points to a user account and use the getLevel(), nextLevelAt() and getPoints() helper functions.

Package Version

^0.0.6

PHP Version

8.1

Laravel Version

10

Which operating systems does with happen with?

macOS

Notes

I think you just change the nextLevelAt() function in the trait to be:

$nextLevel = Level::firstWhere(column: 'level', operator: '=', value: is_null($checkAgainst) ? $this->getLevel() + 1 : $checkAgainst);

and it will work again. The check using ?? that is originally there passes null to the level where check and is breaking because it's checking for a null "level" column instead of a null "next_level_experience" column as intended.

Breaks when app\Multipliers is not present

Discussed in #9

Originally posted by Temian1 July 20, 2023
i tried to give user point and i got that issue

p\project\trendup\app\Multipliers" directory does not exist.
```</div>

[Bug]: LeaderboardService has a hardcoded dependency on a "users" table

What happened?

The LeaderboardService.php has a hard-coded dependency on there being a users table, ignoring the configuration file with ->whereColumn('user_id', 'users.id').

<?php

namespace LevelUp\Experience\Services;

use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use LevelUp\Experience\Models\Experience;

class LeaderboardService
{
    private mixed $userModel;

    public function __construct()
    {
        $this->userModel = config(key: 'level-up.user.model');
    }

    public function generate(bool $paginate = false, int $limit = null): array|Collection|LengthAwarePaginator
    {
        return $this->userModel::query()
            ->with(relations: ['experience', 'level'])
            ->orderByDesc(
                column: Experience::select('experience_points')
                    ->whereColumn('user_id', 'users.id')
                    ->latest()
            )
            ->take($limit)
            ->when($paginate, fn (Builder $query) => $query->paginate(), fn (Builder $query) => $query->get());
    }
}

How to reproduce the bug

Use a table that isn't named 'users'.

Package Version

latest

PHP Version

8.2.11

Laravel Version

10

Which operating systems does with happen with?

No response

Notes

Two database migrations also have hardcoded references to users, while the rest read from the config.

fix: Attempt to read property "next_level_experience" on null

What happened?

Reaching max level and calling nextLevelAt function throws error Attempt to read property "next_level_experience" on null

How to reproduce the bug

I created 4 levels:

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],
);

implement a route where I do this:

$user = \App\Models\User::find(1);

$user->addPoints(50);
echo $user->getLevel();
echo $user->getPoints();
echo $user->nextLevelAt();

Run api calls to the route repeatedly

When the user reaches the maximum level, call the function nextLevelAt

Environment Variables

LEVEL_CAP_ENABLED=true
LEVEL_CAP=4
LEVEL_CAP_POINTS_CONTINUE=true
AUDIT_POINTS=true

Package Version

0.0.5

PHP Version

8.2.8

Laravel Version

10.10

Which operating systems does with happen with?

macOS

Notes

The error seems to be on line 152 of the vendor/cjmellor/level-up/src/Concerns/GiveExperience.php file when trying to look for a level higher than 4 which is the maximum set in my environment variables.

Could it be that I am missing some configuration?

I am using:

  • Docker version 20.10.17, build 100c701
  • PHP 8.2-fpm
  • Postgres 13

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.