diff --git a/ChangeLog.md b/ChangeLog.md index a72815f..8fe2aec 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,8 @@ # Changelog for mtlstats +## current +- only search for active players/goalies on game data input + ## 0.15.0 - Ask for database to load on start-up - Add page break to report file diff --git a/src/Mtlstats/Prompt.hs b/src/Mtlstats/Prompt.hs index 47e65b1..c6c74bc 100644 --- a/src/Mtlstats/Prompt.hs +++ b/src/Mtlstats/Prompt.hs @@ -43,7 +43,9 @@ module Mtlstats.Prompt ( goalieNumPrompt, goalieNamePrompt, selectPlayerPrompt, + selectActivePlayerPrompt, selectGoaliePrompt, + selectActiveGoaliePrompt, selectPositionPrompt, playerToEditPrompt ) where @@ -263,18 +265,21 @@ goalieNamePrompt :: Prompt goalieNamePrompt = namePrompt "Goalie name: " $ modify . (progMode.createGoalieStateL.cgsName .~) --- | Selects a player (creating one if necessary) -selectPlayerPrompt - :: String +-- | Selects a player using a specified search function (creating the +-- player if necessary) +selectPlayerPromptWith + :: (String -> [Player] -> [(Int, Player)]) + -- ^ The search function + -> String -- ^ The prompt string -> (Maybe Int -> Action ()) -- ^ The callback to run (takes the index number of the payer as -- input) -> Prompt -selectPlayerPrompt pStr callback = selectPrompt SelectParams +selectPlayerPromptWith sFunc pStr callback = selectPrompt SelectParams { spPrompt = pStr , spSearchHeader = "Player select:" - , spSearch = \sStr db -> playerSearch sStr (db^.dbPlayers) + , spSearch = \sStr db -> sFunc sStr (db^.dbPlayers) , spSearchExact = \sStr db -> fst <$> playerSearchExact sStr (db^.dbPlayers) , spElemDesc = playerSummary , spProcessChar = capitalizeName @@ -292,18 +297,41 @@ selectPlayerPrompt pStr callback = selectPrompt SelectParams modify $ progMode .~ CreatePlayer cps } --- | Selects a goalie (creating one if necessary) -selectGoaliePrompt +-- | Selects a player (creating one if necessary) +selectPlayerPrompt :: String -- ^ The prompt string -> (Maybe Int -> Action ()) + -- ^ The callback to run (takes the index number of the payer as + -- input) + -> Prompt +selectPlayerPrompt = selectPlayerPromptWith playerSearch + +-- | Selects an active player (creating one if necessary) +selectActivePlayerPrompt + :: String + -- ^ The prompt string + -> (Maybe Int -> Action ()) + -- ^ The callback to run (takes the index number of the payer as + -- input) + -> Prompt +selectActivePlayerPrompt = selectPlayerPromptWith activePlayerSearch + +-- | Selects a goalie with a specified search criteria (creating the +-- goalie if necessary) +selectGoaliePromptWith + :: (String -> [Goalie] -> [(Int, Goalie)]) + -- ^ The search criteria + -> String + -- ^ The prompt string + -> (Maybe Int -> Action ()) -- ^ The callback to run (takes the index number of the goalie as -- input) -> Prompt -selectGoaliePrompt pStr callback = selectPrompt SelectParams +selectGoaliePromptWith criteria pStr callback = selectPrompt SelectParams { spPrompt = pStr , spSearchHeader = "Goalie select:" - , spSearch = \sStr db -> goalieSearch sStr (db^.dbGoalies) + , spSearch = \sStr db -> criteria sStr (db^.dbGoalies) , spSearchExact = \sStr db -> fst <$> goalieSearchExact sStr (db^.dbGoalies) , spElemDesc = goalieSummary , spProcessChar = capitalizeName @@ -321,6 +349,26 @@ selectGoaliePrompt pStr callback = selectPrompt SelectParams modify $ progMode .~ CreateGoalie cgs } +-- | Selects a goalie (creating one if necessary) +selectGoaliePrompt + :: String + -- ^ The prompt string + -> (Maybe Int -> Action ()) + -- ^ The callback to run (takes the index number of the goalie as + -- input) + -> Prompt +selectGoaliePrompt = selectGoaliePromptWith goalieSearch + +-- | Selects an active goalie (creating one if necessary) +selectActiveGoaliePrompt + :: String + -- ^ The prompt string + -> (Maybe Int -> Action ()) + -- ^ The callback to run (takes the index number of the goalie as + -- input) + -> Prompt +selectActiveGoaliePrompt = selectGoaliePromptWith activeGoalieSearch + -- | Selects (or creates) a player position selectPositionPrompt :: String diff --git a/src/Mtlstats/Prompt/NewGame.hs b/src/Mtlstats/Prompt/NewGame.hs index eb35b06..b864a91 100644 --- a/src/Mtlstats/Prompt/NewGame.hs +++ b/src/Mtlstats/Prompt/NewGame.hs @@ -76,7 +76,7 @@ recordGoalPrompt -> Int -- ^ The goal number -> Prompt -recordGoalPrompt game goal = selectPlayerPrompt +recordGoalPrompt game goal = selectActivePlayerPrompt ( "*** GAME " ++ padNum 2 game ++ " ***\n" ++ "Who scored goal number " ++ show goal ++ "? " ) $ modify . (progMode.gameStateL.goalBy .~) @@ -90,7 +90,7 @@ recordAssistPrompt -> Int -- ^ The assist number -> Prompt -recordAssistPrompt game goal assist = selectPlayerPrompt +recordAssistPrompt game goal assist = selectActivePlayerPrompt ( "*** GAME " ++ padNum 2 game ++ " ***\n" ++ "Goal: " ++ show goal ++ "\n" ++ "Assist #" ++ show assist ++ ": " @@ -104,7 +104,7 @@ recordAssistPrompt game goal assist = selectPlayerPrompt -- | Prompts for the player to assign penalty minutes to pMinPlayerPrompt :: Prompt -pMinPlayerPrompt = selectPlayerPrompt +pMinPlayerPrompt = selectActivePlayerPrompt "Assign penalty minutes to: " $ \case Nothing -> modify $ progMode.gameStateL.gamePMinsRecorded .~ True diff --git a/src/Mtlstats/Prompt/NewGame/GoalieInput.hs b/src/Mtlstats/Prompt/NewGame/GoalieInput.hs index 3e87aec..df5e6d4 100644 --- a/src/Mtlstats/Prompt/NewGame/GoalieInput.hs +++ b/src/Mtlstats/Prompt/NewGame/GoalieInput.hs @@ -36,7 +36,8 @@ import Mtlstats.Types -- | Prompts for a goalie who played in the game selectGameGoaliePrompt :: Prompt -selectGameGoaliePrompt = selectGoaliePrompt "Which goalie played this game: " $ +selectGameGoaliePrompt = selectActiveGoaliePrompt + "Which goalie played this game: " $ \case Nothing -> modify finishGoalieEntry Just n -> modify $ progMode.gameStateL.gameSelectedGoalie ?~ n diff --git a/src/Mtlstats/Types.hs b/src/Mtlstats/Types.hs index b64f46a..b5ad653 100644 --- a/src/Mtlstats/Types.hs +++ b/src/Mtlstats/Types.hs @@ -176,6 +176,7 @@ module Mtlstats.Types ( addGameStats, -- ** Player Helpers playerSearch, + activePlayerSearch, playerSearchExact, modifyPlayer, playerSummary, @@ -185,6 +186,7 @@ module Mtlstats.Types ( addPlayerStats, -- ** Goalie Helpers goalieSearch, + activeGoalieSearch, goalieSearchExact, goalieSummary, goalieIsActive, @@ -1003,6 +1005,23 @@ addGameStats s1 s2 = GameStats , _gmsGoalsAgainst = s1^.gmsGoalsAgainst + s2^.gmsGoalsAgainst } +-- | Searches through a list of players with a specified criteria +playerSearchWith + :: (Player -> Bool) + -- ^ The search criteria + -> String + -- ^ The search string + -> [Player] + -- ^ The list of players to search + -> [(Int, Player)] + -- ^ The matching players with their index numbers +playerSearchWith criteria sStr = + filter match . zip [0..] + where + match (_, p) + = map toUpper sStr `isInfixOf` map toUpper (p^.pName) + && criteria p + -- | Searches through a list of players playerSearch :: String @@ -1011,9 +1030,17 @@ playerSearch -- ^ The list of players to search -> [(Int, Player)] -- ^ The matching players with their index numbers -playerSearch sStr = - filter match . zip [0..] - where match (_, p) = map toUpper sStr `isInfixOf` map toUpper (p^.pName) +playerSearch = playerSearchWith $ const True + +-- | Searches through a list of players for an active player +activePlayerSearch + :: String + -- ^ The search string + -> [Player] + -- ^ The list of players to search + -> [(Int, Player)] + -- ^ The matching players with their index numbers +activePlayerSearch = playerSearchWith (^.pActive) -- | Searches for a player by exact match on name playerSearchExact @@ -1068,6 +1095,23 @@ addPlayerStats s1 s2 = newPlayerStats & psAssists .~ s1^.psAssists + s2^.psAssists & psPMin .~ s1^.psPMin + s2^.psPMin +-- | Searches a list of goalies with a search criteria +goalieSearchWith + :: (Goalie -> Bool) + -- ^ The search criteria + -> String + -- ^ The search string + -> [Goalie] + -- ^ The list to search + -> [(Int, Goalie)] + -- ^ The search results with their corresponding index numbers +goalieSearchWith criteria sStr = + filter match . zip [0..] + where + match (_, g) + = map toUpper sStr `isInfixOf` map toUpper (g^.gName) + && criteria g + -- | Searches a list of goalies goalieSearch :: String @@ -1076,9 +1120,17 @@ goalieSearch -- ^ The list to search -> [(Int, Goalie)] -- ^ The search results with their corresponding index numbers -goalieSearch sStr = - filter match . zip [0..] - where match (_, g) = map toUpper sStr `isInfixOf` map toUpper (g^.gName) +goalieSearch = goalieSearchWith $ const True + +-- | Searches a list of goalies for an active goalie +activeGoalieSearch + :: String + -- ^ The search string + -> [Goalie] + -- ^ The list to search + -> [(Int, Goalie)] + -- ^ The search results with their corresponding index numbers +activeGoalieSearch = goalieSearchWith (^.gActive) -- | Searches a list of goalies for an exact match goalieSearchExact diff --git a/test/TypesSpec.hs b/test/TypesSpec.hs index d88de00..e6d6340 100644 --- a/test/TypesSpec.hs +++ b/test/TypesSpec.hs @@ -73,6 +73,7 @@ spec = describe "Mtlstats.Types" $ do gmsPointsSpec addGameStatsSpec playerSearchSpec + activePlayerSearchSpec playerSearchExactSpec modifyPlayerSpec playerSummarySpec @@ -80,6 +81,7 @@ spec = describe "Mtlstats.Types" $ do psPointsSpec addPlayerStatsSpec goalieSearchSpec + activeGoalieSearchSpec goalieSearchExactSpec goalieSummarySpec goalieIsActiveSpec @@ -647,6 +649,19 @@ playerSearchSpec = describe "playerSearch" $ mapM_ , ( "x", [] ) ] +activePlayerSearchSpec :: Spec +activePlayerSearchSpec = describe "activePlayerSearch" $ mapM_ + (\(sStr, expected) -> context sStr $ + it ("should return " ++ show expected) $ let + ps = [joe, bob, steve & pActive .~ False] + in activePlayerSearch sStr ps `shouldBe` expected) + -- search, result + [ ( "joe", [(0, joe)] ) + , ( "o", [(0, joe), (1, bob)] ) + , ( "e", [(0, joe)] ) + , ( "x", [] ) + ] + playerSearchExactSpec :: Spec playerSearchExactSpec = describe "playerSearchExact" $ mapM_ (\(sStr, expected) -> context sStr $ @@ -778,6 +793,28 @@ goalieSearchSpec = describe "goalieSearch" $ do it "should return Bob" $ goalieSearch "bob" goalies `shouldBe` [result 1] +activeGoalieSearchSpec :: Spec +activeGoalieSearchSpec = describe "activeGoalieSearch" $ do + let + goalies = + [ newGoalie 2 "Joe" + , newGoalie 3 "Bob" + , newGoalie 5 "Steve" & gActive .~ False + ] + result n = (n, goalies!!n) + + context "partial match" $ + it "should return Joe" $ + activeGoalieSearch "e" goalies `shouldBe` [result 0] + + context "no match" $ + it "should return an empty list" $ + activeGoalieSearch "x" goalies `shouldBe` [] + + context "exact match" $ + it "should return Bob" $ + activeGoalieSearch "bob" goalies `shouldBe` [result 1] + goalieSearchExactSpec :: Spec goalieSearchExactSpec = describe "goalieSearchExact" $ do let