FMCorz / moodle-block_xp

A gamification plugin for Moodle allowing students to gain experience points and level up.
https://levelup.plus/?ref=github
150 stars 41 forks source link

Associate some levels with badges #87

Closed Canx closed 2 months ago

Canx commented 6 years ago

Hi! it would be great to give Moodle badges at certain levels automatically. I think they don't collide with level_up badges, as they would be "permanent", and associated with a greater achievement.

PD: nice to see that your are improving the plugin again!

FMCorz commented 6 years ago

Agreed! That feature has been in my mind from the start, see the TODO list at the bottom of the readme file heh.

Canx commented 6 years ago

So you are waiting for MDL-39864 to complete hehe, only 5 years old! I just waited 10 years to see MDL-14274 finally completed... Maybe in your retirement, if you get lucky, it will get finished ;)

From my perspective HQ seems to be overloaded or prioritizing other things, your only hope is that some external picks up the task and then even for integration seems to last forever (if they don't reject it)...

I'm sure I'm missing something, I can see that the badge criteria API would be cleaner, but wouldn't be easier (and hackier) to create a settings page to associate levels with badges (only manually granted), and grant badges from the block when user arrives to the level?

FMCorz commented 6 years ago

You're right, waiting wouldn't be a smart choice, and the approach you're suggesting is the one I had in mind to counter the current limitations.

Though, Moodle recently included additional ways to award badges, without changing the API. At this stage, I doubt that the API will change, most users are happy with how they work, or so it seems. Perhaps they is room for a plugin that is does just that, adding ways to earn badges.

Adding additional settings in Level up! is an option, but you know my position regarding adding more and more settings. Temporarily, a small local plugin should be just fine to achieve the goal that you're after.

Canx commented 6 years ago

Hi Fred,

I just wrote some logic to award badges at certain levels in a toy plugin I have. Apparently it works! It's a little of a hack but if can help you (I doubt it), here it is:

I would have wanted to do it better, like an external plugin that could listen level up events thrown by my/your plugin. Maybe in the future!

Cheers!

FMCorz commented 6 years ago

Hi Ruben,

Thanks for sharing that. I see you're on the right track. You may need to include additional tests to ensure that the badge can be issued (manual criteria), and perhaps some logic to ensure that the issuer has the adequate roles.

Note that you could observe the event user_leveledup from block_xp in order to automatically award badges as a user levels up.

Cheers!

Canx commented 6 years ago

Hi,

thanks for having a look at the code! I've been looking to the user_levelup event and I think I can use it to award badges, as currently I need the user, the level and the course to award badges, all of them provided by the event. I can see that the course could be obtained indirectly from the context, so no problem there...

But thinking twice I have doubts if I would need more the block id than the course id, because maybe two different blocks in the same course could interfere in their level-badge association. I've seen that you created a method get_instance_in_context to get your block instance from the context, maybe if I end up extracting into plugin I'll ask you to pass the block_id in the event...

FMCorz commented 6 years ago

In your case I think $event->courseid should be enough, although note that when there is one block per site, that courseid will be 0, and Level up! will be expecting 1. The better approach is to check the context, if the context is system then use SITEID, if the context is from a course, use the courseid.

Using the block ID should not be necessary. Most of the code is completely agnostic of the block and what you've found are just tricks for me to:

a) Check that the block is found somewhere b) Help with modifying the legacy settings that are contained within the block

Canx commented 6 years ago

Hi!

I'm a little stubborn and I copy-and-pasted your get_instance_in_context method in my observer (renamed as get_blockid) to obtain the blockid and apparently it works and I could award badges using block_xp!

I thought having the blockid would make unnecessary to check if the block is on a course or not. Anyway, I needed the blockid because of how I designed the tables, maybe it's not the best option...

Still a lot of cleaning and checks, add tests, learn how to hook links in Moodle UI, extract code into plugin... But little time to do things!

I remember now that you can only have one block_xp per course, and going through this now I understand why it happens. Having a course context instead of a block context adds this limit, am I wrong?

FMCorz commented 6 years ago

Hi!

I'm glad you made it work.

The issue with referring to the block instance is that there could be multiple blocks in different sub contexts of the course. For example, you could display the block only in forums and quizzes. This would effectively create two block instances, while you only want one config for the course itself. That's for that reason that the config is recorded against the courseid and not the blockid. Although, three settings are attached to the block instance, which isn't ideal and we'll probably change that in the future.

In your query, the part AND lb.block_id = ? seems redundant as we already know that there can only be one block per course. Also note that your query might not work properly when the blockid is null.

FMCorz commented 2 months ago

Closing as awarding badges for reaching a level has been added in XP+ 1.15.