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

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

import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers
import Duckling.Quantity.Helpers
import Duckling.Regex.Types
import Duckling.Types
import qualified Duckling.Numeral.Types as TNumeral
import qualified Duckling.Quantity.Types as TQuantity

quantities :: [(Text, String, TQuantity.Unit)]
quantities :: [(Text, String, Unit)]
quantities =
  [ (Text
"<quantity> cups", String
"(كوب(ان|ين)?|[أا]كواب)", Unit
TQuantity.Cup)
  , (Text
"<quantity> grams", String
"(((كيلو|مي?لي?) ?)?((غ|ج)رام(ات|ين|ان)?)|ك(غ|ج)م?|مل(غ|ج)|(غ|ج)م)", Unit
TQuantity.Gram)
  , (Text
"<quantity> lb", String
"(باوند(ان|ين)?)", Unit
TQuantity.Pound)
  , (Text
"<quantity> oz", String
"([أا]ونص([ةه]|تان|تين|ات))", Unit
TQuantity.Ounce)
  ]

opsMap :: HashMap Text (Double -> Double)
opsMap :: HashMap Text (Double -> Double)
opsMap = [(Text, Double -> Double)] -> HashMap Text (Double -> Double)
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HashMap.fromList
  [ ( Text
"غرامان", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2))
  , ( Text
"غرامين", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2))
  , ( Text
"كوبان", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2))
  , ( Text
"كوبين", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2))
  , ( Text
"باوندان", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2))
  , ( Text
"باوندين", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2))
  , ( Text
"اونصتان", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2))
  , ( Text
"اونصتين", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2))
  , ( Text
"أونصتان", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2))
  , ( Text
"أونصتين", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2))
  , ( Text
"جرامان", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2))
  , ( Text
"جرامين", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2))
  , ( Text
"ميلي غرامان", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
500))
  , ( Text
"ميليغرامان", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
500))
  , ( Text
"ميلغرامان", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
500))
  , ( Text
"ميلي غرامين", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
500))
  , ( Text
"ميليغرامين", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
500))
  , ( Text
"ميلغرامين", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
500))
  , ( Text
"ميلي جرامان", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
500))
  , ( Text
"ميليجرامان", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
500))
  , ( Text
"ميلجرامان", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
500))
  , ( Text
"ميلي جرامين", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
500))
  , ( Text
"ميليجرامين", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
500))
  , ( Text
"ميلجرامين", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
500))
  , ( Text
"ميلي غرام", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000))
  , ( Text
"ميليغرام", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000))
  , ( Text
"ميلغرام", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000))
  , ( Text
"كيلوغرام", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
1000))
  , ( Text
"كيلو غرام", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
1000))
  , ( Text
"ميلي غرامات", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000))
  , ( Text
"ميليغرامات", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000))
  , ( Text
"ميلغرامات", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000))
  , ( Text
"ملغ", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000))
  , ( Text
"كغ", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
1000))
  , ( Text
"كغم", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
1000))
  , ( Text
"ميلي جرام", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000))
  , ( Text
"ميليجرام", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000))
  , ( Text
"ميلجرام", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000))
  , ( Text
"ميلي جرامات", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000))
  , ( Text
"ميليجرامات", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000))
  , ( Text
"ميلجرامات", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000))
  , ( Text
"كيلوغرامات", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
1000))
  , ( Text
"كيلو غرامات", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
1000))
  , ( Text
"ملج", (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000))
  , ( Text
"كيلوجرام", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
1000))
  , ( Text
"كيلو جرام", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
1000))
  , ( Text
"كيلوجرامات", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
1000))
  , ( Text
"كيلو جرامات", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
1000))
  , ( Text
"كج", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
1000))
  , ( Text
"كجم", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
1000))
  , ( Text
"كيلوغرامان", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2000))
  , ( Text
"كيلوغرامين", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2000))
  , ( Text
"كيلو غرامان", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2000))
  , ( Text
"كيلو غرامين", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2000))
  , ( Text
"كيلوجرامان", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2000))
  , ( Text
"كيلوجرامين", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2000))
  , ( Text
"كيلو جرامان", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2000))
  , ( Text
"كيلو جرامين", (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
2000))
  ]

ruleNumeralQuantities :: [Rule]
ruleNumeralQuantities :: [Rule]
ruleNumeralQuantities = ((Text, String, Unit) -> Rule) -> [(Text, String, Unit)] -> [Rule]
forall a b. (a -> b) -> [a] -> [b]
map (Text, String, Unit) -> Rule
go [(Text, String, Unit)]
quantities
  where
    go :: (Text, String, TQuantity.Unit) -> Rule
    go :: (Text, String, Unit) -> Rule
go (Text
name, String
regexPattern, Unit
u) = Rule :: Text -> Pattern -> Production -> Rule
Rule
      { name :: Text
name = Text
name
      , pattern :: Pattern
pattern = [ (NumeralData -> Double) -> (Double -> Bool) -> PatternItem
forall t. (NumeralData -> t) -> (t -> Bool) -> PatternItem
numberWith NumeralData -> Double
TNumeral.value (Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0), String -> PatternItem
regex String
regexPattern ]
      , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
        (Token Dimension a
Numeral a
nd:
         Token Dimension a
RegexMatch (GroupMatch (match:_)):
         [Token]
_) -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (QuantityData -> Token) -> QuantityData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension QuantityData -> QuantityData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension QuantityData
Quantity (QuantityData -> Maybe Token) -> QuantityData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Unit -> Double -> QuantityData
quantity Unit
u Double
value
          where value :: Double
value = HashMap Text (Double -> Double) -> Text -> Double -> Double
getValue HashMap Text (Double -> Double)
opsMap Text
match (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ NumeralData -> Double
TNumeral.value a
NumeralData
nd
        [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
      }

ruleAQuantity :: [Rule]
ruleAQuantity :: [Rule]
ruleAQuantity = ((Text, String, Unit) -> Rule) -> [(Text, String, Unit)] -> [Rule]
forall a b. (a -> b) -> [a] -> [b]
map (Text, String, Unit) -> Rule
go [(Text, String, Unit)]
quantities
  where
    go :: (Text, String, TQuantity.Unit) -> Rule
    go :: (Text, String, Unit) -> Rule
go (Text
name, String
regexPattern, Unit
u) = Rule :: Text -> Pattern -> Production -> Rule
Rule
      { name :: Text
name = Text
name
      , pattern :: Pattern
pattern = [ String -> PatternItem
regex String
regexPattern ]
      , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
        (Token Dimension a
RegexMatch (GroupMatch (match:_)):
         [Token]
_) -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (QuantityData -> Token) -> QuantityData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension QuantityData -> QuantityData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension QuantityData
Quantity (QuantityData -> Maybe Token) -> QuantityData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Unit -> Double -> QuantityData
quantity Unit
u (Double -> QuantityData) -> Double -> QuantityData
forall a b. (a -> b) -> a -> b
$ HashMap Text (Double -> Double) -> Text -> Double -> Double
getValue HashMap Text (Double -> Double)
opsMap Text
match Double
1
        [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
      }

ruleQuantityOfProduct :: Rule
ruleQuantityOfProduct :: Rule
ruleQuantityOfProduct = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<quantity> of product"
  , pattern :: Pattern
pattern =
    [ Dimension QuantityData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension QuantityData
Quantity
    , String -> PatternItem
regex String
"من ([ء-ي]+)"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
    (Token Dimension a
Quantity a
qd:Token Dimension a
RegexMatch (GroupMatch (product:_)):[Token]
_) ->
      Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (QuantityData -> Token) -> QuantityData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension QuantityData -> QuantityData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension QuantityData
Quantity (QuantityData -> Maybe Token) -> QuantityData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Text -> QuantityData -> QuantityData
withProduct Text
product a
QuantityData
qd
    [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

rules :: [Rule]
rules :: [Rule]
rules =
  [ Rule
ruleQuantityOfProduct
  ]
  [Rule] -> [Rule] -> [Rule]
forall a. [a] -> [a] -> [a]
++ [Rule]
ruleNumeralQuantities
  [Rule] -> [Rule] -> [Rule]
forall a. [a] -> [a] -> [a]
++ [Rule]
ruleAQuantity