Add haddoc documentation to Cards.hs
This commit is contained in:
parent
7eb9954a05
commit
9eddf454e3
2 changed files with 45 additions and 4 deletions
|
|
@ -151,4 +151,4 @@ run elms = do
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
elms <- runInputT inputSettings $ run testElements
|
elms <- runInputT inputSettings $ run testElements
|
||||||
putStrLn $ show elms
|
putStrLn $ elementsToString elms
|
||||||
|
|
|
||||||
47
src/Cards.hs
47
src/Cards.hs
|
|
@ -5,6 +5,7 @@ module Cards
|
||||||
, toDueCards
|
, toDueCards
|
||||||
, fromCards
|
, fromCards
|
||||||
, elementsToString
|
, elementsToString
|
||||||
|
, parseElements
|
||||||
, Card -- Card stuff
|
, Card -- Card stuff
|
||||||
, sides
|
, sides
|
||||||
, tier
|
, tier
|
||||||
|
|
@ -24,6 +25,11 @@ import Data.List
|
||||||
import qualified Data.Map.Strict as Map
|
import qualified Data.Map.Strict as Map
|
||||||
import Data.Time
|
import Data.Time
|
||||||
|
|
||||||
|
-- | Contains 'Card's and comments with a certain ordering.
|
||||||
|
-- To update some 'Card's in an 'Elements', use 'toCards' or 'toDueCards' and
|
||||||
|
-- 'fromCards'.
|
||||||
|
-- 'Card's can be removed (not added), as long as the numbers
|
||||||
|
-- associated to the remaining cards stay with their original card.
|
||||||
data Elements = Elements (Map.Map Integer Element)
|
data Elements = Elements (Map.Map Integer Element)
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
|
|
@ -31,19 +37,32 @@ data Element = ECard Card
|
||||||
| EComment String
|
| EComment String
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
|
-- | A single index card with one or more sides.
|
||||||
data Card = Card
|
data Card = Card
|
||||||
{ sides :: [String]
|
{ sides :: [String]
|
||||||
|
-- ^ The sides of a 'Card'.
|
||||||
|
-- As opposed to real index cards, a 'Card' may have more or less than two
|
||||||
|
-- sides.
|
||||||
, tier :: Tier
|
, tier :: Tier
|
||||||
|
-- ^ The 'Tier' of a 'Card'.
|
||||||
, lastChecked :: UTCTime
|
, lastChecked :: UTCTime
|
||||||
|
-- ^ The time a 'Card' was last looked at.
|
||||||
, offset :: NominalDiffTime
|
, offset :: NominalDiffTime
|
||||||
|
-- ^ A random offset, used when determining whether a 'Card' needs to be
|
||||||
|
-- revised.
|
||||||
|
-- This is to "stretch out" cards revised in a short time frame.
|
||||||
} deriving (Show)
|
} deriving (Show)
|
||||||
|
|
||||||
|
-- | The "level" of a 'Card' in a typical index card learning scheme.
|
||||||
|
-- Represents the time which should elapse before the 'Card' is looked at again.
|
||||||
data Tier = Unrevised
|
data Tier = Unrevised
|
||||||
| TenMin | TwentyMin | FortyMin
|
| TenMin | TwentyMin | FortyMin
|
||||||
| OneDay | TwoDays | FourDays | EightDays
|
| OneDay | TwoDays | FourDays | EightDays
|
||||||
| SixteenDays | ThirtyTwoDays | SixtyFourDays
|
| SixteenDays | ThirtyTwoDays | SixtyFourDays
|
||||||
deriving (Show, Eq, Ord, Enum, Bounded)
|
deriving (Show, Eq, Ord, Enum, Bounded)
|
||||||
|
|
||||||
|
-- | A 'Elements' containing some cards and some comments, for testing.
|
||||||
|
-- Will be removed soon.
|
||||||
testElements :: Elements
|
testElements :: Elements
|
||||||
testElements = Elements . Map.fromList. zip [1..] $
|
testElements = Elements . Map.fromList. zip [1..] $
|
||||||
[ card ["first card", "really"]
|
[ card ["first card", "really"]
|
||||||
|
|
@ -60,16 +79,26 @@ testElements = Elements . Map.fromList. zip [1..] $
|
||||||
- Elements stuff
|
- Elements stuff
|
||||||
-}
|
-}
|
||||||
|
|
||||||
|
-- | @'updateElements' a b@ adds the updated values from @b@ to @a@.
|
||||||
updateElements :: Elements -> Elements -> Elements
|
updateElements :: Elements -> Elements -> Elements
|
||||||
updateElements (Elements old) (Elements new) = Elements $ Map.union new old
|
updateElements (Elements old) (Elements new) = Elements $ Map.union new old
|
||||||
|
|
||||||
|
-- | Extract all 'Card's from an 'Elements'.
|
||||||
|
-- Entries may be deleted or modified, as long as the numbers are not changed
|
||||||
|
-- and stay associated to their original 'Card'.
|
||||||
toCards :: Elements -> [(Integer, Card)]
|
toCards :: Elements -> [(Integer, Card)]
|
||||||
toCards (Elements elms) =
|
toCards (Elements elms) =
|
||||||
[(key, card) | (key, Just card) <- mapSnd toCard $ Map.toList elms]
|
[(key, card) | (key, Just card) <- mapSnd toCard $ Map.toList elms]
|
||||||
|
|
||||||
|
-- | Extract all 'Card's which are due from an 'Elements'.
|
||||||
|
-- Entries may be deleted or modified, as long as the numbers are not changed
|
||||||
|
-- and stay associated to their original 'Card'.
|
||||||
toDueCards :: UTCTime -> Elements -> [(Integer, Card)]
|
toDueCards :: UTCTime -> Elements -> [(Integer, Card)]
|
||||||
toDueCards time = filter (isDue time . snd) . toCards
|
toDueCards time = filter (isDue time . snd) . toCards
|
||||||
|
|
||||||
|
-- | Convert a list of 'Card's back into an 'Elements'.
|
||||||
|
-- As long as the same numbers are assosiated to the same cards as they were
|
||||||
|
-- originally, this can safely be used to update the original 'Elements'.
|
||||||
fromCards :: [(Integer, Card)] -> Elements
|
fromCards :: [(Integer, Card)] -> Elements
|
||||||
fromCards = Elements . Map.fromList . mapSnd fromCard
|
fromCards = Elements . Map.fromList . mapSnd fromCard
|
||||||
|
|
||||||
|
|
@ -91,6 +120,7 @@ fromCard = ECard
|
||||||
- Card stuff
|
- Card stuff
|
||||||
-}
|
-}
|
||||||
|
|
||||||
|
-- | @'isDue' time card@ returns whether @card@ needs to be revised at @time@.
|
||||||
isDue :: UTCTime -> Card -> Bool
|
isDue :: UTCTime -> Card -> Bool
|
||||||
isDue time Card{tier=t, lastChecked=lc, offset=o} =
|
isDue time Card{tier=t, lastChecked=lc, offset=o} =
|
||||||
diffUTCTime time lc >= o + tierDiff t
|
diffUTCTime time lc >= o + tierDiff t
|
||||||
|
|
@ -101,20 +131,25 @@ updateOffset :: Card -> IO Card
|
||||||
updateOffset Card{sides=s, tier=t, lastChecked=lc} = do
|
updateOffset Card{sides=s, tier=t, lastChecked=lc} = do
|
||||||
return Card{sides=s, tier=t, lastChecked=lc, offset=0}
|
return Card{sides=s, tier=t, lastChecked=lc, offset=0}
|
||||||
|
|
||||||
|
-- | Reset a card's 'Tier'.
|
||||||
|
-- This also resets the 'lastChecked' and 'offset' times.
|
||||||
reset :: UTCTime -> Card -> Card
|
reset :: UTCTime -> Card -> Card
|
||||||
reset time Card{sides=s} =
|
reset time Card{sides=s} =
|
||||||
Card{sides=s, tier=minBound, lastChecked=time, offset=0}
|
Card{sides=s, tier=minBound, lastChecked=time, offset=0}
|
||||||
|
|
||||||
|
-- | Push a 'Card' to the next highest 'Tier'.
|
||||||
|
-- Set the 'lastChecked' and 'offset' time accordingly.
|
||||||
|
-- Uses the IO monad to access the global random number generator.
|
||||||
update :: UTCTime -> Card -> IO Card
|
update :: UTCTime -> Card -> IO Card
|
||||||
update time Card{sides=s, tier=t} =
|
update time Card{sides=s, tier=t} =
|
||||||
updateOffset $ Card {sides=s, tier=boundedSucc t, lastChecked=time, offset=0}
|
updateOffset $ Card {sides=s, tier=boundedSucc t, lastChecked=time, offset=0}
|
||||||
|
|
||||||
-- helper function
|
|
||||||
boundedSucc :: (Eq a, Bounded a, Enum a) => a -> a
|
boundedSucc :: (Eq a, Bounded a, Enum a) => a -> a
|
||||||
boundedSucc a
|
boundedSucc a
|
||||||
| a == maxBound = a
|
| a == maxBound = a
|
||||||
| otherwise = succ a
|
| otherwise = succ a
|
||||||
|
|
||||||
|
-- | Create a new card.
|
||||||
createCard :: UTCTime -> [String] -> Card
|
createCard :: UTCTime -> [String] -> Card
|
||||||
createCard time s =
|
createCard time s =
|
||||||
Card{sides=s, tier=minBound, lastChecked=time, offset=0}
|
Card{sides=s, tier=minBound, lastChecked=time, offset=0}
|
||||||
|
|
@ -123,6 +158,7 @@ createCard time s =
|
||||||
- Tier stuff
|
- Tier stuff
|
||||||
-}
|
-}
|
||||||
|
|
||||||
|
-- | The 'NominalDiffTime' associated with each 'Tier'.
|
||||||
tierDiff :: Tier -> NominalDiffTime
|
tierDiff :: Tier -> NominalDiffTime
|
||||||
tierDiff Unrevised = 0
|
tierDiff Unrevised = 0
|
||||||
tierDiff TenMin = 60 * 10
|
tierDiff TenMin = 60 * 10
|
||||||
|
|
@ -136,6 +172,7 @@ tierDiff SixteenDays = 3600 * (16 * 24 - 8)
|
||||||
tierDiff ThirtyTwoDays = 3600 * (32 * 24 - 8)
|
tierDiff ThirtyTwoDays = 3600 * (32 * 24 - 8)
|
||||||
tierDiff SixtyFourDays = 3600 * (64 * 24 - 8)
|
tierDiff SixtyFourDays = 3600 * (64 * 24 - 8)
|
||||||
|
|
||||||
|
-- | The name associated with each 'Tier'.
|
||||||
tierName :: Tier -> String
|
tierName :: Tier -> String
|
||||||
tierName Unrevised = "unrevised"
|
tierName Unrevised = "unrevised"
|
||||||
tierName TenMin = "10min"
|
tierName TenMin = "10min"
|
||||||
|
|
@ -153,6 +190,8 @@ tierName SixtyFourDays = "64d"
|
||||||
- Converting to String
|
- Converting to String
|
||||||
-}
|
-}
|
||||||
|
|
||||||
|
-- | Convert an 'Elements' to a string which can be parsed by 'parseElements'.
|
||||||
|
-- This string can then be written to a text file for storage.
|
||||||
elementsToString :: Elements -> String
|
elementsToString :: Elements -> String
|
||||||
elementsToString (Elements e) =
|
elementsToString (Elements e) =
|
||||||
let elms = map snd $ Map.toList e
|
let elms = map snd $ Map.toList e
|
||||||
|
|
@ -168,10 +207,12 @@ cardToString Card{sides=s, tier=t, lastChecked=lc, offset=o} =
|
||||||
", \"last_checked\": " ++ (show $ formatTime defaultTimeLocale "%s" lc) ++
|
", \"last_checked\": " ++ (show $ formatTime defaultTimeLocale "%s" lc) ++
|
||||||
", \"delay\": " ++ (show $ fromEnum o) ++
|
", \"delay\": " ++ (show $ fromEnum o) ++
|
||||||
"}"
|
"}"
|
||||||
in unlines $ info : intersperse "::" s
|
in unlines $ info : intersperse "::" s ++ [""] -- newline at the end
|
||||||
|
|
||||||
{-
|
{-
|
||||||
- Parsing
|
- Parsing
|
||||||
-}
|
-}
|
||||||
|
|
||||||
-- TODO
|
-- | Not yet implemented.
|
||||||
|
parseElements :: String -> Maybe Elements
|
||||||
|
parseElements = undefined
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue