mirror of
https://github.com/facebook/duckling.git
synced 2025-01-06 04:53:13 +03:00
Credit cards
Summary: Add the ability to parse credit cards and identify the issuer in Duckling. Credit card numbers are a sequence of 8 to 19 digits, with a few specific digits at the start that identify the card issuer. They also satisfy Luhn checksum (https://en.wikipedia.org/wiki/Luhn_algorithm). Reviewed By: chinmay87 Differential Revision: D13014623 fbshipit-source-id: 96586e074777ae90a4a39c515648c31a8111f0c2
This commit is contained in:
parent
4c4e0c59b7
commit
1052914cb4
57
Duckling/CreditCardNumber/Corpus.hs
Normal file
57
Duckling/CreditCardNumber/Corpus.hs
Normal file
@ -0,0 +1,57 @@
|
||||
-- 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. An additional grant
|
||||
-- of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
module Duckling.CreditCardNumber.Corpus
|
||||
( corpus
|
||||
, negativeCorpus
|
||||
) where
|
||||
|
||||
import Prelude
|
||||
import Data.String
|
||||
import qualified Data.Text as T
|
||||
|
||||
import Duckling.CreditCardNumber.Types
|
||||
import Duckling.CreditCardNumber.Helpers
|
||||
import Duckling.Testing.Types
|
||||
|
||||
corpus :: Corpus
|
||||
corpus = (testContext, testOptions, allExamples)
|
||||
|
||||
negativeCorpus :: NegativeCorpus
|
||||
negativeCorpus = (testContext, testOptions, examples)
|
||||
where
|
||||
examples =
|
||||
[ T.replicate (minNumberDigits - 1) "0"
|
||||
, T.replicate (maxNumberDigits + 1) "0"
|
||||
, "invalid"
|
||||
, "4111111111111110"
|
||||
]
|
||||
|
||||
allExamples :: [Example]
|
||||
allExamples = concat
|
||||
[ examples
|
||||
(CreditCardNumberValue "4111111111111111" Visa)
|
||||
[ "4111111111111111" ]
|
||||
, examples
|
||||
(CreditCardNumberValue "371449635398431" Amex)
|
||||
[ "371449635398431" ]
|
||||
, examples
|
||||
(CreditCardNumberValue "6011111111111117" Discover)
|
||||
[ "6011111111111117" ]
|
||||
, examples
|
||||
(CreditCardNumberValue "5555555555554444" Mastercard)
|
||||
[ "5555555555554444" ]
|
||||
, examples
|
||||
(CreditCardNumberValue "30569309025904" DinerClub)
|
||||
[ "30569309025904" ]
|
||||
, examples
|
||||
(CreditCardNumberValue "3530111333300000" Other)
|
||||
[ "3530111333300000" ]
|
||||
]
|
108
Duckling/CreditCardNumber/Helpers.hs
Normal file
108
Duckling/CreditCardNumber/Helpers.hs
Normal file
@ -0,0 +1,108 @@
|
||||
-- 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. An additional grant
|
||||
-- of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
|
||||
module Duckling.CreditCardNumber.Helpers
|
||||
( otherCreditCardNumberRegex
|
||||
, visaCreditCardNumberRegex
|
||||
, amexCreditCardNumberRegex
|
||||
, discoverCreditCardNumberRegex
|
||||
, mastercardCreditCardNumberRegex
|
||||
, dinerClubCreditCardNumberRegex
|
||||
, isValidCreditCardNumber
|
||||
, minNumberDigits
|
||||
, maxNumberDigits
|
||||
, creditCard
|
||||
) where
|
||||
|
||||
import Data.Text (Text)
|
||||
import Prelude
|
||||
import Data.String
|
||||
|
||||
import Duckling.CreditCardNumber.Types (CreditCardNumberData(..))
|
||||
import qualified Duckling.CreditCardNumber.Types as TCreditCardNumber
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Char as C
|
||||
import qualified Data.Bits as B
|
||||
|
||||
-- -----------------------------------------------------------------
|
||||
-- Patterns
|
||||
|
||||
otherCreditCardNumberRegex :: String
|
||||
otherCreditCardNumberRegex =
|
||||
concat [ "("
|
||||
, "(?!" , visaCreditCardNumberRegex, ")"
|
||||
, "(?!" , amexCreditCardNumberRegex, ")"
|
||||
, "(?!" , discoverCreditCardNumberRegex, ")"
|
||||
, "(?!" , mastercardCreditCardNumberRegex, ")"
|
||||
, "(?!" , dinerClubCreditCardNumberRegex, ")"
|
||||
, "\\d{" , show minNumberDigits , "," , show maxNumberDigits , "}"
|
||||
, ")"
|
||||
]
|
||||
|
||||
-- | Visa credit card regex informed by latest BIN info
|
||||
visaCreditCardNumberRegex :: String
|
||||
visaCreditCardNumberRegex = "(4[0-9]{12}(?:[0-9]{3}))"
|
||||
|
||||
-- | American Express credit card regex informed by latest BIN info
|
||||
amexCreditCardNumberRegex :: String
|
||||
amexCreditCardNumberRegex = "(3[47][0-9]{13})"
|
||||
|
||||
-- | Discover credit card regex informed by latest BIN info
|
||||
discoverCreditCardNumberRegex :: String
|
||||
discoverCreditCardNumberRegex = "(6(?:011|5[0-9]{2})[0-9]{12})"
|
||||
|
||||
-- | Mastercard credit card regex informed by latest BIN info
|
||||
mastercardCreditCardNumberRegex :: String
|
||||
mastercardCreditCardNumberRegex = "(5[1-5][0-9]{14})"
|
||||
|
||||
-- | Diner Club credit card regex informed by latest BIN info
|
||||
dinerClubCreditCardNumberRegex :: String
|
||||
dinerClubCreditCardNumberRegex = "(3(?:0[0-5]|[68][0-9])[0-9]{11})"
|
||||
|
||||
-- -----------------------------------------------------------------
|
||||
-- Validation
|
||||
|
||||
-- | An implementation of the Luhn algorithm (see
|
||||
-- https://en.wikipedia.org/wiki/Luhn_algorithm) to check if a given credit card
|
||||
-- number is valid
|
||||
isValidCreditCardNumber :: Text -> Bool
|
||||
isValidCreditCardNumber ccNum =
|
||||
T.length ccNum >= minNumberDigits &&
|
||||
T.length ccNum <= maxNumberDigits &&
|
||||
validCheckSum
|
||||
where
|
||||
validCheckSum :: Bool
|
||||
validCheckSum =
|
||||
T.all C.isDigit ccNum &&
|
||||
fst (T.foldr f (0, 0) ccNum) `rem` 10 == 0
|
||||
where
|
||||
f char (checksum, e) =
|
||||
let
|
||||
val = C.digitToInt char
|
||||
-- every even digit should be doubled
|
||||
d = sumDigits (B.shift val e)
|
||||
in (checksum + d, 1 - e)
|
||||
-- we only need sum of digits for numbers from 0 to 18
|
||||
sumDigits a
|
||||
| a > 9 = a - 9
|
||||
| otherwise = a
|
||||
|
||||
minNumberDigits :: Int
|
||||
minNumberDigits = 8
|
||||
|
||||
maxNumberDigits :: Int
|
||||
maxNumberDigits = 19
|
||||
|
||||
-- -----------------------------------------------------------------
|
||||
-- Production
|
||||
|
||||
creditCard :: Text -> TCreditCardNumber.Issuer -> CreditCardNumberData
|
||||
creditCard ccNum i =
|
||||
CreditCardNumberData { TCreditCardNumber.number = ccNum
|
||||
, TCreditCardNumber.issuer = i
|
||||
}
|
69
Duckling/CreditCardNumber/Rules.hs
Normal file
69
Duckling/CreditCardNumber/Rules.hs
Normal file
@ -0,0 +1,69 @@
|
||||
-- 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. An additional grant
|
||||
-- of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
|
||||
{-# LANGUAGE GADTs #-}
|
||||
{-# LANGUAGE LambdaCase #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
module Duckling.CreditCardNumber.Rules
|
||||
( rules ) where
|
||||
|
||||
import Prelude
|
||||
import Data.String
|
||||
import Data.Text (Text)
|
||||
import Data.Bool
|
||||
|
||||
import Duckling.Dimensions.Types
|
||||
import Duckling.CreditCardNumber.Helpers
|
||||
import qualified Duckling.CreditCardNumber.Types as TCreditCardNumber
|
||||
import Duckling.Regex.Types
|
||||
import Duckling.Types
|
||||
|
||||
creditCards :: [(Text, PatternItem, TCreditCardNumber.Issuer)]
|
||||
creditCards =
|
||||
[ ( "visa credit card number"
|
||||
, regex visaCreditCardNumberRegex
|
||||
, TCreditCardNumber.Visa
|
||||
)
|
||||
, ( "amex card number"
|
||||
, regex amexCreditCardNumberRegex
|
||||
, TCreditCardNumber.Amex
|
||||
)
|
||||
, ( "discover card number"
|
||||
, regex discoverCreditCardNumberRegex
|
||||
, TCreditCardNumber.Discover
|
||||
)
|
||||
, ( "mastercard card number"
|
||||
, regex mastercardCreditCardNumberRegex
|
||||
, TCreditCardNumber.Mastercard
|
||||
)
|
||||
, ( "diner club card number"
|
||||
, regex dinerClubCreditCardNumberRegex
|
||||
, TCreditCardNumber.DinerClub
|
||||
)
|
||||
, ( "credit card number"
|
||||
, regex otherCreditCardNumberRegex
|
||||
, TCreditCardNumber.Other
|
||||
)
|
||||
]
|
||||
|
||||
rules :: [Rule]
|
||||
rules = map go creditCards
|
||||
where
|
||||
go :: (Text, PatternItem, TCreditCardNumber.Issuer) -> Rule
|
||||
go (name, regexPattern, i) = Rule
|
||||
{ name = name
|
||||
, pattern = [ regexPattern ]
|
||||
, prod = \case
|
||||
(Token RegexMatch (GroupMatch (ccNum:_)):_) ->
|
||||
bool
|
||||
Nothing
|
||||
(Just $ Token CreditCardNumber $ creditCard ccNum i)
|
||||
(isValidCreditCardNumber ccNum)
|
||||
_ -> Nothing
|
||||
}
|
62
Duckling/CreditCardNumber/Types.hs
Normal file
62
Duckling/CreditCardNumber/Types.hs
Normal file
@ -0,0 +1,62 @@
|
||||
-- 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. An additional grant
|
||||
-- of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
|
||||
{-# LANGUAGE DeriveAnyClass #-}
|
||||
{-# LANGUAGE NamedFieldPuns #-}
|
||||
{-# LANGUAGE DeriveGeneric #-}
|
||||
{-# LANGUAGE NoRebindableSyntax #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE TypeFamilies #-}
|
||||
|
||||
module Duckling.CreditCardNumber.Types where
|
||||
|
||||
import Control.DeepSeq
|
||||
import Data.Aeson
|
||||
import Data.Hashable
|
||||
import Data.Text (Text)
|
||||
import qualified Data.Text as Text
|
||||
import GHC.Generics
|
||||
|
||||
import Prelude
|
||||
|
||||
import Duckling.Resolve (Resolve(..))
|
||||
|
||||
data Issuer
|
||||
= Visa
|
||||
| Amex
|
||||
| Discover
|
||||
| Mastercard
|
||||
| DinerClub
|
||||
| Other
|
||||
deriving (Eq, Generic, Hashable, Ord, Show, NFData)
|
||||
|
||||
instance ToJSON Issuer where
|
||||
toJSON = String . Text.toLower . Text.pack . show
|
||||
|
||||
data CreditCardNumberData = CreditCardNumberData
|
||||
{ number :: Text
|
||||
, issuer :: Issuer
|
||||
}
|
||||
deriving (Eq, Generic, Hashable, Ord, Show, NFData)
|
||||
|
||||
instance Resolve CreditCardNumberData where
|
||||
type ResolvedValue CreditCardNumberData = CreditCardNumberValue
|
||||
resolve _ _ CreditCardNumberData {number, issuer} =
|
||||
Just (CreditCardNumberValue number issuer, False)
|
||||
|
||||
data CreditCardNumberValue = CreditCardNumberValue
|
||||
{ vNumber :: Text
|
||||
, vIssuer :: Issuer
|
||||
}
|
||||
deriving (Eq, Ord, Show)
|
||||
|
||||
instance ToJSON CreditCardNumberValue where
|
||||
toJSON (CreditCardNumberValue number issuer) =
|
||||
object [ "value" .= number
|
||||
, "issuer" .= issuer
|
||||
]
|
@ -74,6 +74,7 @@ explicitDimensions targets = HashSet.union targets deps
|
||||
|
||||
-- | Ordinal depends on Numeral for JA, KO, and ZH.
|
||||
dependents :: Some Dimension -> HashSet (Some Dimension)
|
||||
dependents (This CreditCardNumber) = HashSet.empty
|
||||
dependents (This Distance) = HashSet.singleton (This Numeral)
|
||||
dependents (This Duration) = HashSet.fromList [This Numeral, This TimeGrain]
|
||||
dependents (This Numeral) = HashSet.empty
|
||||
|
@ -29,6 +29,7 @@ import Duckling.Types
|
||||
|
||||
toName :: Dimension a -> Text
|
||||
toName RegexMatch = "regex"
|
||||
toName CreditCardNumber = "credit-card-number"
|
||||
toName Distance = "distance"
|
||||
toName Duration = "duration"
|
||||
toName Email = "email"
|
||||
|
@ -37,6 +37,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -34,6 +34,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = Distance.rules
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -28,6 +28,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = []
|
||||
langRules (This Numeral) = Numeral.rules
|
||||
|
@ -30,6 +30,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = Distance.rules
|
||||
langRules (This Duration) = []
|
||||
langRules (This Email) = []
|
||||
|
@ -16,6 +16,7 @@ module Duckling.Rules.Common
|
||||
import Duckling.Dimensions.Types
|
||||
import Duckling.Types
|
||||
import qualified Duckling.AmountOfMoney.Rules as AmountOfMoney
|
||||
import qualified Duckling.CreditCardNumber.Rules as CreditCardNumber
|
||||
import qualified Duckling.Distance.Rules as Distance
|
||||
import qualified Duckling.Duration.Rules as Duration
|
||||
import qualified Duckling.Email.Rules as Email
|
||||
@ -27,6 +28,7 @@ import qualified Duckling.Volume.Rules as Volume
|
||||
|
||||
rules :: Some Dimension -> [Rule]
|
||||
rules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
rules (This CreditCardNumber) = CreditCardNumber.rules
|
||||
rules (This Distance) = Distance.rules
|
||||
rules (This Duration) = Duration.rules
|
||||
rules (This Email) = Email.rules
|
||||
|
@ -33,6 +33,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -34,6 +34,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = Email.rules
|
||||
|
@ -33,6 +33,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -90,6 +90,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = Distance.rules
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = Email.rules
|
||||
|
@ -36,6 +36,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = Distance.rules
|
||||
langRules (This Duration) = []
|
||||
langRules (This Email) = []
|
||||
|
@ -30,6 +30,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = []
|
||||
langRules (This Email) = []
|
||||
|
@ -28,6 +28,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = []
|
||||
langRules (This Email) = []
|
||||
|
@ -39,6 +39,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = Distance.rules
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = Email.rules
|
||||
|
@ -37,6 +37,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = Distance.rules
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -33,6 +33,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -32,6 +32,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Numeral) = Numeral.rules
|
||||
|
@ -39,6 +39,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = Distance.rules
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -33,6 +33,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -31,6 +31,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = []
|
||||
langRules (This Email) = []
|
||||
|
@ -28,6 +28,7 @@ localeRules region (This (CustomDimension dim)) = dimLocaleRules region dim
|
||||
localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = []
|
||||
langRules (This Numeral) = Numeral.rules
|
||||
|
@ -36,6 +36,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = Email.rules
|
||||
|
@ -32,6 +32,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = []
|
||||
langRules (This Email) = []
|
||||
|
@ -34,6 +34,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -34,6 +34,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = Distance.rules
|
||||
langRules (This Duration) = []
|
||||
langRules (This Email) = []
|
||||
|
@ -38,6 +38,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = Distance.rules
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -29,6 +29,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = []
|
||||
langRules (This Email) = []
|
||||
|
@ -30,6 +30,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = []
|
||||
langRules (This Email) = []
|
||||
|
@ -29,6 +29,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = []
|
||||
langRules (This Email) = []
|
||||
|
@ -34,6 +34,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -28,6 +28,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = []
|
||||
langRules (This Numeral) = Numeral.rules
|
||||
|
@ -41,6 +41,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = Distance.rules
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -33,6 +33,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -38,6 +38,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = Distance.rules
|
||||
langRules (This Duration) = []
|
||||
langRules (This Email) = []
|
||||
|
@ -38,6 +38,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = Distance.rules
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -36,6 +36,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = Distance.rules
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -35,6 +35,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = Distance.rules
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -29,6 +29,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = []
|
||||
langRules (This Numeral) = Numeral.rules
|
||||
|
@ -35,6 +35,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = Distance.rules
|
||||
langRules (This Duration) = Duration.rules
|
||||
langRules (This Email) = []
|
||||
|
@ -30,6 +30,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = []
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = []
|
||||
langRules (This Email) = []
|
||||
|
@ -33,6 +33,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = []
|
||||
langRules (This Duration) = []
|
||||
langRules (This Email) = []
|
||||
|
@ -44,6 +44,7 @@ localeRules _ _ = []
|
||||
|
||||
langRules :: Some Dimension -> [Rule]
|
||||
langRules (This AmountOfMoney) = AmountOfMoney.rules
|
||||
langRules (This CreditCardNumber) = []
|
||||
langRules (This Distance) = Distance.rules
|
||||
langRules (This Duration) = []
|
||||
langRules (This Email) = []
|
||||
|
@ -42,6 +42,7 @@ import qualified Text.Regex.PCRE as PCRE
|
||||
import qualified TextShow as TS
|
||||
|
||||
import Duckling.AmountOfMoney.Types (AmountOfMoneyData)
|
||||
import Duckling.CreditCardNumber.Types (CreditCardNumberData)
|
||||
import Duckling.Distance.Types (DistanceData)
|
||||
import Duckling.Duration.Types (DurationData)
|
||||
import Duckling.Email.Types (EmailData)
|
||||
@ -93,6 +94,7 @@ class (Show a, Typeable a, Typeable (DimensionData a)) =>
|
||||
data Dimension a where
|
||||
RegexMatch :: Dimension GroupMatch
|
||||
AmountOfMoney :: Dimension AmountOfMoneyData
|
||||
CreditCardNumber :: Dimension CreditCardNumberData
|
||||
Distance :: Dimension DistanceData
|
||||
Duration :: Dimension DurationData
|
||||
Email :: Dimension EmailData
|
||||
@ -110,6 +112,7 @@ data Dimension a where
|
||||
-- Show
|
||||
instance Show (Dimension a) where
|
||||
show RegexMatch = "RegexMatch"
|
||||
show CreditCardNumber = "CreditCardNumber"
|
||||
show Distance = "Distance"
|
||||
show Duration = "Duration"
|
||||
show Email = "Email"
|
||||
@ -151,10 +154,13 @@ instance Hashable (Dimension a) where
|
||||
hashWithSalt s Url = hashWithSalt s (12::Int)
|
||||
hashWithSalt s Volume = hashWithSalt s (13::Int)
|
||||
hashWithSalt s (CustomDimension _) = hashWithSalt s (14::Int)
|
||||
hashWithSalt s CreditCardNumber = hashWithSalt s (15::Int)
|
||||
|
||||
instance GEq Dimension where
|
||||
geq RegexMatch RegexMatch = Just Refl
|
||||
geq RegexMatch _ = Nothing
|
||||
geq CreditCardNumber CreditCardNumber = Just Refl
|
||||
geq CreditCardNumber _ = Nothing
|
||||
geq Distance Distance = Just Refl
|
||||
geq Distance _ = Nothing
|
||||
geq Duration Duration = Just Refl
|
||||
|
@ -736,6 +736,12 @@ library
|
||||
, Duckling.Volume.Helpers
|
||||
, Duckling.Volume.Rules
|
||||
, Duckling.Volume.Types
|
||||
|
||||
-- CreditCardNumber
|
||||
, Duckling.CreditCardNumber.Corpus
|
||||
, Duckling.CreditCardNumber.Helpers
|
||||
, Duckling.CreditCardNumber.Rules
|
||||
, Duckling.CreditCardNumber.Types
|
||||
build-depends: base >= 4.8.2 && < 5.0
|
||||
, array >= 0.5.1.1 && < 0.6
|
||||
, attoparsec >= 0.13.1.0 && < 0.14
|
||||
@ -1006,6 +1012,9 @@ test-suite duckling-test
|
||||
, Duckling.Volume.TR.Tests
|
||||
, Duckling.Volume.Tests
|
||||
|
||||
-- CreditCardNumber
|
||||
, Duckling.CreditCardNumber.Tests
|
||||
|
||||
ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wincomplete-patterns
|
||||
default-language: Haskell2010
|
||||
default-extensions: OverloadedStrings
|
||||
|
26
tests/Duckling/CreditCardNumber/Tests.hs
Normal file
26
tests/Duckling/CreditCardNumber/Tests.hs
Normal file
@ -0,0 +1,26 @@
|
||||
-- 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. An additional grant
|
||||
-- of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
module Duckling.CreditCardNumber.Tests
|
||||
( tests
|
||||
) where
|
||||
|
||||
import Data.String
|
||||
import Test.Tasty
|
||||
|
||||
import Duckling.Dimensions.Types
|
||||
import Duckling.CreditCardNumber.Corpus
|
||||
import Duckling.Testing.Asserts
|
||||
|
||||
tests :: TestTree
|
||||
tests = testGroup "CreditCardNumber Tests"
|
||||
[ makeCorpusTest [This CreditCardNumber] corpus
|
||||
, makeNegativeCorpusTest [This CreditCardNumber] negativeCorpus
|
||||
]
|
Loading…
Reference in New Issue
Block a user