{-| Module : Types.Order Description : Wrapper for Diplomacy.Order making to JSON-able. Copyright : (c) Alexander Vieth, 2015 Licence : BSD3 Maintainer : aovieth@gmail.com Stability : experimental Portability : non-portable (GHC only) -} {-# LANGUAGE AutoDeriveTypeable #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE StandaloneDeriving #-} module Types.Order ( SomeOrder(..) , SomeOrderObject(..) , parseSomeOrderTypical , parseSomeOrderRetreat , parseSomeOrderAdjust , printSomeOrder , printObject ) where import Control.Applicative import qualified Data.Text as T import Data.Aeson import Data.Aeson.Parser import Data.JSON.Schema import Text.Parsec hiding ((<|>)) import Text.Parsec.Text import Diplomacy.Phase import Diplomacy.OrderType import Diplomacy.Order hiding (Order(..), SomeOrder(..)) import qualified Diplomacy.Order as DO import qualified Diplomacy.OrderObject as DOO import Diplomacy.Subject import Diplomacy.Province import Diplomacy.Unit newtype SomeOrderObject (phase :: Phase) = SomeOrderObject { outSomeOrderObject :: DOO.SomeOrderObject phase } deriving instance Show (SomeOrderObject phase) instance JSONSchema (SomeOrderObject phase) where schema _ = Value (LengthBound Nothing Nothing) instance ToJSON (SomeOrderObject phase) where toJSON (SomeOrderObject (DOO.SomeOrderObject object)) = String (printObject object) instance FromJSON (SomeOrderObject Typical) where parseJSON (String txt) = case parse parseObjectTypical "" txt of Left _ -> empty Right x -> return (SomeOrderObject x) parseJSON _ = empty instance FromJSON (SomeOrderObject Retreat) where parseJSON (String txt) = case parse parseObjectRetreat "" txt of Left _ -> empty Right x -> return (SomeOrderObject x) parseJSON _ = empty instance FromJSON (SomeOrderObject Adjust) where parseJSON (String txt) = case parse parseObjectAdjust "" txt of Left _ -> empty Right x -> return (SomeOrderObject x) parseJSON _ = empty newtype SomeOrder (phase :: Phase) = SomeOrder { outSomeOrder :: DO.SomeOrder phase } deriving instance Show (SomeOrder phase) deriving instance Eq (SomeOrder phase) deriving instance Ord (SomeOrder phase) instance JSONSchema (SomeOrder phase) where schema _ = Value (LengthBound Nothing Nothing) instance ToJSON (SomeOrder phase) where toJSON = String . printSomeOrder instance FromJSON (SomeOrder Typical) where parseJSON (String txt) = case parse parseSomeOrderTypical "" txt of Left _ -> empty Right x -> return x parseJSON _ = empty instance FromJSON (SomeOrder Retreat) where parseJSON (String txt) = case parse parseSomeOrderRetreat "" txt of Left _ -> empty Right x -> return x parseJSON _ = empty instance FromJSON (SomeOrder Adjust) where parseJSON (String txt) = case parse parseSomeOrderAdjust "" txt of Left _ -> empty Right x -> return x parseJSON _ = empty printSomeOrder :: SomeOrder phase -> T.Text printSomeOrder (SomeOrder (DO.SomeOrder order)) = T.concat [ printSubject (orderSubject order) , " " , printObject (orderObject order) ] printSubject :: Subject -> T.Text printSubject (unit, pt) = T.concat [ printUnit unit , " " , printProvinceTarget pt ] printObject :: DOO.OrderObject phase order -> T.Text printObject object = case object of DOO.MoveObject pt -> T.concat ["- ", printProvinceTarget pt] DOO.SupportObject subj pt -> if subjectProvinceTarget subj == pt then T.concat ["S ", printSubject subj] else T.concat ["S ", printSubject subj, " - ", printProvinceTarget pt] DOO.ConvoyObject subj pt -> T.concat ["C ", printSubject subj, " - ", printProvinceTarget pt] DOO.SurrenderObject -> "Surrender" DOO.WithdrawObject pt -> T.concat ["- ", printProvinceTarget pt] DOO.DisbandObject -> "Disband" DOO.BuildObject -> "Build" DOO.ContinueObject -> "Continue" parseSomeOrderTypical :: Parser (SomeOrder Typical) parseSomeOrderTypical = do subject <- parseSubject spaces DOO.SomeOrderObject object <- parseObjectTypical return $ SomeOrder (DO.SomeOrder (DO.Order (subject, object))) parseSomeOrderRetreat :: Parser (SomeOrder Retreat) parseSomeOrderRetreat = do subject <- parseSubject spaces DOO.SomeOrderObject object <- parseObjectRetreat return $ SomeOrder (DO.SomeOrder (DO.Order (subject, object))) parseSomeOrderAdjust :: Parser (SomeOrder Adjust) parseSomeOrderAdjust = do subject <- parseSubject spaces DOO.SomeOrderObject object <- parseObjectAdjust return $ SomeOrder (DO.SomeOrder (DO.Order (subject, object))) parseSubject :: Parser Subject parseSubject = do unit <- parseUnit spaces pt <- parseProvinceTarget return (unit, pt) parseObjectTypical :: Parser (DOO.SomeOrderObject Typical) parseObjectTypical = (DOO.SomeOrderObject <$> try parseMove) <|> (DOO.SomeOrderObject <$> try parseSupport) <|> (DOO.SomeOrderObject <$> try parseConvoy) parseObjectRetreat :: Parser (DOO.SomeOrderObject Retreat) parseObjectRetreat = (DOO.SomeOrderObject <$> try parseSurrender) <|> (DOO.SomeOrderObject <$> try parseWithdraw) parseObjectAdjust :: Parser (DOO.SomeOrderObject Adjust) parseObjectAdjust = (DOO.SomeOrderObject <$> try parseDisband) <|> (DOO.SomeOrderObject <$> try parseBuild) <|> (DOO.SomeOrderObject <$> try parseContinue) parseMove :: Parser (DOO.OrderObject Typical Move) parseMove = do char '-' spaces pt <- parseProvinceTarget return $ DOO.MoveObject pt parseSupport :: Parser (DOO.OrderObject Typical Support) parseSupport = do char 'S' spaces subject <- parseSubject target <- Text.Parsec.option (subjectProvinceTarget subject) (try rest) return $ DOO.SupportObject subject target where rest = do spaces char '-' spaces parseProvinceTarget parseConvoy :: Parser (DOO.OrderObject Typical Convoy) parseConvoy = do char 'C' spaces subject <- parseSubject spaces char '-' spaces target <- parseProvinceTarget return $ DOO.ConvoyObject subject target parseSurrender :: Parser (DOO.OrderObject Retreat Surrender) parseSurrender = do string "Surrender" return $ DOO.SurrenderObject parseWithdraw :: Parser (DOO.OrderObject Retreat Withdraw) parseWithdraw = do char '-' spaces pt <- parseProvinceTarget return $ DOO.WithdrawObject pt parseDisband :: Parser (DOO.OrderObject Adjust Disband) parseDisband = do string "Disband" return $ DOO.DisbandObject parseBuild :: Parser (DOO.OrderObject Adjust Build) parseBuild = do string "Build" return $ DOO.BuildObject parseContinue :: Parser (DOO.OrderObject Adjust Continue) parseContinue = do string "Continue" return $ DOO.ContinueObject