diff --git a/Helper/QualKardHelper.php b/Helper/QualKardHelper.php new file mode 100644 index 0000000..a0a1c53 --- /dev/null +++ b/Helper/QualKardHelper.php @@ -0,0 +1,121 @@ + 0.0, 'hard' => 1.3, 'medium' => 3.0, 'easy' => 5.0); + + /** + * Running average. New card (unread, $old === null) seeds at N - 23%; otherwise the qualcard mean. + */ + public static function nextAverage($old, $score) + { + return $old === null ? ($score - 0.23 * $score) : (($old + $score) / 2.0); + } + + /** + * Average -> review interval in days (qualcard grades G..A). + */ + public static function intervalDays($avg) + { + if ($avg <= 0.60) { + return 1; // G + } + if ($avg <= 1.35) { + return 2; // F + } + if ($avg <= 2.20) { + return 3; // E + } + if ($avg <= 3.05) { + return 5; // D + } + if ($avg <= 3.90) { + return 7; // C + } + if ($avg <= 4.92) { + return 9; // B + } + + return 11; // A + } + + /** + * Next due timestamp: midnight, intervalDays() out. + */ + public static function dueFrom($avg, $now = null) + { + $now = $now ?: time(); + + return strtotime('+'.self::intervalDays($avg).' days', strtotime('today', $now)); + } + + /** + * Mastery badge for a card's average: label + CSS class. null (unread) = "new" (yellow); otherwise + * a percent of 5, coloured red (<50) / green (<90) / blue (>=90). + * + * @param float|null $avg + * @return array{label:string,class:string} + */ + public static function badge($avg) + { + if ($avg === null) { + return array('label' => t('new'), 'class' => 'qk-new'); + } + + $pct = (int) round($avg / 5.0 * 100); + $class = $pct < 50 ? 'qk-low' : ($pct < 90 ? 'qk-mid' : 'qk-high'); + + return array('label' => $pct.'%', 'class' => $class); + } + + /** + * Is QualKard enabled for this board? + * + * @param int $project_id + * @return bool + */ + public function isEnabled($project_id) + { + return (int) $this->projectMetadataModel->get($project_id, 'qualkard_enabled', 0) === 1; + } + + /** + * Is the RecoReco plugin installed? (QualKard needs its move engine.) + * + * @return bool + */ + public function hasRecoReco() + { + foreach ($this->container['pluginLoader']->getPlugins() as $plugin) { + if ($plugin->getPluginName() === 'RecoReco') { + return true; + } + } + + return false; + } + + /** + * The column id stored for a board role ('draft', 'study', 'hairy', ... , 'done'). + * + * @param int $project_id + * @param string $role + * @return int + */ + public function col($project_id, $role) + { + return (int) $this->projectMetadataModel->get($project_id, 'qualkard_col_'.$role, 0); + } +}