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.

Review Heatmap screenshot

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"][0], # graduatingInterval
		conf["lapse"]["mult"], # newLapseInterval
		conf["rev"]["maxIvl"], # maxInterval
		[100] * len(learningSteps), # percentagesCorrectForLearningSteps
		[100] * 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 ~/.local/share/Anki2/addons21/review_forecast/__init__.py.

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!

Modified Review Heatmap screenshot