module Conf(
Conf(..),
locXY,
parseFile
) where
import Text.ParserCombinators.Parsec
import qualified Text.ParserCombinators.Parsec.Token as P
import Text.ParserCombinators.Parsec.Language
import qualified Data.Map as Map
import qualified Diplomacy
import qualified Data.Char
data Conf = Conf {
locations :: Map.Map String (Int, Int)
} deriving Show
keyFromLocation :: Diplomacy.Location -> String
keyFromLocation = tryCases where
tryCases "Liverpool" = "lvp"
tryCases "Gulf of Bothnia" = "bot"
tryCases "North Sea" = "nth"
tryCases "Norwegian Sea" = "nrg"
tryCases x = defaultMunge x
defaultMunge = take 3 . spacefree . lowercase
spacefree = filter (/= ' ')
lowercase = map Data.Char.toLower
locXY :: Conf -> Diplomacy.Location -> (Double, Double)
locXY conf loc = maybe (error ("Bad location " ++ loc)) toDouble coords where
toDouble (x, y) = (fromIntegral x, fromIntegral y)
coords = Map.lookup key (locations conf)
key = keyFromLocation loc
lexer :: P.TokenParser st
lexer = P.makeTokenParser def where
def = emptyDef {
P.commentLine = "#",
P.opStart = opLetter def,
P.opLetter = oneOf "(,)"
}
comma :: CharParser st String
comma = P.comma lexer
decimal :: CharParser st Integer
decimal = P.decimal lexer
identifier :: CharParser st String
identifier = P.identifier lexer
parens :: CharParser st a -> CharParser st a
parens = P.parens lexer
whiteSpace :: CharParser st ()
whiteSpace = P.whiteSpace lexer
p_conf :: GenParser Char () Conf
p_conf = do
whiteSpace
locs <- many1 p_location
return $ Conf (Map.fromList locs)
where
p_location :: Parser (String, (Int,Int))
p_location = do
loc <- identifier
pos <- parens $ do x <- decimal
comma
y <- decimal
return (fromIntegral x, fromIntegral y)
return (loc, pos)
parseFile :: FilePath -> IO (Either String Conf)
parseFile file = do
res <- parseFromFile p_conf file
return $ case res of
Left err -> Left (show err)
Right conf -> Right conf