{-# LANGUAGE CPP                        #-}
{-# LANGUAGE DataKinds                  #-}
{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase                 #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE PatternSynonyms            #-}
{-# LANGUAGE PolyKinds                  #-}
{-# LANGUAGE RecordWildCards            #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE TypeOperators              #-}
{-# LANGUAGE ViewPatterns               #-}

-- |
-- Module      : Advent.Types
-- Copyright   : (c) Justin Le 2019
-- License     : BSD3
--
-- Maintainer  : justin@jle.im
-- Stability   : experimental
-- Portability : non-portable
--
-- Data types used for the underlying API.
--
-- @since 0.2.3.0
--

module Advent.Types (
  -- * Types
    Day(..)
  , Part(..)
  , SubmitInfo(..)
  , SubmitRes(..), showSubmitRes
  , PublicCode(..)
  , Leaderboard(..)
  , LeaderboardMember(..)
  , Rank(..)
  , DailyLeaderboard(..)
  , DailyLeaderboardMember(..)
  , GlobalLeaderboard(..)
  , GlobalLeaderboardMember(..)
  , NextDayTime(..)
  -- * Util
  , mkDay, mkDay_, dayInt
  , _DayInt, pattern DayInt
  , partInt
  , partChar
  , fullDailyBoard
  , dlbmCompleteTime
  , dlbmTime
  , challengeReleaseTime
  -- * Internal
  , parseSubmitRes
  ) where

import           Control.Applicative
import           Data.Aeson
import           Data.Aeson.Types
import           Data.Bifunctor
import           Data.Char
import           Data.Finite
import           Data.Functor.Classes
import           Data.List.NonEmpty         (NonEmpty(..))
import           Data.Map                   (Map)
import           Data.Maybe
import           Data.Profunctor
import           Data.Text                  (Text)
import           Data.Time hiding           (Day)
import           Data.Time.Clock.POSIX
import           Data.Typeable
import           Data.Void
import           GHC.Generics
import           Servant.API
import           Text.Printf
import           Text.Read                  (readMaybe)
import qualified Data.Map                   as M
import qualified Data.Text                  as T
import qualified Text.HTML.TagSoup          as H
import qualified Text.Megaparsec            as P
import qualified Text.Megaparsec.Char       as P
import qualified Text.Megaparsec.Char.Lexer as P
import qualified Web.FormUrlEncoded         as WF


#if !MIN_VERSION_base(4,16,0)
import           Data.Foldable              (asum)
#endif

#if !MIN_VERSION_base(4,11,0)
import           Data.Semigroup ((<>))
#endif

#if !MIN_VERSION_time(1,9,0)
import           Data.Time.LocalTime.Compat
#endif

-- | Describes the day: a number between 1 and 25 inclusive.
--
-- Represented by a 'Finite' ranging from 0 to 24 inclusive; you should
-- probably make one using the smart constructor 'mkDay'.
newtype Day = Day { Day -> Finite 25
dayFinite :: Finite 25 }
  deriving (Day -> Day -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Day -> Day -> Bool
$c/= :: Day -> Day -> Bool
== :: Day -> Day -> Bool
$c== :: Day -> Day -> Bool
Eq, Eq Day
Day -> Day -> Bool
Day -> Day -> Ordering
Day -> Day -> Day
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Day -> Day -> Day
$cmin :: Day -> Day -> Day
max :: Day -> Day -> Day
$cmax :: Day -> Day -> Day
>= :: Day -> Day -> Bool
$c>= :: Day -> Day -> Bool
> :: Day -> Day -> Bool
$c> :: Day -> Day -> Bool
<= :: Day -> Day -> Bool
$c<= :: Day -> Day -> Bool
< :: Day -> Day -> Bool
$c< :: Day -> Day -> Bool
compare :: Day -> Day -> Ordering
$ccompare :: Day -> Day -> Ordering
Ord, Int -> Day
Day -> Int
Day -> [Day]
Day -> Day
Day -> Day -> [Day]
Day -> Day -> Day -> [Day]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Day -> Day -> Day -> [Day]
$cenumFromThenTo :: Day -> Day -> Day -> [Day]
enumFromTo :: Day -> Day -> [Day]
$cenumFromTo :: Day -> Day -> [Day]
enumFromThen :: Day -> Day -> [Day]
$cenumFromThen :: Day -> Day -> [Day]
enumFrom :: Day -> [Day]
$cenumFrom :: Day -> [Day]
fromEnum :: Day -> Int
$cfromEnum :: Day -> Int
toEnum :: Int -> Day
$ctoEnum :: Int -> Day
pred :: Day -> Day
$cpred :: Day -> Day
succ :: Day -> Day
$csucc :: Day -> Day
Enum, Day
forall a. a -> a -> Bounded a
maxBound :: Day
$cmaxBound :: Day
minBound :: Day
$cminBound :: Day
Bounded, Typeable, forall x. Rep Day x -> Day
forall x. Day -> Rep Day x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Day x -> Day
$cfrom :: forall x. Day -> Rep Day x
Generic)

instance Show Day where
    showsPrec :: Int -> Day -> String -> String
showsPrec = forall a.
(Int -> a -> String -> String)
-> String -> Int -> a -> String -> String
showsUnaryWith (\Int
d -> forall a. Show a => Int -> a -> String -> String
showsPrec Int
d forall b c a. (b -> c) -> (a -> b) -> a -> c
. Day -> Integer
dayInt) String
"mkDay"

-- | A given part of a problem.  All Advent of Code challenges are
-- two-parts.
--
-- You can usually get 'Part1' (if it is already released) with a nonsense
-- session key, but 'Part2' always requires a valid session key.
data Part = Part1 | Part2
  deriving (Int -> Part -> String -> String
[Part] -> String -> String
Part -> String
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Part] -> String -> String
$cshowList :: [Part] -> String -> String
show :: Part -> String
$cshow :: Part -> String
showsPrec :: Int -> Part -> String -> String
$cshowsPrec :: Int -> Part -> String -> String
Show, ReadPrec [Part]
ReadPrec Part
Int -> ReadS Part
ReadS [Part]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Part]
$creadListPrec :: ReadPrec [Part]
readPrec :: ReadPrec Part
$creadPrec :: ReadPrec Part
readList :: ReadS [Part]
$creadList :: ReadS [Part]
readsPrec :: Int -> ReadS Part
$creadsPrec :: Int -> ReadS Part
Read, Part -> Part -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Part -> Part -> Bool
$c/= :: Part -> Part -> Bool
== :: Part -> Part -> Bool
$c== :: Part -> Part -> Bool
Eq, Eq Part
Part -> Part -> Bool
Part -> Part -> Ordering
Part -> Part -> Part
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Part -> Part -> Part
$cmin :: Part -> Part -> Part
max :: Part -> Part -> Part
$cmax :: Part -> Part -> Part
>= :: Part -> Part -> Bool
$c>= :: Part -> Part -> Bool
> :: Part -> Part -> Bool
$c> :: Part -> Part -> Bool
<= :: Part -> Part -> Bool
$c<= :: Part -> Part -> Bool
< :: Part -> Part -> Bool
$c< :: Part -> Part -> Bool
compare :: Part -> Part -> Ordering
$ccompare :: Part -> Part -> Ordering
Ord, Int -> Part
Part -> Int
Part -> [Part]
Part -> Part
Part -> Part -> [Part]
Part -> Part -> Part -> [Part]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Part -> Part -> Part -> [Part]
$cenumFromThenTo :: Part -> Part -> Part -> [Part]
enumFromTo :: Part -> Part -> [Part]
$cenumFromTo :: Part -> Part -> [Part]
enumFromThen :: Part -> Part -> [Part]
$cenumFromThen :: Part -> Part -> [Part]
enumFrom :: Part -> [Part]
$cenumFrom :: Part -> [Part]
fromEnum :: Part -> Int
$cfromEnum :: Part -> Int
toEnum :: Int -> Part
$ctoEnum :: Int -> Part
pred :: Part -> Part
$cpred :: Part -> Part
succ :: Part -> Part
$csucc :: Part -> Part
Enum, Part
forall a. a -> a -> Bounded a
maxBound :: Part
$cmaxBound :: Part
minBound :: Part
$cminBound :: Part
Bounded, Typeable, forall x. Rep Part x -> Part
forall x. Part -> Rep Part x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Part x -> Part
$cfrom :: forall x. Part -> Rep Part x
Generic)

-- | Info required to submit an answer for a part.
data SubmitInfo = SubmitInfo
    { SubmitInfo -> Part
siLevel  :: Part
    , SubmitInfo -> String
siAnswer :: String
    }
  deriving (Int -> SubmitInfo -> String -> String
[SubmitInfo] -> String -> String
SubmitInfo -> String
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [SubmitInfo] -> String -> String
$cshowList :: [SubmitInfo] -> String -> String
show :: SubmitInfo -> String
$cshow :: SubmitInfo -> String
showsPrec :: Int -> SubmitInfo -> String -> String
$cshowsPrec :: Int -> SubmitInfo -> String -> String
Show, ReadPrec [SubmitInfo]
ReadPrec SubmitInfo
Int -> ReadS SubmitInfo
ReadS [SubmitInfo]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [SubmitInfo]
$creadListPrec :: ReadPrec [SubmitInfo]
readPrec :: ReadPrec SubmitInfo
$creadPrec :: ReadPrec SubmitInfo
readList :: ReadS [SubmitInfo]
$creadList :: ReadS [SubmitInfo]
readsPrec :: Int -> ReadS SubmitInfo
$creadsPrec :: Int -> ReadS SubmitInfo
Read, SubmitInfo -> SubmitInfo -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SubmitInfo -> SubmitInfo -> Bool
$c/= :: SubmitInfo -> SubmitInfo -> Bool
== :: SubmitInfo -> SubmitInfo -> Bool
$c== :: SubmitInfo -> SubmitInfo -> Bool
Eq, Eq SubmitInfo
SubmitInfo -> SubmitInfo -> Bool
SubmitInfo -> SubmitInfo -> Ordering
SubmitInfo -> SubmitInfo -> SubmitInfo
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: SubmitInfo -> SubmitInfo -> SubmitInfo
$cmin :: SubmitInfo -> SubmitInfo -> SubmitInfo
max :: SubmitInfo -> SubmitInfo -> SubmitInfo
$cmax :: SubmitInfo -> SubmitInfo -> SubmitInfo
>= :: SubmitInfo -> SubmitInfo -> Bool
$c>= :: SubmitInfo -> SubmitInfo -> Bool
> :: SubmitInfo -> SubmitInfo -> Bool
$c> :: SubmitInfo -> SubmitInfo -> Bool
<= :: SubmitInfo -> SubmitInfo -> Bool
$c<= :: SubmitInfo -> SubmitInfo -> Bool
< :: SubmitInfo -> SubmitInfo -> Bool
$c< :: SubmitInfo -> SubmitInfo -> Bool
compare :: SubmitInfo -> SubmitInfo -> Ordering
$ccompare :: SubmitInfo -> SubmitInfo -> Ordering
Ord, Typeable, forall x. Rep SubmitInfo x -> SubmitInfo
forall x. SubmitInfo -> Rep SubmitInfo x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep SubmitInfo x -> SubmitInfo
$cfrom :: forall x. SubmitInfo -> Rep SubmitInfo x
Generic)

-- | The result of a submission.
data SubmitRes
    -- | Correct submission, including global rank (if reported, which
    -- usually happens if rank is under 1000)
    = SubCorrect (Maybe Integer)
    -- | Incorrect submission.  Contains the number of /seconds/ you must
    -- wait before trying again.  The 'Maybe' contains possible hints given
    -- by the server (usually "too low" or "too high").
    | SubIncorrect Int (Maybe String)
    -- | Submission was rejected because an incorrect submission was
    -- recently submitted.  Contains the number of /seconds/ you must wait
    -- before trying again.
    | SubWait Int
    -- | Submission was rejected because it was sent to an invalid question
    -- or part.  Usually happens if you submit to a part you have already
    -- answered or have not yet unlocked.
    | SubInvalid
    -- | Could not parse server response.  Contains parse error.
    | SubUnknown String
  deriving (Int -> SubmitRes -> String -> String
[SubmitRes] -> String -> String
SubmitRes -> String
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [SubmitRes] -> String -> String
$cshowList :: [SubmitRes] -> String -> String
show :: SubmitRes -> String
$cshow :: SubmitRes -> String
showsPrec :: Int -> SubmitRes -> String -> String
$cshowsPrec :: Int -> SubmitRes -> String -> String
Show, ReadPrec [SubmitRes]
ReadPrec SubmitRes
Int -> ReadS SubmitRes
ReadS [SubmitRes]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [SubmitRes]
$creadListPrec :: ReadPrec [SubmitRes]
readPrec :: ReadPrec SubmitRes
$creadPrec :: ReadPrec SubmitRes
readList :: ReadS [SubmitRes]
$creadList :: ReadS [SubmitRes]
readsPrec :: Int -> ReadS SubmitRes
$creadsPrec :: Int -> ReadS SubmitRes
Read, SubmitRes -> SubmitRes -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SubmitRes -> SubmitRes -> Bool
$c/= :: SubmitRes -> SubmitRes -> Bool
== :: SubmitRes -> SubmitRes -> Bool
$c== :: SubmitRes -> SubmitRes -> Bool
Eq, Eq SubmitRes
SubmitRes -> SubmitRes -> Bool
SubmitRes -> SubmitRes -> Ordering
SubmitRes -> SubmitRes -> SubmitRes
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: SubmitRes -> SubmitRes -> SubmitRes
$cmin :: SubmitRes -> SubmitRes -> SubmitRes
max :: SubmitRes -> SubmitRes -> SubmitRes
$cmax :: SubmitRes -> SubmitRes -> SubmitRes
>= :: SubmitRes -> SubmitRes -> Bool
$c>= :: SubmitRes -> SubmitRes -> Bool
> :: SubmitRes -> SubmitRes -> Bool
$c> :: SubmitRes -> SubmitRes -> Bool
<= :: SubmitRes -> SubmitRes -> Bool
$c<= :: SubmitRes -> SubmitRes -> Bool
< :: SubmitRes -> SubmitRes -> Bool
$c< :: SubmitRes -> SubmitRes -> Bool
compare :: SubmitRes -> SubmitRes -> Ordering
$ccompare :: SubmitRes -> SubmitRes -> Ordering
Ord, Typeable, forall x. Rep SubmitRes x -> SubmitRes
forall x. SubmitRes -> Rep SubmitRes x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep SubmitRes x -> SubmitRes
$cfrom :: forall x. SubmitRes -> Rep SubmitRes x
Generic)

-- | Member ID of public leaderboard (the first part of the registration
-- code, before the hyphen).  It can be found as the number in the URL:
--
-- > https://adventofcode.com/2019/leaderboard/private/view/12345
--
-- (the @12345@ above)
newtype PublicCode = PublicCode { PublicCode -> Integer
getPublicCode :: Integer }
  deriving (Int -> PublicCode -> String -> String
[PublicCode] -> String -> String
PublicCode -> String
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [PublicCode] -> String -> String
$cshowList :: [PublicCode] -> String -> String
show :: PublicCode -> String
$cshow :: PublicCode -> String
showsPrec :: Int -> PublicCode -> String -> String
$cshowsPrec :: Int -> PublicCode -> String -> String
Show, ReadPrec [PublicCode]
ReadPrec PublicCode
Int -> ReadS PublicCode
ReadS [PublicCode]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [PublicCode]
$creadListPrec :: ReadPrec [PublicCode]
readPrec :: ReadPrec PublicCode
$creadPrec :: ReadPrec PublicCode
readList :: ReadS [PublicCode]
$creadList :: ReadS [PublicCode]
readsPrec :: Int -> ReadS PublicCode
$creadsPrec :: Int -> ReadS PublicCode
Read, PublicCode -> PublicCode -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PublicCode -> PublicCode -> Bool
$c/= :: PublicCode -> PublicCode -> Bool
== :: PublicCode -> PublicCode -> Bool
$c== :: PublicCode -> PublicCode -> Bool
Eq, Eq PublicCode
PublicCode -> PublicCode -> Bool
PublicCode -> PublicCode -> Ordering
PublicCode -> PublicCode -> PublicCode
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: PublicCode -> PublicCode -> PublicCode
$cmin :: PublicCode -> PublicCode -> PublicCode
max :: PublicCode -> PublicCode -> PublicCode
$cmax :: PublicCode -> PublicCode -> PublicCode
>= :: PublicCode -> PublicCode -> Bool
$c>= :: PublicCode -> PublicCode -> Bool
> :: PublicCode -> PublicCode -> Bool
$c> :: PublicCode -> PublicCode -> Bool
<= :: PublicCode -> PublicCode -> Bool
$c<= :: PublicCode -> PublicCode -> Bool
< :: PublicCode -> PublicCode -> Bool
$c< :: PublicCode -> PublicCode -> Bool
compare :: PublicCode -> PublicCode -> Ordering
$ccompare :: PublicCode -> PublicCode -> Ordering
Ord, Typeable, forall x. Rep PublicCode x -> PublicCode
forall x. PublicCode -> Rep PublicCode x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep PublicCode x -> PublicCode
$cfrom :: forall x. PublicCode -> Rep PublicCode x
Generic)

-- | Leaderboard type, representing private leaderboard information.
data Leaderboard = LB
    { Leaderboard -> Integer
lbEvent   :: Integer                        -- ^ The year of the event
    , Leaderboard -> Integer
lbOwnerId :: Integer                        -- ^ The Member ID of the owner, or the public code
    , Leaderboard -> Map Integer LeaderboardMember
lbMembers :: Map Integer LeaderboardMember  -- ^ A map from member IDs to their leaderboard info
    }
  deriving (Int -> Leaderboard -> String -> String
[Leaderboard] -> String -> String
Leaderboard -> String
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Leaderboard] -> String -> String
$cshowList :: [Leaderboard] -> String -> String
show :: Leaderboard -> String
$cshow :: Leaderboard -> String
showsPrec :: Int -> Leaderboard -> String -> String
$cshowsPrec :: Int -> Leaderboard -> String -> String
Show, Leaderboard -> Leaderboard -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Leaderboard -> Leaderboard -> Bool
$c/= :: Leaderboard -> Leaderboard -> Bool
== :: Leaderboard -> Leaderboard -> Bool
$c== :: Leaderboard -> Leaderboard -> Bool
Eq, Eq Leaderboard
Leaderboard -> Leaderboard -> Bool
Leaderboard -> Leaderboard -> Ordering
Leaderboard -> Leaderboard -> Leaderboard
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Leaderboard -> Leaderboard -> Leaderboard
$cmin :: Leaderboard -> Leaderboard -> Leaderboard
max :: Leaderboard -> Leaderboard -> Leaderboard
$cmax :: Leaderboard -> Leaderboard -> Leaderboard
>= :: Leaderboard -> Leaderboard -> Bool
$c>= :: Leaderboard -> Leaderboard -> Bool
> :: Leaderboard -> Leaderboard -> Bool
$c> :: Leaderboard -> Leaderboard -> Bool
<= :: Leaderboard -> Leaderboard -> Bool
$c<= :: Leaderboard -> Leaderboard -> Bool
< :: Leaderboard -> Leaderboard -> Bool
$c< :: Leaderboard -> Leaderboard -> Bool
compare :: Leaderboard -> Leaderboard -> Ordering
$ccompare :: Leaderboard -> Leaderboard -> Ordering
Ord, Typeable, forall x. Rep Leaderboard x -> Leaderboard
forall x. Leaderboard -> Rep Leaderboard x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Leaderboard x -> Leaderboard
$cfrom :: forall x. Leaderboard -> Rep Leaderboard x
Generic)

-- | Leaderboard position for a given member.
data LeaderboardMember = LBM
    { LeaderboardMember -> Integer
lbmGlobalScore :: Integer                     -- ^ Global leaderboard score
    , LeaderboardMember -> Maybe Text
lbmName        :: Maybe Text                  -- ^ Username, if user specifies one
    , LeaderboardMember -> Integer
lbmLocalScore  :: Integer                     -- ^ Score for this leaderboard
    , LeaderboardMember -> Integer
lbmId          :: Integer                     -- ^ Member ID
    , LeaderboardMember -> Maybe UTCTime
lbmLastStarTS  :: Maybe UTCTime               -- ^ Time of last puzzle solved, if any
    , LeaderboardMember -> Int
lbmStars       :: Int                         -- ^ Number of stars (puzzle parts) solved
    , LeaderboardMember -> Map Day (Map Part UTCTime)
lbmCompletion  :: Map Day (Map Part UTCTime)  -- ^ Completion times of each day and puzzle part
    }
  deriving (Int -> LeaderboardMember -> String -> String
[LeaderboardMember] -> String -> String
LeaderboardMember -> String
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [LeaderboardMember] -> String -> String
$cshowList :: [LeaderboardMember] -> String -> String
show :: LeaderboardMember -> String
$cshow :: LeaderboardMember -> String
showsPrec :: Int -> LeaderboardMember -> String -> String
$cshowsPrec :: Int -> LeaderboardMember -> String -> String
Show, LeaderboardMember -> LeaderboardMember -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LeaderboardMember -> LeaderboardMember -> Bool
$c/= :: LeaderboardMember -> LeaderboardMember -> Bool
== :: LeaderboardMember -> LeaderboardMember -> Bool
$c== :: LeaderboardMember -> LeaderboardMember -> Bool
Eq, Eq LeaderboardMember
LeaderboardMember -> LeaderboardMember -> Bool
LeaderboardMember -> LeaderboardMember -> Ordering
LeaderboardMember -> LeaderboardMember -> LeaderboardMember
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: LeaderboardMember -> LeaderboardMember -> LeaderboardMember
$cmin :: LeaderboardMember -> LeaderboardMember -> LeaderboardMember
max :: LeaderboardMember -> LeaderboardMember -> LeaderboardMember
$cmax :: LeaderboardMember -> LeaderboardMember -> LeaderboardMember
>= :: LeaderboardMember -> LeaderboardMember -> Bool
$c>= :: LeaderboardMember -> LeaderboardMember -> Bool
> :: LeaderboardMember -> LeaderboardMember -> Bool
$c> :: LeaderboardMember -> LeaderboardMember -> Bool
<= :: LeaderboardMember -> LeaderboardMember -> Bool
$c<= :: LeaderboardMember -> LeaderboardMember -> Bool
< :: LeaderboardMember -> LeaderboardMember -> Bool
$c< :: LeaderboardMember -> LeaderboardMember -> Bool
compare :: LeaderboardMember -> LeaderboardMember -> Ordering
$ccompare :: LeaderboardMember -> LeaderboardMember -> Ordering
Ord, Typeable, forall x. Rep LeaderboardMember x -> LeaderboardMember
forall x. LeaderboardMember -> Rep LeaderboardMember x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep LeaderboardMember x -> LeaderboardMember
$cfrom :: forall x. LeaderboardMember -> Rep LeaderboardMember x
Generic)

-- | Ranking between 1 to 100, for daily and global leaderboards
--
-- Note that 'getRank' interanlly stores a number from 0 to 99, so be sure
-- to add or subtract accordingly if you want to display or parse it.
--
-- @since 0.2.3.0
newtype Rank = Rank { Rank -> Finite 100
getRank :: Finite 100 }
  deriving (Int -> Rank -> String -> String
[Rank] -> String -> String
Rank -> String
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Rank] -> String -> String
$cshowList :: [Rank] -> String -> String
show :: Rank -> String
$cshow :: Rank -> String
showsPrec :: Int -> Rank -> String -> String
$cshowsPrec :: Int -> Rank -> String -> String
Show, Rank -> Rank -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Rank -> Rank -> Bool
$c/= :: Rank -> Rank -> Bool
== :: Rank -> Rank -> Bool
$c== :: Rank -> Rank -> Bool
Eq, Eq Rank
Rank -> Rank -> Bool
Rank -> Rank -> Ordering
Rank -> Rank -> Rank
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Rank -> Rank -> Rank
$cmin :: Rank -> Rank -> Rank
max :: Rank -> Rank -> Rank
$cmax :: Rank -> Rank -> Rank
>= :: Rank -> Rank -> Bool
$c>= :: Rank -> Rank -> Bool
> :: Rank -> Rank -> Bool
$c> :: Rank -> Rank -> Bool
<= :: Rank -> Rank -> Bool
$c<= :: Rank -> Rank -> Bool
< :: Rank -> Rank -> Bool
$c< :: Rank -> Rank -> Bool
compare :: Rank -> Rank -> Ordering
$ccompare :: Rank -> Rank -> Ordering
Ord, Typeable, forall x. Rep Rank x -> Rank
forall x. Rank -> Rep Rank x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Rank x -> Rank
$cfrom :: forall x. Rank -> Rep Rank x
Generic)

-- | Single daily leaderboard position
--
-- @since 0.2.3.0
data DailyLeaderboardMember = DLBM
    { DailyLeaderboardMember -> Rank
dlbmRank      :: Rank
    -- | Time from midnight EST of December 1st for that event.  Use
    -- 'dlbmCompleteTime' to convert to an actual time for event
    -- completion, and 'dlbmTime' to get the time it took to solve.
    --
    -- @since 0.2.7.0
    , DailyLeaderboardMember -> NominalDiffTime
dlbmDecTime   :: NominalDiffTime      -- ^ time from midnight EST.
    , DailyLeaderboardMember -> Either Integer Text
dlbmUser      :: Either Integer Text
    , DailyLeaderboardMember -> Maybe Text
dlbmLink      :: Maybe Text
    , DailyLeaderboardMember -> Maybe Text
dlbmImage     :: Maybe Text
    , DailyLeaderboardMember -> Bool
dlbmSupporter :: Bool
    }
  deriving (Int -> DailyLeaderboardMember -> String -> String
[DailyLeaderboardMember] -> String -> String
DailyLeaderboardMember -> String
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [DailyLeaderboardMember] -> String -> String
$cshowList :: [DailyLeaderboardMember] -> String -> String
show :: DailyLeaderboardMember -> String
$cshow :: DailyLeaderboardMember -> String
showsPrec :: Int -> DailyLeaderboardMember -> String -> String
$cshowsPrec :: Int -> DailyLeaderboardMember -> String -> String
Show, DailyLeaderboardMember -> DailyLeaderboardMember -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DailyLeaderboardMember -> DailyLeaderboardMember -> Bool
$c/= :: DailyLeaderboardMember -> DailyLeaderboardMember -> Bool
== :: DailyLeaderboardMember -> DailyLeaderboardMember -> Bool
$c== :: DailyLeaderboardMember -> DailyLeaderboardMember -> Bool
Eq, Eq DailyLeaderboardMember
DailyLeaderboardMember -> DailyLeaderboardMember -> Bool
DailyLeaderboardMember -> DailyLeaderboardMember -> Ordering
DailyLeaderboardMember
-> DailyLeaderboardMember -> DailyLeaderboardMember
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: DailyLeaderboardMember
-> DailyLeaderboardMember -> DailyLeaderboardMember
$cmin :: DailyLeaderboardMember
-> DailyLeaderboardMember -> DailyLeaderboardMember
max :: DailyLeaderboardMember
-> DailyLeaderboardMember -> DailyLeaderboardMember
$cmax :: DailyLeaderboardMember
-> DailyLeaderboardMember -> DailyLeaderboardMember
>= :: DailyLeaderboardMember -> DailyLeaderboardMember -> Bool
$c>= :: DailyLeaderboardMember -> DailyLeaderboardMember -> Bool
> :: DailyLeaderboardMember -> DailyLeaderboardMember -> Bool
$c> :: DailyLeaderboardMember -> DailyLeaderboardMember -> Bool
<= :: DailyLeaderboardMember -> DailyLeaderboardMember -> Bool
$c<= :: DailyLeaderboardMember -> DailyLeaderboardMember -> Bool
< :: DailyLeaderboardMember -> DailyLeaderboardMember -> Bool
$c< :: DailyLeaderboardMember -> DailyLeaderboardMember -> Bool
compare :: DailyLeaderboardMember -> DailyLeaderboardMember -> Ordering
$ccompare :: DailyLeaderboardMember -> DailyLeaderboardMember -> Ordering
Ord, Typeable, forall x. Rep DailyLeaderboardMember x -> DailyLeaderboardMember
forall x. DailyLeaderboardMember -> Rep DailyLeaderboardMember x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep DailyLeaderboardMember x -> DailyLeaderboardMember
$cfrom :: forall x. DailyLeaderboardMember -> Rep DailyLeaderboardMember x
Generic)

-- | Turn a 'dlbmDecTime' field into a 'ZonedTime' for the actual
-- completion of the puzzle, based on the year and day of event.
--
-- @since 0.2.7.0
dlbmCompleteTime :: Integer -> Day -> NominalDiffTime -> ZonedTime
dlbmCompleteTime :: Integer -> Day -> NominalDiffTime -> ZonedTime
dlbmCompleteTime Integer
y Day
d NominalDiffTime
t = ZonedTime
r
    { zonedTimeToLocalTime :: LocalTime
zonedTimeToLocalTime = Day -> NominalDiffTime -> NominalDiffTime
dlbmTime Day
d NominalDiffTime
t NominalDiffTime -> LocalTime -> LocalTime
`addLocalTime` ZonedTime -> LocalTime
zonedTimeToLocalTime ZonedTime
r
    }
  where
    r :: ZonedTime
r = Integer -> Day -> ZonedTime
challengeReleaseTime Integer
y Day
d

-- | Turn a 'dlbmDecTime' field into a 'NominalDiffTime' representing the
-- actual amount of time taken to complete the puzzle.
--
-- @since 0.2.7.0
dlbmTime :: Day -> NominalDiffTime -> NominalDiffTime
dlbmTime :: Day -> NominalDiffTime -> NominalDiffTime
dlbmTime Day
d = forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Integer -> TimeOfDay -> NominalDiffTime
daysAndTimeOfDayToTime
           forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first (forall a. Num a => a -> a -> a
subtract (Day -> Integer
dayInt Day
d forall a. Num a => a -> a -> a
- Integer
1))
           forall b c a. (b -> c) -> (a -> b) -> a -> c
. NominalDiffTime -> (Integer, TimeOfDay)
timeToDaysAndTimeOfDay

-- | Daily leaderboard, containing Star 1 and Star 2 completions
--
-- @since 0.2.3.0
data DailyLeaderboard = DLB {
    DailyLeaderboard -> Map Rank DailyLeaderboardMember
dlbStar1 :: Map Rank DailyLeaderboardMember
  , DailyLeaderboard -> Map Rank DailyLeaderboardMember
dlbStar2 :: Map Rank DailyLeaderboardMember
  }
  deriving (Int -> DailyLeaderboard -> String -> String
[DailyLeaderboard] -> String -> String
DailyLeaderboard -> String
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [DailyLeaderboard] -> String -> String
$cshowList :: [DailyLeaderboard] -> String -> String
show :: DailyLeaderboard -> String
$cshow :: DailyLeaderboard -> String
showsPrec :: Int -> DailyLeaderboard -> String -> String
$cshowsPrec :: Int -> DailyLeaderboard -> String -> String
Show, DailyLeaderboard -> DailyLeaderboard -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DailyLeaderboard -> DailyLeaderboard -> Bool
$c/= :: DailyLeaderboard -> DailyLeaderboard -> Bool
== :: DailyLeaderboard -> DailyLeaderboard -> Bool
$c== :: DailyLeaderboard -> DailyLeaderboard -> Bool
Eq, Eq DailyLeaderboard
DailyLeaderboard -> DailyLeaderboard -> Bool
DailyLeaderboard -> DailyLeaderboard -> Ordering
DailyLeaderboard -> DailyLeaderboard -> DailyLeaderboard
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: DailyLeaderboard -> DailyLeaderboard -> DailyLeaderboard
$cmin :: DailyLeaderboard -> DailyLeaderboard -> DailyLeaderboard
max :: DailyLeaderboard -> DailyLeaderboard -> DailyLeaderboard
$cmax :: DailyLeaderboard -> DailyLeaderboard -> DailyLeaderboard
>= :: DailyLeaderboard -> DailyLeaderboard -> Bool
$c>= :: DailyLeaderboard -> DailyLeaderboard -> Bool
> :: DailyLeaderboard -> DailyLeaderboard -> Bool
$c> :: DailyLeaderboard -> DailyLeaderboard -> Bool
<= :: DailyLeaderboard -> DailyLeaderboard -> Bool
$c<= :: DailyLeaderboard -> DailyLeaderboard -> Bool
< :: DailyLeaderboard -> DailyLeaderboard -> Bool
$c< :: DailyLeaderboard -> DailyLeaderboard -> Bool
compare :: DailyLeaderboard -> DailyLeaderboard -> Ordering
$ccompare :: DailyLeaderboard -> DailyLeaderboard -> Ordering
Ord, Typeable, forall x. Rep DailyLeaderboard x -> DailyLeaderboard
forall x. DailyLeaderboard -> Rep DailyLeaderboard x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep DailyLeaderboard x -> DailyLeaderboard
$cfrom :: forall x. DailyLeaderboard -> Rep DailyLeaderboard x
Generic)

-- | Single global leaderboard position
--
-- @since 0.2.3.0
data GlobalLeaderboardMember = GLBM
    { GlobalLeaderboardMember -> Rank
glbmRank      :: Rank
    , GlobalLeaderboardMember -> Integer
glbmScore     :: Integer
    , GlobalLeaderboardMember -> Either Integer Text
glbmUser      :: Either Integer Text
    , GlobalLeaderboardMember -> Maybe Text
glbmLink      :: Maybe Text
    , GlobalLeaderboardMember -> Maybe Text
glbmImage     :: Maybe Text
    , GlobalLeaderboardMember -> Bool
glbmSupporter :: Bool
    }
  deriving (Int -> GlobalLeaderboardMember -> String -> String
[GlobalLeaderboardMember] -> String -> String
GlobalLeaderboardMember -> String
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [GlobalLeaderboardMember] -> String -> String
$cshowList :: [GlobalLeaderboardMember] -> String -> String
show :: GlobalLeaderboardMember -> String
$cshow :: GlobalLeaderboardMember -> String
showsPrec :: Int -> GlobalLeaderboardMember -> String -> String
$cshowsPrec :: Int -> GlobalLeaderboardMember -> String -> String
Show, GlobalLeaderboardMember -> GlobalLeaderboardMember -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: GlobalLeaderboardMember -> GlobalLeaderboardMember -> Bool
$c/= :: GlobalLeaderboardMember -> GlobalLeaderboardMember -> Bool
== :: GlobalLeaderboardMember -> GlobalLeaderboardMember -> Bool
$c== :: GlobalLeaderboardMember -> GlobalLeaderboardMember -> Bool
Eq, Eq GlobalLeaderboardMember
GlobalLeaderboardMember -> GlobalLeaderboardMember -> Bool
GlobalLeaderboardMember -> GlobalLeaderboardMember -> Ordering
GlobalLeaderboardMember
-> GlobalLeaderboardMember -> GlobalLeaderboardMember
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: GlobalLeaderboardMember
-> GlobalLeaderboardMember -> GlobalLeaderboardMember
$cmin :: GlobalLeaderboardMember
-> GlobalLeaderboardMember -> GlobalLeaderboardMember
max :: GlobalLeaderboardMember
-> GlobalLeaderboardMember -> GlobalLeaderboardMember
$cmax :: GlobalLeaderboardMember
-> GlobalLeaderboardMember -> GlobalLeaderboardMember
>= :: GlobalLeaderboardMember -> GlobalLeaderboardMember -> Bool
$c>= :: GlobalLeaderboardMember -> GlobalLeaderboardMember -> Bool
> :: GlobalLeaderboardMember -> GlobalLeaderboardMember -> Bool
$c> :: GlobalLeaderboardMember -> GlobalLeaderboardMember -> Bool
<= :: GlobalLeaderboardMember -> GlobalLeaderboardMember -> Bool
$c<= :: GlobalLeaderboardMember -> GlobalLeaderboardMember -> Bool
< :: GlobalLeaderboardMember -> GlobalLeaderboardMember -> Bool
$c< :: GlobalLeaderboardMember -> GlobalLeaderboardMember -> Bool
compare :: GlobalLeaderboardMember -> GlobalLeaderboardMember -> Ordering
$ccompare :: GlobalLeaderboardMember -> GlobalLeaderboardMember -> Ordering
Ord, Typeable, forall x. Rep GlobalLeaderboardMember x -> GlobalLeaderboardMember
forall x. GlobalLeaderboardMember -> Rep GlobalLeaderboardMember x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep GlobalLeaderboardMember x -> GlobalLeaderboardMember
$cfrom :: forall x. GlobalLeaderboardMember -> Rep GlobalLeaderboardMember x
Generic)

-- | Global leaderboard for the entire event
--
-- Under each 'Rank' is an 'Integer' for the score at that rank, as well as
-- a non-empty list of all members who achieved that rank and score.
--
-- @since 0.2.3.0
newtype GlobalLeaderboard = GLB {
    GlobalLeaderboard
-> Map Rank (Integer, NonEmpty GlobalLeaderboardMember)
glbMap :: Map Rank (Integer, NonEmpty GlobalLeaderboardMember)
  }
  deriving (Int -> GlobalLeaderboard -> String -> String
[GlobalLeaderboard] -> String -> String
GlobalLeaderboard -> String
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [GlobalLeaderboard] -> String -> String
$cshowList :: [GlobalLeaderboard] -> String -> String
show :: GlobalLeaderboard -> String
$cshow :: GlobalLeaderboard -> String
showsPrec :: Int -> GlobalLeaderboard -> String -> String
$cshowsPrec :: Int -> GlobalLeaderboard -> String -> String
Show, GlobalLeaderboard -> GlobalLeaderboard -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: GlobalLeaderboard -> GlobalLeaderboard -> Bool
$c/= :: GlobalLeaderboard -> GlobalLeaderboard -> Bool
== :: GlobalLeaderboard -> GlobalLeaderboard -> Bool
$c== :: GlobalLeaderboard -> GlobalLeaderboard -> Bool
Eq, Eq GlobalLeaderboard
GlobalLeaderboard -> GlobalLeaderboard -> Bool
GlobalLeaderboard -> GlobalLeaderboard -> Ordering
GlobalLeaderboard -> GlobalLeaderboard -> GlobalLeaderboard
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: GlobalLeaderboard -> GlobalLeaderboard -> GlobalLeaderboard
$cmin :: GlobalLeaderboard -> GlobalLeaderboard -> GlobalLeaderboard
max :: GlobalLeaderboard -> GlobalLeaderboard -> GlobalLeaderboard
$cmax :: GlobalLeaderboard -> GlobalLeaderboard -> GlobalLeaderboard
>= :: GlobalLeaderboard -> GlobalLeaderboard -> Bool
$c>= :: GlobalLeaderboard -> GlobalLeaderboard -> Bool
> :: GlobalLeaderboard -> GlobalLeaderboard -> Bool
$c> :: GlobalLeaderboard -> GlobalLeaderboard -> Bool
<= :: GlobalLeaderboard -> GlobalLeaderboard -> Bool
$c<= :: GlobalLeaderboard -> GlobalLeaderboard -> Bool
< :: GlobalLeaderboard -> GlobalLeaderboard -> Bool
$c< :: GlobalLeaderboard -> GlobalLeaderboard -> Bool
compare :: GlobalLeaderboard -> GlobalLeaderboard -> Ordering
$ccompare :: GlobalLeaderboard -> GlobalLeaderboard -> Ordering
Ord, Typeable, forall x. Rep GlobalLeaderboard x -> GlobalLeaderboard
forall x. GlobalLeaderboard -> Rep GlobalLeaderboard x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep GlobalLeaderboard x -> GlobalLeaderboard
$cfrom :: forall x. GlobalLeaderboard -> Rep GlobalLeaderboard x
Generic)

-- | The next day for a challenge in a given year, and also the number of
-- seconds until the challenge is released.
--
-- @since 0.2.8.0
data NextDayTime = NextDayTime Day Int
                 | NoNextDayTime
  deriving (Int -> NextDayTime -> String -> String
[NextDayTime] -> String -> String
NextDayTime -> String
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [NextDayTime] -> String -> String
$cshowList :: [NextDayTime] -> String -> String
show :: NextDayTime -> String
$cshow :: NextDayTime -> String
showsPrec :: Int -> NextDayTime -> String -> String
$cshowsPrec :: Int -> NextDayTime -> String -> String
Show, NextDayTime -> NextDayTime -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NextDayTime -> NextDayTime -> Bool
$c/= :: NextDayTime -> NextDayTime -> Bool
== :: NextDayTime -> NextDayTime -> Bool
$c== :: NextDayTime -> NextDayTime -> Bool
Eq, Eq NextDayTime
NextDayTime -> NextDayTime -> Bool
NextDayTime -> NextDayTime -> Ordering
NextDayTime -> NextDayTime -> NextDayTime
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: NextDayTime -> NextDayTime -> NextDayTime
$cmin :: NextDayTime -> NextDayTime -> NextDayTime
max :: NextDayTime -> NextDayTime -> NextDayTime
$cmax :: NextDayTime -> NextDayTime -> NextDayTime
>= :: NextDayTime -> NextDayTime -> Bool
$c>= :: NextDayTime -> NextDayTime -> Bool
> :: NextDayTime -> NextDayTime -> Bool
$c> :: NextDayTime -> NextDayTime -> Bool
<= :: NextDayTime -> NextDayTime -> Bool
$c<= :: NextDayTime -> NextDayTime -> Bool
< :: NextDayTime -> NextDayTime -> Bool
$c< :: NextDayTime -> NextDayTime -> Bool
compare :: NextDayTime -> NextDayTime -> Ordering
$ccompare :: NextDayTime -> NextDayTime -> Ordering
Ord, Typeable, forall x. Rep NextDayTime x -> NextDayTime
forall x. NextDayTime -> Rep NextDayTime x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep NextDayTime x -> NextDayTime
$cfrom :: forall x. NextDayTime -> Rep NextDayTime x
Generic)

instance ToHttpApiData Part where
    toUrlPiece :: Part -> Text
toUrlPiece = String -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. Part -> Int
partInt
    toQueryParam :: Part -> Text
toQueryParam = forall a. ToHttpApiData a => a -> Text
toUrlPiece

instance ToHttpApiData Day where
    toUrlPiece :: Day -> Text
toUrlPiece = String -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. Day -> Integer
dayInt
    toQueryParam :: Day -> Text
toQueryParam = forall a. ToHttpApiData a => a -> Text
toUrlPiece

instance ToHttpApiData PublicCode where
    toUrlPiece :: PublicCode -> Text
toUrlPiece   = (forall a. Semigroup a => a -> a -> a
<> Text
".json") forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. PublicCode -> Integer
getPublicCode
    toQueryParam :: PublicCode -> Text
toQueryParam = forall a. ToHttpApiData a => a -> Text
toUrlPiece

instance WF.ToForm SubmitInfo where
    toForm :: SubmitInfo -> Form
toForm = forall a.
(Generic a, GToForm a (Rep a)) =>
FormOptions -> a -> Form
WF.genericToForm WF.FormOptions
      { fieldLabelModifier :: String -> String
WF.fieldLabelModifier = Char -> String -> String
camelTo2 Char
'-' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> [a] -> [a]
drop Int
2 }

instance FromJSON Leaderboard where
    parseJSON :: Value -> Parser Leaderboard
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"Leaderboard" forall a b. (a -> b) -> a -> b
$ \Object
o ->
        Integer -> Integer -> Map Integer LeaderboardMember -> Leaderboard
LB forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall {a} {m :: * -> *}. (Read a, MonadFail m) => String -> m a
strInt forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"event"))
           forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"owner_id"
           forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"members"
      where
        strInt :: String -> m a
strInt String
t = case forall a. Read a => String -> Maybe a
readMaybe String
t of
          Maybe a
Nothing -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"bad int"
          Just a
i  -> forall (f :: * -> *) a. Applicative f => a -> f a
pure a
i

instance FromJSON LeaderboardMember where
    parseJSON :: Value -> Parser LeaderboardMember
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"LeaderboardMember" forall a b. (a -> b) -> a -> b
$ \Object
o ->
        Integer
-> Maybe Text
-> Integer
-> Integer
-> Maybe UTCTime
-> Int
-> Map Day (Map Part UTCTime)
-> LeaderboardMember
LBM forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"global_score"
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"name")
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"local_score"
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"id"
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (
                    (forall {m :: * -> *}. MonadFail m => String -> m UTCTime
fromEpochText   forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"last_star_ts"))
                forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (NominalDiffTime -> UTCTime
fromEpochNumber forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"last_star_ts"))
                )
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"stars"
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (do Map Day (Map Part Object)
cdl <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"completion_day_level"
                    (forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse) (\Object
c ->
                          (forall {m :: * -> *}. MonadFail m => String -> m UTCTime
fromEpochText   forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (Object
c forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"get_star_ts"))
                      forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (NominalDiffTime -> UTCTime
fromEpochNumber forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Object
c forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"get_star_ts"))
                      ) Map Day (Map Part Object)
cdl
                )
      where
        fromEpochText :: String -> m UTCTime
fromEpochText String
t = case forall a. Read a => String -> Maybe a
readMaybe String
t of
          Maybe Integer
Nothing -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"bad stamp"
          Just Integer
i  -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. NominalDiffTime -> UTCTime
posixSecondsToUTCTime forall a b. (a -> b) -> a -> b
$ forall a. Num a => Integer -> a
fromInteger Integer
i
        fromEpochNumber :: NominalDiffTime -> UTCTime
fromEpochNumber = NominalDiffTime -> UTCTime
posixSecondsToUTCTime

-- | @since 0.2.4.2
instance ToJSONKey Day where
    toJSONKey :: ToJSONKeyFunction Day
toJSONKey = forall a. (a -> Text) -> ToJSONKeyFunction a
toJSONKeyText forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. Day -> Integer
dayInt
instance FromJSONKey Day where
    fromJSONKey :: FromJSONKeyFunction Day
fromJSONKey = forall a. (Text -> Parser a) -> FromJSONKeyFunction a
FromJSONKeyTextParser (forall a. FromJSON a => Value -> Parser a
parseJSON forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Value
String)
-- | @since 0.2.4.2
instance ToJSONKey Part where
    toJSONKey :: ToJSONKeyFunction Part
toJSONKey = forall a. (a -> Text) -> ToJSONKeyFunction a
toJSONKeyText forall a b. (a -> b) -> a -> b
$ \case
      Part
Part1 -> Text
"1"
      Part
Part2 -> Text
"2"
instance FromJSONKey Part where
    fromJSONKey :: FromJSONKeyFunction Part
fromJSONKey = forall a. (Text -> Parser a) -> FromJSONKeyFunction a
FromJSONKeyTextParser (forall a. FromJSON a => Value -> Parser a
parseJSON forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Value
String)

-- | @since 0.2.4.2
instance ToJSON Part where
    toJSON :: Part -> Value
toJSON = Text -> Value
String forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\case Part
Part1 -> Text
"1"; Part
Part2 -> Text
"2")
instance FromJSON Part where
    parseJSON :: Value -> Parser Part
parseJSON = forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"Part" forall a b. (a -> b) -> a -> b
$ \case
      Text
"1" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure Part
Part1
      Text
"2" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure Part
Part2
      Text
_   -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Bad part"

-- | @since 0.2.4.2
instance ToJSON Day where
    toJSON :: Day -> Value
toJSON = Text -> Value
String forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. Day -> Integer
dayInt
instance FromJSON Day where
    parseJSON :: Value -> Parser Day
parseJSON = forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"Day" forall a b. (a -> b) -> a -> b
$ \Text
t ->
      case forall a. Read a => String -> Maybe a
readMaybe (Text -> String
T.unpack Text
t) of
        Maybe Integer
Nothing -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"No read day"
        Just Integer
i  -> case Integer -> Maybe Day
mkDay Integer
i of
          Maybe Day
Nothing -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Day out of range"
          Just Day
d  -> forall (f :: * -> *) a. Applicative f => a -> f a
pure Day
d

instance ToJSONKey Rank where
    toJSONKey :: ToJSONKeyFunction Rank
toJSONKey = forall a. (a -> Text) -> ToJSONKeyFunction a
toJSONKeyText forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Num a => a -> a -> a
+ Integer
1) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (n :: Nat). Finite n -> Integer
getFinite forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rank -> Finite 100
getRank
instance FromJSONKey Rank where
    fromJSONKey :: FromJSONKeyFunction Rank
fromJSONKey = forall a. (Text -> Parser a) -> FromJSONKeyFunction a
FromJSONKeyTextParser (forall a. FromJSON a => Value -> Parser a
parseJSON forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Value
String)

instance ToJSON Rank where
    toJSON :: Rank -> Value
toJSON = Text -> Value
String forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Num a => a -> a -> a
+ Integer
1) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (n :: Nat). Finite n -> Integer
getFinite forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rank -> Finite 100
getRank
instance FromJSON Rank where
    parseJSON :: Value -> Parser Rank
parseJSON = forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"Rank" forall a b. (a -> b) -> a -> b
$ \Text
t ->
      case forall a. Read a => String -> Maybe a
readMaybe (Text -> String
T.unpack Text
t) of
        Maybe Integer
Nothing -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"No read rank"
        Just Integer
i  -> case forall (n :: Nat). KnownNat n => Integer -> Maybe (Finite n)
packFinite (Integer
i forall a. Num a => a -> a -> a
- Integer
1) of
          Maybe (Finite 100)
Nothing -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Rank out of range"
          Just Finite 100
d  -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Finite 100 -> Rank
Rank Finite 100
d

instance ToJSON DailyLeaderboard where
    toJSON :: DailyLeaderboard -> Value
toJSON = forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON Options
defaultOptions
        { fieldLabelModifier :: String -> String
fieldLabelModifier = Char -> String -> String
camelTo2 Char
'-' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> [a] -> [a]
drop Int
3 }
instance FromJSON DailyLeaderboard where
    parseJSON :: Value -> Parser DailyLeaderboard
parseJSON = forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON Options
defaultOptions
        { fieldLabelModifier :: String -> String
fieldLabelModifier = Char -> String -> String
camelTo2 Char
'-' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> [a] -> [a]
drop Int
3 }

instance ToJSON GlobalLeaderboard where
    toJSON :: GlobalLeaderboard -> Value
toJSON = forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON Options
defaultOptions
        { fieldLabelModifier :: String -> String
fieldLabelModifier = Char -> String -> String
camelTo2 Char
'-' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> [a] -> [a]
drop Int
3 }
instance FromJSON GlobalLeaderboard where
    parseJSON :: Value -> Parser GlobalLeaderboard
parseJSON = forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON Options
defaultOptions
        { fieldLabelModifier :: String -> String
fieldLabelModifier = Char -> String -> String
camelTo2 Char
'-' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> [a] -> [a]
drop Int
3 }

instance ToJSON DailyLeaderboardMember where
    toJSON :: DailyLeaderboardMember -> Value
toJSON = forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON Options
defaultOptions
        { fieldLabelModifier :: String -> String
fieldLabelModifier = Char -> String -> String
camelTo2 Char
'-' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> [a] -> [a]
drop Int
4 }
instance FromJSON DailyLeaderboardMember where
    parseJSON :: Value -> Parser DailyLeaderboardMember
parseJSON = forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON Options
defaultOptions
        { fieldLabelModifier :: String -> String
fieldLabelModifier = Char -> String -> String
camelTo2 Char
'-' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> [a] -> [a]
drop Int
4 }

instance ToJSON GlobalLeaderboardMember where
    toJSON :: GlobalLeaderboardMember -> Value
toJSON = forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON Options
defaultOptions
        { fieldLabelModifier :: String -> String
fieldLabelModifier = Char -> String -> String
camelTo2 Char
'-' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> [a] -> [a]
drop Int
4 }
instance FromJSON GlobalLeaderboardMember where
    parseJSON :: Value -> Parser GlobalLeaderboardMember
parseJSON = forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON Options
defaultOptions
        { fieldLabelModifier :: String -> String
fieldLabelModifier = Char -> String -> String
camelTo2 Char
'-' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> [a] -> [a]
drop Int
4 }

-- | Parse 'T.Text' into a 'SubmitRes'.
parseSubmitRes :: Text -> SubmitRes
parseSubmitRes :: Text -> SubmitRes
parseSubmitRes = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (String -> SubmitRes
SubUnknown forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s e.
(VisualStream s, TraversableStream s, ShowErrorComponent e) =>
ParseErrorBundle s e -> String
P.errorBundlePretty) forall a. a -> a
id
               forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e s a.
Parsec e s a -> String -> s -> Either (ParseErrorBundle s e) a
P.runParser ParsecT Void Text Identity SubmitRes
choices String
"Submission Response"
               forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Monoid a => [a] -> a
mconcat
               forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe forall {a}. Tag a -> Maybe a
deTag
               forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall str. StringLike str => str -> [Tag str]
H.parseTags
  where
    deTag :: Tag a -> Maybe a
deTag (H.TagText a
t) = forall a. a -> Maybe a
Just a
t
    deTag Tag a
_             = forall a. Maybe a
Nothing
    choices :: ParsecT Void Text Identity SubmitRes
choices             = forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Alternative f) =>
t (f a) -> f a
asum [ forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
P.try ParsecT Void Text Identity SubmitRes
parseCorrect   forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> String -> m a
P.<?> String
"Correct"
                               , forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
P.try ParsecT Void Text Identity SubmitRes
parseIncorrect forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> String -> m a
P.<?> String
"Incorrect"
                               , forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
P.try ParsecT Void Text Identity SubmitRes
parseWait      forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> String -> m a
P.<?> String
"Wait"
                               ,       ParsecT Void Text Identity SubmitRes
parseInvalid   forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> String -> m a
P.<?> String
"Invalid"
                               ]
    parseCorrect :: P.Parsec Void Text SubmitRes
    parseCorrect :: ParsecT Void Text Identity SubmitRes
parseCorrect = do
      [Token Text]
_ <- forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
P.manyTill forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
P.anySingle (forall e s (m :: * -> *).
(MonadParsec e s m, FoldCase (Tokens s)) =>
Tokens s -> m (Tokens s)
P.string' Tokens Text
"that's the right answer") forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> String -> m a
P.<?> String
"Right answer"
      Maybe Integer
r <- forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> String -> m a
P.<?> String
"Rank") forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
P.try forall a b. (a -> b) -> a -> b
$ do
        forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
P.manyTill forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
P.anySingle (forall e s (m :: * -> *).
(MonadParsec e s m, FoldCase (Tokens s)) =>
Tokens s -> m (Tokens s)
P.string' Tokens Text
"rank")
          forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall (m :: * -> *) a. MonadPlus m => m a -> m ()
P.skipMany (forall e s (m :: * -> *).
MonadParsec e s m =>
(Token s -> Bool) -> m (Token s)
P.satisfy (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isDigit))
        forall e s (m :: * -> *) a.
(MonadParsec e s m, Token s ~ Char, Num a) =>
m a
P.decimal
      forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Maybe Integer -> SubmitRes
SubCorrect Maybe Integer
r
    parseIncorrect :: ParsecT Void Text Identity SubmitRes
parseIncorrect = do
      [Token Text]
_ <- forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
P.manyTill forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
P.anySingle (forall e s (m :: * -> *).
(MonadParsec e s m, FoldCase (Tokens s)) =>
Tokens s -> m (Tokens s)
P.string' Tokens Text
"that's not the right answer") forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> String -> m a
P.<?> String
"Not the right answer"
      Maybe Text
hint <- forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> String -> m a
P.<?> String
"Hint") forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
P.try forall a b. (a -> b) -> a -> b
$ do
        forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
P.manyTill forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
P.anySingle ParsecT Void Text Identity Text
"your answer is" forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
P.space1
        forall e s (m :: * -> *).
MonadParsec e s m =>
Maybe String -> (Token s -> Bool) -> m (Tokens s)
P.takeWhile1P (forall a. a -> Maybe a
Just String
"dot") (forall a. Eq a => a -> a -> Bool
/= Char
'.')
      forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
P.manyTill forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
P.anySingle (forall e s (m :: * -> *).
(MonadParsec e s m, FoldCase (Tokens s)) =>
Tokens s -> m (Tokens s)
P.string' Tokens Text
"wait") forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
P.space1
      Int
waitAmt <- (Int
1 forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall e s (m :: * -> *).
(MonadParsec e s m, FoldCase (Tokens s)) =>
Tokens s -> m (Tokens s)
P.string' Tokens Text
"one") forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall e s (m :: * -> *) a.
(MonadParsec e s m, Token s ~ Char, Num a) =>
m a
P.decimal
      forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Int -> Maybe String -> SubmitRes
SubIncorrect (Int
waitAmt forall a. Num a => a -> a -> a
* Int
60) (Text -> String
T.unpack forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Text
hint)
    parseWait :: ParsecT Void Text Identity SubmitRes
parseWait = do
      [Token Text]
_ <- forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
P.manyTill forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
P.anySingle (forall e s (m :: * -> *).
(MonadParsec e s m, FoldCase (Tokens s)) =>
Tokens s -> m (Tokens s)
P.string' Tokens Text
"an answer too recently") forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> String -> m a
P.<?> String
"An answer too recently"
      forall (m :: * -> *) a. MonadPlus m => m a -> m ()
P.skipMany (forall e s (m :: * -> *).
MonadParsec e s m =>
(Token s -> Bool) -> m (Token s)
P.satisfy (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isDigit))
      Maybe Int
m <- forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> String -> m a
P.<?> String
"Delay minutes") forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
P.try forall a b. (a -> b) -> a -> b
$
              forall e s (m :: * -> *) a.
(MonadParsec e s m, Token s ~ Char, Num a) =>
m a
P.decimal forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
P.char Char
'm' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
P.space1
      Int
s <- forall e s (m :: * -> *) a.
(MonadParsec e s m, Token s ~ Char, Num a) =>
m a
P.decimal forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
P.char Char
's' forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> String -> m a
P.<?> String
"Delay seconds"
      forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> SubmitRes
SubWait forall a b. (a -> b) -> a -> b
$ forall b a. b -> (a -> b) -> Maybe a -> b
maybe Int
0 (forall a. Num a => a -> a -> a
* Int
60) Maybe Int
m forall a. Num a => a -> a -> a
+ Int
s
    parseInvalid :: ParsecT Void Text Identity SubmitRes
parseInvalid = SubmitRes
SubInvalid forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
P.manyTill forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
P.anySingle (forall e s (m :: * -> *).
(MonadParsec e s m, FoldCase (Tokens s)) =>
Tokens s -> m (Tokens s)
P.string' Tokens Text
"solving the right level")

-- | Pretty-print a 'SubmitRes'
showSubmitRes :: SubmitRes -> String
showSubmitRes :: SubmitRes -> String
showSubmitRes = \case
    SubCorrect Maybe Integer
Nothing    -> String
"Correct"
    SubCorrect (Just Integer
r)   -> forall r. PrintfType r => String -> r
printf String
"Correct (Rank %d)" Integer
r
    SubIncorrect Int
i Maybe String
Nothing  -> forall r. PrintfType r => String -> r
printf String
"Incorrect (%d minute wait)" (Int
i forall a. Integral a => a -> a -> a
`div` Int
60)
    SubIncorrect Int
i (Just String
h) -> forall r. PrintfType r => String -> r
printf String
"Incorrect (%s) (%d minute wait)" String
h (Int
i forall a. Integral a => a -> a -> a
`div` Int
60)
    SubWait Int
i             -> let (Int
m,Int
s) = Int
i forall a. Integral a => a -> a -> (a, a)
`divMod` Int
60
                             in   forall r. PrintfType r => String -> r
printf String
"Wait (%d min %d sec wait)"  Int
m Int
s
    SubmitRes
SubInvalid            -> String
"Invalid"
    SubUnknown String
r          -> forall r. PrintfType r => String -> r
printf String
"Unknown (%s)" String
r

-- | Convert a @'Finite' 25@ day into a day integer (1 - 25).  Inverse of
-- 'mkDay'.
dayInt :: Day -> Integer
dayInt :: Day -> Integer
dayInt = (forall a. Num a => a -> a -> a
+ Integer
1) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (n :: Nat). Finite n -> Integer
getFinite forall b c a. (b -> c) -> (a -> b) -> a -> c
. Day -> Finite 25
dayFinite

-- | Convert a 'Part' to an 'Int'.
partInt :: Part -> Int
partInt :: Part -> Int
partInt Part
Part1 = Int
1
partInt Part
Part2 = Int
2

-- | Construct a 'Day' from a day integer (1 - 25).  If input is out of
-- range, 'Nothing' is returned.  See 'mkDay_' for an unsafe version useful
-- for literals.
--
-- Inverse of 'dayInt'.
mkDay :: Integer -> Maybe Day
mkDay :: Integer -> Maybe Day
mkDay = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Finite 25 -> Day
Day forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (n :: Nat). KnownNat n => Integer -> Maybe (Finite n)
packFinite forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => a -> a -> a
subtract Integer
1

-- | Construct a @'Finite' 25@ (the type of a Day) from a day
-- integer (1 - 25).  Is undefined if input is out of range.  Can be useful
-- for compile-time literals, like @'mkDay_' 4@
--
-- Inverse of 'dayInt'.
mkDay_ :: Integer -> Day
mkDay_ :: Integer -> Day
mkDay_ = forall a. a -> Maybe a -> a
fromMaybe forall {a}. a
e forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Maybe Day
mkDay
  where
    e :: a
e = forall a. String -> a
errorWithoutStackTrace String
"Advent.mkDay_: Date out of range (1 - 25)"

-- | This is a @Prism' 'Integer' 'Day'@ , to treat an 'Integer' as if it
-- were a 'Day'.
--
-- @since 0.2.4.0
_DayInt :: (Choice p, Applicative f) => p Day (f Day) -> p Integer (f Integer)
_DayInt :: forall (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p Day (f Day) -> p Integer (f Integer)
_DayInt = forall (p :: * -> * -> *) a b c d.
Profunctor p =>
(a -> b) -> (c -> d) -> p b c -> p a d
dimap Integer -> Either Integer Day
a Either Integer (f Day) -> f Integer
b forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) a b c.
Choice p =>
p a b -> p (Either c a) (Either c b)
right'
  where
    a :: Integer -> Either Integer Day
a Integer
i = forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall a b. a -> Either a b
Left Integer
i) forall a b. b -> Either a b
Right forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Maybe Day
mkDay forall a b. (a -> b) -> a -> b
$ Integer
i
    b :: Either Integer (f Day) -> f Integer
b   = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Day -> Integer
dayInt)

-- | Pattern synonym allowing you to match on an 'Integer' as if it were
-- a 'Day':
--
-- @
-- case myInt of
--   DayInt d -> ...
--   _        -> ...
-- @
--
-- Will fail if the integer is out of bounds (outside of 1-25)
--
-- @since 0.2.4.0
pattern DayInt :: Day -> Integer
pattern $bDayInt :: Day -> Integer
$mDayInt :: forall {r}. Integer -> (Day -> r) -> ((# #) -> r) -> r
DayInt d <- (mkDay->Just d)
  where
    DayInt Day
d = Day -> Integer
dayInt Day
d

-- | A character associated with a given part.  'Part1' is associated with
-- @\'a\'@, and 'Part2' is associated with @\'b\'@
partChar :: Part -> Char
partChar :: Part -> Char
partChar Part
Part1 = Char
'a'
partChar Part
Part2 = Char
'b'

-- | Check if a 'DailyLeaderboard' is filled up or not.
--
-- @since 0.2.4.0
fullDailyBoard
    :: DailyLeaderboard
    -> Bool
fullDailyBoard :: DailyLeaderboard -> Bool
fullDailyBoard DLB{Map Rank DailyLeaderboardMember
dlbStar2 :: Map Rank DailyLeaderboardMember
dlbStar1 :: Map Rank DailyLeaderboardMember
dlbStar2 :: DailyLeaderboard -> Map Rank DailyLeaderboardMember
dlbStar1 :: DailyLeaderboard -> Map Rank DailyLeaderboardMember
..} = (forall k a. Map k a -> Int
M.size Map Rank DailyLeaderboardMember
dlbStar1 forall a. Num a => a -> a -> a
+ forall k a. Map k a -> Int
M.size Map Rank DailyLeaderboardMember
dlbStar2) forall a. Ord a => a -> a -> Bool
>= Int
200

-- | Prompt release time.
--
-- Changed from 'UTCTime' to 'ZonedTime' in v0.2.7.0.  To use as
-- a 'UTCTime', use 'zonedTimeToUTC'.
challengeReleaseTime
    :: Integer              -- ^ year
    -> Day                  -- ^ day
    -> ZonedTime
challengeReleaseTime :: Integer -> Day -> ZonedTime
challengeReleaseTime Integer
y Day
d = ZonedTime
    { zonedTimeToLocalTime :: LocalTime
zonedTimeToLocalTime = LocalTime
        { localDay :: Day
localDay       = Integer -> Int -> Int -> Day
fromGregorian Integer
y Int
12 (forall a b. (Integral a, Num b) => a -> b
fromIntegral (Day -> Integer
dayInt Day
d))
        , localTimeOfDay :: TimeOfDay
localTimeOfDay = TimeOfDay
midnight
        }
    , zonedTimeZone :: TimeZone
zonedTimeZone = forall a. Read a => String -> a
read String
"EST"
    }