Better Anki forecasting for Review Heatmap with Anki Simulator
Review Heatmap is an addon for Anki that adds a heatmap showing past and future card review activity. It is handy to see at a glance whether there are any particularly heavy or light days coming up, and a colourful reward for regular reviews.
However, Review Heatmap bases its review forecasts only on cards' current intervals. For example, if I add a bunch of new cards today, I expect to see that I will have a heavy review load in 3 days when those cards are up for review, and regular periods thereafter. Review Heatmap cannot natively handle this projection.
Similarly, in the screenshot above, I have limited my maximum review interval to 30 days, so Review Heatmap does not display any information beyond 30 days.
Anki Simulator is an addon that can ‘simulate Anki progress over time … to estimate your future workload’. We can combine Anki Simulator with Review Heatmap to get the better forecasting that we desire.
Below is a simple Anki addon that extends Review Heatmap to make use of Anki Simulator:
DECK_ID = 1234567890123 # replace with the deck ID of the deck you need to forecast from datetime import datetime, timedelta import review_heatmap from review_simulator import collection_simulator, review_simulator class MWStandin: pass def mp_cardsDue(self, start=None, stop=None): mw = MWStandin() mw.col = self.col col_sim = collection_simulator.CollectionSimulator(mw) conf = self.col.decks.confForDid(DECK_ID) learningSteps = conf["new"]["delays"] lapseSteps = conf["lapse"]["delays"] dateArray = col_sim.generate_for_deck( DECK_ID, 365, # daysToSimulate conf["new"]["perDay"], # newCardsPerDay conf["new"]["initialFactor"] / 10.0, # startingEase len(learningSteps), len(lapseSteps), True, # includeOverdueCards True, # includeSuspendedNewCards 0, # newCardsToGenerate ) sim = review_simulator.ReviewSimulator( dateArray, 365, # daysToSimulate conf["new"]["perDay"], # newCardsPerDay conf["rev"]["ivlFct"], # intervalModifier conf["rev"]["perDay"], # maxReviewsPerDay learningSteps, lapseSteps, conf["new"]["ints"], # graduatingInterval conf["lapse"]["mult"], # newLapseInterval conf["rev"]["maxIvl"], # maxInterval  * len(learningSteps), # percentagesCorrectForLearningSteps  * len(lapseSteps), # percentagesCorrectForLapseSteps 100, # percentageGoodYoung 100, # percentageGoodMature 0, # Percentage hard is set to 0 0, # Percentage easy is set to 0 self.col.schedVer() ) result = sim.simulate() result_dt =  for entry in result: if entry['y']: dt = datetime.strptime(entry['x'], '%Y-%m-%d') dt += timedelta(days=1) # Appears to be necessary for some reason result_dt.append([int(dt.timestamp()), -entry['y']]) # Review Heatmap expects negative numbers return result_dt review_heatmap.activity.ActivityReporter._cardsDue = mp_cardsDue
This can be placed within the Anki addons directory, for example, at
Anki Simulator by default uses the historical percentage of correct cards to forecast future load, thereby resulting in slightly different results each time it is run. The above code disables this by setting the percentage of correct cards to 100%, so the results are deterministic. This does mean, however, that the results will be slightly inaccurate, particularly if the actual correct percentage is significantly less than 100%.
With this modified code, Review Heatmap now projects future reviews out as far as we need!