diff --git a/Helper/QualKardHelper.php b/Helper/QualKardHelper.php index 3cfdb78..4452011 100644 --- a/Helper/QualKardHelper.php +++ b/Helper/QualKardHelper.php @@ -17,6 +17,11 @@ class QualKardHelper extends Base { const SCORE = array('hairy' => 0.0, 'hard' => 1.3, 'medium' => 3.0, 'easy' => 5.0); + // Stored qualkard_avg value for an unread card. A literal, non-empty marker: it survives PHP's + // empty() -- which drops the numeric string "0" on save -- and stays distinct from a real average + // of 0 (a card graded hairy from new). Graded averages are stored with decimals for the same reason. + const UNREAD = 'new'; + /** * Running average. New card (unread, $old === null) seeds at N - 23%; otherwise the qualcard mean. */ @@ -81,6 +86,18 @@ class QualKardHelper extends Base return array('label' => $pct.'%', 'class' => $class); } + /** + * A stored qualkard_avg -> float, or null when the card is unread. The unread marker is the + * literal self::UNREAD; '' and null are also treated as unread for any card written before it. + * + * @param string|null $raw + * @return float|null + */ + private static function parseAvg($raw) + { + return ($raw === '' || $raw === null || $raw === self::UNREAD) ? null : (float) $raw; + } + /** * Is QualKard enabled for this board? * @@ -168,7 +185,7 @@ class QualKardHelper extends Base } $this->taskPositionModel->movePosition($project_id, $task_id, $this->col($project_id, 'draft'), 1, (int) $task['swimlane_id'], false); - $this->taskMetadataModel->save($task_id, array('qualkard_avg' => '')); // '' = unread + $this->taskMetadataModel->save($task_id, array('qualkard_avg' => self::UNREAD)); // brand-new card $this->arm($task_id, $project_id); $this->db->table(TaskModel::TABLE)->eq('id', $task_id)->update(array('date_due' => 0)); } @@ -194,13 +211,14 @@ class QualKardHelper extends Base */ public function grade($task_id, $score) { - $raw = $this->taskMetadataModel->get($task_id, 'qualkard_avg', ''); - $old = ($raw === '' || $raw === null) ? null : (float) $raw; + $raw = $this->taskMetadataModel->get($task_id, 'qualkard_avg', self::UNREAD); + $old = self::parseAvg($raw); $avg = self::nextAverage($old, $score); $due = self::dueFrom($avg); + // Store with decimals so an exact 0 is "0.0000", never the empty()-dropped "0". $this->taskMetadataModel->save($task_id, array( - 'qualkard_avg' => (string) $avg, + 'qualkard_avg' => sprintf('%.4f', $avg), 'recoreco_anchor' => $due, )); $this->db->table(TaskModel::TABLE)->eq('id', $task_id)->update(array('date_due' => $due)); @@ -214,9 +232,8 @@ class QualKardHelper extends Base */ public function cardBadge($task_id) { - $raw = $this->taskMetadataModel->get($task_id, 'qualkard_avg', ''); - $avg = ($raw === '' || $raw === null) ? null : (float) $raw; + $raw = $this->taskMetadataModel->get($task_id, 'qualkard_avg', self::UNREAD); - return self::badge($avg); + return self::badge(self::parseAvg($raw)); } } diff --git a/Plugin.php b/Plugin.php index ee8d733..4b68c9d 100644 --- a/Plugin.php +++ b/Plugin.php @@ -81,7 +81,7 @@ class Plugin extends Base public function getPluginVersion() { - return '1.0.0'; + return '1.1.0'; } public function getPluginHomepage() diff --git a/VERSION b/VERSION index 71749bb..f2a2316 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -QualKard v1.0 +QualKard v1.1