bishbosh-0.1.0.0: src-exe/Duel.hs
{-# LANGUAGE LambdaCase #-}
{-
Copyright (C) 2021 Dr. Alistair Ward
This file is part of Duel.
Duel is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Duel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Duel. If not, see <http://www.gnu.org/licenses/>.
-}
{- |
[@AUTHOR@] Dr. Alistair Ward
[@DESCRIPTION@] Coordinates a duel between two independently configured instances of 'bishbosh'; which can be used to evaluate relative performance.
-}
module Main(main) where
import Control.Arrow((&&&))
import qualified BishBosh.Data.Exception as Data.Exception
import qualified BishBosh.Input.CategorisedCommandLineOptions as Input.CategorisedCommandLineOptions
import qualified BishBosh.Input.CommandLineOption as Input.CommandLineOption
import qualified BishBosh.Input.Verbosity as Input.Verbosity
import qualified BishBosh.Text.Case as Text.Case
import qualified Control.Exception
import qualified Data.Default
import qualified Data.List
import qualified Data.Version
import qualified Duel.Data.Options as Data.Options
import qualified Duel.Process.Intermediary as Process.Intermediary
import qualified Paths_bishbosh as Paths -- Either local stub, or package-instance auto-generated by 'Setup build'.
import qualified System.Console.GetOpt as G
import qualified System.Environment
import qualified System.Exit
import qualified System.Info
-- | The application's entry-point.
main :: IO ()
main = do
progName <- System.Environment.getProgName
let
optDescrList :: [
G.OptDescr (
Maybe (Input.CommandLineOption.Flag, Maybe String {-optional value-}), -- Record command-line specifications.
Input.CommandLineOption.CommandLineOption Data.Options.Options -- Defines the action to take on receipt of a command-line option.
) -- Pair.
]
optDescrList = [
G.Option "?" ["help"] (
G.NoArg (
Nothing {-N/A-},
Input.CommandLineOption.mkIOAction printHelp
)
) "print this help, & then exit.",
G.Option "v" ["version"] (
G.NoArg (
Nothing {-N/A-},
Input.CommandLineOption.mkIOAction printVersion
)
) "print version-information, & then exit.",
G.Option "" [Input.Verbosity.tag] (
G.ReqArg (
Just . (,) Input.Verbosity.tag . Just &&& Input.CommandLineOption.mkOptionsMutator . Data.Options.setVerbosity . Input.CommandLineOption.readArg
) . mkTypeSpecification $ Text.Case.toUpperInitial Input.Verbosity.tag
) . showString "define the log-level; default '" $ shows (Data.Default.def :: Input.Verbosity.Verbosity) "'.",
let
flag = "nGames"
in G.Option "n" [flag] (
G.ReqArg (
Just . (,) flag . Just &&& Input.CommandLineOption.mkOptionsMutator . Data.Options.setNGames . Input.CommandLineOption.readBoundedIntegral
) $ mkTypeSpecification "Int"
) "define the number of games to play.",
let
flag = "readTimeout"
in G.Option "t" [flag] (
G.ReqArg (
Just . (,) flag . Just &&& Input.CommandLineOption.mkOptionsMutator . Data.Options.setReadTimeout . Input.CommandLineOption.readBoundedIntegral
) $ mkTypeSpecification "s"
) . showString "define the read-timeout; default " $ shows (Data.Options.getReadTimeout Data.Default.def) " s.",
let
flag = "appendInputConfigFilePath"
in G.Option "i" [flag] (
G.ReqArg (
Just . (,) flag . Just &&& Input.CommandLineOption.mkOptionsMutator . Data.Options.appendInputConfigFilePath
) $ mkTypeSpecification "File-path"
) . showString "define the path to an XML-file, to forward to an instance of bishbosh; " $ shows Data.Options.requiredInputConfigFiles " are required, White's first, then Black's."
] where
author :: String
author = "Dr. Alistair Ward"
printHelp, printVersion :: Input.CategorisedCommandLineOptions.IOAction
printHelp = putStrLn . showString "Usage: " $ G.usageInfo progName optDescrList
printVersion = putStrLn . showString progName . showChar '-' . showsVersion Paths.version . showString "\n\nCompiled by " . showString System.Info.compilerName . showChar '-' . showsVersion System.Info.compilerVersion . showString ".\n\nCopyright (C) 2021 " . showString author . showString ".\nThis program comes with ABSOLUTELY NO WARRANTY.\nThis is free software, and you are welcome to redistribute it under certain conditions.\n\nWritten by " $ showString author "." where
showsVersion :: Data.Version.Version -> ShowS
showsVersion = foldr (.) id . Data.List.intersperse (showChar '.') . map shows . Data.Version.versionBranch
mkTypeSpecification :: ShowS
mkTypeSpecification s = showChar '<' $ showString s ">"
System.Environment.getArgs >>= (
\case
(commandLineOptions, [{-non-options-}], [{-errors-}])
| not $ null ioActions -> sequence_ ioActions >> System.Exit.exitSuccess
| otherwise -> Process.Intermediary.initialise . foldr ($) Data.Default.def $ Input.CategorisedCommandLineOptions.getOptionsMutators categorisedCommandLineOptions -- Sequentially mutate the configuration, using each of the options-mutators specified on the command-line.
where
categorisedCommandLineOptions = Input.CommandLineOption.categorise $ map snd commandLineOptions
ioActions = Input.CategorisedCommandLineOptions.getIOActions categorisedCommandLineOptions
(_, nonOptions, []) -> Control.Exception.throwIO . Data.Exception.mkRedundantData . showString "unexpected command-line arguments; " $ shows nonOptions "."
(_, _, errors) -> Control.Exception.throwIO . Data.Exception.mkParseFailure $ concat errors
) . G.getOpt G.RequireOrder optDescrList