packages feed

MTGBuilder-0.1.0.0: src/Main.hs

module Main (
    main
) where

import System.Environment
import System.IO
import System.Console.GetOpt
import System.Exit
import Control.Monad
import Control.Monad.Reader
import MTGBuilder.Deck
import MTGBuilder.Parser
import Data.Set (Set)
import qualified Data.Set as Set

data Options = Options  {
    optVerbose      :: Bool,
    optWriteRanking :: String -> IO (),
    optOutput       :: Handle,
    optPrecision    :: Int
}

options :: [OptDescr (Options -> IO Options)]
options =
    [ Option "o" ["output"]
        (ReqArg
            (\arg opt -> do
                handle <- openFile arg WriteMode
                return opt { optOutput = handle })
            "FILE")
        "Output file"
 
    , Option "r" ["ranking"]
        (ReqArg
            (\arg opt -> return opt { optPrecision = read arg })
            "NUMBER")
        "Order of rankings to compose the input decks with"
 
    , Option "f" ["rankingFile"]
        (ReqArg
            (\arg opt -> return opt { optWriteRanking = writeFile arg })
            "FILE")
        "Order of precision to measure interactions with"
 
    , Option "v" ["verbose"]
        (NoArg
            (\opt -> return opt { optVerbose = True }))
        "Enable verbose messages"
 
    , Option "V" ["version"]
        (NoArg
            (\_ -> do
                hPutStrLn stderr "Version 0.1.0.0"
                exitWith ExitSuccess))
        "Print version"
 
    , Option "h" ["help"]
        (NoArg
            (\_ -> do
                hPutStrLn stderr (usageInfo "mtg-builder" options)
                exitWith ExitSuccess))
        "Show help"
    ]

startOptions :: Options
startOptions = Options  {
    optVerbose      = False,
    optWriteRanking  = (\s -> return ()),
    optOutput       = stdout,
    optPrecision    = 2     -- Default to only second order rankings
}

main = do
    args <- getArgs
 
    -- Parse options, getting a list of option actions and input deck files
    let (actions, nonOptions, errors) = getOpt RequireOrder options args

    -- Thread startOptions through all supplied option actions
    opts <- foldl (>>=) (return startOptions) actions
 
    let Options {
        optVerbose = verbose,
        optWriteRanking = writeRanking,
        optOutput = output,
        optPrecision = precision
    } = opts

    -- Produce a list of IO (name, contents)
    let input = sequence $ case nonOptions of
            []      -> [getContents >>= \s -> return ("stdin", s)]
            inputs  -> fmap (\i -> readFile i >>= \s -> return (i, s)) inputs

    -- =)
    when verbose (hPutStrLn stderr "Hello!")
 

    deckNamesAndContents <- input
    namedDecks <- forM deckNamesAndContents (\(name, source) -> case parseDeckString name source of
            Left err    -> fail $ show err
            Right deck  -> do
                when verbose (hPutStrLn stderr ("Parsing deck: " ++ name))
                return (name, deck))

    let decks = fmap snd namedDecks

    -- Produce the rank mappings
    ranking <- runReaderT (makeRanking precision namedDecks) verbose
    writeRanking $ dumpRanking ranking

    -- Compose the decks into the aggregate deck
    deck <- runReaderT (composeDecks ranking 60 decks) verbose
    when verbose $ hPutStrLn stderr ("Final size: " ++ (show $ Set.size deck))
    let dump = dumpDeck deck
    hPutStrLn output dump
    when verbose $ hPutStrLn stderr $ dump
    hClose output
    return ()