Ankiレビュー数の増加

Ankiはフラッシュカードシステム。復習間隔をスケジューリングしてくれる。気になるのは復習するカードが膨大になるんじゃないかということ。そこで、レビュー数(復習+追加)がどうなるかプログラムでチェック。数式でモデリングできそうだけど、数学は頭が錆びついて断念。

  • 一日に10枚と20枚追加する2パターン
  • 正解を続ければ1日、2日、4日、8日...と復習間隔が伸びる
  • 誤答すれば、復習間隔はそのまま
  • 誤答率は、10%、30%、50%の3パターン

結果


レビュー数は始めの3ヶ月ぐらいは急に増えるが、半年ぐらいになると増加は緩やかになる。

確認用スクリプト

#!/usr/bin/perl
use strict;
use warnings;
use GD::Graph::lines;

my $end = shift // 500;

my @data = ( [ 0 .. $end ] );
my @dataset = ();
my $add_per_day;

# Add 10 per day
$add_per_day = 10;
$data[1] = [ simulate_review( $end, 0.1, $add_per_day ) ];
$data[2] = [ simulate_review( $end, 0.3, $add_per_day ) ];
$data[3] = [ simulate_review( $end, 0.5, $add_per_day ) ];
@dataset = (
    "Fail 0.1, Add $add_per_day",
    "Fail 0.3, Add $add_per_day",
    "Fail 0.5, Add $add_per_day",
);

draw_lines( 'anki_add10.jpg', \@data, \@dataset );

# Add 20 per day
$add_per_day = 20;
$data[1] = [ simulate_review( $end, 0.1, $add_per_day ) ];
$data[2] = [ simulate_review( $end, 0.3, $add_per_day ) ];
$data[3] = [ simulate_review( $end, 0.5, $add_per_day ) ];
@dataset = (
    "Fail 0.1, Add $add_per_day",
    "Fail 0.3, Add $add_per_day",
    "Fail 0.5, Add $add_per_day",
);

draw_lines( 'anki_add20.jpg', \@data, \@dataset );

sub simulate_review {
    my $end         = shift // 500;
    my $fail_rate   = shift // 0.3;
    my $add_per_day = shift // 20;

    my @words = ();
    my @data  = ();
    for my $today ( 1 .. $end ) {
        my $review = 0;
        for my $word (@words) {
            $word->{rest}--;
            if ( $word->{rest} <= 0 ) {
                $review++;
                if ( rand > $fail_rate ) {
                    $word->{interval} *= 2;
                }
                $word->{rest} = $word->{interval};
            }
        }
        $data[ $today - 1 ] = $review;

        # Add new word
        for ( 1 .. $add_per_day ) {
            push @words, { interval => 1, rest => 1 };
        }
    }
    return @data;
}

sub draw_lines {
    my $file        = shift;
    my $data_ref    = shift;
    my $dataset_ref = shift;

    my $graph = GD::Graph::lines->new( 400, 400 );
    $graph->set(
        title            => 'Number Of Reviews using ANKI',
        x_label          => 'Day',
        y_label          => 'Review',
        y_max_value      => 350,
        x_label_skip     => 100,
        x_label_position => 0.5,
        r_margin         => 10,
        dclrs            => [qw(black red green)],
        line_types       => [qw(1 1 1)],
    );
    $graph->set_legend(@$dataset_ref) or die "$!";

    my $image = $graph->plot($data_ref);

    open my $fh, '>', $file or die "$file:$!";
    binmode $fh;
    print {$fh} $image->jpeg();
    close $fh or die "$file:$!";
}