HabitRPG/habitrpg — pull request #2219 by SabreCat (2014-01-01 22:19:03+00:00)
Title: Overhauled automatic attribute allocation logic

I spent all day trying to get a backfill button to work, but while the logic seems to be working OK--the numbers fill in just fine--I'm not getting it to pass the right data to and from the server to get it to stick. So for now I'm submitting this PR, which at least gets the process working at levelup time. Synopsis:

* The "Automatic Allocation" preference now has three user-preference modes: `flat`, `classbased`, and `taskbased`.
* `flat`, or "Distribute attribute points evenly", will assign a levelup point to the attribute with the fewest points assigned to it so far, breaking ties INT > PER > STR > CON.
* `classbased`, or "Distribute attribute points based on Class", is the "3:2:1:1" setup discussed [here](https://github.com/HabitRPG/habitrpg/issues/2063), though it does favor class attributes first rather than following the "build the foundation" approach suggested there. The algorithm works by establishing what an "ideal" character build would look like at the player's level, if their class's primary attribute got 3 points per 7 levels, secondary got 2, and the others got 1. It then assigns the levelup point to the attribute furthest behind par according to that scheme.
* `taskbased`, or "Distribute attribute points based on task activity", is an overhaul of the current Automatic Allocation logic. Instead of tallying the user's task values at time of levelup and assigning an attribute point based on the biggest value (including, I suspect though have not confirmed, a bug where it counts Rewards as STR value), the user accumulates "training" points for each attribute behind the scenes as they act on tasks. It uses the same `delta` formula that scoring does, adding the new delta for a task into the `training` variable corresponding to the task's attribute. Then at levelup time, it finds the most-trained attribute that level, assigns it a point, and zeroes out the training.

I think the task-based allocation holds the greatest promise for real-life motivation: if you want to beef up your character's Intelligence, you need to do well on your Mental tasks. If you instead end up doing best on your exercise and wellness goals, your character will reflect that, growing in Strength. (At present, even discounting the Rewards bug, you can end up scoring points in an area you haven't touched, because the value of neglected Dailies and To-Dos increases over time while oft-hit positive Habits become less valuable.) The other two options are best for users who don't want to deal with assigning attributes to their tasks, but want a well-rounded character (`flat`) or one who will excel at class abilities (`classbased`).

Still to do:

* Implement a "Distribute points now" button that will backfill any accrued attribute points according to the selected auto-allocation scheme. I made a valiant attempt at this, but couldn't get it done in time.
* Issue #2098: for task-based auto-allocation, provide feedback to the user on how they're doing over the course of the level. Show them what attribute is likely to level up when they next fill their XP bar, so they can adjust their focus accordingly.