Support for intervals

Summary:
- Supports singular (like English "a")
- Supports intervals (e.g. EUR 100-200)
- Supports open intervals (like English "more than", "less than")

Reviewed By: haoxuany

Differential Revision: D16069296

fbshipit-source-id: 74808ad28f5673c2ca82f07dcc0934f82910b566
This commit is contained in:
Sasa Milic 2019-07-02 13:18:40 -07:00 committed by Facebook Github Bot
parent 7341556898
commit b29bb5d3ed
3 changed files with 227 additions and 4 deletions

View File

@ -23,11 +23,18 @@ corpus = (testContext {locale = makeLocale HR Nothing}, testOptions, allExamples
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"
]
@ -45,6 +52,9 @@ allExamples = concat
, "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"
@ -61,6 +71,9 @@ allExamples = concat
, "dvjesto kuna"
, "dvjesta kuna"
]
, examples (simple EUR 1)
[ "jedan euro"
]
, examples (simple EUR 20)
[ "20€"
, "20 euros"
@ -93,4 +106,28 @@ allExamples = concat
[ "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"
]
]

View File

@ -28,6 +28,20 @@ import Duckling.Types
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>"
@ -197,9 +211,172 @@ ruleAed = Rule
, 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
@ -214,4 +391,13 @@ rules =
, ruleKwd
, ruleQar
, ruleSar
, rulePrecision
, ruleIntervalNumeralDash
, ruleIntervalDash
, ruleIntervalBetweenNumeral1
, ruleIntervalBetweenNumeral2
, ruleIntervalBetween1
, ruleIntervalBetween2
, ruleIntervalMin
, ruleIntervalMax
]

View File

@ -1944,4 +1944,4 @@ classifiers
likelihoods = HashMap.fromList [("", 0.0)], n = 4},
koData =
ClassData{prior = -infinity, unseen = -0.6931471805599453,
likelihoods = HashMap.fromList [], n = 0}})]
likelihoods = HashMap.fromList [], n = 0}})]