module BishBosh.Input.PGNOptions(
PGNOptions(
getDatabaseFilePath,
getIsStrictlySequential,
getValidateMoves,
getIdentificationTags,
getMinimumPlies
),
tag,
databaseFilePathTag,
mkPGNOptions
) where
import qualified BishBosh.Component.Move as Component.Move
import qualified BishBosh.ContextualNotation.PGN as ContextualNotation.PGN
import qualified BishBosh.ContextualNotation.StandardAlgebraic as ContextualNotation.StandardAlgebraic
import qualified BishBosh.Data.Exception as Data.Exception
import qualified BishBosh.Text.ShowList as Text.ShowList
import qualified Control.DeepSeq
import qualified Control.Exception
import qualified Data.Default
import qualified System.FilePath
import qualified Text.XML.HXT.Arrow.Pickle as HXT
import qualified ToolShed.Data.Foldable
tag :: String
tag = "pgnOptions"
databaseFilePathTag :: String
databaseFilePathTag = "databaseFilePath"
validateMovesTag :: String
validateMovesTag = "validateMoves"
isStrictlySequentialTag :: String
isStrictlySequentialTag = "isStrictlySequential"
identificationTagTag :: String
identificationTagTag = "identificationTag"
minimumPliesTag :: String
minimumPliesTag = "minimumPlies"
data PGNOptions = MkPGNOptions {
getDatabaseFilePath :: System.FilePath.FilePath,
getIsStrictlySequential :: ContextualNotation.PGN.IsStrictlySequential,
getValidateMoves :: ContextualNotation.StandardAlgebraic.ValidateMoves,
getIdentificationTags :: [ContextualNotation.PGN.Tag],
getMinimumPlies :: Component.Move.NMoves
} deriving Eq
instance Control.DeepSeq.NFData PGNOptions where
rnf MkPGNOptions {
getDatabaseFilePath = databaseFilePath,
getIsStrictlySequential = isStrictlySequential,
getValidateMoves = validateMoves,
getIdentificationTags = identificationTags,
getMinimumPlies = minimumPlies
} = Control.DeepSeq.rnf (databaseFilePath, isStrictlySequential, validateMoves, identificationTags, minimumPlies)
instance Show PGNOptions where
showsPrec _ MkPGNOptions {
getDatabaseFilePath = databaseFilePath,
getIsStrictlySequential = isStrictlySequential,
getValidateMoves = validateMoves,
getIdentificationTags = identificationTags,
getMinimumPlies = minimumPlies
} = Text.ShowList.showsAssociationList' [
(
databaseFilePathTag,
shows databaseFilePath
), (
isStrictlySequentialTag,
shows isStrictlySequential
), (
validateMovesTag,
shows validateMoves
), (
showString identificationTagTag "s",
shows identificationTags
), (
minimumPliesTag,
shows minimumPlies
)
]
instance Data.Default.Default PGNOptions where
def = MkPGNOptions {
getDatabaseFilePath = "pgn/bishbosh.pgn",
getIsStrictlySequential = True,
getValidateMoves = True,
getIdentificationTags = ["ECO", "Variation"],
getMinimumPlies = 1
}
instance HXT.XmlPickler PGNOptions where
xpickle = HXT.xpElem tag . HXT.xpWrap (
\(a, b, c, d, e) -> mkPGNOptions a b c d e,
\MkPGNOptions {
getDatabaseFilePath = databaseFilePath,
getIsStrictlySequential = isStrictlySequential,
getValidateMoves = validateMoves,
getIdentificationTags = identificationTags,
getMinimumPlies = minimumPlies
} -> (databaseFilePath, isStrictlySequential, validateMoves, identificationTags, minimumPlies)
) $ HXT.xp5Tuple (
HXT.xpTextAttr databaseFilePathTag
) (
getIsStrictlySequential def `HXT.xpDefault` HXT.xpAttr isStrictlySequentialTag HXT.xpickle
) (
getValidateMoves def `HXT.xpDefault` HXT.xpAttr validateMovesTag HXT.xpickle
) (
HXT.xpList . HXT.xpElem identificationTagTag $ HXT.xpTextAttr "tag"
) (
getMinimumPlies def `HXT.xpDefault` HXT.xpAttr minimumPliesTag HXT.xpickle
) where
def = Data.Default.def
mkPGNOptions
:: System.FilePath.FilePath
-> ContextualNotation.PGN.IsStrictlySequential
-> ContextualNotation.StandardAlgebraic.ValidateMoves
-> [ContextualNotation.PGN.Tag]
-> Component.Move.NMoves
-> PGNOptions
mkPGNOptions databaseFilePath isStrictlySequential validateMoves identificationTags minimumPlies
| not $ System.FilePath.isValid databaseFilePath = Control.Exception.throw . Data.Exception.mkInvalidDatum . showString "BishBosh.Input.PGNOptions.mkPGNOptions:\tinvalid " . showString databaseFilePathTag . Text.ShowList.showsAssociation $ shows databaseFilePath "."
| any null identificationTags = Control.Exception.throw . Data.Exception.mkNullDatum . showString "BishBosh.Input.PGNOptions.mkPGNOptions:\tno " $ shows identificationTagTag " can be null."
| not $ null duplicateTags = Control.Exception.throw . Data.Exception.mkDuplicateData . showString "BishBosh.Input.PGNOptions.mkPGNOptions:\tduplicate " . showString identificationTagTag . showChar 's' . Text.ShowList.showsAssociation $ shows duplicateTags "."
| minimumPlies < 0 = Control.Exception.throw . Data.Exception.mkOutOfBounds . showString "BishBosh.Input.PGNOptions.mkPGNOptions:\t" $ shows minimumPliesTag " can't be negative."
| otherwise = MkPGNOptions {
getDatabaseFilePath = databaseFilePath,
getIsStrictlySequential = isStrictlySequential,
getValidateMoves = validateMoves,
getIdentificationTags = identificationTags,
getMinimumPlies = minimumPlies
}
where
duplicateTags :: [ContextualNotation.PGN.Tag]
duplicateTags = map head . filter ((/= 1) . length) $ ToolShed.Data.Foldable.gather identificationTags