For AI agents: the complete documentation index is available at https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/llms.txt, the full documentation bundle is available at https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/llms-full.txt, and this page is available as Markdown at https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/guide/scheduler/default-scheduler.md.
  • 繁體中文
  • DefaultScheduler

    DefaultScheduler 是非同步工廠,回傳一個可直接使用的排程器實例。它把模型(預設 FSRS-7)與 dateChrono 以及標準排程策略組合在一起,因此你只需設定它的選項。內部它與自訂 defineScheduler 使用同一套「定義與實例」機制——預設只是把各部分裝配起來的便利方式。

    選項

    從 FSRS-3~6 升級至 FSRS-7 時,省略 weights 以使用 FSRS-7 預設權重,或提供為 FSRS-7 訓練的權重。重播歷史用於重建卡片狀態,不會轉換舊版權重。

    FSRS-7 卡片除了 stability 與 difficulty,還包含 stabilityFast。舊版 FSRS-3~6 的記憶狀態需透過 Reschedule 重播複習歷史來重建;參數遷移不會遷移卡片狀態,不應以 0.8 * stability 推測演化後的快速軌跡。預設為 FSRS-7 啟用小數天數;enableShortTerm: false 只停用明確的學習步驟,不會停用模型的快速軌跡。

    需要成本自適應保留率時,自行組合定義,以 schedulerCostAdrMiddleware 取代 schedulerDesiredRetentionMiddleware。Cost ADR 不是 DefaultScheduler 選項。

    scheduler.nextInterval(memoryState, desiredRetention, { card, grade, elapsedDays }) 查詢已計算的評分後狀態所對應的間隔,只執行 handlers.nextInterval,不推進卡片或 chrono;共用間隔策略應放在這個掛鉤中。

    選項預設用途
    version'FSRS-7'選擇 FSRS 模型:'FSRS-3'、'FSRS-4'、'FSRS-4.5'、'FSRS-5', 'FSRS-6' 或 'FSRS-7'。FSRS-7 無法遷移舊版 FSRS-3~6 的權重。
    weights預設權重選用的訓練權重;省略時使用所選版本的預設值。FSRS-7 需要恰好 34 個 FSRS-7 權重;傳入舊版權重會在建立排程器時拋出例外。
    desiredRetention0.9在計算間隔前套用的目標保留率。
    enableShortTermtrue啟用學習與再學習步驟。
    learningSteps['1m', '10m']enableShortTerm 開啟時套用的學習步驟。
    relearningSteps['10m']enableShortTerm 開啟時套用的再學習步驟。
    graduatingInterval1卡片處於 Review 時的最短間隔(天)。最終間隔更短時,卡片維持 Learning/Relearning。設定了步驟時,走完步驟以及 Review 卡片按 Hard、Good、Easy 都至少使用這個間隔。
    allowModelOverrideFSRS-7: true; 其他版本: false模型間隔比目前步驟長時,改用模型間隔。Again 不超過 graduatingInterval;Hard、Good 的間隔達到 graduatingInterval 時提前畢業。
    enableFuzzfalse開啟時分散間隔以增加變化。
    maximumInterval36500間隔的天數上限。
    clearStatsOnForgettrueforget 是否清空 reps 與 lapses。

    DefaultScheduler 始終使用 dateChrono,並依中介軟體頁面所述的順序組合標準策略:目標保留率、模糊間隔、統計、scheduled days、學習步驟、最大間隔、單調間隔。選擇 version 只改變模型及其參數,不改變這套策略。

    import { 
    function DefaultScheduler<Version extends DefaultSchedulerVersion = "FSRS-7">(options?: DefaultSchedulerOptions<Version>): Promise<DefaultScheduler<Version>>
    type DefaultScheduler<Version extends DefaultSchedulerVersion = "FSRS-7"> = (Version extends "FSRS-7" ? Omit<SchedulerCore<SchedulerCoreEnv<SchedulerEnvFor<FSRS7DefaultSchedulerModel, Chrono<{
        readonly time: SRSSchema<{
            input: Date;
            output: Date;
        }>;
        readonly config: SRSSchema<{
            input: {
                readonly fractionalDays?: boolean | undefined;
            };
            output: {
                readonly fractionalDays: boolean;
            };
        }>;
        readonly fields: {
            readonly card: SRSSchema<{
                input: {
                    dueAt: Date;
                    lastReviewAt?: (Date | null) | undefined;
                };
                output: {
                    dueAt: Date;
                    lastReviewAt: Date | null;
                };
            }>;
            readonly revlog: SRSSchema<{
                input: {
                    dueAt: Date;
                    lastReviewAt?: (Date | null) | undefined;
                    reviewTime: Date;
                };
                output: {
                    dueAt: Date;
                    lastReviewAt: Date | null;
                    reviewTime: Date;
                };
            }>;
        };
    }>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>, "definition"> : Omit<...> & {
        ...;
    }) & {
        ...;
    }
    DefaultScheduler
    ,
    type Rating = 0 | 1 | 2 | 3 | 4
    const Rating: Readonly<{
        readonly Manual: 0;
        readonly Again: 1;
        readonly Hard: 2;
        readonly Good: 3;
        readonly Easy: 4;
    }>
    Rating
    } from 'ts-fsrs'
    const now = new Date('2026-01-01T00:00:00.000Z') const
    const scheduler: DefaultScheduler<"FSRS-7">
    scheduler
    = await
    DefaultScheduler<"FSRS-7">(options?: DefaultSchedulerOptions<"FSRS-7"> | undefined): Promise<DefaultScheduler<"FSRS-7">>
    DefaultScheduler
    ({
    DefaultSchedulerOptions<"FSRS-7">.version?: "FSRS-7" | undefined

    FSRS model and parameter migration version; defaults to FSRS-7.

    version
    : 'FSRS-7',
    DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.desiredRetention?: number | undefined
    desiredRetention
    : 0.9,
    DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.enableShortTerm?: boolean | undefined

    Enable explicit learning steps. FSRS-7 always retains its intrinsic fast trace.

    enableShortTerm
    : true,
    DefaultSchedulerOptions<"FSRS-7">.learningSteps?: readonly (`${number}d` | `${number}m` | `${number}h`)[] | undefined

    Defaults to ['1m', '10m'].

    learningSteps
    : ['1m', '10m'],
    DefaultSchedulerOptions<"FSRS-7">.relearningSteps?: readonly (`${number}d` | `${number}m` | `${number}h`)[] | undefined

    Defaults to ['10m'].

    relearningSteps
    : ['10m'],
    DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.enableFuzz?: boolean | undefined
    enableFuzz
    : false,
    DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.maximumInterval?: number | undefined
    maximumInterval
    : 36_500,
    }) const
    const card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    }
    card
    =
    const scheduler: DefaultScheduler<"FSRS-7">
    scheduler
    .
    newCard: (options?: ({
        readonly cardId?: string | number | undefined;
    } & {
        readonly now?: Date | undefined;
    }) | undefined) => {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    }
    newCard
    ({ cardId: 'quick-start', now })
    const
    const result: {
        card: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            lapses: number;
            scheduledDays: number;
            learningStep: number;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
        };
        revlog: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            scheduledDays: number;
            learningStep: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
            rating: Grade;
        };
    }
    result
    =
    const scheduler: DefaultScheduler<"FSRS-7">
    scheduler
    .
    review: (input: {
        readonly card: Readonly<Omit<Readonly<{
            stabilityFast: number;
            stability: number;
            difficulty: number;
        } & {
            dueAt: Date;
            lastReviewAt: Date | null;
        } & {
            readonly cardId: string | number;
            readonly reps: number;
            readonly lapses: number;
            readonly scheduledDays: number;
            readonly learningStep?: number | undefined;
        } & SchedulerCoreFields$1<"review" | "new" | "learning">>, keyof SchedulerCoreFields$1<"review" | "new" | "learning">> & SchedulerCoreFields$1<"review" | "new" | "learning">>;
        readonly grade: Grade;
        readonly now?: Date | undefined;
    }) => {
        ...;
    }
    review
    ({ card, grade:
    const Rating: Readonly<{
        readonly Manual: 0;
        readonly Again: 1;
        readonly Hard: 2;
        readonly Good: 3;
        readonly Easy: 4;
    }>
    Rating
    .Good, now })
    console.log( JSON.stringify( { state:
    const result: {
        card: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            lapses: number;
            scheduledDays: number;
            learningStep: number;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
        };
        revlog: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            scheduledDays: number;
            learningStep: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
            rating: Grade;
        };
    }
    result
    .
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    }
    card
    .state,
    dueAt:
    const result: {
        card: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            lapses: number;
            scheduledDays: number;
            learningStep: number;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
        };
        revlog: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            scheduledDays: number;
            learningStep: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
            rating: Grade;
        };
    }
    result
    .
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    }
    card
    .dueAt,
    stability:
    const result: {
        card: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            lapses: number;
            scheduledDays: number;
            learningStep: number;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
        };
        revlog: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            scheduledDays: number;
            learningStep: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
            rating: Grade;
        };
    }
    result
    .
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    }
    card
    .stability,
    stabilityFast:
    const result: {
        card: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            lapses: number;
            scheduledDays: number;
            learningStep: number;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
        };
        revlog: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            scheduledDays: number;
            learningStep: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
            rating: Grade;
        };
    }
    result
    .
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    }
    card
    .stabilityFast,
    difficulty:
    const result: {
        card: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            lapses: number;
            scheduledDays: number;
            learningStep: number;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
        };
        revlog: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            scheduledDays: number;
            learningStep: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
            rating: Grade;
        };
    }
    result
    .
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    }
    card
    .difficulty,
    rating:
    const result: {
        card: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            lapses: number;
            scheduledDays: number;
            learningStep: number;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
        };
        revlog: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            scheduledDays: number;
            learningStep: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
            rating: Grade;
        };
    }
    result
    .
    revlog: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        scheduledDays: number;
        learningStep: number;
        reviewTime: Date;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
        rating: Grade;
    }
    revlog
    .rating,
    }, null, 2 ) )

    該工廠是非同步的,使用回傳的實例前要先 await DefaultScheduler(...)。範例把常用預設值寫得很明確:version、desiredRetention、學習與再學習步驟、模糊間隔和 maximumInterval。省略 weights 即用所選 FSRS 版本的預設。

    預設還是自訂定義

    當預設的 FSRS 模型、dateChrono 與標準策略集契合你的產品時,用 DefaultScheduler——這是最快且正確的起點。當需要不同的模型或 chrono、增減策略,或需要為每個使用者驗證設定時,用 defineScheduler。二者最終都落到同一套排程器實例 API(newCard、review、rollback、preview 與 forget)。定義與實例模型見排程器概覽。