summaryrefslogtreecommitdiff
path: root/src/study/WordDrillModel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/study/WordDrillModel.cpp')
-rw-r--r--src/study/WordDrillModel.cpp163
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;
+ }
+