diff options
Diffstat (limited to 'src/main.hs')
-rw-r--r-- | src/main.hs | 211 |
1 files changed, 0 insertions, 211 deletions
diff --git a/src/main.hs b/src/main.hs deleted file mode 100644 index c66dc6e..0000000 --- a/src/main.hs +++ /dev/null @@ -1,211 +0,0 @@ - - - - --- This source is licensed under Creative Commons CC0 v1.0. - --- To read the full text, see license.txt in the main directory of this repository --- or go to https://creativecommons.org/publicdomain/zero/1.0/legalcode.txt - --- For a human readable summary, go to https://creativecommons.org/publicdomain/zero/1.0/ - - - - -import qualified System.Environment as Env -import qualified System.Console.GetOpt as Opt -import qualified System.Exit as Ex -import qualified System.Directory as Dir -import qualified System.IO as IO -import qualified Control.Monad as Con -import qualified Data.Time.Clock as Time -import qualified Data.Maybe as Maybe -import qualified Counter as Sen -import qualified Candidate as Cand -import qualified Election as Elt -import qualified Miscellaneous as Misc - - - - -data Options = Options - { isVerbose :: Bool - , isVersion :: Bool - , isHelp :: Bool - , getCandFile :: Maybe FilePath - , getPrefFile :: Maybe FilePath - , getOutDir :: Maybe FilePath - , getNumToElect :: Maybe Int - , getState :: Maybe String } - deriving Show - - - - -defaultOptions = Options - { isVerbose = False - , isVersion = False - , isHelp = False - , getCandFile = Nothing - , getPrefFile = Nothing - , getOutDir = Nothing - , getNumToElect = Nothing - , getState = Nothing } - - - - -electOpt :: String -> (Options -> Options) -electOpt str = - let r = Misc.readMaybe str :: Maybe Int - jr = if (Maybe.isJust r && Maybe.fromJust r > 0) then r else Nothing - in (\opts -> opts { getNumToElect = jr }) - - - - -stateOpt :: String -> (Options -> Options) -stateOpt str = - let validStates = ["NSW", "VIC", "TAS", "QLD", "SA", "WA", "NT", "ACT"] - sr = if (str `elem` validStates) then Just str else Nothing - in (\opts -> opts { getState = sr } ) - - - - -optionHeader = - "Usage: stv [OPTION...]\n\n" ++ - "Note that the -c, -p, -o, -e, -s options are all\n" ++ - "required for normal operation.\n" - -furtherHelp = - "Please be sure to provide all required options to run the election counter.\n" ++ - "For further information consult '--help'.\n" - -optionData :: [Opt.OptDescr (Options -> Options)] -optionData = - [ Opt.Option ['v'] ["verbose"] - (Opt.NoArg (\opts -> opts { isVerbose = True}) ) - "chatty output on stderr" - - , Opt.Option ['V'] ["version"] - (Opt.NoArg (\opts -> opts { isVersion = True}) ) - "show version number" - - , Opt.Option ['h'] ["help"] - (Opt.NoArg (\opts -> opts { isHelp = True }) ) - "show this help information" - - , Opt.Option ['c'] ["candidates"] - (Opt.ReqArg (\c opts -> opts { getCandFile = Just c }) "FILE") - ".csv file containing AEC candidate data" - - , Opt.Option ['p'] ["preferences"] - (Opt.ReqArg (\p opts -> opts { getPrefFile = Just p}) "FILE") - ".csv file containing AEC formal preferences" - - , Opt.Option ['o'] ["outdir"] - (Opt.ReqArg (\d opts -> opts { getOutDir = Just d}) "DIR") - "new directory to output count logging" - - , Opt.Option ['e'] ["elect"] - (Opt.ReqArg electOpt "INT") - "number of candidates to elect" - - , Opt.Option ['s'] ["state"] - (Opt.ReqArg stateOpt "STATE") - "state or territory the data corresponds to" ] - - - - -getOpts :: [String] -> IO (Options, [String]) -getOpts argv = - case Opt.getOpt Opt.Permute optionData argv of - (o,n, [] ) -> return (foldl (flip id) defaultOptions o, n) - (_,_,errs) -> ioError (userError (concat errs ++ Opt.usageInfo optionHeader optionData)) - - - - -main = do - rawArgs <- Env.getArgs - (options, arguments) <- getOpts rawArgs - - - -- options that abort the main program - Con.when (isHelp options) $ do - putStrLn (Opt.usageInfo optionHeader optionData) - Ex.exitFailure - - Con.when (isVersion options) $ do - putStrLn "Australian STV Counter v0.1" - Ex.exitFailure - - - -- check that all necessary parameters are - -- both present and valid - let candidateFile = Maybe.fromJust (getCandFile options) - Con.when (Maybe.isNothing (getCandFile options)) $ - Ex.die ("Candidate data file not provided.\n\n" ++ furtherHelp) - doesExist <- Dir.doesFileExist candidateFile - Con.when (not doesExist) $ - Ex.die ("Candidate data file does not exist.\n\n" ++ furtherHelp) - - let preferenceFile = Maybe.fromJust (getPrefFile options) - Con.when (Maybe.isNothing (getPrefFile options)) $ - Ex.die ("Formal preference data file not provided.\n\n" ++ furtherHelp) - doesExist <- Dir.doesFileExist preferenceFile - Con.when (not doesExist) $ - Ex.die ("Formal preference data file does not exist.\n\n" ++ furtherHelp) - - let outputDir = Maybe.fromJust (getOutDir options) - Con.when (Maybe.isNothing (getOutDir options)) $ - Ex.die ("Output logging directory not provided.\n\n" ++ furtherHelp) - doesExist <- Dir.doesDirectoryExist outputDir - Con.when doesExist $ - Ex.die ("Output directory already exists.\n\n" ++ furtherHelp) - - let numToElect = Maybe.fromJust (getNumToElect options) - Con.when (Maybe.isNothing (getNumToElect options)) $ - Ex.die ("Invalid number of candidates to elect or number not provided.\n\n" ++ furtherHelp) - - let state = Maybe.fromJust (getState options) - Con.when (Maybe.isNothing (getState options)) $ - Ex.die ("Invalid state/territory or state/territory not provided.\n\n" ++ furtherHelp) - - - -- set up logging - Dir.createDirectory outputDir - startTime <- Time.getCurrentTime - let mainLog = outputDir ++ "/" ++ "log.txt" - startmsg = "Started election count at " ++ show startTime ++ "\n" - IO.appendFile mainLog startmsg - Con.when (isVerbose options) $ IO.hPutStrLn IO.stderr startmsg - - - -- set up the election processing - Con.when (isVerbose options) $ IO.hPutStrLn IO.stderr "Reading candidate data..." - (aboveBallot, belowBallot) <- Cand.readCandidates candidateFile state - Con.when (isVerbose options) $ IO.hPutStrLn IO.stderr "Reading preference data..." - counter <- Sen.createSenateCounter preferenceFile aboveBallot belowBallot - Con.when (isVerbose options) $ IO.hPutStrLn IO.stderr "Done.\n" - Con.when (isVerbose options) $ IO.hPutStrLn IO.stderr "Setting up election..." - election <- Elt.createElection outputDir mainLog counter numToElect (isVerbose options) - Con.when (isVerbose options) $ IO.hPutStrLn IO.stderr "Done.\n" - - - -- run the show - Con.when (isVerbose options) $ IO.hPutStrLn IO.stderr "Running...\n" - Elt.doCount election - Con.when (isVerbose options) $ IO.hPutStr IO.stderr "\n" - - - -- finish up logging - endTime <- Time.getCurrentTime - let endmsg = "Finished election count at " ++ show endTime ++ "\n" - elapsedmsg = show (Time.diffUTCTime endTime startTime) ++ " elapsed\n" - IO.appendFile mainLog (endmsg ++ elapsedmsg) - Con.when (isVerbose options) $ IO.hPutStrLn IO.stderr (endmsg ++ elapsedmsg) - - |