{-# LANGUAGE TemplateHaskell #-} module States (module States, GenIO) where import Brick (Widget, EventM, Next) import Brick.Forms (Form) import Brick.Widgets.FileBrowser import Brick.Widgets.List (List) import Data.Char (isDigit) import Data.Map.Strict (Map) import Lens.Micro.Platform import System.Random.MWC (GenIO) import Stack hiding (head) import Types import qualified Data.List.NonEmpty as NE import qualified Data.Map.Strict as M import qualified Graphics.Vty as V data Name = -- Settings HintsField | ControlsField | EscapeCodeField | MaxRecentsField -- Parameters | ShuffleField | SubsetField | ChunkField | ReviewModeField | ParametersOkField | Ordinary deriving (Eq, Ord, Show) type Event = () data Mode = MainMenu | Settings | Info | CardSelector | FileBrowser | Cards | Parameter deriving (Show, Eq, Ord) data State = MainMenuState MMS | SettingsState SS | InfoState IS | CardSelectorState CSS | FileBrowserState FBS | ParameterState PS | CardsState CS data Chunk = Chunk Int Int instance Show Chunk where show (Chunk i n) = show i <> "/" <> show n instance Read Chunk where readsPrec _ input = let (i', rest1) = span isDigit input i = read i' :: Int (c:rest2) = rest1 (n', rest3) = span isDigit rest2 n = read n' :: Int in [(Chunk i n, rest3) | c `elem` ['/', ' '] && n >= i && i >= 1] data GlobalState = GlobalState { _mwc :: GenIO , _stack :: Stack Mode , _states :: Map Mode State , _parameters :: Parameters } data CardState = DefinitionState { _flipped :: Bool } | MultipleChoiceState { _highlighted :: Int , _number :: Int , _tried :: Map Int Bool -- indices of tried choices } | MultipleAnswerState { _highlighted :: Int , _selected :: Map Int Bool , _number :: Int , _entered :: Bool } | OpenQuestionState { _gapInput :: Map Int String , _highlighted :: Int , _number :: Int , _entered :: Bool , _correctGaps :: Map Int Bool , _failed :: Bool } | ReorderState { _highlighted :: Int , _grabbed :: Bool , _order :: Map Int (Int, String) , _entered :: Bool , _number :: Int } defaultCardState :: Card -> CardState defaultCardState Definition{} = DefinitionState { _flipped = False } defaultCardState (MultipleChoice _ _ ics) = MultipleChoiceState { _highlighted = 0 , _number = length ics + 1 , _tried = M.fromList [(i, False) | i <- [0..length ics]] } defaultCardState (OpenQuestion _ perforated) = OpenQuestionState { _gapInput = M.empty , _highlighted = 0 , _number = nGapsInPerforated perforated , _entered = False , _correctGaps = M.fromList [(i, False) | i <- [0..nGapsInPerforated perforated - 1]] , _failed = False } defaultCardState (MultipleAnswer _ answers) = MultipleAnswerState { _highlighted = 0 , _selected = M.fromList [(i, False) | i <- [0..NE.length answers-1]] , _entered = False , _number = NE.length answers } defaultCardState (Reorder _ elements) = ReorderState { _highlighted = 0 , _grabbed = False , _order = M.fromList (zip [0..] (NE.toList elements)) , _entered = False , _number = NE.length elements } data CS = CS { _cards :: [Card] -- list of flashcards , _index :: Int -- current card index , _nCards :: Int -- number of cards , _currentCard :: Card , _cardState :: CardState , _showHints :: Bool , _showControls :: Bool , _reviewMode :: Bool , _correctCards :: [Int] -- list of indices of correct cards , _popup :: Maybe (Popup CS) , _pathToFile :: FilePath } data Popup s = Popup { drawPopup :: s -> Widget Name , handlePopupEvent :: GlobalState -> s -> V.Event -> EventM Name (Next GlobalState) , _popupState :: PopupState } data PopupState = CorrectPopup { _popupSelected :: Int } | FinalPopup | DeckMakerPopup { _popupSelected :: Int , _makeDeckIncorrect :: Bool , _makeDeckCorrect :: Bool } deriving Eq newtype MMS = MMS { _l :: List Name String } type IS = () data Settings = FormState { _hints :: Bool , _controls :: Bool , _escapeCode :: Bool , _maxRecents :: Int } deriving (Read, Show) type SS = Form Settings Event Name data CSS = CSS { _list :: List Name String , _exception :: Maybe String , _recents :: Stack FilePath , _maxRecentsToShow :: Int } data FBS = FBS { _fb :: FileBrowser Name , _exception' :: Maybe String , _parsedCards :: [Card] , _filePath :: Maybe FilePath , _showHidden :: Bool } defaultParameters = Parameters { _pShuffle = False , _pSubset = Nothing , _pChunk = Chunk 1 1 , _pReviewMode = True , _pOk = False } data Parameters = Parameters { _pShuffle :: Bool , _pSubset :: Maybe Int , _pChunk :: Chunk , _pReviewMode :: Bool , _pOk :: Bool } data PS = PS { _psCards :: [Card] , _psFp :: FilePath , _psForm :: Form Parameters Event Name } makeLenses ''State makeLenses ''MMS makeLenses ''GlobalState makeLenses ''CardState makeLenses ''CS makeLenses ''Settings makeLenses ''CSS makeLenses ''FBS makeLenses ''PS makeLenses ''Parameters makeLenses ''Popup makeLenses ''PopupState