How would you implement a badge system similar to SO?
I need to do a similar badge system in zend framework.
I开发者_运维知识库 don't know how to implement, I though about a Event/Observer and some actions to trigger an action to check, or a cron which will run every 10 minutes for example, etc..
Any ideas?
As a Django developer who's written a gamification plug-in for a client, I used Stack Overflow and BigDoor as my inspirations. It turns out that Gamification is very easy, and freaking hard all at the same time.
Assuming that you already have a User table in your database, the core of gamifying your application takes exactly two tables: "Currency" and "UserCurrency." The Currency table has one required field, "name", but I recommend a "description" as well. If you write an administrative interface to your gamification layer, the description helps a lot.
The CurrencyUser table has three things: the ID of a user, the ID of a Currency, and the amount of that currency the user has earned.
"Currency" is a gamification buzzword; it does not refer to money, but to whatever it is that you're tracking. For example, SO tracks how many bounties you've put out, how many votes, how many times you've upvoted an answer other than your own, and how many times one of your answers' upvotes passes 10 (note that last one: other people do that, not you!). For each of these events, SO runs through a list of criteria, gets the associated currency, and increments or creates a new UserCurrency for those that have been met.
When the increment happens, that too is an event, and a second tier of functions is triggered, and if a threshold is passed, a badge is awarded.
There are also "secret" badges in SO. Did you know that? You don't get a badge for these, but a flag is set in a different table-- permission to edit, permission to comment, permission to manage the wiki, and so on.
I mention the secret badges to make this clear: the code for tracking user events that award currency is one independent plug-in loosely-coupled to your application, the code for tracking currency events that lead to badges is a second, independent, loosely-coupled piece of code, and the code for tracking currency events that lead to permissions is a third, independent, loosely-coupled piece of code. The internals of each can change to some degree without lousing up the others, so long as the APIs between each are clear.
So gamification is easy to write.
It's also hard as heck. SO is an inspiration because they really thought hard about what they wanted their users to do. The progressive permissions system prevents egregious trolling, the badge system educates users about the badge system from the get-go ("First post badge!") but it also educates the user about what more the user can do. The names and descriptions of badges are delightful, insightful, and lead the user to learn more. "Gamification" is not just about engagement, but it is a kind of documentation that tells the user, "Now that you've figured out X, you can go for award Y!" If you can't hit that mark, don't bother gamifiying.
I would implement that using triggers (pseudocode:)
On update votes_table create new row in users_points (how_many, for_what, when, ...);
on update users_points call check_if_enough_for_some_badge();
I'm approaching it like this: First, virtually all user activity is logged as an event, from the get-go, as new badges and conditions will be added in the future and some of them go over long-term periods.
The app I'm working on is an e-learning game/platform, so Event Types would consist of something like: Quiz, User, Community, and the events within them might be something like: (for Quiz) Answers Question Correctly, Answers Question Incorrectly, Completes Quiz, (for User) Login, Logout, Complete Profile, (for Community) posts question to forum, Post Answer to Forum, Answer Rated +1, etc...
Every event would get a timestamp.
The critera for completing a badge/level/etc is stored in a function, and the function's name is in the table with the badge. This allows me to keep the tables simple, and leverage more creative use of code.
A cron runs on short intervals to go through the queue of badges/levels/etc for everything in the event table, cross-referenced with a log of user activity. In other words, only when a user logs in does he get added to the queue.
Any suggestions to go with this, esp. concerning scalability would be appreciated!
I would do like that:
- create a lot of parameters for the users (like questions answered, votes received, etc)
- create badges with prerequisites on this parameters (5 questions answered, 10 votes received, etc)
- every time you update your user, check for new badges and include them on the users badges
I think it should do the trick (:
If you doesn't need to warn the user when he gets a new badge you don't even have to look for badges every time. Just run a query showing the badges that matches the prerequisites.
精彩评论