Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29fae81513 | ||
|
|
0676bf4067 | ||
|
|
119032ca80 | ||
|
|
2607fc5ce8 | ||
|
|
d18cb7dd59 | ||
|
|
dff11a8316 | ||
|
|
747bdf8f32 | ||
|
|
9b07c6d249 | ||
|
|
e28ef1ff0e | ||
|
|
960fbb3443 | ||
|
|
439aab99d3 | ||
|
|
8d7a7997b1 | ||
|
|
7e409fdbd4 | ||
|
|
28b1fa0e06 | ||
|
|
7c4b7331e8 | ||
|
|
214710661a | ||
|
|
6bb4601e6b | ||
|
|
e51953650c | ||
|
|
14386f9c7d | ||
|
|
ec10aa7998 | ||
|
|
fe28e96145 | ||
|
|
2941998058 | ||
|
|
c22849bb3b | ||
|
|
4315b40732 | ||
|
|
fefa217df1 | ||
|
|
6d77caaa14 | ||
|
|
a69853858d | ||
|
|
045f2915e1 | ||
|
|
dfd226c7bd | ||
|
|
b9d8b263df | ||
|
|
a2968595d8 | ||
|
|
25e4929f0b | ||
|
|
457298e565 | ||
|
|
a80eaa2a40 | ||
|
|
8a6cf10ad3 | ||
|
|
bd5bc21661 | ||
|
|
accc831bc5 | ||
|
|
2c78a591ca | ||
|
|
77dc89c76d | ||
|
|
607a78ccea | ||
|
|
d7c5f24c26 | ||
|
|
d94c6a588e | ||
|
|
bdbe0131d7 | ||
|
|
b0638b95b8 | ||
|
|
ce2d32407e | ||
|
|
5771091f18 | ||
|
|
13a1949446 | ||
|
|
835cb9582b | ||
|
|
8bc9b48aa2 | ||
|
|
378efea24e | ||
|
|
6418ab0eea | ||
|
|
95e74accd4 | ||
|
|
ffc1390755 | ||
|
|
2f0a3a5c57 | ||
|
|
79d527866f |
12
ChangeLog.md
12
ChangeLog.md
@@ -1,5 +1,17 @@
|
||||
# Changelog for mtlstats
|
||||
|
||||
## 0.13.0
|
||||
- Added autocomplete to player position prompt
|
||||
- Don't prompt for lifetime stats on rookie player/goalie creation
|
||||
- Ask whether a player/goalie is active on creation
|
||||
- Don't ask which goalie to assign the game to when there's only one
|
||||
|
||||
## 0.12.0
|
||||
- Edit lifetime stats on new player/goalie creation
|
||||
- Sort goalies by minutes played
|
||||
- Subsort players by lifetime points
|
||||
- Changed wording on edit menus
|
||||
|
||||
## 0.11.0
|
||||
- Added active flag to players/goalies
|
||||
- Clear rookie flag on new (regular) season
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: mtlstats
|
||||
version: 0.11.0
|
||||
version: 0.13.0
|
||||
github: "mtlstats/mtlstats"
|
||||
license: GPL-3
|
||||
author: "Jonathan Lamothe"
|
||||
|
||||
@@ -161,11 +161,15 @@ editSelectedGoalie f s = fromMaybe s $ do
|
||||
addPlayer :: ProgState -> ProgState
|
||||
addPlayer s = fromMaybe s $ do
|
||||
let cps = s^.progMode.createPlayerStateL
|
||||
num <- cps^.cpsNumber
|
||||
num <- cps^.cpsNumber
|
||||
rFlag <- cps^.cpsRookieFlag
|
||||
aFlag <- cps^.cpsActiveFlag
|
||||
let
|
||||
name = cps^.cpsName
|
||||
pos = cps^.cpsPosition
|
||||
player = newPlayer num name pos
|
||||
& pRookie .~ rFlag
|
||||
& pActive .~ aFlag
|
||||
Just $ s & database.dbPlayers
|
||||
%~ (++[player])
|
||||
|
||||
@@ -173,10 +177,14 @@ addPlayer s = fromMaybe s $ do
|
||||
addGoalie :: ProgState -> ProgState
|
||||
addGoalie s = fromMaybe s $ do
|
||||
let cgs = s^.progMode.createGoalieStateL
|
||||
num <- cgs^.cgsNumber
|
||||
num <- cgs^.cgsNumber
|
||||
rFlag <- cgs^.cgsRookieFlag
|
||||
aFlag <- cgs^.cgsActiveFlag
|
||||
let
|
||||
name = cgs^.cgsName
|
||||
goalie = newGoalie num name
|
||||
& gRookie .~ rFlag
|
||||
& gActive .~ aFlag
|
||||
Just $ s & database.dbGoalies
|
||||
%~ (++[goalie])
|
||||
|
||||
|
||||
@@ -36,8 +36,12 @@ import Mtlstats.Util
|
||||
|
||||
-- | Attempts to finish game goalie entry
|
||||
finishGoalieEntry :: ProgState -> ProgState
|
||||
finishGoalieEntry s = s & progMode.gameStateL.gameGoaliesRecorded
|
||||
.~ not (null $ s^.progMode.gameStateL.gameGoalieStats)
|
||||
finishGoalieEntry s = case M.toList $ s^.progMode.gameStateL.gameGoalieStats of
|
||||
[] -> s
|
||||
[(gid, _)] -> setGameGoalie gid s'
|
||||
_ -> s'
|
||||
where
|
||||
s' = s & progMode.gameStateL.gameGoaliesRecorded .~ True
|
||||
|
||||
-- | Records the goalie's game stats
|
||||
recordGoalieStats :: ProgState -> ProgState
|
||||
|
||||
@@ -21,20 +21,15 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
module Mtlstats.Control (dispatch) where
|
||||
|
||||
import Control.Monad (join)
|
||||
import Control.Monad.Trans.State (gets, modify)
|
||||
import Data.Maybe (fromJust)
|
||||
import Lens.Micro ((^.))
|
||||
import Lens.Micro.Extras (view)
|
||||
import qualified UI.NCurses as C
|
||||
|
||||
import Mtlstats.Actions
|
||||
import Mtlstats.Control.TitleScreen
|
||||
import Mtlstats.Control.CreateGoalie
|
||||
import Mtlstats.Control.CreatePlayer
|
||||
import Mtlstats.Control.EditGoalie
|
||||
import Mtlstats.Control.EditPlayer
|
||||
import Mtlstats.Control.EditStandings
|
||||
import Mtlstats.Control.NewGame
|
||||
import Mtlstats.Handlers
|
||||
import Mtlstats.Control.TitleScreen
|
||||
import Mtlstats.Menu
|
||||
import Mtlstats.Prompt
|
||||
import Mtlstats.Types
|
||||
@@ -43,20 +38,13 @@ import Mtlstats.Types
|
||||
-- run
|
||||
dispatch :: ProgState -> Controller
|
||||
dispatch s = case s^.progMode of
|
||||
TitleScreen -> titleScreenC
|
||||
MainMenu -> mainMenuC
|
||||
NewSeason flag -> newSeasonC flag
|
||||
NewGame gs -> newGameC gs
|
||||
EditMenu -> editMenuC
|
||||
CreatePlayer cps
|
||||
| null $ cps^.cpsNumber -> getPlayerNumC
|
||||
| null $ cps^.cpsName -> getPlayerNameC
|
||||
| null $ cps^.cpsPosition -> getPlayerPosC
|
||||
| otherwise -> confirmCreatePlayerC
|
||||
CreateGoalie cgs
|
||||
| null $ cgs^.cgsNumber -> getGoalieNumC
|
||||
| null $ cgs^.cgsName -> getGoalieNameC
|
||||
| otherwise -> confirmCreateGoalieC
|
||||
TitleScreen -> titleScreenC
|
||||
MainMenu -> mainMenuC
|
||||
NewSeason flag -> newSeasonC flag
|
||||
NewGame gs -> newGameC gs
|
||||
EditMenu -> editMenuC
|
||||
CreatePlayer cps -> createPlayerC cps
|
||||
CreateGoalie cgs -> createGoalieC cgs
|
||||
EditPlayer eps -> editPlayerC eps
|
||||
EditGoalie egs -> editGoalieC egs
|
||||
(EditStandings esm) -> editStandingsC esm
|
||||
@@ -73,85 +61,3 @@ newSeasonC True = menuController newSeasonMenu
|
||||
|
||||
editMenuC :: Controller
|
||||
editMenuC = menuController editMenu
|
||||
|
||||
getPlayerNumC :: Controller
|
||||
getPlayerNumC = Controller
|
||||
{ drawController = drawPrompt playerNumPrompt
|
||||
, handleController = \e -> do
|
||||
promptHandler playerNumPrompt e
|
||||
return True
|
||||
}
|
||||
|
||||
getPlayerNameC :: Controller
|
||||
getPlayerNameC = Controller
|
||||
{ drawController = drawPrompt playerNamePrompt
|
||||
, handleController = \e -> do
|
||||
promptHandler playerNamePrompt e
|
||||
return True
|
||||
}
|
||||
|
||||
getPlayerPosC :: Controller
|
||||
getPlayerPosC = Controller
|
||||
{ drawController = drawPrompt playerPosPrompt
|
||||
, handleController = \e -> do
|
||||
promptHandler playerPosPrompt e
|
||||
return True
|
||||
}
|
||||
|
||||
confirmCreatePlayerC :: Controller
|
||||
confirmCreatePlayerC = Controller
|
||||
{ drawController = \s -> do
|
||||
let cps = s^.progMode.createPlayerStateL
|
||||
C.drawString $ " Player number: " ++ show (fromJust $ cps^.cpsNumber) ++ "\n"
|
||||
C.drawString $ " Player name: " ++ cps^.cpsName ++ "\n"
|
||||
C.drawString $ "Player position: " ++ cps^.cpsPosition ++ "\n\n"
|
||||
C.drawString "Create player: are you sure? (Y/N)"
|
||||
return C.CursorInvisible
|
||||
, handleController = \e -> do
|
||||
case ynHandler e of
|
||||
Just True -> do
|
||||
modify addPlayer
|
||||
join $ gets $ view $ progMode.createPlayerStateL.cpsSuccessCallback
|
||||
Just False ->
|
||||
join $ gets $ view $ progMode.createPlayerStateL.cpsFailureCallback
|
||||
Nothing -> return ()
|
||||
return True
|
||||
}
|
||||
|
||||
getGoalieNumC :: Controller
|
||||
getGoalieNumC = Controller
|
||||
{ drawController = drawPrompt goalieNumPrompt
|
||||
, handleController = \e -> do
|
||||
promptHandler goalieNumPrompt e
|
||||
return True
|
||||
}
|
||||
|
||||
getGoalieNameC :: Controller
|
||||
getGoalieNameC = Controller
|
||||
{ drawController = drawPrompt goalieNamePrompt
|
||||
, handleController = \e -> do
|
||||
promptHandler goalieNamePrompt e
|
||||
return True
|
||||
}
|
||||
|
||||
confirmCreateGoalieC :: Controller
|
||||
confirmCreateGoalieC = Controller
|
||||
{ drawController = \s -> do
|
||||
let cgs = s^.progMode.createGoalieStateL
|
||||
C.drawString $ unlines
|
||||
[ "Goalie number: " ++ show (fromJust $ cgs^.cgsNumber)
|
||||
, " Goalie name: " ++ cgs^.cgsName
|
||||
, ""
|
||||
, "Create goalie: are you sure? (Y/N)"
|
||||
]
|
||||
return C.CursorInvisible
|
||||
, handleController = \e -> do
|
||||
case ynHandler e of
|
||||
Just True -> do
|
||||
modify addGoalie
|
||||
join $ gets (^.progMode.createGoalieStateL.cgsSuccessCallback)
|
||||
Just False ->
|
||||
join $ gets (^.progMode.createGoalieStateL.cgsFailureCallback)
|
||||
Nothing -> return ()
|
||||
return True
|
||||
}
|
||||
|
||||
107
src/Mtlstats/Control/CreateGoalie.hs
Normal file
107
src/Mtlstats/Control/CreateGoalie.hs
Normal file
@@ -0,0 +1,107 @@
|
||||
{- |
|
||||
|
||||
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.Control.CreateGoalie (createGoalieC) where
|
||||
|
||||
import Control.Monad.Trans.State (gets, modify)
|
||||
import Lens.Micro ((^.), (.~), (?~), (%~), to)
|
||||
import qualified UI.NCurses as C
|
||||
|
||||
import Mtlstats.Actions
|
||||
import Mtlstats.Format
|
||||
import Mtlstats.Handlers
|
||||
import Mtlstats.Prompt
|
||||
import Mtlstats.Types
|
||||
|
||||
-- | Handles goalie creation
|
||||
createGoalieC :: CreateGoalieState -> Controller
|
||||
createGoalieC cgs
|
||||
| null $ cgs^.cgsNumber = getGoalieNumC
|
||||
| null $ cgs^.cgsName = getGoalieNameC
|
||||
| null $ cgs^.cgsRookieFlag = getRookieFlagC
|
||||
| null $ cgs^.cgsActiveFlag = getActiveFlagC
|
||||
| otherwise = confirmCreateGoalieC
|
||||
|
||||
getGoalieNumC :: Controller
|
||||
getGoalieNumC = promptController goalieNumPrompt
|
||||
|
||||
getGoalieNameC :: Controller
|
||||
getGoalieNameC = promptController goalieNamePrompt
|
||||
|
||||
getRookieFlagC :: Controller
|
||||
getRookieFlagC = Controller
|
||||
{ drawController = const $ do
|
||||
C.drawString "Is this goalie a rookie? (Y/N)"
|
||||
return C.CursorInvisible
|
||||
, handleController = \e -> do
|
||||
modify $ case ynHandler e of
|
||||
Just True -> progMode.createGoalieStateL
|
||||
%~ (cgsRookieFlag ?~ True)
|
||||
. (cgsActiveFlag ?~ True)
|
||||
rf -> progMode.createGoalieStateL.cgsRookieFlag .~ rf
|
||||
return True
|
||||
}
|
||||
|
||||
getActiveFlagC :: Controller
|
||||
getActiveFlagC = Controller
|
||||
{ drawController = const $ do
|
||||
C.drawString "Is this goalie active? (Y/N)"
|
||||
return C.CursorInvisible
|
||||
, handleController = \e -> do
|
||||
modify $ progMode.createGoalieStateL.cgsActiveFlag .~ ynHandler e
|
||||
return True
|
||||
}
|
||||
|
||||
confirmCreateGoalieC :: Controller
|
||||
confirmCreateGoalieC = Controller
|
||||
{ drawController = \s -> do
|
||||
let cgs = s^.progMode.createGoalieStateL
|
||||
C.drawString $ unlines
|
||||
$ labelTable
|
||||
[ ( "Goalie number", maybe "?" show $ cgs^.cgsNumber )
|
||||
, ( "Goalie name", cgs^.cgsName )
|
||||
, ( "Rookie", maybe "?" show $ cgs^.cgsRookieFlag )
|
||||
, ( "Active", maybe "?" show $ cgs^.cgsActiveFlag )
|
||||
]
|
||||
++ [ ""
|
||||
, "Create goalie: are you sure? (Y/N)"
|
||||
]
|
||||
return C.CursorInvisible
|
||||
, handleController = \e -> do
|
||||
cgs <- gets (^.progMode.createGoalieStateL)
|
||||
let
|
||||
success = cgs^.cgsSuccessCallback
|
||||
failure = cgs^.cgsFailureCallback
|
||||
case ynHandler e of
|
||||
Just True -> do
|
||||
gid <- gets (^.database.dbGoalies.to length)
|
||||
let rookie = cgs^.cgsRookieFlag == Just True
|
||||
modify addGoalie
|
||||
if rookie
|
||||
then success
|
||||
else modify $ progMode.editGoalieStateL
|
||||
%~ (egsSelectedGoalie ?~ gid)
|
||||
. (egsMode .~ EGLtGames True)
|
||||
. (egsCallback .~ success)
|
||||
Just False -> failure
|
||||
Nothing -> return ()
|
||||
return True
|
||||
}
|
||||
112
src/Mtlstats/Control/CreatePlayer.hs
Normal file
112
src/Mtlstats/Control/CreatePlayer.hs
Normal file
@@ -0,0 +1,112 @@
|
||||
{- |
|
||||
|
||||
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.Control.CreatePlayer (createPlayerC) where
|
||||
|
||||
import Control.Monad.Trans.State (gets, modify)
|
||||
import Lens.Micro ((^.), (.~), (?~), (%~), to)
|
||||
import qualified UI.NCurses as C
|
||||
|
||||
import Mtlstats.Actions
|
||||
import Mtlstats.Format
|
||||
import Mtlstats.Handlers
|
||||
import Mtlstats.Prompt
|
||||
import Mtlstats.Types
|
||||
|
||||
-- | Handles player creation
|
||||
createPlayerC :: CreatePlayerState -> Controller
|
||||
createPlayerC cps
|
||||
| null $ cps^.cpsNumber = getPlayerNumC
|
||||
| null $ cps^.cpsName = getPlayerNameC
|
||||
| null $ cps^.cpsPosition = getPlayerPosC
|
||||
| null $ cps^.cpsRookieFlag = getRookieFlagC
|
||||
| null $ cps^.cpsActiveFlag = getActiveFlagC
|
||||
| otherwise = confirmCreatePlayerC
|
||||
|
||||
getPlayerNumC :: Controller
|
||||
getPlayerNumC = promptController playerNumPrompt
|
||||
|
||||
getPlayerNameC :: Controller
|
||||
getPlayerNameC = promptController playerNamePrompt
|
||||
|
||||
getPlayerPosC :: Controller
|
||||
getPlayerPosC = promptController playerPosPrompt
|
||||
|
||||
getRookieFlagC :: Controller
|
||||
getRookieFlagC = Controller
|
||||
{ drawController = const $ do
|
||||
C.drawString "Is this player a rookie? (Y/N)"
|
||||
return C.CursorInvisible
|
||||
, handleController = \e -> do
|
||||
modify $ case ynHandler e of
|
||||
Just True -> progMode.createPlayerStateL
|
||||
%~ (cpsRookieFlag ?~ True)
|
||||
. (cpsActiveFlag ?~ True)
|
||||
rf -> progMode.createPlayerStateL.cpsRookieFlag .~ rf
|
||||
return True
|
||||
}
|
||||
|
||||
getActiveFlagC :: Controller
|
||||
getActiveFlagC = Controller
|
||||
{ drawController = const $ do
|
||||
C.drawString "Is the player active? (Y/N)"
|
||||
return C.CursorInvisible
|
||||
, handleController = \e -> do
|
||||
modify $ progMode.createPlayerStateL.cpsActiveFlag .~ ynHandler e
|
||||
return True
|
||||
}
|
||||
|
||||
confirmCreatePlayerC :: Controller
|
||||
confirmCreatePlayerC = Controller
|
||||
{ drawController = \s -> do
|
||||
let cps = s^.progMode.createPlayerStateL
|
||||
C.drawString $ unlines
|
||||
$ labelTable
|
||||
[ ( "Player number", maybe "?" show $ cps^.cpsNumber )
|
||||
, ( "Player name", cps^.cpsName )
|
||||
, ( "Player position", cps^.cpsPosition )
|
||||
, ( "Rookie", maybe "?" show $ cps^.cpsRookieFlag )
|
||||
, ( "Active", maybe "?" show $ cps^.cpsActiveFlag )
|
||||
]
|
||||
++ [ ""
|
||||
, "Create player: are you sure? (Y/N)"
|
||||
]
|
||||
return C.CursorInvisible
|
||||
, handleController = \e -> do
|
||||
cps <- gets (^.progMode.createPlayerStateL)
|
||||
let
|
||||
success = cps^.cpsSuccessCallback
|
||||
failure = cps^.cpsFailureCallback
|
||||
case ynHandler e of
|
||||
Just True -> do
|
||||
pid <- gets (^.database.dbPlayers.to length)
|
||||
let rookie = cps^.cpsRookieFlag == Just True
|
||||
modify addPlayer
|
||||
if rookie
|
||||
then success
|
||||
else modify $ progMode.editPlayerStateL
|
||||
%~ (epsSelectedPlayer ?~ pid)
|
||||
. (epsMode .~ EPLtGoals True)
|
||||
. (epsCallback .~ success)
|
||||
Just False -> failure
|
||||
Nothing -> return ()
|
||||
return True
|
||||
}
|
||||
@@ -39,89 +39,103 @@ import Mtlstats.Util
|
||||
editGoalieC :: EditGoalieState -> Controller
|
||||
editGoalieC egs
|
||||
| null $ egs^.egsSelectedGoalie = selectC
|
||||
| otherwise = editC $ egs^.egsMode
|
||||
| otherwise = editC (egs^.egsCallback) (egs^.egsMode)
|
||||
|
||||
selectC :: Controller
|
||||
selectC = promptController goalieToEditPrompt
|
||||
|
||||
editC :: EditGoalieMode -> Controller
|
||||
editC = \case
|
||||
EGMenu -> menuC
|
||||
EGNumber -> numberC
|
||||
EGName -> nameC
|
||||
EGYtd -> ytdMenuC
|
||||
EGLifetime -> lifetimeMenuC
|
||||
EGYtdGames b -> ytdGamesC b
|
||||
EGYtdMins b -> ytdMinsC b
|
||||
EGYtdGoals b -> ytdGoalsC b
|
||||
EGYtdShutouts b -> ytdShutoutsC b
|
||||
EGYtdWins b -> ytdWinsC b
|
||||
EGYtdLosses b -> ytdLossesC b
|
||||
EGYtdTies -> ytdTiesC
|
||||
EGLtGames b -> ltGamesC b
|
||||
EGLtMins b -> ltMinsC b
|
||||
EGLtGoals b -> ltGoalsC b
|
||||
EGLtShutouts b -> ltShutoutsC b
|
||||
EGLtWins b -> ltWinsC b
|
||||
EGLtLosses b -> ltLossesC b
|
||||
EGLtTies -> ltTiesC
|
||||
editC :: Action () -> EditGoalieMode -> Controller
|
||||
editC cb =
|
||||
( \case
|
||||
EGMenu -> menuC
|
||||
EGNumber -> numberC
|
||||
EGName -> nameC
|
||||
EGYtd -> ytdMenuC
|
||||
EGLifetime -> lifetimeMenuC
|
||||
EGYtdGames b -> ytdGamesC b
|
||||
EGYtdMins b -> ytdMinsC b
|
||||
EGYtdGoals b -> ytdGoalsC b
|
||||
EGYtdShutouts b -> ytdShutoutsC b
|
||||
EGYtdWins b -> ytdWinsC b
|
||||
EGYtdLosses b -> ytdLossesC b
|
||||
EGYtdTies -> ytdTiesC
|
||||
EGLtGames b -> ltGamesC b
|
||||
EGLtMins b -> ltMinsC b
|
||||
EGLtGoals b -> ltGoalsC b
|
||||
EGLtShutouts b -> ltShutoutsC b
|
||||
EGLtWins b -> ltWinsC b
|
||||
EGLtLosses b -> ltLossesC b
|
||||
EGLtTies -> ltTiesC
|
||||
) <*> return cb
|
||||
|
||||
menuC :: Controller
|
||||
menuC = menuControllerWith header editGoalieMenu
|
||||
menuC :: Action () -> Controller
|
||||
menuC _ = menuControllerWith header editGoalieMenu
|
||||
|
||||
numberC :: Controller
|
||||
numberC = promptController editGoalieNumberPrompt
|
||||
numberC :: Action () -> Controller
|
||||
numberC = promptController . editGoalieNumberPrompt
|
||||
|
||||
nameC :: Controller
|
||||
nameC = promptController editGoalieNamePrompt
|
||||
nameC :: Action () -> Controller
|
||||
nameC = promptController . editGoalieNamePrompt
|
||||
|
||||
ytdMenuC :: Controller
|
||||
ytdMenuC = menuControllerWith header editGoalieYtdMenu
|
||||
ytdMenuC :: Action () -> Controller
|
||||
ytdMenuC _ = menuControllerWith header editGoalieYtdMenu
|
||||
|
||||
lifetimeMenuC :: Controller
|
||||
lifetimeMenuC = menuControllerWith header editGoalieLtMenu
|
||||
lifetimeMenuC :: Action () -> Controller
|
||||
lifetimeMenuC _ = menuControllerWith header editGoalieLtMenu
|
||||
|
||||
ytdGamesC :: Bool -> Controller
|
||||
ytdGamesC = promptController . editGoalieYtdGamesPrompt
|
||||
ytdGamesC :: Bool -> Action () -> Controller
|
||||
ytdGamesC = curry $ promptController .
|
||||
uncurry editGoalieYtdGamesPrompt
|
||||
|
||||
ytdMinsC :: Bool -> Controller
|
||||
ytdMinsC = promptController . editGoalieYtdMinsPrompt
|
||||
ytdMinsC :: Bool -> Action () -> Controller
|
||||
ytdMinsC = curry $ promptController .
|
||||
uncurry editGoalieYtdMinsPrompt
|
||||
|
||||
ytdGoalsC :: Bool -> Controller
|
||||
ytdGoalsC = promptController . editGoalieYtdGoalsPrompt
|
||||
ytdGoalsC :: Bool -> Action () -> Controller
|
||||
ytdGoalsC = curry $ promptController .
|
||||
uncurry editGoalieYtdGoalsPrompt
|
||||
|
||||
ytdShutoutsC :: Bool -> Controller
|
||||
ytdShutoutsC = promptController . editGoalieYtdShutoutsPrompt
|
||||
ytdShutoutsC :: Bool -> Action () -> Controller
|
||||
ytdShutoutsC = curry $ promptController .
|
||||
uncurry editGoalieYtdShutoutsPrompt
|
||||
|
||||
ytdWinsC :: Bool -> Controller
|
||||
ytdWinsC = promptController . editGoalieYtdWinsPrompt
|
||||
ytdWinsC :: Bool -> Action () -> Controller
|
||||
ytdWinsC = curry $ promptController .
|
||||
uncurry editGoalieYtdWinsPrompt
|
||||
|
||||
ytdLossesC :: Bool -> Controller
|
||||
ytdLossesC = promptController . editGoalieYtdLossesPrompt
|
||||
ytdLossesC :: Bool -> Action () -> Controller
|
||||
ytdLossesC = curry $ promptController .
|
||||
uncurry editGoalieYtdLossesPrompt
|
||||
|
||||
ytdTiesC :: Controller
|
||||
ytdTiesC = promptController editGoalieYtdTiesPrompt
|
||||
ytdTiesC :: Action () -> Controller
|
||||
ytdTiesC = promptController . editGoalieYtdTiesPrompt
|
||||
|
||||
ltGamesC :: Bool -> Controller
|
||||
ltGamesC = promptController . editGoalieLtGamesPrompt
|
||||
ltGamesC :: Bool -> Action () -> Controller
|
||||
ltGamesC = curry $ promptController .
|
||||
uncurry editGoalieLtGamesPrompt
|
||||
|
||||
ltMinsC :: Bool -> Controller
|
||||
ltMinsC = promptController . editGoalieLtMinsPrompt
|
||||
ltMinsC :: Bool -> Action () -> Controller
|
||||
ltMinsC = curry $ promptController .
|
||||
uncurry editGoalieLtMinsPrompt
|
||||
|
||||
ltGoalsC :: Bool -> Controller
|
||||
ltGoalsC = promptController . editGoalieLtGoalsPrompt
|
||||
ltGoalsC :: Bool -> Action() -> Controller
|
||||
ltGoalsC = curry $ promptController .
|
||||
uncurry editGoalieLtGoalsPrompt
|
||||
|
||||
ltShutoutsC :: Bool -> Controller
|
||||
ltShutoutsC = promptController . editGoalieLtShutoutsPrompt
|
||||
ltShutoutsC :: Bool -> Action () -> Controller
|
||||
ltShutoutsC = curry $ promptController .
|
||||
uncurry editGoalieLtShutoutsPrompt
|
||||
|
||||
ltWinsC :: Bool -> Controller
|
||||
ltWinsC = promptController . editGoalieLtWinsPrompt
|
||||
ltWinsC :: Bool -> Action () -> Controller
|
||||
ltWinsC = curry $ promptController .
|
||||
uncurry editGoalieLtWinsPrompt
|
||||
|
||||
ltLossesC :: Bool -> Controller
|
||||
ltLossesC = promptController . editGoalieLtLossesPrompt
|
||||
ltLossesC :: Bool -> Action () -> Controller
|
||||
ltLossesC = curry $ promptController .
|
||||
uncurry editGoalieLtLossesPrompt
|
||||
|
||||
ltTiesC :: Controller
|
||||
ltTiesC = promptController editGoalieLtTiesPrompt
|
||||
ltTiesC :: Action () -> Controller
|
||||
ltTiesC = promptController . editGoalieLtTiesPrompt
|
||||
|
||||
header :: ProgState -> C.Update ()
|
||||
header s = C.drawString $ fromMaybe "" $ do
|
||||
|
||||
@@ -37,58 +37,64 @@ import Mtlstats.Util
|
||||
editPlayerC :: EditPlayerState -> Controller
|
||||
editPlayerC eps
|
||||
| null $ eps^.epsSelectedPlayer = selectPlayerC
|
||||
| otherwise = case eps^.epsMode of
|
||||
EPMenu -> menuC
|
||||
EPNumber -> numberC
|
||||
EPName -> nameC
|
||||
EPPosition -> positionC
|
||||
EPYtd -> ytdC
|
||||
EPLifetime -> lifetimeC
|
||||
EPYtdGoals b -> ytdGoalsC b
|
||||
EPYtdAssists b -> ytdAssistsC b
|
||||
EPYtdPMin -> ytdPMinC
|
||||
EPLtGoals b -> ltGoalsC b
|
||||
EPLtAssists b -> ltAssistsC b
|
||||
EPLtPMin -> ltPMinC
|
||||
| otherwise =
|
||||
( case eps^.epsMode of
|
||||
EPMenu -> menuC
|
||||
EPNumber -> numberC
|
||||
EPName -> nameC
|
||||
EPPosition -> positionC
|
||||
EPYtd -> ytdC
|
||||
EPLifetime -> lifetimeC
|
||||
EPYtdGoals b -> ytdGoalsC b
|
||||
EPYtdAssists b -> ytdAssistsC b
|
||||
EPYtdPMin -> ytdPMinC
|
||||
EPLtGoals b -> ltGoalsC b
|
||||
EPLtAssists b -> ltAssistsC b
|
||||
EPLtPMin -> ltPMinC
|
||||
) $ eps^.epsCallback
|
||||
|
||||
selectPlayerC :: Controller
|
||||
selectPlayerC = promptController playerToEditPrompt
|
||||
|
||||
menuC :: Controller
|
||||
menuC = menuControllerWith header editPlayerMenu
|
||||
menuC :: Action () -> Controller
|
||||
menuC _ = menuControllerWith header editPlayerMenu
|
||||
|
||||
numberC :: Controller
|
||||
numberC = promptController editPlayerNumPrompt
|
||||
numberC :: Action () -> Controller
|
||||
numberC = promptController . editPlayerNumPrompt
|
||||
|
||||
nameC :: Controller
|
||||
nameC = promptController editPlayerNamePrompt
|
||||
nameC :: Action () -> Controller
|
||||
nameC = promptController . editPlayerNamePrompt
|
||||
|
||||
positionC :: Controller
|
||||
positionC = promptController editPlayerPosPrompt
|
||||
positionC :: Action () -> Controller
|
||||
positionC = promptController . editPlayerPosPrompt
|
||||
|
||||
ytdC :: Controller
|
||||
ytdC = menuControllerWith header editPlayerYtdMenu
|
||||
ytdC :: Action () -> Controller
|
||||
ytdC _ = menuControllerWith header editPlayerYtdMenu
|
||||
|
||||
lifetimeC :: Controller
|
||||
lifetimeC = menuControllerWith header editPlayerLtMenu
|
||||
lifetimeC :: Action () -> Controller
|
||||
lifetimeC _ = menuControllerWith header editPlayerLtMenu
|
||||
|
||||
ytdGoalsC :: Bool -> Controller
|
||||
ytdGoalsC = promptController . editPlayerYtdGoalsPrompt
|
||||
ytdGoalsC :: Bool -> Action () -> Controller
|
||||
ytdGoalsC batchMode callback = promptController $
|
||||
editPlayerYtdGoalsPrompt batchMode callback
|
||||
|
||||
ytdAssistsC :: Bool -> Controller
|
||||
ytdAssistsC = promptController . editPlayerYtdAssistsPrompt
|
||||
ytdAssistsC :: Bool -> Action () -> Controller
|
||||
ytdAssistsC batchMode callback = promptController $
|
||||
editPlayerYtdAssistsPrompt batchMode callback
|
||||
|
||||
ytdPMinC :: Controller
|
||||
ytdPMinC = promptController editPlayerYtdPMinPrompt
|
||||
ytdPMinC :: Action () -> Controller
|
||||
ytdPMinC = promptController . editPlayerYtdPMinPrompt
|
||||
|
||||
ltGoalsC :: Bool -> Controller
|
||||
ltGoalsC = promptController . editPlayerLtGoalsPrompt
|
||||
ltGoalsC :: Bool -> Action () -> Controller
|
||||
ltGoalsC batchMode callback = promptController $
|
||||
editPlayerLtGoalsPrompt batchMode callback
|
||||
|
||||
ltAssistsC :: Bool -> Controller
|
||||
ltAssistsC = promptController . editPlayerLtAssistsPrompt
|
||||
ltAssistsC :: Bool -> Action () -> Controller
|
||||
ltAssistsC batchMode callback = promptController $
|
||||
editPlayerLtAssistsPrompt batchMode callback
|
||||
|
||||
ltPMinC :: Controller
|
||||
ltPMinC = promptController editPlayerLtPMinPrompt
|
||||
ltPMinC :: Action () -> Controller
|
||||
ltPMinC = promptController . editPlayerLtPMinPrompt
|
||||
|
||||
header :: ProgState -> C.Update ()
|
||||
header s = C.drawString $ fromMaybe "" $ do
|
||||
|
||||
89
src/Mtlstats/Helpers/Position.hs
Normal file
89
src/Mtlstats/Helpers/Position.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/>.
|
||||
|
||||
-}
|
||||
|
||||
{-# LANGUAGE LambdaCase #-}
|
||||
|
||||
module Mtlstats.Helpers.Position
|
||||
( posSearch
|
||||
, posSearchExact
|
||||
, posCallback
|
||||
, getPositions
|
||||
) where
|
||||
|
||||
import Control.Monad.Trans.State (gets)
|
||||
import Data.Char (toUpper)
|
||||
import Data.List (isInfixOf)
|
||||
import Data.Maybe (fromMaybe)
|
||||
import qualified Data.Set as S
|
||||
import Lens.Micro ((^.), to)
|
||||
|
||||
import Mtlstats.Types
|
||||
import Mtlstats.Util
|
||||
|
||||
-- | Searches the 'Database' for all the positions used
|
||||
posSearch
|
||||
:: String
|
||||
-- ^ The search string
|
||||
-> Database
|
||||
-- ^ The database
|
||||
-> [(Int, String)]
|
||||
-- ^ A list of result indices and their values
|
||||
posSearch sStr db = filter sFunc $ zip [0..] ps
|
||||
where
|
||||
sFunc (_, pos) = map toUpper sStr `isInfixOf` map toUpper pos
|
||||
ps = getPositions db
|
||||
|
||||
-- | Searches the 'Database' for an exact position
|
||||
posSearchExact
|
||||
:: String
|
||||
-- ^ The search string
|
||||
-> Database
|
||||
-- ^ The database
|
||||
-> Maybe Int
|
||||
-- ^ The index of the result (or 'Nothing' if not found)
|
||||
posSearchExact sStr db = case filter sFunc $ zip [0..] ps of
|
||||
[] -> Nothing
|
||||
(n,_):_ -> Just n
|
||||
where
|
||||
sFunc (_, pos) = sStr == pos
|
||||
ps = getPositions db
|
||||
|
||||
-- | Builds a callback function for when a 'Player' position is
|
||||
-- selected
|
||||
posCallback
|
||||
:: (String -> Action ())
|
||||
-- ^ The raw callback function
|
||||
-> Maybe Int
|
||||
-- ^ The index number of the position selected or 'Nothing' if blank
|
||||
-> Action ()
|
||||
-- ^ The action to perform
|
||||
posCallback callback = \case
|
||||
Nothing -> callback ""
|
||||
Just n -> do
|
||||
ps <- gets (^.database.to getPositions)
|
||||
let pos = fromMaybe "" $ nth n ps
|
||||
callback pos
|
||||
|
||||
-- | Extracts a list of positions from a 'Database'
|
||||
getPositions :: Database -> [String]
|
||||
getPositions = do
|
||||
raw <- map (^.pPosition) . (^.dbPlayers)
|
||||
return $ S.toList $ S.fromList raw
|
||||
@@ -38,12 +38,12 @@ editGoalieMenu = Menu "EDIT GOALTENDER" () $ map
|
||||
(\(ch, label, action) -> MenuItem ch label $ modify action)
|
||||
|
||||
-- key, label, value
|
||||
[ ( '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 )
|
||||
[ ( 'A', "NUMBER", set EGNumber )
|
||||
, ( 'B', "NAME", set EGName )
|
||||
, ( 'C', "ROOKIE FLAG", toggleRookie )
|
||||
, ( 'D', "ACTIVE FLAG", toggleActive )
|
||||
, ( 'E', "YTD STATS", set EGYtd )
|
||||
, ( 'F', "LIFETIME STATS", set EGLifetime )
|
||||
, ( 'R', "RETURN TO EDIT MENU", edit )
|
||||
]
|
||||
|
||||
@@ -56,14 +56,14 @@ editGoalieMenu = Menu "EDIT GOALTENDER" () $ map
|
||||
editGoalieYtdMenu :: Menu ()
|
||||
editGoalieYtdMenu = editMenu "EDIT GOALTENDER YEAR-TO-DATE"
|
||||
-- key, label, value
|
||||
[ ( '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 )
|
||||
[ ( 'A', "ALL YTD STATS", EGYtdGames True )
|
||||
, ( 'B', "YTD GAMES", EGYtdGames False )
|
||||
, ( 'C', "YTD MINUTES", EGYtdMins False )
|
||||
, ( 'D', "YTD GOALS", EGYtdGoals False )
|
||||
, ( 'E', "YTD SHUTOUTS", EGYtdShutouts False )
|
||||
, ( 'F', "YTD WINS", EGYtdWins False )
|
||||
, ( 'G', "YTD LOSSES", EGYtdLosses False )
|
||||
, ( 'H', "YTD TIES", EGYtdTies )
|
||||
, ( 'R', "RETURN TO EDIT MENU", EGMenu )
|
||||
]
|
||||
|
||||
@@ -71,16 +71,16 @@ editGoalieYtdMenu = editMenu "EDIT GOALTENDER YEAR-TO-DATE"
|
||||
editGoalieLtMenu :: Menu ()
|
||||
editGoalieLtMenu = editMenu
|
||||
"EDIT GOALTENDER LIFETIME"
|
||||
-- key, label, value
|
||||
[ ( '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 )
|
||||
-- key, label, value
|
||||
[ ( 'A', "ALL LIFETIME STATS", EGLtGames True )
|
||||
, ( 'B', "LIFETIME GAMES", EGLtGames False )
|
||||
, ( 'C', "LIFETIME MINUTES", EGLtMins False )
|
||||
, ( 'D', "LIFETIME GOALS", EGLtGoals False )
|
||||
, ( 'E', "LIFETIME SHUTOUTS", EGLtShutouts False )
|
||||
, ( 'F', "LIFETIME WINS", EGLtWins False )
|
||||
, ( 'G', "LIFETIME LOSSES", EGLtLosses False )
|
||||
, ( 'H', "LIFETIME TIES", EGLtTies )
|
||||
, ( 'R', "RETURN TO EDIT MENU", EGMenu )
|
||||
]
|
||||
|
||||
editMenu :: String -> [(Char, String, EditGoalieMode)] -> Menu ()
|
||||
|
||||
@@ -38,13 +38,13 @@ editPlayerMenu = Menu "EDIT PLAYER" () $ map
|
||||
(\(ch, label, action) -> MenuItem ch label $ modify action)
|
||||
|
||||
-- key, label, value
|
||||
[ ( '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 )
|
||||
[ ( 'A', "NUMBER", set EPNumber )
|
||||
, ( 'B', "NAME", set EPName )
|
||||
, ( 'C', "POSITION", set EPPosition )
|
||||
, ( 'D', "ROOKIE FLAG", toggleRookie )
|
||||
, ( 'E', "ACTIVE FLAG", toggleActive )
|
||||
, ( 'F', "YTD STATS", set EPYtd )
|
||||
, ( 'G', "LIFETIME STATS", set EPLifetime )
|
||||
, ( 'R', "RETURN TO EDIT MENU", edit )
|
||||
]
|
||||
|
||||
@@ -58,10 +58,10 @@ editPlayerYtdMenu :: Menu ()
|
||||
editPlayerYtdMenu = editMenu
|
||||
"EDIT PLAYER YEAR-TO-DATE"
|
||||
-- key, label, value
|
||||
[ ( '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 )
|
||||
[ ( 'A', "ALL YTD STATS", EPYtdGoals True )
|
||||
, ( 'B', "YTD GOALS", EPYtdGoals False )
|
||||
, ( 'C', "YTD ASSISTS", EPYtdAssists False )
|
||||
, ( 'D', "YTD PENALTY MINS", EPYtdPMin )
|
||||
, ( 'R', "RETURN TO PLAYER EDIT MENU", EPMenu )
|
||||
]
|
||||
|
||||
@@ -70,10 +70,10 @@ editPlayerLtMenu :: Menu ()
|
||||
editPlayerLtMenu = editMenu
|
||||
"EDIT PLAYER LIFETIME"
|
||||
-- key, label, value
|
||||
[ ( '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 )
|
||||
[ ( 'A', "ALL LIFETIME STATS", EPLtGoals True )
|
||||
, ( 'B', "LIFETIME GOALS", EPLtGoals False )
|
||||
, ( 'C', "LIFETIME ASSITS", EPLtAssists False )
|
||||
, ( 'D', "LIFETIME PENALTY MINS", EPLtPMin )
|
||||
, ( 'R', "RETURN TO EDIT PLAYER MENU", EPMenu )
|
||||
]
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ module Mtlstats.Prompt (
|
||||
goalieNamePrompt,
|
||||
selectPlayerPrompt,
|
||||
selectGoaliePrompt,
|
||||
selectPositionPrompt,
|
||||
playerToEditPrompt
|
||||
) where
|
||||
|
||||
@@ -56,6 +57,7 @@ import qualified UI.NCurses as C
|
||||
|
||||
import Mtlstats.Actions
|
||||
import Mtlstats.Config
|
||||
import Mtlstats.Helpers.Position
|
||||
import Mtlstats.Types
|
||||
import Mtlstats.Util
|
||||
|
||||
@@ -172,11 +174,12 @@ numPromptWithFallback pStr fallback act = Prompt
|
||||
-- to
|
||||
newSeasonPrompt :: Prompt
|
||||
newSeasonPrompt = prompt
|
||||
{ promptProcessChar = \ch str -> if isAlphaNum ch
|
||||
{ promptProcessChar = \ch str -> if validChar ch
|
||||
then str ++ [toUpper ch]
|
||||
else str
|
||||
}
|
||||
where
|
||||
|
||||
prompt = strPrompt "Filename to save database: " $ \fn ->
|
||||
if null fn
|
||||
then modify backHome
|
||||
@@ -184,6 +187,8 @@ newSeasonPrompt = prompt
|
||||
saveDatabase $ fn ++ ".json"
|
||||
modify $ progMode .~ NewSeason True
|
||||
|
||||
validChar = (||) <$> isAlphaNum <*> (=='-')
|
||||
|
||||
-- | Builds a selection prompt
|
||||
selectPrompt :: SelectParams a -> Prompt
|
||||
selectPrompt params = Prompt
|
||||
@@ -233,7 +238,7 @@ playerNamePrompt = namePrompt "Player name: " $
|
||||
|
||||
-- | Prompts for a new player's position
|
||||
playerPosPrompt :: Prompt
|
||||
playerPosPrompt = ucStrPrompt "Player position: " $
|
||||
playerPosPrompt = selectPositionPrompt "Player position: " $
|
||||
modify . (progMode.createPlayerStateL.cpsPosition .~)
|
||||
|
||||
-- | Prompts tor the goalie's number
|
||||
@@ -304,6 +309,24 @@ selectGoaliePrompt pStr callback = selectPrompt SelectParams
|
||||
modify $ progMode .~ CreateGoalie cgs
|
||||
}
|
||||
|
||||
-- | Selects (or creates) a player position
|
||||
selectPositionPrompt
|
||||
:: String
|
||||
-- ^ The 'Prompt' string
|
||||
-> (String -> Action ())
|
||||
-- ^ The action to perform when a value is entered
|
||||
-> Prompt
|
||||
selectPositionPrompt pStr callback = selectPrompt SelectParams
|
||||
{ spPrompt = pStr
|
||||
, spSearchHeader = "Positions:"
|
||||
, spSearch = posSearch
|
||||
, spSearchExact = posSearchExact
|
||||
, spElemDesc = id
|
||||
, spProcessChar = \ch -> (++ [toUpper ch])
|
||||
, spCallback = posCallback callback
|
||||
, spNotFound = callback
|
||||
}
|
||||
|
||||
playerToEditPrompt :: Prompt
|
||||
playerToEditPrompt = selectPlayerPrompt "Player to edit: " $
|
||||
modify . (progMode.editPlayerStateL.epsSelectedPlayer .~)
|
||||
|
||||
@@ -52,85 +52,119 @@ goalieToEditPrompt = selectGoaliePrompt "Goalie to edit: " $
|
||||
modify . (progMode.editGoalieStateL.egsSelectedGoalie .~)
|
||||
|
||||
-- | Prompt to edit a goalie's number
|
||||
editGoalieNumberPrompt :: Prompt
|
||||
editGoalieNumberPrompt
|
||||
:: Action ()
|
||||
-- ^ Action to perform on completion
|
||||
-> Prompt
|
||||
editGoalieNumberPrompt = editNum "Goalie number: " EGMenu
|
||||
(gNumber .~)
|
||||
|
||||
-- | Prompt to edit a goalie's name
|
||||
editGoalieNamePrompt :: Prompt
|
||||
editGoalieNamePrompt = namePrompt "Goalie name: " $ \name ->
|
||||
editGoalieNamePrompt
|
||||
:: Action ()
|
||||
-- ^ Action to perform on completion
|
||||
-> Prompt
|
||||
editGoalieNamePrompt cb = namePrompt "Goalie name: " $ \name -> do
|
||||
if null name
|
||||
then goto EGMenu
|
||||
else doEdit EGMenu $ gName .~ name
|
||||
then goto EGMenu
|
||||
else doEdit EGMenu $ gName .~ name
|
||||
cb
|
||||
|
||||
-- | Prompt to edit a goalie's YTD games played
|
||||
editGoalieYtdGamesPrompt
|
||||
:: Bool
|
||||
-- ^ Indicates whether or not we're in batch mode
|
||||
-> Action ()
|
||||
-- ^ Action to perform on completion
|
||||
-> Prompt
|
||||
editGoalieYtdGamesPrompt batchMode =
|
||||
editGoalieYtdGamesPrompt batchMode cb =
|
||||
editNum "Year-to-date games played: " mode
|
||||
(gYtd.gsGames .~)
|
||||
(gYtd.gsGames .~) cb'
|
||||
where
|
||||
mode = if batchMode then EGYtdMins True else EGYtd
|
||||
(mode, cb') = if batchMode
|
||||
then (EGYtdMins True, return ())
|
||||
else (EGYtd, cb)
|
||||
|
||||
-- | Prompt to edit a goalie's YTD minutes played
|
||||
editGoalieYtdMinsPrompt
|
||||
:: Bool
|
||||
-- ^ Indicates whether or not we're in batch mode
|
||||
-> Action ()
|
||||
-- ^ Action to perform on completion
|
||||
-> Prompt
|
||||
editGoalieYtdMinsPrompt batchMode =
|
||||
editGoalieYtdMinsPrompt batchMode cb =
|
||||
editNum "Year-to-date minutes played: " mode
|
||||
(gYtd.gsMinsPlayed .~)
|
||||
(gYtd.gsMinsPlayed .~) cb'
|
||||
where
|
||||
mode = if batchMode then EGYtdGoals True else EGYtd
|
||||
(mode, cb') = if batchMode
|
||||
then (EGYtdGoals True, return ())
|
||||
else (EGYtd, cb)
|
||||
|
||||
-- | Prompt to edit a goalie's YTD goales allowed
|
||||
editGoalieYtdGoalsPrompt
|
||||
:: Bool
|
||||
-- ^ Indicates whether or not we're in batch mode
|
||||
-> Action ()
|
||||
-- ^ Action to perform on completion
|
||||
-> Prompt
|
||||
editGoalieYtdGoalsPrompt batchMode =
|
||||
editGoalieYtdGoalsPrompt batchMode cb =
|
||||
editNum "Year-to-date goals allowed: " mode
|
||||
(gYtd.gsGoalsAllowed .~)
|
||||
(gYtd.gsGoalsAllowed .~) cb'
|
||||
where
|
||||
mode = if batchMode then EGYtdShutouts True else EGYtd
|
||||
(mode, cb') = if batchMode
|
||||
then (EGYtdShutouts True, return ())
|
||||
else (EGYtd, cb)
|
||||
|
||||
-- | Prompt to edit a goalie's YTD shutouts
|
||||
editGoalieYtdShutoutsPrompt
|
||||
:: Bool
|
||||
-- ^ Indicates whether or not we're in batch mode
|
||||
-> Action ()
|
||||
-- ^ Action to perform on completion
|
||||
-> Prompt
|
||||
editGoalieYtdShutoutsPrompt batchMode =
|
||||
editGoalieYtdShutoutsPrompt batchMode cb =
|
||||
editNum "Year-to-date shutouts: " mode
|
||||
(gYtd.gsShutouts .~)
|
||||
(gYtd.gsShutouts .~) cb'
|
||||
where
|
||||
mode = if batchMode then EGYtdWins True else EGYtd
|
||||
(mode, cb') = if batchMode
|
||||
then (EGYtdWins True, return ())
|
||||
else (EGYtd, cb)
|
||||
|
||||
-- | Prompt to edit a goalie's YTD wins
|
||||
editGoalieYtdWinsPrompt
|
||||
:: Bool
|
||||
-- ^ Indicates whether or not we're in batch mode
|
||||
-> Action ()
|
||||
-- ^ Action to perform on completion
|
||||
-> Prompt
|
||||
editGoalieYtdWinsPrompt batchMode =
|
||||
editGoalieYtdWinsPrompt batchMode cb =
|
||||
editNum "Year-to-date wins: " mode
|
||||
(gYtd.gsWins .~)
|
||||
(gYtd.gsWins .~) cb'
|
||||
where
|
||||
mode = if batchMode then EGYtdLosses True else EGYtd
|
||||
(mode, cb') = if batchMode
|
||||
then (EGYtdLosses True, return ())
|
||||
else (EGYtd, cb)
|
||||
|
||||
-- | Prompt to edit a goalie's YTD losses
|
||||
editGoalieYtdLossesPrompt
|
||||
:: Bool
|
||||
-- ^ Indicates whether or not we're in batch mode
|
||||
-> Action ()
|
||||
-- ^ Action to perform on completion
|
||||
-> Prompt
|
||||
editGoalieYtdLossesPrompt batchMode =
|
||||
editGoalieYtdLossesPrompt batchMode cb =
|
||||
editNum "Year-to-date losses: " mode
|
||||
(gYtd.gsLosses .~)
|
||||
(gYtd.gsLosses .~) cb'
|
||||
where
|
||||
mode = if batchMode then EGYtdTies else EGYtd
|
||||
(mode, cb') = if batchMode
|
||||
then (EGYtdTies, return ())
|
||||
else (EGYtd, cb)
|
||||
|
||||
-- | Prompt to edit a goalie's YTD ties
|
||||
editGoalieYtdTiesPrompt :: Prompt
|
||||
editGoalieYtdTiesPrompt
|
||||
:: Action ()
|
||||
-- ^ Action to perform on completion
|
||||
-> Prompt
|
||||
editGoalieYtdTiesPrompt = editNum "Year-to-date ties: " EGYtd
|
||||
(gYtd.gsTies .~)
|
||||
|
||||
@@ -138,70 +172,97 @@ editGoalieYtdTiesPrompt = editNum "Year-to-date ties: " EGYtd
|
||||
editGoalieLtGamesPrompt
|
||||
:: Bool
|
||||
-- ^ Indicates whether or not we're in batch mode
|
||||
-> Action ()
|
||||
-- ^ Action to perform on completion
|
||||
-> Prompt
|
||||
editGoalieLtGamesPrompt batchMode =
|
||||
editGoalieLtGamesPrompt batchMode cb =
|
||||
editNum "Lifetime games played: " mode
|
||||
(gLifetime.gsGames .~)
|
||||
(gLifetime.gsGames .~) cb'
|
||||
where
|
||||
mode = if batchMode then EGLtMins True else EGLifetime
|
||||
(mode, cb') = if batchMode
|
||||
then (EGLtMins True, return ())
|
||||
else (EGLifetime, cb)
|
||||
|
||||
-- | Prompt to edit a goalie's lifetime minutes played
|
||||
editGoalieLtMinsPrompt
|
||||
:: Bool
|
||||
-- ^ Indicates whether or not we're in batch mode
|
||||
-> Action ()
|
||||
-- ^ Action to perform on completion
|
||||
-> Prompt
|
||||
editGoalieLtMinsPrompt batchMode =
|
||||
editGoalieLtMinsPrompt batchMode cb =
|
||||
editNum "Lifetime minutes played: " mode
|
||||
(gLifetime.gsMinsPlayed .~)
|
||||
(gLifetime.gsMinsPlayed .~) cb'
|
||||
where
|
||||
mode = if batchMode then EGLtGoals True else EGLifetime
|
||||
(mode, cb') = if batchMode
|
||||
then (EGLtGoals True, return ())
|
||||
else (EGLifetime, cb)
|
||||
|
||||
-- | Prompt to edit a goalie's lifetime goals allowed
|
||||
editGoalieLtGoalsPrompt
|
||||
:: Bool
|
||||
-- ^ Indicates whether or not we're in batch mode
|
||||
-> Action ()
|
||||
-- ^ Action to perform on completion
|
||||
-> Prompt
|
||||
editGoalieLtGoalsPrompt batchMode =
|
||||
editGoalieLtGoalsPrompt batchMode cb =
|
||||
editNum "Lifetime goals allowed: " mode
|
||||
(gLifetime.gsGoalsAllowed .~)
|
||||
(gLifetime.gsGoalsAllowed .~) cb'
|
||||
where
|
||||
mode = if batchMode then EGLtShutouts True else EGLifetime
|
||||
(mode, cb') = if batchMode
|
||||
then (EGLtShutouts True, return ())
|
||||
else (EGLifetime, cb)
|
||||
|
||||
-- | Prompt to edit a goalie's lifetime shutouts
|
||||
editGoalieLtShutoutsPrompt
|
||||
:: Bool
|
||||
-- ^ Indicates whether or not we're in batch mode
|
||||
-> Action ()
|
||||
-- ^ Action to perform on completion
|
||||
-> Prompt
|
||||
editGoalieLtShutoutsPrompt batchMode =
|
||||
editGoalieLtShutoutsPrompt batchMode cb =
|
||||
editNum "Lifetime shutouts: " mode
|
||||
(gLifetime.gsShutouts .~)
|
||||
(gLifetime.gsShutouts .~) cb'
|
||||
where
|
||||
mode = if batchMode then EGLtWins True else EGLifetime
|
||||
(mode, cb') = if batchMode
|
||||
then (EGLtWins True, return ())
|
||||
else (EGLifetime, cb)
|
||||
|
||||
-- | Prompt to edit a goalie's lifetime wins
|
||||
editGoalieLtWinsPrompt
|
||||
:: Bool
|
||||
-- ^ Indicates whether or not we're in batch mode
|
||||
-> Action ()
|
||||
-- ^ Action to perform on completion
|
||||
-> Prompt
|
||||
editGoalieLtWinsPrompt batchMode =
|
||||
editGoalieLtWinsPrompt batchMode cb =
|
||||
editNum "Lifetime wins: " mode
|
||||
(gLifetime.gsWins .~)
|
||||
(gLifetime.gsWins .~) cb'
|
||||
where
|
||||
mode = if batchMode then EGLtLosses True else EGLifetime
|
||||
(mode, cb') = if batchMode
|
||||
then (EGLtLosses True, return ())
|
||||
else (EGLifetime, cb)
|
||||
|
||||
-- | Prompt to edit a goalie's lifetime losses
|
||||
editGoalieLtLossesPrompt
|
||||
:: Bool
|
||||
-- ^ Indicates whether or not we're in batch mode
|
||||
-> Action ()
|
||||
-- ^ Action to perform on completion
|
||||
-> Prompt
|
||||
editGoalieLtLossesPrompt batchMode =
|
||||
editGoalieLtLossesPrompt batchMode cb =
|
||||
editNum "Lifetime losses: " mode
|
||||
(gLifetime.gsLosses .~)
|
||||
(gLifetime.gsLosses .~) cb'
|
||||
where
|
||||
mode = if batchMode then EGLtTies else EGLifetime
|
||||
(mode, cb') = if batchMode
|
||||
then (EGLtTies, return ())
|
||||
else (EGLifetime, cb)
|
||||
|
||||
-- | Prompt to edit a goalie's lifetime ties
|
||||
editGoalieLtTiesPrompt :: Prompt
|
||||
editGoalieLtTiesPrompt
|
||||
:: Action ()
|
||||
-- ^ Action to perform on completion
|
||||
-> Prompt
|
||||
editGoalieLtTiesPrompt = editNum "Lifetime ties: " EGLifetime
|
||||
(gLifetime.gsTies .~)
|
||||
|
||||
@@ -209,10 +270,13 @@ editNum
|
||||
:: String
|
||||
-> EditGoalieMode
|
||||
-> (Int -> Goalie -> Goalie)
|
||||
-> Action ()
|
||||
-> Prompt
|
||||
editNum pStr mode f = numPromptWithFallback pStr
|
||||
(goto mode)
|
||||
(doEdit mode . f)
|
||||
editNum pStr mode f cb = numPromptWithFallback pStr
|
||||
(goto mode >> cb)
|
||||
(\num -> do
|
||||
doEdit mode $ f num
|
||||
cb)
|
||||
|
||||
doEdit :: EditGoalieMode -> (Goalie -> Goalie) -> Action ()
|
||||
doEdit mode f = do
|
||||
|
||||
@@ -39,46 +39,68 @@ import Mtlstats.Prompt
|
||||
import Mtlstats.Types
|
||||
|
||||
-- | Prompt to edit a player's number
|
||||
editPlayerNumPrompt :: Prompt
|
||||
editPlayerNumPrompt
|
||||
:: Action ()
|
||||
-- ^ The action to be performed upon completion
|
||||
-> Prompt
|
||||
editPlayerNumPrompt = editNum "Player number: " EPMenu
|
||||
(pNumber .~)
|
||||
|
||||
-- | Prompt to edit a player's name
|
||||
editPlayerNamePrompt :: Prompt
|
||||
editPlayerNamePrompt = namePrompt "Player name: " $ \name ->
|
||||
editPlayerNamePrompt
|
||||
:: Action ()
|
||||
-- ^ The action to be performed upon completion
|
||||
-> Prompt
|
||||
editPlayerNamePrompt callback = namePrompt "Player name: " $ \name -> do
|
||||
if null name
|
||||
then goto EPMenu
|
||||
else doEdit EPMenu $ pName .~ name
|
||||
then goto EPMenu
|
||||
else doEdit EPMenu $ pName .~ name
|
||||
callback
|
||||
|
||||
-- | Prompt to edit a player's position
|
||||
editPlayerPosPrompt :: Prompt
|
||||
editPlayerPosPrompt = ucStrPrompt "Player position: " $ \pos ->
|
||||
editPlayerPosPrompt
|
||||
:: Action ()
|
||||
-- ^ The action to be performed upon completion
|
||||
-> Prompt
|
||||
editPlayerPosPrompt callback = selectPositionPrompt "Player position: " $ \pos -> do
|
||||
if null pos
|
||||
then goto EPMenu
|
||||
else doEdit EPMenu $ pPosition .~ pos
|
||||
then goto EPMenu
|
||||
else doEdit EPMenu $ pPosition .~ pos
|
||||
callback
|
||||
|
||||
-- | Prompt to edit a player's year-to-date goals
|
||||
editPlayerYtdGoalsPrompt
|
||||
:: Bool
|
||||
-- ^ Indicates wheter or not we're editing in batch mode
|
||||
-> Action ()
|
||||
-- ^ The action to be performed upon completion
|
||||
-> Prompt
|
||||
editPlayerYtdGoalsPrompt batchMode = editNum "Year-to-date goals: " mode
|
||||
(pYtd.psGoals .~)
|
||||
editPlayerYtdGoalsPrompt batchMode callback = editNum "Year-to-date goals: " mode
|
||||
(pYtd.psGoals .~) callback'
|
||||
where
|
||||
mode = if batchMode then EPYtdAssists True else EPYtd
|
||||
(mode, callback') = if batchMode
|
||||
then (EPYtdAssists True, return ())
|
||||
else (EPYtd, callback)
|
||||
|
||||
-- | Prompt to edit a player's year-to-date assists
|
||||
editPlayerYtdAssistsPrompt
|
||||
:: Bool
|
||||
-- ^ Indicates wheter or not we're editing in batch mode
|
||||
-> Action ()
|
||||
-- ^ The action to be performed upon completion
|
||||
-> Prompt
|
||||
editPlayerYtdAssistsPrompt batchMode = editNum "Year-to-date assists: " mode
|
||||
(pYtd.psAssists .~)
|
||||
editPlayerYtdAssistsPrompt batchMode callback = editNum "Year-to-date assists: " mode
|
||||
(pYtd.psAssists .~) callback'
|
||||
where
|
||||
mode = if batchMode then EPYtdPMin else EPYtd
|
||||
(mode, callback') = if batchMode
|
||||
then (EPYtdPMin, return ())
|
||||
else (EPYtd, callback)
|
||||
|
||||
-- | Prompt to edit a player's year-to-date penalty minutes
|
||||
editPlayerYtdPMinPrompt :: Prompt
|
||||
editPlayerYtdPMinPrompt
|
||||
:: Action ()
|
||||
-- ^ The action to be performed upon completion
|
||||
-> Prompt
|
||||
editPlayerYtdPMinPrompt = editNum "Year-to-date penalty minutes: " EPYtd
|
||||
(pYtd.psPMin .~)
|
||||
|
||||
@@ -86,24 +108,35 @@ editPlayerYtdPMinPrompt = editNum "Year-to-date penalty minutes: " EPYtd
|
||||
editPlayerLtGoalsPrompt
|
||||
:: Bool
|
||||
-- ^ Indicates wheter or not we're editing in batch mode
|
||||
-> Action ()
|
||||
-- ^ The action to be performed upon completion
|
||||
-> Prompt
|
||||
editPlayerLtGoalsPrompt batchMode = editNum "Lifetime goals: " mode
|
||||
(pLifetime.psGoals .~)
|
||||
editPlayerLtGoalsPrompt batchMode callback = editNum "Lifetime goals: " mode
|
||||
(pLifetime.psGoals .~) callback'
|
||||
where
|
||||
mode = if batchMode then EPLtAssists True else EPLifetime
|
||||
(mode, callback') = if batchMode
|
||||
then (EPLtAssists True, return ())
|
||||
else (EPLifetime, callback)
|
||||
|
||||
-- | Prompt to edit a player's lifetime assists
|
||||
editPlayerLtAssistsPrompt
|
||||
:: Bool
|
||||
-- ^ Indicates wheter or not we're editing in batch mode
|
||||
-> Action ()
|
||||
-- ^ The action to be performed upon completion
|
||||
-> Prompt
|
||||
editPlayerLtAssistsPrompt batchMode = editNum "Lifetime assists: " mode
|
||||
(pLifetime.psAssists .~)
|
||||
editPlayerLtAssistsPrompt batchMode callback = editNum "Lifetime assists: " mode
|
||||
(pLifetime.psAssists .~) callback'
|
||||
where
|
||||
mode = if batchMode then EPLtPMin else EPLifetime
|
||||
(mode, callback') = if batchMode
|
||||
then (EPLtPMin, return ())
|
||||
else (EPLifetime, callback)
|
||||
|
||||
-- | Prompt to edit a player's lifetime penalty minutes
|
||||
editPlayerLtPMinPrompt :: Prompt
|
||||
editPlayerLtPMinPrompt
|
||||
:: Action ()
|
||||
-- ^ The action to be performed upon completion
|
||||
-> Prompt
|
||||
editPlayerLtPMinPrompt = editNum "Lifetime penalty minutes: " EPLifetime
|
||||
(pLifetime.psPMin .~)
|
||||
|
||||
@@ -111,10 +144,13 @@ editNum
|
||||
:: String
|
||||
-> EditPlayerMode
|
||||
-> (Int -> Player -> Player)
|
||||
-> Action ()
|
||||
-> Prompt
|
||||
editNum pStr mode f = numPromptWithFallback pStr
|
||||
(goto mode)
|
||||
(doEdit mode . f)
|
||||
editNum pStr mode f callback = numPromptWithFallback pStr
|
||||
(goto mode >> callback)
|
||||
(\num -> do
|
||||
doEdit mode $ f num
|
||||
callback)
|
||||
|
||||
doEdit :: EditPlayerMode -> (Player -> Player) -> Action ()
|
||||
doEdit mode f = do
|
||||
|
||||
@@ -117,7 +117,7 @@ gameStatsReport width s = let
|
||||
gs = s^.progMode.gameStateL
|
||||
db = s^.database
|
||||
|
||||
playerStats = mapMaybe
|
||||
playerStats = sortPlayers $ mapMaybe
|
||||
(\(pid, stats) -> do
|
||||
p <- nth pid $ db^.dbPlayers
|
||||
Just (p, stats))
|
||||
@@ -139,7 +139,7 @@ yearToDateStatsReport :: Int -> ProgState -> [String]
|
||||
yearToDateStatsReport width s = let
|
||||
db = s^.database
|
||||
|
||||
playerStats = sortOn (Down . psPoints . snd)
|
||||
playerStats = sortPlayers
|
||||
$ map (\p -> (p, p^.pYtd))
|
||||
$ filter playerIsActive
|
||||
$ db^.dbPlayers
|
||||
@@ -156,7 +156,7 @@ lifetimeStatsReport :: Int -> ProgState -> [String]
|
||||
lifetimeStatsReport width s = let
|
||||
db = s^.database
|
||||
|
||||
playerStats = sortOn (Down . psPoints . snd)
|
||||
playerStats = sortPlayers
|
||||
$ map (\p -> (p, p^.pLifetime))
|
||||
$ db^.dbPlayers
|
||||
|
||||
@@ -261,8 +261,10 @@ goalieReport width showTotals lineNumbers goalieData = let
|
||||
then "GOALTENDING TOTALS"
|
||||
else ""
|
||||
|
||||
goalieData' = sortGoalies goalieData
|
||||
|
||||
tData = foldl addGoalieStats newGoalieStats
|
||||
$ map snd goalieData
|
||||
$ map snd goalieData'
|
||||
|
||||
header =
|
||||
[ CellText "NO."
|
||||
@@ -287,7 +289,7 @@ goalieReport width showTotals lineNumbers goalieData = let
|
||||
[ CellText $ show (goalie^.gNumber) ++ " "
|
||||
, CellText $ goalieName goalie
|
||||
] ++ rowCells stats)
|
||||
goalieData
|
||||
goalieData'
|
||||
|
||||
separator
|
||||
= replicate 2 (CellText "")
|
||||
@@ -309,6 +311,8 @@ goalieReport width showTotals lineNumbers goalieData = let
|
||||
|
||||
gameGoalieReport :: Int -> [(Goalie, GoalieStats)] -> [String]
|
||||
gameGoalieReport width goalieData = let
|
||||
goalieData' = sortGoalies goalieData
|
||||
|
||||
header =
|
||||
[ CellText "NO."
|
||||
, CellText "GOALTENDER"
|
||||
@@ -325,8 +329,16 @@ gameGoalieReport width goalieData = let
|
||||
, CellText $ show $ stats^.gsGoalsAllowed
|
||||
, CellText $ showFloating $ gsAverage stats
|
||||
])
|
||||
goalieData
|
||||
goalieData'
|
||||
|
||||
in map (centre width)
|
||||
$ complexTable ([right, left] ++ repeat right)
|
||||
$ header : body
|
||||
|
||||
sortPlayers :: [(Player, PlayerStats)] -> [(Player, PlayerStats)]
|
||||
sortPlayers = sortOn $ Down . \(p, ps) ->
|
||||
(psPoints ps, psPoints $ p^.pLifetime)
|
||||
|
||||
sortGoalies :: [(Goalie, GoalieStats)] -> [(Goalie, GoalieStats)]
|
||||
sortGoalies = sortOn $ Down . \(g, gs) ->
|
||||
(gs^.gsMinsPlayed, g^.gLifetime.gsMinsPlayed)
|
||||
|
||||
@@ -88,19 +88,25 @@ module Mtlstats.Types (
|
||||
cpsNumber,
|
||||
cpsName,
|
||||
cpsPosition,
|
||||
cpsRookieFlag,
|
||||
cpsActiveFlag,
|
||||
cpsSuccessCallback,
|
||||
cpsFailureCallback,
|
||||
-- ** CreateGoalieState Lenses
|
||||
cgsNumber,
|
||||
cgsName,
|
||||
cgsRookieFlag,
|
||||
cgsActiveFlag,
|
||||
cgsSuccessCallback,
|
||||
cgsFailureCallback,
|
||||
-- ** EditPlayerState Lenses
|
||||
epsSelectedPlayer,
|
||||
epsMode,
|
||||
epsCallback,
|
||||
-- ** EditGoalieState Lenses
|
||||
egsSelectedGoalie,
|
||||
egsMode,
|
||||
egsCallback,
|
||||
-- ** Database Lenses
|
||||
dbPlayers,
|
||||
dbGoalies,
|
||||
@@ -326,6 +332,10 @@ data CreatePlayerState = CreatePlayerState
|
||||
-- ^ The player's name
|
||||
, _cpsPosition :: String
|
||||
-- ^ The player's position
|
||||
, _cpsRookieFlag :: Maybe Bool
|
||||
-- ^ Indicates whether or not the player is a rookie
|
||||
, _cpsActiveFlag :: Maybe Bool
|
||||
-- ^ Indicates whether or not the plauer is active
|
||||
, _cpsSuccessCallback :: Action ()
|
||||
-- ^ The function to call on success
|
||||
, _cpsFailureCallback :: Action ()
|
||||
@@ -334,10 +344,14 @@ data CreatePlayerState = CreatePlayerState
|
||||
|
||||
-- | Goalie creation status
|
||||
data CreateGoalieState = CreateGoalieState
|
||||
{ _cgsNumber :: Maybe Int
|
||||
{ _cgsNumber :: Maybe Int
|
||||
-- ^ The goalie's number
|
||||
, _cgsName :: String
|
||||
, _cgsName :: String
|
||||
-- ^ The goalie's name
|
||||
, _cgsRookieFlag :: Maybe Bool
|
||||
-- ^ Indicates whether or not the goalie is a rookie
|
||||
, _cgsActiveFlag :: Maybe Bool
|
||||
-- ^ Indicates whether or not the goalie is active
|
||||
, _cgsSuccessCallback :: Action ()
|
||||
-- ^ The function to call on success
|
||||
, _cgsFailureCallback :: Action ()
|
||||
@@ -350,6 +364,8 @@ data EditPlayerState = EditPlayerState
|
||||
-- ^ The index number of the player being edited
|
||||
, _epsMode :: EditPlayerMode
|
||||
-- ^ The editing mode
|
||||
, _epsCallback :: Action ()
|
||||
-- ^ The action to perform when the edit is complete
|
||||
}
|
||||
|
||||
-- | Player editing mode
|
||||
@@ -373,6 +389,9 @@ data EditGoalieState = EditGoalieState
|
||||
{ _egsSelectedGoalie :: Maybe Int
|
||||
-- ^ The index number of the 'Goalie' being edited
|
||||
, _egsMode :: EditGoalieMode
|
||||
-- ^ The editing mode
|
||||
, _egsCallback :: Action ()
|
||||
-- ^ The action to perform when the edit is complete
|
||||
}
|
||||
|
||||
-- | 'Goalie' editing mode
|
||||
@@ -800,6 +819,8 @@ newCreatePlayerState = CreatePlayerState
|
||||
{ _cpsNumber = Nothing
|
||||
, _cpsName = ""
|
||||
, _cpsPosition = ""
|
||||
, _cpsRookieFlag = Nothing
|
||||
, _cpsActiveFlag = Nothing
|
||||
, _cpsSuccessCallback = return ()
|
||||
, _cpsFailureCallback = return ()
|
||||
}
|
||||
@@ -809,6 +830,8 @@ newCreateGoalieState :: CreateGoalieState
|
||||
newCreateGoalieState = CreateGoalieState
|
||||
{ _cgsNumber = Nothing
|
||||
, _cgsName = ""
|
||||
, _cgsRookieFlag = Nothing
|
||||
, _cgsActiveFlag = Nothing
|
||||
, _cgsSuccessCallback = return ()
|
||||
, _cgsFailureCallback = return ()
|
||||
}
|
||||
@@ -818,6 +841,7 @@ newEditPlayerState :: EditPlayerState
|
||||
newEditPlayerState = EditPlayerState
|
||||
{ _epsSelectedPlayer = Nothing
|
||||
, _epsMode = EPMenu
|
||||
, _epsCallback = return ()
|
||||
}
|
||||
|
||||
-- | Constructor for an 'EditGoalieState' value
|
||||
@@ -825,6 +849,7 @@ newEditGoalieState :: EditGoalieState
|
||||
newEditGoalieState = EditGoalieState
|
||||
{ _egsSelectedGoalie = Nothing
|
||||
, _egsMode = EGMenu
|
||||
, _egsCallback = return ()
|
||||
}
|
||||
|
||||
-- | Constructor for a 'Database'
|
||||
|
||||
@@ -23,7 +23,7 @@ module Actions.NewGame.GoalieInputSpec (spec) where
|
||||
|
||||
import qualified Data.Map as M
|
||||
import Data.Maybe (fromJust)
|
||||
import Lens.Micro ((^.), (&), (.~), (?~))
|
||||
import Lens.Micro ((^.), (&), (.~), (?~), (%~))
|
||||
import Test.Hspec (Spec, context, describe, it, shouldBe)
|
||||
|
||||
import Mtlstats.Actions.NewGame.GoalieInput
|
||||
@@ -39,21 +39,44 @@ spec = describe "Mtlstats.Actions.GoalieInput" $ do
|
||||
setGameGoalieSpec
|
||||
|
||||
finishGoalieEntrySpec :: Spec
|
||||
finishGoalieEntrySpec = describe "finishGoalieEntry" $ do
|
||||
let
|
||||
progState stats = newProgState
|
||||
& progMode.gameStateL.gameGoalieStats .~ stats
|
||||
& finishGoalieEntry
|
||||
finishGoalieEntrySpec = describe "finishGoalieEntry" $ mapM_
|
||||
(\(label, stats, grFlag, gaFlag) -> context label $ do
|
||||
let
|
||||
ps = newProgState
|
||||
& progMode.gameStateL
|
||||
%~ (gameGoalieStats .~ stats)
|
||||
. (gameType ?~ HomeGame)
|
||||
. (homeScore ?~ 1)
|
||||
. (awayScore ?~ 0)
|
||||
. (overtimeFlag ?~ False)
|
||||
& database.dbGoalies .~ goalies
|
||||
|
||||
context "no goalie data" $
|
||||
it "should not set goaliesRecorded" $ let
|
||||
s = progState M.empty
|
||||
in s^.progMode.gameStateL.gameGoaliesRecorded `shouldBe` False
|
||||
ps' = finishGoalieEntry ps
|
||||
gs = ps'^.progMode.gameStateL
|
||||
|
||||
context "goalie data" $
|
||||
it "should set goaliesRecorded" $ let
|
||||
s = progState $ M.fromList [(1, newGoalieStats)]
|
||||
in s^.progMode.gameStateL.gameGoaliesRecorded `shouldBe` True
|
||||
describe "gameGoaliesRecorded" $
|
||||
it ("should be " ++ show grFlag) $
|
||||
gs^.gameGoaliesRecorded `shouldBe` grFlag
|
||||
|
||||
describe "gameGoalieAssigned" $
|
||||
it ("should be " ++ show gaFlag) $
|
||||
gs^.gameGoalieAssigned `shouldBe` gaFlag)
|
||||
|
||||
-- label, initial stats, goalies recorded, goalie assigned
|
||||
[ ( "no goalies", noGoalies, False, False )
|
||||
, ( "one goalie", oneGoalie, True, True )
|
||||
, ( "two goalies", twoGoalies, True, False )
|
||||
]
|
||||
|
||||
where
|
||||
goalies = [joe, bob]
|
||||
joe = newGoalie 2 "Joe"
|
||||
bob = newGoalie 3 "Bob"
|
||||
noGoalies = M.empty
|
||||
oneGoalie = M.fromList [joeStats]
|
||||
twoGoalies = M.fromList [joeStats, bobStats]
|
||||
joeStats = (0, newGoalieStats)
|
||||
bobStats = (1, newGoalieStats)
|
||||
|
||||
recordGoalieStatsSpec :: Spec
|
||||
recordGoalieStatsSpec = describe "recordGoalieStats" $ let
|
||||
|
||||
@@ -312,51 +312,93 @@ editSelectedGoalieSpec = describe "editSelectedGoalie" $ mapM_
|
||||
goalie' n = newGoalie n "foo"
|
||||
|
||||
addPlayerSpec :: Spec
|
||||
addPlayerSpec = describe "addPlayer" $ do
|
||||
let
|
||||
p1 = newPlayer 1 "Joe" "centre"
|
||||
p2 = newPlayer 2 "Bob" "defense"
|
||||
db = newDatabase
|
||||
& dbPlayers .~ [p1]
|
||||
s pm = newProgState
|
||||
& progMode .~ pm
|
||||
& database .~ db
|
||||
addPlayerSpec = describe "addPlayer" $ mapM_
|
||||
(\(label, expectation, pm, players) -> context label $
|
||||
it expectation $ let
|
||||
ps = newProgState
|
||||
& progMode .~ pm
|
||||
& database.dbPlayers .~ [joe]
|
||||
ps' = addPlayer ps
|
||||
in ps'^.database.dbPlayers `shouldBe` players)
|
||||
|
||||
context "data available" $
|
||||
it "should create the player" $ let
|
||||
s' = addPlayer $ s $ CreatePlayer $ newCreatePlayerState
|
||||
& cpsNumber ?~ 2
|
||||
& cpsName .~ "Bob"
|
||||
& cpsPosition .~ "defense"
|
||||
in s'^.database.dbPlayers `shouldBe` [p1, p2]
|
||||
-- label, expectation, progMode, players
|
||||
[ ( "wrong mode", failure, MainMenu, [joe] )
|
||||
, ( "missing number", failure, noNum, [joe] )
|
||||
, ( "missing rookie flag", failure, noRookie, [joe] )
|
||||
, ( "missing active flag", failure, noActive, [joe] )
|
||||
, ( "rookie", success, mkRookie, [joe, rookie] )
|
||||
, ( "retired", success, mkRetired, [joe, retired] )
|
||||
, ( "normal player", success, mkNormal, [joe, normal] )
|
||||
]
|
||||
|
||||
context "data unavailable" $
|
||||
it "should not create the player" $ let
|
||||
s' = addPlayer $ s MainMenu
|
||||
in s'^.database.dbPlayers `shouldBe` [p1]
|
||||
where
|
||||
failure = "should not create the player"
|
||||
success = "should create the player"
|
||||
noNum = mkpm Nothing (Just False) (Just True)
|
||||
noRookie = mkpm (Just 3) Nothing (Just True)
|
||||
noActive = mkpm (Just 3) (Just False) Nothing
|
||||
mkRookie = mkpm (Just 3) (Just True) (Just True)
|
||||
mkRetired = mkpm (Just 3) (Just False) (Just False)
|
||||
mkNormal = mkpm (Just 3) (Just False) (Just True)
|
||||
joe = newPlayer 2 "Joe" "centre"
|
||||
rookie = player True True
|
||||
retired = player False False
|
||||
normal = player False True
|
||||
|
||||
player r a = newPlayer 3 "Bob" "defense"
|
||||
& pRookie .~ r
|
||||
& pActive .~ a
|
||||
|
||||
mkpm n r a = CreatePlayer $ newCreatePlayerState
|
||||
& cpsNumber .~ n
|
||||
& cpsName .~ "Bob"
|
||||
& cpsPosition .~ "defense"
|
||||
& cpsRookieFlag .~ r
|
||||
& cpsActiveFlag .~ a
|
||||
|
||||
addGoalieSpec :: Spec
|
||||
addGoalieSpec = describe "addGoalie" $ do
|
||||
let
|
||||
g1 = newGoalie 2 "Joe"
|
||||
g2 = newGoalie 3 "Bob"
|
||||
db = newDatabase
|
||||
& dbGoalies .~ [g1]
|
||||
s pm = newProgState
|
||||
& database .~ db
|
||||
& progMode .~ pm
|
||||
addGoalieSpec = describe "addGoalie" $ mapM_
|
||||
(\(label, expectation, pm, goalies) -> context label $
|
||||
it expectation $ let
|
||||
ps = newProgState
|
||||
& progMode .~ pm
|
||||
& database.dbGoalies .~ [joe]
|
||||
ps' = addGoalie ps
|
||||
in ps'^.database.dbGoalies `shouldBe` goalies)
|
||||
|
||||
context "data available" $
|
||||
it "should create the goalie" $ let
|
||||
s' = addGoalie $ s $ CreateGoalie $ newCreateGoalieState
|
||||
& cgsNumber ?~ 3
|
||||
& cgsName .~ "Bob"
|
||||
in s'^.database.dbGoalies `shouldBe` [g1, g2]
|
||||
-- label, expectation, progMode, expected goalies
|
||||
[ ( "wrong mode", failure, MainMenu, [joe] )
|
||||
, ( "no number", failure, noNum, [joe] )
|
||||
, ( "no rookie flag", failure, noRookie, [joe] )
|
||||
, ( "no active flag", failure, noActive, [joe] )
|
||||
, ( "rookie", success, mkRookie, [joe, rookie] )
|
||||
, ( "retired", success, mkRetired, [joe, retired] )
|
||||
, ( "normal goalie", success, mkNormal, [joe, normal] )
|
||||
]
|
||||
|
||||
context "data unavailable" $
|
||||
it "should not create the goalie" $ let
|
||||
s' = addGoalie $ s MainMenu
|
||||
in s'^.database.dbGoalies `shouldBe` [g1]
|
||||
where
|
||||
failure = "should not create the goalie"
|
||||
success = "should create the goalie"
|
||||
noNum = cgs Nothing (Just False) (Just True)
|
||||
noRookie = cgs (Just 3) Nothing (Just True)
|
||||
noActive = cgs (Just 3) (Just False) Nothing
|
||||
mkRookie = cgs (Just 3) (Just True) (Just True)
|
||||
mkRetired = cgs (Just 3) (Just False) (Just False)
|
||||
mkNormal = cgs (Just 3) (Just False) (Just True)
|
||||
joe = newGoalie 2 "Joe"
|
||||
rookie = goalie True True
|
||||
retired = goalie False False
|
||||
normal = goalie False True
|
||||
|
||||
goalie r a = newGoalie 3 "Bob"
|
||||
& gRookie .~ r
|
||||
& gActive .~ a
|
||||
|
||||
cgs n r a = CreateGoalie $ newCreateGoalieState
|
||||
& cgsNumber .~ n
|
||||
& cgsName .~ "Bob"
|
||||
& cgsRookieFlag .~ r
|
||||
& cgsActiveFlag .~ a
|
||||
|
||||
resetCreatePlayerStateSpec :: Spec
|
||||
resetCreatePlayerStateSpec = describe "resetCreatePlayerState" $ let
|
||||
|
||||
79
test/Helpers/PositionSpec.hs
Normal file
79
test/Helpers/PositionSpec.hs
Normal file
@@ -0,0 +1,79 @@
|
||||
{-
|
||||
|
||||
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 Helpers.PositionSpec (spec) where
|
||||
|
||||
import Lens.Micro ((&), (.~))
|
||||
import Test.Hspec (Spec, context, describe, it, shouldBe)
|
||||
|
||||
import Mtlstats.Helpers.Position
|
||||
import Mtlstats.Types
|
||||
|
||||
spec :: Spec
|
||||
spec = describe "Position" $ do
|
||||
posSearchSpec
|
||||
posSearchExactSpec
|
||||
getPositionsSpec
|
||||
|
||||
posSearchSpec :: Spec
|
||||
posSearchSpec = describe "posSearch" $ mapM_
|
||||
(\(sStr, expected) -> context ("search string: " ++ show sStr) $
|
||||
it ("should be " ++ show expected) $
|
||||
posSearch sStr db `shouldBe` expected)
|
||||
[ ( "fOo"
|
||||
, [ ( 2, "foo" )
|
||||
]
|
||||
)
|
||||
, ( "A"
|
||||
, [ ( 0, "bar" )
|
||||
, ( 1, "baz" )
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
posSearchExactSpec :: Spec
|
||||
posSearchExactSpec = describe "posSearchExact" $ mapM_
|
||||
(\(input, expected) -> context ("input: " ++ show input) $
|
||||
it ("should be " ++ show expected) $
|
||||
posSearchExact input db `shouldBe` expected)
|
||||
|
||||
-- input, expected
|
||||
[ ( "foo", Just 2 )
|
||||
, ( "FOO", Nothing )
|
||||
, ( "bar", Just 0 )
|
||||
, ( "baz", Just 1 )
|
||||
, ( "a", Nothing )
|
||||
, ( "quux", Nothing )
|
||||
]
|
||||
|
||||
getPositionsSpec :: Spec
|
||||
getPositionsSpec = describe "getPositions" $ let
|
||||
expected = ["bar", "baz", "foo"]
|
||||
in it ("should be " ++ show expected) $
|
||||
getPositions db `shouldBe` expected
|
||||
|
||||
db :: Database
|
||||
db = newDatabase & dbPlayers .~
|
||||
[ newPlayer 2 "Joe" "foo"
|
||||
, newPlayer 3 "Bob" "bar"
|
||||
, newPlayer 5 "Bill" "foo"
|
||||
, newPlayer 8 "Ed" "baz"
|
||||
]
|
||||
@@ -25,8 +25,10 @@ import Test.Hspec (Spec, describe)
|
||||
|
||||
import qualified Helpers.GoalieSpec as Goalie
|
||||
import qualified Helpers.PlayerSpec as Player
|
||||
import qualified Helpers.PositionSpec as Position
|
||||
|
||||
spec :: Spec
|
||||
spec = describe "Helper" $ do
|
||||
Player.spec
|
||||
Goalie.spec
|
||||
Position.spec
|
||||
|
||||
Reference in New Issue
Block a user