{- | mtlstats Copyright (C) 1984, 1985, 2019, 2020 Rhéal Lamothe This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . -} module Mtlstats.Menu ( -- * Menu Functions menuController, menuControllerWith, menuStateController, drawMenu, menuHandler, -- * Menus mainMenu, newSeasonMenu, gameMonthMenu, gameTypeMenu, gameGoalieMenu, editMenu ) where import Control.Monad.IO.Class (liftIO) import Control.Monad.Trans.State (gets, modify) import Data.Aeson (encodeFile) import Data.Char (toUpper) import qualified Data.Map as M import Data.Maybe (mapMaybe) import Lens.Micro ((^.), (?~)) import Lens.Micro.Extras (view) import System.EasyFile ( createDirectoryIfMissing , getAppUserDataDirectory , () ) import qualified UI.NCurses as C import Mtlstats.Actions import qualified Mtlstats.Actions.NewGame.GoalieInput as GI import Mtlstats.Config import Mtlstats.Types import Mtlstats.Types.Menu import Mtlstats.Util -- | Generates a simple 'Controller' for a Menu menuController :: Menu () -> Controller menuController = menuControllerWith $ const $ return () -- | Generate a simple 'Controller' for a 'Menu' with a header menuControllerWith :: (ProgState -> C.Update ()) -- ^ Generates the header -> Menu () -- ^ The menu -> Controller -- ^ The resulting controller menuControllerWith header menu = Controller { drawController = \s -> do header s drawMenu menu , handleController = \e -> do menuHandler menu e return True } -- | Generate and create a controller for a menu based on the current -- 'ProgState' menuStateController :: (ProgState -> Menu ()) -- ^ The function to generate the menu -> Controller -- ^ The resulting controller menuStateController menuFunc = Controller { drawController = drawMenu . menuFunc , handleController = \e -> do menu <- gets menuFunc menuHandler menu e return True } -- | The draw function for a 'Menu' drawMenu :: Menu a -> C.Update C.CursorMode drawMenu m = do C.drawString $ show m return C.CursorInvisible -- | The event handler for a 'Menu' menuHandler :: Menu a -> C.Event -> Action a menuHandler m (C.EventCharacter c) = case filter (\i -> i^.miKey == toUpper c) $ m^.menuItems of i:_ -> i^.miAction [] -> return $ m^.menuDefault menuHandler m _ = return $ m^.menuDefault -- | The main menu mainMenu :: Menu Bool mainMenu = Menu "*** MAIN MENU ***" True [ MenuItem '1' "New Season" $ modify startNewSeason >> return True , MenuItem '2' "New Game" $ modify startNewGame >> return True , MenuItem '3' "Edit" $ modify edit >> return True , MenuItem 'X' "Exit" $ do db <- gets $ view database liftIO $ do dir <- getAppUserDataDirectory appName let dbFile = dir dbFname createDirectoryIfMissing True dir encodeFile dbFile db return False ] -- | The new season menu newSeasonMenu :: Menu () newSeasonMenu = Menu "*** SEASON TYPE ***" () [ MenuItem 'R' "Regular Season" $ modify $ resetYtd . resetStandings . startNewGame , MenuItem 'P' "Playoffs" $ modify $ resetStandings . startNewGame ] -- | Requests the month in which the game took place gameMonthMenu :: Menu () gameMonthMenu = Menu "Month:" () $ map (\(ch, name, val) -> MenuItem ch name $ modify $ progMode.gameStateL.gameMonth ?~ val) [ ( 'A', "January", 1 ) , ( 'B', "February", 2 ) , ( 'C', "March", 3 ) , ( 'D', "April", 4 ) , ( 'E', "May", 5 ) , ( 'F', "June", 6 ) , ( 'G', "July", 7 ) , ( 'H', "August", 8 ) , ( 'I', "September", 9 ) , ( 'J', "October", 10 ) , ( 'K', "November", 11 ) , ( 'L', "December", 12 ) ] -- | The game type menu (home/away) gameTypeMenu :: Menu () gameTypeMenu = Menu "Game type:" () [ MenuItem '1' "Home Game" $ modify $ progMode.gameStateL.gameType ?~ HomeGame , MenuItem '2' "Away Game" $ modify $ progMode.gameStateL.gameType ?~ AwayGame ] -- | Game goalie selection menu gameGoalieMenu :: ProgState -> Menu () gameGoalieMenu s = let title = "Which goalie should get credit for the game?" gids = map fst $ M.toList $ s^.progMode.gameStateL.gameGoalieStats goalies = mapMaybe (\n -> do goalie <- nth n $ s^.database.dbGoalies Just (n, goalie)) gids in Menu title () $ map (\(ch, (gid, goalie)) -> MenuItem ch (goalieSummary goalie) $ modify $ GI.setGameGoalie gid) $ zip ['1'..] goalies -- | The edit menu editMenu :: Menu () editMenu = Menu "*** EDIT ***" () [ MenuItem '1' "Create Player" $ modify createPlayer , MenuItem '2' "Create Goalie" $ modify createGoalie , MenuItem '3' "Edit Player" $ modify editPlayer , MenuItem '4' "Edit Goalie" $ modify editGoalie , MenuItem 'R' "Return to Main Menu" $ modify backHome ]