pub fn new(deck: deck::Deck, mut sched: Schedule) -> Scheduler {
        // The cards that have been added to the schedule or the new queue.
        let mut queued_cards = HashSet::new();

        // TODO: Change the on-disk storage structure, such that you can combine the two next two
        //       loops to a single loop over the cards in the deck.

        // Rebuild schedule and new queue.
        let mut new_cards = Vec::new();
        let mut queue = BTreeMap::new();
        for (metacard_ref, metacard) in sched.metacards.iter().enumerate() {
            // Skip cards that have been removed. Note that the data is kept, so if the card is,
            // say, uncommented, it will not have affected the state of the card.
            if !deck.cards.contains_key(&metacard.id) { continue; }

            match metacard.state {
                cards::CardState::New => {
                    new_cards.push(metacard_ref);
                },
                cards::CardState::Learning(_)
                    | cards::CardState::Relearning(_)
                    | cards::CardState::Learnt =>
                {
                    queue.insert(metacard.due, metacard_ref);
                },
            }
            // Add the card to the set of queued cards after it has been added to the scheduler.
            queued_cards.insert(metacard.id.clone());
            // TODO: Get rid of above clone. Idea: add lifetimes to Scheduler. `CardId` should be a
            //       `&str`.
        }

        // De-orphan cards that are not a part of the scheduler yet.
        for (id, card) in deck.cards.iter().filter(|(id, _)| !queued_cards.contains(id.as_str())) {
            // Add the orphaned card to the schedule.
            sched.metacards.push(cards::Metacard::new(id.clone(), deck.tag_settings(&card.tags)));
            // Add the it to the new queue.
            new_cards.push(sched.metacards.len() - 1);
        }

        // Start with empty state.
        let mut sched = Scheduler {
            sched,
            deck,
            new_cards,
            new_queue: Vec::new(),
            // Have a nonsense value, such that in case of any bugs, we should get an OOB.
            current_card: !0,
            queue,
            due: 0,
            prefer_new: false,
        };

        // Populate the new cards queue with the new cards from today, that are not studied yet.
        for _ in 0..sched.sched.new_today {
            if let Some(card) = sched.new_cards.pop() {
                sched.new_queue.push(card);
            } else { break; }
        }

        // Generate the rest of the scheduler.
        sched.update();
        // If the queues are still empty, forcibly add a new card to the new queue.
        if sched.new_queue.is_empty() && sched.queue.is_empty() {
            // We can safely unwrap, since `deck` was assumed nonempty.
            sched.new_queue.push(sched.new_cards.pop().unwrap());
        }
        // Pick a card.
        sched.pick_card();

        sched
    }
/// Create a new scheduler from a deck and schedule.
///
/// `deck.cards` is assumed to be nonempty.
Create a new scheduler from a deck and schedule.
`deck.cards` is assumed to be nonempty.
Create a new scheduler from a deck and schedule . ` deck . cards ` is assumed to be nonempty .
pub fn new(deck: deck::Deck, mut sched: Schedule) -> Scheduler {
        // The cards that have been added to the schedule or the new queue.
        let mut queued_cards = HashSet::new();
        // TODO: Change the on-disk storage structure, such that you can combine the two next two
        //       loops to a single loop over the cards in the deck.
        // Rebuild schedule and new queue.
        let mut new_cards = Vec::new();
        let mut queue = BTreeMap::new();
        for (metacard_ref, metacard) in sched.metacards.iter().enumerate() {
            // Skip cards that have been removed. Note that the data is kept, so if the card is,
            // say, uncommented, it will not have affected the state of the card.
            if !deck.cards.contains_key(&metacard.id) { continue; }
            match metacard.state {
                cards::CardState::New => {
                    new_cards.push(metacard_ref);
                },
                cards::CardState::Learning(_)
                    | cards::CardState::Relearning(_)
                    | cards::CardState::Learnt =>
                {
                    queue.insert(metacard.due, metacard_ref);
                },
            }
            // Add the card to the set of queued cards after it has been added to the scheduler.
            queued_cards.insert(metacard.id.clone());
            // TODO: Get rid of above clone. Idea: add lifetimes to Scheduler. `CardId` should be a
            //       `&str`.
        }
        // De-orphan cards that are not a part of the scheduler yet.
        for (id, card) in deck.cards.iter().filter(|(id, _)| !queued_cards.contains(id.as_str())) {
            // Add the orphaned card to the schedule.
            sched.metacards.push(cards::Metacard::new(id.clone(), deck.tag_settings(&card.tags)));
            // Add the it to the new queue.
            new_cards.push(sched.metacards.len() - 1);
        }
        // Start with empty state.
        let mut sched = Scheduler {
            sched,
            deck,
            new_cards,
            new_queue: Vec::new(),
            // Have a nonsense value, such that in case of any bugs, we should get an OOB.
            current_card: !0,
            queue,
            due: 0,
            prefer_new: false,
        };
        // Populate the new cards queue with the new cards from today, that are not studied yet.
        for _ in 0..sched.sched.new_today {
            if let Some(card) = sched.new_cards.pop() {
                sched.new_queue.push(card);
            } else { break; }
        }
        // Generate the rest of the scheduler.
        sched.update();
        // If the queues are still empty, forcibly add a new card to the new queue.
        if sched.new_queue.is_empty() && sched.queue.is_empty() {
            // We can safely unwrap, since `deck` was assumed nonempty.
            sched.new_queue.push(sched.new_cards.pop().unwrap());
        }
        // Pick a card.
        sched.pick_card();
        sched
    }
pub fn new ( deck : deck :: Deck , mut sched : Schedule ) -> Scheduler { // The cards that have been added to the schedule or the new queue. let mut queued_cards = HashSet :: new ( ) ; // TODO: Change the on-disk storage structure, such that you can combine the two next two //       loops to a single loop over the cards in the deck. // Rebuild schedule and new queue. let mut new_cards = Vec :: new ( ) ; let mut queue = BTreeMap :: new ( ) ; for ( metacard_ref , metacard ) in sched . metacards . iter ( ) . enumerate ( ) { // Skip cards that have been removed. Note that the data is kept, so if the card is, // say, uncommented, it will not have affected the state of the card. if ! deck . cards . contains_key ( & metacard . id ) { continue ; } match metacard . state { cards :: CardState :: New => { new_cards . push ( metacard_ref ) ; } , cards :: CardState :: Learning ( _ ) | cards :: CardState :: Relearning ( _ ) | cards :: CardState :: Learnt => { queue . insert ( metacard . due , metacard_ref ) ; } , } // Add the card to the set of queued cards after it has been added to the scheduler. queued_cards . insert ( metacard . id . clone ( ) ) ; // TODO: Get rid of above clone. Idea: add lifetimes to Scheduler. `CardId` should be a //       `&str`. } // De-orphan cards that are not a part of the scheduler yet. for ( id , card ) in deck . cards . iter ( ) . filter ( | ( id , _ ) | ! queued_cards . contains ( id . as_str ( ) ) ) { // Add the orphaned card to the schedule. sched . metacards . push ( cards :: Metacard :: new ( id . clone ( ) , deck . tag_settings ( & card . tags ) ) ) ; // Add the it to the new queue. new_cards . push ( sched . metacards . len ( ) - 1 ) ; } // Start with empty state. let mut sched = Scheduler { sched , deck , new_cards , new_queue : Vec :: new ( ) , // Have a nonsense value, such that in case of any bugs, we should get an OOB. current_card : ! 0 , queue , due : 0 , prefer_new : false , } ; // Populate the new cards queue with the new cards from today, that are not studied yet. for _ in 0 .. sched . sched . new_today { if let Some ( card ) = sched . new_cards . pop ( ) { sched . new_queue . push ( card ) ; } else { break ; } } // Generate the rest of the scheduler. sched . update ( ) ; // If the queues are still empty, forcibly add a new card to the new queue. if sched . new_queue . is_empty ( ) && sched . queue . is_empty ( ) { // We can safely unwrap, since `deck` was assumed nonempty. sched . new_queue . push ( sched . new_cards . pop ( ) . unwrap ( ) ) ; } // Pick a card. sched . pick_card ( ) ; sched }
Create a new scheduler from a deck and schedule.
Create a new scheduler from a deck and schedule .
deck
deck::Deck
sched
Schedule
deck
deck::Deck
sched
Schedule