clanki-1.0.7: src/Quiz.hs
module Quiz where
import Card
import Decks
import Tracker
import Display
import Text.Printf(printf)
import Safe(readMay)
import Data.Time.Clock.POSIX
import qualified Input
import Control.Monad(filterM)
data QuizAction = AllCards | FromDeck deriving (Show, Eq)
allQuizActions :: [QuizAction]
allQuizActions = [AllCards, FromDeck]
instance Display QuizAction where
display AllCards = "Quiz from all cards"
display FromDeck = "Quiz from a deck"
quizLoop :: [Deck] -> IO [Deck]
quizLoop decks = do
quizAction <- getQuizAction decks
runQuizAction quizAction decks
anyCardsToQuiz :: [Deck] -> IO Bool
anyCardsToQuiz decks = shouldQuizList >>= return . (True `elem`)
where shouldQuizList = sequence [shouldQuizCard card | card <- allCards decks]
runQuizAction :: Maybe QuizAction -> [Deck] -> IO [Deck]
runQuizAction (Just AllCards) decks = quizDecks decks decks
runQuizAction (Just FromDeck) decks = do
input <- Input.getUserChoice decks
case input of
Just deck -> quizFromDeck deck decks
Nothing -> return decks
runQuizAction Nothing decks = return decks
quizDecks :: [Deck] -> [Deck] -> IO [Deck]
quizDecks decksToQuiz allDecks = sequence $ map (\deck -> if deck `elem` decksToQuiz then quizDeck deck else return deck) allDecks
quizDeck :: Deck -> IO Deck
quizDeck deck = do
newCards <- sequence [maybeQuiz card | card <- dCards deck]
return deck {dCards = newCards}
maybeQuiz :: Card -> IO Card
maybeQuiz card = shouldQuizCard card >>= (\shouldQuiz -> if shouldQuiz then quizCard card else return card)
cardsToQuiz :: [Deck] -> IO [Card]
cardsToQuiz decks = filterM shouldQuizCard cards
where cards = allCards decks
{-quizCards :: [Card] -> [Deck] -> IO [Deck]-}
{-quizCards cards decks = return decks-}
{-newTrackers <- sequence [quizCard card tracker | card <- cards, let tracker = trackerOfCard card (cardTrackers decks)]-}
{--- TODO: replace trackers, but not all -}
{-return $ decks {cardTrackers = newTrackers}-}
quizCard :: Card -> IO Card
quizCard card = do
printf $ "Question : " ++ cardQuestion card ++ "\n"
printf "Input your answer, then press enter to continue\n"
_ <- getLine
printf $ "Answer : " ++ cardAnswer card ++ "\n"
printf $ "Rate your answer, 0-5" ++ "\n"
confidence <- getAnswerConfidence
let newEF = adjustEF (ctEF $ cardTracker card) confidence
let oldTracker = cardTracker card
let n = if confidence < 3 then 1 else ctN oldTracker + 1
currentTime <- fmap round getPOSIXTime
printf "\n"
return $ card {cardTracker = oldTracker {ctEF = newEF, ctN = n, ctLastResponseQuality = Just confidence, ctTimeQuizzed = currentTime}}
getAnswerConfidence :: IO Integer
getAnswerConfidence = do
input <- getLine
let readInput = readMay input :: Maybe Integer
case readInput of
Just confidence -> if confidence `elem` [1 .. 5] then return confidence else getAnswerConfidence
Nothing -> getAnswerConfidence
quizFromDeck :: Deck -> [Deck] -> IO [Deck]
quizFromDeck deck decks = quizDeck deck >>= (\newDeck -> return $ replaceDeckNamed (dName deck) newDeck decks)
getQuizAction :: [Deck] -> IO (Maybe QuizAction)
getQuizAction [] = do
printf $ "No decks, returning to menu" ++ "\n"
return Nothing
getQuizAction decks = do
cardsToBeQuizzed <- cardsToQuiz decks
case cardsToBeQuizzed of
[] -> do
printf $ "No cards need to be quizzed at this time" ++ "\n"
return Nothing
_ -> do
printf $ "What would you like to be quizzed on?" ++ "\n"
Input.getUserChoice allQuizActions