Merge pull request #60 from mtlstats/rookie-col

Add rookie flag to players/goalies
This commit is contained in:
Jonathan Lamothe 2020-01-09 01:54:48 -05:00 committed by GitHub
commit 119c28ef18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 358 additions and 193 deletions

View File

@ -32,7 +32,9 @@ module Mtlstats.Actions
, createGoalie , createGoalie
, edit , edit
, editPlayer , editPlayer
, editSelectedPlayer
, editGoalie , editGoalie
, editSelectedGoalie
, addPlayer , addPlayer
, addGoalie , addGoalie
, resetCreatePlayerState , resetCreatePlayerState
@ -47,6 +49,7 @@ import Data.Maybe (fromMaybe)
import Lens.Micro ((^.), (&), (.~), (%~)) import Lens.Micro ((^.), (&), (.~), (%~))
import Mtlstats.Types import Mtlstats.Types
import Mtlstats.Util
-- | Starts a new season -- | Starts a new season
startNewSeason :: ProgState -> ProgState startNewSeason :: ProgState -> ProgState
@ -106,10 +109,36 @@ edit = progMode .~ EditMenu
editPlayer :: ProgState -> ProgState editPlayer :: ProgState -> ProgState
editPlayer = progMode .~ EditPlayer newEditPlayerState editPlayer = progMode .~ EditPlayer newEditPlayerState
-- | Edits the selected 'Player'
editSelectedPlayer
:: (Player -> Player)
-- ^ The modification to be made to the 'Player'
-> ProgState
-> ProgState
editSelectedPlayer f s = fromMaybe s $ do
n <- s^.progMode.editPlayerStateL.epsSelectedPlayer
let
players = s^.database.dbPlayers
players' = modifyNth n f players
Just $ s & database.dbPlayers .~ players'
-- | Starts the 'Goalie' editing process -- | Starts the 'Goalie' editing process
editGoalie :: ProgState -> ProgState editGoalie :: ProgState -> ProgState
editGoalie = progMode .~ EditGoalie newEditGoalieState editGoalie = progMode .~ EditGoalie newEditGoalieState
-- | Edits the selected 'Goalie'
editSelectedGoalie
:: (Goalie -> Goalie)
-- ^ The modification to be made to the 'Goalie'
-> ProgState
-> ProgState
editSelectedGoalie f s = fromMaybe s $ do
n <- s^.progMode.editGoalieStateL.egsSelectedGoalie
let
goalies = s^.database.dbGoalies
goalies' = modifyNth n f goalies
Just $ s & database.dbGoalies .~ goalies'
-- | Adds the entered player to the roster -- | Adds the entered player to the roster
addPlayer :: ProgState -> ProgState addPlayer :: ProgState -> ProgState
addPlayer s = fromMaybe s $ do addPlayer s = fromMaybe s $ do

View File

@ -19,7 +19,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
-} -}
module Mtlstats.Helpers.Goalie (goalieDetails) where module Mtlstats.Helpers.Goalie (goalieDetails, goalieName) where
import Lens.Micro ((^.)) import Lens.Micro ((^.))
@ -31,7 +31,7 @@ goalieDetails :: Goalie -> String
goalieDetails g = let goalieDetails g = let
header = unlines $ labelTable header = unlines $ labelTable
[ ( "Number", show $ g^.gNumber ) [ ( "Number", show $ g^.gNumber )
, ( "Name", g^.gName ) , ( "Name", goalieName g )
] ]
body = unlines $ numTable ["YTD", "Lifetime"] $ map body = unlines $ numTable ["YTD", "Lifetime"] $ map
@ -46,3 +46,13 @@ goalieDetails g = let
] ]
in header ++ "\n" ++ body in header ++ "\n" ++ body
-- | Returns the goalie name, modified if they are a rookie
goalieName :: Goalie -> String
goalieName g = let
suffix = if g^.gRookie
then "*"
else ""
in g^.gName ++ suffix

View File

@ -19,7 +19,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
-} -}
module Mtlstats.Helpers.Player (playerDetails) where module Mtlstats.Helpers.Player (playerDetails, playerName) where
import Lens.Micro ((^.)) import Lens.Micro ((^.))
@ -32,7 +32,7 @@ playerDetails p = unlines $ top ++ [""] ++ table
where where
top = labelTable top = labelTable
[ ( "Number", show $ p^.pNumber ) [ ( "Number", show $ p^.pNumber )
, ( "Name", p^.pName ) , ( "Name", playerName p )
, ( "Position", p^.pPosition ) , ( "Position", p^.pPosition )
] ]
@ -43,3 +43,14 @@ playerDetails p = unlines $ top ++ [""] ++ table
, ( "Assists", psAssists ) , ( "Assists", psAssists )
, ( "Penalty mins", psPMin ) , ( "Penalty mins", psPMin )
] ]
-- | Presents a modified version of the player's name indicating
-- whether or not they're a rookie
playerName :: Player -> String
playerName p = let
suffix = if p^.pRookie
then "*"
else ""
in p^.pName ++ suffix

View File

@ -26,7 +26,7 @@ module Mtlstats.Menu.EditGoalie
) where ) where
import Control.Monad.Trans.State (modify) import Control.Monad.Trans.State (modify)
import Lens.Micro ((.~)) import Lens.Micro ((.~), (%~))
import Mtlstats.Actions import Mtlstats.Actions
import Mtlstats.Types import Mtlstats.Types
@ -35,18 +35,21 @@ import Mtlstats.Types.Menu
-- | The 'Goalie' edit menu -- | The 'Goalie' edit menu
editGoalieMenu :: Menu () editGoalieMenu :: Menu ()
editGoalieMenu = Menu "*** EDIT GOALTENDER ***" () $ map editGoalieMenu = Menu "*** EDIT GOALTENDER ***" () $ map
(\(ch, label, mode) -> MenuItem ch label $ (\(ch, label, action) -> MenuItem ch label $ modify action)
modify $ case mode of
Nothing -> edit
Just m -> progMode.editGoalieStateL.egsMode .~ m)
-- key, label, value -- key, label, value
[ ( '1', "Edit number", Just EGNumber ) [ ( '1', "Edit number", set EGNumber )
, ( '2', "Edit name", Just EGName ) , ( '2', "Edit name", set EGName )
, ( '3', "Edit YTD stats", Just EGYtd ) , ( '3', "Toggle rookie flag", toggle )
, ( '4', "Edit Lifetime stats", Just EGLifetime ) , ( '4', "Edit YTD stats", set EGYtd )
, ( 'R', "Return to Edit Menu", Nothing ) , ( '5', "Edit Lifetime stats", set EGLifetime )
, ( 'R', "Return to Edit Menu", edit )
] ]
where
set mode = progMode.editGoalieStateL.egsMode .~ mode
toggle = editSelectedGoalie (gRookie %~ not)
-- | The 'Goalie' YTD edit menu -- | The 'Goalie' YTD edit menu
editGoalieYtdMenu :: Menu () editGoalieYtdMenu :: Menu ()
editGoalieYtdMenu = editMenu "*** EDIT GOALTENDER YEAR-TO-DATE ***" editGoalieYtdMenu = editMenu "*** EDIT GOALTENDER YEAR-TO-DATE ***"

View File

@ -26,7 +26,7 @@ module Mtlstats.Menu.EditPlayer
) where ) where
import Control.Monad.Trans.State (modify) import Control.Monad.Trans.State (modify)
import Lens.Micro ((.~)) import Lens.Micro ((.~), (%~))
import Mtlstats.Actions import Mtlstats.Actions
import Mtlstats.Types import Mtlstats.Types
@ -35,19 +35,22 @@ import Mtlstats.Types.Menu
-- | The 'Player' edit menu -- | The 'Player' edit menu
editPlayerMenu :: Menu () editPlayerMenu :: Menu ()
editPlayerMenu = Menu "*** EDIT PLAYER ***" () $ map editPlayerMenu = Menu "*** EDIT PLAYER ***" () $ map
(\(ch, label, mode) -> MenuItem ch label $ (\(ch, label, action) -> MenuItem ch label $ modify action)
modify $ case mode of
Nothing -> edit
Just m -> progMode.editPlayerStateL.epsMode .~ m)
-- key, label, value -- key, label, value
[ ( '1', "Edit number", Just EPNumber ) [ ( '1', "Edit number", set EPNumber )
, ( '2', "Edit name", Just EPName ) , ( '2', "Edit name", set EPName )
, ( '3', "Edit position", Just EPPosition ) , ( '3', "Edit position", set EPPosition )
, ( '4', "Edit YTD stats", Just EPYtd ) , ( '4', "Toggle rookie flag", toggle )
, ( '5', "Edit lifetime stats", Just EPLifetime ) , ( '5', "Edit YTD stats", set EPYtd )
, ( 'R', "Return to Edit Menu", Nothing ) , ( '6', "Edit lifetime stats", set EPLifetime )
, ( 'R', "Return to Edit Menu", edit )
] ]
where
set mode = progMode.editPlayerStateL.epsMode .~ mode
toggle = editSelectedPlayer $ pRookie %~ not
-- | The 'Player' YTD stats edit menu -- | The 'Player' YTD stats edit menu
editPlayerYtdMenu :: Menu () editPlayerYtdMenu :: Menu ()
editPlayerYtdMenu = editMenu editPlayerYtdMenu = editMenu

View File

@ -39,13 +39,12 @@ module Mtlstats.Prompt.EditGoalie
, editGoalieLtTiesPrompt , editGoalieLtTiesPrompt
) where ) where
import Control.Monad.Extra (whenJustM) import Control.Monad.Trans.State (modify)
import Control.Monad.Trans.State (gets, modify) import Lens.Micro ((.~))
import Lens.Micro ((^.), (.~), (%~))
import Mtlstats.Actions
import Mtlstats.Prompt import Mtlstats.Prompt
import Mtlstats.Types import Mtlstats.Types
import Mtlstats.Util
-- | Prompt to select a 'Goalie' for editing -- | Prompt to select a 'Goalie' for editing
goalieToEditPrompt :: Prompt goalieToEditPrompt :: Prompt
@ -62,7 +61,7 @@ editGoalieNamePrompt :: Prompt
editGoalieNamePrompt = namePrompt "Goalie name: " $ \name -> editGoalieNamePrompt = namePrompt "Goalie name: " $ \name ->
if null name if null name
then goto EGMenu then goto EGMenu
else editGoalie EGMenu $ gName .~ name else doEdit EGMenu $ gName .~ name
-- | Prompt to edit a goalie's YTD games played -- | Prompt to edit a goalie's YTD games played
editGoalieYtdGamesPrompt editGoalieYtdGamesPrompt
@ -213,12 +212,11 @@ editNum
-> Prompt -> Prompt
editNum pStr mode f = numPromptWithFallback pStr editNum pStr mode f = numPromptWithFallback pStr
(goto mode) (goto mode)
(editGoalie mode . f) (doEdit mode . f)
editGoalie :: EditGoalieMode -> (Goalie -> Goalie) -> Action () doEdit :: EditGoalieMode -> (Goalie -> Goalie) -> Action ()
editGoalie mode f = doEdit mode f = do
whenJustM (gets (^.progMode.editGoalieStateL.egsSelectedGoalie)) $ \gid -> do modify $ editSelectedGoalie f
modify $ database.dbGoalies %~ modifyNth gid f
goto mode goto mode
goto :: EditGoalieMode -> Action () goto :: EditGoalieMode -> Action ()

View File

@ -31,13 +31,12 @@ module Mtlstats.Prompt.EditPlayer
, editPlayerLtPMinPrompt , editPlayerLtPMinPrompt
) where ) where
import Control.Monad.Extra (whenJustM) import Control.Monad.Trans.State (modify)
import Control.Monad.Trans.State (gets, modify) import Lens.Micro ((.~))
import Lens.Micro ((^.), (.~), (%~))
import Mtlstats.Actions
import Mtlstats.Prompt import Mtlstats.Prompt
import Mtlstats.Types import Mtlstats.Types
import Mtlstats.Util
-- | Prompt to edit a player's number -- | Prompt to edit a player's number
editPlayerNumPrompt :: Prompt editPlayerNumPrompt :: Prompt
@ -49,14 +48,14 @@ editPlayerNamePrompt :: Prompt
editPlayerNamePrompt = namePrompt "Player name: " $ \name -> editPlayerNamePrompt = namePrompt "Player name: " $ \name ->
if null name if null name
then goto EPMenu then goto EPMenu
else editPlayer EPMenu $ pName .~ name else doEdit EPMenu $ pName .~ name
-- | Prompt to edit a player's position -- | Prompt to edit a player's position
editPlayerPosPrompt :: Prompt editPlayerPosPrompt :: Prompt
editPlayerPosPrompt = ucStrPrompt "Player position: " $ \pos -> editPlayerPosPrompt = ucStrPrompt "Player position: " $ \pos ->
if null pos if null pos
then goto EPMenu then goto EPMenu
else editPlayer EPMenu $ pPosition .~ pos else doEdit EPMenu $ pPosition .~ pos
-- | Prompt to edit a player's year-to-date goals -- | Prompt to edit a player's year-to-date goals
editPlayerYtdGoalsPrompt editPlayerYtdGoalsPrompt
@ -115,12 +114,11 @@ editNum
-> Prompt -> Prompt
editNum pStr mode f = numPromptWithFallback pStr editNum pStr mode f = numPromptWithFallback pStr
(goto mode) (goto mode)
(editPlayer mode . f) (doEdit mode . f)
editPlayer :: EditPlayerMode -> (Player -> Player) -> Action () doEdit :: EditPlayerMode -> (Player -> Player) -> Action ()
editPlayer mode f = doEdit mode f = do
whenJustM (gets (^.progMode.editPlayerStateL.epsSelectedPlayer)) $ \pid -> do modify $ editSelectedPlayer f
modify $ database.dbPlayers %~ modifyNth pid f
goto mode goto mode
goto :: EditPlayerMode -> Action () goto :: EditPlayerMode -> Action ()

View File

@ -29,6 +29,8 @@ import Lens.Micro ((^.))
import Mtlstats.Config import Mtlstats.Config
import Mtlstats.Format import Mtlstats.Format
import Mtlstats.Helpers.Goalie
import Mtlstats.Helpers.Player
import Mtlstats.Types import Mtlstats.Types
import Mtlstats.Util import Mtlstats.Util
@ -219,7 +221,7 @@ filteredPlayerReport width label criteria showTotals lineNumbers ps = let
body = map body = map
(\(p, stats) -> (\(p, stats) ->
[ CellText $ show (p^.pNumber) ++ " " [ CellText $ show (p^.pNumber) ++ " "
, CellText $ p^.pName , CellText $ playerName p
] ++ statsCells stats) ] ++ statsCells stats)
fps fps
@ -283,7 +285,7 @@ goalieReport width showTotals lineNumbers goalieData = let
body = map body = map
(\(goalie, stats) -> (\(goalie, stats) ->
[ CellText $ show (goalie^.gNumber) ++ " " [ CellText $ show (goalie^.gNumber) ++ " "
, CellText $ goalie^.gName , CellText $ goalieName goalie
] ++ rowCells stats) ] ++ rowCells stats)
goalieData goalieData
@ -318,7 +320,7 @@ gameGoalieReport width goalieData = let
body = map body = map
(\(goalie, stats) -> (\(goalie, stats) ->
[ CellText $ show (goalie^.gNumber) ++ " " [ CellText $ show (goalie^.gNumber) ++ " "
, CellText $ goalie^.gName , CellText $ goalieName goalie
, CellText $ show $ stats^.gsMinsPlayed , CellText $ show $ stats^.gsMinsPlayed
, CellText $ show $ stats^.gsGoalsAllowed , CellText $ show $ stats^.gsGoalsAllowed
, CellText $ showFloating $ gsAverage stats , CellText $ showFloating $ gsAverage stats

View File

@ -106,6 +106,7 @@ module Mtlstats.Types (
pNumber, pNumber,
pName, pName,
pPosition, pPosition,
pRookie,
pYtd, pYtd,
pLifetime, pLifetime,
-- ** PlayerStats Lenses -- ** PlayerStats Lenses
@ -115,6 +116,7 @@ module Mtlstats.Types (
-- ** Goalie Lenses -- ** Goalie Lenses
gNumber, gNumber,
gName, gName,
gRookie,
gYtd, gYtd,
gLifetime, gLifetime,
-- ** GoalieStats Lenses -- ** GoalieStats Lenses
@ -399,29 +401,6 @@ data Database = Database
-- ^ Statistics for away games -- ^ Statistics for away games
} deriving (Eq, Show) } deriving (Eq, Show)
instance FromJSON Database where
parseJSON = withObject "Database" $ \v -> Database
<$> v .: "players"
<*> v .: "goalies"
<*> v .: "games"
<*> v .: "home_game_stats"
<*> v .: "away_game_stats"
instance ToJSON Database where
toJSON (Database players goalies games hgs ags) = object
[ "players" .= players
, "goalies" .= goalies
, "games" .= games
, "home_game_stats" .= hgs
, "away_game_stats" .= ags
]
toEncoding (Database players goalies games hgs ags) = pairs $
"players" .= players <>
"goalies" .= goalies <>
"games" .= games <>
"home_game_stats" .= hgs <>
"away_game_stats" .= ags
-- | Represents a (non-goalie) player -- | Represents a (non-goalie) player
data Player = Player data Player = Player
{ _pNumber :: Int { _pNumber :: Int
@ -430,35 +409,14 @@ data Player = Player
-- ^ The player's name -- ^ The player's name
, _pPosition :: String , _pPosition :: String
-- ^ The player's position -- ^ The player's position
, _pRookie :: Bool
-- ^ Indicates that the player is a rookie
, _pYtd :: PlayerStats , _pYtd :: PlayerStats
-- ^ The Player's year-to-date stats -- ^ The Player's year-to-date stats
, _pLifetime :: PlayerStats , _pLifetime :: PlayerStats
-- ^ The player's lifetime stats -- ^ The player's lifetime stats
} deriving (Eq, Show) } deriving (Eq, Show)
instance FromJSON Player where
parseJSON = withObject "Player" $ \v -> Player
<$> v .: "number"
<*> v .: "name"
<*> v .: "position"
<*> v .: "ytd"
<*> v .: "lifetime"
instance ToJSON Player where
toJSON (Player num name pos ytd lt) = object
[ "number" .= num
, "name" .= name
, "position" .= pos
, "ytd" .= ytd
, "lifetime" .= lt
]
toEncoding (Player num name pos ytd lt) = pairs $
"number" .= num <>
"name" .= name <>
"position" .= pos <>
"ytd" .= ytd <>
"lifetime" .= lt
-- | Represents a (non-goalie) player's stats -- | Represents a (non-goalie) player's stats
data PlayerStats = PlayerStats data PlayerStats = PlayerStats
{ _psGoals :: Int { _psGoals :: Int
@ -469,55 +427,20 @@ data PlayerStats = PlayerStats
-- ^ The number of penalty minutes -- ^ The number of penalty minutes
} deriving (Eq, Show) } deriving (Eq, Show)
instance FromJSON PlayerStats where
parseJSON = withObject "PlayerStats" $ \v -> PlayerStats
<$> v .: "goals"
<*> v .: "assists"
<*> v .: "penalty_mins"
instance ToJSON PlayerStats where
toJSON (PlayerStats g a pm) = object
[ "goals" .= g
, "assists" .= a
, "penalty_mins" .= pm
]
toEncoding (PlayerStats g a pm) = pairs $
"goals" .= g <>
"assists" .= a <>
"penalty_mins" .= pm
-- | Represents a goalie -- | Represents a goalie
data Goalie = Goalie data Goalie = Goalie
{ _gNumber :: Int { _gNumber :: Int
-- ^ The goalie's number -- ^ The goalie's number
, _gName :: String , _gName :: String
-- ^ The goalie's name -- ^ The goalie's name
, _gRookie :: Bool
-- ^ Indicates that the goalie is a rookie
, _gYtd :: GoalieStats , _gYtd :: GoalieStats
-- ^ The goalie's year-to-date stats -- ^ The goalie's year-to-date stats
, _gLifetime :: GoalieStats , _gLifetime :: GoalieStats
-- ^ The goalie's lifetime stats -- ^ The goalie's lifetime stats
} deriving (Eq, Show) } deriving (Eq, Show)
instance FromJSON Goalie where
parseJSON = withObject "Goalie" $ \v -> Goalie
<$> v .: "number"
<*> v .: "name"
<*> v .: "ytd"
<*> v .: "lifetime"
instance ToJSON Goalie where
toJSON (Goalie num name ytd lt) = object
[ "number" .= num
, "name" .= name
, "ytd" .= ytd
, "lifetime" .= lt
]
toEncoding (Goalie num name ytd lt) = pairs $
"number" .= num <>
"name" .= name <>
"ytd" .= ytd <>
"lifetime" .= lt
-- | Represents a goalie's stats -- | Represents a goalie's stats
data GoalieStats = GoalieStats data GoalieStats = GoalieStats
{ _gsGames :: Int { _gsGames :: Int
@ -536,35 +459,6 @@ data GoalieStats = GoalieStats
-- ^ The number of ties -- ^ The number of ties
} deriving (Eq, Show) } deriving (Eq, Show)
instance FromJSON GoalieStats where
parseJSON = withObject "GoalieStats" $ \v -> GoalieStats
<$> v .:? "games" .!= 0
<*> v .:? "mins_played" .!= 0
<*> v .:? "goals_allowed" .!= 0
<*> v .:? "shutouts" .!= 0
<*> v .:? "wins" .!= 0
<*> v .:? "losses" .!= 0
<*> v .:? "ties" .!= 0
instance ToJSON GoalieStats where
toJSON (GoalieStats g m a s w l t) = object
[ "games" .= g
, "mins_played" .= m
, "goals_allowed" .= a
, "shutouts" .= s
, "wins" .= w
, "losses" .= l
, "ties" .= t
]
toEncoding (GoalieStats g m a s w l t) = pairs $
"games" .= g <>
"mins_played" .= m <>
"goals_allowed" .= a <>
"shutouts" .= s <>
"wins" .= w <>
"losses" .= l <>
"ties" .= t
-- | Game statistics -- | Game statistics
data GameStats = GameStats data GameStats = GameStats
{ _gmsWins :: Int { _gmsWins :: Int
@ -579,29 +473,6 @@ data GameStats = GameStats
-- ^ Goals against the team -- ^ Goals against the team
} deriving (Eq, Show) } deriving (Eq, Show)
instance FromJSON GameStats where
parseJSON = withObject "GameStats" $ \v -> GameStats
<$> v .: "wins"
<*> v .: "losses"
<*> v .: "overtime"
<*> v .: "goals_for"
<*> v .: "goals_against"
instance ToJSON GameStats where
toJSON (GameStats w l ot gf ga) = object
[ "wins" .= w
, "losses" .= l
, "overtime" .= ot
, "goals_for" .= gf
, "goals_against" .= ga
]
toEncoding (GameStats w l ot gf ga) = pairs $
"wins" .= w <>
"losses" .= l <>
"overtime" .= ot <>
"goals_for" .= gf <>
"goals_against" .= ga
-- | Defines a user prompt -- | Defines a user prompt
data Prompt = Prompt data Prompt = Prompt
{ promptDrawer :: ProgState -> C.Update () { promptDrawer :: ProgState -> C.Update ()
@ -655,6 +526,147 @@ makeLenses ''Goalie
makeLenses ''GoalieStats makeLenses ''GoalieStats
makeLenses ''GameStats makeLenses ''GameStats
instance FromJSON Database where
parseJSON = withObject "Database" $ \v -> Database
<$> v .:? "players" .!= []
<*> v .:? "goalies" .!= []
<*> v .:? "games" .!= 0
<*> v .:? "home_game_stats" .!= newGameStats
<*> v .:? "away_game_stats" .!= newGameStats
instance ToJSON Database where
toJSON (Database players goalies games hgs ags) = object
[ "players" .= players
, "goalies" .= goalies
, "games" .= games
, "home_game_stats" .= hgs
, "away_game_stats" .= ags
]
toEncoding (Database players goalies games hgs ags) = pairs $
"players" .= players <>
"goalies" .= goalies <>
"games" .= games <>
"home_game_stats" .= hgs <>
"away_game_stats" .= ags
instance FromJSON Player where
parseJSON = withObject "Player" $ \v -> Player
<$> v .: "number"
<*> v .: "name"
<*> v .: "position"
<*> v .:? "rookie" .!= False
<*> v .:? "ytd" .!= newPlayerStats
<*> v .:? "lifetime" .!= newPlayerStats
instance ToJSON Player where
toJSON (Player num name pos rk ytd lt) = object
[ "number" .= num
, "name" .= name
, "position" .= pos
, "rookie" .= rk
, "ytd" .= ytd
, "lifetime" .= lt
]
toEncoding (Player num name pos rk ytd lt) = pairs $
"number" .= num <>
"name" .= name <>
"position" .= pos <>
"rookie" .= rk <>
"ytd" .= ytd <>
"lifetime" .= lt
instance FromJSON PlayerStats where
parseJSON = withObject "PlayerStats" $ \v -> PlayerStats
<$> v .:? "goals" .!= 0
<*> v .:? "assists" .!= 0
<*> v .:? "penalty_mins" .!= 0
instance ToJSON PlayerStats where
toJSON (PlayerStats g a pm) = object
[ "goals" .= g
, "assists" .= a
, "penalty_mins" .= pm
]
toEncoding (PlayerStats g a pm) = pairs $
"goals" .= g <>
"assists" .= a <>
"penalty_mins" .= pm
instance FromJSON Goalie where
parseJSON = withObject "Goalie" $ \v -> Goalie
<$> v .: "number"
<*> v .: "name"
<*> v .:? "rookie" .!= False
<*> v .:? "ytd" .!= newGoalieStats
<*> v .:? "lifetime" .!= newGoalieStats
instance ToJSON Goalie where
toJSON (Goalie num name rk ytd lt) = object
[ "number" .= num
, "name" .= name
, "ytd" .= ytd
, "rookie" .= rk
, "lifetime" .= lt
]
toEncoding (Goalie num name rk ytd lt) = pairs $
"number" .= num <>
"name" .= name <>
"rookie" .= rk <>
"ytd" .= ytd <>
"lifetime" .= lt
instance FromJSON GoalieStats where
parseJSON = withObject "GoalieStats" $ \v -> GoalieStats
<$> v .:? "games" .!= 0
<*> v .:? "mins_played" .!= 0
<*> v .:? "goals_allowed" .!= 0
<*> v .:? "shutouts" .!= 0
<*> v .:? "wins" .!= 0
<*> v .:? "losses" .!= 0
<*> v .:? "ties" .!= 0
instance ToJSON GoalieStats where
toJSON (GoalieStats g m a s w l t) = object
[ "games" .= g
, "mins_played" .= m
, "goals_allowed" .= a
, "shutouts" .= s
, "wins" .= w
, "losses" .= l
, "ties" .= t
]
toEncoding (GoalieStats g m a s w l t) = pairs $
"games" .= g <>
"mins_played" .= m <>
"goals_allowed" .= a <>
"shutouts" .= s <>
"wins" .= w <>
"losses" .= l <>
"ties" .= t
instance FromJSON GameStats where
parseJSON = withObject "GameStats" $ \v -> GameStats
<$> v .: "wins"
<*> v .: "losses"
<*> v .: "overtime"
<*> v .: "goals_for"
<*> v .: "goals_against"
instance ToJSON GameStats where
toJSON (GameStats w l ot gf ga) = object
[ "wins" .= w
, "losses" .= l
, "overtime" .= ot
, "goals_for" .= gf
, "goals_against" .= ga
]
toEncoding (GameStats w l ot gf ga) = pairs $
"wins" .= w <>
"losses" .= l <>
"overtime" .= ot <>
"goals_for" .= gf <>
"goals_against" .= ga
gameStateL :: Lens' ProgMode GameState gameStateL :: Lens' ProgMode GameState
gameStateL = lens gameStateL = lens
(\case (\case
@ -782,6 +794,7 @@ newPlayer num name pos = Player
{ _pNumber = num { _pNumber = num
, _pName = name , _pName = name
, _pPosition = pos , _pPosition = pos
, _pRookie = True
, _pYtd = newPlayerStats , _pYtd = newPlayerStats
, _pLifetime = newPlayerStats , _pLifetime = newPlayerStats
} }
@ -804,6 +817,7 @@ newGoalie
newGoalie num name = Goalie newGoalie num name = Goalie
{ _gNumber = num { _gNumber = num
, _gName = name , _gName = name
, _gRookie = True
, _gYtd = newGoalieStats , _gYtd = newGoalieStats
, _gLifetime = newGoalieStats , _gLifetime = newGoalieStats
} }

View File

@ -53,7 +53,9 @@ spec = describe "Mtlstats.Actions" $ do
createGoalieSpec createGoalieSpec
editSpec editSpec
editPlayerSpec editPlayerSpec
editSelectedPlayerSpec
editGoalieSpec editGoalieSpec
editSelectedGoalieSpec
addPlayerSpec addPlayerSpec
addGoalieSpec addGoalieSpec
resetCreatePlayerStateSpec resetCreatePlayerStateSpec
@ -209,12 +211,64 @@ editPlayerSpec = describe "editPlayer" $
s = editPlayer newProgState s = editPlayer newProgState
in show (s^.progMode) `shouldBe` "EditPlayer" in show (s^.progMode) `shouldBe` "EditPlayer"
editSelectedPlayerSpec :: Spec
editSelectedPlayerSpec = describe "editSelectedPlayer" $ mapM_
(\(label, pState, expected) -> context label $
it "should edit the players appropriately" $ let
pState' = editSelectedPlayer (pName .~ "foo") pState
players' = pState'^.database.dbPlayers
in players' `shouldBe` expected)
-- label, initial state, expected
[ ( "wrong mode", baseState, players )
, ( "not selected", changePlayer Nothing, players )
, ( "player 0", changePlayer $ Just 0, changed0 )
, ( "player 1", changePlayer $ Just 1, changed1 )
, ( "out of bounds", changePlayer $ Just 2, players )
]
where
baseState = newProgState & database.dbPlayers .~ players
changePlayer n = baseState
& (progMode.editPlayerStateL.epsSelectedPlayer .~ n)
players = [ player 0, player 1 ]
changed0 = [ player' 0, player 1 ]
changed1 = [ player 0, player' 1 ]
player n = newPlayer n ("Player " ++ show n) "pos"
player' n = newPlayer n "foo" "pos"
editGoalieSpec :: Spec editGoalieSpec :: Spec
editGoalieSpec = describe "editGoalie" $ editGoalieSpec = describe "editGoalie" $
it "should change the mode appropriately" $ let it "should change the mode appropriately" $ let
s = editGoalie newProgState s = editGoalie newProgState
in show (s^.progMode) `shouldBe` "EditGoalie" in show (s^.progMode) `shouldBe` "EditGoalie"
editSelectedGoalieSpec :: Spec
editSelectedGoalieSpec = describe "editSelectedGoalie" $ mapM_
(\(label, pState, expected) -> context label $
it "should edit the goalies appropriately" $ let
pState' = editSelectedGoalie (gName .~ "foo") pState
goalies' = pState'^.database.dbGoalies
in goalies' `shouldBe` expected)
-- label, initial state, expected
[ ( "wrong mode", baseState, goalies )
, ( "not selected", changeGoalie Nothing, goalies )
, ( "goalie 0", changeGoalie $ Just 0, changed0 )
, ( "goalie 1", changeGoalie $ Just 1, changed1 )
, ( "out of bounds", changeGoalie $ Just 2, goalies )
]
where
baseState = newProgState & database.dbGoalies .~ goalies
changeGoalie n = baseState
& (progMode.editGoalieStateL.egsSelectedGoalie .~ n)
goalies = [ goalie 0, goalie 1 ]
changed0 = [ goalie' 0, goalie 1 ]
changed1 = [ goalie 0, goalie' 1 ]
goalie n = newGoalie n ("Player " ++ show n)
goalie' n = newGoalie n "foo"
addPlayerSpec :: Spec addPlayerSpec :: Spec
addPlayerSpec = describe "addPlayer" $ do addPlayerSpec = describe "addPlayer" $ do
let let

View File

@ -22,18 +22,20 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
module Helpers.GoalieSpec (spec) where module Helpers.GoalieSpec (spec) where
import Lens.Micro ((&), (.~), (%~)) import Lens.Micro ((&), (.~), (%~))
import Test.Hspec (Spec, describe, it, shouldBe) import Test.Hspec (Spec, context, describe, it, shouldBe)
import Mtlstats.Helpers.Goalie import Mtlstats.Helpers.Goalie
import Mtlstats.Types import Mtlstats.Types
spec :: Spec spec :: Spec
spec = describe "Goalie" spec = describe "Goalie" $ do
goalieDetailsSpec goalieDetailsSpec
goalieNameSpec
goalieDetailsSpec :: Spec goalieDetailsSpec :: Spec
goalieDetailsSpec = describe "goalieDetails" $ let goalieDetailsSpec = describe "goalieDetails" $ let
input = newGoalie 1 "Joe" input = newGoalie 1 "Joe"
& gRookie .~ True
& gYtd & gYtd
%~ ( gsGames .~ 2 ) %~ ( gsGames .~ 2 )
. ( gsMinsPlayed .~ 3 ) . ( gsMinsPlayed .~ 3 )
@ -53,7 +55,7 @@ goalieDetailsSpec = describe "goalieDetails" $ let
expected = unlines expected = unlines
[ "Number: 1" [ "Number: 1"
, " Name: Joe" , " Name: Joe*"
, "" , ""
, " YTD Lifetime" , " YTD Lifetime"
, " Games played 2 9" , " Games played 2 9"
@ -67,3 +69,17 @@ goalieDetailsSpec = describe "goalieDetails" $ let
in it "should format the output correctly" $ in it "should format the output correctly" $
goalieDetails input `shouldBe` expected goalieDetails input `shouldBe` expected
goalieNameSpec :: Spec
goalieNameSpec = describe "goalieName" $ mapM_
(\(label, g, expected) -> context label $
it ("should be " ++ expected) $
goalieName g `shouldBe` expected)
-- label, goalie, expected
[ ( "rookie", goalie True, "foo*" )
, ( "non-rookie", goalie False, "foo" )
]
where
goalie r = newGoalie 1 "foo" & gRookie .~ r

View File

@ -22,20 +22,22 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
module Helpers.PlayerSpec (spec) where module Helpers.PlayerSpec (spec) where
import Lens.Micro ((&), (.~)) import Lens.Micro ((&), (.~))
import Test.Hspec (Spec, describe, it, shouldBe) import Test.Hspec (Spec, context, describe, it, shouldBe)
import Mtlstats.Helpers.Player import Mtlstats.Helpers.Player
import Mtlstats.Types import Mtlstats.Types
spec :: Spec spec :: Spec
spec = describe "Player" spec = describe "Player" $ do
playerDetailsSpec playerDetailsSpec
playerNameSpec
playerDetailsSpec :: Spec playerDetailsSpec :: Spec
playerDetailsSpec = describe "playerDetails" $ playerDetailsSpec = describe "playerDetails" $
it "should give a detailed description" $ let it "should give a detailed description" $ let
p = newPlayer 1 "Joe" "centre" p = newPlayer 1 "Joe" "centre"
& pRookie .~ True
& pYtd .~ PlayerStats & pYtd .~ PlayerStats
{ _psGoals = 2 { _psGoals = 2
, _psAssists = 3 , _psAssists = 3
@ -49,7 +51,7 @@ playerDetailsSpec = describe "playerDetails" $
expected = unlines expected = unlines
[ " Number: 1" [ " Number: 1"
, " Name: Joe" , " Name: Joe*"
, "Position: centre" , "Position: centre"
, "" , ""
, " YTD Lifetime" , " YTD Lifetime"
@ -59,3 +61,19 @@ playerDetailsSpec = describe "playerDetails" $
] ]
in playerDetails p `shouldBe` expected in playerDetails p `shouldBe` expected
playerNameSpec :: Spec
playerNameSpec = describe "playerName" $ mapM_
(\(label, p, expected) -> context label $
it ("should be " ++ expected) $
playerName p `shouldBe` expected)
-- label, player, expected
[ ( "rookie", rookie, "foo*" )
, ( "non-rookie", nonRookie, "foo" )
]
where
rookie = player True
nonRookie = player False
player r = newPlayer 1 "foo" "centre" & pRookie .~ r

View File

@ -36,7 +36,7 @@ import Data.Aeson.Types (Value (Object))
import qualified Data.HashMap.Strict as HM import qualified Data.HashMap.Strict as HM
import Data.Ratio ((%)) import Data.Ratio ((%))
import Lens.Micro (Lens', (&), (^.), (.~), (?~)) import Lens.Micro (Lens', (&), (^.), (.~), (?~))
import System.Random (randomRIO) import System.Random (randomIO, randomRIO)
import Test.Hspec (Spec, context, describe, it, shouldBe) import Test.Hspec (Spec, context, describe, it, shouldBe)
import Mtlstats.Config import Mtlstats.Config
@ -271,6 +271,7 @@ lensSpec lens getters setters = do
player :: Player player :: Player
player = newPlayer 1 "Joe" "centre" player = newPlayer 1 "Joe" "centre"
& pRookie .~ False
& pYtd .~ playerStats 1 & pYtd .~ playerStats 1
& pLifetime .~ playerStats 2 & pLifetime .~ playerStats 2
@ -279,6 +280,7 @@ playerJSON = Object $ HM.fromList
[ ( "number", toJSON (1 :: Int) ) [ ( "number", toJSON (1 :: Int) )
, ( "name", toJSON ("Joe" :: String) ) , ( "name", toJSON ("Joe" :: String) )
, ( "position", toJSON ("centre" :: String) ) , ( "position", toJSON ("centre" :: String) )
, ( "rookie", toJSON False )
, ( "ytd", playerStatsJSON 1 ) , ( "ytd", playerStatsJSON 1 )
, ( "lifetime", playerStatsJSON 2 ) , ( "lifetime", playerStatsJSON 2 )
] ]
@ -298,6 +300,7 @@ playerStatsJSON n = Object $ HM.fromList
goalie :: Goalie goalie :: Goalie
goalie = newGoalie 1 "Joe" goalie = newGoalie 1 "Joe"
& gRookie .~ False
& gYtd .~ goalieStats 1 & gYtd .~ goalieStats 1
& gLifetime .~ goalieStats 2 & gLifetime .~ goalieStats 2
@ -305,6 +308,7 @@ goalieJSON :: Value
goalieJSON = Object $ HM.fromList goalieJSON = Object $ HM.fromList
[ ( "number", toJSON (1 :: Int) ) [ ( "number", toJSON (1 :: Int) )
, ( "name", toJSON ("Joe" :: String ) ) , ( "name", toJSON ("Joe" :: String ) )
, ( "rookie", toJSON False )
, ( "ytd", goalieStatsJSON 1 ) , ( "ytd", goalieStatsJSON 1 )
, ( "lifetime", goalieStatsJSON 2 ) , ( "lifetime", goalieStatsJSON 2 )
] ]
@ -843,6 +847,7 @@ makePlayer = Player
<$> makeNum <$> makeNum
<*> makeName <*> makeName
<*> makeName <*> makeName
<*> makeBool
<*> makePlayerStats <*> makePlayerStats
<*> makePlayerStats <*> makePlayerStats
@ -851,6 +856,7 @@ makeGoalie :: IO Goalie
makeGoalie = Goalie makeGoalie = Goalie
<$> makeNum <$> makeNum
<*> makeName <*> makeName
<*> makeBool
<*> makeGoalieStats <*> makeGoalieStats
<*> makeGoalieStats <*> makeGoalieStats
@ -875,6 +881,9 @@ makeGoalieStats = GoalieStats
makeNum :: IO Int makeNum :: IO Int
makeNum = randomRIO (1, 10) makeNum = randomRIO (1, 10)
makeBool :: IO Bool
makeBool = randomIO
makeName :: IO String makeName :: IO String
makeName = replicateM 10 $ randomRIO ('A', 'Z') makeName = replicateM 10 $ randomRIO ('A', 'Z')