npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@ig3/srf-scheduler

v2.1.3

Published

This is the default scheduler for [srf](https://www.npmjs.com/package/@ig3/srf) - spaced repetition flashcards.

Downloads

17

Readme

@ig3/srf-scheduler

This is the default scheduler for srf - spaced repetition flashcards.

It's primary functions are:

  • selecting a card for review
  • re-scheduling a card after review

It controls two aspects of study:

  • average study time per day
  • percentage of cards successfully recalled

installation

$ npm install @ig3/srf-scheduler

If you install srf, this scheduler will be installed as one of its dependencies. There should be no need to install this independently.

Algorithms

new cards

Average study time per day is controlled by adjusting the presentation of new cards. New cards are usually presented interleaved with review cards. If average study time is very low, they may be presented without intervening review cards. If average study time is high, new cards will not be presented.

New cards are presented if:

  • average study time < configured target study time;
  • new cards in the past 24 hours < configured max new cards per day; and
  • there are no overdue cards

If average study time is less than configured minimum study time, then new cards are presented if there are no cards due, until the daily limit on new cards is reached.

For these controls, average study time is determined from:

  • actual study time in the past 24 hours
  • predicted study time in the next 24 hours
  • actual average study time in the past 14 days of study

The number of reviews between new cards is adjusted according to the ratio of average study time to target study time per day, the number of cards due in the next 24 hours and the recent average number of new cards per day.

For this control, average study time is the actual average study time over the previous 14 days of study. This excludes the current day and days on which no reviews were done.

review card selection

Every card that has been viewed has a time when it is scheduled to be reviewed.

If there is more than one card past its scheduled review time, then one of two algorithms is used to select the next card for review:

  • shortest interval first
  • earliest due first

The algorithm is selected randomly, with probability of the earliest due cards being selected first determined by configuration parameter probabilityOldestDue.

For both algorithms, the first five cards are determined and one of these is selected at random.

interval adjustments

Interval is the interval between card reviews. The interval of a card is updated each time it is reviewed, according to its 'ease' (Fail, Hard, Good or Easy). Interval (and due date) are also adjusted after any card with an interval greater than learningThreshold is reviewed, according to the difference between 'percent correct' and percentCorrectTarget.

Fail

If the ease of a review is Fail, then the new interval is the previous interval multiplied by failFactor, with an upper bound of failLearningMaxInterval if the previous interval was less than learningThreshold or failMaxInterval otherwise.

Hard

If the ease of a review is Hard, then the new interval is the previous interval multiplied by hardFactor, with an upper bound of hardLearningMaxInterval if the previous interval was less than learningThreshold or hardMaxInterval otherwise.

Good

If the ease of a review is Good, then the new interval is the greater of

  • goodMinInterval
  • actual time since last review multiplied by goodMinFactor
  • actual time since last review multiplied by the product of goodFactor and the card factor

The new interval is limited to the lesser of maxInterval or maxGoodInterval.

The card factor is the exponentially weighted moving average of ease weights, with a decay factor of decayFactor and ease weights of weightFail, weightHard, weightGood and weightEasy. This reflects how easy or difficult the card has been recently.

Time since last review is used to calculate the new interval, rather than the previously scheduled interval. This will typically be longer than the previously sechedule interval because it is unlikely that the card will be reviewed as soon as it is due.

This makes most difference for learning cards or in the case of a backlog.

For learning cards, assuming one is not studying all day, there will be breaks in study. If a card has an interval of one hour but one does not study again until the next day, then the scheduled interval is one hour but the actual time since last review might be closer to 24 hours. If the card remains good after 24 hours, despite being scheduled for review in one hour, then the longer, actual interval is indicative of ability to recall the card.

In the case of a backlog, a card might not be reviewed until long after it was scheduled for review. Again, the longer actual interval is more indicative of ability to recall the card.

Easy

If the ease of a review is Easy, then the new interval is the actual interval (i.e. time since the last review, rather than the interval scheduled at the last review) multiplied by the easyFactor and the card factor, with a minimum of easyMinInterval and maximum of the lower of maxEasyInterval and maxInteral.

Percent Correct

Whenever a card is reviewed with a new interval greater than learningThreshold, then the intervals and due dates of all cards with interval between learningThreshold and maxInterval are adjusted according to the difference between 'percent correct' and percentCorrectTarget, multiplied by percentCorrectSensitivity.

Configuration

The scheduler is configured by the following configuration parameters.

config.decayFactor

decayFactor determines the exponential decay of ease weight to determine the card ease factor. The resulting card ease factor is one of the factors that contributes the overall factor by which interval is increased for Good and Easy responses.

config.easyFactor

The interval for an Easy response is the interval for a Good response multiplied by easyFactor.

config.easyMinInterval

easyMinInterval is the minimum interval after an Easy response.

config.failFactor

failFactor is the factor by which interval is multiplied after a Fail response.

config.failLearningMaxInterval

failLearningMaxInterval is the maximum interval after a Fail response for a card with interval less than learningThreshold.

config.failMaxInterval

failMaxInterval is the maximum interval after a Fail response.

config.goodFactor

After a Good response, the interval is multiplied by goodFactor and the card ease factor. The product of these is the overal factor by which interval is multiplied.

config.goodMinFactor

goodMinFactor is the minimum factor by which interval is multiplied after a Good response.

config.goodMinInterval

goodMinInterval is the minimum interval after a Good response.

config.hardFactor

hardFactor is the factor by which interval is multiplied after a Hard response.

config.hardLearningMaxInterval

hardLearningMaxInterval is the maximum interval after a Hard response for a card with interval less than learningThreshold.

config.hardMaxInterval

hardMaxInterval is the maximum interval after a Hard response.

config.learningThreshold

learningThreshold is the threshold between cards being treated as 'new' and 'learning' cards.

Card intervals and due dates are modified periodically if their interval is between learningThreshold and maxInterval.

config.matureThreshold

matureThreshold is the threshold between cards being treaded as 'learning' and 'mature' cards.

config.maxEasyInterval

maxEasyInterval is an upper bound on interval after an Easy response.

config.maxGoodInterval

maxGoodInterval is an upper bound on interval after a Good response.

config.maxInterval

maxInterval is an upper bound on interval after a Good or Easy response.

config.maxNewCardsPerDay

maxNewCardsPerDay is the maximum number of new cards which may be presented in a 24 hour period.

config.maxViewTime

maxViewTime is an upper bound on view time recorded in revlog. It doesn't have anything to do with the scheduler. It is here for historic reasons, pending refactoring the processing of card reviews.

config.minPercentCorrectCount

minPercentCorrectCount is the minimum number of reviews of mature cards in the percentCorrectWindow in order that 'percent correct' is calculated. The 'percent correct' is a factor in adjusting the intervals and due dates of cards.

config.minStudyTime

minStudyTime is the minimum study time in a 24 hour period below which new cards will be presented in preference to due cards.

config.minTimeBetweenRelatedCards

Related cards are cares generated from the same field set. minTimeBetweenRelatedCards is the minimum time between reviews of related cards.

config.percentCorrectSensitivity

percentCorrectSensitivity is a factor that determines the sensitivity to the difference between 'percent correct' and percentCorrectTarget. It determines how much the intervals and due dates of cards are modified when adjusted for percent correct.

config.percentCorrectTarget

percentCorrectTarget is the target for 'percent correct'. Below this, intervals are reduced and due dates moved closer. Above this, intervals are increased and due dates moved further away.

config.percentCorrectWindow

percnetCorrectWindow is the window over which 'percent correct' is calculated. Reviews longer ago than this do not contribute.

config.probabilityOldestDue

probabilityOldestDue is the probability the scheduler will select cards according to due date rather than interval.

config.targetStudyTime

targetStudyTime is an upper bound on study time in a 24 hour period above which new cards will not be presented.

config.weightEasy

weightEasy is the weight of an Easy response in calculating the card ease factor by a process of moving average exponential decay.

config.weightFail

weightFail is the weight of a Fail response in calculating the card ease factor by a process of moving average exponential decay.

config.weightGood

weightGood is the weight of a Good response in calculating the card ease factor by a process of moving average exponential decay.

config.weightHard

weightHard is the weight of an Hard response in calculating the card ease factor by a process of moving average exponential decay.

API

getCountCardsDueToday

Returns the number of cards to be reviewed between now and the end of the current day in localtime, excluding deferred cards.

getIntervals(card)

Returns an object with the new interval for each possible ease for the given card.

getNewCardMode()

Returns 'go', 'slow' or 'stop'.

Go if new cards will be presented when there are no cards due.

Slow if new cards will be presented, interleaved with due cards but not if there are no cards due.

Stop if new cards will not be presented.

getNextCard(overrideLimits)

Returns the next card to be studied or undefined.

If overrideLimits is true then getNextCard returns the next due card if there is a card due, otherwise the next new card.

Otherwise, getNextCard returns the next new card if:

  • average study time in the past and next 24 hours is less than config.targetStudyTime; and
  • total new cards studied in the past 24 hours is less than config.maxNewCardsPerDay; and
  • there are no overdue cards; and
  • sufficient due cards have been reviewed since the last new card or there is no due card and average study time is less than config.minStudyTime

Otherwise, getNextCard returns the next due card if there is a card due.

Otherwise, getNextCard returns undefined.

getNextDue(overrideLimits)

getNextDueCard returns a card if one is due, otherwise undefined.

If overrideLimits is true then getNextDueCard one of the five cards with the earliest due dates, selected ramdomly, regardless of whether they are due before or after the current time.

Otherwise, getNextDue selects a sort algorithm randomly, according to config.probabilityOldestDue: sort by interval or sort by due.

In either case, one of the first 5 cards, according to the sort algorithm, is selected at random.

getNextNew

getNextnew returns a new card if one is available, otherwise undefined.

New cards (cards with interval = 0) are sorted by ord, then id.

New cards are ignored if a card from the same fieldset is due within config.minTimeBetweenRelatedCards or if a card from the same fieldset has been reviewed within config.minTimeBetweenRelatedCards.

getStatsNext24Hours

Returns an object with properties:

  • count
  • time

Where count is the number of cards due in the next 24 hours and time is the estimated time (seconds) to study all the cards due in the next 24 hours.

Count is the number of cards due within the next 24 hours, excluding deferred cards (multiple cards from the same fieldset due within minTimeBetweenRelatedCards) and including recent average number of new cards per day.

Time is an estimate of the time to review all these cards, based on recent performance.

getTimeNextDue

Returns the time (seconds since the epoch) when the card with the earliest due time is due. This may be in the past or in the future, depending on current backlog.

review(card, viewTime, studyTime, ease)

Updates the given card, setting new interval and due, according to ease and creates a revlog record recording the review of the card.

The new interval and due are calculated according to the ease.

Changes

1.0.1 - 20231007

  • README updates
  • Default config parameters relevant to the scheduler
  • Fix error in intervalEasy
  • Fix typo in getNextNew

1.0.2 - 20231008

  • Fix getStatsNext24Hours

1.1.0 - 20231011

  • Simplify and improve getAverageStudyTimePerNewCard and getAverageStudyTimePerOldCard
  • Refactor calculation of stats for next 24 hours
  • Improve getStatsNext24Hours - better estimates, including new cards
  • Add API method: getNewCardMode
  • refactor getNextCard to use getNewCardMode
  • Fix calculation of average new cards per day
  • Exclude current date from estimate of time per card and new cards per day
  • Refactor getNextCard and change new card interval

1.1.1 - 20231013

  • Adjust time between new cards according to average study time

1.1.2 - 20231014

  • Fix typo

1.1.3 - 20231014

  • Fix call to getAverageStudyTime

1.1.4 - 20231014

  • Add some tests - not very good but better than nothing

1.2.0 - 20231016

  • Add test for formatLocalDate
  • Introduce new cards slowly if predicted study time in the next 24 hours is more than config.minStudyTime.

1.3.0 - 20231016

  • Refactor formatLocalDate
  • Refactor getPercentCorrect
  • Refactor adjustCards
  • Refactor deferRelated
  • Refactor getCardsToReview
  • Refactor getAverageNewCardsPerDay
  • Refactor getAverageReviewsPerDay
  • Refactor getAverageStudyTime
  • Refactor timeForNewCard
  • Refactor minReviews
  • Add minReviews to getStatsNext24Hours result
  • Add config.newCardRateFactor
  • Base minReviews on cards to study next 24 hours not average

1.3.1 - 20231017

  • Test minReviews with 0 new cards per day

1.3.2 - 20231030

  • Don't include average new cards in stats for next 24 hours
  • Add test for getNewCardMode
  • Fix test of getStatsNext24Hours
  • Add test for getIntervals
  • Add test for getNextDue
  • Add test for getNextNew
  • Average study time over past and next 24 hours
  • Limit range of minReviews

2.0.0 - 20231125

  • Average study time over longer period to determine new card mode
  • Replace reviewsSinceLastNew with reviewsToNextNew

2.0.1 - 20231125

  • truncate reviewsToNextNew to integer on start

2.0.2 - 20240210

  • revise scheduling of new cards
  • fix typoe in newCardFactor
  • handle 'NaN' as card.factor (and other such invalid values)

2.0.3 - 20240314

  • Fix tests to handle reviewsPerNewCard parameter
  • Change intervalEasy to use actual interval

2.1.0 - 20240322

  • Introduce failLearningMaxInterval and hardLearningMaxInterval
  • Base interval for Good on actual interval

2.1.1 - 20240521

  • Make getReviewsToNextNew a bit more aggressive
  • Get new value for minReviews with each call to getStatsNext24Hours
  • Save reviews to next new card to database at each review
  • Limit reviews per new card
  • Update dependencies

2.1.2 - 20240814

  • Fix adjustCards to not set interval larger than maxInterval
  • Change test for reviewed cards from interval != 0 to interval > 0
  • Change test for new cards from interval = 0 to interval <= 0
  • Reduce minimum interval for Good to 2 minutes
  • Update dependencies
  • Replace tape with @ig3/test

2.1.3 - 20240912

  • Remove lapses