Skip to content

Instantly share code, notes, and snippets.

@gquemener
Last active September 7, 2022 07:11
Show Gist options
  • Save gquemener/de9daa5d6891c83384e9 to your computer and use it in GitHub Desktop.
Save gquemener/de9daa5d6891c83384e9 to your computer and use it in GitHub Desktop.
SuperMemo 2 PHP Implementation
composer.lock
/vendor
{
"require": {
"symfony/console": "~2.6"
}
}
<?php
require 'vendor/autoload.php';
function calcInterval($time = 1, $factor = 2.5, $oldInterval=1)
{
if ($time < 1) {
throw new \Exception('The number of repetitions must be 1 or higher');
}
if ($time == 1) {
$interval = 1;
} elseif ($time == 2) {
$interval = 6;
} else {
$interval = $oldInterval * $factor;
}
return ceil($interval);
}
function calcNewFactor($oldFactor = 2.5, $quality = 4)
{
if ($quality > 5 || $quality < 0) {
throw new \Exception('Quality must be between 0 and 5');
}
$newFactor = $oldFactor + (0.1 - (5 - $quality) * (0.08 + (5 - $quality) * 0.02));
return max($newFactor, 1.3);
}
$output = new \Symfony\Component\Console\Output\BufferedOutput();
$table = new \Symfony\Component\Console\Helper\Table($output);
$table->setHeaders(['', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']);
for ($q = 1; $q < 6; $q++) {
$oldInterval = 1;
$oldFactor = 2.5;
$row = [$q];
for ($n = 1; $n < 11; $n++) {
$oldFactor = calcNewFactor($oldFactor, $q);
$oldInterval = calcInterval($n, $oldFactor, $oldInterval);
$row[] = $oldInterval;
}
$table->addRow($row);
}
$table->render($output);
echo $output->fetch();
# +---+---+---+----+----+-----+-----+------+------+-------+-------+
# | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
# +---+---+---+----+----+-----+-----+------+------+-------+-------+
# | 1 | 1 | 6 | 8 | 11 | 15 | 20 | 26 | 34 | 45 | 59 |
# | 2 | 1 | 6 | 10 | 13 | 17 | 23 | 30 | 39 | 51 | 67 |
# | 3 | 1 | 6 | 13 | 26 | 47 | 79 | 121 | 167 | 218 | 284 |
# | 4 | 1 | 6 | 15 | 38 | 95 | 238 | 595 | 1488 | 3720 | 9300 |
# | 5 | 1 | 6 | 17 | 50 | 151 | 469 | 1501 | 4954 | 16844 | 58955 |
# +---+---+---+----+----+-----+-----+------+------+-------+-------+
<?php
require 'vendor/autoload.php';
function calcInterval($time = 1, $factor = 2.5)
{
if ($time < 1) {
throw new \RangeException('The number of repetitions must be 1 or higher');
}
if ($time == 1) {
$interval = 1;
} elseif ($time == 2) {
$interval = 6;
} else {
$interval = calcInterval($time - 1, $factor) * $factor;
}
return ceil($interval);
}
function calcNewFactor($oldFactor = 2.5, $quality = 4)
{
if ($quality > 5 || $quality < 0) {
throw new \Exception('Quality must be between 0 and 5');
}
$newFactor = $oldFactor + (0.1 - (5 - $quality) * (0.08 + (5 - $quality) * 0.02));
return $newFactor > 1.3 ? ($newFactor < 2.5 ? $newFactor : 2.5) : 1.3;
}
$output = new \Symfony\Component\Console\Output\BufferedOutput();
$table = new \Symfony\Component\Console\Helper\Table($output);
$table->setHeaders(['', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']);
for ($q = 1; $q < 6; $q++) {
$oldInterval = 1;
$oldFactor = 2.5;
$row = [$q];
for ($n = 1; $n < 11; $n++) {
$oldFactor = calcNewFactor($oldFactor, $q);
$oldInterval = calcInterval($n, $oldFactor, $oldInterval);
$row[] = $oldInterval;
}
$table->addRow($row);
}
$table->render($output);
echo $output->fetch();
# +---+---+---+----+----+----+-----+-----+------+------+------+
# | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
# +---+---+---+----+----+----+-----+-----+------+------+------+
# | 1 | 1 | 6 | 8 | 11 | 15 | 20 | 26 | 34 | 45 | 59 |
# | 2 | 1 | 6 | 10 | 11 | 15 | 20 | 26 | 34 | 45 | 59 |
# | 3 | 1 | 6 | 13 | 24 | 36 | 49 | 58 | 49 | 45 | 59 |
# | 4 | 1 | 6 | 15 | 38 | 95 | 238 | 595 | 1488 | 3720 | 9300 |
# | 5 | 1 | 6 | 15 | 38 | 95 | 238 | 595 | 1488 | 3720 | 9300 |
# +---+---+---+----+----+----+-----+-----+------+------+------+
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment