I've been digging into the code and the database tables and from what I see this isn't possible but maybe it is. We'd like to use userpoints but have different classifications of points. For example
"Reward points"
"Penalty points"
"Karma points"

Is this possible? Is this a desirable feature if it doesn't exist? I wouldn't mind hacking away and submitting a patch for it if its desirable.

Comments

kbahey’s picture

Version: 4.7.x-2.2 » 5.x-2.9

Yes, this is a good idea.

It is often asked for in the form of different "pools" or "buckets" of points.

This involves an API change though, have to pass the ID of the pool to assign to. Need to have a default pool if this is not specified.

Go ahead and work on a patch, but before you go in too deep, outline the vision you have and how it would affect the data module (database tables and API).

jredding’s picture

Pools/Buckets/Categories, ya its all the same thing. Yes it would require a small API change especially to userpoints_userpointsapi() by adding a category/bucket/pool setting to it (i.e. $bucket="") . In that function we can add a default setting to be "main".

However all of the queries would then needed to be modified to display the points correctly.

Like I said I'm willing to do the work on this and submit a patch. My work would be on 4.7 though as that is our current environment.

jredding’s picture

Whoops.. submitted too soon. I'll do a quick writeup on how I envision it working. Need to dig in a little deeper into the API and the code first though.

jredding’s picture

Heres a quick list of what I think would need to be done.

1) Add a column to userpoints_txn called category
Type: varchar length 30?
--Could be as small as 10, 255 if we want to allow for super flexibility but we're wasting space

2) Change
userpointsapi('points', $points, $uid, $event, $description)
to
userpointsapi('points', $points, $uid, $event, $description, $category='main')

and add code to insert the category in the SQL statement

3) Change
hook_userpoints($op, $points, $uid, $event)
to
hook_userpoints($op, $points, $uid, $event, $category)

4) Change
userpoints_get_current_points($uid)
to
userpoints_get_current_points($uid, $category='main')

obviously we can change the default category and I'll have to write some code to modify the moderation queue queries and all of the returns (for example, the User points display on the account) but in general it shouldn't take long.

What do you think?

At first glance I don't think this would screw up any of the other modules since this is only an API change and we can easily set a default if not passed in. I haven't dug into the other pieces though.

Thoughts/Suggestions?

kbahey’s picture

Here are some random thoughts.

One approach is to have different tables for different pools: e.g. userpoints_{poolname}.

Another is to have columns in the table for each pool. Modules can add columns or remove columns using the .install files.

There are other options for sure, probably better than those above.

jredding’s picture

After talking with Kbahey (thanks by the way) there are the two approaches we see for implementing point categories.
Please comment on them so that we contribute to the whole community.

In either approach we would add a single field to the tables userpoints_txn and userpoints.

What this field is and hold, is the question.

Suggestion 1) The field is an INT which holds a Term ID. If the variable is NULL then all the points wind up in the same category (NULL is a catch all category). The term ID (tid) would come from a vocabulary that the user would choose when enabling the module.

  • Pros
    • category creation/maintenance is done by the core modules
    • Since the DB field is INT performance would be good
    • Category names can change without affecting data integrity
  • Cons
    • Modules couldn't simply add an arbitrary category (like the node table)
    • Modules would have to be configured somehow to discover the appropriate TID to use when adding to a category. This would most like happen through an API call to get the Vocab ID, then a module specific USER based setting to set the TID

In this model an API call, userpoints_get_vid(), would return the vocabulary ID so that contributed modules would know which vocab to use. Those other modules could get present a list of terms to the user for term selection or use some other ingenius method for adding the terms (possibly just adding the term into the vocab directly?)

Suggestion 2) The field is an VARCHAR which holds a category name. This would be similar to the node table for node types (varchar 32)

  • Pros
    • Modules can simply add an arbitrary category (similar to the node table)
    • User administration is simplified as the user doesn't have to select the taxonomy term to use
  • Cons
    • Category names cannot change without affecting data integrity
    • Since the DB field is VARCHAR performance wouldn't be as good as in suggestion 1 (Kbahley suggested 6x less performance; which is HUGE)
    • category creation/maintenance is done by the Core and Contributed modules
mercmobily’s picture

Hi,

I must say, I love the idea of using a term id. It just makes a lot of sense.

This would be an extra field which would go on top of my patch. However, by looking at my patch you can very easily work out where to make the change to add an extra field - which is good, because I remember at least one spot that was tricky to catch.

I don't think creating an extra table for a pool or adding a column is the way to go. From a DB design point of view, it's not acceptable...

Bye!

Merc.

kbahey’s picture

To add to jredding's comments:

Suggestion 3) INT id and a special table for categories.
This means that we have a userpoints_category table that is (cid INT, desc VARCHAR). The rest is like suggestion 1, but we manage the categories instead of relying on taxonomy. We have a cid in both the userpoints table and in the userpoints_txn table. So, to get total points for a user we do a SUM(points). To get by certain category, then we do WHERE for cid, ...etc. If cid is NULL, then behavior is the same as today (one big pool of points).

The dilemma for 1 and 3 are how do you know which category to add the points to? For 2, you just put a string in quotes, and that is it, but it opens the door to unstructured data, and has performance issues.
My original vision was to use event for something like that, but since you can put arbitrary strings in it, people used it for all sorts of things.

Let us see if we have more comments on these approaches.

This and other patches in the queue, will mandate a new 3.x API for userpoints. See my proposal for that here http://drupal.org/node/153626

jredding’s picture

Version: 5.x-2.9 » 5.x-3.x-dev
Component: Code » Code: userpoints
Assigned: Unassigned » jredding
Status: Active » Fixed

Point categories have been implemented in version 3.x via the use of taxonomy. Please follow this thread for more information.
http://drupal.org/node/153626

Anonymous’s picture

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.