-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE LambdaCase #-}

module Duckling.Ordinal.CA.Rules
  ( rules ) where

import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text as Text
import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Ordinal.Helpers
import Duckling.Regex.Types
import Duckling.Types

ordinalsMap :: HashMap.HashMap Text.Text Int
ordinalsMap = HashMap.fromList
  [ ( "primer" , 1 )
  , ( "primers" , 1 )
  , ( "primera" , 1 )
  , ( "primeres" , 1 )
  , ( "segon" , 2 )
  , ( "segona" , 2 )
  , ( "segones" , 2 )
  , ( "segons" , 2 )
  , ( "tercer" , 3 )
  , ( "tercera" , 3 )
  , ( "tercers" , 3 )
  , ( "terceres" , 3 )
  , ( "quart" , 4 )
  , ( "quarta" , 4 )
  , ( "quarts" , 4 )
  , ( "quartes" , 4 )
  , ( "cinquÃ¨" , 5 )
  , ( "cinquena" , 5 )
  , ( "cinquens" , 5 )
  , ( "cinquenes" , 5 )
  , ( "sisÃ¨" , 6 )
  , ( "sisena" , 6 )
  , ( "sisens" , 6 )
  , ( "sisenes" , 6 )
  , ( "setÃ¨" , 7 )
  , ( "setena" , 7 )
  , ( "setens" , 7 )
  , ( "setenes" , 7 )
  , ( "vuitÃ¨" , 8 )
  , ( "vuitena" , 8 )
  , ( "vuitens" , 8 )
  , ( "vuitenes" , 8 )
  , ( "novÃ¨" , 9 )
  , ( "novena" , 9 )
  , ( "novens" , 9 )
  , ( "novenes" , 9 )
  , ( "desÃ¨" , 10 )
  , ( "desena" , 10 )
  , ( "desens" , 10 )
  , ( "desenes" , 10 )
  , ( "onzÃ¨" , 11 )
  , ( "onzena" , 11 )
  , ( "dotzÃ¨" , 12 )
  , ( "dotzena" , 12 )
  , ( "tretzÃ¨" , 13 )
  , ( "tretzena" , 13 )
  , ( "catorzÃ¨" , 14 )
  , ( "catorzena" , 14 )
  , ( "quinzÃ¨" , 15 )
  , ( "quinzena" , 15 )
  , ( "setzÃ¨" , 16 )
  , ( "setzena" , 16 )
  , ( "dissetÃ¨" , 17 )
  , ( "dissetena" , 17 )
  , ( "divuitÃ¨" , 18 )
  , ( "divuitena" , 18 )
  , ( "dinovÃ¨" , 19 )
  , ( "dinovena" , 19 )
  , ( "vintÃ¨" , 20 )
  , ( "vintena" , 20 )
  ]

ruleOrdinalsPrimero :: Rule
ruleOrdinalsPrimero = Rule
  { name = "ordinals (primero..10)"
  , pattern =
    [ regex "(primer(a|s|es)?|segon(a|s|es)?|tercer(a|s|es)?|quart(a|s|es)?|cinqu(Ã¨|(en(a|s|es)))|sis(Ã¨|en(a|s|es))|set(Ã¨|en(a|s|es))|vuit(Ã¨|en(a|s|es))|nov(Ã¨|en(a|s|es))|des(Ã¨|en(a|s|es))|onz(Ã¨|ena)|dotz(Ã¨|ena)|tretz(Ã¨|ena)|catorz(Ã¨|ena)|quinz(Ã¨|ena)|setz(Ã¨|ena)|disset(Ã¨|ena)|divuit(Ã¨|ena)|dinov(Ã¨|ena)|vint(Ã¨|ena))"
    ]
  , prod = \case
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsMap
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinalsPrimero
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.DA.Corpus
  ( corpus ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale DA Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (OrdinalData 4)
             [ "4."
             , "fjerde"
             , "Fjerde"
             ]
  , examples (OrdinalData 41)
             [ "enogfyrrende"
             ]
  , examples (OrdinalData 78)
             [ "otteoghalvfjerdsindstyvende"
             ]
  , examples (OrdinalData 263)
             [ "to hundrede og treogtresindstyvende"
             , "tohundrede og treogtresindstyvende"
             ]
  , examples (OrdinalData 70)
             [ "halvfjerdsende"
             , "halvfjerdsindstyvende"
             ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NoRebindableSyntax #-}

module Duckling.Ordinal.DA.Rules
  ( rules ) where

import Data.HashMap.Strict (HashMap)
import Data.Text (Text)
import Prelude
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text as Text

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt, numberWith)
import Duckling.Numeral.Types (NumeralData (..), getIntValue)
import Duckling.Ordinal.Helpers
import Duckling.Ordinal.Types (OrdinalData (..))
import Duckling.Regex.Types
import Duckling.Types
import qualified Duckling.Numeral.Types as TNumeral

ordinalsMap :: HashMap Text Int
ordinalsMap = HashMap.fromList
  [ ( "fÃ¸rste", 1 )
  , ( "anden", 2 )
  , ( "tredje", 3 )
  , ( "fjerde", 4 )
  , ( "femte", 5 )
  , ( "sjette", 6 )
  , ( "syvende", 7 )
  , ( "ottende", 8 )
  , ( "niende", 9 )
  , ( "tiende", 10 )
  , ( "elfte", 11 )
  , ( "tolvte", 12 )
  , ( "trettende", 13 )
  , ( "fjortende", 14 )
  , ( "femtende", 15 )
  , ( "sekstende", 16 )
  , ( "syttende", 17 )
  , ( "attende", 18 )
  , ( "nittende", 19 )
  , ( "tyvende", 20 )
  , ( "tenogtyvende", 21 )
  , ( "toogtyvende", 22 )
  , ( "treogtyvende", 23 )
  , ( "fireogtyvende", 24 )
  , ( "femogtyvende", 25 )
  , ( "seksogtyvende", 26 )
  , ( "syvogtyvende", 27 )
  , ( "otteogtyvende", 28 )
  , ( "niogtyvende", 29 )
  , ( "tredivte", 30 )
  , ( "enogtredivte", 31 )
  ]

cardinalsMap :: HashMap Text Int
cardinalsMap = HashMap.fromList
  [ ( "tyvende", 20 )
  , ( "tredivte", 30 )
  , ( "fyrrende", 40 )
  , ( "fyrretyvende", 40 )
  , ( "halvtredsende", 50 )
  , ( "halvtredsindstyvende", 50 )
  , ( "tressende", 60 )
  , ( "tresindstyvende", 60 )
  , ( "halvfjerdsende", 70 )
  , ( "halvfjerdsindstyvende", 70 )
  , ( "firsende", 80 )
  , ( "firsindsstyvende", 80 )
  , ( "halvfemsende", 90 )
  , ( "halvfemsindstyvende", 90 )
  ]

oneValMap :: HashMap Text Int
oneValMap = HashMap.fromList
  [ ( "", 0 )
  , ( "enog", 1 )
  , ( "toog", 2 )
  , ( "treog", 3 )
  , ( "fireog", 4 )
  , ( "femog", 5 )
  , ( "seksog", 6 )
  , ( "syvog", 7 )
  , ( "otteog", 8 )
  , ( "niog", 9 )
  ]

ruleOrdinalsFirstst :: Rule
ruleOrdinalsFirstst = Rule
  { name = "ordinals (first..19st)"
  , pattern =
    [ regex "(fÃ¸rste|anden|tredje|fjerde|femte|sjette|syvende|ottende|niende|tiende|elfte|tolvte|trettende|fjortende|femtende|sekstende|syttende|attende|nittende)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsMap
      _ -> Nothing
  }

ruleSpelledOutOrdinals :: Rule
ruleSpelledOutOrdinals = Rule
  { name = "ordinals, 20 to 99, spelled-out"
  , pattern =
    [ regex (concat ["((?:en|to|tre|fire|fem|seks|syv|otte|ni)og)?",
                     "(tyvende",
                     "|tredivte",
                     "|fyrr(?:etyv)?ende",
                     "|halvtreds(?:indstyv)?ende",
                     "|tres(?:indstyv|s)?ende",
                     "|halvfjerds(?:indstyv)?ende",
                     "|firs(?:indstyv)?ende",
                     "|halvfems(?:indstyv)?ende)"])
    ]
  , prod = \case
    (Token RegexMatch (GroupMatch (ones:tens:_)):_) -> do
      oneVal <- HashMap.lookup (Text.toLower ones) oneValMap
      tenVal <- HashMap.lookup (Text.toLower tens) cardinalsMap
      Just $ ordinal (oneVal + tenVal)
    _ -> Nothing

  }

ruleSpelledOutBigOrdinals :: Rule
ruleSpelledOutBigOrdinals = Rule
  { name = "ordinals, above 99, spelled out"
  , pattern =
    [ numberWith TNumeral.value (> 99)
    , regex "og"
    , dimension Ordinal
    ]
  , prod = \case
      Token Numeral NumeralData {TNumeral.value=maybenumnum}:_:Token Ordinal (OrdinalData ordnum):_ ->
            case getIntValue maybenumnum of
              Just numnum -> Just $ ordinal (numnum + ordnum)
              Nothing -> Nothing
      _ -> Nothing
  }

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern =
    [ regex "0*(\\d+)(\\.|ste?)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> do
        v <- parseInt match
        Just $ ordinal v
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinalDigits
  , ruleOrdinalsFirstst
  , ruleSpelledOutOrdinals
  , ruleSpelledOutBigOrdinals
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.DE.Corpus
  ( corpus
  , negativeCorpus
  ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale DE Nothing}, testOptions, allExamples)

negativeCorpus :: NegativeCorpus
negativeCorpus = (testContext {locale = makeLocale DE Nothing}, testOptions, examples)
  where
    examples =
      [ "1.1"
      , "1.1."
      ]

allExamples :: [Example]
allExamples =
  examples (OrdinalData 4)
           [ "vierter"
           , "4ter"
           , "Vierter"
           , "4."
           ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.DE.Rules
  ( rules
  ) where

import Data.Semigroup ((<>))
import Prelude
import Data.String
import Data.Text (Text)
import qualified Data.HashMap.Strict as HashMap
import qualified Data.List as List
import qualified Data.Text as Text

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Helpers
import Duckling.Regex.Types
import Duckling.Types

ordinalList :: [(Text, Int)]
ordinalList =
  [ ("erste", 1)
  , ("zweite", 2)
  , ("dritte", 3)
  , ("vierte", 4)
  , ("fÃ¼nfte", 5)
  , ("sechste", 6)
  , ("siebte", 7)
  , ("achte", 8)
  , ("neunte", 9)
  , ("zehnte", 10)
  , ("elfte", 11)
  , ("zwÃ¶lfte", 12)
  , ("dreizente", 13)
  , ("vierzehnte", 14)
  , ("fÃ¼nfzehnte", 15)
  , ("sechzente", 16)
  , ("siebzehnte", 17)
  , ("achtzehnte", 18)
  , ("neunzehnte", 19)
  , ("zwanzigste", 20)
  , ("einundzwanzigste", 21)
  , ("zweiundzwanzigste", 22)
  , ("dreiundzwanzigste", 23)
  , ("vierundzwanzigste", 24)
  , ("fÃ¼nfundzwanzigste", 25)
  , ("sechsundzwanzigste", 26)
  , ("siebenundzwanzigste", 27)
  , ("achtundzwanzigste", 28)
  , ("neunundzwanzigste", 29)
  , ("dreissigste", 30)
  , ("dreiÃŸigste", 30)
  , ("einunddreissigste", 31)
  , ("einunddreiÃŸigste", 31)
  ]

ruleOrdinalsFirstth :: Rule
ruleOrdinalsFirstth = Rule
  { name = "ordinal (1..31)"
  , pattern =
    [ regex $ Text.unpack construction
    ]
  , prod = \case
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> HashMap.lookup (Text.toLower match) ordinalMap
      _ -> Nothing
  }
  where
    ordinalMap :: HashMap.HashMap Text Int
    ordinalMap = HashMap.fromList ordinalList

    construction :: Text
    construction =
      "("
      <> mconcat (List.intersperse "|" (fst <$> ordinalList))
      <> ")[rsn]?"

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern =
    [ regex "(?<!\\d|\\.)0*(\\d+)(\\.(?!\\d)| ?(te(n|r|s)?)|(ste(n|r|s)?))"
    ]
  , prod = \case
      (Token RegexMatch (GroupMatch (match:_)):_) -> do
        v <- parseInt match
        Just $ ordinal v
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinalsFirstth
  , ruleOrdinalDigits
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.EN.Corpus
  ( corpus
  ) where

import Data.String
import Prelude

import Duckling.Ordinal.Types
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (OrdinalData 1)
             [ "first"
             , "1st"
             ]
  , examples (OrdinalData 2)
             [ "second"
             , "2nd"
             ]
  , examples (OrdinalData 3)
             [ "third"
             , "3rd"
             ]
  , examples (OrdinalData 4)
             [ "fourth"
             , "4th"
             ]
  , examples (OrdinalData 8)
             [ "eighth"
             , "8th"
             ]
  , examples (OrdinalData 25)
             [ "twenty-fifth"
             , "twentyâ€”fifth"
             , "twenty fifth"
             , "twentyfifth"
             , "25th"
             ]
  , examples (OrdinalData 31)
             [ "thirty-first"
             , "thirtyâ€”first"
             , "thirty first"
             , "thirtyfirst"
             , "31st"
             ]
  , examples (OrdinalData 42)
             [ "forty-second"
             , "fortyâ€”second"
             , "forty second"
             , "fortysecond"
             , "42nd"
             ]
  , examples (OrdinalData 73)
            [ "seventy-third"
            , "seventyâ€”third"
            , "seventy third"
            , "seventythird"
            , "73rd"
            ]
  , examples (OrdinalData 90)
            [ "ninetieth"
            , "90th"
            ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NoRebindableSyntax #-}

module Duckling.Ordinal.EN.Rules
  ( rules
  ) where

import Data.HashMap.Strict (HashMap)
import Data.String
import Data.Text (Text)
import Prelude
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text as Text

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Helpers
import Duckling.Regex.Types
import Duckling.Types

ordinalsMap :: HashMap Text Int
ordinalsMap = HashMap.fromList
  [ ( "first", 1 )
  , ( "second", 2 )
  , ( "third", 3 )
  , ( "fourth", 4 )
  , ( "fifth", 5 )
  , ( "sixth", 6 )
  , ( "seventh", 7 )
  , ( "eighth", 8 )
  , ( "ninth", 9 )
  , ( "tenth", 10 )
  , ( "eleventh", 11 )
  , ( "twelfth", 12 )
  , ( "thirteenth", 13 )
  , ( "fourteenth", 14 )
  , ( "fifteenth", 15 )
  , ( "sixteenth", 16 )
  , ( "seventeenth", 17 )
  , ( "eighteenth", 18 )
  , ( "nineteenth", 19 )
  , ( "twentieth", 20 )
  , ( "thirtieth", 30 )
  , ( "fortieth", 40 )
  , ( "fiftieth", 50 )
  , ( "sixtieth", 60 )
  , ( "seventieth", 70 )
  , ( "eightieth", 80 )
  , ( "ninetieth", 90 )
  ]

cardinalsMap :: HashMap Text Int
cardinalsMap = HashMap.fromList
  [ ( "twenty", 20 )
  , ( "thirty", 30 )
  , ( "forty", 40 )
  , ( "fifty", 50 )
  , ( "sixty", 60 )
  , ( "seventy", 70 )
  , ( "eighty", 80 )
  , ( "ninety", 90 )
  ]

ruleOrdinals :: Rule
ruleOrdinals = Rule
  { name = "ordinals (first..twentieth,thirtieth,...)"
  , pattern = [regex "(first|second|third|fourth|fifth|sixth|seventh|eighth|ninth|tenth|eleventh|twelfth|thirteenth|fourteenth|fifteenth|sixteenth|seventeenth|eighteenth|nineteenth|twentieth|thirtieth|fortieth|fiftieth|sixtieth|seventieth|eightieth|ninetieth)"]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsMap
      _ -> Nothing
    }

ruleCompositeOrdinals :: Rule
ruleCompositeOrdinals = Rule
  { name = "ordinals (composite, e.g. eighty-seven, fortyâ€”seventh, twenty ninth, thirtythird)"
  , pattern = [regex "(twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety)[\\s\\-\\â€”]?(first|second|third|fourth|fifth|sixth|seventh|eighth|ninth)"]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (tens:units:_)):_) -> do
        tt <- HashMap.lookup (Text.toLower tens) cardinalsMap
        uu <- HashMap.lookup (Text.toLower units) ordinalsMap
        Just (ordinal (tt + uu))
      _ -> Nothing
  }

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern = [regex "0*(\\d+) ?(st|nd|rd|th)"]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinals
  , ruleCompositeOrdinals
  , ruleOrdinalDigits
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.ES.Corpus
  ( corpus ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale ES Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (OrdinalData 1)
             [ "primer"
             , "primero"
             , "primeras"
             ]
  , examples (OrdinalData 2)
             [ "segundo"
             , "segunda"
             , "segundos"
             ]
  , examples (OrdinalData 3)
             [ "tercero"
             , "tercera"
             , "terceros"
             ]
  , examples (OrdinalData 10)
             [ "decimo"
             , "decimas"
             , "dÃ©cimos"
             ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.ES.Rules
  ( rules ) where

import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text as Text
import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Ordinal.Helpers
import Duckling.Regex.Types
import Duckling.Types

ordinalsMap :: HashMap.HashMap Text.Text Int
ordinalsMap = HashMap.fromList
  [ ( "primer" , 1 )
  , ( "primero" , 1 )
  , ( "primeros" , 1 )
  , ( "primera" , 1 )
  , ( "primeras" , 1 )
  , ( "segundo" , 2 )
  , ( "segunda" , 2 )
  , ( "segundas" , 2 )
  , ( "segundos" , 2 )
  , ( "terceros" , 3 )
  , ( "tercera" , 3 )
  , ( "terceras" , 3 )
  , ( "tercero" , 3 )
  , ( "tercer" , 3 )
  , ( "cuarta" , 4 )
  , ( "cuartas" , 4 )
  , ( "cuartos" , 4 )
  , ( "cuarto" , 4 )
  , ( "quinto" , 5 )
  , ( "quinta" , 5 )
  , ( "quintas" , 5 )
  , ( "quintos" , 5 )
  , ( "sextos" , 6 )
  , ( "sexto" , 6 )
  , ( "sexta" , 6 )
  , ( "sextas" , 6 )
  , ( "sÃ©ptimas" , 7 )
  , ( "septimas" , 7 )
  , ( "sÃ©ptima" , 7 )
  , ( "septimos" , 7 )
  , ( "septima" , 7 )
  , ( "sÃ©ptimo" , 7 )
  , ( "sÃ©ptimos" , 7 )
  , ( "septimo" , 7 )
  , ( "octavas" , 8 )
  , ( "octavo" , 8 )
  , ( "octavos" , 8 )
  , ( "octava" , 8 )
  , ( "novenos" , 9 )
  , ( "novena" , 9 )
  , ( "noveno" , 9 )
  , ( "novenas" , 9 )
  , ( "dÃ©cimos" , 10 )
  , ( "decimo" , 10 )
  , ( "decimos" , 10 )
  , ( "dÃ©cimo" , 10 )
  , ( "decimas" , 10 )
  , ( "dÃ©cima" , 10 )
  , ( "decima" , 10 )
  , ( "dÃ©cimas" , 10 )
  ]

ruleOrdinalsPrimero :: Rule
ruleOrdinalsPrimero = Rule
  { name = "ordinals (primero..10)"
  , pattern =
    [ regex "((primer|segund|tercer|cuart|quint|sext|s[eÃ©]ptim|octav|noven|d[eÃ©]cim)(os?|as?)|(prim|terc)er)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsMap
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinalsPrimero
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.ET.Corpus
  ( corpus ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale ET Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples =
  examples (OrdinalData 4)
           [ "4."
           , "neljas"
           , "Neljas"
           ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.ET.Rules
  ( rules ) where

import Data.HashMap.Strict (HashMap)
import Data.String
import Data.Text (Text)
import Prelude
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text as Text

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Helpers
import Duckling.Regex.Types
import Duckling.Types

ordinalsMap :: HashMap Text Int
ordinalsMap = HashMap.fromList
 [ ("esimene", 1)
 , ("teine", 2)
 , ("kolmas", 3)
 , ("neljas", 4)
 , ("viies", 5)
 , ("kuues", 6)
 , ("seitsmes", 7)
 , ("kaheksas", 8)
 , ("Ã¼heksas", 9)
 , ("kÃ¼mnes", 10)
 , ("Ã¼heteistkÃ¼mnes", 11)
 , ("kaheteistkÃ¼mnes", 12)
 , ("kolmeteistkÃ¼mnes", 13)
 , ("neljateistkÃ¼mnes", 14)
 , ("viieteistkÃ¼mnes", 15)
 , ("kuueteistkÃ¼mnes", 16)
 , ("seitsmeteistkÃ¼mnes", 17)
 , ("kaheksateistkÃ¼mnes", 18)
 , ("Ã¼heksateistkÃ¼mnes", 19)
 ]

ruleOrdinalsFirstth :: Rule
ruleOrdinalsFirstth = Rule
  { name = "ordinals (first..19th)"
  , pattern =
    [ regex "(esimene|teine|kolmas|neljas|viies|kuues|seitsmes|kaheksas|Ã¼heksas|kÃ¼mnes|Ã¼heteistkÃ¼mnes|kaheteistkÃ¼mnes|kolmeteistkÃ¼mnes|neljateistkÃ¼mnes|viieteistkÃ¼mnes|kuueteistkÃ¼mnes|seitsmeteistkÃ¼mnes|kaheksateistkÃ¼mnes|Ã¼heksateistkÃ¼mnes)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsMap
      _ -> Nothing
  }

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern =
    [ regex "0*(\\d+)\\."
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinalDigits
  , ruleOrdinalsFirstth
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.FR.Corpus
  ( corpus ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale FR Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (OrdinalData 1)
             [ "1er"
             , "1ere"
             , "1Ã¨re"
             , "Premier"
             , "premiÃ¨re"
             ]
  , examples (OrdinalData 2)
             [ "deuxieme"
             , "deuxiÃ¨me"
             , "2e"
             , "second"
             , "2eme"
             , "2Ã¨me"
             ]
  , examples (OrdinalData 11)
             [ "onzieme"
             , "onziÃ¨me"
             , "11eme"
             , "11Ã¨me"
             , "11e"
             ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.FR.Rules
  ( rules
  ) where

import Data.HashMap.Strict ( HashMap)
import Data.String
import Data.Text (Text)
import Prelude
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text as Text

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Helpers
import Duckling.Regex.Types (GroupMatch (..))
import Duckling.Types

ordinalsMap :: HashMap Text Int
ordinalsMap = HashMap.fromList
  [ ( "premiÃ¨re", 1 )
  , ( "premiere", 1 )
  , ( "premier", 1 )
  , ( "deuxiÃ¨me", 2 )
  , ( "deuxieme", 2 )
  , ( "second", 2 )
  , ( "seconde", 2 )
  , ( "troisiÃ¨me", 3 )
  , ( "troisieme", 3 )
  , ( "quatrieme", 4 )
  , ( "quatriÃ¨me", 4 )
  , ( "cinquieme", 5 )
  , ( "cinquiÃ¨me", 5 )
  , ( "sixiÃ¨me", 6 )
  , ( "sixieme", 6 )
  , ( "septieme", 7 )
  , ( "septiÃ¨me", 7 )
  , ( "huitiÃ¨me", 8 )
  , ( "huitieme", 8 )
  , ( "neuvieme", 9 )
  , ( "neuviÃ¨me", 9 )
  , ( "dixiÃ¨me", 10 )
  , ( "dixieme", 10 )
  , ( "onziÃ¨me", 11 )
  , ( "onzieme", 11 )
  , ( "douzieme", 12 )
  , ( "douziÃ¨me", 12 )
  , ( "treizieme", 13 )
  , ( "treiziÃ¨me", 13 )
  , ( "quatorziÃ¨me", 14 )
  , ( "quatorzieme", 14 )
  , ( "quinziÃ¨me", 15 )
  , ( "quinzieme", 15 )
  , ( "seizieme", 16 )
  , ( "seiziÃ¨me", 16 )
  ]

ruleOrdinalsPremierseizieme :: Rule
ruleOrdinalsPremierseizieme = Rule
  { name = "ordinals (premier..seizieme)"
  , pattern =
    [ regex "(premi(ere?|Ã¨re)|(deux|trois|quatr|cinqu|six|sept|huit|neuv|dix|onz|douz|treiz|quatorz|quinz|seiz)i(e|Ã¨)me|seconde?)"
    ]
  , prod = \case
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsMap
      _ -> Nothing
  }

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern =
    [ regex "0*(\\d+) ?(ere?|Ã¨re|Ã¨me|eme|e)"
    ]
  , prod = \case
      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinalDigits
  , ruleOrdinalsPremierseizieme
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.GA.Corpus
  ( corpus ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale GA Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (OrdinalData 6)
             [ "sÃ©u"
             , "6a"
             , "6d"
             , "06u"
             , "6 Ãº"
             , "0006 adh"
             ]
  , examples (OrdinalData 1)
             [ "chead"
             , "t-aonu"
             , "t-aonÃº"
             , "Aonu"
             , "aonÃº"
             ]
  , examples (OrdinalData 30)
             [ "trÃochadÃº"
             , "triochadÃº"
             , "trÃochadu"
             ]
  , examples (OrdinalData 50)
             [ "caogadu"
             , "caogadÃº"
             ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.GA.Rules
  ( rules ) where

import qualified Data.Text as Text
import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Helpers
import Duckling.Regex.Types
import Duckling.Types

ruleOrdinalsChadDaraEtc :: Rule
ruleOrdinalsChadDaraEtc = Rule
  { name = "ordinals (chÃ©ad, dara, etc.)"
  , pattern =
    [ regex "(ch(Ã©|e)ad|aon(Ãº|u)|t-aon(Ãº|u)|dara|tr(Ã|i)(Ãº|u)|ceathr(Ãº|u)|c(Ãº|u)igi(Ãº|u)|s(Ã©|e)(Ãº|u)|seacht(Ãº|u)|ocht(Ãº|u)|t-ocht(Ãº|u)|nao(Ãº|u)|deichi(Ãº|u)|fichi(Ãº|u)|tr(Ã|i)ochad(Ãº|u)|daichead(Ãº|u)|caogad(Ãº|u)|seascad(Ãº|u)|seacht(Ã³|o)d(Ãº|u)|ocht(Ã³|o)d(Ãº|u)|t-ocht(Ã³|o)d(Ãº|u)|n(Ã³|o)chad(Ãº|u)|c(Ã©|e)ad(Ãº|u)|mili(Ãº|u)|milli(Ãº|u)n(Ãº|u))"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of
        "t-aonu" -> Just $ ordinal 1
        "aonu" -> Just $ ordinal 1
        "aonÃº" -> Just $ ordinal 1
        "chÃ©ad" -> Just $ ordinal 1
        "chead" -> Just $ ordinal 1
        "t-aonÃº" -> Just $ ordinal 1
        "dara" -> Just $ ordinal 2
        "triÃº" -> Just $ ordinal 3
        "trÃu" -> Just $ ordinal 3
        "trÃÃº" -> Just $ ordinal 3
        "triu" -> Just $ ordinal 3
        "ceathrÃº" -> Just $ ordinal 4
        "ceathru" -> Just $ ordinal 4
        "cÃºigiu" -> Just $ ordinal 5
        "cÃºigiÃº" -> Just $ ordinal 5
        "cuigiu" -> Just $ ordinal 5
        "cuigiÃº" -> Just $ ordinal 5
        "sÃ©u" -> Just $ ordinal 6
        "sÃ©Ãº" -> Just $ ordinal 6
        "seu" -> Just $ ordinal 6
        "seÃº" -> Just $ ordinal 6
        "seachtu" -> Just $ ordinal 7
        "seachtÃº" -> Just $ ordinal 7
        "t-ochtÃº" -> Just $ ordinal 8
        "ochtu" -> Just $ ordinal 8
        "t-ochtu" -> Just $ ordinal 8
        "ochtÃº" -> Just $ ordinal 8
        "naou" -> Just $ ordinal 9
        "naoÃº" -> Just $ ordinal 9
        "deichiu" -> Just $ ordinal 10
        "deichiÃº" -> Just $ ordinal 10
        "fichiu" -> Just $ ordinal 20
        "fichiÃº" -> Just $ ordinal 20
        "trÃochadu" -> Just $ ordinal 30
        "triochadu" -> Just $ ordinal 30
        "trÃochadÃº" -> Just $ ordinal 30
        "triochadÃº" -> Just $ ordinal 30
        "daicheadÃº" -> Just $ ordinal 40
        "daicheadu" -> Just $ ordinal 40
        "caogadu" -> Just $ ordinal 50
        "caogadÃº" -> Just $ ordinal 50
        "seascadu" -> Just $ ordinal 60
        "seascadÃº" -> Just $ ordinal 60
        "seachtodu" -> Just $ ordinal 70
        "seachtodÃº" -> Just $ ordinal 70
        "seachtÃ³dÃº" -> Just $ ordinal 70
        "seachtÃ³du" -> Just $ ordinal 70
        "ochtÃ³du" -> Just $ ordinal 80
        "ochtodu" -> Just $ ordinal 80
        "t-ochtodu" -> Just $ ordinal 80
        "t-ochtÃ³dÃº" -> Just $ ordinal 80
        "t-ochtodÃº" -> Just $ ordinal 80
        "ochtÃ³dÃº" -> Just $ ordinal 80
        "t-ochtÃ³du" -> Just $ ordinal 80
        "ochtodÃº" -> Just $ ordinal 80
        "nÃ³chadÃº" -> Just $ ordinal 90
        "nÃ³chadu" -> Just $ ordinal 90
        "nochadÃº" -> Just $ ordinal 90
        "nochadu" -> Just $ ordinal 90
        "cÃ©adÃº" -> Just $ ordinal 100
        "ceadÃº" -> Just $ ordinal 100
        "ceadu" -> Just $ ordinal 100
        "cÃ©adu" -> Just $ ordinal 100
        "miliu" -> Just $ ordinal 1000
        "miliÃº" -> Just $ ordinal 1000
        "milliunÃº" -> Just $ ordinal 1000000
        "milliunu" -> Just $ ordinal 1000000
        "milliÃºnu" -> Just $ ordinal 1000000
        "milliÃºnÃº" -> Just $ ordinal 1000000
        _ -> Nothing
      _ -> Nothing
  }

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern =
    [ regex "0*(\\d+) ?(adh|a|d|Ãº|u)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinalDigits
  , ruleOrdinalsChadDaraEtc
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.HU.Corpus
  ( corpus ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale HU Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (OrdinalData 1)
             [ "elsÅ‘"
             , "1."
             ]
  , examples (OrdinalData 2)
             [ "mÃ¡sodik"
             , "2."
             ]
  , examples (OrdinalData 3)
             [ "harmadik"
             , "3."
             ]
  , examples (OrdinalData 4)
             [ "negyedik"
             , "4."
             ]
  , examples (OrdinalData 8)
             [ "nyolcadik"
             , "8."
             ]
  , examples (OrdinalData 25)
             [ "huszonÃ¶tÃ¶dik"
             , "25."
             ]
  , examples (OrdinalData 31)
             [ "harmincegyedik"
             , "31."
             ]
  , examples (OrdinalData 42)
             [ "negyvenkettedik"
             , "42."
             ]
  , examples (OrdinalData 77)
            [ "hetvenhetedik"
            , "77."
            ]
  , examples (OrdinalData 90)
            [ "kilencvenedik"
            , "90."
            ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.HU.Rules
  ( rules ) where

import Control.Monad (join)
import Data.HashMap.Strict ( HashMap)
import Data.String
import Data.Text (Text)
import Prelude
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text as Text

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Helpers
import Duckling.Regex.Types
import Duckling.Types

ordinalsMap :: HashMap Text Int
ordinalsMap = HashMap.fromList
  [ ( "elsÅ‘", 1 )
  , ( "mÃ¡sodik", 2 )
  , ( "harmadik", 3 )
  , ( "negyedik", 4 )
  , ( "Ã¶tÃ¶dik", 5 )
  , ( "hatodik", 6 )
  , ( "hetedik", 7 )
  , ( "nyolcadik", 8 )
  , ( "kilencedik", 9 )
  , ( "tizedik", 10 )
  , ( "huszadik", 20 )
  , ( "harmincadik", 30 )
  , ( "negyvenedik", 40 )
  , ( "Ã¶tvenedik", 50 )
  , ( "hatvanadik", 60 )
  , ( "hetvenedik", 70 )
  , ( "nyolcvanadik", 80 )
  , ( "kilencvenedik", 90 )
  ]

ordinalsMap2 :: HashMap Text Int
ordinalsMap2 = HashMap.fromList
    [ ( "egyedik", 1 )
    , ( "kettedik", 2 )
    , ( "harmadik", 3 )
    , ( "negyedik", 4 )
    , ( "Ã¶tÃ¶dik", 5 )
    , ( "hatodik", 6 )
    , ( "hetedik", 7 )
    , ( "nyolcadik", 8 )
    , ( "kilencedik", 9 )
    ]

cardinalsMap :: HashMap Text Int
cardinalsMap = HashMap.fromList
  [ ( "tizen", 10 )
  , ( "huszon", 20 )
  , ( "harminc", 30 )
  , ( "negyven", 40 )
  , ( "Ã¶tven", 50 )
  , ( "hatvan", 60 )
  , ( "hetven", 70 )
  , ( "nyolcvan", 80 )
  , ( "kilencven", 90 )
  ]

ruleOrdinals :: Rule
ruleOrdinals = Rule
  { name = "ordinals (first..twentieth,thirtieth,...)"
  , pattern =
    [ regex "(elsÅ‘|mÃ¡sodik|harmadik|negyedik|Ã¶tÃ¶dik|hatodik|hetedik|nyolcadik|kilencedik|tizedik|huszadik|harmincadik|negyvenedik|Ã¶tvenedik|hatvanadik|hetvenedik|nyolcvanadik|kilencvenedik)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsMap
      _ -> Nothing
    }

ruleCompositeOrdinals :: Rule
ruleCompositeOrdinals = Rule
  { name = "ordinals (composite, e.g., eighty-seven)"
  , pattern =
    [ regex "(tizen|huszon|harminc|negyven|Ã¶tven|hatvan|hetven|nyolcvan|kilencven)\\-?(egyedik|kettedik|harmadik|negyedik|Ã¶tÃ¶dik|hatodik|hetedik|nyolcadik|kilencedik)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (tens:units:_)):_) -> do
        tt <- HashMap.lookup (Text.toLower tens) cardinalsMap
        uu <- HashMap.lookup (Text.toLower units) ordinalsMap2
        Just . ordinal $ tt + uu
      _ -> Nothing
  }

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern =
    [ regex "0*(\\d+)\\."
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinals
  , ruleCompositeOrdinals
  , ruleOrdinalDigits
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.ID.Corpus
  ( corpus ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale ID Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (OrdinalData 4)
             [ "ke-4"
             , "keempat"
             ]
  , examples (OrdinalData 10)
             [ "Kesepuluh"
             ]
  , examples (OrdinalData 3)
             [ "ketiga"
             , "ke-00003"
             ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.ID.Rules
  ( rules ) where

import qualified Data.Text as Text
import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Helpers
import Duckling.Regex.Types
import Duckling.Types

ruleOrdinals :: Rule
ruleOrdinals = Rule
  { name = "ordinals"
  , pattern =
    [ regex "(pertama|kedua|ketiga|keempat|kelima|keenam|ketujuh|kedelapan|kesembilan|kesepuluh)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of
        "pertama" -> Just $ ordinal 1
        "kedua" -> Just $ ordinal 2
        "ketiga" -> Just $ ordinal 3
        "keempat" -> Just $ ordinal 4
        "kelima" -> Just $ ordinal 5
        "keenam" -> Just $ ordinal 6
        "ketujuh" -> Just $ ordinal 7
        "kedelapan" -> Just $ ordinal 8
        "kesembilan" -> Just $ ordinal 9
        "kesepuluh" -> Just $ ordinal 10
        _ -> Nothing
      _ -> Nothing
  }

ruleOrdinalsDigits :: Rule
ruleOrdinalsDigits = Rule
  { name = "ordinals (digits)"
  , pattern =
    [ regex "ke-0*(\\d+)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinals
  , ruleOrdinalsDigits
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.IT.Corpus
  ( corpus ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale IT Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (OrdinalData 1)
             [ "primo"
             , "prima"
             , "1Â°"
             , "1Âª"
             ]
  , examples (OrdinalData 2)
             [ "secondo"
             , "seconda"
             , "2Â°"
             , "2Âª"
             ]
  , examples (OrdinalData 3)
             [ "terzo"
             , "Terza"
             , "3Â°"
             , "3Âª"
             ]
  , examples (OrdinalData 4)
             [ "quarto"
             , "quarta"
             , "4Â°"
             , "4Âª"
             ]
  , examples (OrdinalData 5)
             [ "quinto"
             , "quinta"
             , "5Â°"
             , "5Âª"
             ]
  , examples (OrdinalData 6)
             [ "sesto"
             , "sesta"
             , "6Â°"
             , "6Âª"
             ]
  , examples (OrdinalData 7)
             [ "settimo"
             , "settima"
             , "7Â°"
             , "7Âª"
             ]
  , examples (OrdinalData 8)
             [ "ottavo"
             , "ottava"
             , "8Â°"
             , "8Âª"
             ]
  , examples (OrdinalData 9)
             [ "nono"
             , "nona"
             , "9Â°"
             , "9Âª"
             ]
  , examples (OrdinalData 10)
             [ "decimo"
             , "decima"
             , "10Â°"
             , "10Âª"
             ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.IT.Rules
  ( rules ) where

import qualified Data.Text as Text
import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Helpers
import Duckling.Regex.Types
import Duckling.Types

ruleOrdinalsPrimo :: Rule
ruleOrdinalsPrimo = Rule
  { name = "ordinals (primo..10)"
  , pattern =
    [ regex "((prim|second|terz|quart|quint|sest|settim|ottav|non|decim)(o|a|i|e))"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of
        "primi" -> Just $ ordinal 1
        "prima" -> Just $ ordinal 1
        "primo" -> Just $ ordinal 1
        "prime" -> Just $ ordinal 1
        "seconda" -> Just $ ordinal 2
        "secondi" -> Just $ ordinal 2
        "seconde" -> Just $ ordinal 2
        "secondo" -> Just $ ordinal 2
        "terze" -> Just $ ordinal 3
        "terzi" -> Just $ ordinal 3
        "terzo" -> Just $ ordinal 3
        "terza" -> Just $ ordinal 3
        "quarte" -> Just $ ordinal 4
        "quarto" -> Just $ ordinal 4
        "quarta" -> Just $ ordinal 4
        "quarti" -> Just $ ordinal 4
        "quinto" -> Just $ ordinal 5
        "quinta" -> Just $ ordinal 5
        "quinti" -> Just $ ordinal 5
        "quinte" -> Just $ ordinal 5
        "sesti" -> Just $ ordinal 6
        "seste" -> Just $ ordinal 6
        "sesta" -> Just $ ordinal 6
        "sesto" -> Just $ ordinal 6
        "settimi" -> Just $ ordinal 7
        "settima" -> Just $ ordinal 7
        "settimo" -> Just $ ordinal 7
        "settime" -> Just $ ordinal 7
        "ottavo" -> Just $ ordinal 8
        "ottava" -> Just $ ordinal 8
        "ottavi" -> Just $ ordinal 8
        "ottave" -> Just $ ordinal 8
        "none" -> Just $ ordinal 9
        "noni" -> Just $ ordinal 9
        "nona" -> Just $ ordinal 9
        "nono" -> Just $ ordinal 9
        "decimo" -> Just $ ordinal 10
        "decima" -> Just $ ordinal 10
        "decime" -> Just $ ordinal 10
        "decimi" -> Just $ ordinal 10
        _ -> Nothing
      _ -> Nothing
  }

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern =
    [ regex "0*(\\d+) ?(Âª|Â°|Â°)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinalDigits
  , ruleOrdinalsPrimo
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.JA.Corpus
  ( corpus ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale JA Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples =
  examples (OrdinalData 7)
           [ "ç¬¬ä¸ƒ"
           ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.JA.Rules
  ( rules ) where

import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Numeral.Types (NumeralData (..))
import qualified Duckling.Numeral.Types as TNumeral
import Duckling.Ordinal.Helpers
import Duckling.Types

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern =
    [ regex "ç¬¬"
    , dimension Numeral
    ]
  , prod = \tokens -> case tokens of
      (_:Token Numeral NumeralData{TNumeral.value = v}:_) ->
        Just . ordinal $ floor v
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinalDigits
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.KM.Corpus
  ( corpus
  ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

context :: Context
context = testContext{locale = makeLocale KM Nothing}

corpus :: Corpus
corpus = (context, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (OrdinalData 1)
             [ "áž‘áž¸áž˜áž½áž™"
             , "áž‘áž¸áŸ¡"
             ]
  , examples (OrdinalData 400)
             [ "áž‘áž¸áž”áž½áž“ážšáž™"
             ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.KM.Rules
  ( rules
  ) where

import Data.String
import Prelude

import Duckling.Dimensions.Types
import Duckling.Numeral.Types (NumeralData (..))
import Duckling.Ordinal.Helpers
import Duckling.Types
import qualified Duckling.Numeral.Types as TNumeral

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern =
    [ regex "áž‘áž¸"
    , dimension Numeral
    ]
  , prod = \case
      (_:Token Numeral NumeralData{TNumeral.value = x}:_) ->
        Just . ordinal $ floor x
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinalDigits
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.KO.Rules
  ( rules ) where

import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Ordinal.Helpers
import Duckling.Numeral.Types (NumeralData (..))
import qualified Duckling.Numeral.Types as TNumeral
import Duckling.Types

ruleOrdinals :: Rule
ruleOrdinals = Rule
  { name = "ordinals (ì²«ë²ˆì§¸)"
  , pattern =
    [ dimension Numeral
    , regex "ë²ˆì§¸|ì§¸(ë²ˆ)?"
    ]
  , prod = \tokens -> case tokens of
      (Token Numeral NumeralData{TNumeral.value = v}:_) ->
        Just . ordinal $ floor v
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinals
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.NB.Corpus
  ( corpus ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale NB Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (OrdinalData 4)
             [ "4."
             , "fjerde"
             , "fJerde"
             ]
  , examples (OrdinalData 15)
             [ "15."
             , "femtende"
             ]
  , examples (OrdinalData 5)
             [ "5."
             , "femte"
             ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.NB.Rules
  ( rules ) where

import qualified Data.Text as Text
import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Helpers
import Duckling.Regex.Types
import Duckling.Types

ruleOrdinalsFirstst :: Rule
ruleOrdinalsFirstst = Rule
  { name = "ordinals (first..31st)"
  , pattern =
    [ regex "(fÃ¸rste|andre|tredje|fjerde|femtende|femte|sjette|syvende|Ã¥ttende|niende|tiende|ellevte|tolvte|trettende|fjortende|sekstende|syttende|attende|nittende|tyvende|tjuende|enogtyvende|toogtyvende|treogtyvende|fireogtyvende|femogtyvende|seksogtyvende|syvogtyvende|Ã¥tteogtyvende|niogtyvende|enogtjuende|toogtjuende|treogtjuende|fireogtjuende|femogtjuende|seksogtjuende|syvogtjuende|Ã¥tteogtyvend|niogtjuende|tredefte|enogtredefte)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of
        "fÃ¸rste" -> Just $ ordinal 1
        "andre" -> Just $ ordinal 2
        "tredje" -> Just $ ordinal 3
        "fjerde" -> Just $ ordinal 4
        "femte" -> Just $ ordinal 5
        "sjette" -> Just $ ordinal 6
        "syvende" -> Just $ ordinal 7
        "Ã¥ttende" -> Just $ ordinal 8
        "niende" -> Just $ ordinal 9
        "tiende" -> Just $ ordinal 10
        "ellevte" -> Just $ ordinal 11
        "tolvte" -> Just $ ordinal 12
        "trettende" -> Just $ ordinal 13
        "fjortende" -> Just $ ordinal 14
        "femtende" -> Just $ ordinal 15
        "sekstende" -> Just $ ordinal 16
        "syttende" -> Just $ ordinal 17
        "attende" -> Just $ ordinal 18
        "nittende" -> Just $ ordinal 19
        "tyvende" -> Just $ ordinal 20
        "tjuende" -> Just $ ordinal 20
        "enogtjuende" -> Just $ ordinal 21
        "enogtyvende" -> Just $ ordinal 21
        "toogtyvende" -> Just $ ordinal 22
        "toogtjuende" -> Just $ ordinal 22
        "treogtyvende" -> Just $ ordinal 23
        "treogtjuende" -> Just $ ordinal 23
        "fireogtjuende" -> Just $ ordinal 24
        "fireogtyvende" -> Just $ ordinal 24
        "femogtyvende" -> Just $ ordinal 25
        "femogtjuende" -> Just $ ordinal 25
        "seksogtjuende" -> Just $ ordinal 26
        "seksogtyvende" -> Just $ ordinal 26
        "syvogtyvende" -> Just $ ordinal 27
        "syvogtjuende" -> Just $ ordinal 27
        "Ã¥tteogtyvende" -> Just $ ordinal 28
        "Ã¥tteogtjuende" -> Just $ ordinal 28
        "niogtyvende" -> Just $ ordinal 29
        "niogtjuende" -> Just $ ordinal 29
        "tredefte" -> Just $ ordinal 30
        "enogtredefte" -> Just $ ordinal 31
        _ -> Nothing
      _ -> Nothing
  }

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern =
    [ regex "0*(\\d+)(\\.|ste?)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinalDigits
  , ruleOrdinalsFirstst
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.NL.Corpus
  ( corpus ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale NL Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (OrdinalData 1)
             [ "1ste"
             , "eerste"
             ]
  , examples (OrdinalData 4)
             [ "4de"
             , "vierde"
             ]
  , examples (OrdinalData 17)
             [ "Zeventiende"
             , "17de"
             ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.NL.Rules
  ( rules ) where

import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap
import Data.Text (Text)
import qualified Data.Text as Text
import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Helpers
import Duckling.Regex.Types
import Duckling.Types

zeroNineteenMap :: HashMap Text Int
zeroNineteenMap = HashMap.fromList
  [ ("eerste", 1)
  , ("tweede", 2)
  , ("derde", 3)
  , ("vierde", 4)
  , ("vijfde", 5)
  , ("zesde", 6)
  , ("zevende", 7)
  , ("achste", 8)
  , ("negende", 9)
  , ("tiende", 10)
  , ("elfde", 11)
  , ("twaalfde", 12)
  , ("dertiende", 13)
  , ("veertiende", 14)
  , ("vijftiende", 15)
  , ("zestiende", 16)
  , ("zeventiende", 17)
  , ("achttiende", 18)
  , ("negentiende", 19)
  ]

ruleOrdinalsFirstth :: Rule
ruleOrdinalsFirstth = Rule
  { name = "ordinals (first..19th)"
  , pattern =
    [ regex "(eerste|tweede|derde|vierde|vijfde|zeste|zevende|achtste|negende|tiende|elfde|twaalfde|veertiende|vijftiende|zestiende|zeventiende|achttiende|negentiende)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> HashMap.lookup (Text.toLower match) zeroNineteenMap
      _ -> Nothing
  }

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern =
    [ regex "0*(\\d+)(\\.| ?(ste|de))"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> parseInt match
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinalDigits
  , ruleOrdinalsFirstth
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.PL.Corpus
  ( corpus ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale PL Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples =
  examples (OrdinalData 4)
           [ "4ty"
           , "czwarty"
           ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.PL.Rules
  ( rules ) where

import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Helpers
import Duckling.Ordinal.Types (OrdinalData (..))
import qualified Duckling.Ordinal.Types as TOrdinal
import Duckling.Regex.Types
import Duckling.Types

ruleThOrdinalNoSpace :: Rule
ruleThOrdinalNoSpace = Rule
  { name = "24th ordinal no space"
  , pattern =
    [ regex "dwudziest(ym|y|ego|emu|(a|Ä…)|ej)czwart(y|ego|emu|ym|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 24
  }

ruleThOrdinal16 :: Rule
ruleThOrdinal16 = Rule
  { name = "31-39th ordinal"
  , pattern =
    [ regex "trzydziest(ym|y|ego|emu|(a|Ä…)|ej)( |-)?"
    , dimension Ordinal
    ]
  , prod = \tokens -> case tokens of
      (_:Token Ordinal OrdinalData{TOrdinal.value = v}:_) ->
        Just . ordinal $ 30 + v
      _ -> Nothing
  }

ruleThOrdinal3 :: Rule
ruleThOrdinal3 = Rule
  { name = "10th ordinal"
  , pattern =
    [ regex "dziesi(a|Ä…)t(ym|y|ego|emu|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 10
  }

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern =
    [ regex "0*(\\d+)( |-)?(szy|sza|szym|ego|go|szego|gi(ego|ej)?|st(a|y|ej)|t(ej|y|ego)|ci(ego)?)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match
      _ -> Nothing
  }

ruleThOrdinal8 :: Rule
ruleThOrdinal8 = Rule
  { name = "15th ordinal"
  , pattern =
    [ regex "pi(e|Ä™)tnast(ym|y|ego|emu|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 15
  }

ruleThOrdinal13 :: Rule
ruleThOrdinal13 = Rule
  { name = "20th ordinal"
  , pattern =
    [ regex "dwudziest(ym|y|ego|emu|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 20
  }

ruleThOrdinal4 :: Rule
ruleThOrdinal4 = Rule
  { name = "11th ordinal"
  , pattern =
    [ regex "jedenast(ym|y|ego|emu|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 11
  }

ruleFifthOrdinal :: Rule
ruleFifthOrdinal = Rule
  { name = "fifth ordinal"
  , pattern =
    [ regex "pi(a|Ä…)t(y|ego|emu|m|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 5
  }

ruleThOrdinal11 :: Rule
ruleThOrdinal11 = Rule
  { name = "18th ordinal"
  , pattern =
    [ regex "osiemnast(ym|y|ego|emu|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 18
  }

ruleSecondOrdinal :: Rule
ruleSecondOrdinal = Rule
  { name = "second ordinal"
  , pattern =
    [ regex "drugi?(ego|emu|m|(a|Ä…)|ej)?"
    ]
  , prod = \_ -> Just $ ordinal 2
  }

ruleNdOrdinalNoSpace :: Rule
ruleNdOrdinalNoSpace = Rule
  { name = "22nd ordinal no space"
  , pattern =
    [ regex "dwudziest(ym|y|ego|emu|(a|Ä…)|ej)drugi?(ego|emu|m|(a|Ä…)|ej)?"
    ]
  , prod = \_ -> Just $ ordinal 22
  }

ruleSeventhOrdinal :: Rule
ruleSeventhOrdinal = Rule
  { name = "seventh ordinal"
  , pattern =
    [ regex "si(o|Ã³)dm(y|ego|emu|m|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 7
  }

ruleStOrdinalNoSpace :: Rule
ruleStOrdinalNoSpace = Rule
  { name = "21st ordinal no space"
  , pattern =
    [ regex "dwudziest(ym|y|ego|emu|(a|Ä…)|ej)pierw?sz(y|ego|emu|m|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 21
  }

ruleThOrdinal7 :: Rule
ruleThOrdinal7 = Rule
  { name = "14th ordinal"
  , pattern =
    [ regex "czternast(ym|y|ego|emu|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 14
  }

ruleThOrdinal2 :: Rule
ruleThOrdinal2 = Rule
  { name = "9th ordinal"
  , pattern =
    [ regex "dziewi(a|Ä…)t(ym|y|ego|em|emu|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 9
  }

ruleThOrdinal9 :: Rule
ruleThOrdinal9 = Rule
  { name = "16th ordinal"
  , pattern =
    [ regex "szesnast(ym|y|ego|emu|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 16
  }

ruleThOrdinal :: Rule
ruleThOrdinal = Rule
  { name = "8th ordinal"
  , pattern =
    [ regex "(o|Ã³|Ã“)sm(y|ego|emu|m|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 8
  }

ruleThOrdinal14 :: Rule
ruleThOrdinal14 = Rule
  { name = "21-29th ordinal"
  , pattern =
    [ regex "dwudziest(ym|y|ego|emu|(a|Ä…)|ej)( |-)?"
    , dimension Ordinal
    ]
  , prod = \tokens -> case tokens of
      (_:Token Ordinal OrdinalData{TOrdinal.value = v}:_) ->
        Just . ordinal $ 20 + v
      _ -> Nothing
  }

ruleThOrdinal10 :: Rule
ruleThOrdinal10 = Rule
  { name = "17th ordinal"
  , pattern =
    [ regex "siedemnast(ym|y|ego|emu|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 17
  }

ruleRdOrdinalNoSpace :: Rule
ruleRdOrdinalNoSpace = Rule
  { name = "23rd ordinal no space"
  , pattern =
    [ regex "dwudziest(ym|y|ego|emu|(a|Ä…)|ej)trzeci(ego|ch|emu|m|mi|ej|(a|Ä…))?"
    ]
  , prod = \_ -> Just $ ordinal 23
  }

ruleThOrdinal5 :: Rule
ruleThOrdinal5 = Rule
  { name = "12th ordinal"
  , pattern =
    [ regex "dwunast(ym|y|ego|emu|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 12
  }

ruleThOrdinal6 :: Rule
ruleThOrdinal6 = Rule
  { name = "13th ordinal"
  , pattern =
    [ regex "trzynast(ym|y|ego|emu|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 13
  }

ruleFirstOrdinal :: Rule
ruleFirstOrdinal = Rule
  { name = "first ordinal"
  , pattern =
    [ regex "pierw?sz(y|ego|emu|m|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 1
  }

ruleSixthOrdinal :: Rule
ruleSixthOrdinal = Rule
  { name = "sixth ordinal"
  , pattern =
    [ regex "sz(o|Ã³)st(y|ego|emu|m|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 6
  }

ruleFourthOrdinal :: Rule
ruleFourthOrdinal = Rule
  { name = "fourth ordinal"
  , pattern =
    [ regex "czwart(y|ego|emu|ym|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 4
  }

ruleThOrdinal15 :: Rule
ruleThOrdinal15 = Rule
  { name = "30th ordinal"
  , pattern =
    [ regex "trzydziest(ym|y|ego|emu|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 30
  }

ruleThOrdinal12 :: Rule
ruleThOrdinal12 = Rule
  { name = "19th ordinal"
  , pattern =
    [ regex "dziewi(Ä™|e)tnast(ym|y|ego|emu|(a|Ä…)|ej)"
    ]
  , prod = \_ -> Just $ ordinal 19
  }

ruleThirdOrdinal :: Rule
ruleThirdOrdinal = Rule
  { name = "third ordinal"
  , pattern =
    [ regex "trzeci(ego|ch|emu|m|mi|ej|(a|Ä…))?"
    ]
  , prod = \_ -> Just $ ordinal 3
  }

rules :: [Rule]
rules =
  [ ruleFifthOrdinal
  , ruleFirstOrdinal
  , ruleFourthOrdinal
  , ruleNdOrdinalNoSpace
  , ruleOrdinalDigits
  , ruleRdOrdinalNoSpace
  , ruleSecondOrdinal
  , ruleSeventhOrdinal
  , ruleSixthOrdinal
  , ruleStOrdinalNoSpace
  , ruleThOrdinal
  , ruleThOrdinal10
  , ruleThOrdinal11
  , ruleThOrdinal12
  , ruleThOrdinal13
  , ruleThOrdinal14
  , ruleThOrdinal15
  , ruleThOrdinal16
  , ruleThOrdinal2
  , ruleThOrdinal3
  , ruleThOrdinal4
  , ruleThOrdinal5
  , ruleThOrdinal6
  , ruleThOrdinal7
  , ruleThOrdinal8
  , ruleThOrdinal9
  , ruleThOrdinalNoSpace
  , ruleThirdOrdinal
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.PT.Corpus
  ( corpus
  ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale PT Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (OrdinalData 1)
             [ "primeira"
             , "primeiros"
             ]
  , examples (OrdinalData 2)
             [ "Segundo"
             , "segundas"
             ]
  , examples (OrdinalData 7)
             [ "setimo"
             , "sÃ©timo"
             , "sÃ©timas"
             ]
  , examples (OrdinalData 10)
             [ "decimos"
             , "dÃ©cimos"
             , "decima"
             , "dÃ©cima"
             , "decimas"
             , "dÃ©cimas"
             ]
  , examples (OrdinalData 11)
             [ "decimos primeiros"
             , "dÃ©cimos primeiros"
             , "decimo primeiro"
             , "dÃ©cimo primeiro"
             , "decimas primeiras"
             , "dÃ©cimas primeiras"
             , "decima primeira"
             , "dÃ©cima primeira"
             ]
  , examples (OrdinalData 12)
             [ "decimos segundos"
             , "dÃ©cimos segundos"
             , "decimo segundo"
             , "dÃ©cimo segundo"
             , "decimas segundas"
             , "dÃ©cimas segundas"
             , "decima segunda"
             , "dÃ©cima segunda"
             ]
  , examples (OrdinalData 17)
             [ "decimos setimos"
             , "dÃ©cimos setimos"
             , "decimo setimo"
             , "dÃ©cimo sÃ©timo"
             , "decimas setimas"
             , "dÃ©cimas sÃ©timas"
             , "decima setima"
             , "dÃ©cima setima"
             ]
  , examples (OrdinalData 58)
             [ "quinquagÃ©simas oitavas"
             , "qÃ¼inquagesimo oitavo"
             , "quinquagÃ©simo oitavo"
             ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.PT.Rules
  ( rules
  ) where

import Data.HashMap.Strict (HashMap)
import Data.String
import Data.Text (Text)
import Prelude
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text as Text

import Duckling.Dimensions.Types
import Duckling.Ordinal.Helpers
import Duckling.Ordinal.Types (OrdinalData (..))
import Duckling.Regex.Types (GroupMatch (..))
import Duckling.Types
import qualified Duckling.Ordinal.Types as TOrdinal

ordinalsMap :: HashMap Text Int
ordinalsMap = HashMap.fromList
  [ ( "primeir", 1 )
  , ( "segund", 2 )
  , ( "terceir", 3 )
  , ( "quart", 4 )
  , ( "quint", 5 )
  , ( "sext", 6 )
  , ( "setim", 7 )
  , ( "sÃ©tim", 7 )
  , ( "oitav", 8 )
  , ( "non", 9 )
  , ( "decim", 10 )
  , ( "dÃ©cim", 10 )
  ]

ruleOrdinals :: Rule
ruleOrdinals = Rule
  { name = "ordinals (1..10)"
  , pattern =
    [ regex "(primeir|segund|terceir|quart|quint|sext|s[Ã©e]tim|oitav|non|d[Ã©e]cim)[ao]s?"
    ]
  , prod = \case
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsMap
      _ -> Nothing
  }

cardinalsMap :: HashMap Text Int
cardinalsMap = HashMap.fromList
  [ ( "vi", 20 )
  , ( "tri", 30 )
  , ( "quadra", 40 )
  , ( "qÃ¼inqua", 50 )
  , ( "quinqua", 50 )
  , ( "sexa", 60 )
  , ( "septua", 70 )
  , ( "octo", 80 )
  , ( "nona", 90 )
  ]

ruleCardinals :: Rule
ruleCardinals = Rule
  { name = "cardinals (20 .. 90)"
  , pattern =
    [ regex "(vi|tri|quadra|q[Ã¼u]inqua|sexa|septua|octo|nona)g[Ã©e]sim[ao]s?"
    ]
  , prod = \case
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> HashMap.lookup (Text.toLower match) cardinalsMap
      _ -> Nothing
  }

ruleCompositeOrdinals :: Rule
ruleCompositeOrdinals = Rule
  { name = "ordinals (11..19)"
  , pattern =
    [ oneOf [10, 20 .. 90]
    , oneOf [1..9]
    ]
  , prod = \case
      (Token Ordinal OrdinalData{TOrdinal.value = t}:
       Token Ordinal OrdinalData{TOrdinal.value = u}:
       _) -> Just $ ordinal $ t + u
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinals
  , ruleCardinals
  , ruleCompositeOrdinals
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.RO.Corpus
  ( corpus ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale RO Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (OrdinalData 1)
             [ "primul"
             , "prima"
             ]
  , examples (OrdinalData 2)
             [ "al doilea"
             , "al doi-lea"
             , "al doi lea"
             , "al 2-lea"
             , "al 2 lea"
             , "a 2 a"
             , "a 2-a"
             , "a doua"
             ]
  , examples (OrdinalData 3)
             [ "al treilea"
             , "al trei-lea"
             , "a treia"
             , "a 3-lea"
             , "a 3a"
             ]
  , examples (OrdinalData 4)
             [ "a patra"
             , "a patru-lea"
             ]
  , examples (OrdinalData 6)
             [ "al saselea"
             , "al È™aselea"
             , "al sase-lea"
             , "al È™ase-lea"
             , "a sasea"
             , "a È™ase a"
             ]
  , examples (OrdinalData 9)
             [ "al noualea"
             , "al noua-lea"
             , "al noua lea"
             , "al nouÄƒlea"
             , "al nouÄƒ lea"
             , "a noua"
             ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.RO.Rules
  ( rules ) where

import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap
import Data.Maybe
import Data.Text (Text)
import qualified Data.Text as Text
import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Helpers
import Duckling.Regex.Types
import Duckling.Types

rulePrimulDouaPatraNoua :: Rule
rulePrimulDouaPatraNoua = Rule
 { name = "special ordinals"
 , pattern =
   [ regex "(prim(a|ul)|a (patra|[dn]oua))"
   ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of
        "prima"   -> Just $ ordinal 1
        "primul"  -> Just $ ordinal 1
        "a doua"  -> Just $ ordinal 2
        "a patra" -> Just $ ordinal 4
        "a noua"  -> Just $ ordinal 9
        _         -> Nothing
      _ -> Nothing
 }

-- We can't have a generic rule of the form "al?" + Numeral + "(le)?a"
-- It wouldn't match "al optlea"

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinals (digits)"
  , pattern =
    [ regex "al?\\s0*(\\d+)[ -]?(le)?a"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> parseInt match
      _ -> Nothing
  }

ordinalMap :: HashMap Text Int
ordinalMap = HashMap.fromList
  [ ("doi", 2)
  , ("trei", 3)
  , ("patru", 4)
  , ("cinci", 5)
  , ("sase", 6)
  , ("\537ase", 6)
  , ("sapte", 7)
  , ("\537apte", 7)
  , ("opt", 8)
  , ("noua", 9)
  , ("nouÄƒ", 9)
  ]

ruleSpelledOutOrdinals :: Rule
ruleSpelledOutOrdinals = Rule
  { name = "spelled out ordinals"
  , pattern =
    [ regex "al?\\s(doi|trei|patru|cinci|(s|È™)a(s|pt)e|opt|nou(a|Äƒ))[ -]?(le)?a"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> HashMap.lookup (Text.toLower match) ordinalMap
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinalDigits
  , rulePrimulDouaPatraNoua
  , ruleSpelledOutOrdinals
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.SV.Corpus
  ( corpus ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale SV Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (OrdinalData 1)
             [ "fÃ¶rsta"
             , "fÃ¶rste"
             , "1a"
             , "1:a"
             ]
  , examples (OrdinalData 2)
             [ "andra"
             , "andre"
             , "2a"
             , "2:a"
             ]
  , examples (OrdinalData 3)
             [ "tredje"
             , "3e"
             , "3:e"
             ]
  , examples (OrdinalData 4)
             [ "fjÃ¤rde"
             , "4e"
             , "4:e"
             ]
  , examples (OrdinalData 8)
             [ "Ã¥ttonde"
             , "8e"
             , "8:e"
             ]
  , examples (OrdinalData 25)
             [ "tjugofemte"
             , "25e"
             , "25:e"
             ]
  , examples (OrdinalData 31)
             [ "trettiofÃ¶rsta"
             , "trettiofÃ¶rste"
             , "31a"
             , "31:a"
             ]
  , examples (OrdinalData 42)
             [ "fyrtioandra"
             , "fyrtioandre"
             , "42a"
             , "42:a"
             ]
  , examples (OrdinalData 77)
            [ "sjuttiosjunde"
            , "77e"
            , "77:e"
            ]
  , examples (OrdinalData 90)
            [ "nittionde"
            , "90e"
            , "90:e"
            ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.SV.Rules
  ( rules ) where

import Control.Monad (join)
import Data.HashMap.Strict ( HashMap)
import Data.String
import Data.Text (Text)
import Prelude
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text as Text

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Helpers
import Duckling.Regex.Types
import Duckling.Types

ordinalsMap :: HashMap Text Int
ordinalsMap = HashMap.fromList
  [ ( "fÃ¶rsta", 1 )
  , ( "fÃ¶rste", 1 )
  , ( "andra", 2 )
  , ( "andre", 2)
  , ( "tredje", 3 )
  , ( "fjÃ¤rde", 4 )
  , ( "femte", 5 )
  , ( "sjÃ¤tte", 6 )
  , ( "sjunde", 7 )
  , ( "Ã¥ttonde", 8 )
  , ( "nionde", 9 )
  , ( "tionde", 10 )
  , ( "elfte", 11 )
  , ( "tolfte", 12 )
  , ( "trettonde", 13 )
  , ( "fjortonde", 14 )
  , ( "femtonde", 15 )
  , ( "sextonde", 16 )
  , ( "sjuttonde", 17 )
  , ( "artonde", 18 )
  , ( "nittonde", 19 )
  , ( "tjugonde", 20 )
  , ( "trettionde", 30 )
  , ( "fyrtionde", 40 )
  , ( "femtionde", 50 )
  , ( "sextionde", 60 )
  , ( "sjuttionde", 70 )
  , ( "Ã¥ttionde", 80 )
  , ( "nittionde", 90 )
  ]

cardinalsMap :: HashMap Text Int
cardinalsMap = HashMap.fromList
  [ ( "tjugo", 20 )
  , ( "trettio", 30 )
  , ( "fyrtio", 40 )
  , ( "femtio", 50 )
  , ( "sextio", 60 )
  , ( "sjuttio", 70 )
  , ( "Ã¥ttio", 80 )
  , ( "nittio", 90 )
  ]

ruleOrdinals :: Rule
ruleOrdinals = Rule
  { name = "ordinals (first..twentieth,thirtieth,...)"
  , pattern =
    [ regex "(fÃ¶rsta|fÃ¶rste|andra|andre|tredje|fjÃ¤rde|femte|sjÃ¤tte|sjunde|Ã¥ttonde|nionde|tionde|elfte|tolfte|trettionde|fjortonde|femtonde|sextonde|sjuttonde|artonde|nittonde|tjugonde|trettionde|fyrtionde|femtonde|sextionde|sjuttionde|Ã¥ttionde|nittionde)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsMap
      _ -> Nothing
    }

ruleCompositeOrdinals :: Rule
ruleCompositeOrdinals = Rule
  { name = "ordinals (composite, e.g., eighty-seven)"
  , pattern =
    [ regex "(tjugo|trettio|fyrtio|femtio|sextio|sjuttio|Ã¥ttio|nittio)(fÃ¶rsta|fÃ¶rste|andra|andre|tredje|fjÃ¤rde|femte|sjÃ¤tte|sjunde|Ã¥ttonde|nionde)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (tens:units:_)):_) -> do
        tt <- HashMap.lookup (Text.toLower tens) cardinalsMap
        uu <- HashMap.lookup (Text.toLower units) ordinalsMap
        Just . ordinal $ tt + uu
      _ -> Nothing
  }

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern =
    [ regex "0*(\\d+):?(a|e)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinals
  , ruleCompositeOrdinals
  , ruleOrdinalDigits
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.TR.Corpus
  ( corpus ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale TR Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (OrdinalData 4)
             [ "4Ã¼ncÃ¼"
             , "dÃ¶rdÃ¼ncÃ¼"
             , "4."
             , "4'Ã¼ncÃ¼"
             ]
  , examples (OrdinalData 8)
             [ "sekizinci"
             ]
  , examples (OrdinalData 23)
             [ "yirmi Ã¼Ã§Ã¼ncÃ¼"
             ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.TR.Rules
  ( rules ) where

import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap
import Data.Text (Text)
import qualified Data.Text as Text
import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Helpers
import Duckling.Regex.Types
import Duckling.Types

ordinals :: [Text]
ordinals =
  [ "birinci"
  , "ikinci"
  , "Ã¼Ã§Ã¼ncÃ¼"
  , "dÃ¶rdÃ¼ncÃ¼"
  , "beÅŸinci"
  , "altÄ±ncÄ±"
  , "yedinci"
  , "sekizinci"
  , "dokuzuncu"
  , "onuncu"
  , "on birinci"
  , "on ikinci"
  , "on Ã¼Ã§Ã¼ncÃ¼"
  , "on dÃ¶rdÃ¼ncÃ¼"
  , "on beÅŸinci"
  , "on altÄ±ncÄ±"
  , "on yedinci"
  , "on sekizinci"
  , "on dokuzuncu"
  , "yirminci"
  , "yirmi birinci"
  , "yirmi ikinci"
  , "yirmi Ã¼Ã§Ã¼ncÃ¼"
  , "yirmi dÃ¶rdÃ¼ncÃ¼"
  , "yirmi beÅŸinci"
  , "yirmi altÄ±ncÄ±"
  , "yirmi yedinci"
  , "yirmi sekizinci"
  , "yirmi dokuzuncu"
  , "otuzuncu"
  , "otuz birinci"
  ]

ordinalsHashMap :: HashMap Text Int
ordinalsHashMap = HashMap.fromList $ zip ordinals [1..]

ruleOrdinalsFirstst :: Rule
ruleOrdinalsFirstst = Rule
  { name = "ordinals (first..31st)"
  , pattern =
    [ regex . Text.unpack $
        Text.concat [ "(", Text.intercalate "|" ordinals, ")" ]
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsHashMap
      _ -> Nothing
  }

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern =
    [ regex "0*(\\d+) ?('?)(inci|nci|Ä±ncÄ±|ncÄ±|uncu|ncu|Ã¼ncÃ¼|ncÃ¼|.)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (match:_)):_) ->
        ordinal <$> parseInt match
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinalDigits
  , ruleOrdinalsFirstst
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.VI.Corpus
  ( corpus ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.Ordinal.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale VI Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (OrdinalData 1)
             [ "Ä‘áº§u tiÃªn"
             , "thá»© nháº¥t"
             , "thá»© 1"
             ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.VI.Rules
  ( rules ) where

import Data.String
import Prelude

import Duckling.Dimensions.Types
import Duckling.Ordinal.Helpers
import Duckling.Types

ruleOrdinals :: Rule
ruleOrdinals = Rule
  { name = "ordinals"
  , pattern =
    [ regex "(Ä‘áº§u tiÃªn|thá»© nháº¥t|thá»© 1)"
    ]
  , prod = \_ -> Just $ ordinal 1
  }

rules :: [Rule]
rules =
  [ ruleOrdinals
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Ordinal.ZH.Rules
  ( rules ) where

import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Numeral.Types (NumeralData(..))
import qualified Duckling.Numeral.Types as TNumeral
import Duckling.Ordinal.Helpers
import Duckling.Types

ruleOrdinalDigits :: Rule
ruleOrdinalDigits = Rule
  { name = "ordinal (digits)"
  , pattern =
    [ regex "ç¬¬"
    , dimension Numeral
    ]
  , prod = \tokens -> case tokens of
      (_:Token Numeral NumeralData{TNumeral.value = x}:_) ->
        Just . ordinal $ floor x
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleOrdinalDigits
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.PhoneNumber.Corpus
  ( corpus
  , negativeCorpus
  ) where

import Prelude
import Data.String

import Duckling.PhoneNumber.Types
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext, testOptions, allExamples)

negativeCorpus :: NegativeCorpus
negativeCorpus = (testContext, testOptions, examples)
  where
    examples =
      [ "12345"
      , "1234567890123456777777"
      , "12345678901234567"
      ]

allExamples :: [Example]
allExamples = concat
  [ examples (PhoneNumberValue "6507018887")
             [ "650-701-8887"
             ]
  , examples (PhoneNumberValue "(+1) 6507018887")
             [ "(+1)650-701-8887"
             , "(+1)   650 - 701  8887"
             , "(+1) 650-701-8887"
             , "+1 6507018887"
             ]
  , examples (PhoneNumberValue "(+33) 146647998")
             [ "+33 1 46647998"
             ]
  , examples (PhoneNumberValue "0620702220")
             [ "06 2070 2220"
             ]
  , examples (PhoneNumberValue "6507018887 ext 897")
             [ "(650)-701-8887 ext 897"
             ]
  , examples (PhoneNumberValue "(+1) 2025550121")
             [ "+1-202-555-0121"
             , "+1 202.555.0121"
             ]
  , examples (PhoneNumberValue "4866827")
             [ "4.8.6.6.8.2.7"
             ]
  , examples (PhoneNumberValue "06354640807")
             [ "06354640807"
             ]
  , examples (PhoneNumberValue "18998078030")
             [ "18998078030"
             ]
  , examples (PhoneNumberValue "61992852776")
             [ "61 - 9 9285-2776"
             ]
  , examples (PhoneNumberValue "19997424919")
             [ "(19) 997424919"
             ]
  , examples (PhoneNumberValue "(+55) 19992842606")
             [ "+55 19992842606"
             ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.PhoneNumber.Rules
  ( rules ) where

import qualified Data.Text as Text
import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.PhoneNumber.Types (PhoneNumberData(..))
import qualified Duckling.PhoneNumber.Types as TPhoneNumber
import Duckling.Regex.Types
import Duckling.Types

rulePhoneNumber :: Rule
rulePhoneNumber = Rule
  { name = "phone number"
  , pattern =
    -- We somewhat arbitrarly use 20 here to limit the length of matches,
    -- otherwise due to backtracking the regexp will take very long time
    -- or run out of stack for some inputs.
    [ regex $
        "(?:\\(?\\+(\\d{1,2})\\)?[\\s-\\.]*)?" ++ -- area code
        "((?=[-\\d()\\s\\.]{6,16}(?:\\s*e?xt?\\.?\\s*(?:\\d{1,20}))?(?:[^\\d]+|$))(?:[\\d(]{1,20}(?:[-)\\s\\.]*\\d{1,20}){0,20}){1,20})" ++ -- nums
        "(?:\\s*e?xt?\\.?\\s*(\\d{1,20}))?" -- extension
    ]
  , prod = \xs -> case xs of
      (Token RegexMatch (GroupMatch (code:nums:ext:_)):_) ->
        let parseNum x = toInteger <$> parseInt x
            mcode = parseNum code
            mext = parseNum ext
            cleanup = Text.filter (not . isWhitespace)
            isWhitespace x = elem x ['.', ' ', '-', '\t', '(', ')']
        in Just . Token PhoneNumber $ PhoneNumberData
          { TPhoneNumber.prefix = mcode
          , TPhoneNumber.number = cleanup nums
          , TPhoneNumber.extension = mext
          }
      _ -> Nothing
  }

rules :: [Rule]
rules = [ rulePhoneNumber ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE NoRebindableSyntax #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}

module Duckling.PhoneNumber.Types where

import Control.DeepSeq
import Data.Aeson
import Data.Hashable
import Data.Monoid
import Data.Text (Text)
import qualified Data.Text as Text
import GHC.Generics
import qualified TextShow as TS

import Prelude

import Duckling.Resolve (Resolve(..))

data PhoneNumberData = PhoneNumberData
  { prefix :: Maybe Integer
  , number :: Text
  , extension :: Maybe Integer
  }
  deriving (Eq, Generic, Hashable, Ord, Show, NFData)

instance Resolve PhoneNumberData where
  type ResolvedValue PhoneNumberData = PhoneNumberValue
  resolve _ _ PhoneNumberData {prefix, number, extension} = Just
    (PhoneNumberValue {value = Text.concat [p, number, e]}, False)
    where
      p = case prefix of
        Just p -> "(+" <> TS.showt p <> ") "
        Nothing -> ""
      e = case extension of
        Just e -> " ext " <> TS.showt e
        Nothing -> ""

data PhoneNumberValue = PhoneNumberValue { value :: Text }
  deriving (Eq, Ord, Show)

instance ToJSON PhoneNumberValue where
  toJSON (PhoneNumberValue value) = object
    [ "value" .= value
    , "type"  .= ("value" :: Text)
    ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE OverloadedStrings #-}

module Duckling.PhoneNumber.PT.Corpus
  ( corpus
  ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.PhoneNumber.Types
import Duckling.Resolve
import Duckling.Testing.Types

corpus :: Corpus
corpus = (testContext {locale = makeLocale PT Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (PhoneNumberValue "6502834757 ext 897")
             [ "(650)-283-4757 ramal 897"
             ]
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.PhoneNumber.PT.Rules
  ( rules ) where

import Data.String
import Prelude
import qualified Data.Text as Text

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.PhoneNumber.Types (PhoneNumberData(..))
import Duckling.Regex.Types
import Duckling.Types
import qualified Duckling.PhoneNumber.Types as TPhoneNumber

rulePhoneNumber :: Rule
rulePhoneNumber = Rule
  { name = "phone number"
  , pattern =
    -- We somewhat arbitrarly use 20 here to limit the length of matches,
    -- otherwise due to backtracking the regexp will take very long time
    -- or run out of stack for some inputs.
    [ regex $
        "(?:\\(?\\+(\\d{1,2})\\)?[\\s-\\.]*)?" ++ -- area code
        "((?=[-\\d()\\s\\.]{6,16}(?:\\s*ramal\\.?\\s*(?:\\d{1,20}))?(?:[^\\d]+|$))(?:[\\d(]{1,20}(?:[-)\\s\\.]*\\d{1,20}){0,20}){1,20})" ++ -- nums
        "(?:\\s*ramal\\.?\\s*(\\d{1,20}))?" -- extension
    ]
  , prod = \xs -> case xs of
      (Token RegexMatch (GroupMatch (code:nums:ext:_)):_) ->
        let parseNum x = toInteger <$> parseInt x
            mcode = parseNum code
            mext = parseNum ext
            cleanup = Text.filter (not . isWhitespace)
            isWhitespace x = elem x ['.', ' ', '-', '\t', '(', ')']
        in Just . Token PhoneNumber $ PhoneNumberData
          { TPhoneNumber.prefix = mcode
          , TPhoneNumber.number = cleanup nums
          , TPhoneNumber.extension = mext
          }
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ rulePhoneNumber
  ]


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE GADTs #-}

module Duckling.Quantity.Helpers
  ( getValue
  , isSimpleQuantity
  , quantity
  , unitOnly
  , valueOnly
  , withProduct
  , withUnit
  , withValue
  , withInterval
  , withMin
  , withMax
  , mkLatent
  ) where

import Data.HashMap.Strict (HashMap)
import Data.Text (Text)
import Prelude
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text as Text

import Duckling.Dimensions.Types
import Duckling.Quantity.Types (QuantityData(..))
import Duckling.Types
import qualified Duckling.Quantity.Types as TQuantity

getValue :: HashMap Text (Double -> Double) -> Text -> Double -> Double
getValue opsMap match = HashMap.lookupDefault id (Text.toLower match) opsMap

-- -----------------------------------------------------------------
-- Patterns

isSimpleQuantity :: Predicate
isSimpleQuantity (Token Quantity QuantityData {TQuantity.unit = Just _
                                              , TQuantity.value = Just _})
 = True
isSimpleQuantity _ = False

-- -----------------------------------------------------------------
-- Production

quantity :: TQuantity.Unit -> Double -> QuantityData
quantity u v = QuantityData {TQuantity.unit = Just u
                            , TQuantity.value = Just v
                            , TQuantity.aproduct = Nothing
                            , TQuantity.minValue = Nothing
                            , TQuantity.maxValue = Nothing
                            , TQuantity.latent = False}

unitOnly :: TQuantity.Unit -> QuantityData
unitOnly u = QuantityData {TQuantity.unit = Just u
                          , TQuantity.value = Nothing
                          , TQuantity.aproduct = Nothing
                          , TQuantity.minValue = Nothing
                          , TQuantity.maxValue = Nothing
                          , TQuantity.latent = False}

valueOnly :: Double -> QuantityData
valueOnly v = QuantityData {TQuantity.unit = Nothing
                          , TQuantity.value = Just v
                          , TQuantity.aproduct = Nothing
                          , TQuantity.minValue = Nothing
                          , TQuantity.maxValue = Nothing
                          , TQuantity.latent = False}

withProduct :: Text -> QuantityData -> QuantityData
withProduct p qd = qd {TQuantity.aproduct = Just p}

withUnit :: TQuantity.Unit -> QuantityData -> QuantityData
withUnit u qd = qd {TQuantity.unit = Just u}

withValue :: Double -> QuantityData -> QuantityData
withValue value qd = qd {TQuantity.value = Just value}

withInterval :: (Double, Double) -> QuantityData -> QuantityData
withInterval (from, to) qd = qd {minValue = Just from, maxValue = Just to}

withMin :: Double -> QuantityData -> QuantityData
withMin from qd = qd {minValue = Just from}

withMax :: Double -> QuantityData -> QuantityData
withMax to qd = qd {maxValue = Just to}

mkLatent :: QuantityData -> QuantityData
mkLatent qd = qd {TQuantity.latent = True}


-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.

{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE NoRebindableSyntax #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}
module Duckling.Quantity.Types where

import Control.DeepSeq
import Data.Aeson
import qualified Data.HashMap.Strict as H
import Data.Hashable
import Data.Text (Text)
import qualified Data.Text as Text
import Duckling.Resolve
  ( Resolve(..)
  , Options(..)
  )
import GHC.Generics
import Prelude

data Unit
  = Bowl
  | Cup
  | Custom Text
  | Dish
  | Gram
  | Ounce
  | Pint
  | Pound
  | Quart
  | Tablespoon
  | Teaspoon
  | Unnamed
  deriving (Eq, Generic, Hashable, Ord, Show, NFData)

instance ToJSON Unit where
  toJSON (Custom x) = String $ Text.toLower x
  toJSON x = String . Text.toLower . Text.pack $ show x

data QuantityData = QuantityData
  { unit :: Maybe Unit
  , value :: Maybe Double
  , aproduct :: Maybe Text
  , minValue :: Maybe Double
  , maxValue :: Maybe Double
  , latent :: Bool
  } deriving (Eq, Generic, Hashable, Ord, Show, NFData)

instance Resolve QuantityData where
  type ResolvedValue QuantityData = QuantityValue
  resolve _ Options {withLatent = False} QuantityData {latent = True}
   = Nothing

  resolve _ _ QuantityData {value = Just value
                         , unit = Nothing
                         , aproduct = aproduct
                         , latent = latent}
   = Just (simple Unnamed value aproduct, latent)

  resolve _ _ QuantityData {value = Just value
                         , unit = Just unit
                         , aproduct = aproduct
                         , latent = latent}
   = Just (simple unit value aproduct, latent)

  resolve _ _ QuantityData {value = Nothing
                         , unit = Just unit
                         , aproduct = aproduct
                         , minValue = Just from
                         , maxValue = Just to
                         , latent = latent}
   = Just (between unit (from, to) aproduct, latent)

  resolve _ _ QuantityData {value = Nothing
                         , unit = Just unit
                         , aproduct = aproduct
                         , minValue = Just from
                         , maxValue = Nothing
                         , latent = latent}
   = Just (above unit from aproduct, latent)

  resolve _ _ QuantityData {value = Nothing
                         , unit = Just unit
                         , aproduct = aproduct
                         , minValue = Nothing
                         , maxValue = Just to
                         , latent = latent}
   = Just (under unit to aproduct, latent)

  resolve _ _ _ = Nothing

data IntervalDirection = Above | Under
  deriving (Eq, Generic, Hashable, Ord, Show, NFData)

data SingleValue =
  SingleValue { vUnit :: Unit, vValue :: Double, vProduct :: Maybe Text }
    deriving (Eq, Generic, Hashable, Ord, Show, NFData)

instance ToJSON SingleValue where
    toJSON (SingleValue unit value aproduct) = object $
      [ "value" .= value
      , "unit" .= unit
      ]
      ++ [ "product" .= p | Just p <- [aproduct] ]

data QuantityValue
  = SimpleValue SingleValue
  | IntervalValue (SingleValue, SingleValue)
  | OpenIntervalValue (SingleValue, IntervalDirection)
  deriving (Eq, Ord, Show)

instance ToJSON QuantityValue where
  toJSON (SimpleValue value) = case toJSON value of
    Object o -> Object $ H.insert "type" (toJSON ("value" :: Text)) o
    _ -> Object H.empty
  toJSON (IntervalValue (from, to)) = object
    [ "type" .= ("interval" :: Text)
    , "from" .= toJSON from
    , "to" .= toJSON to
    ]
  toJSON (OpenIntervalValue (from, Above)) = object
    [ "type" .= ("interval" :: Text)
    , "from" .= toJSON from
    ]
  toJSON (OpenIntervalValue (to, Under)) = object
    [ "type" .= ("interval" :: Text)
    , "to" .= toJSON to
    ]

-- -----------------------------------------------------------------
-- Value helpers

simple :: Unit -> Double -> Maybe Text -> QuantityValue
simple u v p = SimpleValue $ single u v p

between :: Unit -> (Double, Double) -> Maybe Text -> QuantityValue
between u (from, to) p = IntervalValue (single u from p, single u to p)

above :: Unit -> Double -> Maybe Text -> QuantityValue
above = openInterval Above

under :: Unit -> Double -> Maybe Text -> QuantityValue
under = openInterval Under

openInterval
  :: IntervalDirection -> Unit -> Double -> Maybe Text -> QuantityValue
openInterval direction u v p = OpenIntervalValue (single u v p, direction)

single :: Unit -> Double -> Maybe Text -> SingleValue
single u v p = SingleValue {vUnit = u, vValue = v, vProduct = p}