Skip to content
Permalink
Browse files

Adds category_id to user_behavior_link

Now, on a check-in, a behavior's category_id (and the category_id
associated with the selected behavior for a  processing question) is
stored alongside the other behavior data in the user_behavior_link
table. This is a helpful change that eases future development and allows
existing code to be somewhat simpler.

Also, this is a good push towards our goal of an "immutable" check-in.
Once a check-in has been done and the window for a redo is done, the
user should not be able to update any data in that check-in. The user
obviously cannot change the category a given behavior belongs to, that
relationship is hardcoded in \common\models\Category. But if that
definition were updated, behaviors that were selected in previous
check-ins would be unaltered. That's good.

Also, soon enough we will support "custom behaviors", which can be
deleted or recategorized at will. The changes in this PR will correctly
preserve history even when a custom behavior is modified.
  • Loading branch information...
CorWatts committed Aug 29, 2019
1 parent 41f8482 commit de078e40fa5318533f3eca02d372b3567ce146c4
@@ -6,10 +6,8 @@ interface UserBehaviorInterface extends \yii\db\ActiveRecordInterface {
public function getUser();
public function getPastCheckinDates();
public function getUserBehaviorsWithCategory($checkin_date);
public function getBehaviorsByDate($start, $end);
public function getBehaviorsByCategory(array $decorated_behaviors);
public function getCheckinBreakdown(int $period);
public static function decorate(array $uo, $with_category);
public static function decorateWithCategory(array $uo);
public static function decorate(array $uo);
public function getBehaviorsWithCounts($limit);
}
@@ -10,6 +10,7 @@
'contentType' => 'image/png',
'setDisposition' => 'inline'
]);
$categories = \common\models\Category::getCategories();
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@@ -189,11 +190,11 @@

<?php
if($user_behaviors) {
foreach($user_behaviors as $user_behavior) { ?>
foreach($user_behaviors as $cat_key => $behaviors) { ?>
<p style="Margin:0;Margin-bottom:10px;color:#0a0a0a;font-family:Arial,Verdana,Helvetica,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0 8px 4px 8px;text-align:left">
<strong style="color:#37b98f"><?= $user_behavior['category_name'] ?></strong>
<strong style="color:#37b98f"><?= $categories[$cat_key] ?></strong>
<?php
foreach($user_behavior['behaviors'] as $behavior) { ?>
foreach($behaviors as $behavior) { ?>
<br><?= $behavior['name'] ?>
<?php
}
@@ -188,8 +188,23 @@ public function getCategories() {
return $cats;
}
/**
*
/**
* Given a $key => $value pair, returns the matching behavior.
* Example:
* getBehavior('id', 1);
* Should return:
* ['id' => 1, 'name' => 'no current secrets', 'category_id' => 1]
*
* @param string $key the name of the attribute to filter on
* @param string $val the value of the attribute to filter on
* @return a single behavior
*/
public static function getBehavior($key, $val) {
$indexed = AH::index(self::$behaviors, null, $key);
return AH::getValue($indexed, $val, [false])[0];
$ret = array_values(array_filter(self::$behaviors, function($bvr) use ($key, $val) {
return $bvr[$key] === $val;
}));
return $ret ? $ret[0] : null;
}
}
@@ -74,12 +74,35 @@ public function attributeLabels()
];
}
/**
* getCategories() returns a array of categories indexed by the category id.
* The format is similar to:
* [
* 1 => 'Restoration',
* 2 => 'Forgetting Priorities',
* ...
* ]
* @return array of categories
*/
public static function getCategories() {
return AH::map(\common\models\Category::$categories, 'id', 'name');
}
/**
* Given a $key => $value pair, returns the matching category.
* Example:
* getCategory('id', 1);
* Should return:
* [ "id" => 1, "name" => "Restoration"]
*
* @param string $key the name of the attribute to filter on
* @param string $val the value of the attribute to filter on
* @return a single category
*/
public static function getCategory($key, $val) {
$indexed = AH::index(self::$categories, null, $key);
return AH::getValue($indexed, $val, [false])[0];
$ret = array_values(array_filter(self::$categories, function($cat) use ($key, $val) {
return $cat[$key] === $val;
}));
return $ret ? $ret[0] : null;
}
}
@@ -10,13 +10,13 @@
* @property integer $id
* @property integer $user_id
* @property integer $behavior_id
* @property integer $category_id
* @property integer $user_behavior_id
* @property integer $question
* @property string $answer
* @property string $date
*
* @property User $user
* @property Behavior $behavior
* @property UserBehaviorLink $userBehavior
*/
class Question extends ActiveRecord implements QuestionInterface
@@ -49,9 +49,10 @@ public static function tableName()
public function rules()
{
return [
[['user_id', 'behavior_id', 'user_behavior_id', 'question', 'answer', 'date'], 'required'],
[['user_id', 'behavior_id', 'user_behavior_id', 'question'], 'integer'],
[['user_id', 'behavior_id', 'category_id', 'user_behavior_id', 'question', 'answer', 'date'], 'required'],
[['user_id', 'behavior_id', 'category_id', 'user_behavior_id', 'question'], 'integer'],
['behavior_id', 'in', 'range' => array_column(\common\models\Behavior::$behaviors, 'id')],
['category_id', 'in', 'range' => array_column(\common\models\Category::$categories, 'id')],
['answer', 'string'],
['date', 'safe']
];
@@ -66,6 +67,7 @@ public function attributeLabels()
'id' => 'ID',
'user_id' => 'User ID',
'behavior_id' => 'Behavior ID',
'category_id' => 'Category ID',
'user_behavior_id' => 'User Behavior ID',
'question' => 'Question',
'answer' => 'Answer',
@@ -391,7 +391,7 @@ public function sendEmailReport($date) {
->get(\common\components\Graph::class)
->create($checkins_last_month);
$user_behaviors = $this->getUserBehaviors($date);
$user_behaviors = $user_behavior->getByDate(Yii::$app->user->id, $date);
$user_questions = $this->getUserQuestions($date);
$messages = [];
@@ -422,6 +422,7 @@ public function getExportData() {
'l.id,
l.date AS "date",
l.behavior_id AS "behavior_id",
l.category_id AS "category_id",
(SELECT q1.answer
FROM question q1
WHERE q1.question = 1
@@ -516,14 +517,6 @@ public function getUserQuestions($local_date = null) {
return $this->parseQuestionData($questions);
}
public function getUserBehaviors($local_date = null) {
if(is_null($local_date)) $local_date = $this->time->getLocalDate();
$behaviors = $this->getBehaviorData($local_date);
$behaviors = \common\models\UserBehavior::decorateWithCategory($behaviors);
return $this->parseBehaviorData($behaviors);
}
public function parseQuestionData($questions) {
if(!$questions) return [];
@@ -544,22 +537,6 @@ public function parseQuestionData($questions) {
return $question_answers;
}
public function parseBehaviorData($behaviors) {
if(!$behaviors) return [];
$opts_by_cat = [];
foreach($behaviors as $behavior) {
$indx = $behavior['behavior']['category_id'];
$opts_by_cat[$indx]['category_name'] = $behavior['behavior']['category']['name'];
$opts_by_cat[$indx]['behaviors'][] = [
"id" => $behavior['behavior_id'],
"name"=>$behavior['behavior']['name']];
}
return $opts_by_cat;
}
public function getQuestionData($local_date) {
list($start, $end) = $this->time->getUTCBookends($local_date);
@@ -581,22 +558,6 @@ public function getQuestionData($local_date) {
return $questions;
}
public function getBehaviorData($local_date) {
list($start, $end) = $this->time->getUTCBookends($local_date);
$user_behavior = Yii::$container->get(UserBehaviorInterface::class);
return $user_behavior->find()
->where("user_id=:user_id
AND date > :start_date
AND date < :end_date",
[
"user_id" => Yii::$app->user->id,
':start_date' => $start,
":end_date" => $end
])
->asArray()
->all();
}
public function cleanExportData($data) {
$order = array_flip(["date", "behavior", "category", "question1", "question2", "question3"]);
@@ -607,10 +568,11 @@ function($row) use ($order) {
$row['date'] = $this->time->convertUTCToLocal($row['date'], false);
// clean up things we don't need
$row['category'] = $row['behavior']['category']['name'];
$row['category'] = $row['category']['name'];
$row['behavior'] = $row['behavior']['name'];
unset($row['id']);
unset($row['behavior_id']);
unset($row['category_id']);
// sort the array into a sensible order
uksort($row, function($a, $b) use ($order) {

0 comments on commit de078e4

Please sign in to comment.
You can’t perform that action at this time.