-- Condorcet voting.
-- Copyright (C) 2005 Evan Martin <martine@danga.com>

module Main where

import qualified Condorcet

import Text.ParserCombinators.Parsec
import Control.Monad.Error

{- | Parses a simple form of ballots as strings.
   Ballot strings are comma-separated list in order of preference;
   equally-ranked candidates are separated with an equals sign.
   E.g., "3=4=5,1,2" -}
parseBallot :: String -> Either ParseError Condorcet.Ballot
parseBallot input = parse ballot "" input where
  ballot :: Parser [[Int]]
  ballot = do { b <- sepBy1 rank (char ','); eof; return b }
  rank :: Parser [Int]
  rank = sepBy1 number (char '=')
  number :: Parser Int
  number = do { ds <- many1 digit; return (read ds) }

-- parse a set of ballots, halting on failure (using the Error monad).
parseBallots :: [String] -> Either String [Condorcet.Ballot]
parseBallots bs = mapM pb bs >>= return where
  pb ballot = case parseBallot ballot of
                Left err -> throwError (show err)
                Right x  -> return x

main :: IO ()
main = do
  case parseBallots ["1,2,3", "2=1,3", "2,1,3"] of
    Left e -> putStrLn e
    Right ballots -> do
      putStrLn $ "Parsed " ++ (show (length ballots)) ++ " ballots:"
      mapM_ print ballots
      putStrLn "Computing winners..."
      let winners = Condorcet.run ballots
      putStrLn "Winners:"
      putStrLn $ show winners

-- vim: set ts=2 sw=2 et :

