aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/Main.hs76
1 files changed, 76 insertions, 0 deletions
diff --git a/cmd/Main.hs b/cmd/Main.hs
new file mode 100644
index 0000000..bbc45cb
--- /dev/null
+++ b/cmd/Main.hs
@@ -0,0 +1,76 @@
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE QuasiQuotes #-}
+
+module Main
+ ( main
+ ) where
+
+import Control.Arrow ((&&&))
+import Control.Monad (when)
+import Data.Version (showVersion)
+import GHC.Generics (Generic)
+import System.Environment (getArgs)
+import System.Exit (die)
+
+import Data.Aeson (FromJSON, eitherDecode, encode)
+import qualified Data.ByteString.Lazy as L
+import qualified Data.HashMap.Strict as HM
+import qualified System.Console.Docopt.NoTH as O
+import Text.InterpolatedString.Perl6 (qc)
+
+import Malodivo.Budget (manyToOne)
+import Malodivo.Types.Bill (Bill)
+import Malodivo.Types.District (District)
+
+import Paths_malodivo (version) -- from cabal
+
+usage :: String
+usage =
+ "malodivo " ++
+ showVersion version ++
+ " - budget planning tool for the Kingdom of Malodivo" ++
+ [qc|
+
+This utility reads input JSON data from standard input
+and writes output JSON data to standard output.
+
+Usage: malodivo [options] < input.json > output.json
+
+Options:
+
+ -h, --help Show this message and exit
+
+
+|]
+
+data DistrictInfo = DistrictInfo
+ { name :: District
+ , availableFunds :: Integer
+ } deriving (Generic, FromJSON)
+
+data SimpleInput = SimpleInput
+ { bills :: [Bill]
+ , districts :: [DistrictInfo]
+ } deriving (Generic, FromJSON)
+
+process :: IO ()
+process = do
+ input <- L.getContents
+ case eitherDecode input of
+ Left err -> die err
+ Right si -> do
+ let nbills = length . bills $ si
+ funds =
+ HM.fromListWith (+) . map (name &&& availableFunds) $ districts si
+ when (nbills /= 1) $ die "We needs exactly one bill in input"
+ when (HM.null funds) $ die "We needs at least one district"
+ L.putStr . encode $ manyToOne funds (head . bills $ si)
+
+main :: IO ()
+main = do
+ doco <- O.parseUsageOrExit usage
+ args <- O.parseArgsOrExit doco =<< getArgs
+ if args `O.isPresent` O.longOption "help"
+ then putStrLn $ O.usage doco
+ else process