summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJed Barber <jjbarber@y7mail.com>2017-01-03 23:38:20 +1100
committerJed Barber <jjbarber@y7mail.com>2017-01-03 23:38:20 +1100
commita13d9db820d7cb83e9472e2cf387eb22c26d402d (patch)
treed9c8ccdc299a00867ee8104c94097aba9234273b
Initial commit
-rw-r--r--src/csv.hs57
-rw-r--r--src/senate.hs28
-rw-r--r--src/senatetypes.hs28
3 files changed, 113 insertions, 0 deletions
diff --git a/src/csv.hs b/src/csv.hs
new file mode 100644
index 0000000..ddef1d2
--- /dev/null
+++ b/src/csv.hs
@@ -0,0 +1,57 @@
+module CSV(
+ Settings(..),
+ specialChars,
+ defaultSettings,
+ parseRecord
+ ) where
+
+
+
+
+import Text.ParserCombinators.Parsec
+import Data.Char
+
+
+
+
+data Settings = Settings { separator :: Char
+ , quote :: Char
+ , escape :: Char }
+
+
+specialChars :: Settings -> String
+specialChars s = (separator s):(quote s):(escape s):[]
+
+
+defaultSettings = Settings { separator = ',', quote = '\"', escape = '\\' }
+
+
+
+
+parseRecord :: Settings -> String -> Either ParseError [String]
+parseRecord settings input =
+ parse (record settings) "error" input
+
+
+
+
+record s = do
+ f <- (field s) `sepBy` (char (separator s))
+ optional eol
+ eof
+ return f
+
+
+field s = many (try (quoted s) <|> many1 (fieldChar s)) >>= return . foldl1 (++)
+quoted s = between (char (quote s)) (char (quote s)) (many (quotedChar s))
+fieldChar s = allExcept s (specialChars s)
+quotedChar s = allExcept s [quote s]
+allExcept s c = try (escapeChar s) <|> satisfy (\x -> (not (isControl x)) && (x `notElem` c))
+escapeChar s = char (escape s) >> oneOf (specialChars s)
+
+
+eol = try (string "\r\n")
+ <|> try (string "\r")
+ <|> try (string "\n")
+ <?> "end of line"
+
diff --git a/src/senate.hs b/src/senate.hs
new file mode 100644
index 0000000..8f24d88
--- /dev/null
+++ b/src/senate.hs
@@ -0,0 +1,28 @@
+module Senate(
+ SenateCounter,
+ createSenateCounter,
+ doCount
+ ) where
+
+
+
+import qualified System.IO as IO
+import qualified SenateTypes as STY
+import qualified CSV as CSV
+
+
+
+data SenateCounter = SenateCounter { inputData : IO.FilePath
+ , upperMap : STY.UpperMap
+ , lowerMap : STY.LowerMap }
+
+
+
+createSenateCounter :: IO.FilePath -> STY.UpperMap -> STY.LowerMap -> SenateCounter
+createSenateCounter = SenateCounter
+-- use this function to errorcheck the input data
+
+
+
+doCount :: SenateCounter -> STY.Trace -> Int
+
diff --git a/src/senatetypes.hs b/src/senatetypes.hs
new file mode 100644
index 0000000..23ef738
--- /dev/null
+++ b/src/senatetypes.hs
@@ -0,0 +1,28 @@
+module SenateTypes(
+ CandidateID,
+ UpperLowerMap
+ ) where
+
+
+
+-- fairly obvious, rankings and candidateIDs are both numbers
+type Ranking = Int
+type CandidateID = Int
+
+
+
+-- positions in the uppermap list correspond to the boxes above the line,
+-- and the lists of candidateIDs are the boxes below the line
+type UpperMap = [[CandidateID]]
+
+
+
+-- merely a list in the order of how candidates were placed below the line
+type LowerMap = [CandidateID]
+
+
+
+-- represents a criteria used for finding ballots that voted a specific
+-- way, for example voted for candidate C as #1, candidate F as #2, etc
+type Trace = [(Ranking,CandidateID)]
+