diff --git a/src/Mtlstats/Types.hs b/src/Mtlstats/Types.hs index f16d84c..a885370 100644 --- a/src/Mtlstats/Types.hs +++ b/src/Mtlstats/Types.hs @@ -4,6 +4,8 @@ module Mtlstats.Types ( -- * Types Player (..), PlayerStats (..), + Goalie (..), + GoalieStats (..), -- * Lenses -- ** Player Lenses pNumber, @@ -15,9 +17,24 @@ module Mtlstats.Types ( psGoals, psAssists, psPMin, + -- ** Goalie Lenses + gNumber, + gName, + gYtd, + gLifetime, + -- ** GoalieStats Lenses + gsGames, + gsMinsPlayed, + gsGoalsAllowed, + gsGoalsAgainst, + gsWins, + gsLosses, + gsTies, -- * Constructors newPlayer, newPlayerStats, + newGoalie, + newGoalieStats, -- * Helper functions pPoints ) where @@ -101,8 +118,89 @@ instance ToJSON PlayerStats where "assists" .= a <> "penalty_mins" .= pm +-- | Represents a goalie +data Goalie = Goalie + { _gNumber :: Int + -- ^ The goalie's number + , _gName :: String + -- ^ The goalie's name + , _gYtd :: GoalieStats + -- ^ The goalie's year-to-date stats + , _gLifetime :: GoalieStats + -- ^ The goalie's lifetime stats + } 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 +data GoalieStats = GoalieStats + { _gsGames :: Int + -- ^ The number of games played + , _gsMinsPlayed :: Int + -- ^ The number of minutes played + , _gsGoalsAllowed :: Int + -- ^ The number of goals allowed + , _gsGoalsAgainst :: Int + -- ^ The number of goals against + , _gsWins :: Int + -- ^ The number of wins + , _gsLosses :: Int + -- ^ The number of losses + , _gsTies :: Int + -- ^ The number of ties + } deriving (Eq, Show) + +instance FromJSON GoalieStats where + parseJSON = withObject "GoalieStats" $ \v -> GoalieStats + <$> v .: "games" + <*> v .: "mins_played" + <*> v .: "goals_allowed" + <*> v .: "goals_against" + <*> v .: "wins" + <*> v .: "losses" + <*> v .: "ties" + +instance ToJSON GoalieStats where + toJSON (GoalieStats g m al ag w l t) = object + [ "games" .= g + , "mins_played" .= m + , "goals_allowed" .= al + , "goals_against" .= ag + , "wins" .= w + , "losses" .= l + , "ties" .= t + ] + toEncoding (GoalieStats g m al ag w l t) = pairs $ + "games" .= g <> + "mins_played" .= m <> + "goals_allowed" .= al <> + "goals_against" .= ag <> + "wins" .= w <> + "losses" .= l <> + "ties" .= t + makeLenses ''Player makeLenses ''PlayerStats +makeLenses ''Goalie +makeLenses ''GoalieStats -- | Constructor for a 'Player' newPlayer @@ -129,6 +227,32 @@ newPlayerStats = PlayerStats , _psPMin = 0 } +-- | Constructor for a 'Goalie' +newGoalie + :: Int + -- ^ The goalie's number + -> String + -- ^ The goalie's name + -> Goalie +newGoalie num name = Goalie + { _gNumber = num + , _gName = name + , _gYtd = newGoalieStats + , _gLifetime = newGoalieStats + } + +-- | Constructor for a 'GoalieStats' value +newGoalieStats :: GoalieStats +newGoalieStats = GoalieStats + { _gsGames = 0 + , _gsMinsPlayed = 0 + , _gsGoalsAllowed = 0 + , _gsGoalsAgainst = 0 + , _gsWins = 0 + , _gsLosses = 0 + , _gsTies = 0 + } + -- | Calculates a player's points pPoints :: PlayerStats -> Int pPoints s = s^.psGoals + s^.psAssists diff --git a/test/TypesSpec.hs b/test/TypesSpec.hs index 6b47455..34833a9 100644 --- a/test/TypesSpec.hs +++ b/test/TypesSpec.hs @@ -13,6 +13,7 @@ spec :: Spec spec = describe "Mtlstats.Types" $ do pPointsSpec playerSpec + goalieSpec pPointsSpec :: Spec pPointsSpec = describe "pPoints" $ mapM_ @@ -43,6 +44,17 @@ playerSpec = describe "Player" $ do it "should encode" $ decode (encode player) `shouldBe` Just player +goalieSpec :: Spec +goalieSpec = describe "Goalie" $ do + + describe "decode" $ + it "should decode" $ + decode goalieJSON `shouldBe` Just goalie + + describe "encode" $ + it "should encode" $ + decode (encode goalie) `shouldBe` Just goalie + player :: Player player = newPlayer 1 "Joe" "centre" & pYtd . psGoals .~ 2 @@ -52,6 +64,23 @@ player = newPlayer 1 "Joe" "centre" & pLifetime . psAssists .~ 6 & pLifetime . psPMin .~ 7 +goalie :: Goalie +goalie = newGoalie 1 "Joe" + & gYtd . gsGames .~ 2 + & gYtd . gsMinsPlayed .~ 3 + & gYtd . gsGoalsAllowed .~ 4 + & gYtd . gsGoalsAgainst .~ 5 + & gYtd . gsWins .~ 6 + & gYtd . gsLosses .~ 7 + & gYtd . gsTies .~ 8 + & gLifetime . gsGames .~ 9 + & gLifetime . gsMinsPlayed .~ 10 + & gLifetime . gsGoalsAllowed .~ 11 + & gLifetime . gsGoalsAgainst .~ 12 + & gLifetime . gsWins .~ 13 + & gLifetime . gsLosses .~ 14 + & gLifetime . gsTies .~ 15 + playerJSON :: ByteString playerJSON = [r| { "number": 1 @@ -68,3 +97,27 @@ playerJSON = [r| , "penalty_mins": 7 } }|] + +goalieJSON :: ByteString +goalieJSON = [r| + { "number": 1 + , "name": "Joe" + , "ytd": + { "games": 2 + , "mins_played": 3 + , "goals_allowed": 4 + , "goals_against": 5 + , "wins": 6 + , "losses": 7 + , "ties": 8 + } + , "lifetime": + { "games": 9 + , "mins_played": 10 + , "goals_allowed": 11 + , "goals_against": 12 + , "wins": 13 + , "losses": 14 + , "ties": 15 + } + }|]