Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
994087a0e6 | ||
|
|
7fbeaac933 | ||
|
|
de56f4f94d | ||
|
|
04ba17324e | ||
|
|
d6ae171dc8 | ||
|
|
72b6f05700 | ||
|
|
4c7a756c5e | ||
|
|
ea3ca4e578 | ||
|
|
179a864cfa | ||
|
|
f2b2ff3fef | ||
|
|
9c2e2291c8 | ||
|
|
abad72ce01 | ||
|
|
a9d4d3351f | ||
|
|
45aea607b2 | ||
|
|
be9d7d80bb | ||
|
|
683c36e2b6 | ||
|
|
83c408cea2 | ||
|
|
dcbd68cdda | ||
|
|
717f2d5932 | ||
|
|
d5de834510 | ||
|
|
75a47ca852 | ||
|
|
d4de7c6f8b | ||
|
|
d50d055b0b | ||
|
|
9c7c295a4b | ||
|
|
49963277be | ||
|
|
264d9f81e2 | ||
|
|
6a0d1f7203 | ||
|
|
18683c1c6e | ||
|
|
107ed507e2 | ||
|
|
baf040deea | ||
|
|
c3bac5e624 | ||
|
|
119cb873eb | ||
|
|
82603ba504 | ||
|
|
a909b9ba7a | ||
|
|
802bf7314e | ||
|
|
a3124aca58 | ||
|
|
f113e46564 | ||
|
|
39646f3fa7 | ||
|
|
2bf8d15bd4 | ||
|
|
3009a8f60c | ||
|
|
3b4ce50ae8 | ||
|
|
fcfbcea72f | ||
|
|
d132ebd502 | ||
|
|
75cd253f3f | ||
|
|
063bebfbb5 | ||
|
|
7923827d22 | ||
|
|
461fb5d942 | ||
|
|
e38275aefe |
12
ChangeLog.md
12
ChangeLog.md
@@ -1,5 +1,13 @@
|
||||
# Changelog for mtlstats
|
||||
|
||||
## 0.11.0
|
||||
- Added active flag to players/goalies
|
||||
- Clear rookie flag on new (regular) season
|
||||
- Save a copy of the database on new season
|
||||
- Implemented game standings editing
|
||||
- Added title screen
|
||||
- Changed sytling of menus
|
||||
|
||||
## 0.10.0
|
||||
- Don't show player number zero in reports
|
||||
- Fixed player/goalie name capitalisation on edit
|
||||
@@ -33,24 +41,20 @@
|
||||
- Reset game standings on new season
|
||||
|
||||
## 0.5.0
|
||||
|
||||
- Fixed player creation bug
|
||||
- Prompt for goalie informaiton on game data entry
|
||||
- Implemented player editing
|
||||
|
||||
## v0.4.0
|
||||
|
||||
- Record penalty minutes
|
||||
- Calculate total game statistics
|
||||
- Generate year-to-date statistics report
|
||||
|
||||
## v0.3.0
|
||||
|
||||
- Record goals and assists
|
||||
- Track goals for and goals against
|
||||
|
||||
## v0.2.0
|
||||
|
||||
- Overtime losses don't count in the loss column
|
||||
- Confirm game data with user before updating stats
|
||||
- Implemented player creation
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: mtlstats
|
||||
version: 0.10.0
|
||||
version: 0.11.0
|
||||
github: "mtlstats/mtlstats"
|
||||
license: GPL-3
|
||||
author: "Jonathan Lamothe"
|
||||
|
||||
@@ -24,6 +24,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
module Mtlstats.Actions
|
||||
( startNewSeason
|
||||
, resetYtd
|
||||
, clearRookies
|
||||
, resetStandings
|
||||
, startNewGame
|
||||
, addChar
|
||||
@@ -42,18 +43,29 @@ module Mtlstats.Actions
|
||||
, backHome
|
||||
, scrollUp
|
||||
, scrollDown
|
||||
, saveDatabase
|
||||
) where
|
||||
|
||||
import Control.Monad.Trans.State (modify)
|
||||
import Control.Monad.IO.Class (liftIO)
|
||||
import Control.Monad.Trans.State (gets, modify)
|
||||
import Data.Aeson (encodeFile)
|
||||
import Data.Maybe (fromMaybe)
|
||||
import Lens.Micro ((^.), (&), (.~), (%~))
|
||||
import System.EasyFile
|
||||
( createDirectoryIfMissing
|
||||
, getAppUserDataDirectory
|
||||
, (</>)
|
||||
)
|
||||
|
||||
import Mtlstats.Config
|
||||
import Mtlstats.Types
|
||||
import Mtlstats.Util
|
||||
|
||||
-- | Starts a new season
|
||||
startNewSeason :: ProgState -> ProgState
|
||||
startNewSeason = (progMode .~ NewSeason) . (database . dbGames .~ 0)
|
||||
startNewSeason
|
||||
= (progMode .~ NewSeason False)
|
||||
. (database.dbGames .~ 0)
|
||||
|
||||
-- | Resets all players year-to-date stats
|
||||
resetYtd :: ProgState -> ProgState
|
||||
@@ -61,6 +73,12 @@ resetYtd
|
||||
= (database . dbPlayers %~ map (pYtd .~ newPlayerStats))
|
||||
. (database . dbGoalies %~ map (gYtd .~ newGoalieStats))
|
||||
|
||||
-- | Clears the rookie flag from all players/goalies
|
||||
clearRookies :: ProgState -> ProgState
|
||||
clearRookies = database
|
||||
%~ (dbPlayers %~ map (pRookie .~ False))
|
||||
. (dbGoalies %~ map (gRookie .~ False))
|
||||
|
||||
-- | Resets game standings
|
||||
resetStandings :: ProgState -> ProgState
|
||||
resetStandings = database
|
||||
@@ -189,3 +207,13 @@ scrollUp = scrollOffset %~ max 0 . pred
|
||||
-- | Scrolls the display down
|
||||
scrollDown :: ProgState -> ProgState
|
||||
scrollDown = scrollOffset %~ succ
|
||||
|
||||
-- | Saves the database
|
||||
saveDatabase :: String -> Action ()
|
||||
saveDatabase fn = do
|
||||
db <- gets (^.database)
|
||||
liftIO $ do
|
||||
dir <- getAppUserDataDirectory appName
|
||||
let dbFile = dir </> fn
|
||||
createDirectoryIfMissing True dir
|
||||
encodeFile dbFile db
|
||||
|
||||
70
src/Mtlstats/Actions/EditStandings.hs
Normal file
70
src/Mtlstats/Actions/EditStandings.hs
Normal file
@@ -0,0 +1,70 @@
|
||||
{- |
|
||||
|
||||
mtlstats
|
||||
Copyright (C) 1984, 1985, 2019, 2020 Rhéal Lamothe
|
||||
<rheal.lamothe@gmail.com>
|
||||
|
||||
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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
-}
|
||||
|
||||
module Mtlstats.Actions.EditStandings
|
||||
( editStandings
|
||||
, editHomeStandings
|
||||
, editAwayStandings
|
||||
, editWins
|
||||
, editLosses
|
||||
, editOvertime
|
||||
, editGoalsFor
|
||||
, editGoalsAgainst
|
||||
) where
|
||||
|
||||
import Lens.Micro ((.~))
|
||||
|
||||
import Mtlstats.Types
|
||||
|
||||
-- | Enters edit standings mode
|
||||
editStandings :: ProgState -> ProgState
|
||||
editStandings = progMode .~ EditStandings ESMMenu
|
||||
|
||||
-- | Edits the home standings
|
||||
editHomeStandings :: ProgState -> ProgState
|
||||
editHomeStandings = progMode .~ EditStandings (ESMHome ESMSubMenu)
|
||||
|
||||
-- | Edits the road standings
|
||||
editAwayStandings :: ProgState -> ProgState
|
||||
editAwayStandings = progMode .~ EditStandings (ESMAway ESMSubMenu)
|
||||
|
||||
-- | Changes to edit wins mode
|
||||
editWins :: ProgState -> ProgState
|
||||
editWins = doEdit ESMEditWins
|
||||
|
||||
-- | Changes to edit losses mode
|
||||
editLosses :: ProgState -> ProgState
|
||||
editLosses = doEdit ESMEditLosses
|
||||
|
||||
-- | Changes to edit overtime mode
|
||||
editOvertime :: ProgState -> ProgState
|
||||
editOvertime = doEdit ESMEditOvertime
|
||||
|
||||
-- | Changes to edit goals for mode
|
||||
editGoalsFor :: ProgState -> ProgState
|
||||
editGoalsFor = doEdit ESMEditGoalsFor
|
||||
|
||||
-- | Changes to edit goals against mode
|
||||
editGoalsAgainst :: ProgState -> ProgState
|
||||
editGoalsAgainst = doEdit ESMEditGoalsAgainst
|
||||
|
||||
doEdit :: ESMSubMode -> ProgState -> ProgState
|
||||
doEdit = (progMode.editStandingsModeL.esmSubModeL .~)
|
||||
@@ -29,8 +29,10 @@ import Lens.Micro.Extras (view)
|
||||
import qualified UI.NCurses as C
|
||||
|
||||
import Mtlstats.Actions
|
||||
import Mtlstats.Control.TitleScreen
|
||||
import Mtlstats.Control.EditGoalie
|
||||
import Mtlstats.Control.EditPlayer
|
||||
import Mtlstats.Control.EditStandings
|
||||
import Mtlstats.Control.NewGame
|
||||
import Mtlstats.Handlers
|
||||
import Mtlstats.Menu
|
||||
@@ -41,10 +43,11 @@ import Mtlstats.Types
|
||||
-- run
|
||||
dispatch :: ProgState -> Controller
|
||||
dispatch s = case s^.progMode of
|
||||
MainMenu -> mainMenuC
|
||||
NewSeason -> newSeasonC
|
||||
NewGame gs -> newGameC gs
|
||||
EditMenu -> editMenuC
|
||||
TitleScreen -> titleScreenC
|
||||
MainMenu -> mainMenuC
|
||||
NewSeason flag -> newSeasonC flag
|
||||
NewGame gs -> newGameC gs
|
||||
EditMenu -> editMenuC
|
||||
CreatePlayer cps
|
||||
| null $ cps^.cpsNumber -> getPlayerNumC
|
||||
| null $ cps^.cpsName -> getPlayerNameC
|
||||
@@ -54,8 +57,9 @@ dispatch s = case s^.progMode of
|
||||
| null $ cgs^.cgsNumber -> getGoalieNumC
|
||||
| null $ cgs^.cgsName -> getGoalieNameC
|
||||
| otherwise -> confirmCreateGoalieC
|
||||
EditPlayer eps -> editPlayerC eps
|
||||
EditGoalie egs -> editGoalieC egs
|
||||
EditPlayer eps -> editPlayerC eps
|
||||
EditGoalie egs -> editGoalieC egs
|
||||
(EditStandings esm) -> editStandingsC esm
|
||||
|
||||
mainMenuC :: Controller
|
||||
mainMenuC = Controller
|
||||
@@ -63,13 +67,9 @@ mainMenuC = Controller
|
||||
, handleController = menuHandler mainMenu
|
||||
}
|
||||
|
||||
newSeasonC :: Controller
|
||||
newSeasonC = Controller
|
||||
{ drawController = const $ drawMenu newSeasonMenu
|
||||
, handleController = \e -> do
|
||||
menuHandler newSeasonMenu e
|
||||
return True
|
||||
}
|
||||
newSeasonC :: Bool -> Controller
|
||||
newSeasonC False = promptController newSeasonPrompt
|
||||
newSeasonC True = menuController newSeasonMenu
|
||||
|
||||
editMenuC :: Controller
|
||||
editMenuC = menuController editMenu
|
||||
|
||||
87
src/Mtlstats/Control/EditStandings.hs
Normal file
87
src/Mtlstats/Control/EditStandings.hs
Normal file
@@ -0,0 +1,87 @@
|
||||
{- |
|
||||
|
||||
mtlstats
|
||||
Copyright (C) 1984, 1985, 2019, 2020 Rhéal Lamothe
|
||||
<rheal.lamothe@gmail.com>
|
||||
|
||||
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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
-}
|
||||
|
||||
{-# LANGUAGE LambdaCase #-}
|
||||
|
||||
module Mtlstats.Control.EditStandings (editStandingsC) where
|
||||
|
||||
import Lens.Micro ((^.))
|
||||
import qualified UI.NCurses as C
|
||||
|
||||
import Mtlstats.Format
|
||||
import Mtlstats.Menu
|
||||
import Mtlstats.Menu.EditStandings
|
||||
import Mtlstats.Prompt
|
||||
import Mtlstats.Prompt.EditStandings
|
||||
import Mtlstats.Types
|
||||
import Mtlstats.Types.Menu
|
||||
|
||||
-- | Controller for the edit standings menu
|
||||
editStandingsC :: EditStandingsMode -> Controller
|
||||
editStandingsC = \case
|
||||
ESMMenu -> menuControllerWith header editStandingsMenu
|
||||
ESMHome m -> editHomeStandingsC m
|
||||
ESMAway m -> editAwayStandingsC m
|
||||
|
||||
editHomeStandingsC :: ESMSubMode -> Controller
|
||||
editHomeStandingsC = \case
|
||||
ESMSubMenu -> menuC editHomeStandingsMenu
|
||||
ESMEditWins -> promptC editHomeWinsPrompt
|
||||
ESMEditLosses -> promptC editHomeLossesPrompt
|
||||
ESMEditOvertime -> promptC editHomeOvertimePrompt
|
||||
ESMEditGoalsFor -> promptC editHomeGoalsForPrompt
|
||||
ESMEditGoalsAgainst -> promptC editHomeGoalsAgainstPrompt
|
||||
|
||||
editAwayStandingsC :: ESMSubMode -> Controller
|
||||
editAwayStandingsC = \case
|
||||
ESMSubMenu -> menuC editAwayStandingsMenu
|
||||
ESMEditWins -> promptC editAwayWinsPrompt
|
||||
ESMEditLosses -> promptC editAwayLossesPrompt
|
||||
ESMEditOvertime -> promptC editAwayOvertimePrompt
|
||||
ESMEditGoalsFor -> promptC editAwayGoalsForPrompt
|
||||
ESMEditGoalsAgainst -> promptC editAwayGoalsAgainstPrompt
|
||||
|
||||
menuC :: Menu () -> Controller
|
||||
menuC = menuControllerWith header
|
||||
|
||||
promptC :: Prompt -> Controller
|
||||
promptC = promptControllerWith header
|
||||
|
||||
header :: ProgState -> C.Update ()
|
||||
header = do
|
||||
db <- (^.database)
|
||||
let
|
||||
home = db^.dbHomeGameStats
|
||||
away = db^.dbAwayGameStats
|
||||
table = numTable [" W", " L", " OT", " GF", " GA"]
|
||||
[ ( "HOME", valsFor home )
|
||||
, ( "ROAD", valsFor away )
|
||||
]
|
||||
return $ C.drawString $ unlines $ table ++ [""]
|
||||
|
||||
valsFor :: GameStats -> [Int]
|
||||
valsFor gs =
|
||||
[ gs^.gmsWins
|
||||
, gs^.gmsLosses
|
||||
, gs^.gmsOvertime
|
||||
, gs^.gmsGoalsFor
|
||||
, gs^.gmsGoalsAgainst
|
||||
]
|
||||
142
src/Mtlstats/Control/TitleScreen.hs
Normal file
142
src/Mtlstats/Control/TitleScreen.hs
Normal file
@@ -0,0 +1,142 @@
|
||||
{- |
|
||||
|
||||
mtlstats
|
||||
Copyright (C) 1984, 1985, 2019, 2020 Rhéal Lamothe
|
||||
<rheal.lamothe@gmail.com>
|
||||
|
||||
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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
-}
|
||||
|
||||
{-# LANGUAGE LambdaCase #-}
|
||||
|
||||
module Mtlstats.Control.TitleScreen (titleScreenC) where
|
||||
|
||||
import Control.Monad.Trans.State (modify)
|
||||
import Data.Char (chr)
|
||||
import qualified UI.NCurses as C
|
||||
|
||||
import Mtlstats.Actions
|
||||
import Mtlstats.Format
|
||||
import Mtlstats.Types
|
||||
|
||||
titleScreenC :: Controller
|
||||
titleScreenC = Controller
|
||||
{ drawController = const $ do
|
||||
(_, cols) <- C.windowSize
|
||||
C.drawString $ unlines $ map (centre $ fromIntegral $ pred cols)
|
||||
$ [ ""
|
||||
, "MONTREAL CANADIENS STATISTICS"
|
||||
]
|
||||
++ titleText
|
||||
++ [ ""
|
||||
, "Copyright (C) 1984, 1985, 2019, 2020 Rhéal Lamothe"
|
||||
, "<rheal.lamothe@gmail.com>"
|
||||
, ""
|
||||
, "Press any key to continue..."
|
||||
]
|
||||
return C.CursorInvisible
|
||||
, handleController = \case
|
||||
C.EventCharacter _ -> modify backHome >> return True
|
||||
C.EventSpecialKey _ -> modify backHome >> return True
|
||||
_ -> return True
|
||||
}
|
||||
|
||||
titleText :: [String]
|
||||
titleText = box $ map (map blockify) $ foldl joinBlocks (repeat "")
|
||||
[chM, chT, chL, chS, chT, chA, chT, chS]
|
||||
|
||||
box :: [String] -> [String]
|
||||
box strs
|
||||
= [[tl] ++ replicate width horiz ++ [tr]]
|
||||
++ map (\str -> [vert] ++ str ++ [vert]) strs
|
||||
++ [[bl] ++ replicate width horiz ++ [br]]
|
||||
where
|
||||
width = length $ head strs
|
||||
tl = chr 0x2554
|
||||
tr = chr 0x2557
|
||||
bl = chr 0x255a
|
||||
br = chr 0x255d
|
||||
horiz = chr 0x2550
|
||||
vert = chr 0x2551
|
||||
|
||||
blockify :: Char -> Char
|
||||
blockify = \case
|
||||
'#' -> chr 0x2588
|
||||
'>' -> chr 0x2590
|
||||
'<' -> chr 0x258c
|
||||
ch -> ch
|
||||
|
||||
joinBlocks :: [String] -> [String] -> [String]
|
||||
joinBlocks = zipWith (++)
|
||||
|
||||
chM :: [String]
|
||||
chM =
|
||||
[ "##< >##"
|
||||
, ">## ##<"
|
||||
, ">##< >##<"
|
||||
, ">### ###<"
|
||||
, ">#######<"
|
||||
, ">#<###>#<"
|
||||
, ">#<>#<>#<"
|
||||
, "##< >##"
|
||||
]
|
||||
|
||||
chT :: [String]
|
||||
chT =
|
||||
[ ">########<"
|
||||
, ">## ## ##<"
|
||||
, ">#< ## >#<"
|
||||
, " ## "
|
||||
, " ## "
|
||||
, " ## "
|
||||
, " ## "
|
||||
, " >##< "
|
||||
]
|
||||
|
||||
chL :: [String]
|
||||
chL =
|
||||
[ "### "
|
||||
, ">#< "
|
||||
, ">#< "
|
||||
, ">#< "
|
||||
, ">#< "
|
||||
, ">#< ##"
|
||||
, ">#< >##"
|
||||
, "#######"
|
||||
]
|
||||
|
||||
chS :: [String]
|
||||
chS =
|
||||
[ " #####< "
|
||||
, ">#< ## "
|
||||
, "## "
|
||||
, " #####< "
|
||||
, " >#<"
|
||||
, " ##"
|
||||
, ">#< >#<"
|
||||
, " ###### "
|
||||
]
|
||||
|
||||
chA :: [String]
|
||||
chA =
|
||||
[ " >##< "
|
||||
, " ## "
|
||||
, " >##< "
|
||||
, " #### "
|
||||
, " >#<>#< "
|
||||
, " ###### "
|
||||
, ">#< >#<"
|
||||
, "### ###"
|
||||
]
|
||||
@@ -51,8 +51,12 @@ goalieDetails g = let
|
||||
goalieName :: Goalie -> String
|
||||
goalieName g = let
|
||||
|
||||
prefix = if g^.gActive
|
||||
then ""
|
||||
else "*"
|
||||
|
||||
suffix = if g^.gRookie
|
||||
then "*"
|
||||
else ""
|
||||
|
||||
in g^.gName ++ suffix
|
||||
in prefix ++ g^.gName ++ suffix
|
||||
|
||||
@@ -49,8 +49,12 @@ playerDetails p = unlines $ top ++ [""] ++ table
|
||||
playerName :: Player -> String
|
||||
playerName p = let
|
||||
|
||||
prefix = if p^.pActive
|
||||
then ""
|
||||
else "*"
|
||||
|
||||
suffix = if p^.pRookie
|
||||
then "*"
|
||||
else ""
|
||||
|
||||
in p^.pName ++ suffix
|
||||
in prefix ++ p^.pName ++ suffix
|
||||
|
||||
@@ -35,24 +35,18 @@ module Mtlstats.Menu (
|
||||
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.Actions.EditStandings
|
||||
import Mtlstats.Config
|
||||
import Mtlstats.Format
|
||||
import Mtlstats.Types
|
||||
import Mtlstats.Types.Menu
|
||||
import Mtlstats.Util
|
||||
@@ -96,7 +90,11 @@ menuStateController menuFunc = Controller
|
||||
-- | The draw function for a 'Menu'
|
||||
drawMenu :: Menu a -> C.Update C.CursorMode
|
||||
drawMenu m = do
|
||||
C.drawString $ show m
|
||||
(_, cols) <- C.windowSize
|
||||
let
|
||||
width = fromIntegral $ pred cols
|
||||
menuText = map (centre width) $ lines $ show m
|
||||
C.drawString $ unlines menuText
|
||||
return C.CursorInvisible
|
||||
|
||||
-- | The event handler for a 'Menu'
|
||||
@@ -109,61 +107,56 @@ menuHandler m _ = return $ m^.menuDefault
|
||||
|
||||
-- | The main menu
|
||||
mainMenu :: Menu Bool
|
||||
mainMenu = Menu "*** MAIN MENU ***" True
|
||||
[ MenuItem '1' "New Season" $
|
||||
mainMenu = Menu "MASTER MENU" True
|
||||
[ MenuItem 'A' "NEW SEASON" $
|
||||
modify startNewSeason >> return True
|
||||
, MenuItem '2' "New Game" $
|
||||
, MenuItem 'B' "NEW GAME" $
|
||||
modify startNewGame >> return True
|
||||
, MenuItem '3' "Edit" $
|
||||
, MenuItem 'C' "EDIT MENU" $
|
||||
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
|
||||
, MenuItem 'E' "EXIT" $
|
||||
saveDatabase dbFname >> return False
|
||||
]
|
||||
|
||||
-- | The new season menu
|
||||
newSeasonMenu :: Menu ()
|
||||
newSeasonMenu = Menu "*** SEASON TYPE ***" ()
|
||||
[ MenuItem 'R' "Regular Season" $ modify
|
||||
newSeasonMenu = Menu "SEASON TYPE" ()
|
||||
[ MenuItem 'R' "REGULAR SEASON" $ modify
|
||||
$ resetYtd
|
||||
. clearRookies
|
||||
. resetStandings
|
||||
. startNewGame
|
||||
, MenuItem 'P' "Playoffs" $ modify
|
||||
, MenuItem 'P' "PLAYOFFS" $ modify
|
||||
$ resetStandings
|
||||
. startNewGame
|
||||
]
|
||||
|
||||
-- | Requests the month in which the game took place
|
||||
gameMonthMenu :: Menu ()
|
||||
gameMonthMenu = Menu "Month:" () $ map
|
||||
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 )
|
||||
[ ( '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" $
|
||||
gameTypeMenu = Menu "GAME TYPE:" ()
|
||||
[ MenuItem 'H' "HOME GAME" $
|
||||
modify $ progMode.gameStateL.gameType ?~ HomeGame
|
||||
, MenuItem '2' "Away Game" $
|
||||
, MenuItem 'A' "AWAY GAME" $
|
||||
modify $ progMode.gameStateL.gameType ?~ AwayGame
|
||||
]
|
||||
|
||||
@@ -184,15 +177,17 @@ gameGoalieMenu s = let
|
||||
|
||||
-- | The edit menu
|
||||
editMenu :: Menu ()
|
||||
editMenu = Menu "*** EDIT ***" ()
|
||||
[ MenuItem '1' "Create Player" $
|
||||
editMenu = Menu "EDIT MENU" ()
|
||||
[ MenuItem 'A' "CREATE PLAYER" $
|
||||
modify createPlayer
|
||||
, MenuItem '2' "Create Goalie" $
|
||||
, MenuItem 'B' "CREATE GOALIE" $
|
||||
modify createGoalie
|
||||
, MenuItem '3' "Edit Player" $
|
||||
, MenuItem 'C' "EDIT PLAYER" $
|
||||
modify editPlayer
|
||||
, MenuItem '4' "Edit Goalie" $
|
||||
, MenuItem 'D' "EDIT GOALIE" $
|
||||
modify editGoalie
|
||||
, MenuItem 'R' "Return to Main Menu" $
|
||||
, MenuItem 'E' "EDIT STANDINGS" $
|
||||
modify editStandings
|
||||
, MenuItem 'R' "RETURN TO MAIN MENU" $
|
||||
modify backHome
|
||||
]
|
||||
|
||||
@@ -34,51 +34,53 @@ import Mtlstats.Types.Menu
|
||||
|
||||
-- | The 'Goalie' edit menu
|
||||
editGoalieMenu :: Menu ()
|
||||
editGoalieMenu = Menu "*** EDIT GOALTENDER ***" () $ map
|
||||
editGoalieMenu = Menu "EDIT GOALTENDER" () $ map
|
||||
(\(ch, label, action) -> MenuItem ch label $ modify action)
|
||||
|
||||
-- key, label, value
|
||||
[ ( '1', "Edit number", set EGNumber )
|
||||
, ( '2', "Edit name", set EGName )
|
||||
, ( '3', "Toggle rookie flag", toggle )
|
||||
, ( '4', "Edit YTD stats", set EGYtd )
|
||||
, ( '5', "Edit Lifetime stats", set EGLifetime )
|
||||
, ( 'R', "Return to Edit Menu", edit )
|
||||
[ ( 'A', "EDIT NUMBER", set EGNumber )
|
||||
, ( 'B', "EDIT NAME", set EGName )
|
||||
, ( 'C', "TOGGLE ROOKIE FLAG", toggleRookie )
|
||||
, ( 'D', "TOGGLE ACTIVE FLAG", toggleActive )
|
||||
, ( 'E', "EDIT YTD STATS", set EGYtd )
|
||||
, ( 'F', "EDIT LIFETIME STATS", set EGLifetime )
|
||||
, ( 'R', "RETURN TO EDIT MENU", edit )
|
||||
]
|
||||
|
||||
where
|
||||
set mode = progMode.editGoalieStateL.egsMode .~ mode
|
||||
toggle = editSelectedGoalie (gRookie %~ not)
|
||||
set mode = progMode.editGoalieStateL.egsMode .~ mode
|
||||
toggleRookie = editSelectedGoalie (gRookie %~ not)
|
||||
toggleActive = editSelectedGoalie (gActive %~ not)
|
||||
|
||||
-- | The 'Goalie' YTD edit menu
|
||||
editGoalieYtdMenu :: Menu ()
|
||||
editGoalieYtdMenu = editMenu "*** EDIT GOALTENDER YEAR-TO-DATE ***"
|
||||
editGoalieYtdMenu = editMenu "EDIT GOALTENDER YEAR-TO-DATE"
|
||||
-- key, label, value
|
||||
[ ( '1', "Edit all YTD stats", EGYtdGames True )
|
||||
, ( '2', "Edit YTD games", EGYtdGames False )
|
||||
, ( '3', "Edit YTD minutes", EGYtdMins False )
|
||||
, ( '4', "Edit YTD goals", EGYtdGoals False )
|
||||
, ( '5', "Edit YTD shutouts", EGYtdShutouts False )
|
||||
, ( '6', "Edit YTD wins", EGYtdWins False )
|
||||
, ( '7', "Edit YTD losses", EGYtdLosses False )
|
||||
, ( '8', "Edit YTD ties", EGYtdTies )
|
||||
, ( 'R', "Return to edit menu", EGMenu )
|
||||
[ ( 'A', "EDIT ALL YTD STATS", EGYtdGames True )
|
||||
, ( 'B', "EDIT YTD GAMES", EGYtdGames False )
|
||||
, ( 'C', "EDIT YTD MINUTES", EGYtdMins False )
|
||||
, ( 'D', "EDIT YTD GOALS", EGYtdGoals False )
|
||||
, ( 'E', "EDIT YTD SHUTOUTS", EGYtdShutouts False )
|
||||
, ( 'F', "EDIT YTD WINS", EGYtdWins False )
|
||||
, ( 'G', "EDIT YTD LOSSES", EGYtdLosses False )
|
||||
, ( 'H', "EDIT YTD TIES", EGYtdTies )
|
||||
, ( 'R', "RETURN TO EDIT MENU", EGMenu )
|
||||
]
|
||||
|
||||
-- | The 'Goalie' lifetime edit menu
|
||||
editGoalieLtMenu :: Menu ()
|
||||
editGoalieLtMenu = editMenu
|
||||
"*** EDIT GOALTENDER LIFETIME ***"
|
||||
"EDIT GOALTENDER LIFETIME"
|
||||
-- key, label, value
|
||||
[ ( '1', "Edit all lifetime stats", EGLtGames True )
|
||||
, ( '2', "Edit lifetime games", EGLtGames False )
|
||||
, ( '3', "Edit lifetime minutes", EGLtMins False )
|
||||
, ( '4', "Edit lifetime goals", EGLtGoals False )
|
||||
, ( '5', "Edit lifetime shutouts", EGLtShutouts False )
|
||||
, ( '6', "Edit lifetime wins", EGLtWins False )
|
||||
, ( '7', "Edit lifetime losses", EGLtLosses False )
|
||||
, ( '8', "Edit lifetime ties", EGLtTies )
|
||||
, ( 'R', "Return to edit menu", EGMenu )
|
||||
[ ( 'A', "EDIT ALL LIFETIME STATS", EGLtGames True )
|
||||
, ( 'B', "EDIT LIFETIME GAMES", EGLtGames False )
|
||||
, ( 'C', "EDIT LIFETIME MINUTES", EGLtMins False )
|
||||
, ( 'D', "EDIT LIFETIME GOALS", EGLtGoals False )
|
||||
, ( 'E', "EDIT LIFETIME SHUTOUTS", EGLtShutouts False )
|
||||
, ( 'F', "EDIT LIFETIME WINS", EGLtWins False )
|
||||
, ( 'G', "EDIT LIFETIME LOSSES", EGLtLosses False )
|
||||
, ( 'H', "EDIT LIFETIME TIES", EGLtTies )
|
||||
, ( 'R', "RETURN TO EDIT MENU", EGMenu )
|
||||
]
|
||||
|
||||
editMenu :: String -> [(Char, String, EditGoalieMode)] -> Menu ()
|
||||
|
||||
@@ -34,45 +34,47 @@ import Mtlstats.Types.Menu
|
||||
|
||||
-- | The 'Player' edit menu
|
||||
editPlayerMenu :: Menu ()
|
||||
editPlayerMenu = Menu "*** EDIT PLAYER ***" () $ map
|
||||
editPlayerMenu = Menu "EDIT PLAYER" () $ map
|
||||
(\(ch, label, action) -> MenuItem ch label $ modify action)
|
||||
|
||||
-- key, label, value
|
||||
[ ( '1', "Edit number", set EPNumber )
|
||||
, ( '2', "Edit name", set EPName )
|
||||
, ( '3', "Edit position", set EPPosition )
|
||||
, ( '4', "Toggle rookie flag", toggle )
|
||||
, ( '5', "Edit YTD stats", set EPYtd )
|
||||
, ( '6', "Edit lifetime stats", set EPLifetime )
|
||||
, ( 'R', "Return to Edit Menu", edit )
|
||||
[ ( 'A', "EDIT NUMBER", set EPNumber )
|
||||
, ( 'B', "EDIT NAME", set EPName )
|
||||
, ( 'C', "EDIT POSITION", set EPPosition )
|
||||
, ( 'D', "TOGGLE ROOKIE FLAG", toggleRookie )
|
||||
, ( 'E', "TOGGLE ACTIVE FLAG", toggleActive )
|
||||
, ( 'F', "EDIT YTD STATS", set EPYtd )
|
||||
, ( 'G', "EDIT LIFETIME STATS", set EPLifetime )
|
||||
, ( 'R', "RETURN TO EDIT MENU", edit )
|
||||
]
|
||||
|
||||
where
|
||||
set mode = progMode.editPlayerStateL.epsMode .~ mode
|
||||
toggle = editSelectedPlayer $ pRookie %~ not
|
||||
set mode = progMode.editPlayerStateL.epsMode .~ mode
|
||||
toggleRookie = editSelectedPlayer $ pRookie %~ not
|
||||
toggleActive = editSelectedPlayer $ pActive %~ not
|
||||
|
||||
-- | The 'Player' YTD stats edit menu
|
||||
editPlayerYtdMenu :: Menu ()
|
||||
editPlayerYtdMenu = editMenu
|
||||
"*** EDIT PLAYER YEAR-TO-DATE ***"
|
||||
"EDIT PLAYER YEAR-TO-DATE"
|
||||
-- key, label, value
|
||||
[ ( '1', "Edit all YTD stats", EPYtdGoals True )
|
||||
, ( '2', "Edit YTD goals", EPYtdGoals False )
|
||||
, ( '3', "Edit YTD assists", EPYtdAssists False )
|
||||
, ( '4', "Edit YTD penalty mins", EPYtdPMin )
|
||||
, ( 'R', "Return to player edit menu", EPMenu )
|
||||
[ ( 'A', "EDIT ALL YTD STATS", EPYtdGoals True )
|
||||
, ( 'B', "EDIT YTD GOALS", EPYtdGoals False )
|
||||
, ( 'C', "EDIT YTD ASSISTS", EPYtdAssists False )
|
||||
, ( 'D', "EDIT YTD PENALTY MINS", EPYtdPMin )
|
||||
, ( 'R', "RETURN TO PLAYER EDIT MENU", EPMenu )
|
||||
]
|
||||
|
||||
-- | The 'Player' lifetime stats edit menu
|
||||
editPlayerLtMenu :: Menu ()
|
||||
editPlayerLtMenu = editMenu
|
||||
"*** EDIT PLAYER LIFETIME ***"
|
||||
"EDIT PLAYER LIFETIME"
|
||||
-- key, label, value
|
||||
[ ( '1', "Edit all lifetime stats", EPLtGoals True )
|
||||
, ( '2', "Edit lifetime goals", EPLtGoals False )
|
||||
, ( '3', "Edit lifetime assits", EPLtAssists False )
|
||||
, ( '4', "Edit lifetime penalty mins", EPLtPMin )
|
||||
, ( 'R', "Return to edit player menu", EPMenu )
|
||||
[ ( 'A', "EDIT ALL LIFETIME STATS", EPLtGoals True )
|
||||
, ( 'B', "EDIT LIFETIME GOALS", EPLtGoals False )
|
||||
, ( 'C', "EDIT LIFETIME ASSITS", EPLtAssists False )
|
||||
, ( 'D', "EDIT LIFETIME PENALTY MINS", EPLtPMin )
|
||||
, ( 'R', "RETURN TO EDIT PLAYER MENU", EPMenu )
|
||||
]
|
||||
|
||||
editMenu :: String -> [(Char, String, EditPlayerMode)] -> Menu ()
|
||||
|
||||
64
src/Mtlstats/Menu/EditStandings.hs
Normal file
64
src/Mtlstats/Menu/EditStandings.hs
Normal file
@@ -0,0 +1,64 @@
|
||||
{- |
|
||||
|
||||
mtlstats
|
||||
Copyright (C) 1984, 1985, 2019, 2020 Rhéal Lamothe
|
||||
<rheal.lamothe@gmail.com>
|
||||
|
||||
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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
-}
|
||||
|
||||
module Mtlstats.Menu.EditStandings
|
||||
( editStandingsMenu
|
||||
, editHomeStandingsMenu
|
||||
, editAwayStandingsMenu
|
||||
) where
|
||||
|
||||
import Control.Monad.Trans.State (modify)
|
||||
|
||||
import Mtlstats.Actions
|
||||
import Mtlstats.Actions.EditStandings
|
||||
import Mtlstats.Types.Menu
|
||||
|
||||
editStandingsMenu :: Menu ()
|
||||
editStandingsMenu = Menu "EDIT STANDINGS" ()
|
||||
[ MenuItem 'A' "EDIT HOME STANDINGS" $
|
||||
modify editHomeStandings
|
||||
, MenuItem 'B' "EDIT ROAD STANDINGS" $
|
||||
modify editAwayStandings
|
||||
, MenuItem 'R' "RETURN TO MAIN MENU" $
|
||||
modify backHome
|
||||
]
|
||||
|
||||
editHomeStandingsMenu :: Menu ()
|
||||
editHomeStandingsMenu = subMenu "HOME"
|
||||
|
||||
editAwayStandingsMenu :: Menu ()
|
||||
editAwayStandingsMenu = subMenu "ROAD"
|
||||
|
||||
subMenu :: String -> Menu ()
|
||||
subMenu str = Menu (str ++ " STANDINGS") ()
|
||||
[ MenuItem 'W' "EDIT WINS" $
|
||||
modify editWins
|
||||
, MenuItem 'L' "EDIT LOSSES" $
|
||||
modify editLosses
|
||||
, MenuItem 'O' "EDIT OVERTIME GAMES" $
|
||||
modify editOvertime
|
||||
, MenuItem 'F' "EDIT GOALS FOR" $
|
||||
modify editGoalsFor
|
||||
, MenuItem 'A' "EDIT GOALS AGAINST" $
|
||||
modify editGoalsAgainst
|
||||
, MenuItem 'R' "RETURN TO EDIT STANDINGS MENU" $
|
||||
modify editStandings
|
||||
]
|
||||
@@ -34,6 +34,7 @@ module Mtlstats.Prompt (
|
||||
numPromptWithFallback,
|
||||
selectPrompt,
|
||||
-- * Individual prompts
|
||||
newSeasonPrompt,
|
||||
playerNumPrompt,
|
||||
playerNamePrompt,
|
||||
playerPosPrompt,
|
||||
@@ -47,7 +48,7 @@ module Mtlstats.Prompt (
|
||||
import Control.Monad (when)
|
||||
import Control.Monad.Extra (whenJust)
|
||||
import Control.Monad.Trans.State (gets, modify)
|
||||
import Data.Char (isDigit, toUpper)
|
||||
import Data.Char (isAlphaNum, isDigit, toUpper)
|
||||
import Lens.Micro ((^.), (&), (.~), (?~), (%~))
|
||||
import Lens.Micro.Extras (view)
|
||||
import Text.Read (readMaybe)
|
||||
@@ -167,6 +168,22 @@ numPromptWithFallback pStr fallback act = Prompt
|
||||
, promptSpecialKey = const $ return ()
|
||||
}
|
||||
|
||||
-- | Prompts the user for a filename to save a backup of the database
|
||||
-- to
|
||||
newSeasonPrompt :: Prompt
|
||||
newSeasonPrompt = prompt
|
||||
{ promptProcessChar = \ch str -> if isAlphaNum ch
|
||||
then str ++ [toUpper ch]
|
||||
else str
|
||||
}
|
||||
where
|
||||
prompt = strPrompt "Filename to save database: " $ \fn ->
|
||||
if null fn
|
||||
then modify backHome
|
||||
else do
|
||||
saveDatabase $ fn ++ ".json"
|
||||
modify $ progMode .~ NewSeason True
|
||||
|
||||
-- | Builds a selection prompt
|
||||
selectPrompt :: SelectParams a -> Prompt
|
||||
selectPrompt params = Prompt
|
||||
|
||||
89
src/Mtlstats/Prompt/EditStandings.hs
Normal file
89
src/Mtlstats/Prompt/EditStandings.hs
Normal file
@@ -0,0 +1,89 @@
|
||||
{- |
|
||||
|
||||
mtlstats
|
||||
Copyright (C) 1984, 1985, 2019, 2020 Rhéal Lamothe
|
||||
<rheal.lamothe@gmail.com>
|
||||
|
||||
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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
-}
|
||||
|
||||
module Mtlstats.Prompt.EditStandings
|
||||
( editHomeWinsPrompt
|
||||
, editHomeLossesPrompt
|
||||
, editHomeOvertimePrompt
|
||||
, editHomeGoalsForPrompt
|
||||
, editHomeGoalsAgainstPrompt
|
||||
, editAwayWinsPrompt
|
||||
, editAwayLossesPrompt
|
||||
, editAwayOvertimePrompt
|
||||
, editAwayGoalsForPrompt
|
||||
, editAwayGoalsAgainstPrompt
|
||||
) where
|
||||
|
||||
import Control.Monad.Trans.State (modify)
|
||||
import Lens.Micro ((.~), (%~))
|
||||
|
||||
import Mtlstats.Prompt
|
||||
import Mtlstats.Types
|
||||
|
||||
editHomeWinsPrompt :: Prompt
|
||||
editHomeWinsPrompt =
|
||||
mkPrompt "Home wins: " (dbHomeGameStats.gmsWins .~)
|
||||
|
||||
editHomeLossesPrompt :: Prompt
|
||||
editHomeLossesPrompt =
|
||||
mkPrompt "Home losses: " (dbHomeGameStats.gmsLosses .~)
|
||||
|
||||
editHomeOvertimePrompt :: Prompt
|
||||
editHomeOvertimePrompt =
|
||||
mkPrompt "Home overtime games: " (dbHomeGameStats.gmsOvertime .~)
|
||||
|
||||
editHomeGoalsForPrompt :: Prompt
|
||||
editHomeGoalsForPrompt =
|
||||
mkPrompt "Home goals for: " (dbHomeGameStats.gmsGoalsFor .~)
|
||||
|
||||
editHomeGoalsAgainstPrompt :: Prompt
|
||||
editHomeGoalsAgainstPrompt =
|
||||
mkPrompt "Home goals against: " (dbHomeGameStats.gmsGoalsAgainst .~)
|
||||
|
||||
editAwayWinsPrompt :: Prompt
|
||||
editAwayWinsPrompt =
|
||||
mkPrompt "Road wins: " (dbAwayGameStats.gmsWins .~)
|
||||
|
||||
editAwayLossesPrompt :: Prompt
|
||||
editAwayLossesPrompt =
|
||||
mkPrompt "Road losses: " (dbAwayGameStats.gmsLosses .~)
|
||||
|
||||
editAwayOvertimePrompt :: Prompt
|
||||
editAwayOvertimePrompt =
|
||||
mkPrompt "Road overtime games: " (dbAwayGameStats.gmsOvertime .~)
|
||||
|
||||
editAwayGoalsForPrompt :: Prompt
|
||||
editAwayGoalsForPrompt =
|
||||
mkPrompt "Road goals for: " (dbAwayGameStats.gmsGoalsFor .~)
|
||||
|
||||
editAwayGoalsAgainstPrompt :: Prompt
|
||||
editAwayGoalsAgainstPrompt =
|
||||
mkPrompt "Road goals against: " (dbAwayGameStats.gmsGoalsAgainst .~)
|
||||
|
||||
mkPrompt :: String -> (Int -> Database -> Database) -> Prompt
|
||||
mkPrompt pStr f = numPromptWithFallback pStr
|
||||
(modify subMenu)
|
||||
(\n -> modify
|
||||
$ (database %~ f n)
|
||||
. subMenu)
|
||||
|
||||
subMenu :: ProgState -> ProgState
|
||||
subMenu = progMode.editStandingsModeL.esmSubModeL .~ ESMSubMenu
|
||||
@@ -35,6 +35,8 @@ module Mtlstats.Types (
|
||||
EditPlayerMode (..),
|
||||
EditGoalieState (..),
|
||||
EditGoalieMode (..),
|
||||
EditStandingsMode (..),
|
||||
ESMSubMode (..),
|
||||
Database (..),
|
||||
Player (..),
|
||||
PlayerStats (..),
|
||||
@@ -56,6 +58,9 @@ module Mtlstats.Types (
|
||||
createGoalieStateL,
|
||||
editPlayerStateL,
|
||||
editGoalieStateL,
|
||||
editStandingsModeL,
|
||||
-- ** EditStandingsMode Lenses
|
||||
esmSubModeL,
|
||||
-- ** GameState Lenses
|
||||
gameYear,
|
||||
gameMonth,
|
||||
@@ -107,6 +112,7 @@ module Mtlstats.Types (
|
||||
pName,
|
||||
pPosition,
|
||||
pRookie,
|
||||
pActive,
|
||||
pYtd,
|
||||
pLifetime,
|
||||
-- ** PlayerStats Lenses
|
||||
@@ -117,6 +123,7 @@ module Mtlstats.Types (
|
||||
gNumber,
|
||||
gName,
|
||||
gRookie,
|
||||
gActive,
|
||||
gYtd,
|
||||
gLifetime,
|
||||
-- ** GoalieStats Lenses
|
||||
@@ -229,24 +236,28 @@ data ProgState = ProgState
|
||||
|
||||
-- | The program mode
|
||||
data ProgMode
|
||||
= MainMenu
|
||||
| NewSeason
|
||||
= TitleScreen
|
||||
| MainMenu
|
||||
| NewSeason Bool
|
||||
| NewGame GameState
|
||||
| EditMenu
|
||||
| CreatePlayer CreatePlayerState
|
||||
| CreateGoalie CreateGoalieState
|
||||
| EditPlayer EditPlayerState
|
||||
| EditGoalie EditGoalieState
|
||||
| EditStandings EditStandingsMode
|
||||
|
||||
instance Show ProgMode where
|
||||
show MainMenu = "MainMenu"
|
||||
show NewSeason = "NewSeason"
|
||||
show (NewGame _) = "NewGame"
|
||||
show EditMenu = "EditMenu"
|
||||
show (CreatePlayer _) = "CreatePlayer"
|
||||
show (CreateGoalie _) = "CreateGoalie"
|
||||
show (EditPlayer _) = "EditPlayer"
|
||||
show (EditGoalie _) = "EditGoalie"
|
||||
show TitleScreen = "TitleScreen"
|
||||
show MainMenu = "MainMenu"
|
||||
show (NewSeason _) = "NewSeason"
|
||||
show (NewGame _) = "NewGame"
|
||||
show EditMenu = "EditMenu"
|
||||
show (CreatePlayer _) = "CreatePlayer"
|
||||
show (CreateGoalie _) = "CreateGoalie"
|
||||
show (EditPlayer _) = "EditPlayer"
|
||||
show (EditGoalie _) = "EditGoalie"
|
||||
show (EditStandings _) = "EditStandings"
|
||||
|
||||
-- | The game state
|
||||
data GameState = GameState
|
||||
@@ -387,6 +398,23 @@ data EditGoalieMode
|
||||
| EGLtTies
|
||||
deriving (Eq, Show)
|
||||
|
||||
-- | Represents the standings edit mode
|
||||
data EditStandingsMode
|
||||
= ESMMenu
|
||||
| ESMHome ESMSubMode
|
||||
| ESMAway ESMSubMode
|
||||
deriving (Eq, Show)
|
||||
|
||||
-- | Represents the standings edit sub-mode
|
||||
data ESMSubMode
|
||||
= ESMSubMenu
|
||||
| ESMEditWins
|
||||
| ESMEditLosses
|
||||
| ESMEditOvertime
|
||||
| ESMEditGoalsFor
|
||||
| ESMEditGoalsAgainst
|
||||
deriving (Eq, Show)
|
||||
|
||||
-- | Represents the database
|
||||
data Database = Database
|
||||
{ _dbPlayers :: [Player]
|
||||
@@ -411,6 +439,8 @@ data Player = Player
|
||||
-- ^ The player's position
|
||||
, _pRookie :: Bool
|
||||
-- ^ Indicates that the player is a rookie
|
||||
, _pActive :: Bool
|
||||
-- ^ Indicates that the player is active
|
||||
, _pYtd :: PlayerStats
|
||||
-- ^ The Player's year-to-date stats
|
||||
, _pLifetime :: PlayerStats
|
||||
@@ -435,6 +465,8 @@ data Goalie = Goalie
|
||||
-- ^ The goalie's name
|
||||
, _gRookie :: Bool
|
||||
-- ^ Indicates that the goalie is a rookie
|
||||
, _gActive :: Bool
|
||||
-- ^ Indicates that the goalie is active
|
||||
, _gYtd :: GoalieStats
|
||||
-- ^ The goalie's year-to-date stats
|
||||
, _gLifetime :: GoalieStats
|
||||
@@ -555,23 +587,26 @@ instance FromJSON Player where
|
||||
<*> v .: "name"
|
||||
<*> v .: "position"
|
||||
<*> v .:? "rookie" .!= False
|
||||
<*> v .:? "active" .!= True
|
||||
<*> v .:? "ytd" .!= newPlayerStats
|
||||
<*> v .:? "lifetime" .!= newPlayerStats
|
||||
|
||||
instance ToJSON Player where
|
||||
toJSON (Player num name pos rk ytd lt) = object
|
||||
toJSON (Player num name pos rk act ytd lt) = object
|
||||
[ "number" .= num
|
||||
, "name" .= name
|
||||
, "position" .= pos
|
||||
, "rookie" .= rk
|
||||
, "active" .= act
|
||||
, "ytd" .= ytd
|
||||
, "lifetime" .= lt
|
||||
]
|
||||
toEncoding (Player num name pos rk ytd lt) = pairs $
|
||||
toEncoding (Player num name pos rk act ytd lt) = pairs $
|
||||
"number" .= num <>
|
||||
"name" .= name <>
|
||||
"position" .= pos <>
|
||||
"rookie" .= rk <>
|
||||
"active" .= act <>
|
||||
"ytd" .= ytd <>
|
||||
"lifetime" .= lt
|
||||
|
||||
@@ -597,21 +632,24 @@ instance FromJSON Goalie where
|
||||
<$> v .: "number"
|
||||
<*> v .: "name"
|
||||
<*> v .:? "rookie" .!= False
|
||||
<*> v .:? "active" .!= True
|
||||
<*> v .:? "ytd" .!= newGoalieStats
|
||||
<*> v .:? "lifetime" .!= newGoalieStats
|
||||
|
||||
instance ToJSON Goalie where
|
||||
toJSON (Goalie num name rk ytd lt) = object
|
||||
toJSON (Goalie num name rk act ytd lt) = object
|
||||
[ "number" .= num
|
||||
, "name" .= name
|
||||
, "ytd" .= ytd
|
||||
, "rookie" .= rk
|
||||
, "active" .= act
|
||||
, "lifetime" .= lt
|
||||
]
|
||||
toEncoding (Goalie num name rk ytd lt) = pairs $
|
||||
toEncoding (Goalie num name rk act ytd lt) = pairs $
|
||||
"number" .= num <>
|
||||
"name" .= name <>
|
||||
"rookie" .= rk <>
|
||||
"active" .= act <>
|
||||
"ytd" .= ytd <>
|
||||
"lifetime" .= lt
|
||||
|
||||
@@ -702,11 +740,29 @@ editGoalieStateL = lens
|
||||
_ -> newEditGoalieState)
|
||||
(\_ egs -> EditGoalie egs)
|
||||
|
||||
editStandingsModeL :: Lens' ProgMode EditStandingsMode
|
||||
editStandingsModeL = lens
|
||||
(\case
|
||||
EditStandings esm -> esm
|
||||
_ -> ESMMenu)
|
||||
(\_ esm -> EditStandings esm)
|
||||
|
||||
esmSubModeL :: Lens' EditStandingsMode ESMSubMode
|
||||
esmSubModeL = lens
|
||||
(\case
|
||||
ESMMenu -> ESMSubMenu
|
||||
ESMHome m -> m
|
||||
ESMAway m -> m)
|
||||
(\mode subMode -> case mode of
|
||||
ESMMenu -> ESMMenu
|
||||
ESMHome _ -> ESMHome subMode
|
||||
ESMAway _ -> ESMAway subMode)
|
||||
|
||||
-- | Constructor for a 'ProgState'
|
||||
newProgState :: ProgState
|
||||
newProgState = ProgState
|
||||
{ _database = newDatabase
|
||||
, _progMode = MainMenu
|
||||
, _progMode = TitleScreen
|
||||
, _inputBuffer = ""
|
||||
, _scrollOffset = 0
|
||||
}
|
||||
@@ -795,6 +851,7 @@ newPlayer num name pos = Player
|
||||
, _pName = name
|
||||
, _pPosition = pos
|
||||
, _pRookie = True
|
||||
, _pActive = True
|
||||
, _pYtd = newPlayerStats
|
||||
, _pLifetime = newPlayerStats
|
||||
}
|
||||
@@ -818,6 +875,7 @@ newGoalie num name = Goalie
|
||||
{ _gNumber = num
|
||||
, _gName = name
|
||||
, _gRookie = True
|
||||
, _gActive = True
|
||||
, _gYtd = newGoalieStats
|
||||
, _gLifetime = newGoalieStats
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ module Mtlstats.Types.Menu (
|
||||
import Lens.Micro ((^.))
|
||||
import Lens.Micro.TH (makeLenses)
|
||||
|
||||
import Mtlstats.Format
|
||||
import Mtlstats.Types
|
||||
|
||||
-- | Defines a menu
|
||||
@@ -65,8 +66,15 @@ makeLenses ''Menu
|
||||
makeLenses ''MenuItem
|
||||
|
||||
instance Show (Menu a) where
|
||||
show m = m ^. menuTitle ++ "\n" ++ items
|
||||
where items = unlines $ map show $ m ^. menuItems
|
||||
show m = unlines
|
||||
$ [ m^.menuTitle
|
||||
, ""
|
||||
]
|
||||
++ body
|
||||
where
|
||||
body = map (left width) items
|
||||
width = maximum $ map length items
|
||||
items = map show $ m^.menuItems
|
||||
|
||||
instance Show (MenuItem a) where
|
||||
show i = [i ^. miKey] ++ ") " ++ i ^. miDescription
|
||||
show i = [i ^. miKey] ++ ": " ++ i ^. miDescription
|
||||
|
||||
83
test/Actions/EditStandingsSpec.hs
Normal file
83
test/Actions/EditStandingsSpec.hs
Normal file
@@ -0,0 +1,83 @@
|
||||
{-
|
||||
|
||||
mtlstats
|
||||
Copyright (C) 1984, 1985, 2019, 2020 Rhéal Lamothe
|
||||
<rheal.lamothe@gmail.com>
|
||||
|
||||
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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
-}
|
||||
|
||||
{-# LANGUAGE LambdaCase #-}
|
||||
|
||||
module Actions.EditStandingsSpec (spec) where
|
||||
|
||||
import Lens.Micro ((^.), (&), (.~))
|
||||
import Test.Hspec
|
||||
( Spec
|
||||
, context
|
||||
, describe
|
||||
, it
|
||||
, shouldBe
|
||||
, shouldSatisfy
|
||||
)
|
||||
|
||||
import Mtlstats.Actions.EditStandings
|
||||
import Mtlstats.Types
|
||||
|
||||
spec :: Spec
|
||||
spec = describe "EditStandings" $ do
|
||||
mapM_
|
||||
(\(label, f, expected) -> describe label $ do
|
||||
let
|
||||
ps = newProgState
|
||||
ps' = f ps
|
||||
|
||||
it "should set progMode to EditStandings" $
|
||||
ps'^.progMode `shouldSatisfy` \case
|
||||
(EditStandings _) -> True
|
||||
_ -> False
|
||||
|
||||
it ("should set editStandingsMode to " ++ show expected) $
|
||||
ps'^.progMode.editStandingsModeL `shouldBe` expected)
|
||||
|
||||
-- label, function, expected mode
|
||||
[ ( "editStandings", editStandings, ESMMenu )
|
||||
, ( "editHomeStandings", editHomeStandings, ESMHome ESMSubMenu )
|
||||
, ( "editAwayStandings", editAwayStandings, ESMAway ESMSubMenu )
|
||||
]
|
||||
|
||||
mapM_
|
||||
(\(label, f, expected) -> describe label $ do
|
||||
mapM_
|
||||
(\prefix -> context ("mode: " ++ show (prefix ESMSubMenu)) $ let
|
||||
ps = newProgState & progMode.editStandingsModeL .~ prefix ESMSubMenu
|
||||
ps' = f ps
|
||||
in it ("should set the mode to " ++ show expected) $
|
||||
ps'^.progMode.editStandingsModeL `shouldBe` prefix expected)
|
||||
[ESMHome, ESMAway]
|
||||
|
||||
context "mode: ESMMenu" $ let
|
||||
ps = newProgState & progMode.editStandingsModeL .~ ESMMenu
|
||||
ps' = f ps
|
||||
in it "should not change the mode" $
|
||||
ps'^.progMode.editStandingsModeL `shouldBe` ESMMenu)
|
||||
|
||||
-- label, function, expected
|
||||
[ ( "editWins", editWins, ESMEditWins )
|
||||
, ( "editLosses", editLosses, ESMEditLosses )
|
||||
, ( "editOvertime", editOvertime, ESMEditOvertime )
|
||||
, ( "editGoalsFor", editGoalsFor, ESMEditGoalsFor )
|
||||
, ( "editGoalsAgainst", editGoalsAgainst, ESMEditGoalsAgainst )
|
||||
]
|
||||
@@ -24,7 +24,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
module ActionsSpec (spec) where
|
||||
|
||||
import Control.Monad (replicateM)
|
||||
import Lens.Micro ((^.), (&), (.~), (?~))
|
||||
import Lens.Micro ((^.), (&), (.~), (?~), (%~))
|
||||
import Test.Hspec
|
||||
( Spec
|
||||
, context
|
||||
@@ -39,6 +39,7 @@ import Mtlstats.Actions
|
||||
import Mtlstats.Types
|
||||
|
||||
import qualified Actions.NewGameSpec as NewGame
|
||||
import qualified Actions.EditStandingsSpec as EditStandings
|
||||
import qualified TypesSpec as TS
|
||||
|
||||
spec :: Spec
|
||||
@@ -46,6 +47,7 @@ spec = describe "Mtlstats.Actions" $ do
|
||||
startNewSeasonSpec
|
||||
startNewGameSpec
|
||||
resetYtdSpec
|
||||
clearRookiesSpec
|
||||
resetStandingsSpec
|
||||
addCharSpec
|
||||
removeCharSpec
|
||||
@@ -64,6 +66,7 @@ spec = describe "Mtlstats.Actions" $ do
|
||||
scrollUpSpec
|
||||
scrollDownSpec
|
||||
NewGame.spec
|
||||
EditStandings.spec
|
||||
|
||||
startNewSeasonSpec :: Spec
|
||||
startNewSeasonSpec = describe "startNewSeason" $ do
|
||||
@@ -129,6 +132,45 @@ resetYtdSpec = describe "resetYtd" $
|
||||
lt ^. gsTies `shouldNotBe` 0) $
|
||||
s ^. database . dbGoalies
|
||||
|
||||
clearRookiesSpec :: Spec
|
||||
clearRookiesSpec = describe "clearRookies" $ do
|
||||
let
|
||||
|
||||
players =
|
||||
[ newPlayer 1 "Joe" "centre" & pRookie .~ True
|
||||
, newPlayer 2 "Bob" "centre" & pRookie .~ False
|
||||
]
|
||||
|
||||
goalies =
|
||||
[ newGoalie 3 "Bill" & gRookie .~ True
|
||||
, newGoalie 4 "Doug" & gRookie .~ False
|
||||
]
|
||||
|
||||
ps = newProgState
|
||||
& database
|
||||
%~ (dbPlayers .~ players)
|
||||
. (dbGoalies .~ goalies)
|
||||
|
||||
ps' = clearRookies ps
|
||||
|
||||
context "Players" $ mapM_
|
||||
(\p -> let
|
||||
name = p^.pName
|
||||
rFlag = p^.pRookie
|
||||
in context name $
|
||||
it "should not be a rookie" $
|
||||
rFlag `shouldBe` False)
|
||||
(ps'^.database.dbPlayers)
|
||||
|
||||
context "Goalies" $ mapM_
|
||||
(\g -> let
|
||||
name = g^.gName
|
||||
rFlag = g^.gRookie
|
||||
in context name $
|
||||
it "should not be a rookie" $
|
||||
rFlag `shouldBe` False)
|
||||
(ps'^.database.dbGoalies)
|
||||
|
||||
resetStandingsSpec :: Spec
|
||||
resetStandingsSpec = describe "resetStandings" $ do
|
||||
let
|
||||
|
||||
@@ -76,10 +76,16 @@ goalieNameSpec = describe "goalieName" $ mapM_
|
||||
it ("should be " ++ expected) $
|
||||
goalieName g `shouldBe` expected)
|
||||
|
||||
-- label, goalie, expected
|
||||
[ ( "rookie", goalie True, "foo*" )
|
||||
, ( "non-rookie", goalie False, "foo" )
|
||||
-- label, goalie, expected
|
||||
[ ( "rookie", rookie, "foo*" )
|
||||
, ( "non-rookie", active, "foo" )
|
||||
, ( "retired", retired, "*foo" )
|
||||
]
|
||||
|
||||
where
|
||||
goalie r = newGoalie 1 "foo" & gRookie .~ r
|
||||
rookie = goalie True True
|
||||
active = goalie False True
|
||||
retired = goalie False False
|
||||
goalie r a = newGoalie 1 "foo"
|
||||
& gRookie .~ r
|
||||
& gActive .~ a
|
||||
|
||||
@@ -71,9 +71,13 @@ playerNameSpec = describe "playerName" $ mapM_
|
||||
-- label, player, expected
|
||||
[ ( "rookie", rookie, "foo*" )
|
||||
, ( "non-rookie", nonRookie, "foo" )
|
||||
, ( "retired", retired, "*foo" )
|
||||
]
|
||||
|
||||
where
|
||||
rookie = player True
|
||||
nonRookie = player False
|
||||
player r = newPlayer 1 "foo" "centre" & pRookie .~ r
|
||||
rookie = player True True
|
||||
nonRookie = player False True
|
||||
retired = player False False
|
||||
player r a = newPlayer 1 "foo" "centre"
|
||||
& pRookie .~ r
|
||||
& pActive .~ a
|
||||
|
||||
@@ -37,11 +37,11 @@ showSpec :: Spec
|
||||
showSpec = describe "show" $
|
||||
it "should display correctly" $ let
|
||||
menu = Menu "Foo" ()
|
||||
[ MenuItem '1' "Item 1" $ return ()
|
||||
, MenuItem '2' "Item 2" $ return ()
|
||||
[ MenuItem '1' "foo" $ return ()
|
||||
, MenuItem '2' "bar baz" $ return ()
|
||||
]
|
||||
expected =
|
||||
"Foo\n\
|
||||
\1) Item 1\n\
|
||||
\2) Item 2\n"
|
||||
"Foo\n\n\
|
||||
\1: foo \n\
|
||||
\2: bar baz\n"
|
||||
in show menu `shouldBe` expected
|
||||
|
||||
@@ -58,6 +58,8 @@ spec = describe "Mtlstats.Types" $ do
|
||||
createGoalieStateLSpec
|
||||
editPlayerStateLSpec
|
||||
editGoalieStateLSpec
|
||||
editStandingsModeLSpec
|
||||
esmSubModeLSpec
|
||||
teamScoreSpec
|
||||
otherScoreSpec
|
||||
homeTeamSpec
|
||||
@@ -191,6 +193,47 @@ editGoalieStateLSpec = describe "editGoalieStateL" $
|
||||
egs2 = newEditGoalieState
|
||||
& egsSelectedGoalie ?~ 2
|
||||
|
||||
editStandingsModeLSpec :: Spec
|
||||
editStandingsModeLSpec = describe "editStandingsModeL" $
|
||||
lensSpec editStandingsModeL
|
||||
-- getters
|
||||
[ ( "missing mode", MainMenu, menu )
|
||||
, ( "with mode", EditStandings home, home )
|
||||
]
|
||||
-- setters
|
||||
[ ( "set mode", MainMenu, home )
|
||||
, ( "change mode", EditStandings home, away )
|
||||
]
|
||||
where
|
||||
menu = ESMMenu
|
||||
home = ESMHome ESMSubMenu
|
||||
away = ESMAway ESMSubMenu
|
||||
|
||||
esmSubModeLSpec :: Spec
|
||||
esmSubModeLSpec = describe "esmSubModeL" $ do
|
||||
|
||||
context "getters" $ mapM_
|
||||
(\(label, mode, expected) -> context label $
|
||||
it ("should be " ++ show expected) $
|
||||
mode^.esmSubModeL `shouldBe` expected)
|
||||
|
||||
-- label, mode, expected
|
||||
[ ( "no state", ESMMenu, ESMSubMenu )
|
||||
, ( "with state", ESMHome ESMEditWins, ESMEditWins )
|
||||
]
|
||||
|
||||
context "setters" $ mapM_
|
||||
(\(label, mode, expected) -> context label $
|
||||
it ("should be " ++ show expected) $ let
|
||||
mode' = mode & esmSubModeL .~ ESMEditWins
|
||||
in mode' `shouldBe` expected)
|
||||
|
||||
-- label, mode, expected
|
||||
[ ( "no state", ESMMenu, ESMMenu )
|
||||
, ( "home mode", ESMHome ESMSubMenu, ESMHome ESMEditWins )
|
||||
, ( "away mode", ESMAway ESMSubMenu, ESMAway ESMEditWins )
|
||||
]
|
||||
|
||||
teamScoreSpec :: Spec
|
||||
teamScoreSpec = describe "teamScore" $ do
|
||||
let
|
||||
@@ -281,6 +324,7 @@ playerJSON = Object $ HM.fromList
|
||||
, ( "name", toJSON ("Joe" :: String) )
|
||||
, ( "position", toJSON ("centre" :: String) )
|
||||
, ( "rookie", toJSON False )
|
||||
, ( "active", toJSON True )
|
||||
, ( "ytd", playerStatsJSON 1 )
|
||||
, ( "lifetime", playerStatsJSON 2 )
|
||||
]
|
||||
@@ -309,6 +353,7 @@ goalieJSON = Object $ HM.fromList
|
||||
[ ( "number", toJSON (1 :: Int) )
|
||||
, ( "name", toJSON ("Joe" :: String ) )
|
||||
, ( "rookie", toJSON False )
|
||||
, ( "active", toJSON True )
|
||||
, ( "ytd", goalieStatsJSON 1 )
|
||||
, ( "lifetime", goalieStatsJSON 2 )
|
||||
]
|
||||
@@ -848,6 +893,7 @@ makePlayer = Player
|
||||
<*> makeName
|
||||
<*> makeName
|
||||
<*> makeBool
|
||||
<*> makeBool
|
||||
<*> makePlayerStats
|
||||
<*> makePlayerStats
|
||||
|
||||
@@ -857,6 +903,7 @@ makeGoalie = Goalie
|
||||
<$> makeNum
|
||||
<*> makeName
|
||||
<*> makeBool
|
||||
<*> makeBool
|
||||
<*> makeGoalieStats
|
||||
<*> makeGoalieStats
|
||||
|
||||
@@ -953,3 +1000,8 @@ instance Comparable CreateGoalieState where
|
||||
describe "cgsName" $
|
||||
it ("should be " ++ expected^.cgsName) $
|
||||
actual^.cgsName `shouldBe` expected^.cgsName
|
||||
|
||||
instance Comparable EditStandingsMode where
|
||||
compareTest actual expected =
|
||||
it ("should be " ++ show expected) $
|
||||
actual `shouldBe` expected
|
||||
|
||||
Reference in New Issue
Block a user