giovannihenriksen / Anki-Simulator

Simulator for Anki
GNU Affero General Public License v3.0
76 stars 11 forks source link

Simulate subdecks from parent deck #34

Open p4nix opened 4 years ago

p4nix commented 4 years ago

Based on my understanding, if you simulate a parent deck with the Simulator add-on, it will take the averaged performance data together with the deck options of the parent deck.

How hard would it be to implement an option to simulate each deck individually (with the amount of new cards for each deck, their performance data, maybe an option to never run out of new cards) and add them together for a more accurate representation of the overall workload?

VincentOostelbos commented 4 years ago

This would be a godsend, since I have everything organized to several hierarchical levels, and anything that is not a lowest-level deck (a leaf of the tree, as it were) is set to 9999 new cards per day, so that it is not a bottleneck, and only the settings on the lowest-level subdecks determine the amount of new cards. That means, however, that whenever I simulate anything but a leaf deck, I get a very inaccurate simulation that suggests I actually do 9999 new cards on the very first day.

It would be fantastic if the simulation knew how many cards the parent decks get per day from each lower level, and for it to be able to percolate that information upward all the way from the bottom of the tree, so that I could accurately simulate my entire overarching parent deck.

brownbat commented 3 years ago

Agreed, this is how I organize my decks too, cards per day set on leafs, with a parent that is just there for organization.

I think there's a hard way and an easy way to implement this.

I. Hard way

To implement this perfectly mimicking Anki, we'd need to:

  1. id all subdecks, (relatively easy)

  2. deduplicate, (uh...)

  3. iteratively run existing algorithm on each, (relatively easy, a for loop)

  4. sum before results (trivial)

  5. id all subdecks

A search for subdeck in Anki's code doesn't make it obvious how, but I guess you would iterate through "col.decks.all_names_and_ids()" and just keep whichever start with the name of the deck you're running it from.

this_deck = "deck"
this_subdeck = "deck::subdeck::subsubdeck"
if this_subdeck[0:len(this_deck)+1] == this_deck:
    ...

Deduplication would be the hardest part here.

You might have intermediate decks that are parents to some subdecks, but also subdecks to other parents. And they might contain their own cards.

So you need to sort the decks you've collected into a hierarchy. Then for each deck ask how many reviews and new cards it allows. Then figure out where it prioritizes pulling those from - does it pull from which subdecks first?

You have to actually follow Anki's algorithm of how it prioritizes which subdecks to pull from, and that gets really complicated quickly.

II. Easy way

So instead... just skip deduplication completely and assume people use Anki in one of two ways: 1) set review limits at the parent, 2) set review limits at the leaves.

Just add some (default off) checkbox in the options that says "Run for lowest level subdecks ONLY."

In that case, you would just do the easy steps above:

  1. find all the lowest level subdecks (those that don't contain any other subdecks),
  2. simulate each,
  3. sum and output

That would cover people who control their deck settings either way.

It wouldn't cover people who use overlapping settings to control things, but that's chaos anyway (I say having been there).

I think that might be the imperfect best compromise solution that's easiest to implement.