{-# LANGUAGE DerivingStrategies #-}

-- | The vocabulary shared by the whole package: the four grades a reviewer can
-- give a card, and the two-variable memory state FSRS tracks for it.
module FSRS.Types
  ( -- * Ratings
    Rating (..)
  , allRatings
  , ratingToInt
  , ratingFromInt

    -- * Memory state
  , MemoryState (..)

    -- * Type synonyms
  , Stability
  , Difficulty
  , Retrievability
  , Days
  ) where

-- | How well the card was recalled. The 'Enum' instance counts from @0@; the
-- FSRS papers and reference implementations number the ratings from @1@, which
-- is what 'ratingToInt' gives you.
data Rating
  = Again
  | Hard
  | Good
  | Easy
  deriving stock (Rating -> Rating -> Bool
(Rating -> Rating -> Bool)
-> (Rating -> Rating -> Bool) -> Eq Rating
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Rating -> Rating -> Bool
== :: Rating -> Rating -> Bool
$c/= :: Rating -> Rating -> Bool
/= :: Rating -> Rating -> Bool
Eq, Eq Rating
Eq Rating =>
(Rating -> Rating -> Ordering)
-> (Rating -> Rating -> Bool)
-> (Rating -> Rating -> Bool)
-> (Rating -> Rating -> Bool)
-> (Rating -> Rating -> Bool)
-> (Rating -> Rating -> Rating)
-> (Rating -> Rating -> Rating)
-> Ord Rating
Rating -> Rating -> Bool
Rating -> Rating -> Ordering
Rating -> Rating -> Rating
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
$ccompare :: Rating -> Rating -> Ordering
compare :: Rating -> Rating -> Ordering
$c< :: Rating -> Rating -> Bool
< :: Rating -> Rating -> Bool
$c<= :: Rating -> Rating -> Bool
<= :: Rating -> Rating -> Bool
$c> :: Rating -> Rating -> Bool
> :: Rating -> Rating -> Bool
$c>= :: Rating -> Rating -> Bool
>= :: Rating -> Rating -> Bool
$cmax :: Rating -> Rating -> Rating
max :: Rating -> Rating -> Rating
$cmin :: Rating -> Rating -> Rating
min :: Rating -> Rating -> Rating
Ord, Int -> Rating -> ShowS
[Rating] -> ShowS
Rating -> String
(Int -> Rating -> ShowS)
-> (Rating -> String) -> ([Rating] -> ShowS) -> Show Rating
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Rating -> ShowS
showsPrec :: Int -> Rating -> ShowS
$cshow :: Rating -> String
show :: Rating -> String
$cshowList :: [Rating] -> ShowS
showList :: [Rating] -> ShowS
Show, ReadPrec [Rating]
ReadPrec Rating
Int -> ReadS Rating
ReadS [Rating]
(Int -> ReadS Rating)
-> ReadS [Rating]
-> ReadPrec Rating
-> ReadPrec [Rating]
-> Read Rating
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Rating
readsPrec :: Int -> ReadS Rating
$creadList :: ReadS [Rating]
readList :: ReadS [Rating]
$creadPrec :: ReadPrec Rating
readPrec :: ReadPrec Rating
$creadListPrec :: ReadPrec [Rating]
readListPrec :: ReadPrec [Rating]
Read, Int -> Rating
Rating -> Int
Rating -> [Rating]
Rating -> Rating
Rating -> Rating -> [Rating]
Rating -> Rating -> Rating -> [Rating]
(Rating -> Rating)
-> (Rating -> Rating)
-> (Int -> Rating)
-> (Rating -> Int)
-> (Rating -> [Rating])
-> (Rating -> Rating -> [Rating])
-> (Rating -> Rating -> [Rating])
-> (Rating -> Rating -> Rating -> [Rating])
-> Enum Rating
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Rating -> Rating
succ :: Rating -> Rating
$cpred :: Rating -> Rating
pred :: Rating -> Rating
$ctoEnum :: Int -> Rating
toEnum :: Int -> Rating
$cfromEnum :: Rating -> Int
fromEnum :: Rating -> Int
$cenumFrom :: Rating -> [Rating]
enumFrom :: Rating -> [Rating]
$cenumFromThen :: Rating -> Rating -> [Rating]
enumFromThen :: Rating -> Rating -> [Rating]
$cenumFromTo :: Rating -> Rating -> [Rating]
enumFromTo :: Rating -> Rating -> [Rating]
$cenumFromThenTo :: Rating -> Rating -> Rating -> [Rating]
enumFromThenTo :: Rating -> Rating -> Rating -> [Rating]
Enum, Rating
Rating -> Rating -> Bounded Rating
forall a. a -> a -> Bounded a
$cminBound :: Rating
minBound :: Rating
$cmaxBound :: Rating
maxBound :: Rating
Bounded)

-- | Every rating, from 'Again' to 'Easy'.
allRatings :: [Rating]
allRatings :: [Rating]
allRatings = [Rating
forall a. Bounded a => a
minBound .. Rating
forall a. Bounded a => a
maxBound]

-- | The rating as FSRS numbers it: @1@ for 'Again' through @4@ for 'Easy'.
ratingToInt :: Rating -> Int
ratingToInt :: Rating -> Int
ratingToInt Rating
r = Rating -> Int
forall a. Enum a => a -> Int
fromEnum Rating
r Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1

-- | Inverse of 'ratingToInt'. 'Nothing' outside @1..4@.
ratingFromInt :: Int -> Maybe Rating
ratingFromInt :: Int -> Maybe Rating
ratingFromInt Int
n
  | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
1 Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
4 = Rating -> Maybe Rating
forall a. a -> Maybe a
Just (Int -> Rating
forall a. Enum a => Int -> a
toEnum (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1))
  | Bool
otherwise = Maybe Rating
forall a. Maybe a
Nothing

-- | Memory half-life in days: the larger it is, the slower the card is
-- forgotten. In FSRS-7 stability is a genuine continuous quantity — sub-day
-- values are meaningful and are what the model uses for same-day reviews.
type Stability = Double

-- | How hard the card is for this reviewer, on a @[1, 10]@ scale.
type Difficulty = Double

-- | Probability of recall, in @(0, 1]@.
type Retrievability = Double

-- | A duration in days. Fractional values are meaningful throughout FSRS-7:
-- ten minutes is @10 / 1440@.
type Days = Double

-- | Everything FSRS remembers about a card.
data MemoryState = MemoryState
  { MemoryState -> Stability
memoryStability :: !Stability
  , MemoryState -> Stability
memoryDifficulty :: !Difficulty
  }
  deriving stock (MemoryState -> MemoryState -> Bool
(MemoryState -> MemoryState -> Bool)
-> (MemoryState -> MemoryState -> Bool) -> Eq MemoryState
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MemoryState -> MemoryState -> Bool
== :: MemoryState -> MemoryState -> Bool
$c/= :: MemoryState -> MemoryState -> Bool
/= :: MemoryState -> MemoryState -> Bool
Eq, Eq MemoryState
Eq MemoryState =>
(MemoryState -> MemoryState -> Ordering)
-> (MemoryState -> MemoryState -> Bool)
-> (MemoryState -> MemoryState -> Bool)
-> (MemoryState -> MemoryState -> Bool)
-> (MemoryState -> MemoryState -> Bool)
-> (MemoryState -> MemoryState -> MemoryState)
-> (MemoryState -> MemoryState -> MemoryState)
-> Ord MemoryState
MemoryState -> MemoryState -> Bool
MemoryState -> MemoryState -> Ordering
MemoryState -> MemoryState -> MemoryState
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
$ccompare :: MemoryState -> MemoryState -> Ordering
compare :: MemoryState -> MemoryState -> Ordering
$c< :: MemoryState -> MemoryState -> Bool
< :: MemoryState -> MemoryState -> Bool
$c<= :: MemoryState -> MemoryState -> Bool
<= :: MemoryState -> MemoryState -> Bool
$c> :: MemoryState -> MemoryState -> Bool
> :: MemoryState -> MemoryState -> Bool
$c>= :: MemoryState -> MemoryState -> Bool
>= :: MemoryState -> MemoryState -> Bool
$cmax :: MemoryState -> MemoryState -> MemoryState
max :: MemoryState -> MemoryState -> MemoryState
$cmin :: MemoryState -> MemoryState -> MemoryState
min :: MemoryState -> MemoryState -> MemoryState
Ord, Int -> MemoryState -> ShowS
[MemoryState] -> ShowS
MemoryState -> String
(Int -> MemoryState -> ShowS)
-> (MemoryState -> String)
-> ([MemoryState] -> ShowS)
-> Show MemoryState
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MemoryState -> ShowS
showsPrec :: Int -> MemoryState -> ShowS
$cshow :: MemoryState -> String
show :: MemoryState -> String
$cshowList :: [MemoryState] -> ShowS
showList :: [MemoryState] -> ShowS
Show, ReadPrec [MemoryState]
ReadPrec MemoryState
Int -> ReadS MemoryState
ReadS [MemoryState]
(Int -> ReadS MemoryState)
-> ReadS [MemoryState]
-> ReadPrec MemoryState
-> ReadPrec [MemoryState]
-> Read MemoryState
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS MemoryState
readsPrec :: Int -> ReadS MemoryState
$creadList :: ReadS [MemoryState]
readList :: ReadS [MemoryState]
$creadPrec :: ReadPrec MemoryState
readPrec :: ReadPrec MemoryState
$creadListPrec :: ReadPrec [MemoryState]
readListPrec :: ReadPrec [MemoryState]
Read)