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

module Duckling.Duration.AR.Rules
  ( rules
  ) where

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

import Duckling.Dimensions.Types
import Duckling.Duration.Helpers
import Duckling.Numeral.Helpers (parseInt, parseInteger)
import Duckling.Numeral.Types (NumeralData(..))
import Duckling.Regex.Types
import Duckling.Types
import qualified Duckling.Numeral.Types as TNumeral
import qualified Duckling.TimeGrain.Types as TG

ruleDurationQuarterOfAnHour :: Rule
ruleDurationQuarterOfAnHour :: Rule
ruleDurationQuarterOfAnHour = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"quarter of an hour"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(ربع ساعة)"
    ]
  , prod :: Production
prod = \[Token]
_ -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DurationData -> Token) -> DurationData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DurationData -> DurationData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DurationData
Duration (DurationData -> Maybe Token) -> DurationData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> DurationData
duration Grain
TG.Minute Int
15
  }

ruleDurationHalfAnHour :: Rule
ruleDurationHalfAnHour :: Rule
ruleDurationHalfAnHour = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"half an hour"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(1/2\\s?ساع[ةه]?|نصف? ساع[ةه])"
    ]
  , prod :: Production
prod = \[Token]
_ -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DurationData -> Token) -> DurationData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DurationData -> DurationData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DurationData
Duration (DurationData -> Maybe Token) -> DurationData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> DurationData
duration Grain
TG.Minute Int
30
  }

ruleDurationThreeQuartersOfAnHour :: Rule
ruleDurationThreeQuartersOfAnHour :: Rule
ruleDurationThreeQuartersOfAnHour = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"three-quarters of an hour"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(3/4\\s?(ال)?ساع[ةه]?|ثلاث[ةه]?(\\s|-)[أا]رباع (ال)?ساع[ةه])"
    ]
  , prod :: Production
prod = \[Token]
_ -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DurationData -> Token) -> DurationData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DurationData -> DurationData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DurationData
Duration (DurationData -> Maybe Token) -> DurationData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> DurationData
duration Grain
TG.Minute Int
45
  }

ruleNumeralQuotes :: Rule
ruleNumeralQuotes :: Rule
ruleNumeralQuotes = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<integer> + '\""
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isNatural
    , String -> PatternItem
regex String
"(['\"])"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Numeral NumeralData{TNumeral.value = v}:
       Token Dimension a
RegexMatch (GroupMatch (x:_)):
       [Token]
_) -> case Text
x of
         Text
"'"  -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token) -> (Int -> Token) -> Int -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DurationData -> DurationData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DurationData
Duration (DurationData -> Token) -> (Int -> DurationData) -> Int -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Minute (Int -> Maybe Token) -> Int -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
floor Double
v
         Text
"\"" -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token) -> (Int -> Token) -> Int -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DurationData -> DurationData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DurationData
Duration (DurationData -> Token) -> (Int -> DurationData) -> Int -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Second (Int -> Maybe Token) -> Int -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
floor Double
v
         Text
_    -> Maybe Token
forall a. Maybe a
Nothing
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDurationDotNumeralHours :: Rule
ruleDurationDotNumeralHours :: Rule
ruleDurationDotNumeralHours = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"number.number hours"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(\\d+)\\.(\\d+) *ساع(ة|ات)"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (h:m:_)):[Token]
_) -> do
        Integer
hh <- Text -> Maybe Integer
parseInteger Text
h
        Integer
mnum <- Text -> Maybe Integer
parseInteger Text
m
        let mden :: Integer
mden = Integer
10 Integer -> Int -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Text -> Int
Text.length Text
m
        Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DurationData -> Token) -> DurationData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DurationData -> DurationData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DurationData
Duration (DurationData -> Maybe Token) -> DurationData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Integer -> Integer -> Integer -> DurationData
minutesFromHourMixedFraction Integer
hh Integer
mnum Integer
mden
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDurationAndHalfHour :: Rule
ruleDurationAndHalfHour :: Rule
ruleDurationAndHalfHour = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<integer> and an half hour"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isNatural
    , String -> PatternItem
regex String
"و ?نصف? ساع[ةه]"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Numeral NumeralData{TNumeral.value = v}:[Token]
_) ->
        Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token) -> (Int -> Token) -> Int -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DurationData -> DurationData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DurationData
Duration (DurationData -> Token) -> (Int -> DurationData) -> Int -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Grain -> Int -> DurationData
duration Grain
TG.Minute (Int -> Maybe Token) -> Int -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int
30 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
60 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
floor Double
v
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleTwoSeconds :: Rule
ruleTwoSeconds :: Rule
ruleTwoSeconds = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"two seconds"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"ثانيتين|ثانيتان|لحظتين|لحظتان"
    ]
  , prod :: Production
prod = \[Token]
_ -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DurationData -> Token) -> DurationData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DurationData -> DurationData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DurationData
Duration (DurationData -> Maybe Token) -> DurationData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> DurationData
duration Grain
TG.Second Int
2
  }

ruleTwoMinutes :: Rule
ruleTwoMinutes :: Rule
ruleTwoMinutes = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"two minutes"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"دقيقتين|دقيقتان"
    ]
  , prod :: Production
prod = \[Token]
_ -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DurationData -> Token) -> DurationData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DurationData -> DurationData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DurationData
Duration (DurationData -> Maybe Token) -> DurationData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> DurationData
duration Grain
TG.Minute Int
2
  }

ruleTwoHours :: Rule
ruleTwoHours :: Rule
ruleTwoHours = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"two hours"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"ساعتين|ساعتان"
    ]
  , prod :: Production
prod = \[Token]
_ -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DurationData -> Token) -> DurationData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DurationData -> DurationData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DurationData
Duration (DurationData -> Maybe Token) -> DurationData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> DurationData
duration Grain
TG.Hour Int
2
  }

ruleTwoYears :: Rule
ruleTwoYears :: Rule
ruleTwoYears = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"dual years"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"سنتين|سنتان"
    ]
  , prod :: Production
prod = \[Token]
_ -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DurationData -> Token) -> DurationData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DurationData -> DurationData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DurationData
Duration (DurationData -> Maybe Token) -> DurationData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> DurationData
duration Grain
TG.Year Int
2
  }

-- this rule handles TG.Day, TG.Week and TG.Month
ruleDualUnitofduration :: Rule
ruleDualUnitofduration :: Rule
ruleDualUnitofduration = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"dual <unit-of-duration>"
  , pattern :: Pattern
pattern =
    [ Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    , String -> PatternItem
regex String
"(ان|ين)"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
TimeGrain a
grain:[Token]
_) -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DurationData -> Token) -> DurationData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DurationData -> DurationData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DurationData
Duration (DurationData -> Maybe Token) -> DurationData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> DurationData
duration a
Grain
grain Int
2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleSingleUnitofduration :: Rule
ruleSingleUnitofduration :: Rule
ruleSingleUnitofduration = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"single <unit-of-duration>"
  , pattern :: Pattern
pattern =
    [ Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
TimeGrain a
grain:[Token]
_) -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DurationData -> Token) -> DurationData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DurationData -> DurationData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DurationData
Duration (DurationData -> Maybe Token) -> DurationData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> DurationData
duration a
Grain
grain Int
1
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

rules :: [Rule]
rules :: [Rule]
rules =
  [ Rule
ruleDurationQuarterOfAnHour
  , Rule
ruleDurationHalfAnHour
  , Rule
ruleDurationThreeQuartersOfAnHour
  , Rule
ruleDurationDotNumeralHours
  , Rule
ruleDurationAndHalfHour
  , Rule
ruleNumeralQuotes
  , Rule
ruleTwoSeconds
  , Rule
ruleTwoMinutes
  , Rule
ruleTwoHours
  , Rule
ruleTwoYears
  , Rule
ruleDualUnitofduration
  , Rule
ruleSingleUnitofduration
  ]