diff options
author | Jedidiah Barber <contact@jedbarber.id.au> | 2021-07-14 11:49:10 +1200 |
---|---|---|
committer | Jedidiah Barber <contact@jedbarber.id.au> | 2021-07-14 11:49:10 +1200 |
commit | d24f813f3f2a05c112e803e4256b53535895fc98 (patch) | |
tree | 601e6ae9a1cd44bcfdcf91739a5ca36aedd827c9 /src/study/WordDrillModel.cpp |
Diffstat (limited to 'src/study/WordDrillModel.cpp')
-rw-r--r-- | src/study/WordDrillModel.cpp | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/study/WordDrillModel.cpp b/src/study/WordDrillModel.cpp new file mode 100644 index 0000000..403535a --- /dev/null +++ b/src/study/WordDrillModel.cpp @@ -0,0 +1,163 @@ +#include "WordDrillModel.h" +#include "../dictionary/Card.h" +#include "../dictionary/CardPack.h" +#include "StudySettings.h" + +#include <stdlib.h> +#include <time.h> + +WordDrillModel::WordDrillModel( CardPack* aCardPack ): + IStudyModel( aCardPack ), m_historyCurPackStart(0) + { + curCardNum = NoCardIndex; + srand( time(NULL) ); + connect( aCardPack, SIGNAL(cardsGenerated()), SLOT(updateStudyState()) ); + + generateFreshPack(); + pickNextCard(); + } + +/** Get current card. + * If the current card doesn't exist any more, find the next valid card. + */ + +Card* WordDrillModel::getCurCard() const + { + if( m_cardHistory.isEmpty() || curCardNum < 0 ) // No cards in the pack + return NULL; + if( curCardNum >= m_cardHistory.size() ) + return NULL; + QString cardName = m_cardHistory.at(curCardNum); + return cardPack->getCard( cardName ); + } + +void WordDrillModel::updateStudyState() + { + generateFreshPack(); + cleanHistoryFromRemovedCards(); + if( getCurCard() ) + emit curCardUpdated(); + else + pickNextCard(); + } + +void WordDrillModel::generateFreshPack() + { + m_freshPack = cardPack->getCardQuestions(); + // Remove already reviewed cards + if( m_historyCurPackStart >= m_cardHistory.size() ) + return; + foreach( QString reviewedCard, m_cardHistory.mid( m_historyCurPackStart ) ) + m_freshPack.removeAll( reviewedCard ); + } + +void WordDrillModel::cleanHistoryFromRemovedCards() + { + if( m_cardHistory.isEmpty() ) + return; + bool cardsRemoved = false; + QMutableStringListIterator it( m_cardHistory ); + int i = 0; + while( it.hasNext() ) + { + QString cardName = it.next(); + if( !cardPack->containsQuestion( cardName ) ) + { + it.remove(); + cardsRemoved = true; + if( i < curCardNum ) + curCardNum--; + } + i++; + } + if( cardsRemoved ) + { + if( curCardNum >= m_cardHistory.size() ) + curCardNum = m_cardHistory.size() - 1; + emit nextCardSelected(); + } + } + + +/** Picks a random card. Removes the selected card from the fresh pack and adds it to the history. + * Thus, the new card is the last entry in the history. + * This function guarantees that the new card's question will be different from the previous one, unless there is no choice. + * + * Updates #m_curCardNum. + */ +void WordDrillModel::pickNextCard() + { + QString selectedCardName; + const Card* selectedCard = NULL; + do + { + if( m_freshPack.isEmpty() ) // No fresh cards + { + m_historyCurPackStart = m_cardHistory.size(); // Refers beyond the history pack + generateFreshPack(); + if( m_freshPack.isEmpty() ) // Still no any cards available - no useful cards in the dictionary or it's empty + { + curCardNum = NoCardIndex; + emit nextCardSelected(); + return; + } + } + if( m_freshPack.size() == 1 ) // Only 1 fresh card, no choice + selectedCardName = m_freshPack.takeFirst(); + else + { + int selectedCardNum; + if( StudySettings::inst()->showRandomly ) + selectedCardNum = rand() % m_freshPack.size(); + else + selectedCardNum = 0; + if( !m_cardHistory.isEmpty() ) + while( m_freshPack[ selectedCardNum ] == m_cardHistory.last() ) // The new question must be different from the current one + { + selectedCardNum++; + selectedCardNum %= m_freshPack.size(); + } + selectedCardName = m_freshPack.takeAt( selectedCardNum ); + } + selectedCard = cardPack->getCard( selectedCardName ); + } + while( !selectedCard ); + m_cardHistory << selectedCardName; + curCardNum = m_cardHistory.size() - 1; + emit nextCardSelected(); + } + +/** Go back along the history line. + * @return true, if the transition was successful + */ +bool WordDrillModel::goBack() + { + if( !canGoBack() ) + return false; + curCardNum--; + emit nextCardSelected(); + return true; + } + +/** Go forward along the history line. + * @return true, if the transition was successful + */ +bool WordDrillModel::goForward() + { + if( !canGoForward() ) + return false; + curCardNum++; + emit nextCardSelected(); + return true; + } + +bool WordDrillModel::canGoBack() + { + return curCardNum > 0; + } + +bool WordDrillModel::canGoForward() + { + return curCardNum < m_cardHistory.size() - 1; + } + |