48 lines
1.6 KiB
Haskell
48 lines
1.6 KiB
Haskell
module Event (
|
|
Event(..)
|
|
, EventType(..)
|
|
) where
|
|
|
|
import CSV (Row(..))
|
|
import Control.Monad (foldM)
|
|
import Data.List (isSuffixOf, takeWhile)
|
|
import Data.Map (Map)
|
|
import qualified Data.Map as Map (delete, empty, insert, lookup, toList)
|
|
import Data.Time (Day)
|
|
import Medicine (MedicineName)
|
|
import Text.ParserCombinators.Parsec.Error (Message(..))
|
|
|
|
data EventType = Prescription | Provisioning deriving (Eq, Show)
|
|
|
|
data Event = Event {
|
|
date :: Day
|
|
, amounts :: Map MedicineName Float
|
|
, eventType :: EventType
|
|
} deriving (Show)
|
|
|
|
instance Row Event where
|
|
fromRow assoc = do
|
|
rowDate <- read <$> get "date"
|
|
(kind, ints) <- foldM addAmount (Nothing, Map.empty) . Map.toList $ Map.delete "date" assoc
|
|
maybe
|
|
(Left $ Expect "A prescription or provisioning for a medicine")
|
|
(Right . Event rowDate ints)
|
|
kind
|
|
where
|
|
get key = maybe (Left $ Expect key) Right $ Map.lookup key assoc
|
|
unexpected = Left . UnExpect . show
|
|
addAmount (evType, ints) (key, val) = do
|
|
(newEvType, amount) <- readAmount val
|
|
let newFloats = Map.insert key amount ints
|
|
case evType of
|
|
Nothing -> Right (Just newEvType, newFloats)
|
|
Just currentEvType ->
|
|
if currentEvType == newEvType then Right (evType, newFloats) else unexpected newEvType
|
|
|
|
readAmount :: String -> Either Message (EventType, Float)
|
|
readAmount [] = Left $ Expect "prescription or provisioning"
|
|
readAmount ('+':n) = Right (Provisioning, read n)
|
|
readAmount s =
|
|
if "/j" `isSuffixOf` s
|
|
then Right (Prescription, read $ takeWhile (/= '/') s)
|
|
else Left $ Expect "rate"
|