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

import Data.String
import Prelude

import Duckling.Dimensions.Types
import Duckling.Distance.Helpers
import Duckling.Distance.Types (DistanceData(..))
import Duckling.Numeral.Helpers
import Duckling.Numeral.Types
import Duckling.Regex.Types
import Duckling.Types
import qualified Duckling.Distance.Types as TDistance
import qualified Duckling.Numeral.Types as TNumeral

ruleDistCentimeters :: Rule
ruleDistCentimeters :: Rule
ruleDistCentimeters = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<dist> centimeters"
  , pattern :: Pattern
pattern =
    [ Dimension DistanceData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension DistanceData
Distance
    , String -> PatternItem
regex String
"cm|厘米|公分"
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
Distance a
dd:[Token]
_) ->
        Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DistanceData -> Token) -> DistanceData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Maybe Token) -> DistanceData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData -> DistanceData
withUnit Unit
TDistance.Centimetre a
DistanceData
dd
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDistMeters :: Rule
ruleDistMeters :: Rule
ruleDistMeters = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<dist> meters"
  , pattern :: Pattern
pattern =
    [ Dimension DistanceData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension DistanceData
Distance
    , String -> PatternItem
regex String
"m|米|公尺"
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
Distance a
dd:[Token]
_) ->
        Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DistanceData -> Token) -> DistanceData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Maybe Token) -> DistanceData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData -> DistanceData
withUnit Unit
TDistance.Metre a
DistanceData
dd
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDistKm :: Rule
ruleDistKm :: Rule
ruleDistKm = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<dist> km"
  , pattern :: Pattern
pattern =
    [ Dimension DistanceData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension DistanceData
Distance
    , String -> PatternItem
regex String
"km|千米|公(里|裏)"
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
Distance a
dd:[Token]
_) ->
        Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DistanceData -> Token) -> DistanceData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Maybe Token) -> DistanceData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData -> DistanceData
withUnit Unit
TDistance.Kilometre a
DistanceData
dd
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }


ruleDistFeetAndDistInch :: Rule
ruleDistFeetAndDistInch :: Rule
ruleDistFeetAndDistInch = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<dist> feet and <dist> inch "
  , pattern :: Pattern
pattern =
    [ Dimension DistanceData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension DistanceData
Distance
    , String -> PatternItem
regex String
"'|f(oo|ee)?ts?|英尺|呎"
    , Dimension DistanceData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension DistanceData
Distance
    , String -> PatternItem
regex String
"''|\"|inch(es)?|英寸|英吋|吋"
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
Distance a
dd:[Token]
_) ->
        Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DistanceData -> Token) -> DistanceData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Maybe Token) -> DistanceData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData -> DistanceData
withUnit Unit
TDistance.Foot a
DistanceData
dd
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDistInch :: Rule
ruleDistInch :: Rule
ruleDistInch = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<dist> inch"
  , pattern :: Pattern
pattern =
    [ Dimension DistanceData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension DistanceData
Distance
    , String -> PatternItem
regex String
"''|\"|inch(es)?|英寸|英吋|吋"
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
Distance a
dd:[Token]
_) ->
        Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DistanceData -> Token) -> DistanceData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Maybe Token) -> DistanceData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData -> DistanceData
withUnit Unit
TDistance.Inch a
DistanceData
dd
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDistFeet :: Rule
ruleDistFeet :: Rule
ruleDistFeet = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<dist> feet"
  , pattern :: Pattern
pattern =
    [ Dimension DistanceData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension DistanceData
Distance
    , String -> PatternItem
regex String
"'|f(oo|ee)?ts?|英尺|呎"
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
Distance a
dd:[Token]
_) ->
        Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DistanceData -> Token) -> DistanceData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Maybe Token) -> DistanceData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData -> DistanceData
withUnit Unit
TDistance.Foot a
DistanceData
dd
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDistMiles :: Rule
ruleDistMiles :: Rule
ruleDistMiles = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<dist> miles"
  , pattern :: Pattern
pattern =
    [ Dimension DistanceData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension DistanceData
Distance
    , String -> PatternItem
regex String
"miles?|英(里|裏)"
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
Distance a
dd:[Token]
_) ->
        Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DistanceData -> Token) -> DistanceData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Maybe Token) -> DistanceData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData -> DistanceData
withUnit Unit
TDistance.Mile a
DistanceData
dd
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDistOneMeterAnd :: Rule
ruleDistOneMeterAnd :: Rule
ruleDistOneMeterAnd = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"one meter and <dist>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"米"
    , Predicate -> PatternItem
Predicate Predicate
isPositive
    ]
  , prod :: Production
prod = \case
      (Token
_:Token Dimension a
Numeral NumeralData{TNumeral.value = v}:[Token]
_) ->
        Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DistanceData -> Token) -> DistanceData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Maybe Token) -> DistanceData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData -> DistanceData
withUnit Unit
TDistance.Metre (Double -> DistanceData
distance (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
vDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
10))
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDistMetersAnd :: Rule
ruleDistMetersAnd :: Rule
ruleDistMetersAnd = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<dist> meters and <dist>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isPositive
    , String -> PatternItem
regex String
"米"
    , Predicate -> PatternItem
Predicate Predicate
isPositive
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
Numeral NumeralData{TNumeral.value = v1}:Token
_:
        Token Dimension a
Numeral NumeralData{TNumeral.value = v2}:[Token]
_) ->
        Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token)
-> (DistanceData -> Token) -> DistanceData -> Maybe Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Maybe Token) -> DistanceData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData -> DistanceData
withUnit Unit
TDistance.Metre (Double -> DistanceData
distance (Double
v1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
v2Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
10))
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalNumeralDash :: Rule
ruleIntervalNumeralDash :: Rule
ruleIntervalNumeralDash = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<numeral> - <dist>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isPositive
    , String -> PatternItem
regex String
"-|~|到|至"
    , Predicate -> PatternItem
Predicate Predicate
isSimpleDistance
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
Numeral NumeralData{TNumeral.value = from}:
       Token
_:
       Token Dimension a
Distance DistanceData{TDistance.value = Just to,
       TDistance.unit = Just u}:[Token]
_) | Double
from Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
to ->
         Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token) -> Token -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Token) -> DistanceData -> Token
forall a b. (a -> b) -> a -> b
$ (Double, Double) -> DistanceData -> DistanceData
withInterval (Double
from, Double
to) (DistanceData -> DistanceData) -> DistanceData -> DistanceData
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData
unitOnly Unit
u
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalDash :: Rule
ruleIntervalDash :: Rule
ruleIntervalDash = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<dist> - <dist>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isSimpleDistance
    , String -> PatternItem
regex String
"-|~|到|至"
    , Predicate -> PatternItem
Predicate Predicate
isSimpleDistance
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
Distance DistanceData{TDistance.value = Just from,
                  TDistance.unit = Just u1}:
       Token
_:
       Token Dimension a
Distance DistanceData{TDistance.value = Just to, TDistance.unit = Just u2}:
       [Token]
_) | Double
from Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
to Bool -> Bool -> Bool
&& Unit
u1 Unit -> Unit -> Bool
forall a. Eq a => a -> a -> Bool
== Unit
u2 ->
         Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token) -> Token -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Token) -> DistanceData -> Token
forall a b. (a -> b) -> a -> b
$ (Double, Double) -> DistanceData -> DistanceData
withInterval (Double
from, Double
to) (DistanceData -> DistanceData) -> DistanceData -> DistanceData
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData
unitOnly Unit
u1
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalBound :: Rule
ruleIntervalBound :: Rule
ruleIntervalBound = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"under/less/lower/no more than <amount-of-money> (最多|至少|最少)"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(最多|至少|最少|起碼)"
    , Predicate -> PatternItem
Predicate Predicate
isSimpleDistance
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
RegexMatch (GroupMatch (match:_)):
       Token Dimension a
Distance DistanceData{TDistance.value = Just to,
                  TDistance.unit = Just u}:
       [Token]
_) -> case Text
match of
        Text
"最多" -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token) -> Token -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Token) -> DistanceData -> Token
forall a b. (a -> b) -> a -> b
$ Double -> DistanceData -> DistanceData
withMax Double
to (DistanceData -> DistanceData) -> DistanceData -> DistanceData
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData
unitOnly Unit
u
        Text
"最少" -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token) -> Token -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Token) -> DistanceData -> Token
forall a b. (a -> b) -> a -> b
$ Double -> DistanceData -> DistanceData
withMin Double
to (DistanceData -> DistanceData) -> DistanceData -> DistanceData
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData
unitOnly Unit
u
        Text
"至少" -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token) -> Token -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Token) -> DistanceData -> Token
forall a b. (a -> b) -> a -> b
$ Double -> DistanceData -> DistanceData
withMin Double
to (DistanceData -> DistanceData) -> DistanceData -> DistanceData
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData
unitOnly Unit
u
        Text
"起碼" -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token) -> Token -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Token) -> DistanceData -> Token
forall a b. (a -> b) -> a -> b
$ Double -> DistanceData -> DistanceData
withMin Double
to (DistanceData -> DistanceData) -> DistanceData -> DistanceData
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData
unitOnly Unit
u
        Text
_ -> Maybe Token
forall a. Maybe a
Nothing
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalBound2 :: Rule
ruleIntervalBound2 :: Rule
ruleIntervalBound2 = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"under/less/lower/no more than <amount-of-money> (以下|以上)"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isSimpleDistance
    , String -> PatternItem
regex String
"(以下|以上)"
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
Distance DistanceData{TDistance.value = Just to,
                  TDistance.unit = Just u}:
       Token Dimension a
RegexMatch (GroupMatch (match:_)):
       [Token]
_) -> case Text
match of
        Text
"以下" -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token) -> Token -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Token) -> DistanceData -> Token
forall a b. (a -> b) -> a -> b
$ Double -> DistanceData -> DistanceData
withMax Double
to (DistanceData -> DistanceData) -> DistanceData -> DistanceData
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData
unitOnly Unit
u
        Text
"以上" -> Token -> Maybe Token
forall a. a -> Maybe a
Just (Token -> Maybe Token) -> Token -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Dimension DistanceData -> DistanceData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension DistanceData
Distance (DistanceData -> Token) -> DistanceData -> Token
forall a b. (a -> b) -> a -> b
$ Double -> DistanceData -> DistanceData
withMin Double
to (DistanceData -> DistanceData) -> DistanceData -> DistanceData
forall a b. (a -> b) -> a -> b
$ Unit -> DistanceData
unitOnly Unit
u
        Text
_ -> Maybe Token
forall a. Maybe a
Nothing
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

rules :: [Rule]
rules :: [Rule]
rules =
  [ Rule
ruleDistCentimeters
  , Rule
ruleDistFeet
  , Rule
ruleDistFeetAndDistInch
  , Rule
ruleDistInch
  , Rule
ruleDistKm
  , Rule
ruleDistMeters
  , Rule
ruleDistMiles
  , Rule
ruleDistOneMeterAnd
  , Rule
ruleDistMetersAnd
  , Rule
ruleDistOneMeterAnd
  , Rule
ruleDistMetersAnd
  , Rule
ruleIntervalNumeralDash
  , Rule
ruleIntervalDash
  , Rule
ruleIntervalBound
  , Rule
ruleIntervalBound2
  ]