daveomcd
daveomcd

Reputation: 6565

Site Design: How to award users tasks with achievements?

So I'm wanting to setup an achievements system on my site. People perform tasks and upload this information which is then stored in a database (think 'time', 'date', 'task', etc.). What would be the best method of checking their information and awarding achievements? Would I just have like an achievement.php that once information is uploaded it would trigger this document to run through all the checks to determine if the user needs to be awarded an achievement? Or is there something server side I should set up to award the user?

Thanks for any help or suggestions, comments, etc. :D

EDIT: I currently have the achievements listed in the database, (id, name, class)

Tasks are stored as ('date_time','time','device','user_id[fk]')

EDIT 2: Also many achievements will be calculated based on not only the tasks the user is currently submitting but takes into account previous tasks in addition to the newly added task. EX: If the user has completed 3 tasks within 3 consecutive days, then they will be awarded for it

Upvotes: 3

Views: 539

Answers (3)

nathan gonzalez
nathan gonzalez

Reputation: 12017

it really depends on where your preference for business logic placement lies, and how real time you want acheivements to be. if you're looking to offload a bunch of business logic on you sql server, put it in a stored procedure, otherwise, class out the calculations into a class in php, and use that class to determine what new achievements have been.

i would definitely suggest doing the processing outside of the normal page response. perhaps kick off a server-side call to the php cli, or set up a cron job to run all individuals through a check for achievements at a certain interval.

edit:

as for the actual methods of awarding achievements, i would think you're most flexible and simple implementation (you will find more simple/less flexible and more flexible/less simple options i'm sure) would be to create an AwardRunner class, an IAward interface and a bunch of individual implementations of IAward for each award you have. the basic idea would be something like:

<?php
    class AwardRunner {
        var $UserId = 0;

        function AwardRunner($userId) {
            $this->UserId = $userId;

            $dir = "/path/to/your/folder/full/of/IAwards/";
            $includes = read_dir($dir);

            //include all files that exist
            foreach($includes as $include)
            {
                if (is_file($include))
                {
                  require($include);
                }
            }
        }

        public function Run() {
            $classList = get_declared_classes();

            foreach($classList as $key => $className)
            {
                if (in_array('IAward', class_implements($className))) {
                    $award = $className();
                    $award->UserId = $this->UserId; 
                    $award->GrantIfUserQualifies();
                }
            }

        }

        //function for reading all files in a directory.
        //this is recursive, so any files in subfolders will also make it in
        function read_dir($dir) 
        {
            $array = array();
            $d = dir($dir); 
            while (false !== ($entry = $d->read())) {
                if($entry!='.' && $entry!='..') {
                    $entry = $dir.'/'.$entry;
                    if(is_dir($entry)) {
                        $array = array_merge($array, read_dir($entry));
                    } else {
                        $array[] = $entry;
                    }
                }
            }
            $d->close();
            return $array;
        }   
}
?>

i would think the idea of what the IAward interface would look like would be pretty clear from the usage, though you'd probably add to it the Id field from your table so it would be able to insert itself into the database, as would the way to call the AwardRunner class.

this idea should work whether you have something batching the awards process looping through all your users, or just fire it off after every task submission.

Upvotes: 1

slandau
slandau

Reputation: 24102

How about you create a trigger on the task submission proc (or however you insert the data when the user completes a task), that then performs the necessary actions for that user to determine if he/she is awarded an achievement, and then updates the achievements table accordingly.

Then, every-time you load up the information for the user on the front end, the data will already be in for him/her in the achievements table, and you can directly access it (which I'm sure you already do).

Upvotes: 1

Dutchie432
Dutchie432

Reputation: 29170

Your best bet is probably to create a table of point values for the tasks, and then create a stored procedure that can fetch the appropriate counts from the appropriate tables and multiply them by the point values. That's what I've done in the past - it allows you modify point values on the fly from the DB as well.

Upvotes: 2

Related Questions