packages feed

duckling 0.1.6.1 → 0.2.0.0

raw patch · 1034 files changed

+87009/−33770 lines, 1034 filesdep +regex-pcre-builtindep ~aesondep ~attoparsecdep ~bytestringsetup-changednew-uploaderPVP ok

version bump matches the API change (PVP)

Dependencies added: regex-pcre-builtin

Dependency ranges changed: aeson, attoparsec, bytestring, containers, dependent-sum, extra, hashable, haskell-src-exts, regex-base, regex-pcre, snap-server, tasty, tasty-hunit, text-show, time, timezone-olson

API changes (from Hackage documentation)

- Duckling.AmountOfMoney.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.AmountOfMoney.Types.AmountOfMoneyValue
- Duckling.AmountOfMoney.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.AmountOfMoney.Types.Currency
- Duckling.AmountOfMoney.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.AmountOfMoney.Types.SingleValue
- Duckling.Core: [This] :: Some k tag
- Duckling.Core: data Some k (tag :: k -> *) :: forall k. () => (k -> *) -> *
- Duckling.Dimensions.Types: [This] :: Some k tag
- Duckling.Dimensions.Types: data Some k (tag :: k -> *) :: forall k. () => (k -> *) -> *
- Duckling.Distance.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Distance.Types.DistanceValue
- Duckling.Distance.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Distance.Types.SingleValue
- Duckling.Distance.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Distance.Types.Unit
- Duckling.Duration.Helpers: timesOneAndAHalf :: Grain -> Int -> Maybe DurationData
- Duckling.Duration.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Duration.Types.DurationData
- Duckling.Duration.Types: instance Data.Semigroup.Semigroup Duckling.Duration.Types.DurationData
- Duckling.Email.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Email.Types.EmailData
- Duckling.Numeral.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Numeral.Types.NumeralValue
- Duckling.Ordinal.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Ordinal.Types.OrdinalData
- Duckling.PhoneNumber.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.PhoneNumber.Types.PhoneNumberValue
- Duckling.Quantity.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Quantity.Types.QuantityValue
- Duckling.Quantity.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Quantity.Types.SingleValue
- Duckling.Quantity.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Quantity.Types.Unit
- Duckling.Regex.Types: data GroupMatch
- Duckling.Temperature.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Temperature.Types.SingleValue
- Duckling.Temperature.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Temperature.Types.TemperatureUnit
- Duckling.Temperature.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Temperature.Types.TemperatureValue
- Duckling.Time.Helpers: isGrain :: Grain -> Predicate
- Duckling.Time.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Time.Types.InstantValue
- Duckling.Time.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Time.Types.SingleTimeValue
- Duckling.Time.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Time.Types.TimeValue
- Duckling.TimeGrain.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.TimeGrain.Types.Grain
- Duckling.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Types.Entity
- Duckling.Types: instance Data.GADT.Compare.GEq Duckling.Types.Dimension
- Duckling.Types: instance Data.GADT.Show.GShow Duckling.Types.Dimension
- Duckling.Types: instance Data.Hashable.Class.Hashable (Data.Some.Some Duckling.Types.Dimension)
- Duckling.Types: instance TextShow.Classes.TextShow (Data.Some.Some Duckling.Types.Dimension)
- Duckling.Url.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Url.Types.UrlData
- Duckling.Volume.Types: VolumeValue :: Unit -> Double -> VolumeValue
- Duckling.Volume.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Volume.Types.Unit
- Duckling.Volume.Types: instance Data.Aeson.Types.Class.ToJSON Duckling.Volume.Types.VolumeValue
- Duckling.Volume.Types: instance GHC.Classes.Ord Duckling.Volume.Types.VolumeValue
+ Duckling.AmountOfMoney.EN.Corpus: latentCorpus :: Corpus
+ Duckling.AmountOfMoney.HE.Corpus: corpus :: Corpus
+ Duckling.AmountOfMoney.HE.Rules: rules :: [Rule]
+ Duckling.AmountOfMoney.Helpers: dollarCoins :: HashMap Text Double
+ Duckling.AmountOfMoney.Helpers: isDollarCoin :: Predicate
+ Duckling.AmountOfMoney.Helpers: mkLatent :: AmountOfMoneyData -> AmountOfMoneyData
+ Duckling.AmountOfMoney.Helpers: valueOnly :: Double -> AmountOfMoneyData
+ Duckling.AmountOfMoney.IT.Corpus: corpus :: Corpus
+ Duckling.AmountOfMoney.IT.Rules: rules :: [Rule]
+ Duckling.AmountOfMoney.KA.Corpus: corpus :: Corpus
+ Duckling.AmountOfMoney.KA.Rules: rules :: [Rule]
+ Duckling.AmountOfMoney.MN.Corpus: corpus :: Corpus
+ Duckling.AmountOfMoney.MN.Rules: rules :: [Rule]
+ Duckling.AmountOfMoney.TR.Corpus: corpus :: Corpus
+ Duckling.AmountOfMoney.TR.Rules: rules :: [Rule]
+ Duckling.AmountOfMoney.Types: CHF :: Currency
+ Duckling.AmountOfMoney.Types: CZK :: Currency
+ Duckling.AmountOfMoney.Types: DKK :: Currency
+ Duckling.AmountOfMoney.Types: GEL :: Currency
+ Duckling.AmountOfMoney.Types: HKD :: Currency
+ Duckling.AmountOfMoney.Types: MNT :: Currency
+ Duckling.AmountOfMoney.Types: PKR :: Currency
+ Duckling.AmountOfMoney.Types: PLN :: Currency
+ Duckling.AmountOfMoney.Types: THB :: Currency
+ Duckling.AmountOfMoney.Types: TRY :: Currency
+ Duckling.AmountOfMoney.Types: UAH :: Currency
+ Duckling.AmountOfMoney.Types: ZAR :: Currency
+ Duckling.AmountOfMoney.Types: [latent] :: AmountOfMoneyData -> Bool
+ Duckling.AmountOfMoney.Types: amountOfMoneyData' :: AmountOfMoneyData
+ Duckling.AmountOfMoney.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.AmountOfMoney.Types.AmountOfMoneyValue
+ Duckling.AmountOfMoney.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.AmountOfMoney.Types.Currency
+ Duckling.AmountOfMoney.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.AmountOfMoney.Types.SingleValue
+ Duckling.Core: AF :: Lang
+ Duckling.Core: BN :: Lang
+ Duckling.Core: CL :: Region
+ Duckling.Core: CO :: Region
+ Duckling.Core: EG :: Region
+ Duckling.Core: FA :: Lang
+ Duckling.Core: FI :: Lang
+ Duckling.Core: IS :: Lang
+ Duckling.Core: KM :: Lang
+ Duckling.Core: KN :: Lang
+ Duckling.Core: LO :: Lang
+ Duckling.Core: ML :: Lang
+ Duckling.Core: MN :: Lang
+ Duckling.Core: MX :: Region
+ Duckling.Core: PE :: Region
+ Duckling.Core: SK :: Lang
+ Duckling.Core: SW :: Lang
+ Duckling.Core: TE :: Lang
+ Duckling.Core: TH :: Lang
+ Duckling.Core: VE :: Region
+ Duckling.Core: [CreditCardNumber] :: Dimension CreditCardNumberData
+ Duckling.Core: [Seal] :: s a -> Seal s
+ Duckling.Core: data Seal s
+ Duckling.Core: withSeal :: Seal s -> (forall t. s t -> r) -> r
+ Duckling.CreditCardNumber.Corpus: corpus :: Corpus
+ Duckling.CreditCardNumber.Corpus: negativeCorpus :: NegativeCorpus
+ Duckling.CreditCardNumber.Helpers: amexCreditCardNumberRegex :: String
+ Duckling.CreditCardNumber.Helpers: creditCard :: Text -> Issuer -> CreditCardNumberData
+ Duckling.CreditCardNumber.Helpers: dinerClubCreditCardNumberRegex :: String
+ Duckling.CreditCardNumber.Helpers: discoverCreditCardNumberRegex :: String
+ Duckling.CreditCardNumber.Helpers: isValidCreditCardNumber :: Text -> Bool
+ Duckling.CreditCardNumber.Helpers: mastercardCreditCardNumberRegex :: String
+ Duckling.CreditCardNumber.Helpers: maxNumberDigits :: Int
+ Duckling.CreditCardNumber.Helpers: minNumberDigits :: Int
+ Duckling.CreditCardNumber.Helpers: otherCreditCardNumberRegex :: String
+ Duckling.CreditCardNumber.Helpers: visaCreditCardNumberRegex :: String
+ Duckling.CreditCardNumber.Rules: rules :: [Rule]
+ Duckling.CreditCardNumber.Types: Amex :: Issuer
+ Duckling.CreditCardNumber.Types: CreditCardNumberData :: Text -> Issuer -> CreditCardNumberData
+ Duckling.CreditCardNumber.Types: CreditCardNumberValue :: Text -> Issuer -> CreditCardNumberValue
+ Duckling.CreditCardNumber.Types: DinerClub :: Issuer
+ Duckling.CreditCardNumber.Types: Discover :: Issuer
+ Duckling.CreditCardNumber.Types: Mastercard :: Issuer
+ Duckling.CreditCardNumber.Types: Other :: Issuer
+ Duckling.CreditCardNumber.Types: Visa :: Issuer
+ Duckling.CreditCardNumber.Types: [issuer] :: CreditCardNumberData -> Issuer
+ Duckling.CreditCardNumber.Types: [number] :: CreditCardNumberData -> Text
+ Duckling.CreditCardNumber.Types: [vIssuer] :: CreditCardNumberValue -> Issuer
+ Duckling.CreditCardNumber.Types: [vNumber] :: CreditCardNumberValue -> Text
+ Duckling.CreditCardNumber.Types: data CreditCardNumberData
+ Duckling.CreditCardNumber.Types: data CreditCardNumberValue
+ Duckling.CreditCardNumber.Types: data Issuer
+ Duckling.CreditCardNumber.Types: instance Control.DeepSeq.NFData Duckling.CreditCardNumber.Types.CreditCardNumberData
+ Duckling.CreditCardNumber.Types: instance Control.DeepSeq.NFData Duckling.CreditCardNumber.Types.Issuer
+ Duckling.CreditCardNumber.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.CreditCardNumber.Types.CreditCardNumberValue
+ Duckling.CreditCardNumber.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.CreditCardNumber.Types.Issuer
+ Duckling.CreditCardNumber.Types: instance Data.Hashable.Class.Hashable Duckling.CreditCardNumber.Types.CreditCardNumberData
+ Duckling.CreditCardNumber.Types: instance Data.Hashable.Class.Hashable Duckling.CreditCardNumber.Types.Issuer
+ Duckling.CreditCardNumber.Types: instance Duckling.Resolve.Resolve Duckling.CreditCardNumber.Types.CreditCardNumberData
+ Duckling.CreditCardNumber.Types: instance GHC.Classes.Eq Duckling.CreditCardNumber.Types.CreditCardNumberData
+ Duckling.CreditCardNumber.Types: instance GHC.Classes.Eq Duckling.CreditCardNumber.Types.CreditCardNumberValue
+ Duckling.CreditCardNumber.Types: instance GHC.Classes.Eq Duckling.CreditCardNumber.Types.Issuer
+ Duckling.CreditCardNumber.Types: instance GHC.Classes.Ord Duckling.CreditCardNumber.Types.CreditCardNumberData
+ Duckling.CreditCardNumber.Types: instance GHC.Classes.Ord Duckling.CreditCardNumber.Types.CreditCardNumberValue
+ Duckling.CreditCardNumber.Types: instance GHC.Classes.Ord Duckling.CreditCardNumber.Types.Issuer
+ Duckling.CreditCardNumber.Types: instance GHC.Generics.Generic Duckling.CreditCardNumber.Types.CreditCardNumberData
+ Duckling.CreditCardNumber.Types: instance GHC.Generics.Generic Duckling.CreditCardNumber.Types.Issuer
+ Duckling.CreditCardNumber.Types: instance GHC.Show.Show Duckling.CreditCardNumber.Types.CreditCardNumberData
+ Duckling.CreditCardNumber.Types: instance GHC.Show.Show Duckling.CreditCardNumber.Types.CreditCardNumberValue
+ Duckling.CreditCardNumber.Types: instance GHC.Show.Show Duckling.CreditCardNumber.Types.Issuer
+ Duckling.Dimensions.AF: allDimensions :: [Seal Dimension]
+ Duckling.Dimensions.BN: allDimensions :: [Seal Dimension]
+ Duckling.Dimensions.CA: allDimensions :: [Seal Dimension]
+ Duckling.Dimensions.FA: allDimensions :: [Seal Dimension]
+ Duckling.Dimensions.FI: allDimensions :: [Seal Dimension]
+ Duckling.Dimensions.IS: allDimensions :: [Seal Dimension]
+ Duckling.Dimensions.KM: allDimensions :: [Seal Dimension]
+ Duckling.Dimensions.KN: allDimensions :: [Seal Dimension]
+ Duckling.Dimensions.LO: allDimensions :: [Seal Dimension]
+ Duckling.Dimensions.ML: allDimensions :: [Seal Dimension]
+ Duckling.Dimensions.MN: allDimensions :: [Seal Dimension]
+ Duckling.Dimensions.SK: allDimensions :: [Seal Dimension]
+ Duckling.Dimensions.SW: allDimensions :: [Seal Dimension]
+ Duckling.Dimensions.TE: allDimensions :: [Seal Dimension]
+ Duckling.Dimensions.TH: allDimensions :: [Seal Dimension]
+ Duckling.Dimensions.Types: [CreditCardNumber] :: Dimension CreditCardNumberData
+ Duckling.Dimensions.Types: [Seal] :: s a -> Seal s
+ Duckling.Dimensions.Types: data Seal s
+ Duckling.Distance.DE.Corpus: corpus :: Corpus
+ Duckling.Distance.DE.Rules: rules :: [Rule]
+ Duckling.Distance.Helpers: distanceSum :: Double -> Unit -> Double -> Unit -> Maybe DistanceData
+ Duckling.Distance.IT.Corpus: corpus :: Corpus
+ Duckling.Distance.IT.Rules: rules :: [Rule]
+ Duckling.Distance.KM.Corpus: corpus :: Corpus
+ Duckling.Distance.KM.Rules: rules :: [Rule]
+ Duckling.Distance.MN.Corpus: corpus :: Corpus
+ Duckling.Distance.MN.Rules: rules :: [Rule]
+ Duckling.Distance.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Distance.Types.DistanceValue
+ Duckling.Distance.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Distance.Types.SingleValue
+ Duckling.Distance.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Distance.Types.Unit
+ Duckling.DistanceUnits.Types: ContextualDistance :: Double -> DeferrableUnit -> ContextualDistance
+ Duckling.DistanceUnits.Types: Nonrelatable :: ContextualDistance
+ Duckling.DistanceUnits.Types: data ContextualDistance
+ Duckling.DistanceUnits.Types: instance GHC.Base.Semigroup Duckling.DistanceUnits.Types.ContextualDistance
+ Duckling.DistanceUnits.Types: instance GHC.Classes.Eq Duckling.DistanceUnits.Types.AmbiguousUnit
+ Duckling.DistanceUnits.Types: instance GHC.Classes.Eq Duckling.DistanceUnits.Types.DeferrableUnit
+ Duckling.DistanceUnits.Types: instance GHC.Classes.Eq Duckling.DistanceUnits.Types.ImperialUnit
+ Duckling.DistanceUnits.Types: instance GHC.Classes.Eq Duckling.DistanceUnits.Types.MetricUnit
+ Duckling.DistanceUnits.Types: instance GHC.Classes.Eq Duckling.DistanceUnits.Types.SystemUnit
+ Duckling.DistanceUnits.Types: instance GHC.Classes.Ord Duckling.DistanceUnits.Types.AmbiguousUnit
+ Duckling.DistanceUnits.Types: instance GHC.Classes.Ord Duckling.DistanceUnits.Types.DeferrableUnit
+ Duckling.DistanceUnits.Types: instance GHC.Classes.Ord Duckling.DistanceUnits.Types.ImperialUnit
+ Duckling.DistanceUnits.Types: instance GHC.Classes.Ord Duckling.DistanceUnits.Types.MetricUnit
+ Duckling.DistanceUnits.Types: instance GHC.Classes.Ord Duckling.DistanceUnits.Types.SystemUnit
+ Duckling.DistanceUnits.Types: toRawUnit :: DeferrableUnit -> Unit
+ Duckling.DistanceUnits.Types: toSystemUnit :: Unit -> DeferrableUnit
+ Duckling.Duration.ES.Corpus: corpus :: Corpus
+ Duckling.Duration.ES.Rules: rules :: [Rule]
+ Duckling.Duration.Helpers: nPlusOneHalf :: Grain -> Int -> Maybe DurationData
+ Duckling.Duration.Helpers: secondsFromHourMixedFraction :: Integer -> Integer -> Integer -> DurationData
+ Duckling.Duration.Helpers: timesOneQuarter :: Grain -> Int -> Maybe DurationData
+ Duckling.Duration.Helpers: timesThreeQuarter :: Grain -> Int -> Maybe DurationData
+ Duckling.Duration.KA.Corpus: corpus :: Corpus
+ Duckling.Duration.KA.Rules: rules :: [Rule]
+ Duckling.Duration.MN.Corpus: corpus :: Corpus
+ Duckling.Duration.MN.Rules: rules :: [Rule]
+ Duckling.Duration.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Duration.Types.DurationData
+ Duckling.Duration.Types: instance GHC.Base.Semigroup Duckling.Duration.Types.DurationData
+ Duckling.Duration.UK.Corpus: corpus :: Corpus
+ Duckling.Duration.UK.Corpus: negativeCorpus :: NegativeCorpus
+ Duckling.Duration.UK.Rules: rules :: [Rule]
+ Duckling.Duration.ZH.Rules: rules :: [Rule]
+ Duckling.Email.DE.Corpus: corpus :: Corpus
+ Duckling.Email.DE.Corpus: negativeCorpus :: NegativeCorpus
+ Duckling.Email.DE.Rules: rules :: [Rule]
+ Duckling.Email.IS.Corpus: corpus :: Corpus
+ Duckling.Email.IS.Rules: rules :: [Rule]
+ Duckling.Email.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Email.Types.EmailData
+ Duckling.Locale: AF :: Lang
+ Duckling.Locale: BN :: Lang
+ Duckling.Locale: CL :: Region
+ Duckling.Locale: CO :: Region
+ Duckling.Locale: EG :: Region
+ Duckling.Locale: FA :: Lang
+ Duckling.Locale: FI :: Lang
+ Duckling.Locale: IS :: Lang
+ Duckling.Locale: KM :: Lang
+ Duckling.Locale: KN :: Lang
+ Duckling.Locale: LO :: Lang
+ Duckling.Locale: ML :: Lang
+ Duckling.Locale: MN :: Lang
+ Duckling.Locale: MX :: Region
+ Duckling.Locale: PE :: Region
+ Duckling.Locale: SK :: Lang
+ Duckling.Locale: SW :: Lang
+ Duckling.Locale: TE :: Lang
+ Duckling.Locale: TH :: Lang
+ Duckling.Locale: VE :: Region
+ Duckling.Numeral.AF.Corpus: corpus :: Corpus
+ Duckling.Numeral.AF.Rules: rules :: [Rule]
+ Duckling.Numeral.AR.EG.Corpus: allExamples :: [Example]
+ Duckling.Numeral.AR.EG.Helpers: digitsMap :: HashMap Text Integer
+ Duckling.Numeral.AR.EG.Helpers: numeralToStringMap :: HashMap Char String
+ Duckling.Numeral.AR.EG.Helpers: parseArabicDoubleAsText :: Text -> Text
+ Duckling.Numeral.AR.EG.Helpers: parseArabicDoubleFromText :: Text -> Maybe Double
+ Duckling.Numeral.AR.EG.Helpers: parseArabicIntAsText :: Text -> Text
+ Duckling.Numeral.AR.EG.Helpers: parseArabicIntegerFromText :: Text -> Maybe Integer
+ Duckling.Numeral.AR.EG.Rules: rules :: [Rule]
+ Duckling.Numeral.AR.Helpers: digitsMap :: HashMap Text Integer
+ Duckling.Numeral.AR.Helpers: numeralToStringMap :: HashMap Char String
+ Duckling.Numeral.AR.Helpers: parseArabicDoubleAsText :: Text -> Text
+ Duckling.Numeral.AR.Helpers: parseArabicDoubleFromText :: Text -> Maybe Double
+ Duckling.Numeral.AR.Helpers: parseArabicIntAsText :: Text -> Text
+ Duckling.Numeral.AR.Helpers: parseArabicIntegerFromText :: Text -> Maybe Integer
+ Duckling.Numeral.BN.Corpus: corpus :: Corpus
+ Duckling.Numeral.BN.Rules: rules :: [Rule]
+ Duckling.Numeral.CA.Corpus: corpus :: Corpus
+ Duckling.Numeral.CA.Rules: rules :: [Rule]
+ Duckling.Numeral.ES.AR.Corpus: allExamples :: [Example]
+ Duckling.Numeral.ES.AR.Rules: rules :: [Rule]
+ Duckling.Numeral.ES.CL.Corpus: allExamples :: [Example]
+ Duckling.Numeral.ES.CL.Rules: rules :: [Rule]
+ Duckling.Numeral.ES.CO.Corpus: allExamples :: [Example]
+ Duckling.Numeral.ES.CO.Rules: rules :: [Rule]
+ Duckling.Numeral.ES.ES.Corpus: allExamples :: [Example]
+ Duckling.Numeral.ES.ES.Rules: rules :: [Rule]
+ Duckling.Numeral.ES.ES.Rules: rulesBackwardCompatible :: [Rule]
+ Duckling.Numeral.ES.MX.Corpus: allExamples :: [Example]
+ Duckling.Numeral.ES.MX.Rules: rules :: [Rule]
+ Duckling.Numeral.ES.PE.Corpus: allExamples :: [Example]
+ Duckling.Numeral.ES.PE.Rules: rules :: [Rule]
+ Duckling.Numeral.ES.VE.Corpus: allExamples :: [Example]
+ Duckling.Numeral.ES.VE.Rules: rules :: [Rule]
+ Duckling.Numeral.FA.Corpus: corpus :: Corpus
+ Duckling.Numeral.FA.Rules: rules :: [Rule]
+ Duckling.Numeral.FI.Corpus: corpus :: Corpus
+ Duckling.Numeral.FI.Rules: rules :: [Rule]
+ Duckling.Numeral.IS.Corpus: corpus :: Corpus
+ Duckling.Numeral.IS.Rules: rules :: [Rule]
+ Duckling.Numeral.KM.Corpus: corpus :: Corpus
+ Duckling.Numeral.KM.Rules: rules :: [Rule]
+ Duckling.Numeral.KN.Corpus: corpus :: Corpus
+ Duckling.Numeral.KN.Rules: rules :: [Rule]
+ Duckling.Numeral.LO.Corpus: corpus :: Corpus
+ Duckling.Numeral.LO.Rules: rules :: [Rule]
+ Duckling.Numeral.ML.Corpus: corpus :: Corpus
+ Duckling.Numeral.ML.Rules: rules :: [Rule]
+ Duckling.Numeral.MN.Corpus: corpus :: Corpus
+ Duckling.Numeral.MN.Rules: rules :: [Rule]
+ Duckling.Numeral.SK.Corpus: corpus :: Corpus
+ Duckling.Numeral.SK.Rules: rules :: [Rule]
+ Duckling.Numeral.SW.Corpus: corpus :: Corpus
+ Duckling.Numeral.SW.Rules: rules :: [Rule]
+ Duckling.Numeral.TE.Corpus: corpus :: Corpus
+ Duckling.Numeral.TE.Rules: rules :: [Rule]
+ Duckling.Numeral.TH.Corpus: corpus :: Corpus
+ Duckling.Numeral.TH.Rules: rules :: [Rule]
+ Duckling.Numeral.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Numeral.Types.NumeralValue
+ Duckling.Ordinal.CA.Corpus: corpus :: Corpus
+ Duckling.Ordinal.CA.Rules: rules :: [Rule]
+ Duckling.Ordinal.KA.Corpus: corpus :: Corpus
+ Duckling.Ordinal.KA.Rules: rules :: [Rule]
+ Duckling.Ordinal.KM.Corpus: corpus :: Corpus
+ Duckling.Ordinal.KM.Rules: rules :: [Rule]
+ Duckling.Ordinal.ML.Corpus: corpus :: Corpus
+ Duckling.Ordinal.ML.Rules: rules :: [Rule]
+ Duckling.Ordinal.MN.Corpus: corpus :: Corpus
+ Duckling.Ordinal.MN.Rules: rules :: [Rule]
+ Duckling.Ordinal.TA.Corpus: corpus :: Corpus
+ Duckling.Ordinal.TA.Rules: rules :: [Rule]
+ Duckling.Ordinal.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Ordinal.Types.OrdinalData
+ Duckling.PhoneNumber.AR.Corpus: corpus :: Corpus
+ Duckling.PhoneNumber.AR.Corpus: negativeCorpus :: NegativeCorpus
+ Duckling.PhoneNumber.AR.Rules: rules :: [Rule]
+ Duckling.PhoneNumber.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.PhoneNumber.Types.PhoneNumberValue
+ Duckling.Quantity.EN.Corpus: latentCorpus :: Corpus
+ Duckling.Quantity.ES.Corpus: corpus :: Corpus
+ Duckling.Quantity.ES.Rules: rules :: [Rule]
+ Duckling.Quantity.Helpers: getValue :: HashMap Text (Double -> Double) -> Text -> Double -> Double
+ Duckling.Quantity.Helpers: mkLatent :: QuantityData -> QuantityData
+ Duckling.Quantity.Helpers: valueOnly :: Double -> QuantityData
+ Duckling.Quantity.KM.Corpus: corpus :: Corpus
+ Duckling.Quantity.KM.Rules: rules :: [Rule]
+ Duckling.Quantity.MN.Corpus: corpus :: Corpus
+ Duckling.Quantity.MN.Rules: rules :: [Rule]
+ Duckling.Quantity.NL.Corpus: corpus :: Corpus
+ Duckling.Quantity.NL.Rules: rules :: [Rule]
+ Duckling.Quantity.Types: [latent] :: QuantityData -> Bool
+ Duckling.Quantity.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Quantity.Types.QuantityValue
+ Duckling.Quantity.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Quantity.Types.SingleValue
+ Duckling.Quantity.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Quantity.Types.Unit
+ Duckling.Ranking.Classifiers.AF_XX: classifiers :: Classifiers
+ Duckling.Ranking.Classifiers.AR_EG: classifiers :: Classifiers
+ Duckling.Ranking.Classifiers.BN_XX: classifiers :: Classifiers
+ Duckling.Ranking.Classifiers.CA_XX: classifiers :: Classifiers
+ Duckling.Ranking.Classifiers.FA_XX: classifiers :: Classifiers
+ Duckling.Ranking.Classifiers.FI_XX: classifiers :: Classifiers
+ Duckling.Ranking.Classifiers.IS_XX: classifiers :: Classifiers
+ Duckling.Ranking.Classifiers.KM_XX: classifiers :: Classifiers
+ Duckling.Ranking.Classifiers.KN_XX: classifiers :: Classifiers
+ Duckling.Ranking.Classifiers.LO_XX: classifiers :: Classifiers
+ Duckling.Ranking.Classifiers.ML_XX: classifiers :: Classifiers
+ Duckling.Ranking.Classifiers.MN_XX: classifiers :: Classifiers
+ Duckling.Ranking.Classifiers.SK_XX: classifiers :: Classifiers
+ Duckling.Ranking.Classifiers.SW_XX: classifiers :: Classifiers
+ Duckling.Ranking.Classifiers.TE_XX: classifiers :: Classifiers
+ Duckling.Ranking.Classifiers.TH_XX: classifiers :: Classifiers
+ Duckling.Regex.Types: newtype GroupMatch
+ Duckling.Region: AR :: Region
+ Duckling.Region: CL :: Region
+ Duckling.Region: CO :: Region
+ Duckling.Region: EG :: Region
+ Duckling.Region: ES :: Region
+ Duckling.Region: MN :: Region
+ Duckling.Region: MX :: Region
+ Duckling.Region: PE :: Region
+ Duckling.Region: VE :: Region
+ Duckling.Rules.AF: defaultRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.AF: langRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.AF: localeRules :: Region -> Seal Dimension -> [Rule]
+ Duckling.Rules.BN: defaultRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.BN: langRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.BN: localeRules :: Region -> Seal Dimension -> [Rule]
+ Duckling.Rules.CA: defaultRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.CA: langRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.CA: localeRules :: Region -> Seal Dimension -> [Rule]
+ Duckling.Rules.FA: defaultRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.FA: langRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.FA: localeRules :: Region -> Seal Dimension -> [Rule]
+ Duckling.Rules.FI: defaultRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.FI: langRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.FI: localeRules :: Region -> Seal Dimension -> [Rule]
+ Duckling.Rules.IS: defaultRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.IS: langRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.IS: localeRules :: Region -> Seal Dimension -> [Rule]
+ Duckling.Rules.KM: defaultRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.KM: langRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.KM: localeRules :: Region -> Seal Dimension -> [Rule]
+ Duckling.Rules.KN: defaultRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.KN: langRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.KN: localeRules :: Region -> Seal Dimension -> [Rule]
+ Duckling.Rules.LO: defaultRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.LO: langRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.LO: localeRules :: Region -> Seal Dimension -> [Rule]
+ Duckling.Rules.ML: defaultRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.ML: langRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.ML: localeRules :: Region -> Seal Dimension -> [Rule]
+ Duckling.Rules.MN: defaultRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.MN: langRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.MN: localeRules :: Region -> Seal Dimension -> [Rule]
+ Duckling.Rules.SK: defaultRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.SK: langRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.SK: localeRules :: Region -> Seal Dimension -> [Rule]
+ Duckling.Rules.SW: defaultRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.SW: langRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.SW: localeRules :: Region -> Seal Dimension -> [Rule]
+ Duckling.Rules.TE: defaultRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.TE: langRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.TE: localeRules :: Region -> Seal Dimension -> [Rule]
+ Duckling.Rules.TH: defaultRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.TH: langRules :: Seal Dimension -> [Rule]
+ Duckling.Rules.TH: localeRules :: Region -> Seal Dimension -> [Rule]
+ Duckling.Temperature.HI.Corpus: corpus :: Corpus
+ Duckling.Temperature.HI.Rules: rules :: [Rule]
+ Duckling.Temperature.KM.Corpus: corpus :: Corpus
+ Duckling.Temperature.KM.Rules: rules :: [Rule]
+ Duckling.Temperature.MN.Corpus: corpus :: Corpus
+ Duckling.Temperature.MN.Rules: rules :: [Rule]
+ Duckling.Temperature.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Temperature.Types.SingleValue
+ Duckling.Temperature.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Temperature.Types.TemperatureUnit
+ Duckling.Temperature.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Temperature.Types.TemperatureValue
+ Duckling.Time.BG.Corpus: corpus :: Corpus
+ Duckling.Time.BG.Corpus: negativeCorpus :: NegativeCorpus
+ Duckling.Time.BG.Rules: rules :: [Rule]
+ Duckling.Time.Computed: ganeshChaturthi :: TimeData
+ Duckling.Time.Computed: guruGobindSinghJayanti :: TimeData
+ Duckling.Time.Computed: karvaChauth :: TimeData
+ Duckling.Time.Computed: krishnaJanmashtami :: TimeData
+ Duckling.Time.Computed: mahaShivaRatri :: TimeData
+ Duckling.Time.Computed: mahavirJayanti :: TimeData
+ Duckling.Time.Computed: pargatDiwas :: TimeData
+ Duckling.Time.Computed: purim :: TimeData
+ Duckling.Time.Computed: rabindraJayanti :: TimeData
+ Duckling.Time.Computed: ramaNavami :: TimeData
+ Duckling.Time.Computed: rathaYatra :: TimeData
+ Duckling.Time.Computed: ravidassJayanti :: TimeData
+ Duckling.Time.Computed: saraswatiJayanti :: TimeData
+ Duckling.Time.Computed: superTuesday :: TimeData
+ Duckling.Time.Computed: ugadi :: TimeData
+ Duckling.Time.Computed: vaisakhi :: TimeData
+ Duckling.Time.EN.Corpus: diffCorpus :: Corpus
+ Duckling.Time.EN.Rules: ruleASAP :: Rule
+ Duckling.Time.EN.Rules: ruleAbsorbCommaTOD :: Rule
+ Duckling.Time.EN.Rules: ruleAbsorbInMonthYear :: Rule
+ Duckling.Time.EN.Rules: ruleAbsorbOnADOW :: Rule
+ Duckling.Time.EN.Rules: ruleAbsorbOnDay :: Rule
+ Duckling.Time.EN.Rules: ruleAfterPartofday :: Rule
+ Duckling.Time.EN.Rules: ruleAtTOD :: Rule
+ Duckling.Time.EN.Rules: ruleBeginningOfMonth :: Rule
+ Duckling.Time.EN.Rules: ruleBeginningOfYear :: Rule
+ Duckling.Time.EN.Rules: ruleClosest :: Rule
+ Duckling.Time.EN.Rules: ruleComputedHolidays :: [Rule]
+ Duckling.Time.EN.Rules: ruleComputedHolidays' :: [Rule]
+ Duckling.Time.EN.Rules: ruleCycleAfterBeforeTime :: Rule
+ Duckling.Time.EN.Rules: ruleCycleLastOrdinalOfTime :: Rule
+ Duckling.Time.EN.Rules: ruleCycleOrdinalAfterTime :: Rule
+ Duckling.Time.EN.Rules: ruleCycleOrdinalOfTime :: Rule
+ Duckling.Time.EN.Rules: ruleCycleOrdinalQuarter :: Rule
+ Duckling.Time.EN.Rules: ruleCycleOrdinalQuarterYear :: Rule
+ Duckling.Time.EN.Rules: ruleCycleTheAfterBeforeTime :: Rule
+ Duckling.Time.EN.Rules: ruleCycleTheLastOrdinalOfTime :: Rule
+ Duckling.Time.EN.Rules: ruleCycleTheOfTime :: Rule
+ Duckling.Time.EN.Rules: ruleCycleTheOfTimeGrain :: Rule
+ Duckling.Time.EN.Rules: ruleCycleTheOrdinalAfterTime :: Rule
+ Duckling.Time.EN.Rules: ruleCycleTheOrdinalOfTime :: Rule
+ Duckling.Time.EN.Rules: ruleCycleTheOrdinalQuarter :: Rule
+ Duckling.Time.EN.Rules: ruleCycleThisLastNext :: Rule
+ Duckling.Time.EN.Rules: ruleDOMLatent :: Rule
+ Duckling.Time.EN.Rules: ruleDOMMonth :: Rule
+ Duckling.Time.EN.Rules: ruleDOMMonthYear :: Rule
+ Duckling.Time.EN.Rules: ruleDOMOfMonth :: Rule
+ Duckling.Time.EN.Rules: ruleDOMOfTimeMonth :: Rule
+ Duckling.Time.EN.Rules: ruleDOMOrdinalMonthYear :: Rule
+ Duckling.Time.EN.Rules: ruleDayDurationHenceAgo :: Rule
+ Duckling.Time.EN.Rules: ruleDayInDuration :: Rule
+ Duckling.Time.EN.Rules: ruleDaysOfWeek :: [Rule]
+ Duckling.Time.EN.Rules: ruleDurationAfterBeforeTime :: Rule
+ Duckling.Time.EN.Rules: ruleDurationHenceAgo :: Rule
+ Duckling.Time.EN.Rules: ruleDurationInWithinAfter :: Rule
+ Duckling.Time.EN.Rules: ruleDurationLastNext :: Rule
+ Duckling.Time.EN.Rules: ruleEarlyMorning :: Rule
+ Duckling.Time.EN.Rules: ruleEndOfMonth :: Rule
+ Duckling.Time.EN.Rules: ruleEndOfYear :: Rule
+ Duckling.Time.EN.Rules: ruleEndOrBeginningOfMonth :: Rule
+ Duckling.Time.EN.Rules: ruleEndOrBeginningOfWeek :: Rule
+ Duckling.Time.EN.Rules: ruleEndOrBeginningOfYear :: Rule
+ Duckling.Time.EN.Rules: ruleHHMM :: Rule
+ Duckling.Time.EN.Rules: ruleHHMMLatent :: Rule
+ Duckling.Time.EN.Rules: ruleHHMMSS :: Rule
+ Duckling.Time.EN.Rules: ruleHHhMM :: Rule
+ Duckling.Time.EN.Rules: ruleHODHalf :: Rule
+ Duckling.Time.EN.Rules: ruleHODQuarter :: Rule
+ Duckling.Time.EN.Rules: ruleHONumeral :: Rule
+ Duckling.Time.EN.Rules: ruleHONumeralAlt :: Rule
+ Duckling.Time.EN.Rules: ruleHalfAfterHOD :: Rule
+ Duckling.Time.EN.Rules: ruleHalfHOD :: Rule
+ Duckling.Time.EN.Rules: ruleHalfToHOD :: Rule
+ Duckling.Time.EN.Rules: ruleIdesOfMonth :: Rule
+ Duckling.Time.EN.Rules: ruleInDurationAtTime :: Rule
+ Duckling.Time.EN.Rules: ruleInNumeral :: Rule
+ Duckling.Time.EN.Rules: ruleInstants :: [Rule]
+ Duckling.Time.EN.Rules: ruleIntersect :: Rule
+ Duckling.Time.EN.Rules: ruleIntersectOf :: Rule
+ Duckling.Time.EN.Rules: ruleIntersectYear :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalAfterFromSinceTime :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalBetween :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalBy :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalByTheEndOf :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalDDDDMonth :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalDash :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalDashTimezone :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalForDurationFrom :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalFrom :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalFromDDDDMonth :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalFromDDDDOfMonth :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalFromMonthDDDD :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalFromTimeForDuration :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalMonthDDDD :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalSlash :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalTODAMPM :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalTODBetween :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalTODDash :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalTODFrom :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalTimeForDuration :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalUntilTime :: Rule
+ Duckling.Time.EN.Rules: ruleIntervalYearLatent :: Rule
+ Duckling.Time.EN.Rules: ruleLastCycleOfTime :: Rule
+ Duckling.Time.EN.Rules: ruleLastDOWOfTime :: Rule
+ Duckling.Time.EN.Rules: ruleLastNight :: Rule
+ Duckling.Time.EN.Rules: ruleLastTime :: Rule
+ Duckling.Time.EN.Rules: ruleLastWeekendOfMonth :: Rule
+ Duckling.Time.EN.Rules: ruleMMYYYY :: Rule
+ Duckling.Time.EN.Rules: ruleMidDay :: Rule
+ Duckling.Time.EN.Rules: ruleMilitaryAMPM :: Rule
+ Duckling.Time.EN.Rules: ruleMilitarySpelledOutAMPM :: Rule
+ Duckling.Time.EN.Rules: ruleMilitarySpelledOutAMPM2 :: Rule
+ Duckling.Time.EN.Rules: ruleMinutesToHOD :: Rule
+ Duckling.Time.EN.Rules: ruleMonthDOMNumeral :: Rule
+ Duckling.Time.EN.Rules: ruleMonths :: [Rule]
+ Duckling.Time.EN.Rules: ruleNDOWFromTime :: Rule
+ Duckling.Time.EN.Rules: ruleNDOWago :: Rule
+ Duckling.Time.EN.Rules: ruleNamedDOMOrdinal :: Rule
+ Duckling.Time.EN.Rules: ruleNextDOW :: Rule
+ Duckling.Time.EN.Rules: ruleNextTime :: Rule
+ Duckling.Time.EN.Rules: ruleNoonMidnightEOD :: Rule
+ Duckling.Time.EN.Rules: ruleNow :: Rule
+ Duckling.Time.EN.Rules: ruleNthClosest :: Rule
+ Duckling.Time.EN.Rules: ruleNthTimeAfterTime :: Rule
+ Duckling.Time.EN.Rules: ruleNthTimeOfTime :: Rule
+ Duckling.Time.EN.Rules: ruleNumeralAfterHOD :: Rule
+ Duckling.Time.EN.Rules: ruleNumeralToHOD :: Rule
+ Duckling.Time.EN.Rules: ruleOrdinalDOWOfTime :: Rule
+ Duckling.Time.EN.Rules: rulePODIn :: Rule
+ Duckling.Time.EN.Rules: rulePODThis :: Rule
+ Duckling.Time.EN.Rules: rulePODatTOD :: Rule
+ Duckling.Time.EN.Rules: rulePODofTime :: Rule
+ Duckling.Time.EN.Rules: rulePartOfDays :: Rule
+ Duckling.Time.EN.Rules: rulePartOfMonth :: Rule
+ Duckling.Time.EN.Rules: rulePeriodicHolidays :: [Rule]
+ Duckling.Time.EN.Rules: rulePrecisionTOD :: Rule
+ Duckling.Time.EN.Rules: ruleQuarterAfterHOD :: Rule
+ Duckling.Time.EN.Rules: ruleQuarterToHOD :: Rule
+ Duckling.Time.EN.Rules: ruleSeason :: Rule
+ Duckling.Time.EN.Rules: ruleSeasons :: [Rule]
+ Duckling.Time.EN.Rules: ruleTODAMPM :: Rule
+ Duckling.Time.EN.Rules: ruleTODLatent :: Rule
+ Duckling.Time.EN.Rules: ruleTODOClock :: Rule
+ Duckling.Time.EN.Rules: ruleTODPOD :: Rule
+ Duckling.Time.EN.Rules: ruleTODPrecision :: Rule
+ Duckling.Time.EN.Rules: ruleTheDOMNumeral :: Rule
+ Duckling.Time.EN.Rules: ruleTheDOMOfMonth :: Rule
+ Duckling.Time.EN.Rules: ruleTheDOMOrdinal :: Rule
+ Duckling.Time.EN.Rules: ruleTheNthTimeAfterTime :: Rule
+ Duckling.Time.EN.Rules: ruleTheNthTimeOfTime :: Rule
+ Duckling.Time.EN.Rules: ruleThisTime :: Rule
+ Duckling.Time.EN.Rules: ruleTimeBeforeLastAfterNext :: Rule
+ Duckling.Time.EN.Rules: ruleTimePOD :: Rule
+ Duckling.Time.EN.Rules: ruleTimezone :: Rule
+ Duckling.Time.EN.Rules: ruleTimezoneBracket :: Rule
+ Duckling.Time.EN.Rules: ruleTonight :: Rule
+ Duckling.Time.EN.Rules: ruleUpcomingGrain :: Rule
+ Duckling.Time.EN.Rules: ruleUpcomingGrainAlt :: Rule
+ Duckling.Time.EN.Rules: ruleWeek :: Rule
+ Duckling.Time.EN.Rules: ruleWeekend :: Rule
+ Duckling.Time.EN.Rules: ruleYYYYMM :: Rule
+ Duckling.Time.EN.Rules: ruleYYYYMMDD :: Rule
+ Duckling.Time.EN.Rules: ruleYYYYQQ :: Rule
+ Duckling.Time.EN.Rules: ruleYearADBC :: Rule
+ Duckling.Time.EN.Rules: ruleYearLatent :: Rule
+ Duckling.Time.EN.Rules: timezoneName :: String
+ Duckling.Time.EN.US.Rules: ruleBackwardCompatibleHolidays :: [Rule]
+ Duckling.Time.EN.US.Rules: ruleComputedHolidays :: [Rule]
+ Duckling.Time.EN.US.Rules: ruleComputedHolidays' :: [Rule]
+ Duckling.Time.EN.US.Rules: ruleMMDD :: Rule
+ Duckling.Time.EN.US.Rules: ruleMMDDYYYY :: Rule
+ Duckling.Time.EN.US.Rules: ruleMMDDYYYYDot :: Rule
+ Duckling.Time.EN.US.Rules: rulePeriodicHolidays :: [Rule]
+ Duckling.Time.EN.US.Rules: rulePeriodicHolidays' :: [Rule]
+ Duckling.Time.EN.US.Rules: tuesday :: String
+ Duckling.Time.ES.Corpus: latentCorpus :: Corpus
+ Duckling.Time.Helpers: hasNoTimezone :: Predicate
+ Duckling.Time.Helpers: hasTimezone :: Predicate
+ Duckling.Time.Helpers: isDurationGreaterThan :: Grain -> Predicate
+ Duckling.Time.Helpers: isGrainCoarserThan :: Grain -> Predicate
+ Duckling.Time.Helpers: predEveryNDaysFrom :: Int -> (Integer, Int, Int) -> Maybe TimeData
+ Duckling.Time.Helpers: sameGrain :: TimeData -> TimeData -> Bool
+ Duckling.Time.Helpers: timeCycle :: Grain -> Predicate
+ Duckling.Time.Helpers: toTimeObjectM :: (Integer, Int, Int) -> Maybe TimeObject
+ Duckling.Time.Helpers: today :: TimeData
+ Duckling.Time.Helpers: workweek :: TimeData
+ Duckling.Time.Helpers: yearMonth :: Int -> Int -> TimeData
+ Duckling.Time.HolidayHelpers: computeEarthHour :: Maybe TimeData
+ Duckling.Time.HolidayHelpers: computeKingsDay :: Maybe TimeData
+ Duckling.Time.KA.Corpus: corpus :: Corpus
+ Duckling.Time.KA.Corpus: defaultCorpus :: Corpus
+ Duckling.Time.KA.Corpus: latentCorpus :: Corpus
+ Duckling.Time.KA.Rules: rules :: [Rule]
+ Duckling.Time.NL.Corpus: latentCorpus :: Corpus
+ Duckling.Time.RU.Corpus: corpus :: Corpus
+ Duckling.Time.RU.Corpus: negativeCorpus :: NegativeCorpus
+ Duckling.Time.RU.Rules: rules :: [Rule]
+ Duckling.Time.TR.Corpus: corpus :: Corpus
+ Duckling.Time.TR.Rules: rules :: [Rule]
+ Duckling.Time.Types: [hasTimezone] :: TimeData -> Bool
+ Duckling.Time.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Time.Types.InstantValue
+ Duckling.Time.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Time.Types.SingleTimeValue
+ Duckling.Time.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Time.Types.TimeValue
+ Duckling.Time.Types: periodicPredicate :: Grain -> Int -> TimeObject -> Predicate
+ Duckling.Time.UK.Corpus: corpus :: Corpus
+ Duckling.Time.UK.Corpus: negativeCorpus :: NegativeCorpus
+ Duckling.Time.UK.Rules: rules :: [Rule]
+ Duckling.Time.VI.Corpus: negativeCorpus :: NegativeCorpus
+ Duckling.TimeGrain.FI.Rules: rules :: [Rule]
+ Duckling.TimeGrain.KA.Rules: rules :: [Rule]
+ Duckling.TimeGrain.MN.Rules: rules :: [Rule]
+ Duckling.TimeGrain.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.TimeGrain.Types.Grain
+ Duckling.TimeGrain.UK.Rules: rules :: [Rule]
+ Duckling.Types: [CreditCardNumber] :: Dimension CreditCardNumberData
+ Duckling.Types: [Seal] :: s a -> Seal s
+ Duckling.Types: data Seal s
+ Duckling.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Types.Entity
+ Duckling.Types: instance Data.GADT.Internal.GEq Duckling.Types.Dimension
+ Duckling.Types: instance Data.GADT.Internal.GEq s => GHC.Classes.Eq (Duckling.Types.Seal s)
+ Duckling.Types: instance Data.GADT.Internal.GShow Duckling.Types.Dimension
+ Duckling.Types: instance Data.GADT.Internal.GShow s => GHC.Show.Show (Duckling.Types.Seal s)
+ Duckling.Types: instance Data.Hashable.Class.Hashable (Duckling.Types.Seal Duckling.Types.Dimension)
+ Duckling.Types: instance TextShow.Classes.TextShow (Duckling.Types.Seal Duckling.Types.Dimension)
+ Duckling.Types: singleStringLookupRule :: HashMap Text a -> Text -> (a -> Maybe Token) -> Rule
+ Duckling.Types: withSeal :: Seal s -> (forall t. s t -> r) -> r
+ Duckling.Url.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Url.Types.UrlData
+ Duckling.Volume.DE.Corpus: corpus :: Corpus
+ Duckling.Volume.DE.Rules: rules :: [Rule]
+ Duckling.Volume.Helpers: isSimpleVolume :: Predicate
+ Duckling.Volume.Helpers: isUnitOnly :: Predicate
+ Duckling.Volume.Helpers: unitOnly :: Unit -> VolumeData
+ Duckling.Volume.Helpers: valueOnly :: Double -> VolumeData
+ Duckling.Volume.Helpers: withInterval :: (Double, Double) -> VolumeData -> VolumeData
+ Duckling.Volume.Helpers: withMax :: Double -> VolumeData -> VolumeData
+ Duckling.Volume.Helpers: withMin :: Double -> VolumeData -> VolumeData
+ Duckling.Volume.Helpers: withValue :: Double -> VolumeData -> VolumeData
+ Duckling.Volume.KM.Corpus: corpus :: Corpus
+ Duckling.Volume.KM.Rules: rules :: [Rule]
+ Duckling.Volume.MN.Corpus: corpus :: Corpus
+ Duckling.Volume.MN.Rules: rules :: [Rule]
+ Duckling.Volume.Types: Above :: IntervalDirection
+ Duckling.Volume.Types: Centilitre :: Unit
+ Duckling.Volume.Types: IntervalValue :: (SingleValue, SingleValue) -> VolumeValue
+ Duckling.Volume.Types: OpenIntervalValue :: (SingleValue, IntervalDirection) -> VolumeValue
+ Duckling.Volume.Types: SimpleValue :: SingleValue -> VolumeValue
+ Duckling.Volume.Types: SingleValue :: Unit -> Double -> SingleValue
+ Duckling.Volume.Types: Under :: IntervalDirection
+ Duckling.Volume.Types: [maxValue] :: VolumeData -> Maybe Double
+ Duckling.Volume.Types: [minValue] :: VolumeData -> Maybe Double
+ Duckling.Volume.Types: above :: Unit -> Double -> VolumeValue
+ Duckling.Volume.Types: between :: Unit -> (Double, Double) -> VolumeValue
+ Duckling.Volume.Types: data IntervalDirection
+ Duckling.Volume.Types: data SingleValue
+ Duckling.Volume.Types: instance Control.DeepSeq.NFData Duckling.Volume.Types.IntervalDirection
+ Duckling.Volume.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Volume.Types.SingleValue
+ Duckling.Volume.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Volume.Types.Unit
+ Duckling.Volume.Types: instance Data.Aeson.Types.ToJSON.ToJSON Duckling.Volume.Types.VolumeValue
+ Duckling.Volume.Types: instance Data.Hashable.Class.Hashable Duckling.Volume.Types.IntervalDirection
+ Duckling.Volume.Types: instance GHC.Classes.Eq Duckling.Volume.Types.IntervalDirection
+ Duckling.Volume.Types: instance GHC.Classes.Eq Duckling.Volume.Types.SingleValue
+ Duckling.Volume.Types: instance GHC.Classes.Ord Duckling.Volume.Types.IntervalDirection
+ Duckling.Volume.Types: instance GHC.Generics.Generic Duckling.Volume.Types.IntervalDirection
+ Duckling.Volume.Types: instance GHC.Show.Show Duckling.Volume.Types.IntervalDirection
+ Duckling.Volume.Types: instance GHC.Show.Show Duckling.Volume.Types.SingleValue
+ Duckling.Volume.Types: openInterval :: IntervalDirection -> Unit -> Double -> VolumeValue
+ Duckling.Volume.Types: simple :: Unit -> Double -> VolumeValue
+ Duckling.Volume.Types: single :: Unit -> Double -> SingleValue
+ Duckling.Volume.Types: under :: Unit -> Double -> VolumeValue
+ Duckling.Volume.ZH.Corpus: corpus :: Corpus
+ Duckling.Volume.ZH.Rules: rules :: [Rule]
- Duckling.AmountOfMoney.Types: AmountOfMoneyData :: Maybe Double -> Currency -> Maybe Double -> Maybe Double -> AmountOfMoneyData
+ Duckling.AmountOfMoney.Types: AmountOfMoneyData :: Maybe Double -> Currency -> Maybe Double -> Maybe Double -> Bool -> AmountOfMoneyData
- Duckling.Api: analyze :: Text -> Context -> Options -> HashSet (Some Dimension) -> [ResolvedToken]
+ Duckling.Api: analyze :: Text -> Context -> Options -> HashSet (Seal Dimension) -> [ResolvedToken]
- Duckling.Api: parse :: Text -> Context -> Options -> [Some Dimension] -> [Entity]
+ Duckling.Api: parse :: Text -> Context -> Options -> [Seal Dimension] -> [Entity]
- Duckling.Api: supportedDimensions :: HashMap Lang [Some Dimension]
+ Duckling.Api: supportedDimensions :: HashMap Lang [Seal Dimension]
- Duckling.Core: CA :: Region
+ Duckling.Core: CA :: Lang
- Duckling.Core: RVal :: (Dimension a) -> (ResolvedValue a) -> ResolvedVal
+ Duckling.Core: RVal :: Dimension a -> ResolvedValue a -> ResolvedVal
- Duckling.Core: fromName :: Text -> Maybe (Some Dimension)
+ Duckling.Core: fromName :: Text -> Maybe (Seal Dimension)
- Duckling.Core: parse :: Text -> Context -> Options -> [Some Dimension] -> [Entity]
+ Duckling.Core: parse :: Text -> Context -> Options -> [Seal Dimension] -> [Entity]
- Duckling.Core: supportedDimensions :: HashMap Lang [Some Dimension]
+ Duckling.Core: supportedDimensions :: HashMap Lang [Seal Dimension]
- Duckling.Debug: allParses :: Locale -> Text -> [Some Dimension] -> IO [Entity]
+ Duckling.Debug: allParses :: Locale -> Text -> [Seal Dimension] -> IO [Entity]
- Duckling.Debug: debug :: Locale -> Text -> [Some Dimension] -> IO [Entity]
+ Duckling.Debug: debug :: Locale -> Text -> [Seal Dimension] -> IO [Entity]
- Duckling.Debug: debugCustom :: Context -> Options -> Text -> [Some Dimension] -> IO [Entity]
+ Duckling.Debug: debugCustom :: Context -> Options -> Text -> [Seal Dimension] -> IO [Entity]
- Duckling.Debug: fullParses :: Locale -> Text -> [Some Dimension] -> IO [Entity]
+ Duckling.Debug: fullParses :: Locale -> Text -> [Seal Dimension] -> IO [Entity]
- Duckling.Dimensions: allDimensions :: Lang -> [Some Dimension]
+ Duckling.Dimensions: allDimensions :: Lang -> [Seal Dimension]
- Duckling.Dimensions: explicitDimensions :: HashSet (Some Dimension) -> HashSet (Some Dimension)
+ Duckling.Dimensions: explicitDimensions :: HashSet (Seal Dimension) -> HashSet (Seal Dimension)
- Duckling.Dimensions.AR: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.AR: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.BG: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.BG: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.CS: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.CS: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.Common: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.Common: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.DA: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.DA: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.DE: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.DE: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.EL: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.EL: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.EN: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.EN: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.ES: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.ES: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.ET: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.ET: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.FR: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.FR: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.GA: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.GA: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.HE: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.HE: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.HI: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.HI: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.HR: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.HR: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.HU: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.HU: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.ID: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.ID: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.IT: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.IT: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.JA: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.JA: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.KA: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.KA: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.KO: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.KO: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.MY: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.MY: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.NB: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.NB: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.NE: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.NE: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.NL: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.NL: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.PL: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.PL: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.PT: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.PT: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.RO: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.RO: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.RU: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.RU: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.SV: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.SV: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.TA: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.TA: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.TR: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.TR: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.Types: fromName :: Text -> Maybe (Some Dimension)
+ Duckling.Dimensions.Types: fromName :: Text -> Maybe (Seal Dimension)
- Duckling.Dimensions.UK: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.UK: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.VI: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.VI: allDimensions :: [Seal Dimension]
- Duckling.Dimensions.ZH: allDimensions :: [Some Dimension]
+ Duckling.Dimensions.ZH: allDimensions :: [Seal Dimension]
- Duckling.Locale: CA :: Region
+ Duckling.Locale: CA :: Lang
- Duckling.Locale: Locale :: Lang -> (Maybe Region) -> Locale
+ Duckling.Locale: Locale :: Lang -> Maybe Region -> Locale
- Duckling.Quantity.Types: QuantityData :: Maybe Unit -> Maybe Double -> Maybe Text -> Maybe Double -> Maybe Double -> QuantityData
+ Duckling.Quantity.Types: QuantityData :: Maybe Unit -> Maybe Double -> Maybe Text -> Maybe Double -> Maybe Double -> Bool -> QuantityData
- Duckling.Ranking.Rank: rank :: Classifiers -> HashSet (Some Dimension) -> [ResolvedToken] -> [ResolvedToken]
+ Duckling.Ranking.Rank: rank :: Classifiers -> HashSet (Seal Dimension) -> [ResolvedToken] -> [ResolvedToken]
- Duckling.Rules: rulesFor :: Locale -> HashSet (Some Dimension) -> [Rule]
+ Duckling.Rules: rulesFor :: Locale -> HashSet (Seal Dimension) -> [Rule]
- Duckling.Rules.AR: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.AR: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.AR: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.AR: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.AR: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.AR: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.BG: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.BG: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.BG: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.BG: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.BG: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.BG: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.CS: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.CS: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.CS: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.CS: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.CS: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.CS: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.Common: rules :: Some Dimension -> [Rule]
+ Duckling.Rules.Common: rules :: Seal Dimension -> [Rule]
- Duckling.Rules.DA: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.DA: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.DA: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.DA: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.DA: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.DA: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.DE: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.DE: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.DE: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.DE: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.DE: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.DE: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.EL: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.EL: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.EL: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.EL: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.EL: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.EL: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.EN: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.EN: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.EN: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.EN: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.EN: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.EN: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.ES: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.ES: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.ES: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.ES: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.ES: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.ES: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.ET: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.ET: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.ET: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.ET: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.ET: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.ET: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.FR: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.FR: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.FR: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.FR: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.FR: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.FR: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.GA: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.GA: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.GA: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.GA: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.GA: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.GA: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.HE: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.HE: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.HE: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.HE: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.HE: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.HE: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.HI: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.HI: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.HI: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.HI: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.HI: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.HI: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.HR: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.HR: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.HR: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.HR: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.HR: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.HR: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.HU: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.HU: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.HU: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.HU: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.HU: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.HU: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.ID: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.ID: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.ID: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.ID: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.ID: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.ID: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.IT: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.IT: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.IT: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.IT: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.IT: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.IT: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.JA: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.JA: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.JA: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.JA: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.JA: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.JA: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.KA: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.KA: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.KA: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.KA: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.KA: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.KA: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.KO: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.KO: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.KO: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.KO: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.KO: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.KO: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.MY: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.MY: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.MY: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.MY: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.MY: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.MY: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.NB: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.NB: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.NB: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.NB: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.NB: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.NB: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.NE: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.NE: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.NE: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.NE: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.NE: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.NE: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.NL: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.NL: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.NL: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.NL: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.NL: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.NL: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.PL: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.PL: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.PL: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.PL: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.PL: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.PL: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.PT: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.PT: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.PT: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.PT: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.PT: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.PT: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.RO: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.RO: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.RO: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.RO: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.RO: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.RO: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.RU: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.RU: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.RU: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.RU: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.RU: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.RU: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.SV: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.SV: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.SV: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.SV: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.SV: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.SV: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.TA: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.TA: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.TA: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.TA: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.TA: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.TA: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.TR: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.TR: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.TR: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.TR: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.TR: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.TR: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.UK: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.UK: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.UK: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.UK: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.UK: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.UK: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.VI: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.VI: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.VI: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.VI: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.VI: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.VI: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Rules.ZH: defaultRules :: Some Dimension -> [Rule]
+ Duckling.Rules.ZH: defaultRules :: Seal Dimension -> [Rule]
- Duckling.Rules.ZH: langRules :: Some Dimension -> [Rule]
+ Duckling.Rules.ZH: langRules :: Seal Dimension -> [Rule]
- Duckling.Rules.ZH: localeRules :: Region -> Some Dimension -> [Rule]
+ Duckling.Rules.ZH: localeRules :: Region -> Seal Dimension -> [Rule]
- Duckling.Temperature.Helpers: valueOnly :: Int -> TemperatureData
+ Duckling.Temperature.Helpers: valueOnly :: Double -> TemperatureData
- Duckling.Temperature.Helpers: withInterval :: (Int, Int) -> TemperatureData -> TemperatureData
+ Duckling.Temperature.Helpers: withInterval :: (Double, Double) -> TemperatureData -> TemperatureData
- Duckling.Temperature.Helpers: withMax :: Int -> TemperatureData -> TemperatureData
+ Duckling.Temperature.Helpers: withMax :: Double -> TemperatureData -> TemperatureData
- Duckling.Temperature.Helpers: withMin :: Int -> TemperatureData -> TemperatureData
+ Duckling.Temperature.Helpers: withMin :: Double -> TemperatureData -> TemperatureData
- Duckling.Temperature.Helpers: withValue :: Int -> TemperatureData -> TemperatureData
+ Duckling.Temperature.Helpers: withValue :: Double -> TemperatureData -> TemperatureData
- Duckling.Temperature.Types: SingleValue :: TemperatureUnit -> Int -> SingleValue
+ Duckling.Temperature.Types: SingleValue :: TemperatureUnit -> Double -> SingleValue
- Duckling.Temperature.Types: TemperatureData :: Maybe TemperatureUnit -> Maybe Int -> Maybe Int -> Maybe Int -> TemperatureData
+ Duckling.Temperature.Types: TemperatureData :: Maybe TemperatureUnit -> Maybe Double -> Maybe Double -> Maybe Double -> TemperatureData
- Duckling.Temperature.Types: [maxValue] :: TemperatureData -> Maybe Int
+ Duckling.Temperature.Types: [maxValue] :: TemperatureData -> Maybe Double
- Duckling.Temperature.Types: [minValue] :: TemperatureData -> Maybe Int
+ Duckling.Temperature.Types: [minValue] :: TemperatureData -> Maybe Double
- Duckling.Temperature.Types: [vValue] :: SingleValue -> Int
+ Duckling.Temperature.Types: [vValue] :: SingleValue -> Double
- Duckling.Temperature.Types: [value] :: TemperatureData -> Maybe Int
+ Duckling.Temperature.Types: [value] :: TemperatureData -> Maybe Double
- Duckling.Temperature.Types: above :: TemperatureUnit -> Int -> TemperatureValue
+ Duckling.Temperature.Types: above :: TemperatureUnit -> Double -> TemperatureValue
- Duckling.Temperature.Types: between :: TemperatureUnit -> (Int, Int) -> TemperatureValue
+ Duckling.Temperature.Types: between :: TemperatureUnit -> (Double, Double) -> TemperatureValue
- Duckling.Temperature.Types: openInterval :: IntervalDirection -> TemperatureUnit -> Int -> TemperatureValue
+ Duckling.Temperature.Types: openInterval :: IntervalDirection -> TemperatureUnit -> Double -> TemperatureValue
- Duckling.Temperature.Types: simple :: TemperatureUnit -> Int -> TemperatureValue
+ Duckling.Temperature.Types: simple :: TemperatureUnit -> Double -> TemperatureValue
- Duckling.Temperature.Types: single :: TemperatureUnit -> Int -> SingleValue
+ Duckling.Temperature.Types: single :: TemperatureUnit -> Double -> SingleValue
- Duckling.Temperature.Types: under :: TemperatureUnit -> Int -> TemperatureValue
+ Duckling.Temperature.Types: under :: TemperatureUnit -> Double -> TemperatureValue
- Duckling.Time.Types: SeriesPredicate :: (NoShow SeriesPredicate) -> Predicate
+ Duckling.Time.Types: SeriesPredicate :: NoShow SeriesPredicate -> Predicate
- Duckling.Time.Types: TimeData :: Predicate -> Bool -> Grain -> Bool -> Maybe Form -> Maybe IntervalDirection -> Bool -> Maybe Text -> TimeData
+ Duckling.Time.Types: TimeData :: Predicate -> Bool -> Grain -> Bool -> Maybe Form -> Maybe IntervalDirection -> Bool -> Maybe Text -> Bool -> TimeData
- Duckling.Time.Types: TimeValue :: SingleTimeValue -> [SingleTimeValue] -> (Maybe Text) -> TimeValue
+ Duckling.Time.Types: TimeValue :: SingleTimeValue -> [SingleTimeValue] -> Maybe Text -> TimeValue
- Duckling.Types: RVal :: (Dimension a) -> (ResolvedValue a) -> ResolvedVal
+ Duckling.Types: RVal :: Dimension a -> ResolvedValue a -> ResolvedVal
- Duckling.Types: Token :: (Dimension a) -> a -> Token
+ Duckling.Types: Token :: Dimension a -> a -> Token
- Duckling.Types: class (Show a, Typeable a) => CustomDimension a where {
+ Duckling.Types: class (Show a, Typeable a, Typeable (DimensionData a)) => CustomDimension a where {
- Duckling.Types: dimDependents :: CustomDimension a => a -> HashSet (Some Dimension)
+ Duckling.Types: dimDependents :: CustomDimension a => a -> HashSet (Seal Dimension)
- Duckling.Volume.Helpers: volume :: Double -> VolumeData
+ Duckling.Volume.Helpers: volume :: Unit -> Double -> VolumeData
- Duckling.Volume.Types: VolumeData :: Maybe Unit -> Double -> VolumeData
+ Duckling.Volume.Types: VolumeData :: Maybe Double -> Maybe Unit -> Maybe Double -> Maybe Double -> VolumeData
- Duckling.Volume.Types: [vUnit] :: VolumeValue -> Unit
+ Duckling.Volume.Types: [vUnit] :: SingleValue -> Unit
- Duckling.Volume.Types: [vValue] :: VolumeValue -> Double
+ Duckling.Volume.Types: [vValue] :: SingleValue -> Double
- Duckling.Volume.Types: [value] :: VolumeData -> Double
+ Duckling.Volume.Types: [value] :: VolumeData -> Maybe Double

This diff is very large; some files are shown as “too large to diff”. Download the raw patch for the complete diff.

Files

+ CHANGELOG.md view
@@ -0,0 +1,784 @@+# Changelog for [`duckling` package](https://github.com/facebook/duckling)++## 0.2.0.0++### Core+  * Bump versions on dependencies+  * ExampleMain: add support for setting the port+  * Support for GHC >= 8.8.x && GHC <= 9.0.1+  * Relicense to BSD-3+  * Probabilistic layer bug fix+  * Remove dependency on Data.Some+  * Depend on regex-pcre-builtin on Windows+  * Update cabal-version to 2.2+  * Migrate to GitHub CI over Travis+  * Some attempts at getting smaller parse trees (less exploitable)++### Rulesets++* Common+  * Correct CDT TimeZone offset  CDT is (-300), not 540.+  * Fixed BST and IST offsets. BST is +1 (60) and IST is +5:30 (330)+  * Make unicode output in tests sane by not relying on `Show`+  * Add type=value to JSON response for Email, PhoneNumber, and Url, for consistency+  * CreditCardNumber: **new!** (duckling can now recognise credit cards)+  * Email: Add DE (German) + IS (Icelandic) spelled out email+  * Numeral: Don't accept dashes ('-') as token separators+  * Time: Add Karva Chauth holiday+  * Time: Add Vaisakhi holiday+  * Time: Add daylight savings start/endtimes to holidays+  * Time: Add Purim and Shushan Purim (Jewish holidays)+  * Time: Add Guru Gobind Singh Jayanti holiday+  * Time: Extend support for Ramadan and Eid al-Fitr from 1950 to 2050+  * Time: Add support for Parsi New Year+  * Time: Add support for Dayananda Saraswati Jayanti holiday+  * Time: Extend support for Mawlid from 1950 to 1998+  * Time: Add Rabindra Jayanti holiday+  * Time: Add Guru Ravidass Jayanti holiday+  * Time: Extend support for Eid al-Adha from 1950 to 2000+  * Time: Add Krishna Janmashtami holiday+  * Time: Add Mahavir Jayanti holiday+  * Time: Add Maha Shivaratri holiday+  * Time: add Ugadi holiday+  * Volume: interval support++* AF (Afrikaans)+  * Numeral: **new!**++* AR (Arabic)+  * Add a new locale: EG (Egyptian)+  * AmountOfMoney: Add more variants of EGP+  * Numeral: Add support for numerals written in Arabic script+  * Numeral: Support decimals and comma-separated integers+  * PhoneNumber: **new!**+  * Time: Add periodic times+  * Time: Add rule for a week ago++* BG (Bulgarian)+  * Time: **new!**++* BN (Bengali)+  * Numeral: **new!**++* CA (Catalan)+  * Numeral: **new!**+  * Ordinal: **new!**++* DA (Danish)+  * Ordinal: Add support for larger spelled-out ordinals+  * Time: recognise abbreviation 'kl'++* DE (German)+  * Distance: **new!**+  * Duration: Add more common durations+  * Numeral: Fix typo on "fünfzehn"(15)+  * Time: Fix wrong parsing of YYYY-MM-DD dates+  * Time: Add rule for 'the day before yesterday'+  * Time: Fix a bug for "fünfter"¬+  * Time: support for "am ersten Dezember" to " am einunddreißigsten Dezember"¬+  * Time: now recognise "der fünfte Dezember"¬+  * Time: Add support for (pre-)computed holidays+  * Time: Don't parse 'so'+  * Time: improve approximations+  * Time: Add rule for week after next+  * Time: Add rule for montag in n wochen+  * Volume: **new!**++* EN (English)+  * AmountOfMoney: Add support for subunits of dollars, e.g. nickels, dimes, quarters, as well as the number of coins+  * AmountOfMoney: Add support for latent+  * AmountOfMoney: Add support for lakh and crore+  * AmountOfMoney: correct regex to match three letter currency codes beginning with C+  * AmountOfMoney: Make ruleInterval{Max,Min} symmetric+  * AmountOfMoney: Support abbreviations of lakh and crore+  * AmountOfMoney: Add UAH currency+  * AmountOfMoney: Add HKD+  * AmountOfMoney: dollar and \<amount-of-money\>+  * AmountOfMoney: dollar and a half+  * AmountOfMoney: intersection for \<amount-of-money\> and a half+  * AmountOfMoney: extend interval support+  * AmountOfMoney: Add more variants of EGP+  * Distance: Support composite distances+  * Distance: one meter and \<distance\>+  * Distance: \<distance\> meters and \<distance\>+  * Distance: Add interval support+  * Duration: Fix composite durations without delimiters.+              It previously only worked with+              commas/'and'-separated tokens+  * Duration: Support more words in `ruleDurationNumeralMore`+  * Duration: \<integer\> and a half minutes+  * Duration: support for \<integer\> hour and \<integer\>+  * Duration: parse Xm as X minutes and X.Y hrs as X.Y hours+  * Duration: Leverage TimeGrain for x.y hours+  * Duration: Support composite duration+  * Numeral: Fix ambiguous parses when both ruleNegative and ruleMultiply apply+  * Numeral: Extend fraction rule+  * Numeral: Add mixed fraction rules+  * Numeral: Add prefix of 10/100/10_000 rules+  * Quantity: Support 'k.g' and 'k.g.' for kilograms+  * Temperature: Support temperatures with decimal values+  * Time: Fix palm sunday regex+  * Time: Fix latent time of days like "ten thirty"+  * Time: Don't parse time of days above 12 with meridiem+          like "13 am"+  * Time: Add rule to match \<time\> + \<timezone\>+  * Time: Add "all week"/"rest of the week" rules+  * Time: Parse time intervals like: 2015-03-28 17:00:00/2015-03-28 21:00:00+  * Time: Add rules to handle "DD/MM/YYYY" or "DD MM YYYY"+  * Time: Add support for YYYYQQ and YYQQ expressions, like+          '2018Q4' and '18Q4'+  * Time: Add rule for 'during \<month\>'+  * Time: Restrict 'on' absorption to days+  * Time: Fix durations, upper intervals should all be exclusive+  * Time: Fix grain on some intervals for time-of-days+  * Time: Add rule 'in \<duration\> at \<time-ofday\>+  * Time: Add \<datetime\> - \<datetime\> (interval) timezone rule+  * Time: '\<day\> in \<duration\> should only operate on grain \> Hour+  * Time: Add '\<integer\> \<day-of-week\> from \<time\>' rule+  * Time: Add \<duration\> past \<time\>+  * Time: Make 'the week' resolve to interval from `today` to `end of week`+  * Time: Add support for \<hour\>h\<min\>+  * Time: Add rule for a quarter after \<hour-of-day\>+  * Time: Support 'Martin Luther Kings Day'+  * Time: Add more holiday aliases (Veteran Day, Mardi Gras, St. Paddy's Day)+  * Time: Intersect "9 tomorrow morning"+  * Time: Support 'Chinese New Years'+  * Time: Support "Saint" Patrick's Day+  * Time: Add Ratha-Yatra Holiday+  * Time: Add support for Ganesh Chaturthi holiday+  * Time: Add rama navami holiday+  * Time: Add '\<part-of-day\> at \<time-of-day\>' rule+  * Time: Modify 'this|last|next \<cycle\>' to capture things like "the month" in "the first Saturday of the month"+  * Time: Support 'the \<day-of-month\> of \<month\>'+  * Time: Add Orthodox Good Friday holiday+  * Time: The (nth) closest (day) to (time)+  * Time: Add rule for 'midday'+  * Time: Fix a problem with parsing fractional minutes+  * Time: parse 'upcoming xxx weeks' and 'xxx upcoming weeks'+  * Time: Add new rule to parse phrase in the pattern 'xxx minutes to \<hour-of-day\>+  * Time: Add support for spelled-out times+  * Time: Add support to parse \<ordinal\> \<day-of-week\>+  * Time: Fix parsing 'next \<day-of-week\>'+  * Time: Treat 'coming' as 'next'+  * Time: Make duckling time not treat 0:xx and 12:xx ambiguously+  * Add 'asap', 'at the moment' to EN time+  * Parse latent year intervals+  * Time: last \<duration\>+  * Time: \<time\> \<day-of-month\>+  * Volume: Extend interval support+  * Time: Handle 2-digit date in existing DD/MM/YYYY rule++* EN_UK (English, United Kingdom)+  * Duration: **new!**+  * Time: **new!**++* EN_US (English, United States)+  * Time: Super Tuesday++* ES (Spanish)+  * AmountOfMoney: Add support for intervals+  * Duration: Add support for parsing phrases like half hour, quarter of an hour+  * Duration: Support composite durations+  * Numeral: Fix typo of 22 (veinto -> venti)+  * Numeral: Add locale rules, since Spain and South America use different decimal separators+  * Numeral: parse 'cero dos' as 'dos'+  * Numeral: composite numerals+  * Ordinal: Add missing 'tercer' regex+  * Quantity: **new!**+  * Time: Add support for periodic holidays+  * Time: Fix `ruleYearLatent` to not match numerals that could be hours+  * Time: Make 'n horas' latent+  * Time: Fixed a problem with parsing 'day of month' that contains 'dia'+  * Time: Add rule for 'next week'+  * Time: \<ordinal\> \<day-of-month\>+  * Time: support for 'noon'+  * Time: Allow para before timestamps+  * Time: Add rule to parse '\<time-of-day\> (in the afternoon)'+  * Time: Add rule to parse 'last \<day-of-week\> of \<time\>'+  * Time: Add rule for next week+  * Time: Add more corpus for tomorrow so that tomorrow latent doesn't prevail+  * Time: Fix multi-word timestamps++* FA (Persian)+  * Numeral: **new!**++* FI (Finnish)+  * Numeral: **new!**++* FR (French)+  * Temperature: Support temperatures with decimal values+  * Time: Update month interval rules to handle ordinals+          and spelled-out numerals (e.g. "du premier au+          quinze juin")+  * Volume: Add 'Centilitre' type++* HE (Hebrew)+  * AmountOfMoney: add more rules++* HI (Hindi)+  * Duration: Pakhwada (पखवाड़ा) is 15 days n, not a fortnight+  * Duration: Add support for composite duration+  * Duration: Add support for specific times+  * Numeral: Support more numerals+  * Temperature: **new!**+  * Time: Add support for quarter till, quarter past, and half++* ID (Indonesian)+  * AmountOfMoney: support intervals++* IS (Icelandic)+  * Numeral: **new!**++* IT (Italian)+  * AmountOfMoney: **new!**+  * Distance: **new!**+  * Duration: Fix ruleDurationAgo++* KA (Georgian)+  * AmountOfMoney: **new!**+  * Duration: **new!**+  * Numeral: **new!**+  * Ordinal: **new!**+  * Time: **new!**+  * Time: Improvements for times in the past+  * Time: Add support for quarters++* KM (Khmer)+  * Distance: **new!**+  * Numeral: **new!**+  * Ordinal: **new!**+  * Quantity: **new!**+  * Temperature: **new!**+  * Volume: **new!**++* KN (Kannada)+  * Numeral: **new!**++* KO (Korean)+  * AmountOfMoney: support intervals++* LO (Lao)+  * Numeral: **new!**++* ML (Malayalam)+  * Numeral: **new!**+  * Ordinal: **new!**++* MN (Mongolian)+  * Numeral: **new!**++* NL (Dutch)+  * AmountOfMoney: make decimal thousands separator optional+  * Duration: Add 'anderhalf uur'+  * Duration: support composite durations+  * Quantity: **new!**+  * Time: Add support for King's Day (Koningsdag)+  * Time: stop 'for \<number\>' from resolving as times+  * Volume: remove gallon+  * Volume: Fix typo in milliliter++* NO (Norwegian)+  * AmountOfMoney: Parse more currencies+  * Numeral: The written numeral 8 had a typo: "otte" -> "åtte"+  * Numeral: Parse powers of ten with spaces as well as dots+  * Numeral: Add more textual powers of ten+  * Numeral: Parse textual numbers from 21 to 99 with _and_ without spaces+  * Time: Add support for half an hour before as e.g. "halv to"+  * Time: Add support for alternative clock denotation "klokka"+  * Time: Add support for alternative tomorrow denotation "i morra"+  * Time: Add some more unambiguous datetime parsing++* PL (Polish)+  * Numeral: Add support for seventy, eighty, ninety+  * Duration: Fix typo: miej -> mniej+  * Time: Add 'evening' to corpus++* PT (Portuguese)+  * Ordinal: Add 13..99+  * Ordinal: Corpus, keep accents consistent+  * Time: Last and quarter expressions++* RO (Romanian)+  * Numeral: Fix multipliers with values above 20+             In Romanian, for numerals above 20, we+             say '20 de milioane', not '20 milioane'.+  * Time: Implement 'the day after tomorrow'++* RU (Russian)+  * AmountOfMoney: Add UAH currency+  * Numeral: Be more permissive with numerals [20, 90]+  * Time: **new!**++* SK (Slovak)+  * Numeral: **new!**++* SW (Swahili)+  * Numeral: **new!**++* TA (Tamil)+  * Ordinal: **new!**++* TE (Telugu)+  * Numeral: **new!**++* TH (Thai)+  * Numeral: **new!**++* TR (Turkish)+  * AmountOfMoney: **new!**+  * Time: **new!**++* VI (Vietnamese)+  * AmountOfMoney: Add interval support+  * AmountOfMoney: ruleNg, ruleDollar, ruleVND modified to better capture usage of VI+  * Numeral: Add "ngàn" common synonym of "nghìn", and "chục",+             colloquially used to count tens.+  * Numeral: Remove ? in some regex where they don't make sense+  * Time: Fix double-digit month matching+  * Time: don't parse ngày++* ZH (Chinese)+  * Duration: Add more common expressions+  * Numeral: Add more common expressions+  * Time: Parse YYYY-MM+  * Time: Value before month can be integer or chinese char+  * Time: Add support for (pre-)computed holidays+  * Time: Add more common expressions+  * Volume: **new!**++### Server+  * Skip logfile creation if no logging+  * Document how example application can use specific dimensions only+  * Use System.FilePath.Posix instead of System.FilePath+  * Use all dimensions by default+  * Load timezones more leniently+  * Docker: Reduce size of image drastically+  * Dockerfile: Use Debian Buster++## 0.1.6.1++### Core++* Warn against incomplete pattern matching in GHC options+* Updated readme for custom dimensions+* Coding style documentation++### Rulesets++* Common+  * AmountOfMoney: change `financeWith` to `isAmountOfMoney` where applicable+  * Temperature: implement temperature intervals++* EN+  * AmountOfMoney: support "grand"+  * Time: Absorb "since" before month/year+  * Time: Fix before/after/until/since + <year>+  * Time: Make partial meridies latent+  * Time: Global Youth Service Day+  * Time: Vesak+  * Time: Earth Hour+  * Time: Regex update for Rosh Hashanah and Chanukkah+  * Time: add <time> for <duration> rules+  * Distance: Millimeter units and UK spellings+  * Duration: Handle half time grains++* EN_US+  * Time: Fix Emancipation Day+  * Time: Tax Day+  * Time: Siblings Day+  * Time: EMS Week and EMSC Day++* EN_AU+  * Time: Ekka++* EN_XX+  * Time: Administrative Professionals' Day+  * Time: Parse 'second last week of October 2018'+  * Time: AD/BC parsing for years++* AR+  * Numeral: Fix dual big numbers+  * Numeral: Fix million++* DA_XX+  * Time: Remove 'man'++* DE+  * Time: Remove am/pm rule++* HI+  * Duration: **new!**+  * TimeGrain: **new!**++* NL+  * Time: Fix Sinterklaas for Belgium++* RO+  * AmountOfMoney: Fix for values above 20+  * AmountOfMoney: Support intervals+  * Distance: Fix for values above 20+  * Duration: Fix for values above 20+  * Quantity: Fix for values above 20+  * Temperature: Fix for values above 20+  * Volume: Fix for values above 20++* ZH+  * Quantity: **new!**+  * Time: Support Periodic Holidays++## 0.1.6.0++### Core++The `value` field of `Entity` is now typed! Use `toJText` to get the JSON-encoded string back.++## 0.1.5.0++### Testing+* Prompt ambiguous parses in corpus tests++### Rulesets++* Common+  * Add an option to return latent time entities.+  * AmountOfMoney: Distribute ruleUnitAmount to all languages+  * Time: Make all years latent+  * Lambda-case for Rule production+  * Numeral: fix intersect rule to work with negative numbers+  * Support custom dimensions++* BG_XX:+  * Distance: **new!**+  * TimeGrain: **new!**+  * Duration: **new!**+  * Ordinal: **new!**++* EN_XX+  * Time: periodic holidays+  * Time: handle Easter+  * Time: parse "DD MM YYYY", "MM DD YYYY"  as date instead of only phone fix+  * Time: added rules for the beginning / end of year / month / week+  * Time: "late tonight"+  * Time: "last night" and "late last night"+  * Time: fixes in holidays+  * Time: Return Holiday Name in response+  * Duration: composite+  * Time: support for this|last|next season+  * Time: added Easter-based holidays+  * Time: precomputed Orthodox Easter dates+  * Time: added Orthodox Easter-based holidays+  * Time: fix Labour Day, add Heroes' Day and National Patriots' Day+  * Time: Chinese New Year+  * Time: added Boss's Day+  * Time: fix computed past series and Jewish holidays+  * Time: added rules to cover EOY, EOM, BOY, BOM+  * Time: rule <Day of month> of month+  * Time: Islamic holidays+  * Time: fix "in" + year+  * Time: Added precomputed Jewish holiday "Tu BiShvat"+  * Time: time + n years ago/in n years+  * Time: make "may" latent+  * Duration: move composite duration rule to English+  * Time: add Diwali, Navaratri, Vasant Panchami, Holika Dahan, Holi and other Hindu holidays++* EN_AU+  * Time: add Reconciliation Day++* EN_CA+  * Time: add Discovery day+  * Time: Add "Groundhogs day" in regex for "Groundhog Day"++* EN_GB+  * Time: fixed mother's day++* EN_US+  * Time: Washington's birthday, President day and Lincoln's birthday+  * Time: Add "Groundhogs day" in regex for "Groundhog Day"++* ES_XX+  * Time: use `mkRuleSeasons`++* DE_XX+  * Time: return Holiday Name in response++* NL_XX+  * Time: return Holiday Name in response+  * AmountOfMoney: **new!**++* PL_XX+  * Time: month regex fix++* RU_XX+  * Ordinal: refactor pattern match to hashmap lookup++* SV_XX+  * Distance: **new!**+  * Distance: fix mil++* TA_XX+  * Numerals: **new!**++* VI_XX+  * AmountOfMoney: Use comma "," as decimal separator++* ZH_XX+  * Distance: **new!**+  * Time: remove unused `ruleLastTuesdayLastJuly`+  * Numeral/Distance/Time: generalize and expand digit specifier usage+  * AmountOfMoney: **new!**++## 0.1.4.0++### Core+* Bumped to LTS 9.10+* API: Added `Node` to `Entity` to return the parse tree++### Rulesets+* Common+  * AmountOfMoney: don't recursively compare cents+  * AmountOfMoney: don't allow decreasing intervals+  * Duration: added `type` in response+  * Numeral: common rule to parse numbers+  * Numeral: common rule to parse fractions+  * Numeral: don't compose negative numbers+  * Time: fixed empty values for past datetimes+  * Time: fixed case sensitivity for timezones+  * Url: fragments support+* AR_XX+  * AmountOfMoney: **new!**+  * Duration: **new!**+  * Ordinal: more rules+  * Quantity: **new!**+  * Temperature: **new!**+  * Time: **new!**+  * Volume: **new!**+* DE_XX+  * Numeral: fixed keiner+  * Time: fixed this/next/last for holidays/months/days of week/seasons/weekend only+* EL_XX+  * Duration: **new!**+  * Numeral: **new!**+  * Ordinal: **new!**+  * Time: **new!**+* EN_GB+  * Time: fix parsing Oct-Dec months+* EN_XX+  * AmountOfMoney: intervals support+  * Distance: intervals support+  * Email: spelled out 'dot'+  * Numeral: prevent double negatives+  * Numeral: skip hundred for alphabetical numbers only+  * Quantity: intervals support+  * Time: don't parse "at" + phone number+  * Time: fixed date format in non-US locales+  * Time: fixed Thanksgiving in locales+  * Time: don't parse "this in 2 minutes"+  * Time: spelled out times + AM/PM+  * Time: fixed case sensitivity+  * Time: fixed "from" + time of day+  * Time: support MM.DD.YYYY+* FR_XX+  * Numeral: space as thousand separator+* GA_XX+  * Numeral: fix old vigesimal+* HI_XX+  * Numeral: **new!**+  * Ordinal: **new!**+* JA_XX+  * Time: removed dimension, as it is not implemented yet+* NE_XX+  * Numeral: **new!**+* NL_XX+  * Time: **new!**+  * Time: don't be too eager on days of week+  * Time: today/tomorrow/yesterday evening/afternoon/morning+  * Time: fixed this/next/last for holidays/months/days of week/seasons/weekend only+* PT_XX+  * Numeral: fixed rules+* RU_XX+  * AmountOfMoney: **new!**+  * Distance: **new!**+  * Duration:: **new!**+  * Numeral: 1.5 rule, more 0 rules, fixed 11, 300 and 400+  * Ordinal: fixes+  * Quantity: **new!**+  * Volume: **new!**+* SV_XX+  * Duration: extend support for "about" + duration++### Server+* Fixed Dockerfile+* Added reference time parameter++## 0.1.3.0++### Core+* Support locales+* Don't allow matches in the middle of words++### Rulesets+* Common+  * All: converted back all escaped characters to unicode+  * Time: don't shift duration on "`Duration` before/after `Time`"+  * Time: don't parse subsequent numbers+  * Time: fix `nthDOWOfMonth`+  * Time: reuse the `weekend` helper in all languages+* BG_XX+  * AmountOfMoney: **new!**+  * Numeral: **new!**+* DA_XX+  * Time: Consolidated rules for months and days of week+* DE_XX+  * Time: don't parse "nächste 5"+  * Time: Consolidated rules for months and days of week+  * Time: Consolidated rules for holidays, instants and seasons+* EN_CA+  * Time: Fixed Thanksgiving Day+* EN_GB+  * Time: Fixed DDMM and YYYYDDMM+* EN_XX+  * Time: "for `Duration` from `Time`"+  * Time: "from 10 to 16 August"+  * Time: "August 27th-30th"+  * Time: "23rd to 26th Oct", "1-8 september"+  * Time: Support misspelled "tonights" and "weekends"+  * Quantity: Support ounces+  * Email: restrict domain extensions to letters when spelling out+* ES_XX+  * Time: Consolidated rules for months and days of week+  * Ordinal: Fixed "first" variants + accents+* FR_XX+  * Time: don't parse "a un"+  * Time: Consolidated rules for months and days of week+* GA_XX+  * Time: Consolidated rules for months and days of week+* HE_XX+  * Time: Consolidated rules for months+* HR_XX+  * Time: Consolidated rules for months and days of week+* HU_XX+  * Duration: **new!**+  * Numeral: **new!**+  * Ordinal: **new!**+  * Time: **new!**+* IT_XX+  * Time: Consolidated rules for months and days of week+* JA_XX+  *Numeral: Optimized regex lookup+* KA_XX+  * Numeral: **new!**+* NB_XX+  * Time: Consolidated rules for months and days of week+* NL_XX+  * Duration: **new!**+* PL_XX+  * Time: don't parse "nie"+  * Time: don't parse ordinals without context+  * Time: Consolidated rules for months and days of week+* PT_XX+  * Time: don't parse "um" alone+  * Time: don't parse "ter"+* RO_XX+  * Time: Consolidated rules for months and days of week+  * Time: don't parse "sa"+* SV_XX+  * Ordinal: Fixed ordinals+  * Time: "i + day-of-week"+  * Time: Consolidated rules for months and days of week+* VI_XX+  * Time: Consolidated rules for months and days of week+* ZH_TW+  * Time: Fixed National Day+* ZH_XX+  * Time: Consolidated rules for months and days of week++## 0.1.2.0++### Core++* `weekend` production helper+* Numeral flag for Time patterns++### Rulesets++* FR+  * Time+    * `début|milieu|fin de matinée` (`early|mid|late morning`)+    * `début|milieu|fin de après-midi` (`early|mid|late afternoon`)+    * `début|milieu|fin de journée` (`early|mid|late day`)+    * `début|fin de soirée` (`early|late evening`)+    * `début|fin de mois` (`early|late month`)+    * `début|fin d'année` (`early|late year`)+    * `plus tard` (`later`)+    * `plus tard que ...` (`later than ...`)+    * `plus tard <time>` (`later than <time>`)+    * `plus tard <part-of-day>` (`later than <part-of-day>`)+* EN+  * Time+    * Support dates of type mm-dd+    * Fix issue #50 "last weekend of october"+    * Added a rule to handle "from <month> dd-dd"+    * Add MM/YYYY+* DE+  * Time+    * Make last dot optional in "13.03."+    * Handle variations of "13.-15.10." correctly+    * Treat "14/15Uhr" the same as "14-15Uhr"+    * Extended "bis" to also match "bis zum" and "auf den"+    * Changed `hh:mm` matching to also get the expression "17h00"+* PT+  * Numeral+    * Numerals between 100 and 999 in Portuguese fixed+* GA+  * Ordinal+    * Also match old-style -adh ending++## 0.1.1.0++### Core+* More optimizations for `Time` internals.+* `Entity` value is now a `Value` (was a JSON-encoded `Text`).++### Rulesets+* Common+  * AmountOfMoney: MYR currency+  * Duration: Helper for "<numeral>.<numeral> hours"+* CS+  * Distance: **new!**+  * Numeral: **new!**+* DE+  * Ordinal: Don't parse "1.1."+  * Time: Small improvements+* EN+  * AmountOfMoney+    * Support pence as cents+    * Support Malaysian ringgits+  * Distance: Abbreviations for inches, miles+  * Numeral: Fractions+  * Quantity: Generic product+  * Time+    * Allow spaces in e.g. "2 / 15"+    * Afternoonish+    * Early/mid/late month+* ID+  * Numeral: Optimization for regex matching+* KO+  * Time: Fixed typo in the day after tomorrow+* SV+  * Time: vid+* TR+  * Distance: **new!**+  * Duration: **new!**+  * Numeral: Comma as decimal mark+  * Temperature: **new!**+  * Volume: **new!**+* ZH+  * Time: Cantonese support++### Server+* Added dockerfile+* Fixed warnings around logs++## 0.1.0.0++* Initial version. Released on an unsuspecting world.
Duckling/AmountOfMoney/AR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -87,6 +86,8 @@              [ "42 EGP"              , "42 جنيه مصري"              , "42 جنيهات مصريه"+             , "42 ج.م"+             , "42 ج.م."              ]   , examples (simple QAR 42)              [ "42 QAR"
Duckling/AmountOfMoney/AR/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -52,6 +51,15 @@   , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound   } +ruleEgpAbrreviation :: Rule+ruleEgpAbrreviation = Rule+  { name = "EGP abbreviation"+  , pattern =+    [ regex "ج[.]م[.]?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly EGP+  }+ ruleDinars :: Rule ruleDinars = Rule   { name = "dinars"@@ -391,6 +399,7 @@   [ ruleUnitAmount   , ruleCent   , rulePounds+  , ruleEgpAbrreviation   , ruleDinars   , ruleDirhams   , ruleRiyals
Duckling/AmountOfMoney/BG/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} 
Duckling/AmountOfMoney/BG/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/AmountOfMoney/EN/AU/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} @@ -27,6 +26,26 @@              ]   , examples (simple AUD 10000)              [ "10 grand"+             , "two hundred thousand nickels"+             ]+  , examples (simple AUD 1)+             [ "four quarters"+             , "ten dimes"+             , "twenty nickels"+             ]+  , examples (simple AUD 0.1)+             [ "dime"+             , "a dime"+             , "two nickels"+             ]+  , examples (simple AUD 0.25)+             [ "quarter"+             , "a quarter"+             , "five nickels"+             ]+  , examples (simple AUD 0.05)+             [ "nickel"+             , "a nickel"              ]   ] 
Duckling/AmountOfMoney/EN/AU/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}@@ -13,17 +12,22 @@   ( rules   ) where +import Data.HashMap.Strict (HashMap) import Data.String+import Data.Text (Text) import Prelude  import Duckling.AmountOfMoney.Helpers import Duckling.AmountOfMoney.Types (Currency(..)) import Duckling.Numeral.Helpers (isPositive)+import Duckling.Regex.Types import Duckling.Types +import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text+import qualified Duckling.AmountOfMoney.Helpers as Helpers import qualified Duckling.Numeral.Types as TNumeral - ruleAGrand :: Rule ruleAGrand = Rule   { name = "a grand"@@ -46,8 +50,22 @@       _ -> Nothing   } +ruleDollarCoin :: Rule+ruleDollarCoin = Rule+  { name = "dollar coin"+  , pattern =+    [ regex "(nickel|dime|quarter)s?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        c <- HashMap.lookup (Text.toLower match) Helpers.dollarCoins+        Just . Token AmountOfMoney . withValue c $ currencyOnly AUD+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleAGrand   , ruleGrand+  , ruleDollarCoin   ]
Duckling/AmountOfMoney/EN/BZ/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} @@ -27,6 +26,26 @@              ]   , examples (simple Dollar 10000)              [ "10 grand"+             , "two hundred thousand nickels"+             ]+  , examples (simple Dollar 1)+             [ "four quarters"+             , "ten dimes"+             , "twenty nickels"+             ]+  , examples (simple Dollar 0.1)+             [ "dime"+             , "a dime"+             , "two nickels"+             ]+  , examples (simple Dollar 0.25)+             [ "quarter"+             , "a quarter"+             , "five nickels"+             ]+  , examples (simple Dollar 0.05)+             [ "nickel"+             , "a nickel"              ]   ] 
Duckling/AmountOfMoney/EN/BZ/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}@@ -13,17 +12,22 @@   ( rules   ) where +import Data.HashMap.Strict (HashMap) import Data.String+import Data.Text (Text) import Prelude  import Duckling.AmountOfMoney.Helpers import Duckling.AmountOfMoney.Types (Currency(..)) import Duckling.Numeral.Helpers (isPositive)+import Duckling.Regex.Types import Duckling.Types +import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text+import qualified Duckling.AmountOfMoney.Helpers as Helpers import qualified Duckling.Numeral.Types as TNumeral - ruleAGrand :: Rule ruleAGrand = Rule   { name = "a grand"@@ -48,8 +52,22 @@       _ -> Nothing   } +ruleDollarCoin :: Rule+ruleDollarCoin = Rule+  { name = "dollar coin"+  , pattern =+    [ regex "(nickel|dime|quarter)s?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        c <- HashMap.lookup (Text.toLower match) Helpers.dollarCoins+        Just . Token AmountOfMoney . withValue c $ currencyOnly Dollar+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleAGrand   , ruleGrand+  , ruleDollarCoin   ]
Duckling/AmountOfMoney/EN/CA/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} @@ -27,6 +26,26 @@              ]   , examples (simple CAD 10000)              [ "10 grand"+             , "two hundred thousand nickels"+             ]+  , examples (simple CAD 1)+             [ "four quarters"+             , "ten dimes"+             , "twenty nickels"+             ]+  , examples (simple CAD 0.1)+             [ "dime"+             , "a dime"+             , "two nickels"+             ]+  , examples (simple CAD 0.25)+             [ "quarter"+             , "a quarter"+             , "five nickels"+             ]+  , examples (simple CAD 0.05)+             [ "nickel"+             , "a nickel"              ]   ] 
Duckling/AmountOfMoney/EN/CA/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}@@ -13,17 +12,22 @@   ( rules   ) where +import Data.HashMap.Strict (HashMap) import Data.String+import Data.Text (Text) import Prelude  import Duckling.AmountOfMoney.Helpers import Duckling.AmountOfMoney.Types (Currency(..)) import Duckling.Numeral.Helpers (isPositive)+import Duckling.Regex.Types import Duckling.Types +import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text+import qualified Duckling.AmountOfMoney.Helpers as Helpers import qualified Duckling.Numeral.Types as TNumeral - ruleAGrand :: Rule ruleAGrand = Rule   { name = "a grand"@@ -46,8 +50,22 @@       _ -> Nothing   } +ruleDollarCoin :: Rule+ruleDollarCoin = Rule+  { name = "dollar coin"+  , pattern =+    [ regex "(nickel|dime|quarter)s?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        c <- HashMap.lookup (Text.toLower match) Helpers.dollarCoins+        Just . Token AmountOfMoney . withValue c $ currencyOnly CAD+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleAGrand   , ruleGrand+  , ruleDollarCoin   ]
Duckling/AmountOfMoney/EN/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -11,12 +10,14 @@ module Duckling.AmountOfMoney.EN.Corpus   ( corpus   , negativeCorpus+  , latentCorpus   ) where  import Data.String import Prelude  import Duckling.AmountOfMoney.Types+import Duckling.Resolve (Options(..)) import Duckling.Testing.Types  negativeCorpus :: NegativeCorpus@@ -29,6 +30,21 @@ corpus :: Corpus corpus = (testContext, testOptions, allExamples) +latentCorpus :: Corpus+latentCorpus = (testContext, testOptions {withLatent = True}, xs)+  where+    xs = concat+      [ examples (simple Unnamed 5)+                 [ "five"+                 , "5"+                 , "about 5"+                 ]+      , examples (simple Unnamed 7.2)+                 [ "7.2"+                 , "7.20000"+                 ]+      ]+ allExamples :: [Example] allExamples = concat   [ examples (simple Dollar 1)@@ -59,6 +75,7 @@              [ "USD3.14"              , "3.14US$"              , "US$ 3.14"+             , "US$3 and fourteen"              ]   , examples (simple EUR 20)              [ "20\x20ac"@@ -98,7 +115,24 @@              [ "GBP3.01"              , "GBP 3.01"              , "3 GBP 1 pence"+             , "3 GBP and one"              ]+  , examples (simple CAD 3.03)+             [ "CAD3.03"+             , "CAD 3.03"+             , "3 CAD 3 cents"+             ]+  , examples (simple CHF 3.04)+             [ "CHF3.04"+             , "CHF 3.04"+             , "3 CHF 4 cents"+             ]+  , examples (simple CNY 3)+             [ "CNY3"+             , "CNY 3"+             , "3 CNY"+             , "3 yuan"+             ]   , examples (simple Unnamed 42)              [ "42 bucks"              , "around 42 bucks"@@ -115,6 +149,12 @@   , examples (simple EGP 42)              [ "42 EGP"              , "42 egyptianpound"+             , "42 LE"+             , "42 L.E"+             , "42 l.e."+             , "42 le"+             , "42 geneh"+             , "42 genihat masriya"              ]   , examples (simple QAR 42)              [ "42 QAR"@@ -186,11 +226,40 @@              [ "under seven euros"              , "less than 7 EUR"              , "lower than 7€"+             , "no more than 7 euros"+             , "at most 7€"              ]   , examples (above Dollar 1.42)              [ "more than 1 dollar and forty-two cents"              , "at least $1.42"              , "over 1.42 dollars"              , "above a dollar and 42 cents"+             , "no less than $1.42"+             ]+   , examples (simple INR 5e5)+             [ "5 lakh rupees"+             , "five lakhs rupees"+             ]+   , examples (between INR (7, 9e5))+             [ "7-9 lakh rupees"+             ]+   , examples (simple INR 4e7)+             [ "four crore rupees"+             , "4 crores rupees"+             ]+   , examples (simple MNT 10)+             [ "ten tugriks"+             , "10 Tugrik"+             , "10MNT"+             ]+   , examples (simple USD 4.7e9)+             [ "US$4.7 billion"+             , "a US$4.7 billion"+             , "a US$ 4.7 billion"+             ]+  , examples (simple UAH 3.04)+             [ "UAH3.04"+             , "UAH 3.04"+             , "3 UAH 4 kopiykas"              ]   ]
Duckling/AmountOfMoney/EN/GB/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} @@ -27,6 +26,25 @@              ]   , examples (simple GBP 10000)              [ "10 grand"+             ]+  , examples (simple Dollar 1)+             [ "four quarters"+             , "ten dimes"+             , "twenty nickels"+             ]+  , examples (simple Dollar 0.1)+             [ "dime"+             , "a dime"+             , "two nickels"+             ]+  , examples (simple Dollar 0.25)+             [ "quarter"+             , "a quarter"+             , "five nickels"+             ]+  , examples (simple Dollar 0.05)+             [ "nickel"+             , "a nickel"              ]   ] 
Duckling/AmountOfMoney/EN/GB/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}@@ -13,17 +12,22 @@   ( rules   ) where +import Data.HashMap.Strict (HashMap) import Data.String+import Data.Text (Text) import Prelude  import Duckling.AmountOfMoney.Helpers import Duckling.AmountOfMoney.Types (Currency(..)) import Duckling.Numeral.Helpers (isPositive)+import Duckling.Regex.Types import Duckling.Types +import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text+import qualified Duckling.AmountOfMoney.Helpers as Helpers import qualified Duckling.Numeral.Types as TNumeral - ruleAGrand :: Rule ruleAGrand = Rule   { name = "a grand"@@ -46,8 +50,22 @@       _ -> Nothing   } +ruleDollarCoin :: Rule+ruleDollarCoin = Rule+  { name = "dollar coin"+  , pattern =+    [ regex "(nickel|dime|quarter)s?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        c <- HashMap.lookup (Text.toLower match) Helpers.dollarCoins+        Just . Token AmountOfMoney . withValue c $ currencyOnly Dollar+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleAGrand   , ruleGrand+  , ruleDollarCoin   ]
Duckling/AmountOfMoney/EN/IE/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} @@ -27,6 +26,26 @@              ]   , examples (simple Dollar 10000)              [ "10 grand"+             , "two hundred thousand nickels"+             ]+  , examples (simple Dollar 1)+             [ "four quarters"+             , "ten dimes"+             , "twenty nickels"+             ]+  , examples (simple Dollar 0.1)+             [ "dime"+             , "a dime"+             , "two nickels"+             ]+  , examples (simple Dollar 0.25)+             [ "quarter"+             , "a quarter"+             , "five nickels"+             ]+  , examples (simple Dollar 0.05)+             [ "nickel"+             , "a nickel"              ]   ] 
Duckling/AmountOfMoney/EN/IE/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}@@ -13,14 +12,20 @@   ( rules   ) where +import Data.HashMap.Strict (HashMap) import Data.String+import Data.Text (Text) import Prelude  import Duckling.AmountOfMoney.Helpers import Duckling.AmountOfMoney.Types (Currency(..)) import Duckling.Numeral.Helpers (isPositive)+import Duckling.Regex.Types import Duckling.Types +import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text+import qualified Duckling.AmountOfMoney.Helpers as Helpers import qualified Duckling.Numeral.Types as TNumeral  @@ -48,8 +53,22 @@       _ -> Nothing   } +ruleDollarCoin :: Rule+ruleDollarCoin = Rule+  { name = "dollar coin"+  , pattern =+    [ regex "(nickel|dime|quarter)s?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        c <- HashMap.lookup (Text.toLower match) Helpers.dollarCoins+        Just . Token AmountOfMoney . withValue c $ currencyOnly Dollar+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleAGrand   , ruleGrand+  , ruleDollarCoin   ]
Duckling/AmountOfMoney/EN/IN/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} @@ -27,6 +26,26 @@              ]   , examples (simple Dollar 10000)              [ "10 grand"+             , "two hundred thousand nickels"+             ]+  , examples (simple Dollar 1)+             [ "four quarters"+             , "ten dimes"+             , "twenty nickels"+             ]+  , examples (simple Dollar 0.1)+             [ "dime"+             , "a dime"+             , "two nickels"+             ]+  , examples (simple Dollar 0.25)+             [ "quarter"+             , "a quarter"+             , "five nickels"+             ]+  , examples (simple Dollar 0.05)+             [ "nickel"+             , "a nickel"              ]   ] 
Duckling/AmountOfMoney/EN/IN/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}@@ -13,17 +12,22 @@   ( rules   ) where +import Data.HashMap.Strict (HashMap) import Data.String+import Data.Text (Text) import Prelude  import Duckling.AmountOfMoney.Helpers import Duckling.AmountOfMoney.Types (Currency(..)) import Duckling.Numeral.Helpers (isPositive)+import Duckling.Regex.Types import Duckling.Types +import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text+import qualified Duckling.AmountOfMoney.Helpers as Helpers import qualified Duckling.Numeral.Types as TNumeral - ruleAGrand :: Rule ruleAGrand = Rule   { name = "a grand"@@ -46,8 +50,22 @@       _ -> Nothing   } +ruleDollarCoin :: Rule+ruleDollarCoin = Rule+  { name = "dollar coin"+  , pattern =+    [ regex "(nickel|dime|quarter)s?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        c <- HashMap.lookup (Text.toLower match) Helpers.dollarCoins+        Just . Token AmountOfMoney . withValue c $ currencyOnly Dollar+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleAGrand   , ruleGrand+  , ruleDollarCoin   ]
Duckling/AmountOfMoney/EN/JM/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} @@ -27,9 +26,28 @@              ]   , examples (simple JMD 10000)              [ "10 grand"+             , "two hundred thousand nickels"              ]+  , examples (simple JMD 1)+             [ "four quarters"+             , "ten dimes"+             , "twenty nickels"+             ]+  , examples (simple JMD 0.1)+             [ "dime"+             , "a dime"+             , "two nickels"+             ]+  , examples (simple JMD 0.25)+             [ "quarter"+             , "a quarter"+             , "five nickels"+             ]+  , examples (simple JMD 0.05)+             [ "nickel"+             , "a nickel"+             ]   ]- negativeExamples :: [Text] negativeExamples =   [ "grand"
Duckling/AmountOfMoney/EN/JM/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}@@ -13,17 +12,22 @@   ( rules   ) where +import Data.HashMap.Strict (HashMap) import Data.String+import Data.Text (Text) import Prelude  import Duckling.AmountOfMoney.Helpers import Duckling.AmountOfMoney.Types (Currency(..)) import Duckling.Numeral.Helpers (isPositive)+import Duckling.Regex.Types import Duckling.Types +import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text+import qualified Duckling.AmountOfMoney.Helpers as Helpers import qualified Duckling.Numeral.Types as TNumeral - ruleAGrand :: Rule ruleAGrand = Rule   { name = "a grand"@@ -48,8 +52,22 @@       _ -> Nothing   } +ruleDollarCoin :: Rule+ruleDollarCoin = Rule+  { name = "dollar coin"+  , pattern =+    [ regex "(nickel|dime|quarter)s?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        c <- HashMap.lookup (Text.toLower match) Helpers.dollarCoins+        Just . Token AmountOfMoney . withValue c $ currencyOnly JMD+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleAGrand   , ruleGrand+  , ruleDollarCoin   ]
Duckling/AmountOfMoney/EN/NZ/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} @@ -27,6 +26,26 @@              ]   , examples (simple NZD 10000)              [ "10 grand"+             , "two hundred thousand nickels"+             ]+  , examples (simple NZD 1)+             [ "four quarters"+             , "ten dimes"+             , "twenty nickels"+             ]+  , examples (simple NZD 0.1)+             [ "dime"+             , "a dime"+             , "two nickels"+             ]+  , examples (simple NZD 0.25)+             [ "quarter"+             , "a quarter"+             , "five nickels"+             ]+  , examples (simple NZD 0.05)+             [ "nickel"+             , "a nickel"              ]   ] 
Duckling/AmountOfMoney/EN/NZ/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}@@ -13,17 +12,22 @@   ( rules   ) where +import Data.HashMap.Strict (HashMap) import Data.String+import Data.Text (Text) import Prelude  import Duckling.AmountOfMoney.Helpers import Duckling.AmountOfMoney.Types (Currency(..)) import Duckling.Numeral.Helpers (isPositive)+import Duckling.Regex.Types import Duckling.Types +import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text+import qualified Duckling.AmountOfMoney.Helpers as Helpers import qualified Duckling.Numeral.Types as TNumeral - ruleAGrand :: Rule ruleAGrand = Rule   { name = "a grand"@@ -48,8 +52,22 @@       _ -> Nothing   } +ruleDollarCoin :: Rule+ruleDollarCoin = Rule+  { name = "dollar coin"+  , pattern =+    [ regex "(nickel|dime|quarter)s?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        c <- HashMap.lookup (Text.toLower match) Helpers.dollarCoins+        Just . Token AmountOfMoney . withValue c $ currencyOnly NZD+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleAGrand   , ruleGrand+  , ruleDollarCoin   ]
Duckling/AmountOfMoney/EN/PH/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} @@ -27,6 +26,26 @@              ]   , examples (simple Dollar 10000)              [ "10 grand"+             , "two hundred thousand nickels"+             ]+  , examples (simple Dollar 1)+             [ "four quarters"+             , "ten dimes"+             , "twenty nickels"+             ]+  , examples (simple Dollar 0.1)+             [ "dime"+             , "a dime"+             , "two nickels"+             ]+  , examples (simple Dollar 0.25)+             [ "quarter"+             , "a quarter"+             , "five nickels"+             ]+  , examples (simple Dollar 0.05)+             [ "nickel"+             , "a nickel"              ]   ] 
Duckling/AmountOfMoney/EN/PH/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}@@ -13,17 +12,22 @@   ( rules   ) where +import Data.HashMap.Strict (HashMap) import Data.String+import Data.Text (Text) import Prelude  import Duckling.AmountOfMoney.Helpers import Duckling.AmountOfMoney.Types (Currency(..)) import Duckling.Numeral.Helpers (isPositive)+import Duckling.Regex.Types import Duckling.Types +import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text+import qualified Duckling.AmountOfMoney.Helpers as Helpers import qualified Duckling.Numeral.Types as TNumeral - ruleAGrand :: Rule ruleAGrand = Rule   { name = "a grand"@@ -48,8 +52,22 @@       _ -> Nothing   } +ruleDollarCoin :: Rule+ruleDollarCoin = Rule+  { name = "dollar coin"+  , pattern =+    [ regex "(nickel|dime|quarter)s?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        c <- HashMap.lookup (Text.toLower match) dollarCoins+        Just . Token AmountOfMoney . withValue c $ Helpers.currencyOnly Dollar+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleAGrand   , ruleGrand+  , ruleDollarCoin   ]
Duckling/AmountOfMoney/EN/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -66,6 +65,24 @@       _ -> Nothing   } +ruleEgpAbrreviation :: Rule+ruleEgpAbrreviation = Rule+  { name = "livre égyptienne"+  , pattern =+    [ regex "[lL].?[eE].?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly EGP+  }++ruleEgpArabizi :: Rule+ruleEgpArabizi = Rule+  { name = "geneh"+  , pattern =+    [ regex "[Gg][eiy]*n[eiy]*h(at)?( m[aiey]?sr[eiy]+a?)?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly EGP+  }+ ruleRiyals :: Rule ruleRiyals = Rule   { name = "riyals"@@ -111,6 +128,15 @@   , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly MYR   } +ruleHryvnia :: Rule+ruleHryvnia = Rule+  { name = "hryvnia"+  , pattern =+      [ regex "hryvnia" -- TODO: complete+      ]+  , prod = \_ -> Just $ Token AmountOfMoney $ currencyOnly UAH+  }+ ruleCent :: Rule ruleCent = Rule   { name = "cent"@@ -120,6 +146,15 @@   , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent   } +ruleKopiyka :: Rule+ruleKopiyka = Rule+  { name = "kopiyka"+  , pattern =+    [ regex "kopiy(ok|kas?)"+    ]+  , prod = \_ -> Just $ Token AmountOfMoney $ currencyOnly Cent+  }+ ruleBucks :: Rule ruleBucks = Rule   { name = "bucks"@@ -143,6 +178,47 @@       _ -> Nothing   } +ruleAbsorbA :: Rule+ruleAbsorbA = Rule+  { name = "a <amount-of-money>"+  , pattern =+    [ regex "an?"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (_:Token AmountOfMoney fd:_) -> Just $ Token AmountOfMoney fd+      _ -> Nothing+  }++ruleADollarCoin :: Rule+ruleADollarCoin = Rule+  { name = "a <dollar coin>"+  , pattern =+    [ regex "an?"+    , Predicate isDollarCoin+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token AmountOfMoney fd:+       _) -> Just . Token AmountOfMoney $ fd+      _ -> Nothing+  }++ruleNumDollarCoins :: Rule+ruleNumDollarCoins = Rule+  { name = "X <dollar coins>"+  , pattern =+    [ Predicate isNatural+    , Predicate isDollarCoin+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = c}:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just d,+                                             TAmountOfMoney.currency = cur}:+       _) -> Just . Token AmountOfMoney $ withValue (c * d) $ currencyOnly cur+      _ -> Nothing+  }+ ruleIntersectAndXCents :: Rule ruleIntersectAndXCents = Rule   { name = "intersect (and X cents)"@@ -297,7 +373,7 @@ ruleIntervalMax = Rule   { name = "under/less/lower/no more than <amount-of-money>"   , pattern =-    [ regex "under|(less|lower|not? more) than"+    [ regex "under|at most|(less|lower|not? more) than"     , Predicate isSimpleAmountOfMoney     ]   , prod = \tokens -> case tokens of@@ -312,7 +388,7 @@ ruleIntervalMin = Rule   { name = "over/above/at least/more than <amount-of-money>"   , pattern =-    [ regex "over|above|at least|more than"+    [ regex "over|above|at least|(more|not? less) than"     , Predicate isSimpleAmountOfMoney     ]   , prod = \tokens -> case tokens of@@ -327,10 +403,14 @@ rules =   [ ruleUnitAmount   , ruleACurrency+  , ruleAbsorbA   , ruleBucks   , ruleCent+  , ruleADollarCoin+  , ruleNumDollarCoins   , ruleDinars   , ruleDirham+  , ruleHryvnia   , ruleIntersect   , ruleIntersectAndNumeral   , ruleIntersectAndXCents@@ -341,7 +421,10 @@   , ruleIntervalMin   , ruleIntervalNumeralDash   , ruleIntervalDash+  , ruleKopiyka   , ruleOtherPounds+  , ruleEgpAbrreviation+  , ruleEgpArabizi   , rulePounds   , rulePrecision   , ruleRinggit
Duckling/AmountOfMoney/EN/TT/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} @@ -27,6 +26,26 @@              ]   , examples (simple TTD 10000)              [ "10 grand"+             , "two hundred thousand nickels"+             ]+  , examples (simple TTD 1)+             [ "four quarters"+             , "ten dimes"+             , "twenty nickels"+             ]+  , examples (simple TTD 0.1)+             [ "dime"+             , "a dime"+             , "two nickels"+             ]+  , examples (simple TTD 0.25)+             [ "quarter"+             , "a quarter"+             , "five nickels"+             ]+  , examples (simple TTD 0.05)+             [ "nickel"+             , "a nickel"              ]   ] 
Duckling/AmountOfMoney/EN/TT/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}@@ -13,17 +12,22 @@   ( rules   ) where +import Data.HashMap.Strict (HashMap) import Data.String+import Data.Text (Text) import Prelude  import Duckling.AmountOfMoney.Helpers import Duckling.AmountOfMoney.Types (Currency(..)) import Duckling.Numeral.Helpers (isPositive)+import Duckling.Regex.Types import Duckling.Types +import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text+import qualified Duckling.AmountOfMoney.Helpers as Helpers import qualified Duckling.Numeral.Types as TNumeral - ruleAGrand :: Rule ruleAGrand = Rule   { name = "a grand"@@ -48,8 +52,22 @@       _ -> Nothing   } +ruleDollarCoin :: Rule+ruleDollarCoin = Rule+  { name = "dollar coin"+  , pattern =+    [ regex "(nickel|dime|quarter)s?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        c <- HashMap.lookup (Text.toLower match) Helpers.dollarCoins+        Just . Token AmountOfMoney . withValue c $ currencyOnly TTD+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleAGrand   , ruleGrand+  , ruleDollarCoin   ]
Duckling/AmountOfMoney/EN/US/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} @@ -27,6 +26,26 @@              ]   , examples (simple USD 10000)              [ "10 grand"+             , "two hundred thousand nickels"+             ]+  , examples (simple USD 1)+             [ "four quarters"+             , "ten dimes"+             , "twenty nickels"+             ]+  , examples (simple USD 0.1)+             [ "dime"+             , "a dime"+             , "two nickels"+             ]+  , examples (simple USD 0.25)+             [ "quarter"+             , "a quarter"+             , "five nickels"+             ]+  , examples (simple USD 0.05)+             [ "nickel"+             , "a nickel"              ]   ] 
Duckling/AmountOfMoney/EN/US/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}@@ -13,17 +12,22 @@   ( rules   ) where +import Data.HashMap.Strict (HashMap) import Data.String+import Data.Text (Text) import Prelude  import Duckling.AmountOfMoney.Helpers import Duckling.AmountOfMoney.Types (Currency(..)) import Duckling.Numeral.Helpers (isPositive)+import Duckling.Regex.Types import Duckling.Types +import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text+import qualified Duckling.AmountOfMoney.Helpers as Helpers import qualified Duckling.Numeral.Types as TNumeral - ruleAGrand :: Rule ruleAGrand = Rule   { name = "a grand"@@ -46,8 +50,22 @@       _ -> Nothing   } +ruleDollarCoin :: Rule+ruleDollarCoin = Rule+  { name = "dollar coin"+  , pattern =+    [ regex "(nickel|dime|quarter)s?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        c <- HashMap.lookup (Text.toLower match) Helpers.dollarCoins+        Just . Token AmountOfMoney . withValue c $ currencyOnly USD+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleAGrand   , ruleGrand+  , ruleDollarCoin   ]
Duckling/AmountOfMoney/EN/ZA/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} @@ -27,6 +26,26 @@              ]   , examples (simple Dollar 10000)              [ "10 grand"+             , "two hundred thousand nickels"+             ]+  , examples (simple Dollar 1)+             [ "four quarters"+             , "ten dimes"+             , "twenty nickels"+             ]+  , examples (simple Dollar 0.1)+             [ "dime"+             , "a dime"+             , "two nickels"+             ]+  , examples (simple Dollar 0.25)+             [ "quarter"+             , "a quarter"+             , "five nickels"+             ]+  , examples (simple Dollar 0.05)+             [ "nickel"+             , "a nickel"              ]   ] 
Duckling/AmountOfMoney/EN/ZA/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}@@ -13,17 +12,22 @@   ( rules   ) where +import Data.HashMap.Strict (HashMap) import Data.String+import Data.Text (Text) import Prelude  import Duckling.AmountOfMoney.Helpers import Duckling.AmountOfMoney.Types (Currency(..)) import Duckling.Numeral.Helpers (isPositive)+import Duckling.Regex.Types import Duckling.Types +import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text+import qualified Duckling.AmountOfMoney.Helpers as Helpers import qualified Duckling.Numeral.Types as TNumeral - ruleAGrand :: Rule ruleAGrand = Rule   { name = "a grand"@@ -48,8 +52,22 @@       _ -> Nothing   } +ruleDollarCoin :: Rule+ruleDollarCoin = Rule+  { name = "dollar coin"+  , pattern =+    [ regex "(nickel|dime|quarter)s?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        c <- HashMap.lookup (Text.toLower match) Helpers.dollarCoins+        Just . Token AmountOfMoney . withValue c $ currencyOnly Dollar+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleAGrand   , ruleGrand+  , ruleDollarCoin   ]
Duckling/AmountOfMoney/ES/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -64,5 +63,19 @@              [ "15 Pt"              , "15pta"              , "15Ptas"+             ]+  , examples (between Dollar (10, 20))+             [ "entre 10 y 20 dólares"+             , "de $10 y $20"+             , "$10 - 20 dólares"+             , "10 - 20 $"+             ]+  , examples (under Dollar 10)+             [ "menos de 10 dólares"+             , "no más de $10"+             ]+  , examples (above Dollar 10)+             [ "no menos de 10 dólares"+             , "más de $10"              ]   ]
Duckling/AmountOfMoney/ES/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -128,6 +127,114 @@       _ -> Nothing   } +ruleIntervalBetweenNumeral :: Rule+ruleIntervalBetweenNumeral = Rule+  { name = "between|from <numeral> to|and <amount-of-money>"+  , pattern =+    [ regex "de|entre"+    , Predicate isPositive+    , regex "a|y"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (_:+       Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                                             TAmountOfMoney.currency = c}:+       _) | from < to ->+        Just $ Token AmountOfMoney $ withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalBetween :: Rule+ruleIntervalBetween = Rule+  { name = "between|from <amount-of-money> to|and <amount-of-money>"+  , pattern =+    [ regex "de|entre"+    , Predicate isSimpleAmountOfMoney+    , regex "a|y"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just from,+                                             TAmountOfMoney.currency = c1}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                                             TAmountOfMoney.currency = c2}:+       _) | from < to && c1 == c2 ->+        Just $ Token AmountOfMoney $ withInterval (from, to) $ currencyOnly c1+      _ -> Nothing+  }++ruleIntervalNumeralDash :: Rule+ruleIntervalNumeralDash = Rule+  { name = "<numeral> - <amount-of-money>"+  , pattern =+    [ Predicate isNatural+    , regex "-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                                             TAmountOfMoney.currency = c}:+       _) | from < to->+         Just $ Token AmountOfMoney $ withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalDash :: Rule+ruleIntervalDash = Rule+  { name = "<amount-of-money> - <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just from,+                                             TAmountOfMoney.currency = c1}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                                             TAmountOfMoney.currency = c2}:+       _) | from < to && c1 == c2 ->+        Just $ Token AmountOfMoney $ withInterval (from, to) $ currencyOnly c1+      _ -> Nothing+  }++ruleIntervalMax :: Rule+ruleIntervalMax = Rule+  { name = "less/no more than <amount-of-money>"+  , pattern =+    [ regex "menos de|no más de"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                                             TAmountOfMoney.currency = c}:+       _) -> Just $ Token AmountOfMoney $ withMax to $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalMin :: Rule+ruleIntervalMin = Rule+  { name = "no less/more than <amount-of-money>"+  , pattern =+    [ regex "más de|no menos de"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                                             TAmountOfMoney.currency = c}:+       _) -> Just $ Token AmountOfMoney $ withMin to $ currencyOnly c+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleUnitAmount@@ -138,4 +245,10 @@   , ruleIntersectAndXCents   , ruleIntersectXCents   , rulePounds+  , ruleIntervalBetweenNumeral+  , ruleIntervalBetween+  , ruleIntervalNumeralDash+  , ruleIntervalDash+  , ruleIntervalMax+  , ruleIntervalMin   ]
Duckling/AmountOfMoney/FR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/AmountOfMoney/FR/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -205,7 +204,6 @@        _) -> Just . Token AmountOfMoney . withMin to $ currencyOnly c       _ -> Nothing   }-  rulePounds :: Rule rulePounds = Rule
Duckling/AmountOfMoney/GA/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/AmountOfMoney/GA/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
+ Duckling/AmountOfMoney/HE/Corpus.hs view
@@ -0,0 +1,124 @@+-- 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.AmountOfMoney.HE.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.AmountOfMoney.Types+import Duckling.Locale+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus =+  (testContext { locale = makeLocale HE Nothing }, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (simple ILS 10)+             [ "עשר שקל"+             , "עשרה שקלים"+             , "עשר ש״ח"+             , "עשר שח"+             , "10₪"+             ]+  , examples (simple ILS 10000)+             [ "עשר אלף שקל"+             , "10000 שקלים"+             , "10 אשח"+             , "10 אש״ח"+             ]+  , examples (simple ILS 10000000)+             [ "10 מיליון שקלים"+             , "10 משח"+             , "10 מש״ח"+             ]+  , examples (simple ILS 0.01)+             [ "אגורה"+             ]+  , examples (simple ILS 1)+             [ "שקל"+             , "שקל אחד"+             , "שקל בודד"+             , "100 אגורות"+             ]+  , examples (simple ILS 0.05)+             [ "חמש אגורות"+             ]+  , examples (simple ILS 0)+             [ "אפס ש״ח"+             ]+  , examples (simple ILS 1.5)+             [ "שקל וחצי"+             , "1.5 ש״ח"+             ]+  , examples (simple ILS 2)+             [ "שנקל"+             , "2 שקל"+             ]+  , examples (simple Dollar 10)+             [ "$10"+             , "10$"+             , "עשר דולר"+             , "עשרה דולר"+             , "עשרה דולרים"+             , "עשר דולרים"+             ]+  , examples (simple Dollar 20)+             [ "עשרים דולר"+             ]+  , examples (simple Dollar 2.23)+             [ "2 דולר ו23 סנט"+             ]+  , examples (simple EUR 20)+             [ "20€"+             , "20 יורו"+             , "EUR 20"+             , "20 אירו"+             ]+  , examples (simple EUR 29.99)+             [ "29.99 יורו"+             ]+  , examples (simple Pound 9)+             [ "£9"+             , "תשע פאונד"+             ]+  , examples (simple GBP 1)+             [ "לירה שטרלינג"+             ]+  , examples (simple GBP 10)+             [ "10 לירות שטרלינג"+             ]+  , examples (between Dollar (10, 20))+             [ "מ10 עד 20 דולר"+             , "מעשר עד עשרים דולר"+             , "בין 10 ל20 דולר"+             , "10$-20$"+             , "10-20$"+             , "10-20 דולר"+             , "בין 10 דולר ל20 דולר"+             ]+  , examples (under EUR 7)+             [ "פחות מ7 יורו"+             , "עד 7 יורו"+             , "לא יותר מ7 יורו"+             , "מתחת ל7 יורו"+             , "לא מעל 7 יורו"+             ]+  , examples (above Dollar 5)+             [ "יותר מ5 דולר"+             , "מעל 5 דולר"+             , "מ5 דולר"+             , "לא פחות מ5 דולר"+             , "לא מתחת ל5 דולר"+             ]+    ]
+ Duckling/AmountOfMoney/HE/Rules.hs view
@@ -0,0 +1,348 @@+-- 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.AmountOfMoney.HE.Rules+  ( rules+  ) where++import Data.Maybe+import Data.String+import Prelude++import Duckling.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types+  ( Currency(..)+  , AmountOfMoneyData(..)+  )+import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers+  ( isPositive+  )+import Duckling.Numeral.Types (NumeralData(..))+import Duckling.Types+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import qualified Duckling.Numeral.Types as TNumeral++ruleUnitAmount :: Rule+ruleUnitAmount = Rule+  { name = "<unit> <amount>"+  , pattern =+    [ Predicate isCurrencyOnly+    , Predicate isPositive+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.currency = c}:+       Token Numeral NumeralData{TNumeral.value = v}:+       _) -> Just . Token AmountOfMoney . withValue v $ currencyOnly c+      _ -> Nothing+  }++ruleOneShekel :: Rule+ruleOneShekel = Rule+  { name    = "שקל"+  , pattern = [regex "שקל( אחד| בודד)?"]+  , prod    = \_ -> Just . Token AmountOfMoney $ withValue 1 $ currencyOnly ILS+  }+ruleTwoShekel :: Rule+ruleTwoShekel = Rule+  { name    = "שנקל"+  , pattern = [regex "שנקל"]+  , prod    = \_ -> Just . Token AmountOfMoney $ withValue 2 $ currencyOnly ILS+  }+ruleOneAgura :: Rule+ruleOneAgura = Rule+  { name    = "oneAgura"+  , pattern = [regex "אגורה( אחת| בודדת)?"]+  , prod    = \_ -> Just . Token AmountOfMoney $ withValue 0.01 $+                    currencyOnly ILS+  }+ruleShekel :: Rule+ruleShekel = Rule+  { name    = "שקל"+  , pattern = [regex "שקל(ים)?|ש״?ח"]+  , prod    = \_ -> Just . Token AmountOfMoney $ currencyOnly ILS+  }++ruleThousandShekel :: Rule+ruleThousandShekel = Rule+    { name = "אש״ח"+    , pattern =+      [ Predicate isPositive+      , regex "אש״?ח"+      ]+    , prod = \case+        (Token Numeral NumeralData{TNumeral.value = v}:+         _) -> Just . Token AmountOfMoney $ withValue (v*1000) $+               currencyOnly ILS+        _ -> Nothing+    }++ruleMillionShekel :: Rule+ruleMillionShekel = Rule+    { name = "מש״ח"+    , pattern =+      [ Predicate isPositive+      , regex "מש״?ח"+      ]+    , prod = \case+        (Token Numeral NumeralData{TNumeral.value = v}:+         _) -> Just . Token AmountOfMoney $ withValue (v*1000000) $+               currencyOnly ILS+        _ -> Nothing+    }+ruleAgura :: Rule+ruleAgura = Rule+    { name = "multiple agura"+    , pattern =+      [ Predicate isPositive+      , regex "אגורות"+      ]+    , prod = \case+        (Token Numeral NumeralData{TNumeral.value = v}:+         _) -> Just . Token AmountOfMoney $ withValue (v*0.01) $+               currencyOnly ILS+        _ -> Nothing+    }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isWithoutCents+    , regex "ו"+    , Predicate isPositive+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just v,+                  TAmountOfMoney.currency = c}:+       _:+       Token Numeral NumeralData { TNumeral.value = p }:+       _) -> Just . Token AmountOfMoney $ withValue (v + p) $ currencyOnly c+      _ -> Nothing+  }++ruleIntersectAndXCents :: Rule+ruleIntersectAndXCents = Rule+  { name = "intersect (and X cents)"+  , pattern =+    [ Predicate isWithoutCents+    , regex "ו"+    , Predicate isCents+    ]+  , prod = \case+      (Token AmountOfMoney fd :+       _ :+       Token AmountOfMoney AmountOfMoneyData { TAmountOfMoney.value = Just c }:+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++rulePounds :: Rule+rulePounds = Rule+  { name = "£"+  , pattern =+    [ regex "פאונד(ים)?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound+  }++ruleDollar :: Rule+ruleDollar = Rule+  { name    = "$"+  , pattern =+    [ regex "דולר(ים)?"+    ]+  , prod    = \_ -> Just . Token AmountOfMoney $ currencyOnly Dollar+  }++ruleCent :: Rule+ruleCent = Rule+  { name = "cent"+  , pattern =+      [ regex "סנט(ים)?"+      ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  }++ruleEUR :: Rule+ruleEUR = Rule+  { name    = "€"+  , pattern =+    [ regex "אירו|יורו"+    ]+  , prod    = \_ -> Just . Token AmountOfMoney $ currencyOnly EUR+  }+ruleOneGBP :: Rule+ruleOneGBP = Rule+  { name = "OneGBP"+  , pattern =+    [ regex "לירה שטרלינג"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ withValue 1 $ currencyOnly GBP+  }+ruleGBP :: Rule+ruleGBP = Rule+  { name = "OneGBP"+  , pattern =+    [ regex "לירות שטרלינג"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly GBP+  }++rulePrecision :: Rule+rulePrecision = Rule+  { name = "about|exactly <amount-of-money>"+  , pattern =+      [ regex "בערך|בדיוק|קרוב ל"+      , Predicate isMoneyWithValue+      ]+  , prod = \case+      (_:+       token:+       _) -> Just token+      _ -> Nothing+  }++ruleIntervalBetweenNumeral :: Rule+ruleIntervalBetweenNumeral = Rule+  { name = "between|from <numeral> to|and <amount-of-money>"+  , pattern =+      [ regex "מ?|בין "+      , Predicate isPositive+      , regex "עד |ל"+      , Predicate isSimpleAmountOfMoney+      ]+  , prod = \case+      (_:+       Token Numeral NumeralData { TNumeral.value = from }:+       _:+       Token AmountOfMoney AmountOfMoneyData { TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c }:+       _) | from < to ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalBetween :: Rule+ruleIntervalBetween = Rule+  { name = "between|from <amount-of-money> to|and <amount-of-money>"+  , pattern =+      [ regex "מ?|בין "+      , Predicate isSimpleAmountOfMoney+      , regex "עד |ל"+      , Predicate isSimpleAmountOfMoney+      ]+  , prod = \case+      (_:+       Token AmountOfMoney AmountOfMoneyData { TAmountOfMoney.value = Just from,+                  TAmountOfMoney.currency = c1 }:+       _:+       Token AmountOfMoney AmountOfMoneyData { TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c2 }:+       _) | from < to && c1 == c2 ->+            Just . Token AmountOfMoney . withInterval (from, to) $+              currencyOnly c1+      _ -> Nothing+  }++ruleIntervalNumeralDash :: Rule+ruleIntervalNumeralDash = Rule+  { name = "<numeral> - <amount-of-money>"+  , pattern =+    [ Predicate isPositive+    , regex "-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (Token Numeral NumeralData { TNumeral.value = from }:+       _:+       Token AmountOfMoney AmountOfMoneyData { TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c }:+       _) | from < to -> Just . Token AmountOfMoney . withInterval (from, to) $+            currencyOnly c+      _ -> Nothing+  }++ruleIntervalDash :: Rule+ruleIntervalDash = Rule+  { name = "<amount-of-money> - <amount-of-money>"+  , pattern =+      [ Predicate isSimpleAmountOfMoney+      , regex "-"+      , Predicate isSimpleAmountOfMoney+      ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData { TAmountOfMoney.value = Just from,+                  TAmountOfMoney.currency = c1 }:+       _:+       Token AmountOfMoney AmountOfMoneyData { TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c2 }:+       _) | from < to && c1 == c2 ->+            Just . Token AmountOfMoney . withInterval (from, to) $+              currencyOnly c1+      _ -> Nothing+  }++ruleIntervalMax :: Rule+ruleIntervalMax = Rule+  { name = "under/less/lower/no more than <amount-of-money>"+  , pattern =+      [ regex "פחות מ|עד|לא יותר מ|מתחת ל?|לא מעל"+      , Predicate isSimpleAmountOfMoney+      ]+  , prod = \case+      (_:+       Token AmountOfMoney AmountOfMoneyData { TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c }:+       _) -> Just . Token AmountOfMoney . withMax to $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalMin :: Rule+ruleIntervalMin = Rule+  { name = "over/above/at least/more than <amount-of-money>"+  , pattern =+      [ regex "יותר מ|מעל|מ|לא פחות מ|לא מתחת ל"+      , Predicate isSimpleAmountOfMoney+      ]+  , prod = \case+      (_:+       Token AmountOfMoney AmountOfMoneyData { TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c }:+       _) -> Just . Token AmountOfMoney . withMin to $ currencyOnly c+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleUnitAmount+  , ruleCent+  , ruleEUR+  , ruleIntersectAndXCents+  , ruleIntervalBetweenNumeral+  , ruleIntervalBetween+  , ruleIntervalMax+  , ruleIntervalMin+  , ruleIntervalNumeralDash+  , ruleIntervalDash+  , rulePounds+  , ruleOneGBP+  , ruleGBP+  , rulePrecision+  , ruleIntersect+  , ruleAgura+  , ruleShekel+  , ruleOneShekel+  , ruleTwoShekel+  , ruleOneAgura+  , ruleThousandShekel+  , ruleMillionShekel+  , ruleDollar+  ]
Duckling/AmountOfMoney/HR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} @@ -24,11 +23,18 @@  allExamples :: [Example] allExamples = concat-  [ examples (simple Dollar 10)+  [ examples (simple Dollar 1)+             [ "$1"+             , "jedan dolar"+             ]+  , examples (simple Dollar 10)              [ "$10"              , "10$"              , "deset dolara"              ]+  , examples (simple Cent 1)+             [ "jedan cent"+             ]   , examples (simple Cent 10)              [ "deset centa"              ]@@ -46,6 +52,9 @@              , "2 dolara 23"              , "dva dolara i 23"              ]+  , examples (simple HRK 1)+             [ "jedna kuna"+             ]   , examples (simple HRK 2.23)              [ "2 kune i 23 lipe"              , "dvije kune 23 lipe"@@ -62,6 +71,9 @@              , "dvjesto kuna"              , "dvjesta kuna"              ]+  , examples (simple EUR 1)+             [ "jedan euro"+             ]   , examples (simple EUR 20)              [ "20€"              , "20 euros"@@ -94,4 +106,28 @@              [ "GBP3,01"              , "GBP 3,01"              ]-  ]+ , examples (between Dollar (100, 200))+            [ "od 100 do 200 dolara"+            , "od 100 dolara do 200 dolara"+            , "otprilike 100 do 200 dolara"+            , "otprilike 100 dolara do 200 dolara"+            , "100 dolara - 200 dolara"+            , "100-200 dolara"+            , "oko 100-200 dolara"+            , "u blizini 100-200 dolara"+            , "skoro 100-200 dolara"+            , "približno 100 do 200 dolara"+            , "izmedju 100 i 200 dolara"+            , "izmedju 100 dolara i 200 dolara"+            ]+  , examples (under EUR 7)+             [ "manje od EUR 7"+             , "ispod EUR 7"+             ]+  , examples (above Dollar 1.42)+             [ "više od jednog dolara i četrdeset dva centa"+             , "najmanje 1,42 dolara"+             , "preko 1,42 dolara"+             , "iznad 1,42 dolara"+             ]+ ]
Duckling/AmountOfMoney/HR/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}@@ -29,6 +28,20 @@ import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney import qualified Duckling.Numeral.Types as TNumeral +ruleACurrency :: Rule+ruleACurrency = Rule+  { name = "a <currency>"+  , pattern =+    [ regex "jed(an|na|no)"+    , Predicate isCurrencyOnly+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.currency = c}:+       _) -> Just . Token AmountOfMoney $ withValue 1 $ currencyOnly c+      _ -> Nothing+  }+ ruleUnitAmount :: Rule ruleUnitAmount = Rule   { name = "<unit> <amount>"@@ -198,9 +211,172 @@   , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly AED   } +rulePrecision :: Rule+rulePrecision = Rule+  { name = "about|exactly <amount-of-money>"+  , pattern =+    [ regex "oko|otprilike|u blizini|skoro|približno"+    , Predicate isMoneyWithValue+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleIntervalNumeralDash :: Rule+ruleIntervalNumeralDash = Rule+  { name = "<numeral> - <amount-of-money>"+  , pattern =+    [ Predicate isNatural+    , regex "-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) | from < to->+         Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalDash :: Rule+ruleIntervalDash = Rule+  { name = "<amount-of-money> - <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just from,+                  TAmountOfMoney.currency = c1}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c2}:+       _) | from < to && c1 == c2 ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c1+      _ -> Nothing+  }++ruleIntervalBetweenNumeral1 :: Rule+ruleIntervalBetweenNumeral1 = Rule+  { name = "between|from <numeral> to|and <amount-of-money>"+  , pattern =+    [ regex "od|otprilike|približno"+    , Predicate isPositive+    , regex "do"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) | from < to ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalBetweenNumeral2 :: Rule+ruleIntervalBetweenNumeral2 = Rule+  { name = "between|from <numeral> to|and <amount-of-money>"+  , pattern =+    [ regex "izmedju"+    , Predicate isPositive+    , regex "i"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) | from < to ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalBetween1 :: Rule+ruleIntervalBetween1 = Rule+  { name = "between|from <amount-of-money> to|and <amount-of-money>"+  , pattern =+    [ regex "od|otprilike"+    , Predicate isSimpleAmountOfMoney+    , regex "do"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just from,+                  TAmountOfMoney.currency = c1}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c2}:+       _) | from < to && c1 == c2 ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c1+      _ -> Nothing+  }++ruleIntervalBetween2 :: Rule+ruleIntervalBetween2 = Rule+  { name = "between|from <amount-of-money> to|and <amount-of-money>"+  , pattern =+    [ regex "izmedju"+    , Predicate isSimpleAmountOfMoney+    , regex "i"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just from,+                  TAmountOfMoney.currency = c1}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c2}:+       _) | from < to && c1 == c2 ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c1+      _ -> Nothing+  }++ruleIntervalMin :: Rule+ruleIntervalMin = Rule+  { name = "over/above/at least/more than <amount-of-money>"+  , pattern =+    [ regex "više od|najmanje|preko|iznad"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) -> Just . Token AmountOfMoney . withMin to $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalMax :: Rule+ruleIntervalMax = Rule+  { name = "under/less/lower/no more than <amount-of-money>"+  , pattern =+    [ regex "ispod|manje od"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) -> Just . Token AmountOfMoney . withMax to $ currencyOnly c+      _ -> Nothing+  }++ rules :: [Rule] rules =-  [ ruleUnitAmount+  [ ruleACurrency+  , ruleUnitAmount   , ruleDollar   , rulePound   , ruleOtherPounds@@ -215,4 +391,13 @@   , ruleKwd   , ruleQar   , ruleSar+  , rulePrecision+  , ruleIntervalNumeralDash+  , ruleIntervalDash+  , ruleIntervalBetweenNumeral1+  , ruleIntervalBetweenNumeral2+  , ruleIntervalBetween1+  , ruleIntervalBetween2+  , ruleIntervalMin+  , ruleIntervalMax   ]
Duckling/AmountOfMoney/Helpers.hs view
@@ -2,18 +2,19 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}-+{-# LANGUAGE NamedFieldPuns #-}  module Duckling.AmountOfMoney.Helpers   ( currencyOnly+  , valueOnly   , isSimpleAmountOfMoney   , isCent   , isCents+  , isDollarCoin   , isCurrencyOnly   , isDime   , isMoneyWithValue@@ -23,18 +24,42 @@   , withMax   , withMin   , withValue+  , mkLatent+  , dollarCoins   )   where +import Data.HashMap.Strict (HashMap) import Data.Maybe (isJust)+import Data.String+import Data.Text (Text) import Prelude -import Duckling.AmountOfMoney.Types (Currency (..), AmountOfMoneyData (..))+import Duckling.AmountOfMoney.Types+  ( Currency (..)+  , AmountOfMoneyData (..)+  , amountOfMoneyData'+  ) import Duckling.Numeral.Types (getIntValue, isInteger) import Duckling.Dimensions.Types import Duckling.Types hiding (Entity(..)) +import qualified Data.HashMap.Strict as HashMap+ -- -----------------------------------------------------------------+-- Dollar coin Types++dollarCoins :: HashMap Text Double+dollarCoins = HashMap.fromList+  [ ("nickel", 0.05)+  , ("nickels", 0.05)+  , ("dime", 0.1)+  , ("dimes", 0.1)+  , ("quarter", 0.25)+  , ("quarters", 0.25)+  ]++-- ----------------------------------------------------------------- -- Patterns  isCents :: Predicate@@ -56,6 +81,12 @@   {value = Nothing, minValue = Nothing, maxValue = Nothing}) = True isCurrencyOnly _ = False +isDollarCoin :: Predicate+isDollarCoin (Token AmountOfMoney AmountOfMoneyData{value = Just d, currency}) =+  elem d [0.05, 0.1, 0.25] && elem currency [Dollar, AUD, CAD, JMD,+                                             NZD,    SGD, TTD, USD]+isDollarCoin _ = False+ isSimpleAmountOfMoney :: Predicate isSimpleAmountOfMoney (Token AmountOfMoney AmountOfMoneyData   {value = Just _, minValue = Nothing, maxValue = Nothing}) = True@@ -77,17 +108,19 @@ -- Production  currencyOnly :: Currency -> AmountOfMoneyData-currencyOnly c = AmountOfMoneyData-  {currency = c, value = Nothing, minValue = Nothing, maxValue = Nothing}+currencyOnly c = amountOfMoneyData'{currency = c} +valueOnly :: Double -> AmountOfMoneyData+valueOnly x = amountOfMoneyData'{value = Just x}+ withValue :: Double -> AmountOfMoneyData -> AmountOfMoneyData withValue x fd = fd {value = Just x}  withCents :: Double -> AmountOfMoneyData -> AmountOfMoneyData withCents x fd@AmountOfMoneyData {value = Just value} = fd   {value = Just $ value + x / 100}-withCents x AmountOfMoneyData {value = Nothing} = AmountOfMoneyData-  {value = Just x, currency = Cent, minValue = Nothing, maxValue = Nothing}+withCents x AmountOfMoneyData {value = Nothing} =+  amountOfMoneyData'{value = Just x, currency = Cent}  withInterval :: (Double, Double) -> AmountOfMoneyData -> AmountOfMoneyData withInterval (from, to) fd = fd@@ -98,3 +131,6 @@  withMax :: Double -> AmountOfMoneyData -> AmountOfMoneyData withMax x fd = fd {maxValue = Just x}++mkLatent :: AmountOfMoneyData -> AmountOfMoneyData+mkLatent fd = fd {latent = True}
Duckling/AmountOfMoney/ID/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -39,7 +38,7 @@              [ "USD1,23"              ]   , examples (simple Dollar 2)-             [ "2 dola"+             [ "2 dolar"              , "dua dolar"              ]   , examples (simple EUR 20)@@ -79,5 +78,49 @@              [ "10 yen"              , "10¥"              , "10 ¥."+             ]+  , examples (between Dollar(10, 20))+             [ "antara 10 sampai 20 dolar"+             , "dari 10 dolar sampai 20 dolar"+             , "sekitar 10 sampai 20 dolar"+             , "antara 10 hingga 20 dolar"+             , "sekitar 10 dolar hingga 20 dolar"+             , "kira-kira 10-20 dolar"+             , "10-20 dolar"+             ]+  , examples (between IDR(1000, 10000))+             [ "antara Rp1000 sampai Rp10000"+             , "dari 1000 Rupiah hingga 10000 Rupiah"+             , "sekitar 1000 sampai 10000 Rupiah"+             , "1000-10000 Rupiah"+             , "kira-kira Rp1000 sampai Rp10000"+             , "dari Rp1.000 sampai Rp10.000"+             , "antara 1.000 hingga 10.000 Rupiah"+             , "kira-kira 1.000-10.000 Rupiah"+             , "sekitar 1.000 hingga 10.000 Rupiah"+             ]+  , examples (under EUR 7)+             [ "kurang dari 7 euro"+             , "di bawah EUR 7"+             , "tidak sampai 7 euro"+             , "lebih murah dari EUR 7"+             ]+  , examples (under IDR 500)+             [ "kurang dari 500 Rupiah"+             , "tidak sampai Rp500"+             , "di bawah Rp 500"+             , "lebih murah dari 500 rupiah"+             ]+  , examples (above USD 1.42)+             [ "di atas USD1,42"+             , "lebih dari USD1,42"+             , "melebihi USD1,42"+             , "melewati USD1,42"+             ]+  , examples (above IDR 33000)+             [ "di atas 33.000 Rupiah"+             , "lebih dari Rp33000"+             , "melebihi Rp33.000"+             , "melewati 33000 rupiah"              ]   ]
Duckling/AmountOfMoney/ID/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -91,6 +90,126 @@   , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly JPY   } +rulePrecision :: Rule+rulePrecision = Rule+  { name = "about|exactly <amount-of-money>"+  , pattern =+    [ regex "tepatnya|kira-kira|sekitar|hampir"+    , Predicate isMoneyWithValue+    ]+  , prod = \case+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleIntervalBetweenNumeral :: Rule+ruleIntervalBetweenNumeral = Rule+  { name = "between|from <numeral> to|and <amount-of-money>"+  , pattern =+    [ regex "sekitar|dari|antara"+    , Predicate isPositive+    , regex "sampai|hingga"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (_:+       Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) | from < to ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalBetween :: Rule+ruleIntervalBetween = Rule+  { name = "between|from <amount-of-money> to|and <amount-of-money>"+  , pattern =+    [ regex "sekitar|dari|antara|kira-kira"+    , Predicate isSimpleAmountOfMoney+    , regex "sampai|hingga"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just from,+                  TAmountOfMoney.currency = c1}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c2}:+       _) | from < to && c1 == c2 ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c1+      _ -> Nothing+  }++ruleIntervalNumeralDash :: Rule+ruleIntervalNumeralDash = Rule+  { name = "<numeral> - <amount-of-money>"+  , pattern =+    [ Predicate isNatural+    , regex "\\-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) | from < to ->+         Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalDash :: Rule+ruleIntervalDash = Rule+  { name = "<amount-of-money> - <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "\\-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just from,+                  TAmountOfMoney.currency = c1}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c2}:+       _) | from < to && c1 == c2 ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c1+      _ -> Nothing+  }++ruleIntervalMax :: Rule+ruleIntervalMax = Rule+  { name = "under/less/lower/no more than <amount-of-money>"+  , pattern =+    [ regex "(kurang|lebih murah) dari|tidak sampai|di bawah"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) -> Just . Token AmountOfMoney . withMax to $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalMin :: Rule+ruleIntervalMin = Rule+  { name = "over/above/at least/more than <amount-of-money>"+  , pattern =+    [ regex "di atas|lebih dari|melebihi|melewati"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) -> Just . Token AmountOfMoney . withMin to $ currencyOnly c+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleUnitAmount@@ -99,4 +218,11 @@   , ruleIntersect   , ruleJpy   , rulePounds+  , rulePrecision+  , ruleIntervalBetweenNumeral+  , ruleIntervalBetween+  , ruleIntervalMax+  , ruleIntervalMin+  , ruleIntervalNumeralDash+  , ruleIntervalDash   ]
+ Duckling/AmountOfMoney/IT/Corpus.hs view
@@ -0,0 +1,77 @@+-- 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.AmountOfMoney.IT.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.AmountOfMoney.Types+import Duckling.Locale+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {locale = makeLocale IT Nothing}, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (simple Dollar 10)+             [ "$10"+             , "10$"+             , "dieci dollari"+             ]+  , examples (simple Dollar 10000)+             [ "$10.000"+             , "10K$"+             , "$10k"+             , "10 000 dollari"+             , "10 000,00 $"+             ]+  , examples (simple USD 1.23)+             [ "USD1,23"+             , "1 USD e 23 centesimi"+             , "1 USD 23 centesimi"+             ]+  , examples (simple EUR 20)+             [ "20€"+             , "20 euro"+             , "20 Euro"+             , "20 Euro"+             , "EUR 20"+             ]+  , examples (simple EUR 29.99)+             [ "EUR29,99"+             ]+  , examples (simple Pound 9)+             [ "nove sterline"+             , "quasi nove sterline"+             ]+  , examples (simple GBP 3.01)+             [ "GBP3,01"+             , "GBP 3,01"+             ]+  , examples (between EUR (10, 20))+             [ "tra 10 e 20 euro"+             , "tra 10 euro e 20 euro"+             , "10 - 20 euro"+             , "10 euro - 20 euro"+             ]+  , examples (above EUR 10)+             [ "almeno 10 euro"+             , "più di 10 euro"+             , "più di 10 euro"+             ]+  , examples (under Dollar 10)+             [ "meno di 10 dollari"+             , "non più di 10 dollari"+             ]+  ]
+ Duckling/AmountOfMoney/IT/Rules.hs view
@@ -0,0 +1,270 @@+-- 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.AmountOfMoney.IT.Rules+  ( rules+  ) where++import Data.Maybe+import Data.String+import Prelude+import qualified Data.Text as Text++import Duckling.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types (Currency (..), AmountOfMoneyData (..))+import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (isNatural, isPositive)+import Duckling.Numeral.Types (NumeralData (..))+import Duckling.Regex.Types (GroupMatch (..))+import Duckling.Types+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import qualified Duckling.Numeral.Types as TNumeral++ruleUnitAmount :: Rule+ruleUnitAmount = Rule+  { name = "<unit> <amount>"+  , pattern =+    [ Predicate isCurrencyOnly+    , Predicate isPositive+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.currency = c}:+       Token Numeral NumeralData{TNumeral.value = v}:+       _) -> Just . Token AmountOfMoney . withValue v $ currencyOnly c+      _ -> Nothing+  }++ruleIntersectAndNumeral :: Rule+ruleIntersectAndNumeral = Rule+  { name = "intersect (and number)"+  , pattern =+    [ Predicate isWithoutCents+    , regex "e"+    , Predicate isNatural+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token Numeral NumeralData{TNumeral.value = c}:+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++rulePrecision :: Rule+rulePrecision = Rule+  { name = "precision"+  , pattern =+    [ regex "esattamente|quasi|più o meno|circa"+    , Predicate isMoneyWithValue+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleCent :: Rule+ruleCent = Rule+  { name = "cent"+  , pattern =+    [ regex "cent(esim)i?o?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  }++ruleIntersectXCents :: Rule+ruleIntersectXCents = Rule+  { name = "intersect (X cents)"+  , pattern =+    [ Predicate isWithoutCents+    , Predicate isCents+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just c}:+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleIntervalBetweenNumeral :: Rule+ruleIntervalBetweenNumeral = Rule+  { name = "between|from <numeral> to|and <amount-of-money>"+  , pattern =+    [ regex "tra"+    , Predicate isPositive+    , regex "e"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) | from < to ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }+++ruleIntervalBetween :: Rule+ruleIntervalBetween = Rule+  { name = "between|from <amount-of-money> to|and <amount-of-money>"+  , pattern =+    [ regex "tra"+    , Predicate isSimpleAmountOfMoney+    , regex "e"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token AmountOfMoney AmountOfMoneyData {+         TAmountOfMoney.value = Just from,+         TAmountOfMoney.currency = c1+       }:+       _:+       Token AmountOfMoney AmountOfMoneyData {+         TAmountOfMoney.value = Just to,+         TAmountOfMoney.currency = c2+       }:+       _) | c1 == c2, from < to ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c1+      _ -> Nothing+  }+++ruleIntervalNumeralDash :: Rule+ruleIntervalNumeralDash = Rule+  { name = "<numeral> - <amount-of-money>"+  , pattern =+    [ Predicate isNatural+    , regex "-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) | from < to ->+         Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalDash :: Rule+ruleIntervalDash = Rule+  { name = "<amount-of-money> - <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just from,+                  TAmountOfMoney.currency = c1}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c2}:+       _) | from < to && c1 == c2 ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c1+      _ -> Nothing+  }++ruleIntervalMax :: Rule+ruleIntervalMax = Rule+  { name = "under/less/lower/no more than <amount-of-money>"+  , pattern =+    [ regex "(meno|non più) di"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) -> Just . Token AmountOfMoney . withMax to $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalMin :: Rule+ruleIntervalMin = Rule+  { name = "over/above/at least/more than <amount-of-money>"+  , pattern =+    [ regex "più di|almeno"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) -> Just . Token AmountOfMoney . withMin to $ currencyOnly c+      _ -> Nothing+  }++ruleCurrencies :: Rule+ruleCurrencies = Rule+  { name = "£, $"+  , pattern =+    [ regex "(dollari|sterline)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "dollari"  -> Just . Token AmountOfMoney $ currencyOnly Dollar+        "sterline" -> Just . Token AmountOfMoney $ currencyOnly Pound+        _          -> Nothing+      _ -> Nothing+  }++ruleIntersectAndXCents :: Rule+ruleIntersectAndXCents = Rule+  { name = "intersect (and X cents)"+  , pattern =+    [ Predicate isWithoutCents+    , regex "e"+    , Predicate isCents+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just c}:+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isWithoutCents+    , Predicate isNatural+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token Numeral NumeralData{TNumeral.value = c}:+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleUnitAmount+  , ruleCent+  , ruleIntersect+  , ruleIntersectAndNumeral+  , ruleIntersectAndXCents+  , ruleIntersectXCents+  , ruleIntervalBetween+  , ruleIntervalBetweenNumeral+  , ruleIntervalDash+  , ruleIntervalMax+  , ruleIntervalMin+  , ruleIntervalNumeralDash+  , ruleCurrencies+  , rulePrecision+  ]
+ Duckling/AmountOfMoney/KA/Corpus.hs view
@@ -0,0 +1,136 @@+-- 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.++-- /Note/: All commented-out tests are failing due to https://github.com/facebook/duckling/issues/541+{-# LANGUAGE OverloadedStrings #-}++module Duckling.AmountOfMoney.KA.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.AmountOfMoney.Types+import Duckling.Locale+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {locale = makeLocale KA Nothing}, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (simple Dollar 1)+             [ "$1"+             , "ერთი დოლარი"+             , "1 დოლარი"+             ]+  , examples (simple Dollar 10)+             [ "$10"+             , "$ 10"+             , "10$"+             , "10 დოლარი"+             , "ათი დოლარი"+             ]+  , examples (simple Cent 10)+             [ "10 ცენტი"+             , "ათი ცენტი"+             , "10 c"+             , "10¢"+             ]+  , examples (simple Dollar 1e4)+             [ "$10K"+             , "10k$"+             , "$10,000"+             ]+  , examples (simple USD 3.14)+             [ "USD3.14"+             , "3.14US$"+             , "US$ 3.14"+             ]+  , examples (simple EUR 20)+             [ "20\x20ac"+             , "20 ევრო"+             , "EUR 20"+             , "EUR 20.0"+             , "20€"+             , "20 €ur"+             ]+  , examples (simple Pound 10)+             [ "\x00a3\&10"+             , "ათი ფუნტი"+             ]+  , examples (simple Dollar 20.43)+             [ "$20 და 43c"+             , "20 დოლარი და 43c"+             , "20 დოლარი 43 ცენტი"+             , "ოცი დოლარი 43 ცენტი"+             -- , "ოცი დოლარი და ორმოცდასამი ცენტი"+             ]+  , examples (simple GBP 3.01)+             [ "GBP3.01"+             , "GBP 3.01"+             , "3 GBP 1 პენსი"+             ]+  , examples (simple KWD 42)+             [ "42 KWD"+             , "42 ქუვეითური დინარი"+             ]+  , examples (simple LBP 42)+             [ "42 LBP"+             , "42 ლიბანური ფუნტი"+             ]+  , examples (simple EGP 42)+             [ "42 EGP"+             , "42 ეგვიპტური ფუნტი"+             ]+  , examples (simple QAR 42)+             [ "42 QAR"+             , "42 კატარული რიალი"+             ]+  , examples (between Dollar (10, 20))+             [ "დაახლოებით 10-20 დოლარი"+             -- , "10 დოლარიდან 20 დოლარამდე"+             -- , "10-დან 20 დოლარამდე"+             , "გძეტა $10-$20"+             , "10-20 დოლარი"+             ]+{-+  , examples (between Dollar (1.1, 1.3))+             [ "1.1-დან 1.3 დოლარამდე"+             , "ერთი მთელი ერთი დოლარიდან ერთი მთელი სამ დოლარამდე"+             ]+  , examples (under EUR 7)+             [ "7 ევრომდე"+             , "7 ევროზე ნაკლები"+             ]+  , examples (above Dollar 1.42)+             [ "1 დოლარი და 42 ცენტზე მეტი"+             ]+  , examples (between GEL (10, 20))+             [ "დაახლოებით 10-20 ლარი"+             , "10 ლარიდან 20 ლარამდე"+             , "10-დან 20 ლარამდე"+             , "გძეტა 10-20 ლარი"+             , "10-20 ლარი"+             ]+  , examples (between GEL (1.1, 1.3))+             [ "1.1-დან 1.3 ლარამდე"+             , "ერთი მთელი ერთი ლარიდან ერთი მთელი სამ ლარამდე"+             ]+  , examples (under GEL 7)+             [ "7 ლარამდე"+             , "7 ლარზე ნაკლები"+             ]+  , examples (above GEL 1.42)+             [ "1 ლარი და 42 თეთრზე მეტი"+             ]+  , examples (between GEL (1, 4))+             [ "1ლარიდან 4ლარამდე"+             ]+-}+  ]
+ Duckling/AmountOfMoney/KA/Rules.hs view
@@ -0,0 +1,347 @@+-- 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.AmountOfMoney.KA.Rules+  ( rules+  ) where++import Data.Maybe+import Data.String+import Prelude+import qualified Data.Text as Text++import Duckling.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types (Currency(..), AmountOfMoneyData (..))+import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (isNatural, isPositive)+import Duckling.Numeral.Types (NumeralData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import qualified Duckling.Numeral.Types as TNumeral++ruleUnitAmount :: Rule+ruleUnitAmount = Rule+  { name = "<unit> <amount>"+  , pattern =+    [ Predicate isCurrencyOnly+    , Predicate isPositive+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.currency = c}:+       Token Numeral NumeralData{TNumeral.value = v}:+       _) -> Just . Token AmountOfMoney . withValue v $ currencyOnly c+      _ -> Nothing+  }++rulePounds :: Rule+rulePounds = Rule+  { name = "£"+  , pattern =+    [ regex "(გირვანქა )?სტერლინგი?ს?(ად)?თ?|(გირვანქა )?ფუნ?ტი?ს?(ად)?თ?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound+  }++ruleOtherPounds :: Rule+ruleOtherPounds = Rule+  { name = "other pounds"+  , pattern =+    [ regex "(ეგვიპტური|ლიბანური) ?ფუნ?ტი?ს?(ად)?თ?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "ეგვიპტური" -> Just . Token AmountOfMoney $ currencyOnly EGP+        "ლიბანური" -> Just . Token AmountOfMoney $ currencyOnly LBP+        _          -> Nothing+      _ -> Nothing+  }++ruleRiyals :: Rule+ruleRiyals = Rule+  { name = "riyals"+  , pattern =+    [ regex "(კატარული|საუდის არაბული) ?რიალი?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "კატარული" -> Just . Token AmountOfMoney $ currencyOnly QAR+        "საუდის არაბული"  -> Just . Token AmountOfMoney $ currencyOnly SAR+        _        -> Nothing+      _ -> Nothing+  }++ruleDinars :: Rule+ruleDinars = Rule+  { name = "dinars"+  , pattern =+    [ regex "(ქუვეითური)? ?დინარი?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "ქუვეითური" -> Just . Token AmountOfMoney $ currencyOnly KWD+        _         -> Nothing+      _ -> Nothing+  }++ruleDirham :: Rule+ruleDirham = Rule+  { name = "დირჰემი"+  , pattern =+    [ regex "დირჰემი?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly AED+  }++ruleRinggit :: Rule+ruleRinggit = Rule+  { name = "ringgit"+  , pattern =+    [ regex "(მალაიზი?ური? )?რინგიტი?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly MYR+  }++ruleCent :: Rule+ruleCent = Rule+  { name = "cent"+  , pattern =+    [ regex "ცენტი?ს?(ად)?თ?|თეთრი?ს?(ად)?თ?|პენსი?ს?(ად)?თ?|ევროცენტი?ს?(ად)?თ?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  }++ruleLari :: Rule+ruleLari = Rule+  { name = "Lari"+  , pattern =+    [ regex "(ლარი?ს?(ად)?თ?)|GEL"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly GEL+  }++ruleDollars :: Rule+ruleDollars = Rule+  { name = "Dollars"+  , pattern =+    [ regex "დოლარი?ს?(ად)?თ?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Dollar+  }++ruleEuros :: Rule+ruleEuros = Rule+  { name = "Euros"+  , pattern =+    [ regex "ევრო?ს?დ?თ?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly EUR+  }++ruleACurrency :: Rule+ruleACurrency = Rule+  { name = "a <currency>"+  , pattern =+    [ Predicate isCurrencyOnly+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _) -> Just . Token AmountOfMoney $ fd {TAmountOfMoney.value = Just 1}+      _ -> Nothing+  }++ruleIntersectAndXCents :: Rule+ruleIntersectAndXCents = Rule+  { name = "intersect (and X cents)"+  , pattern =+    [ Predicate isWithoutCents+    , regex "და"+    , Predicate isCents+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just c}:+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleIntersectAndNumeral :: Rule+ruleIntersectAndNumeral = Rule+  { name = "intersect (and number)"+  , pattern =+    [ Predicate isWithoutCents+    , regex "და"+    , Predicate isNatural+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token Numeral NumeralData{TNumeral.value = c}:+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleIntersectXCents :: Rule+ruleIntersectXCents = Rule+  { name = "intersect (X cents)"+  , pattern =+    [ Predicate isWithoutCents+    , Predicate isCents+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just c}:+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++rulePrecision :: Rule+rulePrecision = Rule+  { name = "about|exactly <amount-of-money>"+  , pattern =+    [ regex "ზუსტად|იმენა|დაახლოებით|გძეტა"+    , Predicate isMoneyWithValue+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleIntervalBetweenNumeral :: Rule+ruleIntervalBetweenNumeral = Rule+  { name = "between|from <numeral> to|and <amount-of-money>"+  , pattern =+    [ Predicate isPositive+    , regex "-დან|დან"+    , Predicate isSimpleAmountOfMoney+    , regex "-ა?მდე|ა?მდე"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) | from < to ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalBetween :: Rule+ruleIntervalBetween = Rule+  { name = "between|from <amount-of-money> to|and <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "-დან|დან"+    , Predicate isSimpleAmountOfMoney+    , regex "-ა?მდე|ა?მდე"+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just from,+                  TAmountOfMoney.currency = c1}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c2}:+       _) | from < to && c1 == c2 ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c1+      _ -> Nothing+  }++ruleIntervalNumeralDash :: Rule+ruleIntervalNumeralDash = Rule+  { name = "<numeral> - <amount-of-money>"+  , pattern =+    [ Predicate isNatural+    , regex "-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) | from < to->+         Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalDash :: Rule+ruleIntervalDash = Rule+  { name = "<amount-of-money> - <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just from,+                  TAmountOfMoney.currency = c1}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c2}:+       _) | from < to && c1 == c2 ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c1+      _ -> Nothing+  }++ruleIntervalMax :: Rule+ruleIntervalMax = Rule+  { name = "under/less/lower/no more than <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "-ა?მდე|ა?მდე|(-ზე|ზე) ნაკლები"+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) -> Just . Token AmountOfMoney . withMax to $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalMin :: Rule+ruleIntervalMin = Rule+  { name = "over/above/at least/more than <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "-დან|დან|(-ზე|ზე) მეტი"+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) -> Just . Token AmountOfMoney . withMin to $ currencyOnly c+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleUnitAmount+  , ruleACurrency+  , ruleDollars+  , ruleCent+  , ruleEuros+  , ruleDinars+  , ruleDirham+  , ruleIntersectAndNumeral+  , ruleIntersectAndXCents+  , ruleIntersectXCents+  , ruleIntervalBetweenNumeral+  , ruleIntervalBetween+  , ruleIntervalMax+  , ruleIntervalMin+  , ruleIntervalNumeralDash+  , ruleIntervalDash+  , ruleOtherPounds+  , rulePounds+  , rulePrecision+  , ruleRinggit+  , ruleRiyals+  , ruleLari+  ]
Duckling/AmountOfMoney/KO/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -75,5 +74,39 @@              [ "십원"              , "10원"              , "10₩"+             ]+  , examples (between KRW (25000, 30000))+             [ "25000 - 30000원"+             , "25000원 - 30000원"+             , "이만오천원 - 삼만원"+             ]+  , examples (above KRW 5000)+             [ "5000원 이상"+             , "5000원 초과"+             , "오천원 이상"+             , "오천원 초과"+             ]+  , examples (under KRW 10000)+             [ "10000원 이하"+             , "10000원 미만"+             , "만원 이하"+             , "만원 미만"+             ]+  , examples (between Dollar (10, 20))+             [ "10 - 20 달러"+             , "10달러 - 20달러"+             , "십달러 - 이십달러"+             ]+  , examples (above Dollar 10)+             [ "10달러 이상"+             , "10달러 초과"+             , "십달러 이상"+             , "십달러 초과"+             ]+  , examples (under Dollar 10)+             [ "10달러 이하"+             , "10달러 미만"+             , "십달러 이하"+             , "십달러 미만"              ]   ]
Duckling/AmountOfMoney/KO/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -21,7 +20,7 @@ import Duckling.Dimensions.Types import Duckling.AmountOfMoney.Helpers import Duckling.AmountOfMoney.Types (Currency(..), AmountOfMoneyData (..))-import Duckling.Numeral.Helpers (isPositive)+import Duckling.Numeral.Helpers (isNatural, isPositive) import Duckling.Numeral.Types (NumeralData (..)) import Duckling.Types import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney@@ -87,7 +86,7 @@ ruleCent = Rule   { name = "cent"   , pattern =-    [ regex "cents?|센(트|츠)"+    [ regex "센트"     ]   , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent   }@@ -158,11 +157,108 @@ ruleDirham = Rule   { name = "dirham"   , pattern =-    [ regex "dirhams?"+    [ regex "디르함"     ]   , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly AED   } +ruleIntervalBetweenNumeral :: Rule+ruleIntervalBetweenNumeral = Rule+  { name = "between|from <numeral> to|and <amount-of-money>"+  , pattern =+    [ Predicate isPositive+    , regex "에서"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (Token Numeral NumeralData {TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData {TAmountOfMoney.value = Just to, TAmountOfMoney.currency = c}:+       _) ->+        (Just (Token AmountOfMoney $ withInterval (from, to) $ currencyOnly c))+      _ -> Nothing+  }++ruleIntervalBetween :: Rule+ruleIntervalBetween = Rule+  { name = "between|from <amount-of-money> to|and <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "부터"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData {TAmountOfMoney.value = Just from, TAmountOfMoney.currency = c1}:+       _:+       Token AmountOfMoney AmountOfMoneyData {TAmountOfMoney.value = Just to, TAmountOfMoney.currency = c2}:+       _) | c1 == c2 ->+        (Just (Token AmountOfMoney $ withInterval (from, to) $ currencyOnly c1))+      _ -> Nothing+  }++ruleIntervalNumeralDash :: Rule+ruleIntervalNumeralDash = Rule+  { name = "<numeral> - <amount-of-money>"+  , pattern =+    [ Predicate isNatural+    , regex "-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (Token Numeral NumeralData {TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData {TAmountOfMoney.value = Just to, TAmountOfMoney.currency = c}:+       _) ->+        (Just (Token AmountOfMoney $ withInterval (from, to) $ currencyOnly c))+      _ -> Nothing+  }++ruleIntervalDash :: Rule+ruleIntervalDash = Rule+  { name = "<amount-of-money> - <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData {TAmountOfMoney.value = Just from, TAmountOfMoney.currency = c1}:+       _:+       Token AmountOfMoney AmountOfMoneyData {TAmountOfMoney.value = Just to, TAmountOfMoney.currency = c2}:+       _) | c1 == c2 ->+        (Just (Token AmountOfMoney $ withInterval (from, to) $ currencyOnly c1))+      _ -> Nothing+  }++ruleIntervalMax :: Rule+ruleIntervalMax = Rule+  { name = "under/less/lower/no more than <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "미만|이하"+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData {TAmountOfMoney.value = Just to, TAmountOfMoney.currency = c}:+       _:+       _) -> (Just (Token AmountOfMoney $ withMax to $ currencyOnly c))+      _ -> Nothing+  }++ruleIntervalMin :: Rule+ruleIntervalMin = Rule+  { name = "over/above/at least/more than <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "초과|이상"+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData {TAmountOfMoney.value = Just to, TAmountOfMoney.currency = c}:+       _:+       _) -> (Just (Token AmountOfMoney $ withMin to $ currencyOnly c))+      _ -> Nothing+  }++ rules :: [Rule] rules =   [ ruleUnitAmount@@ -178,4 +274,10 @@   , ruleIntersectXCents   , ruleKrw   , rulePounds+  , ruleIntervalBetweenNumeral+  , ruleIntervalBetween+  , ruleIntervalNumeralDash+  , ruleIntervalDash+  , ruleIntervalMax+  , ruleIntervalMin   ]
+ Duckling/AmountOfMoney/MN/Corpus.hs view
@@ -0,0 +1,95 @@+-- 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.AmountOfMoney.MN.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.AmountOfMoney.Types+import Duckling.Locale+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {locale = makeLocale MN Nothing}, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (simple MNT 1)+             [ "1 төг"+             , "нэг төгрөг"+             , "1 ₮"+             , "1 төгрөг"+             ]+  , examples (simple MNT 10)+             [ "10 төгрөг"+             , "₮ 10"+             , "10₮"+             , "10MNT"+             , "10төг"+             , "10 төгрөг"+             , "төгрөг 10"+             , "10 төгрөгийн"+             ]+  , examples (simple Dollar 1)+             [ "$1"+             , "нэг доллар"+             ]+  , examples (simple Dollar 10)+             [ "$10"+             , "$ 10"+             , "10$"+             , "10 доллар"+             , "арван доллар"+             ]+  , examples (simple Cent 10)+             [ "10 цент"+             , "арван пени"+             , "арван цент"+             , "10 c"+             , "10¢"+             ]+  , examples (simple EUR 20)+             [ "20€"+             , "20 €ur"+             , "20 евро"+             , "Евро 20"+             ]+  , examples (simple Pound 10)+             [ "\x00a3\&10"+             , "арван фунт"+             ]+  , examples (simple INR 20)+             [ "20Rs"+             , "Rs20"+             ]+  , examples (simple GBP 3.01)+             [ "GBP3.01"+             , "GBP 3.01"+             , "3.01 Английн фунт"+             ]+  , examples (under MNT 10)+             [ "10₮-c бага"+             ]+  , examples (above MNT 20)+             [ "20MNT-c их"+             ]+  , examples (between MNT (5, 10))+             [ "5-c MNT10 хүртэл"+             , "5-c ₮10 хүртэл"+             , "5-c 10 MNT хүртэл"+             , "MNT5-c 10 хүртэл"+             , "MNT5-c 10₮ хооронд"+             , "5-c ₮10-н хооронд"+             , "MNT5-c 10₮-н хүртэл"+             ]+  ]
+ Duckling/AmountOfMoney/MN/Rules.hs view
@@ -0,0 +1,260 @@+-- 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.AmountOfMoney.MN.Rules+  ( rules+  ) where++import Data.Maybe+import Data.String+import Prelude++import Duckling.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types (Currency(..), AmountOfMoneyData(..))+import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (isNatural, isPositive)+import Duckling.Numeral.Types (NumeralData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import qualified Duckling.Numeral.Types as TNumeral++ruleUnitAmount :: Rule+ruleUnitAmount = Rule+  { name = "<unit> <amount>"+  , pattern =+    [ Predicate isCurrencyOnly+    , Predicate isPositive+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.currency = c}:+       Token Numeral NumeralData{TNumeral.value = v}:+       _) -> Just . Token AmountOfMoney . withValue v $ currencyOnly c+      _ -> Nothing+  }++ruleTugriks :: Rule+ruleTugriks = Rule+  { name = "төг"+  , pattern =+    [ regex "төг(рөг(ийн)?)?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly MNT+  }++rulePounds :: Rule+rulePounds = Rule+  { name = "£"+  , pattern =+    [ regex "фунт(аар|тай|аас)?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound+  }++ruleGBP :: Rule+ruleGBP = Rule+  { name = "Mongolian GBP"+  , pattern =+    [ regex "Английн\\s+фунт"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly GBP+  }++ruleDollar :: Rule+ruleDollar = Rule+  { name = "$"+  , pattern =+    [ regex "доллар(ын|оор|оос|той)?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Dollar+  }++ruleCent :: Rule+ruleCent = Rule+  { name = "cent"+  , pattern =+    [ regex "цент(ийн|ээс|ээр|тэй)?|пени|пенс(ээр|гээр|тэй|ээс|гээс)?|ц"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  }++ruleEUR :: Rule+ruleEUR = Rule+  { name = "€"+  , pattern =+    [ regex "евро"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly EUR+  }++ruleBucks :: Rule+ruleBucks = Rule+  { name = "bucks"+  , pattern =+    [ regex "бакс(аар|тай|аас)?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Unnamed+  }++rulePrecision :: Rule+rulePrecision = Rule+  { name = "about|exactly <amount-of-money>"+  , pattern =+    [ regex "яг|ойролцоогоор|бараг"+    , Predicate isMoneyWithValue+    ]+  , prod = \case+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleIntervalBetweenNumeral :: Rule+ruleIntervalBetweenNumeral = Rule+  { name = "between|from <numeral> to|and <amount-of-money>"+  , pattern =+    [ Predicate isPositive+    , regex "-c"+    , Predicate isSimpleAmountOfMoney+    , regex "(-н\\s+)?(хооронд|хүртэл)"+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) | from < to ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalBetweenNumeral2 :: Rule+ruleIntervalBetweenNumeral2 = Rule+  { name = "between|from <amount-of-money> to|and <numeral>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "-c"+    , Predicate isNatural+    , regex "(-н\\s+)?(хооронд|хүртэл)"+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just from,+                  TAmountOfMoney.currency = c}:+       _:+       Token Numeral NumeralData{TNumeral.value = to}:+       _) | from < to ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalBetween :: Rule+ruleIntervalBetween = Rule+  { name = "between|from <amount-of-money> to|and <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "-c"+    , Predicate isSimpleAmountOfMoney+    , regex "(-н\\s+)?(хооронд|хүртэл)"+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just from,+                  TAmountOfMoney.currency = c1}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c2}:+       _) | from < to && c1 == c2 ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c1+      _ -> Nothing+  }++ruleIntervalNumeralDash :: Rule+ruleIntervalNumeralDash = Rule+  { name = "<numeral> - <amount-of-money>"+  , pattern =+    [ Predicate isPositive+    , regex "-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) | from < to ->+         Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalDash :: Rule+ruleIntervalDash = Rule+  { name = "<amount-of-money> - <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just from,+                  TAmountOfMoney.currency = c1}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c2}:+       _) | from < to && c1 == c2 ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c1+      _ -> Nothing+  }++ruleIntervalMax :: Rule+ruleIntervalMax = Rule+  { name = "under/less/lower/no more than <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "-c\\s+(бага|доогуур|ихгүй)"+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) -> Just . Token AmountOfMoney . withMax to $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalMin :: Rule+ruleIntervalMin = Rule+  { name = "over/above/at least/more than <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "-c\\s+(их|дээгүүр|илүү)"+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) -> Just . Token AmountOfMoney . withMin to $ currencyOnly c+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleUnitAmount+  , ruleBucks+  , ruleCent+  , ruleDollar+  , ruleEUR+  , ruleGBP+  , ruleIntervalBetweenNumeral+  , ruleIntervalBetweenNumeral2+  , ruleIntervalBetween+  , ruleIntervalMax+  , ruleIntervalMin+  , ruleIntervalNumeralDash+  , ruleIntervalDash+  , rulePounds+  , rulePrecision+  , ruleTugriks+  ]
Duckling/AmountOfMoney/NB/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -46,12 +45,479 @@              , "10kr"              , "ti kroner"              , "10 NOK"+             , "ti norske kroner"              ]+  , examples (simple SEK 10)+             [ "10kronor"+             , "10 svenske kroner"+             , "10 svenske kr"+             , "10 svenske kronor"+             , "ti kronor"+             ]+  , examples (simple DKK 10)+             [ "10 danske kroner"+             , "ti danske kroner"+             , "ti danske kr"+             ]+  , examples (simple AUD 10)+             [ "10 australske dollar"+             , "10 australske dollars"+             ]+  , examples (simple CAD 10)+             [ "10 kanadiske dollar"+             , "10 kanadiske dollars"+             , "10 canadiske dollar"+             , "10 canadiske dollars"+             ]+  , examples (simple CHF 10)+             [ "10 sveitsiske franc"+             , "10 sveitsiske francs"+             ]+  , examples (simple CNY 10)+             [ "10 yuan"+             , "10 kinesiske yuan"+             , "10 kinesisk yuan"+             , "10 renminbi"+             , "10 kinesiske renminbi"+             , "10 kinesisk renminbi"+             ]+  , examples (simple CZK 10)+             [ "10 koruna"+             , "10 tsjekkiske koruna"+             ]+  , examples (simple INR 10)+             [ "10 rupi"+             , "10 rupier"+             , "10 rupee"+             , "10 rupees"+             , "10 indisk rupi"+             , "10 indiske rupi"+             , "10 indiske rupee"+             , "10 indiske rupees"+             , "10 indiske rupier"+             , "10 indisk rupier"+             , "ti rupi"+             , "ti rupier"+             , "ti indisk rupi"+             , "ti indiske rupi"+             , "ti indiske rupee"+             , "ti indiske rupees"+             , "ti indiske rupier"+             , "ti indisk rupier"+             ]+  , examples (simple JPY 10)+             [ "10 japanske yen"+             , "10 yen"+             , "ti japanske yen"+             , "ti yen"+             ]+  , examples (simple PKR 10)+             [ "10 pakistansk rupi"+             , "10 pakistanske rupi"+             , "10 pakistanske rupee"+             , "10 pakistanske rupees"+             , "10 pakistanske rupier"+             , "10 pakistansk rupier"+             , "ti pakistansk rupi"+             , "ti pakistanske rupi"+             , "ti pakistanske rupee"+             , "ti pakistanske rupees"+             , "ti pakistanske rupier"+             , "ti pakistansk rupier"+             ]+  , examples (simple PLN 10)+             [ "10 zloty"+             , "10 sloty"+             , "10 polske zloty"+             , "10 polske sloty"+             , "ti zloty"+             , "ti sloty"+             , "ti polske zloty"+             , "ti polske sloty"+             ]+  , examples (simple SGD 10)+             [ "10 singapore dollar"+             , "10 singapore dollars"+             , "10 singaporske dollar"+             , "10 singaporske dollars"+             , "ti singapore dollar"+             , "ti singapore dollars"+             , "ti singaporske dollar"+             , "ti singaporske dollars"+             ]+  , examples (simple THB 10)+             [ "10 bhat"+             , "10 thai baht"+             , "10 thai bhat"+             , "10 thailand baht"+             , "10 thailand bhat"+             , "10 thailandske baht"+             , "10 thailandske bhat"+             , "ti baht"+             , "ti bhat"+             , "ti thai baht"+             , "ti thai bhat"+             , "ti thailand baht"+             , "ti thailand bhat"+             , "ti thailandske baht"+             , "ti thailandske bhat"+             ]+  , examples (simple ZAR 10)+             [ "10 rand"+             , "10 sørafrikanske rand"+             , "10 sør-afrikanske rand"+             , "10 rand"+             , "10 sørafrikanske rand"+             , "10 sør-afrikanske rand"+             , "ti rand"+             , "ti sørafrikanske rand"+             , "ti sør-afrikanske rand"+             ]   , examples (simple NOK 2.23)              [ "2 kroner og 23 øre"              , "to kroner 23 øre"              , "to kroner og 23 øre"              , "to kr 23"+             ]+  , examples (simple SEK 2.23)+             [ "2 kronor og 23 öre"+             , "to kronor 23 öre"+             , "to svenske kronor 23 öre"+             , "to svenske kroner 23 öre"+             , "to svenske kroner 23 øre"+             , "to kronor og 23 öre"+             , "to svenske kronor og 23 öre"+             , "to svenske kroner og 23 öre"+             , "to svenske kroner og 23 øre"+             , "to svensk kroner og 23 øre"+             ]+  , examples (simple DKK 2.23)+             [ "2 danske kroner og 23 øre"+             , "to danske kroner 23 øre"+             , "to danske kroner og 23 øre"+             , "to danske kr 23"+             , "to dansk kr 23"+             ]+  , examples (simple USD 2.23)+             [ "2 amerikanske dollar og 23 cent"+             , "2 amerikanske dollars og 23 cent"+             , "2 amerikanske dollar og 23 cents"+             , "2 amerikanske dollars og 23 cents"+             , "to amerikanske dollar 23 cent"+             , "to amerikanske dollars 23 cent"+             , "to amerikanske dollar 23 cents"+             , "to amerikanske dollars 23 cents"+             , "to amerikanske dollar og 23 cent"+             , "to amerikanske dollars og 23 cent"+             , "to amerikanske dollar og 23 cents"+             , "to amerikanske dollars og 23 cents"+             , "to amerikanske dollar 23"+             , "to amerikanske dollars 23"+             ]+  , examples (simple AUD 2.23)+             [ "2 australske dollar og 23 cent"+             , "2 australske dollars og 23 cent"+             , "2 australske dollar og 23 cents"+             , "2 australske dollars og 23 cents"+             , "to australske dollar 23 cent"+             , "to australske dollars 23 cent"+             , "to australske dollar 23 cents"+             , "to australske dollars 23 cents"+             , "to australske dollar og 23 cent"+             , "to australske dollars og 23 cent"+             , "to australske dollar og 23 cents"+             , "to australske dollars og 23 cents"+             , "to australske dollar 23"+             , "to australske dollars 23"+             ]+  , examples (simple CAD 2.23)+             [ "2 kanadiske dollar og 23 cent"+             , "2 kanadiske dollars og 23 cent"+             , "2 canadiske dollar og 23 cent"+             , "2 canadiske dollars og 23 cent"+             , "2 kanadiske dollar og 23 cents"+             , "2 kanadiske dollars og 23 cents"+             , "2 canadiske dollar og 23 cents"+             , "2 canadiske dollars og 23 cents"+             , "to kanadiske dollar 23 cent"+             , "to kanadiske dollars 23 cent"+             , "to canadiske dollar 23 cent"+             , "to canadiske dollars 23 cent"+             , "to kanadiske dollar 23 cents"+             , "to kanadiske dollars 23 cents"+             , "to canadiske dollar 23 cents"+             , "to canadiske dollars 23 cents"+             , "to kanadiske dollar og 23 cent"+             , "to kanadiske dollars og 23 cent"+             , "to canadiske dollar og 23 cent"+             , "to canadiske dollars og 23 cent"+             , "to kanadiske dollar og 23 cents"+             , "to kanadiske dollars og 23 cents"+             , "to canadiske dollar og 23 cents"+             , "to canadiske dollars og 23 cents"+             , "to kanadiske dollar 23"+             , "to kanadiske dollars 23"+             , "to canadiske dollar 23"+             , "to canadiske dollars 23"+             ]+  , examples (simple CHF 2.23)+             [ "2 sveitsiske franc og 23 rappen"+             , "2 sveitsiske francs og 23 rappen"+             , "2 sveitsiske franc og 23 rp"+             , "2 sveitsiske francs og 23 rp"+             , "2 sveitsiske franc og 23 centime"+             , "2 sveitsiske francs og 23 centime"+             , "2 sveitsiske franc og 23 c"+             , "2 sveitsiske francs og 23 c"+             , "2 sveitsiske franc og 23 centesimo"+             , "2 sveitsiske francs og 23 centesimo"+             , "2 sveitsiske franc og 23 ct"+             , "2 sveitsiske francs og 23 ct"+             , "2 sveitsiske franc og 23 rap"+             , "2 sveitsiske francs og 23 rap"+             , "to sveitsiske franc 23 rappen"+             , "to sveitsiske francs 23 rappen"+             , "to sveitsiske franc 23 rp"+             , "to sveitsiske francs 23 rp"+             , "to sveitsiske franc 23 centime"+             , "to sveitsiske francs 23 centime"+             , "to sveitsiske franc 23 c"+             , "to sveitsiske francs 23 c"+             , "to sveitsiske franc 23 centesimo"+             , "to sveitsiske francs 23 centesimo"+             , "to sveitsiske franc 23 ct"+             , "to sveitsiske francs 23 ct"+             , "to sveitsiske franc 23 rap"+             , "to sveitsiske francs 23 rap"+             , "to sveitsiske franc og 23 rappen"+             , "to sveitsiske francs og 23 rappen"+             , "to sveitsiske franc og 23 rp"+             , "to sveitsiske francs og 23 rp"+             , "to sveitsiske franc og 23 centime"+             , "to sveitsiske francs og 23 centime"+             , "to sveitsiske franc og 23 c"+             , "to sveitsiske francs og 23 c"+             , "to sveitsiske franc og 23 centesimo"+             , "to sveitsiske francs og 23 centesimo"+             , "to sveitsiske franc og 23 ct"+             , "to sveitsiske francs og 23 ct"+             , "to sveitsiske franc og 23 rap"+             , "to sveitsiske francs og 23 rap"+             , "to sveitsiske franc 23"+             , "to sveitsiske francs 23"+             ]+  , examples (simple CNY 2.23)+             [ "2 yuan og 23 fen"+             , "2 kinesiske yuan og 23 fen"+             , "2 renminbi og 23 fen"+             , "2 kinesiske renminbi og 23 fen"+             , "to yuan 23 fen"+             , "to kinesiske yuan 23 fen"+             , "to renminbi 23 fen"+             , "to kinesiske renminbi 23 fen"+             , "to yuan og 23 fen"+             , "to kinesiske yuan og 23 fen"+             , "to renminbi og 23 fen"+             , "to kinesiske renminbi og 23 fen"+             , "to yuan 23"+             , "to kinesiske yuan 23"+             , "to renminbi 23"+             , "to kinesiske renminbi 23"+             ]+  , examples (simple CZK 2.23)+             [ "2 koruna og 23 haleru"+             , "2 tsjekkiske koruna og 23 haleru"+             , "to koruna 23 haleru"+             , "to tsjekkiske koruna 23 haleru"+             , "to koruna og 23 haleru"+             , "to tsjekkiske koruna og 23 haleru"+             , "to koruna 23"+             , "to tsjekkiske koruna 23"+             ]+  , examples (simple HKD 2.23)+             [ "2 hong kong dollar og 23 cent"+             , "2 hong kong dollar og 23 cents"+             , "2 hong kong dollars og 23 cent"+             , "2 hong kong dollars og 23 cents"+             , "2 hong kong dollar og 23 cents"+             , "2 hong kong dollars og 23 cents"+             , "to hong kong dollar 23 cent"+             , "to hong kong dollars 23 cent"+             , "to hong kong dollar 23 cents"+             , "to hong kong dollars 23 cents"+             , "to hong kong dollar og 23 cent"+             , "to hong kong dollars og 23 cent"+             , "to hong kong dollar og 23 cents"+             , "to hong kong dollars og 23 cents"+             , "to hong kong dollar 23"+             , "to hong kong dollars 23"+             ]+  , examples (simple INR 2.23)+             [ "2 indiske rupi og 23 paise"+             , "2 indiske rupier og 23 paise"+             , "to indiske rupi 23 paise"+             , "to indiske rupier 23 paise"+             , "to indiske rupier 23 paise"+             , "to indiske rupi og 23 paise"+             , "to indiske rupier og 23 paise"+             , "to indiske rupi 23"+             , "to indiske rupier 23"+             ]+  , examples (simple NZD 2.23)+             [ "2 new zealand dollar og 23 cent"+             , "2 new zealand dollars og 23 cent"+             , "2 new zealand dollars og 23 cents"+             , "2 new zealandske dollar og 23 cent"+             , "2 new zealandske dollars og 23 cent"+             , "2 new zealandske dollars og 23 cents"+             , "2 new zealand dollar og 23 cents"+             , "2 new zealand dollars og 23 cents"+             , "2 nz dollar og 23 cents"+             , "2 nz dollars og 23 cents"+             , "to new zealand dollar 23 cent"+             , "to new zealand dollars 23 cent"+             , "to new zealand dollars 23 cents"+             , "to new zealandske dollar 23 cent"+             , "to new zealandske dollars 23 cent"+             , "to new zealandske dollars 23 cents"+             , "to new zealand dollar 23 cents"+             , "to new zealand dollars 23 cents"+             , "to new zealand dollars 23 cent"+             , "to new zealand dollar og 23 cent"+             , "to new zealand dollars og 23 cent"+             , "to new zealandske dollar og 23 cent"+             , "to new zealandske dollars og 23 cent"+             , "to new zealandske dollars og 23 cents"+             , "to new zealand dollar og 23 cents"+             , "to new zealand dollars og 23 cent"+             , "to new zealand dollars og 23 cents"+             , "to new zealand dollar 23"+             , "to new zealand dollars 23"+             , "to new zealandske dollar 23"+             , "to new zealandske dollars 23"+             , "to nz dollar 23"+             , "to nz dollars 23"+             ]+  , examples (simple PLN 2.23)+             [ "2 zloty og 23 groszy"+             , "2 sloty og 23 groszy"+             , "2 polske zloty og 23 groszy"+             , "2 polske sloty og 23 groszy"+             , "to zloty 23 groszy"+             , "to sloty 23 groszy"+             , "to polske zloty 23 groszy"+             , "to polske sloty 23 groszy"+             , "to zloty og 23 groszy"+             , "to sloty og 23 groszy"+             , "to polske zloty og 23 groszy"+             , "to polske sloty og 23 groszy"+             , "to zloty 23"+             , "to sloty 23"+             , "to polske zloty 23"+             , "to polske sloty 23"+             ]+  , examples (simple SGD 2.23)+             [ "2 singapore dollar og 23 cent"+             , "2 singapore dollars og 23 cent"+             , "2 singaporske dollar og 23 cent"+             , "2 singaporske dollars og 23 cent"+             , "2 singapore dollar og 23 cents"+             , "2 singapore dollars og 23 cents"+             , "to singapore dollar 23 cent"+             , "to singapore dollars 23 cent"+             , "to singaporske dollar 23 cent"+             , "to singaporske dollars 23 cent"+             , "to singapore dollar 23 cents"+             , "to singapore dollars 23 cents"+             , "to singapore dollar og 23 cent"+             , "to singapore dollars og 23 cent"+             , "to singaporske dollar og 23 cent"+             , "to singaporske dollars og 23 cent"+             , "to singapore dollar og 23 cents"+             , "to singapore dollars og 23 cents"+             , "to singapore dollar 23"+             , "to singapore dollars 23"+             , "to singaporske dollar 23"+             , "to singaporske dollars 23"+             ]+  , examples (simple ZAR 2.23)+             [ "2 rand og 23 cent"+             , "2 sørafrikanske rand og 23 cent"+             , "2 sørafrikanske rand og 23 cents"+             , "2 sør-afrikanske rand og 23 cent"+             , "2 sør-afrikanske rand og 23 cents"+             , "to rand 23 cent"+             , "to sørafrikanske rand 23 cent"+             , "to sørafrikanske rand 23 cents"+             , "to sør-afrikanske rand 23 cent"+             , "to sør-afrikanske rand 23 cents"+             , "to rand og 23 cent"+             , "to sørafrikanske rand og 23 cent"+             , "to sørafrikanske rand og 23 cents"+             , "to sør-afrikanske rand og 23 cent"+             , "to sør-afrikanske rand og 23 cents"+             , "to rand 23"+             , "to sørafrikanske rand 23"+             , "to sør-afrikanske rand 23"+             ]+  , examples (simple THB 2.23)+             [ "2 baht og 23 satang"+             , "2 bhat og 23 satang"+             , "2 thai baht og 23 satang"+             , "2 thai bhat og 23 satang"+             , "2 thailandske baht og 23 satang"+             , "2 thailandske bhat og 23 satang"+             , "to baht 23 satang"+             , "to bhat 23 satang"+             , "to thai baht 23 satang"+             , "to thai bhat 23 satang"+             , "to thailandske baht 23 satang"+             , "to thailandske bhat 23 satang"+             , "to baht og 23 satang"+             , "to bhat og 23 satang"+             , "to thai baht og 23 satang"+             , "to thai bhat og 23 satang"+             , "to thailandske baht og 23 satang"+             , "to thailandske bhat og 23 satang"+             , "to baht 23"+             , "to bhat 23"+             , "to thai baht 23"+             , "to thai bhat 23"+             , "to thailandske baht 23"+             , "to thailandske bhat 23"+             ]+  , examples (simple Cent 10)+             [ "ti cent"+             , "ti cents"+             , "ti pence"+             , "ti penny"+             , "ti pennies"+             , "10 cent"+             , "10 cents"+             , "10 cents"+             , "10 pence"+             , "10 penny"+             , "10 øre"+             , "10 ører"+             , "10 öre"+             , "10 örer"+             , "10 p"+             , "10 c"+             , "10 fen"+             , "10 haleru"+             , "10 groszy"+             , "10 paise"+             , "10 paisa"+             , "10 centesimo"+             , "10 centesimi"+             , "10 centime"+             , "10 centimes"+             , "10 ct"+             , "10 rap"+             , "10 rappen"+             , "10 rappens"+             , "10 rp"+             , "10 satang"              ]   , examples (simple EUR 20)              [ "20€"
Duckling/AmountOfMoney/NB/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -37,7 +36,7 @@   , prod = \case       (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.currency = c}:        Token Numeral NumeralData{TNumeral.value = v}:-       _) -> Just . Token AmountOfMoney . withValue v $ currencyOnly c+       _) -> Just $ Token AmountOfMoney . withValue v $ currencyOnly c       _ -> Nothing   } @@ -49,11 +48,11 @@     , regex "og"     , Predicate isNatural     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token AmountOfMoney fd:        _:        Token Numeral NumeralData{TNumeral.value = c}:-       _) -> Just . Token AmountOfMoney $ withCents c fd+       _) -> Just $ Token AmountOfMoney $ withCents c fd       _ -> Nothing   } @@ -64,7 +63,7 @@     [ regex "omtrent|cirka|rundt|ca"     , Predicate isMoneyWithValue     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (_:token:_) -> Just token       _ -> Nothing   }@@ -73,9 +72,10 @@ ruleCent = Rule   { name = "cent"   , pattern =-    [ regex "cents?|penn(y|ies)|(ø)re"+    [ regex "cent(?:\\b|s)|\\bc\\b|pen(?:ce|ny|nies)|\\bp\\b|(?:ø|ö)rer?|fen|haleru|groszy|pais(?:e|a)\+           \|centesim(?:o|i)|centimes?|\\bct?\\b|\\brp?\\b|rap(?:pen)?s?|satang"     ]-  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly Cent   }  ruleIntersectXCents :: Rule@@ -85,26 +85,10 @@     [ Predicate isWithoutCents     , Predicate isCents     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token AmountOfMoney fd:        Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just c}:-       _) -> Just . Token AmountOfMoney $ withCents c fd-      _ -> Nothing-  }--ruleIntersectXCentsWithAnd :: Rule-ruleIntersectXCentsWithAnd = Rule-  { name = "intersect (X cents) with and"-  , pattern =-    [ Predicate isWithoutCents-    , regex "og"-    , Predicate isCents-    ]-  , prod = \tokens -> case tokens of-      (Token AmountOfMoney fd:-       _:-       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just c}:-       _) -> Just . Token AmountOfMoney $ withCents c fd+       _) -> Just $ Token AmountOfMoney $ withCents c fd       _ -> Nothing   } @@ -112,18 +96,18 @@ ruleNok = Rule   { name = "NOK"   , pattern =-    [ regex "kr(oner)?"+    [ regex "(?:norske? ?)?kr(?:oner?)?"     ]-  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly NOK+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly NOK   }  rulePound :: Rule rulePound = Rule   { name = "£"   , pattern =-    [ regex "pund?"+    [ regex "po?und?s?"     ]-  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly Pound   }  ruleIntersectAndXCents :: Rule@@ -134,11 +118,11 @@     , regex "og"     , Predicate isCents     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token AmountOfMoney fd:        _:        Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just c}:-       _) -> Just . Token AmountOfMoney $ withCents c fd+       _) -> Just $ Token AmountOfMoney $ withCents c fd       _ -> Nothing   } @@ -149,10 +133,10 @@     [ Predicate isWithoutCents     , Predicate isNatural     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token AmountOfMoney fd:        Token Numeral NumeralData{TNumeral.value = c}:-       _) -> Just . Token AmountOfMoney $ withCents c fd+       _) -> Just $ Token AmountOfMoney $ withCents c fd       _ -> Nothing   } @@ -162,9 +146,171 @@   , pattern =     [ regex "dirhams?"     ]-  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly AED+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly AED   } +ruleSEK :: Rule+ruleSEK = Rule+  { name = "SEK"+  , pattern =+    [ regex "(?:svenske? )?kron(?:a|or)|svenske? kr(?:oner?)?"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly SEK+  }++ruleGBP :: Rule+ruleGBP = Rule+  { name = "GBP"+  , pattern =+    [ regex "(?:britiske?|engelske?) po?unds?"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly GBP+  }++ruleDKK :: Rule+ruleDKK = Rule+  { name = "DKK"+  , pattern =+    [ regex "danske? kr(?:oner?)?"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly DKK+  }++ruleUSD :: Rule+ruleUSD = Rule+  { name = "USD"+  , pattern =+    [ regex "amerikanske? dollars?"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly USD+  }++ruleAUD :: Rule+ruleAUD = Rule+  { name = "AUD"+  , pattern =+    [ regex "australske? dollars?"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly AUD+  }++ruleCAD :: Rule+ruleCAD = Rule+  { name = "CAD"+  , pattern =+    [ regex "(?:k|c)anadiske? dollars?"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly CAD+  }++ruleCHF :: Rule+ruleCHF = Rule+  { name = "CHF"+  , pattern =+    [ regex "sveitsiske? francs?"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly CHF+  }++ruleCNY :: Rule+ruleCNY = Rule+  { name = "CNY"+  , pattern =+    [ regex "(?:kinesiske? )?(?:yuan|renminbi)"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly CNY+  }++ruleCZK :: Rule+ruleCZK = Rule+  { name = "CZK"+  , pattern =+    [ regex "(?:tsjekkiske? )?koruna"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly CZK+  }++ruleHKD :: Rule+ruleHKD = Rule+  { name = "HKD"+  , pattern =+    [ regex "hong kong dollars?"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly HKD+  }++ruleINR :: Rule+ruleINR = Rule+  { name = "INR"+  , pattern =+    [ regex "(?:indiske? )?rup(?:i(?:er)?|ees?)"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly INR+  }++ruleJPY :: Rule+ruleJPY = Rule+  { name = "JPY"+  , pattern =+    [ regex "japanske? yen"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly JPY+  }++ruleNZD :: Rule+ruleNZD = Rule+  { name = "NZD"+  , pattern =+    [ regex "(?:nz|new zealand(?:ske)?) dollars?"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly NZD+  }++rulePKR :: Rule+rulePKR = Rule+  { name = "PKR"+  , pattern =+    [ regex "pakistanske? rup(?:i(?:er)?|ees?)"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly PKR+  }++rulePLN :: Rule+rulePLN = Rule+  { name = "PLN"+  , pattern =+    [ regex "(?:polske? )?(?:z|s)?lotys?"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly PLN+  }++ruleSGD :: Rule+ruleSGD = Rule+  { name = "SGD"+  , pattern =+    [ regex "singapor(?:e|ske?) dollars?"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly SGD+  }++ruleTHB :: Rule+ruleTHB = Rule+  { name = "THB"+  , pattern =+    [ regex "(?:thai(?:land(?:ske?)?)? )?b(?:ah|ha)t"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly THB+  }++ruleZAR :: Rule+ruleZAR = Rule+  { name = "ZAR"+  , pattern =+    [ regex "(?:sør(?: |-)?afrika(?:nske?)? )?rand"+    ]+  , prod = const $ Just $ Token AmountOfMoney $ currencyOnly ZAR+  }+ rules :: [Rule] rules =   [ ruleUnitAmount@@ -175,7 +321,24 @@   , ruleIntersectAndNumeral   , ruleIntersectAndXCents   , ruleIntersectXCents-  , ruleIntersectXCentsWithAnd   , ruleNok   , rulePound+  , ruleSEK+  , ruleDKK+  , ruleUSD+  , ruleAUD+  , ruleCAD+  , ruleGBP+  , ruleCHF+  , ruleCNY+  , ruleCZK+  , ruleHKD+  , ruleINR+  , ruleJPY+  , ruleNZD+  , rulePKR+  , rulePLN+  , ruleSGD+  , ruleTHB+  , ruleZAR   ]
Duckling/AmountOfMoney/NL/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -47,6 +46,8 @@              [ "$10K"              , "10k$"              , "$10000"+             , "$10.000"+             , "$10.000,00"              , "10000,00 $"              ]   , examples (simple USD 3.14)
Duckling/AmountOfMoney/NL/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/AmountOfMoney/PT/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/AmountOfMoney/PT/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/AmountOfMoney/RO/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/AmountOfMoney/RO/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/AmountOfMoney/RU/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -140,6 +139,15 @@              , "42RM"              , "RM42"              , "MYR42"+             ]+  , examples (simple UAH 3.04)+             [ "UAH 3.04"+             , "UAH3.04"+             , "3.04 грн"+             , "грн 3.04"+             , "₴3.04"+             , "₴ 3.04"+             , "3.04₴"              ]   , examples (between Dollar (10, 20))              [ "между 10 и 20 долларами"
Duckling/AmountOfMoney/RU/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -97,6 +96,15 @@   , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Unnamed   } +ruleHryvnia :: Rule+ruleHryvnia = Rule+  { name = "Hryvnia"+  , pattern =+    [ regex "грн"+    ]+  , prod = \_ -> Just $ Token AmountOfMoney $ currencyOnly UAH+  }+ ruleIntersectAndXCents :: Rule ruleIntersectAndXCents = Rule   { name = "intersect (and X cents)"@@ -304,6 +312,7 @@   , ruleCent   , ruleDollar   , ruleEUR+  , ruleHryvnia   , ruleIntersect   , ruleIntersectAndNumeral   , ruleIntersectAndXCents
Duckling/AmountOfMoney/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -41,12 +40,15 @@   , ("cad", CAD)   , ("¢", Cent)   , ("c", Cent)+  , ("chf", CHF)   , ("cny", CNY)+  , ("czk", CZK)   , ("rmb", CNY)   , ("yuan", CNY)   , ("$", Dollar)   , ("dinar", Dinar)   , ("dinars", Dinar)+  , ("dkk", DKK)   , ("dollar", Dollar)   , ("dollars", Dollar)   , ("egp", EGP)@@ -60,9 +62,13 @@   , ("€uros", EUR)   , ("€urs", EUR)   , ("gbp", GBP)+  , ("gel", GEL)+  , ("hkd", HKD)   , ("hrk", HRK)   , ("idr", IDR)   , ("ils", ILS)+  , ("₪", ILS)+  , ("nis", ILS)   , ("inr", INR)   , ("iqd", IQD)   , ("rs", INR)@@ -73,15 +79,23 @@   , ("jod", JOD)   , ("¥", JPY)   , ("jpy", JPY)+  , ("lari", GEL)+  , ("\x20BE", GEL)   , ("yen", JPY)   , ("krw", KRW)   , ("kwd", KWD)   , ("lbp", LBP)   , ("mad", MAD)+  , ("mnt", MNT)   , ("myr", MYR)   , ("rm", MYR)+  , ("₮", MNT)+  , ("tugrik", MNT)+  , ("tugriks", MNT)   , ("nok", NOK)   , ("nzd", NZD)+  , ("pkr", PKR)+  , ("pln", PLN)   , ("£", Pound)   , ("pt", PTS)   , ("pta", PTS)@@ -100,17 +114,24 @@   , ("sgd", SGD)   , ("shekel", ILS)   , ("shekels", ILS)+  , ("thb", THB)   , ("ttd", TTD)+  , ("₴", UAH)+  , ("uah", UAH)   , ("usd", USD)   , ("us$", USD)   , ("vnd", VND)+  , ("zar", ZAR)+  , ("tl", TRY)+  , ("lira", TRY)+  , ("₺", TRY)   ]  ruleCurrencies :: Rule ruleCurrencies = Rule   { name = "currencies"   , pattern =-    [ regex "(aed|aud|bgn|brl|byn|¢|c|cad|cny|\\$|dinars?|dollars?|egp|(e|€)uro?s?|€|gbp|hrk|idr|ils|inr|iqd|jmd|jod|¥|jpy|krw|kwd|lbp|mad|myr|rm|nok|nzd|£|pta?s?|qar|₽|rs\\.?|riy?als?|ron|rub|rupees?|sar|sek|sgb|shekels?|ttd|us(d|\\$)|vnd|yen|yuan)"+    [ regex "(aed|aud|bgn|brl|byn|¢|cad|chf|cny|c|\\$|dinars?|dkk|dollars?|egp|(e|€)uro?s?|€|gbp|gel|\x20BE|hkd|hrk|idr|ils|₪|inr|iqd|jmd|jod|¥|jpy|lari|krw|kwd|lbp|mad|₮|mnt|tugriks?|myr|rm|nis|nok|nzd|£|pkr|pln|pta?s?|qar|₽|rs\\.?|riy?als?|ron|rub|rupees?|sar|sek|sgb|shekels?|thb|ttd|₴|uah|us(d|\\$)|vnd|yen|yuan|zar|tl|lira|₺)"     ]   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (match:_)):_) -> do@@ -133,8 +154,21 @@       _ -> Nothing   } +ruleAmountLatent :: Rule+ruleAmountLatent = Rule+  { name = "<amount> (latent)"+  , pattern =+    [ Predicate isPositive+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = v}:_) ->+        Just . Token AmountOfMoney . mkLatent $ valueOnly v+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleAmountUnit+  , ruleAmountLatent   , ruleCurrencies   ]
Duckling/AmountOfMoney/SV/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/AmountOfMoney/SV/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
+ Duckling/AmountOfMoney/TR/Corpus.hs view
@@ -0,0 +1,55 @@+-- 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.AmountOfMoney.TR.Corpus+  ( corpus+  ) where++import Data.String (fromString)+import Prelude++import Duckling.AmountOfMoney.Types+import Duckling.Testing.Types+import Duckling.Locale+import Duckling.Resolve++corpus :: Corpus+corpus = (testContext {locale = makeLocale TR Nothing}, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (simple TRY 10000)+             [ "10 bin lira"+             , "on bin lira"+             , "10000 lira"+             ]+  , examples (simple TRY 1)+             [ "bir lira"+             , "1 lira"+             ]+  , examples (simple Cent 10)+             [ "on kuruş"+             , "10 kuruş"+             ]+  , examples (simple Cent 25)+             [ "25 kuruş"+             , "yirmi beş kuruş"+             ]+  , examples (simple Cent 5)+             [ "beş kuruş"+             , "5 kuruş"+             ]+  , examples (simple Cent 66)+             [ "altmış altı kuruş"+             , "66 kuruş"+             ]+  , examples (simple TRY 100.75)+             [ "yüz lira yetmiş beş kuruş"+             , "100 lira 75 kuruş"+             ]+  ]
+ Duckling/AmountOfMoney/TR/Rules.hs view
@@ -0,0 +1,160 @@+-- 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.AmountOfMoney.TR.Rules+  ( rules+  ) where++import Data.String (fromString)+import Prelude++import Duckling.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types (Currency(..), AmountOfMoneyData (..))+import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (isNatural, isPositive)+import Duckling.Numeral.Types (NumeralData (..))+import Duckling.Types+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import qualified Duckling.Numeral.Types as TNumeral++ruleUnitAmount :: Rule+ruleUnitAmount = Rule+  { name = "<unit> <amount>"+  , pattern =+    [ Predicate isCurrencyOnly+    , Predicate isPositive+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.currency = c}:+       Token Numeral NumeralData{TNumeral.value = v}:+       _) -> Just $ Token AmountOfMoney $ withValue v $ currencyOnly c+      _ -> Nothing+  }++rulePounds :: Rule+rulePounds = Rule+  { name = "₺"+  , pattern =+    [ regex "₺"+    ]+  , prod = \_ -> Just $ Token AmountOfMoney $ currencyOnly TRY+  }++ruleCent :: Rule+ruleCent = Rule+  { name = "cent"+  , pattern =+    [ regex "kuruş?"+    ]+  , prod = \_ -> Just $ Token AmountOfMoney $ currencyOnly Cent+  }++ruleADollarCoin :: Rule+ruleADollarCoin = Rule+  { name = "a <dollar coin>"+  , pattern =+    [ regex "kuruş"+    , Predicate isDollarCoin+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token AmountOfMoney fd:+       _) -> Just $ Token AmountOfMoney fd+      _ -> Nothing+  }++ruleNumDollarCoins :: Rule+ruleNumDollarCoins = Rule+  { name = "X <dollar coins>"+  , pattern =+    [ Predicate isNatural+    , Predicate isDollarCoin+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = c}:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just d,+                                             TAmountOfMoney.currency = cur}:+       _) -> Just $ Token AmountOfMoney $ withValue (c * d) $ currencyOnly cur+      _ -> Nothing+  }++ruleIntersectAndXCents :: Rule+ruleIntersectAndXCents = Rule+  { name = "intersect (and X cents)"+  , pattern =+    [ Predicate isWithoutCents+    , regex "(lira|tl)"+    , Predicate isCents+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just c}:+       _) -> Just $ Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isWithoutCents+    , Predicate isNatural+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token Numeral NumeralData{TNumeral.value = c}:+       _) -> Just $ Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleIntersectAndNumeral :: Rule+ruleIntersectAndNumeral = Rule+  { name = "intersect (and number)"+  , pattern =+    [ Predicate isWithoutCents+    , regex "(lira|tl)"+    , Predicate isNatural+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token Numeral NumeralData{TNumeral.value = c}:+       _) -> Just $ Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleIntersectXCents :: Rule+ruleIntersectXCents = Rule+  { name = "intersect (X cents)"+  , pattern =+    [ Predicate isWithoutCents+    , Predicate isCents+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just c}:+       _) -> Just $ Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleUnitAmount+  , ruleCent+  , ruleADollarCoin+  , ruleNumDollarCoins+  , ruleIntersect+  , ruleIntersectAndNumeral+  , ruleIntersectAndXCents+  , ruleIntersectXCents+  , rulePounds+  ]
Duckling/AmountOfMoney/Types.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE DeriveAnyClass #-}@@ -23,7 +22,7 @@ import Prelude import qualified Data.HashMap.Strict as H -import Duckling.Resolve (Resolve(..))+import Duckling.Resolve (Resolve(..), Options(..))  data Currency   -- ambiguous@@ -42,10 +41,14 @@   | BRL   | BYN   | CAD+  | CHF   | CNY+  | CZK+  | DKK   | EGP   | EUR   | GBP+  | HKD   | HRK   | IDR   | ILS@@ -54,13 +57,17 @@   | JMD   | JOD   | JPY+  | GEL   | KRW   | KWD   | LBP   | MAD+  | MNT   | MYR   | NOK   | NZD+  | PKR+  | PLN   | PTS   | QAR   | RON@@ -68,9 +75,13 @@   | SAR   | SEK   | SGD+  | THB   | TTD   | USD   | VND+  | ZAR+  | UAH+  | TRY   deriving (Eq, Generic, Hashable, Show, Ord, NFData)  instance ToJSON Currency where@@ -88,10 +99,14 @@   toJSON BRL     = "BRL"   toJSON BYN     = "BYN"   toJSON CAD     = "CAD"+  toJSON CHF     = "CHF"   toJSON CNY     = "CNY"+  toJSON CZK     = "CZK"+  toJSON DKK     = "DKK"   toJSON EGP     = "EGP"   toJSON EUR     = "EUR"   toJSON GBP     = "GBP"+  toJSON HKD     = "HKD"   toJSON HRK     = "HRK"   toJSON IDR     = "IDR"   toJSON ILS     = "ILS"@@ -100,47 +115,71 @@   toJSON JMD     = "JMD"   toJSON JOD     = "JOD"   toJSON JPY     = "JPY"+  toJSON GEL     = "GEL"   toJSON KRW     = "KRW"   toJSON KWD     = "KWD"   toJSON LBP     = "LBP"   toJSON MAD     = "MAD"+  toJSON MNT     = "MNT"   toJSON MYR     = "MYR"   toJSON NOK     = "NOK"   toJSON NZD     = "NZD"   toJSON PTS     = "PTS"+  toJSON PKR     = "PKR"+  toJSON PLN     = "PLN"   toJSON QAR     = "QAR"   toJSON RON     = "RON"   toJSON RUB     = "RUB"   toJSON SAR     = "SAR"   toJSON SEK     = "SEK"   toJSON SGD     = "SGD"+  toJSON THB     = "THB"   toJSON TTD     = "TTD"   toJSON USD     = "USD"   toJSON VND     = "VND"+  toJSON ZAR     = "ZAR"+  toJSON UAH     = "UAH"+  toJSON TRY     = "TRY"  data AmountOfMoneyData = AmountOfMoneyData   { value    :: Maybe Double   , currency :: Currency   , minValue :: Maybe Double   , maxValue :: Maybe Double+  , latent   :: Bool   }   deriving (Eq, Generic, Hashable, Show, Ord, NFData)  instance Resolve AmountOfMoneyData where   type ResolvedValue AmountOfMoneyData = AmountOfMoneyValue+  resolve _ Options {withLatent = False} AmountOfMoneyData {latent = True} =+    Nothing   resolve _ _ AmountOfMoneyData {value = Nothing, minValue = Nothing-                              , maxValue = Nothing} = Nothing-  resolve _ _ AmountOfMoneyData {value = Just value, currency} =-    Just (simple currency value, False)+                              , maxValue = Nothing} =+    Nothing+  resolve _ _ AmountOfMoneyData {value = Just value, currency, latent} =+    Just (simple currency value, latent)   resolve _ _ AmountOfMoneyData {value = Nothing, currency = c-                              , minValue = Just from, maxValue = Just to} =-    Just (between c (from, to), False)+                              , minValue = Just from, maxValue = Just to+                              , latent} =+    Just (between c (from, to), latent)   resolve _ _ AmountOfMoneyData {value = Nothing, currency = c-                              , minValue = Just v, maxValue = Nothing} =-    Just (above c v, False)+                              , minValue = Just v, maxValue = Nothing+                              , latent} =+    Just (above c v, latent)   resolve _ _ AmountOfMoneyData {value = Nothing, currency = c-                              , minValue = Nothing, maxValue = Just v} =-    Just (under c v, False)+                              , minValue = Nothing, maxValue = Just v+                              , latent} =+    Just (under c v, latent)++amountOfMoneyData' :: AmountOfMoneyData+amountOfMoneyData' = AmountOfMoneyData+  { value = Nothing+  , currency = Unnamed+  , minValue = Nothing+  , maxValue = Nothing+  , latent = False+  }  data IntervalDirection = Above | Under   deriving (Eq, Generic, Hashable, Ord, Show, NFData)
Duckling/AmountOfMoney/VI/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -100,5 +99,40 @@   , examples (simple AED 1)              [ "1 AED."              , "1 dirham"+             ]+  , examples (between VND (1000, 2000))+             [ "giữa 1000 và 2000 đồng"+             , "giữa 1000 đồng và 2000 đồng"+             , "từ 1000 đồng đến 2000 đồng"+             , "từ 1000 VNĐ tới 2000 VNĐ"+             , "từ 1000 đến 2000 đồng"+             , "khoảng 1000-2000 đồng"+             , "khoảng chừng từ 1000 đến 2000 đồng"+             , "tầm khoảng 1000 tới 2000 đồng"+             , "xấp xỉ VND1000-VND2000"+             , "1000-2000 đồng"+             ]+  , examples (between Dollar (1.1, 1.3))+             [ "giữa 1,1 và 1,3 đô la"+             , "từ 1 phẩy 1 đến một chấm ba đô la"+             ]+  , examples (under VND 7000)+             [ "dưới bảy ngàn đồng"+             , "ít hơn bảy nghìn đồng"+             , "kém hơn 7k đồng"+             , "không tới 7000 đồng"+             , "không cao hơn 7000 đồng"+             , "không hơn 7.000 đồng"+             , "không quá 7.000 đồng"+             , "từ 7000 đồng trở xuống"+             ]+  , examples (above Dollar 1.42)+             [ "nhiều hơn 1 đô la và bốn mươi hai xen"+             , "ít nhất $1,42"+             , "hơn 1,42 đô la"+             , "trên một đô la và 42 xu"+             , "không ít hơn 1,42 đô la"+             , "cao hơn $1,42"+             , "từ $1,42 trở lên"              ]   ]
Duckling/AmountOfMoney/VI/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -45,7 +44,7 @@ ruleNg = Rule   { name = "đồng"   , pattern =-    [ regex "đồng?"+    [ regex "đ(ồng)?"     ]   , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly VND   }@@ -54,7 +53,7 @@ ruleDollar = Rule   { name = "$"   , pattern =-    [ regex "đô la|đô mỹ|đ(ô)?"+    [ regex "đô( la)?( mỹ)?"     ]   , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Dollar   }@@ -63,7 +62,7 @@ ruleVnd = Rule   { name = "VNĐ"   , pattern =-    [ regex "vn(Đ|\\$)"+    [ regex "vn(Đ|D|\\$)"     ]   , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly VND   }@@ -72,7 +71,7 @@ ruleCent = Rule   { name = "cent"   , pattern =-    [ regex "xen|xu?|penn(y|ies)"+    [ regex "xen|xu|cắc|penn(y|ies)"     ]   , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent   }@@ -81,7 +80,7 @@ rulePounds = Rule   { name = "£"   , pattern =-    [ regex "pounds?"+    [ regex "pounds?|pao"     ]   , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound   }@@ -93,7 +92,7 @@     [ Predicate isWithoutCents     , Predicate isNatural     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token AmountOfMoney fd:        Token Numeral NumeralData{TNumeral.value = c}:        _) -> Just . Token AmountOfMoney $ withCents c fd@@ -108,7 +107,7 @@     , regex "và"     , Predicate isNatural     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token AmountOfMoney fd:        _:        Token Numeral NumeralData{TNumeral.value = c}:@@ -123,7 +122,7 @@     [ Predicate isWithoutCents     , Predicate isCents     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token AmountOfMoney fd:        Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just c}:        _) -> Just . Token AmountOfMoney $ withCents c fd@@ -138,7 +137,7 @@     , regex "và"     , Predicate isCents     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token AmountOfMoney fd:        _:        Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just c}:@@ -155,6 +154,158 @@   , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly AED   } +rulePrecision :: Rule+rulePrecision = Rule+  { name = "about|exactly <amount-of-money>"+  , pattern =+    [ regex "đúng|chính xác|khoảng( chừng)?|tầm|xấp xỉ|gần"+    , Predicate isMoneyWithValue+    ]+  , prod = \case+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleIntervalBetweenNumeral :: Rule+ruleIntervalBetweenNumeral = Rule+  { name = "between|from <numeral> to|and <amount-of-money>"+  , pattern =+    [ regex "từ|giữa|khoảng"+    , Predicate isPositive+    , regex "đến|tới|và"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (_:+       Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) | from < to ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalBetween :: Rule+ruleIntervalBetween = Rule+  { name = "từ|giữa <amount-of-money> đến|tới|và <amount-of-money>"+  , pattern =+    [ regex "từ|giữa"+    , Predicate isSimpleAmountOfMoney+    , regex "đến|tới|và"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just from,+                  TAmountOfMoney.currency = c1}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c2}:+       _) | from < to && c1 == c2 ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c1+      _ -> Nothing+  }++ruleIntervalNumeralDash :: Rule+ruleIntervalNumeralDash = Rule+  { name = "<numeral> - <amount-of-money>"+  , pattern =+    [ Predicate isNatural+    , regex "-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) | from < to->+         Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalDash :: Rule+ruleIntervalDash = Rule+  { name = "<amount-of-money> - <amount-of-money>"+  , pattern =+    [ Predicate isSimpleAmountOfMoney+    , regex "-"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just from,+                  TAmountOfMoney.currency = c1}:+       _:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c2}:+       _) | from < to && c1 == c2 ->+        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c1+      _ -> Nothing+  }++ruleIntervalMax :: Rule+ruleIntervalMax = Rule+  { name = "under/less/lower/no more than <amount-of-money>"+  , pattern =+    [ regex "dưới|(bé|ít|thấp|kém|không( cao| nhiều)?) hơn|không (đến|tới|quá)|(nhiều|cao) nhất"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) -> Just . Token AmountOfMoney . withMax to $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalMax2 :: Rule+ruleIntervalMax2 = Rule+  { name = "under <amount-of-money>"+  , pattern =+    [ regex "từ"+    , Predicate isSimpleAmountOfMoney+    , regex "trở xuống"+    ]+  , prod = \case+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) -> Just . Token AmountOfMoney . withMax to $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalMin :: Rule+ruleIntervalMin = Rule+  { name = "over/above/at least/more than <amount-of-money>"+  , pattern =+    [ regex "trên|(lớn |nhiều |cao |không (thấp|ít|kém) )?hơn|(ít|thấp) nhất"+    , Predicate isSimpleAmountOfMoney+    ]+  , prod = \case+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) -> Just . Token AmountOfMoney . withMin to $ currencyOnly c+      _ -> Nothing+  }++ruleIntervalMin2 :: Rule+ruleIntervalMin2 = Rule+  { name = "above <amount-of-money>"+  , pattern =+    [ regex "từ"+    , Predicate isSimpleAmountOfMoney+    , regex "trở lên"+    ]+  , prod = \case+      (_:+       Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,+                  TAmountOfMoney.currency = c}:+       _) -> Just . Token AmountOfMoney . withMin to $ currencyOnly c+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleUnitAmount@@ -165,7 +316,16 @@   , ruleIntersectAndNumeral   , ruleIntersectVXXuxen   , ruleIntersectXXuxen+  , ruleIntervalBetweenNumeral+  , ruleIntervalBetween+  , ruleIntervalDash+  , ruleIntervalNumeralDash+  , ruleIntervalMax+  , ruleIntervalMax2+  , ruleIntervalMin+  , ruleIntervalMin2   , ruleNg   , rulePounds+  , rulePrecision   , ruleVnd   ]
Duckling/AmountOfMoney/ZH/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -29,12 +28,14 @@   [ examples (simple Cent 5)              [ "五分"              , "5分"+             , "五仙"              ]   , examples (simple Cent 20)              [ "20分"              , "二十分"              , "2角"              , "两毛"+             , "两毫"              ]   , examples (simple Cent 25)              [ "25分"@@ -45,11 +46,27 @@   , examples (simple Dollar 7)              [ "7块"              , "七元"+             , "七蚊"              ]+  , examples (simple Dollar 5.5)+             [ "五個半"+             ]+  , examples (simple Dollar 1.5)+             [ "個半"+             , "一個半"+             ]+  , examples (simple Dollar 1.9)+             [ "個九"+             ]   , examples (simple CNY 3.14)              [ "3.14人民币"              , "人民幣3.14"              ]+  , examples (simple HKD 3.14)+             [ "3.14港幣"+             , "港幣3.14"+             , "港幣三個一毫四"+             ]   , examples (under Dollar 1.2)              [ "1.2元以下"              , "最多一块二角"@@ -59,10 +76,12 @@              [ "3.04块以上"              , "至少三块四分"              , "至少三块零四"+             , "起碼三蚊零四"              ]   , examples (between Dollar (5.6, 5.78))              [ "5.6到5.78元"              , "五元六角-五元七毛八分"              , "五块六到五块七毛八"+             , "五蚊六毫至五蚊七毫八"              ]   ]
Duckling/AmountOfMoney/ZH/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -17,12 +16,11 @@ import Data.Maybe import Data.String import Prelude-import qualified Data.Text as Text  import Duckling.AmountOfMoney.Helpers import Duckling.AmountOfMoney.Types (Currency (..), AmountOfMoneyData (..)) import Duckling.Dimensions.Types-import Duckling.Numeral.Helpers (isNatural, isPositive, oneOf)+import Duckling.Numeral.Helpers (isNatural, isPositive, oneOf, numberBetween, decimalsToDouble) import Duckling.Numeral.Types (NumeralData (..)) import Duckling.Regex.Types import Duckling.Types@@ -35,7 +33,7 @@   , pattern =     [ regex "人民币|人民幣"     ]-  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly CNY+  , prod = \_ -> Just $ Token AmountOfMoney $ currencyOnly CNY   }  ruleCNYPrefix :: Rule@@ -47,17 +45,39 @@     ]   , prod = \case       (_:Token Numeral NumeralData{TNumeral.value = v}:_) ->-        Just . Token AmountOfMoney . withValue v $ currencyOnly CNY+        Just $ Token AmountOfMoney $ withValue v $ currencyOnly CNY       _ -> Nothing   } +ruleHKD :: Rule+ruleHKD = Rule+  { name = "HKD"+  , pattern =+    [ regex "港幣"+    ]+  , prod = \_ -> Just $ Token AmountOfMoney $ currencyOnly HKD+  }++ruleHKDPrefix :: Rule+ruleHKDPrefix = Rule+  { name = "hkd prefix"+  , pattern =+    [ regex "港幣"+    , Predicate isPositive+    ]+  , prod = \case+      (_:Token Numeral NumeralData{TNumeral.value = v}:_) ->+        Just $ Token AmountOfMoney $ withValue v $ currencyOnly HKD+      _ -> Nothing+  }+ ruleCent :: Rule ruleCent = Rule   { name = "cent"   , pattern =-    [ regex "分"+    [ regex "分|仙"     ]-  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  , prod = \_ -> Just $ Token AmountOfMoney $ currencyOnly Cent }  ruleDime :: Rule@@ -65,11 +85,11 @@   { name = "dime"   , pattern =     [ Predicate isPositive-    , regex "角|毛"+    , regex "角|毛|毫"     ]   , prod = \case       (Token Numeral NumeralData{TNumeral.value = v}:_) ->-        Just . Token AmountOfMoney $+        Just $ Token AmountOfMoney $         withCents (v * 10) $ currencyOnly Cent       _ -> Nothing   }@@ -78,9 +98,9 @@ ruleDollar = Rule   { name = "dollar"   , pattern =-    [ regex "元|圆|块"+    [ regex "元|圆|块|蚊|個"     ]-  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Dollar+  , prod = \_ -> Just $ Token AmountOfMoney $ currencyOnly Dollar   }  rulePrecision :: Rule@@ -118,7 +138,7 @@       (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just d}:        Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just c}:        _) ->-         Just . Token AmountOfMoney $ withCents (c + d) $ currencyOnly Cent+         Just $ Token AmountOfMoney $ withCents (c + d) $ currencyOnly Cent       _ -> Nothing   } @@ -132,10 +152,23 @@   , prod = \case       (Token AmountOfMoney fd:        Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just c}:-       _) -> Just . Token AmountOfMoney $ withCents c fd+       _) -> Just $ Token AmountOfMoney $ withCents c fd       _ -> Nothing   } +ruleIntersectDollarsAndAHalf :: Rule+ruleIntersectDollarsAndAHalf = Rule+  { name = "<amount-of-money> and a half"+  , pattern =+    [ Predicate $ and . sequence [isSimpleAmountOfMoney, isWithoutCents]+    , regex "半"+    ]+  , prod = \case+      (Token AmountOfMoney fd:_) ->+        Just $ Token AmountOfMoney $ withCents 50 fd+      _ -> Nothing+  }+ ruleIntersect :: Rule ruleIntersect = Rule   { name = "intersect (implicit 0 delimited cents)"@@ -147,7 +180,7 @@   , prod = \case       (Token AmountOfMoney fd:_:        Token Numeral NumeralData{TNumeral.value = c}:-       _) -> Just . Token AmountOfMoney $ withCents c fd+       _) -> Just $ Token AmountOfMoney $ withCents c fd       _ -> Nothing   } @@ -161,7 +194,7 @@   , prod = \case       (Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just v}:        Token Numeral NumeralData{TNumeral.value = c}:-       _) -> Just . Token AmountOfMoney $ withCents (v + c) $ currencyOnly Cent+       _) -> Just $ Token AmountOfMoney $ withCents (v + c) $ currencyOnly Cent       _ -> Nothing   } @@ -175,16 +208,38 @@   , prod = \case       (Token AmountOfMoney fd:        Token Numeral NumeralData{TNumeral.value = d}:-       _) -> Just . Token AmountOfMoney $ withCents (d * 10) fd+       _) -> Just $ Token AmountOfMoney $ withCents (d * 10) fd       _ -> Nothing   } +ruleOneDollarAndAHalf :: Rule+ruleOneDollarAndAHalf = Rule+  { name = "one dollar and a half (short form)"+  , pattern =+    [ regex "個半"+    ]+  , prod = \_ -> Just $ Token AmountOfMoney $ withValue 1.5 (currencyOnly Dollar)+  }++ruleOneDollarAnd :: Rule+ruleOneDollarAnd = Rule+  { name = "one dollar and x dimes (short form)"+  , pattern =+    [ regex "個"+    , numberBetween 1 10+    ]+  , prod = \case+      (_:Token Numeral NumeralData{TNumeral.value = v}:_) ->+        Just $ Token AmountOfMoney $ withValue (1 + decimalsToDouble(v)) (currencyOnly Dollar)+      _ -> Nothing+  }+ ruleIntervalNumeralDash :: Rule ruleIntervalNumeralDash = Rule   { name = "<numeral> - <amount-of-money>"   , pattern =     [ Predicate isPositive-    , regex "-|~|到"+    , regex "-|~|到|至"     , Predicate isSimpleAmountOfMoney     ]   , prod = \case@@ -193,7 +248,7 @@        Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,                   TAmountOfMoney.currency = c}:        _) | from < to ->-         Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c+         Just $ Token AmountOfMoney $ withInterval (from, to) $ currencyOnly c       _ -> Nothing   } @@ -202,7 +257,7 @@   { name = "<amount-of-money> - <amount-of-money>"   , pattern =     [ Predicate isSimpleAmountOfMoney-    , regex "-|~|到"+    , regex "-|~|到|至"     , Predicate isSimpleAmountOfMoney     ]   , prod = \case@@ -212,7 +267,7 @@        Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,                   TAmountOfMoney.currency = c2}:        _) | from < to && c1 == c2 ->-        Just . Token AmountOfMoney . withInterval (from, to) $ currencyOnly c1+        Just $ Token AmountOfMoney $ withInterval (from, to) $ currencyOnly c1       _ -> Nothing   } @@ -220,7 +275,7 @@ ruleIntervalBound = Rule   { name = "under/less/lower/no more than <amount-of-money> (最多|至少|最少)"   , pattern =-    [ regex "(最多|至少|最少)"+    [ regex "(最多|至少|最少|起碼)"     , Predicate isSimpleAmountOfMoney     ]   , prod = \case@@ -228,9 +283,10 @@        Token AmountOfMoney AmountOfMoneyData{TAmountOfMoney.value = Just to,                   TAmountOfMoney.currency = c}:        _) -> case match of-        "最多" -> Just . Token AmountOfMoney . withMax to $ currencyOnly c-        "最少" -> Just . Token AmountOfMoney . withMin to $ currencyOnly c-        "至少" -> Just . Token AmountOfMoney . withMin to $ currencyOnly c+        "最多" -> Just $ Token AmountOfMoney $ withMax to $ currencyOnly c+        "最少" -> Just $ Token AmountOfMoney $ withMin to $ currencyOnly c+        "至少" -> Just $ Token AmountOfMoney $ withMin to $ currencyOnly c+        "起碼" -> Just $ Token AmountOfMoney $ withMin to $ currencyOnly c         _ -> Nothing       _ -> Nothing   }@@ -247,8 +303,8 @@                   TAmountOfMoney.currency = c}:        Token RegexMatch (GroupMatch (match:_)):        _) -> case match of-        "以下" -> Just . Token AmountOfMoney . withMax to $ currencyOnly c-        "以上" -> Just . Token AmountOfMoney . withMin to $ currencyOnly c+        "以下" -> Just $ Token AmountOfMoney $ withMax to $ currencyOnly c+        "以上" -> Just $ Token AmountOfMoney $ withMin to $ currencyOnly c         _ -> Nothing       _ -> Nothing   }@@ -258,6 +314,8 @@   [ ruleCent   , ruleCNY   , ruleCNYPrefix+  , ruleHKD+  , ruleHKDPrefix   , ruleDime   , ruleDollar   , ruleIntersect@@ -265,10 +323,13 @@   , ruleIntersect3   , ruleIntersectDimesAndCents   , ruleIntersectDollarsAndDimesCents+  , ruleIntersectDollarsAndAHalf   , ruleIntervalDash   , ruleIntervalNumeralDash   , ruleIntervalBound   , ruleIntervalBound2   , rulePrecision   , rulePrecision2+  , ruleOneDollarAndAHalf+  , ruleOneDollarAnd   ]
Duckling/Api.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE NamedFieldPuns #-}@@ -36,22 +35,22 @@ import Duckling.Types  -- | Parses `input` and returns a curated list of entities found.-parse :: Text -> Context -> Options -> [Some Dimension] -> [Entity]+parse :: Text -> Context -> Options -> [Seal Dimension] -> [Entity] parse input ctx options = map (formatToken input) . analyze input ctx options .   HashSet.fromList -supportedDimensions :: HashMap Lang [Some Dimension]+supportedDimensions :: HashMap Lang [Seal Dimension] supportedDimensions =   HashMap.fromList [ (l, allDimensions l) | l <- [minBound..maxBound] ]  -- | Returns a curated list of resolved tokens found -- When `targets` is non-empty, returns only tokens of such dimensions.-analyze :: Text -> Context -> Options -> HashSet (Some Dimension)+analyze :: Text -> Context -> Options -> HashSet (Seal Dimension)   -> [ResolvedToken] analyze input context@Context{..} options targets =   rank (classifiers locale) targets   . filter (\Resolved{node = Node{token = (Token d _)}} ->-      HashSet.null targets || HashSet.member (This d) targets+      HashSet.null targets || HashSet.member (Seal d) targets     )   $ parseAndResolve (rulesFor locale targets) input context options 
Duckling/Core.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE NoRebindableSyntax #-}@@ -21,7 +20,8 @@   , Range(..)   , Region(..)   , ResolvedVal(..)-  , Some(..)+  , Seal(..)+  , withSeal   , fromName   , makeLocale   , toJText
+ Duckling/CreditCardNumber/Corpus.hs view
@@ -0,0 +1,75 @@+-- 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.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"+      , "41111111-1111-1111"+      , "371449635398430"+      , "3714496353-98431"+      , "6011111111111110"+      , "60111111-1111-1117"+      , "5555555555554440"+      , "55555555-5555-4444"+      , "30569309025900"+      , "3056930902-5904"+      ]++allExamples :: [Example]+allExamples = concat+  [ examples+      (CreditCardNumberValue "4111111111111111" Visa)+      [ "4111111111111111"+      , "4111-1111-1111-1111"+      ]+  , examples+      (CreditCardNumberValue "371449635398431" Amex)+      [ "371449635398431"+      , "3714-496353-98431"+      ]+  , examples+      (CreditCardNumberValue "6011111111111117" Discover)+      [ "6011111111111117"+      , "6011-1111-1111-1117"+      ]+  , examples+      (CreditCardNumberValue "5555555555554444" Mastercard)+      [ "5555555555554444"+      , "5555-5555-5555-4444"+      ]+  , examples+      (CreditCardNumberValue "30569309025904" DinerClub)+      [ "30569309025904"+      , "3056-930902-5904"+      ]+  , examples+      (CreditCardNumberValue "3530111333300000" Other)+      [ "3530111333300000" ]+  ]
+ Duckling/CreditCardNumber/Helpers.hs view
@@ -0,0 +1,123 @@+-- 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.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 = "(" ++ withoutDashes ++ "|" ++ withDashes ++")"+  where+    withoutDashes = "4[0-9]{15}"+    withDashes = "4[0-9]{3}-[0-9]{4}-[0-9]{4}-[0-9]{4}"++-- | American Express credit card regex informed by latest BIN info+amexCreditCardNumberRegex :: String+amexCreditCardNumberRegex = "(" ++ withoutDashes ++ "|" ++ withDashes ++")"+  where+    withoutDashes = "3[47][0-9]{13}"+    withDashes = "3[47][0-9]{2}-[0-9]{6}-[0-9]{5}"++-- | Discover credit card regex informed by latest BIN info+discoverCreditCardNumberRegex :: String+discoverCreditCardNumberRegex = "(" ++ withoutDashes ++ "|" ++ withDashes ++")"+  where+    withoutDashes = "6(?:011|[45][0-9]{2})[0-9]{12}"+    withDashes = "6(?:011|[45][0-9]{2})-[0-9]{4}-[0-9]{4}-[0-9]{4}"++-- | Mastercard credit card regex informed by latest BIN info+mastercardCreditCardNumberRegex :: String+mastercardCreditCardNumberRegex =+  "(" ++ withoutDashes ++ "|" ++ withDashes ++")"+  where+    withoutDashes = "5[1-5][0-9]{14}"+    withDashes = "5[1-5][0-9]{2}-[0-9]{4}-[0-9]{4}-[0-9]{4}"++-- | Diner Club credit card regex informed by latest BIN info+dinerClubCreditCardNumberRegex :: String+dinerClubCreditCardNumberRegex = "(" ++ withoutDashes ++ "|" ++ withDashes ++")"+  where+    withoutDashes = "3(?:0[0-5]|[68][0-9])[0-9]{11}"+    withDashes = "3(?:0[0-5]|[68][0-9])[0-9]-[0-9]{6}-[0-9]{4}"++-- -----------------------------------------------------------------+-- 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+                       }
+ Duckling/CreditCardNumber/Rules.hs view
@@ -0,0 +1,72 @@+-- 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.CreditCardNumber.Rules+  ( rules ) where++import Prelude+import Data.String+import Data.Text (Text)+import Data.Bool+import qualified Data.Text as T+import qualified Data.Char as C++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 (ccNumGroup:_)):_) ->+            bool+              Nothing+              (Just $ Token CreditCardNumber $ creditCard ccNum i)+              (isValidCreditCardNumber ccNum)+            where+              ccNum = T.filter C.isDigit ccNumGroup+          _ -> Nothing+      }
+ Duckling/CreditCardNumber/Types.hs view
@@ -0,0 +1,61 @@+-- 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 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+           ]
Duckling/Debug.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE NamedFieldPuns #-}@@ -37,20 +36,20 @@ -- ----------------------------------------------------------------- -- API -debug :: Locale -> Text -> [Some Dimension] -> IO [Entity]+debug :: Locale -> Text -> [Seal Dimension] -> IO [Entity] debug locale = debugCustom testContext {locale = locale} testOptions -allParses :: Locale -> Text -> [Some Dimension] -> IO [Entity]+allParses :: Locale -> Text -> [Seal Dimension] -> IO [Entity] allParses l sentence targets = debugTokens sentence $ parses l sentence targets -fullParses :: Locale -> Text -> [Some Dimension] -> IO [Entity]+fullParses :: Locale -> Text -> [Seal Dimension] -> IO [Entity] fullParses l sentence targets = debugTokens sentence .   filter (\Resolved{range = Range start end} -> start == 0 && end == n) $   parses l sentence targets   where     n = Text.length sentence -debugCustom :: Context -> Options -> Text -> [Some Dimension] -> IO [Entity]+debugCustom :: Context -> Options -> Text -> [Seal Dimension] -> IO [Entity] debugCustom context options sentence targets = debugTokens sentence .   analyze sentence context options $ HashSet.fromList targets @@ -60,12 +59,12 @@ -- ----------------------------------------------------------------- -- Internals -parses :: Locale -> Text -> [Some Dimension] -> [ResolvedToken]+parses :: Locale -> Text -> [Seal Dimension] -> [ResolvedToken] parses l sentence targets = flip filter tokens $   \Resolved{node = Node{token = (Token d _)}} ->     case targets of       [] -> True-      _ -> elem (This d) targets+      _ -> elem (Seal d) targets   where     tokens = parseAndResolve rules sentence testContext {locale = l} testOptions     rules = rulesFor l $ HashSet.fromList targets
Duckling/Dimensions.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -22,8 +21,11 @@ import Duckling.Locale import Duckling.Types import qualified Duckling.Dimensions.Common as CommonDimensions+import qualified Duckling.Dimensions.AF as AFDimensions import qualified Duckling.Dimensions.AR as ARDimensions import qualified Duckling.Dimensions.BG as BGDimensions+import qualified Duckling.Dimensions.BN as BNDimensions+import qualified Duckling.Dimensions.CA as CADimensions import qualified Duckling.Dimensions.CS as CSDimensions import qualified Duckling.Dimensions.DA as DADimensions import qualified Duckling.Dimensions.DE as DEDimensions@@ -31,6 +33,8 @@ import qualified Duckling.Dimensions.EN as ENDimensions import qualified Duckling.Dimensions.ES as ESDimensions import qualified Duckling.Dimensions.ET as ETDimensions+import qualified Duckling.Dimensions.FA as FADimensions+import qualified Duckling.Dimensions.FI as FIDimensions import qualified Duckling.Dimensions.FR as FRDimensions import qualified Duckling.Dimensions.GA as GADimensions import qualified Duckling.Dimensions.HE as HEDimensions@@ -38,10 +42,16 @@ import qualified Duckling.Dimensions.HR as HRDimensions import qualified Duckling.Dimensions.HU as HUDimensions import qualified Duckling.Dimensions.ID as IDDimensions+import qualified Duckling.Dimensions.IS as ISDimensions import qualified Duckling.Dimensions.IT as ITDimensions import qualified Duckling.Dimensions.JA as JADimensions import qualified Duckling.Dimensions.KA as KADimensions+import qualified Duckling.Dimensions.KM as KMDimensions+import qualified Duckling.Dimensions.KN as KNDimensions import qualified Duckling.Dimensions.KO as KODimensions+import qualified Duckling.Dimensions.LO as LODimensions+import qualified Duckling.Dimensions.ML as MLDimensions+import qualified Duckling.Dimensions.MN as MNDimensions import qualified Duckling.Dimensions.MY as MYDimensions import qualified Duckling.Dimensions.NB as NBDimensions import qualified Duckling.Dimensions.NE as NEDimensions@@ -50,44 +60,53 @@ import qualified Duckling.Dimensions.PT as PTDimensions import qualified Duckling.Dimensions.RO as RODimensions import qualified Duckling.Dimensions.RU as RUDimensions+import qualified Duckling.Dimensions.SK as SKDimensions import qualified Duckling.Dimensions.SV as SVDimensions+import qualified Duckling.Dimensions.SW as SWDimensions import qualified Duckling.Dimensions.TA as TADimensions+import qualified Duckling.Dimensions.TE as TEDimensions+import qualified Duckling.Dimensions.TH as THDimensions import qualified Duckling.Dimensions.TR as TRDimensions import qualified Duckling.Dimensions.UK as UKDimensions import qualified Duckling.Dimensions.VI as VIDimensions import qualified Duckling.Dimensions.ZH as ZHDimensions -allDimensions :: Lang -> [Some Dimension]++allDimensions :: Lang -> [Seal Dimension] allDimensions lang = CommonDimensions.allDimensions ++ langDimensions lang  -- | Augments `targets` with all dependent dimensions.-explicitDimensions :: HashSet (Some Dimension) -> HashSet (Some Dimension)+explicitDimensions :: HashSet (Seal Dimension) -> HashSet (Seal Dimension) explicitDimensions targets = HashSet.union targets deps   where     deps = HashSet.unions . map dependents $ HashSet.toList targets  -- | Ordinal depends on Numeral for JA, KO, and ZH.-dependents :: Some Dimension -> HashSet (Some Dimension)-dependents (This Distance) = HashSet.singleton (This Numeral)-dependents (This Duration) = HashSet.fromList [This Numeral, This TimeGrain]-dependents (This Numeral) = HashSet.empty-dependents (This Email) = HashSet.empty-dependents (This AmountOfMoney) = HashSet.singleton (This Numeral)-dependents (This Ordinal) = HashSet.singleton (This Numeral)-dependents (This PhoneNumber) = HashSet.empty-dependents (This Quantity) = HashSet.singleton (This Numeral)-dependents (This RegexMatch) = HashSet.empty-dependents (This Temperature) = HashSet.singleton (This Numeral)-dependents (This Time) =-  HashSet.fromList [This Numeral, This Duration, This Ordinal, This TimeGrain]-dependents (This TimeGrain) = HashSet.empty-dependents (This Url) = HashSet.empty-dependents (This Volume) = HashSet.singleton (This Numeral)-dependents (This (CustomDimension dim)) = dimDependents dim+dependents :: Seal Dimension -> HashSet (Seal Dimension)+dependents (Seal CreditCardNumber) = HashSet.empty+dependents (Seal Distance) = HashSet.singleton (Seal Numeral)+dependents (Seal Duration) = HashSet.fromList [Seal Numeral, Seal TimeGrain]+dependents (Seal Numeral) = HashSet.empty+dependents (Seal Email) = HashSet.empty+dependents (Seal AmountOfMoney) = HashSet.singleton (Seal Numeral)+dependents (Seal Ordinal) = HashSet.singleton (Seal Numeral)+dependents (Seal PhoneNumber) = HashSet.empty+dependents (Seal Quantity) = HashSet.singleton (Seal Numeral)+dependents (Seal RegexMatch) = HashSet.empty+dependents (Seal Temperature) = HashSet.singleton (Seal Numeral)+dependents (Seal Time) =+  HashSet.fromList [Seal Numeral, Seal Duration, Seal Ordinal, Seal TimeGrain]+dependents (Seal TimeGrain) = HashSet.empty+dependents (Seal Url) = HashSet.empty+dependents (Seal Volume) = HashSet.singleton (Seal Numeral)+dependents (Seal (CustomDimension dim)) = dimDependents dim -langDimensions :: Lang -> [Some Dimension]+langDimensions :: Lang -> [Seal Dimension]+langDimensions AF = AFDimensions.allDimensions langDimensions AR = ARDimensions.allDimensions langDimensions BG = BGDimensions.allDimensions+langDimensions BN = BNDimensions.allDimensions+langDimensions CA = CADimensions.allDimensions langDimensions CS = CSDimensions.allDimensions langDimensions DA = DADimensions.allDimensions langDimensions DE = DEDimensions.allDimensions@@ -95,6 +114,8 @@ langDimensions EN = ENDimensions.allDimensions langDimensions ES = ESDimensions.allDimensions langDimensions ET = ETDimensions.allDimensions+langDimensions FA = FADimensions.allDimensions+langDimensions FI = FIDimensions.allDimensions langDimensions FR = FRDimensions.allDimensions langDimensions GA = GADimensions.allDimensions langDimensions HE = HEDimensions.allDimensions@@ -102,10 +123,16 @@ langDimensions HR = HRDimensions.allDimensions langDimensions HU = HUDimensions.allDimensions langDimensions ID = IDDimensions.allDimensions+langDimensions IS = ISDimensions.allDimensions langDimensions IT = ITDimensions.allDimensions langDimensions JA = JADimensions.allDimensions langDimensions KA = KADimensions.allDimensions+langDimensions KM = KMDimensions.allDimensions+langDimensions KN = KNDimensions.allDimensions langDimensions KO = KODimensions.allDimensions+langDimensions LO = LODimensions.allDimensions+langDimensions ML = MLDimensions.allDimensions+langDimensions MN = MNDimensions.allDimensions langDimensions MY = MYDimensions.allDimensions langDimensions NB = NBDimensions.allDimensions langDimensions NE = NEDimensions.allDimensions@@ -114,8 +141,12 @@ langDimensions PT = PTDimensions.allDimensions langDimensions RO = RODimensions.allDimensions langDimensions RU = RUDimensions.allDimensions+langDimensions SK = SKDimensions.allDimensions langDimensions SV = SVDimensions.allDimensions+langDimensions SW = SWDimensions.allDimensions langDimensions TA = TADimensions.allDimensions+langDimensions TE = TEDimensions.allDimensions+langDimensions TH = THDimensions.allDimensions langDimensions TR = TRDimensions.allDimensions langDimensions UK = UKDimensions.allDimensions langDimensions VI = VIDimensions.allDimensions
+ Duckling/Dimensions/AF.hs view
@@ -0,0 +1,17 @@+-- 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.Dimensions.AF+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Seal Dimension]+allDimensions =+  [ Seal Numeral+  ]
Duckling/Dimensions/AR.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.AR@@ -12,13 +11,13 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Duration-  , This Numeral-  , This Ordinal-  , This Quantity-  , This Temperature-  , This Time-  , This Volume+  [ Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Quantity+  , Seal Temperature+  , Seal Time+  , Seal Volume   ]
Duckling/Dimensions/BG.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.BG@@ -12,10 +11,11 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Distance-  , This Duration-  , This Numeral-  , This Ordinal+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Time   ]
+ Duckling/Dimensions/BN.hs view
@@ -0,0 +1,17 @@+-- 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.Dimensions.BN+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Seal Dimension]+allDimensions =+  [ Seal Numeral+  ]
+ Duckling/Dimensions/CA.hs view
@@ -0,0 +1,17 @@+-- 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.Dimensions.CA+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Seal Dimension]+allDimensions =+  [ Seal Numeral+  ]
Duckling/Dimensions/CS.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.CS@@ -12,8 +11,8 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Distance-  , This Numeral+  [ Seal Distance+  , Seal Numeral   ]
Duckling/Dimensions/Common.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.Common@@ -12,11 +11,12 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This AmountOfMoney-  , This Email-  , This Numeral-  , This PhoneNumber-  , This Url+  [ Seal AmountOfMoney+  , Seal CreditCardNumber+  , Seal Email+  , Seal Numeral+  , Seal PhoneNumber+  , Seal Url   ]
Duckling/Dimensions/DA.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.DA@@ -12,10 +11,10 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Duration-  , This Numeral-  , This Ordinal-  , This Time+  [ Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Time   ]
Duckling/Dimensions/DE.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.DE@@ -12,10 +11,12 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Duration-  , This Numeral-  , This Ordinal-  , This Time+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Time+  , Seal Volume   ]
Duckling/Dimensions/EL.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.EL@@ -12,10 +11,10 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Duration-  , This Numeral-  , This Ordinal-  , This Time+  [ Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Time   ]
Duckling/Dimensions/EN.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.EN@@ -12,14 +11,14 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Distance-  , This Duration-  , This Numeral-  , This Ordinal-  , This Quantity-  , This Temperature-  , This Time-  , This Volume+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Quantity+  , Seal Temperature+  , Seal Time+  , Seal Volume   ]
Duckling/Dimensions/ES.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.ES@@ -12,13 +11,14 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Distance-  , This Duration-  , This Numeral-  , This Ordinal-  , This Temperature-  , This Time-  , This Volume+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Quantity+  , Seal Temperature+  , Seal Time+  , Seal Volume   ]
Duckling/Dimensions/ET.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.ET@@ -12,8 +11,8 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Numeral-  , This Ordinal+  [ Seal Numeral+  , Seal Ordinal   ]
+ Duckling/Dimensions/FA.hs view
@@ -0,0 +1,16 @@+-- 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.Dimensions.FA+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Seal Dimension]+allDimensions  =+  [ Seal Numeral+  ]
+ Duckling/Dimensions/FI.hs view
@@ -0,0 +1,16 @@+-- 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.Dimensions.FI+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Seal Dimension]+allDimensions  =+  [ Seal Numeral+  ]
Duckling/Dimensions/FR.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.FR@@ -12,14 +11,14 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Distance-  , This Duration-  , This Numeral-  , This Ordinal-  , This Quantity-  , This Temperature-  , This Time-  , This Volume+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Quantity+  , Seal Temperature+  , Seal Time+  , Seal Volume   ]
Duckling/Dimensions/GA.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.GA@@ -12,13 +11,13 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Distance-  , This Duration-  , This Numeral-  , This Ordinal-  , This Temperature-  , This Time-  , This Volume+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Temperature+  , Seal Time+  , Seal Volume   ]
Duckling/Dimensions/HE.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.HE@@ -12,10 +11,10 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Duration-  , This Numeral-  , This Ordinal-  , This Time+  [ Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Time   ]
Duckling/Dimensions/HI.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.HI@@ -12,9 +11,10 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Duration-  , This Numeral-  , This Ordinal+  [ Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Temperature   ]
Duckling/Dimensions/HR.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.HR@@ -12,14 +11,14 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Distance-  , This Duration-  , This Numeral-  , This Ordinal-  , This Quantity-  , This Temperature-  , This Time-  , This Volume+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Quantity+  , Seal Temperature+  , Seal Time+  , Seal Volume   ]
Duckling/Dimensions/HU.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.HU@@ -12,10 +11,10 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Duration-  , This Numeral-  , This Ordinal-  , This Time+  [ Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Time   ]
Duckling/Dimensions/ID.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.ID@@ -12,8 +11,8 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Numeral-  , This Ordinal+  [ Seal Numeral+  , Seal Ordinal   ]
+ Duckling/Dimensions/IS.hs view
@@ -0,0 +1,17 @@+-- 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.Dimensions.IS+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Seal Dimension]+allDimensions =+  [ Seal Numeral+  ]
Duckling/Dimensions/IT.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.IT@@ -12,12 +11,13 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Duration-  , This Numeral-  , This Ordinal-  , This Temperature-  , This Time-  , This Volume+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Temperature+  , Seal Time+  , Seal Volume   ]
Duckling/Dimensions/JA.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.JA@@ -12,10 +11,10 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Duration-  , This Numeral-  , This Ordinal-  , This Temperature+  [ Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Temperature   ]
Duckling/Dimensions/KA.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.KA@@ -12,6 +11,10 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Numeral ]+  [ Seal Numeral+  , Seal Ordinal+  , Seal Duration+  , Seal Time+  ]
+ Duckling/Dimensions/KM.hs view
@@ -0,0 +1,22 @@+-- 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.Dimensions.KM+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Seal Dimension]+allDimensions =+  [ Seal Distance+  , Seal Numeral+  , Seal Ordinal+  , Seal Quantity+  , Seal Temperature+  , Seal Volume+  ]
+ Duckling/Dimensions/KN.hs view
@@ -0,0 +1,17 @@+-- 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.Dimensions.KN+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Seal Dimension]+allDimensions =+  [ Seal Numeral+  ]
Duckling/Dimensions/KO.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.KO@@ -12,14 +11,14 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Distance-  , This Duration-  , This Numeral-  , This Ordinal-  , This Quantity-  , This Temperature-  , This Time-  , This Volume+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Quantity+  , Seal Temperature+  , Seal Time+  , Seal Volume   ]
+ Duckling/Dimensions/LO.hs view
@@ -0,0 +1,17 @@+-- 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.Dimensions.LO+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Seal Dimension]+allDimensions =+  [ Seal Numeral+  ]
+ Duckling/Dimensions/ML.hs view
@@ -0,0 +1,18 @@+-- 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.Dimensions.ML+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Seal Dimension]+allDimensions =+  [ Seal Numeral,+    Seal Ordinal+  ]
+ Duckling/Dimensions/MN.hs view
@@ -0,0 +1,23 @@+-- 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.Dimensions.MN+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Seal Dimension]+allDimensions =+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Quantity+  , Seal Temperature+  , Seal Volume+  ]
Duckling/Dimensions/MY.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.MY@@ -12,7 +11,7 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Numeral+  [ Seal Numeral   ]
Duckling/Dimensions/NB.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.NB@@ -12,10 +11,10 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Duration-  , This Numeral-  , This Ordinal-  , This Time+  [ Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Time   ]
Duckling/Dimensions/NE.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.NE@@ -12,7 +11,7 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Numeral+  [ Seal Numeral   ]
Duckling/Dimensions/NL.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.NL@@ -12,12 +11,13 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Distance-  , This Duration-  , This Numeral-  , This Ordinal-  , This Time-  , This Volume+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Quantity+  , Seal Time+  , Seal Volume   ]
Duckling/Dimensions/PL.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.PL@@ -12,10 +11,10 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Duration-  , This Numeral-  , This Ordinal-  , This Time+  [ Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Time   ]
Duckling/Dimensions/PT.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.PT@@ -12,14 +11,14 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Distance-  , This Duration-  , This Numeral-  , This Ordinal-  , This Quantity-  , This Temperature-  , This Time-  , This Volume+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Quantity+  , Seal Temperature+  , Seal Time+  , Seal Volume   ]
Duckling/Dimensions/RO.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.RO@@ -12,14 +11,14 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Distance-  , This Duration-  , This Numeral-  , This Ordinal-  , This Quantity-  , This Temperature-  , This Time-  , This Volume+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Quantity+  , Seal Temperature+  , Seal Time+  , Seal Volume   ]
Duckling/Dimensions/RU.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.RU@@ -12,12 +11,13 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Distance-  , This Duration-  , This Numeral-  , This Ordinal-  , This Quantity-  , This Volume+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Quantity+  , Seal Volume+  , Seal Time   ]
+ Duckling/Dimensions/SK.hs view
@@ -0,0 +1,18 @@+-- 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.Dimensions.SK+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Seal Dimension]+allDimensions =+  [ Seal Numeral+  ]
Duckling/Dimensions/SV.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.SV@@ -12,11 +11,11 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Distance-  , This Duration-  , This Numeral-  , This Ordinal-  , This Time+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Time   ]
+ Duckling/Dimensions/SW.hs view
@@ -0,0 +1,17 @@+-- 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.Dimensions.SW+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Seal Dimension]+allDimensions =+  [ Seal Numeral+  ]
Duckling/Dimensions/TA.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.TA@@ -12,7 +11,8 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Numeral+  [ Seal Numeral+  , Seal Ordinal   ]
+ Duckling/Dimensions/TE.hs view
@@ -0,0 +1,17 @@+-- 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.Dimensions.TE+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Seal Dimension]+allDimensions =+  [ Seal Numeral+  ]
+ Duckling/Dimensions/TH.hs view
@@ -0,0 +1,17 @@+-- 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.Dimensions.TH+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Seal Dimension]+allDimensions =+  [ Seal Numeral+  ]
Duckling/Dimensions/TR.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.TR@@ -12,12 +11,13 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Distance-  , This Duration-  , This Numeral-  , This Ordinal-  , This Temperature-  , This Volume+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Temperature+  , Seal Time+  , Seal Volume   ]
Duckling/Dimensions/Types.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -11,7 +10,7 @@   module Duckling.Dimensions.Types-  ( Some(..)+  ( Seal(..)   , Dimension(..)    , fromName@@ -19,7 +18,6 @@   ) where  import Data.Maybe-import Data.Some import Data.Text (Text) import Prelude import qualified Data.HashMap.Strict as HashMap@@ -29,6 +27,7 @@  toName :: Dimension a -> Text toName RegexMatch = "regex"+toName CreditCardNumber = "credit-card-number" toName Distance = "distance" toName Duration = "duration" toName Email = "email"@@ -44,20 +43,22 @@ toName Volume = "volume" toName (CustomDimension dim) = Text.pack (show dim) -fromName :: Text -> Maybe (Some Dimension)+fromName :: Text -> Maybe (Seal Dimension) fromName name = HashMap.lookup name m   where     m = HashMap.fromList-      [ ("amount-of-money", This AmountOfMoney)-      , ("distance", This Distance)-      , ("duration", This Duration)-      , ("email", This Email)-      , ("number", This Numeral)-      , ("ordinal", This Ordinal)-      , ("phone-number", This PhoneNumber)-      , ("quantity", This Quantity)-      , ("temperature", This Temperature)-      , ("time", This Time)-      , ("url", This Url)-      , ("volume", This Volume)+      [ ("amount-of-money", Seal AmountOfMoney)+      , ("credit-card-number", Seal CreditCardNumber)+      , ("distance", Seal Distance)+      , ("duration", Seal Duration)+      , ("email", Seal Email)+      , ("number", Seal Numeral)+      , ("ordinal", Seal Ordinal)+      , ("phone-number", Seal PhoneNumber)+      , ("quantity", Seal Quantity)+      , ("temperature", Seal Temperature)+      , ("time", Seal Time)+      , ("time-grain", Seal TimeGrain)+      , ("url", Seal Url)+      , ("volume", Seal Volume)       ]
Duckling/Dimensions/UK.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.UK@@ -12,8 +11,10 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Numeral-  , This Ordinal+  [ Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Time   ]
Duckling/Dimensions/VI.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.VI@@ -12,10 +11,10 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Duration-  , This Numeral-  , This Ordinal-  , This Time+  [ Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Time   ]
Duckling/Dimensions/ZH.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Dimensions.ZH@@ -12,13 +11,13 @@  import Duckling.Dimensions.Types -allDimensions :: [Some Dimension]+allDimensions :: [Seal Dimension] allDimensions =-  [ This Distance-  , This Duration-  , This Numeral-  , This Ordinal-  , This Quantity-  , This Temperature-  , This Time+  [ Seal Distance+  , Seal Duration+  , Seal Numeral+  , Seal Ordinal+  , Seal Quantity+  , Seal Temperature+  , Seal Time   ]
Duckling/Distance/BG/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Distance/BG/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Distance/CS/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Distance/CS/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
+ Duckling/Distance/DE/Corpus.hs view
@@ -0,0 +1,74 @@+-- 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.Distance.DE.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Distance.Types+import Duckling.Locale+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {locale = makeLocale DE Nothing}, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (simple Kilometre 3)+             [ "3 kilometer"+             , "3 km"+             , "3km"+             , "3,0 km"+             ]+  , examples (simple Mile 8)+             [ "acht meilen"+             , "8 meilen"+             ]+  , examples (simple Metre 9)+             [ "9m"+             ]+  , examples (simple Centimetre 2)+             [ "2cm"+             , "2 zentimeter"+             ]+  , examples (simple Inch 5)+             [ "5''"+             , "fünf zoll"+             , "5\""+             ]+  , examples (simple Metre 1.87)+             [ "1,87 meter"+             ]+  , examples (between Kilometre (3, 5))+             [ "zwischen 3 und 5 kilometern"+             , "von 3km bis 5km"+             , "um die 3-5 kilometer"+             , "etwa 3km-5km"+             , "3-5 kilometer"+             ]+  , examples (under Mile 3.5)+             [ "unter 3,5 meilen"+             , "weniger als 3,5meilen"+             --, "niedriger als dreikommafünf meilen"+             ]+  , examples (above Inch 5)+             [ "mehr als fünf zoll"+             , "mindestens 5''"+             , "über 5\""+             ]+  , examples (between Millimetre (5, 6))+             [ "zwischen 5 und sechs Millimetern"+             , "zwischen 5 und sechs millimeter"+             , "5-6 mm"+             ]+  ]
+ Duckling/Distance/DE/Rules.hs view
@@ -0,0 +1,172 @@+-- 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.DE.Rules (rules) where++import Data.String+import Data.Text (Text)+import Prelude++import Duckling.Dimensions.Types+import Duckling.Distance.Helpers+import Duckling.Distance.Types (DistanceData(..))+import qualified Duckling.Distance.Types as TDistance+import Duckling.Numeral.Helpers+import Duckling.Numeral.Types (NumeralData(..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Types++distances :: [(Text, String, TDistance.Unit)]+distances =+  [ -- Imperial+    ("miles", "meilen?", TDistance.Mile)+  , ("inch", "(\"|''|zoll)", TDistance.Inch)+              -- Metric+  , ("km", "k(ilo)?m(etern?)?", TDistance.Kilometre)+  , ("meters", "m(etern?)?", TDistance.Metre)+  , ("centimeters", "(cm|[zc]entimetern?)", TDistance.Centimetre)+  , ("millimeters", "(mm|millimetern?)", TDistance.Millimetre)+  ]++rulePrecision :: Rule+rulePrecision = Rule+  { name = "about|exactly <dist>"+  , pattern =+    [ regex "genau|exakt|präzise|ungefähr|(in )?etwa|nahe?( an)?|um( die)?|fast|rund|gut"+    , dimension Distance+    ]+  , prod = \case+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleDistances :: [Rule]+ruleDistances = map go distances+  where+    go :: (Text, String, TDistance.Unit) -> Rule+    go (name, regexPattern, u) = Rule+      { name = name+      , pattern = [ dimension Distance, regex regexPattern ]+      , prod = \case+          (Token Distance dd:_) -> Just . Token Distance $ withUnit u dd+          _ -> Nothing+      }++ruleIntervalBetweenNumeral :: Rule+ruleIntervalBetweenNumeral = Rule+  { name = "between|from <numeral> to|and <dist>"+  , pattern =+    [ regex "zwischen|von"+    , Predicate isPositive+    , regex "bis|und"+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (_:+       Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token Distance DistanceData{TDistance.value = Just to, TDistance.unit = Just u}:+       _) | from < to ->+        Just . Token Distance . withInterval (from, to) $ unitOnly u+      _ -> Nothing+  }++ruleIntervalBetween :: Rule+ruleIntervalBetween = Rule+  { name = "between|from <dist> to|and <dist>"+  , pattern =+    [ regex "zwischen|von"+    , Predicate isSimpleDistance+    , regex "und|bis"+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (_:+       Token Distance DistanceData{TDistance.value = Just from, TDistance.unit = Just u1}:+       _:+       Token Distance DistanceData{TDistance.value = Just to, TDistance.unit = Just u2}:+       _) | from < to && u1 == u2 ->+        Just . Token Distance . withInterval (from, to) $ unitOnly u1+      _ -> Nothing+  }++ruleIntervalNumeralDash :: Rule+ruleIntervalNumeralDash = Rule+  { name = "<numeral> - <dist>"+  , pattern =+    [ Predicate isPositive+    , regex "-"+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token Distance DistanceData{TDistance.value = Just to, TDistance.unit = Just u}:+       _) | from < to ->+         Just . Token Distance . withInterval (from, to) $ unitOnly u+      _ -> Nothing+  }++ruleIntervalDash :: Rule+ruleIntervalDash = Rule+  { name = "<dist> - <dist>"+  , pattern =+    [ Predicate isSimpleDistance+    , regex "-"+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (Token Distance DistanceData{TDistance.value = Just from, TDistance.unit = Just u1}:+       _:+       Token Distance DistanceData{TDistance.value = Just to, TDistance.unit = Just u2}:+       _) | from < to && u1 == u2 ->+        Just . Token Distance . withInterval (from, to) $ unitOnly u1+      _ -> Nothing+  }++ruleIntervalMax :: Rule+ruleIntervalMax = Rule+  { name = "under/less/lower/no more than <dist>"+  , pattern =+    [ regex "unter|höchstens|maximal|(weniger|nicht mehr) als"+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (_:+       Token Distance DistanceData{TDistance.value = Just to, TDistance.unit = Just u}:+       _) -> Just . Token Distance . withMax to $ unitOnly u+      _ -> Nothing+  }++ruleIntervalMin :: Rule+ruleIntervalMin = Rule+  { name = "over/above/at least/more than <dist>"+  , pattern =+    [ regex "über|(mehr|nicht weniger) als|mindestens|wenigstens|minimal"+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (_:+       Token Distance DistanceData{TDistance.value = Just to, TDistance.unit = Just u}:+       _) -> Just . Token Distance . withMin to $ unitOnly u+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleIntervalBetweenNumeral+  , ruleIntervalBetween+  , ruleIntervalMax+  , ruleIntervalMin+  , ruleIntervalNumeralDash+  , ruleIntervalDash+  , rulePrecision+  ]+    ++ ruleDistances
Duckling/Distance/EN/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -51,6 +50,52 @@   , examples (simple Metre 1.87)              [ "1.87 meters"              ]+  -- Composite values:+  , examples (simple Inch 94)+             [ "7 feet and 10 inches"+             , "7 feet, 10 inches"+             , "7 feet 10 inches"+             ]+  , examples (simple Metre 2001)+             [ "2 km and 1 meter"+             , "2 kilometer, 1 metre"+             , "2 kilometer 1 metre"+             ]+  , examples (simple Inch 166)+             [ "2 yards 7 ft 10 inches"+             , "2 yds, 7 feet and 10 inches"+             , "2 yards, 7 feet, 10 in"+             ]+  , examples (simple Foot 13)+             [ "2 yards and 7 feet"+             , "2 yards, 7 feet"+             , "2 yd 7'"+             ]+  , examples (simple Centimetre 1000806)+             [ "10 kms 8 metres 6 cm"+             , "10 kms, 8 meters, 6 cm"+             , "10 kms, 8 meters and 6 centimeters"+--             , "10 kms, 8 meters, and 6 cm" -- Oxford comma not supported+             ]+  , examples (simple Metre 1.3048)+             [ "1 meter and 1 foot"+             ]+  , examples (simple Kilometre 2.609344)+             [ "1 kilometer and 1 mile"+             ]+  , examples (simple M 3)+             -- The original, ambiguous "m" unit is preserved+             [ "3m"+             ]+  , examples (simple Centimetre 305)+             -- The ambiguous "m" unit is inferred as "meteres"+             [ "3m and 5cm"+             ]+  , examples (simple Foot 5281)+             -- The ambiguous "m" unit is inferred as "miles"+             [ "1m and 1ft"+             ]+  -- Ranges:   , examples (between Kilometre (3, 5))              [ "between 3 and 5 kilometers"              , "from 3km to 5km"
Duckling/Distance/EN/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -24,54 +23,23 @@ import Duckling.Numeral.Helpers import Duckling.Numeral.Types (NumeralData (..)) import Duckling.Types-import qualified Duckling.Distance.Types as TDistance+import qualified Duckling.Distance.Types as TDist import qualified Duckling.Numeral.Types as TNumeral -ruleDistanceFeetInch :: Rule-ruleDistanceFeetInch = Rule-  { name = "<distance|feet> <distance|inch>"-  , pattern =-    [ Predicate $ isDistanceOfUnit TDistance.Foot-    , Predicate $ isDistanceOfUnit TDistance.Inch-    ]-  , prod = \case-      (Token Distance DistanceData {TDistance.value = Just feet}:-       Token Distance DistanceData {TDistance.value = Just inches}:-       _) -> Just . Token Distance . withUnit TDistance.Inch . distance $-        feet * 12 + inches-      _ -> Nothing-  } -ruleDistanceFeetAndInch :: Rule-ruleDistanceFeetAndInch = Rule-  { name = "<distance|feet> and <distance|inch>"-  , pattern =-    [ Predicate $ isDistanceOfUnit TDistance.Foot-    , regex "and"-    , Predicate $ isDistanceOfUnit TDistance.Inch-    ]-  , prod = \case-      (Token Distance DistanceData {TDistance.value = Just feet}:-       _:-       Token Distance DistanceData {TDistance.value = Just inches}:-       _) -> Just . Token Distance . withUnit TDistance.Inch . distance $-        feet * 12 + inches-      _ -> Nothing-  }--distances :: [(Text, String, TDistance.Unit)]+distances :: [(Text, String, TDist.Unit)] distances = [ -- Imperial-              ("miles", "mi(le(s)?)?", TDistance.Mile)-            , ("yard", "y(ar)?ds?", TDistance.Yard)-            , ("feet", "('|f(oo|ee)?ts?)", TDistance.Foot)-            , ("inch", "(\"|''|in(ch(es)?)?)", TDistance.Inch)+              ("miles", "mi(le(s)?)?", TDist.Mile)+            , ("yard", "y(ar)?ds?", TDist.Yard)+            , ("feet", "('|f(oo|ee)?ts?)", TDist.Foot)+            , ("inch", "(\"|''|in(ch(es)?)?)", TDist.Inch)               -- Metric-            , ("km", "k(ilo)?m?(et(er|re))?s?", TDistance.Kilometre)-            , ("meters", "met(er|re)s?", TDistance.Metre)-            , ("centimeters", "cm|centimet(er|re)s?", TDistance.Centimetre)-            , ("millimeters", "mm|millimet(er|re)s?", TDistance.Millimetre)+            , ("km", "k(ilo)?m?(et(er|re))?s?", TDist.Kilometre)+            , ("meters", "met(er|re)s?", TDist.Metre)+            , ("centimeters", "cm|centimet(er|re)s?", TDist.Centimetre)+            , ("millimeters", "mm|millimet(er|re)s?", TDist.Millimetre)               -- Ambiguous-            , ("m (miles or meters)", "m", TDistance.M)+            , ("m (miles or meters)", "m", TDist.M)             ]  rulePrecision :: Rule@@ -89,7 +57,7 @@ ruleDistances :: [Rule] ruleDistances = map go distances   where-    go :: (Text, String, TDistance.Unit) -> Rule+    go :: (Text, String, TDist.Unit) -> Rule     go (name, regexPattern, u) = Rule       { name = name       , pattern = [ dimension Distance, regex regexPattern ]@@ -111,7 +79,7 @@       (_:        Token Numeral NumeralData{TNumeral.value = from}:        _:-       Token Distance DistanceData{TDistance.value = Just to, TDistance.unit = Just u}:+       Token Distance DistanceData{TDist.value=Just to, TDist.unit=Just u}:        _) | from < to ->         Just . Token Distance . withInterval (from, to) $ unitOnly u       _ -> Nothing@@ -128,9 +96,9 @@     ]   , prod = \case       (_:-       Token Distance DistanceData{TDistance.value = Just from, TDistance.unit = Just u1}:+       Token Distance DistanceData{TDist.value=Just from, TDist.unit=Just u1}:        _:-       Token Distance DistanceData{TDistance.value = Just to, TDistance.unit = Just u2}:+       Token Distance DistanceData{TDist.value=Just to, TDist.unit=Just u2}:        _) | from < to && u1 == u2 ->         Just . Token Distance . withInterval (from, to) $ unitOnly u1       _ -> Nothing@@ -147,7 +115,7 @@   , prod = \case       (Token Numeral NumeralData{TNumeral.value = from}:        _:-       Token Distance DistanceData{TDistance.value = Just to, TDistance.unit = Just u}:+       Token Distance DistanceData{TDist.value=Just to, TDist.unit=Just u}:        _) | from < to ->          Just . Token Distance . withInterval (from, to) $ unitOnly u       _ -> Nothing@@ -162,9 +130,9 @@     , Predicate isSimpleDistance     ]   , prod = \case-      (Token Distance DistanceData{TDistance.value = Just from, TDistance.unit = Just u1}:+      (Token Distance DistanceData{TDist.value=Just from, TDist.unit=Just u1}:        _:-       Token Distance DistanceData{TDistance.value = Just to, TDistance.unit = Just u2}:+       Token Distance DistanceData{TDist.value=Just to, TDist.unit=Just u2}:        _) | from < to && u1 == u2 ->         Just . Token Distance . withInterval (from, to) $ unitOnly u1       _ -> Nothing@@ -179,7 +147,7 @@     ]   , prod = \case       (_:-       Token Distance DistanceData{TDistance.value = Just to, TDistance.unit = Just u}:+       Token Distance DistanceData{TDist.value=Just to, TDist.unit=Just u}:        _) -> Just . Token Distance . withMax to $ unitOnly u       _ -> Nothing   }@@ -193,20 +161,53 @@     ]   , prod = \case       (_:-       Token Distance DistanceData{TDistance.value = Just to, TDistance.unit = Just u}:+       Token Distance DistanceData{TDist.value=Just to, TDist.unit=Just u}:        _) -> Just . Token Distance . withMin to $ unitOnly u       _ -> Nothing   } +-- | NOTE: Oxford comma is not supported.+ruleCompositeDistanceCommasAnd :: Rule+ruleCompositeDistanceCommasAnd = Rule+  { name = "composite <distance> (with ,/and)"+  , pattern =+    [ Predicate isSimpleDistance+    , regex ",|and"+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (Token Distance DistanceData{TDist.value=Just v1, TDist.unit=Just u1}:+       _:+       Token Distance DistanceData{TDist.value=Just v2, TDist.unit=Just u2}:+       _) | u1 /= u2 && v1 > 0 && v2 > 0 -> Token Distance <$>+                                              distanceSum v1 u1 v2 u2+      _ -> Nothing+  }++ruleCompositeDistance :: Rule+ruleCompositeDistance = Rule+  { name = "composite <distance>"+  , pattern =+    [ Predicate isSimpleDistance+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (Token Distance DistanceData{TDist.value=Just v1, TDist.unit=Just u1}:+       Token Distance DistanceData{TDist.value=Just v2, TDist.unit=Just u2}:+       _) | u1 /= u2 && v1 > 0 && v2 > 0 -> Token Distance <$>+                                              distanceSum v1 u1 v2 u2+      _ -> Nothing+  }+ rules :: [Rule] rules =-  [ ruleDistanceFeetInch-  , ruleDistanceFeetAndInch-  , ruleIntervalBetweenNumeral+  [ ruleIntervalBetweenNumeral   , ruleIntervalBetween   , ruleIntervalMax   , ruleIntervalMin   , ruleIntervalNumeralDash   , ruleIntervalDash-  , rulePrecision]-  ++ ruleDistances+  , rulePrecision+  , ruleCompositeDistanceCommasAnd+  , ruleCompositeDistance+  ] ++ ruleDistances
Duckling/Distance/ES/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Distance/ES/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Distance/FR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Distance/FR/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Distance/GA/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Distance/GA/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Distance/HR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} 
Duckling/Distance/HR/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-}
Duckling/Distance/Helpers.hs view
@@ -2,14 +2,14 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}  module Duckling.Distance.Helpers   ( distance+  , distanceSum   , isDistanceOfUnit   , isSimpleDistance   , unitOnly@@ -21,11 +21,13 @@   ) where  import Prelude+import Data.Semigroup ((<>))  import Duckling.Dimensions.Types import Duckling.Distance.Types (DistanceData(..)) import Duckling.Types import qualified Duckling.Distance.Types as TDistance+import qualified Duckling.DistanceUnits.Types as DGTypes  -- ----------------------------------------------------------------- -- Patterns@@ -36,7 +38,8 @@ isSimpleDistance _ = False  isDistanceOfUnit :: TDistance.Unit -> Predicate-isDistanceOfUnit unit (Token Distance DistanceData {TDistance.unit = Just u}) = unit == u+isDistanceOfUnit unit (Token Distance DistanceData {TDistance.unit = Just u}) =+    unit == u isDistanceOfUnit _ _ = False  -- -----------------------------------------------------------------@@ -47,6 +50,22 @@                           , TDistance.unit = Nothing                           , TDistance.minValue = Nothing                           , TDistance.maxValue = Nothing}++distanceSum ::+     Double+  -> TDistance.Unit+  -> Double+  -> TDistance.Unit+  -> Maybe DistanceData+distanceSum v1 u1 v2 u2 = unwrapContext $ cd1 <> cd2+  where+    wrapContext v u = DGTypes.ContextualDistance v $ DGTypes.toSystemUnit u+    cd1 = wrapContext v1 u1+    cd2 = wrapContext v2 u2++    unwrapContext DGTypes.Nonrelatable = Nothing+    unwrapContext (DGTypes.ContextualDistance v u) =+        Just $ withUnit (DGTypes.toRawUnit u) $ distance v  unitOnly :: TDistance.Unit -> DistanceData unitOnly u = DistanceData {TDistance.unit = Just u
+ Duckling/Distance/IT/Corpus.hs view
@@ -0,0 +1,50 @@+-- 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.Distance.IT.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Distance.Types+import Duckling.Locale+import Duckling.Resolve+import Duckling.Testing.Types++context :: Context+context = testContext {locale = makeLocale IT Nothing}++corpus :: Corpus+corpus = (context, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (simple Kilometre 3)+             [ "3 kilometri"+             , "3 chilometri"+             , "3 km"+             , "3km"+             ]+  , examples (simple Kilometre 3.0)+             [ "3,0 km"+             ]+  , examples (simple Mile 8)+             [ "8 miglia"+             ]+  , examples (simple Metre 9)+             [ "9 metri"+             , "9m"+             ]+  , examples (simple Centimetre 2)+             [ "2cm"+             , "2 centimetri"+             ]+  ]
+ Duckling/Distance/IT/Rules.hs view
@@ -0,0 +1,81 @@+-- 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.Distance.IT.Rules+  ( rules+  ) where++import Data.String+import Prelude++import Duckling.Dimensions.Types+import Duckling.Distance.Helpers+import Duckling.Types+import qualified Duckling.Distance.Types as TDistance++ruleLatentDistKm :: Rule+ruleLatentDistKm = Rule+  { name = "<latent dist> km"+  , pattern =+    [ dimension Distance+    , regex "km|(k|ch)(ilo)?m?(etr)o?i?"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Kilometre dd+      _ -> Nothing+  }++ruleDistMeters :: Rule+ruleDistMeters = Rule+  { name = "<dist> meters"+  , pattern =+    [ dimension Distance+    , regex "metro?i?|m"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Metre dd+      _ -> Nothing+  }++ruleDistCentimeters :: Rule+ruleDistCentimeters = Rule+  { name = "<dist> centimeters"+  , pattern =+    [ dimension Distance+    , regex "cm|centimetro?i?"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Centimetre dd+      _ -> Nothing+  }++ruleDistMiles :: Rule+ruleDistMiles = Rule+  { name = "<dist> miles"+  , pattern =+    [ dimension Distance+    , regex "miglio?a?"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Mile dd+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDistCentimeters+  , ruleDistMeters+  , ruleDistMiles+  , ruleLatentDistKm+  ]
+ Duckling/Distance/KM/Corpus.hs view
@@ -0,0 +1,59 @@+-- 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.Distance.KM.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Distance.Types+import Duckling.Resolve+import Duckling.Testing.Types++context :: Context+context = testContext{locale = makeLocale KM Nothing}++corpus :: Corpus+corpus = (context, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (simple Kilometre 3)+             [ "3 km"+             , "៣គីឡូ"+             , "បីគីឡូម៉ែត្រ"+             ]+  , examples (simple Centimetre 2)+             [ "2cm"+             , "២សង់ទីម៉ែត្រ"+             , "ពីរសង់ទីម៉ែត្រ"+             ]+  , examples (between Metre (3, 5))+             [ "ចាប់ពី 3 ដល់ 5 m"+             , "ចន្លោះពី ៣ ដល់ ៥ម៉ែត្រ"+             , "ចន្លោះ ៣ម៉ែត្រ និង ៥ម៉ែត្រ"+             , "ប្រហែល ៣-៥ ម៉ែត្រ"+             , "~3-5ម៉ែត្រ"+             ]+  , examples (under Centimetre 4)+             [ "តិចជាងបួនសង់ទីម៉ែត្រ"+             , "មិនលើស៤សង់ទីម៉ែត្រ"+             , "ក្រោម៤សង់ទីម៉ែត្រ"+             , "យ៉ាងច្រើន៤សង់ទីម៉ែត្រ"+             ]+  , examples (above Millimetre 10)+             [ "ច្រើនជាងដប់មីលីម៉ែត្រ"+             , "មិនតិចជាងដប់មីលីម៉ែត្រ"+             , "លើសពីដប់មីលីម៉ែត្រ"+             , "យ៉ាងតិចដប់មីលីម៉ែត្រ"+             ]+  ]
+ Duckling/Distance/KM/Rules.hs view
@@ -0,0 +1,178 @@+-- 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.KM.Rules+  ( rules+  ) where++import Data.String+import Data.Text (Text)+import Prelude++import Duckling.Dimensions.Types+import Duckling.Distance.Helpers+import Duckling.Distance.Types (DistanceData(..))+import Duckling.Numeral.Helpers+import Duckling.Numeral.Types (NumeralData (..))+import Duckling.Types+import qualified Duckling.Distance.Types as TDistance+import qualified Duckling.Numeral.Types as TNumeral++distances :: [(Text, String, TDistance.Unit)]+distances = [ ("km", "km|គីឡូ(ម៉ែត្រ)?", TDistance.Kilometre)+            , ("meters", "m|ម៉ែត្រ", TDistance.Metre)+            , ("centimeters", "cm|សង់ទីម៉ែត្រ", TDistance.Centimetre)+            , ("millimeters", "mm|មីលីម៉ែត្រ", TDistance.Millimetre)+            ]++rulePrecision :: Rule+rulePrecision = Rule+  { name = "about|exactly <dist>"+  , pattern =+    [ regex "\\~|ប្រហែល"+    , dimension Distance+    ]+  , prod = \case+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleDistances :: [Rule]+ruleDistances = map go distances+  where+    go :: (Text, String, TDistance.Unit) -> Rule+    go (name, regexPattern, u) = Rule+      { name = name+      , pattern = [ dimension Distance, regex regexPattern ]+      , prod = \case+          (Token Distance dd:_) -> Just . Token Distance $ withUnit u dd+          _ -> Nothing+      }++ruleIntervalBetweenNumeral :: Rule+ruleIntervalBetweenNumeral = Rule+  { name = "between|from <numeral> to|and <dist>"+  , pattern =+    [ regex "ចន្លោះ(ពី)?|ចាប់ពី"+    , Predicate isPositive+    , regex "និង|ដល់"+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (_:+       Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token Distance DistanceData{TDistance.value = Just to,+                                   TDistance.unit = Just u}:+       _) | from < to ->+        Just . Token Distance . withInterval (from, to) $ unitOnly u+      _ -> Nothing+  }++ruleIntervalBetween :: Rule+ruleIntervalBetween = Rule+  { name = "between|from <dist> to|and <dist>"+  , pattern =+    [ regex "ចន្លោះ(ពី)?|ចាប់ពី"+    , Predicate isSimpleDistance+    , regex "និង|ដល់"+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (_:+       Token Distance DistanceData{TDistance.value = Just from,+                                   TDistance.unit = Just u1}:+       _:+       Token Distance DistanceData{TDistance.value = Just to,+                                   TDistance.unit = Just u2}:+       _) | from < to && u1 == u2 ->+        Just . Token Distance . withInterval (from, to) $ unitOnly u1+      _ -> Nothing+  }++ruleIntervalNumeralDash :: Rule+ruleIntervalNumeralDash = Rule+  { name = "<numeral> - <dist>"+  , pattern =+    [ Predicate isPositive+    , regex "-"+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token Distance DistanceData{TDistance.value = Just to,+                                   TDistance.unit = Just u}:+       _) | from < to ->+         Just . Token Distance . withInterval (from, to) $ unitOnly u+      _ -> Nothing+  }++ruleIntervalDash :: Rule+ruleIntervalDash = Rule+  { name = "<dist> - <dist>"+  , pattern =+    [ Predicate isSimpleDistance+    , regex "-"+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (Token Distance DistanceData{TDistance.value = Just from,+                                   TDistance.unit = Just u1}:+       _:+       Token Distance DistanceData{TDistance.value = Just to,+                                   TDistance.unit = Just u2}:+       _) | from < to && u1 == u2 ->+        Just . Token Distance . withInterval (from, to) $ unitOnly u1+      _ -> Nothing+  }++ruleIntervalMax :: Rule+ruleIntervalMax = Rule+  { name = "Max Rule"+  , pattern =+    [ regex "ក្រោម|តិចជាង|មិនដល់|យ៉ាងច្រើន|មិនលើស"+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (_:+       Token Distance DistanceData{TDistance.value = Just to,+                                   TDistance.unit = Just u}:+       _) -> Just . Token Distance . withMax to $ unitOnly u+      _ -> Nothing+  }++ruleIntervalMin :: Rule+ruleIntervalMin = Rule+  { name = "Min Rule"+  , pattern =+    [ regex "លើស(ពី)?|មិនតិចជាង|លើ|ច្រើនជាង|យ៉ាងតិច|យ៉ាងហោច"+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (_:+       Token Distance DistanceData{TDistance.value = Just to,+                                   TDistance.unit = Just u}:+       _) -> Just . Token Distance . withMin to $ unitOnly u+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleIntervalBetweenNumeral+  , ruleIntervalBetween+  , ruleIntervalMax+  , ruleIntervalMin+  , ruleIntervalNumeralDash+  , ruleIntervalDash+  , rulePrecision+  ]+  ++ ruleDistances
Duckling/Distance/KO/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Distance/KO/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
+ Duckling/Distance/MN/Corpus.hs view
@@ -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.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Distance.MN.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Resolve+import Duckling.Distance.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {locale = makeLocale MN Nothing}, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (simple Kilometre 3)+             [ "3 километр"+             , "3 км"+             , "3км"+             ]+  , examples (simple Mile 8)+             [ "8 миль"+             ]+  , examples (simple Metre 1)+             [ "1 м"+             , "1 метр"+             ]+  , examples (simple Centimetre 2)+             [ "2см"+             ]+  , examples (simple Millimetre 4)+             [ "4мм"+             , "4 миллиметр"+             ]+  , examples (simple Inch 5)+             [ "5 инч"+             , "5\""+             ]+  , examples (simple Foot 35)+             [ "35 фут"+             , "35'"+             ]+  , examples (simple Yard 47)+             [ "47 яард"+             ]+  ]
+ Duckling/Distance/MN/Rules.hs view
@@ -0,0 +1,49 @@+-- 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.Distance.MN.Rules+  ( rules+  ) where++import Data.String+import Data.Text (Text)+import Prelude++import Duckling.Dimensions.Types+import Duckling.Distance.Helpers+import Duckling.Distance.Types (DistanceData(..))+import Duckling.Types+import qualified Duckling.Distance.Types as TDistance++distances :: [(Text, String, TDistance.Unit)]+distances = [ ("<latent dist> km", "км|километр", TDistance.Kilometre)+            , ("<latent dist> feet", "('|фут)", TDistance.Foot)+            , ("<latent dist> inch", "(\"|''|дюйм|инч)", TDistance.Inch)+            , ("<latent dist> yard", "яард", TDistance.Yard)+            , ("<dist> meters", "м(етр(ийн|ээр)?)?", TDistance.Metre)+            , ("<dist> centimeters", "см|сантиметр", TDistance.Centimetre)+            , ("<dist> millimeters", "мм|миллиметр", TDistance.Millimetre)+            , ("<dist> miles", "мил(и|ь)", TDistance.Mile)+            ]++ruleDistances :: [Rule]+ruleDistances = map go distances+  where+    go :: (Text, String, TDistance.Unit) -> Rule+    go (name, regexPattern, u) = Rule+      { name = name+      , pattern = [ dimension Distance, regex regexPattern ]+      , prod = \tokens -> case tokens of+          (Token Distance dd:_) -> Just . Token Distance $ withUnit u dd+          _ -> Nothing+      }++rules :: [Rule]+rules = ruleDistances
Duckling/Distance/NL/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Distance/NL/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Distance/PT/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Distance/PT/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Distance/RO/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Distance/RO/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Distance/RU/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Distance/RU/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Distance/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Distance/SV/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Distance/SV/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Distance/TR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Distance/TR/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Distance/Types.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE DeriveAnyClass #-}
Duckling/Distance/ZH/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -68,5 +67,31 @@              , "1 miles"              , "1英里"              , "一英裏"+             ]+  , examples (simple Metre 1.9)+             [ "1.9 m"+             , "1.9米"+             , "米九"+             ]+  , examples (simple Metre 3.9)+             [ "3.9 m"+             , "3.9米"+             , "三米九"+             ]+  , examples (between Metre (1.6, 3.9))+             [ "1.6m-3.9m"+             , "1.6~3.9米"+             , "一點六至三點九公尺"+             , "米六到三米九"+             ]+  , examples (under Mile 3.5)+             [ "最多三點五英里"+             , "3.5英裏以下"+             ]+  , examples (above Inch 5)+             [ "至少5\""+             , "最少五吋"+             , "五英吋以上"+             , "起碼五英寸"              ]   ]
Duckling/Distance/ZH/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -18,7 +17,10 @@  import Duckling.Dimensions.Types import Duckling.Distance.Helpers-import Duckling.Numeral.Types (NumeralData (..))+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@@ -70,7 +72,7 @@     [ dimension Distance     , regex "'|f(oo|ee)?ts?|英尺|呎"     , dimension Distance-    , regex "''|inch(es)?|英寸|英吋|吋"+    , regex "''|\"|inch(es)?|英寸|英吋|吋"     ]   , prod = \case       (Token Distance dd:_) ->@@ -83,7 +85,7 @@   { name = "<dist> inch"   , pattern =     [ dimension Distance-    , regex "''|inch(es)?|英寸|英吋|吋"+    , regex "''|\"|inch(es)?|英寸|英吋|吋"     ]   , prod = \case       (Token Distance dd:_) ->@@ -117,6 +119,107 @@       _ -> Nothing   } +ruleDistOneMeterAnd :: Rule+ruleDistOneMeterAnd = Rule+  { name = "one meter and <dist>"+  , pattern =+    [ regex "米"+    , Predicate isPositive+    ]+  , prod = \case+      (_:Token Numeral NumeralData{TNumeral.value = v}:_) ->+        Just . Token Distance $ withUnit TDistance.Metre (distance (1 + v/10))+      _ -> Nothing+  }++ruleDistMetersAnd :: Rule+ruleDistMetersAnd = Rule+  { name = "<dist> meters and <dist>"+  , pattern =+    [ Predicate isPositive+    , regex "米"+    , Predicate isPositive+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v1}:_:+        Token Numeral NumeralData{TNumeral.value = v2}:_) ->+        Just . Token Distance $ withUnit TDistance.Metre (distance (v1 + v2/10))+      _ -> Nothing+  }++ruleIntervalNumeralDash :: Rule+ruleIntervalNumeralDash = Rule+  { name = "<numeral> - <dist>"+  , pattern =+    [ Predicate isPositive+    , regex "-|~|到|至"+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = from}:+       _:+       Token Distance DistanceData{TDistance.value = Just to,+       TDistance.unit = Just u}:_) | from < to ->+         Just $ Token Distance $ withInterval (from, to) $ unitOnly u+      _ -> Nothing+  }++ruleIntervalDash :: Rule+ruleIntervalDash = Rule+  { name = "<dist> - <dist>"+  , pattern =+    [ Predicate isSimpleDistance+    , regex "-|~|到|至"+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (Token Distance DistanceData{TDistance.value = Just from,+                  TDistance.unit = Just u1}:+       _:+       Token Distance DistanceData{TDistance.value = Just to, TDistance.unit = Just u2}:+       _) | from < to && u1 == u2 ->+         Just $ Token Distance $ withInterval (from, to) $ unitOnly u1+      _ -> Nothing+  }++ruleIntervalBound :: Rule+ruleIntervalBound = Rule+  { name = "under/less/lower/no more than <amount-of-money> (最多|至少|最少)"+  , pattern =+    [ regex "(最多|至少|最少|起碼)"+    , Predicate isSimpleDistance+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):+       Token Distance DistanceData{TDistance.value = Just to,+                  TDistance.unit = Just u}:+       _) -> case match of+        "最多" -> Just $ Token Distance $ withMax to $ unitOnly u+        "最少" -> Just $ Token Distance $ withMin to $ unitOnly u+        "至少" -> Just $ Token Distance $ withMin to $ unitOnly u+        "起碼" -> Just $ Token Distance $ withMin to $ unitOnly u+        _ -> Nothing+      _ -> Nothing+  }++ruleIntervalBound2 :: Rule+ruleIntervalBound2 = Rule+  { name = "under/less/lower/no more than <amount-of-money> (以下|以上)"+  , pattern =+    [ Predicate isSimpleDistance+    , regex "(以下|以上)"+    ]+  , prod = \case+      (Token Distance DistanceData{TDistance.value = Just to,+                  TDistance.unit = Just u}:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> case match of+        "以下" -> Just $ Token Distance $ withMax to $ unitOnly u+        "以上" -> Just $ Token Distance $ withMin to $ unitOnly u+        _ -> Nothing+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleDistCentimeters@@ -126,4 +229,12 @@   , ruleDistKm   , ruleDistMeters   , ruleDistMiles+  , ruleDistOneMeterAnd+  , ruleDistMetersAnd+  , ruleDistOneMeterAnd+  , ruleDistMetersAnd+  , ruleIntervalNumeralDash+  , ruleIntervalDash+  , ruleIntervalBound+  , ruleIntervalBound2   ]
+ Duckling/DistanceUnits/Types.hs view
@@ -0,0 +1,190 @@+-- 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.+++-- | This module shadows names of some units previously defined in+-- 'Duckling.Distance.Types'.+-- Therefore, the units from that module must be used qualified by module.+module Duckling.DistanceUnits.Types+  ( ContextualDistance (..)+  , toSystemUnit+  , toRawUnit+  ) where++import Data.Semigroup+import Data.Tuple.Extra (both)+import Prelude++import qualified Duckling.Distance.Types as TDist+++-- | Supports deferred resolution of ambiguous units.+-- Note that this sum type cannot be simply replaced by+-- "Maybe (ContextualDistance Double DeferrableUnit)"+-- (with "Nothing" representing "Nonrelatable").+-- See "NOTE A" below.+data ContextualDistance+  = Nonrelatable+    -- ^ If two different ambiguous units were to be composed, then+    -- it would not be possible to decide which to resolve to. As of today,+    -- this won't happen since for now "M" is the lone ambiguous unit.+  | ContextualDistance Double DeferrableUnit++-- | This represents Units that have not yet been established as unrelatable.+-- The "Definite" constructor is purposely listed in front of "Ambiguous",+-- so that it will be preferred when taking choosing the "min" between+-- an "Ambiguous" and "Definite" unit.+data DeferrableUnit+  = Definite SystemUnit+  | Ambiguous AmbiguousUnit+  deriving (Eq, Ord)++-- | These measurement-system-specific units exist to disambiguate+-- the \"M\" of the 'Unit' type and to maintain the measurement-system context+-- for resolving to the appropriate precision.+--+-- It's also just handy to have separate programmatically accessible lists+-- of units for each type of measurement system.+data SystemUnit+  = Metric MetricUnit+  | Imperial ImperialUnit+  deriving (Eq, Ord)++data ImperialUnit+  = Inch+  | Foot+  | Yard+  | Mile+  deriving (Eq, Ord)++data MetricUnit+  = Millimetre+  | Centimetre+  | Metre+  | Kilometre+  deriving (Eq, Ord)++-- | Currently there is only one actually ambiguous unit, but this design allows+-- for expansion.+data AmbiguousUnit+  = M -- ^ "Miles" or "Metres"+  deriving (Eq, Ord)++-- | Represents a value with an unambiguous unit+data UnitValuePair = UnitValuePair SystemUnit Double++sumScaledUnits :: SystemUnit -> (UnitValuePair, UnitValuePair) -> Double+sumScaledUnits preferredUnit = uncurry (+) . both (scaleUnits preferredUnit)++-- | Determine the definite meaning of an "Ambiguous" unit using the context of+-- another "Definite" unit+reconcileAmbiguousWithDefinite ::+     Double+  -> AmbiguousUnit+  -> Double+  -> SystemUnit+  -> ContextualDistance+reconcileAmbiguousWithDefinite av au dv du =+  ContextualDistance combinedValue $ Definite preferredUnit+  where+    resolvedAmbiguousUnit = resolveUnit au du+    preferredUnit = du `min` resolvedAmbiguousUnit+    combinedValue = sumScaledUnits preferredUnit+      (UnitValuePair resolvedAmbiguousUnit av, UnitValuePair du dv)++-- | When both Metric and Imperial units are given, resolve to Metric.+-- Otherwise, preserve the original measurement system and use the smaller unit.+-- For the purpose of this resolution, all Metric units are considered "smaller"+-- than Imperial units.+instance Semigroup ContextualDistance where++  _ <> Nonrelatable = Nonrelatable+  Nonrelatable <> _ = Nonrelatable++  (ContextualDistance v1 u@(Ambiguous u1))+    <> (ContextualDistance v2 (Ambiguous u2))+      | u1 == u2  = ContextualDistance (v1 + v2) u+      | otherwise = Nonrelatable+      -- NOTE A: Needing to return "Nonrelatable" in this edge case is why+      -- the two-member "ContextualDistance" sum type cannot be simply+      -- represented as (Maybe (ContextualDistance Double DeferrableUnit)).++  (ContextualDistance av (Ambiguous au))+    <> (ContextualDistance dv (Definite du)) =+      reconcileAmbiguousWithDefinite av au dv du++  (ContextualDistance dv (Definite du))+    <> (ContextualDistance av (Ambiguous au)) =+      reconcileAmbiguousWithDefinite av au dv du++  (ContextualDistance v1 (Definite u1))+    <> (ContextualDistance v2 (Definite u2)) =+      ContextualDistance v $ Definite u+      where+        v = sumScaledUnits u (UnitValuePair u1 v1, UnitValuePair u2 v2)+        u = u1 `min` u2++resolveUnit :: AmbiguousUnit -> SystemUnit -> SystemUnit+resolveUnit M (Metric _) = Metric Metre+resolveUnit M (Imperial _) = Imperial Mile+++-- | Disambiguation of original Unit type+toSystemUnit :: TDist.Unit -> DeferrableUnit+toSystemUnit TDist.M          = Ambiguous M+toSystemUnit TDist.Millimetre = Definite $ Metric Millimetre+toSystemUnit TDist.Centimetre = Definite $ Metric Centimetre+toSystemUnit TDist.Metre      = Definite $ Metric Metre+toSystemUnit TDist.Kilometre  = Definite $ Metric Kilometre+toSystemUnit TDist.Inch       = Definite $ Imperial Inch+toSystemUnit TDist.Foot       = Definite $ Imperial Foot+toSystemUnit TDist.Yard       = Definite $ Imperial Yard+toSystemUnit TDist.Mile       = Definite $ Imperial Mile++-- | Reconversion to original Unit type+toRawUnit :: DeferrableUnit -> TDist.Unit+toRawUnit (Ambiguous M) = TDist.M+toRawUnit (Definite (Metric Millimetre)) = TDist.Millimetre+toRawUnit (Definite (Metric Centimetre)) = TDist.Centimetre+toRawUnit (Definite (Metric Metre)) = TDist.Metre+toRawUnit (Definite (Metric Kilometre)) = TDist.Kilometre+toRawUnit (Definite (Imperial Inch)) = TDist.Inch+toRawUnit (Definite (Imperial Foot)) = TDist.Foot+toRawUnit (Definite (Imperial Yard)) = TDist.Yard+toRawUnit (Definite (Imperial Mile)) = TDist.Mile++-- | Convert a distance to the given units.+-- This only works if the unit is unambiguous.+scaleUnits ::+     SystemUnit -- ^ target unit+  -> UnitValuePair -- ^ Original unit and value+  -> Double+scaleUnits targetUnit (UnitValuePair startingUnit v)+  | startingUnit == targetUnit = v+  | otherwise = inSIUnits v startingUnit / inSIUnits 1 targetUnit++-- | This is used when distances+-- must be normalized across measurement systems.+-- The Metric metre is the Standard International unit of distance.+inSIUnits :: Double -> SystemUnit -> Double+inSIUnits val (Metric u) = inMetres u val+inSIUnits val (Imperial u) = inInches u val * metersPerInch++-- | This conversion factor is exact.+metersPerInch :: Double+metersPerInch = 0.0254++inMetres :: Fractional a => MetricUnit -> a -> a+inMetres Millimetre n = n / 1000+inMetres Centimetre n = n / 100+inMetres Metre      n = n+inMetres Kilometre  n = n * 1000++inInches :: Num a => ImperialUnit -> a -> a+inInches Inch n = n+inInches Foot n = 12   * n+inInches Yard n = 3    * inInches Foot n+inInches Mile n = 5280 * inInches Foot n
Duckling/Duration/AR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Duration/AR/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Duration/BG/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Duration/BG/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -37,7 +36,7 @@     , dimension TimeGrain     ]   , prod = \tokens -> case tokens of-      (_:Token TimeGrain grain:_) -> Token Duration <$> timesOneAndAHalf grain 0+      (_:Token TimeGrain grain:_) -> Token Duration <$> nPlusOneHalf grain 0       _ -> Nothing   } @@ -49,7 +48,7 @@     , regex "и половина"     ]   , prod = \tokens -> case tokens of-      (Token TimeGrain grain:_) -> Token Duration <$> timesOneAndAHalf grain 1+      (Token TimeGrain grain:_) -> Token Duration <$> nPlusOneHalf grain 1       _ -> Nothing   } @@ -64,7 +63,7 @@   , prod = \tokens -> case tokens of       (Token Numeral NumeralData{TNumeral.value = v}:        Token TimeGrain grain:-       _) -> timesOneAndAHalf grain (floor $ v) >>= Just . Token Duration+       _) -> nPlusOneHalf grain (floor $ v) >>= Just . Token Duration       _ -> Nothing   } 
Duckling/Duration/DA/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Duration/DE/Rules.hs view
@@ -2,136 +2,248 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}  module Duckling.Duration.DE.Rules   ( rules ) where -import Control.Monad (join)-import qualified Data.Text as Text-import Prelude-import Data.String  import Duckling.Dimensions.Types import Duckling.Duration.Helpers-import Duckling.Numeral.Helpers (parseInteger)-import Duckling.Numeral.Types (NumeralData (..))-import qualified Duckling.Numeral.Types as TNumeral import Duckling.Regex.Types+import Control.Monad (join)+import qualified Data.Text as Text+import Prelude+import Duckling.Numeral.Helpers (parseInteger)+import Duckling.Duration.Types (DurationData(..))+import qualified Duckling.Duration.Types as TDuration+import Data.String+import Duckling.Numeral.Types (NumeralData(..)) import qualified Duckling.TimeGrain.Types as TG+import qualified Duckling.Numeral.Types as TNumeral import Duckling.Types +ruleQuarterOfAnHour :: Rule+ruleQuarterOfAnHour = Rule+  { name = "quarter of an hour"+  , pattern =+    [ regex "(einer? )?Viertelstunde"+    ]+  , prod = \_ -> Just $ Token Duration $ duration TG.Minute 15+  }+ ruleHalfAnHour :: Rule ruleHalfAnHour = Rule   { name = "half an hour"   , pattern =-    [ regex "(1/2\\s?|(einer )halbe?n? )stunde"+    [ regex "(1/2\\s?|(eine )?halbe |(einer )?halben )stunde"     ]-  , prod = \_ -> Just . Token Duration $ duration TG.Minute 30+  , prod = \_ -> Just $ Token Duration $ duration TG.Minute 30   } +ruleThreeQuartersOfAnHour :: Rule+ruleThreeQuartersOfAnHour = Rule+  { name = "three-quarters of an hour"+  , pattern =+    [ regex "3/4\\s?stunde|(einer? )?dreiviertel stunde|drei viertelstunden"+    ]+  , prod = \_ -> Just $ Token Duration $ duration TG.Minute 45+  }+ ruleFortnight :: Rule ruleFortnight = Rule   { name = "fortnight"   , pattern =-    [ regex "(a|one)? fortnight"+    [ regex "zwei Wochen"     ]-  , prod = \_ -> Just . Token Duration $ duration TG.Day 14+  , prod = \_ -> Just $ Token Duration $ duration TG.Day 14   } -ruleIntegerMoreUnitofduration :: Rule-ruleIntegerMoreUnitofduration = Rule-  { name = "<integer> more <unit-of-duration>"+rulePrecision :: Rule+rulePrecision = Rule+  { name = "about|exactly <duration>"   , pattern =-    [ Predicate isNatural-    , regex "mehr|weniger"-    , dimension TimeGrain+    [ regex "ungef(ä|a)hr|zirka|genau|exakt"+    , dimension Duration     ]-  , prod = \tokens -> case tokens of-      (Token Numeral NumeralData{TNumeral.value = v}:-       _:-       Token TimeGrain grain:-       _) -> Just . Token Duration . duration grain $ floor v+  , prod = \case+      (_:token:_) -> Just token       _ -> Nothing   } -ruleNumeralnumberHours :: Rule-ruleNumeralnumberHours = Rule-  { name = "number.number hours"+ruleCommaNumeralHours :: Rule+ruleCommaNumeralHours = Rule+  { name = "number,number hours"   , pattern =-    [ regex "(\\d+)\\.(\\d+) stunden?"+    [ regex "(\\d+),(\\d+)"+    , Predicate $ isGrain TG.Hour     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token RegexMatch (GroupMatch (h:m:_)):_) -> do         hh <- parseInteger h         mnum <- parseInteger m         let mden = 10 ^ Text.length m-        Just . Token Duration $ minutesFromHourMixedFraction hh mnum mden+        Just $ Token Duration $ minutesFromHourMixedFraction hh mnum mden       _ -> Nothing   } -ruleIntegerAndAnHalfHours :: Rule-ruleIntegerAndAnHalfHours = Rule-  { name = "<integer> and an half hours"+ruleCommaNumeralMinutes :: Rule+ruleCommaNumeralMinutes = Rule+  { name = "number,number minutes"   , pattern =+    [ regex "(\\d+),(\\d+)"+    , Predicate $ isGrain TG.Minute+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (m:s:_)):_) -> do+        mm <- parseInteger m+        ss <- parseInteger s+        let sden = 10 ^ Text.length s+        Just $ Token Duration $ secondsFromHourMixedFraction mm ss sden+      _ -> Nothing+  }++ruleAndHalfHour :: Rule+ruleAndHalfHour = Rule+  { name = "<integer> and a half hour"+  , pattern =     [ Predicate isNatural-    , regex "ein ?halb stunden?"+    , regex "(und )?(ein(en?)? )?halb(en?)?"+    , Predicate $ isGrain TG.Hour     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token Numeral NumeralData{TNumeral.value = v}:_) ->-        Just . Token Duration . duration TG.Minute $ 30 + 60 * floor v+        Just $ Token Duration $ duration TG.Minute $ 30 + 60 * floor v       _ -> Nothing   } -ruleAUnitofduration :: Rule-ruleAUnitofduration = Rule+ruleAndHalfMinute :: Rule+ruleAndHalfMinute = Rule+  { name = "<integer> and a half minutes"+  , pattern =+    [ Predicate isNatural+    , regex "(und )?(ein(en?)? ?)?halb(en?)?"+    , Predicate $ isGrain TG.Minute+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:_) ->+        Just $ Token Duration $ duration TG.Second $ 30 + 60 * floor v+      _ -> Nothing+  }++ruleArticle :: Rule+ruleArticle = Rule   { name = "a <unit-of-duration>"   , pattern =-    [ regex "eine?(r|n)?"+    [ regex "ein(en?)?"     , dimension TimeGrain     ]-  , prod = \tokens -> case tokens of-      (_:Token TimeGrain grain:_) -> Just . Token Duration $ duration grain 1+  , prod = \case+      (_:Token TimeGrain grain:_) -> Just $ Token Duration $ duration grain 1       _ -> Nothing   } -ruleAboutDuration :: Rule-ruleAboutDuration = Rule-  { name = "about <duration>"+ruleHalfTimeGrain :: Rule+ruleHalfTimeGrain = Rule+  { name = "half a <time-grain>"   , pattern =-    [ regex "ungefähr|zirka"+    [ regex "(ein(en)?)?(1/2|halbe?)"+    , dimension TimeGrain+    ]+  , prod = \case+      (_:Token TimeGrain grain:_) -> Token Duration <$> nPlusOneHalf grain 0+      _ -> Nothing+  }++ruleCompositeDurationCommasAnd :: Rule+ruleCompositeDurationCommasAnd = Rule+  { name = "composite <duration> (with ,/and)"+  , pattern =+    [ Predicate isNatural+    , dimension TimeGrain+    , regex ",|und"     , dimension Duration     ]-  , prod = \tokens -> case tokens of-      (_:token:_) -> Just token+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:+       Token TimeGrain g:+       _:+       Token Duration dd@DurationData{TDuration.grain = dg}:+       _) | g > dg -> Just $ Token Duration $ duration g (floor v) <> dd       _ -> Nothing   } -ruleExactlyDuration :: Rule-ruleExactlyDuration = Rule-  { name = "exactly <duration>"+ruleCompositeDuration :: Rule+ruleCompositeDuration = Rule+  { name = "composite <duration>"   , pattern =-    [ regex "genau|exakt"+    [ Predicate isNatural+    , dimension TimeGrain     , dimension Duration     ]-  , prod = \tokens -> case tokens of-      (_:token:_) -> Just token+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:+       Token TimeGrain g:+       Token Duration dd@DurationData{TDuration.grain = dg}:+       _) | g > dg -> Just $ Token Duration $ duration g (floor v) <> dd       _ -> Nothing   } +ruleCompositeDurationAnd :: Rule+ruleCompositeDurationAnd = Rule+  { name = "composite <duration> and <duration>"+  , pattern =+    [ dimension Duration+    , regex ",|und"+    , dimension Duration+    ]+  , prod = \case+      (Token Duration DurationData{TDuration.value = v, TDuration.grain = g}:+       _:+       Token Duration dd@DurationData{TDuration.grain = dg}:+       _) | g > dg -> Just $ Token Duration $ duration g v <> dd+      _ -> Nothing+  }++ruleHoursAndMinutes :: Rule+ruleHoursAndMinutes = Rule+  { name = "<integer> hour and <integer>"+  , pattern =+    [ Predicate isNatural+    , regex "(ein(en?) )?stunden?( und)?"+    , Predicate isNatural+    , Predicate $ isGrain TG.Minute+    ]+  , prod = \case+      (Token Numeral h:+       _:+       Token Numeral m:+       _) -> Just $ Token Duration $ duration TG.Minute $+                floor (TNumeral.value m) + 60 * floor (TNumeral.value h)+      _ -> Nothing+  }+ rules :: [Rule] rules =-  [ ruleAUnitofduration-  , ruleAboutDuration-  , ruleExactlyDuration-  , ruleFortnight+  [ ruleQuarterOfAnHour   , ruleHalfAnHour-  , ruleIntegerAndAnHalfHours-  , ruleIntegerMoreUnitofduration-  , ruleNumeralnumberHours+  , ruleThreeQuartersOfAnHour+  , rulePrecision+  , ruleCommaNumeralHours+  , ruleCommaNumeralMinutes+  , ruleFortnight+  , ruleAndHalfHour+  , ruleAndHalfMinute+  , ruleArticle+  , ruleHalfTimeGrain+  , ruleCompositeDurationCommasAnd+  , ruleCompositeDuration+  , ruleCompositeDurationAnd+  , ruleHoursAndMinutes+  , ruleAndHalfMinute   ]
Duckling/Duration/EL/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Duration/EL/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -159,7 +158,7 @@     , dimension TimeGrain     ]   , prod = \tokens -> case tokens of-      (_:Token TimeGrain g:_) -> Token Duration <$> timesOneAndAHalf g 0+      (_:Token TimeGrain g:_) -> Token Duration <$> nPlusOneHalf g 0       _ -> Nothing   } @@ -173,7 +172,7 @@     ]   , prod = \tokens -> case tokens of       (Token Numeral nd:_:Token TimeGrain grain:_) ->-        timesOneAndAHalf grain (floor $ TNumeral.value nd) >>=+        nPlusOneHalf grain (floor $ TNumeral.value nd) >>=         Just . Token Duration       _ -> Nothing   }@@ -189,7 +188,7 @@   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (num:_)):Token TimeGrain grain:_) ->         HashMap.lookup (Text.toLower num) numeralMapEL >>=-        timesOneAndAHalf grain >>=+        nPlusOneHalf grain >>=         Just . Token Duration       _ -> Nothing   }
Duckling/Duration/EN/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -45,6 +44,13 @@              [ "2 mins"              , "two minutes"              , "2'"+             , "2 more minutes"+             , "two additional minutes"+             , "2 extra minutes"+             , "2 less minutes"+             , "2 fewer minutes"+             , "2m"+             , "2 m"              ]   , examples (DurationData 30 Day)              [ "30 days"@@ -77,7 +83,33 @@   , examples (DurationData 90 Minute)              [ "an hour and a half"              , "one hour and half"+             , "1 hour thirty"+             , "1 hour and thirty"+             , "1.5 hours"+             , "1.5 hrs"+             , "one and two quarter hour"+             , "one and two quarters hour"+             , "one and two quarter of hour"+             , "one and two quarters of hour"              ]+  , examples (DurationData 75 Minute)+             [ "1 hour fifteen"+             , "1 hour and fifteen"+             , "one and quarter hour"+             , "one and a quarter hour"+             , "one and one quarter hour"+             , "one and quarter of hour"+             , "one and a quarter of hour"+             , "one and one quarter of hour"+             ]+  , examples (DurationData 130 Minute)+             [ "2 hours ten"+             , "2 hour and 10"+             ]+  , examples (DurationData 3615 Second)+             [ "1 hour fifteen seconds"+             , "1 hour and fifteen seconds"+             ]   , examples (DurationData 45 Day)              [ "a month and a half"              , "one month and half"@@ -85,8 +117,47 @@   , examples (DurationData 27 Month)              [ "2 years and 3 months"              , "2 years, 3 months"+             , "2 years 3 months"              ]   , examples (DurationData 31719604 Second)              [ "1 year, 2 days, 3 hours and 4 seconds"+             , "1 year 2 days 3 hours and 4 seconds"+               -- Oxford comma not supported:+--           , "1 year, 2 days, 3 hours, and 4 seconds"              ]+  , examples (DurationData 330 Second)+             [ "5 and a half minutes"+             , "five and half min"+             , "5 and an half minute"+             ]+  , examples (DurationData 105 Minute)+              [ "one and three quarter hour"+              , "one and three quarters hour"+              , "one and three quarter of hour"+              , "one and three quarters of hour"+              , "one and three quarter of hours"+              , "one and three quarters of hours"+              ]+  , examples (DurationData 135 Minute)+             [ "two and quarter hour"+             , "two and a quarter of hour"+             , "two and quarter of hours"+             , "two and a quarter of hours"+             ]+  , examples (DurationData 105 Minute)+              [ "an hour and 45 minutes"+              , "one hour and 45 minutes"+              ]+  , examples (DurationData 90 Second)+              [ "a minute and 30 seconds"+              , "one minute and 30 seconds"+              ]+  , examples (DurationData 3630 Second)+              [ "an hour and 30 seconds"]+  , examples (DurationData 930 Second)+              [ "15.5 minutes"+              , "15.5 minute"+              , "15.5 mins"+              , "15.5 min"+              ]   ]
Duckling/Duration/EN/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -16,14 +15,13 @@   ) where  import Data.Semigroup ((<>))-import Data.String import Prelude import qualified Data.Text as Text  import Duckling.Dimensions.Types import Duckling.Duration.Helpers import Duckling.Duration.Types (DurationData(..))-import Duckling.Numeral.Helpers (parseInt, parseInteger)+import Duckling.Numeral.Helpers (parseInteger) import Duckling.Numeral.Types (NumeralData(..)) import Duckling.Regex.Types import Duckling.Types@@ -89,7 +87,7 @@   { name = "<integer> more <unit-of-duration>"   , pattern =     [ Predicate isNatural-    , regex "more|less"+    , regex "more|additional|extra|less|fewer"     , dimension TimeGrain     ]   , prod = \case@@ -102,7 +100,8 @@ ruleDurationDotNumeralHours = Rule   { name = "number.number hours"   , pattern =-    [ regex "(\\d+)\\.(\\d+) *hours?"+    [ regex "(\\d+)\\.(\\d+)"+    , Predicate $ isGrain TG.Hour     ]   , prod = \case       (Token RegexMatch (GroupMatch (h:m:_)):_) -> do@@ -126,6 +125,19 @@       _ -> Nothing   } +ruleDurationAndHalfMinute :: Rule+ruleDurationAndHalfMinute = Rule+  { name = "<integer> and a half minutes"+  , pattern =+    [ Predicate isNatural+    , regex "and (an? )?half min(ute)?s?"+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:_) ->+        Just . Token Duration . duration TG.Second $ 30 + 60 * floor v+      _ -> Nothing+  }+ ruleDurationA :: Rule ruleDurationA = Rule   { name = "a <unit-of-duration>"@@ -146,7 +158,7 @@     , dimension TimeGrain     ]   , prod = \case-      (_:Token TimeGrain grain:_) -> Token Duration <$> timesOneAndAHalf grain 0+      (_:Token TimeGrain grain:_) -> Token Duration <$> nPlusOneHalf grain 0       _ -> Nothing   } @@ -159,10 +171,27 @@     , regex "and (a )?half"     ]   , prod = \case-      (_:Token TimeGrain grain:_) -> Token Duration <$> timesOneAndAHalf grain 1+      (_:Token TimeGrain grain:_) -> Token Duration <$> nPlusOneHalf grain 1       _ -> Nothing   } +ruleDurationHoursAndMinutes :: Rule+ruleDurationHoursAndMinutes = Rule+  { name = "<integer> hour and <integer>"+  , pattern =+    [ Predicate isNatural+    , regex "hours?( and)?"+    , Predicate isNatural+    ]+  , prod = \case+      (Token Numeral h:+       _:+       Token Numeral m:+       _) -> Just . Token Duration . duration TG.Minute $+         (floor $ TNumeral.value m) + 60 * floor (TNumeral.value h)+      _ -> Nothing+  }+ ruleDurationPrecision :: Rule ruleDurationPrecision = Rule   { name = "about|exactly <duration>"@@ -175,37 +204,115 @@         _ -> Nothing   } +-- | NOTE: Oxford comma is not supported.+ruleCompositeDurationCommasAnd :: Rule+ruleCompositeDurationCommasAnd = Rule+  { name = "composite <duration> (with ,/and)"+  , pattern =+    [ Predicate isNatural+    , dimension TimeGrain+    , regex ",|and"+    , dimension Duration+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:+       Token TimeGrain g:+       _:+       Token Duration dd@DurationData{TDuration.grain = dg}:+       _) | g > dg -> Just . Token Duration $ duration g (floor v) <> dd+      _ -> Nothing+  }+ ruleCompositeDuration :: Rule ruleCompositeDuration = Rule   { name = "composite <duration>"   , pattern =     [ Predicate isNatural     , dimension TimeGrain-    , regex ",|and"     , dimension Duration     ]   , prod = \case       (Token Numeral NumeralData{TNumeral.value = v}:        Token TimeGrain g:-       _:        Token Duration dd@DurationData{TDuration.grain = dg}:        _) | g > dg -> Just . Token Duration $ duration g (floor v) <> dd       _ -> Nothing   } +ruleCompositeDurationAnd :: Rule+ruleCompositeDurationAnd = Rule+  { name = "composite <duration> and <duration>"+  , pattern =+    [ dimension Duration+    , regex ",|and"+    , dimension Duration+    ]+  , prod = \case+      (Token Duration DurationData{TDuration.value = v, TDuration.grain = g}:+       _:+       Token Duration dd@DurationData{TDuration.grain = dg}:+       _) | g > dg -> Just . Token Duration $ duration g (v) <> dd+      _ -> Nothing+  }++ruleDurationDotNumeralMinutes :: Rule+ruleDurationDotNumeralMinutes = Rule+  { name = "number.number minutes"+  , pattern =+    [ regex "(\\d+)\\.(\\d+)"+    , Predicate $ isGrain TG.Minute+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (m:s:_)):_) -> do+        mm <- parseInteger m+        ss <- parseInteger s+        let sden = 10 ^ Text.length s+        Just $ Token Duration $ secondsFromHourMixedFraction mm ss sden+      _ -> Nothing+  }++ruleDurationNumeralAndQuarterHour :: Rule+ruleDurationNumeralAndQuarterHour = Rule+  { name = "<Integer> and <Integer> quarter of hour"+  , pattern =+    [ Predicate isNatural+    , regex "and (a |an |one |two |three )?quarters?( of)?( an)?"+    , Predicate $ isGrain TG.Hour+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = h}:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> do+         q <- case Text.strip $ Text.toLower match of "a"     -> Just 1+                                                      "an"    -> Just 1+                                                      "one"   -> Just 1+                                                      "two"   -> Just 2+                                                      "three" -> Just 3+                                                      _       -> Just 1+         Just . Token Duration . duration TG.Minute $ 15 * q + 60 * floor h+      _ -> Nothing+  }+ rules :: [Rule] rules =-  [ ruleDurationQuarterOfAnHour+  [ ruleCompositeDurationCommasAnd+  , ruleDurationQuarterOfAnHour   , ruleDurationHalfAnHourAbbrev   , ruleDurationThreeQuartersOfAnHour   , ruleDurationFortnight   , ruleDurationNumeralMore   , ruleDurationDotNumeralHours   , ruleDurationAndHalfHour+  , ruleDurationAndHalfMinute   , ruleDurationA   , ruleDurationHalfATimeGrain   , ruleDurationOneGrainAndHalf+  , ruleDurationHoursAndMinutes   , ruleDurationPrecision   , ruleNumeralQuotes   , ruleCompositeDuration+  , ruleCompositeDurationAnd+  , ruleCompositeDurationCommasAnd+  , ruleDurationDotNumeralMinutes+  , ruleDurationNumeralAndQuarterHour   ]
+ Duckling/Duration/ES/Corpus.hs view
@@ -0,0 +1,58 @@+-- 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.Duration.ES.Corpus+  ( corpus+  ) where++import Prelude+import Data.String++import Duckling.Duration.Types+import Duckling.Locale+import Duckling.Resolve+import Duckling.Testing.Types+import Duckling.TimeGrain.Types (Grain(..))++corpus :: Corpus+corpus = (testContext {locale = makeLocale ES Nothing}, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DurationData 30 Minute)+             [ "media hora"+             , "media horas"+             , "30 minutos"+             , "treinta minutos"+             ]+  , examples (DurationData 15 Minute)+             [  "cuarto de hora"+             ,  "cuartos de hora"+             ,  "quince minutos"+             ,  "15 minutos"+             ]+  , examples (DurationData 45 Minute)+             [  "tres cuartos de hora"+             ,  "tres cuartos de horas"+             ,  "tres cuarto de hora"+             ,  "tres cuarto de horas"+             ,  "cuarenta y cinco minutos"+             ,  "45 minutos"+             ]+  , examples (DurationData 92 Minute)+             [+               "una hora y treinta y dos minutos"+             , "una hora treinta y dos minutos"+             ]+  , examples (DurationData 155 Minute)+             [+               "dos hora y treinta y cinco minutos"+             , "dos hora  treinta y cinco minutos"+             ]+  ]
+ Duckling/Duration/ES/Rules.hs view
@@ -0,0 +1,98 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Duration.ES.Rules+  ( rules+  ) where++import Prelude+import Data.Semigroup ((<>))+import Duckling.Dimensions.Types+import Duckling.Duration.Helpers+import Duckling.Duration.Types (DurationData(..))+import Duckling.Numeral.Types (NumeralData(..))+import Duckling.Types+import qualified Duckling.Duration.Types as TDuration+import qualified Duckling.Numeral.Types as TNumeral+import qualified Duckling.TimeGrain.Types as TG++ruleDurationQuarterOfAnHour :: Rule+ruleDurationQuarterOfAnHour = Rule+  { name = "quarter of an hour"+  , pattern =+    [ regex "cuartos? de hora"+    ]+  , prod = \_ -> Just $ Token Duration $ duration TG.Minute 15+  }++ruleDurationHalfOfAnHour :: Rule+ruleDurationHalfOfAnHour = Rule+  { name = "half of an hour"+  , pattern =+    [ regex "media horas?"+    ]+  , prod = \_ -> Just $ Token Duration $ duration TG.Minute 30+  }++ruleDurationThreeQuartersOfAnHour :: Rule+ruleDurationThreeQuartersOfAnHour = Rule+  { name = "three-quarters of an hour"+  , pattern =+    [ regex "tres cuartos? de horas?"+    ]+  , prod = \_ -> Just $ Token Duration $ duration TG.Minute 45+  }++ruleCompositeDurationCommasAnd :: Rule+ruleCompositeDurationCommasAnd = Rule+  { name = "composite <duration> (with and)"+  , pattern =+    [ Predicate isNatural+    , dimension TimeGrain+    , regex "y"+    , dimension Duration+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:+       Token TimeGrain g:+       _:+       Token Duration dd@DurationData{TDuration.grain = dg}:+       _) | g > dg -> Just $ Token Duration $ duration g (floor v) <> dd+      _ -> Nothing+  }++ruleCompositeDuration :: Rule+ruleCompositeDuration = Rule+  {+    name = "composite <duration>"+  , pattern =+    [+      Predicate isNatural+    , dimension TimeGrain+    , dimension Duration+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:+       Token TimeGrain g:+       Token Duration dd@DurationData{TDuration.grain = dg}:+       _) | g > dg -> Just $ Token Duration $ duration g (floor v) <> dd+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDurationHalfOfAnHour+  , ruleDurationQuarterOfAnHour+  , ruleDurationThreeQuartersOfAnHour+  , ruleCompositeDuration+  , ruleCompositeDurationCommasAnd+  ]
Duckling/Duration/FR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Duration/FR/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Duration/GA/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Duration/GA/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Duration/HE/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-}
Duckling/Duration/HI/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -36,6 +35,7 @@   , examples (DurationData 1 Day)              [ "दिवस"              , "एक दिन"+             , "बिल्कुल एक दिन"              ]   , examples (DurationData 14 Day)              [ "पखवाड़ा"@@ -45,5 +45,38 @@              [ "एक साल"              , "केवल एक वर्ष"              , "लगभग एक साल"+             , "एक बरस"+             , "केवल एक साल"+             ]+  , examples (DurationData 21 Month)+             [ "पौने 2 साल"+             ]+  , examples (DurationData 105 Minute)+             [ "पौने 2 घंटा"+             ]+  , examples (DurationData 27 Month)+             [ "सवा 2 साल"+             , "2 साल और 3 महीना"+             , "2 साल, 3 महीना"+             , "2 साल 3 महीना"+             ]+  , examples (DurationData 135 Minute)+             [ "सवा 2 घंटा"+             ]+  , examples (DurationData 42 Month)+             [ "साड़े 3 साल"+             ]+  , examples (DurationData 210 Minute)+             [ "साड़े 3 घंटा"+             ]+  , examples (DurationData 31719604 Second)+             [ "1 साल, 2 दिन, 3 घंटा और 4 सेकंड"+             , "1 साल 2 दिन 3 घंटा और 4 सेकंड"+             ]+  , examples (DurationData 30 Month)+             [ "ढाई साल"+             ]+  , examples (DurationData 90 Minute)+             [ "डेढ़ घंटा"              ]   ]
Duckling/Duration/HI/Rules.hs view
@@ -2,18 +2,17 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}  module Duckling.Duration.HI.Rules   ( rules   ) where -import Control.Monad (join) import Data.String import Data.HashMap.Strict (HashMap) import Data.Text (Text)@@ -23,34 +22,39 @@  import Duckling.Dimensions.Types import Duckling.Duration.Helpers-import Duckling.Numeral.Helpers (parseInteger)+import Duckling.Duration.Types (DurationData(..)) import Duckling.Numeral.Types (NumeralData (..)) import Duckling.Regex.Types import Duckling.Types+import qualified Duckling.Duration.Types as TDuration import qualified Duckling.Numeral.Types as TNumeral import qualified Duckling.TimeGrain.Types as TG  avadhiMap :: HashMap Text TG.Grain avadhiMap = HashMap.fromList   [ ("मिनट" , TG.Minute)+  , ("क्षण", TG.Minute)   , ("घंटा" , TG.Hour)   , ("दिवस" , TG.Day)   , ("दिन"  , TG.Day)   , ("महीना", TG.Month)+  , ("माह", TG.Month)+  , ("मास", TG.Month)   , ("वर्ष" , TG.Year)   , ("साल"  , TG.Year)+  , ("बरस", TG.Year)   ]  ruleAadha :: Rule ruleAadha = Rule   { name = "half of a duration"   , pattern =-    [ regex "आधा ((साल|वर्ष)|(महीना)|(दिन|दिवस)|(घंटा)|(मिनट))"+    [ regex "आधा ((साल|वर्ष|बरस)|(महीना|मास|माह)|(दिन|दिवस)|(घंटा)|(मिनट|क्षण))"     ]   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (x:_)):_) -> do         grain <- HashMap.lookup (Text.toLower x) avadhiMap-        Token Duration <$> timesOneAndAHalf grain 0+        Token Duration <$> nPlusOneHalf grain 0       _ -> Nothing   } @@ -60,7 +64,7 @@   , pattern =     [ regex "पंद्रह मिनट"     ]-  , prod = \_ -> Just . Token Duration $ duration TG.Minute 15+  , prod = \_ -> Just $ Token Duration $ duration TG.Minute 15   }  ruleDurationPakhwaada :: Rule@@ -69,7 +73,7 @@   , pattern =     [ regex "((एक पखवाड़ा)|(पखवाड़ा))"     ]-  , prod = \_ -> Just . Token Duration $ duration TG.Day 14+  , prod = \_ -> Just $ Token Duration $ duration TG.Day 14   }  ruleDurationDin :: Rule@@ -78,16 +82,16 @@   , pattern =     [ regex "((एक दिन)|(एक दिवस)|(दिन|दिवस))"     ]-  , prod = \_ -> Just . Token Duration $ duration TG.Day 1+  , prod = \_ -> Just $ Token Duration $ duration TG.Day 1   }  ruleDurationEkSaal :: Rule ruleDurationEkSaal = Rule   { name = "one year"   , pattern =-    [ regex "एक (साल|वर्ष)"+    [ regex "एक (साल|वर्ष|बरस)"     ]-  , prod = \_ -> Just . Token Duration $ duration TG.Year 1+  , prod = \_ -> Just $ Token Duration $ duration TG.Year 1   }  ruleDurationPreciseImprecise :: Rule@@ -102,7 +106,107 @@         _ -> Nothing   } +rulePauneDuration :: Rule+rulePauneDuration = Rule+  { name = "Paune duration"+  , pattern =+    [ regex "पौने"+    , Predicate isNatural+    , dimension TimeGrain+    ]+  , prod = \case+      (_:+       Token Numeral NumeralData{TNumeral.value = v}:+       Token TimeGrain grain:+       _) -> Token Duration <$> timesThreeQuarter grain (floor (v - 1))+      _ -> Nothing+  } +ruleSavaDuration :: Rule+ruleSavaDuration = Rule+  { name = "Sava duration"+  , pattern =+    [ regex "सवा"+    , Predicate isNatural+    , dimension TimeGrain+    ]+  , prod = \case+      (_:+       Token Numeral NumeralData{TNumeral.value = v}:+       Token TimeGrain grain:+       _) -> Token Duration <$> timesOneQuarter grain (floor v)+      _ -> Nothing+  }++ruleSaadeDuration :: Rule+ruleSaadeDuration = Rule+  { name = "Saade duration"+  , pattern =+    [ regex "साढ़े|साड़े"+    , Predicate isNatural+    , dimension TimeGrain+    ]+  , prod = \case+      (_:+        Token Numeral NumeralData{TNumeral.value = v}:+        Token TimeGrain grain:+        _) -> Token Duration <$> nPlusOneHalf grain (floor v)+      _ -> Nothing+  }++ruleCompositeDuration :: Rule+ruleCompositeDuration = Rule+  { name = "composite <duration>"+  , pattern =+    [ Predicate isNatural+    , dimension TimeGrain+    , dimension Duration+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:+       Token TimeGrain g:+       Token Duration dd@DurationData{TDuration.grain = dg}:+       _) | g > dg -> Just $ Token Duration $ duration g (floor v) <> dd+      _ -> Nothing+  }++ruleCompositeDurationCommasAnd :: Rule+ruleCompositeDurationCommasAnd = Rule+  { name = "composite <duration> (with ,/और)"+  , pattern =+    [ Predicate isNatural+    , dimension TimeGrain+    , regex ",|और"+    , dimension Duration+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:+        Token TimeGrain g:+        _:+        Token Duration dd@DurationData{TDuration.grain = dg}:+        _) | g > dg -> Just $ Token Duration $ duration g (floor v) <> dd+      _ -> Nothing+  }++ruleNAndHalfDuration :: Rule+ruleNAndHalfDuration = Rule+  { name = "डेढ़|ढाई <duration>"+  , pattern =+    [ regex "(डेढ़|ढाई)"+    , dimension TimeGrain+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):+       Token TimeGrain grain:+       _) -> do+        h <- case Text.toLower match of+          "डेढ़" -> Just 1+          "ढाई" -> Just 2+          _ -> Nothing+        Token Duration <$> nPlusOneHalf grain h+      _ -> Nothing+  }+ rules :: [Rule] rules =   [  ruleDurationPandrahMinat@@ -111,4 +215,10 @@   ,  ruleAadha   ,  ruleDurationEkSaal   ,  ruleDurationPreciseImprecise+  ,  rulePauneDuration+  ,  ruleSavaDuration+  ,  ruleSaadeDuration+  ,  ruleCompositeDuration+  ,  ruleCompositeDurationCommasAnd+  ,  ruleNAndHalfDuration   ]
Duckling/Duration/HR/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-}
Duckling/Duration/HU/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} 
Duckling/Duration/HU/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Duration/Helpers.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -13,7 +12,10 @@   , isGrain   , isNatural   , minutesFromHourMixedFraction-  , timesOneAndAHalf+  , nPlusOneHalf+  , secondsFromHourMixedFraction+  , timesOneQuarter+  , timesThreeQuarter   ) where  import Prelude@@ -42,11 +44,33 @@ minutesFromHourMixedFraction h n d =   duration TG.Minute $ fromIntegral $ 60 * h + quot (n * 60) d -timesOneAndAHalf :: TG.Grain -> Int -> Maybe DurationData-timesOneAndAHalf grain = case grain of+nPlusOneHalf :: TG.Grain -> Int -> Maybe DurationData+nPlusOneHalf grain = case grain of   TG.Minute -> Just . duration TG.Second . (30+) . (60*)   TG.Hour   -> Just . duration TG.Minute . (30+) . (60*)   TG.Day    -> Just . duration TG.Hour   . (12+) . (24*)   TG.Month  -> Just . duration TG.Day    . (15+) . (30*)   TG.Year   -> Just . duration TG.Month  . (6+)  . (12*)+  _         -> const Nothing++secondsFromHourMixedFraction :: Integer -> Integer -> Integer -> DurationData+secondsFromHourMixedFraction m s d =+  duration TG.Second $ fromIntegral $ 60 * m + quot (s * 60) d++timesOneQuarter :: TG.Grain -> Int -> Maybe DurationData+timesOneQuarter grain = case grain of+  TG.Minute -> Just . duration TG.Second . (15+) . (60*)+  TG.Hour   -> Just . duration TG.Minute . (15+) . (60*)+  TG.Day    -> Just . duration TG.Hour   . (6+) . (24*)+  TG.Month  -> Just . duration TG.Day    . (7+) . (30*)+  TG.Year   -> Just . duration TG.Month  . (3+)  . (12*)+  _         -> const Nothing++timesThreeQuarter :: TG.Grain -> Int -> Maybe DurationData+timesThreeQuarter grain = case grain of+  TG.Minute -> Just . duration TG.Second . (45+) . (60*)+  TG.Hour   -> Just . duration TG.Minute . (45+) . (60*)+  TG.Day    -> Just . duration TG.Hour   . (18+) . (24*)+  TG.Month  -> Just . duration TG.Day    . (21+) . (30*)+  TG.Year   -> Just . duration TG.Month  . (9+)  . (12*)   _         -> const Nothing
Duckling/Duration/IT/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Duration/JA/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
+ Duckling/Duration/KA/Corpus.hs view
@@ -0,0 +1,58 @@+-- 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.Duration.KA.Corpus+  ( corpus+  ) where++import Prelude+import Data.String++import Duckling.Duration.Types+import Duckling.Testing.Types+import Duckling.TimeGrain.Types (Grain(..))++import Duckling.Locale+import Duckling.Resolve++corpus :: Corpus+corpus = (testContext {locale = makeLocale KA Nothing},+  testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DurationData 1 Second)+             [ "ერთი წამი"+             , "1 წამი"+             ]+  , examples (DurationData 2 Minute)+             [ "2 წუთი"+             , "ორი წუთი"+             ]+  , examples (DurationData 30 Day)+             [ "30 დღე"+             ]+  , examples (DurationData 7 Week)+             [ "შვიდი კვირა"+             ]+  , examples (DurationData 1 Month)+             [ "1 თვე"+             , "ერთი თვე"+             ]+  , examples (DurationData 3 Quarter)+             [ "3 კვარტალი"+             ]+  , examples (DurationData 27 Month)+             [ "2 წელი და 3 თვე"+             , "2 წელი, 3 თვე"+             ]+  , examples (DurationData 31719604 Second)+             [ "1 წელი, 2 დღე, 3 საათი და 4 წამი"+             ]+  ]
+ Duckling/Duration/KA/Rules.hs view
@@ -0,0 +1,155 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Duration.KA.Rules+  ( rules+  ) where++import Data.Semigroup ((<>))+import Data.String+import Prelude+import qualified Data.Text as Text++import Duckling.Dimensions.Types+import Duckling.Duration.Helpers+import Duckling.Duration.Types (DurationData(..))+import Duckling.Numeral.Helpers (parseInt, parseInteger)+import Duckling.Numeral.Types (NumeralData(..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Duration.Types as TDuration+import qualified Duckling.Numeral.Types as TNumeral+import qualified Duckling.TimeGrain.Types as TG++ruleCompositeDuration :: Rule+ruleCompositeDuration = Rule+  { name = "composite <duration>"+  , pattern =+    [ Predicate isNatural+    , dimension TimeGrain+    , regex ",|და"+    , dimension Duration+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:+       Token TimeGrain g:_:+       Token Duration dd@DurationData{TDuration.grain = dg}:+       _) | g > dg -> Just . Token Duration $ duration g (floor v) <> dd+      _ -> Nothing+  }++ruleCompositeDuration1 :: Rule+ruleCompositeDuration1 = Rule+  { name = "composite <duration>"+  , pattern =+    [ dimension TimeGrain+    , regex ",|და"+    , dimension Duration+    ]+  , prod = \case+      (Token TimeGrain g:_:+       Token Duration dd@DurationData{TDuration.grain = dg}:+       _) | g > dg -> Just . Token Duration $ duration g 1 <> dd+      _ -> Nothing+  }++ruleDurationYear :: Rule+ruleDurationYear = Rule+  { name = "<integer> year"+  , pattern =+    [ Predicate isNatural+    , regex "წელიწად(ის)?(ი)?(ში)?|წლი(ის)?(ში)?|წელშ?ი"+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:_) ->+        Just . Token Duration . duration TG.Month $ 12 * floor v+      _ -> Nothing+  }++ruleDurationAndHalfYear :: Rule+ruleDurationAndHalfYear = Rule+  { name = "<integer> and an half year"+  , pattern =+    [ Predicate isNatural+    , regex "წელიწადნახევა?(რის)?(რი)?(რში)?|წლინახევრ(ის)?(არში)?"+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:_) ->+        Just . Token Duration . duration TG.Month $ 6 + 12 * floor v+      _ -> Nothing+  }++ruleDurationAndHalfYear1 :: Rule+ruleDurationAndHalfYear1 = Rule+  { name = "<integer> and an half year"+  , pattern =+    [ regex "წელიწადნახევა?(რის)?(რი)?(რში)?|წლინახევრ(ის)?(არში)?"+    ]+  , prod = const $ Just . Token Duration . duration TG.Month $ 18+  }++ruleDurationAndHalfMonth :: Rule+ruleDurationAndHalfMonth = Rule+  { name = "<integer> and an half month"+  , pattern =+    [ Predicate isNatural+    , regex "თვენახევა?(რის)?(რი)?(რში)?"+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:_) ->+        Just . Token Duration . duration TG.Day $ 15 + 30 * floor v+      _ -> Nothing+  }++ruleDurationAndHalfMonth1 :: Rule+ruleDurationAndHalfMonth1 = Rule+  { name = "month and an half month"+  , pattern =+    [ regex "თვენახევა?(რის)?(რი)?(რში)?"+    ]+  , prod = const $ Just . Token Duration . duration TG.Day $ 45+  }++ruleDurationAndHalfWeek :: Rule+ruleDurationAndHalfWeek = Rule+  { name = "<integer> and an half week"+  , pattern =+    [ Predicate isNatural+    , regex "თვენახევა?(რის)?(რი)?(რში)?"+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:_) ->+        Just . Token Duration . duration TG.Day $ 3 + 7 * floor v+      _ -> Nothing+  }++ruleDurationAndHalfWeek1 :: Rule+ruleDurationAndHalfWeek1 = Rule+  { name = "week and an half week"+  , pattern =+    [ regex "კვირანახევა?(რის)?(რი)?(რში)?"+    ]+  , prod = const $ Just . Token Duration . duration TG.Day $ 10+  }++rules :: [Rule]+rules =+  [ ruleCompositeDuration+  , ruleCompositeDuration1+  , ruleDurationAndHalfYear+  , ruleDurationAndHalfYear1+  , ruleDurationAndHalfMonth+  , ruleDurationAndHalfMonth1+  , ruleDurationAndHalfWeek+  , ruleDurationAndHalfWeek1+  , ruleDurationYear+  ]
Duckling/Duration/KO/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Duration/KO/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
+ Duckling/Duration/MN/Corpus.hs view
@@ -0,0 +1,67 @@+-- 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.Duration.MN.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Duration.Types+import Duckling.Locale+import Duckling.Resolve+import Duckling.Testing.Types+import Duckling.TimeGrain.Types (Grain(..))++corpus :: Corpus+corpus = (testContext {locale = makeLocale MN Nothing}, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DurationData 1 Second)+             [ "1 сек"+             , "1 секунд"+             , "секунд"+             , "1\""+             ]+  , examples (DurationData 15 Minute)+             [ "15 мин"+             , "15'"+             ]+  , examples (DurationData 30 Minute)+             [ "30 минут"+             ]+  , examples (DurationData 5400 Second)+             [ "5400 секунд"+             ]+  , examples (DurationData 8 Hour)+             [ "8 цаг"+             , "8 ц"+             ]+  , examples (DurationData 15 Day)+             [ "15 өдөр"+             ]+  , examples (DurationData 7 Week)+             [ "7 долоо хоног"+             ]+  , examples (DurationData 1 Month)+             [ "1 сар"+             , "сар"+             ]+  , examples (DurationData 6 Month)+             [ "6 сар"+             ]+  , examples (DurationData 2 Year)+             [ "2 жил"+             ]+  , examples (DurationData 12 Hour)+             [ "12 цаг"+             ]+  ]
+ Duckling/Duration/MN/Rules.hs view
@@ -0,0 +1,117 @@+-- 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.MN.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.Duration.Helpers+import Duckling.Numeral.Helpers (numberWith)+import Duckling.Numeral.Types (NumeralData(..), isInteger)+import Duckling.Duration.Types (DurationData (DurationData))+import Duckling.Regex.Types+import Duckling.Types+import Duckling.TimeGrain.Types+import qualified Duckling.Numeral.Types as TNumeral++grainsMap :: HashMap Text Grain+grainsMap = HashMap.fromList+  [ ("жил"  , Year)+  , ("сар", Month)+  , ("өдөр"   , Day)+  , ("цаг"  , Hour)+  , ("минут", Minute)+  ]++-- TODO: Single-word composition (#110)+ruleHalves :: Rule+ruleHalves = Rule+  { name = "half of a grain"+  , pattern =+    [ regex "хагас\\s?(жил|сар|өдөр|цаг|минут)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (x:_)):_) -> do+        grain <- HashMap.lookup (Text.toLower x) grainsMap+        Token Duration <$> nPlusOneHalf grain 0+      _ -> Nothing+  }++ruleNumeralQuotes :: Rule+ruleNumeralQuotes = Rule+  { name = "<integer> + '\""+  , pattern =+    [ Predicate isNatural+    , regex "(['\"])"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = v}:+       Token RegexMatch (GroupMatch (x:_)):+       _) -> case x of+         "'"  -> Just . Token Duration . duration Minute $ floor v+         "\"" -> Just . Token Duration . duration Second $ floor v+         _    -> Nothing+      _ -> Nothing+  }++ruleDurationPrecision :: Rule+ruleDurationPrecision = Rule+  { name = "about|exactly <duration>"+  , pattern =+    [ regex "(ойролцоогоор|яг)"+    , dimension Duration+    ]+    , prod = \tokens -> case tokens of+        (_:token:_) -> Just token+        _ -> Nothing+  }++ruleGrainAsDuration :: Rule+ruleGrainAsDuration = Rule+  { name = "a <unit-of-duration>"+  , pattern =+    [ dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_) -> Just . Token Duration $ duration grain 1+      _ -> Nothing+  }++rulePositiveDuration :: Rule+rulePositiveDuration = Rule+  { name = "<positive-numeral> <time-grain>"+  , pattern =+    [ numberWith TNumeral.value $ and . sequence [not . isInteger, (>0)]+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = v}:+       Token TimeGrain grain:+       _) -> Just . Token Duration . duration Second . floor $ inSeconds grain v+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ rulePositiveDuration+  , ruleDurationPrecision+  , ruleNumeralQuotes+  , ruleGrainAsDuration+  , ruleHalves+  ]
Duckling/Duration/NB/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Duration/NB/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Duration/NL/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -58,6 +57,21 @@   , examples (DurationData 45 Minute)              [ "3 kwartier"              ]+  , examples (DurationData 90 Minute)+             [ "anderhalf uur"+             ]+  , examples (DurationData 75 Minute)+             [ "een uur en een kwartier"+             , "een uur en 15 minuten"+             , "een uur, 15 minuten"+             , "een uur 15 minuten"+             ]+  , examples (DurationData 165 Minute)+             [ "twee uur en drie kwartier"+             , "twee uur, 3 kwartier"+             , "twee uur, 45 minuten"+             , "twee uur 45 minuten"+             ]   , examples (DurationData 1 Hour)              [ "een uur"              , "één uur"@@ -66,6 +80,7 @@              ]   , examples (DurationData 30 Day)              [ "30 dagen"+             , "4 weken en 2 dagen"              ]   , examples (DurationData 7 Day)              [ "7 dagen"
Duckling/Duration/NL/Rules.hs view
@@ -2,12 +2,12 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE LambdaCase #-}  module Duckling.Duration.NL.Rules   ( rules ) where@@ -19,10 +19,12 @@  import Duckling.Dimensions.Types import Duckling.Duration.Helpers+import Duckling.Duration.Types (DurationData(..)) import Duckling.Numeral.Helpers (parseInt, parseInteger) import Duckling.Numeral.Types (NumeralData(..)) import Duckling.Regex.Types import Duckling.Types+import qualified Duckling.Duration.Types as TDuration import qualified Duckling.Numeral.Types as TNumeral import qualified Duckling.TimeGrain.Types as TG @@ -103,6 +105,48 @@       _ -> Nothing   } +ruleDurationOneAndHalfHour :: Rule+ruleDurationOneAndHalfHour = Rule+  { name = "1 and an half hour"+  , pattern = [ regex "anderhalf uur"]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 90+  }++-- | NOTE: Oxford comma is not supported.+ruleCompositeDurationCommasAnd :: Rule+ruleCompositeDurationCommasAnd = Rule+  { name = "composite <duration> (with ,/and)"+  , pattern =+    [ Predicate isNatural+    , dimension TimeGrain+    , regex ",|en|plus"+    , dimension Duration+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:+       Token TimeGrain g:+       _:+       Token Duration dd@DurationData{TDuration.grain = dg}:+       _) | g > dg -> Just . Token Duration $ duration g (floor v) <> dd+      _ -> Nothing+  }++ruleCompositeDuration :: Rule+ruleCompositeDuration = Rule+  { name = "composite <duration>"+  , pattern =+    [ Predicate isNatural+    , dimension TimeGrain+    , dimension Duration+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:+       Token TimeGrain g:+       Token Duration dd@DurationData{TDuration.grain = dg}:+       _) | g > dg -> Just . Token Duration $ duration g (floor v) <> dd+      _ -> Nothing+  }+ ruleDurationPrecision :: Rule ruleDurationPrecision = Rule   { name = "about|exactly <duration>"@@ -119,10 +163,13 @@ rules =   [ ruleDurationQuarterOfAnHour   , ruleDurationKwartier+  , ruleCompositeDurationCommasAnd+  , ruleCompositeDuration   , ruleDurationHalfAnHour   , ruleDurationThreeQuartersOfAnHour   , ruleDurationDotNumeralHours   , ruleDurationAndHalfHour+  , ruleDurationOneAndHalfHour   , ruleDurationPrecision   , ruleNumeralQuotes   ]
Duckling/Duration/PL/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -31,6 +30,7 @@              , "1 sekund"              , "jeden sekundzie"              , "pojedynczy sekundach"+             , "mniej więcej jedną sekundę"              ]   , examples (DurationData 30 Minute)              [ "pol godziny"
Duckling/Duration/PL/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -96,7 +95,7 @@ ruleAboutDuration = Rule   { name = "about <duration>"   , pattern =-    [ regex "(oko(l|ł)o|miej wi(ę|e)cej|jakie(s|ś))"+    [ regex "(oko(l|ł)o|mniej wi(ę|e)cej|jakie(s|ś))"     , dimension Duration     ]   , prod = \tokens -> case tokens of
Duckling/Duration/PT/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Duration/RO/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Duration/RO/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Duration/RU/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Duration/RU/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -50,7 +49,7 @@   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (x:_)):_) -> do         grain <- HashMap.lookup (Text.toLower x) grainsMap-        Token Duration <$> timesOneAndAHalf grain 0+        Token Duration <$> nPlusOneHalf grain 0       _ -> Nothing   } 
Duckling/Duration/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Duration/SV/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Duration/SV/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Duration/TR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Duration/TR/Rules.hs view
@@ -2,11 +2,10 @@ -- 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.-+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}  module Duckling.Duration.TR.Rules@@ -44,7 +43,7 @@ ruleDurationThreeQuartersOfAnHour :: Rule ruleDurationThreeQuartersOfAnHour = Rule   { name = "three-quarters of an hour"-  , pattern = [regex "(3/4\\s?sa(at)?|üçe \231eyrek sa(at)?)"]+  , pattern = [regex "(3/4\\s?sa(at)?|üç \231eyrek sa(at)?)"]   , prod = \_ -> Just . Token Duration $ duration TG.Minute 45   } @@ -90,7 +89,7 @@   { name = "<integer> and an half hour"   , pattern =     [ Predicate isNatural-    , regex "buçeuk sa(at)?"+    , regex "buçuk sa(at)?"     ]   , prod = \tokens -> case tokens of       (Token Numeral NumeralData{TNumeral.value = v}:_) ->@@ -103,7 +102,7 @@ ruleDurationPrecision = Rule   { name = "<duration> about|exactly"   , pattern =-    [ regex "(gibi|civar\305nda|yaklaş\305k|tam( olarak)?)"+    [ regex "(yaklaşık|tam(\\solarak)?)"     , dimension Duration     ]     , prod = \tokens -> case tokens of@@ -111,6 +110,18 @@         _           -> Nothing   } +ruleDurationPrecision2 :: Rule+ruleDurationPrecision2 = Rule+  { name = "<duration> about|exactly"+  , pattern =+    [ dimension Duration+    , regex "gibi|civarında"+    ]+  , prod = \case+      (token:_:_) -> Just token+      _           -> Nothing+  }+ rules :: [Rule] rules =   [ ruleDurationQuarterOfAnHour@@ -120,5 +131,6 @@   , ruleDurationDotNumeralHours   , ruleDurationAndHalfHour   , ruleDurationPrecision+  , ruleDurationPrecision2   , ruleNumeralQuotes   ]
Duckling/Duration/Types.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE DeriveAnyClass #-}
+ Duckling/Duration/UK/Corpus.hs view
@@ -0,0 +1,78 @@+-- 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.Duration.UK.Corpus+  ( corpus+  , negativeCorpus+  ) where++import Prelude+import Data.String++import Duckling.Duration.Types+import Duckling.Locale+import Duckling.Resolve+import Duckling.Testing.Types+import Duckling.TimeGrain.Types (Grain(..))++context :: Context+context = testContext {locale = makeLocale UK Nothing}++corpus :: Corpus+corpus = (context, testOptions, allExamples)++negativeCorpus :: NegativeCorpus+negativeCorpus = (context, testOptions, examples)+  where+    examples =+      [ "в дні"+      , "секретар"+      , "хвилини"+      ]++allExamples :: [Example]+allExamples = concat+  [ examples (DurationData 1 Second)+             [ "1 секунда"+             , "одна сек"+             ]+  , examples (DurationData 2 Minute)+             [ "2 хв"+             , "дві хвилини"+             ]+  , examples (DurationData 30 Day)+             [ "30 днів"+             ]+  , examples (DurationData 7 Week)+             [ "сім тижнів"+             ]+  , examples (DurationData 1 Month)+             [ "1 місяць"+             ]+  , examples (DurationData 2 Year)+             [ "2 роки"+             ]+  , examples (DurationData 30 Minute)+             [ "півгодини"+             , "1/2 години"+             ]+  , examples (DurationData 12 Hour)+             [ "пів дня"+             ]+  , examples (DurationData 90 Minute)+             [ "півтори години"+             ]+  , examples (DurationData 27 Month)+             [ "2 роки і 3 місяці"+             , "2 роки, 3 місяці"+             ]+  , examples (DurationData 31719604 Second)+             [ "1 рік, 2 дня, 3 години і 4 секунди"+             ]+  ]
+ Duckling/Duration/UK/Rules.hs view
@@ -0,0 +1,144 @@+-- 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.Duration.UK.Rules+  ( rules ) where++import Control.Monad (join)+import Data.Semigroup ((<>))+import Data.String+import Prelude+import qualified Data.Text as Text++import Duckling.Dimensions.Types+import Duckling.Duration.Helpers+import Duckling.Duration.Types (DurationData(..))+import Duckling.Numeral.Helpers (parseInt, parseInteger)+import Duckling.Numeral.Types (NumeralData(..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Duration.Types as TDuration+import qualified Duckling.Numeral.Types as TNumeral+import qualified Duckling.TimeGrain.Types as TG++ruleHalfAnHour :: Rule+ruleHalfAnHour = Rule+  { name = "half an hour"+  , pattern =+    [ regex "(1/2\\s?|пів\\s?)години?"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 30+  }++ruleNumeralnumberHours :: Rule+ruleNumeralnumberHours = Rule+  { name = "number.number hours"+  , pattern =+    [ regex "(\\d+)\\.(\\d+) години?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (h:m:_)):_) -> do+        hh <- parseInteger h+        mnum <- parseInteger m+        let mden = 10 ^ Text.length m+        Just . Token Duration $ minutesFromHourMixedFraction hh mnum mden+      _ -> Nothing+  }++ruleIntegerAndAnHalfHours :: Rule+ruleIntegerAndAnHalfHours = Rule+  { name = "<integer> and an half hours"+  , pattern =+    [ Predicate isNatural+    , regex "з половиною години"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = v}:_) ->+        Just . Token Duration . duration TG.Minute $ 30 + 60 * floor v+      _ -> Nothing+  }++ruleAboutDuration :: Rule+ruleAboutDuration = Rule+  { name = "about <duration>"+  , pattern =+    [ regex "близько"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleExactlyDuration :: Rule+ruleExactlyDuration = Rule+  { name = "exactly <duration>"+  , pattern =+    [ regex "рівно"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleDurationHalfATimeGrain :: Rule+ruleDurationHalfATimeGrain = Rule+  { name = "half a <time-grain>"+  , pattern =+    [ regex "(1/2|пів)"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> Token Duration <$> nPlusOneHalf grain 0+      _ -> Nothing+  }++ruleDurationOneGrainAndHalf :: Rule+ruleDurationOneGrainAndHalf = Rule+  { name = "one and a hald <unit-of-duration>"+  , pattern =+    [ regex "півтори"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> Token Duration <$> nPlusOneHalf grain 1+      _ -> Nothing+  }++ruleCompositeDurationCommasAnd :: Rule+ruleCompositeDurationCommasAnd = Rule+  { name = "composite <duration> (with ,/and)"+  , pattern =+    [ Predicate isNatural+    , dimension TimeGrain+    , regex ",|і"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = v}:+       Token TimeGrain g:+       _:+       Token Duration dd@DurationData{TDuration.grain = dg}:+       _) | g > dg -> Just . Token Duration $ duration g (floor v) <> dd+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAboutDuration+  , ruleExactlyDuration+  , ruleHalfAnHour+  , ruleIntegerAndAnHalfHours+  , ruleNumeralnumberHours+  , ruleDurationHalfATimeGrain+  , ruleDurationOneGrainAndHalf+  , ruleCompositeDurationCommasAnd+  ]
Duckling/Duration/ZH/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -48,4 +47,60 @@              [ "10 月"              , "十 月"              ]+  , examples (DurationData 30 Minute)+             [ "30分鐘"+             , "半個鐘"+             , "半小時"+             , "三十分鐘"+             , "卅分鐘"+             ]+  , examples (DurationData 12 Hour)+             [ "半日"+             , "半天"+             , "十二小時"+             , "十二個鐘"+             ]+  , examples (DurationData 90 Minute)+             [ "一個半小時"+             , "個半小時"+             , "個半鐘"+             , "一個半鐘"+             , "1.5小時"+             , "一個小時三十分鐘"+             , "一小時零三十分鐘"+             ]+  , examples (DurationData 130 Minute)+             [ "兩小時十分"+             , "一百三十分鐘"+             ]+  , examples (DurationData 3615 Second)+             [ "一小時零十五秒"+             , "一個鐘零十五秒"+             ]+  , examples (DurationData 45 Day)+             [ "一個半月"+             , "個半月"+             ]+  , examples (DurationData 27 Month)+             [ "兩年零三個月"+             , "廿七個月"+             ]+  , examples (DurationData 330 Second)+             [ "五個半分鐘"+             , "五點五分鐘"+             , "5.5分鐘"+             , "五分三十秒"+             , "五分半鐘"+             , "五分半"+             ]+  , examples (DurationData 90 Second)+              [ "一分半鐘"+              , "一分半"+              , "分半鐘"+              , "分半"+              ]+  , examples (DurationData 15 Minute)+              [ "3個字"+              , "三個字"+              ]   ]
+ Duckling/Duration/ZH/Rules.hs view
@@ -0,0 +1,301 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Duration.ZH.Rules+  ( rules+  ) where++import Prelude+import qualified Data.Text as Text++import Duckling.Dimensions.Types+import Duckling.Duration.Helpers+import Duckling.Duration.Types (DurationData(..))+import Duckling.Numeral.Helpers (parseInteger, decimalsToDouble)+import Duckling.Numeral.Types (NumeralData(..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Duration.Types as TDuration+import qualified Duckling.Numeral.Types as TNumeral+import qualified Duckling.TimeGrain.Types as TG++ruleDurationNFiveMinutes :: Rule+ruleDurationNFiveMinutes = Rule+  { name = "number of five minutes"+  , pattern =+    [ Predicate isNatural+    , regex "個字"+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:_) ->+        Just $ Token Duration $ duration TG.Minute $ floor v * 5+      _ -> Nothing+  }++ruleDurationHalfATimeGrain :: Rule+ruleDurationHalfATimeGrain = Rule+  { name = "half a <time-grain>"+  , pattern =+    [ regex "半"+    , dimension TimeGrain+    ]+  , prod = \case+      (_:Token TimeGrain grain:_) -> Token Duration <$> nPlusOneHalf grain 0+      _ -> Nothing+  }++ruleDurationOneGrainAndHalf :: Rule+ruleDurationOneGrainAndHalf = Rule+  { name = "a <unit-of-duration> and a half"+  , pattern =+    [ regex "一個半|個半"+    , dimension TimeGrain+    ]+  , prod = \case+      (_:Token TimeGrain grain:_) -> Token Duration <$> nPlusOneHalf grain 1+      _ -> Nothing+  }++ruleDurationOneGrainAndHalf2 :: Rule+ruleDurationOneGrainAndHalf2 = Rule+  { name = "a <unit-of-duration> and a half"+  , pattern =+    [ dimension TimeGrain+    , regex "半(鐘)?"+    ]+  , prod = \case+      (Token TimeGrain grain:_) -> Token Duration <$> nPlusOneHalf grain 1+      _ -> Nothing+  }++ruleDurationAndHalfGrain :: Rule+ruleDurationAndHalfGrain = Rule+  { name = "<integer> and a half <unit-of-duration>"+  , pattern =+    [ Predicate isNatural+    , dimension TimeGrain+    , regex "半(鐘)?"+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:Token TimeGrain grain:_) -> do+        let vv = floor v+        Token Duration <$> nPlusOneHalf grain vv+      _ -> Nothing+  }++ruleDurationAndHalfGrain2 :: Rule+ruleDurationAndHalfGrain2 = Rule+  { name = "<integer> and a half <unit-of-duration>"+  , pattern =+    [ Predicate isNatural+    , regex "個半"+    , dimension TimeGrain+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:_:Token TimeGrain grain:_) -> do+        let vv = floor v+        Token Duration <$> nPlusOneHalf grain vv+      _ -> Nothing+  }++ruleDurationDotNumeralHours :: Rule+ruleDurationDotNumeralHours = Rule+  { name = "number.number hours"+  , pattern =+    [ regex "(\\d+)\\.(\\d+)"+    , Predicate $ isGrain TG.Hour+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (h:m:_)):_) -> do+        hh <- parseInteger h+        mnum <- parseInteger m+        let mden = 10 ^ Text.length m+        Just $ Token Duration $ minutesFromHourMixedFraction hh mnum mden+      _ -> Nothing+  }++ruleDurationDotNumeralHours2 :: Rule+ruleDurationDotNumeralHours2 = Rule+  { name = "number.number hours"+  , pattern =+    [ Predicate isNatural+    , regex "點"+    , Predicate isNatural+    , Predicate $ isGrain TG.Hour+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = m}:+       _:+       Token Numeral NumeralData{TNumeral.value = s}:+       _) -> Just+        $ Token Duration+        $ duration TG.Minute+        $ floor ((m + decimalsToDouble s) * 60)+      _ -> Nothing+  }++ruleDurationDotNumeralMinutes :: Rule+ruleDurationDotNumeralMinutes = Rule+  { name = "number.number minutes"+  , pattern =+    [ regex "(\\d+)\\.(\\d+)"+    , Predicate $ isGrain TG.Minute+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (m:s:_)):_) -> do+        mm <- parseInteger m+        ss <- parseInteger s+        let sden = 10 ^ Text.length s+        Just $ Token Duration $ secondsFromHourMixedFraction mm ss sden+      _ -> Nothing+  }++ruleDurationDotNumeralMinutes2 :: Rule+ruleDurationDotNumeralMinutes2 = Rule+  { name = "number.number minutes"+  , pattern =+    [ Predicate isNatural+    , regex "點"+    , Predicate isNatural+    , Predicate $ isGrain TG.Minute+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = m}:+       _:+       Token Numeral NumeralData{TNumeral.value = s}:+       _) -> Just+        $ Token Duration+        $ duration TG.Second+        $ floor ((m + decimalsToDouble s) * 60)+      _ -> Nothing+  }++ruleDurationHoursAndMinutes :: Rule+ruleDurationHoursAndMinutes = Rule+  { name = "<integer> hours and <integer> minutes"+  , pattern =+    [ Predicate isNatural+    , Predicate $ isGrain TG.Hour+    , Predicate isNatural+    , Predicate $ isGrain TG.Minute+    ]+  , prod = \case+      (Token Numeral h:+       _:+       Token Numeral m:+       _) -> Just+        $ Token Duration+        $ duration TG.Minute+        $ floor (TNumeral.value m) + 60 * floor (TNumeral.value h)+      _ -> Nothing+  }++ruleDurationMinutesAndSeconds :: Rule+ruleDurationMinutesAndSeconds = Rule+  { name = "<integer> minutes and <integer> seconds"+  , pattern =+    [ Predicate isNatural+    , Predicate $ isGrain TG.Minute+    , Predicate isNatural+    , Predicate $ isGrain TG.Second+    ]+  , prod = \case+      (Token Numeral m:+       _:+       Token Numeral s:+       _) -> Just+        $ Token Duration+        $ duration TG.Second+        $ floor (TNumeral.value s) + 60 * floor (TNumeral.value m)+      _ -> Nothing+  }++ruleDurationHoursAndSeconds :: Rule+ruleDurationHoursAndSeconds = Rule+  { name = "<integer> hours and <integer> seconds"+  , pattern =+    [ Predicate isNatural+    , Predicate $ isGrain TG.Hour+    , Predicate isNatural+    , Predicate $ isGrain TG.Second+    ]+  , prod = \case+      (Token Numeral h:+       _:+       Token Numeral s:+       _) -> Just+         $ Token Duration+         $ duration TG.Second+         $ floor (TNumeral.value s) + 3600 * floor (TNumeral.value h)+      _ -> Nothing+  }++ruleDurationHoursAndMinutesAndSeconds :: Rule+ruleDurationHoursAndMinutesAndSeconds = Rule+  { name = "<integer> hours and <integer> minutes and <integer> seconds"+  , pattern =+    [ Predicate isNatural+    , Predicate $ isGrain TG.Hour+    , Predicate isNatural+    , Predicate $ isGrain TG.Minute+    , Predicate isNatural+    , Predicate $ isGrain TG.Second+    ]+  , prod = \case+      (Token Numeral h:+       _:+       Token Numeral m:+       _:+       Token Numeral s:+       _) -> Just+         $ Token Duration+         $ duration TG.Second+         $          floor (TNumeral.value s)+           + 60   * floor (TNumeral.value m)+           + 3600 * floor (TNumeral.value h)+      _ -> Nothing+  }++ruleCompositeDurationAnd :: Rule+ruleCompositeDurationAnd = Rule+  { name = "composite <duration> and <duration>"+  , pattern =+    [ dimension Duration+    , regex "零"+    , dimension Duration+    ]+  , prod = \case+      (Token Duration DurationData{TDuration.value = v, TDuration.grain = g}:+       _:+       Token Duration dd@DurationData{TDuration.grain = dg}:+       _) | g > dg -> Just $ Token Duration $ duration g v <> dd+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDurationNFiveMinutes+  , ruleDurationHalfATimeGrain+  , ruleDurationOneGrainAndHalf+  , ruleDurationOneGrainAndHalf2+  , ruleDurationAndHalfGrain+  , ruleDurationAndHalfGrain2+  , ruleDurationDotNumeralHours+  , ruleDurationDotNumeralHours2+  , ruleDurationDotNumeralMinutes+  , ruleDurationDotNumeralMinutes2+  , ruleDurationHoursAndMinutes+  , ruleDurationMinutesAndSeconds+  , ruleDurationHoursAndSeconds+  , ruleDurationHoursAndMinutesAndSeconds+  , ruleCompositeDurationAnd+  ]
Duckling/Email/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
+ Duckling/Email/DE/Corpus.hs view
@@ -0,0 +1,64 @@+-- 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.Email.DE.Corpus+  ( corpus+  , negativeCorpus+  ) where++import Data.String+import Prelude+import qualified Data.Text as Text++import Duckling.Email.Types+import Duckling.Locale+import Duckling.Resolve+import Duckling.Testing.Types++context :: Context+context = testContext {locale = makeLocale DE Nothing}++negativeCorpus :: NegativeCorpus+negativeCorpus = (context, testOptions, examples)+  where+    examples =+      [ "fitness at 6.40"+      , "class at 12.00"+      , "tonight at 9.15"+      , " dot 2@abci"+      , "x@ dot x"+      , "x@ x dot "+      , "abc@x dot "+      , Text.replicate 10000 "a at a"+      ]++corpus :: Corpus+corpus = (context, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (EmailData "alice@exAmple.io")+             [ "alice at exAmple.io"+             ]+  , examples (EmailData "yo+yo@blah.org")+             [ "yo+yo at blah.org"+             ]+  , examples (EmailData "1234+abc@x.net")+             [ "1234+abc at x.net"+             ]+  , examples (EmailData "jean-jacques@stuff.co.uk")+             [ "jean-jacques at stuff.co.uk"+             ]+  , examples (EmailData "asdf+ab.c@gmail.com")+             [ "asdf+ab punkt c at gmail punkt com"+             ]+  , examples (EmailData "asdf.k@fb.com")+             [ "asdf punkt k@fb punkt com"+             ]+  ]
+ Duckling/Email/DE/Rules.hs view
@@ -0,0 +1,41 @@+-- 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.Email.DE.Rules+  ( rules ) where++import Data.String+import Prelude+import qualified Data.Text as Text++import Duckling.Dimensions.Types+import Duckling.Email.Types (EmailData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Email.Types as TEmail++ruleEmailSpelledOut :: Rule+ruleEmailSpelledOut = Rule+  { name = "email spelled out"+  , pattern =+    [ regex "([\\w_+-]+(?:(?: punkt |\\.)[\\w_+-]+){0,10})(?: at |@)([a-zA-Z]+(?:(?:\\.| punkt )[\\w_-]+){1,10})"+    ]+  , prod = \xs -> case xs of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) ->+        Just $ Token Email EmailData+          { TEmail.value = Text.concat [replaceDots m1, "@", replaceDots m2] }+        where replaceDots = Text.replace " punkt " "."+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleEmailSpelledOut+  ]
Duckling/Email/EN/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Email/EN/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Email/FR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Email/FR/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
+ Duckling/Email/IS/Corpus.hs view
@@ -0,0 +1,39 @@+-- 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.Email.IS.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Email.Types+import Duckling.Locale+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {locale = makeLocale IS Nothing}, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (EmailData "alice@exAmple.io")+             [ "alice ingi exAmple.io"+             ]+  , examples (EmailData "yo+yo@blah.org")+             [ "yo+yo ingi blah.org"+             ]+  , examples (EmailData "1234+abc@x.net")+             [ "1234+abc ingi x.net"+             ]+  , examples (EmailData "jean-jacques@stuff.co.uk")+             [ "jean-jacques ingi stuff.co.uk"+             ]+  ]
+ Duckling/Email/IS/Rules.hs view
@@ -0,0 +1,39 @@+-- 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.Email.IS.Rules+  ( rules ) where++import Data.String+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Email.Types (EmailData (..))+import qualified Duckling.Email.Types as TEmail+import Duckling.Regex.Types+import Duckling.Types++ruleEmailSpelledOut :: Rule+ruleEmailSpelledOut = Rule+  { name = "email spelled out"+  , pattern =+    [ regex "([\\w\\._+-]+) ingi ([\\w_-]+(\\.[\\w_-]+)+)"+    ]+  , prod = \xs -> case xs of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) ->+        Just $ Token Email EmailData {TEmail.value = Text.concat [m1, "@", m2]}+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleEmailSpelledOut+  ]
Duckling/Email/IT/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Email/IT/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Email/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Email/Types.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE DeriveAnyClass #-}@@ -32,4 +31,7 @@   resolve _ _ x = Just (x, False)  instance ToJSON EmailData where-  toJSON EmailData {value} = object [ "value" .= value ]+  toJSON EmailData {value} = object+    [ "value" .= value+    , "type"  .= ("value" :: Text)+    ]
Duckling/Engine.hs view
@@ -2,15 +2,12 @@ -- 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.-+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE NoRebindableSyntax #-} - module Duckling.Engine   ( parseAndResolve   , lookupRegexAnywhere@@ -92,8 +89,9 @@   -- on here   (substring, rangeToText, translateRange) =     Document.byteStringFromPos doc position-  nodes = mapMaybe (f . Array.elems) $ Foldable.toList $-    matchFun regex substring+  nodes = mapMaybe (f . Array.elems)+    $ Foldable.toList+    $ matchFun regex substring   f :: [(Int, Int)] -> Maybe Node   f [] = Nothing   f ((0,0):_) = Nothing
Duckling/Engine/Regex.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   module Duckling.Engine.Regex
Duckling/Locale.hs view
@@ -2,40 +2,76 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE NoRebindableSyntax #-}- module Duckling.Locale   ( Lang(..)   , Locale(..)-  , Region(AU,BE,BZ,CA,CN,GB,HK,IE,IN,JM,MO,NZ,PH,TT,TW,US,ZA)+  , Region+      ( AU+      , BE+      , BZ+      , CL+      , CN+      , CO+      , EG+      , GB+      , HK+      , IE+      , IN+      , JM+      , MO+      , MX+      , NZ+      , PE+      , PH+      , TT+      , TW+      , US+      , VE+      , ZA+      )   , allLocales   , makeLocale   ) where -import Data.Hashable import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap import Data.HashSet (HashSet)+import qualified Data.HashSet as HashSet+import Data.Hashable import GHC.Generics import Prelude import TextShow (TextShow)-import qualified Data.HashMap.Strict as HashMap-import qualified Data.HashSet as HashSet import qualified TextShow as TS -import Duckling.Region hiding (NL)-import qualified Duckling.Region as R (Region(NL))+import Duckling.Region hiding+  ( AR+  , CA+  , ES+  , NL+  )+import qualified Duckling.Region as R+  ( Region+      ( AR+      , CA+      , ES+      , NL+      )+  )  -- | ISO 639-1 Language. -- See https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes data Lang-  = AR+  = AF+  | AR   | BG+  | BN+  | CA   | CS   | DA   | DE@@ -43,6 +79,8 @@   | EN   | ES   | ET+  | FA+  | FI   | FR   | GA   | HE@@ -50,10 +88,16 @@   | HR   | HU   | ID+  | IS   | IT   | JA   | KA+  | KN+  | KM   | KO+  | LO+  | ML+  | MN   | MY   | NB   | NE@@ -62,8 +106,12 @@   | PT   | RO   | RU+  | SK   | SV+  | SW   | TA+  | TE+  | TH   | TR   | UK   | VI@@ -92,8 +140,11 @@     locales = HashMap.lookupDefault HashSet.empty lang allLocales  allLocales :: HashMap Lang (HashSet Region)-allLocales = HashMap.fromList-  [ (EN, HashSet.fromList [AU, BZ, CA, GB, IN, IE, JM, NZ, PH, ZA, TT, US])-  , (NL, HashSet.fromList [BE, R.NL])-  , (ZH, HashSet.fromList [CN, HK, MO, TW])-  ]+allLocales =+  HashMap.fromList+    [ (AR, HashSet.fromList [EG])+    , (EN, HashSet.fromList [AU, BZ, R.CA, GB, IN, IE, JM, NZ, PH, ZA, TT, US])+    , (ES, HashSet.fromList [R.AR, CL, CO, R.ES, MX, PE, VE])+    , (NL, HashSet.fromList [BE, R.NL])+    , (ZH, HashSet.fromList [CN, HK, MO, TW])+    ]
+ Duckling/Numeral/AF/Corpus.hs view
@@ -0,0 +1,152 @@+-- 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.Numeral.AF.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus =+  ( testContext {locale = makeLocale AF Nothing}+  , testOptions+  , allExamples+  )++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "nul"+             , "geen"+             , "niks"+             ]+  , examples (NumeralValue 1)+             [ "een"+             ]+  , examples (NumeralValue 2)+             [ "twee"+             ]+  , examples (NumeralValue 3)+             [ "drie"+             ]+  , examples (NumeralValue 4)+             [ "vier"+             ]+  , examples (NumeralValue 5)+             [ "vyf"+             ]+  , examples (NumeralValue 6)+             [ "ses"+             ]+  , examples (NumeralValue 7)+             [ "sewe"+             ]+  , examples (NumeralValue 8)+             [ "agt"+             , "ag"+             ]+  , examples (NumeralValue 9)+             [ "nege"+             ]+  , examples (NumeralValue 10)+             [ "tien"+             ]+  , examples (NumeralValue 11)+             [ "elf"+             ]+  , examples (NumeralValue 12)+             [ "twaalf"+             , "dosyn"+             ]+  , examples (NumeralValue 14)+             [ "veertien"+             ]+  , examples (NumeralValue 15)+             [ "vyftien"+             ]+  , examples (NumeralValue 16)+             [ "sestien"+             ]+  , examples (NumeralValue 17)+             [ "sewentien"+             ]+  , examples (NumeralValue 19)+             [ "negentien"+             , "neentien"+             ]+  , examples (NumeralValue 20)+             [ "twintig"+             ]+  , examples (NumeralValue 22)+             [ "twee en twintig"+             ]+  , examples (NumeralValue 24)+             [ "vier en twintig"+             ]+  , examples (NumeralValue 26)+             [ "ses en twintig"+             ]+  , examples (NumeralValue 28)+             [ "agt en twintig"+             ]+  , examples (NumeralValue 33)+             [ "drie en dertig"+             ]+  , examples (NumeralValue 34)+             [ "vier en dertig"+             ]+  , examples (NumeralValue 50)+             [ "vyftig"+             ]+  , examples (NumeralValue 55)+             [ "vyf en vyftig"+             ]+  , examples (NumeralValue 1.1)+             [ "1,1"+             , "1,10"+             , "01,10"+             ]+  , examples (NumeralValue 0.77)+             [ "0,77"+             , ",77"+             ]+  , examples (NumeralValue 300)+             [ "3 honderd"+             , "drie honderd"+             ]+  , examples (NumeralValue 5000)+             [ "5 duisend"+             , "vyf duisend"+             ]+  , examples (NumeralValue 144)+             [ "een honderd vier en veertig"+             , "honderd vier en veertig"+             ]+  , examples (NumeralValue 122)+             [ "een honderd twee en twintig"+             , "honderd twee en twintig"+             ]+  , examples (NumeralValue 20000)+             [ "twintig duisend"+             ]+  , examples (NumeralValue 0.2)+             [ "0,2"+             , "1/5"+             , "2/10"+             , "3/15"+             , "20/100"+             ]+  ]
+ Duckling/Numeral/AF/Rules.hs view
@@ -0,0 +1,210 @@+-- 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 #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Numeral.AF.Rules+  ( rules+  ) where++import Control.Applicative ((<|>))+import Data.HashMap.Strict (HashMap)+import Data.Maybe+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.Numeral.Types (NumeralData(..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral++zeroAndTenMap :: HashMap Text Integer+zeroAndTenMap = HashMap.fromList+  [ ( "nul" , 0  )+  , ( "geen", 0  )+  , ( "niks", 0  )+  , ( "zero", 0  )+  , ( "tien", 10 )+  ]++oneToNineMap :: HashMap Text Integer+oneToNineMap = HashMap.fromList+  [ ( "een" , 1 )+  , ( "twee", 2 )+  , ( "drie", 3 )+  , ( "vier", 4 )+  , ( "vyf" , 5 )+  , ( "ses" , 6 )+  , ( "sewe", 7 )+  , ( "agt" , 8 )+  , ( "ag"  , 8 )+  , ( "nege", 9 )+  ]++ruleNumeral :: Rule+ruleNumeral = Rule+  { name = "number (0..10)"+  , pattern =+    [ regex . Text.unpack $+        Text.concat [ "(", Text.intercalate "|"+          ((HashMap.keys zeroAndTenMap) ++ (HashMap.keys oneToNineMap)), ")" ]+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        let x = Text.toLower match in+        (HashMap.lookup x oneToNineMap >>= integer) <|>+        (HashMap.lookup x zeroAndTenMap >>= integer)+      _ -> Nothing+  }++elevenToNineteenMap :: HashMap Text Integer+elevenToNineteenMap = HashMap.fromList+  [ ( "elf"      , 11 )+  , ( "twaalf"   , 12 )+  , ( "dertien"  , 13 )+  , ( "veertien" , 14 )+  , ( "vyftien"  , 15 )+  , ( "sestien"  , 16 )+  , ( "sewentien", 17 )+  , ( "agtien"   , 18 )+  , ( "negentien", 19 )+  , ( "neentien" , 19 )+  ]++ruleElevenToNineteen :: Rule+ruleElevenToNineteen = Rule+  { name = "number (11..19)"+  , pattern =+    [ regex "(elf|twaalf|dertien|veertien|vyftien|sestien|sewentien|agtien|neg?entien)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) elevenToNineteenMap >>= integer+      _ -> Nothing+  }++tensMap :: HashMap Text Integer+tensMap = HashMap.fromList+  [ ( "twin" , 20 )+  , ( "der"  , 30 )+  , ( "veer" , 40 )+  , ( "vyf"  , 50 )+  , ( "ses"  , 60 )+  , ( "sewen", 70 )+  , ( "tag"  , 80 )+  , ( "negen", 90 )+  , ( "neen" , 90 )+  ]++ruleTens :: Rule+ruleTens = Rule+  { name = "integer (20,30..90)"+  , pattern =+    [ regex "(twin|der|veer|vyf|ses|sewen|tag|neg?en)tig"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) tensMap >>= integer+      _ -> Nothing+  }++ruleCompositeTens :: Rule+ruleCompositeTens = Rule+  { name = "integer ([3-9][1-9])"+  , pattern =+    [ numberBetween 1 10+    , regex "en"+    , oneOf [20, 30..90]+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = units}:+       _:+       Token Numeral NumeralData{TNumeral.value = tens}:+       _) -> double $ tens + units+      _ -> Nothing+  }++ruleDecimals :: Rule+ruleDecimals = Rule+  { name = "decimal number"+  , pattern =+    [ regex "(\\d*\\,\\d+)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) -> parseDecimal False match+      _ -> Nothing+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(honderd|duisend)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "honderd" -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "duisend" -> double 1e3 >>= withGrain 3 >>= withMultipliable+        _ -> Nothing+      _ -> Nothing+  }++ruleDozen :: Rule+ruleDozen = Rule+  { name = "a dozen of"+  , pattern =+    [ regex "dosyn"+    ]+  , prod = \_ -> integer 12 >>= withMultipliable >>= notOkForAnyTime+  }++ruleSum :: Rule+ruleSum = Rule+  { name = "intersect 2 numbers"+  , pattern =+    [ Predicate $ and . sequence [hasGrain, isPositive]+    , Predicate $ and . sequence [not . isMultipliable, isPositive]+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = val1, TNumeral.grain = Just g}:+       Token Numeral NumeralData{TNumeral.value = val2}:+       _) | (10 ** fromIntegral g) > val2 -> double $ val1 + val2+      _ -> Nothing+  }++ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ dimension Numeral+    , Predicate isMultipliable+    ]+  , prod = \case+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleNumeral+  , ruleDozen+  , ruleDecimals+  , rulePowersOfTen+  , ruleElevenToNineteen+  , ruleTens+  , ruleCompositeTens+  , ruleSum+  , ruleMultiply+  ]
Duckling/Numeral/AR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -28,106 +27,155 @@   [ examples (NumeralValue 0)              [ "0"              , "صفر"+             , "٠"+             , "٠٫٠"              ]   , examples (NumeralValue 1)              [ "1"              , "واحد"+             , "١"+             , "١٫٠"              ]   , examples (NumeralValue 4)              [ "4"              , "أربعة"              , "أربع"              , "اربعه"+             , "٤"+             , "٤٫٠"              ]   , examples (NumeralValue 6)              [ "6"              , "ستة"              , "ست"              , "سته"+             , "٦"+             , "٦٫٠"              ]   , examples (NumeralValue 10)              [ "10"              , "عشرة"              , "عشره"+             , "١٠"+             , "١٠٫٠"              ]   , examples (NumeralValue 11)              [ "11"              , "إحدى عشرة"              , "إحدى عشر"              , "احد عشر"+             , "١١"+             , "١١٫٠"              ]   , examples (NumeralValue 12)              [ "12"              , "إثنتى عشر"              , "إثنى عشر"+             , "١٢"+             , "١٢٫٠"              ]   , examples (NumeralValue 14)              [ "14"              , "أربع عشر"+             , "١٤"+             , "١٤٫٠"              ]   , examples (NumeralValue 16)              [ "16"              , "ستة عشر"+             , "١٦"+             , "١٦٫٠"              ]   , examples (NumeralValue 17)              [ "17"              , "سبع عشر"+             , "١٧"+             , "١٧٫٠"              ]   , examples (NumeralValue 18)              [ "18"              , "ثمان عشرة"+             , "١٨"+             , "١٨٫٠"              ]   , examples (NumeralValue 20)              [ "عشرون"              , "عشرين"+             , "٢٠"+             , "٢٠٫٠"              ]   , examples (NumeralValue 21)              [ "واحدة و عشرون"              , "21"+             , "٢١"+             , "٢١٫٠"              ]   , examples (NumeralValue 24)              [ "أربعة و عشرون"              , "24"+             , "٢٤"+             , "٢٤٫٠"              ]   , examples (NumeralValue 26)              [ "ستة و عشرون"              , "26"+             , "٢٦"+             , "٢٦٫٠"              ]   , examples (NumeralValue 20)              [ "عشرون"              , "عشرين"+             , "٢٠"              ]   , examples (NumeralValue 30)              [ "ثلاثون"              , "ثلاثين"+             , "٣٠"+             , "٣٠٫٠"              ]   , examples (NumeralValue 33)              [ "33"              , "ثلاث و ثلاثون"+             , "٣٣"+             , "٣٣٫٠"              ]   , examples (NumeralValue 40)              [ "اربعون"              , "أربعين"+             , "٤٠"+             , "٤٠٫٠"              ]   , examples (NumeralValue 200)              [ "مائتين"              , "مائتان"+             , "٢٠٠"+             , "٢٠٠٫٠"              ]   , examples (NumeralValue 300)              [ "ثلاثمائة"+             , "٣٠٠"+             , "٣٠٠٫٠"              ]   , examples (NumeralValue 350)              [ "ثلاثمائة وخمسين"+             , "٣٥٠"+             , "٣٥٠٫٠"              ]   , examples (NumeralValue 500)              [ "خمسمائة"+             , "٥٠٠"+             , "٥٠٠٫٠"              ]   , examples (NumeralValue 525)              [ "خمسمائة و خمسة و عشرون"              , "525"+             , "٥٢٥"+             , "٥٢٥٫٠"              ]   , examples (NumeralValue 700)              [ "سبعمائة"+             , "٧٠٠"+             , "٧٠٠٫٠"              ]   , examples (NumeralValue 1.1)              [ "1.1"@@ -135,40 +183,78 @@              , "01.10"              , "1 فاصلة 1"              , "واحد فاصلة واحد"+             , "١١/١٠"+             , "١٫١"+             , "١٫١٠"              ]   , examples (NumeralValue 0.77)              [ "0.77"              , ".77"+             , "٧٧/١٠٠"+             , "٫٧٧"+             , "٠٫٧٧"+             , "٠٫٧٧٠"              ]   , examples (NumeralValue 2000)              [ "2000"              , "الفان"+             , "٢٠٠٠"              , "الفين"              ]   , examples (NumeralValue 100000)              [ "100000"              , "100 الف"+             , "١٠٠٠٠٠"+             , "١٠٠٠٠٠٫٠٠"+             , "١٠٠٬٠٠٠"+             , "١٠٠٬٠٠٠٫٠"              ]   , examples (NumeralValue 10000)              [ "10000"              , "10 آلاف"+             , "١٠٠٠٠"+             , "١٠٠٠٠٫٠٠"+             , "١٠٬٠٠٠"+             , "١٠٬٠٠٠٫٠٠"              ]   , examples (NumeralValue 1000000)              [ "1000000"              , "مليون"+             , "١٠٠٠٠٠٠"+             , "١٠٠٠٠٠٠٫٠٠"+             , "١٬٠٠٠٬٠٠٠"+             , "١٬٠٠٠٬٠٠٠٫٠٠"              ]   , examples (NumeralValue 2000000)              [ "2000000"              , "2 مليون"              , "مليونان"              , "مليونين"+             , "٢٠٠٠٠٠٠"+             , "٢٠٠٠٠٠٠٫٠٠"+             , "٢٬٠٠٠٬٠٠٠"+             , "٢٬٠٠٠٬٠٠٠٫٠٠"              ]   , examples (NumeralValue 3000000)              [ "3 ملايين"              , "3000000"              , "3 مليون"+             , "٣٠٠٠٠٠٠"+             , "٣٠٠٠٠٠٠٫٠٠"+             , "٣٬٠٠٠٬٠٠٠"+             , "٣٬٠٠٠٬٠٠٠٫٠٠"              ]   , examples (NumeralValue (-1200000))              [ "-1200000"+             , "-١٢٠٠٠٠٠"+             , "-١٢٠٠٠٠٠٫٠٠"+             , "-١٬٢٠٠٬٠٠٠"+             , "-١٬٢٠٠٬٠٠٠٫٠٠"+             ]+  , examples (NumeralValue (-1.2))+             [ "-١٢/١٠"+             , "-1.2"+             , "-١٫٢"+             , "-١٫٢٠"              ]   ]
+ Duckling/Numeral/AR/EG/Corpus.hs view
@@ -0,0 +1,257 @@+-- 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.Numeral.AR.EG.Corpus (allExamples) where++import Data.String+import Prelude++import Duckling.Numeral.Types+import Duckling.Testing.Types++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "صفر"+             , "٠"+             , "٠٫٠"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "واحد"+             , "١"+             , "١٫٠"+             ]+  , examples (NumeralValue 4)+             [ "4"+             , "أربع"+             , "اربعه"+             , "٤"+             , "٤٫٠"+             ]+  , examples (NumeralValue 6)+             [ "6"+             , "ستة"+             , "ست"+             , "سته"+             , "٦"+             , "٦٫٠"+             ]+  , examples (NumeralValue 10)+             [ "10"+             , "عشرة"+             , "عشره"+             , "١٠"+             , "١٠٫٠"+             ]+  , examples (NumeralValue 11)+             [ "11"+             , "حداشر"+             , "١١"+             , "١١٫٠"+             ]+  , examples (NumeralValue 12)+             [ "12"+             , "إتناشر"+             , "١٢"+             , "١٢٫٠"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "اربعتاشر"+             , "١٤"+             , "١٤٫٠"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "ستاشر"+             , "١٦"+             , "١٦٫٠"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "سبعتاشر"+             , "١٧"+             , "١٧٫٠"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "تمنتاشر"+             , "١٨"+             , "١٨٫٠"+             ]+  , examples (NumeralValue 20)+             [ "عشرين"+             , "٢٠"+             , "٢٠٫٠"+             ]+  , examples (NumeralValue 21)+             [ "واحد و عشرين"+             , "21"+             , "٢١"+             , "٢١٫٠"+             ]+  , examples (NumeralValue 24)+             [ "أربعة و عشرين"+             , "24"+             , "٢٤"+             , "٢٤٫٠"+             ]+  , examples (NumeralValue 26)+             [ "ستة و عشرين"+             , "26"+             , "٢٦"+             , "٢٦٫٠"+             ]+  , examples (NumeralValue 20)+             [ "عشرين"+             , "٢٠"+             ]+  , examples (NumeralValue 30)+             [ "ثلاثين"+             , "٣٠"+             , "٣٠٫٠"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "تلاتة و تلاتين"+             , "٣٣"+             , "٣٣٫٠"+             ]+  , examples (NumeralValue 40)+             [ "أربعين"+             , "٤٠"+             , "٤٠٫٠"+             ]+  , examples (NumeralValue 200)+             [ "متين"+             , "٢٠٠"+             , "٢٠٠٫٠"+             ]+  , examples (NumeralValue 210)+             [ "متين وعشرة"+             , "٢١٠"+             , "٢١٠٫٠"+             ]+  , examples (NumeralValue 221)+             [ "متين واحد وعشرين"+             , "٢٢١"+             , "٢٢١٫٠"+             ]+  , examples (NumeralValue 263)+             [ "متين تلاتة وستين"+             , "٢٦٣"+             , "٢٦٣٫٠"+             ]+  , examples (NumeralValue 300)+             [ "تلتمية"+             , "٣٠٠"+             , "٣٠٠٫٠"+             ]+  , examples (NumeralValue 350)+             [ "تلتمية وخمسين"+             , "٣٥٠"+             , "٣٥٠٫٠"+             ]+  , examples (NumeralValue 500)+             [ "خمسمية"+             , "٥٠٠"+             , "٥٠٠٫٠"+             ]+  , examples (NumeralValue 525)+             [ "خمسمية خمسة و عشرين"+             , "525"+             , "٥٢٥"+             , "٥٢٥٫٠"+             ]+  , examples (NumeralValue 700)+             [ "سبعمية"+             , "٧٠٠"+             , "٧٠٠٫٠"+             ]+  , examples (NumeralValue 1.1)+             [ "1.1"+             , "1.10"+             , "01.10"+             , "1 فاصلة 1"+             , "واحد فاصلة واحد"+             , "١١/١٠"+             , "١٫١"+             , "١٫١٠"+             ]+  , examples (NumeralValue 0.77)+             [ "0.77"+             , ".77"+             , "٧٧/١٠٠"+             , "٫٧٧"+             , "٠٫٧٧"+             , "٠٫٧٧٠"+             ]+  , examples (NumeralValue 2000)+             [ "2000"+             , "٢٠٠٠"+             , "الفين"+             ]+  , examples (NumeralValue 100000)+             [ "100000"+             , "100 الف"+             , "١٠٠٠٠٠"+             , "١٠٠٠٠٠٫٠٠"+             , "١٠٠٬٠٠٠"+             , "١٠٠٬٠٠٠٫٠"+             ]+  , examples (NumeralValue 10000)+             [ "10000"+             , "10 آلاف"+             , "١٠٠٠٠"+             , "١٠٠٠٠٫٠٠"+             , "١٠٬٠٠٠"+             , "١٠٬٠٠٠٫٠٠"+             ]+  , examples (NumeralValue 1000000)+             [ "1000000"+             , "مليون"+             , "١٠٠٠٠٠٠"+             , "١٠٠٠٠٠٠٫٠٠"+             , "١٬٠٠٠٬٠٠٠"+             , "١٬٠٠٠٬٠٠٠٫٠٠"+             ]+  , examples (NumeralValue 2000000)+             [ "2000000"+             , "2 مليون"+             , "اتنين مليون"+             , "٢٠٠٠٠٠٠"+             , "٢٠٠٠٠٠٠٫٠٠"+             , "٢٬٠٠٠٬٠٠٠"+             , "٢٬٠٠٠٬٠٠٠٫٠٠"+             ]+  , examples (NumeralValue 3000000)+             [ "3 ملايين"+             , "3000000"+             , "3 مليون"+             , "٣٠٠٠٠٠٠"+             , "٣٠٠٠٠٠٠٫٠٠"+             , "٣٬٠٠٠٬٠٠٠"+             , "٣٬٠٠٠٬٠٠٠٫٠٠"+             ]+  , examples (NumeralValue (-1200000))+             [ "-1200000"+             , "-١٢٠٠٠٠٠"+             , "-١٢٠٠٠٠٠٫٠٠"+             , "-١٬٢٠٠٬٠٠٠"+             , "-١٬٢٠٠٬٠٠٠٫٠٠"+             ]+  , examples (NumeralValue (-1.2))+             [ "-١٢/١٠"+             , "-1.2"+             , "-١٫٢"+             , "-١٫٢٠"+             ]+  ]
+ Duckling/Numeral/AR/EG/Helpers.hs view
@@ -0,0 +1,80 @@+-- 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.Numeral.AR.EG.Helpers+  ( digitsMap+  , numeralToStringMap+  , parseArabicDoubleAsText+  , parseArabicDoubleFromText+  , parseArabicIntAsText+  , parseArabicIntegerFromText+  ) where++import Control.Monad (join)+import Data.HashMap.Strict (HashMap)+import Data.Maybe (mapMaybe)+import Data.String+import Data.Text (Text)+import Duckling.Numeral.Helpers+  ( parseDouble+  , parseInteger+  )+import Prelude++import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text++numeralToStringMap :: HashMap Char String+numeralToStringMap =+  HashMap.fromList+    [ ('٠', "0")+    , ('١', "1")+    , ('٢', "2")+    , ('٣', "3")+    , ('٤', "4")+    , ('٥', "5")+    , ('٦', "6")+    , ('٧', "7")+    , ('٨', "8")+    , ('٩', "9")+    ]++digitsMap :: HashMap Text Integer+digitsMap =+  HashMap.fromList+    [ ("اتنين", 2)+    , ("تلات", 3)+    , ("اربع", 4)+    , ("أربع", 4)+    , ("خمس", 5)+    , ("ست", 6)+    , ("سبع", 7)+    , ("تمان", 8)+    , ("تسع", 9)+    ]++parseArabicIntAsText :: Text -> Text+parseArabicIntAsText =+  Text.pack+    . join+    . mapMaybe (`HashMap.lookup` numeralToStringMap)+    . Text.unpack++parseArabicIntegerFromText :: Text -> Maybe Integer+parseArabicIntegerFromText = parseInteger . parseArabicIntAsText++parseArabicDoubleAsText :: Text -> Text+parseArabicDoubleAsText =+  Text.pack+    . join+    . mapMaybe (`HashMap.lookup` HashMap.insert '٫' "." numeralToStringMap)+    . Text.unpack++parseArabicDoubleFromText :: Text -> Maybe Double+parseArabicDoubleFromText = parseDouble . parseArabicDoubleAsText
+ Duckling/Numeral/AR/EG/Rules.hs view
@@ -0,0 +1,343 @@+-- 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 #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Numeral.AR.EG.Rules (rules) where++import Data.Maybe+import Prelude+import qualified Data.HashMap.Strict as HashMap++import Duckling.Dimensions.Types+import Duckling.Numeral.AR.EG.Helpers+  ( digitsMap+  , parseArabicDoubleFromText+  , parseArabicIntegerFromText+  )+import Duckling.Numeral.Helpers+import Duckling.Numeral.Types (NumeralData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer 2"+  , pattern =+    [ regex "[إأا]?تني[ي]?ن"+    ]+  , prod = \_ -> integer 2+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer 3"+  , pattern =+    [ regex "تلات[هة]?"+    ]+  , prod = \_ -> integer 3+  }++ruleInteger8 :: Rule+ruleInteger8 = Rule+  { name = "integer 8"+  , pattern =+    [ regex "تمان(ي[هة])?"+    ]+  , prod = \_ -> integer 8+  }++ruleInteger11 :: Rule+ruleInteger11 = Rule+  { name = "integer 11"+  , pattern =+    [ regex "(إأا)?حداشر"+    ]+  , prod = \_ -> integer 11+  }++ruleInteger12 :: Rule+ruleInteger12 = Rule+  { name = "integer 12"+  , pattern =+    [ regex "[إأا]?[تط]ناشر"+    ]+  , prod = \_ -> integer 12+  }++ruleInteger13 :: Rule+ruleInteger13 = Rule+  { name = "integer 13"+  , pattern =+    [ regex "[تط]ل(ا)?[تط]اشر"+    ]+  , prod = \_ -> integer 13+  }++ruleInteger14 :: Rule+ruleInteger14 = Rule+  { name = "integer 14"+  , pattern =+    [ regex "[إأا]ربع[تط]اشر"+    ]+  , prod = \_ -> integer 14+  }++ruleInteger15 :: Rule+ruleInteger15 = Rule+  { name = "integer 15"+  , pattern =+    [ regex "خمس[تط]اشر"+    ]+  , prod = \_ -> integer 15+  }++ruleInteger16 :: Rule+ruleInteger16 = Rule+  { name = "integer 16"+  , pattern =+    [ regex "س[تط]اشر"+    ]+  , prod = \_ -> integer 16+  }++ruleInteger17 :: Rule+ruleInteger17 = Rule+  { name = "integer 17"+  , pattern =+    [ regex "سبع[تط]اشر"+    ]+  , prod = \_ -> integer 17+  }++ruleInteger18 :: Rule+ruleInteger18 = Rule+  { name = "integer 18"+  , pattern =+    [ regex "[تط]من[تط]اشر"+    ]+  , prod = \_ -> integer 18+  }++ruleInteger19 :: Rule+ruleInteger19 = Rule+  { name = "integer 19"+  , pattern =+    [ regex "تسع[تط]اشر"+    ]+  , prod = \_ -> integer 19+  }++ruleInteger30_80 :: Rule+ruleInteger30_80 = Rule+  { name = "integer (30, 80)"+  , pattern =+    [ regex "([تط]لا[تط]|[تط]مان)(ين)"+    ]+  , prod = \tokens -> case tokens of+      Token RegexMatch (GroupMatch (match:_)):_ ->+        (* 10) <$> HashMap.lookup match digitsMap >>= integer+      _ -> Nothing+  }++ruleInteger100 :: Rule+ruleInteger100 = Rule+  { name = "integer (100)"+  , pattern =+    [ regex "مي[هةت]"+    ]+  , prod = const $ integer 100+  }++ruleInteger200 :: Rule+ruleInteger200 = Rule+  { name = "integer (200)"+  , pattern =+    [ regex "م(ي)?تين"+    ]+  , prod = const $ integer 200+  }++ruleInteger300 :: Rule+ruleInteger300 = Rule+  { name = "integer (300)"+  , pattern =+    [ regex "([تط]و?لا?[تط]و?)مي[هةت]"+    ]+  , prod = const $ integer 300+  }++ruleInteger400 :: Rule+ruleInteger400 = Rule+  { name = "integer (400)"+  , pattern =+    [ regex "(رو?بعو?)مي[هةت]"+    ]+  , prod = const $ integer 400+  }++ruleInteger500 :: Rule+ruleInteger500 = Rule+  { name = "integer (500)"+  , pattern =+    [ regex "(خو?مسو?)مي[هةت]"+    ]+  , prod = const $ integer 500+  }++ruleInteger600 :: Rule+ruleInteger600 = Rule+  { name = "integer (600)"+  , pattern =+    [ regex "(سو?تو?)مي[هةت]"+    ]+  , prod = const $ integer 600+  }++ruleInteger700 :: Rule+ruleInteger700 = Rule+  { name = "integer (700)"+  , pattern =+    [ regex "(سو?بعو?)مي[هةت]"+    ]+  , prod = const $ integer 700+  }++ruleInteger800 :: Rule+ruleInteger800 = Rule+  { name = "integer (800)"+  , pattern =+    [ regex "([تط]و?منو?)مي[هةت]"+    ]+  , prod = const $ integer 800+  }++ruleInteger900 :: Rule+ruleInteger900 = Rule+  { name = "integer (900)"+  , pattern =+    [ regex "([تط]و?سعو?)مي[هةت]"+    ]+  , prod = const $ integer 900+  }++ruleInteger101_999 :: Rule+ruleInteger101_999 = Rule+  { name = "integer 101..999"+  , pattern =+    [ oneOf [100, 200 .. 900]+    , regex "\\s"+    , oneOf $ map (+) [10, 20 .. 90] <*> [1..9]+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = v1}:+       _:+       Token Numeral NumeralData{TNumeral.value = v2}:+       _) -> double $ v1 + v2+      _ -> Nothing+  }+++ruleInteger3000 :: Rule+ruleInteger3000 = Rule+  { name = "integer (3000)"+  , pattern =+    [ regex "([تط]لا?[تط])( ?[اآ])?لاف"+    ]+  , prod = const $ integer 3000+  }++ruleInteger4000 :: Rule+ruleInteger4000 = Rule+  { name = "integer (4000)"+  , pattern =+    [ regex "[أا]ربع(ت| ?[اآ])لاف"+    ]+  , prod = const $ integer 4000+  }++ruleInteger5000 :: Rule+ruleInteger5000 = Rule+  { name = "integer (5000)"+  , pattern =+    [ regex "خمس(ت| ?[اآ])لاف"+    ]+  , prod = const $ integer 5000+  }++ruleInteger6000 :: Rule+ruleInteger6000 = Rule+  { name = "integer (6000)"+  , pattern =+    [ regex "س(ت| ?[اآ])لاف"+    ]+  , prod = const $ integer 6000+  }++ruleInteger7000 :: Rule+ruleInteger7000 = Rule+  { name = "integer (7000)"+  , pattern =+    [ regex "سبع(ت| ?[اآ])لاف"+    ]+  , prod = const $ integer 7000+  }++ruleInteger8000 :: Rule+ruleInteger8000 = Rule+  { name = "integer (8000)"+  , pattern =+    [ regex "[تط]م[ا]?ن(ت| ?[اآ])لاف"+    ]+  , prod = const $ integer 8000+  }++ruleInteger9000 :: Rule+ruleInteger9000 = Rule+  { name = "integer (9000)"+  , pattern =+    [ regex "([تط]سع)(ت| ?[اآ])لاف"+    ]+  , prod = const $ integer 9000+  }++rules :: [Rule]+rules =+  [ ruleInteger2+  , ruleInteger3+  , ruleInteger8+  , ruleInteger11+  , ruleInteger12+  , ruleInteger13+  , ruleInteger14+  , ruleInteger15+  , ruleInteger16+  , ruleInteger17+  , ruleInteger18+  , ruleInteger19+  , ruleInteger30_80+  , ruleInteger100+  , ruleInteger200+  , ruleInteger300+  , ruleInteger400+  , ruleInteger500+  , ruleInteger600+  , ruleInteger700+  , ruleInteger800+  , ruleInteger900+  , ruleInteger101_999+  , ruleInteger3000+  , ruleInteger4000+  , ruleInteger5000+  , ruleInteger6000+  , ruleInteger7000+  , ruleInteger8000+  , ruleInteger9000+  ]
+ Duckling/Numeral/AR/Helpers.hs view
@@ -0,0 +1,80 @@+-- 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.Numeral.AR.Helpers+  ( digitsMap+  , numeralToStringMap+  , parseArabicDoubleAsText+  , parseArabicDoubleFromText+  , parseArabicIntAsText+  , parseArabicIntegerFromText+  ) where++import Control.Monad (join)+import Data.HashMap.Strict (HashMap)+import Data.Maybe (mapMaybe)+import Data.String+import Data.Text (Text)+import Duckling.Numeral.Helpers+  ( parseDouble+  , parseInteger+  )+import Prelude++import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text++numeralToStringMap :: HashMap Char String+numeralToStringMap =+  HashMap.fromList+    [ ('٠', "0")+    , ('١', "1")+    , ('٢', "2")+    , ('٣', "3")+    , ('٤', "4")+    , ('٥', "5")+    , ('٦', "6")+    , ('٧', "7")+    , ('٨', "8")+    , ('٩', "9")+    ]++digitsMap :: HashMap Text Integer+digitsMap =+  HashMap.fromList+    [ ("عشر", 2)+    , ("ثلاث", 3)+    , ("اربع", 4)+    , ("أربع", 4)+    , ("خمس", 5)+    , ("ست", 6)+    , ("سبع", 7)+    , ("ثمان", 8)+    , ("تسع", 9)+    ]++parseArabicIntAsText :: Text -> Text+parseArabicIntAsText =+  Text.pack+    . join+    . mapMaybe (`HashMap.lookup` numeralToStringMap)+    . Text.unpack++parseArabicIntegerFromText :: Text -> Maybe Integer+parseArabicIntegerFromText = parseInteger . parseArabicIntAsText++parseArabicDoubleAsText :: Text -> Text+parseArabicDoubleAsText =+  Text.pack+    . join+    . mapMaybe (`HashMap.lookup` HashMap.insert '٫' "." numeralToStringMap)+    . Text.unpack++parseArabicDoubleFromText :: Text -> Maybe Double+parseArabicDoubleFromText = parseDouble . parseArabicDoubleAsText
Duckling/Numeral/AR/Rules.hs view
@@ -2,26 +2,25 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-}--module Duckling.Numeral.AR.Rules-  ( rules-  ) where+{-# LANGUAGE NoRebindableSyntax #-} -import Data.HashMap.Strict (HashMap)+module Duckling.Numeral.AR.Rules (rules) where import Data.Maybe-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.AR.Helpers+  ( digitsMap+  , parseArabicDoubleFromText+  , parseArabicIntegerFromText+  ) import Duckling.Numeral.Helpers import Duckling.Numeral.Types (NumeralData (..)) import Duckling.Regex.Types@@ -62,19 +61,6 @@   , prod = \_ -> integer 12   } -digitsMap :: HashMap Text Integer-digitsMap = HashMap.fromList-  [ ("عشر", 2)-  , ("ثلاث", 3)-  , ("اربع", 4)-  , ("أربع", 4)-  , ("خمس", 5)-  , ("ست", 6)-  , ("سبع", 7)-  , ("ثمان", 8)-  , ("تسع", 9)-  ]- ruleInteger19 :: Rule ruleInteger19 = Rule   { name = "integer (20..90)"@@ -342,9 +328,62 @@       _ -> Nothing   } +ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "Arabic integer numeric"+  , pattern =+    [ regex "([٠-٩]{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseArabicIntegerFromText match >>= integer+      _ -> Nothing+  }++ruleFractionsNumeric :: Rule+ruleFractionsNumeric = Rule+  { name = "Arabic fractional number numeric"+  , pattern =+    [ regex "([٠-٩]+)/([٠-٩]+)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (numerator:denominator:_)):_) -> do+        n <- parseArabicIntegerFromText numerator >>= integer+        d <- parseArabicIntegerFromText denominator >>= integer+        divide n d >>= notOkForAnyTime+      _ -> Nothing+  }++ruleArabicDecimal :: Rule+ruleArabicDecimal = Rule+  { name = "Arabic decimal number with Arabic decimal separator"+  , pattern =+    [ regex "([٠-٩]*٫[٠-٩]+)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseArabicDoubleFromText match >>= double+      _ -> Nothing+  }++ruleArabicCommas :: Rule+ruleArabicCommas = Rule+  { name = "Arabic number with commas and optional Arabic decimal separator"+  , pattern =+    [ regex "([٠-٩]{1,3}(٬[٠-٩]{3}){1,5}(٫[٠-٩]+)?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseArabicDoubleFromText (Text.replace "٬" Text.empty match) >>=+          double+      _ -> Nothing+  }+ rules :: [Rule] rules =-  [ ruleDecimalNumeral+  [ ruleIntegerNumeric+  , ruleFractionsNumeric+  , ruleDecimalNumeral   , ruleDecimalWithThousandsSeparator   , ruleInteger   , ruleInteger11@@ -369,4 +408,6 @@   , ruleNumeralsPrefixWithMinus   , rulePowersOfTen   , ruleInteger200+  , ruleArabicDecimal+  , ruleArabicCommas   ]
Duckling/Numeral/BG/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/BG/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
+ Duckling/Numeral/BN/Corpus.hs view
@@ -0,0 +1,101 @@+-- 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.Numeral.BN.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {locale = makeLocale BN Nothing}, testOptions,+          allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+            [ "শূন্য"+            , "০"+            ]+  , examples (NumeralValue 1)+            [ "এক"+            ]+  , examples (NumeralValue 2)+            [ "দুই"+            ]+  , examples (NumeralValue 3)+            [ "তিন"+            ]+  , examples (NumeralValue 4)+            [ "চার"+            ]+  , examples (NumeralValue 5)+            [ "পাঁচ"+            ]+  , examples (NumeralValue 6)+            [ "ছয়"+            ]+  , examples (NumeralValue 7)+            [ "সাত"+            ]+  , examples (NumeralValue 8)+            [ "আট"+            ]+  , examples (NumeralValue 9)+            [ "নয়"+            ]+  , examples (NumeralValue 10)+            [ "দশ"+            ]+  , examples (NumeralValue 11)+            [ "এগারো"+            ]+  , examples (NumeralValue 15)+            [ "পনেরো"+            ]+  , examples (NumeralValue 17)+            [ "সতেরো"+            ]+  , examples (NumeralValue 20)+            [ "কুড়ি"+            ]+  , examples (NumeralValue 22)+            [ "বাইশ"+            ]+  , examples (NumeralValue 24)+            [ "চব্বিশ"+            ]+  , examples (NumeralValue 25)+            [ "পঁচিশ"+            ]+  , examples (NumeralValue 26)+            [ "ছাব্বিশ"+            ]+  , examples (NumeralValue 28)+            [ "আঠাশ"+            ]+  , examples (NumeralValue 30)+            [ "তিরিশ"+            ]+  , examples (NumeralValue 40)+            [ "চল্লিশ"+            ]+  , examples (NumeralValue 50)+            [ "পঞ্চাশ"+            ]+  , examples (NumeralValue 70)+            [ "সত্তর"+            ]+  ]
+ Duckling/Numeral/BN/Rules.hs view
@@ -0,0 +1,169 @@+-- 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 #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE LambdaCase #-}++module Duckling.Numeral.BN.Rules+  ( rules+  ) where++import Data.HashMap.Strict (HashMap)+import Data.Maybe+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.Numeral.Types (NumeralData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral++bengaliMap :: HashMap Char Char+bengaliMap = HashMap.fromList+  [ ( '০', '0' )+  , ( '১', '1' )+  , ( '২', '2' )+  , ( '৩', '3' )+  , ( '৪', '4' )+  , ( '৫', '5' )+  , ( '৬', '6' )+  , ( '৭', '7' )+  , ( '৮', '8' )+  , ( '৯', '9' )+  ]++bengaliToArab :: Char -> Char+bengaliToArab c = HashMap.lookupDefault c c bengaliMap++ruleBengali :: Rule+ruleBengali = Rule+  { name = "bengali forms"+  , pattern =+    [ regex "([০১২৩৪৫৬৭৮৯]{1,18})"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        toInteger <$> parseInt (Text.map bengaliToArab match) >>= integer+      _ -> Nothing+}++ruleNumeralMap :: HashMap Text Integer+ruleNumeralMap = HashMap.fromList+  [ ( "শূন্য", 0 )+  , ( "এক", 1 )+  , ( "দুই" , 2 )+  , ( "তিন", 3 )+  , ( "চার", 4 )+  , ( "পাঁচ", 5 )+  , ( "ছয়", 6 )+  , ( "সাত", 7 )+  , ( "আট", 8 )+  , ( "নয়" , 9 )+  , ( "দশ", 10 )+  ]++ruleNumeral :: Rule+ruleNumeral = Rule+  { name = "number (0..10)"+  , pattern =+    [ regex "(শূন্য|এক|দুই|তিন|চার|পাঁচ|ছয়|সাত|আট|নয়|দশ)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup match ruleNumeralMap >>= integer+      _ -> Nothing+}++elevenToNineteenMap :: HashMap Text Integer+elevenToNineteenMap = HashMap.fromList+  [ ( "এগারো", 11 )+  , ( "বারো", 12 )+  , ( "তেরো", 13 )+  , ( "চৌদ্দ", 14 )+  , ( "পনেরো", 15 )+  , ( "ষোল", 16 )+  , ( "সতেরো", 17 )+  , ( "আঠারো", 18 )+  , ( "উনিশ", 19 )+  ]++ruleElevenToNineteen :: Rule+ruleElevenToNineteen = Rule+  { name = "number (11..19)"+  , pattern =+    [ regex "(এগারো|বারো|তেরো|চৌদ্দ|পনেরো|ষোল|সতেরো|আঠারো|উনিশ)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup match elevenToNineteenMap >>= integer+      _ -> Nothing+}++twentyoneToTwentynineMap :: HashMap Text Integer+twentyoneToTwentynineMap = HashMap.fromList+  [ ( "একুশ", 21 )+  , ( "বাইশ", 22 )+  , ( "তেইশ", 23 )+  , ( "চব্বিশ", 24 )+  , ( "পঁচিশ", 25 )+  , ( "ছাব্বিশ", 26 )+  , ( "সাতাশ", 27 )+  , ( "আঠাশ", 28 )+  , ( "ঊনত্রিশ", 29 )+  ]++ruleTwentyoneToTwentynine :: Rule+ruleTwentyoneToTwentynine = Rule+  { name = "number (21..29)"+  , pattern =+    [ regex "(একুশ|বাইশ|তেইশ|চব্বিশ|পঁচিশ|ছাব্বিশ|সাতাশ|আঠাশ|ঊনত্রিশ)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup match twentyoneToTwentynineMap >>= integer+      _ -> Nothing+}++tensMap :: HashMap Text Integer+tensMap = HashMap.fromList+  [ ( "কুড়ি", 20 )+  , ( "তিরিশ", 30 )+  , ( "চল্লিশ", 40 )+  , ( "পঞ্চাশ", 50 )+  , ( "ষাট", 60 )+  , ( "সত্তর", 70 )+  , ( "আশি", 80 )+  , ( "নব্বই", 90 )+  ]++ruleTens :: Rule+ruleTens = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(কুড়ি|তিরিশ|চল্লিশ|পঞ্চাশ|ষাট|সত্তর|আশি|নব্বই)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup match tensMap >>= integer+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleBengali+  , ruleNumeral+  , ruleElevenToNineteen+  , ruleTwentyoneToTwentynine+  , ruleTens+  ]
+ Duckling/Numeral/CA/Corpus.hs view
@@ -0,0 +1,162 @@+-- 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.Numeral.CA.Corpus (corpus) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus =+  (testContext { locale = makeLocale CA Nothing }, testOptions, allExamples)++allExamples :: [Example]+allExamples =+  concat+    [ examples (NumeralValue 1)+        [ "1"+        , "u"+        , "un"+        , "una"+        ]+    , examples (NumeralValue 11)+        [ "onze"+        ]+    , examples (NumeralValue 12)+        [ "dotze"+        ]+    , examples (NumeralValue 13)+        [ "tretze"+        ]+    , examples (NumeralValue 14)+        [ "catorze"+        ]+    , examples (NumeralValue 15)+        [ "quinze"+        ]+    , examples (NumeralValue 16)+        [ "setze"+        ]+    , examples (NumeralValue 17)+        [ "disset"+        , "dèsset"+        ]+    , examples (NumeralValue 18)+        [ "divuit"+        , "dihuit"+        , "devuit"+        ]+    , examples (NumeralValue 19)+        [ "dinou"+        , "dènou"+        , "denou"+        ]+    , examples (NumeralValue 20)+        [ "vint"+        ]+    , examples (NumeralValue 21)+        [ "vint-i-un"+        , "vint i un"+        ]+    , examples (NumeralValue 22)+        [ "vint-i-dos"+        , "vint i dos"+        ]+    , examples (NumeralValue 23)+        [ "vint-i-tres"+        , "vint i tres"+        ]+    , examples (NumeralValue 37)+        [ "trenta-set"+        ]+    , examples (NumeralValue 40)+        [ "quaranta"+        ]+    , examples (NumeralValue 70)+        [ "setanta"+        ]+    , examples (NumeralValue 78)+        [ "Setanta-vuit"+        ]+    , examples (NumeralValue 80)+        [ "vuitanta"+        ]+    , examples (NumeralValue 33)+        [ "33"+        , "trenta-tres"+        , "trenta-3"+        ]+    , examples (NumeralValue 100000)+        [ "100000"+        , "100K"+        , "100k"+        ]+    , examples (NumeralValue 300)+        [ "tres-cents"+        ]+    , examples (NumeralValue 243)+        [ "243"+        ]+    , examples (NumeralValue 85)+        [ "vuitanta-cinc"+        ]+    , examples (NumeralValue 3000000)+        [ "3M"+        , "3000K"+        , "3000000"+        ]+    , examples (NumeralValue 1200000)+        [ "1200000"+        , "1200K"+        ]+    , examples (NumeralValue (-1200000))+        [ "-1200000"+        , "-1200K"+        ]+    , examples (NumeralValue 1.5)+        [ "1 coma cinc"+        , "una coma cinc"+        , "u coma cinc"+        ]+    , examples (NumeralValue 1)+        [ "zero u"+        , "zero un"+        ]+    , examples (NumeralValue 2)+        [ "zero dos"+        ]+    , examples (NumeralValue 3)+        [ "zero tres"+        ]+    , examples (NumeralValue 4)+        [ "zero quatre"+        ]+    , examples (NumeralValue 5)+        [ "zero cinc"+        ]+    , examples (NumeralValue 6)+        [ "zero sis"+        ]+    , examples (NumeralValue 7)+        [ "zero set"+        ]+    , examples (NumeralValue 8)+        [ "zero vuit"+        ]+    , examples (NumeralValue 9)+        [ "zero nou"+        ]+    ]++-- Ull, revisar la xifra amb decimals
+ Duckling/Numeral/CA/Rules.hs view
@@ -0,0 +1,300 @@+-- 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.Numeral.CA.Rules (rules) where++import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import Data.String+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers+import Duckling.Numeral.Types (NumeralData(..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Regex.Types+import Duckling.Types++zeroToFifteenMap :: HashMap Text Integer+zeroToFifteenMap =+  HashMap.fromList+    [ ("zero", 0)+    , ("u", 1)+    , ("un", 1)+    , ("una", 1)+    , ("dos", 2)+    , ("dues", 2)+    , ("tres", 3)+    , ("quatre", 4)+    , ("cinc", 5)+    , ("sis", 6)+    , ("set", 7)+    , ("vuit", 8)+    , ("nou", 9)+    , ("deu", 10)+    , ("onze", 11)+    , ("dotze", 12)+    , ("tretze", 13)+    , ("catorze", 14)+    , ("quinze", 15)+    ]++ruleZeroToFifteen :: Rule+ruleZeroToFifteen = Rule+  { name = "number (0..15)"+  , pattern =+      [ regex+          "(zero|u(na|n)?|d(o|ue)s|tres|quatre|cinc|sis|set|vuit|nou|deu|onze|dotze|tretze|catorze|quinze)"+      ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) zeroToFifteenMap >>= integer+      _ -> Nothing+  }++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern = [regex "-|menys", Predicate isPositive]+  , prod = \case+      (_ : Token Numeral NumeralData { TNumeral.value = v } : _) ->+        double $ negate v+      _ -> Nothing+  }++tensMap :: HashMap Text Integer+tensMap =+  HashMap.fromList+    [ ("vint", 20)+    , ("trenta", 30)+    , ("quaranta", 40)+    , ("cinquanta", 50)+    , ("seixanta", 60)+    , ("setanta", 70)+    , ("vuitanta", 80)+    , ("noranta", 90)+    ]++ruleTens :: Rule+ruleTens = Rule+  { name = "number (20..90)"+  , pattern =+      [ regex+          "(vint|(tre|quara|cinqua|seixa|seta|vuita|nora)nta)"+      ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)) : _) ->+        HashMap.lookup (Text.toLower match) tensMap >>= integer+      _ -> Nothing+  }++sixteenToTwentyNineMap :: HashMap Text Integer+sixteenToTwentyNineMap =+  HashMap.fromList+    [ ("setze", 16)+    , ("disset", 17)+    , ("dèsset", 17)+    , ("devuit", 18)+    , ("divuit", 18)+    , ("dihuit", 18)+    , ("dinou", 19)+    , ("dènou", 19)+    , ("denou", 19)+    , ("vint-i-u", 21)+    , ("vint-i-una", 21)+    , ("vint-i-dos", 22)+    , ("vint-i-tres", 23)+    , ("vint-i-quatre", 24)+    , ("vint-i-cinc", 25)+    , ("vint-i-sis", 26)+    , ("vint-i-set", 27)+    , ("vint-i-vuit", 28)+    , ("vint-i-nou", 29)+    ]++ruleLowerTensWithOnes :: Rule+ruleLowerTensWithOnes = Rule+  { name = "number (16..19 21..29)"+  , pattern =+      [ regex+          "(setze|d(i|e|è)sset|d(e|i)(v|h)uit|d(i|e|è)nou|vint-i-u(na)?|vint-i-dos|vint-i-tres|vint-i-quatre|vint-i-cinc|vint-i-sis|vint-i-set|vint-i-vuit|vint-i-nou)"+      ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) sixteenToTwentyNineMap >>= integer+      _ -> Nothing+  }++ruleHigherTensWithOnes :: Rule+ruleHigherTensWithOnes = Rule+  { name = "number (31..39 41..49 51..59 61..69 71..79 81..89 91..99)"+  , pattern =+      [oneOf [30, 40, 50, 60, 70, 80, 90], regex "-", numberBetween 1 9]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v1}:+       _:+       Token Numeral NumeralData{TNumeral.value = v2}:+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleNumeralsSuffixesKMG :: Rule+ruleNumeralsSuffixesKMG = Rule+  { name = "numbers suffixes (K, M, G)"+  , pattern = [dimension Numeral, regex "([kmg])(?=[\\W\\$€]|$)"]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:+       Token RegexMatch (GroupMatch (match:_)):+       _) ->+        case Text.toLower match of+          "k" -> double $ v * 1e3+          "m" -> double $ v * 1e6+          "g" -> double $ v * 1e9+          _ -> Nothing+      _ -> Nothing+  }++oneHundredToThousandMap :: HashMap Text Integer+oneHundredToThousandMap =+  HashMap.fromList+    [ ("cent", 100)+    , ("cents", 100)+    , ("dos-cents", 200)+    , ("tres-cents", 300)+    , ("quatre-cents", 400)+    , ("cinc-cents", 500)+    , ("sis-cents", 600)+    , ("set-cents", 700)+    , ("vuit-cents", 800)+    , ("nou-cents", 900)+    , ("mil", 1000)+    ]++ruleTwenties :: Rule+ruleTwenties = Rule+  { name = "number (21..29)"+  , pattern =+      [oneOf [20], regex "(-i-| i )", numberBetween 1 10]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v1}:+       _:+       Token Numeral NumeralData{TNumeral.value = v2}:+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleHundreds :: Rule+ruleHundreds = Rule+  { name = "number 100..1000 "+  , pattern =+      [ regex+          "(cent(s)?|dos-cents|tres-cents|quatre-cents|cinc-cents|sis-cents|set-cents|vuit-cents|nou-cents|mil)"+      ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) oneHundredToThousandMap >>= integer+      _ -> Nothing+  }++-- Afegeixo regex "-" perque les centenes s'escriuen dos-cent, tres-cent+ruleNumerals :: Rule+ruleNumerals = Rule+  { name = "numbers 200..999"+  , pattern =+      [ numberBetween 2 10+      , regex "-"+      , numberWith TNumeral.value (== 100)+      , numberBetween 0 100+      ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v1}:+       _:+       Token Numeral NumeralData{TNumeral.value = v2}:+       _) -> double $ 100 * v1 + v2+      _ -> Nothing+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number"+  , pattern = [dimension Numeral, regex "coma", Predicate $ not . hasGrain]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v1}:+       _:+       Token Numeral NumeralData{TNumeral.value = v2}:+       _) -> double $ v1 + decimalsToDouble v2+      _ -> Nothing+  }++ruleBelowTenWithTwoDigits :: Rule+ruleBelowTenWithTwoDigits = Rule+  { name = "integer (0-9) with two digits"+  , pattern =+      [ regex "zero|0"+      , numberBetween 1 10+      ]+  , prod = \case+      (_:Token Numeral NumeralData{TNumeral.value = v}:_) -> double v+      _ -> Nothing+  }++ruleDecimalWithThousandsSeparator :: Rule+ruleDecimalWithThousandsSeparator = Rule+  { name = "decimal with thousands separator ."+  , pattern = [regex "(\\d+(\\.\\d\\d\\d)+,\\d+)"]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        let fmt = Text.replace "," "." . Text.replace "." Text.empty $ match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++ruleDecimalNumeral :: Rule+ruleDecimalNumeral = Rule+  { name = "decimal number ,"+  , pattern = [regex "(\\d*,\\d+)"]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDecimal False match+      _ -> Nothing+  }++ruleIntegerWithThousandsSeparator :: Rule+ruleIntegerWithThousandsSeparator = Rule+  { name = "integer with thousands separator ."+  , pattern = [regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDouble (Text.replace "." Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleBelowTenWithTwoDigits+  , ruleZeroToFifteen+  , ruleTens+  , ruleTwenties+  , ruleLowerTensWithOnes+  , ruleHigherTensWithOnes+  , ruleHundreds++  , ruleNumeralDotNumeral+  , ruleNumerals+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  , ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleIntegerWithThousandsSeparator+  ]
Duckling/Numeral/CS/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/CS/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Numeral/DA/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/DA/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -142,14 +141,16 @@ rulePowersOfTen = Rule   { name = "powers of tens"   , pattern =-    [ regex "(hundrede?|tusinde?|million(er)?)"+    [ regex "(hundrede?|tohundrede|tusinde?|totusinde|million(er)?)"     ]   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of         "hundred"   -> double 1e2 >>= withGrain 2 >>= withMultipliable         "hundrede"  -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "tohundrede"  -> double (2 * 1e2) >>= withGrain 2 >>= withMultipliable         "tusind"    -> double 1e3 >>= withGrain 3 >>= withMultipliable         "tusinde"   -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "totusinde"   -> double (2 * 1e3) >>= withGrain 3 >>= withMultipliable         "million"   -> double 1e6 >>= withGrain 6 >>= withMultipliable         "millioner" -> double 1e6 >>= withGrain 6 >>= withMultipliable         _           -> Nothing
Duckling/Numeral/DE/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -58,6 +57,10 @@   , examples (NumeralValue 14)              [ "14"              , "vierzehn"+             ]+  , examples (NumeralValue 15)+             [ "15"+             , "fünfzehn"              ]   , examples (NumeralValue 16)              [ "16"
Duckling/Numeral/DE/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -90,7 +89,7 @@ ruleInteger3 = Rule   { name = "integer ([2-9][1-9])"   , pattern =-    [ regex "(ein|zwei|drei|vier|fünf|sechs|sieben|acht|neun)und(zwanzig|dreissig|vierzig|fünfzig|sechzig|siebzig|achtzig|neunzig)"+    [ regex "(ein|zwei|drei|vier|fünf|sechs|sieben|acht|neun)und(zwanzig|dreissig|dreißig|vierzig|fünfzig|sechzig|siebzig|achtzig|neunzig)"     ]   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do@@ -108,6 +107,7 @@         v2 <- case Text.toLower m2 of           "zwanzig" -> Just 20           "dreissig" -> Just 30+          "dreißig" -> Just 30           "vierzig" -> Just 40           "fünfzig" -> Just 50           "sechzig" -> Just 60@@ -255,7 +255,7 @@ ruleZeroToNineteen = Rule   { name = "integer (0..19)"   , pattern =-    [ regex "(keine[rn]|keine?s?|null|nichts|eins?(er)?|zwei|dreizehn|drei|vierzehn|vier|fünf|sechzehn|sechs|siebzehn|sieben|achtzehn|acht|neunzehn|neun|elf|zwölf|füfzehn)"+    [ regex "(keine[rn]|keine?s?|null|nichts|eins?(er)?|zwei|dreizehn|drei|vierzehn|vier|fünfzehn|fünf|sechzehn|sechs|siebzehn|sieben|achtzehn|acht|neunzehn|neun|elf|zwölf)"     ]   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (match:_)):_) ->@@ -267,6 +267,7 @@ tensMap = HashMap.fromList   [ ( "zwanzig" , 20 )   , ( "dreissig", 30 )+  , ( "dreißig" , 30 )   , ( "vierzig" , 40 )   , ( "fünfzig" , 50 )   , ( "sechzig" , 60 )@@ -280,7 +281,7 @@ ruleInteger2 = Rule   { name = "integer (20..90)"   , pattern =-    [ regex "(zwanzig|dreissig|vierzig|fünfzig|sechzig|siebzig|achtzig|neunzig)"+    [ regex "(zwanzig|dreissig|dreißig|vierzig|fünfzig|sechzig|siebzig|achtzig|neunzig)"     ]   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (match:_)):_) ->
Duckling/Numeral/EL/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/EL/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Numeral/EN/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -115,6 +114,9 @@              , "3000000"              , "3,000,000"              , "3 million"+             , "30 lakh"+             , "30 lkh"+             , "30 l"              ]   , examples (NumeralValue 1.2e6)              [ "1,200,000"@@ -122,6 +124,8 @@              , "1.2M"              , "1200k"              , ".0012G"+             , "12 lakhs"+             , "12 lkhs"              ]   , examples (NumeralValue 5000)              [ "5 thousand"@@ -140,6 +144,11 @@              , "-1200K"              , "-.0012G"              ]+  , examples (NumeralValue (-3200000))+             [ "-3,200,000"+             , "-3200000"+             , "minus three million two hundred thousand"+             ]   , examples (NumeralValue 122)              [ "one twenty two"              , "ONE TwentY tWO"@@ -156,6 +165,8 @@              ]   , examples (NumeralValue 31256721)              [ "thirty-one million two hundred fifty-six thousand seven hundred twenty-one"+             , "three crore twelve lakh fifty-six thousand seven hundred twenty-one"+             , "three cr twelve lac fifty-six thousand seven hundred twenty-one"              ]   , examples (NumeralValue 2400)              [ "two hundred dozens"@@ -167,5 +178,10 @@   , examples (NumeralValue 3000000000)              [ "three billions"              , "three thousand millions"+             , "three hundred crores"+             , "three hundred Cr"+             , "three hundred koti"+             , "three hundred krores"+             , "three hundred Kr"              ]   ]
Duckling/Numeral/EN/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -17,7 +16,6 @@ import Control.Applicative ((<|>)) import Data.HashMap.Strict (HashMap) import Data.Maybe-import Data.String import Data.Text (Text) import Prelude import qualified Data.HashMap.Strict as HashMap@@ -127,19 +125,32 @@       _ -> Nothing   } +powersOfTensMap :: HashMap Text Int+powersOfTensMap = HashMap.fromList+  [ ("hundred", 2)+  , ("thousand", 3)+  , ("lakh", 5)+  , ("lkh", 5)+  , ("l", 5)+  , ("lac", 5)+  , ("million", 6)+  , ("cr", 7)+  , ("crore", 7)+  , ("krore", 7)+  , ("kr", 7)+  , ("koti", 7)+  , ("billion", 9)+  , ("trillion", 12)+  ]+ rulePowersOfTen :: Rule rulePowersOfTen = Rule   { name = "powers of tens"-  , pattern =-    [ regex "(hundred|thousand|million|billion)s?"-    ]+  , pattern = [regex "(hundred|thousand|l(ac|(a?kh)?)|million|((k|c)r(ore)?|koti)|billion)s?"]   , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of-        "hundred"  -> double 1e2 >>= withGrain 2 >>= withMultipliable-        "thousand" -> double 1e3 >>= withGrain 3 >>= withMultipliable-        "million"  -> double 1e6 >>= withGrain 6 >>= withMultipliable-        "billion"  -> double 1e9 >>= withGrain 9 >>= withMultipliable-        _          -> Nothing+      (Token RegexMatch (GroupMatch (match : _)) : _) -> do+        grain <- HashMap.lookup (Text.toLower match) powersOfTensMap+        double (10 ^ grain) >>= withGrain grain >>= withMultipliable       _ -> Nothing   } @@ -148,10 +159,12 @@   { name = "integer 21..99"   , pattern =     [ oneOf [20,30..90]+    , regex "[\\s\\-]+"     , numberBetween 1 10     ]   , prod = \tokens -> case tokens of       (Token Numeral NumeralData{TNumeral.value = tens}:+       _:        Token Numeral NumeralData{TNumeral.value = units}:        _) -> double $ tens + units       _ -> Nothing@@ -312,7 +325,7 @@ ruleMultiply = Rule   { name = "compose by multiplication"   , pattern =-    [ dimension Numeral+    [ Predicate isPositive     , Predicate isMultipliable     ]   , prod = \tokens -> case tokens of
+ Duckling/Numeral/ES/AR/Corpus.hs view
@@ -0,0 +1,32 @@+-- 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.Numeral.ES.AR.Corpus (allExamples) where++import Data.String+import Prelude++import Duckling.Numeral.Types+import Duckling.Testing.Types++allExamples :: [Example]+allExamples =+  concat+    [ examples (NumeralValue 1) ["1"]+    , examples (NumeralValue 33) ["33"]+    , examples (NumeralValue 1.1) ["1,1", "1,10", "01,10"]+    , examples (NumeralValue 0.77) ["0,77", ",77"]+    , examples (NumeralValue 100000) ["100.000", "100000"]+    , examples (NumeralValue 243) ["243"]+    , examples (NumeralValue 3000000) ["3000000", "3.000.000"]+    , examples (NumeralValue 1200000) ["1.200.000", "1200000"]+    , examples+        (NumeralValue (-1200000))+        ["- 1.200.000", "menos 1.200.000", "-1,2M", "-,0012G"]+    , examples (NumeralValue 1.5) ["1,5"]+    ]
+ Duckling/Numeral/ES/AR/Rules.hs view
@@ -0,0 +1,58 @@+-- 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.Numeral.ES.AR.Rules (rules) where++import Data.Maybe+import Data.String+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers+import Duckling.Regex.Types+import Duckling.Types++ruleDecimalWithThousandsSeparator :: Rule+ruleDecimalWithThousandsSeparator = Rule+  { name = "decimal with thousands separator ."+  , pattern = [regex "(\\d+(\\.\\d\\d\\d)+,\\d+)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        let fmt = Text.replace "," "." $ Text.replace "." Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++ruleDecimalNumeral :: Rule+ruleDecimalNumeral = Rule+  { name = "decimal number ,"+  , pattern = [regex "(\\d*,\\d+)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        parseDecimal False match+      _ -> Nothing+  }++ruleIntegerWithThousandsSeparator :: Rule+ruleIntegerWithThousandsSeparator = Rule+  { name = "integer with thousands separator ."+  , pattern = [regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        parseDouble (Text.replace "." Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleIntegerWithThousandsSeparator+  ]
+ Duckling/Numeral/ES/CL/Corpus.hs view
@@ -0,0 +1,32 @@+-- 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.Numeral.ES.CL.Corpus (allExamples) where++import Data.String+import Prelude++import Duckling.Numeral.Types+import Duckling.Testing.Types++allExamples :: [Example]+allExamples =+  concat+    [ examples (NumeralValue 1) ["1"]+    , examples (NumeralValue 33) ["33"]+    , examples (NumeralValue 1.1) ["1,1", "1,10", "01,10"]+    , examples (NumeralValue 0.77) ["0,77", ",77"]+    , examples (NumeralValue 100000) ["100.000", "100000"]+    , examples (NumeralValue 243) ["243"]+    , examples (NumeralValue 3000000) ["3000000", "3.000.000"]+    , examples (NumeralValue 1200000) ["1.200.000", "1200000"]+    , examples+        (NumeralValue (-1200000))+        ["- 1.200.000", "menos 1.200.000", "-1,2M", "-,0012G"]+    , examples (NumeralValue 1.5) ["1,5"]+    ]
+ Duckling/Numeral/ES/CL/Rules.hs view
@@ -0,0 +1,58 @@+-- 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.Numeral.ES.CL.Rules (rules) where++import Data.Maybe+import Data.String+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers+import Duckling.Regex.Types+import Duckling.Types++ruleDecimalWithThousandsSeparator :: Rule+ruleDecimalWithThousandsSeparator = Rule+  { name = "decimal with thousands separator ."+  , pattern = [regex "(\\d+(\\.\\d\\d\\d)+,\\d+)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        let fmt = Text.replace "," "." $ Text.replace "." Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++ruleDecimalNumeral :: Rule+ruleDecimalNumeral = Rule+  { name = "decimal number ,"+  , pattern = [regex "(\\d*,\\d+)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        parseDecimal False match+      _ -> Nothing+  }++ruleIntegerWithThousandsSeparator :: Rule+ruleIntegerWithThousandsSeparator = Rule+  { name = "integer with thousands separator ."+  , pattern = [regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        parseDouble (Text.replace "." Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleIntegerWithThousandsSeparator+  ]
+ Duckling/Numeral/ES/CO/Corpus.hs view
@@ -0,0 +1,32 @@+-- 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.Numeral.ES.CO.Corpus (allExamples) where++import Data.String+import Prelude++import Duckling.Numeral.Types+import Duckling.Testing.Types++allExamples :: [Example]+allExamples =+  concat+    [ examples (NumeralValue 1) ["1"]+    , examples (NumeralValue 33) ["33"]+    , examples (NumeralValue 1.1) ["1,1", "1,10", "01,10"]+    , examples (NumeralValue 0.77) ["0,77", ",77"]+    , examples (NumeralValue 100000) ["100.000", "100000"]+    , examples (NumeralValue 243) ["243"]+    , examples (NumeralValue 3000000) ["3000000", "3.000.000"]+    , examples (NumeralValue 1200000) ["1.200.000", "1200000"]+    , examples+        (NumeralValue (-1200000))+        ["- 1.200.000", "menos 1.200.000", "-1,2M", "-,0012G"]+    , examples (NumeralValue 1.5) ["1,5"]+    ]
+ Duckling/Numeral/ES/CO/Rules.hs view
@@ -0,0 +1,58 @@+-- 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.Numeral.ES.CO.Rules (rules) where++import Data.Maybe+import Data.String+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers+import Duckling.Regex.Types+import Duckling.Types++ruleDecimalWithThousandsSeparator :: Rule+ruleDecimalWithThousandsSeparator = Rule+  { name = "decimal with thousands separator ."+  , pattern = [regex "(\\d+(\\.\\d\\d\\d)+,\\d+)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        let fmt = Text.replace "," "." $ Text.replace "." Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++ruleDecimalNumeral :: Rule+ruleDecimalNumeral = Rule+  { name = "decimal number ,"+  , pattern = [regex "(\\d*,\\d+)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        parseDecimal False match+      _ -> Nothing+  }++ruleIntegerWithThousandsSeparator :: Rule+ruleIntegerWithThousandsSeparator = Rule+  { name = "integer with thousands separator ."+  , pattern = [regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        parseDouble (Text.replace "." Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleIntegerWithThousandsSeparator+  ]
Duckling/Numeral/ES/Corpus.hs view
@@ -2,17 +2,14 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}--module Duckling.Numeral.ES.Corpus-  ( corpus ) where+module Duckling.Numeral.ES.Corpus (corpus) where -import Prelude import Data.String+import Prelude  import Duckling.Locale import Duckling.Numeral.Types@@ -20,91 +17,50 @@ import Duckling.Testing.Types  corpus :: Corpus-corpus = (testContext {locale = makeLocale ES Nothing}, testOptions, allExamples)+corpus =+  (testContext { locale = makeLocale ES Nothing }, testOptions, allExamples)  allExamples :: [Example]-allExamples = concat-  [ examples (NumeralValue 1)-             [ "1"-             , "uno"-             , "una"-             ]-  , examples (NumeralValue 11)-             [ "once"-             ]-  , examples (NumeralValue 16)-             [ "dieciséis"-             , "dieciseis"-             , "Diesiseis"-             , "diez y seis"-             ]-  , examples (NumeralValue 21)-             [ "veintiuno"-             , "veinte y uno"-             ]-  , examples (NumeralValue 23)-             [ "veintitrés"-             , "veinte y tres"-             ]-  , examples (NumeralValue 70)-             [ "setenta"-             ]-  , examples (NumeralValue 78)-             [ "Setenta y ocho"-             ]-  , examples (NumeralValue 80)-             [ "ochenta"-             ]-  , examples (NumeralValue 33)-             [ "33"-             , "treinta y tres"-             , "treinta y 3"-             ]-  , examples (NumeralValue 1.1)-             [ "1,1"-             , "1,10"-             , "01,10"-             ]-  , examples (NumeralValue 0.77)-             [ "0,77"-             , ",77"-             ]-  , examples (NumeralValue 100000)-             [ "100.000"-             , "100000"-             , "100K"-             , "100k"-             ]-  , examples (NumeralValue 300)-             [ "trescientos"-             ]-  , examples (NumeralValue 243)-             [ "243"-             ]-  , examples (NumeralValue 3000000)-             [ "3M"-             , "3000K"-             , "3000000"-             , "3.000.000"-             ]-  , examples (NumeralValue 1200000)-             [ "1.200.000"-             , "1200000"-             , "1,2M"-             , "1200K"-             , ",0012G"-             ]-  , examples (NumeralValue (-1200000))-             [ "- 1.200.000"-             , "-1200000"-             , "menos 1.200.000"-             , "-1,2M"-             , "-1200K"-             , "-,0012G"-             ]-  , examples (NumeralValue 1.5)-             [ "1 punto cinco"-             , "una punto cinco"-             , "1,5"-             ]-  ]+allExamples =+  concat+    [ examples (NumeralValue 1) ["1", "uno", "una"]+    , examples (NumeralValue 11) ["once"]+    , examples+        (NumeralValue 16)+        ["dieciséis", "dieciseis", "Diesiseis", "diez y seis"]+    , examples (NumeralValue 21) ["veintiuno", "veinte y uno"]+    , examples (NumeralValue 22) ["veintidós"]+    , examples (NumeralValue 23) ["veintitrés", "veinte y tres"]+    , examples (NumeralValue 70) ["setenta"]+    , examples (NumeralValue 78) ["Setenta y ocho"]+    , examples (NumeralValue 80) ["ochenta"]+    , examples (NumeralValue 33) ["33", "treinta y tres", "treinta y 3"]+    , examples (NumeralValue 100000) ["100000", "100K", "100k"]+    , examples (NumeralValue 300) ["trescientos"]+    , examples (NumeralValue 243) ["243"]+    , examples (NumeralValue 3000000) ["3M", "3000K", "3000000"]+    , examples (NumeralValue 1200000) ["1200000", "1200K"]+    , examples (NumeralValue (-1200000)) ["-1200000", "-1200K"]+    , examples (NumeralValue 1.5) ["1 punto cinco", "una punto cinco"]+    , examples (NumeralValue 1) ["cero uno", "zero uno"]+    , examples (NumeralValue 2) ["cero dos", "zero dos"]+    , examples (NumeralValue 3)+               [+                 "cero tres",+                 "cero trés",+                 "zero tres",+                 "zero trés"+               ]+    , examples (NumeralValue 4) ["cero cuatro", "zero cuatro"]+    , examples (NumeralValue 5) ["cero cinco", "zero cinco"]+    , examples (NumeralValue 6)+               [+                 "cero seis",+                 "cero séis",+                 "zero seis",+                 "zero séis"+               ]+    , examples (NumeralValue 7) ["cero siete", "zero siete"]+    , examples (NumeralValue 8) ["cero ocho", "zero ocho"]+    , examples (NumeralValue 9) ["cero nueve", "zero nueve"]+    ]
+ Duckling/Numeral/ES/ES/Corpus.hs view
@@ -0,0 +1,32 @@+-- 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.Numeral.ES.ES.Corpus (allExamples) where++import Data.String+import Prelude++import Duckling.Numeral.Types+import Duckling.Testing.Types++allExamples :: [Example]+allExamples =+  concat+    [ examples (NumeralValue 1) ["1"]+    , examples (NumeralValue 33) ["33"]+    , examples (NumeralValue 1.1) ["1,1", "1,10", "01,10"]+    , examples (NumeralValue 0.77) ["0,77", ",77"]+    , examples (NumeralValue 100000) ["100.000", "100000"]+    , examples (NumeralValue 243) ["243"]+    , examples (NumeralValue 3000000) ["3000000", "3.000.000"]+    , examples (NumeralValue 1200000) ["1.200.000", "1200000"]+    , examples+        (NumeralValue (-1200000))+        ["- 1.200.000", "menos 1.200.000", "-1,2M", "-,0012G"]+    , examples (NumeralValue 1.5) ["1,5"]+    ]
+ Duckling/Numeral/ES/ES/Rules.hs view
@@ -0,0 +1,67 @@+-- 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.Numeral.ES.ES.Rules+  ( rules+  , rulesBackwardCompatible+  ) where++import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import Data.String+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers+import Duckling.Numeral.Types (NumeralData(..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Regex.Types+import Duckling.Types++ruleDecimalWithThousandsSeparator :: Rule+ruleDecimalWithThousandsSeparator = Rule+  { name = "decimal with thousands separator ."+  , pattern = [regex "(\\d+(\\.\\d\\d\\d)+,\\d+)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        let fmt = Text.replace "," "." $ Text.replace "." Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++ruleDecimalNumeral :: Rule+ruleDecimalNumeral = Rule+  { name = "decimal number ,"+  , pattern = [regex "(\\d*,\\d+)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        parseDecimal False match+      _ -> Nothing+  }++ruleIntegerWithThousandsSeparator :: Rule+ruleIntegerWithThousandsSeparator = Rule+  { name = "integer with thousands separator ."+  , pattern = [regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        parseDouble (Text.replace "." Text.empty match) >>= double+      _ -> Nothing+  }++rulesBackwardCompatible :: [Rule]+rulesBackwardCompatible =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleIntegerWithThousandsSeparator+  ]++rules :: [Rule]+rules = rulesBackwardCompatible
+ Duckling/Numeral/ES/MX/Corpus.hs view
@@ -0,0 +1,32 @@+-- 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.Numeral.ES.MX.Corpus (allExamples) where++import Data.String+import Prelude++import Duckling.Numeral.Types+import Duckling.Testing.Types++allExamples :: [Example]+allExamples =+  concat+    [ examples (NumeralValue 1) ["1"]+    , examples (NumeralValue 33) ["33"]+    , examples (NumeralValue 1.1) ["1.1", "1.10", "01.10"]+    , examples (NumeralValue 0.77) ["0.77", ".77"]+    , examples (NumeralValue 100000) ["100,000", "100000"]+    , examples (NumeralValue 243) ["243"]+    , examples (NumeralValue 3000000) ["3000000", "3,000,000"]+    , examples (NumeralValue 1200000) ["1,200,000", "1200000"]+    , examples+        (NumeralValue (-1200000))+        ["- 1,200,000", "menos 1,200,000", "-1.2M", "-.0012G"]+    , examples (NumeralValue 1.5) ["1.5"]+    ]
+ Duckling/Numeral/ES/MX/Rules.hs view
@@ -0,0 +1,58 @@+-- 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.Numeral.ES.MX.Rules (rules) where++import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import Data.String+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers+import Duckling.Regex.Types+import Duckling.Types++ruleDecimalWithThousandsSeparator :: Rule+ruleDecimalWithThousandsSeparator = Rule+  { name = "decimal with thousands separator"+  , pattern = [regex "(\\d+(\\,\\d\\d\\d)+\\.\\d+)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        parseDouble (Text.replace "," Text.empty match) >>= double+      _ -> Nothing+  }++ruleDecimalNumeral :: Rule+ruleDecimalNumeral = Rule+  { name = "decimal number ."+  , pattern = [regex "(\\d*\\.\\d+)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        parseDecimal False match+      _ -> Nothing+  }++ruleIntegerWithThousandsSeparator :: Rule+ruleIntegerWithThousandsSeparator = Rule+  { name = "integer with thousands separator ,"+  , pattern = [regex "(\\d{1,3}(\\,\\d\\d\\d){1,5})"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        parseDouble (Text.replace "," Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleIntegerWithThousandsSeparator+  ]
+ Duckling/Numeral/ES/PE/Corpus.hs view
@@ -0,0 +1,32 @@+-- 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.Numeral.ES.PE.Corpus (allExamples) where++import Data.String+import Prelude++import Duckling.Numeral.Types+import Duckling.Testing.Types++allExamples :: [Example]+allExamples =+  concat+    [ examples (NumeralValue 1) ["1"]+    , examples (NumeralValue 33) ["33"]+    , examples (NumeralValue 1.1) ["1,1", "1,10", "01,10"]+    , examples (NumeralValue 0.77) ["0,77", ",77"]+    , examples (NumeralValue 100000) ["100.000", "100000"]+    , examples (NumeralValue 243) ["243"]+    , examples (NumeralValue 3000000) ["3000000", "3.000.000"]+    , examples (NumeralValue 1200000) ["1.200.000", "1200000"]+    , examples+        (NumeralValue (-1200000))+        ["- 1.200.000", "menos 1.200.000", "-1,2M", "-,0012G"]+    , examples (NumeralValue 1.5) ["1,5"]+    ]
+ Duckling/Numeral/ES/PE/Rules.hs view
@@ -0,0 +1,58 @@+-- 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.Numeral.ES.PE.Rules (rules) where++import Data.Maybe+import Data.String+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers+import Duckling.Regex.Types+import Duckling.Types++ruleDecimalWithThousandsSeparator :: Rule+ruleDecimalWithThousandsSeparator = Rule+  { name = "decimal with thousands separator ."+  , pattern = [regex "(\\d+(\\.\\d\\d\\d)+,\\d+)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        let fmt = Text.replace "," "." $ Text.replace "." Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++ruleDecimalNumeral :: Rule+ruleDecimalNumeral = Rule+  { name = "decimal number ,"+  , pattern = [regex "(\\d*,\\d+)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        parseDecimal False match+      _ -> Nothing+  }++ruleIntegerWithThousandsSeparator :: Rule+ruleIntegerWithThousandsSeparator = Rule+  { name = "integer with thousands separator ."+  , pattern = [regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        parseDouble (Text.replace "." Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleIntegerWithThousandsSeparator+  ]
Duckling/Numeral/ES/Rules.hs view
@@ -2,161 +2,138 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE LambdaCase #-} -module Duckling.Numeral.ES.Rules-  ( rules-  ) where+module Duckling.Numeral.ES.Rules (rules) where +import qualified Data.HashMap.Strict as HashMap import Data.Maybe import Data.String-import Prelude-import qualified Data.HashMap.Strict as HashMap import qualified Data.Text as Text+import Prelude  import Duckling.Dimensions.Types import Duckling.Numeral.Helpers-import Duckling.Numeral.Types (NumeralData (..))+import Duckling.Numeral.Types (NumeralData(..))+import qualified Duckling.Numeral.Types as TNumeral import Duckling.Regex.Types import Duckling.Types-import qualified Duckling.Numeral.Types as TNumeral  ruleNumeralsPrefixWithNegativeOrMinus :: Rule ruleNumeralsPrefixWithNegativeOrMinus = Rule   { name = "numbers prefix with -, negative or minus"-  , pattern =-    [ regex "-|menos"-    , Predicate isPositive-    ]-  , prod = \tokens -> case tokens of-      (_:Token Numeral NumeralData{TNumeral.value = v}:_) ->-        double $ v * (- 1)-      _ -> Nothing-  }--ruleDecimalWithThousandsSeparator :: Rule-ruleDecimalWithThousandsSeparator = Rule-  { name = "decimal with thousands separator"-  , pattern =-    [ regex "(\\d+(\\.\\d\\d\\d)+,\\d+)"-    ]-  , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):-       _) -> let fmt = Text.replace "," "." $ Text.replace "." Text.empty match-        in parseDouble fmt >>= double-      _ -> Nothing-  }--ruleDecimalNumeral :: Rule-ruleDecimalNumeral = Rule-  { name = "decimal number"-  , pattern =-    [ regex "(\\d*,\\d+)"-    ]+  , pattern = [regex "-|menos", Predicate isPositive]   , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):_) ->-        parseDecimal False match+      (_ : Token Numeral NumeralData { TNumeral.value = v } : _) ->+        double $ v * (-1)       _ -> Nothing   }  byTensMap :: HashMap.HashMap Text.Text Integer-byTensMap = HashMap.fromList-  [ ( "veinte" , 20 )-  , ( "treinta" , 30 )-  , ( "cuarenta" , 40 )-  , ( "cincuenta" , 50 )-  , ( "sesenta" , 60 )-  , ( "setenta" , 70 )-  , ( "ochenta" , 80 )-  , ( "noventa" , 90 )-  ]+byTensMap =+  HashMap.fromList+    [ ("veinte", 20)+    , ("treinta", 30)+    , ("cuarenta", 40)+    , ("cincuenta", 50)+    , ("sesenta", 60)+    , ("setenta", 70)+    , ("ochenta", 80)+    , ("noventa", 90)+    ]  ruleNumeral2 :: Rule ruleNumeral2 = Rule   { name = "number (20..90)"   , pattern =-    [ regex "(veinte|treinta|cuarenta|cincuenta|sesenta|setenta|ochenta|noventa)"-    ]+      [ regex+          "(veinte|treinta|cuarenta|cincuenta|sesenta|setenta|ochenta|noventa)"+      ]   , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):_) ->+      (Token RegexMatch (GroupMatch (match : _)) : _) ->         HashMap.lookup (Text.toLower match) byTensMap >>= integer       _ -> Nothing   }  zeroToFifteenMap :: HashMap.HashMap Text.Text Integer-zeroToFifteenMap = HashMap.fromList-  [ ( "zero" , 0 )-  , ( "cero" , 0 )-  , ( "un" , 1 )-  , ( "una" , 1 )-  , ( "uno" , 1 )-  , ( "dos" , 2 )-  , ( "trés" , 3 )-  , ( "tres" , 3 )-  , ( "cuatro" , 4 )-  , ( "cinco" , 5 )-  , ( "seis" , 6 )-  , ( "séis" , 6 )-  , ( "siete" , 7 )-  , ( "ocho" , 8 )-  , ( "nueve" , 9 )-  , ( "diez" , 10 )-  , ( "dies" , 10 )-  , ( "once" , 11 )-  , ( "doce" , 12 )-  , ( "trece" , 13 )-  , ( "catorce" , 14 )-  , ( "quince" , 15 )-  ]+zeroToFifteenMap =+  HashMap.fromList+    [ ("zero", 0)+    , ("cero", 0)+    , ("un", 1)+    , ("una", 1)+    , ("uno", 1)+    , ("dos", 2)+    , ("trés", 3)+    , ("tres", 3)+    , ("cuatro", 4)+    , ("cinco", 5)+    , ("seis", 6)+    , ("séis", 6)+    , ("siete", 7)+    , ("ocho", 8)+    , ("nueve", 9)+    , ("diez", 10)+    , ("dies", 10)+    , ("once", 11)+    , ("doce", 12)+    , ("trece", 13)+    , ("catorce", 14)+    , ("quince", 15)+    ]  ruleNumeral :: Rule ruleNumeral = Rule   { name = "number (0..15)"   , pattern =-    [ regex "((c|z)ero|un(o|a)?|dos|tr(é|e)s|cuatro|cinco|s(e|é)is|siete|ocho|nueve|die(z|s)|once|doce|trece|catorce|quince)"-    ]+      [ regex+          "((c|z)ero|un(o|a)?|dos|tr(é|e)s|cuatro|cinco|s(e|é)is|siete|ocho|nueve|die(z|s)|once|doce|trece|catorce|quince)"+      ]   , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):_) ->+      (Token RegexMatch (GroupMatch (match : _)) : _) ->         HashMap.lookup (Text.toLower match) zeroToFifteenMap >>= integer       _ -> Nothing   }  sixteenToTwentyNineMap :: HashMap.HashMap Text.Text Integer-sixteenToTwentyNineMap = HashMap.fromList-  [ ( "dieciseis" , 16 )-  , ( "diesiséis" , 16 )-  , ( "diesiseis" , 16 )-  , ( "dieciséis" , 16 )-  , ( "diecisiete" , 17 )-  , ( "dieciocho" , 18 )-  , ( "diecinueve" , 19 )-  , ( "veintiuno" , 21 )-  , ( "veintiuna" , 21 )-  , ( "veintidos" , 22 )-  , ( "veintitrés" , 23 )-  , ( "veintitres" , 23 )-  , ( "veinticuatro" , 24 )-  , ( "veinticinco" , 25 )-  , ( "veintiséis" , 26 )-  , ( "veintiseis" , 26 )-  , ( "veintisiete" , 27 )-  , ( "veintiocho" , 28 )-  , ( "veintinueve" , 29 )-  ]+sixteenToTwentyNineMap =+  HashMap.fromList+    [ ("dieciseis", 16)+    , ("diesiséis", 16)+    , ("diesiseis", 16)+    , ("dieciséis", 16)+    , ("diecisiete", 17)+    , ("dieciocho", 18)+    , ("diecinueve", 19)+    , ("veintiuno", 21)+    , ("veintiuna", 21)+    , ("veintidos", 22)+    , ("veintidós", 22)+    , ("veintitrés", 23)+    , ("veintitres", 23)+    , ("veinticuatro", 24)+    , ("veinticinco", 25)+    , ("veintiséis", 26)+    , ("veintiseis", 26)+    , ("veintisiete", 27)+    , ("veintiocho", 28)+    , ("veintinueve", 29)+    ]  ruleNumeral5 :: Rule ruleNumeral5 = Rule   { name = "number (16..19 21..29)"   , pattern =-    [ regex "(die(c|s)is(é|e)is|diecisiete|dieciocho|diecinueve|veintiun(o|a)|veintidos|veintitr(é|e)s|veinticuatro|veinticinco|veintis(é|e)is|veintisiete|veintiocho|veintinueve)"-    ]+      [ regex+          "(die(c|s)is(é|e)is|diecisiete|dieciocho|diecinueve|veintiun(o|a)|veintid(o|ó)s|veintitr(é|e)s|veinticuatro|veinticinco|veintis(é|e)is|veintisiete|veintiocho|veintinueve|treinta)"+      ]   , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):_) ->+      (Token RegexMatch (GroupMatch (match : _)) : _) ->         HashMap.lookup (Text.toLower match) sixteenToTwentyNineMap >>= integer       _ -> Nothing   }@@ -164,13 +141,9 @@ ruleNumeral3 :: Rule ruleNumeral3 = Rule   { name = "number (16..19)"-  , pattern =-    [ numberWith TNumeral.value (== 10)-    , regex "y"-    , numberBetween 6 10-    ]+  , pattern = [numberWith TNumeral.value (== 10), regex "y", numberBetween 6 10]   , prod = \tokens -> case tokens of-      (_:_:Token Numeral NumeralData{TNumeral.value = v}:_) ->+      (_ : _ : Token Numeral NumeralData { TNumeral.value = v } : _) ->         double $ 10 + v       _ -> Nothing   }@@ -178,14 +151,10 @@ ruleNumeralsSuffixesKMG :: Rule ruleNumeralsSuffixesKMG = Rule   { name = "numbers suffixes (K, M, G)"-  , pattern =-    [ dimension Numeral-    , regex "([kmg])(?=[\\W\\$€]|$)"-    ]+  , pattern = [dimension Numeral, regex "([kmg])(?=[\\W\\$€]|$)"]   , prod = \tokens -> case tokens of-      (Token Numeral NumeralData{TNumeral.value = v}:-       Token RegexMatch (GroupMatch (match:_)):-       _) -> case Text.toLower match of+      (Token Numeral NumeralData { TNumeral.value = v } : Token RegexMatch (GroupMatch (match : _)) : _) ->+        case Text.toLower match of           "k" -> double $ v * 1e3           "m" -> double $ v * 1e6           "g" -> double $ v * 1e9@@ -194,30 +163,31 @@   }  oneHundredToThousandMap :: HashMap.HashMap Text.Text Integer-oneHundredToThousandMap = HashMap.fromList-  [ ( "cien" , 100 )-  , ( "cientos" , 100 )-  , ( "ciento" , 100 )-  , ( "doscientos" , 200 )-  , ( "trescientos" , 300 )-  , ( "cuatrocientos" , 400 )-  , ( "quinientos" , 500 )-  , ( "seiscientos" , 600 )-  , ( "setecientos" , 700 )-  , ( "ochocientos" , 800 )-  , ( "novecientos" , 900 )-  , ( "mil" , 1000 )-  ]-+oneHundredToThousandMap =+  HashMap.fromList+    [ ("cien", 100)+    , ("cientos", 100)+    , ("ciento", 100)+    , ("doscientos", 200)+    , ("trescientos", 300)+    , ("cuatrocientos", 400)+    , ("quinientos", 500)+    , ("seiscientos", 600)+    , ("setecientos", 700)+    , ("ochocientos", 800)+    , ("novecientos", 900)+    , ("mil", 1000)+    ]  ruleNumeral6 :: Rule ruleNumeral6 = Rule   { name = "number 100..1000 "   , pattern =-    [ regex "(cien(to)?s?|doscientos|trescientos|cuatrocientos|quinientos|seiscientos|setecientos|ochocientos|novecientos|mil)"-    ]+      [ regex+          "(cien(to)?s?|doscientos|trescientos|cuatrocientos|quinientos|seiscientos|setecientos|ochocientos|novecientos|mil)"+      ]   , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):_) ->+      (Token RegexMatch (GroupMatch (match : _)) : _) ->         HashMap.lookup (Text.toLower match) oneHundredToThousandMap >>= integer       _ -> Nothing   }@@ -226,15 +196,10 @@ ruleNumeral4 = Rule   { name = "number (21..29 31..39 41..49 51..59 61..69 71..79 81..89 91..99)"   , pattern =-    [ oneOf [70, 20, 60, 50, 40, 90, 30, 80]-    , regex "y"-    , numberBetween 1 10-    ]+      [oneOf [70, 20, 60, 50, 40, 90, 30, 80], regex "y", numberBetween 1 10]   , prod = \tokens -> case tokens of-      (Token Numeral NumeralData{TNumeral.value = v1}:-       _:-       Token Numeral NumeralData{TNumeral.value = v2}:-       _) -> double $ v1 + v2+      (Token Numeral NumeralData { TNumeral.value = v1 } : _ : Token Numeral NumeralData { TNumeral.value = v2 } : _) ->+        double $ v1 + v2       _ -> Nothing   } @@ -242,51 +207,47 @@ ruleNumerals = Rule   { name = "numbers 200..999"   , pattern =-    [ numberBetween 2 10-    , numberWith TNumeral.value (== 100)-    , numberBetween 0 100-    ]+      [ numberBetween 2 10+      , numberWith TNumeral.value (== 100)+      , numberBetween 0 100+      ]   , prod = \tokens -> case tokens of-      (Token Numeral NumeralData{TNumeral.value = v1}:-       _:-       Token Numeral NumeralData{TNumeral.value = v2}:-       _) -> double $ 100 * v1 + v2+      (Token Numeral NumeralData { TNumeral.value = v1 } : _ : Token Numeral NumeralData { TNumeral.value = v2 } : _) ->+        double $ 100 * v1 + v2       _ -> Nothing   }  ruleNumeralDotNumeral :: Rule ruleNumeralDotNumeral = Rule   { name = "number dot number"-  , pattern =-    [ dimension Numeral-    , regex "punto"-    , Predicate $ not . hasGrain-    ]+  , pattern = [dimension Numeral, regex "punto", Predicate $ not . hasGrain]   , prod = \tokens -> case tokens of-      (Token Numeral NumeralData{TNumeral.value = v1}:-       _:-       Token Numeral NumeralData{TNumeral.value = v2}:-       _) -> double $ v1 + decimalsToDouble v2+      (Token Numeral NumeralData { TNumeral.value = v1 } : _ : Token Numeral NumeralData { TNumeral.value = v2 } : _) ->+        double $ v1 + decimalsToDouble v2       _ -> Nothing   } -ruleIntegerWithThousandsSeparator :: Rule-ruleIntegerWithThousandsSeparator = Rule-  { name = "integer with thousands separator ."+ruleBelowTenWithTwoDigits :: Rule+ruleBelowTenWithTwoDigits = Rule+  {+    name = "integer (0-9) with two digits"   , pattern =-    [ regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"-    ]-  , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):_) ->-        parseDouble (Text.replace "." Text.empty match) >>= double+      [+        regex "((c|z)ero)|0"+      , numberBetween 1 10+      ]+  , prod = \case+      (+        _:+        Token Numeral NumeralData { TNumeral.value = v }:+        _+        ) -> double v       _ -> Nothing   }  rules :: [Rule] rules =-  [ ruleDecimalNumeral-  , ruleDecimalWithThousandsSeparator-  , ruleIntegerWithThousandsSeparator+  [ ruleBelowTenWithTwoDigits   , ruleNumeral   , ruleNumeral2   , ruleNumeral3
+ Duckling/Numeral/ES/VE/Corpus.hs view
@@ -0,0 +1,32 @@+-- 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.Numeral.ES.VE.Corpus (allExamples) where++import Data.String+import Prelude++import Duckling.Numeral.Types+import Duckling.Testing.Types++allExamples :: [Example]+allExamples =+  concat+    [ examples (NumeralValue 1) ["1"]+    , examples (NumeralValue 33) ["33"]+    , examples (NumeralValue 1.1) ["1,1", "1,10", "01,10"]+    , examples (NumeralValue 0.77) ["0,77", ",77"]+    , examples (NumeralValue 100000) ["100.000", "100000"]+    , examples (NumeralValue 243) ["243"]+    , examples (NumeralValue 3000000) ["3000000", "3.000.000"]+    , examples (NumeralValue 1200000) ["1.200.000", "1200000"]+    , examples+        (NumeralValue (-1200000))+        ["- 1.200.000", "menos 1.200.000", "-1,2M", "-,0012G"]+    , examples (NumeralValue 1.5) ["1,5"]+    ]
+ Duckling/Numeral/ES/VE/Rules.hs view
@@ -0,0 +1,58 @@+-- 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.Numeral.ES.VE.Rules (rules) where++import Data.Maybe+import Data.String+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers+import Duckling.Regex.Types+import Duckling.Types++ruleDecimalWithThousandsSeparator :: Rule+ruleDecimalWithThousandsSeparator = Rule+  { name = "decimal with thousands separator ."+  , pattern = [regex "(\\d+(\\.\\d\\d\\d)+,\\d+)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        let fmt = Text.replace "," "." $ Text.replace "." Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++ruleDecimalNumeral :: Rule+ruleDecimalNumeral = Rule+  { name = "decimal number ,"+  , pattern = [regex "(\\d*,\\d+)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        parseDecimal False match+      _ -> Nothing+  }++ruleIntegerWithThousandsSeparator :: Rule+ruleIntegerWithThousandsSeparator = Rule+  { name = "integer with thousands separator ."+  , pattern = [regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        parseDouble (Text.replace "." Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleIntegerWithThousandsSeparator+  ]
Duckling/Numeral/ET/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/ET/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
+ Duckling/Numeral/FA/Corpus.hs view
@@ -0,0 +1,102 @@+-- 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.Numeral.FA.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {locale = makeLocale FA Nothing}, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "۰"+             , "صفر"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "۱"+             , "یک"+             ]+  , examples (NumeralValue 11)+             [ "یازده"+             ]+  , examples (NumeralValue 17)+             [ "هفده"+             ]+  , examples (NumeralValue 21)+             [ "بیست و یک"+             ]+  , examples (NumeralValue 23)+             [ "بیست و سه"+             ]+  , examples (NumeralValue 70)+             [ "هفتاد"+             ]+  , examples (NumeralValue 71)+             [ "هفتاد و یک"+             ]+  , examples (NumeralValue 78)+             [ "هفتاد و هشت"+             ]+  , examples (NumeralValue 73)+             [ "هفتاد و سه"+             ]+  , examples (NumeralValue 80)+             [ "هشتاد"+             ]+  , examples (NumeralValue 81)+             [ "هشتاد و یک"+             ]+  , examples (NumeralValue 82)+             [ "هشتاد و دو"+             ]+  , examples (NumeralValue 90)+             [ "نود"+             ]+  , examples (NumeralValue 91)+             [ "نود و یک"+             ]+  , examples (NumeralValue 92)+             [ "نود و دو"+             ]+  , examples (NumeralValue 99)+             [ "نود و نه"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "۳۳"+             , "سی و سه"+             ]+  , examples (NumeralValue 118)+             [ "صد و هجده"+             ]+  , examples (NumeralValue 4020)+             [ "چهار هزار و بیست"+             ]+  , examples (NumeralValue 100000)+             [ "صد هزار"+             , "100000"+             , "۱۰۰۰۰۰"+             ]+  , examples (NumeralValue 3000000)+             [ "سه میلیون"+             , "3000000"+             ]+  ]
+ Duckling/Numeral/FA/Rules.hs view
@@ -0,0 +1,254 @@+-- 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 OverloadedStrings #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Numeral.FA.Rules+  ( rules ) where++import Control.Monad (join)+import Data.HashMap.Strict (HashMap)+import Data.Maybe+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.Numeral.Types (NumeralData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral++zeroNineteenMap :: HashMap Text Integer+zeroNineteenMap = HashMap.fromList+  [ ("صفر", 0)+  , ("یک", 1)+  , ("دو", 2)+  , ("سه", 3)+  , ("چهار", 4)+  , ("پنج", 5)+  , ("شش", 6)+  , ("شیش", 6)+  , ("هفت", 7)+  , ("هشت", 8)+  , ("نه", 9)+  , ("ده", 10)+  , ("یازده", 11)+  , ("دوازده", 12)+  , ("سیزده", 13)+  , ("چهارده", 14)+  , ("پانزده", 15)+  , ("پونزده", 15)+  , ("شانزده", 16)+  , ("شونزده", 16)+  , ("هفده", 17)+  , ("هیفده", 17)+  , ("هجده", 18)+  , ("هیجده", 18)+  , ("نوزده", 19)+  ]++ruleToNineteen :: Rule+ruleToNineteen = Rule+  { name = "integer (0..19)"+  , pattern =+    [ regex "(صفر|یک|سه|چهارده|چهار|پنج|شی?ش|هفت|هشت|نه|یازده|دوازده|سیزده|پ(ا|و)نزده|ش(ا|و)نزده|هی?فده|هی?جده|نوزده|ده|دو)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        let x = Text.toLower match in+        (HashMap.lookup x zeroNineteenMap >>= integer)+      _ -> Nothing+  }++tensMap :: HashMap Text Integer+tensMap = HashMap.fromList+  [ ( "بیست"  , 20 )+  , ( "سی"  , 30 )+  , ( "چهل"  , 40 )+  , ( "پنجاه"   , 50 )+  , ( "شصت"   , 60 )+  , ( "هفتاد" , 70 )+  , ( "هشتاد"  , 80 )+  , ( "نود"  , 90 )+  , ( "صد"  , 100 )+  , ( "دویست"  , 200 )+  , ( "سیصد"  , 300 )+  , ( "سی صد"  , 300 )+  , ( "چهارصد"  , 400 )+  , ( "چهار صد"  , 400 )+  , ( "پانصد"  , 500 )+  , ( "پونصد"  , 500 )+  , ( "شیشصد"  , 600 )+  , ( "شیش صد"  , 600 )+  , ( "ششصد"  , 600 )+  , ( "شش صد"  , 600 )+  , ( "هفتصد"  , 700 )+  , ( "هفت صد"  , 700 )+  , ( "هشتصد"  , 800 )+  , ( "هشت صد"  , 800 )+  , ( "نهصد"  , 900 )+  , ( "نه صد"  , 900 )+  ]++ruleTens :: Rule+ruleTens = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(دویست|(سی|چهار|پان|پون|شی?ش|هفت|هشت|نه)? ?صد|بیست|سی|چهل|پنجاه|شصت|هفتاد|هشتاد|نود)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) tensMap >>= integer+      _ -> Nothing+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(هزار|میلیون|ملیون|میلیارد)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "هزار"  -> double 1e3 >>= withGrain 2 >>= withMultipliable+        "میلیون" -> double 1e6 >>= withGrain 3 >>= withMultipliable+        "ملیون"  -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "میلیارد"  -> double 1e9 >>= withGrain 9 >>= withMultipliable+        _          -> Nothing+      _ -> Nothing+  }++ruleCompositeTens :: Rule+ruleCompositeTens = Rule+  { name = "integer 21..99"+  , pattern =+    [ oneOf [20,30..90]+    , regex "و"+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = tens}:+       _:+       Token Numeral NumeralData{TNumeral.value = units}:+       _) -> double $ tens + units+      _ -> Nothing+  }++ruleCompositeHundred :: Rule+ruleCompositeHundred = Rule+  { name = "integer 21..99"+  , pattern =+    [ oneOf [100,200..900]+    , regex "و"+    , numberBetween 1 100+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = tens}:+       _:+       Token Numeral NumeralData{TNumeral.value = units}:+       _) -> double $ tens + units+      _ -> Nothing+  }++ruleSum :: Rule+ruleSum = Rule+  { name = "intersect 2 numbers"+  , pattern =+    [ Predicate $ and . sequence [hasGrain, isPositive]+    , Predicate $ and . sequence [not . isMultipliable, isPositive]+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = val1, TNumeral.grain = Just g}:+       Token Numeral NumeralData{TNumeral.value = val2}:+       _) | (10 ** fromIntegral g) > val2 -> double $ val1 + val2+      _ -> Nothing+  }++ruleSumAnd :: Rule+ruleSumAnd = Rule+  { name = "intersect 2 numbers (with and)"+  , pattern =+    [ Predicate $ and . sequence [hasGrain, isPositive]+    , regex "و"+    , Predicate $ and . sequence [not . isMultipliable, isPositive]+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = val1, TNumeral.grain = Just g}:+       _:+       Token Numeral NumeralData{TNumeral.value = val2}:+       _) | (10 ** fromIntegral g) > val2 -> double $ val1 + val2+      _ -> Nothing+  }++ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ dimension Numeral+    , Predicate isMultipliable+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++numeralToStringMap :: HashMap Char String+numeralToStringMap =+  HashMap.fromList+    [ ('۰', "0")+    , ('۱', "1")+    , ('۲', "2")+    , ('۳', "3")+    , ('۴', "4")+    , ('۵', "5")+    , ('۶', "6")+    , ('۷', "7")+    , ('۸', "8")+    , ('۹', "9")+    ]++parseIntAsText :: Text -> Text+parseIntAsText =+  Text.pack+    . join+    . mapMaybe (`HashMap.lookup` numeralToStringMap)+    . Text.unpack++parseIntegerFromText :: Text -> Maybe Integer+parseIntegerFromText = parseInteger . parseIntAsText++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "Persian integer numeric"+  , pattern =+    [ regex "([۰-۹]{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseIntegerFromText match >>= integer+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleIntegerNumeric+  , ruleToNineteen+  , ruleTens+  , rulePowersOfTen+  , ruleCompositeTens+  , ruleCompositeHundred+  , ruleSum+  , ruleSumAnd+  , ruleMultiply+  ]
+ Duckling/Numeral/FI/Corpus.hs view
@@ -0,0 +1,122 @@+-- 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.Numeral.FI.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++context :: Context+context = testContext {locale = makeLocale FI Nothing}++corpus :: Corpus+corpus = (context, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "nolla"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "yksi"+             ]+  , examples (NumeralValue 2)+             [ "kaksi"+             ]+  , examples (NumeralValue 3)+             [ "kolme"+             ]+  , examples (NumeralValue 4)+             [ "neljä"+             ]+  , examples (NumeralValue 5)+             [ "viisi"+             ]+  , examples (NumeralValue 6)+             [ "kuusi"+             ]+  , examples (NumeralValue 7)+             [ "seitsemän"+             ]+  , examples (NumeralValue 8)+             [ "kahdeksan"+             ]+  , examples (NumeralValue 9)+             [ "yhdeksän"+             ]+  , examples (NumeralValue 10)+             [ "10"+             , "kymmenen"+             ]+  , examples (NumeralValue 11)+             [ "yksitoista"+             ]+  , examples (NumeralValue 12)+             [ "kaksitoista"+             ]+  , examples (NumeralValue 13)+             [ "kolmetoista"+             ]+  , examples (NumeralValue 14)+             [ "neljätoista"+             ]+  , examples (NumeralValue 15)+             [ "viisitoista"+             ]+  , examples (NumeralValue 16)+             [ "kuusitoista"+             ]+  , examples (NumeralValue 17)+             [ "seitsemäntoista"+             ]+  , examples (NumeralValue 18)+             [ "kahdeksantoista"+             ]+  , examples (NumeralValue 19)+             [ "yhdeksäntoista"+             ]+  , examples (NumeralValue 20)+             [ "20"+             , "kaksikymmentä"+             ]+  , examples (NumeralValue 24)+             [ "24"+             , "kaksikymmentäneljä"+             ]+  , examples (NumeralValue 35)+             [ "kolmekymmentäviisi"+             ]+  , examples (NumeralValue 42)+             [ "neljäkymmentäkaksi"+             ]+  , examples (NumeralValue 52)+             [ "viisikymmentäkaksi"+             ]+  , examples (NumeralValue 62)+             [ "kuusikymmentäkaksi"+             ]+  , examples (NumeralValue 72)+             [ "seitsemänkymmentäkaksi"+             ]+  , examples (NumeralValue 82)+             [ "kahdeksankymmentäkaksi"+             ]+  , examples (NumeralValue 99)+             [ "99"+             , "yhdeksänkymmentäyhdeksän"+             ]+  ]
+ Duckling/Numeral/FI/Rules.hs view
@@ -0,0 +1,141 @@+-- 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 #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Numeral.FI.Rules+  ( rules+  ) where++import Data.HashMap.Strict (HashMap)+import Data.Maybe+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.Numeral.Types (NumeralData(..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- parseInt match+        integer $ toInteger v+      _ -> Nothing+  }++numeralMap :: HashMap Text Integer+numeralMap = HashMap.fromList+  [ ( "nolla", 0 )+  , ( "yksi", 1 )+  , ( "kaksi", 2 )+  , ( "kolme", 3 )+  , ( "neljä", 4 )+  , ( "viisi", 5 )+  , ( "kuusi", 6 )+  , ( "seitsemän", 7 )+  , ( "kahdeksan", 8 )+  , ( "yhdeksän", 9 )+  , ( "kymmenen", 10 )+  ]++ruleNumeral :: Rule+ruleNumeral = Rule+  { name = "number (0..10)"+  , pattern =+    [ regex "(nolla|yksi|kaksi|kolme|neljä|viisi|kuusi|seitsemän|kahdeksan|yhdeksän|kymmenen)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) numeralMap >>= integer+      _ -> Nothing+  }++elevenToNineteenMap :: HashMap Text Integer+elevenToNineteenMap = HashMap.fromList+  [ ( "yksitoista", 11 )+  , ( "kaksitoista", 12 )+  , ( "kolmetoista", 13 )+  , ( "neljätoista", 14 )+  , ( "viisitoista", 15 )+  , ( "kuusitoista", 16 )+  , ( "seitsemäntoista", 17 )+  , ( "kahdeksantoista", 18 )+  , ( "yhdeksäntoista", 19 )+  ]++ruleElevenToNineteen :: Rule+ruleElevenToNineteen = Rule+  { name = "number (11..19)"+  , pattern =+    [ regex "(yksitoista|kaksitoista|kolmetoista|neljätoista|viisitoista|kuusitoista|seitsemäntoista|kahdeksantoista|yhdeksäntoista)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) elevenToNineteenMap >>= integer+      _ -> Nothing+  }++tensMap :: HashMap Text Integer+tensMap = HashMap.fromList+  [ ( "kaksikymmentä", 20 )+  , ( "kolmekymmentä", 30 )+  , ( "neljäkymmentä", 40 )+  , ( "viisikymmentä", 50 )+  , ( "kuusikymmentä", 60 )+  , ( "seitsemänkymmentä", 70 )+  , ( "kahdeksankymmentä", 80 )+  , ( "yhdeksänkymmentä", 90 )+  ]++ruleTens :: Rule+ruleTens = Rule+  { name = "integer (20,30..90)"+  , pattern =+    [ regex "(kaksikymmentä|kolmekymmentä|neljäkymmentä|viisikymmentä|kuusikymmentä|seitsemänkymmentä|kahdeksankymmentä|yhdeksänkymmentä)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) tensMap >>= integer+      _ -> Nothing+  }++ruleCompositeTens :: Rule+ruleCompositeTens = Rule+  { name = "integer ([2-9][1-9])"+  , pattern =+    [ regex "(kaksikymmentä|kolmekymmentä|neljäkymmentä|viisikymmentä|kuusikymmentä|seitsemänkymmentä|kahdeksankymmentä|yhdeksänkymmentä)(yksi|kaksi|kolme|neljä|viisi|kuusi|seitsemän|kahdeksan|yhdeksän)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        v1 <- HashMap.lookup (Text.toLower m1) tensMap+        v2 <- HashMap.lookup (Text.toLower m2) numeralMap+        integer $ v1 + v2+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleIntegerNumeric+  , ruleNumeral+  , ruleElevenToNineteen+  , ruleTens+  , ruleCompositeTens+  ]
Duckling/Numeral/FR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -125,5 +124,12 @@              , "-1,2M"              , "-1200K"              , "-,0012G"+             ]+  , examples (NumeralValue 6.7)+             [ "6,7"+             ]+  , examples (NumeralValue 6700.54)+             [ "6.700,54"+             , "6 700,54"              ]   ]
Duckling/Numeral/FR/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -57,10 +56,12 @@   { name = "numbers 22..29 32..39 .. 52..59"   , pattern =     [ oneOf [20, 50, 40, 30]+    , regex "[\\s\\-]+"     , numberBetween 2 10     ]   , prod = \tokens -> case tokens of       (Token Numeral NumeralData{TNumeral.value = v1}:+       _:        Token Numeral NumeralData{TNumeral.value = v2}:        _) -> double $ v1 + v2       _ -> Nothing@@ -117,10 +118,12 @@   { name = "numbers 62..69 .. 92..99"   , pattern =     [ oneOf [60, 80]+    , regex "[\\s\\-]+"     , numberBetween 2 20     ]   , prod = \tokens -> case tokens of       (Token Numeral NumeralData{TNumeral.value = v1}:+       _:        Token Numeral NumeralData{TNumeral.value = v2}:        _) -> double $ v1 + v2       _ -> Nothing@@ -166,10 +169,12 @@   { name = "number (17..19)"   , pattern =     [ numberWith TNumeral.value (== 10)+    , regex "[\\s\\-]+"     , numberBetween 7 10     ]   , prod = \tokens -> case tokens of       (_:+       _:        Token Numeral NumeralData{TNumeral.value = v}:        _) -> double $ 10 + v       _ -> Nothing@@ -224,7 +229,7 @@   { name = "numbers 21 31 41 51"   , pattern =     [ oneOf [20, 50, 40, 30]-    , regex "et"+    , regex "-?et-?"     , numberWith TNumeral.value (== 1)     ]   , prod = \tokens -> case tokens of
Duckling/Numeral/GA/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/GA/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Numeral/HE/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} @@ -69,6 +68,10 @@              [ "1.1"              , "1.10"              , "01.10"+             ]+  , examples (NumeralValue 0.5)+             [ "חצי"+             , "0.5"              ]   , examples (NumeralValue 0.77)              [ "0.77"
Duckling/Numeral/HE/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-}@@ -344,6 +343,15 @@       _ -> Nothing   } +ruleHalf :: Rule+ruleHalf = Rule+  { name = "half"+  , pattern =+    [ regex "חצי"+    ]+  , prod = \_ -> double 0.5+  }+ rules :: [Rule] rules =   [ ruleCommas@@ -373,4 +381,5 @@   , ruleNumeralsPrefixWithNegativeOrMinus   , rulePowersOfTen   , ruleSingle+  , ruleHalf   ]
Duckling/Numeral/HI/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -83,5 +82,22 @@   , examples (NumeralValue 50)              [ "५०"              , "पचास"+             ]+  , examples (NumeralValue 300)+             [ "तीन सौ"+             ]+  , examples (NumeralValue 81)+             [ "इक्यासी"+             ]+  , examples (NumeralValue 150)+             [ "एक सौ पचास"+             ]+  , examples (NumeralValue 1000)+             [ "हज़ार"+             , "एक हज़ार"+             , "हज़ार" -- हज़ार using a different character scheme+             ]+  , examples (NumeralValue 1520)+             [ "एक हज़ार पाँच सौ बीस"              ]   ]
Duckling/Numeral/HI/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -16,7 +15,6 @@  import Data.HashMap.Strict (HashMap) import Data.Maybe-import Data.String import Data.Text (Text) import Prelude import qualified Data.HashMap.Strict as HashMap@@ -58,36 +56,20 @@       _ -> Nothing   } -ruleNumeralMap :: HashMap Text Integer-ruleNumeralMap = HashMap.fromList+ruleZeroToNinetyNineMap :: HashMap Text Integer+ruleZeroToNinetyNineMap = HashMap.fromList   [ ( "शून्य", 0 )   , ( "एक", 1 )-  , ( "दो" , 2 )+  , ( "दो", 2 )   , ( "तीन", 3 )   , ( "चार", 4 )   , ( "पाँच", 5 )+  , ( "छः", 6 )   , ( "छह", 6 )   , ( "सात", 7 )   , ( "आठ", 8 )-  , ( "नौ" , 9 )-  , ( "दस", 10 )-  ]--ruleNumeral :: Rule-ruleNumeral = Rule-  { name = "number (0..10)"-  , pattern =-    [ regex "(शून्य|एक|दो|तीन|चार|पाँच|छह|सात|आठ|नौ|दस)"-    ]-  , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):_) ->-        HashMap.lookup match ruleNumeralMap >>= integer-      _ -> Nothing-  }--elevenToNineteenMap :: HashMap Text Integer-elevenToNineteenMap = HashMap.fromList-  [ ( "ग्यारह", 11 )+  , ( "नौ", 9 )+  , ( "ग्यारह", 11 )   , ( "बारह", 12 )   , ( "तेरह", 13 )   , ( "चौदह", 14 )@@ -96,23 +78,7 @@   , ( "सत्रह", 17 )   , ( "अठारह", 18 )   , ( "उन्नीस", 19 )-  ]--ruleElevenToNineteen :: Rule-ruleElevenToNineteen = Rule-  { name = "number (11..19)"-  , pattern =-    [ regex "(ग्यारह|बारह|तेरह|चौदह|पन्द्रह|सोलह|सत्रह|अठारह|उन्नीस)"-    ]-  , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):_) ->-        HashMap.lookup match elevenToNineteenMap >>= integer-      _ -> Nothing-  }--twentyoneToTwentynineMap :: HashMap Text Integer-twentyoneToTwentynineMap = HashMap.fromList-  [ ( "इक्कीस", 21 )+  , ( "इक्कीस", 21 )   , ( "बाईस", 22 )   , ( "तेईस", 23 )   , ( "चौबीस", 24 )@@ -121,23 +87,88 @@   , ( "सत्ताईस", 27 )   , ( "अट्ठाईस", 28 )   , ( "उनतीस", 29 )+  , ( "इकतीस", 31 )+  , ( "इकत्तीस", 31 )+  , ( "बत्तीस", 32 )+  , ( "तैंतीस", 33 )+  , ( "चौंतीस", 34 )+  , ( "पैंतीस", 35 )+  , ( "छत्तीस", 36 )+  , ( "सैंतीस", 37 )+  , ( "अड़तीस", 38 )+  , ( "उनतालीस", 39 )+  , ( "इकतालीस", 41 )+  , ( "बयालीस", 42 )+  , ( "तैंतालीस", 43 )+  , ( "चौवालीस", 44 )+  , ( "पैंतालीस", 45 )+  , ( "छियालीस", 46 )+  , ( "सैंतालीस", 47 )+  , ( "अड़तालीस", 48 )+  , ( "उनचास", 49 )+  , ( "इक्यावन", 51 )+  , ( "बावन", 52 )+  , ( "तिरेपन", 53 )+  , ( "चौवन", 54 )+  , ( "पचपन", 55 )+  , ( "छप्पन", 56 )+  , ( "सत्तावन", 57 )+  , ( "अट्ठावन", 58 )+  , ( "उनसठ", 59 )+  , ( "इकसठ", 61 )+  , ( "बासठ", 62 )+  , ( "तिरेसठ", 63 )+  , ( "चौंसठ", 64 )+  , ( "पैंसठ", 65 )+  , ( "छियासठ", 66 )+  , ( "सड़सठ", 67 )+  , ( "अड़सठ", 68 )+  , ( "उनहत्तर", 69 )+  , ( "इकहत्तर", 71 )+  , ( "बहत्तर", 72 )+  , ( "तिहत्तर", 73 )+  , ( "चौहत्तर", 74 )+  , ( "पचहत्तर", 75 )+  , ( "छिहत्तर", 76 )+  , ( "सतहत्तर", 77 )+  , ( "अठहत्तर", 78 )+  , ( "उनासी", 79 )+  , ( "इक्यासी", 81 )+  , ( "बयासी", 82 )+  , ( "तिरासी", 83 )+  , ( "चौरासी", 84 )+  , ( "पचासी", 85 )+  , ( "छियासी", 86 )+  , ( "सतासी", 87 )+  , ( "अट्ठासी", 88 )+  , ( "नवासी", 89 )+  , ( "इक्यानवे", 91 )+  , ( "बानवे", 92 )+  , ( "तिरानवे", 93 )+  , ( "चौरानवे", 94 )+  , ( "पचानवे", 95 )+  , ( "छियानवे", 96 )+  , ( "सत्तानवे", 97 )+  , ( "अट्ठानवे", 98 )+  , ( "निन्यानवे", 99 )   ] -ruleTwentyoneToTwentynine :: Rule-ruleTwentyoneToTwentynine = Rule-  { name = "number (21..29)"+ruleZeroToNinetyNine :: Rule+ruleZeroToNinetyNine = Rule+  { name = "number (0..99)"   , pattern =-    [ regex "(इक्कीस|बाईस|तेईस|चौबीस|पच्चीस|छब्बीस|सत्ताईस|अट्ठाईस|उनतीस)"+    [ regex "(शून्य|एक|दो|तीन|चार|पाँच|छे|छह|सात|आठ|नौ|ग्यारह|बारह|तेरह|चौदह|पन्द्रह|सोलह|सत्रह|अठारह|उन्नीस|इक्कीस|बाईस|तेईस|चौबीस|पच्चीस|छब्बीस|सत्ताईस|अट्ठाईस|उनतीस|इकतीस|बत्तीस|तैंतीस|चौंतीस|पैंतीस|छत्तीस|सैंतीस|अड़तीस|उनतालीस|इकतालीस|बयालीस|तैंतालीस|चौवालीस|पैंतालीस|छियालीस|सैंतालीस|अड़तालीस|उनचास|इक्यावन|बावन|तिरेपन|चौवन|पचपन|छप्पन|सत्तावन|अट्ठावन|उनसठ|इकसठ|बासठ|तिरेसठ|चौंसठ|पैंसठ|छियासठ|सड़सठ|अड़सठ|उनहत्तर|इकहत्तर|बहत्तर|तिहत्तर|चौहत्तर|पचहत्तर|छिहत्तर|सतहत्तर|अठहत्तर|उनासी|इक्यासी|बयासी|तिरासी|चौरासी|पचासी|छियासी|सतासी|अट्ठासी|नवासी|इक्यानवे|बानवे|तिरानवे|चौरानवे|पचानवे|छियानवे|सत्तानवे|अट्ठानवे|निन्यानवे)"     ]   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (match:_)):_) ->-        HashMap.lookup match twentyoneToTwentynineMap >>= integer+        HashMap.lookup match ruleZeroToNinetyNineMap >>= integer       _ -> Nothing   }  tensMap :: HashMap Text Integer tensMap = HashMap.fromList-  [ ( "बीस", 20 )+  [ ("दस", 10)+  , ( "बीस", 20 )   , ( "तीस", 30 )   , ( "चालीस", 40 )   , ( "पचास", 50 )@@ -151,7 +182,7 @@ ruleTens = Rule   { name = "integer (20,30..90)"   , pattern =-    [ regex "(बीस|तीस|चालीस|पचास|साठ|सत्तर|अस्सी|नब्बे)"+    [ regex "(दस|बीस|तीस|चालीस|पचास|साठ|सत्तर|अस्सी|नब्बे)"     ]   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (match:_)):_) ->@@ -159,12 +190,72 @@       _ -> Nothing   } +rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern = [regex "(सौ|हज़ार|हज़ार)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        case Text.toLower match of+          "सौ" -> double 1e2 >>= withGrain 2 >>= withMultipliable+          "हज़ार" -> double 1e3 >>= withGrain 3 >>= withMultipliable+          "हज़ार" -> double 1e3 >>= withGrain 3 >>= withMultipliable+          _ -> Nothing+      _ -> Nothing+  } +ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ Predicate isPositive+    , Predicate isMultipliable+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++ruleCompositeHundreds :: Rule+ruleCompositeHundreds = Rule+  { name = "integer 100s.."+  , pattern =+    [ oneOf [100,200..5000]+    , regex "[\\s\\-]+"+    , numberBetween 1 99+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = hundreds}:+       _:+       Token Numeral NumeralData{TNumeral.value = remaining}:+       _) -> double $ hundreds + remaining+      _ -> Nothing+  }+++ruleCompositeThousands :: Rule+ruleCompositeThousands = Rule+  { name = "integer 100s.."+  , pattern =+    [ oneOf [1000,2000..50000]+    , regex "[\\s\\-]+"+    , numberBetween 1 999+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = thousands}:+       _:+       Token Numeral NumeralData{TNumeral.value = remaining}:+       _) -> double $ thousands + remaining+      _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleDevanagari-  , ruleNumeral-  , ruleElevenToNineteen-  , ruleTwentyoneToTwentynine+  , ruleZeroToNinetyNine   , ruleTens+  , rulePowersOfTen+  , ruleMultiply+  , ruleCompositeHundreds+  , ruleCompositeThousands   ]
Duckling/Numeral/HR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} 
Duckling/Numeral/HR/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/HU/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/HU/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Numeral/Helpers.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Numeral/ID/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/ID/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
+ Duckling/Numeral/IS/Corpus.hs view
@@ -0,0 +1,79 @@+-- 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.Numeral.IS.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++context :: Context+context = testContext{locale = makeLocale IS Nothing}++corpus :: Corpus+corpus = (context, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "núll"+             , "null"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "einn"+             ]+  , examples (NumeralValue 2)+             [ "tveir"+             ]+  , examples (NumeralValue 3)+             [ "þrír"+             ]+  , examples (NumeralValue 4)+             [ "fjórir"+             ]+  , examples (NumeralValue 5)+             [ "fimm"+             ]+  , examples (NumeralValue 6)+             [ "sex"+             ]+  , examples (NumeralValue 7)+             [ "sjö"+             ]+  , examples (NumeralValue 8)+             [ "átta"+             ]+  , examples (NumeralValue 9)+             [ "níu"+             ]+  , examples (NumeralValue 10)+             [ "tíu"+             ]+  , examples (NumeralValue 11)+             [ "ellefu"+             ]+  , examples (NumeralValue 15)+             [ "fimmtán"+             ]+  , examples (NumeralValue 17)+             [ "sautján"+             ]+  , examples (NumeralValue 20)+             [ "20"+             , "tuttugu"+             ]+  ]
+ Duckling/Numeral/IS/Rules.hs view
@@ -0,0 +1,73 @@+-- 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 #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Numeral.IS.Rules+  ( rules+  ) where++import Data.HashMap.Strict (HashMap)+import Data.Maybe+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.Numeral.Types (NumeralData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral++zeroToTwentyMap:: HashMap Text Integer+zeroToTwentyMap = HashMap.fromList+  [ ( "núll", 0 )+  , ( "null", 0 )+  , ( "einn", 1 )+  , ( "tveir", 2 )+  , ( "þrír", 3 )+  , ( "fjórir", 4 )+  , ( "fimm", 5 )+  , ( "sex", 6 )+  , ( "sjö", 7 )+  , ( "átta", 8 )+  , ( "níu", 9 )+  , ( "tíu", 10 )+  , ( "ellefu", 11 )+  , ( "tólf", 12 )+  , ( "þrettán", 13 )+  , ( "fjórtán", 14 )+  , ( "fimmtán", 15 )+  , ( "sextán", 16 )+  , ( "sautján", 17 )+  , ( "átján", 18 )+  , ( "nítján", 19 )+  , ( "tuttugu", 20 )+  ]++ruleZeroToTwenty :: Rule+ruleZeroToTwenty = Rule+  { name = "number (0..20)"+  , pattern =+    [ regex "(n[úu]ll|einn|tveir|þrír|fjórir|fimm(tán)?|sex(tán)?|sjö|átta|níu|tíu|ellefu|tólf|þrettán|fjórtán|sautján|átján|nítján|tuttugu)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) zeroToTwentyMap >>= integer+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleZeroToTwenty+  ]
Duckling/Numeral/IT/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -129,12 +128,14 @@              , "100000"              , "100K"              , "100k"+             , "100 000"              ]   , examples (NumeralValue 3000000)              [ "3M"              , "3000K"              , "3000000"              , "3.000.000"+             , "3 000 000"              ]   , examples (NumeralValue 1200000)              [ "1.200.000"@@ -151,5 +152,12 @@              , "-1,2M"              , "-1200K"              , "-,0012G"+             ]+  , examples (NumeralValue 6.7)+             [ "6,7"+             ]+  , examples (NumeralValue 6700.54)+             [ "6.700,54"+             , "6 700,54"              ]   ]
Duckling/Numeral/IT/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -43,11 +42,11 @@ ruleDecimalWithThousandsSeparator = Rule   { name = "decimal with thousands separator"   , pattern =-    [ regex "(\\d+(\\.\\d\\d\\d)+,\\d+)"+    [ regex "(\\d+(([\\. ])\\d\\d\\d)+,\\d+)"     ]   , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):-       _) -> let fmt = Text.replace "," "." $ Text.replace "." Text.empty match+      (Token RegexMatch (GroupMatch (match:_:sep:_)):+       _) -> let fmt = Text.replace "," "." $ Text.replace sep Text.empty match         in parseDouble fmt >>= double       _ -> Nothing   }@@ -304,11 +303,12 @@ ruleIntegerWithThousandsSeparator = Rule   { name = "integer with thousands separator ."   , pattern =-    [ regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"+    [ regex "(\\d{1,3}(([\\. ])\\d\\d\\d){1,5})"     ]   , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):_) ->-        parseDouble (Text.replace "." Text.empty match) >>= double+      (Token RegexMatch (GroupMatch (match:_:sep:_)):+       _) -> let fmt = Text.replace sep Text.empty match+        in parseDouble fmt >>= double       _ -> Nothing   } 
Duckling/Numeral/JA/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/JA/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Numeral/KA/Corpus.hs view
@@ -2,14 +2,15 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-} +-- /Note/: All commented-out tests are failing due to https://github.com/facebook/duckling/issues/541 module Duckling.Numeral.KA.Corpus-  ( corpus ) where+  ( corpus+  ) where  import Data.String import Prelude@@ -19,14 +20,19 @@ import Duckling.Resolve import Duckling.Testing.Types +context :: Context+context = testContext {locale = makeLocale KA Nothing}+ corpus :: Corpus-corpus = (testContext {locale = makeLocale KA Nothing}, testOptions, allExamples)+corpus = (context, testOptions, allExamples)  allExamples :: [Example] allExamples = concat   [ examples (NumeralValue 0)              [ "0"+             , "ნოლი"              , "ნული"+             , "ნოლ"              ]   , examples (NumeralValue 1)              [ "1"@@ -35,9 +41,380 @@   , examples (NumeralValue 2)              [ "2"              , "ორი"+             , "წყვილი"+             , "წყვილები"              ]   , examples (NumeralValue 3)              [ "3"              , "სამი"+             , "ცოტა"+             , "რამდენიმე"+             , "რამოდენიმე"              ]+  , examples (NumeralValue 4)+             [ "4"+             , "ოთხი"+             ]+  , examples (NumeralValue 5)+             [ "5"+             , "ხუთი"+             ]+  , examples (NumeralValue 6)+             [ "6"+             , "ექვსი"+             ]+  , examples (NumeralValue 7)+             [ "7"+             , "შვიდი"+             ]+  , examples (NumeralValue 8)+             [ "8"+             , "რვა"+             ]+  , examples (NumeralValue 9)+             [ "9"+             , "ცხრა"+             ]+  , examples (NumeralValue 10)+             [ "10"+             , "ათი"+             ]+  , examples (NumeralValue 11)+             [ "11"+             , "თერთმეტი"+             ]+  , examples (NumeralValue 12)+             [ "12"+             , "თორმეტი"+             ]+  , examples (NumeralValue 13)+             [ "13"+             , "ცამეტი"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "თოთხმეტი"+             ]+  , examples (NumeralValue 15)+             [ "15"+             , "თხუთმეტი"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "თექვსმეტი"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "ჩვიდმეტი"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "თვრამეტი"+             ]+  , examples (NumeralValue 19)+             [ "19"+             , "ცხრამეტი"+             ]+  , examples (NumeralValue 20)+             [ "20"+             , "ოცი"+             ]+  , examples (NumeralValue 21)+             [ "21"+             -- , "ოცდაერთი"+             ]+  , examples (NumeralValue 22)+             [ "22"+             -- , "ოცდაორი"+             ]+  , examples (NumeralValue 23)+             [ "23"+             -- , "ოცდასამი"+             ]+  , examples (NumeralValue 24)+             [ "24"+             -- , "ოცდაოთხი"+             ]+  , examples (NumeralValue 25)+             [ "25"+             -- , "ოცდახუთი"+             ]+  , examples (NumeralValue 26)+             [ "26"+             -- , "ოცდაექვსი"+             ]+  , examples (NumeralValue 27)+             [ "27"+             -- , "ოცდაშვიდი"+             ]+  , examples (NumeralValue 30)+             [ "30"+             , "ოცდაათი"+             ]+  , examples (NumeralValue 31)+             [ "31"+             -- , "ოცდათერთმეტი"+             ]+  , examples (NumeralValue 38)+             [ "38"+             -- , "ოცდათვრამეტი"+             ]+  , examples (NumeralValue 39)+             [ "39"+             -- , "ოცდაცხრამეტი"+             ]+  , examples (NumeralValue 40)+             [ "40"+             , "ორმოცი"+             ]+  , examples (NumeralValue 42)+             [ "42"+             -- , "ორმოცდაორი"+             ]+  , examples (NumeralValue 47)+             [ "47"+             -- , "ორმოცდაშვიდი"+             ]+  , examples (NumeralValue 99)+             [ "99"+             --, "ოთხმოცდაცხრამეტი"+             ]+  , examples (NumeralValue 100)+             [ "100"+             , "ასი"+             ]+  , examples (NumeralValue 101)+             [ "101"+             , "ას ერთი"+             ]+  , examples (NumeralValue 102)+             [ "102"+             , "ას ორი"+             ]+  , examples (NumeralValue 121)+             [ "121"+             --, "ას ოცდაერთი"+             ]+  , examples (NumeralValue 200)+             [ "200"+             , "ორასი"+             ]+  , examples (NumeralValue 201)+             [ "201"+             , "ორას ერთი"+             ]+  , examples (NumeralValue 250)+             [ "250"+             , "ორას ორმოცდაათი"+             ]+  , examples (NumeralValue 300)+             [ "300"+             , "სამასი"+             ]+  , examples (NumeralValue 310)+             [ "310"+             , "სამას ათი"+             ]+  , examples (NumeralValue 415)+             [ "415"+             , "ოთხას თხუთმეტი"+             ]+  , examples (NumeralValue 600)+             [ "600"+             , "ექვსასი"+             ]+  , examples (NumeralValue 909)+             [ "909"+             , "ცხრაას ცხრა"+             ]+  , examples (NumeralValue 999)+             [ "999"+             --, "ცხრაას ოთხმოცდაცხრამეტი"+             ]+  , examples (NumeralValue 1000)+             [ "1000"+             , "ათასი"+             ]+  , examples (NumeralValue 1001)+             [ "1001"+             , "ათას ერთი"+             ]+  , examples (NumeralValue 2000)+             [ "2000"+             , "ორი ათასი"+             ]+  , examples (NumeralValue 2010)+             [ "2010"+             , "ორი ათას ათი"+             ]+  , examples (NumeralValue 7892)+             [ "7892"+             --, "შვიდი ათას რვაას ოთხმოცდათორმეტი"+             ]+  , examples (NumeralValue 10000)+             [ "10000"+             , "ათი ათასი"+             ]+  , examples (NumeralValue 121000)+             [ "121000"+             --, "ას ოცდაერთი ათასი"+             ]+  , examples (NumeralValue 120000)+             [ "120000"+             , "ას ოცი ათასი"+             ]+  , examples (NumeralValue 124000)+             [ "124000"+             --, "ას ოცდაოთხი ათასი"+             ]+  , examples (NumeralValue 999000)+             [ "999000"+             --, "ცხრაას ოთხმოცდაცხრამეტი ათასი"+             ]+  , examples (NumeralValue 999900)+             [ "999900"+             --, "ცხრაას ოთხმოცდაცხრამეტი ათას ცხრაასი"+             ]+  , examples (NumeralValue 999990)+             [ "999990"+             --, "ცხრაას ოთხმოცდაცხრამეტი ათას ცხრაას ოთხმოცდაათი"+             ]+  , examples (NumeralValue 999999)+             [ "999999"+             -- , "ცხრაას ოთხმოცდაცხრამეტი ათას ცხრაას ოთხმოცდაცხრამეტი"+             ]+  , examples (NumeralValue 1000000)+             [ "1000000"+             , "ერთი მილიონი"+             ]+  , examples (NumeralValue 2000000)+             [ "2000000"+             , "ორი მილიონი"+             ]+  , examples (NumeralValue 999000999)+             [ "999000999"+             -- , "ცხრაას ოთხმოცდაცხრამეტი მილიონ ცხრაას ოთხმოცდაცხრამეტი"+             ]+  , examples (NumeralValue 999999999)+             [ "999999999"+             -- ,  "ცხრაას ოთხმოცდაცხრამეტი მილიონ ცხრაას ოთხმოცდაცხრამეტი ათას ცხრაას ოთხმოცდაცხრამეტი"+             ]+  , examples (NumeralValue 1174315110)+             [ "1174315110"+             -- , "ერთი მილიარდ ას სამოცდათოთხმეტი მილიონ სამას თხუთმეტი ათას ას ათი"+             ]+  , examples (NumeralValue 1174315119)+             [ "1174315119"+             -- , "ერთი მილიარდ ას სამოცდათოთხმეტი მილიონ სამას თხუთმეტი ათას ას ცხრამეტი"+             ]+  , examples (NumeralValue 15174315110)+             [ "15174315110"+             -- , "თხუთმეტი მილიარდ ას სამოცდათოთხმეტი მილიონ სამას თხუთმეტი ათას ას ათი"+             ]+  , examples (NumeralValue 35174315119)+             [ "35174315119"+             -- , "ოცდათხუთმეტი მილიარდ ას სამოცდათოთხმეტი მილიონ სამას თხუთმეტი ათას ას ცხრამეტი"+             ]+  , examples (NumeralValue 935174315119)+             [ "935174315119"+             -- , "ცხრაას ოცდათხუთმეტი მილიარდ ას სამოცდათოთხმეტი მილიონ სამას თხუთმეტი ათას ას ცხრამეტი"+             ]+  , examples (NumeralValue 33)+             [ "33"+             -- , "ოცდაცამეტი"+             , "0033"+             ]+  , examples (NumeralValue 24)+             [ "24"+             -- , "ოცდაოთხი"+             ]+  , examples (NumeralValue 1.1)+             [ "1.1"+             , "1.10"+             , "01.10"+             , "1 მთელი 1"+             , "ერთი მთელი ერთი"+             ]+  , examples (NumeralValue 0.77)+             [ ".77"+             , "0.77"+             -- , "ნოლი მთელი სამოცდაჩვიდმეტი"+             -- , "ნული მთელი სამოცდაჩვიდმეტი"+             ]+  , examples (NumeralValue 100000)+             [ "100,000"+             , "100,000.0"+             , "100000"+             , "100k"+             -- , "ასი ათასი"+             ]+  , examples (NumeralValue 0.2)+             [ "1/5"+             , "2/10"+             , "3/15"+             , "20/100"+             ]+  , examples (NumeralValue 3e6)+             [ "3M"+             , "3000K"+             , "3000000"+             , "3,000,000"+             , "3 მილიონი"+             -- , "სამი მილიონი"+             ]+  , examples (NumeralValue 1.2e6)+             [ "1,200,000"+             , "1200000"+             , "1.2M"+             , "1200k"+             , ".0012G"+             ]+  , examples (NumeralValue 5000)+             [ "5 ათასი"+             -- , "ხუთი ათასი"+             ]+  , examples (NumeralValue (-504))+             [ "-504"+             -- , "მინუს ხუთას ოთხი"+             -- , "მინუს 504"+             ]+  , examples (NumeralValue (-1.2e6))+             [ "- 1,200,000"+             , "-1200000"+             -- , "მინუს 1,200,000"+             -- , "მინუს 1200000"+             , "-1.2M"+             , "-1200K"+             , "-.0012G"+             ]+{-+  , examples (NumeralValue 122)+             [ "ას ოცდაორი"+             , "ასოცდაორი"+             ]+  , examples (NumeralValue 2e5)+             [ "ორასი ათასი"+             ]+  , examples (NumeralValue 21011)+             [ "ოცდაერთიათას თერთმეტი"+             ]+  , examples (NumeralValue 721012)+             [ "შვიდას ოცდაერთი ათას თორმეტი"+             ]+  , examples (NumeralValue 31256721)+             [ "ოცდათერთმეტი მილიონ ორას ორმოცდათექვსმეტი ათას შვიდას ოცდაერთი"+             ]+  , examples (NumeralValue 2400)+             [ "ორიათას ოთხასი"+             , "ორიათასოთხასი"+             ]+  , examples (NumeralValue 2200000)+             [ "ორი მთელი ორი მილიონი"+             , "ორი მილიონ ორასი ათას"+             ]+  , examples (NumeralValue 3000000000)+             [ "სამი მილიარდი"+             , "3 მილიარდი"+             ]+-}   ]
Duckling/Numeral/KA/Rules.hs view
@@ -2,17 +2,19 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE NoRebindableSyntax #-} {-# LANGUAGE OverloadedStrings #-}  module Duckling.Numeral.KA.Rules   ( rules   ) where +import Control.Applicative ((<|>)) import Data.HashMap.Strict (HashMap) import Data.Maybe import Data.String@@ -28,34 +30,376 @@ import Duckling.Types import qualified Duckling.Numeral.Types as TNumeral -ruleNumeralMap :: HashMap Text Integer-ruleNumeralMap = HashMap.fromList-  [ ( "ნული", 0 )-  , ( "ერთი", 1 )-  , ( "ორი", 2 )-  , ( "სამი", 3 )-  , ( "ოთხი", 4 )-  , ( "ხუთი", 5)-  , ( "ექვსი", 6)-  , ( "შვიდი", 7)-  , ( "რვა", 8)-  , ( "ცხრა", 9)-  , ( "ათი", 10)+zeroNineteenMap :: HashMap Text Integer+zeroNineteenMap = HashMap.fromList+  [ ( "ნოლ"       , 0  )+  , ( "ნულ"       , 0  )+  , ( "ნული"      , 0  )+  , ( "ნოლ"       , 0  )+  , ( "ნოლი"      , 0  )+  , ( "ერთი"      , 1  )+  , ( "ორი"       , 2  )+  , ( "ორ"        , 2  )+  , ( "სამი"      , 3  )+  , ( "სამ"       , 3  )+  , ( "ოთხი"      , 4  )+  , ( "ოთხ"       , 4  )+  , ( "ხუთი"      , 5  )+  , ( "ხუთ"       , 5  )+  , ( "ექვსი"     , 6  )+  , ( "ექვს"      , 6  )+  , ( "შვიდი"     , 7  )+  , ( "შვიდ"      , 7  )+  , ( "რვა"       , 8  )+  , ( "რვ"        , 8  )+  , ( "ცხრა"      , 9  )+  , ( "ცხრ"       , 9  )+  , ( "ათი"       , 10 )+  , ( "აათი"      , 10 )+  , ( "თერთმეტი"  , 11 )+  , ( "თერთმეტ"   , 11 )+  , ( "თორმეტი"   , 12 )+  , ( "თორმეტ"    , 12 )+  , ( "ცამეტი"    , 13 )+  , ( "ცამეტ"     , 13 )+  , ( "თოთხმეტი"  , 14 )+  , ( "თოთხმეტ"   , 14 )+  , ( "თხუთმეტი"  , 15 )+  , ( "თხუთმეტ"   , 15 )+  , ( "თექვსმეტი" , 16 )+  , ( "თექვსმეტ"  , 16 )+  , ( "ჩვიდმეტი"  , 17 )+  , ( "ჩვიდმეტ"   , 17 )+  , ( "თვრამეტი"  , 18 )+  , ( "თვრამეტ"   , 18 )+  , ( "ცხრამეტი"  , 19 )+  , ( "ცხრამეტ"   , 19 )   ] -ruleNumeral :: Rule-ruleNumeral = Rule-  { name = "number (0..10)"+informalMap :: HashMap Text Integer+informalMap = HashMap.fromList+  [ ( "ერთი"       , 1 )+  , ( "წყვილი"     , 2 )+  , ( "წყვილები"   , 2 )+  , ( "ცოტა"       , 3 )+  , ( "რამდენიმე"  , 3 )+  , ( "რამოდენიმე" , 3 )+  ]++ruleToNineteen :: Rule+ruleToNineteen = Rule+  { name = "integer (0..19)"   , pattern =-    [ regex "(ნული|ერთი|ორი|სამი|ოთხი|ხუთი|ექვსი|შვიდი|რვა|ცხრა|ათი)"+    [ regex "(წყვილ(ებ)?ი|ცოტა|რამდენიმე|რამოდენიმე|ნოლი?|ნული?|ერთი|ორი?|სამი?|ოთხი?|ხუთი?|ექვსი?|შვიდი?|რვა|თერთმეტი?|თორმეტი?|ცამეტი?|თოთხმეტი?|თხუთმეტი?|თექვსმეტი?|ჩვიდმეტი?|თვრამეტი?|ცხრამეტი?|ცხრა|ა?ათი)"     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token RegexMatch (GroupMatch (match:_)):_) ->-        HashMap.lookup (Text.toLower match) ruleNumeralMap >>= integer+        let x = Text.toLower match in+        (HashMap.lookup x zeroNineteenMap >>= integer) <|>+        (HashMap.lookup x informalMap >>= integer >>= notOkForAnyTime)       _ -> Nothing   } +tensMap :: HashMap Text Integer+tensMap = HashMap.fromList+  [ ( "ოცი"         , 20 )+  , ( "ოცდა"        , 20 )+  , ( "ოც"          , 20 )+  , ( "ოცდაათ"      , 30 )+  , ( "ოცდაათი"     , 30 )+  , ( "ორმოც"       , 40 )+  , ( "ორმოცი"      , 40 )+  , ( "ორმოცდა"     , 40 )+  , ( "ორმოცდაათ"   , 50 )+  , ( "ორმოცდაათი"  , 50 )+  , ( "სამოც"       , 60 )+  , ( "სამოცი"      , 60 )+  , ( "სამოცდა"     , 60 )+  , ( "სამოცდაათ"   , 70 )+  , ( "სამოცდაათი"  , 70 )+  , ( "ოთხმოც"      , 80 )+  , ( "ოთხმოცი"     , 80 )+  , ( "ოთხმოცდა"    , 80 )+  , ( "ოთხმოცდაათ"  , 90 )+  , ( "ოთხმოცდაათი" , 90 )+  ]++ruleTens :: Rule+ruleTens = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(ოცდაათი?|ორმოცდაათი?|სამოცდაათი?|ოთხმოცდაათი?|ოცდა|ორმოცდა|სამოცდა|ოთხმოცდა|ოცი?|ორმოცი?|სამოცი?|ოთხმოცი?)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) tensMap >>= integer+      _ -> Nothing+  }++hundredsMap :: HashMap Text Integer+hundredsMap = HashMap.fromList+  [ ( "ასი"      , 100 )+  , ( "ორასი"    , 200 )+  , ( "სამასი"   , 300 )+  , ( "ოთხასი"   , 400 )+  , ( "ხუთასი"   , 500 )+  , ( "ექვსასი"  , 600 )+  , ( "შვიდასი"  , 700 )+  , ( "რვაასი"   , 800 )+  , ( "ცხრაასი"  , 900 )+  , ( "ას"       , 100 )+  , ( "ორას"     , 200 )+  , ( "სამას"    , 300 )+  , ( "ოთხას"    , 400 )+  , ( "ხუთას"    , 500 )+  , ( "ექვსას"   , 600 )+  , ( "შვიდას"   , 700 )+  , ( "რვაას"    , 800 )+  , ( "ცხრაას"   , 900 )+  , ( "ორ ას"    , 200 )+  , ( "სამ ას"   , 300 )+  , ( "ოთხ ას"   , 400 )+  , ( "ხუთ ას"   , 500 )+  , ( "ექვს ას"  , 600 )+  , ( "შვიდ ას"  , 700 )+  , ( "რვა ას"   , 800 )+  , ( "ცხრა ას"  , 900 )+  , ( "ორ ასი"   , 200 )+  , ( "სამ ასი"  , 300 )+  , ( "ოთხ ასი"  , 400 )+  , ( "ხუთ ასი"  , 500 )+  , ( "ექვს ასი" , 600 )+  , ( "შვიდ ასი" , 700 )+  , ( "რვა ასი"  , 800 )+  , ( "ცხრა ასი" , 900 )+  ]++ruleHundreds :: Rule+ruleHundreds = Rule+  { name = "integer (800..900)"+  , pattern =+    [ regex "(ასი?|ორ ?ასი?|სამ ?ასი?|ოთხ ?ასი?|ხუთ ?ასი?|ექვს ?ასი?|შვიდ ?ასი?|რვა ?ასი?|ცხრა ?ასი?)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) hundredsMap >>= integer+      _ -> Nothing+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(ათასი?|მილიონი?|მილიარდი?)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "ათასი" -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "ათას" -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "მილიონი"  -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "მილიონ"  -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "მილიარდი"  -> double 1e9 >>= withGrain 9 >>= withMultipliable+        "მილიარდ"  -> double 1e9 >>= withGrain 9 >>= withMultipliable+        _          -> Nothing+      _ -> Nothing+  }++ruleCompositeTens :: Rule+ruleCompositeTens = Rule+  { name = "integer 21..99"+  , pattern =+    [ oneOf [20,40..90]+    , numberBetween 1 20+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = tens}:+       Token Numeral NumeralData{TNumeral.value = units}:+       _) -> double $ tens + units+      _ -> Nothing+  }++ruleCompositeHundreds :: Rule+ruleCompositeHundreds = Rule+  { name = "integer 100..999"+  , pattern =+    [ oneOf [100,200..900]+    , oneOf [20,40..90]+    , numberBetween 1 20+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = hundreds}:+       Token Numeral NumeralData{TNumeral.value = tens}:+       Token Numeral NumeralData{TNumeral.value = units}:+       _) -> double $ hundreds + tens + units+      _ -> Nothing+  }++ruleCompositeHundredsAndUnits :: Rule+ruleCompositeHundredsAndUnits = Rule+  { name = "integer 100..999"+  , pattern =+    [ oneOf [100,200..900]+    , numberBetween 1 20+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = hundreds}:+       Token Numeral NumeralData{TNumeral.value = units}:+       _) -> double $ hundreds + units+      _ -> Nothing+  }++ruleCompositeHundredsAndTens :: Rule+ruleCompositeHundredsAndTens = Rule+  { name = "integer 100..999"+  , pattern =+    [ oneOf [100,200..900]+    , oneOf [10,20..90]+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = hundreds}:+       Token Numeral NumeralData{TNumeral.value = tens}:+       _) -> double $ hundreds + tens+      _ -> Nothing+  }++ruleDotSpelledOut :: Rule+ruleDotSpelledOut = Rule+  { name = "one point 2"+  , pattern =+    [ dimension Numeral+    , regex "წერტილი|მთელი"+    , Predicate $ not . hasGrain+    ]+  , prod = \case+      (Token Numeral nd1:_:Token Numeral nd2:_) ->+        double $ TNumeral.value nd1 + decimalsToDouble (TNumeral.value nd2)+      _ -> Nothing+  }++ruleLeadingDotSpelledOut :: Rule+ruleLeadingDotSpelledOut = Rule+  { name = "point 77"+  , pattern =+    [ regex "წერტილი|მთელი"+    , Predicate $ not . hasGrain+    ]+  , prod = \case+      (_:Token Numeral nd:_) -> double . decimalsToDouble $ TNumeral.value nd+      _ -> Nothing+  }++ruleDecimals :: Rule+ruleDecimals = Rule+  { name = "decimal number"+  , pattern =+    [ regex "(\\d*\\.\\d+)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) -> parseDecimal True match+      _ -> Nothing+  }++ruleCommas :: Rule+ruleCommas = Rule+  { name = "comma-separated numbers"+  , pattern =+    [ regex "(\\d+(,\\d\\d\\d)+(\\.\\d+)?)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDouble (Text.replace "," Text.empty match) >>= double+      _ -> Nothing+  }++ruleSuffixes :: Rule+ruleSuffixes = Rule+  { name = "suffixes (K,M,G))"+  , pattern =+    [ dimension Numeral+    , regex "(k|m|g)(?=[\\W$€¢£]|$)"+    ]+  , prod = \case+      (Token Numeral nd : Token RegexMatch (GroupMatch (match : _)):_) -> do+        x <- case Text.toLower match of+          "k" -> Just 1e3+          "m" -> Just 1e6+          "g" -> Just 1e9+          _ -> Nothing+        double $ TNumeral.value nd * x+      _ -> Nothing+  }++ruleNegative :: Rule+ruleNegative = Rule+  { name = "negative numbers"+  , pattern =+    [ regex "(-|მინუს|მინ)(?!\\s*-)"+    , Predicate isPositive+    ]+  , prod = \case+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleSum :: Rule+ruleSum = Rule+  { name = "intersect 2 numbers"+  , pattern =+    [ Predicate $ and . sequence [hasGrain, isPositive]+    , Predicate $ and . sequence [not . isMultipliable, isPositive]+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = val1, TNumeral.grain = Just g}:+       Token Numeral NumeralData{TNumeral.value = val2}:+       _) | (10 ** fromIntegral g) > val2 -> double $ val1 + val2+      _ -> Nothing+  }++ruleSumAnd :: Rule+ruleSumAnd = Rule+  { name = "intersect 2 numbers (with and)"+  , pattern =+    [ Predicate $ and . sequence [hasGrain, isPositive]+    , regex "და"+    , Predicate $ and . sequence [not . isMultipliable, isPositive]+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = val1, TNumeral.grain = Just g}:+       _:+       Token Numeral NumeralData{TNumeral.value = val2}:+       _) | (10 ** fromIntegral g) > val2 -> double $ val1 + val2+      _ -> Nothing+  }++ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ dimension Numeral+    , Predicate isMultipliable+    ]+  , prod = \case+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }+ rules :: [Rule] rules =-  [ ruleNumeral+  [ ruleToNineteen+  , ruleHundreds+  , ruleCompositeHundreds+  , ruleCompositeHundredsAndUnits+  , ruleCompositeHundredsAndTens+  , ruleTens+  , rulePowersOfTen+  , ruleCompositeTens+  , ruleDotSpelledOut+  , ruleLeadingDotSpelledOut+  , ruleDecimals+  , ruleCommas+  , ruleSuffixes+  , ruleNegative+  , ruleSum+  , ruleSumAnd+  , ruleMultiply   ]
+ Duckling/Numeral/KM/Corpus.hs view
@@ -0,0 +1,107 @@+-- 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.Numeral.KM.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++context :: Context+context = testContext {locale = makeLocale KM Nothing}++corpus :: Corpus+corpus = (context, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "០"+             , "សូន្យ"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "១"+             , "មួយ"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "២"+             , "ពីរ"+             ]+  , examples (NumeralValue 3)+             [ "3"+             , "៣"+             , "បី"+             ]+  , examples (NumeralValue 4)+             [ "4"+             , "៤"+             , "បួន"+             ]+  , examples (NumeralValue 5)+             [ "5"+             , "៥"+             , "ប្រាំ"+             ]+  , examples (NumeralValue 6)+             [ "6"+             , "៦"+             , "ប្រាំមួយ"+             ]+  , examples (NumeralValue 7)+             [ "7"+             , "៧"+             , "ប្រាំពីរ"+             ]+  , examples (NumeralValue 8)+             [ "8"+             , "៨"+             , "ប្រាំបី"+             ]+  , examples (NumeralValue 9)+             [ "9"+             , "៩"+             , "ប្រាំបួន"+             ]+  , examples (NumeralValue 10)+             [ "ដប់"+             ]+  , examples (NumeralValue 11)+             [ "ដប់មួយ"+             ]+  , examples (NumeralValue 22)+             [ "ម្ភៃពីរ"+             ]+  , examples (NumeralValue 33)+             [ "សាមបី"+             ]+  , examples (NumeralValue 99)+             [ "កៅប្រាំបួន"+             ]+  , examples (NumeralValue 320)+             [ "បីរយម្ភៃ"+             ]+  , examples (NumeralValue 6078)+             [ "ប្រាំមួយពាន់ចិតប្រាំបី"+             ]+  , examples (NumeralValue 5689443)+             [ "ប្រាំលានប្រាំមួយសែនប្រាំបីម៉ឺនប្រាំបួនពាន់បួនរយសែបី"+             ]+  , examples (NumeralValue 800000000)+             [ "ប្រាំបីរយលាន"+             ]+  ]
+ Duckling/Numeral/KM/Rules.hs view
@@ -0,0 +1,163 @@+-- 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 #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Numeral.KM.Rules+  ( rules+  ) where++import Data.HashMap.Strict (HashMap)+import Data.Maybe+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.Numeral.Types (NumeralData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral++ruleNumeralMap :: HashMap Text Integer+ruleNumeralMap = HashMap.fromList+  [ ( "០", 0 )+  , ( "១", 1 )+  , ( "២", 2 )+  , ( "៣", 3 )+  , ( "៤", 4 )+  , ( "៥", 5 )+  , ( "៦", 6 )+  , ( "៧", 7 )+  , ( "៨", 8 )+  , ( "៩", 9 )+  , ( "សូន្យ", 0 )+  , ( "មួយ", 1 )+  , ( "ពីរ", 2 )+  , ( "បី", 3 )+  , ( "បួន", 4 )+  , ( "ប្រាំ", 5 )+  , ( "ប្រាំមួយ", 6 )+  , ( "ប្រាំពីរ", 7 )+  , ( "ប្រាំបី", 8 )+  , ( "ប្រាំបួន", 9 )+  ]++ruleNumeral :: Rule+ruleNumeral = Rule+  { name = "integer (0..9)"+  -- ត្រូវដាក់ពាក្យ ប្រាំមួយ ប្រាំពីរ ប្រាំបី និងប្រាំបួន នៅខាងមុខលេខប្រាំ។ បើមិនដូច្នោះទេ វាមិនអាចផ្គូរផ្គងត្រូវទេ។+  , pattern =+    [ regex "(០|១|២|៣|៤|៥|៦|៧|៨|៩|ប្រាំបួន|ប្រាំបី|ប្រាំពីរ|ប្រាំមួយ|ប្រាំ|បួន|បី|ពីរ|មួយ|សូន្យ)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup match ruleNumeralMap >>= integer+      _ -> Nothing+  }++ruleTensMap :: HashMap Text Integer+ruleTensMap = HashMap.fromList+  -- លេខ ១០ ២០ ៣០ ៤០ ៥០ ៦០ ៧០ ៨០ ៩០ អត់ត្រូវបានបញ្ចូលទេ ព្រោះមិនទាន់អាចរក+  -- វិធីដកលេខ ០ ចេញ នៅពេលផ្គំុជាមួយលេខដទៃ។+  -- ពពួក "សិប" ក៏មិនត្រូវបានបញ្ចូលដែរ ព្រោះមិនទាន់រកឃើញវិធីផ្គូរផ្គងត្រូវ។+  [ ( "ដប់", 10 )+  , ( "ម្ភៃ", 20 )+  , ( "សាម", 30 )+  , ( "សែ", 40 )+  , ( "ហា", 50 )+  , ( "ហុក", 60 )+  , ( "ចិត", 70 )+  , ( "ប៉ែត", 80 )+  , ( "កៅ", 90 )+  ]++ruleTens :: Rule+ruleTens = Rule+  { name = "integer (10..90)"+  , pattern =+    [ regex "(កៅ|ប៉ែត|ចិត|ហុក|ហា|សែ|សាម|ម្ភៃ|ដប់)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup match ruleTensMap >>= integer+      _ -> Nothing+  }++ruleCompositeTens :: Rule+ruleCompositeTens = Rule+  { name = "integer (11..99)"+  , pattern =+    [ oneOf [10, 20 .. 90]+    , oneOf [1 .. 9]+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = v1}:+       Token Numeral NumeralData{TNumeral.value = v2}:+       _) -> double $ v1 + v2+      _ -> Nothing+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(រយ|ពាន់|ម៉ឺន|សែន|លាន)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "រយ" -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "ពាន់" -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "ម៉ឺន" -> double 1e4 >>= withGrain 4 >>= withMultipliable+        "សែន" -> double 1e5 >>= withGrain 5 >>= withMultipliable+        "លាន" -> double 1e6 >>= withGrain 6 >>= withMultipliable+        _ -> Nothing+      _ -> Nothing+  }++-- សម្រាប់ផ្គុំពីរលេខ ដែលចាប់ពីខ្ទង់រយទៅ និងខ្ទង់រាយ+ruleSum :: Rule+ruleSum = Rule+  { name = "intersect 2 numbers"+  , pattern =+    [ Predicate $ and . sequence [hasGrain, isPositive]+    , Predicate $ and . sequence [not . isMultipliable, isPositive]+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = val1, TNumeral.grain = Just g}:+       Token Numeral NumeralData{TNumeral.value = val2}:+       _) | (10 ** fromIntegral g) > val2 -> double $ val1 + val2+      _ -> Nothing+  }++-- សម្រាប់លេខចាប់ពីខ្ទង់រយទៅ+ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ dimension Numeral+    , Predicate isMultipliable+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleNumeral+  , ruleTens+  , ruleCompositeTens+  , rulePowersOfTen+  , ruleSum+  , ruleMultiply+  ]
+ Duckling/Numeral/KN/Corpus.hs view
@@ -0,0 +1,67 @@+-- 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.Numeral.KN.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {locale = makeLocale KN Nothing}, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "ಸೊನ್ನೆ"+             , "೦"+             ]+  , examples (NumeralValue 1)+             [ "ಒಂದು"+             , "೧"+             ]+  , examples (NumeralValue 2)+             [ "ಎರಡು"+             , "೨"+             ]+  , examples (NumeralValue 3)+             [ "ಮೂರು"+             , "೩"+             ]+  , examples (NumeralValue 4)+             [ "ನಾಲ್ಕು"+             , "೪"+             ]+  , examples (NumeralValue 5)+             [ "ಐದು"+             , "೫"+             ]+  , examples (NumeralValue 6)+             [ "ಆರು"+             , "೬"+             ]+  , examples (NumeralValue 7)+             [ "ಏಳು"+             , "೭"+             ]+  , examples (NumeralValue 8)+             [ "ಎಂಟು"+             , "೮"+             ]+  , examples (NumeralValue 9)+             [ "ಒಂಬತ್ತು"+             , "೯"+             ]+  ]
+ Duckling/Numeral/KN/Rules.hs view
@@ -0,0 +1,90 @@+-- 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 #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Numeral.KN.Rules+  ( rules+  ) where++import Data.HashMap.Strict (HashMap)+import Data.Maybe+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.Regex.Types+import Duckling.Types++ankiMap :: HashMap Char Char+ankiMap = HashMap.fromList+  [ ('೦', '0')+  , ('೧', '1')+  , ('೨', '2')+  , ('೩', '3')+  , ('೪', '4')+  , ('೫', '5')+  , ('೬', '6')+  , ('೭', '7')+  , ('೮', '8')+  , ('೯', '9')+  ]++ankiToArab :: Char -> Char+ankiToArab c = HashMap.lookupDefault c c ankiMap++ruleAnki :: Rule+ruleAnki = Rule+  { name = "anki forms"+  , pattern =+    [ regex "([೦೧೨೩೪೫೬೭೮೯]{1,10})"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        toInteger <$> parseInt (Text.map ankiToArab match) >>= integer+      _ -> Nothing+  }++ruleNumeralMap :: [(Text, Integer)]+ruleNumeralMap =+  [ ("ಸೊನ್ನೆ", 0)+  , ("ಒಂದು", 1)+  , ("ಎರಡು", 2)+  , ("ಮೂರು", 3)+  , ("ನಾಲ್ಕು", 4)+  , ("ಐದು", 5)+  , ("ಆರು", 6)+  , ("ಏಳು", 7)+  , ("ಎಂಟು", 8)+  , ("ಒಂಬತ್ತು", 9)+  ]++ruleNumerals :: [Rule]+ruleNumerals =+  map constructRule ruleNumeralMap+  where+    constructRule :: (Text, Integer) -> Rule+    constructRule (s, i) = Rule+      { name = "number: " `mappend` s+      , pattern =+        [ regex $ Text.unpack s+        ]+      , prod = const $ integer i+      }+++rules :: [Rule]+rules =+  [ ruleAnki+  ]+  ++ ruleNumerals
Duckling/Numeral/KO/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/KO/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
+ Duckling/Numeral/LO/Corpus.hs view
@@ -0,0 +1,89 @@+-- 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.Numeral.LO.Corpus+  ( corpus ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {locale = makeLocale LO Nothing}, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "ສູນ"+             ]+  , examples (NumeralValue 1)+             [ "ໜຶ່ງ"+             ]+  , examples (NumeralValue 2)+             [ "ສອງ"+             ]+  , examples (NumeralValue 3)+             [ "ສາມ"+             ]+  , examples (NumeralValue 4)+             [ "ສີ່"+             ]+  , examples (NumeralValue 5)+             [ "ຫ້າ"+             ]+  , examples (NumeralValue 6)+             [ "ຫົກ"+             ]+  , examples (NumeralValue 7)+             [ "ເຈັດ"+             ]+  , examples (NumeralValue 8)+             [ "ແປດ"+             ]+  , examples (NumeralValue 9)+             [ "ເກົ້າ"+             ]+  , examples (NumeralValue 11)+             [ "ສິບເອັດ"+             ]+  , examples (NumeralValue 15)+             [ "ສິບຫ້າ"+             ]+  , examples (NumeralValue 17)+             [ "ສິບເຈັດ"+             ]+  , examples (NumeralValue 22)+             [ "ຊາວສອງ"+             ]+  , examples (NumeralValue 24)+             [ "ຊາວສີ່"+             ]+  , examples (NumeralValue 26)+             [ "ຊາວຫົກ"+             ]+  , examples (NumeralValue 28)+             [ "ຊາວແປດ"+             ]+  , examples (NumeralValue 34)+             [ "ສາມສິບສີ່"+             ]+  , examples (NumeralValue 10)+             [ "ສິບ"+             ]+  , examples (NumeralValue 20)+             [ "ຊາວ"+             ]+  , examples (NumeralValue 50)+             [ "ຫ້າສິບ"+             ]+  ]
+ Duckling/Numeral/LO/Rules.hs view
@@ -0,0 +1,153 @@+-- 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 #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Numeral.LO.Rules+  ( rules+  ) where++import Data.HashMap.Strict (HashMap)+import Data.Maybe+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.Numeral.Types (NumeralData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral++ruleNumeralMap :: HashMap Text Integer+ruleNumeralMap = HashMap.fromList+  [ ( "ສູນ", 0 )+  , ( "ໜຶ່ງ", 1 )+  , ( "ສອງ", 2 )+  , ( "ສາມ", 3 )+  , ( "ສີ່", 4 )+  , ( "ຫ້າ", 5)+  , ( "ຫົກ", 6)+  , ( "ເຈັດ", 7)+  , ( "ແປດ", 8)+  , ( "ເກົ້າ", 9)+  , ( "ສິບ", 10)+  ]++ruleNumeral :: Rule+ruleNumeral = Rule+  { name = "number (0..10)"+  , pattern =+    [ regex "(ສູນ|ໜຶ່ງ|ສອງ|ສາມ|ສີ່|ຫ້າ|ຫົກ|ເຈັດ|ແປດ|ເກົ້າ|ສິບ)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) ruleNumeralMap >>= integer+      _ -> Nothing+  }++elevenToNineteenMap :: HashMap Text Integer+elevenToNineteenMap = HashMap.fromList+  [ ( "ສິບເອັດ", 11 )+  , ( "ສິບສອງ", 12 )+  , ( "ສິບສາມ", 13 )+  , ( "ສິບສີ່", 14 )+  , ( "ສິບຫ້າ", 15 )+  , ( "ສິບຫົກ", 16 )+  , ( "ສິບເຈັດ", 17 )+  , ( "ສິບແປດ", 18 )+  , ( "ສິບເກົ້າ", 19 )+  ]++ruleElevenToNineteen :: Rule+ruleElevenToNineteen = Rule+  { name = "number (11..19)"+  , pattern =+    [ regex "(ສິບເອັດ|ສິບສອງ|ສິບສາມ|ສິບສີ່|ສິບຫ້າ|ສິບຫົກ|ສິບເຈັດ|ສິບແປດ|ສິບເກົ້າ)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) elevenToNineteenMap >>= integer+      _ -> Nothing+  }++twentyoneToTwentynineMap :: HashMap Text Integer+twentyoneToTwentynineMap = HashMap.fromList+  [ ( "ຊາວເອັດ", 21 )+  , ( "ຊາວສອງ", 22 )+  , ( "ຊາວສາມ", 23 )+  , ( "ຊາວສີ່", 24 )+  , ( "ຊາວຫ້າ", 25 )+  , ( "ຊາວຫົກ", 26 )+  , ( "ຊາວເຈັດ", 27 )+  , ( "ຊາວແປດ", 28 )+  , ( "ຊາວເກົ້າ", 29 )+  ]++ruleTwentyoneToTwentynine :: Rule+ruleTwentyoneToTwentynine = Rule+  { name = "number (21..29)"+  , pattern =+    [ regex "(ຊາວເອັດ|ຊາວສອງ|ຊາວສາມ|ຊາວສີ່|ຊາວຫ້າ|ຊາວຫົກ|ຊາວເຈັດ|ຊາວແປດ|ຊາວເກົ້າ)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) twentyoneToTwentynineMap >>= integer+      _ -> Nothing+  }++tensMap :: HashMap Text Integer+tensMap = HashMap.fromList+  [ ( "ຊາວ", 20 )+  , ( "ສາມສິບ", 30 )+  , ( "ສິບສີ່", 40 )+  , ( "ຫ້າສິບ", 50 )+  , ( "ຫົກສິບ", 60 )+  , ( "ເຈັດສິບ", 70 )+  , ( "ແປດສິບ", 80 )+  , ( "ເກົ້າສິບ", 90 )+  ]++ruleTens :: Rule+ruleTens = Rule+  { name = "integer (20,30..90)"+  , pattern =+    [ regex "(ຊາວ|ສາມສິບ|ສິບສີ່|ຫ້າສິບ|ຫົກສິບ|ເຈັດສິບ|ແປດສິບ|ເກົ້າສິບ)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) tensMap >>= integer+      _ -> Nothing+  }++ruleCompositeTens :: Rule+ruleCompositeTens = Rule+  { name = "integer ([3-9][1-9])"+  , pattern =+    [ regex "(ສາມສິບ|ສິບສີ່|ຫ້າສິບ|ຫົກສິບ|ເຈັດສິບ|ແປດສິບ|ເກົ້າສິບ)(ໜຶ່ງ|ສອງ|ສາມ|ສີ່|ຫ້າ|ຫົກ|ເຈັດ|ແປດ|ເກົ້າ)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        v1 <- HashMap.lookup (Text.toLower m1) tensMap+        v2 <- HashMap.lookup (Text.toLower m2) ruleNumeralMap+        integer $ v1 + v2+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleNumeral+  , ruleElevenToNineteen+  , ruleTwentyoneToTwentynine+  , ruleTens+  , ruleCompositeTens+  ]
+ Duckling/Numeral/ML/Corpus.hs view
@@ -0,0 +1,100 @@+-- 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.Numeral.ML.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types+++context :: Context+context = testContext {locale = makeLocale ML Nothing}++corpus :: Corpus+corpus = (context, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "പൂജ്യം"+             ]+  , examples (NumeralValue 1)+             [ "ഒന്ന്"+             ]+  , examples (NumeralValue 2)+             [ "രണ്ട്"+             ]+  , examples (NumeralValue 3)+             [ "മുന്ന്"+             ]+  , examples (NumeralValue 4)+             [ "നാല്"+             ]+  , examples (NumeralValue 5)+             [ "അഞ്ച്"+             ]+  , examples (NumeralValue 6)+             [ "ആറ്"+             ]+  , examples (NumeralValue 7)+             [ "ഏഴ്"+             ]+  , examples (NumeralValue 8)+             [ "എട്ട്"+             ]+  , examples (NumeralValue 9)+             [ "ഒൻപത്"+             ]+  , examples (NumeralValue 10)+             [ "പത്ത്"+             ]+  , examples (NumeralValue 11)+             [ "പതിനൊന്ന്"+             ]+  , examples (NumeralValue 12)+             [ "പന്ത്രണ്ട്"+             ]+  , examples (NumeralValue 13)+             [ "പതിമൂന്ന്"+             ]+  , examples (NumeralValue 19)+             [ "പത്തൊമ്പത്"+             ]+  , examples (NumeralValue 20)+             [ "ഇരുപത്"+             ]+  , examples (NumeralValue 21)+             [ "ഇരുപത്തിഒന്ന്"+             ]+  , examples (NumeralValue 22)+             [ "ഇരുപത്തിരണ്ട്"+             ]+  , examples (NumeralValue 26)+             [ "ഇരുപത്തിആറ്"+             ]+  , examples (NumeralValue 30)+             [ "മുപ്പത്"+             ]+   , examples (NumeralValue 33)+             [ "മുപ്പത്തിമുന്ന്"+             ]+  , examples (NumeralValue 50)+             [ "അമ്പത്"+             ]+  , examples (NumeralValue 51)+             [ "അമ്പത്തിഒന്ന്"+             ]+  ]
+ Duckling/Numeral/ML/Rules.hs view
@@ -0,0 +1,138 @@+-- 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 #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE LambdaCase #-}++module Duckling.Numeral.ML.Rules+  ( rules+  ) where++import Data.HashMap.Strict (HashMap)+import Data.Maybe+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.Numeral.Types (NumeralData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral+++zeroToNineMap :: HashMap Text Integer+zeroToNineMap = HashMap.fromList+  [ ( "പൂജ്യം", 0 )+  , ( "ഒന്ന്", 1 )+  , ( "രണ്ട്", 2 )+  , ( "മുന്ന്", 3 )+  , ( "നാല്", 4 )+  , ( "അഞ്ച്", 5 )+  , ( "ആറ്", 6 )+  , ( "ഏഴ്", 7 )+  , ( "എട്ട്", 8 )+  , ( "ഒൻപത്", 9 )+  ]++ruleZeroToNine :: Rule+ruleZeroToNine = Rule+  { name = "integer (0..9)"+  , pattern =+    [ regex "(പൂജ്യം|ഒന്ന്|രണ്ട്|മുന്ന്|നാല്|അഞ്ച്|ആറ്|ഏഴ്|എട്ട്|ഒൻപത്)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) zeroToNineMap >>= integer+      _ -> Nothing+  }++tenToNineteenMap :: HashMap Text Integer+tenToNineteenMap = HashMap.fromList+  [ ( "പത്ത്", 10 )+  , ( "പതിനൊന്ന്", 11 )+  , ( "പന്ത്രണ്ട്", 12 )+  , ( "പതിമൂന്ന്", 13 )+  , ( "പതിനാല്", 14 )+  , ( "പതിനഞ്ച്", 15 )+  , ( "പതിനാറ്", 16 )+  , ( "പതിനേഴ്", 17 )+  , ( "പതിനെട്ട്", 18 )+  , ( "പത്തൊമ്പത്", 19 )+  ]++ruleTenToNineteen :: Rule+ruleTenToNineteen = Rule+  { name = "integer (10..19)"+  , pattern =+    [+      regex "(പത്ത്|പതിനൊന്ന്|പന്ത്രണ്ട്|പതിമൂന്ന്|പതിനാല്|പതിനഞ്ച്|പതിനാറ്|പതിനേഴ്|പതിനെട്ട്|പത്തൊമ്പത്)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) tenToNineteenMap >>= integer+      _ -> Nothing+  }++tensMap :: HashMap Text Integer+tensMap = HashMap.fromList+  [ ( "ഇരുപത്", 20 )+  , ( "ഇരുപത്തി", 20 )+  , ( "മുപ്പത്", 30 )+  , ( "മുപ്പത്തി", 30 )+  , ( "നാല്പത്", 40 )+  , ( "നാല്പത്തി", 40 )+  , ( "അമ്പത്", 50 )+  , ( "അമ്പത്തി", 50 )+  , ( "അറുപത്", 60 )+  , ( "അറുപത്തി", 60 )+  , ( "എഴുപത്", 70 )+  , ( "എഴുപത്തി", 70 )+  , ( "എൺപത്", 80 )+  , ( "എൺപത്തി", 80 )+  , ( "തൊണ്ണൂറ്", 90 )+  , ( "തൊണ്ണൂറ്റി", 90 )+  ]++ruleTens :: Rule+ruleTens = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(ഇരുപത്|മുപ്പത്|നാല്പത്|അമ്പത്|അറുപത്|എഴുപത്|എൺപത്|തൊണ്ണൂറ്)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) tensMap >>= integer+      _ -> Nothing+  }++ruleCompositeTens :: Rule+ruleCompositeTens = Rule+  { name = "integer ([2-9][1-9])"+  , pattern =+    [ regex "(ഇരുപത്തി|മുപ്പത്തി|നാല്പത്തി|അമ്പത്തി|അറുപത്തി|എഴുപത്തി|എൺപത്തി|തൊണ്ണൂറ്റി)(ഒന്ന്|രണ്ട്|മുന്ന്|നാല്|അഞ്ച്|ആറ്|ഏഴ്|എട്ട്|ഒൻപത്)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        v1 <- HashMap.lookup (Text.toLower m1) tensMap+        v2 <- HashMap.lookup (Text.toLower m2) zeroToNineMap+        integer $ v1 + v2+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleZeroToNine+  , ruleTenToNineteen+  , ruleCompositeTens+  , ruleTens+  ]
+ Duckling/Numeral/MN/Corpus.hs view
@@ -0,0 +1,104 @@+-- 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.Numeral.MN.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++context :: Context+context = testContext {locale = makeLocale MN Nothing}++corpus :: Corpus+corpus = (context, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "нойл"+             , "тэг"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "нэг"+             ]+  , examples (NumeralValue 2)+             [ "хоёр"+             ]+  , examples (NumeralValue 3)+             [ "гурав"+             ]+  , examples (NumeralValue 4)+             [ "дөрөв"+             ]+  , examples (NumeralValue 5)+             [ "тав"+             ]+  , examples (NumeralValue 6)+             [ "зургаа"+             ]+  , examples (NumeralValue 7)+             [ "долоо"+             ]+  , examples (NumeralValue 8)+             [ "найм"+             ]+  , examples (NumeralValue 9)+             [ "ес"+             ]+  , examples (NumeralValue 11)+             [ "арван нэг"+             ]+  , examples (NumeralValue 15)+             [ "арван тав"+             ]+  , examples (NumeralValue 17)+             [ "арван долоо"+             ]+  , examples (NumeralValue 20)+             [ "20"+             , "хорь"+             ]+  , examples (NumeralValue 22)+             [ "хорин хоёр"+             ]+  , examples (NumeralValue 24)+             [ "24"+             , "хорин дөрөв"+             ]+  , examples (NumeralValue 26)+             [ "хорин зургаа"+             ]+  , examples (NumeralValue 28)+             [ "хорин найм"+             ]+  , examples (NumeralValue 10)+             [ "арав"+             ]+  , examples (NumeralValue 20)+             [ "хорь"+             ]+  , examples (NumeralValue 50)+             [ "тавь"+             ]+  , examples (NumeralValue 34)+             [ "гучин дөрөв"+             ]+  , examples (NumeralValue 99)+             [ "ерэн ес"+             ]+  ]
+ Duckling/Numeral/MN/Rules.hs view
@@ -0,0 +1,319 @@+-- 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.Numeral.MN.Rules+  ( rules+  ) where++import Data.HashMap.Strict (HashMap)+import Data.Maybe+import Data.Text (Text)+import Prelude+import Data.String+import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers+import Duckling.Numeral.Types (NumeralData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|хасах|сөрөг"+    , Predicate isPositive+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral NumeralData{TNumeral.value = v}:_) ->+        double $ v * (- 1)+      _ -> Nothing+  }++ruleFew :: Rule+ruleFew = Rule+  { name = "few"+  , pattern =+    [ regex "хэдхэн"+    ]+  , prod = \_ -> integer 3+  }++ruleTen :: Rule+ruleTen = Rule+  { name = "ten"+  , pattern =+    [ regex "арав"+    ]+  , prod = \_ -> integer 10 >>= withGrain 1+  }++ruleDecimalWithThousandsSeparator :: Rule+ruleDecimalWithThousandsSeparator = Rule+  { name = "decimal with thousands separator"+  , pattern =+    [ regex "(\\d+(\\.\\d\\d\\d)+\\,\\d+)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):+       _) -> let fmt = Text.replace "," "." $ Text.replace "." Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }+++-- TODO: Single-word composition (#110)+ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer ([2-9][1-9])"+  , pattern =+    [ regex "(хорин|гучин|дөчин|тавин|жаран|далан|наян|ерэн) ?(нэг|хоёр|гурав|дөрөв|тав|зургаа|долоо|найм|ес)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        v1 <- case Text.toLower m1 of+          "хорин" -> Just 20+          "гучин" -> Just 30+          "дөчин" -> Just 40+          "тавин" -> Just 50+          "жаран" -> Just 60+          "далан" -> Just 70+          "наян" -> Just 80+          "ерэн" -> Just 90+          _ -> Nothing+        v2 <- case Text.toLower m2 of+          "нэг" -> Just 1+          "хоёр" -> Just 2+          "гурав" -> Just 3+          "дөрөв" -> Just 4+          "тав" -> Just 5+          "зургаа" -> Just 6+          "долоо" -> Just 7+          "найм" -> Just 8+          "ес" -> Just 9+          _ -> Nothing+        integer $ v1 + v2+      _ -> Nothing+  }++ruleNumeralsUnd :: Rule+ruleNumeralsUnd = Rule+  { name = "numbers und"+  , pattern =+    [ oneOf [20, 30 .. 90]+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = v1}:+       Token Numeral NumeralData{TNumeral.value = v2}:+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ dimension Numeral+    , Predicate isMultipliable+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate hasGrain+    , Predicate $ and . sequence [not . isMultipliable, isPositive]+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = val1, TNumeral.grain = Just g}:+       Token Numeral NumeralData{TNumeral.value = val2}:+       _) | (10 ** fromIntegral g) > val2 -> double $ val1 + val2+      _ -> Nothing+  }++ruleNumeralsSuffixesKMG :: Rule+ruleNumeralsSuffixesKMG = Rule+  { name = "numbers suffixes (K, M, G)"+  , pattern =+    [ dimension Numeral+    , regex "([kmg])(?=[\\W\\$€]|$)"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = v}:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> case Text.toLower match of+         "k" -> double $ v * 1e3+         "m" -> double $ v * 1e6+         "g" -> double $ v * 1e9+         _ -> Nothing+      _ -> Nothing+  }++ruleCouple :: Rule+ruleCouple = Rule+  { name = "couple"+  , pattern =+    [ regex "хос"+    ]+  , prod = \_ -> integer 2+  }+++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(зуу?|мянга?|сая?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "зуу"   -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "зуун"  -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "мянга"   -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "мянган"  -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "сая"   -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "саяын" -> double 1e6 >>= withGrain 6 >>= withMultipliable+        _           -> Nothing+      _ -> Nothing+  }++zeroNineteenMap :: HashMap Text Integer+zeroNineteenMap = HashMap.fromList+  [ ("нуль", 0)+  , ("тэг", 0)+  , ("нойл", 0)+  , ("нэг", 1)+  , ("ганц", 1)+  , ("хоёр", 2)+  , ("гурав", 3)+  , ("дөрөв", 4)+  , ("тав", 5)+  , ("зургаа", 6)+  , ("долоо", 7)+  , ("найм", 8)+  , ("ес", 9)+  , ("арван", 10)+  , ("арав", 10)+  , ("арван нэг", 11)+  , ("арван хоёр", 12)+  , ("арван гурав", 13)+  , ("арван дөрөв", 14)+  , ("арван тав", 15)+  , ("арван зургаа", 16)+  , ("арван долоо", 17)+  , ("арван найм", 18)+  , ("арван ес", 19)+  ]++-- TODO: Single-word composition (#110)+ruleZeroToNineteen :: Rule+ruleZeroToNineteen = Rule+  { name = "integer (0..19)"+  , pattern =+    [ regex "(нуль|тэг|нойл|нэг|ганц|хоёр|гурав|дөрөв|тав|зургаа|долоо|найм|ес|арван нэг|арван хоёр|арван гурав|арван дөрөв|арван тав|арван зургаа|арван долоо|арван найм|арван ес|арав|арван)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) zeroNineteenMap >>= integer+      _ -> Nothing+  }++tensMap :: HashMap Text Integer+tensMap = HashMap.fromList+  [ ( "хорь" , 20 )+  , ( "гуч", 30 )+  , ( "дөч" , 40 )+  , ( "тавь" , 50 )+  , ( "жар" , 60 )+  , ( "дал" , 70 )+  , ( "ная" , 80 )+  , ( "ер" , 90 )+  ]++-- TODO: Single-word composition (#110)+ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(хорь|гуч|дөч|тавь|жар|дал|ная|ер)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) tensMap >>= integer+      _ -> Nothing+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number"+  , pattern =+    [ dimension Numeral+    , regex "цэг"+    , Predicate $ not . hasGrain+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = v1}:+       _:+       Token Numeral NumeralData{TNumeral.value = v2}:+       _) -> double $ v1 + decimalsToDouble v2+      _ -> Nothing+  }++ruleDecimalNumeral :: Rule+ruleDecimalNumeral = Rule+  { name = "decimal number"+  , pattern =+    [ regex "(\\d*\\.\\d+)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> parseDecimal True match+      _ -> Nothing+  }++ruleIntegerWithThousandsSeparator :: Rule+ruleIntegerWithThousandsSeparator = Rule+  { name = "integer with thousands separator ."+  , pattern =+    [ regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDouble (Text.replace "." Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleCouple+  , ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleFew+  , ruleInteger2+  , ruleInteger3+  , ruleIntegerWithThousandsSeparator+  , ruleIntersect+  , ruleMultiply+  , ruleNumeralDotNumeral+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  , ruleNumeralsUnd+  , rulePowersOfTen+  , ruleTen+  , ruleZeroToNineteen+  ]
Duckling/Numeral/MY/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/MY/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Numeral/NB/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -90,12 +89,14 @@              , "100000"              , "100K"              , "100k"+             , "100 000"              ]   , examples (NumeralValue 3000000)              [ "3M"              , "3000K"              , "3000000"              , "3.000.000"+             , "3 000 000"              ]   , examples (NumeralValue 1200000)              [ "1.200.000"@@ -103,6 +104,7 @@              , "1,2M"              , "1200K"              , ",0012G"+             , "1 200 000"              ]   , examples (NumeralValue (-1200000))              [ "- 1.200.000"@@ -112,15 +114,313 @@              , "-1,2M"              , "-1200K"              , "-,0012G"+             , "-1 200 000"              ]   , examples (NumeralValue 5000)              [ "5 tusen"              , "fem tusen"+             , "5 000"              ]   , examples (NumeralValue 100)              [ "hundre"              ]   , examples (NumeralValue 5020)              [ "fem tusen og tjue"+             ]+  , examples (NumeralValue 1e9)+             [ "en milliard"+             ]+  , examples (NumeralValue 1e12)+             [ "en billion"+             ]+  , examples (NumeralValue 1e15)+             [ "en billiard"+             ]+  , examples (NumeralValue 1e18)+             [ "en trillion"+             ]+  , examples (NumeralValue 1e21)+             [ "en trilliard"+             ]+  , examples (NumeralValue 1e24)+             [ "en kvadrillion"+             ]+  , examples (NumeralValue 1e27)+             [ "en kvadrilliard"+             ]+  , examples (NumeralValue 6e10)+             [ "seksti milliarder"+             , "60 milliarder"+             ]+  , examples (NumeralValue 3e12)+             [ "tre billioner"+             , "3 billioner"+             ]+  , examples (NumeralValue 4e17)+             [ "fire hundre billiarder"+             , "400 billiarder"+             ]+  , examples (NumeralValue 2e18)+             [ "to trillioner"+             , "2 trillioner"+             ]+  , examples (NumeralValue 1.8e22)+             [ "atten trilliarder"+             , "18 trilliarder"+             ]+  , examples (NumeralValue 1.8e22)+             [ "atten trilliarder"+             , "18 trilliarder"+             ]+  , examples (NumeralValue 4.11e26)+             [ "fire hundre og elleve kvadrillioner"+             , "411 kvadrillioner"+             ]+  , examples (NumeralValue 9e27)+             [ "ni kvadrilliarder"+             , "9 kvadrilliarder"+             ]+  , examples (NumeralValue 21)+             [ "tjueen"+             , "tjueén"+             ]+  , examples (NumeralValue 22)+             [ "tjueto"+             ]+  , examples (NumeralValue 23)+             [ "tjuetre"+             ]+  , examples (NumeralValue 24)+             [ "tjuefire"+             ]+  , examples (NumeralValue 25)+             [ "tjuefem"+             ]+  , examples (NumeralValue 26)+             [ "tjueseks"+             ]+  , examples (NumeralValue 27)+             [ "tjuesju"+             , "tjuesyv"+             ]+  , examples (NumeralValue 28)+             [ "tjueåtte"+             ]+  , examples (NumeralValue 29)+             [ "tjueni"+             ]+  , examples (NumeralValue 31)+             [ "trettien"+             , "trettién"+             ]+  , examples (NumeralValue 32)+             [ "trettito"+             ]+  , examples (NumeralValue 33)+             [ "trettitre"+             ]+  , examples (NumeralValue 34)+             [ "trettifire"+             ]+  , examples (NumeralValue 35)+             [ "trettifem"+             ]+  , examples (NumeralValue 36)+             [ "trettiseks"+             ]+  , examples (NumeralValue 37)+             [ "trettisju"+             , "trettisyv"+             ]+  , examples (NumeralValue 38)+             [ "trettiåtte"+             ]+  , examples (NumeralValue 39)+             [ "trettini"+             ]+  , examples (NumeralValue 41)+             [ "førtien"+             , "førtién"+             ]+  , examples (NumeralValue 42)+             [ "førtito"+             ]+  , examples (NumeralValue 43)+             [ "førtitre"+             ]+  , examples (NumeralValue 44)+             [ "førtifire"+             ]+  , examples (NumeralValue 45)+             [ "førtifem"+             ]+  , examples (NumeralValue 46)+             [ "førtiseks"+             ]+  , examples (NumeralValue 47)+             [ "førtisju"+             , "førtisyv"+             ]+  , examples (NumeralValue 48)+             [ "førtiåtte"+             ]+  , examples (NumeralValue 49)+             [ "førtini"+             ]+  , examples (NumeralValue 51)+             [ "femtien"+             , "femtién"+             ]+  , examples (NumeralValue 52)+             [ "femtito"+             ]+  , examples (NumeralValue 53)+             [ "femtitre"+             ]+  , examples (NumeralValue 54)+             [ "femtifire"+             ]+  , examples (NumeralValue 55)+             [ "femtifem"+             ]+  , examples (NumeralValue 56)+             [ "femtiseks"+             ]+  , examples (NumeralValue 57)+             [ "femtisju"+             , "femtisyv"+             ]+  , examples (NumeralValue 58)+             [ "femtiåtte"+             ]+  , examples (NumeralValue 59)+             [ "femtini"+             ]+  , examples (NumeralValue 61)+             [ "sekstien"+             , "sekstién"+             ]+  , examples (NumeralValue 62)+             [ "sekstito"+             ]+  , examples (NumeralValue 63)+             [ "sekstitre"+             ]+  , examples (NumeralValue 64)+             [ "sekstifire"+             ]+  , examples (NumeralValue 65)+             [ "sekstifem"+             ]+  , examples (NumeralValue 66)+             [ "sekstiseks"+             ]+  , examples (NumeralValue 67)+             [ "sekstisju"+             , "sekstisyv"+             ]+  , examples (NumeralValue 68)+             [ "sekstiåtte"+             ]+  , examples (NumeralValue 69)+             [ "sekstini"+             ]+  , examples (NumeralValue 71)+             [ "syttien"+             , "søttien"+             , "søttién"+             , "søttién"+             ]+  , examples (NumeralValue 72)+             [ "syttito"+             , "søttito"+             ]+  , examples (NumeralValue 73)+             [ "syttitre"+             , "søttitre"+             ]+  , examples (NumeralValue 74)+             [ "syttifire"+             , "søttifire"+             ]+  , examples (NumeralValue 75)+             [ "syttifem"+             , "søttifem"+             ]+  , examples (NumeralValue 76)+             [ "syttiseks"+             , "søttiseks"+             ]+  , examples (NumeralValue 77)+             [ "syttisju"+             , "syttisju"+             , "søttisyv"+             , "søttisyv"+             ]+  , examples (NumeralValue 78)+             [ "søttiåtte"+             , "søttiåtte"+             ]+  , examples (NumeralValue 79)+             [ "søttini"+             , "søttini"+             ]+  , examples (NumeralValue 81)+             [ "åttien"+             , "åttién"+             ]+  , examples (NumeralValue 82)+             [ "åttito"+             ]+  , examples (NumeralValue 83)+             [ "åttitre"+             ]+  , examples (NumeralValue 84)+             [ "åttifire"+             ]+  , examples (NumeralValue 85)+             [ "åttifem"+             ]+  , examples (NumeralValue 86)+             [ "åttiseks"+             ]+  , examples (NumeralValue 87)+             [ "åttisju"+             , "åttisyv"+             ]+  , examples (NumeralValue 88)+             [ "åttiåtte"+             ]+  , examples (NumeralValue 89)+             [ "åttini"+             ]+  , examples (NumeralValue 91)+             [ "nittien"+             , "nittién"+             ]+  , examples (NumeralValue 92)+             [ "nittito"+             ]+  , examples (NumeralValue 93)+             [ "nittitre"+             ]+  , examples (NumeralValue 94)+             [ "nittifire"+             ]+  , examples (NumeralValue 95)+             [ "nittifem"+             ]+  , examples (NumeralValue 96)+             [ "nittiseks"+             ]+  , examples (NumeralValue 97)+             [ "nittisju"+             , "nittisyv"+             ]+  , examples (NumeralValue 98)+             [ "nittiåtte"+             ]+  , examples (NumeralValue 99)+             [ "nittini"              ]   ]
Duckling/Numeral/NB/Rules.hs view
@@ -2,11 +2,11 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}  module Duckling.Numeral.NB.Rules@@ -36,7 +36,7 @@     , regex "og"     , Predicate $ and . sequence [not . isMultipliable, isPositive]     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token Numeral NumeralData{TNumeral.value = val1, TNumeral.grain = Just g}:        _:        Token Numeral NumeralData{TNumeral.value = val2}:@@ -51,7 +51,7 @@     [ regex "-|minus|negativ"     , Predicate isPositive     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))       _ -> Nothing   }@@ -71,7 +71,7 @@   , pattern =     [ regex "(\\d+(\\.\\d\\d\\d)+\\,\\d+)"     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token RegexMatch (GroupMatch (match:_)):        _) -> let fmt = Text.replace "," "." $ Text.replace "." Text.empty match         in parseDouble fmt >>= double@@ -85,7 +85,7 @@     [ dimension Numeral     , Predicate isMultipliable     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (token1:token2:_) -> multiply token1 token2       _ -> Nothing   }@@ -96,7 +96,7 @@   , pattern =     [ regex "(\\d*,\\d+)"     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token RegexMatch (GroupMatch (match:_)):        _) -> parseDecimal False match       _ -> Nothing@@ -109,7 +109,7 @@     [ oneOf [70, 20, 60, 50, 40, 90, 30, 80]     , numberBetween 1 10     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token Numeral NumeralData{TNumeral.value = v1}:        Token Numeral NumeralData{TNumeral.value = v2}:        _) -> double $ v1 + v2@@ -132,7 +132,7 @@     [ Predicate hasGrain     , Predicate $ and . sequence [not . isMultipliable, isPositive]     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token Numeral NumeralData{TNumeral.value = val1, TNumeral.grain = Just g}:        Token Numeral NumeralData{TNumeral.value = val2}:        _) | (10 ** fromIntegral g) > val2 -> double $ val1 + val2@@ -146,7 +146,7 @@     [ dimension Numeral     , regex "([kmg])(?=[\\W\\$€]|$)"     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token Numeral NumeralData{TNumeral.value = v}:        Token RegexMatch (GroupMatch (match:_)):        _) -> case Text.toLower match of@@ -161,9 +161,9 @@ rulePowersOfTen = Rule   { name = "powers of tens"   , pattern =-    [ regex "(hundre(de)?|tusen?|million(er)?)"+    [ regex "(hundre(de)?|tusen?|million(er)?|milliard(?:er)?|billion(?:er)?|billiard(?:er)?|trillion(?:er)?|trilliard(?:er)?|kvadrillion(?:er)?|kvadrilliard(?:er)?)"     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of         "hundre"    -> double 1e2 >>= withGrain 2 >>= withMultipliable         "hundrede"  -> double 1e2 >>= withGrain 2 >>= withMultipliable@@ -171,6 +171,20 @@         "tusen"     -> double 1e3 >>= withGrain 3 >>= withMultipliable         "million"   -> double 1e6 >>= withGrain 6 >>= withMultipliable         "millioner" -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "milliard" -> double 1e9 >>= withGrain 9 >>= withMultipliable+        "milliarder" -> double 1e9 >>= withGrain 9 >>= withMultipliable+        "billion" -> double 1e12 >>= withGrain 12 >>= withMultipliable+        "billioner" -> double 1e12 >>= withGrain 12 >>= withMultipliable+        "billiard" -> double 1e15 >>= withGrain 15 >>= withMultipliable+        "billiarder" -> double 1e15 >>= withGrain 15 >>= withMultipliable+        "trillion" -> double 1e18 >>= withGrain 18 >>= withMultipliable+        "trillioner" -> double 1e18 >>= withGrain 18 >>= withMultipliable+        "trilliard" -> double 1e21 >>= withGrain 21 >>= withMultipliable+        "trilliarder" -> double 1e21 >>= withGrain 21 >>= withMultipliable+        "kvadrillion" -> double 1e24 >>= withGrain 24 >>= withMultipliable+        "kvadrillioner" -> double 1e24 >>= withGrain 24 >>= withMultipliable+        "kvadrilliard" -> double 1e27 >>= withGrain 27 >>= withMultipliable+        "kvadrilliarder" -> double 1e27 >>= withGrain 27 >>= withMultipliable         _           -> Nothing       _ -> Nothing   }@@ -208,7 +222,7 @@   , ( "seks" , 6 )   , ( "sju" , 7 )   , ( "syv" , 7 )-  , ( "otte" , 8 )+  , ( "åtte" , 8 )   , ( "ni" , 9 )   , ( "ti" , 10 )   , ( "elleve" , 11 )@@ -229,12 +243,137 @@   , pattern =     [ regex "(intet|ingen|null|en|ett|én|to|tretten|tre|fire|femten|fem|seksten|seks|syv|sju|åtte|nitten|ni|ti|elleve|tolv|fjorten|sytten|søtten|atten)"     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token RegexMatch (GroupMatch (match:_)):_) ->         HashMap.lookup (Text.toLower match) zeroToNineteenMap >>= integer       _ -> Nothing   } +twentyToHundredMap :: HashMap Text Integer+twentyToHundredMap = HashMap.fromList+  [ ("tjueen", 21)+  , ("tjueén", 21)+  , ("tjueto", 22)+  , ("tjuetre", 23)+  , ("tjuefire", 24)+  , ("tjuefem", 25)+  , ("tjueseks", 26)+  , ("tjuesju", 27)+  , ("tjuesyv", 27)+  , ("tjueåtte", 28)+  , ("tjueni", 29)+  , ("trettien", 31)+  , ("trettién", 31)+  , ("trettito", 32)+  , ("trettitre", 33)+  , ("trettifire", 34)+  , ("trettifem", 35)+  , ("trettiseks", 36)+  , ("trettisju", 37)+  , ("trettisyv", 37)+  , ("trettiåtte", 38)+  , ("trettini", 39)+  , ("førtien", 41)+  , ("førtién", 41)+  , ("førtito", 42)+  , ("førtitre", 43)+  , ("førtifire", 44)+  , ("førtifem", 45)+  , ("førtiseks", 46)+  , ("førtisju", 47)+  , ("førtisyv", 47)+  , ("førtiåtte", 48)+  , ("førtini", 49)+  , ("femtien", 51)+  , ("femtién", 51)+  , ("femtito", 52)+  , ("femtitre", 53)+  , ("femtifire", 54)+  , ("femtifem", 55)+  , ("femtiseks", 56)+  , ("femtisju", 57)+  , ("femtisyv", 57)+  , ("femtiåtte", 58)+  , ("femtini", 59)+  , ("sekstien", 61)+  , ("sekstién", 61)+  , ("sekstito", 62)+  , ("sekstitre", 63)+  , ("sekstifire", 64)+  , ("sekstifem", 65)+  , ("sekstiseks", 66)+  , ("sekstisju", 67)+  , ("sekstisyv", 67)+  , ("sekstiåtte", 68)+  , ("sekstini", 69)+  , ("syttien", 71)+  , ("syttién", 71)+  , ("syttito", 72)+  , ("syttitre", 73)+  , ("syttifire", 74)+  , ("syttifem", 75)+  , ("syttiseks", 76)+  , ("syttisju", 77)+  , ("syttisyv", 77)+  , ("syttiåtte", 78)+  , ("syttini", 79)+  , ("søttien", 71)+  , ("søttién", 71)+  , ("søttito", 72)+  , ("søttitre", 73)+  , ("søttifire", 74)+  , ("søttifem", 75)+  , ("søttiseks", 76)+  , ("søttisju", 77)+  , ("søttisyv", 77)+  , ("søttiåtte", 78)+  , ("søttini", 79)+  , ("åttien", 81)+  , ("åttién", 81)+  , ("åttito", 82)+  , ("åttitre", 83)+  , ("åttifire", 84)+  , ("åttifem", 85)+  , ("åttiseks", 86)+  , ("åttisju", 87)+  , ("åttisyv", 87)+  , ("åttiåtte", 88)+  , ("åttini", 89)+  , ("nittien", 91)+  , ("nittién", 91)+  , ("nittito", 92)+  , ("nittitre", 93)+  , ("nittifire", 94)+  , ("nittifem", 95)+  , ("nittiseks", 96)+  , ("nittisju", 97)+  , ("nittisyv", 97)+  , ("nittiåtte", 98)+  , ("nittini", 99)+  ]++ruleInteger4 :: Rule+ruleInteger4 = Rule+  { name = "integer (21..99)"+  , pattern =+    [ regex "(tjueen|tjueén|tjueto|tjuetre|tjuefire|tjuefem|tjueseks|tjuesju|tjuesyv|tjueåtte|tjueni\+            \|trettien|trettién|trettito|trettitre|trettifire|trettifem|trettiseks|trettisju|trettisyv|trettiåtte|trettini\+            \|førtien|førtién|førtito|førtitre|førtifire|førtifem|førtiseks|førtisju|førtisyv|førtiåtte|førtini\+            \|femtien|femtién|femtito|femtitre|femtifire|femtifem|femtiseks|femtisju|femtisyv|femtiåtte|femtini\+            \|sekstien|sekstién|sekstito|sekstitre|sekstifire|sekstifem|sekstiseks|sekstisju|sekstisyv|sekstiåtte|sekstini\+            \|syttien|syttién|syttito|syttitre|syttifire|syttifem|syttiseks|syttisju|syttisyv|syttiåtte|syttini\+            \|søttien|søttién|søttito|søttitre|søttifire|søttifem|søttiseks|søttisju|søttisyv|søttiåtte|søttini\+            \|åttien|åttién|åttito|åttitre|åttifire|åttifem|åttiseks|åttisju|åttisyv|åttiåtte|åttini\+            \|nittien|nittién|nittito|nittitre|nittifire|nittifem|nittiseks|nittisju|nittisyv|nittiåtte|nittini\+            \)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) twentyToHundredMap >>= integer+      _ -> Nothing+  }++ tensMap :: HashMap Text Integer tensMap = HashMap.fromList   [ ( "tyve" , 20 )@@ -256,7 +395,7 @@   , pattern =     [ regex "(tyve|tjue|tredve|tretti|førti|femti|seksti|sytti|søtti|åtti|nitti)"     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token RegexMatch (GroupMatch (match:_)):_) ->         HashMap.lookup (Text.toLower match) tensMap >>= integer       _ -> Nothing@@ -270,7 +409,7 @@     , regex "komma"     , Predicate $ not . hasGrain     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token Numeral nd1:_:Token Numeral nd2:_) ->         double $ TNumeral.value nd1 + decimalsToDouble (TNumeral.value nd2)       _ -> Nothing@@ -280,11 +419,12 @@ ruleIntegerWithThousandsSeparator = Rule   { name = "integer with thousands separator ."   , pattern =-    [ regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"+    [ regex "(\\d{1,3}((?:\\.| )\\d\\d\\d){1,5})"     ]-  , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):_) ->-        parseDouble (Text.replace "." Text.empty match) >>= double+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) -> parseDouble+        (Text.replace " " Text.empty $ Text.replace "." Text.empty $ match)+        >>= double       _ -> Nothing   } @@ -298,6 +438,7 @@   , ruleInteger   , ruleInteger2   , ruleInteger3+  , ruleInteger4   , ruleIntegerWithThousandsSeparator   , ruleIntersect   , ruleIntersectWithAnd
Duckling/Numeral/NE/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/NE/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Numeral/NL/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -77,6 +76,14 @@              [ "0,77"              , ",77"              ]+  , examples (NumeralValue 100000)+             [ "100.000"+             , "100.000,0"+             , "100000"+             , "100K"+             , "100k"+             , "honderd duizend"+             ]   , examples (NumeralValue 300)              [ "3 honderd"              , "drie honderd"@@ -84,6 +91,8 @@   , examples (NumeralValue 5000)              [ "5 duizend"              , "vijf duizend"+             , "5.000"+             , "5.000,00"              ]   , examples (NumeralValue 144)              [ "gros"@@ -95,6 +104,9 @@              ]   , examples (NumeralValue 20000)              [ "twintig duizend"+             , "20.000"+             , "20000"+             , "20.000,00"              ]   , examples (NumeralValue 0.2)              [ "1/5"
Duckling/Numeral/NL/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -63,7 +62,7 @@ ruleDecimalWithThousandsSeparator = Rule   { name = "decimal with thousands separator"   , pattern =-    [ regex "(\\d+(\\.\\d\\d\\d)+,\\d+)"+    [ regex "(\\d+(\\.\\d\\d\\d)+(,\\d+)?)"     ]   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (match:_)):@@ -148,7 +147,7 @@   { name = "numbers en"   , pattern =     [ numberBetween 1 10-    , regex "en"+    , regex "-?en-?"     , oneOf [20, 30 .. 90]     ]   , prod = \tokens -> case tokens of
Duckling/Numeral/PL/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -98,6 +97,22 @@   , examples (NumeralValue 5000)              [ "5 tysięcy"              , "pięć tysięcy"+             ]+  , examples (NumeralValue 79)+             [ "siedemdziesiąt dziewięć"+             , "siedemdziesięciu dziewięciu"+             ]+  , examples (NumeralValue 84)+             [ "osiemdziesiąt cztery"+             , "osiemdziesiat cztery"+             , "osiemdziesięciu czterem"+             , "osiemdziesieciu czterem"+             ]+  , examples (NumeralValue 92)+             [ "dziewięćdziesiąt dwa"+             , "dziewiecdziesiat dwa"+             , "dziewięćdziesięciu dwóm"+             , "dziewiecdziesieciu dwom"              ]   , examples (NumeralValue 122)              [ "sto dwadzieścia dwa"
Duckling/Numeral/PL/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -61,6 +60,33 @@   , prod = \_ -> integer 60   } +ruleSeventy :: Rule+ruleSeventy = Rule+  { name = "seventy"+  , pattern =+    [ regex "siedemdziesi((a|ą)t|(e|ę)ci(u|oma))"+    ]+  , prod = \_ -> integer 70+  }++ruleEighty :: Rule+ruleEighty = Rule+  { name = "eighty"+  , pattern =+    [ regex "osiemdziesi((a|ą)t|(e|ę)ci(u|oma))"+    ]+  , prod = \_ -> integer 80+  }++ruleNinety :: Rule+ruleNinety = Rule+  { name = "ninety"+  , pattern =+    [ regex "dziewi(e|ę)(c|ć)dziesi((a|ą)|(e|ę))(t|ci(u|oma))"+    ]+  , prod = \_ -> integer 90+  }+ ruleIntersectWithAnd :: Rule ruleIntersectWithAnd = Rule   { name = "intersect (with and)"@@ -553,6 +579,7 @@   , ruleDozen   , ruleEight   , ruleEighteen+  , ruleEighty   , ruleEleven   , ruleFifteen   , ruleFifty@@ -568,6 +595,7 @@   , ruleMultiply   , ruleNine   , ruleNineteen+  , ruleNinety   , ruleNumeral   , ruleNumeral2   , ruleNumeral3@@ -583,6 +611,7 @@   , ruleOne   , ruleSeven   , ruleSeventeen+  , ruleSeventy   , ruleSingle   , ruleSix   , ruleSixteen
Duckling/Numeral/PT/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/PT/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Numeral/RO/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -20,8 +19,11 @@ import Duckling.Resolve import Duckling.Testing.Types +context :: Context+context = testContext {locale = makeLocale RO Nothing}+ corpus :: Corpus-corpus = (testContext {locale = makeLocale RO Nothing}, testOptions, allExamples)+corpus = (context, testOptions, allExamples)  allExamples :: [Example] allExamples = concat@@ -164,6 +166,10 @@              [ "7 milioane"              , "sapte milioane"              , "șapte milioane"+             ]+  , examples (NumeralValue 21000000)+             [ "21 de milioane"+             , "douazeci si unu de milioane"              ]   , examples (NumeralValue 1000000000)              [ "un miliard"
Duckling/Numeral/RO/Rules.hs view
@@ -2,11 +2,11 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}  module Duckling.Numeral.RO.Rules@@ -23,7 +23,7 @@  import Duckling.Dimensions.Types import Duckling.Numeral.Helpers-import Duckling.Numeral.Types (NumeralData (..))+import Duckling.Numeral.Types (NumeralData(..)) import Duckling.Regex.Types import Duckling.Types import qualified Duckling.Numeral.Types as TNumeral@@ -35,7 +35,7 @@     [ regex "-|minus"     , Predicate isPositive     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))       _ -> Nothing   }@@ -46,7 +46,7 @@   , pattern =     [ regex "(\\d+(\\.\\d\\d\\d)+,\\d+)"     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token RegexMatch (GroupMatch (match:_)):        _) -> let fmt = Text.replace "," "." $ Text.replace "." Text.empty match         in parseDouble fmt >>= double@@ -59,9 +59,8 @@   , pattern =     [ regex "(\\d*,\\d+)"     ]-  , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):-       _) -> parseDecimal False match+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) -> parseDecimal False match       _ -> Nothing   } @@ -72,7 +71,7 @@     [ oneOf [20, 30 .. 90]     , numberBetween 1 10     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token Numeral NumeralData{TNumeral.value = v1}:        Token Numeral NumeralData{TNumeral.value = v2}:        _) -> double $ v1 + v2@@ -86,11 +85,24 @@     [ dimension Numeral     , Predicate isMultipliable     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (token1:token2:_) -> multiply token1 token2       _ -> Nothing   } +ruleMultiplyDe :: Rule+ruleMultiplyDe = Rule+  { name = "compose by multiplication"+  , pattern =+    [ numberWith TNumeral.value (>= 20)+    , regex "de"+    , Predicate isMultipliable+    ]+  , prod = \case+      (token1:_:token2:_) -> multiply token1 token2+      _ -> Nothing+  }+ ruleIntersect :: Rule ruleIntersect = Rule   { name = "intersect"@@ -98,7 +110,7 @@     [ Predicate hasGrain     , Predicate $ and . sequence [not . isMultipliable, isPositive]     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token Numeral NumeralData{TNumeral.value = val1, TNumeral.grain = Just g}:        Token Numeral NumeralData{TNumeral.value = val2}:        _) | (10 ** fromIntegral g) > val2 -> double $ val1 + val2@@ -110,10 +122,10 @@   { name = "intersect (cu și)"   , pattern =     [ Predicate hasGrain-    , regex "(s|ș)i"+    , regex "[sș]i"     , Predicate $ and . sequence [not . isMultipliable, isPositive]     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token Numeral NumeralData{TNumeral.value = val1, TNumeral.grain = Just g}:        _:        Token Numeral NumeralData{TNumeral.value = val2}:@@ -128,7 +140,7 @@     [ Predicate isPositive     , regex "neg(ativ)?"     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token Numeral NumeralData{TNumeral.value = v}:        _) -> double $ v * (-1)       _ -> Nothing@@ -140,7 +152,7 @@   , pattern =     [ regex "(sut(a|e|ă)?|milio(n|ane)?|miliar(de?)?|mi[ei]?)"     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of         "suta"      -> double 1e2 >>= withGrain 2 >>= withMultipliable         "sute"      -> double 1e2 >>= withGrain 2 >>= withMultipliable@@ -199,7 +211,7 @@   , pattern =     [ regex "(zero|nimic|nici(\\s?o|\\sun(a|ul?))|una|unul?|doi|dou(a|ă)|trei|patru|cinci|(s|ș)ase|(s|ș)apte|opt|nou(a|ă)|zec[ei]|(i|î)nt(a|â)i|un|o)"     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token RegexMatch (GroupMatch (match:_)):_) ->         HashMap.lookup (Text.toLower match) zeroTenMap >>= integer       _ -> Nothing@@ -231,7 +243,7 @@   , pattern =     [ regex "(cin|sapti|opti)(s|ș)pe|(cinci|(s|ș)apte|opt)sprezece|(un|doi|trei|pai|(s|ș)ai|nou(a|ă))((s|ș)pe|sprezece)"     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token RegexMatch (GroupMatch (e1:_:e2:_:r:_)):_) -> do         match <- case () of           _ | not $ Text.null e1 -> Just e1@@ -246,9 +258,9 @@ ruleInteger2 = Rule   { name = "integer (20..90)"   , pattern =-    [ regex "(dou(a|ă)|trei|patru|cinci|(s|ș)ai|(s|ș)apte|opt|nou(a|ă))\\s?zeci"+    [ regex "(dou[aă]|trei|patru|cinci|[sș]ai|[sș]apte|opt|nou[aă])\\s?zeci"     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token RegexMatch (GroupMatch (match:_)):_) -> do         unit <- HashMap.lookup (Text.toLower match) zeroTenMap         integer (unit * 10) >>= withGrain 2 >>= withMultipliable@@ -261,7 +273,7 @@   , pattern =     [ regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token RegexMatch (GroupMatch (match:_)):        _) -> let fmt = Text.replace "." Text.empty match         in parseDouble fmt >>= double@@ -280,6 +292,7 @@   , ruleIntersect   , ruleIntersectCuI   , ruleMultiply+  , ruleMultiplyDe   , ruleNumeralsPrefixWithOrMinus   , ruleNumeralsSuffixesWithNegativ   , rulePowersOfTen
Duckling/Numeral/RU/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -56,6 +55,7 @@   , examples (NumeralValue 33)              [ "33"              , "тридцать три"+             , "тридцати три"              , "0033"              ]   , examples (NumeralValue 11)@@ -84,11 +84,33 @@              ]   , examples (NumeralValue 444)              [ "четыреста сорок четыре"+             , "четыреста сорока четыре"              , "444"              ]   , examples (NumeralValue 525)              [ "пятьсот двадцать пять"+             , "пятьсот двадцати пять"              , "525"+             ]+  , examples (NumeralValue 555)+             [ "пятьсот пятьдесят пять"+             , "пятьсот пятидесяти пять"+             ]+  , examples (NumeralValue 565)+             [ "пятьсот шестьдесят пять"+             , "пятьсот шестидесяти пять"+             ]+  , examples (NumeralValue 575)+             [ "пятьсот семьдесят пять"+             , "пятьсот семидесяти пять"+             ]+  , examples (NumeralValue 585)+             [ "пятьсот восемьдесят пять"+             , "пятьсот восьмидесяти пять"+             ]+  , examples (NumeralValue 595)+             [ "пятьсот девяносто пять"+             , "пятьсот девяноста пять"              ]   , examples (NumeralValue 1.5)              [ "1.5"
Duckling/Numeral/RU/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -31,20 +30,32 @@ tensMap :: HashMap Text Integer tensMap = HashMap.fromList   [ ( "двадцать", 20)+  , ( "двадцати", 20)   , ( "тридцать", 30)+  , ( "тридцати", 30)   , ( "сорок", 40)+  , ( "сорока", 40)   , ( "пятьдесят", 50)+  , ( "пятидесяти", 50)   , ( "шестьдесят", 60)+  , ( "шестидесяти", 60)+  , ( "шестидесят", 60)   , ( "семьдесят", 70)+  , ( "семидесяти", 70)+  , ( "семидесят", 70)   , ( "восемьдесят", 80)+  , ( "восьмидесяти", 80)+  , ( "восьмидесят", 80)+  , ( "восемьдесяти", 80)   , ( "девяносто", 90)+  , ( "девяноста", 90)   ]  ruleInteger5 :: Rule ruleInteger5 = Rule   { name = "integer (20..90)"   , pattern =-    [ regex "(двадцать|тридцать|сорок|пятьдесят|шестьдесят|семьдесят|восемьдесят|девяносто)"+    [ regex "(двадцат(ь|и)|тридцат(ь|и)|сорока?|пят(ь|и)десяти?|шест(ь|и)десяти?|сем(ь|и)десяти?|вос(е|ь)м(ь|и)десяти?|девяност(о|а))"     ]   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (match:_)):_) ->@@ -79,7 +90,7 @@ ruleInteger3 = Rule   { name = "integer 2"   , pattern =-    [ regex "(два|две|двое|пара|пару|парочку|парочка)"+    [ regex "(дв(а|е|ух|ое)|пар(а|у|очк(у|а)))"     ]   , prod = \_ -> integer 2   }
Duckling/Numeral/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
+ Duckling/Numeral/SK/Corpus.hs view
@@ -0,0 +1,110 @@+-- 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.Numeral.SK.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus =+  ( testContext {locale = makeLocale SK Nothing}+  , testOptions+  , allExamples+  )++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "nula"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "jeden"+             , "jedna"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "dva"+             , "dve"+             ]+  , examples (NumeralValue 7)+             [ "7"+             , "sedem"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "štrnásť"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "šestnásť"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "sedemnásť"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "osemnásť"+             ]+  , examples (NumeralValue 20)+             [ "20"+             , "dvadsať"+             ]+  , examples (NumeralValue 1.1)+             [ "1,1"+             , "1,10"+             , "01,10"+             ]+  , examples (NumeralValue 0.77)+             [ "0,77"+             , ",77"+             ]+  , examples (NumeralValue 100000)+             [ "100.000"+             , "100000"+             , "100K"+             , "100k"+             ]+  , examples (NumeralValue 3000000)+             [ "3M"+             , "3000K"+             , "3000000"+             , "3.000.000"+             ]+  , examples (NumeralValue 1200000)+             [ "1.200.000"+             , "1200000"+             , "1,2M"+             , "1200K"+             , ",0012G"+             ]+  , examples (NumeralValue (-1200000))+             [ "- 1.200.000"+             , "-1200000"+             , "mínus 1.200.000"+             , "-1,2M"+             , "-1200K"+             , "-,0012G"+             ]+  , examples (NumeralValue 5000)+             [ "5 tisíc"+             , "päť tisíc"+             ]+  ]
+ Duckling/Numeral/SK/Rules.hs view
@@ -0,0 +1,309 @@+-- 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.Numeral.SK.Rules+  ( rules+  ) where++import Data.HashMap.Strict (HashMap)+import Data.Maybe+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.Numeral.Types (NumeralData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral++ruleIntersectWithAnd :: Rule+ruleIntersectWithAnd = Rule+  { name = "intersect (with and)"+  , pattern =+    [ Predicate hasGrain+    , regex "a"+    , Predicate $ and . sequence [not . isMultipliable, isPositive]+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = val1, TNumeral.grain = Just g}:+       _:+       Token Numeral NumeralData{TNumeral.value = val2}:+       _) | (10 ** fromIntegral g) > val2 -> double $ val1 + val2+      _ -> Nothing+  }++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|mínus|záporné"+    , Predicate isPositive+    ]+  , prod = \case+      (_:+       Token Numeral NumeralData{TNumeral.value = v}:+       _) -> double $ v * (-1)+      _ -> Nothing+  }++ruleFew :: Rule+ruleFew = Rule+  { name = "few"+  , pattern =+    [ regex "(zo)?pár"+    ]+  , prod = \_ -> integer 3+  }++ruleDecimalWithThousandsSeparator :: Rule+ruleDecimalWithThousandsSeparator = Rule+  { name = "decimal with thousands separator"+  , pattern =+    [ regex "(\\d+(\\.\\d\\d\\d)+\\,\\d+)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):+       _) -> let fmt = Text.replace "," "." $ Text.replace "." Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++ruleDecimalNumeral :: Rule+ruleDecimalNumeral = Rule+  { name = "decimal number"+  , pattern =+    [ regex "(\\d*,\\d+)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):+       _) -> parseDecimal False match+      _ -> Nothing+  }++ruleIntegerCompositeTens :: Rule+ruleIntegerCompositeTens = Rule+  { name = "integer 21..99"+  , pattern =+    [ oneOf [20, 30..90]+    , numberBetween 1 10+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = tens}:+       Token Numeral NumeralData{TNumeral.value = units}:+       _) -> double $ tens + units+      _ -> Nothing+  }++ruleSingle :: Rule+ruleSingle = Rule+  { name = "single"+  , pattern =+    [ regex "jed(en|no|na)"+    ]+  , prod = \_ -> integer 1 >>= withGrain 1+  }++ruleSum :: Rule+ruleSum = Rule+  { name = "intersect"+  , pattern =+    [ Predicate hasGrain+    , Predicate $ and . sequence [not . isMultipliable, isPositive]+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = val1, TNumeral.grain = Just g}:+       Token Numeral NumeralData{TNumeral.value = val2}:+       _) | (10 ** fromIntegral g) > val2 -> double $ val1 + val2+      _ -> Nothing+  }++ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ dimension Numeral+    , Predicate isMultipliable+    ]+  , prod = \case+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++ruleNumeralsSuffixesKMG :: Rule+ruleNumeralsSuffixesKMG = Rule+  { name = "numbers suffixes (K, M, G)"+  , pattern =+    [ dimension Numeral+    , regex "([kmg])(?=[\\W\\$€]|$)"+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = v}:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> case Text.toLower match of+         "k" -> double $ v * 1e3+         "m" -> double $ v * 1e6+         "g" -> double $ v * 1e9+         _   -> Nothing+      _ -> Nothing+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(sto(vky)?|tisíce?|milióny?)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "sto"     -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "stovky"  -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "tisíc"   -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "tisíce"  -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "milión"  -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "milióny" -> double 1e6 >>= withGrain 6 >>= withMultipliable+        _         -> Nothing+      _ -> Nothing+  }++ruleCouple :: Rule+ruleCouple = Rule+  { name = "couple, a pair"+  , pattern =+    [ regex "páry?"+    ]+  , prod = \_ -> integer 2+  }++ruleDozen :: Rule+ruleDozen = Rule+  { name = "dozen"+  , pattern =+    [ regex "tucet"+    ]+  , prod = \_ -> integer 12 >>= withGrain 1 >>= withMultipliable+  }++zeroToNineteenMap :: HashMap Text Integer+zeroToNineteenMap = HashMap.fromList+  [ ( "nula"    , 0 )+  , ( "jeden"   , 1 )+  , ( "jedna"   , 1 )+  , ( "jedno"   , 1 )+  , ( "dva"     , 2 )+  , ( "dve"     , 2 )+  , ( "tri"     , 3 )+  , ( "štyri"   , 4 )+  , ( "päť"     , 5 )+  , ( "šesť"    , 6 )+  , ( "sedem"   , 7 )+  , ( "osem"    , 8 )+  , ( "deväť"   , 9 )+  , ( "desať"   , 10 )+  , ( "jedenásť", 11 )+  , ( "dvanásť" , 12 )+  , ( "trinásť" , 13 )+  , ( "štrnásť" , 14 )+  , ( "pätnásť" , 15 )+  , ( "šestnásť", 16 )+  , ( "sedemnásť", 17 )+  , ( "osemnásť" , 18 )+  , ( "devätnásť", 19 )+  ]++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer (0..19)"+  -- e.g. jedenásť must be before jeden, otherwise jeden will always shadow jedenásť+  , pattern =+    [ regex "(nula|jed(enásť|en|na|no)|dv(anásť|a|e)|trinásť|tri|štrnásť|štyri|pätnásť|päť|šestnásť|šesť|sedemnásť|sedem|osemnásť|osem|devätnásť|deväť|desať)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) zeroToNineteenMap >>= integer+      _ -> Nothing+  }++dozenMap :: HashMap Text Integer+dozenMap = HashMap.fromList+  [ ( "dvadsať"        , 20)+  , ( "tridsať"        , 30)+  , ( "štyridsať"      , 40)+  , ( "päťdesiat"      , 50)+  , ( "šesťdesiat"     , 60)+  , ( "sedemdesiat"    , 70)+  , ( "osemdesiat"     , 80)+  , ( "devätdesiat"    , 90)+  ]++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "((dva|tri|štyri)dsať|(päť|šesť|sedem|osem|devät)desiat)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) dozenMap >>= integer+      _ -> Nothing+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number"+  , pattern =+    [ dimension Numeral+    , regex "celá|celých|celé"+    , Predicate $ not . hasGrain+    ]+  , prod = \case+      (Token Numeral nd1:_:Token Numeral nd2:_) ->+        double $ TNumeral.value nd1 + decimalsToDouble (TNumeral.value nd2)+      _ -> Nothing+  }++ruleIntegerWithThousandsSeparator :: Rule+ruleIntegerWithThousandsSeparator = Rule+  { name = "integer with thousands separator ."+  , pattern =+    [ regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):+       _) -> let fmt = Text.replace "." Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleCouple+  , ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleDozen+  , ruleFew+  , ruleInteger+  , ruleInteger2+  , ruleIntegerCompositeTens+  , ruleIntegerWithThousandsSeparator+  , ruleSum+  , ruleIntersectWithAnd+  , ruleMultiply+  , ruleNumeralDotNumeral+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  , rulePowersOfTen+  , ruleSingle+  ]
Duckling/Numeral/SV/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/SV/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
+ Duckling/Numeral/SW/Corpus.hs view
@@ -0,0 +1,86 @@+-- 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.Numeral.SW.Corpus+  ( corpus ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {locale = makeLocale SW Nothing}, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "sufuri"+             , "zero"+             ]+  , examples (NumeralValue 1)+             [ "moja"+             ]+  , examples (NumeralValue 2)+             [ "mbili"+             ]+  , examples (NumeralValue 3)+             [ "tatu"+             ]+  , examples (NumeralValue 4)+             [ "nne"+             ]+  , examples (NumeralValue 5)+             [ "tano"+             ]+  , examples (NumeralValue 6)+             [ "sita"+             ]+  , examples (NumeralValue 7)+             [ "saba"+             ]+  , examples (NumeralValue 8)+             [ "nane"+             ]+  , examples (NumeralValue 9)+             [ "tisa"+             ]+  , examples (NumeralValue 10)+             [ "kumi"+             ]+  , examples (NumeralValue 20)+             [ "ishirini"+             ]+  , examples (NumeralValue 30)+             [ "thelathini"+             ]+  , examples (NumeralValue 40)+             [ "arubaini"+             , "arobaini"+             ]+  , examples (NumeralValue 50)+             [ "hamsini"+             ]+  , examples (NumeralValue 60)+             [ "sitini"+             ]+  , examples (NumeralValue 70)+             [ "sabini"+             ]+  , examples (NumeralValue 80)+             [ "themanini"+             ]+  , examples (NumeralValue 90)+             [ "tisini"+             ]+  ]
+ Duckling/Numeral/SW/Rules.hs view
@@ -0,0 +1,104 @@+-- 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 #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Numeral.SW.Rules+  ( rules+  ) where++import Data.HashMap.Strict (HashMap)+import Data.Maybe+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.Numeral.Types (NumeralData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral++ruleNumeralMap :: HashMap Text Integer+ruleNumeralMap = HashMap.fromList+  [ ( "sufuri", 0 )+  , ( "zero", 0 )+  , ( "moja", 1 )+  , ( "mbili", 2 )+  , ( "tatu", 3 )+  , ( "nne", 4 )+  , ( "tano", 5)+  , ( "sita", 6)+  , ( "saba", 7)+  , ( "nane", 8)+  , ( "tisa", 9)+  , ( "kumi", 10)+  ]++ruleNumeral :: Rule+ruleNumeral = Rule+  { name = "number (0..10)"+  , pattern =+    [ regex "(sufuri|zero|moja|mbili|tatu|nne|tano|sita|saba|nane|tisa|kumi)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) ruleNumeralMap >>= integer+      _ -> Nothing+  }++tensMap :: HashMap Text Integer+tensMap = HashMap.fromList+  [ ( "ishirini", 20 )+  , ( "thelathini", 30 )+  , ( "arubaini", 40 )+  , ( "arobaini", 40 )+  , ( "hamsini", 50 )+  , ( "sitini", 60 )+  , ( "sabini", 70 )+  , ( "themanini", 80 )+  , ( "tisini", 90 )+  ]++ruleTens :: Rule+ruleTens = Rule+  { name = "integer (20,30..90)"+  , pattern =+    [ regex "(ishirini|thelathini|arubaini|arobaini|hamsini|sitini|sabini|themanini|tisini)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) tensMap >>= integer+      _ -> Nothing+  }+++ruleCompositeTens :: Rule+ruleCompositeTens = Rule+  { name = "integer 11..19 21..29 .. 91..99"+  , pattern = [oneOf [20,30..90]+  , regex "-?na-?"+  , numberBetween 1 10]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = v1}:+       Token Numeral NumeralData{TNumeral.value = v2}:+       _) -> double $ v1 + v2+      _ -> Nothing+  }+++rules :: [Rule]+rules =+  [ ruleNumeral+  , ruleTens+  , ruleCompositeTens+  ]
Duckling/Numeral/TA/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/TA/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
+ Duckling/Numeral/TE/Corpus.hs view
@@ -0,0 +1,123 @@+-- 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.Numeral.TE.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {locale = makeLocale TE Nothing}, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "సున్న"+             ]+  , examples (NumeralValue 1)+             [ "ఒకటి"+             ]+  , examples (NumeralValue 2)+             [ "రెండు"+             ]+  , examples (NumeralValue 3)+             [ "మూడు"+             ]+  , examples (NumeralValue 4)+             [ "నాలుగు"+             ]+  , examples (NumeralValue 5)+             [ "ఐదు"+             ]+  , examples (NumeralValue 6)+             [ "ఆరు"+             ]+  , examples (NumeralValue 7)+             [ "ఏడు"+             ]+  , examples (NumeralValue 8)+             [ "ఎనిమిది"+             ]+  , examples (NumeralValue 9)+             [ "తొమ్మిది"+             ]+  , examples (NumeralValue 10)+             [ "పది"+             ]+  , examples (NumeralValue 11)+             [ "పదకొండు"+             ]+  , examples (NumeralValue 12)+             [ "పన్నెండు"+             ]+  , examples (NumeralValue 13)+             [ "పదమూడు"+             ]+  , examples (NumeralValue 14)+             [ "పద్నాల్గు"+             ]+  , examples (NumeralValue 15)+             [ "పదిహేను"+             ]+  , examples (NumeralValue 16)+             [ "పదహారు"+             ]+  , examples (NumeralValue 17)+             [ "పదిహేడు"+             ]+  , examples (NumeralValue 18)+             [ "పద్దెనిమిది"+             ]+  , examples (NumeralValue 19)+             [ "పంతొమ్మిది"+             ]+  , examples (NumeralValue 20)+             [ "ఇరవై"+             ]+  , examples (NumeralValue 30)+             [ "ముప్పై"+             ]+   , examples (NumeralValue 40)+             [ "నలబై"+             ]+  , examples (NumeralValue 50)+             [ "యాబై"+             ]+  , examples (NumeralValue 60)+             [ "అరవై"+             ]+  , examples (NumeralValue 70)+             [ "డెబ్బై"+             ]+  , examples (NumeralValue 80)+             [ "ఎనబై"+             ]+  , examples (NumeralValue 90)+             [ "తొంబై"+             ]+  , examples (NumeralValue 100)+             [ "వంద"+             ]+  , examples (NumeralValue 1000)+             [ "వెయ్యి"+             ]+  , examples (NumeralValue 100000)+             [ "లక్ష"+             ]+  , examples (NumeralValue 10000000)+             [ "కోటి"+             ]+  ]
+ Duckling/Numeral/TE/Rules.hs view
@@ -0,0 +1,161 @@+-- 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 #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Numeral.TE.Rules+  ( rules+  ) where++import Data.HashMap.Strict (HashMap)+import Data.Maybe+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.Regex.Types+import Duckling.Types++teluguMap :: HashMap Char Char+teluguMap = HashMap.fromList+  [ ( '౦', '0' )+  , ( '౧', '1' )+  , ( '౨', '2' )+  , ( '౩', '3' )+  , ( '౪', '4' )+  , ( '౫', '5' )+  , ( '౬', '6' )+  , ( '౭', '7' )+  , ( '౮', '8' )+  , ( '౯', '9' )+  ]++teluguToArab :: Char -> Char+teluguToArab c = HashMap.lookupDefault c c teluguMap++ruleTelugu :: Rule+ruleTelugu = Rule+  { name = "telugu forms"+  , pattern =+    [ regex "([౦౧౨౩౪౫౬౭౮౯]{1,18})"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        toInteger <$> parseInt (Text.map teluguToArab match) >>= integer+      _ -> Nothing+  }++zeroToNineMap :: HashMap Text Integer+zeroToNineMap = HashMap.fromList+  [ ( "సున్న", 0 )+  , ( "ఒకటి", 1 )+  , ( "రెండు", 2 )+  , ( "మూడు", 3 )+  , ( "నాలుగు", 4 )+  , ( "ఐదు", 5 )+  , ( "ఆరు", 6 )+  , ( "ఏడు", 7 )+  , ( "ఎనిమిది", 8 )+  , ( "తొమ్మిది", 9 )+  ]++ruleZeroToNine :: Rule+ruleZeroToNine = Rule+  { name = "integer (0..9)"+  , pattern =+    [ regex "(సున్న|ఒకటి|రెండు|మూడు|నాలుగు|ఐదు|ఆరు|ఏడు|ఎనిమిది|తొమ్మిది)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) zeroToNineMap >>= integer+      _ -> Nothing+  }++tenToNineteenMap :: HashMap Text Integer+tenToNineteenMap = HashMap.fromList+  [ ( "పది", 10 )+  , ( "పదకొండు", 11 )+  , ( "పన్నెండు", 12 )+  , ( "పదమూడు", 13 )+  , ( "పద్నాల్గు", 14 )+  , ( "పదిహేను", 15 )+  , ( "పదహారు", 16 )+  , ( "పదిహేడు", 17 )+  , ( "పద్దెనిమిది", 18 )+  , ( "పంతొమ్మిది", 19 )+  ]++ruleTenToNineteen :: Rule+ruleTenToNineteen = Rule+  { name = "integer (10..19)"+  , pattern =+    [ regex "(పదకొండు|పన్నెండు|పదమూడు|పద్నాల్గు|పదిహేను|పదహారు|పదిహేడు|పద్దెనిమిది|పంతొమ్మిది|పది)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) tenToNineteenMap >>= integer+      _ -> Nothing+  }++tensMap :: HashMap Text Integer+tensMap = HashMap.fromList+  [ ( "ఇరవై", 20 )+  , ( "ముప్పై", 30 )+  , ( "నలబై", 40 )+  , ( "యాబై", 50 )+  , ( "అరవై", 60 )+  , ( "డెబ్బై", 70 )+  , ( "ఎనబై", 80 )+  , ( "తొంబై", 90 )+  ]++ruleTens :: Rule+ruleTens = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(ఇరవై|ముప్పై|నలబై|యాబై|అరవై|డెబ్బై|ఎనబై|తొంబై)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup match tensMap >>= integer+      _ -> Nothing+  }++hundredsMap :: HashMap Text Integer+hundredsMap = HashMap.fromList+  [ ( "వంద", 100 )+  , ( "వెయ్యి", 1000 )+  , ( "లక్ష", 100000 )+  , ( "కోటి", 10000000 )+  ]++rulehundreds :: Rule+rulehundreds = Rule+  { name = "integer (100,1000,100000,10000000)"+  , pattern =+    [ regex "(వంద|వెయ్యి|లక్ష|కోటి)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) hundredsMap >>= integer+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleTelugu+  , ruleZeroToNine+  , ruleTenToNineteen+  , ruleTens+  , rulehundreds+  ]
+ Duckling/Numeral/TH/Corpus.hs view
@@ -0,0 +1,153 @@+-- 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.Numeral.TH.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Locale+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {locale = makeLocale TH Nothing}, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [+    examples (NumeralValue 0)+             [ "0"+             , "ไม่มี"+             , "ศูนย์"+             ]+   ,examples (NumeralValue 1)+             [ "1"+             , "หนึ่ง"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "สอง"+             ]+  , examples (NumeralValue 3)+             [ "3"+             , "สาม"+             ]+  , examples (NumeralValue 10)+             [ "10"+             , "สิบ"+             ]+  , examples (NumeralValue 12)+             [ "12"+             , "สิบสอง"+             , "โหล"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "สิบสี่"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "สิบหก"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "สิบเจ็ด"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "สิบแปด"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "0033"+             ]+  , examples (NumeralValue 24)+             [ "24"+             , "สองโหล"+             ]+  , examples (NumeralValue 1.1)+             [ "1.1"+             , "1.10"+             , "01.10"+             , "1 จุด 1"+             , "หนึ่งจุดหนึ่ง"+             ]+  , examples (NumeralValue 0.77)+             [ ".77"+             , "0.77"+             , "จุด 77"+             ]+  , examples (NumeralValue 100000)+             [ "100,000"+             , "100,000.0"+             , "100000"+             , "หนึ่งแสน"+             ]+  , examples (NumeralValue 0.2)+             [ "1/5"+             , "2/10"+             , "3/15"+             , "20/100"+             , "ศูนย์จุดสอง"+             ]+  , examples (NumeralValue 3e6)+             [ "3000000"+             , "3,000,000"+             , "3 ล้าน"+             , "สามล้าน"+             ]+  , examples (NumeralValue 1.2e6)+             [ "1,200,000"+             , "1200000"+             , "1.2 ล้าน"+             , "หนึ่งจุดสองล้าน"+             ]+  , examples (NumeralValue 5000)+             [ "ห้าพัน"+             ]+  , examples (NumeralValue (-504))+             [ "-504"+             ]+  , examples (NumeralValue (-1.2e6))+             [ "- 1,200,000"+             , "-1200000"+             , "ลบ 1,200,000"+             ]+  , examples (NumeralValue 122)+             [ "หนึ่งร้อยยี่สิบสอง"+             ]+  , examples (NumeralValue 2e5)+             [ "สองแสน"+             ]+  , examples (NumeralValue 21011)+             [ "สองหมื่นหนึ่งพันสิบเอ็ด"+             , "สองหมื่นหนึ่งพันสิบหนึ่ง"+             ]+  , examples (NumeralValue 721012)+             [ "เจ็ดแสนสองหมื่นหนึ่งพันสิบสอง"+             ]+  , examples (NumeralValue 31256721)+             [ "สามสิบเอ็ดล้านสองแสนห้าหมื่นหกพันเจ็ดร้อยยี่สิบเอ็ด"+             , "สามสิบหนึ่งล้านสองแสนห้าหมื่นหกพันเจ็ดร้อยยี่สิบหนึ่ง"+             ]+  , examples (NumeralValue 2400)+             [ "สองร้อยโหล"+             , "200 โหล"+             ]+  , examples (NumeralValue 2200000)+             [ "สองจุดสองล้าน"+             , "สองล้านสองแสน"+             ]+  , examples (NumeralValue 3000000000)+             [ "สามพันล้าน"+             ]+  ]
+ Duckling/Numeral/TH/Rules.hs view
@@ -0,0 +1,460 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Numeral.TH.Rules+  ( rules+  ) where++import Control.Applicative ((<|>))+import Data.HashMap.Strict (HashMap)+import Data.Maybe+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.Numeral.Types (NumeralData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral++ruleDozen :: Rule+ruleDozen = Rule+  { name = "a dozen of"+  , pattern =+    [ regex "โหล?( ของ)?"+    ]+  , prod = \_ -> integer 12 >>= withMultipliable >>= notOkForAnyTime+  }++zeroNineteenMap :: HashMap Text Integer+zeroNineteenMap = HashMap.fromList+  [ ( "ไม่มี", 0 )+  , ( "ศูนย์", 0 )+  , ( "หนึ่ง", 1 )+  , ( "เอ็ด", 1 )+  , ( "สอง", 2 )+  , ( "สาม", 3 )+  , ( "สี่", 4 )+  , ( "ห้า", 5 )+  , ( "หก", 6 )+  , ( "เจ็ด", 7 )+  , ( "แปด", 8 )+  , ( "เก้า", 9 )+  , ( "สิบ", 10 )+  , ( "สิบเอ็ด", 11 )+  , ( "สิบหนึ่ง", 11 )+  , ( "สิบสอง", 12 )+  , ( "สิบสาม", 13 )+  , ( "สิบสี่", 14 )+  , ( "สิบห้า", 15 )+  , ( "สิบหก", 16 )+  , ( "สิบเจ็ด", 17 )+  , ( "สิบแปด", 18 )+  , ( "สิบเก้า", 19 )+  ]++informalMap :: HashMap Text Integer+informalMap = HashMap.fromList+  [ ( "อันนึง", 1 )+  , ( "คู่นึง", 2 )+  , ( "คู่ของ", 2 )+  ]++ruleToNineteen :: Rule+ruleToNineteen = Rule+  { name = "integer (0..19)"+  -- e.g. fourteen must be before four, otherwise four will always shadow fourteen+  , pattern =+    [ regex "(ไม่มี|ศูนย์|สิบหนึ่ง|หนึ่ง|(คู่)s?( ของ)?|(คู่)s?( นึง)?|สิบเอ็ด|เอ็ด|สิบสอง|สิบสาม|สิบสี่|สิบห้า|สิบหก|สิบเจ็ด|สิบแปด|สิบเก้า|สอง|สาม|สี่|ห้า|หก|เจ็ด|แปด|เก้า|สิบ)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        let x = Text.toLower match in+        (HashMap.lookup x zeroNineteenMap >>= integer) <|>+        (HashMap.lookup x informalMap >>= integer >>= notOkForAnyTime)+      _ -> Nothing+  }++tensMap :: HashMap Text Integer+tensMap = HashMap.fromList+  [ ( "ยี่สิบ", 20 )+  , ( "สามสิบ", 30 )+  , ( "สี่สิบ", 40 )+  , ( "ห้าสิบ", 50 )+  , ( "หกสิบ", 60 )+  , ( "เจ็ดสิบ", 70 )+  , ( "แปดสิบ", 80 )+  , ( "เก้าสิบ", 90 )+  ]++ruleTens :: Rule+ruleTens = singleStringLookupRule tensMap "integer (20..90)" integer++digitsHundredTwentyToTwentyNineMap :: HashMap Text Integer+digitsHundredTwentyToTwentyNineMap = HashMap.fromList+  [ ( "ร้อยยี่สิบ", 120 )+  , ( "ร้อยยี่สิบเอ็ด", 121 )+  , ( "ร้อยยี่สิบหนึ่ง", 121 )+  , ( "ร้อยยี่สิบสอง", 122 )+  , ( "ร้อยยี่สิบสาม", 123 )+  , ( "ร้อยยี่สิบสี่", 124 )+  , ( "ร้อยยี่สิบห้า", 125 )+  , ( "ร้อยยี่สิบหก", 126 )+  , ( "ร้อยยี่สิบเจ็ด", 127 )+  , ( "ร้อยยี่สิบแปด", 128 )+  , ( "ร้อยยี่สิบเก้า", 129 )+  , ( "หนึ่งร้อยยี่สิบ", 120 )+  , ( "หนึ่งร้อยยี่สิบเอ็ด", 121 )+  , ( "หนึ่งร้อยยี่สิบหนึ่ง", 121 )+  , ( "หนึ่งร้อยยี่สิบสอง", 122 )+  , ( "หนึ่งร้อยยี่สิบสาม", 123 )+  , ( "หนึ่งร้อยยี่สิบสี่", 124 )+  , ( "หนึ่งร้อยยี่สิบห้า", 125 )+  , ( "หนึ่งร้อยยี่สิบหก", 126 )+  , ( "หนึ่งร้อยยี่สิบเจ็ด", 127 )+  , ( "หนึ่งร้อยยี่สิบแปด", 128 )+  , ( "หนึ่งร้อยยี่สิบเก้า", 129 )+  , ( "สองร้อยยี่สิบ", 220 )+  , ( "สองร้อยยี่สิบเอ็ด", 221 )+  , ( "สองร้อยยี่สิบหนึ่ง", 221 )+  , ( "สองร้อยยี่สิบสอง", 222 )+  , ( "สองร้อยยี่สิบสาม", 223 )+  , ( "สองร้อยยี่สิบสี่", 224 )+  , ( "สองร้อยยี่สิบห้า", 225 )+  , ( "สองร้อยยี่สิบหก", 226 )+  , ( "สองร้อยยี่สิบเจ็ด", 227 )+  , ( "สองร้อยยี่สิบแปด", 228 )+  , ( "สองร้อยยี่สิบเก้า", 229 )+  , ( "สามร้อยยี่สิบ", 320 )+  , ( "สามร้อยยี่สิบเอ็ด", 321 )+  , ( "สามร้อยยี่สิบหนึ่ง", 321 )+  , ( "สามร้อยยี่สิบสอง", 322 )+  , ( "สามร้อยยี่สิบสาม", 323 )+  , ( "สามร้อยยี่สิบสี่", 324 )+  , ( "สามร้อยยี่สิบห้า", 325 )+  , ( "สามร้อยยี่สิบหก", 326 )+  , ( "สามร้อยยี่สิบเจ็ด", 327 )+  , ( "สามร้อยยี่สิบแปด", 328 )+  , ( "สามร้อยยี่สิบเก้า", 329 )+  , ( "สี่ร้อยยี่สิบ", 420 )+  , ( "สี่ร้อยยี่สิบเอ็ด", 421 )+  , ( "สี่ร้อยยี่สิบหนึ่ง", 421 )+  , ( "สี่ร้อยยี่สิบสอง", 422 )+  , ( "สี่ร้อยยี่สิบสาม", 423 )+  , ( "สี่ร้อยยี่สิบสี่", 424 )+  , ( "สี่ร้อยยี่สิบห้า", 425 )+  , ( "สี่ร้อยยี่สิบหก", 426 )+  , ( "สี่ร้อยยี่สิบเจ็ด", 427 )+  , ( "สี่ร้อยยี่สิบแปด", 428 )+  , ( "สี่ร้อยยี่สิบเก้า", 429 )+  , ( "ห้าร้อยยี่สิบ", 520 )+  , ( "ห้าร้อยยี่สิบเอ็ด", 521 )+  , ( "ห้าร้อยยี่สิบหนึ่ง", 521 )+  , ( "ห้าร้อยยี่สิบสอง", 522 )+  , ( "ห้าร้อยยี่สิบสาม", 523 )+  , ( "ห้าร้อยยี่สิบสี่", 524 )+  , ( "ห้าร้อยยี่สิบห้า", 525 )+  , ( "ห้าร้อยยี่สิบหก", 526 )+  , ( "ห้าร้อยยี่สิบเจ็ด", 527 )+  , ( "ห้าร้อยยี่สิบแปด", 528 )+  , ( "ห้าร้อยยี่สิบเก้า", 529 )+  , ( "หกร้อยยี่สิบ", 620 )+  , ( "หกร้อยยี่สิบเอ็ด", 621 )+  , ( "หกร้อยยี่สิบหนึ่ง", 621 )+  , ( "หกร้อยยี่สิบสอง", 622 )+  , ( "หกร้อยยี่สิบสาม", 623 )+  , ( "หกร้อยยี่สิบสี่", 624 )+  , ( "หกร้อยยี่สิบห้า", 625 )+  , ( "หกร้อยยี่สิบหก", 626 )+  , ( "หกร้อยยี่สิบเจ็ด", 627 )+  , ( "หกร้อยยี่สิบแปด", 628 )+  , ( "หกร้อยยี่สิบเก้า", 629 )+  , ( "เจ็ดร้อยยี่สิบ", 720 )+  , ( "เจ็ดร้อยยี่สิบเอ็ด", 721 )+  , ( "เจ็ดร้อยยี่สิบหนึ่ง", 721 )+  , ( "เจ็ดร้อยยี่สิบสอง", 722 )+  , ( "เจ็ดร้อยยี่สิบสาม", 723 )+  , ( "เจ็ดร้อยยี่สิบสี่", 724 )+  , ( "เจ็ดร้อยยี่สิบห้า", 725 )+  , ( "เจ็ดร้อยยี่สิบหก", 726 )+  , ( "เจ็ดร้อยยี่สิบเจ็ด", 727 )+  , ( "เจ็ดร้อยยี่สิบแปด", 728 )+  , ( "เจ็ดร้อยยี่สิบเก้า", 729 )+  , ( "แปดร้อยยี่สิบ", 820 )+  , ( "แปดร้อยยี่สิบเอ็ด", 821 )+  , ( "แปดร้อยยี่สิบหนึ่ง", 821 )+  , ( "แปดร้อยยี่สิบสอง", 822 )+  , ( "แปดร้อยยี่สิบสาม", 823 )+  , ( "แปดร้อยยี่สิบสี่", 824 )+  , ( "แปดร้อยยี่สิบห้า", 825 )+  , ( "แปดร้อยยี่สิบหก", 826 )+  , ( "แปดร้อยยี่สิบเจ็ด", 827 )+  , ( "แปดร้อยยี่สิบแปด", 828 )+  , ( "แปดร้อยยี่สิบเก้า", 829 )+  , ( "เก้าร้อยยี่สิบ", 920 )+  , ( "เก้าร้อยยี่สิบเอ็ด", 921 )+  , ( "เก้าร้อยยี่สิบหนึ่ง", 921 )+  , ( "เก้าร้อยยี่สิบสอง", 922 )+  , ( "เก้าร้อยยี่สิบสาม", 923 )+  , ( "เก้าร้อยยี่สิบสี่", 924 )+  , ( "เก้าร้อยยี่สิบห้า", 925 )+  , ( "เก้าร้อยยี่สิบหก", 926 )+  , ( "เก้าร้อยยี่สิบเจ็ด", 927 )+  , ( "เก้าร้อยยี่สิบแปด", 928 )+  , ( "เก้าร้อยยี่สิบเก้า", 929 )+  ]++ruleXHundredTwentyToXHundredTwentyNine :: Rule+ruleXHundredTwentyToXHundredTwentyNine = singleStringLookupRule+  digitsHundredTwentyToTwentyNineMap "integer (x20,x21,...,x29)" integer++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern = [regex "(ร้อย|พัน|หมื่น|แสน|ล้าน|สิบล้าน|ร้อยล้าน|พันล้าน)"]+  , prod = \case+      (Token RegexMatch (GroupMatch (match : _)) : _) ->+        case Text.toLower match of+          "ร้อย" -> double 1e2 >>= withGrain 2 >>= withMultipliable+          "พัน" -> double 1e3 >>= withGrain 3 >>= withMultipliable+          "หมื่น" -> double 1e4 >>= withGrain 4 >>= withMultipliable+          "แสน" -> double 1e5 >>= withGrain 5 >>= withMultipliable+          "ล้าน" -> double 1e6 >>= withGrain 6 >>= withMultipliable+          "สิบล้าน" -> double 1e7 >>= withGrain 7 >>= withMultipliable+          "ร้อยล้าน" -> double 1e8 >>= withGrain 8 >>= withMultipliable+          "พันล้าน" -> double 1e9 >>= withGrain 9 >>= withMultipliable+          _ -> Nothing+      _ -> Nothing+  }++ruleCompositeTens :: Rule+ruleCompositeTens = Rule+  { name = "integer 21..99"+  , pattern =+    [ oneOf [20,30..90]+    , regex "[\\s\\-]+"+    , numberBetween 1 10+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = tens}:+       _:+       Token Numeral NumeralData{TNumeral.value = units}:+       _) -> double $ tens + units+      _ -> Nothing+  }++ruleSumTenDigits :: Rule+ruleSumTenDigits = Rule+  { name = "สามสิบสี่"+  , pattern =+    [ regex "(ยี่สิบ|สามสิบ|สี่สิบ|ห้าสิบ|หกสิบ|เจ็ดสิบ|แปดสิบ|เก้าสิบ)"+    , regex "(หนึ่ง|เอ็ด|สอง|สาม|สี่|ห้า|หก|เจ็ด|แปด|เก้า|สิบ)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (m1:_)):+       Token RegexMatch (GroupMatch (m2:_)):+       _) -> do+       let x1 = Text.toLower m1+       let x2 = Text.toLower m2+       hundreds <- HashMap.lookup x1 tensMap+       rest <- HashMap.lookup x2 zeroNineteenMap+       integer (hundreds + rest)+      _ -> Nothing+  }++ruleSkipHundreds1 :: Rule+ruleSkipHundreds1 = Rule+  { name = "one eleven"+  , pattern =+    [ regex "(หนึ่ง|สอง|สาม|สี่|ห้า|หก|เจ็ด|แปด|เก้า)"+    , regex "(สิบ|สิบเอ็ด|สิบสอง|สิบสาม|สิบสี่|สิบห้า|สิบหก|สิบเจ็ด|สิบแปด|สิบเก้า|ยี่สิบ|สามสิบ|สี่สิบ|ห้าสิบ|หกสิบ|เจ็ดสิบ|แปดสิบ|เก้าสิบ)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (m1:_)):+       Token RegexMatch (GroupMatch (m2:_)):+       _) -> do+       let x1 = Text.toLower m1+       let x2 = Text.toLower m2+       hundreds <- HashMap.lookup x1 zeroNineteenMap+       rest <- HashMap.lookup x2 zeroNineteenMap <|> HashMap.lookup x2 tensMap+       integer (hundreds * 100 + rest)+      _ -> Nothing+  }++ruleSkipHundreds2 :: Rule+ruleSkipHundreds2 = Rule+  { name = "one twenty two"+  , pattern =+    [ regex "(หนึ่ง|สอง|สาม|สี่|ห้า|หก|เจ็ด|แปด|เก้า)"+    , regex "(ยี่สิบ|สามสิบ|สี่สิบ|ห้าสิบ|หกสิบ|เจ็ดสิบ|แปดสิบ|เก้าสิบ)"+    , regex "(หนึ่ง|สอง|สาม|สี่|ห้า|หก|เจ็ด|แปด|เก้า)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (m1:_)):+       Token RegexMatch (GroupMatch (m2:_)):+       Token RegexMatch (GroupMatch (m3:_)):+       _) -> do+       let x1 = Text.toLower m1+       let x2 = Text.toLower m2+       let x3 = Text.toLower m3+       hundreds <- HashMap.lookup x1 zeroNineteenMap+       tens <- HashMap.lookup x2 tensMap+       rest <- HashMap.lookup x3 zeroNineteenMap+       integer (hundreds * 100 + tens + rest)+      _ -> Nothing+  }++ruleDotSpelledOut :: Rule+ruleDotSpelledOut = Rule+  { name = "one point 2"+  , pattern =+    [ dimension Numeral+    , regex "จุด"+    , Predicate $ not . hasGrain+    ]+  , prod = \case+      (Token Numeral nd1:_:Token Numeral nd2:_) ->+        double $ TNumeral.value nd1 + decimalsToDouble (TNumeral.value nd2)+      _ -> Nothing+  }++ruleLeadingDotSpelledOut :: Rule+ruleLeadingDotSpelledOut = Rule+  { name = "point 77"+  , pattern =+    [ regex "จุด"+    , Predicate $ not . hasGrain+    ]+  , prod = \case+      (_:Token Numeral nd:_) -> double $ decimalsToDouble $ TNumeral.value nd+      _ -> Nothing+  }++ruleDecimals :: Rule+ruleDecimals = Rule+  { name = "decimal number"+  , pattern =+    [ regex "(\\d*\\.\\d+)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) -> parseDecimal True match+      _ -> Nothing+  }++ruleCommas :: Rule+ruleCommas = Rule+  { name = "comma-separated numbers"+  , pattern =+    [ regex "(\\d+(,\\d\\d\\d)+(\\.\\d+)?)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDouble (Text.replace "," Text.empty match) >>= double+      _ -> Nothing+  }++ruleSuffixes :: Rule+ruleSuffixes = Rule+  { name = "suffixes (กิโลกรัม,กรัม))"+  , pattern =+    [ dimension Numeral+    , regex "(กิโลกรัม|กรัม)(?=[\\W$€¢£]|$)"+    ]+  , prod = \case+      (Token Numeral nd : Token RegexMatch (GroupMatch (match : _)):_) -> do+        x <- case Text.toLower match of+          "กิโลกรัม" -> Just 1e3+          "กรัม" -> Just 1e1+          _ -> Nothing+        double $ TNumeral.value nd * x+      _ -> Nothing+  }++ruleNegative :: Rule+ruleNegative = Rule+  { name = "negative numbers"+  , pattern =+    [ regex "(-|ลบ)(?!\\s*-)"+    , Predicate isPositive+    ]+  , prod = \case+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleSum :: Rule+ruleSum = Rule+  { name = "intersect 2 numbers"+  , pattern =+    [ Predicate $ and . sequence [hasGrain, isPositive]+    , Predicate $ and . sequence [not . isMultipliable, isPositive]+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = val1, TNumeral.grain = Just g}:+       Token Numeral NumeralData{TNumeral.value = val2}:+       _) | (10 ** fromIntegral g) > val2 -> double $ val1 + val2+      _ -> Nothing+  }++ruleSumAnd :: Rule+ruleSumAnd = Rule+  { name = "intersect 2 numbers (with and)"+  , pattern =+    [ Predicate $ and . sequence [hasGrain, isPositive]+    , regex "และ"+    , Predicate $ and . sequence [not . isMultipliable, isPositive]+    ]+  , prod = \case+      (Token Numeral NumeralData{TNumeral.value = val1, TNumeral.grain = Just g}:+       _:+       Token Numeral NumeralData{TNumeral.value = val2}:+       _) | (10 ** fromIntegral g) > val2 -> double $ val1 + val2+      _ -> Nothing+  }++ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ dimension Numeral+    , Predicate isMultipliable+    ]+  , prod = \case+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleXHundredTwentyToXHundredTwentyNine+  , ruleSkipHundreds1+  , ruleSkipHundreds2+  , ruleToNineteen+  , ruleTens+  , rulePowersOfTen+  , ruleCompositeTens+  , ruleSumTenDigits+  , ruleDotSpelledOut+  , ruleLeadingDotSpelledOut+  , ruleDecimals+  , ruleCommas+  , ruleSuffixes+  , ruleNegative+  , ruleSum+  , ruleSumAnd+  , ruleMultiply+  , ruleDozen+  ]
Duckling/Numeral/TR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/TR/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -153,7 +152,7 @@ ruleNumeralSuffixesHalfsuffixText = Rule   { name = "number suffixes (half-suffix text) (1..9)"   , pattern =-    [ regex "((bir?|iki|üç|dört|beş|altı|yedi|sekiz|dokuz)(buçuk))"+    [ regex "((bir?|iki|üçü?|dört|beş|altı|yedi|sekiz|dokuz)(buçuk))"     ]   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (match:_)):_) ->@@ -515,7 +514,7 @@ ruleInteger9 = Rule   { name = "integer 11..19 21..29 31..39 41..49 51..59 61..69 71..79 81..89 91..99"   , pattern =-    [ regex "((on|yirmi|otuz|kırk|elli|atmış|altmış|yetmiş|seksen|doksan)(bir|bi|iki|üç|dört|beş|altı|yedi|sekiz|dokuz)(buçuk))"+    [ regex "((on|yirmi|otuz|kırk|elli|atmış|altmış|yetmiş|seksen|doksan)(bir|bi|iki|üçü?|dört|beş|altı|yedi|sekiz|dokuz)(buçuk))"     ]   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (match:_)):_) ->@@ -543,6 +542,7 @@   , ( "tek", 1)   , ( "iki", 2)   , ( "üç", 3)+  , ( "üçü", 3)   , ( "dört", 4)   , ( "beş", 5)   , ( "altı", 6)@@ -555,7 +555,7 @@ ruleInteger = Rule   { name = "integer (0..9)"   , pattern =-    [ regex "(yok|hi(ç)|s(ı)f(ı)r|bir?|[ty]ek|iki|(ü)(ç)|d(ö)rt|be(ş)|alt(ı)|yedi|sekiz|dokuz)"+    [ regex "(yok|hi(ç)|s(ı)f(ı)r|bir?|[ty]ek|iki|(ü)(ç)(ü)?|d(ö)rt|be(ş)|alt(ı)|yedi|sekiz|dokuz)"     ]   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (match:_)):_) ->
Duckling/Numeral/Types.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE DeriveAnyClass #-}
Duckling/Numeral/UK/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Numeral/UK/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Numeral/VI/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -58,7 +57,7 @@              ]   , examples (NumeralValue 100)             [ "100"-            , "tră"+            , "trăm"             ]   , examples (NumeralValue 1.1)              [ "1,1"@@ -96,15 +95,22 @@              , "-1200K"              , "-,0012G"              ]+  , examples (NumeralValue 20)+             [ "hai chục"+             , "hai mươi"+             ]   , examples (NumeralValue 5000)              [ "5 nghìn"              , "năm nghìn"+             , "năm ngàn"              ]   , examples (NumeralValue 200000)              [ "hai trăm nghìn"+             , "hai trăm ngàn"              ]   , examples (NumeralValue 1000000000)              [ "một tỷ"+             , "một tỉ"              ]   , examples (NumeralValue 21011)              [ "hai mươi mốt nghìn không trăm mười một"
Duckling/Numeral/VI/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -28,21 +27,20 @@  powersOfTenMap :: HashMap.HashMap Text.Text (Double, Int) powersOfTenMap = HashMap.fromList-  [ ( "tră",   (1e2, 2) )+  [ ( "chục",  (1e1, 1) )   , ( "trăm",  (1e2, 2) )-  , ( "nghì",  (1e3, 3) )   , ( "nghìn", (1e3, 3) )-  , ( "triệ",  (1e6, 6) )+  , ( "ngàn",  (1e3, 3) )   , ( "triệu", (1e6, 6) )-  , ( "t",     (1e9, 9) )   , ( "tỷ",    (1e9, 9) )+  , ( "tỉ",    (1e9, 9) )   ]  rulePowersOfTen :: Rule rulePowersOfTen = Rule   { name = "powers of tens"   , pattern =-    [ regex "(trăm?|nghìn?|triệu?|tỷ?)"+    [ regex "(chục|trăm|nghìn|ngàn|triệu|t(ỷ|ỉ))"     ]   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (match:_)):_) -> do
Duckling/Numeral/ZH/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -36,67 +35,97 @@              , "一"              , "一个"              , "1个"+             , "壹"              ]   , examples (NumeralValue 2)              [ "2"              , "二個"              , "二个"+             , "貳"+             , "一對"+             , "一雙"              ]   , examples (NumeralValue 10)              [ "10"              , "十"+             , "拾"+             , "五對"+             , "五雙"              ]   , examples (NumeralValue 11)              [ "11"              , "十一"+             , "拾壹"              ]   , examples (NumeralValue 20)              [ "20"              , "二十"+             , "貳拾"+             , "廿"              ]   , examples (NumeralValue 60)              [ "60"              , "六十"+             , "陸拾"+             , "五打"              ]   , examples (NumeralValue 33)              [ "33"              , "三十三"+             , "參拾參"+             , "卅三"              ]   , examples (NumeralValue 96)              [ "96"              , "九十六"+             , "玖拾陸"+             , "八打"              ]   , examples (NumeralValue 203)              [ "203"              , "二百零三"+             , "貳佰零參"              ]   , examples (NumeralValue 534)              [ "534"              , "五百三十四"+             , "伍佰參拾肆"+             , "五百卅四"              ]   , examples (NumeralValue 34567)              [ "34567"              , "34,567"              , "三万四千五百六十七"+             , "三萬四千五百六十七"+             , "參萬肆仟伍佰陸拾柒"              ]   , examples (NumeralValue 10040)              [ "10040"              , "10,040"              , "一万零四十"+             , "一萬零四十"+             , "壹萬零肆拾"+             , "一萬零卌"              ]   , examples (NumeralValue 1.1)              [ "1.1"              , "1.10"              , "01.10"+             , "一點一"+             , "十份十一"+             , "一又十分一"              ]   , examples (NumeralValue 0.77)              [ "0.77"              , ".77"+             , "零點77"              ]   , examples (NumeralValue 34507)              [ "34507"              , "34,507"              , "三万四千五百零七"+             , "三萬四千五百零七"+             , "參萬肆仟伍佰零柒"              ]   , examples (NumeralValue 100000)              [ "100,000"@@ -104,18 +133,24 @@              , "100K"              , "100k"              , "十万"+             , "十萬"+             , "拾萬"              ]   , examples (NumeralValue 3000000)              [ "3M"              , "3000000"              , "3,000,000"              , "三百万"+             , "三百萬"+             , "參佰萬"              ]   , examples (NumeralValue 1040000)              [ "1,040,000"              , "1040000"              , "1.04M"              , "一百零四万"+             , "一百零四萬"+             , "壹佰零肆萬"              ]   , examples (NumeralValue 1200000)              [ "1,200,000"@@ -123,6 +158,9 @@              , "1.2M"              , ".0012G"              , "一百二十万"+             , "一百二十萬"+             , "壹佰貳拾萬"+             , "百二萬"              ]   , examples (NumeralValue (-1200000))              [ "- 1,200,000"@@ -136,5 +174,25 @@              , "-1200K"              , "-.0012G"              , "负一百二十万"+             , "負一百二十萬"+             , "負壹佰貳拾萬"+             ]+    , examples (NumeralValue 0.5)+             [ "0.5"+             , "一半"+             , "一半半"+             , "1半"+             , "半个"+             , "半個"+             , "零點五"+             , "二分之一"+             , "二份一"+             ]+    , examples (NumeralValue 1100)+             [ "千一"+             , "一千一百"+             ]+    , examples (NumeralValue 19000)+             [ "萬九"              ]   ]
Duckling/Numeral/ZH/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -32,7 +31,7 @@ ruleInteger = Rule   { name = "integer (0..10)"   , pattern =-    [ regex "(〇|零|一|二|两|兩|三|四|五|六|七|八|九|十)"+    [ regex "(〇|零|一|二|两|兩|三|四|五|六|七|八|九|十|壹|貳|參|肆|伍|陸|柒|捌|玖|拾)"     ]   , prod = \case       (Token RegexMatch (GroupMatch (match:_)):_) ->@@ -45,20 +44,64 @@   [ ( "〇", 0 )   , ( "零", 0 )   , ( "一", 1 )+  , ( "壹", 1 )   , ( "兩", 2 )   , ( "两", 2 )   , ( "二", 2 )+  , ( "貳", 2 )   , ( "三", 3 )+  , ( "參", 3 )   , ( "四", 4 )+  , ( "肆", 4 )   , ( "五", 5 )+  , ( "伍", 5 )   , ( "六", 6 )+  , ( "陸", 6 )   , ( "七", 7 )+  , ( "柒", 7 )   , ( "八", 8 )+  , ( "捌", 8 )   , ( "九", 9 )+  , ( "玖", 9 )   , ( "十", 10 )+  , ( "拾", 10 )   ] +tensMap :: HashMap.HashMap Text Integer+tensMap = HashMap.fromList+  [ ( "廿" , 20 )+  , ( "卅" , 30 )+  , ( "卌" , 40 )+  ] +ruleTens :: Rule+ruleTens = Rule+  { name = "integer (20,30,40)"+  , pattern =+    [ regex "(廿|卅|卌)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) tensMap >>= integer+      _ -> Nothing+  }++ruleCompositeTens :: Rule+ruleCompositeTens = Rule+  { name = "integer 21..49"+  , pattern =+    [ oneOf [20,30,40]+    , regex "[\\s\\-]+"+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = tens}:+       _:+       Token Numeral NumeralData{TNumeral.value = units}:+       _) -> double $ tens + units+      _ -> Nothing+  }+ ruleNumeralsPrefixWithNegativeOrMinus :: Rule ruleNumeralsPrefixWithNegativeOrMinus = Rule   { name = "numbers prefix with -, negative or minus"@@ -94,6 +137,56 @@       _ -> Nothing   } +ruleDotSpelledOut :: Rule+ruleDotSpelledOut = Rule+  { name = "one point 2"+  , pattern =+    [ dimension Numeral+    , regex "點"+    , Predicate $ not . hasGrain+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral nd1:_:Token Numeral nd2:_) ->+        double $ TNumeral.value nd1 + decimalsToDouble (TNumeral.value nd2)+      _ -> Nothing+  }++ruleFraction :: Rule+ruleFraction = Rule+  { name = "fraction"+  , pattern =+    [ dimension Numeral+    , regex "分之|分|份"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = v1}:+       _:+       Token Numeral NumeralData{TNumeral.value = v2}:+       _) -> double $ v2 / v1+      _ -> Nothing+  }++ruleMixedFraction :: Rule+ruleMixedFraction = Rule+  { name = " mixed fraction"+  , pattern =+    [ dimension Numeral+    , regex "又"+    , dimension Numeral+    , regex "分之|分|份"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData{TNumeral.value = v1}:+       _:+       Token Numeral NumeralData{TNumeral.value = v2}:+       _:+       Token Numeral NumeralData{TNumeral.value = v3}:+       _) -> double $ v3 / v2 + v1+      _ -> Nothing+  }+ ruleNumeral :: Rule ruleNumeral = Rule   { name = "<number>个/個"@@ -106,16 +199,45 @@       _ -> Nothing   } +ruleHalf :: Rule+ruleHalf = Rule+  { name = "half"+  , pattern =+    [ regex "(1|一)?半(半|个|個)?"+    ]+  , prod = \case+      (_:_) -> double 0.5 >>= withMultipliable+      _ -> Nothing+  }++ruleDozen :: Rule+ruleDozen = Rule+  { name = "a dozen of"+  , pattern =+    [ regex "打"+    ]+  , prod = \_ -> integer 12 >>= withMultipliable >>= notOkForAnyTime+  }++rulePair :: Rule+rulePair = Rule+  { name = "a pair"+  , pattern =+    [ regex "雙|對"+    ]+  , prod = \_ -> integer 2 >>= withMultipliable >>= notOkForAnyTime+  }+ numeralSuffixList :: [(Text, Maybe Token)] numeralSuffixList =   [ ("K", double 1e3 >>= withGrain 3 >>= withMultipliable)   , ("M", double 1e6 >>= withGrain 6 >>= withMultipliable)   , ("G", double 1e9 >>= withGrain 9 >>= withMultipliable)-  , ("十", double 1e1 >>= withGrain 1 >>= withMultipliable)-  , ("百", double 1e2 >>= withGrain 2 >>= withMultipliable)-  , ("千", double 1e3 >>= withGrain 3 >>= withMultipliable)-  , ("万", double 1e4 >>= withGrain 4 >>= withMultipliable)-  , ("亿", double 1e8 >>= withGrain 8 >>= withMultipliable)+  , ("十|拾", double 1e1 >>= withGrain 1 >>= withMultipliable)+  , ("百|佰", double 1e2 >>= withGrain 2 >>= withMultipliable)+  , ("千|仟", double 1e3 >>= withGrain 3 >>= withMultipliable)+  , ("万|萬", double 1e4 >>= withGrain 4 >>= withMultipliable)+  , ("亿|億", double 1e8 >>= withGrain 8 >>= withMultipliable)   ]  ruleNumeralSuffixes :: [Rule]@@ -197,6 +319,45 @@       | d == 1 = Just $ v1 + v2       | otherwise = Nothing +ruleHundredPrefix :: Rule+ruleHundredPrefix = Rule+  { name = "one hundred and <integer> (short form)"+  , pattern =+    [ regex "百|佰"+    , numberBetween 1 10+    ]+  , prod = \case+    (_:Token Numeral NumeralData{TNumeral.value = v}:_) ->+      double $ 100 + v*10+    _ -> Nothing+  }++ruleThousandPrefix :: Rule+ruleThousandPrefix = Rule+  { name = "one thousand and <integer> (short form)"+  , pattern =+    [ regex "千|仟"+    , numberBetween 1 10+    ]+  , prod = \case+    (_:Token Numeral NumeralData{TNumeral.value = v}:_) ->+      double $ 1000 + v*100+    _ -> Nothing+  }++ruleTenThousandPrefix :: Rule+ruleTenThousandPrefix = Rule+  { name = "ten thousand and <integer> (short form)"+  , pattern =+    [ regex "万|萬"+    , numberBetween 1 10+    ]+  , prod = \case+    (_:Token Numeral NumeralData{TNumeral.value = v}:_) ->+      double $ 10000 + v*1000+    _ -> Nothing+  }+ rules :: [Rule] rules =   [ ruleDecimalNumeral@@ -208,5 +369,16 @@   , ruleNumeralsIntersectNonconsectiveUnit   , ruleNumeralsPrefixWithNegativeOrMinus   , ruleMultiply+  , ruleTens+  , ruleCompositeTens+  , ruleHalf+  , ruleDotSpelledOut+  , ruleDozen+  , rulePair+  , ruleFraction+  , ruleMixedFraction+  , ruleHundredPrefix+  , ruleThousandPrefix+  , ruleTenThousandPrefix   ]   ++ ruleNumeralSuffixes
Duckling/Ordinal/AR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Ordinal/AR/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Ordinal/BG/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Ordinal/BG/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
+ Duckling/Ordinal/CA/Corpus.hs view
@@ -0,0 +1,126 @@+-- 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.Ordinal.CA.Corpus+  ( corpus ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {locale = makeLocale CA Nothing}, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 1)+             [ "primer"+             , "primera"+             , "primers"+             , "primeres"+             ]+   , examples (OrdinalData 2)+              [ "segon"+              , "segona"+              , "segons"+              , "segones"+              ]+   , examples (OrdinalData 3)+              [ "tercer"+              , "tercera"+              , "tercers"+              , "terceres"+              ]+   , examples (OrdinalData 4)+              [ "quart"+              , "quarta"+              , "quarts"+              , "quartes"+              ]+   , examples (OrdinalData 5)+              [ "cinquè"+              , "cinquena"+              , "cinquens"+              , "cinquenes"+              ]+   , examples (OrdinalData 6)+              [ "sisè"+              , "sisena"+              , "sisens"+              , "sisenes"+              ]+   , examples (OrdinalData 7)+              [ "setè"+              , "setena"+              , "setens"+              , "setenes"+              ]+   , examples (OrdinalData 8)+              [ "vuitè"+              , "vuitena"+              , "vuitens"+              , "vuitenes"+              ]+   , examples (OrdinalData 9)+              [ "novè"+              , "novena"+              , "novens"+              , "novenes"+              ]+   , examples (OrdinalData 10)+              [ "desè"+              , "desena"+              , "desens"+              , "desenes"+              ]+    , examples (OrdinalData 11)+              [ "onzè"+              , "onzena"+              ]+    , examples (OrdinalData 12)+              [ "dotzè"+              , "dotzena"+              ]+    , examples (OrdinalData 13)+              [ "tretzè"+              , "tretzena"+              ]+    , examples (OrdinalData 14)+              [ "catorzè"+              , "catorzena"+              ]+    , examples (OrdinalData 15)+              [ "quinzè"+              , "quinzena"+              ]+    , examples (OrdinalData 16)+              [ "setzè"+              , "setzena"+              ]+    , examples (OrdinalData 17)+              [ "dissetè"+              , "dissetena"+              ]+    , examples (OrdinalData 18)+              [ "divuitè"+              , "divuitena"+              ]+    , examples (OrdinalData 19)+              [ "dinovè"+              , "dinovena"+              ]+    , examples (OrdinalData 20)+              [ "vintè"+              , "vintena"+              ]+  ]
+ Duckling/Ordinal/CA/Rules.hs view
@@ -0,0 +1,104 @@+-- 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 #-}+{-# LANGUAGE LambdaCase #-}++module Duckling.Ordinal.CA.Rules+  ( rules ) where++import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Ordinal.Helpers+import Duckling.Regex.Types+import Duckling.Types++ordinalsMap :: HashMap.HashMap Text.Text Int+ordinalsMap = HashMap.fromList+  [ ( "primer" , 1 )+  , ( "primers" , 1 )+  , ( "primera" , 1 )+  , ( "primeres" , 1 )+  , ( "segon" , 2 )+  , ( "segona" , 2 )+  , ( "segones" , 2 )+  , ( "segons" , 2 )+  , ( "tercer" , 3 )+  , ( "tercera" , 3 )+  , ( "tercers" , 3 )+  , ( "terceres" , 3 )+  , ( "quart" , 4 )+  , ( "quarta" , 4 )+  , ( "quarts" , 4 )+  , ( "quartes" , 4 )+  , ( "cinquè" , 5 )+  , ( "cinquena" , 5 )+  , ( "cinquens" , 5 )+  , ( "cinquenes" , 5 )+  , ( "sisè" , 6 )+  , ( "sisena" , 6 )+  , ( "sisens" , 6 )+  , ( "sisenes" , 6 )+  , ( "setè" , 7 )+  , ( "setena" , 7 )+  , ( "setens" , 7 )+  , ( "setenes" , 7 )+  , ( "vuitè" , 8 )+  , ( "vuitena" , 8 )+  , ( "vuitens" , 8 )+  , ( "vuitenes" , 8 )+  , ( "novè" , 9 )+  , ( "novena" , 9 )+  , ( "novens" , 9 )+  , ( "novenes" , 9 )+  , ( "desè" , 10 )+  , ( "desena" , 10 )+  , ( "desens" , 10 )+  , ( "desenes" , 10 )+  , ( "onzè" , 11 )+  , ( "onzena" , 11 )+  , ( "dotzè" , 12 )+  , ( "dotzena" , 12 )+  , ( "tretzè" , 13 )+  , ( "tretzena" , 13 )+  , ( "catorzè" , 14 )+  , ( "catorzena" , 14 )+  , ( "quinzè" , 15 )+  , ( "quinzena" , 15 )+  , ( "setzè" , 16 )+  , ( "setzena" , 16 )+  , ( "dissetè" , 17 )+  , ( "dissetena" , 17 )+  , ( "divuitè" , 18 )+  , ( "divuitena" , 18 )+  , ( "dinovè" , 19 )+  , ( "dinovena" , 19 )+  , ( "vintè" , 20 )+  , ( "vintena" , 20 )+  ]++ruleOrdinalsPrimero :: Rule+ruleOrdinalsPrimero = Rule+  { name = "ordinals (primero..10)"+  , pattern =+    [ regex "(primer(a|s|es)?|segon(a|s|es)?|tercer(a|s|es)?|quart(a|s|es)?|cinqu(è|(en(a|s|es)))|sis(è|en(a|s|es))|set(è|en(a|s|es))|vuit(è|en(a|s|es))|nov(è|en(a|s|es))|des(è|en(a|s|es))|onz(è|ena)|dotz(è|ena)|tretz(è|ena)|catorz(è|ena)|quinz(è|ena)|setz(è|ena)|disset(è|ena)|divuit(è|ena)|dinov(è|ena)|vint(è|ena))"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsMap+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalsPrimero+  ]
Duckling/Ordinal/DA/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -23,9 +22,24 @@ corpus = (testContext {locale = makeLocale DA Nothing}, testOptions, allExamples)  allExamples :: [Example]-allExamples =-  examples (OrdinalData 4)-           [ "4."-           , "fjerde"-           , "Fjerde"-           ]+allExamples = concat+  [ examples (OrdinalData 4)+             [ "4."+             , "fjerde"+             , "Fjerde"+             ]+  , examples (OrdinalData 41)+             [ "enogfyrrende"+             ]+  , examples (OrdinalData 78)+             [ "otteoghalvfjerdsindstyvende"+             ]+  , examples (OrdinalData 263)+             [ "to hundrede og treogtresindstyvende"+             , "tohundrede og treogtresindstyvende"+             ]+  , examples (OrdinalData 70)+             [ "halvfjerdsende"+             , "halvfjerdsindstyvende"+             ]+  ]
Duckling/Ordinal/DA/Rules.hs view
@@ -2,69 +2,151 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE NoRebindableSyntax #-}  module Duckling.Ordinal.DA.Rules   ( rules ) where -import qualified Data.Text as Text++import Data.HashMap.Strict (HashMap)+import Data.Text (Text) import Prelude-import Data.String+import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text  import Duckling.Dimensions.Types-import Duckling.Numeral.Helpers (parseInt)+import Duckling.Numeral.Helpers (parseInt, numberWith)+import Duckling.Numeral.Types (NumeralData (..), getIntValue) import Duckling.Ordinal.Helpers+import Duckling.Ordinal.Types (OrdinalData (..)) import Duckling.Regex.Types import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral +ordinalsMap :: HashMap Text Int+ordinalsMap = HashMap.fromList+  [ ( "første", 1 )+  , ( "anden", 2 )+  , ( "tredje", 3 )+  , ( "fjerde", 4 )+  , ( "femte", 5 )+  , ( "sjette", 6 )+  , ( "syvende", 7 )+  , ( "ottende", 8 )+  , ( "niende", 9 )+  , ( "tiende", 10 )+  , ( "elfte", 11 )+  , ( "tolvte", 12 )+  , ( "trettende", 13 )+  , ( "fjortende", 14 )+  , ( "femtende", 15 )+  , ( "sekstende", 16 )+  , ( "syttende", 17 )+  , ( "attende", 18 )+  , ( "nittende", 19 )+  , ( "tyvende", 20 )+  , ( "tenogtyvende", 21 )+  , ( "toogtyvende", 22 )+  , ( "treogtyvende", 23 )+  , ( "fireogtyvende", 24 )+  , ( "femogtyvende", 25 )+  , ( "seksogtyvende", 26 )+  , ( "syvogtyvende", 27 )+  , ( "otteogtyvende", 28 )+  , ( "niogtyvende", 29 )+  , ( "tredivte", 30 )+  , ( "enogtredivte", 31 )+  ]++cardinalsMap :: HashMap Text Int+cardinalsMap = HashMap.fromList+  [ ( "tyvende", 20 )+  , ( "tredivte", 30 )+  , ( "fyrrende", 40 )+  , ( "fyrretyvende", 40 )+  , ( "halvtredsende", 50 )+  , ( "halvtredsindstyvende", 50 )+  , ( "tressende", 60 )+  , ( "tresindstyvende", 60 )+  , ( "halvfjerdsende", 70 )+  , ( "halvfjerdsindstyvende", 70 )+  , ( "firsende", 80 )+  , ( "firsindsstyvende", 80 )+  , ( "halvfemsende", 90 )+  , ( "halvfemsindstyvende", 90 )+  ]++oneValMap :: HashMap Text Int+oneValMap = HashMap.fromList+  [ ( "", 0 )+  , ( "enog", 1 )+  , ( "toog", 2 )+  , ( "treog", 3 )+  , ( "fireog", 4 )+  , ( "femog", 5 )+  , ( "seksog", 6 )+  , ( "syvog", 7 )+  , ( "otteog", 8 )+  , ( "niog", 9 )+  ]+ ruleOrdinalsFirstst :: Rule ruleOrdinalsFirstst = Rule-  { name = "ordinals (first..31st)"+  { name = "ordinals (first..19st)"   , pattern =-    [ regex "(første|anden|tredje|fjerde|femte|sjette|syvende|ottende|niende|tiende|elfte|tolvte|trettende|fjortende|femtende|sekstende|syttende|attende|nittende|tyvende|tenogtyvende|toogtyvende|treogtyvende|fireogtyvende|femogtyvende|seksogtyvende|syvogtyvende|otteogtyvende|niogtyvende|tredivte|enogtredivte)"+    [ regex "(første|anden|tredje|fjerde|femte|sjette|syvende|ottende|niende|tiende|elfte|tolvte|trettende|fjortende|femtende|sekstende|syttende|attende|nittende)"     ]   , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of-        "første" -> Just $ ordinal 1-        "anden" -> Just $ ordinal 2-        "tredje" -> Just $ ordinal 3-        "fjerde" -> Just $ ordinal 4-        "femte" -> Just $ ordinal 5-        "sjette" -> Just $ ordinal 6-        "syvende" -> Just $ ordinal 7-        "ottende" -> Just $ ordinal 8-        "niende" -> Just $ ordinal 9-        "tiende" -> Just $ ordinal 10-        "elfte" -> Just $ ordinal 11-        "tolvte" -> Just $ ordinal 12-        "trettende" -> Just $ ordinal 13-        "fjortende" -> Just $ ordinal 14-        "femtende" -> Just $ ordinal 15-        "sekstende" -> Just $ ordinal 16-        "syttende" -> Just $ ordinal 17-        "attende" -> Just $ ordinal 18-        "nittende" -> Just $ ordinal 19-        "tyvende" -> Just $ ordinal 20-        "tenogtyvende" -> Just $ ordinal 21-        "toogtyvende" -> Just $ ordinal 22-        "treogtyvende" -> Just $ ordinal 23-        "fireogtyvende" -> Just $ ordinal 24-        "femogtyvende" -> Just $ ordinal 25-        "seksogtyvende" -> Just $ ordinal 26-        "syvogtyvende" -> Just $ ordinal 27-        "otteogtyvende" -> Just $ ordinal 28-        "niogtyvende" -> Just $ ordinal 29-        "tredivte" -> Just $ ordinal 30-        "enogtredivte" -> Just $ ordinal 31-        _ -> Nothing+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsMap       _ -> Nothing   } +ruleSpelledOutOrdinals :: Rule+ruleSpelledOutOrdinals = Rule+  { name = "ordinals, 20 to 99, spelled-out"+  , pattern =+    [ regex (concat ["((?:en|to|tre|fire|fem|seks|syv|otte|ni)og)?",+                     "(tyvende",+                     "|tredivte",+                     "|fyrr(?:etyv)?ende",+                     "|halvtreds(?:indstyv)?ende",+                     "|tres(?:indstyv|s)?ende",+                     "|halvfjerds(?:indstyv)?ende",+                     "|firs(?:indstyv)?ende",+                     "|halvfems(?:indstyv)?ende)"])+    ]+  , prod = \case+    (Token RegexMatch (GroupMatch (ones:tens:_)):_) -> do+      oneVal <- HashMap.lookup (Text.toLower ones) oneValMap+      tenVal <- HashMap.lookup (Text.toLower tens) cardinalsMap+      Just $ ordinal (oneVal + tenVal)+    _ -> Nothing++  }++ruleSpelledOutBigOrdinals :: Rule+ruleSpelledOutBigOrdinals = Rule+  { name = "ordinals, above 99, spelled out"+  , pattern =+    [ numberWith TNumeral.value (> 99)+    , regex "og"+    , dimension Ordinal+    ]+  , prod = \case+      Token Numeral NumeralData {TNumeral.value=maybenumnum}:_:Token Ordinal (OrdinalData ordnum):_ ->+            case getIntValue maybenumnum of+              Just numnum -> Just $ ordinal (numnum + ordnum)+              Nothing -> Nothing+      _ -> Nothing+  }+ ruleOrdinalDigits :: Rule ruleOrdinalDigits = Rule   { name = "ordinal (digits)"@@ -82,4 +164,6 @@ rules =   [ ruleOrdinalDigits   , ruleOrdinalsFirstst+  , ruleSpelledOutOrdinals+  , ruleSpelledOutBigOrdinals   ]
Duckling/Ordinal/DE/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Ordinal/DE/Rules.hs view
@@ -2,19 +2,24 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}  module Duckling.Ordinal.DE.Rules-  ( rules ) where+  ( rules+  ) where -import qualified Data.Text as Text+import Data.Semigroup ((<>)) import Prelude import Data.String+import Data.Text (Text)+import qualified Data.HashMap.Strict as HashMap+import qualified Data.List as List+import qualified Data.Text as Text  import Duckling.Dimensions.Types import Duckling.Numeral.Helpers (parseInt)@@ -22,64 +27,71 @@ import Duckling.Regex.Types import Duckling.Types +ordinalList :: [(Text, Int)]+ordinalList =+  [ ("erste", 1)+  , ("zweite", 2)+  , ("dritte", 3)+  , ("vierte", 4)+  , ("fünfte", 5)+  , ("sechste", 6)+  , ("siebte", 7)+  , ("achte", 8)+  , ("neunte", 9)+  , ("zehnte", 10)+  , ("elfte", 11)+  , ("zwölfte", 12)+  , ("dreizente", 13)+  , ("vierzehnte", 14)+  , ("fünfzehnte", 15)+  , ("sechzente", 16)+  , ("siebzehnte", 17)+  , ("achtzehnte", 18)+  , ("neunzehnte", 19)+  , ("zwanzigste", 20)+  , ("einundzwanzigste", 21)+  , ("zweiundzwanzigste", 22)+  , ("dreiundzwanzigste", 23)+  , ("vierundzwanzigste", 24)+  , ("fünfundzwanzigste", 25)+  , ("sechsundzwanzigste", 26)+  , ("siebenundzwanzigste", 27)+  , ("achtundzwanzigste", 28)+  , ("neunundzwanzigste", 29)+  , ("dreissigste", 30)+  , ("dreißigste", 30)+  , ("einunddreissigste", 31)+  , ("einunddreißigste", 31)+  ]+ ruleOrdinalsFirstth :: Rule ruleOrdinalsFirstth = Rule-  { name = "ordinals (first..19th)"+  { name = "ordinal (1..31)"   , pattern =-    [ regex "(erste(r|s)?|zweite(r|s)|dritte(r|s)|vierte(r|s)|fuenfte(r|s)|sechste(r|s)|siebte(r|s)|achte(r|s)|neunte(r|s)|zehnte(r|s)|elfter|zwölfter|dreizenter|vierzehnter|fünfzehnter|sechzenter|siebzehnter|achtzehnter|neunzehnter)"+    [ regex $ Text.unpack construction     ]-  , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of-        "erstes" -> Just $ ordinal 1-        "erster" -> Just $ ordinal 1-        "erste" -> Just $ ordinal 1-        "zweiter" -> Just $ ordinal 2-        "zweite" -> Just $ ordinal 2-        "zweites" -> Just $ ordinal 2-        "drittes" -> Just $ ordinal 3-        "dritte" -> Just $ ordinal 3-        "dritter" -> Just $ ordinal 3-        "viertes" -> Just $ ordinal 4-        "vierte" -> Just $ ordinal 4-        "vierter" -> Just $ ordinal 4-        "fünftes" -> Just $ ordinal 5-        "fünfter" -> Just $ ordinal 5-        "fünfte" -> Just $ ordinal 5-        "sechste" -> Just $ ordinal 6-        "sechstes" -> Just $ ordinal 6-        "sechster" -> Just $ ordinal 6-        "siebtes" -> Just $ ordinal 7-        "siebte" -> Just $ ordinal 7-        "siebter" -> Just $ ordinal 7-        "achtes" -> Just $ ordinal 8-        "achte" -> Just $ ordinal 8-        "achter" -> Just $ ordinal 8-        "neuntes" -> Just $ ordinal 9-        "neunter" -> Just $ ordinal 9-        "neunte" -> Just $ ordinal 9-        "zehnte" -> Just $ ordinal 10-        "zehnter" -> Just $ ordinal 10-        "zehntes" -> Just $ ordinal 10-        "elfter" -> Just $ ordinal 11-        "zwölfter" -> Just $ ordinal 12-        "dreizehnter" -> Just $ ordinal 13-        "vierzehnter" -> Just $ ordinal 14-        "fünfzehnter" -> Just $ ordinal 15-        "sechzehnter" -> Just $ ordinal 16-        "siebzehnter" -> Just $ ordinal 17-        "achtzehnter" -> Just $ ordinal 18-        "neunzehnter" -> Just $ ordinal 19-        _ -> Nothing+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        ordinal <$> HashMap.lookup (Text.toLower match) ordinalMap       _ -> Nothing   }+  where+    ordinalMap :: HashMap.HashMap Text Int+    ordinalMap = HashMap.fromList ordinalList +    construction :: Text+    construction =+      "("+      <> mconcat (List.intersperse "|" (fst <$> ordinalList))+      <> ")[rsn]?"+ ruleOrdinalDigits :: Rule ruleOrdinalDigits = Rule   { name = "ordinal (digits)"   , pattern =     [ regex "(?<!\\d|\\.)0*(\\d+)(\\.(?!\\d)| ?(te(n|r|s)?)|(ste(n|r|s)?))"     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token RegexMatch (GroupMatch (match:_)):_) -> do         v <- parseInt match         Just $ ordinal v@@ -88,6 +100,6 @@  rules :: [Rule] rules =-  [ ruleOrdinalDigits-  , ruleOrdinalsFirstth+  [ ruleOrdinalsFirstth+  , ruleOrdinalDigits   ]
Duckling/Ordinal/EL/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Ordinal/EL/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Ordinal/EN/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Ordinal/EN/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Ordinal/ES/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}@@ -33,6 +32,11 @@              [ "segundo"              , "segunda"              , "segundos"+             ]+  , examples (OrdinalData 3)+             [ "tercero"+             , "tercera"+             , "terceros"              ]   , examples (OrdinalData 10)              [ "decimo"
Duckling/Ordinal/ES/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -80,7 +79,7 @@ ruleOrdinalsPrimero = Rule   { name = "ordinals (primero..10)"   , pattern =-    [ regex "((primer|segund|cuart|quint|sext|s[eé]ptim|octav|noven|d[eé]cim)(os?|as?)|(prim|terc)er)"+    [ regex "((primer|segund|tercer|cuart|quint|sext|s[eé]ptim|octav|noven|d[eé]cim)(os?|as?)|(prim|terc)er)"     ]   , prod = \tokens -> case tokens of       (Token RegexMatch (GroupMatch (match:_)):_) ->
Duckling/Ordinal/ET/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Ordinal/ET/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Ordinal/FR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Ordinal/FR/Rules.hs view
@@ -2,66 +2,67 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}  module Duckling.Ordinal.FR.Rules-  ( rules ) where+  ( rules+  ) where  import Data.HashMap.Strict ( HashMap)-import qualified Data.HashMap.Strict as HashMap+import Data.String import Data.Text (Text)-import qualified Data.Text as Text import Prelude-import Data.String+import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text as Text  import Duckling.Dimensions.Types import Duckling.Numeral.Helpers (parseInt) import Duckling.Ordinal.Helpers-import Duckling.Regex.Types+import Duckling.Regex.Types (GroupMatch (..)) import Duckling.Types -ruleOrdinalsPremierseiziemeMap :: HashMap Text Int-ruleOrdinalsPremierseiziemeMap = HashMap.fromList-  [ ( "première"   , 1 )-  , ( "premiere"        , 1 )-  , ( "premier"         , 1 )-  , ( "deuxième"   , 2 )-  , ( "deuxieme"        , 2 )-  , ( "second"          , 2 )-  , ( "seconde"         , 2 )-  , ( "troisième"  , 3 )-  , ( "troisieme"       , 3 )-  , ( "quatrieme"       , 4 )-  , ( "quatrième"  , 4 )-  , ( "cinquieme"       , 5 )-  , ( "cinquième"  , 5 )-  , ( "sixième"    , 6 )-  , ( "sixieme"         , 6 )-  , ( "septieme"        , 7 )-  , ( "septième"   , 7 )-  , ( "huitième"   , 8 )-  , ( "huitieme"        , 8 )-  , ( "neuvieme"        , 9 )-  , ( "neuvième"   , 9 )-  , ( "dixième"    , 10 )-  , ( "dixieme"         , 10 )-  , ( "onzième"    , 11 )-  , ( "onzieme"         , 11 )-  , ( "douzieme"        , 12 )-  , ( "douzième"   , 12 )-  , ( "treizieme"       , 13 )-  , ( "treizième"  , 13 )+ordinalsMap :: HashMap Text Int+ordinalsMap = HashMap.fromList+  [ ( "première", 1 )+  , ( "premiere", 1 )+  , ( "premier", 1 )+  , ( "deuxième", 2 )+  , ( "deuxieme", 2 )+  , ( "second", 2 )+  , ( "seconde", 2 )+  , ( "troisième", 3 )+  , ( "troisieme", 3 )+  , ( "quatrieme", 4 )+  , ( "quatrième", 4 )+  , ( "cinquieme", 5 )+  , ( "cinquième", 5 )+  , ( "sixième", 6 )+  , ( "sixieme", 6 )+  , ( "septieme", 7 )+  , ( "septième", 7 )+  , ( "huitième", 8 )+  , ( "huitieme", 8 )+  , ( "neuvieme", 9 )+  , ( "neuvième", 9 )+  , ( "dixième", 10 )+  , ( "dixieme", 10 )+  , ( "onzième", 11 )+  , ( "onzieme", 11 )+  , ( "douzieme", 12 )+  , ( "douzième", 12 )+  , ( "treizieme", 13 )+  , ( "treizième", 13 )   , ( "quatorzième", 14 )-  , ( "quatorzieme"     , 14 )-  , ( "quinzième"  , 15 )-  , ( "quinzieme"       , 15 )-  , ( "seizieme"        , 16 )-  , ( "seizième"   , 16 )+  , ( "quatorzieme", 14 )+  , ( "quinzième", 15 )+  , ( "quinzieme", 15 )+  , ( "seizieme", 16 )+  , ( "seizième", 16 )   ]  ruleOrdinalsPremierseizieme :: Rule@@ -70,9 +71,9 @@   , pattern =     [ regex "(premi(ere?|ère)|(deux|trois|quatr|cinqu|six|sept|huit|neuv|dix|onz|douz|treiz|quatorz|quinz|seiz)i(e|è)me|seconde?)"     ]-  , prod = \tokens -> case tokens of+  , prod = \case       (Token RegexMatch (GroupMatch (match:_)):_) ->-        ordinal <$> HashMap.lookup (Text.toLower match) ruleOrdinalsPremierseiziemeMap+        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsMap       _ -> Nothing   } @@ -82,10 +83,8 @@   , pattern =     [ regex "0*(\\d+) ?(ere?|ère|ème|eme|e)"     ]-  , prod = \tokens -> case tokens of-      (Token RegexMatch (GroupMatch (match:_)):_) -> do-        n <- parseInt match-        Just $ ordinal n+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match       _ -> Nothing   } 
Duckling/Ordinal/GA/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Ordinal/GA/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Ordinal/HE/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} 
Duckling/Ordinal/HE/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-}
Duckling/Ordinal/HI/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Ordinal/HI/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Ordinal/HR/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE OverloadedStrings #-} 
Duckling/Ordinal/HR/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.  {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-}
Duckling/Ordinal/HU/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Ordinal/HU/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Ordinal/Helpers.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}@@ -17,20 +16,20 @@  import Duckling.Dimensions.Types import Duckling.Ordinal.Types (OrdinalData (..))-import qualified Duckling.Ordinal.Types as TOrdinal import Duckling.Types+import qualified Duckling.Ordinal.Types as TOrdinal  -- ----------------------------------------------------------------- -- Patterns --- -------------------------------------------------------------------- Production--ordinal :: Int -> Token-ordinal x = Token Ordinal OrdinalData {TOrdinal.value = x}- oneOf :: [Int] -> PatternItem oneOf vs = Predicate $ \x ->   case x of     (Token Ordinal OrdinalData {TOrdinal.value = v}) -> elem v vs     _ -> False++-- -----------------------------------------------------------------+-- Production++ordinal :: Int -> Token+ordinal x = Token Ordinal OrdinalData {TOrdinal.value = x}
Duckling/Ordinal/ID/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Ordinal/ID/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Ordinal/IT/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Ordinal/IT/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
Duckling/Ordinal/JA/Corpus.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE OverloadedStrings #-}
Duckling/Ordinal/JA/Rules.hs view
@@ -2,8 +2,7 @@ -- 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.+-- LICENSE file in the root directory of this source tree.   {-# LANGUAGE GADTs #-}
+ Duckling/Ordinal/KA/Corpus.hs view
@@ -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.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Ordinal.KA.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Ordinal.Types+import Duckling.Testing.Types++import Duckling.Locale+import Duckling.Resolve++corpus :: Corpus+corpus = (testContext {locale = makeLocale KA Nothing}, testOptions, allExamples)+++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 1)+             [ "პირველი"+             , "1-ლი"+             ]+  , examples (OrdinalData 2)+             [ "მეორე"+             , "მე-2"+             ]+  , examples (OrdinalData 3)+             [ "მესამე"+             , "მე-3"+             ]+  , examples (OrdinalData 4)+             [ "მეოთხე"+             , "მე-4"+             ]+  , examples (OrdinalData 8)+             [ "მერვე"+             , "მე-8"+             ]+  , examples (OrdinalData 25)+             [ "ოცდამეხუთე"+             , "25-ე"+             ]+  , examples (OrdinalData 31)+             [ "ოცდამეთერთმეტე"+             , "31-ე"+             ]+  , examples (OrdinalData 42)+             [ "ორმოცდამეორე"+             , "42-ე"+             ]+  , examples (OrdinalData 73)+            [ "სამოცდამეცამეტე"+            , "73-ე"+            ]+  , examples (OrdinalData 90)+            [ "ოთხმოცდამეათე"+            , "90-ე"+            ]+  ]
+ Duckling/Ordinal/KA/Rules.hs view
@@ -0,0 +1,145 @@+-- 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 #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Ordinal.KA.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 (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Regex.Types+import Duckling.Types++ordinalsMap :: HashMap Text Int+ordinalsMap = HashMap.fromList+  [ ("პირველი", 1)+  , ("პირველ", 1)+  , ("მეერთე", 1)+  , ("მეორე", 2)+  , ("მესამე", 3)+  , ("მეოთხე", 4)+  , ("მეხუთე", 5)+  , ("მეექვსე", 6)+  , ("მეშვიდე", 7)+  , ("მერვე", 8)+  , ("მეცხრე", 9)+  , ("მეათე", 10)+  , ("მეთერთმეტე", 11)+  , ("მეთორმეტე", 12)+  , ("მეცამეტე", 13)+  , ("მეთოთხმეტე", 14)+  , ("მეთხუთმეტე", 15)+  , ("მეთქვსმეტე", 16)+  , ("მეჩვიდმეტე", 17)+  , ("მეთვრამეტე", 18)+  , ("მეცხრამეტე", 19)+  , ("მეოცე", 20)+  , ("ოცდამეათე", 30)+  , ("მეორმოცე", 40)+  , ("ორმოცდამეათე", 50)+  , ("მესამოცე", 60)+  , ("სამოცდამეათე", 70)+  , ("მეოთხმოცე", 80)+  , ("ოთხმოცდამეათე", 90)+  ]++cardinalsMap :: HashMap Text Int+cardinalsMap = HashMap.fromList+  [ ("ოცი", 20)+  , ("ოცდა", 20)+  , ("ოცდაათი", 30)+  , ("ორმოცი", 40)+  , ("ორმოცდა", 40)+  , ("ორმოცდაათი", 50)+  , ("სამოცი", 60)+  , ("სამოცდა", 60)+  , ("სამოცდაათი", 70)+  , ("ოთხმოცი", 80)+  , ("ოთხმოცდა", 80)+  , ("ოთხმოცდაათი", 90)+  ]++ruleOrdinals :: Rule+ruleOrdinals = Rule+  { name = "ordinals (first..twentieth,thirtieth,...)"+  , pattern =+    [ regex "(პირველი?|მეორე|მესამე|მეოთხე|მეხუთე|მეექვსე|მეშვიდე|მერვე|მეცხრე|მეათე|მეთერთმეტე|მეთოთხმეტე|მეცამეტე|მეთოთხმეტე|მეთხუთმეტე|მეთექვსმეტე|მეჩვიდმეტე|მეთვრამეტე|მეცხრამეტე|მეოცე|ოცდამეათე|მეორმოცე|ორმოცდამეათე|მესამოცე|სამოცდამეათე|მეოთხმოცე|ოთხმოცდამეათე)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsMap+      _ -> Nothing+    }++ruleCompositeOrdinals :: Rule+ruleCompositeOrdinals = Rule+  { name = "ordinals (composite, e.g. eighty-seven, forty—seventh, twenty ninth, thirtythird)"+  , pattern =+    [ regex "(ოცდა|ორმოცდა|სამოცდა|ოთხმოცდა)[\\s\\-\\—]?(მეერთე|მეორე|მესამე|მეოთხე|მეხუთე|მეექვსე|მეშვიდე|მერვე|მეცხრე|მეათე|მეთერთმეტე|მეთოთხმეტე|მეცამეტე|მეთოთხმეტე|მეთხუთმეტე|მეთექვსმეტე|მეჩვიდმეტე|მეთვრამეტე|მეცხრამეტე)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (tens:units:_)):_) -> do+        tt <- HashMap.lookup (Text.toLower tens) cardinalsMap+        uu <- HashMap.lookup (Text.toLower units) ordinalsMap+        Just (ordinal (tt + uu))+      _ -> Nothing+  }++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "0*(\\d+) ?(-ლი|-ე)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match+      _ -> Nothing+  }++ruleOrdinalDigits1 :: Rule+ruleOrdinalDigits1 = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "მე-? ?0*(\\d+)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match+      _ -> Nothing+  }++ruleOrdinalDigits2 :: Rule+ruleOrdinalDigits2 = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "მე-? ?0*(\\d+) ?(-ლი|-ე)"+    ]+  , prod = \case+      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinals+  , ruleCompositeOrdinals+  , ruleOrdinalDigits+  , ruleOrdinalDigits1+  , ruleOrdinalDigits2+  ]
+ Duckling/Ordinal/KM/Corpus.hs view
@@ -0,0 +1,37 @@+-- 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.Ordinal.KM.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Locale+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++context :: Context+context = testContext{locale = makeLocale KM Nothing}++corpus :: Corpus+corpus = (context, testOptions, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 1)+             [ "ទីមួយ"+             , "ទី១"+             ]+  , examples (OrdinalData 400)+             [ "ទីបួនរយ"+             ]+  ]
+ Duckling/Ordinal/KM/Rules.hs view

file too large to diff

Duckling/Ordinal/KO/Corpus.hs view

file too large to diff

Duckling/Ordinal/KO/Rules.hs view

file too large to diff

+ Duckling/Ordinal/ML/Corpus.hs view

file too large to diff

+ Duckling/Ordinal/ML/Rules.hs view

file too large to diff

+ Duckling/Ordinal/MN/Corpus.hs view

file too large to diff

+ Duckling/Ordinal/MN/Rules.hs view

file too large to diff

Duckling/Ordinal/NB/Corpus.hs view

file too large to diff

Duckling/Ordinal/NB/Rules.hs view

file too large to diff

Duckling/Ordinal/NL/Corpus.hs view

file too large to diff

Duckling/Ordinal/NL/Rules.hs view

file too large to diff

Duckling/Ordinal/PL/Corpus.hs view

file too large to diff

Duckling/Ordinal/PL/Rules.hs view

file too large to diff

Duckling/Ordinal/PT/Corpus.hs view

file too large to diff

Duckling/Ordinal/PT/Rules.hs view

file too large to diff

Duckling/Ordinal/RO/Corpus.hs view

file too large to diff

Duckling/Ordinal/RO/Rules.hs view

file too large to diff

Duckling/Ordinal/RU/Corpus.hs view

file too large to diff

Duckling/Ordinal/RU/Rules.hs view

file too large to diff

Duckling/Ordinal/SV/Corpus.hs view

file too large to diff

Duckling/Ordinal/SV/Rules.hs view

file too large to diff

+ Duckling/Ordinal/TA/Corpus.hs view

file too large to diff

+ Duckling/Ordinal/TA/Rules.hs view

file too large to diff

Duckling/Ordinal/TR/Corpus.hs view

file too large to diff

Duckling/Ordinal/TR/Rules.hs view

file too large to diff

Duckling/Ordinal/Types.hs view

file too large to diff

Duckling/Ordinal/UK/Corpus.hs view

file too large to diff

Duckling/Ordinal/UK/Rules.hs view

file too large to diff

Duckling/Ordinal/VI/Corpus.hs view

file too large to diff

Duckling/Ordinal/VI/Rules.hs view

file too large to diff

Duckling/Ordinal/ZH/Corpus.hs view

file too large to diff

Duckling/Ordinal/ZH/Rules.hs view

file too large to diff

+ Duckling/PhoneNumber/AR/Corpus.hs view

file too large to diff

+ Duckling/PhoneNumber/AR/Rules.hs view

file too large to diff

Duckling/PhoneNumber/Corpus.hs view

file too large to diff

Duckling/PhoneNumber/PT/Corpus.hs view

file too large to diff

Duckling/PhoneNumber/PT/Rules.hs view

file too large to diff

Duckling/PhoneNumber/Rules.hs view

file too large to diff

Duckling/PhoneNumber/Types.hs view

file too large to diff

Duckling/Quantity/AR/Corpus.hs view

file too large to diff

Duckling/Quantity/AR/Rules.hs view

file too large to diff

Duckling/Quantity/EN/Corpus.hs view

file too large to diff

Duckling/Quantity/EN/Rules.hs view

file too large to diff

+ Duckling/Quantity/ES/Corpus.hs view

file too large to diff

+ Duckling/Quantity/ES/Rules.hs view

file too large to diff

Duckling/Quantity/FR/Corpus.hs view

file too large to diff

Duckling/Quantity/FR/Rules.hs view

file too large to diff

Duckling/Quantity/HR/Corpus.hs view

file too large to diff

Duckling/Quantity/HR/Rules.hs view

file too large to diff

Duckling/Quantity/Helpers.hs view

file too large to diff

+ Duckling/Quantity/KM/Corpus.hs view

file too large to diff

+ Duckling/Quantity/KM/Rules.hs view

file too large to diff

Duckling/Quantity/KO/Corpus.hs view

file too large to diff

Duckling/Quantity/KO/Rules.hs view

file too large to diff

+ Duckling/Quantity/MN/Corpus.hs view

file too large to diff

+ Duckling/Quantity/MN/Rules.hs view

file too large to diff

+ Duckling/Quantity/NL/Corpus.hs view

file too large to diff

+ Duckling/Quantity/NL/Rules.hs view

file too large to diff

Duckling/Quantity/PT/Corpus.hs view

file too large to diff

Duckling/Quantity/PT/Rules.hs view

file too large to diff

Duckling/Quantity/RO/Corpus.hs view

file too large to diff

Duckling/Quantity/RO/Rules.hs view

file too large to diff

Duckling/Quantity/RU/Corpus.hs view

file too large to diff

Duckling/Quantity/RU/Rules.hs view

file too large to diff

Duckling/Quantity/Types.hs view

file too large to diff

Duckling/Quantity/ZH/Corpus.hs view

file too large to diff

Duckling/Quantity/ZH/Rules.hs view

file too large to diff

Duckling/Ranking/Classifiers.hs view

file too large to diff

+ Duckling/Ranking/Classifiers/AF_XX.hs view

file too large to diff

+ Duckling/Ranking/Classifiers/AR_EG.hs view

file too large to diff

Duckling/Ranking/Classifiers/AR_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/BG_XX.hs view

file too large to diff

+ Duckling/Ranking/Classifiers/BN_XX.hs view

file too large to diff

+ Duckling/Ranking/Classifiers/CA_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/DA_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/DE_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/EL_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/EN_CA.hs view

file too large to diff

Duckling/Ranking/Classifiers/EN_GB.hs view

file too large to diff

Duckling/Ranking/Classifiers/EN_US.hs view

file too large to diff

Duckling/Ranking/Classifiers/EN_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/ES_XX.hs view

file too large to diff

+ Duckling/Ranking/Classifiers/FA_XX.hs view

file too large to diff

+ Duckling/Ranking/Classifiers/FI_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/FR_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/HE_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/HR_XX.hs view

file too large to diff

+ Duckling/Ranking/Classifiers/IS_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/IT_XX.hs view

file too large to diff

+ Duckling/Ranking/Classifiers/KM_XX.hs view

file too large to diff

+ Duckling/Ranking/Classifiers/KN_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/KO_XX.hs view

file too large to diff

+ Duckling/Ranking/Classifiers/LO_XX.hs view

file too large to diff

+ Duckling/Ranking/Classifiers/ML_XX.hs view

file too large to diff

+ Duckling/Ranking/Classifiers/MN_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/NB_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/NL_BE.hs view

file too large to diff

Duckling/Ranking/Classifiers/NL_NL.hs view

file too large to diff

Duckling/Ranking/Classifiers/NL_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/PL_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/PT_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/RO_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/RU_XX.hs view

file too large to diff

+ Duckling/Ranking/Classifiers/SK_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/SV_XX.hs view

file too large to diff

+ Duckling/Ranking/Classifiers/SW_XX.hs view

file too large to diff

+ Duckling/Ranking/Classifiers/TE_XX.hs view

file too large to diff

+ Duckling/Ranking/Classifiers/TH_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/TR_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/UK_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/VI_XX.hs view

file too large to diff

Duckling/Ranking/Classifiers/ZH_CN.hs view

file too large to diff

Duckling/Ranking/Classifiers/ZH_HK.hs view

file too large to diff

Duckling/Ranking/Classifiers/ZH_MO.hs view

file too large to diff

Duckling/Ranking/Classifiers/ZH_TW.hs view

file too large to diff

Duckling/Ranking/Classifiers/ZH_XX.hs view

file too large to diff

Duckling/Ranking/Extraction.hs view

file too large to diff

Duckling/Ranking/Rank.hs view

file too large to diff

Duckling/Ranking/Types.hs view

file too large to diff

Duckling/Regex/Types.hs view

file too large to diff

Duckling/Region.hs view

file too large to diff

Duckling/Resolve.hs view

file too large to diff

Duckling/Rules.hs view

file too large to diff

+ Duckling/Rules/AF.hs view

file too large to diff

Duckling/Rules/AR.hs view

file too large to diff

Duckling/Rules/BG.hs view

file too large to diff

+ Duckling/Rules/BN.hs view

file too large to diff

+ Duckling/Rules/CA.hs view

file too large to diff

Duckling/Rules/CS.hs view

file too large to diff

Duckling/Rules/Common.hs view

file too large to diff

Duckling/Rules/DA.hs view

file too large to diff

Duckling/Rules/DE.hs view

file too large to diff

Duckling/Rules/EL.hs view

file too large to diff

Duckling/Rules/EN.hs view

file too large to diff

Duckling/Rules/ES.hs view

file too large to diff

Duckling/Rules/ET.hs view

file too large to diff

+ Duckling/Rules/FA.hs view

file too large to diff

+ Duckling/Rules/FI.hs view

file too large to diff

Duckling/Rules/FR.hs view

file too large to diff

Duckling/Rules/GA.hs view

file too large to diff

Duckling/Rules/HE.hs view

file too large to diff

Duckling/Rules/HI.hs view

file too large to diff

Duckling/Rules/HR.hs view

file too large to diff

Duckling/Rules/HU.hs view

file too large to diff

Duckling/Rules/ID.hs view

file too large to diff

+ Duckling/Rules/IS.hs view

file too large to diff

Duckling/Rules/IT.hs view

file too large to diff

Duckling/Rules/JA.hs view

file too large to diff

Duckling/Rules/KA.hs view

file too large to diff

+ Duckling/Rules/KM.hs view

file too large to diff

+ Duckling/Rules/KN.hs view

file too large to diff

Duckling/Rules/KO.hs view

file too large to diff

+ Duckling/Rules/LO.hs view

file too large to diff

+ Duckling/Rules/ML.hs view

file too large to diff

+ Duckling/Rules/MN.hs view

file too large to diff

Duckling/Rules/MY.hs view

file too large to diff

Duckling/Rules/NB.hs view

file too large to diff

Duckling/Rules/NE.hs view

file too large to diff

Duckling/Rules/NL.hs view

file too large to diff

Duckling/Rules/PL.hs view

file too large to diff

Duckling/Rules/PT.hs view

file too large to diff

Duckling/Rules/RO.hs view

file too large to diff

Duckling/Rules/RU.hs view

file too large to diff

+ Duckling/Rules/SK.hs view

file too large to diff

Duckling/Rules/SV.hs view

file too large to diff

+ Duckling/Rules/SW.hs view

file too large to diff

Duckling/Rules/TA.hs view

file too large to diff

+ Duckling/Rules/TE.hs view

file too large to diff

+ Duckling/Rules/TH.hs view

file too large to diff

Duckling/Rules/TR.hs view

file too large to diff

Duckling/Rules/UK.hs view

file too large to diff

Duckling/Rules/VI.hs view

file too large to diff

Duckling/Rules/ZH.hs view

file too large to diff

Duckling/Temperature/AR/Corpus.hs view

file too large to diff

Duckling/Temperature/AR/Rules.hs view

file too large to diff

Duckling/Temperature/EN/Corpus.hs view

file too large to diff

Duckling/Temperature/EN/Rules.hs view

file too large to diff

Duckling/Temperature/ES/Corpus.hs view

file too large to diff

Duckling/Temperature/ES/Rules.hs view

file too large to diff

Duckling/Temperature/FR/Corpus.hs view

file too large to diff

Duckling/Temperature/FR/Rules.hs view

file too large to diff

Duckling/Temperature/GA/Corpus.hs view

file too large to diff

Duckling/Temperature/GA/Rules.hs view

file too large to diff

+ Duckling/Temperature/HI/Corpus.hs view

file too large to diff

+ Duckling/Temperature/HI/Rules.hs view

file too large to diff

Duckling/Temperature/HR/Corpus.hs view

file too large to diff

Duckling/Temperature/HR/Rules.hs view

file too large to diff

Duckling/Temperature/Helpers.hs view

file too large to diff

Duckling/Temperature/IT/Corpus.hs view

file too large to diff

Duckling/Temperature/IT/Rules.hs view

file too large to diff

Duckling/Temperature/JA/Corpus.hs view

file too large to diff

Duckling/Temperature/JA/Rules.hs view

file too large to diff

+ Duckling/Temperature/KM/Corpus.hs view

file too large to diff

+ Duckling/Temperature/KM/Rules.hs view

file too large to diff

Duckling/Temperature/KO/Corpus.hs view

file too large to diff

Duckling/Temperature/KO/Rules.hs view

file too large to diff

+ Duckling/Temperature/MN/Corpus.hs view

file too large to diff

+ Duckling/Temperature/MN/Rules.hs view

file too large to diff

Duckling/Temperature/PT/Corpus.hs view

file too large to diff

Duckling/Temperature/PT/Rules.hs view

file too large to diff

Duckling/Temperature/RO/Corpus.hs view

file too large to diff

Duckling/Temperature/RO/Rules.hs view

file too large to diff

Duckling/Temperature/Rules.hs view

file too large to diff

Duckling/Temperature/TR/Corpus.hs view

file too large to diff

Duckling/Temperature/TR/Rules.hs view

file too large to diff

Duckling/Temperature/Types.hs view

file too large to diff

Duckling/Temperature/ZH/Corpus.hs view

file too large to diff

Duckling/Temperature/ZH/Rules.hs view

file too large to diff

Duckling/Testing/Types.hs view

file too large to diff

Duckling/Time/AR/Corpus.hs view

file too large to diff

Duckling/Time/AR/Rules.hs view

file too large to diff

+ Duckling/Time/BG/Corpus.hs view

file too large to diff

+ Duckling/Time/BG/Rules.hs view

file too large to diff

Duckling/Time/Computed.hs view

file too large to diff

Duckling/Time/Corpus.hs view

file too large to diff

Duckling/Time/DA/Corpus.hs view

file too large to diff

Duckling/Time/DA/Rules.hs view

file too large to diff

Duckling/Time/DE/Corpus.hs view

file too large to diff

Duckling/Time/DE/Rules.hs view

file too large to diff

Duckling/Time/EL/Corpus.hs view

file too large to diff

Duckling/Time/EL/Rules.hs view

file too large to diff

Duckling/Time/EN/AU/Corpus.hs view

file too large to diff

Duckling/Time/EN/AU/Rules.hs view

file too large to diff

Duckling/Time/EN/BZ/Corpus.hs view

file too large to diff

Duckling/Time/EN/BZ/Rules.hs view

file too large to diff

Duckling/Time/EN/CA/Corpus.hs view

file too large to diff

Duckling/Time/EN/CA/Rules.hs view

file too large to diff

Duckling/Time/EN/Corpus.hs view

file too large to diff

Duckling/Time/EN/GB/Corpus.hs view

file too large to diff

Duckling/Time/EN/GB/Rules.hs view

file too large to diff

Duckling/Time/EN/IE/Corpus.hs view

file too large to diff

Duckling/Time/EN/IE/Rules.hs view

file too large to diff

Duckling/Time/EN/IN/Corpus.hs view

file too large to diff

Duckling/Time/EN/IN/Rules.hs view

file too large to diff

Duckling/Time/EN/JM/Corpus.hs view

file too large to diff

Duckling/Time/EN/JM/Rules.hs view

file too large to diff

Duckling/Time/EN/NZ/Corpus.hs view

file too large to diff

Duckling/Time/EN/NZ/Rules.hs view

file too large to diff

Duckling/Time/EN/PH/Corpus.hs view

file too large to diff

Duckling/Time/EN/PH/Rules.hs view

file too large to diff

Duckling/Time/EN/Rules.hs view

file too large to diff

Duckling/Time/EN/TT/Corpus.hs view

file too large to diff

Duckling/Time/EN/TT/Rules.hs view

file too large to diff

Duckling/Time/EN/US/Corpus.hs view

file too large to diff

Duckling/Time/EN/US/Rules.hs view

file too large to diff

Duckling/Time/EN/ZA/Corpus.hs view

file too large to diff

Duckling/Time/EN/ZA/Rules.hs view

file too large to diff

Duckling/Time/ES/Corpus.hs view

file too large to diff

Duckling/Time/ES/Rules.hs view

file too large to diff

Duckling/Time/FR/Corpus.hs view

file too large to diff

Duckling/Time/FR/Rules.hs view

file too large to diff

Duckling/Time/GA/Corpus.hs view

file too large to diff

Duckling/Time/GA/Rules.hs view

file too large to diff

Duckling/Time/HE/Corpus.hs view

file too large to diff

Duckling/Time/HE/Rules.hs view

file too large to diff

Duckling/Time/HR/Corpus.hs view

file too large to diff

Duckling/Time/HR/Rules.hs view

file too large to diff

Duckling/Time/HU/Corpus.hs view

file too large to diff

Duckling/Time/HU/Rules.hs view

file too large to diff

Duckling/Time/Helpers.hs view

file too large to diff

+ Duckling/Time/HolidayHelpers.hs view

file too large to diff

Duckling/Time/IT/Corpus.hs view

file too large to diff

Duckling/Time/IT/Rules.hs view

file too large to diff

+ Duckling/Time/KA/Corpus.hs view

file too large to diff

+ Duckling/Time/KA/Rules.hs view

file too large to diff

Duckling/Time/KO/Corpus.hs view

file too large to diff

Duckling/Time/KO/Rules.hs view

file too large to diff

Duckling/Time/NB/Corpus.hs view

file too large to diff

Duckling/Time/NB/Rules.hs view

file too large to diff

Duckling/Time/NL/BE/Corpus.hs view

file too large to diff

Duckling/Time/NL/BE/Rules.hs view

file too large to diff

Duckling/Time/NL/Corpus.hs view

file too large to diff

Duckling/Time/NL/NL/Rules.hs view

file too large to diff

Duckling/Time/NL/Rules.hs view

file too large to diff

Duckling/Time/PL/Corpus.hs view

file too large to diff

Duckling/Time/PL/Rules.hs view

file too large to diff

Duckling/Time/PT/Corpus.hs view

file too large to diff

Duckling/Time/PT/Rules.hs view

file too large to diff

Duckling/Time/RO/Corpus.hs view

file too large to diff

Duckling/Time/RO/Rules.hs view

file too large to diff

+ Duckling/Time/RU/Corpus.hs view

file too large to diff

+ Duckling/Time/RU/Rules.hs view

file too large to diff

Duckling/Time/SV/Corpus.hs view

file too large to diff

Duckling/Time/SV/Rules.hs view

file too large to diff

+ Duckling/Time/TR/Corpus.hs view

file too large to diff

+ Duckling/Time/TR/Rules.hs view

file too large to diff

Duckling/Time/TimeZone/Parse.hs view

file too large to diff

Duckling/Time/Types.hs view

file too large to diff

+ Duckling/Time/UK/Corpus.hs view

file too large to diff

+ Duckling/Time/UK/Rules.hs view

file too large to diff

Duckling/Time/VI/Corpus.hs view

file too large to diff

Duckling/Time/VI/Rules.hs view

file too large to diff

Duckling/Time/ZH/CN/Corpus.hs view

file too large to diff

Duckling/Time/ZH/CN/Rules.hs view

file too large to diff

Duckling/Time/ZH/Corpus.hs view

file too large to diff

Duckling/Time/ZH/HK/Corpus.hs view

file too large to diff

Duckling/Time/ZH/HK/Rules.hs view

file too large to diff

Duckling/Time/ZH/MO/Corpus.hs view

file too large to diff

Duckling/Time/ZH/MO/Rules.hs view

file too large to diff

Duckling/Time/ZH/Rules.hs view

file too large to diff

Duckling/Time/ZH/TW/Corpus.hs view

file too large to diff

Duckling/Time/ZH/TW/Rules.hs view

file too large to diff

Duckling/TimeGrain/AR/Rules.hs view

file too large to diff

Duckling/TimeGrain/BG/Rules.hs view

file too large to diff

Duckling/TimeGrain/DA/Rules.hs view

file too large to diff

Duckling/TimeGrain/DE/Rules.hs view

file too large to diff

Duckling/TimeGrain/EL/Rules.hs view

file too large to diff

Duckling/TimeGrain/EN/Rules.hs view

file too large to diff

Duckling/TimeGrain/ES/Rules.hs view

file too large to diff

+ Duckling/TimeGrain/FI/Rules.hs view

file too large to diff

Duckling/TimeGrain/FR/Rules.hs view

file too large to diff

Duckling/TimeGrain/GA/Rules.hs view

file too large to diff

Duckling/TimeGrain/HE/Rules.hs view

file too large to diff

Duckling/TimeGrain/HI/Rules.hs view

file too large to diff

Duckling/TimeGrain/HR/Rules.hs view

file too large to diff

Duckling/TimeGrain/HU/Rules.hs view

file too large to diff

Duckling/TimeGrain/IT/Rules.hs view

file too large to diff

Duckling/TimeGrain/JA/Rules.hs view

file too large to diff

+ Duckling/TimeGrain/KA/Rules.hs view

file too large to diff

Duckling/TimeGrain/KO/Rules.hs view

file too large to diff

+ Duckling/TimeGrain/MN/Rules.hs view

file too large to diff

Duckling/TimeGrain/NB/Rules.hs view

file too large to diff

Duckling/TimeGrain/NL/Rules.hs view

file too large to diff

Duckling/TimeGrain/PL/Rules.hs view

file too large to diff

Duckling/TimeGrain/PT/Rules.hs view

file too large to diff

Duckling/TimeGrain/RO/Rules.hs view

file too large to diff

Duckling/TimeGrain/RU/Rules.hs view

file too large to diff

Duckling/TimeGrain/SV/Rules.hs view

file too large to diff

Duckling/TimeGrain/TR/Rules.hs view

file too large to diff

Duckling/TimeGrain/Types.hs view

file too large to diff

+ Duckling/TimeGrain/UK/Rules.hs view

file too large to diff

Duckling/TimeGrain/VI/Rules.hs view

file too large to diff

Duckling/TimeGrain/ZH/Rules.hs view

file too large to diff

Duckling/Types.hs view

file too large to diff

Duckling/Types/Document.hs view

file too large to diff

Duckling/Types/Stash.hs view

file too large to diff

Duckling/Url/Corpus.hs view

file too large to diff

Duckling/Url/Helpers.hs view

file too large to diff

Duckling/Url/Rules.hs view

file too large to diff

Duckling/Url/Types.hs view

file too large to diff

Duckling/Volume/AR/Corpus.hs view

file too large to diff

Duckling/Volume/AR/Rules.hs view

file too large to diff

+ Duckling/Volume/DE/Corpus.hs view

file too large to diff

+ Duckling/Volume/DE/Rules.hs view

file too large to diff

Duckling/Volume/EN/Corpus.hs view

file too large to diff

Duckling/Volume/EN/Rules.hs view

file too large to diff

Duckling/Volume/ES/Corpus.hs view

file too large to diff

Duckling/Volume/ES/Rules.hs view

file too large to diff

Duckling/Volume/FR/Corpus.hs view

file too large to diff

Duckling/Volume/FR/Rules.hs view

file too large to diff

Duckling/Volume/GA/Corpus.hs view

file too large to diff

Duckling/Volume/GA/Rules.hs view

file too large to diff

Duckling/Volume/HR/Corpus.hs view

file too large to diff

Duckling/Volume/HR/Rules.hs view

file too large to diff

Duckling/Volume/Helpers.hs view

file too large to diff

Duckling/Volume/IT/Corpus.hs view

file too large to diff

Duckling/Volume/IT/Rules.hs view

file too large to diff

+ Duckling/Volume/KM/Corpus.hs view

file too large to diff

+ Duckling/Volume/KM/Rules.hs view

file too large to diff

Duckling/Volume/KO/Corpus.hs view

file too large to diff

Duckling/Volume/KO/Rules.hs view

file too large to diff

+ Duckling/Volume/MN/Corpus.hs view

file too large to diff

+ Duckling/Volume/MN/Rules.hs view

file too large to diff

Duckling/Volume/NL/Corpus.hs view

file too large to diff

Duckling/Volume/NL/Rules.hs view

file too large to diff

Duckling/Volume/PT/Corpus.hs view

file too large to diff

Duckling/Volume/PT/Rules.hs view

file too large to diff

Duckling/Volume/RO/Corpus.hs view

file too large to diff

Duckling/Volume/RO/Rules.hs view

file too large to diff

Duckling/Volume/RU/Corpus.hs view

file too large to diff

Duckling/Volume/RU/Rules.hs view

file too large to diff

Duckling/Volume/Rules.hs view

file too large to diff

Duckling/Volume/TR/Corpus.hs view

file too large to diff

Duckling/Volume/TR/Rules.hs view

file too large to diff

Duckling/Volume/Types.hs view

file too large to diff

+ Duckling/Volume/ZH/Corpus.hs view

file too large to diff

+ Duckling/Volume/ZH/Rules.hs view

file too large to diff

− PATENTS

file too large to diff

README.md view

file too large to diff

− Setup.hs

file too large to diff

duckling.cabal view

file too large to diff

exe/CustomDimensionExample.hs view

file too large to diff

exe/Duckling/Data/TimeZone.hs view

file too large to diff

exe/Duckling/Ranking/Generate.hs view

file too large to diff

exe/Duckling/Ranking/Train.hs view

file too large to diff

exe/DucklingExpensive.hs view

file too large to diff

exe/DucklingRequestSample.hs view

file too large to diff

exe/ExampleMain.hs view

file too large to diff

exe/RegenMain.hs view

file too large to diff

tests/Duckling/AmountOfMoney/AR/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/BG/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/EN/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/ES/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/FR/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/GA/Tests.hs view

file too large to diff

+ tests/Duckling/AmountOfMoney/HE/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/HR/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/ID/Tests.hs view

file too large to diff

+ tests/Duckling/AmountOfMoney/IT/Tests.hs view

file too large to diff

+ tests/Duckling/AmountOfMoney/KA/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/KO/Tests.hs view

file too large to diff

+ tests/Duckling/AmountOfMoney/MN/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/NB/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/NL/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/PT/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/RO/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/RU/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/SV/Tests.hs view

file too large to diff

+ tests/Duckling/AmountOfMoney/TR/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/VI/Tests.hs view

file too large to diff

tests/Duckling/AmountOfMoney/ZH/Tests.hs view

file too large to diff

tests/Duckling/Api/Tests.hs view

file too large to diff

+ tests/Duckling/CreditCardNumber/Tests.hs view

file too large to diff

tests/Duckling/Dimensions/Tests.hs view

file too large to diff

tests/Duckling/Distance/BG/Tests.hs view

file too large to diff

tests/Duckling/Distance/CS/Tests.hs view

file too large to diff

+ tests/Duckling/Distance/DE/Tests.hs view

file too large to diff

tests/Duckling/Distance/EN/Tests.hs view

file too large to diff

tests/Duckling/Distance/ES/Tests.hs view

file too large to diff

tests/Duckling/Distance/FR/Tests.hs view

file too large to diff

tests/Duckling/Distance/GA/Tests.hs view

file too large to diff

tests/Duckling/Distance/HR/Tests.hs view

file too large to diff

+ tests/Duckling/Distance/IT/Tests.hs view

file too large to diff

+ tests/Duckling/Distance/KM/Tests.hs view

file too large to diff

tests/Duckling/Distance/KO/Tests.hs view

file too large to diff

+ tests/Duckling/Distance/MN/Tests.hs view

file too large to diff

tests/Duckling/Distance/NL/Tests.hs view

file too large to diff

tests/Duckling/Distance/PT/Tests.hs view

file too large to diff

tests/Duckling/Distance/RO/Tests.hs view

file too large to diff

tests/Duckling/Distance/RU/Tests.hs view

file too large to diff

tests/Duckling/Distance/SV/Tests.hs view

file too large to diff

tests/Duckling/Distance/TR/Tests.hs view

file too large to diff

tests/Duckling/Distance/Tests.hs view

file too large to diff

tests/Duckling/Distance/ZH/Tests.hs view

file too large to diff

tests/Duckling/Duration/AR/Tests.hs view

file too large to diff

tests/Duckling/Duration/BG/Tests.hs view

file too large to diff

tests/Duckling/Duration/EL/Tests.hs view

file too large to diff

tests/Duckling/Duration/EN/Tests.hs view

file too large to diff

+ tests/Duckling/Duration/ES/Tests.hs view

file too large to diff

tests/Duckling/Duration/FR/Tests.hs view

file too large to diff

tests/Duckling/Duration/GA/Tests.hs view

file too large to diff

tests/Duckling/Duration/HI/Tests.hs view

file too large to diff

tests/Duckling/Duration/HU/Tests.hs view

file too large to diff

tests/Duckling/Duration/JA/Tests.hs view

file too large to diff

+ tests/Duckling/Duration/KA/Tests.hs view

file too large to diff

tests/Duckling/Duration/KO/Tests.hs view

file too large to diff

+ tests/Duckling/Duration/MN/Tests.hs view

file too large to diff

tests/Duckling/Duration/NB/Tests.hs view

file too large to diff

tests/Duckling/Duration/NL/Tests.hs view

file too large to diff

tests/Duckling/Duration/PL/Tests.hs view

file too large to diff

tests/Duckling/Duration/PT/Tests.hs view

file too large to diff

tests/Duckling/Duration/RO/Tests.hs view

file too large to diff

tests/Duckling/Duration/RU/Tests.hs view

file too large to diff

tests/Duckling/Duration/SV/Tests.hs view

file too large to diff

tests/Duckling/Duration/TR/Tests.hs view

file too large to diff

tests/Duckling/Duration/Tests.hs view

file too large to diff

+ tests/Duckling/Duration/UK/Tests.hs view

file too large to diff

tests/Duckling/Duration/ZH/Tests.hs view

file too large to diff

+ tests/Duckling/Email/DE/Tests.hs view

file too large to diff

tests/Duckling/Email/EN/Tests.hs view

file too large to diff

tests/Duckling/Email/FR/Tests.hs view

file too large to diff

+ tests/Duckling/Email/IS/Tests.hs view

file too large to diff

tests/Duckling/Email/IT/Tests.hs view

file too large to diff

tests/Duckling/Email/Tests.hs view

file too large to diff

tests/Duckling/Engine/Tests.hs view

file too large to diff

+ tests/Duckling/Numeral/AF/Tests.hs view

file too large to diff

tests/Duckling/Numeral/AR/Tests.hs view

file too large to diff

tests/Duckling/Numeral/BG/Tests.hs view

file too large to diff

+ tests/Duckling/Numeral/BN/Tests.hs view

file too large to diff

+ tests/Duckling/Numeral/CA/Tests.hs view

file too large to diff

tests/Duckling/Numeral/CS/Tests.hs view

file too large to diff

tests/Duckling/Numeral/DA/Tests.hs view

file too large to diff

tests/Duckling/Numeral/DE/Tests.hs view

file too large to diff

tests/Duckling/Numeral/EL/Tests.hs view

file too large to diff

tests/Duckling/Numeral/EN/Tests.hs view

file too large to diff

tests/Duckling/Numeral/ES/Tests.hs view

file too large to diff

tests/Duckling/Numeral/ET/Tests.hs view

file too large to diff

+ tests/Duckling/Numeral/FA/Tests.hs view

file too large to diff

+ tests/Duckling/Numeral/FI/Tests.hs view

file too large to diff

tests/Duckling/Numeral/FR/Tests.hs view

file too large to diff

tests/Duckling/Numeral/GA/Tests.hs view

file too large to diff

tests/Duckling/Numeral/HE/Tests.hs view

file too large to diff

tests/Duckling/Numeral/HI/Tests.hs view

file too large to diff

tests/Duckling/Numeral/HR/Tests.hs view

file too large to diff

tests/Duckling/Numeral/HU/Tests.hs view

file too large to diff

tests/Duckling/Numeral/ID/Tests.hs view

file too large to diff

+ tests/Duckling/Numeral/IS/Tests.hs view

file too large to diff

tests/Duckling/Numeral/IT/Tests.hs view

file too large to diff

tests/Duckling/Numeral/JA/Tests.hs view

file too large to diff

tests/Duckling/Numeral/KA/Tests.hs view

file too large to diff

+ tests/Duckling/Numeral/KM/Tests.hs view

file too large to diff

+ tests/Duckling/Numeral/KN/Tests.hs view

file too large to diff

tests/Duckling/Numeral/KO/Tests.hs view

file too large to diff

+ tests/Duckling/Numeral/LO/Tests.hs view

file too large to diff

+ tests/Duckling/Numeral/ML/Tests.hs view

file too large to diff

+ tests/Duckling/Numeral/MN/Tests.hs view

file too large to diff

tests/Duckling/Numeral/MY/Tests.hs view

file too large to diff

tests/Duckling/Numeral/NB/Tests.hs view

file too large to diff

tests/Duckling/Numeral/NE/Tests.hs view

file too large to diff

tests/Duckling/Numeral/NL/Tests.hs view

file too large to diff

tests/Duckling/Numeral/PL/Tests.hs view

file too large to diff

tests/Duckling/Numeral/PT/Tests.hs view

file too large to diff

tests/Duckling/Numeral/RO/Tests.hs view

file too large to diff

tests/Duckling/Numeral/RU/Tests.hs view

file too large to diff

+ tests/Duckling/Numeral/SK/Tests.hs view

file too large to diff

tests/Duckling/Numeral/SV/Tests.hs view

file too large to diff

+ tests/Duckling/Numeral/SW/Tests.hs view

file too large to diff

tests/Duckling/Numeral/TA/Tests.hs view

file too large to diff

+ tests/Duckling/Numeral/TE/Tests.hs view

file too large to diff

+ tests/Duckling/Numeral/TH/Tests.hs view

file too large to diff

tests/Duckling/Numeral/TR/Tests.hs view

file too large to diff

tests/Duckling/Numeral/Tests.hs view

file too large to diff

tests/Duckling/Numeral/UK/Tests.hs view

file too large to diff

tests/Duckling/Numeral/VI/Tests.hs view

file too large to diff

tests/Duckling/Numeral/ZH/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/AR/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/BG/Tests.hs view

file too large to diff

+ tests/Duckling/Ordinal/CA/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/DA/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/DE/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/EL/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/EN/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/ES/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/ET/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/FR/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/GA/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/HE/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/HI/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/HR/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/HU/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/ID/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/IT/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/JA/Tests.hs view

file too large to diff

+ tests/Duckling/Ordinal/KA/Tests.hs view

file too large to diff

+ tests/Duckling/Ordinal/KM/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/KO/Tests.hs view

file too large to diff

+ tests/Duckling/Ordinal/ML/Tests.hs view

file too large to diff

+ tests/Duckling/Ordinal/MN/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/NB/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/NL/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/PL/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/PT/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/RO/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/RU/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/SV/Tests.hs view

file too large to diff

+ tests/Duckling/Ordinal/TA/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/TR/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/UK/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/VI/Tests.hs view

file too large to diff

tests/Duckling/Ordinal/ZH/Tests.hs view

file too large to diff

+ tests/Duckling/PhoneNumber/AR/Tests.hs view

file too large to diff

tests/Duckling/PhoneNumber/PT/Tests.hs view

file too large to diff

tests/Duckling/PhoneNumber/Tests.hs view

file too large to diff

tests/Duckling/Quantity/AR/Tests.hs view

file too large to diff

tests/Duckling/Quantity/EN/Tests.hs view

file too large to diff

+ tests/Duckling/Quantity/ES/Tests.hs view

file too large to diff

tests/Duckling/Quantity/FR/Tests.hs view

file too large to diff

tests/Duckling/Quantity/HR/Tests.hs view

file too large to diff

+ tests/Duckling/Quantity/KM/Tests.hs view

file too large to diff

tests/Duckling/Quantity/KO/Tests.hs view

file too large to diff

+ tests/Duckling/Quantity/MN/Tests.hs view

file too large to diff

+ tests/Duckling/Quantity/NL/Tests.hs view

file too large to diff

tests/Duckling/Quantity/PT/Tests.hs view

file too large to diff

tests/Duckling/Quantity/RO/Tests.hs view

file too large to diff

tests/Duckling/Quantity/RU/Tests.hs view

file too large to diff

tests/Duckling/Quantity/Tests.hs view

file too large to diff

tests/Duckling/Quantity/ZH/Tests.hs view

file too large to diff

tests/Duckling/Temperature/AR/Tests.hs view

file too large to diff

tests/Duckling/Temperature/EN/Tests.hs view

file too large to diff

tests/Duckling/Temperature/ES/Tests.hs view

file too large to diff

tests/Duckling/Temperature/FR/Tests.hs view

file too large to diff

tests/Duckling/Temperature/GA/Tests.hs view

file too large to diff

+ tests/Duckling/Temperature/HI/Tests.hs view

file too large to diff

tests/Duckling/Temperature/HR/Tests.hs view

file too large to diff

tests/Duckling/Temperature/IT/Tests.hs view

file too large to diff

tests/Duckling/Temperature/JA/Tests.hs view

file too large to diff

+ tests/Duckling/Temperature/KM/Tests.hs view

file too large to diff

tests/Duckling/Temperature/KO/Tests.hs view

file too large to diff

+ tests/Duckling/Temperature/MN/Tests.hs view

file too large to diff

tests/Duckling/Temperature/PT/Tests.hs view

file too large to diff

tests/Duckling/Temperature/RO/Tests.hs view

file too large to diff

tests/Duckling/Temperature/TR/Tests.hs view

file too large to diff

tests/Duckling/Temperature/Tests.hs view

file too large to diff

tests/Duckling/Temperature/ZH/Tests.hs view

file too large to diff

tests/Duckling/Testing/Asserts.hs view

file too large to diff

tests/Duckling/Tests.hs view

file too large to diff

tests/Duckling/Time/AR/Tests.hs view

file too large to diff

+ tests/Duckling/Time/BG/Tests.hs view

file too large to diff

tests/Duckling/Time/DA/Tests.hs view

file too large to diff

tests/Duckling/Time/DE/Tests.hs view

file too large to diff

tests/Duckling/Time/EL/Tests.hs view

file too large to diff

tests/Duckling/Time/EN/Tests.hs view

file too large to diff

tests/Duckling/Time/ES/Tests.hs view

file too large to diff

tests/Duckling/Time/FR/Tests.hs view

file too large to diff

tests/Duckling/Time/GA/Tests.hs view

file too large to diff

tests/Duckling/Time/HE/Tests.hs view

file too large to diff

tests/Duckling/Time/HR/Tests.hs view

file too large to diff

tests/Duckling/Time/HU/Tests.hs view

file too large to diff

tests/Duckling/Time/IT/Tests.hs view

file too large to diff

+ tests/Duckling/Time/KA/Tests.hs view

file too large to diff

tests/Duckling/Time/KO/Tests.hs view

file too large to diff

tests/Duckling/Time/NB/Tests.hs view

file too large to diff

tests/Duckling/Time/NL/Tests.hs view

file too large to diff

tests/Duckling/Time/PL/Tests.hs view

file too large to diff

tests/Duckling/Time/PT/Tests.hs view

file too large to diff

tests/Duckling/Time/RO/Tests.hs view

file too large to diff

+ tests/Duckling/Time/RU/Tests.hs view

file too large to diff

tests/Duckling/Time/SV/Tests.hs view

file too large to diff

tests/Duckling/Time/Tests.hs view

file too large to diff

+ tests/Duckling/Time/UK/Tests.hs view

file too large to diff

tests/Duckling/Time/VI/Tests.hs view

file too large to diff

tests/Duckling/Time/ZH/Tests.hs view

file too large to diff

tests/Duckling/Url/Tests.hs view

file too large to diff

tests/Duckling/Volume/AR/Tests.hs view

file too large to diff

+ tests/Duckling/Volume/DE/Tests.hs view

file too large to diff

tests/Duckling/Volume/EN/Tests.hs view

file too large to diff

tests/Duckling/Volume/ES/Tests.hs view

file too large to diff

tests/Duckling/Volume/FR/Tests.hs view

file too large to diff

tests/Duckling/Volume/GA/Tests.hs view

file too large to diff

tests/Duckling/Volume/HR/Tests.hs view

file too large to diff

tests/Duckling/Volume/IT/Tests.hs view

file too large to diff

+ tests/Duckling/Volume/KM/Tests.hs view

file too large to diff

tests/Duckling/Volume/KO/Tests.hs view

file too large to diff

+ tests/Duckling/Volume/MN/Tests.hs view

file too large to diff

tests/Duckling/Volume/NL/Tests.hs view

file too large to diff

tests/Duckling/Volume/PT/Tests.hs view

file too large to diff

tests/Duckling/Volume/RO/Tests.hs view

file too large to diff

tests/Duckling/Volume/RU/Tests.hs view

file too large to diff

tests/Duckling/Volume/TR/Tests.hs view

file too large to diff

tests/Duckling/Volume/Tests.hs view

file too large to diff

+ tests/Duckling/Volume/ZH/Tests.hs view

file too large to diff

tests/TestMain.hs view

file too large to diff