Implement --date option to evaluate the situation at a different date than when the command is run
This commit is contained in:
parent
e1f338f1f1
commit
3ac6c2d40c
3 changed files with 43 additions and 24 deletions
33
src/CLI.hs
33
src/CLI.hs
|
@ -1,30 +1,47 @@
|
||||||
module CLI (
|
module CLI (
|
||||||
Invocation(..)
|
Invocation(..)
|
||||||
|
, Mode(..)
|
||||||
, invoked
|
, invoked
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Options.Applicative (
|
import Options.Applicative (
|
||||||
Parser, execParser, flag, flag', fullDesc, header, help, helper, info, long, short
|
Parser, auto, execParser, flag, fullDesc, header, help, helper, info
|
||||||
|
, infoOption, long, option, short, value
|
||||||
)
|
)
|
||||||
import Control.Applicative ((<**>), (<|>))
|
import Control.Applicative ((<**>), optional)
|
||||||
import Data.Monoid ((<>))
|
import Data.Monoid ((<>))
|
||||||
|
import Data.Time (Day)
|
||||||
import Data.Version (showVersion)
|
import Data.Version (showVersion)
|
||||||
import qualified Paths_pilu as Pilu (version)
|
import qualified Paths_pilu as Pilu (version)
|
||||||
|
|
||||||
data Invocation = Inventory | Schedule | Version String
|
data Mode = Inventory | Schedule
|
||||||
|
|
||||||
|
data Invocation = Invocation {
|
||||||
|
mode :: Mode
|
||||||
|
, date :: Maybe Day
|
||||||
|
}
|
||||||
|
|
||||||
versionStr :: String
|
versionStr :: String
|
||||||
versionStr = showVersion Pilu.version
|
versionStr = showVersion Pilu.version
|
||||||
|
|
||||||
|
version :: Parser (Invocation -> Invocation)
|
||||||
|
version =
|
||||||
|
infoOption versionStr
|
||||||
|
(short 'v' <> long "version" <> help "Show the version number")
|
||||||
|
|
||||||
invocation :: Parser Invocation
|
invocation :: Parser Invocation
|
||||||
invocation =
|
invocation = Invocation
|
||||||
flag' Inventory
|
<$> flag Schedule Inventory
|
||||||
(short 'i' <> long "inventory" <> help "Show a full inventory")
|
(short 'i' <> long "inventory" <> help "Show a full inventory")
|
||||||
<|> flag Schedule (Version versionStr)
|
<*> option (optional auto) (
|
||||||
(long "version" <> help "Show the version number")
|
value Nothing
|
||||||
|
<> short 'd'
|
||||||
|
<> long "date"
|
||||||
|
<> help "Evaluate the situation at that date"
|
||||||
|
)
|
||||||
|
|
||||||
invoked :: IO Invocation
|
invoked :: IO Invocation
|
||||||
invoked = execParser $
|
invoked = execParser $
|
||||||
info
|
info
|
||||||
(invocation <**> helper)
|
(invocation <**> version <**> helper)
|
||||||
(fullDesc <> header ("Pilu v" ++ versionStr))
|
(fullDesc <> header ("Pilu v" ++ versionStr))
|
||||||
|
|
25
src/Main.hs
25
src/Main.hs
|
@ -1,11 +1,11 @@
|
||||||
{-# LANGUAGE NamedFieldPuns #-}
|
{-# LANGUAGE NamedFieldPuns #-}
|
||||||
module Main where
|
module Main where
|
||||||
|
|
||||||
import CLI (Invocation(..), invoked)
|
import CLI (Invocation(..), Mode(..), invoked)
|
||||||
import CSV (Row, parse)
|
import CSV (Row, parse)
|
||||||
import Data.Time (UTCTime(..), getCurrentTime)
|
import Data.Time (Day, UTCTime(..), getCurrentTime)
|
||||||
import Medicine (Pharmacy, pharmacy)
|
import Medicine (Pharmacy, pharmacy)
|
||||||
import System.Exit (exitFailure, exitSuccess)
|
import System.Exit (exitFailure)
|
||||||
import Schedule (schedule)
|
import Schedule (schedule)
|
||||||
import Timeline (State(..), stateAt)
|
import Timeline (State(..), stateAt)
|
||||||
import YAML (encode)
|
import YAML (encode)
|
||||||
|
@ -17,20 +17,19 @@ readCSV filePath = do
|
||||||
Left e -> (putStrLn $ show e) >> exitFailure
|
Left e -> (putStrLn $ show e) >> exitFailure
|
||||||
Right rows -> return rows
|
Right rows -> return rows
|
||||||
|
|
||||||
getState :: Pharmacy -> IO State
|
getState :: Pharmacy -> Maybe Day -> IO State
|
||||||
getState aPharmacy =
|
getState aPharmacy atDate =
|
||||||
stateAt
|
stateAt
|
||||||
<$> (utctDay <$> getCurrentTime)
|
<$> maybe (utctDay <$> getCurrentTime) return atDate
|
||||||
<*> (return aPharmacy)
|
<*> return aPharmacy
|
||||||
<*> readCSV "timeline.csv"
|
<*> readCSV "timeline.csv"
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
invocation <- invoked
|
invocation <- invoked
|
||||||
display <- case invocation of
|
|
||||||
Inventory -> return $ const encode
|
|
||||||
Schedule -> return $ \ph -> encode . schedule ph
|
|
||||||
Version version -> putStrLn version >> exitSuccess
|
|
||||||
thePharmacy <- pharmacy <$> readCSV "medicine.csv"
|
thePharmacy <- pharmacy <$> readCSV "medicine.csv"
|
||||||
theState <- getState thePharmacy
|
theState <- getState thePharmacy $ date invocation
|
||||||
putStrLn $ display thePharmacy theState
|
let display = case mode invocation of
|
||||||
|
Inventory -> encode
|
||||||
|
Schedule -> encode . schedule thePharmacy
|
||||||
|
putStrLn $ display theState
|
||||||
|
|
|
@ -51,7 +51,10 @@ setDay newDay state@(State {day, stock, consumptionRate}) = state {
|
||||||
max 0 $ initialAmount - duration * (consumptionRate ! medicineName)
|
max 0 $ initialAmount - duration * (consumptionRate ! medicineName)
|
||||||
|
|
||||||
stateAt :: Day -> Pharmacy -> [Event] -> State
|
stateAt :: Day -> Pharmacy -> [Event] -> State
|
||||||
stateAt targetDay pharmacy events =
|
stateAt targetDay pharmacy =
|
||||||
setDay targetDay lastState
|
setDay targetDay . lastState
|
||||||
where
|
where
|
||||||
lastState = foldl applyEvent (initState pharmacy) (sortOn date events)
|
lastState =
|
||||||
|
foldl applyEvent (initState pharmacy)
|
||||||
|
. sortOn date
|
||||||
|
. filter ((<= targetDay) . date)
|
||||||
|
|
Loading…
Reference in a new issue