-- 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 TypeFamilies #-}

module Duckling.TimeGrain.Types
  ( Grain(..)
  , add
  , inSeconds
  , lower
  )
  where

import Control.DeepSeq
import Data.Aeson
import Data.Hashable
import GHC.Generics
import Prelude
import TextShow
import qualified Data.Text as Text
import qualified Data.Time as Time

import Duckling.Resolve (Resolve(..))

data Grain
  -- NoGrain is helpful to define "now"
  = NoGrain | Second | Minute | Hour | Day | Week | Month | Quarter | Year
  deriving (Eq, Generic, Hashable, Ord, Bounded, Enum, Show, NFData)

instance Resolve Grain where
  type ResolvedValue Grain = Grain
  resolve _ _ _ = Nothing

instance TextShow Grain where
  showb = fromText . Text.toLower . Text.pack . show

instance ToJSON Grain where
  toJSON = String . showt

updateUTCDay :: Time.UTCTime -> (Time.Day -> Time.Day) -> Time.UTCTime
updateUTCDay (Time.UTCTime day diffTime) f = Time.UTCTime (f day) diffTime

add :: Time.UTCTime -> Grain -> Integer -> Time.UTCTime
add utcTime NoGrain n = Time.addUTCTime (realToFrac n) utcTime
add utcTime Second n = Time.addUTCTime (realToFrac n) utcTime
add utcTime Minute n = Time.addUTCTime (realToFrac $ 60 * n) utcTime
add utcTime Hour n = Time.addUTCTime (realToFrac $ 3600 * n) utcTime
add utcTime Day n = updateUTCDay utcTime $ Time.addDays n
add utcTime Week n = updateUTCDay utcTime . Time.addDays $ 7 * n
add utcTime Month n = updateUTCDay utcTime $ Time.addGregorianMonthsClip n
add utcTime Quarter n =
  updateUTCDay utcTime $ Time.addGregorianMonthsClip $ 3 * n
add utcTime Year n = updateUTCDay utcTime $ Time.addGregorianYearsClip n

inSeconds :: Num a => Grain -> a -> a
inSeconds NoGrain n = n
inSeconds Second  n = n
inSeconds Minute  n = n * 60
inSeconds Hour    n = n * inSeconds Minute 60
inSeconds Day     n = n * inSeconds Hour 24
inSeconds Week    n = n * inSeconds Day 7
inSeconds Month   n = n * inSeconds Day 30
inSeconds Quarter n = n * inSeconds Month 3
inSeconds Year    n = n * inSeconds Day 365

lower :: Grain -> Grain
lower NoGrain = Second
lower Second = Second
lower Year = Month
lower Month = Day
lower x = pred x


-- 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.TimeGrain.AR.Rules
  ( rules
  ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import qualified Duckling.TimeGrain.Types as TG

grains :: [(Text, String, TG.Grain)]
grains = [ ("second (grain) ", "(Ø«Ø§Ù†ÙŠ(Ø©|Ù‡)?|Ø«ÙˆØ§Ù†ÙŠ|Ù„ØØ¸(Ø©|Ù‡|Ø§Øª))"   , TG.Second)
         , ("minute (grain)" , "Ø¯Ù‚(ÙŠÙ‚(Ø©|Ù‡)|Ø§Ø¦Ù‚)"                  , TG.Minute)
         , ("hour (grain)"   , "Ø³Ø§Ø¹(Ø©|Ù‡|Ø§Øª)"                      , TG.Hour)
         , ("day (grain)"    , "ÙŠÙˆÙ…|(Ø§|Ø£)ÙŠØ§Ù…"                     , TG.Day)
         , ("week (grain)"   , "(Ø§|Ø£|Ø¥)Ø³(Ø¨ÙˆØ¹|Ø§Ø¨ÙŠØ¹)"               , TG.Week)
         , ("month (grain)"  , "Ø´Ù‡Ø±|(Ø§|Ø£|Ø¥)Ø´Ù‡Ø±"                   , TG.Month)
         , ("quarter (grain)", "(Ø±Ø¨Ø¹(ÙŠÙ†|Ø§Ù†)|[Ø£Ø§]Ø±Ø¨Ø§Ø¹)(Ø³Ù†Ø©|Ø¹Ø§Ù…)?"  , TG.Quarter)
         , ("year (grain)"   , "Ø³Ù†(Ø©|ÙŠÙ†)|Ø¹Ø§Ù…"                     , TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.CA.Rules
  ( rules ) where

import Data.Text (Text)
import Prelude
import Data.String

import Duckling.Dimensions.Types
import qualified Duckling.TimeGrain.Types as TG
import Duckling.Types

grains :: [(Text, String, TG.Grain)]
grains = [ ("segon (grain)", "seg(on)?s?", TG.Second)
         , ("minuts (grain)", "min(ut)?s?", TG.Minute)
         , ("hora (grain)", "h(or(a|es))?", TG.Hour)
         , ("dia (grain)", "d(Ã|i)(a|es)", TG.Day)
         , ("setmana (grain)", "setman(a|es)", TG.Week)
         , ("mes (grain)", "mes(os)?", TG.Month)
         , ("trimestre (grain)", "trimestres?", TG.Quarter)
         , ("any (grain)", "anys?", TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.DA.Rules
  ( rules ) where

import Data.Text (Text)
import Prelude
import Data.String

import Duckling.Dimensions.Types
import qualified Duckling.TimeGrain.Types as TG
import Duckling.Types

grains :: [(Text, String, TG.Grain)]
grains = [ ("second (grain)", "sekund(er)?", TG.Second)
         , ("minute (grain)", "minut(ter)?", TG.Minute)
         , ("hour (grain)", "t(imer?)?", TG.Hour)
         , ("day (grain)", "dag(e)?", TG.Day)
         , ("week (grain)", "uger?", TG.Week)
         , ("month (grain)", "mÃ¥ned(er)?", TG.Month)
         , ("quarter (grain)", "kvartal(er)?", TG.Quarter)
         , ("year (grain)", "Ã¥r", TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.DE.Rules
  ( rules ) where

import Data.Text (Text)
import Prelude
import Data.String

import Duckling.Dimensions.Types
import qualified Duckling.TimeGrain.Types as TG
import Duckling.Types

grains :: [(Text, String, TG.Grain)]
grains = [ ("second (grain)", "sekunden?", TG.Second)
         , ("minute (grain)", "min(uten?)?", TG.Minute)
         , ("hour (grain)", "stunden?", TG.Hour)
         , ("day (grain)", "tage?n?", TG.Day)
         , ("week (grain)", "wochen?", TG.Week)
         , ("month (grain)", "monate?n?", TG.Month)
         , ("quarter (grain)", "quartale?", TG.Quarter)
         , ("year (grain)", "jahre?n?", TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.EN.Rules
  ( rules
  ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import qualified Duckling.TimeGrain.Types as TG

grains :: [(Text, String, TG.Grain)]
grains = [ ("second (grain) ", "sec(ond)?s?",      TG.Second)
         , ("minute (grain)" , "m(in(ute)?s?)?",   TG.Minute)
         , ("hour (grain)"   , "h(((ou)?rs?)|r)?", TG.Hour)
         , ("day (grain)"    , "days?",            TG.Day)
         , ("week (grain)"   , "weeks?",           TG.Week)
         , ("month (grain)"  , "months?",          TG.Month)
         , ("quarter (grain)", "(quarter|qtr)s?",  TG.Quarter)
         , ("year (grain)"   , "y(ea)?rs?",        TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.ES.Rules
  ( rules ) where

import Data.Text (Text)
import Prelude
import Data.String

import Duckling.Dimensions.Types
import qualified Duckling.TimeGrain.Types as TG
import Duckling.Types

grains :: [(Text, String, TG.Grain)]
grains = [ ("segundo (grain)", "seg(undo)?s?", TG.Second)
         , ("minutos (grain)", "min(uto)?s?", TG.Minute)
         , ("hora (grain)", "h(ora)?s?", TG.Hour)
         , ("dia (grain)", "d(Ã|i)as?", TG.Day)
         , ("semana (grain)", "semanas?", TG.Week)
         , ("mes (grain)", "mes(es)?", TG.Month)
         , ("trimestre (grain)", "trimestres?", TG.Quarter)
         , ("aÃ±o (grain)", "a(n|Ã±)os?", TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.FI.Rules
  ( rules
  ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import qualified Duckling.TimeGrain.Types as TG

grains :: [(Text, String, TG.Grain)]
grains = [ ("second (grain) ", "sekuntia?|s", TG.Second)
         , ("minute (grain)" , "minuuttia?|min", TG.Minute)
         , ("hour (grain)"   , "tuntia?|h", TG.Hour)
         , ("day (grain)"    , "pÃ¤ivÃ¤(Ã¤)?|vuorokau(si|tta)|vrk|d", TG.Day)
         , ("week (grain)"   , "viikkoa?|vko?", TG.Week)
         , ("month (grain)"  , "kuukau(si|tta)|kk", TG.Month)
         , ("quarter (grain)", "kvartaali(a)?|neljÃ¤nnesvuo(si|tta)", TG.Quarter)
         , ("year (grain)"   , "vuo(si|tta)|v\\.?|a", TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.FR.Rules
  ( rules ) where

import Data.Text (Text)
import Prelude
import Data.String

import Duckling.Dimensions.Types
import qualified Duckling.TimeGrain.Types as TG
import Duckling.Types

grains :: [(Text, String, TG.Grain)]
grains = [ ("seconde (grain)", "sec(onde)?s?", TG.Second)
         , ("minute (grain)", "min(ute)?s?", TG.Minute)
         , ("heure (grain)", "heures?", TG.Hour)
         , ("jour (grain)", "jour(n(e|Ã©)e?)?s?", TG.Day)
         , ("semaine (grain)", "semaines?", TG.Week)
         , ("mois (grain)", "mois", TG.Month)
         , ("trimestre (grain)", "trimestres?", TG.Quarter)
         , ("annÃ©e (grain)", "an(n(e|Ã©)e?)?s?", TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.GA.Rules
  ( rules ) where

import Data.Text (Text)
import Prelude
import Data.String

import Duckling.Dimensions.Types
import qualified Duckling.TimeGrain.Types as TG
import Duckling.Types

grains :: [(Text, String, TG.Grain)]
grains = [ ("soicind (grain)", "t?sh?oicind(Ã|i)?", TG.Second)
         , ("nÃ³imÃ©ad (grain)", "n[Ã³o]im(Ã©|e)[ai]da?", TG.Minute)
         , ("uair (grain)", "([thn]-?)?uair(e|eanta)?", TG.Hour)
         , ("lÃ¡ (grain)", "l(ae(thanta)?|(Ã¡|a))", TG.Day)
         , ("seachtain (grain)", "t?sh?eachtain(e|(Ã|i))?", TG.Week)
         , ("mÃ (grain)", "mh?(Ã|i)(sa|nna)", TG.Month)
         , ("rÃ¡ithe (grain)", "r(Ã¡|a)ith(e|(Ã|i))", TG.Quarter)
         , ("bliain (grain)", "m?bh?lia(in|na|nta)", TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.HU.Rules
  ( rules ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import qualified Duckling.TimeGrain.Types as TG

grains :: [(Text, String, TG.Grain)]
grains = [ ("second (grain) ", "m\x00E1sodperc(ek)?|mp",    TG.Second)
         , ("minute (grain)" , "perc(ek)?",                 TG.Minute)
         , ("hour (grain)"   , "\x00F3ra|\x00F3r\x00E1k",   TG.Hour)
         , ("day (grain)"    , "nap(ok)?",                  TG.Day)
         , ("week (grain)"   , "h\x00E9t|hetek",            TG.Week)
         , ("month (grain)"  , "h\x00F3nap|h\x00F3napok",   TG.Month)
         , ("quarter (grain)", "negyed\\s?\x00E9v(ek)?",    TG.Quarter)
         , ("year (grain)"   , "\x00E9v(ek)?",              TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.IT.Rules
  ( rules ) where

import Data.Text (Text)
import Prelude
import Data.String

import Duckling.Dimensions.Types
import qualified Duckling.TimeGrain.Types as TG
import Duckling.Types

grains :: [(Text, String, TG.Grain)]
grains = [ ("seconde (grain)", "second[oi]", TG.Second)
         , ("minute (grain)", "minut[oi]", TG.Minute)
         , ("heure (grain)", "or[ae]", TG.Hour)
         , ("jour (grain)", "giorn[oi]", TG.Day)
         , ("semaine (grain)", "settiman[ae]", TG.Week)
         , ("mois (grain)", "mes[ei]", TG.Month)
         , ("trimestre (grain)", "trimestr[ei]", TG.Quarter)
         , ("annÃ©e (grain)", "ann?[oi]", TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.NB.Rules
  ( rules ) where

import Data.Text (Text)
import Prelude
import Data.String

import Duckling.Dimensions.Types
import qualified Duckling.TimeGrain.Types as TG
import Duckling.Types

grains :: [(Text, String, TG.Grain)]
grains = [ ("second (grain)", "sek(und(er)?)?", TG.Second)
         , ("minute (grain)", "min(utt(er)?)?", TG.Minute)
         , ("hour (grain)", "t(ime(r)?)?", TG.Hour)
         , ("day (grain)", "dag(er)?", TG.Day)
         , ("week (grain)", "uke(r|n)?", TG.Week)
         , ("month (grain)", "mÃ¥ned(er)?", TG.Month)
         , ("quarter (grain)", "kvart(al|er)(et)?", TG.Quarter)
         , ("year (grain)", "Ã¥r", TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.NL.Rules
  ( rules ) where

import Data.Text (Text)
import Data.String
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import qualified Duckling.TimeGrain.Types as TG

grains :: [(Text, String, TG.Grain)]
grains = [ ("second (grain) " , "(seconde(n|s)?|sec|s)" , TG.Second)
         , ("minute (grain)"  , "(minuut|minuten|min|m)", TG.Minute)
         , ("hour (grain)"    , "(uur|uren|u|h)",         TG.Hour)
         , ("day (grain)"     , "dagen|dag|d",            TG.Day)
         , ("week (grain)"    , "(weken|week|w)",         TG.Week)
         , ("month (grain)"   , "(maanden|maand|mnd)",    TG.Month)
         , ("quarter (grain)" , "(kwartaal|kwartalen)",   TG.Quarter)
         , ("year (grain)"    , "(jaren|jaar|j)",         TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.PL.Rules
  ( rules ) where

import Data.Text (Text)
import Prelude
import Data.String

import Duckling.Dimensions.Types
import qualified Duckling.TimeGrain.Types as TG
import Duckling.Types

grains :: [(Text, String, TG.Grain)]
grains = [ ("second (grain)", "sekund(y|zie|(e|Ä™)|om|ami|ach|o|a)?|s", TG.Second)
         , ("minute (grain)", "minut(y|cie|(e|Ä™)|om|o|ami|ach|(a|Ä…))?|m", TG.Minute)
         , ("hour (grain)", "h|godzin(y|(e|Ä™)|ie|om|o|ami|ach|(a|Ä…))?", TG.Hour)
         , ("day (grain)", "dzie(n|Å„|ni(a|Ä…))|dni(owi|ach|a|Ä…)?", TG.Day)
         , ("week (grain)", "tydzie(n|Å„|)|tygod(ni(owi|u|a|em))|tygodn(iach|iami|iom|ie|i)|tyg\\.?", TG.Week)
         , ("month (grain)", "miesi(a|Ä…)c(owi|em|u|e|om|ami|ach|a)?", TG.Month)
         , ("quarter (grain)", "kwarta(l|Å‚)(u|owi|em|e|(o|Ã³)w|om|ach|ami|y)?", TG.Quarter)
         , ("year (grain)", "rok(u|owi|iem)?|lat(ami|ach|a|om)?", TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.PT.Rules
  ( rules
  ) where

import Data.Text (Text)
import Data.String
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import qualified Duckling.TimeGrain.Types as TG

grains :: [(Text, String, TG.Grain)]
grains = [ ("segundo (grain)", "seg(undo)?s?", TG.Second)
         , ("minutos (grain)", "min(uto)?s?", TG.Minute)
         , ("hora (grain)", "h(ora)?s?", TG.Hour)
         , ("dia (grain)", "d(Ã|i)as?", TG.Day)
         , ("semana (grain)", "semanas?", TG.Week)
         , ("mes (grain)", "m(e|Ãª)s(es)?", TG.Month)
         , ("trimestre (grain)", "trimestres?", TG.Quarter)
         , ("ano (grain)", "anos?", TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.RO.Rules
  ( rules
  ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import qualified Duckling.TimeGrain.Types as TG

grains :: [(Text, String, TG.Grain)]
grains = [ ("secunde (grain)", "sec(und(a|e|Äƒ))?", TG.Second)
         , ("minute (grain)", "min(ut(e|ul)?)?", TG.Minute)
         , ("ore (grain)", "h|or(a|e(le)?|Äƒ)", TG.Hour)
         , ("zile (grain)", "zi(le(le)?|u(a|Äƒ))?", TG.Day)
         , ("saptamani (grain)", "sapt(a|Äƒ)m(a|Ã¢)n(ile|a|Äƒ|i)", TG.Week)
         , ("luni (grain)", "lun(i(le)?|a|Äƒ)", TG.Month)
         , ("trimestru (grain)", "trimestr(e(le)?|ul?)", TG.Quarter)
         , ("ani (grain)", "an(ul|ii?)?", TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.SV.Rules
  ( rules ) where

import Data.Text (Text)
import Prelude
import Data.String

import Duckling.Dimensions.Types
import qualified Duckling.TimeGrain.Types as TG
import Duckling.Types

grains :: [(Text, String, TG.Grain)]
grains = [ ("second (grain)", "sek(und(er(na)?)?)?", TG.Second)
         , ("minute (grain)", "min(ut(er(na)?)?)?", TG.Minute)
         , ("hour (grain)", "t(imm(e(n)?|ar(na)?)?)?", TG.Hour)
         , ("day (grain)", "dag(en|ar(na)?)?", TG.Day)
         , ("week (grain)", "veck(or(na)?|a(n)?)?", TG.Week)
         , ("month (grain)", "mÃ¥nad(er(na)?)?", TG.Month)
         , ("quarter (grain)", "kvart(al)(et)?", TG.Quarter)
         , ("year (grain)", "Ã¥r(e[nt])?", TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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.TimeGrain.TR.Rules
  ( rules
  ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import qualified Duckling.TimeGrain.Types  as TG

grains :: [(Text, String, TG.Grain)]
grains = [ ("saniye (grain)",     "sa?n(iye)?(nin)?",           TG.Second)
         , ("dakika (grain)",     "da?k(ika)?(nÄ±n)?",           TG.Minute)
         , ("saat (grain)",       "sa(at)?(in)?",              TG.Hour)
         , ("gÃ¼n (grain)",        "gÃ¼n(Ã¼n)?",             TG.Day)
         , ("hafta (grain)",      "hafta(nÄ±n)?",                TG.Week)
         , ("ay (grain)",         "ay(Ä±n)?",                   TG.Month)
         , ("Ã§eyrek yÄ±l (grain)", "\231eyrek y\305l(Ä±n)?",     TG.Quarter)
         , ("yÄ±l (grain)",        "y\305l(Ä±n)?",               TG.Year)
         ]

rules :: [Rule]
rules = map go grains
  where
    go (name, regexPattern, grain) = Rule
      { name = name
      , pattern = [regex regexPattern]
      , prod = \_ -> Just $ Token TimeGrain grain
      }


-- 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 RecordWildCards #-}
{-# LANGUAGE NoRebindableSyntax #-}

module Duckling.Types.Stash where

import qualified Data.IntMap.Strict as IntMap
import Data.IntMap.Strict (IntMap)
import qualified Data.HashSet as HashSet
import Data.HashSet (HashSet)
import Data.Maybe
import Prelude

import Duckling.Types

newtype Stash = Stash { getSet :: IntMap (HashSet Node) }

filter :: (Node -> Bool) -> Stash -> Stash
filter p Stash{..} = Stash (IntMap.map (HashSet.filter p) getSet)

toPosOrderedList:: Stash -> [Node]
toPosOrderedList Stash{..} = concatMap HashSet.toList $ IntMap.elems getSet

toPosOrderedListFrom :: Stash -> Int -> [Node]
toPosOrderedListFrom Stash{..} pos =
  concatMap HashSet.toList $ maybeToList equal ++ IntMap.elems bigger
  where
  (_smaller, equal, bigger) = IntMap.splitLookup pos getSet
  -- this is where we take advantage of the order

empty :: Stash
empty = Stash IntMap.empty

fromList :: [Node] -> Stash
fromList ns = Stash (IntMap.fromListWith HashSet.union $ map mkKV ns)
  where
  mkKV n@Node{nodeRange = Range start _} = (start, HashSet.singleton n)

union :: Stash -> Stash -> Stash
union (Stash set1) (Stash set2) =
  Stash (IntMap.unionWith HashSet.union set1 set2)

-- Checks if two stashes have equal amount of Nodes on each position.
-- Used to detect a fixpoint, because the Stashes are only growing.
--
-- Not proud of this, but the algorithm shouldn't use it as the termination
-- condition, it should know when it stopped adding tokens
sizeEqual :: Stash -> Stash -> Bool
sizeEqual (Stash set1) (Stash set2) =
  go (IntMap.toAscList set1) (IntMap.toAscList set2)
  where
  go [] [] = True
  go [] (_:_) = False
  go (_:_) [] = False
  go ((k1, h1):rest1) ((k2, h2):rest2) =
    k1 == k2 && HashSet.size h1 == HashSet.size h2 && go rest1 rest2

null :: Stash -> Bool
null (Stash set) = IntMap.null set


-- 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.Url.Corpus
  ( corpus
  , negativeCorpus
  ) where

import Data.String
import Prelude

import Duckling.Testing.Types
import Duckling.Url.Types

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

negativeCorpus :: NegativeCorpus
negativeCorpus = (testContext, testOptions, examples)
  where
    examples =
      [ "foo"
      , "MYHOST"
      , "hey:42"
      , "25"
      ]

allExamples :: [Example]
allExamples = concat
  [ examples (UrlData "http://www.bla.com" "bla.com")
             [ "http://www.bla.com"
             ]
  , examples (UrlData "www.bla.com:8080/path" "bla.com")
             [ "www.bla.com:8080/path"
             ]
  , examples (UrlData "https://myserver?foo=bar" "myserver")
             [ "https://myserver?foo=bar"
             ]
  , examples (UrlData "cnn.com/info" "cnn.com")
             [ "cnn.com/info"
             ]
  , examples (UrlData "bla.com/path/path?ext=%23&foo=bla" "bla.com")
             [ "bla.com/path/path?ext=%23&foo=bla"
             ]
  , examples (UrlData "localhost" "localhost")
             [ "localhost"
             ]
  , examples (UrlData "localhost:8000" "localhost")
             [ "localhost:8000"
             ]
  , examples (UrlData "http://kimchi" "kimchi")
             [ "http://kimchi"
             ]
  , examples (UrlData "https://500px.com:443/about" "500px.com")
             [ "https://500px.com:443/about"
             ]
  , examples (UrlData "www2.foo-bar.net?foo=bar" "foo-bar.net")
             [ "www2.foo-bar.net?foo=bar"
             ]
  , examples (UrlData "https://api.wit.ai/message?q=hi" "api.wit.ai")
             [ "https://api.wit.ai/message?q=hi"
             ]
  , examples (UrlData "aMaZon.co.uk/?page=home" "amazon.co.uk")
             [ "aMaZon.co.uk/?page=home"
             ]
  , examples (UrlData "https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax" "en.wikipedia.org")
             [ "https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax"
             ]
  , examples (UrlData "http://example.com/data.csv#cell=4,1-6,2" "example.com")
             [ "http://example.com/data.csv#cell=4,1-6,2"
             ]
  , examples (UrlData "http://example.com/bar.webm#t=40,80&xywh=160,120,320,240" "example.com")
             [ "http://example.com/bar.webm#t=40,80&xywh=160,120,320,240"
             ]
  ]


-- 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.

module Duckling.Url.Helpers
  ( url
  ) where

import Data.Text (Text)
import qualified Data.Text as Text

import qualified Duckling.Url.Types as TUrl
import Duckling.Url.Types (UrlData(..))

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

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

url :: Text -> Text -> UrlData
url value domain = UrlData
  {TUrl.value = value, TUrl.domain = Text.toLower domain}


-- 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.Url.Rules
  ( rules ) where

import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Regex.Types
import Duckling.Types
import Duckling.Url.Helpers

ruleURL :: Rule
ruleURL = Rule
  { name = "url"
  , pattern =
    [ regex "((([a-zA-Z]+)://)?(w{2,3}[0-9]*\\.)?(([\\w_-]+\\.)+[a-z]{2,4})(:(\\d+))?(/[^?\\s#]*)?(\\?[^\\s#]+)?(#[\\-,*=&a-z0-9]+)?)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (m:_:_protocol:_:domain:_:_:_port:_path:_query:_)):
       _) -> Just . Token Url $ url m domain
      _ -> Nothing
  }

ruleLocalhost :: Rule
ruleLocalhost = Rule
  { name = "localhost"
  , pattern =
    [ regex "((([a-zA-Z]+)://)?localhost(:(\\d+))?(/[^?\\s#]*)?(\\?[^\\s#]+)?)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (m:_:_protocol:_:_port:_path:_query:_)):_) ->
        Just . Token Url $ url m "localhost"
      _ -> Nothing
  }

ruleLocalURL :: Rule
ruleLocalURL = Rule
  { name = "local url"
  , pattern =
    [ regex "(([a-zA-Z]+)://([\\w_-]+)(:(\\d+))?(/[^?\\s#]*)?(\\?[^\\s#]+)?)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (m:_protocol:domain:_:_port:_path:_query:_)):
       _) -> Just . Token Url $ url m domain
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleURL
  , ruleLocalhost
  , ruleLocalURL
  ]


-- 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 NamedFieldPuns #-}
{-# LANGUAGE NoRebindableSyntax #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}

module Duckling.Url.Types where

import Control.DeepSeq
import Data.Aeson
import Data.Hashable
import Data.Maybe
import Data.Text (Text)
import GHC.Generics
import Prelude

import Duckling.Resolve (Resolve(..))

data UrlData = UrlData
  { value :: Text
  , domain :: Text
  }
  deriving (Eq, Generic, Hashable, Ord, Show, NFData)

instance Resolve UrlData where
  type ResolvedValue UrlData = UrlData
  resolve _ _ x = Just (x, False)

instance ToJSON UrlData where
  toJSON (UrlData value domain) = object
    [ "value"  .= value
    , "domain" .= domain
    , "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 GADTs #-}

module Duckling.Volume.Helpers
  ( isSimpleVolume
  , isUnitOnly
  , volume
  , unitOnly
  , valueOnly
  , withUnit
  , withValue
  , withInterval
  , withMin
  , withMax
  ) where

import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Volume.Types (Unit(..), VolumeData(..))
import Duckling.Types
import qualified Duckling.Volume.Types as TVolume

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

isSimpleVolume :: Predicate
isSimpleVolume (Token Volume VolumeData {TVolume.value = Just _
                                        , TVolume.minValue = Nothing
                                        , TVolume.maxValue = Nothing}) = True
isSimpleVolume _ = False

isUnitOnly :: Predicate
isUnitOnly (Token Volume VolumeData {TVolume.value = Nothing
                                    , TVolume.unit = Just _
                                    , TVolume.minValue = Nothing
                                    , TVolume.maxValue = Nothing}) = True
isUnitOnly _ = False

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

volume :: Unit -> Double -> VolumeData
volume u v = VolumeData {TVolume.unit = Just u
                        , TVolume.value = Just v
                        , TVolume.minValue = Nothing
                        , TVolume.maxValue = Nothing}

unitOnly :: Unit -> VolumeData
unitOnly u = VolumeData {TVolume.unit = Just u
                        , TVolume.value = Nothing
                        , TVolume.minValue = Nothing
                        , TVolume.maxValue = Nothing}

valueOnly :: Double -> VolumeData
valueOnly v = VolumeData {TVolume.unit = Nothing
                        , TVolume.value = Just v
                        , TVolume.minValue = Nothing
                        , TVolume.maxValue = Nothing}

withUnit :: Unit -> VolumeData -> VolumeData
withUnit u vd = vd {TVolume.unit = Just u}

withValue :: Double -> VolumeData -> VolumeData
withValue v vd = vd {TVolume.value = Just v}

withInterval :: (Double, Double) -> VolumeData -> VolumeData
withInterval (from, to) vd = vd {TVolume.value = Nothing
                                , TVolume.minValue = Just from
                                , TVolume.maxValue = Just to}

withMin :: Double -> VolumeData -> VolumeData
withMin from vd = vd {TVolume.minValue = Just from}

withMax :: Double -> VolumeData -> VolumeData
withMax to vd = vd {TVolume.maxValue = Just to}


-- 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.Volume.Rules
  ( rules
  ) where

import Data.String
import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Types
import Duckling.Regex.Types
import Duckling.Volume.Helpers
import Duckling.Numeral.Helpers (isPositive)
import qualified Duckling.Volume.Types as TVolume
import qualified Duckling.Numeral.Types as TNumeral

ruleNumeralAsVolume :: Rule
ruleNumeralAsVolume = Rule
  { name = "number as volume"
  , pattern =
    [ Predicate isPositive
    ]
  , prod = \case
    (Token Numeral TNumeral.NumeralData {TNumeral.value = v}:
     _) ->
      Just . Token Volume $ valueOnly v
    _ -> Nothing
  }

ruleNumeralVolumes :: Rule
ruleNumeralVolumes = Rule
  { name = "<number> <volume>"
  , pattern =
    [ Predicate isPositive
    , Predicate isUnitOnly
    ]
  , prod = \case
    (Token Numeral TNumeral.NumeralData{TNumeral.value = v}:
     Token Volume TVolume.VolumeData{TVolume.unit = Just u}:
     _) ->
      Just . Token Volume $ volume u v
    _ -> Nothing
  }

ruleIntervalNumeralDash :: Rule
ruleIntervalNumeralDash = Rule
  { name = "<numeral> - <volume>"
  , pattern =
    [ Predicate isPositive
    , regex "\\-"
    , Predicate isSimpleVolume
    ]
  , prod = \case
      (Token Numeral TNumeral.NumeralData{TNumeral.value = from}:
       _:
       Token Volume TVolume.VolumeData{TVolume.value = Just to
                                  , TVolume.unit = Just u}:
       _) | from < to ->
        Just . Token Volume . withInterval (from, to) $ unitOnly u
      _ -> Nothing
  }

ruleIntervalDash :: Rule
ruleIntervalDash = Rule
  { name = "<volume> - <volume>"
  , pattern =
    [ Predicate isSimpleVolume
    , regex "\\-"
    , Predicate isSimpleVolume
    ]
  , prod = \case
      (Token Volume TVolume.VolumeData{TVolume.value = Just from
                                  , TVolume.unit = Just u1}:
       _:
       Token Volume TVolume.VolumeData{TVolume.value = Just to
                                  , TVolume.unit = Just u2}:
       _) | from < to && u1 == u2 ->
        Just . Token Volume . withInterval (from, to) $ unitOnly u1
      _ -> Nothing
  }

rules :: [Rule]
rules = [ ruleNumeralAsVolume
        , ruleNumeralVolumes
        , ruleIntervalNumeralDash
        , ruleIntervalDash
        ]


-- 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 NamedFieldPuns #-}
{-# LANGUAGE NoRebindableSyntax #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}

module Duckling.Volume.Types where

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

data Unit
  = Gallon
  | Hectolitre
  | Litre
  | Centilitre
  | Millilitre
  deriving (Eq, Generic, Hashable, Ord, Show, NFData)

instance ToJSON Unit where
  toJSON = String . Text.toLower . Text.pack . show

data VolumeData = VolumeData
  { value :: Maybe Double
  , unit :: Maybe Unit
  , minValue :: Maybe Double
  , maxValue :: Maybe Double
  }
  deriving (Eq, Generic, Hashable, Ord, Show, NFData)

instance Resolve VolumeData where
  type ResolvedValue VolumeData = VolumeValue
  resolve _ _ VolumeData {value = Just v, unit = Just u} =
    Just (simple u v, False)
  resolve _ _ VolumeData {value = Nothing, unit = Just u
                         , minValue = Just from, maxValue = Just to} =
    Just (between u (from, to), False)
  resolve _ _ VolumeData {value = Nothing, unit = Just u
                         , minValue = Just v, maxValue = Nothing} =
    Just (above u v, False)
  resolve _ _ VolumeData {value = Nothing, unit = Just u
                         , minValue = Nothing, maxValue = Just v} =
    Just (under u v, False)
  resolve _ _ _ = Nothing

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

data SingleValue = SingleValue
  { vUnit :: Unit
  , vValue :: Double
  }
  deriving (Eq, Show)

instance ToJSON SingleValue where
  toJSON SingleValue {vUnit, vValue} = object
    [ "value" .= vValue
    , "unit"  .= vUnit
    ]

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

instance ToJSON VolumeValue 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 -> VolumeValue
simple u v = SimpleValue $ single u v

between :: Unit -> (Double, Double) -> VolumeValue
between u (from,to) = IntervalValue (single u from, single u to)

above :: Unit -> Double -> VolumeValue
above = openInterval Above

under :: Unit -> Double -> VolumeValue
under = openInterval Under

openInterval :: IntervalDirection -> Unit -> Double -> VolumeValue
openInterval direction u v = OpenIntervalValue (single u v, direction)

single :: Unit -> Double -> SingleValue
single u v = SingleValue {vUnit = u, vValue = v}


-- 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.Volume.CA.Corpus
  ( corpus ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Resolve
import Duckling.Volume.Types
import Duckling.Testing.Types

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

allExamples :: [Example]
allExamples = concat
  [ examples (simple Millilitre 250)
             [ "250 mililitres"
             , "250ml"
             , "250 ml"
             ]
  , examples (simple Litre 2)
             [ "2 litres"
             ]
  , examples (simple Gallon 3)
             [ "3 galÃ³"
             ]
  , examples (simple Hectolitre 3)
             [ "3 hectolitres"
             ]
  , examples (simple Litre 0.5)
             [ "mig litre"
             ]
  ]


-- 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.Volume.CA.Rules
  ( rules ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import Duckling.Volume.Helpers
import qualified Duckling.Volume.Types as TVolume

volumes :: [(Text, String, TVolume.Unit)]
volumes = [ ("<latent vol> ml"    , "m(l|ililitres?)", TVolume.Millilitre)
          , ("<vol> hectoliters"  , "(hectolitres?)" , TVolume.Hectolitre)
          , ("<vol> liters"       , "l(itres?)?"     , TVolume.Litre)
          , ("<latent vol> gallon", "gal(ons|Ã³)"     , TVolume.Gallon)
          ]

rulesVolumes :: [Rule]
rulesVolumes = map go volumes
  where
    go :: (Text, String, TVolume.Unit) -> Rule
    go (name, regexPattern, u) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        ]
      , prod = \_ -> Just $ Token Volume $ unitOnly u
      }

fractions :: [(Text, String, Double)]
fractions = [ ("half", "mig", 1/2)
            ]

rulesFractionalVolume :: [Rule]
rulesFractionalVolume = map go fractions
  where
    go :: (Text, String, Double) -> Rule
    go (name, regexPattern, f) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        , Predicate isUnitOnly
        ]
      , prod = \case
        (_:
         Token Volume TVolume.VolumeData{TVolume.unit = Just u}:
         _) ->
          Just $ Token Volume $ volume u f
        _ -> Nothing
      }

rules :: [Rule]
rules =
     rulesVolumes
  ++ rulesFractionalVolume


-- 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.Volume.DE.Corpus
  ( corpus ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Resolve
import Duckling.Testing.Types
import Duckling.Volume.Types

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

allExamples :: [Example]
allExamples = concat
  [ examples (simple Litre 1)
             [ "1 liter"
             --, "ein liter"
             ]
  , examples (simple Litre 2)
             [ "2 liter"
             , "2l"
             ]
  , examples (simple Litre 1000)
             [ "1000 liter"
             , "tausend liter"
             ]
  , examples (simple Litre 0.5)
             [ "halber liter"
            , "ein halber liter"
             ]
  , examples (simple Litre 0.25)
             [ "viertel liter"
            , "ein viertel liter"
             ]
  , examples (simple Millilitre 1)
             [ "ein milliliter"
             , "ein ml"
             , "1ml"
             ]
  , examples (simple Millilitre 250)
             [ "250 milliliter"
             , "250ml"
             , "250 ml"
             ]
  , examples (simple Hectolitre 3)
             [ "3 hektoliter"
             ]
  , examples (between Litre (100,1000))
             [ "zwischen 100 und 1000 litern"
             , "100-1000 liter"
             , "von 100 bis 1000 l"
             , "100 - 1000 l"
             ]
  , examples (between Litre (2,7))
             [ "etwa 2 -7 l"
             , "~2-7 liter"
             , "von 2 bis 7 l"
             , "zwischen 2,0 l und ungefÃ¤hr 7,0 l"
             , "zwischen 2l und etwa 7l"
             , "2 - ~7 liter"
             ]
  , examples (under Hectolitre 2)
             [ "nicht mehr als 2 hektoliter"
             , "hÃ¶chstens zwei hektoliter"
             , "unter 2 hektolitern"
             , "weniger als 2 hektoliter"
             ]
  , examples (above Millilitre 4)
             [ "mehr als 4 ml"
             , "wenigstens 4,0 ml"
             , "Ã¼ber vier milliliter"
             , "mindestens vier ml"
             ]
  ]


-- 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.Volume.DE.Rules
  ( rules ) where

import Data.Text (Text)
import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Types
import Duckling.Regex.Types
import Duckling.Volume.Helpers
import Duckling.Numeral.Helpers (isPositive)
import qualified Duckling.Volume.Types as TVolume
import qualified Duckling.Numeral.Types as TNumeral

volumes :: [(Text, String, TVolume.Unit)]
volumes = [ ("<latent vol> ml", "m(l|illiliter[ns]?)", TVolume.Millilitre)
          , ("<vol> hectoliters", "hektoliter[ns]?", TVolume.Hectolitre)
          , ("<vol> liters", "l(iter[ns]?)?", TVolume.Litre)
          ]

rulesVolumes :: [Rule]
rulesVolumes = map go volumes
  where
    go :: (Text, String, TVolume.Unit) -> Rule
    go (name, regexPattern, u) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        ]
      , prod = \_ -> Just . Token Volume $ unitOnly u
      }

fractions :: [(Text, String, Double)]
fractions = [ ("one","ein(e[ns])?", 1)
            , ("half", "(ein(e[ns])? )?halb(e[rn])? ", 1/2)
            , ("third", "(ein(e[ns])? )?dritttel ", 1/3)
            , ("fourth", "(ein(e[ns])? )?viertel ", 1/4)
            , ("fifth", "(ein(e[ns])? )?fÃ¼nftel ", 1/5)
            , ("tenth", "(ein(e[ns])? )?zehntel ", 1/10)
            ]

rulesFractionalVolume :: [Rule]
rulesFractionalVolume = map go fractions
  where
    go :: (Text, String, Double) -> Rule
    go (name, regexPattern, f) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        , Predicate isUnitOnly
        ]
      , prod = \case
        (_:
         Token Volume TVolume.VolumeData{TVolume.unit = Just u}:
         _) ->
          Just . Token Volume $ volume u f
        _ -> Nothing
      }

rulePrecision :: Rule
rulePrecision = Rule
  { name = "about <volume>"
  , pattern =
    [ regex "\\~|(ganz )?genau|prÃ¤zise|(in )?etwa|ungefÃ¤hr|um( die)?|fast"
    , dimension Volume
    ]
    , prod = \case
      (_:token:_) -> Just token
      _ -> Nothing
  }

ruleIntervalBetweenNumeral :: Rule
ruleIntervalBetweenNumeral = Rule
  { name = "between|from <numeral> and|to <volume>"
  , pattern =
    [ regex "zwischen|von"
    , Predicate isPositive
    , regex "und|bis( zu)?"
    , Predicate isSimpleVolume
    ]
  , prod = \case
      (_:
       Token Numeral TNumeral.NumeralData{TNumeral.value = from}:
       _:
       Token Volume TVolume.VolumeData{TVolume.value = Just to
                                  , TVolume.unit = Just u}:
       _) | from < to ->
        Just . Token Volume . withInterval (from, to) $ unitOnly u
      _ -> Nothing
  }

ruleIntervalBetween :: Rule
ruleIntervalBetween = Rule
  { name = "between|from <volume> to|and <volume>"
  , pattern =
    [ regex "zwischen|von"
    , Predicate isSimpleVolume
    , regex "bis( zu)?|und"
    , Predicate isSimpleVolume
    ]
  , prod = \case
      (_:
       Token Volume TVolume.VolumeData{TVolume.value = Just from
                                  , TVolume.unit = Just u1}:
       _:
       Token Volume TVolume.VolumeData{TVolume.value = Just to
                                  , TVolume.unit = Just u2}:
       _) | from < to && u1 == u2 ->
        Just . Token Volume . withInterval (from, to) $ unitOnly u1
      _ -> Nothing
  }

ruleIntervalMax :: Rule
ruleIntervalMax = Rule
  { name = "at most <volume>"
  , pattern =
    [ regex "unter|weniger( als)?|hÃ¶chstens|nicht mehr als"
    , Predicate isSimpleVolume
    ]
  , prod = \case
      (_:
       Token Volume TVolume.VolumeData{TVolume.value = Just to
                                  , TVolume.unit = Just u}:
       _) ->
        Just . Token Volume . withMax to $ unitOnly u
      _ -> Nothing
  }

ruleIntervalMin :: Rule
ruleIntervalMin = Rule
  { name = "more than <volume>"
  , pattern =
      [ regex "Ã¼ber|mindestens|wenigstens|mehr als|grÃ¶ÃŸer( als)?"
      , Predicate isSimpleVolume
      ]
    , prod = \case
        (_:
         Token Volume TVolume.VolumeData{TVolume.value = Just from
                                    , TVolume.unit = Just u}:
         _) ->
          Just . Token Volume . withMin from $ unitOnly u
        _ -> Nothing
    }

rules :: [Rule]
rules = [ rulePrecision
        , ruleIntervalBetweenNumeral
        , ruleIntervalBetween
        , ruleIntervalMax
        , ruleIntervalMin
        ]
        ++ rulesVolumes
        ++ rulesFractionalVolume


-- 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.Volume.EN.Corpus
  ( corpus ) where

import Data.String
import Prelude

import Duckling.Testing.Types
import Duckling.Volume.Types

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

allExamples :: [Example]
allExamples = concat
  [ examples (simple Litre 1)
             [ "1 liter"
             , "1 litre"
             , "one liter"
             , "a liter"
             ]
  , examples (simple Litre 2)
             [ "2 liters"
             , "2l"
             ]
  , examples (simple Litre 1000)
             [ "1000 liters"
             , "thousand liters"
             ]
  , examples (simple Litre 0.5)
             [ "half liter"
             , "half-litre"
             , "half a liter"
             ]
  , examples (simple Litre 0.25)
             [ "quarter-litre"
             , "fourth of liter"
             ]
  , examples (simple Millilitre 1)
             [ "one milliliter"
             , "an ml"
             , "a millilitre"
             ]
  , examples (simple Millilitre 250)
             [ "250 milliliters"
             , "250 millilitres"
             , "250ml"
             , "250mls"
             , "250 ml"
             ]
  , examples (simple Gallon 3)
             [ "3 gallons"
             , "3 gal"
             , "3gal"
             , "around three gallons"
             ]
  , examples (simple Gallon 0.5)
             [ "0.5 gals"
             , "1/2 gallon"
             , "half a gallon"
             ]
  , examples (simple Gallon 0.1)
             [ "0.1 gallons"
             , "tenth of a gallon"
             ]
  , examples (simple Hectolitre 3)
             [ "3 hectoliters"
             ]
  , examples (between Litre (100,1000))
             [ "between 100 and 1000 liters"
             , "100-1000 liters"
             , "from 100 to 1000 l"
             , "100 - 1000 l"
             ]
  , examples (between Litre (2,7))
             [ "around 2 -7 l"
             , "~2-7 liters"
             , "from 2 to 7 l"
             , "between 2.0 l and about 7.0 l"
             , "between 2l and about 7l"
             , "2 - ~7 litres"
             ]
  , examples (under Gallon 6)
             [ "less than six gallons"
             , "under six gallon"
             , "no more than 6 gals"
             , "below 6.0gal"
             , "at most six gallons"
             ]
  , examples (above Hectolitre 2)
             [ "exceeding 2 hectoliters"
             , "at least two hectolitres"
             , "over 2 hectolitre"
             , "more than 2 hectoliter"
             ]
  , examples (above Millilitre 4)
             [ "exceeding 4 ml"
             , "at least 4.0 ml"
             , "over four milliliters"
             , "more than four mls"
             ]
  ]


-- 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.Volume.EN.Rules
  ( rules ) where

import Data.Text (Text)
import Prelude
import Data.String

import Duckling.Dimensions.Types
import Duckling.Types
import Duckling.Regex.Types
import Duckling.Volume.Helpers
import Duckling.Numeral.Helpers (isPositive)
import qualified Duckling.Volume.Types as TVolume
import qualified Duckling.Numeral.Types as TNumeral

volumes :: [(Text, String, TVolume.Unit)]
volumes = [ ("<latent vol> ml", "m(l(s?)|illilit(er|re)s?)", TVolume.Millilitre)
          , ("<vol> hectoliters", "hectolit(er|re)s?", TVolume.Hectolitre)
          , ("<vol> liters", "l(it(er|re)s?)?", TVolume.Litre)
          , ("<latent vol> gallon", "gal((l?ons?)|s)?", TVolume.Gallon)
          ]

rulesVolumes :: [Rule]
rulesVolumes = map go volumes
  where
    go :: (Text, String, TVolume.Unit) -> Rule
    go (name, regexPattern, u) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        ]
      , prod = \_ -> Just . Token Volume $ unitOnly u
      }

fractions :: [(Text, String, Double)]
fractions = [ ("one", "an? ", 1)
            , ("half", "half(-|(( of)?( a(n?))?))?", 1/2)
            , ("third", "third(-|(( of)?( a(n?))?))?", 1/3)
            , ("fourth", "(quarter|fourth)(-|(( of)?( a(n?))?))?", 1/4)
            , ("fifth", "fifth(-|(( of)?( a(n?))?))?", 1/5)
            , ("tenth", "tenth(-|(( of)?( a(n?))?))?", 1/10)
            ]

rulesFractionalVolume :: [Rule]
rulesFractionalVolume = map go fractions
  where
    go :: (Text, String, Double) -> Rule
    go (name, regexPattern, f) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        , Predicate isUnitOnly
        ]
      , prod = \case
        (_:
         Token Volume TVolume.VolumeData{TVolume.unit = Just u}:
         _) ->
          Just . Token Volume $ volume u f
        _ -> Nothing
      }

rulePrecision :: Rule
rulePrecision = Rule
  { name = "about <volume>"
  , pattern =
    [ regex "\\~|exactly|precisely|about|approx(\\.|imately)?|close to|near( to)?|around|almost"
    , dimension Volume
    ]
    , prod = \case
      (_:token:_) -> Just token
      _ -> Nothing
  }

ruleIntervalBetweenNumeral :: Rule
ruleIntervalBetweenNumeral = Rule
  { name = "between|from <numeral> and|to <volume>"
  , pattern =
    [ regex "between|from"
    , Predicate isPositive
    , regex "to|and"
    , Predicate isSimpleVolume
    ]
  , prod = \case
      (_:
       Token Numeral TNumeral.NumeralData{TNumeral.value = from}:
       _:
       Token Volume TVolume.VolumeData{TVolume.value = Just to
                                  , TVolume.unit = Just u}:
       _) | from < to ->
        Just . Token Volume . withInterval (from, to) $ unitOnly u
      _ -> Nothing
  }

ruleIntervalBetween :: Rule
ruleIntervalBetween = Rule
  { name = "between|from <volume> to|and <volume>"
  , pattern =
    [ regex "between|from"
    , Predicate isSimpleVolume
    , regex "to|and"
    , Predicate isSimpleVolume
    ]
  , prod = \case
      (_:
       Token Volume TVolume.VolumeData{TVolume.value = Just from
                                  , TVolume.unit = Just u1}:
       _:
       Token Volume TVolume.VolumeData{TVolume.value = Just to
                                  , TVolume.unit = Just u2}:
       _) | from < to && u1 == u2 ->
        Just . Token Volume . withInterval (from, to) $ unitOnly u1
      _ -> Nothing
  }

ruleIntervalMax :: Rule
ruleIntervalMax = Rule
  { name = "at most <volume>"
  , pattern =
    [ regex "under|below|at most|(less|lower|not? more) than"
    , Predicate isSimpleVolume
    ]
  , prod = \case
      (_:
       Token Volume TVolume.VolumeData{TVolume.value = Just to
                                  , TVolume.unit = Just u}:
       _) ->
        Just . Token Volume . withMax to $ unitOnly u
      _ -> Nothing
  }

ruleIntervalMin :: Rule
ruleIntervalMin = Rule
  { name = "more than <volume>"
  , pattern =
      [ regex "over|above|exceeding|beyond|at least|(more|larger|bigger|heavier) than"
      , Predicate isSimpleVolume
      ]
    , prod = \case
        (_:
         Token Volume TVolume.VolumeData{TVolume.value = Just from
                                    , TVolume.unit = Just u}:
         _) ->
          Just . Token Volume . withMin from $ unitOnly u
        _ -> Nothing
    }

rules :: [Rule]
rules = [ rulePrecision
        , ruleIntervalBetweenNumeral
        , ruleIntervalBetween
        , ruleIntervalMax
        , ruleIntervalMin
        ]
        ++ rulesVolumes
        ++ rulesFractionalVolume


-- 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.Volume.ES.Corpus
  ( corpus ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Resolve
import Duckling.Volume.Types
import Duckling.Testing.Types

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

allExamples :: [Example]
allExamples = concat
  [ examples (simple Millilitre 250)
             [ "250 mililitros"
             , "250ml"
             , "250 ml"
             ]
  , examples (simple Litre 2)
             [ "2 litros"
             ]
  , examples (simple Gallon 3)
             [ "3 galÃ³n"
             ]
  , examples (simple Hectolitre 3)
             [ "3 hectolitros"
             ]
  , examples (simple Litre 0.5)
             [ "medio litro"
             ]
  ]


-- 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.Volume.ES.Rules
  ( rules ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import Duckling.Regex.Types
import Duckling.Volume.Helpers
import Duckling.Numeral.Helpers (isPositive)
import qualified Duckling.Volume.Types as TVolume
import qualified Duckling.Numeral.Types as TNumeral

volumes :: [(Text, String, TVolume.Unit)]
volumes = [ ("<latent vol> ml"    , "m(l|ililitros?)" , TVolume.Millilitre)
          , ("<vol> hectoliters"  , "(hectolitros?)"    , TVolume.Hectolitre)
          , ("<vol> liters"       , "l(itros?)?"     , TVolume.Litre)
          , ("<latent vol> gallon", "gal(o|Ã³)ne?s?"   , TVolume.Gallon)
          ]

rulesVolumes :: [Rule]
rulesVolumes = map go volumes
  where
    go :: (Text, String, TVolume.Unit) -> Rule
    go (name, regexPattern, u) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        ]
      , prod = \_ -> Just . Token Volume $ unitOnly u
      }

fractions :: [(Text, String, Double)]
fractions = [ ("half", "medio", 1/2)
            ]

rulesFractionalVolume :: [Rule]
rulesFractionalVolume = map go fractions
  where
    go :: (Text, String, Double) -> Rule
    go (name, regexPattern, f) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        , Predicate isUnitOnly
        ]
      , prod = \case
        (_:
         Token Volume TVolume.VolumeData{TVolume.unit = Just u}:
         _) ->
          Just . Token Volume $ volume u f
        _ -> Nothing
      }

rules :: [Rule]
rules =
  [
  ]
  ++ rulesVolumes
  ++ rulesFractionalVolume


-- 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.Volume.FR.Corpus
  ( corpus ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Resolve
import Duckling.Volume.Types
import Duckling.Testing.Types

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

allExamples :: [Example]
allExamples = concat
  [ examples (simple Millilitre 250)
             [ "250 millilitres"
             , "250ml"
             , "250 ml"
             ]
  , examples (simple Centilitre 25)
             [ "25 centilitres"
             , "25cl"
             , "25 cl"
             ]
  , examples (simple Litre 2)
             [ "2 litres"
             ]
  , examples (simple Gallon 3)
             [ "3 gallons"
             , "3 gal"
             ]
  , examples (simple Hectolitre 3)
             [ "3 hectolitres"
             ]
  , examples (simple Litre 0.5)
             [ "demi-litre"
             , "demi litre"
             ]
  , examples (simple Litre 0.25)
             [ "quart de litre"
             ]
  ]


-- 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.Volume.FR.Rules
  ( rules ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import Duckling.Regex.Types
import Duckling.Volume.Helpers
import Duckling.Numeral.Helpers (isPositive)
import qualified Duckling.Volume.Types as TVolume
import qualified Duckling.Numeral.Types as TNumeral

volumes :: [(Text, String, TVolume.Unit)]
volumes = [ ("<latent vol> ml"    , "m(l|illilitres?)" , TVolume.Millilitre)
          , ("<latent vol> cl"    , "c(l|entilitres?)" , TVolume.Centilitre)
          , ("<vol> hectoliters"  , "(hectolitres?)"    , TVolume.Hectolitre)
          , ("<vol> liters"       , "l(itres?)?"     , TVolume.Litre)
          , ("<latent vol> gallon", "gal(l?ons?)?"   , TVolume.Gallon)
          ]

rulesVolumes :: [Rule]
rulesVolumes = map go volumes
  where
    go :: (Text, String, TVolume.Unit) -> Rule
    go (name, regexPattern, u) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        ]
      , prod = \_ -> Just . Token Volume $ unitOnly u
      }

fractions :: [(Text, String, Double)]
fractions = [ ("quart", "quart de", 1/4)
            , ("half", "demi-?", 1/2)
            ]

rulesFractionalVolume :: [Rule]
rulesFractionalVolume = map go fractions
  where
    go :: (Text, String, Double) -> Rule
    go (name, regexPattern, f) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        , Predicate isUnitOnly
        ]
      , prod = \case
        (_:
         Token Volume TVolume.VolumeData{TVolume.unit = Just u}:
         _) ->
          Just . Token Volume $ volume u f
        _ -> Nothing
      }

rules :: [Rule]
rules =
  [
  ]
  ++ rulesVolumes
  ++ rulesFractionalVolume


-- 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.Volume.GA.Corpus
  ( corpus ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Resolve
import Duckling.Volume.Types
import Duckling.Testing.Types

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

allExamples :: [Example]
allExamples = concat
  [ examples (simple Millilitre 250)
             [ "250 millilÃtir"
             , "250 millilitir"
             , "250ml"
             , "250 ml"
             ]
  , examples (simple Litre 2)
             [ "2 lÃtir"
             ]
  , examples (simple Gallon 5)
             [ "5 galÃºin"
             ]
  , examples (simple Hectolitre 20)
             [ "20 heictilitear"
             , "2 kl"
             ]
  ]


-- 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.Volume.GA.Rules
  ( rules ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import Duckling.Regex.Types
import Duckling.Volume.Helpers
import Duckling.Numeral.Helpers (isPositive)
import qualified Duckling.Volume.Types as TVolume
import qualified Duckling.Numeral.Types as TNumeral

volumes :: [(Text, String, TVolume.Unit)]
volumes = [ ("<latent vol> ml", "m(l\\.?|h?illil(Ã|i)t(ea|i)r)"
            , TVolume.Millilitre)
          , ("<vol> hectoliters" , "heictil(Ã|i)t(ea|i)r"
            , TVolume.Hectolitre)
          , ("<vol> liters", "(l(Ã|i)t(ea|i)r|l\\.?)"
            , TVolume.Litre)
          , ("<latent vol> gallon", "n?gh?al(Ãº|u)i?n"
            , TVolume.Gallon)
          ]

rulesVolumes :: [Rule]
rulesVolumes = map go volumes
  where
    go :: (Text, String, TVolume.Unit) -> Rule
    go (name, regexPattern, u) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        ]
      , prod = \_ -> Just . Token Volume $ unitOnly u
      }

ruleKiloliter :: Rule
ruleKiloliter = Rule
  { name = "kiloliter"
  , pattern =
    [ Predicate isPositive
    , regex "(kl\\.?|g?ch?illil(Ã|i)t(ea|i)r)"
    ]
  , prod = \case
    (Token Numeral TNumeral.NumeralData{TNumeral.value = v}:
     _:_) ->
      Just . Token Volume . withUnit TVolume.Hectolitre $ valueOnly (10.0 * v)
    _ -> Nothing
  }

rules :: [Rule]
rules = [ ruleKiloliter
        ]
        ++ rulesVolumes


-- 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.Volume.HR.Corpus
  ( corpus ) where

import Prelude
import Data.String

import Duckling.Locale
import Duckling.Resolve
import Duckling.Testing.Types
import Duckling.Volume.Types

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

allExamples :: [Example]
allExamples = concat
  [ examples (simple Millilitre 250)
             [ "250 mililitara"
             , "250ml"
             , "250 ml"
             ]
  , examples (simple Litre 2)
             [ "2 litre"
             ]
  , examples (simple Gallon 3)
             [ "3 galona"
             , "3 gal"
             ]
  , examples (simple Hectolitre 3)
             [ "3 hektolitra"
             ]
  , examples (simple Litre 0.5)
             [ "pola litre"
             ]
  ]


-- 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.Volume.HR.Rules
  ( rules ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import Duckling.Regex.Types
import Duckling.Volume.Helpers
import Duckling.Numeral.Helpers (isPositive)
import qualified Duckling.Volume.Types as TVolume
import qualified Duckling.Numeral.Types as TNumeral

volumes :: [(Text, String, TVolume.Unit)]
volumes = [ ("<latent vol> ml"    , "m(l|ililita?ra?)" , TVolume.Millilitre)
          , ("<vol> hectoliters"  , "(hektolita?ra?)"    , TVolume.Hectolitre)
          , ("<vol> liters"       , "l(it(a)?r(a|e)?)?"     , TVolume.Litre)
          , ("<latent vol> gallon", "gal(ona?)?"   , TVolume.Gallon)
          ]

rulesVolumes :: [Rule]
rulesVolumes = map go volumes
  where
    go :: (Text, String, TVolume.Unit) -> Rule
    go (name, regexPattern, u) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        ]
      , prod = \_ -> Just . Token Volume $ unitOnly u
      }

fractions :: [(Text, String, Double)]
fractions = [ ("half", "pola", 1/2)
            ]

rulesFractionalVolume :: [Rule]
rulesFractionalVolume = map go fractions
  where
    go :: (Text, String, Double) -> Rule
    go (name, regexPattern, f) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        , Predicate isUnitOnly
        ]
      , prod = \case
        (_:
         Token Volume TVolume.VolumeData{TVolume.unit = Just u}:
         _) ->
          Just . Token Volume $ volume u f
        _ -> Nothing
      }

rules :: [Rule]
rules =
  [
  ]
  ++ rulesVolumes
  ++ rulesFractionalVolume


-- 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.Volume.IT.Corpus
  ( corpus ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Resolve
import Duckling.Volume.Types
import Duckling.Testing.Types

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

allExamples :: [Example]
allExamples = concat
  [ examples (simple Millilitre 250)
             [ "250 millilitri"
             , "250ml"
             , "250 ml"
             ]
  , examples (simple Litre 2)
             [ "2 litri"
             , "2l"
             ]
  , examples (simple Gallon 3)
             [ "3 galloni"
             , "3 gal"
             ]
  , examples (simple Hectolitre 3)
             [ "3 ettolitri"
             ]
  , examples (simple Litre 0.5)
             [ "mezzo litro"
             ]
  ]


-- 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.Volume.IT.Rules
  ( rules ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import Duckling.Regex.Types
import Duckling.Volume.Helpers
import Duckling.Numeral.Helpers (isPositive)
import qualified Duckling.Volume.Types as TVolume
import qualified Duckling.Numeral.Types as TNumeral

volumes :: [(Text, String, TVolume.Unit)]
volumes = [ ("<latent vol> ml"    , "m(l|illilitr(i|o))" , TVolume.Millilitre)
          , ("<vol> hectoliters"  , "ettolitr(i|o)"    , TVolume.Hectolitre)
          , ("<vol> liters"       , "l(itr(i|o))?"    , TVolume.Litre)
          , ("<latent vol> gallon", "gal(lon(e|i))?"   , TVolume.Gallon)
          ]

rulesVolumes :: [Rule]
rulesVolumes = map go volumes
  where
    go :: (Text, String, TVolume.Unit) -> Rule
    go (name, regexPattern, u) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        ]
      , prod = \_ -> Just . Token Volume $ unitOnly u
      }

fractions :: [(Text, String, Double)]
fractions = [ ("half", "mezzo", 1/2)
            ]

rulesFractionalVolume :: [Rule]
rulesFractionalVolume = map go fractions
  where
    go :: (Text, String, Double) -> Rule
    go (name, regexPattern, f) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        , Predicate isUnitOnly
        ]
      , prod = \case
        (_:
         Token Volume TVolume.VolumeData{TVolume.unit = Just u}:
         _) ->
          Just . Token Volume $ volume u f
        _ -> Nothing
      }

rules :: [Rule]
rules =
  [
  ]
  ++ rulesVolumes
  ++ rulesFractionalVolume


-- 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.Volume.KO.Rules
  ( rules ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import Duckling.Regex.Types
import Duckling.Volume.Helpers
import Duckling.Numeral.Helpers (isPositive)
import qualified Duckling.Volume.Types as TVolume
import qualified Duckling.Numeral.Types as TNumeral

volumes :: [(Text, String, TVolume.Unit)]
volumes = [ ("<latent vol> ml"    , "ml|(ë°€|ë¯¸)ë¦¬ë¦¬í„°" , TVolume.Millilitre)
          , ("<vol> hectoliters"  , "(í•µ|í—¥)í† ë¦¬í„°"    , TVolume.Hectolitre)
          , ("<vol> liters"       , "(l|ë¦¬í„°)"     , TVolume.Litre)
          , ("<latent vol> gallon", "gal(l?ons?)?|ê°¤(ëŸ°|ë¡ )"   , TVolume.Gallon)
          ]

rulesVolumes :: [Rule]
rulesVolumes = map go volumes
  where
    go :: (Text, String, TVolume.Unit) -> Rule
    go (name, regexPattern, u) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        ]
      , prod = \_ -> Just . Token Volume $ unitOnly u
      }

rules :: [Rule]
rules =
  [
  ]
  ++ rulesVolumes


-- 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.Volume.NL.Corpus
  ( corpus ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Resolve
import Duckling.Volume.Types
import Duckling.Testing.Types

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

allExamples :: [Example]
allExamples = concat
  [ examples (simple Millilitre 250)
             [ "250 milliliter"
             , "250ml"
             , "250 ml"
             ]
  , examples (simple Litre 2)
             [ "2 liter"
             , "2 liters"
             , "2l"
             , "2 l"
             ]
  , examples (simple Hectolitre 3)
             [ "3 hectoliter"
             , "3 hl"
             ]
  , examples (simple Litre 0.5)
             [ "halve liter"
             ]
  ]


-- 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.Volume.NL.Rules
  ( rules
  ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import Duckling.Regex.Types (GroupMatch(..))
import Duckling.Volume.Helpers
import Duckling.Numeral.Helpers (isPositive)
import qualified Duckling.Volume.Types as TVolume
import qualified Duckling.Numeral.Types as TNumeral

volumes :: [(Text, String, TVolume.Unit)]
volumes = [ ("<latent vol> ml"    , "m(illi)?l(iter)?" , TVolume.Millilitre)
          , ("<vol> hl"           , "h(ecto)?l(iter)?"   , TVolume.Hectolitre)
          , ("<vol> liters"       , "l(iters?)?"    , TVolume.Litre)
          ]

rulesVolumes :: [Rule]
rulesVolumes = map go volumes
  where
    go :: (Text, String, TVolume.Unit) -> Rule
    go (name, regexPattern, u) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        ]
      , prod = \_ -> Just . Token Volume $ unitOnly u
      }

fractions :: [(Text, String, Double)]
fractions = [ ("half", "halve", 1/2)
            ]

rulesFractionalVolume :: [Rule]
rulesFractionalVolume = map go fractions
  where
    go :: (Text, String, Double) -> Rule
    go (name, regexPattern, f) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        , Predicate isUnitOnly
        ]
      , prod = \case
        (_:
         Token Volume TVolume.VolumeData{TVolume.unit = Just u}:
         _) ->
          Just . Token Volume $ volume u f
        _ -> Nothing
      }

rules :: [Rule]
rules =
  [
  ]
  ++ rulesVolumes
  ++ rulesFractionalVolume


-- 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.Volume.PT.Corpus
  ( corpus ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Resolve
import Duckling.Volume.Types
import Duckling.Testing.Types

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

allExamples :: [Example]
allExamples = concat
  [ examples (simple Millilitre 250)
             [ "250 mililitros"
             , "250ml"
             , "250 ml"
             ]
  , examples (simple Litre 2)
             [ "2 litros"
             ]
  , examples (simple Gallon 1)
             [ "1 galÃ£o"
             ]
  , examples (simple Gallon 3)
             [ "3 galÃµes"
             ]
  , examples (simple Hectolitre 3)
             [ "3 hectolitros"
             ]
  , examples (simple Litre 0.5)
             [ "meio litro"
             ]
  ]


-- 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.Volume.PT.Rules
  ( rules ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import Duckling.Regex.Types
import Duckling.Volume.Helpers
import Duckling.Numeral.Helpers (isPositive)
import qualified Duckling.Volume.Types as TVolume
import qualified Duckling.Numeral.Types as TNumeral

volumes :: [(Text, String, TVolume.Unit)]
volumes = [ ("<latent vol> ml"    , "m(l|ililitros?)" , TVolume.Millilitre)
          , ("<vol> hectoliters"  , "(hectolitros?)"    , TVolume.Hectolitre)
          , ("<vol> liters"       , "l(itros?)?"     , TVolume.Litre)
          , ("<latent vol> gallon", "gal(a|Ã£|o|Ãµ)o?e?s?"   , TVolume.Gallon)
          ]

rulesVolumes :: [Rule]
rulesVolumes = map go volumes
  where
    go :: (Text, String, TVolume.Unit) -> Rule
    go (name, regexPattern, u) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        ]
      , prod = \_ -> Just . Token Volume $ unitOnly u
      }

fractions :: [(Text, String, Double)]
fractions = [ ("half", "meio", 1/2)
            ]

rulesFractionalVolume :: [Rule]
rulesFractionalVolume = map go fractions
  where
    go :: (Text, String, Double) -> Rule
    go (name, regexPattern, f) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        , Predicate isUnitOnly
        ]
      , prod = \case
        (_:
         Token Volume TVolume.VolumeData{TVolume.unit = Just u}:
         _) ->
          Just . Token Volume $ volume u f
        _ -> Nothing
      }

rules :: [Rule]
rules =
  [
  ]
  ++ rulesVolumes
  ++ rulesFractionalVolume


-- 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.Volume.RO.Corpus
  ( corpus
  ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Resolve
import Duckling.Volume.Types
import Duckling.Testing.Types

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

allExamples :: [Example]
allExamples = concat
  [ examples (simple Millilitre 250)
             [ "250 mililitri"
             , "250 de mililitri"
             , "250ml"
             , "250 ml"
             , "250 de ml"
             ]
  , examples (simple Litre 2)
             [ "2 litri"
             , "2 l"
             , "2l"
             ]
  , examples (simple Gallon 3)
             [ "3 galoane"
             , "3 gal"
             ]
  , examples (simple Hectolitre 3)
             [ "3 hectolitri"
             ]
  , examples (simple Litre 0.5)
             [ "jumatate de litru"
             , "jumÄƒtate de litru"
             ]
  , examples (simple Gallon 20)
             [ "douazeci de galoane"
             ]
  ]


-- 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.Volume.RO.Rules
  ( rules
  ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import Duckling.Regex.Types
import Duckling.Volume.Helpers
import Duckling.Numeral.Helpers (isPositive)
import qualified Duckling.Volume.Types as TVolume
import qualified Duckling.Numeral.Types as TNumeral

volumes :: [(Text, String, TVolume.Unit)]
volumes = [ ("<latent vol> ml"    , "(de )?m(ililitr[ui]|l)" , TVolume.Millilitre)
          , ("<vol> hectoliters"  , "(de )?hectolitr[ui]"    , TVolume.Hectolitre)
          , ("<vol> liters"       , "(de )?l(itr[ui])?"     , TVolume.Litre)
          , ("<latent vol> gallon", "(de )?gal(oane|on)?"   , TVolume.Gallon)
          ]

rulesVolumes :: [Rule]
rulesVolumes = map go volumes
  where
    go :: (Text, String, TVolume.Unit) -> Rule
    go (name, regexPattern, u) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        ]
      , prod = \_ -> Just . Token Volume $ unitOnly u
      }

fractions :: [(Text, String, Double)]
fractions = [ ("half", "jum(a|Äƒ)tate", 1/2)
            ]

rulesFractionalVolume :: [Rule]
rulesFractionalVolume = map go fractions
  where
    go :: (Text, String, Double) -> Rule
    go (name, regexPattern, f) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        , Predicate isUnitOnly
        ]
      , prod = \case
        (_:
         Token Volume TVolume.VolumeData{TVolume.unit = Just u}:
         _) ->
          Just . Token Volume $ volume u f
        _ -> Nothing
      }

rules :: [Rule]
rules =
  [
  ]
  ++ rulesVolumes
  ++ rulesFractionalVolume


-- 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.Volume.RU.Corpus
  ( corpus
  ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Resolve
import Duckling.Testing.Types
import Duckling.Volume.Types

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

allExamples :: [Example]
allExamples = concat
  [ examples (simple Millilitre 250)
             [ "250 Ð¼Ð¸Ð»Ð»Ð¸Ð»Ð¸Ñ‚Ñ€Ð¾Ð²"
             , "250Ð¼Ð»"
             , "250 Ð¼Ð»"
             ]
  , examples (simple Litre 2)
             [ "2 Ð»Ð¸Ñ‚Ñ€Ð°"
             , "2 Ð»"
             , "Ð´Ð²Ð° Ð»Ð¸Ñ‚Ñ€Ð°"
             ]
  , examples (simple Litre 1)
             [ "1 Ð»Ð¸Ñ‚Ñ€"
             , "Ð¾Ð´Ð¸Ð½ Ð»Ð¸Ñ‚Ñ€"
             , "1Ð»"
             ]
  , examples (simple Gallon 3)
             [ "3 Ð³Ð°Ð»Ð»Ð¾Ð½Ð°"
             ]
  , examples (simple Hectolitre 3)
             [ "3 Ð³ÐµÐºÑ‚Ð¾Ð»Ð¸Ñ‚Ñ€Ð°"
             , "3 Ð³Ð»"
             , "3Ð³Ð»"
             ]
  , examples (simple Litre 0.5)
             [ "Ð¿Ð¾Ð»-Ð»Ð¸Ñ‚Ñ€Ð°"
             , "Ð¿Ð¾Ð»Ð»Ð¸Ñ‚Ñ€Ð°"
             , "Ð¿Ð¾Ð» Ð»Ð¸Ñ‚Ñ€Ð°"
             ]
  , examples (simple Litre 1.5)
             [ "Ð¿Ð¾Ð»Ñ‚Ð¾Ñ€Ð° Ð»Ð¸Ñ‚Ñ€Ð°"
             ]
  ]


-- 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.Volume.RU.Rules
  ( rules
  ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import Duckling.Regex.Types
import Duckling.Volume.Helpers
import Duckling.Numeral.Helpers (isPositive)
import qualified Duckling.Volume.Types as TVolume
import qualified Duckling.Numeral.Types as TNumeral

volumes :: [(Text, String, TVolume.Unit)]
volumes = [ ("<latent vol> ml"    , "Ð¼Ð»|Ð¼Ð¸Ð»Ð»Ð¸Ð»Ð¸Ñ‚Ñ€(Ð°|Ð¾Ð²)?" , TVolume.Millilitre)
          , ("<vol> hectoliters"  , "Ð³Ð»|Ð³ÐµÐºÑ‚Ð¾Ð»Ð¸Ñ‚Ñ€(Ð°|Ð¾Ð²)?" , TVolume.Hectolitre)
          , ("<vol> liters"       , "Ð»(Ð¸Ñ‚Ñ€(Ð°|Ð¾Ð²)?)?"      , TVolume.Litre)
          , ("<latent vol> gallon", "Ð³Ð°Ð»Ð»Ð¾Ð½(Ð°|Ð¾Ð²)?"       , TVolume.Gallon)
          ]

rulesVolumes :: [Rule]
rulesVolumes = map go volumes
  where
    go :: (Text, String, TVolume.Unit) -> Rule
    go (name, regexPattern, u) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        ]
      , prod = \_ -> Just . Token Volume $ unitOnly u
      }

fractions :: [(Text, String, Double)]
fractions = [ ("half", "Ð¿Ð¾Ð»[-\\s]?", 1/2)
            ]

rulesFractionalVolume :: [Rule]
rulesFractionalVolume = map go fractions
  where
    go :: (Text, String, Double) -> Rule
    go (name, regexPattern, f) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        , Predicate isUnitOnly
        ]
      , prod = \case
        (_:
         Token Volume TVolume.VolumeData{TVolume.unit = Just u}:
         _) ->
          Just . Token Volume $ volume u f
        _ -> Nothing
      }

ruleHalfLiter :: Rule
ruleHalfLiter = Rule
  { name = "half liter"
  , pattern =
    [ regex "Ð¿Ð¾Ð»Ð»Ð¸Ñ‚Ñ€Ð°"
    ]
  , prod = \_ -> Just . Token Volume . withUnit TVolume.Litre $ valueOnly 0.5
  }

rules :: [Rule]
rules = [ ruleHalfLiter
        ]
        ++ rulesVolumes
        ++ rulesFractionalVolume


-- 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.Volume.TR.Corpus
  ( corpus ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Resolve
import Duckling.Testing.Types
import Duckling.Volume.Types

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

allExamples :: [Example]
allExamples = concat
  [ examples (simple Millilitre 250)
             [ "250 mililitre"
             , "250ml"
             , "250 ml"
             ]
  , examples (simple Litre 2)
             [ "2 litre" ]
  , examples (simple Gallon 3)
             [ "3 galon"
             , "3 gal"
             ]
  , examples (simple Hectolitre 3)
             [ "3 hektolitre"
             ]
  , examples (simple Litre 0.5)
             [ "yarÄ±m litre"
             ]
  ]


-- 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.Volume.TR.Rules
  ( rules ) where

import Data.String
import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Types
import Duckling.Regex.Types
import Duckling.Volume.Helpers
import Duckling.Numeral.Helpers (isPositive)
import qualified Duckling.Volume.Types as TVolume
import qualified Duckling.Numeral.Types as TNumeral

volumes :: [(Text, String, TVolume.Unit)]
volumes = [ ("<latent vol> ml"    , "m(l|ililitre)" , TVolume.Millilitre)
          , ("<vol> hectoliters"  , "(hektolitre)"  , TVolume.Hectolitre)
          , ("<vol> liters"       , "l(t|itre)"     , TVolume.Litre)
          , ("<latent vol> gallon", "gal(l?on?)?"   , TVolume.Gallon)
          ]

rulesVolumes :: [Rule]
rulesVolumes = map go volumes
  where
    go :: (Text, String, TVolume.Unit) -> Rule
    go (name, regexPattern, u) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        ]
      , prod = \_ -> Just . Token Volume $ unitOnly u
      }

fractions :: [(Text, String, Double)]
fractions = [ ("half", "yar\305m", 1/2)
            ]

rulesFractionalVolume :: [Rule]
rulesFractionalVolume = map go fractions
  where
    go :: (Text, String, Double) -> Rule
    go (name, regexPattern, f) = Rule
      { name = name
      , pattern =
        [ regex regexPattern
        , Predicate isUnitOnly
        ]
      , prod = \case
        (_:
         Token Volume TVolume.VolumeData{TVolume.unit = Just u}:
         _) ->
          Just . Token Volume $ volume u f
        _ -> Nothing
      }

rules :: [Rule]
rules =
  [
  ]
  ++ rulesVolumes
  ++ rulesFractionalVolume


-- 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 LambdaCase #-}
{-# LANGUAGE NoRebindableSyntax #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}

module Main (main) where

import Control.DeepSeq
import Control.Monad
import Data.Aeson
import Data.Hashable
import Data.Semigroup ((<>))
import Data.Text (Text)
import Data.Typeable
import GHC.Generics
import Prelude
import qualified Data.HashSet as HashSet
import qualified TextShow as TS

import Duckling.Debug
import Duckling.Locale
import Duckling.Regex.Types (GroupMatch(..))
import Duckling.Resolve (Resolve(..))
import Duckling.Types

data MyDimension = MyDimension deriving (Eq, Show, Typeable)

instance CustomDimension MyDimension where
  type DimensionData MyDimension = MyData
  dimRules _ = [myDimensionRule, myDimensionRule']
  dimLangRules _ _ = []
  dimLocaleRules _ _ = []
  dimDependents _ = HashSet.empty

data MyData = MyData
  { iField :: Int
  , bField :: Bool
  , tField :: Text
  }
  deriving (Eq, Generic, Hashable, Ord, Show, NFData)

instance Resolve MyData where
  type ResolvedValue MyData = MyValue
  resolve _ _ MyData{..} = Just
    ( MyValue $ TS.showt iField <> "," <> TS.showt bField <> "," <> tField
    , False )

newtype MyValue = MyValue { value :: Text }
  deriving (Eq, Ord, Show)

instance ToJSON MyValue where
  toJSON (MyValue value) = object [ "value" .= value ]

myDimensionPredicate :: Predicate
myDimensionPredicate (Token (CustomDimension (dim :: a)) dimData)
  | Just Refl <- eqT @a @MyDimension, MyData{..} <- dimData =
      iField == 42 && bField
myDimensionPredicate _ = False

myDimensionRule :: Rule
myDimensionRule = Rule
  { name = "my dimension (simple)"
  , pattern =
    [ regex "my dimension"
    ]
  , prod = \case
      (_:_) -> Just . Token (CustomDimension MyDimension) $ MyData
                 { iField = 42
                 , bField = True
                 , tField = "hello world"
                 }
      _ -> Nothing
  }

myDimensionRule' :: Rule
myDimensionRule' = Rule
  { name = "my dimension (pattern match)"
  , pattern =
    [ Predicate myDimensionPredicate
    , regex "pattern match"
    ]
  , prod = \case
      ((Token (CustomDimension (dim :: a)) dimData):
       Token RegexMatch (GroupMatch _):
       _)
        | Just Refl <- eqT @a @MyDimension, MyData{..} <- dimData ->
            Just . Token (CustomDimension MyDimension) $ MyData
              { iField = iField * 10
              , bField = not bField
              , tField = "goodnight moon"
              }
      _ -> Nothing
  }

main :: IO ()
main = do
  let en = makeLocale EN Nothing
  debug en "testing my dimension" [Seal (CustomDimension MyDimension)] >>= print
  debug en "testing my dimension pattern match" [Seal (CustomDimension MyDimension)] >>= print


-- 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 ScopedTypeVariables #-}
{-# OPTIONS -fno-full-laziness #-}

module Main (main) where

import Control.Monad
import System.Environment

import Duckling.Debug
import Duckling.Dimensions.Types
import Duckling.Locale

main :: IO ()
main = do
  (repeatCount :: Int) <- read . head <$> getArgs
  void $ replicateM repeatCount $ void $ do
    debug en "Monday 3rd at 9.30am or 2.30pm, Saturday 8th at 10.30am, Tuesday 11th at 2pm, Wednesday 12th at 2.30pm, Friday 14th at 12.30pm xx" [Seal Time]
    debug es "Horario es de Lunes a Viernes de 2 pm a 10 pm. S\195\161bado de 9 am a 7 pm" [Seal Time]
    where
      en = makeLocale EN Nothing
      es = makeLocale ES Nothing


-- 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 ScopedTypeVariables #-}
{-# OPTIONS -fno-full-laziness #-}

module Main (main) where

import Control.Monad
import System.Environment

import Duckling.Debug
import Duckling.Dimensions.Types
import Duckling.Locale

main :: IO ()
main = do
  (repeatCount :: Int) <- read . head <$> getArgs
  void $ replicateM repeatCount $ void $ do
    debug en "My number is 123" [Seal PhoneNumber,Seal Distance,Seal Numeral,Seal Email]
    debug en "Wednesday 5:00PM 3/29/2017" [Seal Numeral,Seal Time]
    debug zh "12:30pm" [Seal Time]
    debug en "tomorrow at 4pm" [Seal Time]
    debug en "Tomorrow at 12.30?" [Seal Time]
    debug en "Wednesday 9am" [Seal Time]
    debug en "Sure do! Will 11:30 work?" [Seal Time,Seal AmountOfMoney]
    debug en "8:00am" [Seal Time]
    where
      en = makeLocale EN Nothing
      zh = makeLocale ZH Nothing